aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/org/traccar/BasePipelineFactory.java312
-rw-r--r--src/org/traccar/BaseProtocolDecoder.java4
-rw-r--r--src/org/traccar/Context.java159
-rw-r--r--src/org/traccar/Main.java4
-rw-r--r--src/org/traccar/MainEventHandler.java5
-rw-r--r--src/org/traccar/MainModule.java337
-rw-r--r--src/org/traccar/WebDataHandler.java51
-rw-r--r--src/org/traccar/api/MediaFilter.java4
-rw-r--r--src/org/traccar/api/SecurityRequestFilter.java6
-rw-r--r--src/org/traccar/api/resource/AttributeResource.java11
-rw-r--r--src/org/traccar/config/Config.java (renamed from src/org/traccar/Config.java)68
-rw-r--r--src/org/traccar/config/ConfigKey.java36
-rw-r--r--src/org/traccar/config/ConfigSuffix.java28
-rw-r--r--src/org/traccar/config/Keys.java356
-rw-r--r--src/org/traccar/database/ConnectionManager.java12
-rw-r--r--src/org/traccar/database/DataManager.java2
-rw-r--r--src/org/traccar/database/DeviceManager.java6
-rw-r--r--src/org/traccar/database/IdentityManager.java2
-rw-r--r--src/org/traccar/database/LdapProvider.java2
-rw-r--r--src/org/traccar/database/MailManager.java3
-rw-r--r--src/org/traccar/database/StatisticsManager.java26
-rw-r--r--src/org/traccar/handler/ComputedAttributesHandler.java (renamed from src/org/traccar/processing/ComputedAttributesHandler.java)39
-rw-r--r--src/org/traccar/handler/CopyAttributesHandler.java (renamed from src/org/traccar/processing/CopyAttributesHandler.java)19
-rw-r--r--src/org/traccar/handler/DefaultDataHandler.java (renamed from src/org/traccar/DefaultDataHandler.java)16
-rw-r--r--src/org/traccar/handler/DistanceHandler.java (renamed from src/org/traccar/DistanceHandler.java)28
-rw-r--r--src/org/traccar/handler/EngineHoursHandler.java (renamed from src/org/traccar/EngineHoursHandler.java)14
-rw-r--r--src/org/traccar/handler/FilterHandler.java (renamed from src/org/traccar/FilterHandler.java)93
-rw-r--r--src/org/traccar/handler/GeocoderHandler.java (renamed from src/org/traccar/GeocoderHandler.java)33
-rw-r--r--src/org/traccar/handler/GeolocationHandler.java (renamed from src/org/traccar/GeolocationHandler.java)18
-rw-r--r--src/org/traccar/handler/HemisphereHandler.java (renamed from src/org/traccar/HemisphereHandler.java)13
-rw-r--r--src/org/traccar/handler/MotionHandler.java (renamed from src/org/traccar/MotionHandler.java)5
-rw-r--r--src/org/traccar/handler/NetworkMessageHandler.java57
-rw-r--r--src/org/traccar/handler/OpenChannelHandler.java42
-rw-r--r--src/org/traccar/handler/RemoteAddressHandler.java (renamed from src/org/traccar/RemoteAddressHandler.java)2
-rw-r--r--src/org/traccar/handler/StandardLoggingHandler.java81
-rw-r--r--src/org/traccar/handler/events/AlertEventHandler.java (renamed from src/org/traccar/events/AlertEventHandler.java)17
-rw-r--r--src/org/traccar/handler/events/BaseEventHandler.java (renamed from src/org/traccar/BaseEventHandler.java)4
-rw-r--r--src/org/traccar/handler/events/CommandResultEventHandler.java (renamed from src/org/traccar/events/CommandResultEventHandler.java)3
-rw-r--r--src/org/traccar/handler/events/DriverEventHandler.java (renamed from src/org/traccar/events/DriverEventHandler.java)17
-rw-r--r--src/org/traccar/handler/events/FuelDropEventHandler.java (renamed from src/org/traccar/events/FuelDropEventHandler.java)21
-rw-r--r--src/org/traccar/handler/events/GeofenceEventHandler.java (renamed from src/org/traccar/events/GeofenceEventHandler.java)28
-rw-r--r--src/org/traccar/handler/events/IgnitionEventHandler.java (renamed from src/org/traccar/events/IgnitionEventHandler.java)19
-rw-r--r--src/org/traccar/handler/events/MaintenanceEventHandler.java (renamed from src/org/traccar/events/MaintenanceEventHandler.java)24
-rw-r--r--src/org/traccar/handler/events/MotionEventHandler.java (renamed from src/org/traccar/events/MotionEventHandler.java)24
-rw-r--r--src/org/traccar/handler/events/OverspeedEventHandler.java (renamed from src/org/traccar/events/OverspeedEventHandler.java)46
-rw-r--r--src/org/traccar/helper/Log.java22
-rw-r--r--src/org/traccar/helper/PatternBuilder.java2
-rw-r--r--src/org/traccar/model/Server.java5
-rw-r--r--src/org/traccar/notification/EventForwarder.java20
-rw-r--r--src/org/traccar/notification/PropertiesProvider.java2
-rw-r--r--src/org/traccar/notificators/NotificatorSms.java6
-rw-r--r--src/org/traccar/protocol/BoxProtocolDecoder.java15
-rw-r--r--src/org/traccar/protocol/CguardProtocolDecoder.java6
-rw-r--r--src/org/traccar/protocol/EnforaProtocol.java9
-rw-r--r--src/org/traccar/protocol/FifotrackProtocol.java2
-rw-r--r--src/org/traccar/protocol/FifotrackProtocolDecoder.java83
-rw-r--r--src/org/traccar/protocol/ItsProtocolDecoder.java12
-rw-r--r--src/org/traccar/protocol/L100ProtocolDecoder.java6
-rw-r--r--src/org/traccar/protocol/OwnTracksProtocolDecoder.java3
-rw-r--r--src/org/traccar/protocol/TeltonikaProtocolDecoder.java2
-rw-r--r--src/org/traccar/reports/ReportUtils.java7
-rw-r--r--src/org/traccar/reports/Stops.java8
-rw-r--r--src/org/traccar/reports/Trips.java8
-rw-r--r--src/org/traccar/sms/smpp/ClientSmppSessionHandler.java1
-rw-r--r--src/org/traccar/sms/smpp/TextMessageEventHandler.java (renamed from src/org/traccar/events/TextMessageEventHandler.java)2
-rw-r--r--src/org/traccar/web/WebServer.java2
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;