diff options
Diffstat (limited to 'src/org/traccar')
66 files changed, 1591 insertions, 729 deletions
diff --git a/src/org/traccar/BasePipelineFactory.java b/src/org/traccar/BasePipelineFactory.java index b45e3a280..b3d37f689 100644 --- a/src/org/traccar/BasePipelineFactory.java +++ b/src/org/traccar/BasePipelineFactory.java @@ -15,36 +15,40 @@ */ package org.traccar; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import io.netty.channel.Channel; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandler; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOutboundHandler; import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelPromise; -import io.netty.channel.socket.DatagramChannel; -import io.netty.channel.socket.DatagramPacket; import io.netty.handler.timeout.IdleStateHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.events.CommandResultEventHandler; -import org.traccar.events.DriverEventHandler; -import org.traccar.events.FuelDropEventHandler; -import org.traccar.events.GeofenceEventHandler; -import org.traccar.events.IgnitionEventHandler; -import org.traccar.events.MaintenanceEventHandler; -import org.traccar.events.MotionEventHandler; -import org.traccar.events.OverspeedEventHandler; -import org.traccar.events.AlertEventHandler; -import org.traccar.processing.ComputedAttributesHandler; -import org.traccar.processing.CopyAttributesHandler; +import org.traccar.config.Keys; +import org.traccar.handler.DefaultDataHandler; +import org.traccar.handler.events.AlertEventHandler; +import org.traccar.handler.events.CommandResultEventHandler; +import org.traccar.handler.events.DriverEventHandler; +import org.traccar.handler.events.FuelDropEventHandler; +import org.traccar.handler.events.GeofenceEventHandler; +import org.traccar.handler.events.IgnitionEventHandler; +import org.traccar.handler.events.MaintenanceEventHandler; +import org.traccar.handler.events.MotionEventHandler; +import org.traccar.handler.events.OverspeedEventHandler; +import org.traccar.handler.ComputedAttributesHandler; +import org.traccar.handler.CopyAttributesHandler; +import org.traccar.handler.DistanceHandler; +import org.traccar.handler.EngineHoursHandler; +import org.traccar.handler.FilterHandler; +import org.traccar.handler.GeocoderHandler; +import org.traccar.handler.GeolocationHandler; +import org.traccar.handler.HemisphereHandler; +import org.traccar.handler.MotionHandler; +import org.traccar.handler.NetworkMessageHandler; +import org.traccar.handler.OpenChannelHandler; +import org.traccar.handler.RemoteAddressHandler; +import org.traccar.handler.StandardLoggingHandler; -import java.net.InetSocketAddress; -import java.net.SocketAddress; import java.util.Map; public abstract class BasePipelineFactory extends ChannelInitializer<Channel> { @@ -52,207 +56,25 @@ public abstract class BasePipelineFactory extends ChannelInitializer<Channel> { private static final Logger LOGGER = LoggerFactory.getLogger(BasePipelineFactory.class); private final TrackerServer server; + private boolean eventsEnabled; private int timeout; - private FilterHandler filterHandler; - private DistanceHandler distanceHandler; - private EngineHoursHandler engineHoursHandler; - private RemoteAddressHandler remoteAddressHandler; - private MotionHandler motionHandler; - private GeocoderHandler geocoderHandler; - private GeolocationHandler geolocationHandler; - private HemisphereHandler hemisphereHandler; - private CopyAttributesHandler copyAttributesHandler; - private ComputedAttributesHandler computedAttributesHandler; - - private CommandResultEventHandler commandResultEventHandler; - private OverspeedEventHandler overspeedEventHandler; - private FuelDropEventHandler fuelDropEventHandler; - private MotionEventHandler motionEventHandler; - private GeofenceEventHandler geofenceEventHandler; - private AlertEventHandler alertEventHandler; - private IgnitionEventHandler ignitionEventHandler; - private MaintenanceEventHandler maintenanceEventHandler; - private DriverEventHandler driverEventHandler; - - private static final class OpenChannelHandler extends ChannelDuplexHandler { - - private final TrackerServer server; - - private OpenChannelHandler(TrackerServer server) { - this.server = server; - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - super.channelActive(ctx); - server.getChannelGroup().add(ctx.channel()); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - super.channelInactive(ctx); - server.getChannelGroup().remove(ctx.channel()); - } - - } - - private static class NetworkMessageHandler extends ChannelDuplexHandler { - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - if (ctx.channel() instanceof DatagramChannel) { - DatagramPacket packet = (DatagramPacket) msg; - ctx.fireChannelRead(new NetworkMessage(packet.content(), packet.sender())); - } else if (msg instanceof ByteBuf) { - ByteBuf buffer = (ByteBuf) msg; - ctx.fireChannelRead(new NetworkMessage(buffer, ctx.channel().remoteAddress())); - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - if (msg instanceof NetworkMessage) { - NetworkMessage message = (NetworkMessage) msg; - if (ctx.channel() instanceof DatagramChannel) { - InetSocketAddress recipient = (InetSocketAddress) message.getRemoteAddress(); - InetSocketAddress sender = (InetSocketAddress) ctx.channel().localAddress(); - ctx.write(new DatagramPacket((ByteBuf) message.getMessage(), recipient, sender), promise); - } else { - ctx.write(message.getMessage(), promise); - } - } else { - ctx.write(msg, promise); - } - } - - } - - private static class StandardLoggingHandler extends ChannelDuplexHandler { - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - log(ctx, false, msg); - super.channelRead(ctx, msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - log(ctx, true, msg); - super.write(ctx, msg, promise); - } - - public void log(ChannelHandlerContext ctx, boolean downstream, Object o) { - if (o instanceof NetworkMessage) { - NetworkMessage networkMessage = (NetworkMessage) o; - if (networkMessage.getMessage() instanceof ByteBuf) { - log(ctx, downstream, networkMessage.getRemoteAddress(), (ByteBuf) networkMessage.getMessage()); - } - } else if (o instanceof ByteBuf) { - log(ctx, downstream, ctx.channel().remoteAddress(), (ByteBuf) o); - } - } - - public void log(ChannelHandlerContext ctx, boolean downstream, SocketAddress remoteAddress, ByteBuf buf) { - StringBuilder message = new StringBuilder(); - - message.append("[").append(ctx.channel().id().asShortText()).append(": "); - message.append(((InetSocketAddress) ctx.channel().localAddress()).getPort()); - if (downstream) { - message.append(" > "); - } else { - message.append(" < "); - } - - if (remoteAddress instanceof InetSocketAddress) { - message.append(((InetSocketAddress) remoteAddress).getHostString()); - } else { - message.append("unknown"); - } - message.append("]"); - - message.append(" HEX: "); - message.append(ByteBufUtil.hexDump(buf)); - - LOGGER.info(message.toString()); - } - - } - public BasePipelineFactory(TrackerServer server, String protocol) { this.server = server; - - timeout = Context.getConfig().getInteger(protocol + ".timeout"); + eventsEnabled = Context.getConfig().getBoolean(Keys.EVENT_ENABLE); + timeout = Context.getConfig().getInteger(Keys.PROTOCOL_TIMEOUT.withPrefix(protocol)); if (timeout == 0) { - timeout = Context.getConfig().getInteger(protocol + ".resetDelay"); // temporary - if (timeout == 0) { - timeout = Context.getConfig().getInteger("server.timeout"); - } - } - - distanceHandler = new DistanceHandler( - Context.getConfig().getBoolean("coordinates.filter"), - Context.getConfig().getInteger("coordinates.minError"), - Context.getConfig().getInteger("coordinates.maxError")); - - if (Context.getConfig().getBoolean("processing.remoteAddress.enable")) { - remoteAddressHandler = new RemoteAddressHandler(); - } - - if (Context.getConfig().getBoolean("filter.enable")) { - filterHandler = new FilterHandler(); - } - - if (Context.getGeocoder() != null && !Context.getConfig().getBoolean("geocoder.ignorePositions")) { - geocoderHandler = new GeocoderHandler( - Context.getGeocoder(), - Context.getConfig().getBoolean("geocoder.processInvalidPositions")); - } - - if (Context.getGeolocationProvider() != null) { - geolocationHandler = new GeolocationHandler( - Context.getGeolocationProvider(), - Context.getConfig().getBoolean("geolocation.processInvalidPositions")); - } - - motionHandler = new MotionHandler(Context.getTripsConfig().getSpeedThreshold()); - - if (Context.getConfig().getBoolean("processing.engineHours.enable")) { - engineHoursHandler = new EngineHoursHandler(); - } - - if (Context.getConfig().hasKey("location.latitudeHemisphere") - || Context.getConfig().hasKey("location.longitudeHemisphere")) { - hemisphereHandler = new HemisphereHandler(); - } - - if (Context.getConfig().getBoolean("processing.copyAttributes.enable")) { - copyAttributesHandler = new CopyAttributesHandler(); - } - - if (Context.getConfig().getBoolean("processing.computedAttributes.enable")) { - computedAttributesHandler = new ComputedAttributesHandler(); - } - - if (Context.getConfig().getBoolean("event.enable")) { - commandResultEventHandler = new CommandResultEventHandler(); - overspeedEventHandler = Context.getOverspeedEventHandler(); - fuelDropEventHandler = new FuelDropEventHandler(); - motionEventHandler = Context.getMotionEventHandler(); - geofenceEventHandler = new GeofenceEventHandler(); - alertEventHandler = new AlertEventHandler(); - ignitionEventHandler = new IgnitionEventHandler(); - maintenanceEventHandler = new MaintenanceEventHandler(); - driverEventHandler = new DriverEventHandler(); + timeout = Context.getConfig().getInteger(Keys.SERVER_TIMEOUT); } } protected abstract void addProtocolHandlers(PipelineBuilder pipeline); - private void addHandlers(ChannelPipeline pipeline, ChannelHandler... handlers) { - for (ChannelHandler handler : handlers) { - if (handler != null) { - pipeline.addLast(handler); + @SafeVarargs + private final void addHandlers(ChannelPipeline pipeline, Class<? extends ChannelHandler>... handlerClasses) { + for (Class<? extends ChannelHandler> handlerClass : handlerClasses) { + if (handlerClass != null) { + pipeline.addLast(Main.getInjector().getInstance(handlerClass)); } } } @@ -273,8 +95,9 @@ public abstract class BasePipelineFactory extends ChannelInitializer<Channel> { } @Override - protected void initChannel(Channel channel) throws Exception { + protected void initChannel(Channel channel) { final ChannelPipeline pipeline = channel.pipeline(); + if (timeout > 0 && !server.isDatagram()) { pipeline.addLast(new IdleStateHandler(timeout, 0, 0)); } @@ -295,53 +118,48 @@ public abstract class BasePipelineFactory extends ChannelInitializer<Channel> { addHandlers( pipeline, - geolocationHandler, - hemisphereHandler, - distanceHandler, - remoteAddressHandler); + GeolocationHandler.class, + HemisphereHandler.class, + DistanceHandler.class, + RemoteAddressHandler.class); addDynamicHandlers(pipeline); addHandlers( pipeline, - filterHandler, - geocoderHandler, - motionHandler, - engineHoursHandler, - copyAttributesHandler, - computedAttributesHandler); - - if (Context.getDataManager() != null) { - pipeline.addLast(new DefaultDataHandler()); - } - - if (Context.getConfig().getBoolean("forward.enable")) { - pipeline.addLast(Main.getInjector().getInstance(WebDataHandler.Factory.class).create( - Context.getConfig().getString("forward.url"), Context.getConfig().getBoolean("forward.json"))); + FilterHandler.class, + GeocoderHandler.class, + MotionHandler.class, + EngineHoursHandler.class, + CopyAttributesHandler.class, + ComputedAttributesHandler.class, + WebDataHandler.class, + DefaultDataHandler.class); + + if (eventsEnabled) { + addHandlers( + pipeline, + CommandResultEventHandler.class, + OverspeedEventHandler.class, + FuelDropEventHandler.class, + MotionEventHandler.class, + GeofenceEventHandler.class, + AlertEventHandler.class, + IgnitionEventHandler.class, + MaintenanceEventHandler.class, + DriverEventHandler.class); } - addHandlers( - pipeline, - commandResultEventHandler, - overspeedEventHandler, - fuelDropEventHandler, - motionEventHandler, - geofenceEventHandler, - alertEventHandler, - ignitionEventHandler, - maintenanceEventHandler, - driverEventHandler); - pipeline.addLast(new MainEventHandler()); } private void addDynamicHandlers(ChannelPipeline pipeline) { - if (Context.getConfig().hasKey("extra.handlers")) { - String[] handlers = Context.getConfig().getString("extra.handlers").split(","); - for (String handler : handlers) { + String handlers = Context.getConfig().getString(Keys.EXTRA_HANDLERS); + if (handlers != null) { + for (String handler : handlers.split(",")) { try { - pipeline.addLast((ChannelHandler) Class.forName(handler).newInstance()); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException error) { + pipeline.addLast((ChannelHandler) Class.forName(handler).getDeclaredConstructor().newInstance()); + } catch (ReflectiveOperationException error) { LOGGER.warn("Dynamic handler error", error); } } diff --git a/src/org/traccar/BaseProtocolDecoder.java b/src/org/traccar/BaseProtocolDecoder.java index cbef4568d..aa5be612e 100644 --- a/src/org/traccar/BaseProtocolDecoder.java +++ b/src/org/traccar/BaseProtocolDecoder.java @@ -20,6 +20,7 @@ import io.netty.channel.socket.DatagramChannel; import io.netty.handler.codec.http.HttpRequestDecoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.traccar.config.Config; import org.traccar.database.ConnectionManager; import org.traccar.database.IdentityManager; import org.traccar.database.StatisticsManager; @@ -44,11 +45,12 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { private final Config config = Context.getConfig(); private final IdentityManager identityManager = Context.getIdentityManager(); private final ConnectionManager connectionManager = Context.getConnectionManager(); - private final StatisticsManager statisticsManager = Context.getStatisticsManager(); + private final StatisticsManager statisticsManager; private final Protocol protocol; public BaseProtocolDecoder(Protocol protocol) { this.protocol = protocol; + statisticsManager = Main.getInjector() != null ? Main.getInjector().getInstance(StatisticsManager.class) : null; } public String getProtocolName() { diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java index d679842cd..9c20db9e4 100644 --- a/src/org/traccar/Context.java +++ b/src/org/traccar/Context.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,24 +17,22 @@ package org.traccar; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Properties; - import com.fasterxml.jackson.datatype.jsr353.JSR353Module; import org.apache.velocity.app.VelocityEngine; import org.eclipse.jetty.util.URIUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.database.CalendarManager; -import org.traccar.database.CommandsManager; +import org.traccar.config.Config; import org.traccar.database.AttributesManager; import org.traccar.database.BaseObjectManager; +import org.traccar.database.CalendarManager; +import org.traccar.database.CommandsManager; import org.traccar.database.ConnectionManager; import org.traccar.database.DataManager; import org.traccar.database.DeviceManager; import org.traccar.database.DriversManager; +import org.traccar.database.GeofenceManager; +import org.traccar.database.GroupsManager; import org.traccar.database.IdentityManager; import org.traccar.database.LdapProvider; import org.traccar.database.MailManager; @@ -42,27 +40,8 @@ import org.traccar.database.MaintenancesManager; import org.traccar.database.MediaManager; import org.traccar.database.NotificationManager; import org.traccar.database.PermissionsManager; -import org.traccar.database.GeofenceManager; -import org.traccar.database.GroupsManager; -import org.traccar.database.StatisticsManager; import org.traccar.database.UsersManager; -import org.traccar.events.MotionEventHandler; -import org.traccar.events.OverspeedEventHandler; -import org.traccar.geocoder.AddressFormat; -import org.traccar.geocoder.BingMapsGeocoder; -import org.traccar.geocoder.FactualGeocoder; -import org.traccar.geocoder.GeocodeFarmGeocoder; -import org.traccar.geocoder.GeocodeXyzGeocoder; -import org.traccar.geocoder.GisgraphyGeocoder; -import org.traccar.geocoder.BanGeocoder; -import org.traccar.geocoder.GoogleGeocoder; -import org.traccar.geocoder.HereGeocoder; -import org.traccar.geocoder.MapQuestGeocoder; -import org.traccar.geocoder.NominatimGeocoder; -import org.traccar.geocoder.OpenCageGeocoder; -import org.traccar.geocoder.MapmyIndiaGeocoder; import org.traccar.geocoder.Geocoder; -import org.traccar.geolocation.UnwiredGeolocationProvider; import org.traccar.helper.Log; import org.traccar.helper.SanitizerModule; import org.traccar.model.Attribute; @@ -76,10 +55,6 @@ import org.traccar.model.Group; import org.traccar.model.Maintenance; import org.traccar.model.Notification; import org.traccar.model.User; -import org.traccar.geolocation.GoogleGeolocationProvider; -import org.traccar.geolocation.GeolocationProvider; -import org.traccar.geolocation.MozillaGeolocationProvider; -import org.traccar.geolocation.OpenCellIdGeolocationProvider; import org.traccar.notification.EventForwarder; import org.traccar.notification.JsonTypeEventForwarder; import org.traccar.notification.NotificatorManager; @@ -91,6 +66,9 @@ import org.traccar.web.WebServer; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.ext.ContextResolver; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Properties; public final class Context { @@ -99,10 +77,6 @@ public final class Context { private Context() { } - public static String getAppVersion() { - return Context.class.getPackage().getImplementationVersion(); - } - private static Config config; public static Config getConfig() { @@ -175,16 +149,8 @@ public final class Context { return permissionsManager; } - private static Geocoder geocoder; - public static Geocoder getGeocoder() { - return geocoder; - } - - private static GeolocationProvider geolocationProvider; - - public static GeolocationProvider getGeolocationProvider() { - return geolocationProvider; + return Main.getInjector() != null ? Main.getInjector().getInstance(Geocoder.class) : null; } private static WebServer webServer; @@ -265,30 +231,12 @@ public final class Context { return maintenancesManager; } - private static StatisticsManager statisticsManager; - - public static StatisticsManager getStatisticsManager() { - return statisticsManager; - } - private static SmsManager smsManager; public static SmsManager getSmsManager() { return smsManager; } - private static MotionEventHandler motionEventHandler; - - public static MotionEventHandler getMotionEventHandler() { - return motionEventHandler; - } - - private static OverspeedEventHandler overspeedEventHandler; - - public static OverspeedEventHandler getOverspeedEventHandler() { - return overspeedEventHandler; - } - private static TripsConfig tripsConfig; public static TripsConfig getTripsConfig() { @@ -315,56 +263,12 @@ public final class Context { } - public static Geocoder initGeocoder() { - String type = config.getString("geocoder.type", "google"); - String url = config.getString("geocoder.url"); - String id = config.getString("geocoder.id"); - String key = config.getString("geocoder.key"); - String language = config.getString("geocoder.language"); - - String formatString = config.getString("geocoder.format"); - AddressFormat addressFormat; - if (formatString != null) { - addressFormat = new AddressFormat(formatString); - } else { - addressFormat = new AddressFormat(); - } - - int cacheSize = config.getInteger("geocoder.cacheSize"); - switch (type) { - case "nominatim": - return new NominatimGeocoder(url, key, language, cacheSize, addressFormat); - case "gisgraphy": - return new GisgraphyGeocoder(url, cacheSize, addressFormat); - case "mapquest": - return new MapQuestGeocoder(url, key, cacheSize, addressFormat); - case "opencage": - return new OpenCageGeocoder(url, key, cacheSize, addressFormat); - case "bingmaps": - return new BingMapsGeocoder(url, key, cacheSize, addressFormat); - case "factual": - return new FactualGeocoder(url, key, cacheSize, addressFormat); - case "geocodefarm": - return new GeocodeFarmGeocoder(key, language, cacheSize, addressFormat); - case "geocodexyz": - return new GeocodeXyzGeocoder(key, cacheSize, addressFormat); - case "ban": - return new BanGeocoder(cacheSize, addressFormat); - case "here": - return new HereGeocoder(id, key, language, cacheSize, addressFormat); - case "mapmyindia": - return new MapmyIndiaGeocoder(url, key, cacheSize, addressFormat); - default: - return new GoogleGeocoder(key, language, cacheSize, addressFormat); - } - } - public static void init(String configFile) throws Exception { try { - config = new Config(); - config.load(configFile); + config = new Config(configFile); } catch (Exception e) { + config = new Config(); Log.setupDefaultLogger(); throw e; } @@ -384,7 +288,6 @@ public final class Context { client = ClientBuilder.newClient().register(new ObjectMapperContextResolver()); - if (config.hasKey("database.url")) { dataManager = new DataManager(config); } @@ -405,14 +308,6 @@ public final class Context { identityManager = deviceManager; - if (config.getBoolean("geocoder.enable")) { - geocoder = initGeocoder(); - } - - if (config.getBoolean("geolocation.enable")) { - initGeolocationModule(); - } - if (config.getBoolean("web.enable")) { webServer = new WebServer(config); } @@ -448,30 +343,6 @@ public final class Context { commandsManager = new CommandsManager(dataManager, config.getBoolean("commands.queueing")); - statisticsManager = new StatisticsManager(); - - } - - private static void initGeolocationModule() { - - String type = config.getString("geolocation.type", "mozilla"); - String url = config.getString("geolocation.url"); - String key = config.getString("geolocation.key"); - - switch (type) { - case "google": - geolocationProvider = new GoogleGeolocationProvider(key); - break; - case "opencellid": - geolocationProvider = new OpenCellIdGeolocationProvider(key); - break; - case "unwired": - geolocationProvider = new UnwiredGeolocationProvider(url, key); - break; - default: - geolocationProvider = new MozillaGeolocationProvider(key); - break; - } } private static void initEventsModule() { @@ -500,12 +371,6 @@ public final class Context { velocityEngine = new VelocityEngine(); velocityEngine.init(velocityProperties); - - motionEventHandler = new MotionEventHandler(tripsConfig); - overspeedEventHandler = new OverspeedEventHandler( - Context.getConfig().getLong("event.overspeed.minimalDuration") * 1000, - Context.getConfig().getBoolean("event.overspeed.notRepeat"), - Context.getConfig().getBoolean("event.overspeed.preferLowest")); } public static void init(IdentityManager testIdentityManager, MediaManager testMediaManager) { diff --git a/src/org/traccar/Main.java b/src/org/traccar/Main.java index c85d93431..6ebd1d399 100644 --- a/src/org/traccar/Main.java +++ b/src/org/traccar/Main.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2012 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -110,7 +110,7 @@ public final class Main { Context.init(configFile); injector = Guice.createInjector(new MainModule()); logSystemInfo(); - LOGGER.info("Version: " + Context.getAppVersion()); + LOGGER.info("Version: " + Main.class.getPackage().getImplementationVersion()); LOGGER.info("Starting server..."); Context.getServerManager().start(); diff --git a/src/org/traccar/MainEventHandler.java b/src/org/traccar/MainEventHandler.java index 75dafcc29..a8b53ff60 100644 --- a/src/org/traccar/MainEventHandler.java +++ b/src/org/traccar/MainEventHandler.java @@ -23,6 +23,7 @@ import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.timeout.IdleStateEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.traccar.database.StatisticsManager; import org.traccar.helper.DateUtil; import org.traccar.model.Position; @@ -34,7 +35,7 @@ import java.util.Set; public class MainEventHandler extends ChannelInboundHandlerAdapter { - private static final Logger LOGGER = LoggerFactory.getLogger(GeocoderHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MainEventHandler.class); private static final String DEFAULT_LOGGER_ATTRIBUTES = "time,position,speed,course,accuracy,result"; @@ -108,7 +109,7 @@ public class MainEventHandler extends ChannelInboundHandlerAdapter { } LOGGER.info(builder.toString()); - Context.getStatisticsManager().registerMessageStored(position.getDeviceId()); + Main.getInjector().getInstance(StatisticsManager.class).registerMessageStored(position.getDeviceId()); } } diff --git a/src/org/traccar/MainModule.java b/src/org/traccar/MainModule.java index 6c66a90b8..6fe8bad1c 100644 --- a/src/org/traccar/MainModule.java +++ b/src/org/traccar/MainModule.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,31 +18,356 @@ package org.traccar; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.AbstractModule; import com.google.inject.Provides; -import com.google.inject.assistedinject.FactoryModuleBuilder; +import com.google.inject.Singleton; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.database.AttributesManager; +import org.traccar.database.CalendarManager; +import org.traccar.database.DataManager; +import org.traccar.database.DeviceManager; +import org.traccar.database.GeofenceManager; import org.traccar.database.IdentityManager; +import org.traccar.database.MaintenancesManager; +import org.traccar.database.StatisticsManager; +import org.traccar.geocoder.AddressFormat; +import org.traccar.geocoder.BanGeocoder; +import org.traccar.geocoder.BingMapsGeocoder; +import org.traccar.geocoder.FactualGeocoder; +import org.traccar.geocoder.GeocodeFarmGeocoder; +import org.traccar.geocoder.GeocodeXyzGeocoder; +import org.traccar.geocoder.Geocoder; +import org.traccar.geocoder.GisgraphyGeocoder; +import org.traccar.geocoder.GoogleGeocoder; +import org.traccar.geocoder.HereGeocoder; +import org.traccar.geocoder.MapQuestGeocoder; +import org.traccar.geocoder.MapmyIndiaGeocoder; +import org.traccar.geocoder.NominatimGeocoder; +import org.traccar.geocoder.OpenCageGeocoder; +import org.traccar.geolocation.GeolocationProvider; +import org.traccar.geolocation.GoogleGeolocationProvider; +import org.traccar.geolocation.MozillaGeolocationProvider; +import org.traccar.geolocation.OpenCellIdGeolocationProvider; +import org.traccar.geolocation.UnwiredGeolocationProvider; +import org.traccar.handler.ComputedAttributesHandler; +import org.traccar.handler.CopyAttributesHandler; +import org.traccar.handler.DefaultDataHandler; +import org.traccar.handler.DistanceHandler; +import org.traccar.handler.EngineHoursHandler; +import org.traccar.handler.FilterHandler; +import org.traccar.handler.GeocoderHandler; +import org.traccar.handler.GeolocationHandler; +import org.traccar.handler.HemisphereHandler; +import org.traccar.handler.MotionHandler; +import org.traccar.handler.RemoteAddressHandler; +import org.traccar.handler.events.AlertEventHandler; +import org.traccar.handler.events.CommandResultEventHandler; +import org.traccar.handler.events.DriverEventHandler; +import org.traccar.handler.events.FuelDropEventHandler; +import org.traccar.handler.events.GeofenceEventHandler; +import org.traccar.handler.events.IgnitionEventHandler; +import org.traccar.handler.events.MaintenanceEventHandler; +import org.traccar.handler.events.MotionEventHandler; +import org.traccar.handler.events.OverspeedEventHandler; +import org.traccar.reports.model.TripsConfig; +import javax.annotation.Nullable; import javax.ws.rs.client.Client; public class MainModule extends AbstractModule { @Provides - public static ObjectMapper getObjectMapper() { + public static ObjectMapper provideObjectMapper() { return Context.getObjectMapper(); } @Provides - public static IdentityManager getIdentityManager() { + public static Config provideConfig() { + return Context.getConfig(); + } + + @Provides + public static DataManager provideDataManager() { + return Context.getDataManager(); + } + + @Provides + public static IdentityManager provideIdentityManager() { return Context.getIdentityManager(); } @Provides - public static Client getClient() { + public static Client provideClient() { return Context.getClient(); } + @Provides + public static TripsConfig provideTripsConfig() { + return Context.getTripsConfig(); + } + + @Provides + public static DeviceManager provideDeviceManager() { + return Context.getDeviceManager(); + } + + @Provides + public static GeofenceManager provideGeofenceManager() { + return Context.getGeofenceManager(); + } + + @Provides + public static CalendarManager provideCalendarManager() { + return Context.getCalendarManager(); + } + + @Provides + public static AttributesManager provideAttributesManager() { + return Context.getAttributesManager(); + } + + @Provides + public static MaintenancesManager provideMaintenancesManager() { + return Context.getMaintenancesManager(); + } + + @Singleton + @Provides + public static StatisticsManager provideStatisticsManager(Config config, DataManager dataManager, Client client) { + return new StatisticsManager(config, dataManager, client); + } + + @Singleton + @Provides + public static Geocoder provideGeocoder(Config config) { + if (config.getBoolean(Keys.GEOCODER_ENABLE)) { + String type = config.getString(Keys.GEOCODER_TYPE, "google"); + String url = config.getString(Keys.GEOCODER_URL); + String id = config.getString(Keys.GEOCODER_ID); + String key = config.getString(Keys.GEOCODER_KEY); + String language = config.getString(Keys.GEOCODER_LANGUAGE); + String formatString = config.getString(Keys.GEOCODER_FORMAT); + AddressFormat addressFormat = formatString != null ? new AddressFormat(formatString) : new AddressFormat(); + + int cacheSize = config.getInteger(Keys.GEOCODER_CACHE_SIZE); + switch (type) { + case "nominatim": + return new NominatimGeocoder(url, key, language, cacheSize, addressFormat); + case "gisgraphy": + return new GisgraphyGeocoder(url, cacheSize, addressFormat); + case "mapquest": + return new MapQuestGeocoder(url, key, cacheSize, addressFormat); + case "opencage": + return new OpenCageGeocoder(url, key, cacheSize, addressFormat); + case "bingmaps": + return new BingMapsGeocoder(url, key, cacheSize, addressFormat); + case "factual": + return new FactualGeocoder(url, key, cacheSize, addressFormat); + case "geocodefarm": + return new GeocodeFarmGeocoder(key, language, cacheSize, addressFormat); + case "geocodexyz": + return new GeocodeXyzGeocoder(key, cacheSize, addressFormat); + case "ban": + return new BanGeocoder(cacheSize, addressFormat); + case "here": + return new HereGeocoder(id, key, language, cacheSize, addressFormat); + case "mapmyindia": + return new MapmyIndiaGeocoder(url, key, cacheSize, addressFormat); + default: + return new GoogleGeocoder(key, language, cacheSize, addressFormat); + } + } + return null; + } + + @Singleton + @Provides + public static GeolocationProvider provideGeolocationProvider(Config config) { + if (config.getBoolean(Keys.GEOLOCATION_ENABLE)) { + String type = config.getString(Keys.GEOLOCATION_TYPE, "mozilla"); + String url = config.getString(Keys.GEOLOCATION_URL); + String key = config.getString(Keys.GEOLOCATION_KEY); + switch (type) { + case "google": + return new GoogleGeolocationProvider(key); + case "opencellid": + return new OpenCellIdGeolocationProvider(key); + case "unwired": + return new UnwiredGeolocationProvider(url, key); + default: + return new MozillaGeolocationProvider(key); + } + } + return null; + } + + @Singleton + @Provides + public static DistanceHandler provideDistanceHandler(Config config, IdentityManager identityManager) { + return new DistanceHandler(config, identityManager); + } + + @Singleton + @Provides + public static FilterHandler provideFilterHandler(Config config) { + if (config.getBoolean(Keys.FILTER_ENABLE)) { + return new FilterHandler(config); + } + return null; + } + + @Singleton + @Provides + public static HemisphereHandler provideHemisphereHandler(Config config) { + if (config.hasKey(Keys.LOCATION_LATITUDE_HEMISPHERE) || config.hasKey(Keys.LOCATION_LONGITUDE_HEMISPHERE)) { + return new HemisphereHandler(config); + } + return null; + } + + @Singleton + @Provides + public static RemoteAddressHandler provideRemoteAddressHandler(Config config) { + if (config.getBoolean(Keys.PROCESSING_REMOTE_ADDRESS_ENABLE)) { + return new RemoteAddressHandler(); + } + return null; + } + + @Singleton + @Provides + public static WebDataHandler provideWebDataHandler( + Config config, IdentityManager identityManager, ObjectMapper objectMapper, Client client) { + if (config.getBoolean(Keys.FORWARD_ENABLE)) { + return new WebDataHandler(config, identityManager, objectMapper, client); + } + return null; + } + + @Singleton + @Provides + public static GeolocationHandler provideGeolocationHandler( + Config config, @Nullable GeolocationProvider geolocationProvider, StatisticsManager statisticsManager) { + if (geolocationProvider != null) { + return new GeolocationHandler(config, geolocationProvider, statisticsManager); + } + return null; + } + + @Singleton + @Provides + public static GeocoderHandler provideGeocoderHandler( + Config config, @Nullable Geocoder geocoder, IdentityManager identityManager, + StatisticsManager statisticsManager) { + if (geocoder != null) { + return new GeocoderHandler(config, geocoder, identityManager, statisticsManager); + } + return null; + } + + @Singleton + @Provides + public static MotionHandler provideMotionHandler(TripsConfig tripsConfig) { + return new MotionHandler(tripsConfig.getSpeedThreshold()); + } + + @Singleton + @Provides + public static EngineHoursHandler provideEngineHoursHandler(Config config, IdentityManager identityManager) { + if (config.getBoolean(Keys.PROCESSING_ENGINE_HOURS_ENABLE)) { + return new EngineHoursHandler(identityManager); + } + return null; + } + + @Singleton + @Provides + public static CopyAttributesHandler provideCopyAttributesHandler(Config config, IdentityManager identityManager) { + if (config.getBoolean(Keys.PROCESSING_COPY_ATTRIBUTES_ENABLE)) { + return new CopyAttributesHandler(identityManager); + } + return null; + } + + @Singleton + @Provides + public static ComputedAttributesHandler provideComputedAttributesHandler( + Config config, IdentityManager identityManager, AttributesManager attributesManager) { + if (config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_ENABLE)) { + return new ComputedAttributesHandler(config, identityManager, attributesManager); + } + return null; + } + + @Singleton + @Provides + public static DefaultDataHandler provideDefaultDataHandler(@Nullable DataManager dataManager) { + if (dataManager != null) { + return new DefaultDataHandler(dataManager); + } + return null; + } + + @Singleton + @Provides + public static CommandResultEventHandler provideCommandResultEventHandler() { + return new CommandResultEventHandler(); + } + + @Singleton + @Provides + public static OverspeedEventHandler provideOverspeedEventHandler( + Config config, DeviceManager deviceManager, GeofenceManager geofenceManager) { + return new OverspeedEventHandler(config, deviceManager, geofenceManager); + } + + @Singleton + @Provides + public static FuelDropEventHandler provideFuelDropEventHandler(IdentityManager identityManager) { + return new FuelDropEventHandler(identityManager); + } + + @Singleton + @Provides + public static MotionEventHandler provideMotionEventHandler( + IdentityManager identityManager, DeviceManager deviceManager, TripsConfig tripsConfig) { + return new MotionEventHandler(identityManager, deviceManager, tripsConfig); + } + + @Singleton + @Provides + public static GeofenceEventHandler provideGeofenceEventHandler( + IdentityManager identityManager, GeofenceManager geofenceManager, CalendarManager calendarManager) { + return new GeofenceEventHandler(identityManager, geofenceManager, calendarManager); + } + + @Singleton + @Provides + public static AlertEventHandler provideAlertEventHandler(Config config, IdentityManager identityManager) { + return new AlertEventHandler(config, identityManager); + } + + @Singleton + @Provides + public static IgnitionEventHandler provideIgnitionEventHandler(IdentityManager identityManager) { + return new IgnitionEventHandler(identityManager); + } + + @Singleton + @Provides + public static MaintenanceEventHandler provideMaintenanceEventHandler( + IdentityManager identityManager, MaintenancesManager maintenancesManager) { + return new MaintenanceEventHandler(identityManager, maintenancesManager); + } + + @Singleton + @Provides + public static DriverEventHandler provideDriverEventHandler(IdentityManager identityManager) { + return new DriverEventHandler(identityManager); + } + @Override protected void configure() { - install(new FactoryModuleBuilder().build(WebDataHandler.Factory.class)); + binder().requireExplicitBindings(); } } diff --git a/src/org/traccar/WebDataHandler.java b/src/org/traccar/WebDataHandler.java index a8e20c698..64396de03 100644 --- a/src/org/traccar/WebDataHandler.java +++ b/src/org/traccar/WebDataHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,9 @@ package org.traccar; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.inject.assistedinject.Assisted; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.netty.channel.ChannelHandler; +import org.traccar.config.Config; +import org.traccar.config.Keys; import org.traccar.database.IdentityManager; import org.traccar.helper.Checksum; import org.traccar.model.Device; @@ -29,6 +29,7 @@ import org.traccar.model.Group; import javax.inject.Inject; import javax.ws.rs.client.Client; import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; import java.util.HashMap; import java.util.Map; import java.io.UnsupportedEncodingException; @@ -39,10 +40,9 @@ import java.util.Formatter; import java.util.Locale; import java.util.TimeZone; +@ChannelHandler.Sharable public class WebDataHandler extends BaseDataHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(WebDataHandler.class); - private static final String KEY_POSITION = "position"; private static final String KEY_DEVICE = "device"; @@ -51,21 +51,18 @@ public class WebDataHandler extends BaseDataHandler { private final Client client; private final String url; + private final String header; private final boolean json; - public interface Factory { - WebDataHandler create(String url, boolean json); - } - @Inject public WebDataHandler( - IdentityManager identityManager, ObjectMapper objectMapper, Client client, - @Assisted String url, @Assisted boolean json) { + Config config, IdentityManager identityManager, ObjectMapper objectMapper, Client client) { this.identityManager = identityManager; this.objectMapper = objectMapper; this.client = client; - this.url = url; - this.json = json; + this.url = config.getString(Keys.FORWARD_URL); + this.header = config.getString(Keys.FORWARD_HEADER); + this.json = config.getBoolean(Keys.FORWARD_JSON); } private static String formatSentence(Position position) { @@ -157,19 +154,37 @@ public class WebDataHandler extends BaseDataHandler { @Override protected Position handlePosition(Position position) { + + String url; if (json) { - client.target(url).request().async().post(Entity.json(prepareJsonPayload(position))); + url = this.url; } else { try { - client.target(formatRequest(position)).request().async().get(); + url = formatRequest(position); } catch (UnsupportedEncodingException | JsonProcessingException e) { - LOGGER.warn("Forwarding formatting error", e); + throw new RuntimeException("Forwarding formatting error", e); } } + + Invocation.Builder requestBuilder = client.target(url).request(); + + if (header != null && !header.isEmpty()) { + for (String line: header.split("\\r?\\n")) { + String[] values = line.split(":", 2); + requestBuilder.header(values[0].trim(), values[1].trim()); + } + } + + if (json) { + requestBuilder.async().post(Entity.json(prepareJsonPayload(position))); + } else { + requestBuilder.async().get(); + } + return position; } - protected Map<String, Object> prepareJsonPayload(Position position) { + private Map<String, Object> prepareJsonPayload(Position position) { Map<String, Object> data = new HashMap<>(); Device device = identityManager.getById(position.getDeviceId()); diff --git a/src/org/traccar/api/MediaFilter.java b/src/org/traccar/api/MediaFilter.java index 25e242b01..53539770f 100644 --- a/src/org/traccar/api/MediaFilter.java +++ b/src/org/traccar/api/MediaFilter.java @@ -30,7 +30,9 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.traccar.Context; +import org.traccar.Main; import org.traccar.api.resource.SessionResource; +import org.traccar.database.StatisticsManager; import org.traccar.helper.Log; import org.traccar.model.Device; @@ -51,7 +53,7 @@ public class MediaFilter implements Filter { userId = (Long) session.getAttribute(SessionResource.USER_ID_KEY); if (userId != null) { Context.getPermissionsManager().checkUserEnabled(userId); - Context.getStatisticsManager().registerRequest(userId); + Main.getInjector().getInstance(StatisticsManager.class).registerRequest(userId); } } if (userId == null) { diff --git a/src/org/traccar/api/SecurityRequestFilter.java b/src/org/traccar/api/SecurityRequestFilter.java index 195c1f72f..33b6b37df 100644 --- a/src/org/traccar/api/SecurityRequestFilter.java +++ b/src/org/traccar/api/SecurityRequestFilter.java @@ -18,7 +18,9 @@ package org.traccar.api; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; +import org.traccar.Main; import org.traccar.api.resource.SessionResource; +import org.traccar.database.StatisticsManager; import org.traccar.helper.DataConverter; import org.traccar.model.User; @@ -77,7 +79,7 @@ public class SecurityRequestFilter implements ContainerRequestFilter { String[] auth = decodeBasicAuth(authHeader); User user = Context.getPermissionsManager().login(auth[0], auth[1]); if (user != null) { - Context.getStatisticsManager().registerRequest(user.getId()); + Main.getInjector().getInstance(StatisticsManager.class).registerRequest(user.getId()); securityContext = new UserSecurityContext(new UserPrincipal(user.getId())); } } catch (SQLException e) { @@ -89,7 +91,7 @@ public class SecurityRequestFilter implements ContainerRequestFilter { Long userId = (Long) request.getSession().getAttribute(SessionResource.USER_ID_KEY); if (userId != null) { Context.getPermissionsManager().checkUserEnabled(userId); - Context.getStatisticsManager().registerRequest(userId); + Main.getInjector().getInstance(StatisticsManager.class).registerRequest(userId); securityContext = new UserSecurityContext(new UserPrincipal(userId)); } diff --git a/src/org/traccar/api/resource/AttributeResource.java b/src/org/traccar/api/resource/AttributeResource.java index d10ca4a72..de69d871c 100644 --- a/src/org/traccar/api/resource/AttributeResource.java +++ b/src/org/traccar/api/resource/AttributeResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +33,7 @@ import org.traccar.Context; import org.traccar.api.ExtendedObjectResource; import org.traccar.model.Attribute; import org.traccar.model.Position; -import org.traccar.processing.ComputedAttributesHandler; +import org.traccar.handler.ComputedAttributesHandler; @Path("attributes/computed") @Produces(MediaType.APPLICATION_JSON) @@ -46,12 +46,15 @@ public class AttributeResource extends ExtendedObjectResource<Attribute> { @POST @Path("test") - public Response test(@QueryParam("deviceId") long deviceId, Attribute entity) throws SQLException { + public Response test(@QueryParam("deviceId") long deviceId, Attribute entity) { Context.getPermissionsManager().checkAdmin(getUserId()); Context.getPermissionsManager().checkDevice(getUserId(), deviceId); Position last = Context.getIdentityManager().getLastPosition(deviceId); if (last != null) { - Object result = new ComputedAttributesHandler().computeAttribute(entity, last); + Object result = new ComputedAttributesHandler( + Context.getConfig(), + Context.getIdentityManager(), + Context.getAttributesManager()).computeAttribute(entity, last); if (result != null) { switch (entity.getType()) { case "number": diff --git a/src/org/traccar/Config.java b/src/org/traccar/config/Config.java index 370123ae1..d8f2a0e99 100644 --- a/src/org/traccar/Config.java +++ b/src/org/traccar/config/Config.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.config; import java.io.FileInputStream; import java.io.IOException; @@ -27,7 +27,10 @@ public class Config { private boolean useEnvironmentVariables; - void load(String file) throws IOException { + public Config() { + } + + public Config(String file) throws IOException { try { Properties mainProperties = new Properties(); try (InputStream inputStream = new FileInputStream(file)) { @@ -50,11 +53,21 @@ public class Config { } } + public boolean hasKey(ConfigKey key) { + return hasKey(key.getKey()); + } + + @Deprecated public boolean hasKey(String key) { return useEnvironmentVariables && System.getenv().containsKey(getEnvironmentVariableName(key)) || properties.containsKey(key); } + public String getString(ConfigKey key) { + return getString(key.getKey()); + } + + @Deprecated public String getString(String key) { if (useEnvironmentVariables) { String value = System.getenv(getEnvironmentVariableName(key)); @@ -65,44 +78,89 @@ public class Config { return properties.getProperty(key); } + public String getString(ConfigKey key, String defaultValue) { + return getString(key.getKey(), defaultValue); + } + + @Deprecated public String getString(String key, String defaultValue) { return hasKey(key) ? getString(key) : defaultValue; } + public boolean getBoolean(ConfigKey key) { + return getBoolean(key.getKey()); + } + + @Deprecated public boolean getBoolean(String key) { return Boolean.parseBoolean(getString(key)); } + public int getInteger(ConfigKey key) { + return getInteger(key.getKey()); + } + + @Deprecated public int getInteger(String key) { return getInteger(key, 0); } + public int getInteger(ConfigKey key, int defaultValue) { + return getInteger(key.getKey(), defaultValue); + } + + @Deprecated public int getInteger(String key, int defaultValue) { return hasKey(key) ? Integer.parseInt(getString(key)) : defaultValue; } + public long getLong(ConfigKey key) { + return getLong(key.getKey()); + } + + @Deprecated public long getLong(String key) { return getLong(key, 0); } + public long getLong(ConfigKey key, long defaultValue) { + return getLong(key.getKey(), defaultValue); + } + + @Deprecated public long getLong(String key, long defaultValue) { return hasKey(key) ? Long.parseLong(getString(key)) : defaultValue; } + public double getDouble(ConfigKey key) { + return getDouble(key.getKey()); + } + + @Deprecated public double getDouble(String key) { return getDouble(key, 0.0); } + public double getDouble(ConfigKey key, double defaultValue) { + return getDouble(key.getKey(), defaultValue); + } + + @Deprecated public double getDouble(String key, double defaultValue) { return hasKey(key) ? Double.parseDouble(getString(key)) : defaultValue; } - public static String getEnvironmentVariableName(String key) { - return key.replaceAll("\\.", "_").replaceAll("(\\p{Lu})", "_$1").toUpperCase(); + public void setString(ConfigKey key, String value) { + setString(key.getKey(), value); } + @Deprecated public void setString(String key, String value) { properties.put(key, value); } + static String getEnvironmentVariableName(String key) { + return key.replaceAll("\\.", "_").replaceAll("(\\p{Lu})", "_$1").toUpperCase(); + } + } diff --git a/src/org/traccar/config/ConfigKey.java b/src/org/traccar/config/ConfigKey.java new file mode 100644 index 000000000..2e54ad392 --- /dev/null +++ b/src/org/traccar/config/ConfigKey.java @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.config; + +public class ConfigKey { + + private final String key; + private final Class clazz; + + ConfigKey(String key, Class clazz) { + this.key = key; + this.clazz = clazz; + } + + String getKey() { + return key; + } + + Class getValueClass() { + return clazz; + } + +} diff --git a/src/org/traccar/config/ConfigSuffix.java b/src/org/traccar/config/ConfigSuffix.java new file mode 100644 index 000000000..149b2cd00 --- /dev/null +++ b/src/org/traccar/config/ConfigSuffix.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.config; + +public class ConfigSuffix extends ConfigKey { + + ConfigSuffix(String key, Class clazz) { + super(key, clazz); + } + + public ConfigKey withPrefix(String prefix) { + return new ConfigKey(prefix + getKey(), getValueClass()); + } + +} diff --git a/src/org/traccar/config/Keys.java b/src/org/traccar/config/Keys.java new file mode 100644 index 000000000..48cf3e558 --- /dev/null +++ b/src/org/traccar/config/Keys.java @@ -0,0 +1,356 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.config; + +public final class Keys { + + /** + * Connection timeout value in seconds. Because sometimes there is no way to detect lost TCP connection old + * connections stay in open state. On most systems there is a limit on number of open connection, so this leads to + * problems with establishing new connections when number of devices is high or devices data connections are + * unstable. + */ + public static final ConfigSuffix PROTOCOL_TIMEOUT = new ConfigSuffix( + ".timeout", Integer.class); + + /** + * Server wide connection timeout value in seconds. See protocol timeout for more information. + */ + public static final ConfigKey SERVER_TIMEOUT = new ConfigKey( + "server.timeout", Integer.class); + + /** + * Address for uploading aggregated anonymous usage statistics. Uploaded information is the same you can see on the + * statistics screen in the web app. It does not include any sensitive (e.g. locations). + */ + public static final ConfigKey SERVER_STATISTICS = new ConfigKey( + "server.statistics", Boolean.class); + + /** + * Enable events subsystem. Flag to enable all events handlers. + */ + public static final ConfigKey EVENT_ENABLE = new ConfigKey( + "event.enable", Boolean.class); + + /** + * If true, the event is generated once at the beginning of overspeeding period. + */ + public static final ConfigKey EVENT_OVERSPEED_NOT_REPEAT = new ConfigKey( + "event.overspeed.notRepeat", Boolean.class); + + /** + * Minimal over speed duration to trigger the event. Value in seconds. + */ + public static final ConfigKey EVENT_OVERSPEED_MINIMAL_DURATION = new ConfigKey( + "event.overspeed.minimalDuration", Long.class); + + /** + * Relevant only for geofence speed limits. Use lowest speed limits from all geofences. + */ + public static final ConfigKey EVENT_OVERSPEED_PREFER_LOWEST = new ConfigKey( + "event.overspeed.preferLowest", Boolean.class); + + /** + * Do not generate alert event if same alert was present in last known location. + */ + public static final ConfigKey EVENT_IGNORE_DUPLICATE_ALERTS = new ConfigKey( + "event.ignoreDuplicateAlerts", Boolean.class); + + /** + * List of external handler classes to use in Netty pipeline. + */ + public static final ConfigKey EXTRA_HANDLERS = new ConfigKey( + "extra.handlers", String.class); + + /** + * Enable positions forwarding to other web server. + */ + public static final ConfigKey FORWARD_ENABLE = new ConfigKey( + "forward.enable", Boolean.class); + + /** + * URL to forward positions. Data is passed through URL parameters. For example, {uniqueId} for device identifier, + * {latitude} and {longitude} for coordinates. + */ + public static final ConfigKey FORWARD_URL = new ConfigKey( + "forward.url", String.class); + + /** + * Additional HTTP header, can be used for authorization. + */ + public static final ConfigKey FORWARD_HEADER = new ConfigKey( + "forward.header", String.class); + + /** + * Boolean value to enable forwarding in JSON format. + */ + public static final ConfigKey FORWARD_JSON = new ConfigKey( + "forward.json", Boolean.class); + + /** + * Boolean flag to enable or disable position filtering. + */ + public static final ConfigKey FILTER_ENABLE = new ConfigKey( + "filter.enable", Boolean.class); + + /** + * Filter invalid (valid field is set to false) positions. + */ + public static final ConfigKey FILTER_INVALID = new ConfigKey( + "filter.invalid", Boolean.class); + + /** + * Filter zero coordinates. Zero latitude and longitude are theoretically valid values, but it practice it usually + * indicates invalid GPS data. + */ + public static final ConfigKey FILTER_ZERO = new ConfigKey( + "filter.zero", Boolean.class); + + /** + * Filter duplicate records (duplicates are detected by time value). + */ + public static final ConfigKey FILTER_DUPLICATE = new ConfigKey( + "filter.duplicate", Boolean.class); + + /** + * Filter records with fix time in future. The values is specified in seconds. Records that have fix time more than + * specified number of seconds later than current server time would be filtered out. + */ + public static final ConfigKey FILTER_FUTURE = new ConfigKey( + "filter.future", Long.class); + + /** + * Filter positions with accuracy less than specified value in meters. + */ + public static final ConfigKey FILTER_ACCURACY = new ConfigKey( + "filter.accuracy", Integer.class); + + /** + * Filter cell and wifi locations that are coming from geolocation provider. + */ + public static final ConfigKey FILTER_APPROXIMATE = new ConfigKey( + "filter.approximate", Boolean.class); + + /** + * Filter positions with exactly zero speed values. + */ + public static final ConfigKey FILTER_STATIC = new ConfigKey( + "filter.static", Boolean.class); + + /** + * Filter records by distance. The values is specified in meters. If the new position is less far than this value + * from the last one it gets filtered out. + */ + public static final ConfigKey FILTER_DISTANCE = new ConfigKey( + "filter.distance", Integer.class); + + /** + * Filter records by Maximum Speed value in knots. Can be used to filter jumps to far locations even if they're + * marked as valid. Shouldn't be too low. Start testing with values at about 25000. + */ + public static final ConfigKey FILTER_MAX_SPEED = new ConfigKey( + "filter.maxSpeed", Integer.class); + + /** + * Filter position if time from previous position is less than specified value in seconds. + */ + public static final ConfigKey FILTER_MIN_PERIOD = new ConfigKey( + "filter.minPeriod", Integer.class); + + /** + * Time limit for the filtering in seconds. If the time difference between last position and a new one is more than + * this limit, the new position will not be filtered out. + */ + public static final ConfigKey FILTER_SKIP_LIMIT = new ConfigKey( + "filter.skipLimit", Long.class); + + /** + * Enable attributes skipping. Attribute skipping can be enabled in the config or device attributes. + */ + public static final ConfigKey FILTER_SKIP_ATTRIBUTES_ENABLE = new ConfigKey( + "filter.skipAttributes.enable", Boolean.class); + + /** + * Replaces coordinates with last known if change is less than a 'coordinates.error' meters. Helps to avoid + * coordinates jumps during parking period. + */ + public static final ConfigKey COORDINATES_FILTER = new ConfigKey( + "coordinates.filter", Boolean.class); + + /** + * Distance in meters. Distances below this value gets handled like explained in 'coordinates.filter'. + */ + public static final ConfigKey COORDINATES_MIN_ERROR = new ConfigKey( + "coordinates.minError", Integer.class); + + /** + * Distance in meters. Distances above this value gets handled like explained in 'coordinates.filter', but only if + * Position is also marked as 'invalid'. + */ + public static final ConfigKey COORDINATES_MAX_ERROR = new ConfigKey( + "filter.maxError", Integer.class); + + /** + * Enable to save device IP addresses information. Disabled by default. + */ + public static final ConfigKey PROCESSING_REMOTE_ADDRESS_ENABLE = new ConfigKey( + "processing.remoteAddress.enable", Boolean.class); + + /** + * Enable engine hours calculation on the server side. It uses ignition value to determine engine state. + */ + public static final ConfigKey PROCESSING_ENGINE_HOURS_ENABLE = new ConfigKey( + "processing.engineHours.enable", Boolean.class); + + /** + * Enable copying of missing attributes from last position to the current one. Might be useful if device doesn't + * send some values in every message. + */ + public static final ConfigKey PROCESSING_COPY_ATTRIBUTES_ENABLE = new ConfigKey( + "processing.copyAttributes.enable", Boolean.class); + + /** + * Enable computed attributes processing. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_ENABLE = new ConfigKey( + "processing.computedAttributes.enable", Boolean.class); + + /** + * Enable computed attributes processing. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new ConfigKey( + "processing.computedAttributes.deviceAttributes", Boolean.class); + + /** + * Boolean flag to enable or disable reverse geocoder. + */ + public static final ConfigKey GEOCODER_ENABLE = new ConfigKey( + "geocoder.enable", Boolean.class); + + /** + * Reverse geocoder type. Check reverse geocoding documentation for more info. By default (if the value is not + * specified) server uses Google API. + */ + public static final ConfigKey GEOCODER_TYPE = new ConfigKey( + "geocoder.type", String.class); + + /** + * Geocoder server URL. Applicable only to Nominatim and Gisgraphy providers. + */ + public static final ConfigKey GEOCODER_URL = new ConfigKey( + "geocoder.url", String.class); + + /** + * App id for use with Here provider. + */ + public static final ConfigKey GEOCODER_ID = new ConfigKey( + "geocoder.id", String.class); + + /** + * Provider API key. Most providers require API keys. + */ + public static final ConfigKey GEOCODER_KEY = new ConfigKey( + "geocoder.key", String.class); + + /** + * Language parameter for providers that support localization (e.g. Google and Nominatim). + */ + public static final ConfigKey GEOCODER_LANGUAGE = new ConfigKey( + "geocoder.language", String.class); + + /** + * Address format string. Default value is %h %r, %t, %s, %c. See AddressFormat for more info. + */ + public static final ConfigKey GEOCODER_FORMAT = new ConfigKey( + "geocoder.format", String.class); + + /** + * Cache size for geocoding results. + */ + public static final ConfigKey GEOCODER_CACHE_SIZE = new ConfigKey( + "geocoder.cacheSize", Integer.class); + + /** + * Disable automatic reverse geocoding requests for all positions. + */ + public static final ConfigKey GEOCODER_IGNORE_POSITIONS = new ConfigKey( + "geocoder.ignorePositions", Boolean.class); + + /** + * Boolean flag to apply reverse geocoding to invalid positions. + */ + public static final ConfigKey GEOCODER_PROCESS_INVALID_POSITIONS = new ConfigKey( + "geocoder.processInvalidPositions", Boolean.class); + + /** + * Optional parameter to specify minimum distance for new reverse geocoding request. If distance is less than + * specified value (in meters), then Traccar will reuse last known address. + */ + public static final ConfigKey GEOCODER_REUSE_DISTANCE = new ConfigKey( + "geocoder.reuseDistance", Integer.class); + + /** + * Boolean flag to enable LBS location resolution. Some devices send cell towers information and WiFi point when GPS + * location is not available. Traccar can determine coordinates based on that information using third party + * services. Default value is false. + */ + public static final ConfigKey GEOLOCATION_ENABLE = new ConfigKey( + "geolocation.enable", Boolean.class); + + /** + * Provider to use for LBS location. Available options: google, mozilla and opencellid. By default opencellid is + * used. You have to supply a key that you get from corresponding provider. For more information see LBS geolocation + * documentation. + */ + public static final ConfigKey GEOLOCATION_TYPE = new ConfigKey( + "geolocation.type", String.class); + + /** + * Geolocation provider API URL address. Not required for most providers. + */ + public static final ConfigKey GEOLOCATION_URL = new ConfigKey( + "geolocation.url", String.class); + + /** + * Provider API key. OpenCellID service requires API key. + */ + public static final ConfigKey GEOLOCATION_KEY = new ConfigKey( + "geolocation.key", String.class); + + /** + * Boolean flag to apply geolocation to invalid positions. + */ + public static final ConfigKey GEOLOCATION_PROCESS_INVALID_POSITIONS = new ConfigKey( + "geolocation.processInvalidPositions", Boolean.class); + + /** + * Override latitude sign / hemisphere. Useful in cases where value is incorrect because of device bug. Value can be + * N for North or S for South. + */ + public static final ConfigKey LOCATION_LATITUDE_HEMISPHERE = new ConfigKey( + "location.latitudeHemisphere", Boolean.class); + + /** + * Override longitude sign / hemisphere. Useful in cases where value is incorrect because of device bug. Value can + * be E for East or W for West. + */ + public static final ConfigKey LOCATION_LONGITUDE_HEMISPHERE = new ConfigKey( + "location.longitudeHemisphere", Boolean.class); + + private Keys() { + } + +} diff --git a/src/org/traccar/database/ConnectionManager.java b/src/org/traccar/database/ConnectionManager.java index 3d37af710..8bae1ea93 100644 --- a/src/org/traccar/database/ConnectionManager.java +++ b/src/org/traccar/database/ConnectionManager.java @@ -22,8 +22,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; import org.traccar.GlobalTimer; +import org.traccar.Main; import org.traccar.Protocol; -import org.traccar.events.OverspeedEventHandler; +import org.traccar.handler.events.MotionEventHandler; +import org.traccar.handler.events.OverspeedEventHandler; import org.traccar.model.Device; import org.traccar.model.DeviceState; import org.traccar.model.Event; @@ -147,13 +149,15 @@ public class ConnectionManager { DeviceState deviceState = Context.getDeviceManager().getDeviceState(deviceId); Map<Event, Position> result = new HashMap<>(); - Map<Event, Position> event = Context.getMotionEventHandler().updateMotionState(deviceState); + Map<Event, Position> event = Main.getInjector() + .getInstance(MotionEventHandler.class).updateMotionState(deviceState); if (event != null) { result.putAll(event); } - event = Context.getOverspeedEventHandler().updateOverspeedState(deviceState, Context.getDeviceManager(). - lookupAttributeDouble(deviceId, OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT, 0, false)); + event = Main.getInjector().getInstance(OverspeedEventHandler.class) + .updateOverspeedState(deviceState, Context.getDeviceManager(). + lookupAttributeDouble(deviceId, OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT, 0, false)); if (event != null) { result.putAll(event); } diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 8da6f2cca..8e9071736 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -39,7 +39,7 @@ import liquibase.resource.ResourceAccessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.Config; +import org.traccar.config.Config; import org.traccar.Context; import org.traccar.helper.DateUtil; import org.traccar.model.Attribute; diff --git a/src/org/traccar/database/DeviceManager.java b/src/org/traccar/database/DeviceManager.java index ab2c142cc..de4607d1f 100644 --- a/src/org/traccar/database/DeviceManager.java +++ b/src/org/traccar/database/DeviceManager.java @@ -27,7 +27,7 @@ import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.Config; +import org.traccar.config.Config; import org.traccar.Context; import org.traccar.model.Device; import org.traccar.model.DeviceState; @@ -310,6 +310,7 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity return result; } + @Override public boolean lookupAttributeBoolean( long deviceId, String attributeName, boolean defaultValue, boolean lookupConfig) { Object result = lookupAttribute(deviceId, attributeName, lookupConfig); @@ -319,12 +320,14 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity return defaultValue; } + @Override public String lookupAttributeString( long deviceId, String attributeName, String defaultValue, boolean lookupConfig) { Object result = lookupAttribute(deviceId, attributeName, lookupConfig); return result != null ? (String) result : defaultValue; } + @Override public int lookupAttributeInteger(long deviceId, String attributeName, int defaultValue, boolean lookupConfig) { Object result = lookupAttribute(deviceId, attributeName, lookupConfig); if (result != null) { @@ -333,6 +336,7 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity return defaultValue; } + @Override public long lookupAttributeLong( long deviceId, String attributeName, long defaultValue, boolean lookupConfig) { Object result = lookupAttribute(deviceId, attributeName, lookupConfig); diff --git a/src/org/traccar/database/IdentityManager.java b/src/org/traccar/database/IdentityManager.java index 59d2f9362..6228a0f75 100644 --- a/src/org/traccar/database/IdentityManager.java +++ b/src/org/traccar/database/IdentityManager.java @@ -38,4 +38,6 @@ public interface IdentityManager { long lookupAttributeLong(long deviceId, String attributeName, long defaultValue, boolean lookupConfig); + double lookupAttributeDouble(long deviceId, String attributeName, double defaultValue, boolean lookupConfig); + } diff --git a/src/org/traccar/database/LdapProvider.java b/src/org/traccar/database/LdapProvider.java index b30ab45ed..d8b5c9f52 100644 --- a/src/org/traccar/database/LdapProvider.java +++ b/src/org/traccar/database/LdapProvider.java @@ -25,7 +25,7 @@ import javax.naming.directory.SearchResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.Config; +import org.traccar.config.Config; import org.traccar.model.User; import java.util.Hashtable; diff --git a/src/org/traccar/database/MailManager.java b/src/org/traccar/database/MailManager.java index e64aa638a..8a2f002cd 100644 --- a/src/org/traccar/database/MailManager.java +++ b/src/org/traccar/database/MailManager.java @@ -19,6 +19,7 @@ package org.traccar.database; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; +import org.traccar.Main; import org.traccar.model.User; import org.traccar.notification.PropertiesProvider; @@ -134,7 +135,7 @@ public final class MailManager { } try (Transport transport = session.getTransport()) { - Context.getStatisticsManager().registerMail(); + Main.getInjector().getInstance(StatisticsManager.class).registerMail(); transport.connect( properties.getProperty("mail.smtp.host"), properties.getProperty("mail.smtp.username"), diff --git a/src/org/traccar/database/StatisticsManager.java b/src/org/traccar/database/StatisticsManager.java index 4e656bfd8..e59f8e767 100644 --- a/src/org/traccar/database/StatisticsManager.java +++ b/src/org/traccar/database/StatisticsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,10 +17,13 @@ package org.traccar.database; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.Context; +import org.traccar.config.Config; +import org.traccar.config.Keys; import org.traccar.helper.DateUtil; import org.traccar.model.Statistics; +import javax.inject.Inject; +import javax.ws.rs.client.Client; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Form; import java.sql.SQLException; @@ -36,6 +39,10 @@ public class StatisticsManager { private static final int SPLIT_MODE = Calendar.DAY_OF_MONTH; + private final Config config; + private final DataManager dataManager; + private final Client client; + private AtomicInteger lastUpdate = new AtomicInteger(Calendar.getInstance().get(SPLIT_MODE)); private Set<Long> users = new HashSet<>(); @@ -49,6 +56,13 @@ public class StatisticsManager { private int geocoderRequests; private int geolocationRequests; + @Inject + public StatisticsManager(Config config, DataManager dataManager, Client client) { + this.config = config; + this.dataManager = dataManager; + this.client = client; + } + private void checkSplit() { int currentUpdate = Calendar.getInstance().get(SPLIT_MODE); if (lastUpdate.getAndSet(currentUpdate) != currentUpdate) { @@ -65,17 +79,17 @@ public class StatisticsManager { statistics.setGeolocationRequests(geolocationRequests); try { - Context.getDataManager().addObject(statistics); + dataManager.addObject(statistics); } catch (SQLException e) { LOGGER.warn("Error saving statistics", e); } - String url = Context.getConfig().getString("server.statistics"); + String url = config.getString(Keys.SERVER_STATISTICS); if (url != null) { String time = DateUtil.formatDate(statistics.getCaptureTime()); Form form = new Form(); - form.param("version", Context.getAppVersion()); + form.param("version", getClass().getPackage().getImplementationVersion()); form.param("captureTime", time); form.param("activeUsers", String.valueOf(statistics.getActiveUsers())); form.param("activeDevices", String.valueOf(statistics.getActiveDevices())); @@ -87,7 +101,7 @@ public class StatisticsManager { form.param("geocoderRequests", String.valueOf(statistics.getGeocoderRequests())); form.param("geolocationRequests", String.valueOf(statistics.getGeolocationRequests())); - Context.getClient().target(url).request().async().post(Entity.form(form)); + client.target(url).request().async().post(Entity.form(form)); } users.clear(); diff --git a/src/org/traccar/processing/ComputedAttributesHandler.java b/src/org/traccar/handler/ComputedAttributesHandler.java index c346661d3..153da29b9 100644 --- a/src/org/traccar/processing/ComputedAttributesHandler.java +++ b/src/org/traccar/handler/ComputedAttributesHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.processing; +package org.traccar.handler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -32,7 +32,10 @@ import org.apache.commons.jexl2.MapContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.BaseDataHandler; -import org.traccar.Context; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.database.AttributesManager; +import org.traccar.database.IdentityManager; import org.traccar.model.Attribute; import org.traccar.model.Device; import org.traccar.model.Position; @@ -42,23 +45,27 @@ public class ComputedAttributesHandler extends BaseDataHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ComputedAttributesHandler.class); - private JexlEngine engine; + private final IdentityManager identityManager; + private final AttributesManager attributesManager; - private boolean mapDeviceAttributes; + private final JexlEngine engine; - public ComputedAttributesHandler() { + private final boolean includeDeviceAttributes; + + public ComputedAttributesHandler( + Config config, IdentityManager identityManager, AttributesManager attributesManager) { + this.identityManager = identityManager; + this.attributesManager = attributesManager; engine = new JexlEngine(); engine.setStrict(true); - engine.setFunctions(Collections.singletonMap("math", (Object) Math.class)); - if (Context.getConfig() != null) { - mapDeviceAttributes = Context.getConfig().getBoolean("processing.computedAttributes.deviceAttributes"); - } + engine.setFunctions(Collections.singletonMap("math", Math.class)); + includeDeviceAttributes = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES); } private MapContext prepareContext(Position position) { MapContext result = new MapContext(); - if (mapDeviceAttributes) { - Device device = Context.getIdentityManager().getById(position.getDeviceId()); + if (includeDeviceAttributes) { + Device device = identityManager.getById(position.getDeviceId()); if (device != null) { for (Object key : device.getAttributes().keySet()) { result.set((String) key, device.getAttributes().get(key)); @@ -87,14 +94,18 @@ public class ComputedAttributesHandler extends BaseDataHandler { return result; } + /** + * @deprecated logic needs to be extracted to be used in API resource + */ + @Deprecated public Object computeAttribute(Attribute attribute, Position position) throws JexlException { return engine.createExpression(attribute.getExpression()).evaluate(prepareContext(position)); } @Override protected Position handlePosition(Position position) { - Collection<Attribute> attributes = Context.getAttributesManager().getItems( - Context.getAttributesManager().getAllDeviceItems(position.getDeviceId())); + Collection<Attribute> attributes = attributesManager.getItems( + attributesManager.getAllDeviceItems(position.getDeviceId())); for (Attribute attribute : attributes) { if (attribute.getAttribute() != null) { Object result = null; diff --git a/src/org/traccar/processing/CopyAttributesHandler.java b/src/org/traccar/handler/CopyAttributesHandler.java index bdd73b141..6a0966d33 100644 --- a/src/org/traccar/processing/CopyAttributesHandler.java +++ b/src/org/traccar/handler/CopyAttributesHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2016 - 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,33 +14,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.processing; +package org.traccar.handler; import io.netty.channel.ChannelHandler; import org.traccar.BaseDataHandler; -import org.traccar.Context; +import org.traccar.database.IdentityManager; import org.traccar.model.Position; @ChannelHandler.Sharable public class CopyAttributesHandler extends BaseDataHandler { - private Position getLastPosition(long deviceId) { - if (Context.getIdentityManager() != null) { - return Context.getIdentityManager().getLastPosition(deviceId); - } - return null; + private IdentityManager identityManager; + + public CopyAttributesHandler(IdentityManager identityManager) { + this.identityManager = identityManager; } @Override protected Position handlePosition(Position position) { - String attributesString = Context.getDeviceManager().lookupAttributeString( + String attributesString = identityManager.lookupAttributeString( position.getDeviceId(), "processing.copyAttributes", "", true); - Position last = getLastPosition(position.getDeviceId()); if (attributesString.isEmpty()) { attributesString = Position.KEY_DRIVER_UNIQUE_ID; } else { attributesString += "," + Position.KEY_DRIVER_UNIQUE_ID; } + Position last = identityManager.getLastPosition(position.getDeviceId()); if (last != null) { for (String attribute : attributesString.split("[ ,]")) { if (last.getAttributes().containsKey(attribute) && !position.getAttributes().containsKey(attribute)) { diff --git a/src/org/traccar/DefaultDataHandler.java b/src/org/traccar/handler/DefaultDataHandler.java index 876ecd90e..9d8ea044d 100644 --- a/src/org/traccar/DefaultDataHandler.java +++ b/src/org/traccar/handler/DefaultDataHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,21 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; +import io.netty.channel.ChannelHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.traccar.BaseDataHandler; +import org.traccar.database.DataManager; import org.traccar.model.Position; +@ChannelHandler.Sharable public class DefaultDataHandler extends BaseDataHandler { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultDataHandler.class); + private final DataManager dataManager; + + public DefaultDataHandler(DataManager dataManager) { + this.dataManager = dataManager; + } + @Override protected Position handlePosition(Position position) { try { - Context.getDataManager().addObject(position); + dataManager.addObject(position); } catch (Exception error) { LOGGER.warn("Failed to store position", error); } diff --git a/src/org/traccar/DistanceHandler.java b/src/org/traccar/handler/DistanceHandler.java index 657f74edf..a336a884e 100644 --- a/src/org/traccar/DistanceHandler.java +++ b/src/org/traccar/handler/DistanceHandler.java @@ -1,6 +1,6 @@ /* * Copyright 2015 Amila Silva - * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; import io.netty.channel.ChannelHandler; +import org.traccar.BaseDataHandler; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.database.IdentityManager; import org.traccar.helper.DistanceCalculator; import org.traccar.model.Position; @@ -26,21 +30,17 @@ import java.math.RoundingMode; @ChannelHandler.Sharable public class DistanceHandler extends BaseDataHandler { + private final IdentityManager identityManager; + private final boolean filter; private final int coordinatesMinError; private final int coordinatesMaxError; - public DistanceHandler(boolean filter, int coordinatesMinError, int coordinatesMaxError) { - this.filter = filter; - this.coordinatesMinError = coordinatesMinError; - this.coordinatesMaxError = coordinatesMaxError; - } - - private Position getLastPosition(long deviceId) { - if (Context.getIdentityManager() != null) { - return Context.getIdentityManager().getLastPosition(deviceId); - } - return null; + public DistanceHandler(Config config, IdentityManager identityManager) { + this.identityManager = identityManager; + this.filter = config.getBoolean(Keys.COORDINATES_FILTER); + this.coordinatesMinError = config.getInteger(Keys.COORDINATES_MIN_ERROR); + this.coordinatesMaxError = config.getInteger(Keys.COORDINATES_MAX_ERROR); } @Override @@ -52,7 +52,7 @@ public class DistanceHandler extends BaseDataHandler { } double totalDistance = 0.0; - Position last = getLastPosition(position.getDeviceId()); + Position last = identityManager != null ? identityManager.getLastPosition(position.getDeviceId()) : null; if (last != null) { totalDistance = last.getDouble(Position.KEY_TOTAL_DISTANCE); if (!position.getAttributes().containsKey(Position.KEY_DISTANCE)) { diff --git a/src/org/traccar/EngineHoursHandler.java b/src/org/traccar/handler/EngineHoursHandler.java index c9fbc186c..92da84e6b 100644 --- a/src/org/traccar/EngineHoursHandler.java +++ b/src/org/traccar/handler/EngineHoursHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,18 +14,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; import io.netty.channel.ChannelHandler; +import org.traccar.BaseDataHandler; +import org.traccar.database.IdentityManager; import org.traccar.model.Position; @ChannelHandler.Sharable public class EngineHoursHandler extends BaseDataHandler { + private final IdentityManager identityManager; + + public EngineHoursHandler(IdentityManager identityManager) { + this.identityManager = identityManager; + } + @Override protected Position handlePosition(Position position) { if (!position.getAttributes().containsKey(Position.KEY_HOURS)) { - Position last = Context.getIdentityManager().getLastPosition(position.getDeviceId()); + Position last = identityManager.getLastPosition(position.getDeviceId()); if (last != null) { long hours = last.getLong(Position.KEY_HOURS); if (last.getBoolean(Position.KEY_IGNITION) && position.getBoolean(Position.KEY_IGNITION)) { diff --git a/src/org/traccar/FilterHandler.java b/src/org/traccar/handler/FilterHandler.java index b127e190a..dceaede01 100644 --- a/src/org/traccar/FilterHandler.java +++ b/src/org/traccar/handler/FilterHandler.java @@ -13,11 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; import io.netty.channel.ChannelHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.traccar.BaseDataHandler; +import org.traccar.Context; +import org.traccar.config.Config; +import org.traccar.config.Keys; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; @@ -39,70 +43,19 @@ public class FilterHandler extends BaseDataHandler { private long skipLimit; private boolean skipAttributes; - public void setFilterInvalid(boolean filterInvalid) { - this.filterInvalid = filterInvalid; - } - - public void setFilterZero(boolean filterZero) { - this.filterZero = filterZero; - } - - public void setFilterDuplicate(boolean filterDuplicate) { - this.filterDuplicate = filterDuplicate; - } - - public void setFilterFuture(long filterFuture) { - this.filterFuture = filterFuture; - } - - public void setFilterAccuracy(int filterAccuracy) { - this.filterAccuracy = filterAccuracy; - } - - public void setFilterApproximate(boolean filterApproximate) { - this.filterApproximate = filterApproximate; - } - - public void setFilterStatic(boolean filterStatic) { - this.filterStatic = filterStatic; - } - - public void setFilterDistance(int filterDistance) { - this.filterDistance = filterDistance; - } - - public void setFilterMaxSpeed(int filterMaxSpeed) { - this.filterMaxSpeed = filterMaxSpeed; - } - - public void setFilterMinPeriod(int filterMinPeriod) { - this.filterMinPeriod = filterMinPeriod; - } - - public void setSkipLimit(long skipLimit) { - this.skipLimit = skipLimit; - } - - public void setSkipAttributes(boolean skipAttributes) { - this.skipAttributes = skipAttributes; - } - - public FilterHandler() { - Config config = Context.getConfig(); - if (config != null) { - filterInvalid = config.getBoolean("filter.invalid"); - filterZero = config.getBoolean("filter.zero"); - filterDuplicate = config.getBoolean("filter.duplicate"); - filterFuture = config.getLong("filter.future") * 1000; - filterAccuracy = config.getInteger("filter.accuracy"); - filterApproximate = config.getBoolean("filter.approximate"); - filterStatic = config.getBoolean("filter.static"); - filterDistance = config.getInteger("filter.distance"); - filterMaxSpeed = config.getInteger("filter.maxSpeed"); - filterMinPeriod = config.getInteger("filter.minPeriod") * 1000; - skipLimit = config.getLong("filter.skipLimit") * 1000; - skipAttributes = config.getBoolean("filter.skipAttributes.enable"); - } + public FilterHandler(Config config) { + filterInvalid = config.getBoolean(Keys.FILTER_INVALID); + filterZero = config.getBoolean(Keys.FILTER_ZERO); + filterDuplicate = config.getBoolean(Keys.FILTER_DUPLICATE); + filterFuture = config.getLong(Keys.FILTER_FUTURE) * 1000; + filterAccuracy = config.getInteger(Keys.FILTER_ACCURACY); + filterApproximate = config.getBoolean(Keys.FILTER_APPROXIMATE); + filterStatic = config.getBoolean(Keys.FILTER_STATIC); + filterDistance = config.getInteger(Keys.FILTER_DISTANCE); + filterMaxSpeed = config.getInteger(Keys.FILTER_MAX_SPEED); + filterMinPeriod = config.getInteger(Keys.FILTER_MIN_PERIOD) * 1000; + skipLimit = config.getLong(Keys.FILTER_SKIP_LIMIT) * 1000; + skipAttributes = config.getBoolean(Keys.FILTER_SKIP_ATTRIBUTES_ENABLE); } private boolean filterInvalid(Position position) { @@ -196,17 +149,13 @@ public class FilterHandler extends BaseDataHandler { last = Context.getIdentityManager().getLastPosition(position.getDeviceId()); } - if (skipLimit(position, last) || skipAttributes(position)) { - return false; - } - if (filterInvalid(position)) { filterType.append("Invalid "); } if (filterZero(position)) { filterType.append("Zero "); } - if (filterDuplicate(position, last)) { + if (filterDuplicate(position, last) && !skipLimit(position, last) && !skipAttributes(position)) { filterType.append("Duplicate "); } if (filterFuture(position)) { @@ -218,10 +167,10 @@ public class FilterHandler extends BaseDataHandler { if (filterApproximate(position)) { filterType.append("Approximate "); } - if (filterStatic(position)) { + if (filterStatic(position) && !skipLimit(position, last) && !skipAttributes(position)) { filterType.append("Static "); } - if (filterDistance(position, last)) { + if (filterDistance(position, last) && !skipLimit(position, last) && !skipAttributes(position)) { filterType.append("Distance "); } if (filterMaxSpeed(position, last)) { diff --git a/src/org/traccar/GeocoderHandler.java b/src/org/traccar/handler/GeocoderHandler.java index 72f164948..b96f01b3a 100644 --- a/src/org/traccar/GeocoderHandler.java +++ b/src/org/traccar/handler/GeocoderHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2012 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.traccar.Context; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.database.IdentityManager; +import org.traccar.database.StatisticsManager; import org.traccar.geocoder.Geocoder; import org.traccar.model.Position; @@ -29,23 +34,29 @@ public class GeocoderHandler extends ChannelInboundHandlerAdapter { private static final Logger LOGGER = LoggerFactory.getLogger(GeocoderHandler.class); private final Geocoder geocoder; + private final IdentityManager identityManager; + private final StatisticsManager statisticsManager; + private final boolean ignorePositions; private final boolean processInvalidPositions; private final int geocoderReuseDistance; - public GeocoderHandler(Geocoder geocoder, boolean processInvalidPositions) { + public GeocoderHandler( + Config config, Geocoder geocoder, IdentityManager identityManager, StatisticsManager statisticsManager) { this.geocoder = geocoder; - this.processInvalidPositions = processInvalidPositions; - - geocoderReuseDistance = Context.getConfig().getInteger("geocoder.reuseDistance", 0); + this.identityManager = identityManager; + this.statisticsManager = statisticsManager; + ignorePositions = Context.getConfig().getBoolean(Keys.GEOCODER_IGNORE_POSITIONS); + processInvalidPositions = config.getBoolean(Keys.GEOCODER_PROCESS_INVALID_POSITIONS); + geocoderReuseDistance = config.getInteger(Keys.GEOCODER_REUSE_DISTANCE, 0); } @Override - public void channelRead(final ChannelHandlerContext ctx, Object message) throws Exception { - if (message instanceof Position) { + public void channelRead(final ChannelHandlerContext ctx, Object message) { + if (message instanceof Position && !ignorePositions) { final Position position = (Position) message; if (processInvalidPositions || position.getValid()) { if (geocoderReuseDistance != 0) { - Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId()); + Position lastPosition = identityManager.getLastPosition(position.getDeviceId()); if (lastPosition != null && lastPosition.getAddress() != null && position.getDouble(Position.KEY_DISTANCE) <= geocoderReuseDistance) { position.setAddress(lastPosition.getAddress()); @@ -54,7 +65,9 @@ public class GeocoderHandler extends ChannelInboundHandlerAdapter { } } - Context.getStatisticsManager().registerGeocoderRequest(); + if (statisticsManager != null) { + statisticsManager.registerGeocoderRequest(); + } geocoder.getAddress(position.getLatitude(), position.getLongitude(), new Geocoder.ReverseGeocoderCallback() { diff --git a/src/org/traccar/GeolocationHandler.java b/src/org/traccar/handler/GeolocationHandler.java index 97b5fda6a..c7b39e491 100644 --- a/src/org/traccar/GeolocationHandler.java +++ b/src/org/traccar/handler/GeolocationHandler.java @@ -13,13 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.database.StatisticsManager; import org.traccar.geolocation.GeolocationProvider; import org.traccar.model.Position; @@ -29,20 +32,25 @@ public class GeolocationHandler extends ChannelInboundHandlerAdapter { private static final Logger LOGGER = LoggerFactory.getLogger(GeolocationHandler.class); private final GeolocationProvider geolocationProvider; + private final StatisticsManager statisticsManager; private final boolean processInvalidPositions; - public GeolocationHandler(GeolocationProvider geolocationProvider, boolean processInvalidPositions) { + public GeolocationHandler( + Config config, GeolocationProvider geolocationProvider, StatisticsManager statisticsManager) { this.geolocationProvider = geolocationProvider; - this.processInvalidPositions = processInvalidPositions; + this.statisticsManager = statisticsManager; + this.processInvalidPositions = config.getBoolean(Keys.GEOLOCATION_PROCESS_INVALID_POSITIONS); } @Override - public void channelRead(final ChannelHandlerContext ctx, Object message) throws Exception { + public void channelRead(final ChannelHandlerContext ctx, Object message) { if (message instanceof Position) { final Position position = (Position) message; if ((position.getOutdated() || processInvalidPositions && !position.getValid()) && position.getNetwork() != null) { - Context.getStatisticsManager().registerGeolocationRequest(); + if (statisticsManager != null) { + statisticsManager.registerGeolocationRequest(); + } geolocationProvider.getLocation(position.getNetwork(), new GeolocationProvider.LocationProviderCallback() { diff --git a/src/org/traccar/HemisphereHandler.java b/src/org/traccar/handler/HemisphereHandler.java index d1bcd340b..aff3d8a64 100644 --- a/src/org/traccar/HemisphereHandler.java +++ b/src/org/traccar/handler/HemisphereHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,9 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; import io.netty.channel.ChannelHandler; +import org.traccar.BaseDataHandler; +import org.traccar.config.Config; +import org.traccar.config.Keys; import org.traccar.model.Position; @ChannelHandler.Sharable @@ -24,8 +27,8 @@ public class HemisphereHandler extends BaseDataHandler { private int latitudeFactor; private int longitudeFactor; - public HemisphereHandler() { - String latitudeHemisphere = Context.getConfig().getString("location.latitudeHemisphere"); + public HemisphereHandler(Config config) { + String latitudeHemisphere = config.getString(Keys.LOCATION_LATITUDE_HEMISPHERE); if (latitudeHemisphere != null) { if (latitudeHemisphere.equalsIgnoreCase("N")) { latitudeFactor = 1; @@ -33,7 +36,7 @@ public class HemisphereHandler extends BaseDataHandler { latitudeFactor = -1; } } - String longitudeHemisphere = Context.getConfig().getString("location.longitudeHemisphere"); + String longitudeHemisphere = config.getString(Keys.LOCATION_LATITUDE_HEMISPHERE); if (longitudeHemisphere != null) { if (longitudeHemisphere.equalsIgnoreCase("E")) { longitudeFactor = 1; diff --git a/src/org/traccar/MotionHandler.java b/src/org/traccar/handler/MotionHandler.java index ec9a5ffd7..e8051dd75 100644 --- a/src/org/traccar/MotionHandler.java +++ b/src/org/traccar/handler/MotionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; import io.netty.channel.ChannelHandler; +import org.traccar.BaseDataHandler; import org.traccar.model.Position; @ChannelHandler.Sharable diff --git a/src/org/traccar/handler/NetworkMessageHandler.java b/src/org/traccar/handler/NetworkMessageHandler.java new file mode 100644 index 000000000..b1d926bfa --- /dev/null +++ b/src/org/traccar/handler/NetworkMessageHandler.java @@ -0,0 +1,57 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.socket.DatagramChannel; +import io.netty.channel.socket.DatagramPacket; +import org.traccar.NetworkMessage; + +import java.net.InetSocketAddress; + +public class NetworkMessageHandler extends ChannelDuplexHandler { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + if (ctx.channel() instanceof DatagramChannel) { + DatagramPacket packet = (DatagramPacket) msg; + ctx.fireChannelRead(new NetworkMessage(packet.content(), packet.sender())); + } else if (msg instanceof ByteBuf) { + ByteBuf buffer = (ByteBuf) msg; + ctx.fireChannelRead(new NetworkMessage(buffer, ctx.channel().remoteAddress())); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { + if (msg instanceof NetworkMessage) { + NetworkMessage message = (NetworkMessage) msg; + if (ctx.channel() instanceof DatagramChannel) { + InetSocketAddress recipient = (InetSocketAddress) message.getRemoteAddress(); + InetSocketAddress sender = (InetSocketAddress) ctx.channel().localAddress(); + ctx.write(new DatagramPacket((ByteBuf) message.getMessage(), recipient, sender), promise); + } else { + ctx.write(message.getMessage(), promise); + } + } else { + ctx.write(msg, promise); + } + } + +} diff --git a/src/org/traccar/handler/OpenChannelHandler.java b/src/org/traccar/handler/OpenChannelHandler.java new file mode 100644 index 000000000..d09d617ab --- /dev/null +++ b/src/org/traccar/handler/OpenChannelHandler.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.handler; + +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import org.traccar.TrackerServer; + +public class OpenChannelHandler extends ChannelDuplexHandler { + + private final TrackerServer server; + + public OpenChannelHandler(TrackerServer server) { + this.server = server; + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + super.channelActive(ctx); + server.getChannelGroup().add(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + server.getChannelGroup().remove(ctx.channel()); + } + +} diff --git a/src/org/traccar/RemoteAddressHandler.java b/src/org/traccar/handler/RemoteAddressHandler.java index aabc5715e..c09b8c39a 100644 --- a/src/org/traccar/RemoteAddressHandler.java +++ b/src/org/traccar/handler/RemoteAddressHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; diff --git a/src/org/traccar/handler/StandardLoggingHandler.java b/src/org/traccar/handler/StandardLoggingHandler.java new file mode 100644 index 000000000..88010458f --- /dev/null +++ b/src/org/traccar/handler/StandardLoggingHandler.java @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.traccar.NetworkMessage; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +public class StandardLoggingHandler extends ChannelDuplexHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(StandardLoggingHandler.class); + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + log(ctx, false, msg); + super.channelRead(ctx, msg); + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + log(ctx, true, msg); + super.write(ctx, msg, promise); + } + + public void log(ChannelHandlerContext ctx, boolean downstream, Object o) { + if (o instanceof NetworkMessage) { + NetworkMessage networkMessage = (NetworkMessage) o; + if (networkMessage.getMessage() instanceof ByteBuf) { + log(ctx, downstream, networkMessage.getRemoteAddress(), (ByteBuf) networkMessage.getMessage()); + } + } else if (o instanceof ByteBuf) { + log(ctx, downstream, ctx.channel().remoteAddress(), (ByteBuf) o); + } + } + + public void log(ChannelHandlerContext ctx, boolean downstream, SocketAddress remoteAddress, ByteBuf buf) { + StringBuilder message = new StringBuilder(); + + message.append("[").append(ctx.channel().id().asShortText()).append(": "); + message.append(((InetSocketAddress) ctx.channel().localAddress()).getPort()); + if (downstream) { + message.append(" > "); + } else { + message.append(" < "); + } + + if (remoteAddress instanceof InetSocketAddress) { + message.append(((InetSocketAddress) remoteAddress).getHostString()); + } else { + message.append("unknown"); + } + message.append("]"); + + message.append(" HEX: "); + message.append(ByteBufUtil.hexDump(buf)); + + LOGGER.info(message.toString()); + } + +} diff --git a/src/org/traccar/events/AlertEventHandler.java b/src/org/traccar/handler/events/AlertEventHandler.java index b14869e72..0b7c8d23e 100644 --- a/src/org/traccar/events/AlertEventHandler.java +++ b/src/org/traccar/handler/events/AlertEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,24 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import java.util.Collections; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; -import org.traccar.Context; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.database.IdentityManager; import org.traccar.model.Event; import org.traccar.model.Position; @ChannelHandler.Sharable public class AlertEventHandler extends BaseEventHandler { + private final IdentityManager identityManager; private final boolean ignoreDuplicateAlerts; - public AlertEventHandler() { - ignoreDuplicateAlerts = Context.getConfig().getBoolean("event.ignoreDuplicateAlerts"); + public AlertEventHandler(Config config, IdentityManager identityManager) { + this.identityManager = identityManager; + ignoreDuplicateAlerts = config.getBoolean(Keys.EVENT_IGNORE_DUPLICATE_ALERTS); } @Override @@ -39,7 +42,7 @@ public class AlertEventHandler extends BaseEventHandler { if (alarm != null) { boolean ignoreAlert = false; if (ignoreDuplicateAlerts) { - Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId()); + Position lastPosition = identityManager.getLastPosition(position.getDeviceId()); if (lastPosition != null && alarm.equals(lastPosition.getAttributes().get(Position.KEY_ALARM))) { ignoreAlert = true; } diff --git a/src/org/traccar/BaseEventHandler.java b/src/org/traccar/handler/events/BaseEventHandler.java index 50bbbefa2..41f677f6c 100644 --- a/src/org/traccar/BaseEventHandler.java +++ b/src/org/traccar/handler/events/BaseEventHandler.java @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar; +package org.traccar.handler.events; import java.util.Map; +import org.traccar.BaseDataHandler; +import org.traccar.Context; import org.traccar.model.Event; import org.traccar.model.Position; diff --git a/src/org/traccar/events/CommandResultEventHandler.java b/src/org/traccar/handler/events/CommandResultEventHandler.java index 89ec44190..cfe676653 100644 --- a/src/org/traccar/events/CommandResultEventHandler.java +++ b/src/org/traccar/handler/events/CommandResultEventHandler.java @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import java.util.Collections; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; import org.traccar.model.Event; import org.traccar.model.Position; diff --git a/src/org/traccar/events/DriverEventHandler.java b/src/org/traccar/handler/events/DriverEventHandler.java index c8efd0576..994df93fa 100644 --- a/src/org/traccar/events/DriverEventHandler.java +++ b/src/org/traccar/handler/events/DriverEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,29 +14,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import java.util.Collections; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; -import org.traccar.Context; +import org.traccar.database.IdentityManager; import org.traccar.model.Event; import org.traccar.model.Position; @ChannelHandler.Sharable public class DriverEventHandler extends BaseEventHandler { + private final IdentityManager identityManager; + + public DriverEventHandler(IdentityManager identityManager) { + this.identityManager = identityManager; + } + @Override protected Map<Event, Position> analyzePosition(Position position) { - if (!Context.getIdentityManager().isLatestPosition(position)) { + if (!identityManager.isLatestPosition(position)) { return null; } String driverUniqueId = position.getString(Position.KEY_DRIVER_UNIQUE_ID); if (driverUniqueId != null) { String oldDriverUniqueId = null; - Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId()); + Position lastPosition = identityManager.getLastPosition(position.getDeviceId()); if (lastPosition != null) { oldDriverUniqueId = lastPosition.getString(Position.KEY_DRIVER_UNIQUE_ID); } diff --git a/src/org/traccar/events/FuelDropEventHandler.java b/src/org/traccar/handler/events/FuelDropEventHandler.java index 31b17d500..59de61bba 100644 --- a/src/org/traccar/events/FuelDropEventHandler.java +++ b/src/org/traccar/handler/events/FuelDropEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; -import org.traccar.Context; +import org.traccar.database.IdentityManager; import org.traccar.model.Device; import org.traccar.model.Event; import org.traccar.model.Position; @@ -30,22 +29,28 @@ public class FuelDropEventHandler extends BaseEventHandler { public static final String ATTRIBUTE_FUEL_DROP_THRESHOLD = "fuelDropThreshold"; + private final IdentityManager identityManager; + + public FuelDropEventHandler(IdentityManager identityManager) { + this.identityManager = identityManager; + } + @Override protected Map<Event, Position> analyzePosition(Position position) { - Device device = Context.getIdentityManager().getById(position.getDeviceId()); + Device device = identityManager.getById(position.getDeviceId()); if (device == null) { return null; } - if (!Context.getIdentityManager().isLatestPosition(position)) { + if (!identityManager.isLatestPosition(position)) { return null; } - double fuelDropThreshold = Context.getDeviceManager() + double fuelDropThreshold = identityManager .lookupAttributeDouble(device.getId(), ATTRIBUTE_FUEL_DROP_THRESHOLD, 0, false); if (fuelDropThreshold > 0) { - Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId()); + Position lastPosition = identityManager.getLastPosition(position.getDeviceId()); if (position.getAttributes().containsKey(Position.KEY_FUEL_LEVEL) && lastPosition != null && lastPosition.getAttributes().containsKey(Position.KEY_FUEL_LEVEL)) { diff --git a/src/org/traccar/events/GeofenceEventHandler.java b/src/org/traccar/handler/events/GeofenceEventHandler.java index 313553195..067c97957 100644 --- a/src/org/traccar/events/GeofenceEventHandler.java +++ b/src/org/traccar/handler/events/GeofenceEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import java.util.ArrayList; import java.util.HashMap; @@ -21,9 +21,9 @@ import java.util.List; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; -import org.traccar.Context; +import org.traccar.database.CalendarManager; import org.traccar.database.GeofenceManager; +import org.traccar.database.IdentityManager; import org.traccar.model.Calendar; import org.traccar.model.Device; import org.traccar.model.Event; @@ -32,19 +32,24 @@ import org.traccar.model.Position; @ChannelHandler.Sharable public class GeofenceEventHandler extends BaseEventHandler { - private GeofenceManager geofenceManager; + private final IdentityManager identityManager; + private final GeofenceManager geofenceManager; + private final CalendarManager calendarManager; - public GeofenceEventHandler() { - geofenceManager = Context.getGeofenceManager(); + public GeofenceEventHandler( + IdentityManager identityManager, GeofenceManager geofenceManager, CalendarManager calendarManager) { + this.identityManager = identityManager; + this.geofenceManager = geofenceManager; + this.calendarManager = calendarManager; } @Override protected Map<Event, Position> analyzePosition(Position position) { - Device device = Context.getIdentityManager().getById(position.getDeviceId()); + Device device = identityManager.getById(position.getDeviceId()); if (device == null) { return null; } - if (!Context.getIdentityManager().isLatestPosition(position) || !position.getValid()) { + if (!identityManager.isLatestPosition(position) || !position.getValid()) { return null; } @@ -62,7 +67,7 @@ public class GeofenceEventHandler extends BaseEventHandler { Map<Event, Position> events = new HashMap<>(); for (long geofenceId : oldGeofences) { long calendarId = geofenceManager.getById(geofenceId).getCalendarId(); - Calendar calendar = calendarId != 0 ? Context.getCalendarManager().getById(calendarId) : null; + Calendar calendar = calendarId != 0 ? calendarManager.getById(calendarId) : null; if (calendar == null || calendar.checkMoment(position.getFixTime())) { Event event = new Event(Event.TYPE_GEOFENCE_EXIT, position.getDeviceId(), position.getId()); event.setGeofenceId(geofenceId); @@ -71,7 +76,7 @@ public class GeofenceEventHandler extends BaseEventHandler { } for (long geofenceId : newGeofences) { long calendarId = geofenceManager.getById(geofenceId).getCalendarId(); - Calendar calendar = calendarId != 0 ? Context.getCalendarManager().getById(calendarId) : null; + Calendar calendar = calendarId != 0 ? calendarManager.getById(calendarId) : null; if (calendar == null || calendar.checkMoment(position.getFixTime())) { Event event = new Event(Event.TYPE_GEOFENCE_ENTER, position.getDeviceId(), position.getId()); event.setGeofenceId(geofenceId); @@ -80,4 +85,5 @@ public class GeofenceEventHandler extends BaseEventHandler { } return events; } + } diff --git a/src/org/traccar/events/IgnitionEventHandler.java b/src/org/traccar/handler/events/IgnitionEventHandler.java index a17f15318..ec133bafc 100644 --- a/src/org/traccar/events/IgnitionEventHandler.java +++ b/src/org/traccar/handler/events/IgnitionEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import java.util.Collections; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; -import org.traccar.Context; +import org.traccar.database.IdentityManager; import org.traccar.model.Device; import org.traccar.model.Event; import org.traccar.model.Position; @@ -29,10 +28,16 @@ import org.traccar.model.Position; @ChannelHandler.Sharable public class IgnitionEventHandler extends BaseEventHandler { + private final IdentityManager identityManager; + + public IgnitionEventHandler(IdentityManager identityManager) { + this.identityManager = identityManager; + } + @Override protected Map<Event, Position> analyzePosition(Position position) { - Device device = Context.getIdentityManager().getById(position.getDeviceId()); - if (device == null || !Context.getIdentityManager().isLatestPosition(position)) { + Device device = identityManager.getById(position.getDeviceId()); + if (device == null || !identityManager.isLatestPosition(position)) { return null; } @@ -41,7 +46,7 @@ public class IgnitionEventHandler extends BaseEventHandler { if (position.getAttributes().containsKey(Position.KEY_IGNITION)) { boolean ignition = position.getBoolean(Position.KEY_IGNITION); - Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId()); + Position lastPosition = identityManager.getLastPosition(position.getDeviceId()); if (lastPosition != null && lastPosition.getAttributes().containsKey(Position.KEY_IGNITION)) { boolean oldIgnition = lastPosition.getBoolean(Position.KEY_IGNITION); diff --git a/src/org/traccar/events/MaintenanceEventHandler.java b/src/org/traccar/handler/events/MaintenanceEventHandler.java index 5bebb1baf..93ae74142 100644 --- a/src/org/traccar/events/MaintenanceEventHandler.java +++ b/src/org/traccar/handler/events/MaintenanceEventHandler.java @@ -14,14 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import java.util.HashMap; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; -import org.traccar.Context; +import org.traccar.database.IdentityManager; +import org.traccar.database.MaintenancesManager; import org.traccar.model.Event; import org.traccar.model.Maintenance; import org.traccar.model.Position; @@ -29,21 +29,29 @@ import org.traccar.model.Position; @ChannelHandler.Sharable public class MaintenanceEventHandler extends BaseEventHandler { + private final IdentityManager identityManager; + private final MaintenancesManager maintenancesManager; + + public MaintenanceEventHandler(IdentityManager identityManager, MaintenancesManager maintenancesManager) { + this.identityManager = identityManager; + this.maintenancesManager = maintenancesManager; + } + @Override protected Map<Event, Position> analyzePosition(Position position) { - if (Context.getIdentityManager().getById(position.getDeviceId()) == null - || !Context.getIdentityManager().isLatestPosition(position)) { + if (identityManager.getById(position.getDeviceId()) == null + || !identityManager.isLatestPosition(position)) { return null; } - Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId()); + Position lastPosition = identityManager.getLastPosition(position.getDeviceId()); if (lastPosition == null) { return null; } Map<Event, Position> events = new HashMap<>(); - for (long maintenanceId : Context.getMaintenancesManager().getAllDeviceItems(position.getDeviceId())) { - Maintenance maintenance = Context.getMaintenancesManager().getById(maintenanceId); + for (long maintenanceId : maintenancesManager.getAllDeviceItems(position.getDeviceId())) { + Maintenance maintenance = maintenancesManager.getById(maintenanceId); if (maintenance.getPeriod() != 0) { double oldValue = lastPosition.getDouble(maintenance.getType()); double newValue = position.getDouble(maintenance.getType()); diff --git a/src/org/traccar/events/MotionEventHandler.java b/src/org/traccar/handler/events/MotionEventHandler.java index 4047b83a4..9ec02ccfb 100644 --- a/src/org/traccar/events/MotionEventHandler.java +++ b/src/org/traccar/handler/events/MotionEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import java.util.Collections; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; -import org.traccar.Context; +import org.traccar.database.DeviceManager; +import org.traccar.database.IdentityManager; import org.traccar.model.Device; import org.traccar.model.DeviceState; import org.traccar.model.Event; @@ -32,9 +32,13 @@ import org.traccar.reports.model.TripsConfig; @ChannelHandler.Sharable public class MotionEventHandler extends BaseEventHandler { - private TripsConfig tripsConfig; + private final IdentityManager identityManager; + private final DeviceManager deviceManager; + private final TripsConfig tripsConfig; - public MotionEventHandler(TripsConfig tripsConfig) { + public MotionEventHandler(IdentityManager identityManager, DeviceManager deviceManager, TripsConfig tripsConfig) { + this.identityManager = identityManager; + this.deviceManager = deviceManager; this.tripsConfig = tripsConfig; } @@ -107,24 +111,24 @@ public class MotionEventHandler extends BaseEventHandler { protected Map<Event, Position> analyzePosition(Position position) { long deviceId = position.getDeviceId(); - Device device = Context.getIdentityManager().getById(deviceId); + Device device = identityManager.getById(deviceId); if (device == null) { return null; } - if (!Context.getIdentityManager().isLatestPosition(position) + if (!identityManager.isLatestPosition(position) || !tripsConfig.getProcessInvalidPositions() && !position.getValid()) { return null; } Map<Event, Position> result = null; - DeviceState deviceState = Context.getDeviceManager().getDeviceState(deviceId); + DeviceState deviceState = deviceManager.getDeviceState(deviceId); if (deviceState.getMotionState() == null) { deviceState.setMotionState(position.getBoolean(Position.KEY_MOTION)); } else { result = updateMotionState(deviceState, position); } - Context.getDeviceManager().setDeviceState(deviceId, deviceState); + deviceManager.setDeviceState(deviceId, deviceState); return result; } diff --git a/src/org/traccar/events/OverspeedEventHandler.java b/src/org/traccar/handler/events/OverspeedEventHandler.java index 4f9a35793..157bb64e0 100644 --- a/src/org/traccar/events/OverspeedEventHandler.java +++ b/src/org/traccar/handler/events/OverspeedEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.handler.events; import java.util.Collections; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.BaseEventHandler; -import org.traccar.Context; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.database.DeviceManager; +import org.traccar.database.GeofenceManager; import org.traccar.model.Device; import org.traccar.model.DeviceState; import org.traccar.model.Event; @@ -31,22 +33,28 @@ import org.traccar.model.Position; @ChannelHandler.Sharable public class OverspeedEventHandler extends BaseEventHandler { + public static final String ATTRIBUTE_SPEED = "speed"; public static final String ATTRIBUTE_SPEED_LIMIT = "speedLimit"; - private boolean notRepeat; - private boolean preferLowest; - private long minimalDuration; + private final DeviceManager deviceManager; + private final GeofenceManager geofenceManager; - public OverspeedEventHandler(long minimalDuration, boolean notRepeat, boolean preferLowest) { - this.notRepeat = notRepeat; - this.minimalDuration = minimalDuration; - this.preferLowest = preferLowest; + private final boolean notRepeat; + private final long minimalDuration; + private final boolean preferLowest; + + public OverspeedEventHandler(Config config, DeviceManager deviceManager, GeofenceManager geofenceManager) { + this.deviceManager = deviceManager; + this.geofenceManager = geofenceManager; + notRepeat = config.getBoolean(Keys.EVENT_OVERSPEED_NOT_REPEAT); + minimalDuration = config.getLong(Keys.EVENT_OVERSPEED_MINIMAL_DURATION) * 1000; + preferLowest = config.getBoolean(Keys.EVENT_OVERSPEED_PREFER_LOWEST); } private Map<Event, Position> newEvent(DeviceState deviceState, double speedLimit) { Position position = deviceState.getOverspeedPosition(); Event event = new Event(Event.TYPE_DEVICE_OVERSPEED, position.getDeviceId(), position.getId()); - event.set("speed", deviceState.getOverspeedPosition().getSpeed()); + event.set(ATTRIBUTE_SPEED, deviceState.getOverspeedPosition().getSpeed()); event.set(ATTRIBUTE_SPEED_LIMIT, speedLimit); event.setGeofenceId(deviceState.getOverspeedGeofenceId()); deviceState.setOverspeedState(notRepeat); @@ -104,22 +112,22 @@ public class OverspeedEventHandler extends BaseEventHandler { protected Map<Event, Position> analyzePosition(Position position) { long deviceId = position.getDeviceId(); - Device device = Context.getIdentityManager().getById(deviceId); + Device device = deviceManager.getById(deviceId); if (device == null) { return null; } - if (!Context.getIdentityManager().isLatestPosition(position) || !position.getValid()) { + if (!deviceManager.isLatestPosition(position) || !position.getValid()) { return null; } - double speedLimit = Context.getDeviceManager().lookupAttributeDouble(deviceId, ATTRIBUTE_SPEED_LIMIT, 0, false); + double speedLimit = deviceManager.lookupAttributeDouble(deviceId, ATTRIBUTE_SPEED_LIMIT, 0, false); double geofenceSpeedLimit = 0; long overspeedGeofenceId = 0; - if (Context.getGeofenceManager() != null && device.getGeofenceIds() != null) { + if (geofenceManager != null && device.getGeofenceIds() != null) { for (long geofenceId : device.getGeofenceIds()) { - Geofence geofence = Context.getGeofenceManager().getById(geofenceId); + Geofence geofence = geofenceManager.getById(geofenceId); if (geofence != null) { double currentSpeedLimit = geofence.getDouble(ATTRIBUTE_SPEED_LIMIT); if (currentSpeedLimit > 0 && geofenceSpeedLimit == 0 @@ -140,7 +148,7 @@ public class OverspeedEventHandler extends BaseEventHandler { } Map<Event, Position> result = null; - DeviceState deviceState = Context.getDeviceManager().getDeviceState(deviceId); + DeviceState deviceState = deviceManager.getDeviceState(deviceId); if (deviceState.getOverspeedState() == null) { deviceState.setOverspeedState(position.getSpeed() > speedLimit); @@ -149,7 +157,7 @@ public class OverspeedEventHandler extends BaseEventHandler { result = updateOverspeedState(deviceState, position, speedLimit, overspeedGeofenceId); } - Context.getDeviceManager().setDeviceState(deviceId, deviceState); + deviceManager.setDeviceState(deviceId, deviceState); return result; } diff --git a/src/org/traccar/helper/Log.java b/src/org/traccar/helper/Log.java index df0c9abc1..f328e8ce9 100644 --- a/src/org/traccar/helper/Log.java +++ b/src/org/traccar/helper/Log.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2012 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ */ package org.traccar.helper; -import org.traccar.Config; +import org.traccar.config.Config; import java.io.BufferedWriter; import java.io.File; @@ -25,6 +25,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; @@ -162,12 +163,17 @@ public final class Log { } public static void setupDefaultLogger() { - File jarPath = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()); - File logsPath = new File(jarPath, "logs"); - if (!logsPath.exists() || !logsPath.isDirectory()) { - logsPath = jarPath; + String path = null; + URL url = ClassLoader.getSystemClassLoader().getResource("."); + if (url != null) { + File jarPath = new File(url.getPath()); + File logsPath = new File(jarPath, "logs"); + if (!logsPath.exists() || !logsPath.isDirectory()) { + logsPath = jarPath; + } + path = new File(logsPath, "tracker-server.log").getPath(); } - setupLogger(false, new File(logsPath, "tracker-server.log").getPath(), Level.WARNING.getName(), false, true); + setupLogger(path == null, path, Level.WARNING.getName(), false, true); } public static void setupLogger(Config config) { @@ -237,7 +243,7 @@ public final class Log { s.append("*"); } else { file = element.getFileName(); - s.append(file.substring(0, file.length() - 5)); // remove ".java" + s.append(file, 0, file.length() - 5); // remove ".java" count -= 1; } s.append(":").append(element.getLineNumber()); diff --git a/src/org/traccar/helper/PatternBuilder.java b/src/org/traccar/helper/PatternBuilder.java index f3de5c1e5..5c4638189 100644 --- a/src/org/traccar/helper/PatternBuilder.java +++ b/src/org/traccar/helper/PatternBuilder.java @@ -56,7 +56,7 @@ public class PatternBuilder { } public PatternBuilder any() { - fragments.add(".*?"); + fragments.add(".*"); return this; } diff --git a/src/org/traccar/model/Server.java b/src/org/traccar/model/Server.java index 66aa7ee75..ad37e7078 100644 --- a/src/org/traccar/model/Server.java +++ b/src/org/traccar/model/Server.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,14 +15,13 @@ */ package org.traccar.model; -import org.traccar.Context; import org.traccar.database.QueryIgnore; public class Server extends ExtendedModel { @QueryIgnore public String getVersion() { - return Context.getAppVersion(); + return getClass().getPackage().getImplementationVersion(); } public void setVersion(String version) { diff --git a/src/org/traccar/notification/EventForwarder.java b/src/org/traccar/notification/EventForwarder.java index b8990d84f..c0010ebbd 100644 --- a/src/org/traccar/notification/EventForwarder.java +++ b/src/org/traccar/notification/EventForwarder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,8 +15,6 @@ */ package org.traccar.notification; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.traccar.Context; import org.traccar.model.Device; import org.traccar.model.Event; @@ -52,25 +50,15 @@ public abstract class EventForwarder { Invocation.Builder requestBuilder = Context.getClient().target(url).request(); if (header != null && !header.isEmpty()) { - for (Map.Entry<String, String> entry : splitKeyValues(header, ":").entries()) { - requestBuilder = requestBuilder.header(entry.getKey(), entry.getValue()); + for (String line: header.split("\\r?\\n")) { + String[] values = line.split(":", 2); + requestBuilder.header(values[0].trim(), values[1].trim()); } } executeRequest(event, position, users, requestBuilder.async()); } - protected MultiValuedMap<String, String> splitKeyValues(String params, String separator) { - MultiValuedMap<String, String> data = new ArrayListValuedHashMap<>(); - for (String line: params.split("\\r?\\n")) { - String[] values = line.split(separator, 2); - if (values.length == 2) { - data.put(values[0].trim(), values[1].trim()); - } - } - return data; - } - protected Map<String, Object> preparePayload(Event event, Position position, Set<Long> users) { Map<String, Object> data = new HashMap<>(); data.put(KEY_EVENT, event); diff --git a/src/org/traccar/notification/PropertiesProvider.java b/src/org/traccar/notification/PropertiesProvider.java index 8f5965a82..f0078feef 100644 --- a/src/org/traccar/notification/PropertiesProvider.java +++ b/src/org/traccar/notification/PropertiesProvider.java @@ -15,7 +15,7 @@ */ package org.traccar.notification; -import org.traccar.Config; +import org.traccar.config.Config; import org.traccar.model.ExtendedModel; public class PropertiesProvider { diff --git a/src/org/traccar/notificators/NotificatorSms.java b/src/org/traccar/notificators/NotificatorSms.java index d4052c626..d5c791eae 100644 --- a/src/org/traccar/notificators/NotificatorSms.java +++ b/src/org/traccar/notificators/NotificatorSms.java @@ -17,6 +17,8 @@ package org.traccar.notificators; import org.traccar.Context; +import org.traccar.Main; +import org.traccar.database.StatisticsManager; import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.model.User; @@ -41,7 +43,7 @@ public final class NotificatorSms extends Notificator { public void sendAsync(long userId, Event event, Position position) { final User user = Context.getPermissionsManager().getUser(userId); if (user.getPhone() != null) { - Context.getStatisticsManager().registerSms(); + Main.getInjector().getInstance(StatisticsManager.class).registerSms(); smsManager.sendMessageAsync(user.getPhone(), NotificationFormatter.formatShortMessage(userId, event, position), false); } @@ -51,7 +53,7 @@ public final class NotificatorSms extends Notificator { public void sendSync(long userId, Event event, Position position) throws MessageException, InterruptedException { final User user = Context.getPermissionsManager().getUser(userId); if (user.getPhone() != null) { - Context.getStatisticsManager().registerSms(); + Main.getInjector().getInstance(StatisticsManager.class).registerSms(); smsManager.sendMessageSync(user.getPhone(), NotificationFormatter.formatShortMessage(userId, event, position), false); } diff --git a/src/org/traccar/protocol/BoxProtocolDecoder.java b/src/org/traccar/protocol/BoxProtocolDecoder.java index 9f3ce29b2..d7b401a2d 100644 --- a/src/org/traccar/protocol/BoxProtocolDecoder.java +++ b/src/org/traccar/protocol/BoxProtocolDecoder.java @@ -20,6 +20,7 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; import org.traccar.NetworkMessage; import org.traccar.Protocol; +import org.traccar.helper.BitUtil; import org.traccar.helper.Parser; import org.traccar.helper.PatternBuilder; import org.traccar.helper.UnitsConverter; @@ -84,16 +85,16 @@ public class BoxProtocolDecoder extends BaseProtocolDecoder { position.setTime(parser.nextDateTime()); - position.setLatitude(parser.nextDouble(0)); - position.setLongitude(parser.nextDouble(0)); - position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0))); - position.setCourse(parser.nextDouble(0)); + position.setLatitude(parser.nextDouble()); + position.setLongitude(parser.nextDouble()); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble())); + position.setCourse(parser.nextDouble()); - position.set(Position.KEY_ODOMETER_TRIP, parser.nextDouble(0) * 1000); + position.set(Position.KEY_ODOMETER_TRIP, parser.nextDouble() * 1000); position.set(Position.KEY_EVENT, parser.next()); - int status = parser.nextInt(0); - position.setValid((status & 0x04) == 0); + int status = parser.nextInt(); + position.setValid(!BitUtil.check(status, 2)); position.set(Position.KEY_STATUS, status); return position; diff --git a/src/org/traccar/protocol/CguardProtocolDecoder.java b/src/org/traccar/protocol/CguardProtocolDecoder.java index 9786afd6a..d934921f1 100644 --- a/src/org/traccar/protocol/CguardProtocolDecoder.java +++ b/src/org/traccar/protocol/CguardProtocolDecoder.java @@ -101,7 +101,11 @@ public class CguardProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_SATELLITES, Integer.parseInt(value)); break; case "BAT1": - position.set(Position.KEY_BATTERY_LEVEL, Integer.parseInt(value)); + if (value.contains(".")) { + position.set(Position.KEY_BATTERY, Double.parseDouble(value)); + } else { + position.set(Position.KEY_BATTERY_LEVEL, Integer.parseInt(value)); + } break; case "PWR1": position.set(Position.KEY_POWER, Double.parseDouble(value)); diff --git a/src/org/traccar/protocol/EnforaProtocol.java b/src/org/traccar/protocol/EnforaProtocol.java index 3bbbee6a2..f78e4b377 100644 --- a/src/org/traccar/protocol/EnforaProtocol.java +++ b/src/org/traccar/protocol/EnforaProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,13 @@ public class EnforaProtocol extends BaseProtocol { pipeline.addLast(new EnforaProtocolDecoder(EnforaProtocol.this)); } }); + addServer(new TrackerServer(true, getName()) { + @Override + protected void addProtocolHandlers(PipelineBuilder pipeline) { + pipeline.addLast(new EnforaProtocolEncoder()); + pipeline.addLast(new EnforaProtocolDecoder(EnforaProtocol.this)); + } + }); } } diff --git a/src/org/traccar/protocol/FifotrackProtocol.java b/src/org/traccar/protocol/FifotrackProtocol.java index 5de581c7a..371e01e55 100644 --- a/src/org/traccar/protocol/FifotrackProtocol.java +++ b/src/org/traccar/protocol/FifotrackProtocol.java @@ -17,6 +17,7 @@ package org.traccar.protocol; import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; import org.traccar.BaseProtocol; import org.traccar.PipelineBuilder; import org.traccar.TrackerServer; @@ -28,6 +29,7 @@ public class FifotrackProtocol extends BaseProtocol { @Override protected void addProtocolHandlers(PipelineBuilder pipeline) { pipeline.addLast(new LineBasedFrameDecoder(1024)); + pipeline.addLast(new StringEncoder()); pipeline.addLast(new StringDecoder()); pipeline.addLast(new FifotrackProtocolDecoder(FifotrackProtocol.this)); } diff --git a/src/org/traccar/protocol/FifotrackProtocolDecoder.java b/src/org/traccar/protocol/FifotrackProtocolDecoder.java index 4412df86b..5831a75dd 100644 --- a/src/org/traccar/protocol/FifotrackProtocolDecoder.java +++ b/src/org/traccar/protocol/FifotrackProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,15 @@ */ package org.traccar.protocol; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; +import org.traccar.NetworkMessage; import org.traccar.Protocol; +import org.traccar.helper.Checksum; +import org.traccar.helper.DataConverter; import org.traccar.helper.Parser; import org.traccar.helper.PatternBuilder; import org.traccar.helper.UnitsConverter; @@ -31,6 +36,8 @@ import java.util.regex.Pattern; public class FifotrackProtocolDecoder extends BaseProtocolDecoder { + private ByteBuf photo; + public FifotrackProtocolDecoder(Protocol protocol) { super(protocol); } @@ -65,11 +72,43 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder { .any() .compile(); - @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + private static final Pattern PATTERN_PHOTO = new PatternBuilder() + .text("$$") + .number("d+,") // length + .number("(d+),") // imei + .any() + .number("(d+),") // length + .expression("([^*]+)") // photo id + .text("*") + .number("xx") + .compile(); + + private static final Pattern PATTERN_PHOTO_DATA = new PatternBuilder() + .text("$$") + .number("d+,") // length + .number("(d+),") // imei + .expression("([^*]+)") // photo id + .number("(d+),") // offset + .number("(d+),") // size + .number("(x+)") // data + .text("*") + .number("xx") + .compile(); - Parser parser = new Parser(PATTERN, (String) msg); + private void requestPhoto(Channel channel, SocketAddress socketAddress, String imei, String file) { + if (channel != null) { + String content = "D06," + file + "," + photo.writerIndex() + "," + Math.min(1024, photo.writableBytes()); + int length = 1 + imei.length() + 1 + content.length() + 5; + String response = String.format("@@%02d,%s,%s*", length, imei, content); + response += Checksum.sum(response) + "\r\n"; + channel.writeAndFlush(new NetworkMessage(response, socketAddress)); + } + } + + private Object decodeLocation( + Channel channel, SocketAddress remoteAddress, String sentence) { + + Parser parser = new Parser(PATTERN, sentence); if (!parser.matches()) { return null; } @@ -122,4 +161,38 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder { return position; } + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + String sentence = (String) msg; + int typeIndex = sentence.indexOf(',', sentence.indexOf(',', sentence.indexOf(',') + 1) + 1) + 1; + String type = sentence.substring(typeIndex, typeIndex + 3); + + if (type.equals("D05")) { + Parser parser = new Parser(PATTERN_PHOTO, sentence); + if (parser.matches()) { + String imei = parser.next(); + int length = parser.nextInt(); + String photoId = parser.next(); + photo = Unpooled.buffer(length); + requestPhoto(channel, remoteAddress, imei, photoId); + } + } else if (type.equals("D06")) { + Parser parser = new Parser(PATTERN_PHOTO_DATA, sentence); + if (parser.matches()) { + String imei = parser.next(); + String photoId = parser.next(); + parser.nextInt(); // offset + parser.nextInt(); // size + photo.writeBytes(DataConverter.parseHex(parser.next())); + requestPhoto(channel, remoteAddress, imei, photoId); + } + } else { + return decodeLocation(channel, remoteAddress, sentence); + } + + return null; + } + } diff --git a/src/org/traccar/protocol/ItsProtocolDecoder.java b/src/org/traccar/protocol/ItsProtocolDecoder.java index e2b1dc238..a200ff8b7 100644 --- a/src/org/traccar/protocol/ItsProtocolDecoder.java +++ b/src/org/traccar/protocol/ItsProtocolDecoder.java @@ -36,22 +36,22 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder { private static final Pattern PATTERN = new PatternBuilder() .expression("[^$]*") - .text("$,") - .expression("[^,]+,") // event + .text("$") + .expression(",?[^,]+,") // event .groupBegin() .expression("[^,]+,") // vendor .expression("[^,]+,") // firmware version - .groupEnd("?") .expression("[^,]+,") // type - .groupBegin() .number("d+,") .expression("[LH],") // history - .groupEnd("?") + .or() + .expression("[^,]+,") // type + .groupEnd() .number("(d{15}),") // imei .groupBegin() .expression("(?:NM|SP),") // status .or() - .expression("[^,]+,") // vehicle registration + .expression("[^,]*,") // vehicle registration .number("([01]),") // valid .groupEnd() .number("(dd),?(dd),?(dddd),") // date (ddmmyyyy) diff --git a/src/org/traccar/protocol/L100ProtocolDecoder.java b/src/org/traccar/protocol/L100ProtocolDecoder.java index 4d6b8f34b..9868de435 100644 --- a/src/org/traccar/protocol/L100ProtocolDecoder.java +++ b/src/org/traccar/protocol/L100ProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -189,6 +189,10 @@ public class L100ProtocolDecoder extends BaseProtocolDecoder { parser.nextInt(), parser.nextInt(), parser.nextHexInt(), parser.nextHexInt(), rssi))); } + if (channel != null) { + channel.writeAndFlush(new NetworkMessage(String.valueOf((char) 0x01), remoteAddress)); + } + return position; } diff --git a/src/org/traccar/protocol/OwnTracksProtocolDecoder.java b/src/org/traccar/protocol/OwnTracksProtocolDecoder.java index 4ce880316..323d97fa3 100644 --- a/src/org/traccar/protocol/OwnTracksProtocolDecoder.java +++ b/src/org/traccar/protocol/OwnTracksProtocolDecoder.java @@ -56,7 +56,7 @@ public class OwnTracksProtocolDecoder extends BaseHttpProtocolDecoder { return null; } - Position position = new Position(); + Position position = new Position(getProtocolName()); String uniqueId; if (root.containsKey("topic")) { @@ -84,7 +84,6 @@ public class OwnTracksProtocolDecoder extends BaseHttpProtocolDecoder { } position.setDeviceId(deviceSession.getDeviceId()); - position.setProtocol(getProtocolName()); position.setTime(new Date(root.getJsonNumber("tst").longValue() * 1000)); if (root.containsKey("sent")) { diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java index c80cd9cda..974d2c106 100644 --- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java +++ b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java @@ -97,7 +97,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { response.writeByte(1); // nod response.writeShort(0); response.writeShort(Checksum.crc16( - Checksum.CRC16_IBM, response.nioBuffer(8, response.readableBytes() - 8))); + Checksum.CRC16_IBM, response.nioBuffer(8, response.readableBytes() - 10))); channel.writeAndFlush(new NetworkMessage(response, remoteAddress)); } } diff --git a/src/org/traccar/reports/ReportUtils.java b/src/org/traccar/reports/ReportUtils.java index ea383d598..3a631e0d9 100644 --- a/src/org/traccar/reports/ReportUtils.java +++ b/src/org/traccar/reports/ReportUtils.java @@ -26,7 +26,9 @@ import org.jxls.transform.Transformer; import org.jxls.transform.poi.PoiTransformer; import org.jxls.util.TransformerFactory; import org.traccar.Context; -import org.traccar.events.MotionEventHandler; +import org.traccar.database.DeviceManager; +import org.traccar.database.IdentityManager; +import org.traccar.handler.events.MotionEventHandler; import org.traccar.model.DeviceState; import org.traccar.model.Driver; import org.traccar.model.Event; @@ -323,6 +325,7 @@ public final class ReportUtils { } public static <T extends BaseReport> Collection<T> detectTripsAndStops( + IdentityManager identityManager, DeviceManager deviceManager, Collection<Position> positionCollection, TripsConfig tripsConfig, boolean ignoreOdometer, Class<T> reportClass) { @@ -331,7 +334,7 @@ public final class ReportUtils { ArrayList<Position> positions = new ArrayList<>(positionCollection); if (!positions.isEmpty()) { boolean trips = reportClass.equals(TripReport.class); - MotionEventHandler motionHandler = new MotionEventHandler(tripsConfig); + MotionEventHandler motionHandler = new MotionEventHandler(identityManager, deviceManager, tripsConfig); DeviceState deviceState = new DeviceState(); deviceState.setMotionState(isMoving(positions, 0, tripsConfig)); int startEventIndex = trips == deviceState.getMotionState() ? 0 : -1; diff --git a/src/org/traccar/reports/Stops.java b/src/org/traccar/reports/Stops.java index aa7a1ef20..98c9cef00 100644 --- a/src/org/traccar/reports/Stops.java +++ b/src/org/traccar/reports/Stops.java @@ -28,6 +28,9 @@ import java.util.Date; import org.apache.poi.ss.util.WorkbookUtil; import org.traccar.Context; +import org.traccar.Main; +import org.traccar.database.DeviceManager; +import org.traccar.database.IdentityManager; import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.reports.model.DeviceReport; @@ -42,8 +45,11 @@ public final class Stops { boolean ignoreOdometer = Context.getDeviceManager() .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true); + IdentityManager identityManager = Main.getInjector().getInstance(IdentityManager.class); + DeviceManager deviceManager = Main.getInjector().getInstance(DeviceManager.class); + return ReportUtils.detectTripsAndStops( - Context.getDataManager().getPositions(deviceId, from, to), + identityManager, deviceManager, Context.getDataManager().getPositions(deviceId, from, to), Context.getTripsConfig(), ignoreOdometer, StopReport.class); } diff --git a/src/org/traccar/reports/Trips.java b/src/org/traccar/reports/Trips.java index 792833c27..3cda65553 100644 --- a/src/org/traccar/reports/Trips.java +++ b/src/org/traccar/reports/Trips.java @@ -27,6 +27,9 @@ import java.util.Date; import org.apache.poi.ss.util.WorkbookUtil; import org.traccar.Context; +import org.traccar.Main; +import org.traccar.database.DeviceManager; +import org.traccar.database.IdentityManager; import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.reports.model.DeviceReport; @@ -41,8 +44,11 @@ public final class Trips { boolean ignoreOdometer = Context.getDeviceManager() .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true); + IdentityManager identityManager = Main.getInjector().getInstance(IdentityManager.class); + DeviceManager deviceManager = Main.getInjector().getInstance(DeviceManager.class); + return ReportUtils.detectTripsAndStops( - Context.getDataManager().getPositions(deviceId, from, to), + identityManager, deviceManager, Context.getDataManager().getPositions(deviceId, from, to), Context.getTripsConfig(), ignoreOdometer, TripReport.class); } diff --git a/src/org/traccar/sms/smpp/ClientSmppSessionHandler.java b/src/org/traccar/sms/smpp/ClientSmppSessionHandler.java index f48721ff9..6b9de3107 100644 --- a/src/org/traccar/sms/smpp/ClientSmppSessionHandler.java +++ b/src/org/traccar/sms/smpp/ClientSmppSessionHandler.java @@ -18,7 +18,6 @@ package org.traccar.sms.smpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.events.TextMessageEventHandler; import com.cloudhopper.commons.charset.CharsetUtil; import com.cloudhopper.smpp.SmppConstants; diff --git a/src/org/traccar/events/TextMessageEventHandler.java b/src/org/traccar/sms/smpp/TextMessageEventHandler.java index be4a193a7..37c29972d 100644 --- a/src/org/traccar/events/TextMessageEventHandler.java +++ b/src/org/traccar/sms/smpp/TextMessageEventHandler.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.traccar.events; +package org.traccar.sms.smpp; import org.traccar.Context; import org.traccar.model.Device; diff --git a/src/org/traccar/web/WebServer.java b/src/org/traccar/web/WebServer.java index 13a5a4238..70fef4ed3 100644 --- a/src/org/traccar/web/WebServer.java +++ b/src/org/traccar/web/WebServer.java @@ -30,7 +30,7 @@ import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.servlet.ServletContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.Config; +import org.traccar.config.Config; import org.traccar.api.AsyncSocketServlet; import org.traccar.api.CorsResponseFilter; import org.traccar.api.MediaFilter; |