aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/traccar/BaseProtocolDecoder.java8
-rw-r--r--src/main/java/org/traccar/BaseProtocolEncoder.java25
-rw-r--r--src/main/java/org/traccar/StringProtocolEncoder.java6
-rw-r--r--src/main/java/org/traccar/config/Keys.java7
-rw-r--r--src/main/java/org/traccar/database/ConnectionManager.java2
-rw-r--r--src/main/java/org/traccar/database/DeviceManager.java57
-rw-r--r--src/main/java/org/traccar/database/IdentityManager.java19
-rw-r--r--src/main/java/org/traccar/handler/CopyAttributesHandler.java2
-rw-r--r--src/main/java/org/traccar/handler/FilterHandler.java2
-rw-r--r--src/main/java/org/traccar/handler/GeolocationHandler.java1
-rw-r--r--src/main/java/org/traccar/handler/events/FuelDropEventHandler.java2
-rw-r--r--src/main/java/org/traccar/handler/events/OverspeedEventHandler.java2
-rw-r--r--src/main/java/org/traccar/helper/DateBuilder.java4
-rw-r--r--src/main/java/org/traccar/model/Network.java6
-rw-r--r--src/main/java/org/traccar/model/Position.java3
-rw-r--r--src/main/java/org/traccar/protocol/AdmProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/AdmProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/AquilaProtocolDecoder.java194
-rw-r--r--src/main/java/org/traccar/protocol/AtrackProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java40
-rw-r--r--src/main/java/org/traccar/protocol/AtrackProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/AvemaProtocolDecoder.java13
-rw-r--r--src/main/java/org/traccar/protocol/BceProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/BceProtocolDecoder.java94
-rw-r--r--src/main/java/org/traccar/protocol/BceProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/CalAmpProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/CarcellProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/CarcellProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/CarcellProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/CastelProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/CastelProtocolDecoder.java242
-rw-r--r--src/main/java/org/traccar/protocol/CastelProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/CellocatorProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java67
-rw-r--r--src/main/java/org/traccar/protocol/CellocatorProtocolEncoder.java44
-rw-r--r--src/main/java/org/traccar/protocol/CityeasyProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/CityeasyProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/DmtProtocolDecoder.java3
-rw-r--r--src/main/java/org/traccar/protocol/EelinkProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java3
-rw-r--r--src/main/java/org/traccar/protocol/EelinkProtocolEncoder.java6
-rw-r--r--src/main/java/org/traccar/protocol/EgtsProtocolDecoder.java32
-rw-r--r--src/main/java/org/traccar/protocol/EnforaProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/EnforaProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/EsealProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/EsealProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/FifotrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java54
-rw-r--r--src/main/java/org/traccar/protocol/FifotrackProtocolEncoder.java5
-rw-r--r--src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java3
-rw-r--r--src/main/java/org/traccar/protocol/GalileoProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/GalileoProtocolDecoder.java6
-rw-r--r--src/main/java/org/traccar/protocol/GalileoProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/GatorProtocolDecoder.java8
-rw-r--r--src/main/java/org/traccar/protocol/Gl200Protocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/Gl200ProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java18
-rw-r--r--src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java70
-rw-r--r--src/main/java/org/traccar/protocol/GotopProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/Gps103Protocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/Gps103ProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/GranitProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/GranitProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/GranitProtocolSmsEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/Gt06Protocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java134
-rw-r--r--src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java21
-rw-r--r--src/main/java/org/traccar/protocol/H02Protocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/H02ProtocolDecoder.java9
-rw-r--r--src/main/java/org/traccar/protocol/H02ProtocolEncoder.java9
-rw-r--r--src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java32
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java31
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/ItsProtocolDecoder.java29
-rw-r--r--src/main/java/org/traccar/protocol/ItsProtocolEncoder.java5
-rw-r--r--src/main/java/org/traccar/protocol/Jt600FrameDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/Jt600Protocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java9
-rw-r--r--src/main/java/org/traccar/protocol/Jt600ProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/KhdProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/KhdProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/LaipacProtocol.java10
-rw-r--r--src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java178
-rw-r--r--src/main/java/org/traccar/protocol/LaipacProtocolEncoder.java57
-rw-r--r--src/main/java/org/traccar/protocol/LeafSpyProtocol.java40
-rw-r--r--src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java139
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/MeitrackProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/MeitrackProtocolEncoder.java9
-rw-r--r--src/main/java/org/traccar/protocol/MictrackProtocol.java47
-rw-r--r--src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java181
-rw-r--r--src/main/java/org/traccar/protocol/MiniFinderProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/MiniFinderProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java29
-rw-r--r--src/main/java/org/traccar/protocol/NavisetFrameDecoder.java39
-rw-r--r--src/main/java/org/traccar/protocol/NavisetProtocol.java34
-rw-r--r--src/main/java/org/traccar/protocol/NavisetProtocolDecoder.java249
-rw-r--r--src/main/java/org/traccar/protocol/NoranProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/NoranProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/PacificTrackProtocol.java33
-rw-r--r--src/main/java/org/traccar/protocol/PacificTrackProtocolDecoder.java104
-rw-r--r--src/main/java/org/traccar/protocol/PluginProtocol.java39
-rw-r--r--src/main/java/org/traccar/protocol/PluginProtocolDecoder.java93
-rw-r--r--src/main/java/org/traccar/protocol/PretraceProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/PretraceProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/Pt215FrameDecoder.java55
-rw-r--r--src/main/java/org/traccar/protocol/Pt215Protocol.java34
-rw-r--r--src/main/java/org/traccar/protocol/Pt215ProtocolDecoder.java118
-rw-r--r--src/main/java/org/traccar/protocol/Pt502Protocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/Pt502ProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java39
-rw-r--r--src/main/java/org/traccar/protocol/RaceDynamicsProtocolDecoder.java171
-rw-r--r--src/main/java/org/traccar/protocol/RstProtocol.java37
-rw-r--r--src/main/java/org/traccar/protocol/RstProtocolDecoder.java128
-rw-r--r--src/main/java/org/traccar/protocol/RuptelaProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/RuptelaProtocolEncoder.java5
-rw-r--r--src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java125
-rw-r--r--src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java58
-rw-r--r--src/main/java/org/traccar/protocol/SuntechProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java50
-rw-r--r--src/main/java/org/traccar/protocol/SuntechProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/SviasProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/SviasProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/T55ProtocolDecoder.java35
-rw-r--r--src/main/java/org/traccar/protocol/T800xProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/T800xProtocolDecoder.java169
-rw-r--r--src/main/java/org/traccar/protocol/T800xProtocolEncoder.java22
-rw-r--r--src/main/java/org/traccar/protocol/TechTltProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TechTltProtocolDecoder.java53
-rw-r--r--src/main/java/org/traccar/protocol/TelicProtocolDecoder.java36
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java8
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java14
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaProtocolEncoder.java5
-rw-r--r--src/main/java/org/traccar/protocol/Tk103Protocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/Tk103ProtocolEncoder.java11
-rw-r--r--src/main/java/org/traccar/protocol/TotemProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/TotemProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/TramigoFrameDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/TrvProtocolDecoder.java10
-rw-r--r--src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java59
-rw-r--r--src/main/java/org/traccar/protocol/UlbotechProtocolDecoder.java5
-rw-r--r--src/main/java/org/traccar/protocol/UproProtocolDecoder.java67
-rw-r--r--src/main/java/org/traccar/protocol/WatchProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/WatchProtocolDecoder.java15
-rw-r--r--src/main/java/org/traccar/protocol/WatchProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/WialonProtocol.java23
-rw-r--r--src/main/java/org/traccar/protocol/WialonProtocolDecoder.java49
-rw-r--r--src/main/java/org/traccar/protocol/WialonProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/WondexProtocol.java8
-rw-r--r--src/main/java/org/traccar/protocol/WondexProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/XexunProtocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/XexunProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/XirgoProtocol.java6
-rw-r--r--src/main/java/org/traccar/protocol/XirgoProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/XirgoProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/Xrb28Protocol.java4
-rw-r--r--src/main/java/org/traccar/protocol/Xrb28ProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java20
-rw-r--r--src/main/java/org/traccar/reports/Stops.java2
-rw-r--r--src/main/java/org/traccar/reports/Summary.java2
-rw-r--r--src/main/java/org/traccar/reports/Trips.java2
164 files changed, 3550 insertions, 893 deletions
diff --git a/src/main/java/org/traccar/BaseProtocolDecoder.java b/src/main/java/org/traccar/BaseProtocolDecoder.java
index aa5be612e..e6e02c2d6 100644
--- a/src/main/java/org/traccar/BaseProtocolDecoder.java
+++ b/src/main/java/org/traccar/BaseProtocolDecoder.java
@@ -86,7 +86,7 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder {
protected TimeZone getTimeZone(long deviceId, String defaultTimeZone) {
TimeZone result = TimeZone.getTimeZone(defaultTimeZone);
- String timeZoneName = identityManager.lookupAttributeString(deviceId, "decoder.timezone", null, true);
+ String timeZoneName = identityManager.lookupAttributeString(deviceId, "decoder.timezone", null, false, true);
if (timeZoneName != null) {
result = TimeZone.getTimeZone(timeZoneName);
} else {
@@ -143,7 +143,13 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder {
}
public DeviceSession getDeviceSession(Channel channel, SocketAddress remoteAddress, String... uniqueIds) {
+ return getDeviceSession(channel, remoteAddress, false, uniqueIds);
+ }
+
+ public DeviceSession getDeviceSession(
+ Channel channel, SocketAddress remoteAddress, boolean ignoreCache, String... uniqueIds) {
if (channel != null && BasePipelineFactory.getHandler(channel.pipeline(), HttpRequestDecoder.class) != null
+ || ignoreCache || config.getBoolean(getProtocolName() + ".ignoreSessionCache")
|| config.getBoolean("decoder.ignoreSessionCache")) {
long deviceId = findDeviceId(remoteAddress, uniqueIds);
if (deviceId != 0) {
diff --git a/src/main/java/org/traccar/BaseProtocolEncoder.java b/src/main/java/org/traccar/BaseProtocolEncoder.java
index d7625e4b8..b6df07b98 100644
--- a/src/main/java/org/traccar/BaseProtocolEncoder.java
+++ b/src/main/java/org/traccar/BaseProtocolEncoder.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.
@@ -22,25 +22,32 @@ import io.netty.channel.ChannelPromise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.traccar.model.Command;
-import org.traccar.model.Device;
public abstract class BaseProtocolEncoder extends ChannelOutboundHandlerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(BaseProtocolEncoder.class);
+ private static final String PROTOCOL_UNKNOWN = "unknown";
+
+ private final Protocol protocol;
+
+ public BaseProtocolEncoder(Protocol protocol) {
+ this.protocol = protocol;
+ }
+
+ public String getProtocolName() {
+ return protocol != null ? protocol.getName() : PROTOCOL_UNKNOWN;
+ }
+
protected String getUniqueId(long deviceId) {
return Context.getIdentityManager().getById(deviceId).getUniqueId();
}
protected void initDevicePassword(Command command, String defaultPassword) {
if (!command.getAttributes().containsKey(Command.KEY_DEVICE_PASSWORD)) {
- Device device = Context.getIdentityManager().getById(command.getDeviceId());
- String password = device.getString(Command.KEY_DEVICE_PASSWORD);
- if (password != null) {
- command.set(Command.KEY_DEVICE_PASSWORD, password);
- } else {
- command.set(Command.KEY_DEVICE_PASSWORD, defaultPassword);
- }
+ String password = Context.getIdentityManager()
+ .getDevicePassword(command.getDeviceId(), getProtocolName(), defaultPassword);
+ command.set(Command.KEY_DEVICE_PASSWORD, password);
}
}
diff --git a/src/main/java/org/traccar/StringProtocolEncoder.java b/src/main/java/org/traccar/StringProtocolEncoder.java
index 1945ae174..d9acce7f0 100644
--- a/src/main/java/org/traccar/StringProtocolEncoder.java
+++ b/src/main/java/org/traccar/StringProtocolEncoder.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.
@@ -21,6 +21,10 @@ import java.util.Map;
public abstract class StringProtocolEncoder extends BaseProtocolEncoder {
+ public StringProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
public interface ValueFormatter {
String formatValue(String key, Object value);
}
diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java
index a000329e2..2c5dcefd5 100644
--- a/src/main/java/org/traccar/config/Keys.java
+++ b/src/main/java/org/traccar/config/Keys.java
@@ -197,8 +197,9 @@ public final class Keys {
"time.protocols", String.class);
/**
- * Replaces coordinates with last known if change is less than a 'coordinates.error' meters. Helps to avoid
- * coordinates jumps during parking period.
+ * Replaces coordinates with last known if change is less than a 'coordinates.minError' meters
+ * or more than a 'coordinates.maxError' meters. Helps to avoid coordinates jumps during parking period
+ * or jumps to zero coordinates.
*/
public static final ConfigKey COORDINATES_FILTER = new ConfigKey(
"coordinates.filter", Boolean.class);
@@ -214,7 +215,7 @@ public final class Keys {
* Position is also marked as 'invalid'.
*/
public static final ConfigKey COORDINATES_MAX_ERROR = new ConfigKey(
- "filter.maxError", Integer.class);
+ "coordinates.maxError", Integer.class);
/**
* Enable to save device IP addresses information. Disabled by default.
diff --git a/src/main/java/org/traccar/database/ConnectionManager.java b/src/main/java/org/traccar/database/ConnectionManager.java
index 8bae1ea93..dd0071143 100644
--- a/src/main/java/org/traccar/database/ConnectionManager.java
+++ b/src/main/java/org/traccar/database/ConnectionManager.java
@@ -157,7 +157,7 @@ public class ConnectionManager {
event = Main.getInjector().getInstance(OverspeedEventHandler.class)
.updateOverspeedState(deviceState, Context.getDeviceManager().
- lookupAttributeDouble(deviceId, OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT, 0, false));
+ lookupAttributeDouble(deviceId, OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT, 0, true, false));
if (event != null) {
result.putAll(event);
}
diff --git a/src/main/java/org/traccar/database/DeviceManager.java b/src/main/java/org/traccar/database/DeviceManager.java
index de4607d1f..fa95adeb2 100644
--- a/src/main/java/org/traccar/database/DeviceManager.java
+++ b/src/main/java/org/traccar/database/DeviceManager.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.
@@ -29,6 +29,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.traccar.config.Config;
import org.traccar.Context;
+import org.traccar.model.Command;
import org.traccar.model.Device;
import org.traccar.model.DeviceState;
import org.traccar.model.DeviceAccumulators;
@@ -114,6 +115,24 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
return devicesByUniqueId.get(uniqueId);
}
+ @Override
+ public String getDevicePassword(long id, String protocol, String defaultPassword) {
+
+ String password = lookupAttributeString(id, Command.KEY_DEVICE_PASSWORD, null, false, false);
+ if (password != null) {
+ return password;
+ }
+
+ if (protocol != null) {
+ password = Context.getConfig().getString(protocol + "." + Command.KEY_DEVICE_PASSWORD);
+ if (password != null) {
+ return password;
+ }
+ }
+
+ return defaultPassword;
+ }
+
public Device getDeviceByPhone(String phone) {
return devicesByPhone.get(phone);
}
@@ -312,8 +331,8 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
@Override
public boolean lookupAttributeBoolean(
- long deviceId, String attributeName, boolean defaultValue, boolean lookupConfig) {
- Object result = lookupAttribute(deviceId, attributeName, lookupConfig);
+ long deviceId, String attributeName, boolean defaultValue, boolean lookupServer, boolean lookupConfig) {
+ Object result = lookupAttribute(deviceId, attributeName, lookupServer, lookupConfig);
if (result != null) {
return result instanceof String ? Boolean.parseBoolean((String) result) : (Boolean) result;
}
@@ -322,14 +341,15 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
@Override
public String lookupAttributeString(
- long deviceId, String attributeName, String defaultValue, boolean lookupConfig) {
- Object result = lookupAttribute(deviceId, attributeName, lookupConfig);
+ long deviceId, String attributeName, String defaultValue, boolean lookupServer, boolean lookupConfig) {
+ Object result = lookupAttribute(deviceId, attributeName, lookupServer, 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);
+ public int lookupAttributeInteger(
+ long deviceId, String attributeName, int defaultValue, boolean lookupServer, boolean lookupConfig) {
+ Object result = lookupAttribute(deviceId, attributeName, lookupServer, lookupConfig);
if (result != null) {
return result instanceof String ? Integer.parseInt((String) result) : ((Number) result).intValue();
}
@@ -338,8 +358,8 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
@Override
public long lookupAttributeLong(
- long deviceId, String attributeName, long defaultValue, boolean lookupConfig) {
- Object result = lookupAttribute(deviceId, attributeName, lookupConfig);
+ long deviceId, String attributeName, long defaultValue, boolean lookupServer, boolean lookupConfig) {
+ Object result = lookupAttribute(deviceId, attributeName, lookupServer, lookupConfig);
if (result != null) {
return result instanceof String ? Long.parseLong((String) result) : ((Number) result).longValue();
}
@@ -347,15 +367,15 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
}
public double lookupAttributeDouble(
- long deviceId, String attributeName, double defaultValue, boolean lookupConfig) {
- Object result = lookupAttribute(deviceId, attributeName, lookupConfig);
+ long deviceId, String attributeName, double defaultValue, boolean lookupServer, boolean lookupConfig) {
+ Object result = lookupAttribute(deviceId, attributeName, lookupServer, lookupConfig);
if (result != null) {
return result instanceof String ? Double.parseDouble((String) result) : ((Number) result).doubleValue();
}
return defaultValue;
}
- private Object lookupAttribute(long deviceId, String attributeName, boolean lookupConfig) {
+ private Object lookupAttribute(long deviceId, String attributeName, boolean lookupServer, boolean lookupConfig) {
Object result = null;
Device device = getById(deviceId);
if (device != null) {
@@ -375,13 +395,12 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
}
}
}
- if (result == null) {
- if (lookupConfig) {
- result = Context.getConfig().getString(attributeName);
- } else {
- Server server = Context.getPermissionsManager().getServer();
- result = server.getAttributes().get(attributeName);
- }
+ if (result == null && lookupServer) {
+ Server server = Context.getPermissionsManager().getServer();
+ result = server.getAttributes().get(attributeName);
+ }
+ if (result == null && lookupConfig) {
+ result = Context.getConfig().getString(attributeName);
}
}
return result;
diff --git a/src/main/java/org/traccar/database/IdentityManager.java b/src/main/java/org/traccar/database/IdentityManager.java
index 6228a0f75..af6a6ce71 100644
--- a/src/main/java/org/traccar/database/IdentityManager.java
+++ b/src/main/java/org/traccar/database/IdentityManager.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.
@@ -26,18 +26,25 @@ public interface IdentityManager {
Device getByUniqueId(String uniqueId) throws Exception;
+ String getDevicePassword(long id, String protocol, String defaultPassword);
+
Position getLastPosition(long deviceId);
boolean isLatestPosition(Position position);
- boolean lookupAttributeBoolean(long deviceId, String attributeName, boolean defaultValue, boolean lookupConfig);
+ boolean lookupAttributeBoolean(
+ long deviceId, String attributeName, boolean defaultValue, boolean lookupServer, boolean lookupConfig);
- String lookupAttributeString(long deviceId, String attributeName, String defaultValue, boolean lookupConfig);
+ String lookupAttributeString(
+ long deviceId, String attributeName, String defaultValue, boolean lookupServer, boolean lookupConfig);
- int lookupAttributeInteger(long deviceId, String attributeName, int defaultValue, boolean lookupConfig);
+ int lookupAttributeInteger(
+ long deviceId, String attributeName, int defaultValue, boolean lookupServer, boolean lookupConfig);
- long lookupAttributeLong(long deviceId, String attributeName, long defaultValue, boolean lookupConfig);
+ long lookupAttributeLong(
+ long deviceId, String attributeName, long defaultValue, boolean lookupServer, boolean lookupConfig);
- double lookupAttributeDouble(long deviceId, String attributeName, double defaultValue, boolean lookupConfig);
+ double lookupAttributeDouble(
+ long deviceId, String attributeName, double defaultValue, boolean lookupServer, boolean lookupConfig);
}
diff --git a/src/main/java/org/traccar/handler/CopyAttributesHandler.java b/src/main/java/org/traccar/handler/CopyAttributesHandler.java
index 6a0966d33..3cd7d144d 100644
--- a/src/main/java/org/traccar/handler/CopyAttributesHandler.java
+++ b/src/main/java/org/traccar/handler/CopyAttributesHandler.java
@@ -33,7 +33,7 @@ public class CopyAttributesHandler extends BaseDataHandler {
@Override
protected Position handlePosition(Position position) {
String attributesString = identityManager.lookupAttributeString(
- position.getDeviceId(), "processing.copyAttributes", "", true);
+ position.getDeviceId(), "processing.copyAttributes", "", false, true);
if (attributesString.isEmpty()) {
attributesString = Position.KEY_DRIVER_UNIQUE_ID;
} else {
diff --git a/src/main/java/org/traccar/handler/FilterHandler.java b/src/main/java/org/traccar/handler/FilterHandler.java
index dceaede01..7cd9153c1 100644
--- a/src/main/java/org/traccar/handler/FilterHandler.java
+++ b/src/main/java/org/traccar/handler/FilterHandler.java
@@ -130,7 +130,7 @@ public class FilterHandler extends BaseDataHandler {
private boolean skipAttributes(Position position) {
if (skipAttributes) {
String attributesString = Context.getIdentityManager().lookupAttributeString(
- position.getDeviceId(), "filter.skipAttributes", "", true);
+ position.getDeviceId(), "filter.skipAttributes", "", false, true);
for (String attribute : attributesString.split("[ ,]")) {
if (position.getAttributes().containsKey(attribute)) {
return true;
diff --git a/src/main/java/org/traccar/handler/GeolocationHandler.java b/src/main/java/org/traccar/handler/GeolocationHandler.java
index c7b39e491..0e78322c8 100644
--- a/src/main/java/org/traccar/handler/GeolocationHandler.java
+++ b/src/main/java/org/traccar/handler/GeolocationHandler.java
@@ -65,7 +65,6 @@ public class GeolocationHandler extends ChannelInboundHandlerAdapter {
position.setAltitude(0);
position.setSpeed(0);
position.setCourse(0);
- position.set(Position.KEY_RSSI, 0);
ctx.fireChannelRead(position);
}
diff --git a/src/main/java/org/traccar/handler/events/FuelDropEventHandler.java b/src/main/java/org/traccar/handler/events/FuelDropEventHandler.java
index 59de61bba..bc1426b86 100644
--- a/src/main/java/org/traccar/handler/events/FuelDropEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/FuelDropEventHandler.java
@@ -47,7 +47,7 @@ public class FuelDropEventHandler extends BaseEventHandler {
}
double fuelDropThreshold = identityManager
- .lookupAttributeDouble(device.getId(), ATTRIBUTE_FUEL_DROP_THRESHOLD, 0, false);
+ .lookupAttributeDouble(device.getId(), ATTRIBUTE_FUEL_DROP_THRESHOLD, 0, true, false);
if (fuelDropThreshold > 0) {
Position lastPosition = identityManager.getLastPosition(position.getDeviceId());
diff --git a/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java b/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java
index 157bb64e0..e534df9de 100644
--- a/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java
@@ -120,7 +120,7 @@ public class OverspeedEventHandler extends BaseEventHandler {
return null;
}
- double speedLimit = deviceManager.lookupAttributeDouble(deviceId, ATTRIBUTE_SPEED_LIMIT, 0, false);
+ double speedLimit = deviceManager.lookupAttributeDouble(deviceId, ATTRIBUTE_SPEED_LIMIT, 0, true, false);
double geofenceSpeedLimit = 0;
long overspeedGeofenceId = 0;
diff --git a/src/main/java/org/traccar/helper/DateBuilder.java b/src/main/java/org/traccar/helper/DateBuilder.java
index 6e1b779f0..9752f6977 100644
--- a/src/main/java/org/traccar/helper/DateBuilder.java
+++ b/src/main/java/org/traccar/helper/DateBuilder.java
@@ -69,7 +69,9 @@ public class DateBuilder {
public DateBuilder setCurrentDate() {
Calendar now = Calendar.getInstance(calendar.getTimeZone());
- return setYear(now.get(Calendar.YEAR)).setMonth(now.get(Calendar.MONTH)).setDay(now.get(Calendar.DAY_OF_MONTH));
+ return setYear(now.get(Calendar.YEAR))
+ .setMonth(now.get(Calendar.MONTH) + 1)
+ .setDay(now.get(Calendar.DAY_OF_MONTH));
}
public DateBuilder setHour(int hour) {
diff --git a/src/main/java/org/traccar/model/Network.java b/src/main/java/org/traccar/model/Network.java
index 2d56950f1..4d67fc5d8 100644
--- a/src/main/java/org/traccar/model/Network.java
+++ b/src/main/java/org/traccar/model/Network.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.
@@ -30,6 +30,10 @@ public class Network {
addCellTower(cellTower);
}
+ public Network(WifiAccessPoint wifiAccessPoint) {
+ addWifiAccessPoint(wifiAccessPoint);
+ }
+
private Integer homeMobileCountryCode;
public Integer getHomeMobileCountryCode() {
diff --git a/src/main/java/org/traccar/model/Position.java b/src/main/java/org/traccar/model/Position.java
index 6032dc588..2c0e22c9e 100644
--- a/src/main/java/org/traccar/model/Position.java
+++ b/src/main/java/org/traccar/model/Position.java
@@ -82,6 +82,9 @@ public class Position extends Message {
public static final String KEY_BLOCKED = "blocked";
public static final String KEY_DOOR = "door";
public static final String KEY_AXLE_WEIGHT = "axleWeight";
+ public static final String KEY_G_SENSOR = "gSensor";
+ public static final String KEY_ICCID = "iccid";
+ public static final String KEY_PHONE = "phone";
public static final String KEY_DTCS = "dtcs";
public static final String KEY_OBD_SPEED = "obdSpeed"; // knots
diff --git a/src/main/java/org/traccar/protocol/AdmProtocol.java b/src/main/java/org/traccar/protocol/AdmProtocol.java
index 08f932ceb..93b1e355a 100644
--- a/src/main/java/org/traccar/protocol/AdmProtocol.java
+++ b/src/main/java/org/traccar/protocol/AdmProtocol.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.
@@ -35,7 +35,7 @@ public class AdmProtocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN, 1024, 2, 1, -3, 0, true));
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new AdmProtocolEncoder());
+ pipeline.addLast(new AdmProtocolEncoder(AdmProtocol.this));
pipeline.addLast(new AdmProtocolDecoder(AdmProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/AdmProtocolEncoder.java b/src/main/java/org/traccar/protocol/AdmProtocolEncoder.java
index e76bc2ddc..1c3dfc156 100644
--- a/src/main/java/org/traccar/protocol/AdmProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/AdmProtocolEncoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org)
* Copyright 2017 Anatoliy Golubev (darth.naihil@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,9 +18,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class AdmProtocolEncoder extends StringProtocolEncoder {
+ public AdmProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/AquilaProtocolDecoder.java b/src/main/java/org/traccar/protocol/AquilaProtocolDecoder.java
index 57af5e366..3c43ddf2a 100644
--- a/src/main/java/org/traccar/protocol/AquilaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AquilaProtocolDecoder.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,15 +17,11 @@ package org.traccar.protocol;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
-import org.traccar.Context;
import org.traccar.DeviceSession;
-import org.traccar.NetworkMessage;
import org.traccar.Protocol;
import org.traccar.helper.Parser;
import org.traccar.helper.PatternBuilder;
import org.traccar.helper.UnitsConverter;
-import org.traccar.model.CellTower;
-import org.traccar.model.Network;
import org.traccar.model.Position;
import java.net.SocketAddress;
@@ -134,9 +130,11 @@ public class AquilaProtocolDecoder extends BaseProtocolDecoder {
.number("xx") // checksum
.compile();
- private Position decodeA(Channel channel, SocketAddress remoteAddress, String sentence) {
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
- Parser parser = new Parser(PATTERN_A, sentence);
+ Parser parser = new Parser(PATTERN_A, (String) msg);
if (!parser.matches()) {
return null;
}
@@ -218,186 +216,4 @@ public class AquilaProtocolDecoder extends BaseProtocolDecoder {
return position;
}
- private static final Pattern PATTERN_B_1 = new PatternBuilder()
- .text("$")
- .expression("[^,]+,") // header
- .expression("[^,]+,") // client
- .expression("[^,]+,") // firmware version
- .expression(".{2},") // packet type
- .number("d+,") // message id
- .expression("[LH],") // status
- .number("(d+),") // imei
- .expression("[^,]+,") // registration number
- .number("([01]),") // validity
- .number("(dd)(dd)(dddd),") // date (ddmmyyyy)
- .number("(dd)(dd)(dd),") // time (hhmmss)
- .number("(-?d+.d+),") // latitude
- .expression("([NS]),")
- .number("(-?d+.d+),") // longitude
- .expression("([EW]),")
- .number("(d+.d+),") // speed
- .number("(d+),") // course
- .number("(d+),") // satellites
- .number("(-?d+.d+),") // altitude
- .number("(d+.d+),") // pdop
- .number("(d+.d+),") // hdop
- .expression("[^,]+,") // operator
- .number("([01]),") // ignition
- .number("([01]),") // charge
- .number("(d+.d+),") // power
- .number("(d+.d+),") // battery
- .number("([01]),") // emergency
- .expression("[CO],") // tamper
- .number("(d+),") // rssi
- .number("(d+),") // mcc
- .number("(d+),") // mnc
- .number("(x+),") // lac
- .number("(x+),") // cid
- .number("(d+),(x+),(x+),") // cell 1
- .number("(d+),(x+),(x+),") // cell 2
- .number("(d+),(x+),(x+),") // cell 3
- .number("(d+),(x+),(x+),") // cell 4
- .number("([01])+,") // inputs
- .number("([01])+,") // outputs
- .number("d+,") // frame number
- .number("(d+.d+),") // adc1
- .number("(d+.d+),") // adc2
- .number("d+,") // delta distance
- .any()
- .compile();
-
- private static final Pattern PATTERN_B_2 = new PatternBuilder()
- .text("$")
- .expression("[^,]+,") // header
- .expression("[^,]+,") // client
- .expression("(.{3}),") // message type
- .number("(d+),") // imei
- .expression(".{2},") // packet type
- .number("(dd)(dd)(dddd)") // date (ddmmyyyy)
- .number("(dd)(dd)(dd),") // time (hhmmss)
- .expression("([AV]),") // validity
- .number("(-?d+.d+),") // latitude
- .expression("([NS]),")
- .number("(-?d+.d+),") // longitude
- .expression("([EW]),")
- .number("(-?d+.d+),") // altitude
- .number("(d+.d+),") // speed
- .any()
- .compile();
-
- private Position decodeB2(Channel channel, SocketAddress remoteAddress, String sentence) {
-
- Parser parser = new Parser(PATTERN_B_2, sentence);
- if (!parser.matches()) {
- return null;
- }
-
- String type = parser.next();
- String id = parser.next();
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id);
- if (deviceSession == null) {
- return null;
- }
-
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
-
- position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
- position.setValid(parser.next().equals("A"));
- position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
- position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
- position.setAltitude(parser.nextDouble());
- position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble()));
-
- if (type.equals("EMR") && channel != null) {
- String password = Context.getIdentityManager().lookupAttributeString(
- deviceSession.getDeviceId(), getProtocolName() + ".password", "aquila123", true);
- channel.writeAndFlush(new NetworkMessage(
- "#set$" + id + "@" + password + "#EMR_MODE:0*", remoteAddress));
- }
-
- return position;
- }
-
- private Position decodeB1(Channel channel, SocketAddress remoteAddress, String sentence) {
-
- Parser parser = new Parser(PATTERN_B_1, sentence);
- if (!parser.matches()) {
- return null;
- }
-
- String id = parser.next();
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id);
- if (deviceSession == null) {
- return null;
- }
-
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
-
- position.setValid(parser.nextInt() == 1);
- position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
- position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
- position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
- position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble()));
- position.setCourse(parser.nextInt());
-
- position.set(Position.KEY_SATELLITES, parser.nextInt());
-
- position.setAltitude(parser.nextDouble());
-
- position.set(Position.KEY_PDOP, parser.nextDouble());
- position.set(Position.KEY_HDOP, parser.nextDouble());
- position.set(Position.KEY_IGNITION, parser.nextInt() == 1);
- position.set(Position.KEY_CHARGE, parser.nextInt() == 1);
- position.set(Position.KEY_POWER, parser.nextDouble());
- position.set(Position.KEY_BATTERY, parser.nextDouble());
-
- if (parser.nextInt() == 1) {
- position.set(Position.KEY_ALARM, Position.ALARM_SOS);
- }
-
- Network network = new Network();
-
- int rssi = parser.nextInt();
- int mcc = parser.nextInt();
- int mnc = parser.nextInt();
-
- network.addCellTower(CellTower.from(mcc, mnc, parser.nextHexInt(), parser.nextHexInt(), rssi));
- for (int i = 0; i < 4; i++) {
- rssi = parser.nextInt();
- network.addCellTower(CellTower.from(mcc, mnc, parser.nextHexInt(), parser.nextHexInt(), rssi));
- }
-
- position.setNetwork(network);
-
- position.set(Position.KEY_INPUT, parser.nextBinInt());
- position.set(Position.KEY_OUTPUT, parser.nextBinInt());
- position.set(Position.PREFIX_ADC + 1, parser.nextDouble());
- position.set(Position.PREFIX_ADC + 2, parser.nextDouble());
-
- return position;
- }
-
- private Position decodeB(Channel channel, SocketAddress remoteAddress, String sentence) {
- if (sentence.contains("EMR") || sentence.contains("SEM")) {
- return decodeB2(channel, remoteAddress, sentence);
- } else {
- return decodeB1(channel, remoteAddress, sentence);
- }
- }
-
- @Override
- protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
-
- String sentence = (String) msg;
-
- if (sentence.startsWith("$$")) {
- return decodeA(channel, remoteAddress, sentence);
- } else {
- return decodeB(channel, remoteAddress, sentence);
- }
- }
-
}
diff --git a/src/main/java/org/traccar/protocol/AtrackProtocol.java b/src/main/java/org/traccar/protocol/AtrackProtocol.java
index 8e5cfe9ff..429708b26 100644
--- a/src/main/java/org/traccar/protocol/AtrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/AtrackProtocol.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.
@@ -29,14 +29,14 @@ public class AtrackProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new AtrackFrameDecoder());
- pipeline.addLast(new AtrackProtocolEncoder());
+ pipeline.addLast(new AtrackProtocolEncoder(AtrackProtocol.this));
pipeline.addLast(new AtrackProtocolDecoder(AtrackProtocol.this));
}
});
addServer(new TrackerServer(true, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new AtrackProtocolEncoder());
+ pipeline.addLast(new AtrackProtocolEncoder(AtrackProtocol.this));
pipeline.addLast(new AtrackProtocolDecoder(AtrackProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java
index 71bb6791c..53f04234d 100644
--- a/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 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.
@@ -84,6 +84,10 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder {
this.custom = custom;
}
+ public void setForm(String form) {
+ this.form = form;
+ }
+
private static void sendResponse(Channel channel, SocketAddress remoteAddress, long rawId, int index) {
if (channel != null) {
ByteBuf response = Unpooled.buffer(12);
@@ -156,7 +160,7 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_THROTTLE, Integer.parseInt(values[i]));
break;
case "ET":
- position.set(Position.PREFIX_TEMP + 1, Integer.parseInt(values[i]));
+ position.set(Position.KEY_COOLANT_TEMP, Integer.parseInt(values[i]));
break;
case "FL":
position.set(Position.KEY_FUEL_LEVEL, Integer.parseInt(values[i]));
@@ -167,6 +171,36 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder {
case "AV1":
position.set(Position.PREFIX_ADC + 1, Integer.parseInt(values[i]));
break;
+ case "CD":
+ position.set(Position.KEY_ICCID, values[i]);
+ break;
+ case "EH":
+ position.set(Position.KEY_HOURS, UnitsConverter.msFromHours(Integer.parseInt(values[i]) * 0.1));
+ break;
+ case "IA":
+ position.set("intakeTemp", Integer.parseInt(values[i]));
+ break;
+ case "EL":
+ position.set(Position.KEY_ENGINE_LOAD, Integer.parseInt(values[i]));
+ break;
+ case "HA":
+ if (Integer.parseInt(values[i]) > 0) {
+ position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION);
+ }
+ break;
+ case "HB":
+ if (Integer.parseInt(values[i]) > 0) {
+ position.set(Position.KEY_ALARM, Position.ALARM_BRAKING);
+ }
+ break;
+ case "HC":
+ if (Integer.parseInt(values[i]) > 0) {
+ position.set(Position.KEY_ALARM, Position.ALARM_CORNERING);
+ }
+ break;
+ case "MT":
+ position.set(Position.KEY_MOTION, Integer.parseInt(values[i]) > 0);
+ break;
default:
break;
}
@@ -274,7 +308,7 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedByte(); // pending code status
break;
case "CD":
- readString(buf); // sim cid
+ position.set(Position.KEY_ICCID, readString(buf));
break;
case "CM":
buf.readLong(); // imsi
diff --git a/src/main/java/org/traccar/protocol/AtrackProtocolEncoder.java b/src/main/java/org/traccar/protocol/AtrackProtocolEncoder.java
index 1e085cb26..d803ae391 100644
--- a/src/main/java/org/traccar/protocol/AtrackProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/AtrackProtocolEncoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 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.
@@ -18,11 +18,16 @@ package org.traccar.protocol;
import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
public class AtrackProtocolEncoder extends BaseProtocolEncoder {
+ public AtrackProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/AvemaProtocolDecoder.java b/src/main/java/org/traccar/protocol/AvemaProtocolDecoder.java
index 16a31162a..37836ad5f 100644
--- a/src/main/java/org/traccar/protocol/AvemaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AvemaProtocolDecoder.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.
@@ -48,17 +48,19 @@ public class AvemaProtocolDecoder extends BaseProtocolDecoder {
.number("(d+),") // event
.number("(d+.d+),") // odometer
.number("(d+),") // input
- .number("(d+.d+)V,") // adc 1
- .number("(d+.d+)V,") // adc 2
+ .number("(d+.d+)V?,") // adc 1
+ .number("(d+.d+)V?,") // adc 2
.number("(d+),") // output
.number("(d),") // roaming
.number("(d+),") // rssi
.number("d,") // communication system
- .number("(ddd)") // mcc
- .number("(dd),") // mnc
+ .number("(ddd)-?") // mcc
+ .number("(d+),") // mnc
.number("(x+),") // lac
.number("(x+),") // cid
+ .number("(d+.d+),").optional() // battery
.number("([^,]+)?") // rfid
+ .any()
.compile();
@Override
@@ -99,6 +101,7 @@ public class AvemaProtocolDecoder extends BaseProtocolDecoder {
position.setNetwork(new Network(CellTower.from(
parser.nextInt(), parser.nextInt(), parser.nextHexInt(), parser.nextHexInt(), rssi)));
+ position.set(Position.KEY_BATTERY, parser.nextDouble());
position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next());
return position;
diff --git a/src/main/java/org/traccar/protocol/BceProtocol.java b/src/main/java/org/traccar/protocol/BceProtocol.java
index 6453a05a9..c5e1dd04c 100644
--- a/src/main/java/org/traccar/protocol/BceProtocol.java
+++ b/src/main/java/org/traccar/protocol/BceProtocol.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.
@@ -29,7 +29,7 @@ public class BceProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new BceFrameDecoder());
- pipeline.addLast(new BceProtocolEncoder());
+ pipeline.addLast(new BceProtocolEncoder(BceProtocol.this));
pipeline.addLast(new BceProtocolDecoder(BceProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java
index ad7271f2f..30f9bb1f3 100644
--- a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java
@@ -29,6 +29,7 @@ import org.traccar.model.Network;
import org.traccar.model.Position;
import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@@ -106,31 +107,31 @@ public class BceProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedByte(); // acceleration pedal
}
if (BitUtil.check(mask, 2)) {
- buf.readUnsignedIntLE(); // total fuel used
+ position.set(Position.KEY_FUEL_USED, buf.readUnsignedIntLE());
}
if (BitUtil.check(mask, 3)) {
- buf.readUnsignedByte(); // fuel level
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte());
}
if (BitUtil.check(mask, 4)) {
- buf.readUnsignedShortLE(); // engine speed
+ position.set(Position.KEY_RPM, buf.readUnsignedShortLE());
}
if (BitUtil.check(mask, 5)) {
- buf.readUnsignedIntLE(); // total hours
+ position.set(Position.KEY_HOURS, buf.readUnsignedIntLE());
}
if (BitUtil.check(mask, 6)) {
- buf.readUnsignedIntLE(); // total distance
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE());
}
if (BitUtil.check(mask, 7)) {
- buf.readUnsignedByte(); // engine coolant
+ position.set(Position.KEY_COOLANT_TEMP, (int) buf.readByte());
}
if (BitUtil.check(mask, 8)) {
- buf.readUnsignedByte(); // fuel level 2
+ position.set("fuel2", buf.readUnsignedByte());
}
if (BitUtil.check(mask, 9)) {
- buf.readUnsignedByte(); // engine load
+ position.set(Position.KEY_ENGINE_LOAD, buf.readUnsignedByte());
}
if (BitUtil.check(mask, 10)) {
- buf.readUnsignedShortLE(); // service distance
+ position.set(Position.KEY_ODOMETER_SERVICE, buf.readUnsignedShortLE());
}
if (BitUtil.check(mask, 11)) {
buf.skipBytes(8); // sensors
@@ -142,7 +143,7 @@ public class BceProtocolDecoder extends BaseProtocolDecoder {
buf.skipBytes(8); // trailer id
}
if (BitUtil.check(mask, 14)) {
- buf.readUnsignedShortLE(); // fuel rate
+ position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShortLE());
}
}
@@ -152,10 +153,10 @@ public class BceProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedShortLE(); // fuel economy
}
if (BitUtil.check(mask, 1)) {
- buf.readUnsignedIntLE(); // fuel consumption
+ position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedIntLE());
}
if (BitUtil.check(mask, 2)) {
- buf.readUnsignedMediumLE(); // axle weight
+ position.set(Position.KEY_AXLE_WEIGHT, buf.readUnsignedMediumLE());
}
if (BitUtil.check(mask, 3)) {
buf.readUnsignedByte(); // mil status
@@ -169,6 +170,70 @@ public class BceProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(mask, 6)) {
position.set(Position.KEY_DRIVER_UNIQUE_ID, String.valueOf(buf.readLongLE()));
}
+ if (BitUtil.check(mask, 7)) {
+ buf.readUnsignedShortLE(); // dallas temperature
+ }
+ if (BitUtil.check(mask, 8)) {
+ buf.readUnsignedShortLE(); // dallas humidity
+ }
+ if (BitUtil.check(mask, 9)) {
+ buf.skipBytes(6); // lls group 1
+ }
+ if (BitUtil.check(mask, 10)) {
+ buf.skipBytes(6); // lls group 2
+ }
+ if (BitUtil.check(mask, 11)) {
+ buf.skipBytes(21); // j1979 group 1
+ }
+ if (BitUtil.check(mask, 12)) {
+ buf.skipBytes(20); // j1979 dtc
+ }
+ if (BitUtil.check(mask, 13)) {
+ buf.skipBytes(9); // j1708 group 1
+ }
+ if (BitUtil.check(mask, 14)) {
+ buf.skipBytes(21); // driving quality
+ }
+ }
+
+ private void decodeMask4(ByteBuf buf, int mask, Position position) {
+
+ if (BitUtil.check(mask, 0)) {
+ buf.readUnsignedIntLE();
+ }
+ if (BitUtil.check(mask, 1)) {
+ buf.skipBytes(30); // lls group 3
+ }
+ if (BitUtil.check(mask, 2)) {
+ buf.readUnsignedIntLE(); // instant fuel consumption
+ }
+ if (BitUtil.check(mask, 3)) {
+ buf.skipBytes(10); // axle weight group
+ }
+ if (BitUtil.check(mask, 4)) {
+ buf.readUnsignedByte();
+ }
+ if (BitUtil.check(mask, 5)) {
+ buf.readUnsignedShortLE();
+ }
+ if (BitUtil.check(mask, 6)) {
+ buf.readUnsignedByte(); // maximum acceleration
+ buf.readUnsignedByte(); // maximum deceleration
+ buf.readUnsignedByte(); // maximum cornering
+ }
+ if (BitUtil.check(mask, 7)) {
+ buf.skipBytes(16);
+ }
+ if (BitUtil.check(mask, 8)) {
+ buf.skipBytes(40); // temperature sensors
+ }
+ if (BitUtil.check(mask, 9)) {
+ position.set("driver1", buf.readCharSequence(16, StandardCharsets.US_ASCII).toString().trim());
+ position.set("driver2", buf.readCharSequence(16, StandardCharsets.US_ASCII).toString().trim());
+ }
+ if (BitUtil.check(mask, 10)) {
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE());
+ }
}
@Override
@@ -230,6 +295,11 @@ public class BceProtocolDecoder extends BaseProtocolDecoder {
mask = masks.get(2);
decodeMask3(buf, mask, position);
}
+
+ if (masks.size() >= 4) {
+ mask = masks.get(3);
+ decodeMask4(buf, mask, position);
+ }
}
buf.readerIndex(structEnd);
diff --git a/src/main/java/org/traccar/protocol/BceProtocolEncoder.java b/src/main/java/org/traccar/protocol/BceProtocolEncoder.java
index 1bbf3db12..53ac51581 100644
--- a/src/main/java/org/traccar/protocol/BceProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/BceProtocolEncoder.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.
@@ -20,9 +20,14 @@ import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class BceProtocolEncoder extends BaseProtocolEncoder {
+ public BceProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/CalAmpProtocolDecoder.java b/src/main/java/org/traccar/protocol/CalAmpProtocolDecoder.java
index 31416d7f1..dad0ae774 100644
--- a/src/main/java/org/traccar/protocol/CalAmpProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CalAmpProtocolDecoder.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.
@@ -153,7 +153,7 @@ public class CalAmpProtocolDecoder extends BaseProtocolDecoder {
int content = buf.readUnsignedByte();
if (BitUtil.check(content, 0)) {
- String id = ByteBufUtil.hexDump(buf.readSlice(buf.readUnsignedByte()));
+ String id = ByteBufUtil.hexDump(buf.readSlice(buf.readUnsignedByte())).replace("f", "");
getDeviceSession(channel, remoteAddress, id);
}
diff --git a/src/main/java/org/traccar/protocol/CarcellProtocol.java b/src/main/java/org/traccar/protocol/CarcellProtocol.java
index 0c305efcb..f08ab3bd9 100644
--- a/src/main/java/org/traccar/protocol/CarcellProtocol.java
+++ b/src/main/java/org/traccar/protocol/CarcellProtocol.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.
@@ -35,7 +35,7 @@ public class CarcellProtocol extends BaseProtocol {
pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, '\r'));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new CarcellProtocolEncoder());
+ pipeline.addLast(new CarcellProtocolEncoder(CarcellProtocol.this));
pipeline.addLast(new CarcellProtocolDecoder(CarcellProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/CarcellProtocolDecoder.java b/src/main/java/org/traccar/protocol/CarcellProtocolDecoder.java
index 344b2f1ea..ec640ba71 100644
--- a/src/main/java/org/traccar/protocol/CarcellProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CarcellProtocolDecoder.java
@@ -155,7 +155,7 @@ public class CarcellProtocolDecoder extends BaseProtocolDecoder {
Double mainVoltage = parser.nextDouble(0) / 100d;
position.set(Position.KEY_POWER, mainVoltage);
- position.set("iccid", parser.next());
+ position.set(Position.KEY_ICCID, parser.next());
}
return position;
diff --git a/src/main/java/org/traccar/protocol/CarcellProtocolEncoder.java b/src/main/java/org/traccar/protocol/CarcellProtocolEncoder.java
index e8f0081a0..083fe9a9e 100644
--- a/src/main/java/org/traccar/protocol/CarcellProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/CarcellProtocolEncoder.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.
@@ -17,9 +17,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class CarcellProtocolEncoder extends StringProtocolEncoder {
+ public CarcellProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/CastelProtocol.java b/src/main/java/org/traccar/protocol/CastelProtocol.java
index 9b854afc3..44c52d68f 100644
--- a/src/main/java/org/traccar/protocol/CastelProtocol.java
+++ b/src/main/java/org/traccar/protocol/CastelProtocol.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.
@@ -32,14 +32,14 @@ public class CastelProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN, 1024, 2, 2, -4, 0, true));
- pipeline.addLast(new CastelProtocolEncoder());
+ pipeline.addLast(new CastelProtocolEncoder(CastelProtocol.this));
pipeline.addLast(new CastelProtocolDecoder(CastelProtocol.this));
}
});
addServer(new TrackerServer(true, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new CastelProtocolEncoder());
+ pipeline.addLast(new CastelProtocolEncoder(CastelProtocol.this));
pipeline.addLast(new CastelProtocolDecoder(CastelProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java b/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java
index 0541adf6f..03e4b25fd 100644
--- a/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CastelProtocolDecoder.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.
@@ -84,6 +84,7 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder {
public static final short MSG_SC_HEARTBEAT_RESPONSE = (short) 0x9003;
public static final short MSG_SC_GPS = 0x4001;
public static final short MSG_SC_PID_DATA = 0x4002;
+ public static final short MSG_SC_G_SENSOR = 0x4003;
public static final short MSG_SC_SUPPORTED_PID = 0x4004;
public static final short MSG_SC_OBD_DATA = 0x4005;
public static final short MSG_SC_DTCS_PASSENGER = 0x4006;
@@ -290,152 +291,179 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder {
Channel channel, SocketAddress remoteAddress, ByteBuf buf,
int version, ByteBuf id, short type, DeviceSession deviceSession) {
- if (type == MSG_SC_HEARTBEAT) {
-
- sendResponse(channel, remoteAddress, version, id, MSG_SC_HEARTBEAT_RESPONSE, null);
-
- } else if (type == MSG_SC_LOGIN || type == MSG_SC_LOGOUT || type == MSG_SC_GPS
- || type == MSG_SC_ALARM || type == MSG_SC_CURRENT_LOCATION || type == MSG_SC_FUEL) {
-
- if (type == MSG_SC_LOGIN) {
- ByteBuf response = Unpooled.buffer(10);
- response.writeIntLE(0xFFFFFFFF);
- response.writeShortLE(0);
- response.writeIntLE((int) (System.currentTimeMillis() / 1000));
- sendResponse(channel, remoteAddress, version, id, MSG_SC_LOGIN_RESPONSE, response);
- }
-
- if (type == MSG_SC_GPS) {
- buf.readUnsignedByte(); // historical
- } else if (type == MSG_SC_ALARM) {
- buf.readUnsignedIntLE(); // alarm
- } else if (type == MSG_SC_CURRENT_LOCATION) {
- buf.readUnsignedShortLE();
- }
-
- buf.readUnsignedIntLE(); // ACC ON time
- buf.readUnsignedIntLE(); // UTC time
- long odometer = buf.readUnsignedIntLE();
- long tripOdometer = buf.readUnsignedIntLE();
- long fuelConsumption = buf.readUnsignedIntLE();
- buf.readUnsignedShortLE(); // current fuel consumption
- long status = buf.readUnsignedIntLE();
- buf.skipBytes(8);
-
- int count = buf.readUnsignedByte();
+ Position position;
+ int count;
+
+ switch (type) {
+
+ case MSG_SC_HEARTBEAT:
+ sendResponse(channel, remoteAddress, version, id, MSG_SC_HEARTBEAT_RESPONSE, null);
+ return null;
+
+ case MSG_SC_LOGIN:
+ case MSG_SC_LOGOUT:
+ case MSG_SC_GPS:
+ case MSG_SC_ALARM:
+ case MSG_SC_CURRENT_LOCATION:
+ case MSG_SC_FUEL:
+ if (type == MSG_SC_LOGIN) {
+ ByteBuf response = Unpooled.buffer(10);
+ response.writeIntLE(0xFFFFFFFF);
+ response.writeShortLE(0);
+ response.writeIntLE((int) (System.currentTimeMillis() / 1000));
+ sendResponse(channel, remoteAddress, version, id, MSG_SC_LOGIN_RESPONSE, response);
+ }
- List<Position> positions = new LinkedList<>();
+ if (type == MSG_SC_GPS) {
+ buf.readUnsignedByte(); // historical
+ } else if (type == MSG_SC_ALARM) {
+ buf.readUnsignedIntLE(); // alarm
+ } else if (type == MSG_SC_CURRENT_LOCATION) {
+ buf.readUnsignedShortLE();
+ }
- for (int i = 0; i < count; i++) {
- Position position = readPosition(deviceSession, buf);
- position.set(Position.KEY_ODOMETER, odometer);
- position.set(Position.KEY_ODOMETER_TRIP, tripOdometer);
- position.set(Position.KEY_FUEL_CONSUMPTION, fuelConsumption);
- position.set(Position.KEY_STATUS, status);
- positions.add(position);
- }
+ buf.readUnsignedIntLE(); // ACC ON time
+ buf.readUnsignedIntLE(); // UTC time
+ long odometer = buf.readUnsignedIntLE();
+ long tripOdometer = buf.readUnsignedIntLE();
+ long fuelConsumption = buf.readUnsignedIntLE();
+ buf.readUnsignedShortLE(); // current fuel consumption
+ long status = buf.readUnsignedIntLE();
+ buf.skipBytes(8);
+
+ count = buf.readUnsignedByte();
+
+ List<Position> positions = new LinkedList<>();
+
+ for (int i = 0; i < count; i++) {
+ position = readPosition(deviceSession, buf);
+ position.set(Position.KEY_ODOMETER, odometer);
+ position.set(Position.KEY_ODOMETER_TRIP, tripOdometer);
+ position.set(Position.KEY_FUEL_CONSUMPTION, fuelConsumption);
+ position.set(Position.KEY_STATUS, status);
+ positions.add(position);
+ }
- if (type == MSG_SC_ALARM) {
- int alarmCount = buf.readUnsignedByte();
- for (int i = 0; i < alarmCount; i++) {
- if (buf.readUnsignedByte() != 0) {
- int alarm = buf.readUnsignedByte();
- for (Position position : positions) {
- decodeAlarm(position, alarm);
+ if (type == MSG_SC_ALARM) {
+ int alarmCount = buf.readUnsignedByte();
+ for (int i = 0; i < alarmCount; i++) {
+ if (buf.readUnsignedByte() != 0) {
+ int alarm = buf.readUnsignedByte();
+ for (Position p : positions) {
+ decodeAlarm(p, alarm);
+ }
+ buf.readUnsignedShortLE(); // description
+ buf.readUnsignedShortLE(); // threshold
}
- buf.readUnsignedShortLE(); // description
- buf.readUnsignedShortLE(); // threshold
+ }
+ } else if (type == MSG_SC_FUEL) {
+ for (Position p : positions) {
+ p.set(Position.PREFIX_ADC + 1, buf.readUnsignedShortLE());
}
}
- } else if (type == MSG_SC_FUEL) {
- for (Position position : positions) {
- position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShortLE());
- }
- }
- if (!positions.isEmpty()) {
- return positions;
- }
+ return positions.isEmpty() ? null : positions;
- } else if (type == MSG_SC_GPS_SLEEP) {
+ case MSG_SC_GPS_SLEEP:
+ buf.readUnsignedIntLE(); // device time
+ return readPosition(deviceSession, buf);
- buf.readUnsignedIntLE(); // device time
+ case MSG_SC_AGPS_REQUEST:
+ return readPosition(deviceSession, buf);
- return readPosition(deviceSession, buf);
+ case MSG_SC_PID_DATA:
+ position = createPosition(deviceSession);
- } else if (type == MSG_SC_AGPS_REQUEST) {
+ decodeStat(position, buf);
- return readPosition(deviceSession, buf);
+ buf.readUnsignedShortLE(); // sample rate
+ decodeObd(position, buf, true);
- } else if (type == MSG_SC_PID_DATA) {
+ return position;
- Position position = createPosition(deviceSession);
+ case MSG_SC_G_SENSOR:
+ position = createPosition(deviceSession);
- decodeStat(position, buf);
+ decodeStat(position, buf);
- buf.readUnsignedShortLE(); // sample rate
- decodeObd(position, buf, true);
+ buf.readUnsignedShortLE(); // sample rate
- return position;
+ count = buf.readUnsignedByte();
- } else if (type == MSG_SC_DTCS_PASSENGER) {
+ StringBuilder data = new StringBuilder("[");
+ for (int i = 0; i < count; i++) {
+ if (i > 0) {
+ data.append(",");
+ }
+ data.append("[");
+ data.append(buf.readShortLE() * 0.015625);
+ data.append(",");
+ data.append(buf.readShortLE() * 0.015625);
+ data.append(",");
+ data.append(buf.readShortLE() * 0.015625);
+ data.append("]");
+ }
+ data.append("]");
- Position position = createPosition(deviceSession);
+ position.set(Position.KEY_G_SENSOR, data.toString());
- decodeStat(position, buf);
+ return position;
- buf.readUnsignedByte(); // flag
- position.add(ObdDecoder.decodeCodes(ByteBufUtil.hexDump(buf.readSlice(buf.readUnsignedByte()))));
+ case MSG_SC_DTCS_PASSENGER:
+ position = createPosition(deviceSession);
- return position;
+ decodeStat(position, buf);
- } else if (type == MSG_SC_OBD_DATA) {
+ buf.readUnsignedByte(); // flag
+ position.add(ObdDecoder.decodeCodes(ByteBufUtil.hexDump(buf.readSlice(buf.readUnsignedByte()))));
- Position position = createPosition(deviceSession);
+ return position;
- decodeStat(position, buf);
+ case MSG_SC_OBD_DATA:
+ position = createPosition(deviceSession);
- buf.readUnsignedByte(); // flag
- decodeObd(position, buf, false);
+ decodeStat(position, buf);
- return position;
+ buf.readUnsignedByte(); // flag
+ decodeObd(position, buf, false);
- } else if (type == MSG_SC_CELL) {
+ return position;
- Position position = createPosition(deviceSession);
+ case MSG_SC_CELL:
+ position = createPosition(deviceSession);
- decodeStat(position, buf);
+ decodeStat(position, buf);
- position.setNetwork(new Network(
- CellTower.fromLacCid(buf.readUnsignedShortLE(), buf.readUnsignedShortLE())));
+ position.setNetwork(new Network(
+ CellTower.fromLacCid(buf.readUnsignedShortLE(), buf.readUnsignedShortLE())));
- return position;
+ return position;
- } else if (type == MSG_SC_QUERY_RESPONSE) {
+ case MSG_SC_QUERY_RESPONSE:
+ position = createPosition(deviceSession);
- Position position = createPosition(deviceSession);
+ buf.readUnsignedShortLE(); // index
+ buf.readUnsignedByte(); // response count
+ buf.readUnsignedByte(); // response index
- buf.readUnsignedShortLE(); // index
- buf.readUnsignedByte(); // response count
- buf.readUnsignedByte(); // response index
+ int failureCount = buf.readUnsignedByte();
+ for (int i = 0; i < failureCount; i++) {
+ buf.readUnsignedShortLE(); // tag
+ }
- int failureCount = buf.readUnsignedByte();
- for (int i = 0; i < failureCount; i++) {
- buf.readUnsignedShortLE(); // tag
- }
+ int successCount = buf.readUnsignedByte();
+ for (int i = 0; i < successCount; i++) {
+ buf.readUnsignedShortLE(); // tag
+ position.set(Position.KEY_RESULT,
+ buf.readSlice(buf.readUnsignedShortLE()).toString(StandardCharsets.US_ASCII));
+ }
- int successCount = buf.readUnsignedByte();
- for (int i = 0; i < successCount; i++) {
- buf.readUnsignedShortLE(); // tag
- position.set(Position.KEY_RESULT,
- buf.readSlice(buf.readUnsignedShortLE()).toString(StandardCharsets.US_ASCII));
- }
+ return position;
- return position;
+ default:
+ return null;
}
-
- return null;
}
private Object decodeCc(
diff --git a/src/main/java/org/traccar/protocol/CastelProtocolEncoder.java b/src/main/java/org/traccar/protocol/CastelProtocolEncoder.java
index e1f78e7c1..dc694da28 100644
--- a/src/main/java/org/traccar/protocol/CastelProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/CastelProtocolEncoder.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.
@@ -21,11 +21,16 @@ import org.traccar.BaseProtocolEncoder;
import org.traccar.Context;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
public class CastelProtocolEncoder extends BaseProtocolEncoder {
+ public CastelProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeContent(long deviceId, short type, ByteBuf content) {
ByteBuf buf = Unpooled.buffer(0);
diff --git a/src/main/java/org/traccar/protocol/CellocatorProtocol.java b/src/main/java/org/traccar/protocol/CellocatorProtocol.java
index a52170dc9..d910877cf 100644
--- a/src/main/java/org/traccar/protocol/CellocatorProtocol.java
+++ b/src/main/java/org/traccar/protocol/CellocatorProtocol.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.
@@ -29,14 +29,14 @@ public class CellocatorProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new CellocatorFrameDecoder());
- pipeline.addLast(new CellocatorProtocolEncoder());
+ pipeline.addLast(new CellocatorProtocolEncoder(CellocatorProtocol.this));
pipeline.addLast(new CellocatorProtocolDecoder(CellocatorProtocol.this));
}
});
addServer(new TrackerServer(true, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new CellocatorProtocolEncoder());
+ pipeline.addLast(new CellocatorProtocolEncoder(CellocatorProtocol.this));
pipeline.addLast(new CellocatorProtocolDecoder(CellocatorProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java
index 14d14f4b6..aa13a0aa2 100644
--- a/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java
@@ -43,29 +43,52 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_SERVER_ACKNOWLEDGE = 4;
- private byte commandCount;
+ public static ByteBuf encodeContent(int type, int uniqueId, int packetNumber, ByteBuf content) {
+
+ ByteBuf buf = Unpooled.buffer();
+ buf.writeByte('M');
+ buf.writeByte('C');
+ buf.writeByte('G');
+ buf.writeByte('P');
+ buf.writeByte(type);
+ buf.writeIntLE(uniqueId);
+ buf.writeByte(packetNumber);
+ buf.writeIntLE(0); // authentication code
+ buf.writeBytes(content);
+
+ byte checksum = 0;
+ for (int i = 4; i < buf.writerIndex(); i++) {
+ checksum += buf.getByte(i);
+ }
+ buf.writeByte(checksum);
+
+ return buf;
+ }
private void sendResponse(Channel channel, SocketAddress remoteAddress, long deviceId, byte packetNumber) {
if (channel != null) {
- ByteBuf reply = Unpooled.buffer(28);
- reply.writeByte('M');
- reply.writeByte('C');
- reply.writeByte('G');
- reply.writeByte('P');
- reply.writeByte(MSG_SERVER_ACKNOWLEDGE);
- reply.writeIntLE((int) deviceId);
- reply.writeByte(commandCount++);
- reply.writeIntLE(0); // authentication code
- reply.writeByte(0);
- reply.writeByte(packetNumber);
- reply.writeZero(11);
-
- byte checksum = 0;
- for (int i = 4; i < 27; i++) {
- checksum += reply.getByte(i);
- }
- reply.writeByte(checksum);
+ ByteBuf content = Unpooled.buffer();
+ content.writeByte(0);
+ content.writeByte(packetNumber);
+ content.writeZero(11);
+ ByteBuf reply = encodeContent(MSG_SERVER_ACKNOWLEDGE, (int) deviceId, packetNumber, content);
+ channel.writeAndFlush(new NetworkMessage(reply, remoteAddress));
+ }
+ }
+
+ private void sendModuleResponse(Channel channel, SocketAddress remoteAddress, long deviceId, byte packetNumber) {
+ if (channel != null) {
+ ByteBuf content = Unpooled.buffer();
+ content.writeByte(0x80);
+ content.writeShortLE(10); // modules length
+ content.writeIntLE(0); // reserved
+ content.writeByte(9); // ack module type
+ content.writeShortLE(3); // module length
+ content.writeByte(0); // ack
+ content.writeShortLE(0); // reserved
+
+ ByteBuf reply = encodeContent(MSG_CLIENT_MODULAR_EXT, (int) deviceId, packetNumber, content);
channel.writeAndFlush(new NetworkMessage(reply, remoteAddress));
}
}
@@ -225,7 +248,11 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder {
}
byte packetNumber = buf.readByte();
- sendResponse(channel, remoteAddress, deviceUniqueId, packetNumber);
+ if (type == MSG_CLIENT_MODULAR_EXT) {
+ sendModuleResponse(channel, remoteAddress, deviceUniqueId, packetNumber);
+ } else {
+ sendResponse(channel, remoteAddress, deviceUniqueId, packetNumber);
+ }
if (type == MSG_CLIENT_STATUS) {
return decodeStatus(buf, deviceSession, alternative);
diff --git a/src/main/java/org/traccar/protocol/CellocatorProtocolEncoder.java b/src/main/java/org/traccar/protocol/CellocatorProtocolEncoder.java
index 0382dbbc7..76fa67686 100644
--- a/src/main/java/org/traccar/protocol/CellocatorProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/CellocatorProtocolEncoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 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.
@@ -19,27 +19,26 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class CellocatorProtocolEncoder extends BaseProtocolEncoder {
- private ByteBuf encodeContent(long deviceId, int command, int data1, int data2) {
+ public CellocatorProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public static ByteBuf encodeContent(int type, int uniqueId, int packetNumber, ByteBuf content) {
- ByteBuf buf = Unpooled.buffer(0);
+ ByteBuf buf = Unpooled.buffer();
buf.writeByte('M');
buf.writeByte('C');
buf.writeByte('G');
buf.writeByte('P');
- buf.writeByte(0);
- buf.writeIntLE(Integer.parseInt(getUniqueId(deviceId)));
- buf.writeByte(0); // command numerator
+ buf.writeByte(type);
+ buf.writeIntLE(uniqueId);
+ buf.writeByte(packetNumber);
buf.writeIntLE(0); // authentication code
- buf.writeByte(command);
- buf.writeByte(command);
- buf.writeByte(data1);
- buf.writeByte(data1);
- buf.writeByte(data2);
- buf.writeByte(data2);
- buf.writeIntLE(0); // command specific data
+ buf.writeBytes(content);
byte checksum = 0;
for (int i = 4; i < buf.writerIndex(); i++) {
@@ -50,6 +49,23 @@ public class CellocatorProtocolEncoder extends BaseProtocolEncoder {
return buf;
}
+ private ByteBuf encodeCommand(long deviceId, int command, int data1, int data2) {
+
+ ByteBuf content = Unpooled.buffer();
+ content.writeByte(command);
+ content.writeByte(command);
+ content.writeByte(data1);
+ content.writeByte(data1);
+ content.writeByte(data2);
+ content.writeByte(data2);
+ content.writeIntLE(0); // command specific data
+
+ ByteBuf buf = encodeContent(0, Integer.parseInt(getUniqueId(deviceId)), 0, content);
+ content.release();
+
+ return buf;
+ }
+
@Override
protected Object encodeCommand(Command command) {
@@ -57,7 +73,7 @@ public class CellocatorProtocolEncoder extends BaseProtocolEncoder {
case Command.TYPE_OUTPUT_CONTROL:
int data = Integer.parseInt(command.getString(Command.KEY_DATA)) << 4
+ command.getInteger(Command.KEY_INDEX);
- return encodeContent(command.getDeviceId(), 0x03, data, 0);
+ return encodeCommand(command.getDeviceId(), 0x03, data, 0);
default:
return null;
}
diff --git a/src/main/java/org/traccar/protocol/CityeasyProtocol.java b/src/main/java/org/traccar/protocol/CityeasyProtocol.java
index f4b49c9ff..8ab4ce93a 100644
--- a/src/main/java/org/traccar/protocol/CityeasyProtocol.java
+++ b/src/main/java/org/traccar/protocol/CityeasyProtocol.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.
@@ -33,7 +33,7 @@ public class CityeasyProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 2, 2, -4, 0));
- pipeline.addLast(new CityeasyProtocolEncoder());
+ pipeline.addLast(new CityeasyProtocolEncoder(CityeasyProtocol.this));
pipeline.addLast(new CityeasyProtocolDecoder(CityeasyProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/CityeasyProtocolEncoder.java b/src/main/java/org/traccar/protocol/CityeasyProtocolEncoder.java
index 350fdf0ab..934105862 100644
--- a/src/main/java/org/traccar/protocol/CityeasyProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/CityeasyProtocolEncoder.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.
@@ -22,9 +22,14 @@ import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class CityeasyProtocolEncoder extends BaseProtocolEncoder {
+ public CityeasyProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeContent(int type, ByteBuf content) {
ByteBuf buf = Unpooled.buffer();
diff --git a/src/main/java/org/traccar/protocol/DmtProtocolDecoder.java b/src/main/java/org/traccar/protocol/DmtProtocolDecoder.java
index c49f06d65..58a5a88e3 100644
--- a/src/main/java/org/traccar/protocol/DmtProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/DmtProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 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.
@@ -208,6 +208,7 @@ public class DmtProtocolDecoder extends BaseProtocolDecoder {
position.set("solarPower", buf.readUnsignedShortLE() * 0.001);
break;
default:
+ buf.readUnsignedShortLE(); // other
break;
}
}
diff --git a/src/main/java/org/traccar/protocol/EelinkProtocol.java b/src/main/java/org/traccar/protocol/EelinkProtocol.java
index de4ea971b..8a055d643 100644
--- a/src/main/java/org/traccar/protocol/EelinkProtocol.java
+++ b/src/main/java/org/traccar/protocol/EelinkProtocol.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.
@@ -34,14 +34,14 @@ public class EelinkProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 3, 2));
- pipeline.addLast(new EelinkProtocolEncoder(false));
+ pipeline.addLast(new EelinkProtocolEncoder(EelinkProtocol.this, false));
pipeline.addLast(new EelinkProtocolDecoder(EelinkProtocol.this));
}
});
addServer(new TrackerServer(true, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new EelinkProtocolEncoder(true));
+ pipeline.addLast(new EelinkProtocolEncoder(EelinkProtocol.this, true));
pipeline.addLast(new EelinkProtocolDecoder(EelinkProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java b/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java
index a6fd94b83..41d76f37f 100644
--- a/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java
@@ -412,7 +412,8 @@ public class EelinkProtocolDecoder extends BaseProtocolDecoder {
return decodeNew(deviceSession, buf, type, index);
- } else if (type == MSG_HEARTBEAT && buf.readableBytes() >= 2) {
+ } else if (type == MSG_HEARTBEAT && buf.readableBytes() >= 2
+ || type == MSG_OBD && buf.readableBytes() == 4) {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
diff --git a/src/main/java/org/traccar/protocol/EelinkProtocolEncoder.java b/src/main/java/org/traccar/protocol/EelinkProtocolEncoder.java
index 8f33441fb..3673c35b3 100644
--- a/src/main/java/org/traccar/protocol/EelinkProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/EelinkProtocolEncoder.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.
@@ -20,6 +20,7 @@ import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.DataConverter;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@@ -28,7 +29,8 @@ public class EelinkProtocolEncoder extends BaseProtocolEncoder {
private boolean connectionless;
- public EelinkProtocolEncoder(boolean connectionless) {
+ public EelinkProtocolEncoder(Protocol protocol, boolean connectionless) {
+ super(protocol);
this.connectionless = connectionless;
}
diff --git a/src/main/java/org/traccar/protocol/EgtsProtocolDecoder.java b/src/main/java/org/traccar/protocol/EgtsProtocolDecoder.java
index b9fcb2f44..9f0baf6b2 100644
--- a/src/main/java/org/traccar/protocol/EgtsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EgtsProtocolDecoder.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.
@@ -39,6 +39,8 @@ public class EgtsProtocolDecoder extends BaseProtocolDecoder {
super(protocol);
}
+ private boolean useObjectIdAsDeviceId = true;
+
public static final int PT_RESPONSE = 0;
public static final int PT_APPDATA = 1;
public static final int PT_SIGNED_APPDATA = 2;
@@ -68,7 +70,7 @@ public class EgtsProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_ABS_CNTR_DATA = 25;
public static final int MSG_ABS_LOOPIN_DATA = 26;
public static final int MSG_LIQUID_LEVEL_SENSOR = 27;
- public static final int MSG_PASSENGERS_COUNTERS = 28;
+ public static final int MSG_PASSENGERS_COUNTERS = 28;
private int packetId;
@@ -121,11 +123,18 @@ public class EgtsProtocolDecoder extends BaseProtocolDecoder {
ByteBuf buf = (ByteBuf) msg;
+ List<Position> positions = new LinkedList<>();
+
+ short headerLength = buf.getUnsignedByte(buf.readerIndex() + 3);
int index = buf.getUnsignedShort(buf.readerIndex() + 5 + 2);
- buf.skipBytes(buf.getUnsignedByte(buf.readerIndex() + 3));
+ short packetType = buf.getUnsignedByte(buf.readerIndex() + 5 + 2 + 2);
+ buf.skipBytes(headerLength);
- List<Position> positions = new LinkedList<>();
+ if (packetType == PT_RESPONSE) {
+ return null;
+ }
+ long objectId = 0L;
while (buf.readableBytes() > 2) {
int length = buf.readUnsignedShortLE();
@@ -133,7 +142,7 @@ public class EgtsProtocolDecoder extends BaseProtocolDecoder {
int recordFlags = buf.readUnsignedByte();
if (BitUtil.check(recordFlags, 0)) {
- buf.readUnsignedIntLE(); // object id
+ objectId = buf.readUnsignedIntLE();
}
if (BitUtil.check(recordFlags, 1)) {
@@ -164,6 +173,7 @@ public class EgtsProtocolDecoder extends BaseProtocolDecoder {
int end = buf.readUnsignedShortLE() + buf.readerIndex();
if (type == MSG_TERM_IDENTITY) {
+ useObjectIdAsDeviceId = false;
buf.readUnsignedIntLE(); // object id
int flags = buf.readUnsignedByte();
@@ -254,8 +264,16 @@ public class EgtsProtocolDecoder extends BaseProtocolDecoder {
buf.readerIndex(end);
}
- if (serviceType == SERVICE_TELEDATA && deviceSession != null) {
- positions.add(position);
+ if (serviceType == SERVICE_TELEDATA && position.getValid()) {
+ if (useObjectIdAsDeviceId && objectId != 0L) {
+ deviceSession = getDeviceSession(channel, remoteAddress, true, String.valueOf(objectId));
+ if (deviceSession != null) {
+ position.setDeviceId(deviceSession.getDeviceId());
+ }
+ }
+ if (deviceSession != null) {
+ positions.add(position);
+ }
}
}
diff --git a/src/main/java/org/traccar/protocol/EnforaProtocol.java b/src/main/java/org/traccar/protocol/EnforaProtocol.java
index f78e4b377..e462ab322 100644
--- a/src/main/java/org/traccar/protocol/EnforaProtocol.java
+++ b/src/main/java/org/traccar/protocol/EnforaProtocol.java
@@ -32,14 +32,14 @@ public class EnforaProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 2, -2, 2));
- pipeline.addLast(new EnforaProtocolEncoder());
+ pipeline.addLast(new EnforaProtocolEncoder(EnforaProtocol.this));
pipeline.addLast(new EnforaProtocolDecoder(EnforaProtocol.this));
}
});
addServer(new TrackerServer(true, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new EnforaProtocolEncoder());
+ pipeline.addLast(new EnforaProtocolEncoder(EnforaProtocol.this));
pipeline.addLast(new EnforaProtocolDecoder(EnforaProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/EnforaProtocolEncoder.java b/src/main/java/org/traccar/protocol/EnforaProtocolEncoder.java
index a46e6367d..8cc24dc0f 100644
--- a/src/main/java/org/traccar/protocol/EnforaProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/EnforaProtocolEncoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org)
* Copyright 2017 Jose Castellanos
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,11 +20,16 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
public class EnforaProtocolEncoder extends StringProtocolEncoder {
+ public EnforaProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeContent(String content) {
ByteBuf buf = Unpooled.buffer();
diff --git a/src/main/java/org/traccar/protocol/EsealProtocol.java b/src/main/java/org/traccar/protocol/EsealProtocol.java
index 7a27c617d..fc1d342e1 100644
--- a/src/main/java/org/traccar/protocol/EsealProtocol.java
+++ b/src/main/java/org/traccar/protocol/EsealProtocol.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.
@@ -36,7 +36,7 @@ public class EsealProtocol extends BaseProtocol {
pipeline.addLast(new LineBasedFrameDecoder(1024));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new EsealProtocolEncoder());
+ pipeline.addLast(new EsealProtocolEncoder(EsealProtocol.this));
pipeline.addLast(new EsealProtocolDecoder(EsealProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/EsealProtocolEncoder.java b/src/main/java/org/traccar/protocol/EsealProtocolEncoder.java
index b9bcc5b0a..6ee305ed8 100644
--- a/src/main/java/org/traccar/protocol/EsealProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/EsealProtocolEncoder.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.
@@ -17,9 +17,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class EsealProtocolEncoder extends StringProtocolEncoder {
+ public EsealProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/FifotrackProtocol.java b/src/main/java/org/traccar/protocol/FifotrackProtocol.java
index d1c3cf695..4a0a12ed3 100644
--- a/src/main/java/org/traccar/protocol/FifotrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/FifotrackProtocol.java
@@ -32,7 +32,7 @@ public class FifotrackProtocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new FifotrackFrameDecoder());
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new FifotrackProtocolEncoder());
+ pipeline.addLast(new FifotrackProtocolEncoder(FifotrackProtocol.this));
pipeline.addLast(new FifotrackProtocolDecoder(FifotrackProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java
index 2e728a918..40e146e0b 100644
--- a/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java
@@ -60,7 +60,7 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
.number("(-?d+),") // altitude
.number("(d+),") // odometer
.number("d+,") // runtime
- .number("(xxxx),") // status
+ .number("(x{4,8}),") // status
.number("(x+)?,") // input
.number("(x+)?,") // output
.number("(d+)|") // mcc
@@ -69,7 +69,7 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
.number("(x+),") // cid
.number("([x|]+)") // adc
.expression(",([^,]+)") // rfid
- .expression(",([^*]+)").optional(2) // sensors
+ .expression(",([^*]*)").optional(2) // sensors
.any()
.compile();
@@ -105,6 +105,24 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
}
}
+ private String decodeAlarm(Integer alarm) {
+ if (alarm != null) {
+ switch (alarm) {
+ case 2:
+ return Position.ALARM_SOS;
+ case 14:
+ return Position.ALARM_LOW_POWER;
+ case 15:
+ return Position.ALARM_POWER_CUT;
+ case 16:
+ return Position.ALARM_POWER_RESTORED;
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+
private Object decodeLocation(
Channel channel, SocketAddress remoteAddress, String sentence) {
@@ -121,35 +139,33 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
- position.set(Position.KEY_ALARM, parser.next());
+ position.set(Position.KEY_ALARM, decodeAlarm(parser.nextInt()));
position.setTime(parser.nextDateTime());
position.setValid(parser.next().equals("A"));
- position.setLatitude(parser.nextDouble(0));
- position.setLongitude(parser.nextDouble(0));
- position.setSpeed(UnitsConverter.knotsFromKph(parser.nextInt(0)));
- position.setCourse(parser.nextInt(0));
- position.setAltitude(parser.nextInt(0));
-
- position.set(Position.KEY_ODOMETER, parser.nextLong(0));
- position.set(Position.KEY_STATUS, parser.nextHexInt(0));
- if (parser.hasNext()) {
- position.set(Position.KEY_INPUT, parser.nextHexInt(0));
- }
- if (parser.hasNext()) {
- position.set(Position.KEY_OUTPUT, parser.nextHexInt(0));
- }
+ position.setLatitude(parser.nextDouble());
+ position.setLongitude(parser.nextDouble());
+ position.setSpeed(UnitsConverter.knotsFromKph(parser.nextInt()));
+ position.setCourse(parser.nextInt());
+ position.setAltitude(parser.nextInt());
+
+ position.set(Position.KEY_ODOMETER, parser.nextLong());
+ position.set(Position.KEY_STATUS, parser.nextHexLong());
+ position.set(Position.KEY_INPUT, parser.nextHexInt());
+ position.set(Position.KEY_OUTPUT, parser.nextHexInt());
position.setNetwork(new Network(CellTower.from(
- parser.nextInt(0), parser.nextInt(0), parser.nextHexInt(0), parser.nextHexInt(0))));
+ parser.nextInt(), parser.nextInt(), parser.nextHexInt(), parser.nextHexInt())));
String[] adc = parser.next().split("\\|");
for (int i = 0; i < adc.length; i++) {
position.set(Position.PREFIX_ADC + (i + 1), Integer.parseInt(adc[i], 16));
}
- position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next());
+ if (parser.hasNext()) {
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, String.valueOf(parser.nextHexInt()));
+ }
if (parser.hasNext()) {
String[] sensors = parser.next().split("\\|");
diff --git a/src/main/java/org/traccar/protocol/FifotrackProtocolEncoder.java b/src/main/java/org/traccar/protocol/FifotrackProtocolEncoder.java
index ff0a2e56e..a4e69b47b 100644
--- a/src/main/java/org/traccar/protocol/FifotrackProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/FifotrackProtocolEncoder.java
@@ -18,9 +18,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class FifotrackProtocolEncoder extends StringProtocolEncoder {
+ public FifotrackProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private Object formatCommand(Command command, String content) {
String uniqueId = getUniqueId(command.getDeviceId());
int length = 1 + uniqueId.length() + 3 + content.length();
diff --git a/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java b/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java
index 86da3943e..7405fb6ef 100644
--- a/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java
@@ -21,6 +21,7 @@ import io.netty.handler.codec.http.HttpResponseStatus;
import org.traccar.BaseHttpProtocolDecoder;
import org.traccar.DeviceSession;
import org.traccar.Protocol;
+import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
import javax.json.Json;
@@ -102,7 +103,7 @@ public class FlespiProtocolDecoder extends BaseHttpProtocolDecoder {
position.setLongitude(((JsonNumber) value).doubleValue());
return true;
case "position.speed":
- position.setSpeed(((JsonNumber) value).doubleValue());
+ position.setSpeed(UnitsConverter.knotsFromKph(((JsonNumber) value).doubleValue()));
return true;
case "position.direction":
position.setCourse(((JsonNumber) value).doubleValue());
diff --git a/src/main/java/org/traccar/protocol/GalileoProtocol.java b/src/main/java/org/traccar/protocol/GalileoProtocol.java
index 9b7fe1a4b..a1570c9b0 100644
--- a/src/main/java/org/traccar/protocol/GalileoProtocol.java
+++ b/src/main/java/org/traccar/protocol/GalileoProtocol.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.
@@ -30,7 +30,7 @@ public class GalileoProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new GalileoFrameDecoder());
- pipeline.addLast(new GalileoProtocolEncoder());
+ pipeline.addLast(new GalileoProtocolEncoder(GalileoProtocol.this));
pipeline.addLast(new GalileoProtocolDecoder(GalileoProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/GalileoProtocolDecoder.java b/src/main/java/org/traccar/protocol/GalileoProtocolDecoder.java
index 5b843324c..dfaedd695 100644
--- a/src/main/java/org/traccar/protocol/GalileoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GalileoProtocolDecoder.java
@@ -318,7 +318,9 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedByte(); // part number
photo.writeBytes(buf, length - 1);
- } else {
+ sendResponse(channel, 0x07, buf.readUnsignedShortLE());
+
+ } else if (photo != null) {
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
String uniqueId = Context.getIdentityManager().getById(deviceSession.getDeviceId()).getUniqueId();
@@ -334,8 +336,6 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder {
}
- sendResponse(channel, 0x07, buf.readUnsignedShortLE());
-
return position;
}
diff --git a/src/main/java/org/traccar/protocol/GalileoProtocolEncoder.java b/src/main/java/org/traccar/protocol/GalileoProtocolEncoder.java
index 3b2145e74..cd068b251 100644
--- a/src/main/java/org/traccar/protocol/GalileoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/GalileoProtocolEncoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 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.
@@ -20,11 +20,16 @@ import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
public class GalileoProtocolEncoder extends BaseProtocolEncoder {
+ public GalileoProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeText(String uniqueId, String text) {
ByteBuf buf = Unpooled.buffer(256);
diff --git a/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java
index 31500bae6..043839be9 100644
--- a/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 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.
@@ -120,8 +120,10 @@ public class GatorProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_STATUS, buf.readUnsignedByte());
position.set("key", buf.readUnsignedByte());
- position.set("oil", buf.readUnsignedShort() / 10.0);
- position.set(Position.KEY_POWER, buf.readUnsignedByte() + buf.readUnsignedByte() * 0.01);
+
+ position.set(Position.PREFIX_ADC + 1, buf.readUnsignedByte() + buf.readUnsignedByte() * 0.01);
+ position.set(Position.PREFIX_ADC + 2, buf.readUnsignedByte() + buf.readUnsignedByte() * 0.01);
+
position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
return position;
diff --git a/src/main/java/org/traccar/protocol/Gl200Protocol.java b/src/main/java/org/traccar/protocol/Gl200Protocol.java
index c5343dae0..e2d0c6d2a 100644
--- a/src/main/java/org/traccar/protocol/Gl200Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gl200Protocol.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,7 +36,7 @@ public class Gl200Protocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new Gl200FrameDecoder());
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new Gl200ProtocolEncoder());
+ pipeline.addLast(new Gl200ProtocolEncoder(Gl200Protocol.this));
pipeline.addLast(new Gl200ProtocolDecoder(Gl200Protocol.this));
}
});
@@ -44,7 +44,7 @@ public class Gl200Protocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new Gl200ProtocolEncoder());
+ pipeline.addLast(new Gl200ProtocolEncoder(Gl200Protocol.this));
pipeline.addLast(new Gl200ProtocolDecoder(Gl200Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/Gl200ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Gl200ProtocolEncoder.java
index 285106c67..32307446b 100644
--- a/src/main/java/org/traccar/protocol/Gl200ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200ProtocolEncoder.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.
@@ -17,9 +17,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class Gl200ProtocolEncoder extends StringProtocolEncoder {
+ public Gl200ProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java
index 5a0ff4197..283dbeb37 100644
--- a/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.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.
@@ -119,9 +119,9 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
.compile();
private static final Pattern PATTERN_LOCATION = new PatternBuilder()
- .number("(d{1,2})?,") // hdop
+ .number("(d{1,2}.?d?)?,") // hdop
.number("(d{1,3}.d)?,") // speed
- .number("(d{1,3})?,") // course
+ .number("(d{1,3}.?d?)?,") // course
.number("(-?d{1,5}.d)?,") // altitude
.number("(-?d{1,3}.d{6})?,") // longitude
.number("(-?d{1,2}.d{6})?,") // latitude
@@ -184,7 +184,7 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
.number("(d+)?,") // power
.number("d{1,2},").optional() // report type
.number("d{1,2},").optional() // count
- .number(",").optional() // reserved
+ .number("d*,").optional() // reserved
.number("(d+),").optional() // battery
.expression("((?:")
.expression(PATTERN_LOCATION.pattern())
@@ -202,6 +202,9 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
.or()
.number("(d{1,7}.d)?,").optional() // odometer
.number("(d{1,3})?,") // battery
+ .or()
+ .number("(-?d),") // rssi
+ .number("(d{1,3}),") // battery
.groupEnd()
.any()
.number("(dddd)(dd)(dd)") // date (yyyymmdd)
@@ -514,7 +517,7 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
}
private void decodeLocation(Position position, Parser parser) {
- Integer hdop = parser.nextInt();
+ Double hdop = parser.nextDouble();
position.setValid(hdop == null || hdop > 0);
position.set(Position.KEY_HDOP, hdop);
@@ -848,6 +851,8 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000);
}
position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
+ position.set(Position.KEY_RSSI, parser.nextInt());
+ position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
decodeDeviceTime(position, parser);
if (ignoreFixTime) {
@@ -1224,8 +1229,11 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
case "CAN":
result = decodeCan(channel, remoteAddress, sentence);
break;
+ case "CTN":
case "FRI":
case "GEO":
+ case "RTL":
+ case "DOG":
case "STR":
result = decodeFri(channel, remoteAddress, sentence);
break;
diff --git a/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java b/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java
index 95ef18f20..76278070e 100644
--- a/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.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.
@@ -30,7 +30,8 @@ import org.traccar.model.Network;
import org.traccar.model.Position;
import java.net.SocketAddress;
-import java.util.Date;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
@@ -45,8 +46,6 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder {
.text("*GS") // header
.number("d+,") // protocol version
.number("(d+),") // imei
- .number("(dd)(dd)(dd)") // time (hhmmss)
- .number("(dd)(dd)(dd),") // date (ddmmyy)
.expression("([^#]*)#?") // data
.compile();
@@ -68,6 +67,7 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder {
.compile();
private void decodeFragment(Position position, String fragment) {
+
int dataIndex = fragment.indexOf(':');
int index = 0;
String[] values;
@@ -76,6 +76,7 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder {
} else {
values = fragment.substring(dataIndex + 1).split(";");
}
+
switch (fragment.substring(0, dataIndex)) {
case "GPS":
position.setValid(values[index++].equals("A"));
@@ -162,8 +163,15 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder {
position.set("tagData", values[index++]);
break;
case "IWD":
- if (index < values.length && values[index + 1].equals("0")) {
- position.set(Position.KEY_DRIVER_UNIQUE_ID, values[index + 2]);
+ while (index < values.length) {
+ int sensorIndex = Integer.parseInt(values[index++]);
+ int dataType = Integer.parseInt(values[index++]);
+ if (dataType == 0) {
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, values[index++]);
+ } else if (dataType == 1) {
+ index += 1; // temperature sensor serial number
+ position.set(Position.PREFIX_TEMP + sensorIndex, Double.parseDouble(values[index++]));
+ }
}
break;
default:
@@ -171,42 +179,27 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder {
}
}
- private Object decodeData(DeviceSession deviceSession, Date time, String data) {
-
- List<Position> positions = new LinkedList<>();
- Position position = null;
- int index = 0;
- String[] fragments = data.split(",");
+ private Position decodePosition(DeviceSession deviceSession, String sentence) throws ParseException {
- while (index < fragments.length) {
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
- if (fragments[index].isEmpty() || Character.isDigit(fragments[index].charAt(0))) {
-
- if (position != null) {
- positions.add(position);
- }
+ int index = 0;
+ String[] fragments = sentence.split(",");
- position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
- position.setTime(time);
+ position.setTime(new SimpleDateFormat("HHmmssddMMyy").parse(fragments[index++]));
- if (!fragments[index++].isEmpty()) {
- position.set(Position.KEY_EVENT, Integer.parseInt(fragments[index - 1]));
+ for (; index < fragments.length; index += 1) {
+ if (!fragments[index].isEmpty()) {
+ if (fragments[index].matches("\\p{XDigit}+")) {
+ position.set(Position.KEY_EVENT, Integer.parseInt(fragments[index], 16));
+ } else {
+ decodeFragment(position, fragments[index]);
}
-
- } else {
-
- decodeFragment(position, fragments[index++]);
-
}
-
}
- if (position != null) {
- positions.add(position);
- }
-
- return positions;
+ return position;
}
@Override
@@ -256,12 +249,11 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder {
} else {
- Date time = new Date();
- if (parser.hasNext(6)) {
- time = parser.nextDateTime(Parser.DateTimeFormat.HMS_DMY);
+ List<Position> positions = new LinkedList<>();
+ for (String item : parser.next().split("\\$")) {
+ positions.add(decodePosition(deviceSession, item));
}
-
- return decodeData(deviceSession, time, parser.next());
+ return positions;
}
}
diff --git a/src/main/java/org/traccar/protocol/GotopProtocolDecoder.java b/src/main/java/org/traccar/protocol/GotopProtocolDecoder.java
index 2ef975fe5..a867451aa 100644
--- a/src/main/java/org/traccar/protocol/GotopProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GotopProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 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.
@@ -40,7 +40,7 @@ public class GotopProtocolDecoder extends BaseProtocolDecoder {
.number("DATE:(dd)(dd)(dd),") // date (yyddmm)
.number("TIME:(dd)(dd)(dd),") // time (hhmmss)
.number("LAT:(d+.d+)([NS]),") // latitude
- .number("LOT:(d+.d+)([EW]),") // longitude
+ .number("LO[NT]:(d+.d+)([EW]),") // longitude
.text("Speed:").number("(d+.d+),") // speed
.expression("([^,]+),") // status
.number("(d+)?") // course
diff --git a/src/main/java/org/traccar/protocol/Gps103Protocol.java b/src/main/java/org/traccar/protocol/Gps103Protocol.java
index 6272a3fd1..5356387ce 100644
--- a/src/main/java/org/traccar/protocol/Gps103Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gps103Protocol.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.
@@ -42,7 +42,7 @@ public class Gps103Protocol extends BaseProtocol {
pipeline.addLast(new CharacterDelimiterFrameDecoder(2048, false, "\r\n", "\n", ";", "*"));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new Gps103ProtocolEncoder());
+ pipeline.addLast(new Gps103ProtocolEncoder(Gps103Protocol.this));
pipeline.addLast(new Gps103ProtocolDecoder(Gps103Protocol.this));
}
});
@@ -51,7 +51,7 @@ public class Gps103Protocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new Gps103ProtocolEncoder());
+ pipeline.addLast(new Gps103ProtocolEncoder(Gps103Protocol.this));
pipeline.addLast(new Gps103ProtocolDecoder(Gps103Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/Gps103ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Gps103ProtocolEncoder.java
index 47ef2f333..7128823ed 100644
--- a/src/main/java/org/traccar/protocol/Gps103ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Gps103ProtocolEncoder.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.
@@ -17,9 +17,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class Gps103ProtocolEncoder extends StringProtocolEncoder implements StringProtocolEncoder.ValueFormatter {
+ public Gps103ProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
public String formatValue(String key, Object value) {
diff --git a/src/main/java/org/traccar/protocol/GranitProtocol.java b/src/main/java/org/traccar/protocol/GranitProtocol.java
index 6785f2a2e..244c3977b 100644
--- a/src/main/java/org/traccar/protocol/GranitProtocol.java
+++ b/src/main/java/org/traccar/protocol/GranitProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org)
* Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,7 +28,7 @@ public class GranitProtocol extends BaseProtocol {
Command.TYPE_IDENTIFICATION,
Command.TYPE_REBOOT_DEVICE,
Command.TYPE_POSITION_SINGLE);
- setTextCommandEncoder(new GranitProtocolSmsEncoder());
+ setTextCommandEncoder(new GranitProtocolSmsEncoder(this));
setSupportedTextCommands(
Command.TYPE_REBOOT_DEVICE,
Command.TYPE_POSITION_PERIODIC);
@@ -36,7 +36,7 @@ public class GranitProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new GranitFrameDecoder());
- pipeline.addLast(new GranitProtocolEncoder());
+ pipeline.addLast(new GranitProtocolEncoder(GranitProtocol.this));
pipeline.addLast(new GranitProtocolDecoder(GranitProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/GranitProtocolEncoder.java b/src/main/java/org/traccar/protocol/GranitProtocolEncoder.java
index 6345ff971..66c2a4973 100644
--- a/src/main/java/org/traccar/protocol/GranitProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/GranitProtocolEncoder.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.
@@ -21,9 +21,14 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class GranitProtocolEncoder extends BaseProtocolEncoder {
+ public GranitProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeCommand(String commandString) {
ByteBuf buffer = Unpooled.buffer();
buffer.writeBytes(commandString.getBytes(StandardCharsets.US_ASCII));
diff --git a/src/main/java/org/traccar/protocol/GranitProtocolSmsEncoder.java b/src/main/java/org/traccar/protocol/GranitProtocolSmsEncoder.java
index 7d5518c17..7dd4b2d77 100644
--- a/src/main/java/org/traccar/protocol/GranitProtocolSmsEncoder.java
+++ b/src/main/java/org/traccar/protocol/GranitProtocolSmsEncoder.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");
@@ -18,9 +18,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class GranitProtocolSmsEncoder extends StringProtocolEncoder {
+ public GranitProtocolSmsEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected String encodeCommand(Command command) {
switch (command.getType()) {
diff --git a/src/main/java/org/traccar/protocol/Gt06Protocol.java b/src/main/java/org/traccar/protocol/Gt06Protocol.java
index 6e5435cd4..9ec8de098 100644
--- a/src/main/java/org/traccar/protocol/Gt06Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gt06Protocol.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.
@@ -31,7 +31,7 @@ public class Gt06Protocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new Gt06FrameDecoder());
- pipeline.addLast(new Gt06ProtocolEncoder());
+ pipeline.addLast(new Gt06ProtocolEncoder(Gt06Protocol.this));
pipeline.addLast(new Gt06ProtocolDecoder(Gt06Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
index 4665290c3..e1ff0b6b6 100644
--- a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
@@ -81,11 +81,13 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_X1_PHOTO_INFO = 0x35;
public static final int MSG_X1_PHOTO_DATA = 0x36;
public static final int MSG_WIFI_2 = 0x69;
+ public static final int MSG_GPS_MODULAR = 0x70;
public static final int MSG_COMMAND_0 = 0x80;
public static final int MSG_COMMAND_1 = 0x81;
public static final int MSG_COMMAND_2 = 0x82;
public static final int MSG_TIME_REQUEST = 0x8A;
public static final int MSG_INFO = 0x94;
+ public static final int MSG_RFID = 0x9B;
public static final int MSG_STRING_INFO = 0x21;
public static final int MSG_GPS_2 = 0xA0;
public static final int MSG_LBS_2 = 0xA1;
@@ -101,6 +103,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_MULTIMEDIA = 0x21;
public static final int MSG_BMS_2 = 0x40;
public static final int MSG_MULTIMEDIA_2 = 0x41;
+ public static final int MSG_ALARM = 0x95;
private static boolean isSupported(int type) {
return hasGps(type) || hasLbs(type) || hasStatus(type);
@@ -748,6 +751,39 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ARCHIVE, buf.readUnsignedByte() > 0);
}
+ } else if (type == MSG_ALARM) {
+
+ DateBuilder dateBuilder = new DateBuilder(deviceSession.getTimeZone())
+ .setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
+ .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte());
+
+ getLastLocation(position, dateBuilder.getDate());
+
+ short alarmType = buf.readUnsignedByte();
+
+ switch (alarmType) {
+ case 0x80:
+ position.set(Position.KEY_ALARM, Position.ALARM_VIBRATION);
+ break;
+ case 0x87:
+ position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED);
+ break;
+ case 0x90:
+ position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION);
+ break;
+ case 0x91:
+ position.set(Position.KEY_ALARM, Position.ALARM_BRAKING);
+ break;
+ case 0x92:
+ position.set(Position.KEY_ALARM, Position.ALARM_CORNERING);
+ break;
+ default:
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ break;
+ }
+
+ position.set("alarmValue", buf.readShort());
+
} else {
if (dataLength > 0) {
@@ -814,7 +850,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
getLastLocation(position, null);
if (subType == 0x00) {
- position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
+ position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort() * 0.01);
return position;
} else if (subType == 0x05) {
int flags = buf.readUnsignedByte();
@@ -824,7 +860,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
} else if (subType == 0x0a) {
buf.skipBytes(8); // imei
buf.skipBytes(8); // imsi
- position.set("iccid", ByteBufUtil.hexDump(buf.readSlice(8)));
+ position.set(Position.KEY_ICCID, ByteBufUtil.hexDump(buf.readSlice(8)));
return position;
} else if (subType == 0x0d) {
if (buf.getByte(buf.readerIndex()) != '!') {
@@ -942,6 +978,22 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
return position;
+ } else if (type == MSG_RFID) {
+
+ getLastLocation(position, null);
+
+ buf.readUnsignedByte(); // external device type code
+ buf.readUnsignedByte(); // card type
+ position.set(
+ Position.KEY_DRIVER_UNIQUE_ID,
+ buf.readCharSequence(buf.readableBytes() - 9, StandardCharsets.US_ASCII).toString());
+
+ return position;
+
+ } else if (type == MSG_GPS_MODULAR) {
+
+ return decodeExtendedModular(channel, buf, deviceSession, type);
+
} else {
return decodeExtendedOther(channel, buf, deviceSession, type);
@@ -951,6 +1003,84 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
return null;
}
+ private Object decodeExtendedModular(Channel channel, ByteBuf buf, DeviceSession deviceSession, int type) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ while (buf.readableBytes() > 6) {
+ int moduleType = buf.readUnsignedShort();
+ int moduleLength = buf.readUnsignedShort();
+ switch (moduleType) {
+ case 0x18:
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.01);
+ break;
+ case 0x28:
+ position.set(Position.KEY_HDOP, buf.readUnsignedByte() * 0.1);
+ break;
+ case 0x29:
+ position.set(Position.KEY_INDEX, buf.readUnsignedInt());
+ break;
+ case 0x2a:
+ int input = buf.readUnsignedByte();
+ position.set(Position.KEY_DOOR, BitUtil.to(input, 4) > 0);
+ position.set("tamper", BitUtil.from(input, 4) > 0);
+ break;
+ case 0x2b:
+ int event = buf.readUnsignedByte();
+ switch (event) {
+ case 0x11:
+ position.set(Position.KEY_ALARM, Position.ALARM_LOW_BATTERY);
+ break;
+ case 0x12:
+ position.set(Position.KEY_ALARM, Position.ALARM_LOW_POWER);
+ break;
+ case 0x13:
+ position.set(Position.KEY_ALARM, Position.ALARM_POWER_CUT);
+ break;
+ case 0x14:
+ position.set(Position.KEY_ALARM, Position.ALARM_REMOVING);
+ break;
+ default:
+ break;
+ }
+ position.set(Position.KEY_EVENT, event);
+ break;
+ case 0x2e:
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE());
+ break;
+ case 0x33:
+ position.setTime(new Date(buf.readUnsignedInt() * 1000));
+ position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
+ position.setAltitude(buf.readShort());
+
+ double latitude = buf.readUnsignedInt() / 60.0 / 30000.0;
+ double longitude = buf.readUnsignedInt() / 60.0 / 30000.0;
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+
+ int flags = buf.readUnsignedShort();
+ position.setCourse(BitUtil.to(flags, 10));
+ position.setValid(BitUtil.check(flags, 12));
+
+ if (!BitUtil.check(flags, 10)) {
+ latitude = -latitude;
+ }
+ if (BitUtil.check(flags, 11)) {
+ longitude = -longitude;
+ }
+
+ position.setLatitude(latitude);
+ position.setLongitude(longitude);
+ break;
+ default:
+ buf.skipBytes(moduleLength);
+ break;
+ }
+ }
+
+ return position;
+ }
+
private Object decodeExtendedOther(Channel channel, ByteBuf buf, DeviceSession deviceSession, int type) {
Position position = null;
diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java
index 05560229f..9115ba10f 100644
--- a/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.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.
@@ -21,14 +21,20 @@ import org.traccar.BaseProtocolEncoder;
import org.traccar.Context;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
public class Gt06ProtocolEncoder extends BaseProtocolEncoder {
+ public Gt06ProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeContent(long deviceId, String content) {
- boolean language = Context.getIdentityManager().lookupAttributeBoolean(deviceId, "gt06.language", false, true);
+ boolean language = Context.getIdentityManager()
+ .lookupAttributeBoolean(deviceId, getProtocolName() + ".language", false, false, true);
ByteBuf buf = Unpooled.buffer();
@@ -61,13 +67,18 @@ public class Gt06ProtocolEncoder extends BaseProtocolEncoder {
protected Object encodeCommand(Command command) {
boolean alternative = Context.getIdentityManager().lookupAttributeBoolean(
- command.getDeviceId(), "gt06.alternative", false, true);
+ command.getDeviceId(), getProtocolName() + ".alternative", false, false, true);
+
+ String password = Context.getIdentityManager()
+ .getDevicePassword(command.getDeviceId(), getProtocolName(), "123456");
switch (command.getType()) {
case Command.TYPE_ENGINE_STOP:
- return encodeContent(command.getDeviceId(), alternative ? "DYD,123456#" : "Relay,1#");
+ return encodeContent(command.getDeviceId(),
+ alternative ? "DYD," + password + "#" : "Relay,1#");
case Command.TYPE_ENGINE_RESUME:
- return encodeContent(command.getDeviceId(), alternative ? "HFYD,123456#" : "Relay,0#");
+ return encodeContent(command.getDeviceId(),
+ alternative ? "HFYD," + password + "#" : "Relay,0#");
case Command.TYPE_CUSTOM:
return encodeContent(command.getDeviceId(), command.getString(Command.KEY_DATA));
default:
diff --git a/src/main/java/org/traccar/protocol/H02Protocol.java b/src/main/java/org/traccar/protocol/H02Protocol.java
index 251beac5e..b897d83ad 100644
--- a/src/main/java/org/traccar/protocol/H02Protocol.java
+++ b/src/main/java/org/traccar/protocol/H02Protocol.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.
@@ -38,7 +38,7 @@ public class H02Protocol extends BaseProtocol {
int messageLength = Context.getConfig().getInteger(getName() + ".messageLength");
pipeline.addLast(new H02FrameDecoder(messageLength));
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new H02ProtocolEncoder());
+ pipeline.addLast(new H02ProtocolEncoder(H02Protocol.this));
pipeline.addLast(new H02ProtocolDecoder(H02Protocol.this));
}
});
@@ -46,7 +46,7 @@ public class H02Protocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new H02ProtocolEncoder());
+ pipeline.addLast(new H02ProtocolEncoder(H02Protocol.this));
pipeline.addLast(new H02ProtocolDecoder(H02Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/H02ProtocolDecoder.java b/src/main/java/org/traccar/protocol/H02ProtocolDecoder.java
index 22bbe4441..137689a67 100644
--- a/src/main/java/org/traccar/protocol/H02ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/H02ProtocolDecoder.java
@@ -554,9 +554,18 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder {
String sentence = buf.toString(StandardCharsets.US_ASCII).trim();
int typeStart = sentence.indexOf(',', sentence.indexOf(',') + 1) + 1;
int typeEnd = sentence.indexOf(',', typeStart);
+ if (typeEnd < 0) {
+ typeEnd = sentence.indexOf('#', typeStart);
+ }
if (typeEnd > 0) {
String type = sentence.substring(typeStart, typeEnd);
switch (type) {
+ case "V0":
+ case "HTBT":
+ if (channel != null) {
+ channel.writeAndFlush(new NetworkMessage(sentence, remoteAddress));
+ }
+ return null;
case "NBR":
return decodeLbs(sentence, channel, remoteAddress);
case "LINK":
diff --git a/src/main/java/org/traccar/protocol/H02ProtocolEncoder.java b/src/main/java/org/traccar/protocol/H02ProtocolEncoder.java
index 614a07dd1..7a765332c 100644
--- a/src/main/java/org/traccar/protocol/H02ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/H02ProtocolEncoder.java
@@ -1,6 +1,6 @@
/*
* Copyright 2016 Gabor Somogyi (gabor.g.somogyi@gmail.com)
- * 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.
@@ -19,6 +19,7 @@ package org.traccar.protocol;
import org.traccar.Context;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.util.Date;
@@ -26,6 +27,10 @@ public class H02ProtocolEncoder extends StringProtocolEncoder {
private static final String MARKER = "HQ";
+ public H02ProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private Object formatCommand(Date time, String uniqueId, String type, String... params) {
StringBuilder result = new StringBuilder(
@@ -55,7 +60,7 @@ public class H02ProtocolEncoder extends StringProtocolEncoder {
case Command.TYPE_POSITION_PERIODIC:
String frequency = command.getAttributes().get(Command.KEY_FREQUENCY).toString();
if (Context.getIdentityManager().lookupAttributeBoolean(
- command.getDeviceId(), "h02.alternative", false, true)) {
+ command.getDeviceId(), getProtocolName() + ".alternative", false, false, true)) {
return formatCommand(time, uniqueId, "D1", frequency);
} else {
return formatCommand(time, uniqueId, "S71", "22", frequency);
diff --git a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
index 8a937a194..9449e2d5c 100644
--- a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
@@ -83,7 +83,7 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
int subtype = buf.readUnsignedShort();
int length = buf.readUnsignedShort() - 4;
if (subtype == 0x0003) {
- String imei = buf.readSlice(length).toString(StandardCharsets.US_ASCII);
+ String imei = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString();
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei);
if (deviceSession != null && channel != null) {
ByteBuf content = Unpooled.buffer();
@@ -117,7 +117,7 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_IGNITION, BitUtil.check(status, 14));
position.set(Position.KEY_EVENT, buf.readUnsignedShort());
- String time = buf.readSlice(12).toString(StandardCharsets.US_ASCII);
+ String time = buf.readCharSequence(12, StandardCharsets.US_ASCII).toString();
DateBuilder dateBuilder = new DateBuilder()
.setYear(Integer.parseInt(time.substring(0, 2)))
@@ -138,9 +138,33 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ODOMETER, buf.readUnsignedShort() * 1000);
while (buf.readableBytes() > 4) {
- buf.readUnsignedShort(); // subtype
+ int subtype = buf.readUnsignedShort();
int length = buf.readUnsignedShort() - 4;
- buf.skipBytes(length);
+ switch (subtype) {
+ case 0x0001:
+ position.set(Position.KEY_COOLANT_TEMP, buf.readUnsignedByte() - 40);
+ position.set(Position.KEY_RPM, buf.readUnsignedShort());
+ position.set("averageSpeed", buf.readUnsignedByte());
+ buf.readUnsignedShort(); // interval fuel consumption
+ position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShort() * 0.01);
+ position.set(Position.KEY_ODOMETER_TRIP, buf.readUnsignedShort());
+ position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte() * 0.4);
+ buf.readUnsignedInt(); // trip id
+ break;
+ case 0x0005:
+ position.set(Position.KEY_RSSI, buf.readUnsignedByte());
+ position.set(Position.KEY_HDOP, buf.readUnsignedByte());
+ buf.readUnsignedInt(); // run time
+ break;
+ case 0x0009:
+ position.set(
+ Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString());
+ break;
+ default:
+ buf.skipBytes(length);
+ break;
+ }
}
sendResponse(channel, MSG_POSITION_RSP, index, null);
diff --git a/src/main/java/org/traccar/protocol/HuabaoProtocol.java b/src/main/java/org/traccar/protocol/HuabaoProtocol.java
index 44c9f7ac7..791672b85 100644
--- a/src/main/java/org/traccar/protocol/HuabaoProtocol.java
+++ b/src/main/java/org/traccar/protocol/HuabaoProtocol.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.
@@ -30,7 +30,7 @@ public class HuabaoProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new HuabaoFrameDecoder());
- pipeline.addLast(new HuabaoProtocolEncoder());
+ pipeline.addLast(new HuabaoProtocolEncoder(HuabaoProtocol.this));
pipeline.addLast(new HuabaoProtocolDecoder(HuabaoProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java
index 6e2e1377b..fceefa73a 100644
--- a/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java
@@ -58,7 +58,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
buf.writeShort(type);
buf.writeShort(data.readableBytes());
buf.writeBytes(id);
- buf.writeShort(1); // index
+ buf.writeShort(0); // index
buf.writeBytes(data);
data.release();
buf.writeByte(Checksum.xor(buf.nioBuffer(1, buf.readableBytes() - 1)));
@@ -131,7 +131,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
ByteBuf response = Unpooled.buffer();
response.writeShort(index);
response.writeByte(RESULT_SUCCESS);
- response.writeBytes("authentication".getBytes(StandardCharsets.US_ASCII));
+ response.writeBytes(ByteBufUtil.hexDump(id).getBytes(StandardCharsets.US_ASCII));
channel.writeAndFlush(new NetworkMessage(
formatMessage(MSG_TERMINAL_REGISTER_RESPONSE, id, response), remoteAddress));
}
@@ -197,20 +197,44 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
while (buf.readableBytes() > 2) {
int subtype = buf.readUnsignedByte();
int length = buf.readUnsignedByte();
+ int endIndex = buf.readerIndex() + length;
switch (subtype) {
case 0x01:
position.set(Position.KEY_ODOMETER, buf.readUnsignedInt() * 100);
break;
+ case 0x02:
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedShort() * 0.1);
+ break;
case 0x30:
position.set(Position.KEY_RSSI, buf.readUnsignedByte());
break;
case 0x31:
position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
break;
+ case 0x91:
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.1);
+ position.set(Position.KEY_RPM, buf.readUnsignedShort());
+ position.set(Position.KEY_OBD_SPEED, buf.readUnsignedByte());
+ position.set(Position.KEY_THROTTLE, buf.readUnsignedByte() * 100 / 255);
+ position.set(Position.KEY_ENGINE_LOAD, buf.readUnsignedByte() * 100 / 255);
+ position.set(Position.KEY_COOLANT_TEMP, buf.readUnsignedByte() - 40);
+ buf.readUnsignedShort();
+ position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShort() * 0.01);
+ buf.readUnsignedShort();
+ buf.readUnsignedInt();
+ buf.readUnsignedShort();
+ position.set(Position.KEY_FUEL_USED, buf.readUnsignedShort() * 0.01);
+ break;
+ case 0x94:
+ if (length > 0) {
+ position.set(
+ Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString());
+ }
+ break;
default:
- buf.skipBytes(length);
break;
}
+ buf.readerIndex(endIndex);
}
return position;
@@ -233,3 +257,4 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
}
}
+
diff --git a/src/main/java/org/traccar/protocol/HuabaoProtocolEncoder.java b/src/main/java/org/traccar/protocol/HuabaoProtocolEncoder.java
index 7759790c4..40d07230d 100644
--- a/src/main/java/org/traccar/protocol/HuabaoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/HuabaoProtocolEncoder.java
@@ -21,17 +21,22 @@ import org.traccar.BaseProtocolEncoder;
import org.traccar.Context;
import org.traccar.helper.DataConverter;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HuabaoProtocolEncoder extends BaseProtocolEncoder {
+ public HuabaoProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
boolean alternative = Context.getIdentityManager().lookupAttributeBoolean(
- command.getDeviceId(), "huabao.alternative", false, true);
+ command.getDeviceId(), getProtocolName() + ".alternative", false, false, true);
ByteBuf id = Unpooled.wrappedBuffer(
DataConverter.parseHex(getUniqueId(command.getDeviceId())));
diff --git a/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java b/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java
index 8c1b9b480..d76d9c92e 100644
--- a/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java
@@ -44,7 +44,7 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder {
.expression("[^,]+,") // vendor
.expression("[^,]+,") // firmware version
.expression("(..),") // status
- .number("(d+),") // event
+ .number("(d+),").optional() // event
.expression("([LH]),") // history
.or()
.expression("([^,]+),") // type
@@ -56,7 +56,7 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder {
.expression("[^,]*,") // vehicle registration
.number("([01]),").optional() // valid
.groupEnd()
- .number("(dd),?(dd),?(dddd),") // date (ddmmyyyy)
+ .number("(dd),?(dd),?(d{2,4}),") // date (ddmmyyyy)
.number("(dd),?(dd),?(dd),") // time (hhmmss)
.expression("([01AV]),").optional() // valid
.number("(d+.d+),([NS]),") // latitude
@@ -69,16 +69,15 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder {
.number("(d+.?d*),") // altitude
.number("d+.?d*,") // pdop
.number("d+.?d*,") // hdop
- .expression("[^,]*,")
+ .expression("[^,]*,") // operator
.number("([01]),") // ignition
.number("([01]),") // charging
.number("(d+.?d*),") // power
.number("(d+.?d*),") // battery
.number("([01]),") // emergency
.expression("[CO]?,") // tamper
- .number("((?:x+,){5}") // main cell
- .number("(?:-?x+,){12})") // other cells
- .number("([01]{4}),") // inputs
+ .expression("(.*),") // cells
+ .number("([012]{4}),") // inputs
.number("([01]{2}),") // outputs
.groupBegin()
.number("d+,") // index
@@ -202,16 +201,22 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder {
int lac = Integer.parseInt(cells[3], 16);
int cid = Integer.parseInt(cells[4], 16);
Network network = new Network(CellTower.from(mcc, mnc, lac, cid, Integer.parseInt(cells[0])));
- for (int i = 0; i < 4; i++) {
- lac = Integer.parseInt(cells[5 + 3 * i + 1], 16);
- cid = Integer.parseInt(cells[5 + 3 * i + 2], 16);
- if (lac > 0 && cid > 0) {
- network.addCellTower(CellTower.from(mcc, mnc, lac, cid));
+ if (!cells[5].startsWith("(")) {
+ for (int i = 0; i < 4; i++) {
+ lac = Integer.parseInt(cells[5 + 3 * i + 1], 16);
+ cid = Integer.parseInt(cells[5 + 3 * i + 2], 16);
+ if (lac > 0 && cid > 0) {
+ network.addCellTower(CellTower.from(mcc, mnc, lac, cid));
+ }
}
}
position.setNetwork(network);
- position.set(Position.KEY_INPUT, parser.nextBinInt());
+ String input = parser.next();
+ if (input.charAt(input.length() - 1) == '2') {
+ input = input.substring(0, input.length() - 1) + '0';
+ }
+ position.set(Position.KEY_INPUT, Integer.parseInt(input, 2));
position.set(Position.KEY_OUTPUT, parser.nextBinInt());
}
diff --git a/src/main/java/org/traccar/protocol/ItsProtocolEncoder.java b/src/main/java/org/traccar/protocol/ItsProtocolEncoder.java
index ebbbd87cd..f82b8e3ac 100644
--- a/src/main/java/org/traccar/protocol/ItsProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/ItsProtocolEncoder.java
@@ -17,9 +17,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class ItsProtocolEncoder extends StringProtocolEncoder {
+ public ItsProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java b/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java
index b5d060ecc..bfefb94a7 100644
--- a/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java
@@ -35,7 +35,7 @@ public class Jt600FrameDecoder extends BaseFrameDecoder {
char type = (char) buf.getByte(buf.readerIndex());
if (type == '$') {
- boolean longFormat = buf.getUnsignedByte(buf.readerIndex() + 1) == 0x75;
+ boolean longFormat = Jt600ProtocolDecoder.isLongFormat(buf, buf.readerIndex() + 1);
int length = buf.getUnsignedShort(buf.readerIndex() + (longFormat ? 8 : 7)) + 10;
if (length <= buf.readableBytes()) {
return buf.readRetainedSlice(length);
diff --git a/src/main/java/org/traccar/protocol/Jt600Protocol.java b/src/main/java/org/traccar/protocol/Jt600Protocol.java
index 97c5fa6ce..37c82f741 100644
--- a/src/main/java/org/traccar/protocol/Jt600Protocol.java
+++ b/src/main/java/org/traccar/protocol/Jt600Protocol.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.
@@ -34,7 +34,7 @@ public class Jt600Protocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new Jt600FrameDecoder());
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new Jt600ProtocolEncoder());
+ pipeline.addLast(new Jt600ProtocolEncoder(Jt600Protocol.this));
pipeline.addLast(new Jt600ProtocolDecoder(Jt600Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java
index 1351706e2..f456cd1ef 100644
--- a/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.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.
@@ -86,13 +86,17 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder {
}
+ static boolean isLongFormat(ByteBuf buf, int flagIndex) {
+ return buf.getUnsignedByte(flagIndex) >> 4 == 0x7;
+ }
+
private List<Position> decodeBinary(ByteBuf buf, Channel channel, SocketAddress remoteAddress) {
List<Position> positions = new LinkedList<>();
buf.readByte(); // header
- boolean longFormat = buf.getUnsignedByte(buf.readerIndex()) == 0x75;
+ boolean longFormat = isLongFormat(buf, buf.readerIndex());
String id = String.valueOf(Long.parseLong(ByteBufUtil.hexDump(buf.readSlice(5))));
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id);
@@ -170,6 +174,7 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder {
if (protocolVersion == 0x17) {
buf.readUnsignedByte(); // geofence id
buf.skipBytes(3); // reserved
+ buf.skipBytes(buf.readableBytes() - 1);
}
} else if (version == 1) {
diff --git a/src/main/java/org/traccar/protocol/Jt600ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Jt600ProtocolEncoder.java
index fe5c63c32..199467a38 100644
--- a/src/main/java/org/traccar/protocol/Jt600ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Jt600ProtocolEncoder.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.
@@ -19,9 +19,14 @@ import java.util.TimeZone;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class Jt600ProtocolEncoder extends StringProtocolEncoder {
+ public Jt600ProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/KhdProtocol.java b/src/main/java/org/traccar/protocol/KhdProtocol.java
index cec7158ed..f77f4c311 100644
--- a/src/main/java/org/traccar/protocol/KhdProtocol.java
+++ b/src/main/java/org/traccar/protocol/KhdProtocol.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.
@@ -31,7 +31,7 @@ public class KhdProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(512, 3, 2));
- pipeline.addLast(new KhdProtocolEncoder());
+ pipeline.addLast(new KhdProtocolEncoder(KhdProtocol.this));
pipeline.addLast(new KhdProtocolDecoder(KhdProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/KhdProtocolEncoder.java b/src/main/java/org/traccar/protocol/KhdProtocolEncoder.java
index c66129283..4a8df26c8 100644
--- a/src/main/java/org/traccar/protocol/KhdProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/KhdProtocolEncoder.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.
@@ -20,12 +20,17 @@ import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class KhdProtocolEncoder extends BaseProtocolEncoder {
public static final int MSG_CUT_OIL = 0x39;
public static final int MSG_RESUME_OIL = 0x38;
+ public KhdProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeCommand(int command, String uniqueId) {
ByteBuf buf = Unpooled.buffer();
diff --git a/src/main/java/org/traccar/protocol/LaipacProtocol.java b/src/main/java/org/traccar/protocol/LaipacProtocol.java
index 923b08a16..1d561dbd2 100644
--- a/src/main/java/org/traccar/protocol/LaipacProtocol.java
+++ b/src/main/java/org/traccar/protocol/LaipacProtocol.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.
@@ -18,6 +18,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.model.Command;
import org.traccar.BaseProtocol;
import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
@@ -25,12 +26,19 @@ import org.traccar.TrackerServer;
public class LaipacProtocol extends BaseProtocol {
public LaipacProtocol() {
+
+ setSupportedDataCommands(
+ Command.TYPE_CUSTOM,
+ Command.TYPE_POSITION_SINGLE,
+ Command.TYPE_REBOOT_DEVICE);
+
addServer(new TrackerServer(false, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LineBasedFrameDecoder(1024));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new LaipacProtocolEncoder(LaipacProtocol.this));
pipeline.addLast(new LaipacProtocolDecoder(LaipacProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java b/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java
index 2f3cbb1b9..0c72568f3 100644
--- a/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 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,6 +17,7 @@ package org.traccar.protocol;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.Context;
import org.traccar.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -37,29 +38,44 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
super(protocol);
}
- private static final Pattern PATTERN = new PatternBuilder()
+ public static final String DEFAULT_DEVICE_PASSWORD = "00000000";
+
+ private static final Pattern PATTERN_EAVSYS = new PatternBuilder()
+ .text("$EAVSYS,")
+ .expression("([^,]+),") // identifier
+ .expression("([0-9]+),") // iccid
+ .expression("(\\+?[0-9]+)?,") // sim phone number
+ .expression("(?:[^,]*),") // owner name
+ .expression("([^,]*)?") // firmware version
+ .text("*")
+ .number("(xx)") // checksum
+ .compile();
+
+ private static final Pattern PATTERN_AVRMC = new PatternBuilder()
.text("$AVRMC,")
.expression("([^,]+),") // identifier
.number("(dd)(dd)(dd),") // time (hhmmss)
.expression("([AVRPavrp]),") // validity
.number("(dd)(dd.d+),") // latitude
- .expression("([NS]),")
+ .expression("([NS]),") // latitude hemisphere
.number("(ddd)(dd.d+),") // longitude
- .number("([EW]),")
+ .number("([EW]),") // longitude hemisphere
.number("(d+.d+),") // speed
.number("(d+.d+),") // course
.number("(dd)(dd)(dd),") // date (ddmmyy)
- .expression("([abZXTSMHFE86430]),") // event code
+ .expression("([0-9A-Za-z]),") // event code
.expression("([\\d.]+),") // battery voltage
.number("(d+),") // current mileage
.number("(d),") // gps status
.number("(d+),") // adc1
.number("(d+)") // adc2
- .number(",(xxxx)") // lac
- .number("(xxxx),") // cid
- .number("(ddd)") // mcc
- .number("(ddd)") // mnc
+ .number(",(xxxx|x)") // lac | lac+cid = 0
+ .number("(xxxx),") // cid | nothing
+ .number("(ddd|d)") // mcc | mcc+mnc = 0
+ .number("(ddd)") // mnc | nothing
.optional(4)
+ .expression(",([^*]*)") // anything remaining (be forward compatible)
+ .optional(1)
.text("*")
.number("(xx)") // checksum
.compile();
@@ -68,6 +84,8 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
switch (event) {
case "Z":
return Position.ALARM_LOW_BATTERY;
+ case "Y":
+ return Position.ALARM_TOW;
case "X":
return Position.ALARM_GEOFENCE_ENTER;
case "T":
@@ -81,6 +99,8 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
return Position.ALARM_GEOFENCE_EXIT;
case "6":
return Position.ALARM_OVERSPEED;
+ case "5":
+ return Position.ALARM_POWER_CUT;
case "3":
return Position.ALARM_SOS;
default:
@@ -88,23 +108,77 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
}
}
- @Override
- protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+ private String decodeEvent(String event, Position position) {
- String sentence = (String) msg;
+ if (event.length() == 1) {
+ char inputStatus = event.charAt(0);
+ if (inputStatus >= 'A' && inputStatus <= 'D') {
+ int inputStatusInt = inputStatus - 'A';
+ position.set(Position.PREFIX_IN + 1, inputStatusInt & 1);
+ position.set(Position.PREFIX_IN + 2, inputStatusInt & 2);
+ return null;
+ }
+ }
- if (sentence.startsWith("$ECHK") && channel != null) {
- channel.writeAndFlush(new NetworkMessage(sentence + "\r\n", remoteAddress)); // heartbeat
- return null;
+ return event;
+ }
+
+ private void sendEventResponse(
+ String event, String devicePassword, Channel channel, SocketAddress remoteAddress) {
+
+ String responseCode = null;
+
+ switch (event) {
+ case "3":
+ responseCode = "d";
+ break;
+ case "S":
+ case "T":
+ responseCode = "t";
+ break;
+ case "X":
+ case "4":
+ responseCode = "x";
+ break;
+ case "Y":
+ responseCode = "y";
+ break;
+ case "Z":
+ responseCode = "z";
+ break;
+ default:
+ break;
+ }
+
+ if (responseCode != null) {
+ String response = "$AVCFG," + devicePassword + "," + responseCode;
+ response += Checksum.nmea(response) + "\r\n";
+ channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
+ }
+
+ }
+
+ private void sendAcknowledge(
+ String status, String event, String checksum, Channel channel, SocketAddress remoteAddress) {
+
+ if (Character.isLowerCase(status.charAt(0))) {
+ String response = "$EAVACK," + event + "," + checksum;
+ response += Checksum.nmea(response) + "\r\n";
+ channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
}
- Parser parser = new Parser(PATTERN, sentence);
+ }
+
+ protected Object decodeEavsys(
+ String sentence, Channel channel, SocketAddress remoteAddress) {
+
+ Parser parser = new Parser(PATTERN_EAVSYS, sentence);
if (!parser.matches()) {
return null;
}
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ DeviceSession deviceSession =
+ getDeviceSession(channel, remoteAddress, parser.next());
if (deviceSession == null) {
return null;
}
@@ -112,6 +186,32 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
+ getLastLocation(position, null);
+
+ position.set(Position.KEY_ICCID, parser.next());
+ position.set(Position.KEY_PHONE, parser.next());
+ position.set(Position.KEY_VERSION_FW, parser.next());
+
+ return position;
+ }
+
+ protected Object decodeAvrmc(
+ String sentence, Channel channel, SocketAddress remoteAddress) {
+
+ Parser parser = new Parser(PATTERN_AVRMC, sentence);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ DeviceSession deviceSession =
+ getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+
+ position.setDeviceId(deviceSession.getDeviceId());
DateBuilder dateBuilder = new DateBuilder()
.setTime(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0));
@@ -130,9 +230,9 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
String event = parser.next();
position.set(Position.KEY_ALARM, decodeAlarm(event));
- position.set(Position.KEY_EVENT, event);
+ position.set(Position.KEY_EVENT, decodeEvent(event, position));
position.set(Position.KEY_BATTERY, Double.parseDouble(parser.next().replaceAll("\\.", "")) * 0.001);
- position.set(Position.KEY_ODOMETER, parser.nextDouble());
+ position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000);
position.set(Position.KEY_GPS, parser.nextInt());
position.set(Position.PREFIX_ADC + 1, parser.nextDouble() * 0.001);
position.set(Position.PREFIX_ADC + 2, parser.nextDouble() * 0.001);
@@ -145,23 +245,39 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
position.setNetwork(new Network(CellTower.from(mcc, mnc, lac, cid)));
}
+ parser.next(); // unused
+
String checksum = parser.next();
if (channel != null) {
- if (event.equals("3")) {
- channel.writeAndFlush(new NetworkMessage("$AVCFG,00000000,d*31\r\n", remoteAddress));
- } else if (event.equals("X") || event.equals("4")) {
- channel.writeAndFlush(new NetworkMessage("$AVCFG,00000000,x*2D\r\n", remoteAddress));
- } else if (event.equals("Z")) {
- channel.writeAndFlush(new NetworkMessage("$AVCFG,00000000,z*2F\r\n", remoteAddress));
- } else if (Character.isLowerCase(status.charAt(0))) {
- String response = "$EAVACK," + event + "," + checksum;
- response += Checksum.nmea(response) + "\r\n";
- channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
- }
+
+ sendAcknowledge(status, event, checksum, channel, remoteAddress);
+
+ String devicePassword = Context.getIdentityManager()
+ .getDevicePassword(deviceSession.getDeviceId(), getProtocolName(), DEFAULT_DEVICE_PASSWORD);
+ sendEventResponse(event, devicePassword, channel, remoteAddress);
}
return position;
}
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ String sentence = (String) msg;
+
+ if (sentence.startsWith("$ECHK")) {
+ if (channel != null) {
+ channel.writeAndFlush(new NetworkMessage(sentence + "\r\n", remoteAddress));
+ }
+ } else if (sentence.startsWith("$EAVSYS")) {
+ return decodeEavsys(sentence, channel, remoteAddress);
+ } else if (sentence.startsWith("$AVRMC")) {
+ return decodeAvrmc(sentence, channel, remoteAddress);
+ }
+
+ return null;
+ }
+
}
diff --git a/src/main/java/org/traccar/protocol/LaipacProtocolEncoder.java b/src/main/java/org/traccar/protocol/LaipacProtocolEncoder.java
new file mode 100644
index 000000000..343ac9431
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/LaipacProtocolEncoder.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.protocol;
+
+import org.traccar.StringProtocolEncoder;
+import org.traccar.model.Command;
+import org.traccar.helper.Checksum;
+import org.traccar.Protocol;
+
+public class LaipacProtocolEncoder extends StringProtocolEncoder {
+
+ public LaipacProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ @Override
+ protected String formatCommand(Command command, String format, String... keys) {
+ String sentence = super.formatCommand(command, "$" + format, keys);
+ sentence += Checksum.nmea(sentence) + "\r\n";
+ return sentence;
+ }
+
+ @Override
+ protected Object encodeCommand(Command command) {
+
+ initDevicePassword(command, LaipacProtocolDecoder.DEFAULT_DEVICE_PASSWORD);
+
+ switch (command.getType()) {
+ case Command.TYPE_CUSTOM:
+ return formatCommand(command, "{%s}",
+ Command.KEY_DATA);
+ case Command.TYPE_POSITION_SINGLE:
+ return formatCommand(command, "AVREQ,{%s},1",
+ Command.KEY_DEVICE_PASSWORD);
+ case Command.TYPE_REBOOT_DEVICE:
+ return formatCommand(command, "AVRESET,{%s},{%s}",
+ Command.KEY_UNIQUE_ID, Command.KEY_DEVICE_PASSWORD);
+ default:
+ return null;
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocol.java b/src/main/java/org/traccar/protocol/LeafSpyProtocol.java
new file mode 100644
index 000000000..05f63a2d7
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/LeafSpyProtocol.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 Anton Tananaev (anton@traccar.org)
+ * Copyright 2019 Jesse Hills (jesserockz@gmail.com)
+ *
+ * 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.protocol;
+
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+
+public class LeafSpyProtocol extends BaseProtocol {
+
+ public LeafSpyProtocol() {
+ addServer(new TrackerServer(false, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new HttpResponseEncoder());
+ pipeline.addLast(new HttpRequestDecoder());
+ pipeline.addLast(new HttpObjectAggregator(16384));
+ pipeline.addLast(new LeafSpyProtocolDecoder(LeafSpyProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java
new file mode 100644
index 000000000..5b352a961
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2019 Anton Tananaev (anton@traccar.org)
+ * Copyright 2019 Jesse Hills (jesserockz@gmail.com)
+ *
+ * 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.protocol;
+
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.HttpResponse;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+import io.netty.handler.codec.http.QueryStringDecoder;
+import org.traccar.BaseHttpProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.Protocol;
+import org.traccar.model.Position;
+import org.traccar.NetworkMessage;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+public class LeafSpyProtocolDecoder extends BaseHttpProtocolDecoder {
+
+ public LeafSpyProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ @Override
+ protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ FullHttpRequest request = (FullHttpRequest) msg;
+ QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
+ Map<String, List<String>> params = decoder.parameters();
+ if (params.isEmpty()) {
+ decoder = new QueryStringDecoder(request.content().toString(StandardCharsets.US_ASCII), false);
+ params = decoder.parameters();
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setValid(true);
+
+ for (Map.Entry<String, List<String>> entry : params.entrySet()) {
+ for (String value : entry.getValue()) {
+ switch (entry.getKey()) {
+ case "pass":
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, value);
+ if (deviceSession == null) {
+ sendResponse(channel, HttpResponseStatus.BAD_REQUEST);
+ return null;
+ }
+ position.setDeviceId(deviceSession.getDeviceId());
+ break;
+ case "Lat":
+ position.setLatitude(Double.parseDouble(value));
+ break;
+ case "Long":
+ position.setLongitude(Double.parseDouble(value));
+ break;
+ case "RPM":
+ position.set(Position.KEY_RPM, Integer.parseInt(value));
+ position.setSpeed(convertSpeed(Double.parseDouble(value) / 63, "kmh"));
+ break;
+ case "Elv":
+ position.setAltitude(Double.parseDouble(value));
+ break;
+ case "SOC":
+ position.set(Position.KEY_BATTERY_LEVEL, Double.parseDouble(value));
+ break;
+ case "user":
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, value);
+ break;
+ case "ChrgMode":
+ position.set(Position.KEY_CHARGE, Integer.parseInt(value) != 0);
+ break;
+ case "Odo":
+ position.set(Position.KEY_OBD_ODOMETER, Integer.parseInt(value) * 1000);
+ break;
+ default:
+ try {
+ position.set(entry.getKey(), Double.parseDouble(value));
+ } catch (NumberFormatException e) {
+ switch (value) {
+ case "true":
+ position.set(entry.getKey(), true);
+ break;
+ case "false":
+ position.set(entry.getKey(), false);
+ break;
+ default:
+ position.set(entry.getKey(), value);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ if (position.getFixTime() == null) {
+ position.setTime(new Date());
+ }
+
+ if (position.getLatitude() == 0 && position.getLongitude() == 0) {
+ getLastLocation(position, position.getDeviceTime());
+ }
+
+ if (position.getDeviceId() != 0) {
+ if (channel != null) {
+ HttpResponse response = new DefaultFullHttpResponse(
+ HttpVersion.HTTP_1_1,
+ HttpResponseStatus.OK,
+ Unpooled.copiedBuffer("\"status\":\"0\"", StandardCharsets.US_ASCII));
+ channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress()));
+ }
+ return position;
+ } else {
+ sendResponse(channel, HttpResponseStatus.BAD_REQUEST);
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/MeiligaoProtocol.java b/src/main/java/org/traccar/protocol/MeiligaoProtocol.java
index c307c7318..e8a66e49f 100644
--- a/src/main/java/org/traccar/protocol/MeiligaoProtocol.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoProtocol.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,14 +36,14 @@ public class MeiligaoProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new MeiligaoFrameDecoder());
- pipeline.addLast(new MeiligaoProtocolEncoder());
+ pipeline.addLast(new MeiligaoProtocolEncoder(MeiligaoProtocol.this));
pipeline.addLast(new MeiligaoProtocolDecoder(MeiligaoProtocol.this));
}
});
addServer(new TrackerServer(true, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new MeiligaoProtocolEncoder());
+ pipeline.addLast(new MeiligaoProtocolEncoder(MeiligaoProtocol.this));
pipeline.addLast(new MeiligaoProtocolDecoder(MeiligaoProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java b/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java
index 57cbbe0fc..36e94195c 100644
--- a/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.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.
@@ -21,12 +21,17 @@ import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.helper.DataConverter;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
import java.util.TimeZone;
public class MeiligaoProtocolEncoder extends BaseProtocolEncoder {
+ public MeiligaoProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeContent(long deviceId, int type, ByteBuf content) {
ByteBuf buf = Unpooled.buffer();
diff --git a/src/main/java/org/traccar/protocol/MeitrackProtocol.java b/src/main/java/org/traccar/protocol/MeitrackProtocol.java
index c887cd3a0..7439ea611 100644
--- a/src/main/java/org/traccar/protocol/MeitrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/MeitrackProtocol.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.
@@ -37,7 +37,7 @@ public class MeitrackProtocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new MeitrackFrameDecoder());
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new MeitrackProtocolEncoder());
+ pipeline.addLast(new MeitrackProtocolEncoder(MeitrackProtocol.this));
pipeline.addLast(new MeitrackProtocolDecoder(MeitrackProtocol.this));
}
});
@@ -45,7 +45,7 @@ public class MeitrackProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new MeitrackProtocolEncoder());
+ pipeline.addLast(new MeitrackProtocolEncoder(MeitrackProtocol.this));
pipeline.addLast(new MeitrackProtocolDecoder(MeitrackProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/MeitrackProtocolEncoder.java b/src/main/java/org/traccar/protocol/MeitrackProtocolEncoder.java
index abb6ec9d4..354e81434 100644
--- a/src/main/java/org/traccar/protocol/MeitrackProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/MeitrackProtocolEncoder.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.
@@ -19,11 +19,16 @@ import org.traccar.Context;
import org.traccar.StringProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.util.Map;
public class MeitrackProtocolEncoder extends StringProtocolEncoder {
+ public MeitrackProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private Object formatCommand(Command command, char dataId, String content) {
String uniqueId = getUniqueId(command.getDeviceId());
int length = 1 + uniqueId.length() + 1 + content.length() + 5;
@@ -38,7 +43,7 @@ public class MeitrackProtocolEncoder extends StringProtocolEncoder {
Map<String, Object> attributes = command.getAttributes();
boolean alternative = Context.getIdentityManager().lookupAttributeBoolean(
- command.getDeviceId(), "meitrack.alternative", false, true);
+ command.getDeviceId(), getProtocolName() + ".alternative", false, false, true);
switch (command.getType()) {
case Command.TYPE_POSITION_SINGLE:
diff --git a/src/main/java/org/traccar/protocol/MictrackProtocol.java b/src/main/java/org/traccar/protocol/MictrackProtocol.java
new file mode 100644
index 000000000..c8d64fd81
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/MictrackProtocol.java
@@ -0,0 +1,47 @@
+/*
+ * 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.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;
+
+public class MictrackProtocol extends BaseProtocol {
+
+ public MictrackProtocol() {
+ addServer(new TrackerServer(false, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new LineBasedFrameDecoder(1024));
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new MictrackProtocolDecoder(MictrackProtocol.this));
+ }
+ });
+ addServer(new TrackerServer(true, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new MictrackProtocolDecoder(MictrackProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java
new file mode 100644
index 000000000..a2fccb707
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java
@@ -0,0 +1,181 @@
+/*
+ * 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.protocol;
+
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.Protocol;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.CellTower;
+import org.traccar.model.Network;
+import org.traccar.model.Position;
+import org.traccar.model.WifiAccessPoint;
+
+import java.net.SocketAddress;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class MictrackProtocolDecoder extends BaseProtocolDecoder {
+
+ public MictrackProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private Date decodeTime(String data) throws ParseException {
+ DateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return dateFormat.parse(data);
+ }
+
+ private String decodeAlarm(int event) {
+ switch (event) {
+ case 5:
+ return Position.ALARM_SOS;
+ case 8:
+ return Position.ALARM_LOW_BATTERY;
+ case 9:
+ return Position.ALARM_GEOFENCE_ENTER;
+ case 10:
+ return Position.ALARM_GEOFENCE_EXIT;
+ case 12:
+ return Position.ALARM_POWER_OFF;
+ default:
+ return null;
+ }
+ }
+
+ private void decodeLocation(Position position, String data) throws ParseException {
+ int index = 0;
+ String[] values = data.split("\\+");
+
+ position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++]));
+
+ position.setValid(true);
+ position.setTime(decodeTime(values[index++]));
+ position.setLatitude(Double.parseDouble(values[index++]));
+ position.setLongitude(Double.parseDouble(values[index++]));
+ position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++])));
+ position.setCourse(Integer.parseInt(values[index++]));
+
+ int event = Integer.parseInt(values[index++]);
+ position.set(Position.KEY_ALARM, decodeAlarm(event));
+ position.set(Position.KEY_EVENT, event);
+ position.set(Position.KEY_BATTERY, Integer.parseInt(values[index++]) * 0.001);
+ }
+
+ private void decodeCell(Network network, String data) {
+ String[] values = data.split(",");
+ int length = values.length % 5 == 0 ? 5 : 4;
+ for (int i = 0; i < values.length / length; i++) {
+ int mnc = Integer.parseInt(values[i * length]);
+ int cid = Integer.parseInt(values[i * length + 1]);
+ int lac = Integer.parseInt(values[i * length + 2]);
+ int mcc = Integer.parseInt(values[i * length + 3]);
+ network.addCellTower(CellTower.from(mcc, mnc, lac, cid));
+ }
+ }
+
+ private void decodeWifi(Network network, String data) {
+ String[] values = data.split(",");
+ for (int i = 0; i < values.length / 2; i++) {
+ network.addWifiAccessPoint(WifiAccessPoint.from(values[i * 2], Integer.parseInt(values[i * 2 + 1])));
+ }
+ }
+
+ private void decodeNetwork(Position position, String data, boolean hasWifi, boolean hasCell) throws ParseException {
+ int index = 0;
+ String[] values = data.split("\\+");
+
+ getLastLocation(position, decodeTime(values[index++]));
+
+ Network network = new Network();
+
+ if (hasWifi) {
+ decodeWifi(network, values[index++]);
+ }
+
+ if (hasCell) {
+ decodeCell(network, values[index++]);
+ }
+
+ position.setNetwork(network);
+
+ int event = Integer.parseInt(values[index++]);
+ position.set(Position.KEY_ALARM, decodeAlarm(event));
+ position.set(Position.KEY_EVENT, event);
+ position.set(Position.KEY_BATTERY, Integer.parseInt(values[index++]) * 0.001);
+ }
+
+ private void decodeStatus(Position position, String data) throws ParseException {
+ int index = 0;
+ String[] values = data.split("\\+");
+
+ position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++]));
+
+ getLastLocation(position, decodeTime(values[index++]));
+
+ index += 4; // fix values
+
+ int event = Integer.parseInt(values[index++]);
+ position.set(Position.KEY_ALARM, decodeAlarm(event));
+ position.set(Position.KEY_EVENT, event);
+ position.set(Position.KEY_BATTERY, Integer.parseInt(values[index++]) * 0.001);
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ String[] fragments = ((String) msg).split(";");
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, fragments[2]);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ switch (fragments[3]) {
+ case "R0":
+ decodeLocation(position, fragments[4]);
+ break;
+ case "R1":
+ decodeNetwork(position, fragments[4], true, false);
+ break;
+ case "R2":
+ case "R3":
+ decodeNetwork(position, fragments[4], false, true);
+ break;
+ case "R12":
+ case "R13":
+ decodeNetwork(position, fragments[4], true, true);
+ break;
+ case "RH":
+ decodeStatus(position, fragments[4]);
+ break;
+ default:
+ return null;
+ }
+
+ return position;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/MiniFinderProtocol.java b/src/main/java/org/traccar/protocol/MiniFinderProtocol.java
index d4a154053..82534ecd8 100644
--- a/src/main/java/org/traccar/protocol/MiniFinderProtocol.java
+++ b/src/main/java/org/traccar/protocol/MiniFinderProtocol.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.
@@ -44,7 +44,7 @@ public class MiniFinderProtocol extends BaseProtocol {
pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, ';'));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new MiniFinderProtocolEncoder());
+ pipeline.addLast(new MiniFinderProtocolEncoder(MiniFinderProtocol.this));
pipeline.addLast(new MiniFinderProtocolDecoder(MiniFinderProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/MiniFinderProtocolEncoder.java b/src/main/java/org/traccar/protocol/MiniFinderProtocolEncoder.java
index 7a3d5b226..36fb9fc2f 100644
--- a/src/main/java/org/traccar/protocol/MiniFinderProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/MiniFinderProtocolEncoder.java
@@ -1,5 +1,5 @@
/*
- * 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.
@@ -19,9 +19,14 @@ import java.util.TimeZone;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class MiniFinderProtocolEncoder extends StringProtocolEncoder implements StringProtocolEncoder.ValueFormatter {
+ public MiniFinderProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
public String formatValue(String key, Object value) {
switch (key) {
diff --git a/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java
index 51b32ae3e..b6f257d2c 100644
--- a/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java
@@ -33,6 +33,7 @@ import org.traccar.model.WifiAccessPoint;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
+import java.util.Date;
public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
@@ -72,8 +73,13 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
ByteBuf buf = (ByteBuf) msg;
buf.readUnsignedByte(); // header
+ int flags = buf.readUnsignedByte();
+ buf.readUnsignedShortLE(); // length
+ buf.readUnsignedShortLE(); // checksum
+ int index = buf.readUnsignedShortLE();
+ int type = buf.readUnsignedByte();
- if (BitUtil.check(buf.readUnsignedByte(), 4) && channel != null) {
+ if (BitUtil.check(flags, 4) && channel != null) {
ByteBuf content = Unpooled.buffer();
content.writeByte(MSG_RESPONSE);
@@ -82,21 +88,16 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
ByteBuf response = Unpooled.buffer();
response.writeByte(0xAB); // header
- response.writeByte(0); // properties
- response.writeShortLE(3);
+ response.writeByte(0x00); // properties
+ response.writeShortLE(content.readableBytes());
response.writeShortLE(Checksum.crc16(Checksum.CRC16_XMODEM, content.nioBuffer()));
- response.writeShortLE(0); // index
+ response.writeShortLE(index);
response.writeBytes(content);
content.release();
channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
}
- buf.readUnsignedShortLE(); // length
- buf.readUnsignedShortLE(); // checksum
- buf.readUnsignedShortLE(); // index
- int type = buf.readUnsignedByte();
-
if (type == MSG_DATA) {
Position position = new Position(getProtocolName());
@@ -116,6 +117,10 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
case 0x02:
position.set(Position.KEY_ALARM, decodeAlarm(buf.readIntLE()));
break;
+ case 0x14:
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.001);
+ break;
case 0x20:
position.setLatitude(buf.readIntLE() * 0.0000001);
position.setLongitude(buf.readIntLE() * 0.0000001);
@@ -149,6 +154,12 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
mac.substring(0, mac.length() - 1), rssi));
}
break;
+ case 0x24:
+ position.setTime(new Date(buf.readUnsignedIntLE() * 1000));
+ long status = buf.readUnsignedIntLE();
+ position.set(Position.KEY_BATTERY_LEVEL, BitUtil.from(status, 24));
+ position.set(Position.KEY_STATUS, status);
+ break;
case 0x40:
buf.readUnsignedIntLE(); // timestamp
int heartRate = buf.readUnsignedByte();
diff --git a/src/main/java/org/traccar/protocol/NavisetFrameDecoder.java b/src/main/java/org/traccar/protocol/NavisetFrameDecoder.java
new file mode 100644
index 000000000..e5e13b305
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/NavisetFrameDecoder.java
@@ -0,0 +1,39 @@
+/*
+ * 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.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import org.traccar.BaseFrameDecoder;
+import org.traccar.helper.BitUtil;
+
+public class NavisetFrameDecoder extends BaseFrameDecoder {
+
+ @Override
+ protected Object decode(
+ ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception {
+
+ int length = 2 + BitUtil.to(buf.getUnsignedShortLE(buf.readerIndex()), 12) + 2;
+
+ if (buf.readableBytes() >= length) {
+ return buf.readRetainedSlice(length);
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/NavisetProtocol.java b/src/main/java/org/traccar/protocol/NavisetProtocol.java
new file mode 100644
index 000000000..78755ea4d
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/NavisetProtocol.java
@@ -0,0 +1,34 @@
+/*
+ * 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.protocol;
+
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+
+public class NavisetProtocol extends BaseProtocol {
+
+ public NavisetProtocol() {
+ addServer(new TrackerServer(false, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new NavisetFrameDecoder());
+ pipeline.addLast(new NavisetProtocolDecoder(NavisetProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/NavisetProtocolDecoder.java b/src/main/java/org/traccar/protocol/NavisetProtocolDecoder.java
new file mode 100644
index 000000000..10d71d76c
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/NavisetProtocolDecoder.java
@@ -0,0 +1,249 @@
+/*
+ * 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.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.BitUtil;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+public class NavisetProtocolDecoder extends BaseProtocolDecoder {
+
+ public NavisetProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public static final int MSG_HEADER = 0b00;
+ public static final int MSG_DATA = 0b01;
+ public static final int MSG_RESPONSE = 0b10;
+ public static final int MSG_RESERVE = 0b11;
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ByteBuf buf = (ByteBuf) msg;
+
+ if (channel != null) {
+ ByteBuf response = Unpooled.buffer();
+ response.writeByte(0x01);
+ response.writeShortLE(buf.getUnsignedShortLE(buf.writerIndex() - 2));
+ channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress()));
+ }
+
+ int length = buf.readUnsignedShortLE();
+ int type = BitUtil.between(length, 14, 16);
+ buf.readUnsignedShortLE(); // device number
+
+ if (type == MSG_HEADER) {
+
+ getDeviceSession(channel, remoteAddress, buf.readCharSequence(15, StandardCharsets.US_ASCII).toString());
+
+ } else if (type == MSG_DATA) {
+
+ List<Position> positions = new LinkedList<>();
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ int blockMask = buf.readUnsignedByte();
+
+ while (buf.readableBytes() > 2) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.set(Position.KEY_INDEX, buf.readUnsignedShortLE());
+ position.set(Position.KEY_STATUS, buf.readUnsignedByte());
+ position.setValid(true);
+ position.setTime(new Date(buf.readUnsignedIntLE() * 1000));
+ position.setLatitude(buf.readUnsignedIntLE() * 0.000001);
+ position.setLongitude(buf.readUnsignedIntLE() * 0.000001);
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShortLE() * 0.1));
+
+ if (BitUtil.check(blockMask, 0)) {
+ int dataMask = buf.readUnsignedByte();
+ if (BitUtil.check(dataMask, 0)) {
+ int satellites = buf.readUnsignedByte();
+ position.setValid(BitUtil.check(satellites, 7));
+ position.set(Position.KEY_SATELLITES, BitUtil.to(satellites, 7));
+ }
+ if (BitUtil.check(dataMask, 1)) {
+ position.setCourse(buf.readUnsignedShortLE() * 0.1);
+ }
+ if (BitUtil.check(dataMask, 2)) {
+ position.setAltitude(buf.readShortLE());
+ }
+ if (BitUtil.check(dataMask, 3)) {
+ position.set(Position.KEY_HDOP, buf.readUnsignedByte() * 0.1);
+ }
+ if (BitUtil.check(dataMask, 4)) {
+ position.set(Position.KEY_POWER, buf.readUnsignedShortLE() * 0.001);
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.001);
+ }
+ if (BitUtil.check(dataMask, 5)) {
+ position.set(Position.KEY_INPUT, buf.readUnsignedByte());
+ position.set(Position.KEY_OUTPUT, buf.readUnsignedByte());
+ }
+ if (BitUtil.check(dataMask, 6)) {
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE());
+ }
+ if (BitUtil.check(dataMask, 7)) {
+ buf.skipBytes(6); // accelerometer
+ }
+ }
+
+ if (BitUtil.check(blockMask, 1)) {
+ int dataMask = buf.readUnsignedByte();
+ for (int i = 0; i < 8; i++) {
+ if (BitUtil.check(dataMask, i)) {
+ position.set(Position.PREFIX_ADC + (i + 1), buf.readUnsignedShortLE());
+ }
+ }
+ }
+
+ if (BitUtil.check(blockMask, 2)) {
+ int dataMask = buf.readUnsignedByte();
+ if (BitUtil.check(dataMask, 0)) {
+ position.set(Position.KEY_DEVICE_TEMP, (int) buf.readByte());
+ }
+ if (BitUtil.check(dataMask, 1)) {
+ buf.skipBytes(6); // key code
+ }
+ if (BitUtil.check(dataMask, 2)) {
+ position.set(Position.PREFIX_TEMP + 1, (int) buf.readByte());
+ position.set(Position.PREFIX_TEMP + 2, (int) buf.readByte());
+ }
+ if (BitUtil.check(dataMask, 3)) {
+ position.set(Position.PREFIX_TEMP + 3, (int) buf.readByte());
+ position.set(Position.PREFIX_TEMP + 4, (int) buf.readByte());
+ }
+ if (BitUtil.check(dataMask, 4)) {
+ position.set(Position.PREFIX_TEMP + 5, (int) buf.readByte());
+ position.set(Position.PREFIX_TEMP + 6, (int) buf.readByte());
+ position.set(Position.PREFIX_TEMP + 7, (int) buf.readByte());
+ position.set(Position.PREFIX_TEMP + 8, (int) buf.readByte());
+ }
+ if (BitUtil.check(dataMask, 5)) {
+ position.set(Position.KEY_HOURS, buf.readUnsignedShortLE() / 60.0);
+ }
+ if (BitUtil.check(dataMask, 6)) {
+ buf.readUnsignedByte(); // extra status
+ }
+ if (BitUtil.check(dataMask, 7)) {
+ buf.readUnsignedByte(); // geofence
+ }
+ }
+
+ if (BitUtil.check(blockMask, 3)) {
+ int dataMask = buf.readUnsignedByte();
+ if (BitUtil.check(dataMask, 0)) {
+ position.set("fuel1", buf.readUnsignedShortLE());
+ }
+ if (BitUtil.check(dataMask, 1)) {
+ position.set("fuel2", buf.readUnsignedShortLE());
+ }
+ if (BitUtil.check(dataMask, 2)) {
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedShortLE());
+ }
+ if (BitUtil.check(dataMask, 3)) {
+ buf.skipBytes(18);
+ }
+ if (BitUtil.check(dataMask, 4)) {
+ buf.readUnsignedByte(); // fuel 1 temperature
+ }
+ if (BitUtil.check(dataMask, 5)) {
+ buf.readUnsignedByte(); // fuel 2 temperature
+ }
+ if (BitUtil.check(dataMask, 6)) {
+ buf.readUnsignedShortLE(); // fuel 1 frequency
+ }
+ if (BitUtil.check(dataMask, 7)) {
+ buf.readUnsignedShortLE(); // fuel 2 frequency
+ }
+ }
+
+ if (BitUtil.check(blockMask, 4)) {
+ int dataMask = buf.readUnsignedByte();
+ if (BitUtil.check(dataMask, 0)) {
+ buf.readUnsignedByte(); // fuel level (percentage)
+ position.set(Position.KEY_RPM, buf.readUnsignedShortLE());
+ position.set(Position.KEY_COOLANT_TEMP, (int) buf.readByte());
+ }
+ if (BitUtil.check(dataMask, 1)) {
+ buf.readUnsignedIntLE(); // fuel consumption
+ }
+ if (BitUtil.check(dataMask, 2)) {
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE());
+ }
+ for (int i = 3; i < 8; i++) {
+ if (BitUtil.check(dataMask, i)) {
+ buf.readUnsignedShortLE(); // axle weight
+ }
+ }
+ }
+
+ if (BitUtil.check(blockMask, 4)) {
+ int dataMask = buf.readUnsignedByte();
+ if (BitUtil.check(dataMask, 0)) {
+ buf.readUnsignedByte(); // speed
+ }
+ if (BitUtil.check(dataMask, 1)) {
+ buf.readUnsignedMediumLE(); // prefix S
+ }
+ if (BitUtil.check(dataMask, 2)) {
+ buf.readUnsignedIntLE(); // prefix P
+ }
+ if (BitUtil.check(dataMask, 3)) {
+ buf.readUnsignedIntLE(); // prefix A or B
+ }
+ if (BitUtil.check(dataMask, 4)) {
+ buf.readUnsignedShortLE(); // prefix R
+ }
+ if (BitUtil.check(dataMask, 5)) {
+ buf.skipBytes(26);
+ }
+ if (BitUtil.check(dataMask, 6)) {
+ buf.readUnsignedIntLE(); // reserved
+ }
+ if (BitUtil.check(dataMask, 7)) {
+ buf.readUnsignedIntLE(); // reserved
+ }
+ }
+
+ positions.add(position);
+ }
+
+ return positions;
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/NoranProtocol.java b/src/main/java/org/traccar/protocol/NoranProtocol.java
index 9f3078d6d..3df364c30 100644
--- a/src/main/java/org/traccar/protocol/NoranProtocol.java
+++ b/src/main/java/org/traccar/protocol/NoranProtocol.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.
@@ -32,7 +32,7 @@ public class NoranProtocol extends BaseProtocol {
addServer(new TrackerServer(true, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new NoranProtocolEncoder());
+ pipeline.addLast(new NoranProtocolEncoder(NoranProtocol.this));
pipeline.addLast(new NoranProtocolDecoder(NoranProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/NoranProtocolEncoder.java b/src/main/java/org/traccar/protocol/NoranProtocolEncoder.java
index 92826c8b2..e02a1313c 100644
--- a/src/main/java/org/traccar/protocol/NoranProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/NoranProtocolEncoder.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.
@@ -19,11 +19,16 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
public class NoranProtocolEncoder extends BaseProtocolEncoder {
+ public NoranProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeContent(String content) {
ByteBuf buf = Unpooled.buffer(12 + 56);
diff --git a/src/main/java/org/traccar/protocol/PacificTrackProtocol.java b/src/main/java/org/traccar/protocol/PacificTrackProtocol.java
new file mode 100644
index 000000000..08991ab64
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/PacificTrackProtocol.java
@@ -0,0 +1,33 @@
+/*
+ * 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.protocol;
+
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+
+public class PacificTrackProtocol extends BaseProtocol {
+
+ public PacificTrackProtocol() {
+ addServer(new TrackerServer(true, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new PacificTrackProtocolDecoder(PacificTrackProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/PacificTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/PacificTrackProtocolDecoder.java
new file mode 100644
index 000000000..199348c54
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/PacificTrackProtocolDecoder.java
@@ -0,0 +1,104 @@
+/*
+ * 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.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.Protocol;
+import org.traccar.helper.BitUtil;
+import org.traccar.helper.DateBuilder;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+
+public class PacificTrackProtocolDecoder extends BaseProtocolDecoder {
+
+ public PacificTrackProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public static int readBitExt(ByteBuf buf) {
+ int result = 0;
+ while (buf.isReadable()) {
+ int b = buf.readUnsignedByte();
+ result <<= 7;
+ result += BitUtil.to(b, 7);
+ if (BitUtil.check(b, 7)) {
+ break;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ByteBuf buf = (ByteBuf) msg;
+
+ buf.readByte(); // frame start
+ readBitExt(buf); // frame control
+ readBitExt(buf); // frame length
+
+ DeviceSession deviceSession = null;
+ Position position = new Position(getProtocolName());
+
+ while (buf.isReadable()) {
+
+ int segmentId = readBitExt(buf);
+ int segmentLength = readBitExt(buf);
+
+ switch (segmentId) {
+ case 0x01:
+ position.set(Position.KEY_EVENT, readBitExt(buf));
+ break;
+ case 0x10:
+ position.setValid(BitUtil.check(buf.readUnsignedByte(), 4));
+ int date = buf.readUnsignedByte();
+ DateBuilder dateBuilder = new DateBuilder()
+ .setDate(2000 + BitUtil.from(date, 4), BitUtil.to(date, 4), buf.readUnsignedByte())
+ .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte());
+ position.setTime(dateBuilder.getDate());
+ position.setLatitude(buf.readUnsignedInt() / 1000000.0 - 90.0);
+ position.setLongitude(buf.readUnsignedInt() / 1000000.0 - 180.0);
+ int speedAndCourse = buf.readUnsignedMedium();
+ position.setCourse(BitUtil.from(speedAndCourse, 12));
+ position.setSpeed(UnitsConverter.knotsFromKph(BitUtil.to(speedAndCourse, 12)));
+ position.set(Position.KEY_INDEX, buf.readUnsignedShort());
+ break;
+ case 0x100:
+ String imei = ByteBufUtil.hexDump(buf.readSlice(8)).substring(1);
+ deviceSession = getDeviceSession(channel, remoteAddress, imei);
+ break;
+ default:
+ buf.skipBytes(segmentLength);
+ break;
+ }
+ }
+
+ if (deviceSession != null) {
+ position.setDeviceId(deviceSession.getDeviceId());
+ return position;
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/PluginProtocol.java b/src/main/java/org/traccar/protocol/PluginProtocol.java
new file mode 100644
index 000000000..d5f28da9d
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/PluginProtocol.java
@@ -0,0 +1,39 @@
+/*
+ * 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.protocol;
+
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import org.traccar.BaseProtocol;
+import org.traccar.CharacterDelimiterFrameDecoder;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+
+public class PluginProtocol extends BaseProtocol {
+
+ public PluginProtocol() {
+ addServer(new TrackerServer(false, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, '#'));
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new PluginProtocolDecoder(PluginProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/PluginProtocolDecoder.java b/src/main/java/org/traccar/protocol/PluginProtocolDecoder.java
new file mode 100644
index 000000000..106889ee0
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/PluginProtocolDecoder.java
@@ -0,0 +1,93 @@
+/*
+ * 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.protocol;
+
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.Protocol;
+import org.traccar.helper.Parser;
+import org.traccar.helper.PatternBuilder;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.util.regex.Pattern;
+
+public class PluginProtocolDecoder extends BaseProtocolDecoder {
+
+ public PluginProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .expression("[^0-9,]*,?")
+ .number("([^,]+),") // device id
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd),") // time (hhmmss)
+ .number("(-?d+.d+),") // longitude
+ .number("(-?d+.d+),") // latitude
+ .number("(d+),") // speed
+ .number("(d+),") // course
+ .number("(-?d+),") // altitude
+ .number("(-?d+),") // satellites
+ .number("d+,") // type
+ .number("(d+),") // odometer
+ .number("(d+),") // status
+ .expression("[^,]*,")
+ .expression("[^,]*,")
+ .text("0")
+ .groupBegin()
+ .text(",+,")
+ .number("(d+),") // event
+ .groupEnd("?")
+ .any()
+ .compile();
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ Parser parser = new Parser(PATTERN, (String) msg);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setValid(true);
+ position.setTime(parser.nextDateTime());
+ position.setLongitude(parser.nextDouble());
+ position.setLatitude(parser.nextDouble());
+ position.setSpeed(UnitsConverter.knotsFromKph(parser.nextInt()));
+ position.setCourse(parser.nextInt());
+ position.setAltitude(parser.nextInt());
+
+ position.set(Position.KEY_SATELLITES, parser.nextInt());
+ position.set(Position.KEY_ODOMETER, parser.nextInt());
+ position.set(Position.KEY_STATUS, parser.nextInt());
+ position.set(Position.KEY_EVENT, parser.nextInt());
+
+ return position;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/PretraceProtocol.java b/src/main/java/org/traccar/protocol/PretraceProtocol.java
index f753cbdb4..9d35c1c2f 100644
--- a/src/main/java/org/traccar/protocol/PretraceProtocol.java
+++ b/src/main/java/org/traccar/protocol/PretraceProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 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.
@@ -35,7 +35,7 @@ public class PretraceProtocol extends BaseProtocol {
pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, ')'));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new PretraceProtocolEncoder());
+ pipeline.addLast(new PretraceProtocolEncoder(PretraceProtocol.this));
pipeline.addLast(new PretraceProtocolDecoder(PretraceProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/PretraceProtocolEncoder.java b/src/main/java/org/traccar/protocol/PretraceProtocolEncoder.java
index 9cf951e3b..1083a252e 100644
--- a/src/main/java/org/traccar/protocol/PretraceProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/PretraceProtocolEncoder.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.
@@ -19,9 +19,14 @@ import org.traccar.BaseProtocolEncoder;
import org.traccar.Context;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class PretraceProtocolEncoder extends BaseProtocolEncoder {
+ public PretraceProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private String formatCommand(String uniqueId, String data) {
String content = uniqueId + data;
return String.format("(%s^%02X)", content, Checksum.xor(content));
diff --git a/src/main/java/org/traccar/protocol/Pt215FrameDecoder.java b/src/main/java/org/traccar/protocol/Pt215FrameDecoder.java
new file mode 100644
index 000000000..0b3bae914
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/Pt215FrameDecoder.java
@@ -0,0 +1,55 @@
+/*
+ * 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.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import org.traccar.BaseFrameDecoder;
+
+public class Pt215FrameDecoder extends BaseFrameDecoder {
+
+ private ByteBuf decodeFrame(ByteBuf buf, int length) {
+ if (buf.readableBytes() >= length) {
+ return buf.readRetainedSlice(length);
+ }
+ return null;
+ }
+
+ @Override
+ protected Object decode(
+ ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception {
+
+ if (buf.readableBytes() < 5) {
+ return null;
+ }
+
+ int type = buf.getUnsignedByte(buf.readerIndex() + 2 + 1);
+ switch (type) {
+ case Pt215ProtocolDecoder.MSG_LOGIN:
+ return decodeFrame(buf, 15);
+ case Pt215ProtocolDecoder.MSG_GPS_REALTIME:
+ case Pt215ProtocolDecoder.MSG_GPS_OFFLINE:
+ return decodeFrame(buf, 27);
+ case Pt215ProtocolDecoder.MSG_STATUS:
+ return decodeFrame(buf, 11);
+ default:
+ return null;
+
+ }
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/Pt215Protocol.java b/src/main/java/org/traccar/protocol/Pt215Protocol.java
new file mode 100644
index 000000000..31ddc2c7a
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/Pt215Protocol.java
@@ -0,0 +1,34 @@
+/*
+ * 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.protocol;
+
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+
+public class Pt215Protocol extends BaseProtocol {
+
+ public Pt215Protocol() {
+ addServer(new TrackerServer(false, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new Pt215FrameDecoder());
+ pipeline.addLast(new Pt215ProtocolDecoder(Pt215Protocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/Pt215ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Pt215ProtocolDecoder.java
new file mode 100644
index 000000000..48ce7dede
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/Pt215ProtocolDecoder.java
@@ -0,0 +1,118 @@
+/*
+ * 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.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+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.BitUtil;
+import org.traccar.helper.DateBuilder;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+
+public class Pt215ProtocolDecoder extends BaseProtocolDecoder {
+
+ public Pt215ProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public static final int MSG_LOGIN = 0x01;
+ public static final int MSG_HEARTBEAT = 0x08;
+ public static final int MSG_GPS_REALTIME = 0x10;
+ public static final int MSG_GPS_OFFLINE = 0x11;
+ public static final int MSG_STATUS = 0x13;
+
+ private void sendResponse(
+ Channel channel, SocketAddress remoteAddress, int type, ByteBuf content) {
+ if (channel != null) {
+ ByteBuf response = Unpooled.buffer();
+ response.writeByte('X');
+ response.writeByte('X');
+ response.writeByte(content != null ? 1 + content.readableBytes() : 1);
+ response.writeByte(type);
+ if (content != null) {
+ response.writeBytes(content);
+ content.release();
+ }
+ response.writeByte('\r');
+ response.writeByte('\n');
+ channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
+ }
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ByteBuf buf = (ByteBuf) msg;
+
+ buf.skipBytes(2); // header
+ buf.readUnsignedByte(); // length
+ int type = buf.readUnsignedByte();
+
+ if (type == MSG_LOGIN) {
+
+ getDeviceSession(channel, remoteAddress, ByteBufUtil.hexDump(buf.readSlice(8)).substring(1));
+ sendResponse(channel, remoteAddress, type, null);
+
+ } else if (type == MSG_GPS_OFFLINE || type == MSG_GPS_REALTIME) {
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ sendResponse(channel, remoteAddress, type, buf.retainedSlice(buf.readerIndex(), 6));
+
+ DateBuilder dateBuilder = new DateBuilder()
+ .setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
+ .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte());
+ position.setTime(dateBuilder.getDate());
+
+ double latitude = buf.readUnsignedInt() / 60.0 / 30000.0;
+ double longitude = buf.readUnsignedInt() / 60.0 / 30000.0;
+
+ int flags = buf.readUnsignedShort();
+ position.setCourse(BitUtil.to(flags, 10));
+ position.setValid(BitUtil.check(flags, 12));
+
+ if (!BitUtil.check(flags, 10)) {
+ latitude = -latitude;
+ }
+ if (BitUtil.check(flags, 11)) {
+ longitude = -longitude;
+ }
+
+ position.setLatitude(latitude);
+ position.setLongitude(longitude);
+
+ return position;
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/Pt502Protocol.java b/src/main/java/org/traccar/protocol/Pt502Protocol.java
index 5afb9451d..56444fb42 100644
--- a/src/main/java/org/traccar/protocol/Pt502Protocol.java
+++ b/src/main/java/org/traccar/protocol/Pt502Protocol.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.
@@ -35,7 +35,7 @@ public class Pt502Protocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new Pt502FrameDecoder());
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new Pt502ProtocolEncoder());
+ pipeline.addLast(new Pt502ProtocolEncoder(Pt502Protocol.this));
pipeline.addLast(new Pt502ProtocolDecoder(Pt502Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/Pt502ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Pt502ProtocolEncoder.java
index ed18208cc..ba08b16ae 100644
--- a/src/main/java/org/traccar/protocol/Pt502ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Pt502ProtocolEncoder.java
@@ -1,5 +1,5 @@
/*
- * 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.
@@ -19,9 +19,14 @@ import java.util.TimeZone;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class Pt502ProtocolEncoder extends StringProtocolEncoder implements StringProtocolEncoder.ValueFormatter {
+ public Pt502ProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
public String formatValue(String key, Object value) {
if (key.equals(Command.KEY_TIMEZONE)) {
diff --git a/src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java b/src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java
new file mode 100644
index 000000000..c9db10610
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java
@@ -0,0 +1,39 @@
+/*
+ * 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.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;
+
+public class RaceDynamicsProtocol extends BaseProtocol {
+
+ public RaceDynamicsProtocol() {
+ addServer(new TrackerServer(false, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new LineBasedFrameDecoder(1500));
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new RaceDynamicsProtocolDecoder(RaceDynamicsProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/RaceDynamicsProtocolDecoder.java b/src/main/java/org/traccar/protocol/RaceDynamicsProtocolDecoder.java
new file mode 100644
index 000000000..f441bf8ed
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/RaceDynamicsProtocolDecoder.java
@@ -0,0 +1,171 @@
+/*
+ * 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.protocol;
+
+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.DateBuilder;
+import org.traccar.helper.Parser;
+import org.traccar.helper.PatternBuilder;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class RaceDynamicsProtocolDecoder extends BaseProtocolDecoder {
+
+ public RaceDynamicsProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public static final int MSG_LOGIN = 12;
+ public static final int MSG_LOCATION = 15;
+
+ private static final Pattern PATTERN_LOGIN = new PatternBuilder()
+ .text("$GPRMC,")
+ .number("d+,") // type
+ .number("d{6},") // date
+ .number("d{6},") // time
+ .number("(d{15}),")
+ .compile();
+
+ private static final Pattern PATTERN_LOCATION = new PatternBuilder()
+ .number("(dd)(dd)(dd),") // time (hhmmss)
+ .expression("([AV]),") // validity
+ .number("(dd)(dd.d+),") // latitude
+ .expression("([NS]),")
+ .number("(ddd)(dd.d+),") // longitude
+ .expression("([EW]),")
+ .number("(d+),") // speed
+ .number("(dd)(dd)(dd),") // date (ddmmyy)
+ .number("(-?d+),") // altitude
+ .number("(d+),") // satellites
+ .number("([01]),") // ignition
+ .number("(d+),") // index
+ .text("%,")
+ .number("([^,]+),") // ibutton
+ .number("d+,") // acceleration
+ .number("d+,") // deceleration
+ .number("[01],") // cruise control
+ .number("[01],") // seat belt
+ .number("[01],") // wrong ibutton
+ .number("(d+),") // power
+ .number("[01],") // power status
+ .number("(d+),") // battery
+ .number("([01]),") // panic
+ .number("d+,")
+ .number("d+,")
+ .number("(d),") // overspeed
+ .number("d+,") // speed limit
+ .number("d+,") // tachometer
+ .number("d+,d+,d+,") // aux
+ .number("d+,") // geofence id
+ .number("d+,") // road speed type
+ .number("d+,") // ibutton count
+ .number("(d),") // overdriver alert
+ .any()
+ .compile();
+
+ private String imei;
+
+ private void sendResponse(Channel channel, SocketAddress remoteAddress, int type) {
+ if (channel != null) {
+ String response = String.format(
+ "$GPRMC,%1$d,%2$td%2$tm%2$ty,%2$tH%2$tM%2$tS,%3$s,\r\n", type, new Date(), imei);
+ channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
+ }
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ String sentence = (String) msg;
+
+ int type = Integer.parseInt(sentence.substring(7, 9));
+
+ if (type == MSG_LOGIN) {
+
+ Parser parser = new Parser(PATTERN_LOGIN, sentence);
+ if (parser.matches()) {
+ imei = parser.next();
+ getDeviceSession(channel, remoteAddress, imei);
+ sendResponse(channel, remoteAddress, type);
+ }
+
+ } else if (type == MSG_LOCATION) {
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ List<Position> positions = new LinkedList<>();
+
+ for (String data : sentence.substring(17, sentence.length() - 3).split(",#,#,")) {
+ Parser parser = new Parser(PATTERN_LOCATION, data);
+ if (parser.matches()) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ DateBuilder dateBuilder = new DateBuilder()
+ .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
+
+ position.setValid(parser.next().equals("A"));
+ position.setLatitude(parser.nextCoordinate());
+ position.setLongitude(parser.nextCoordinate());
+ position.setSpeed(parser.nextDouble());
+
+ dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ position.setTime(dateBuilder.getDate());
+
+ position.setAltitude(parser.nextInt());
+ position.set(Position.KEY_SATELLITES, parser.nextInt());
+ position.set(Position.KEY_IGNITION, parser.nextInt() == 1);
+ position.set(Position.KEY_INDEX, parser.nextInt());
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next());
+ position.set(Position.KEY_POWER, parser.nextInt() * 0.01);
+ position.set(Position.KEY_BATTERY, parser.nextInt() * 0.01);
+ position.set(Position.KEY_ALARM, parser.nextInt() > 0 ? Position.ALARM_SOS : null);
+ position.set(Position.KEY_ALARM, parser.nextInt() > 0 ? Position.ALARM_OVERSPEED : null);
+
+ int overDriver = parser.nextInt();
+ if (overDriver > 0) {
+ position.set("overDriver", overDriver);
+ }
+
+ positions.add(position);
+
+ }
+ }
+
+ sendResponse(channel, remoteAddress, type);
+
+ return positions;
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/RstProtocol.java b/src/main/java/org/traccar/protocol/RstProtocol.java
new file mode 100644
index 000000000..10d11d493
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/RstProtocol.java
@@ -0,0 +1,37 @@
+/*
+ * 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.protocol;
+
+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;
+
+public class RstProtocol extends BaseProtocol {
+
+ public RstProtocol() {
+ addServer(new TrackerServer(true, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new RstProtocolDecoder(RstProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/RstProtocolDecoder.java b/src/main/java/org/traccar/protocol/RstProtocolDecoder.java
new file mode 100644
index 000000000..071200d6d
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/RstProtocolDecoder.java
@@ -0,0 +1,128 @@
+/*
+ * 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.protocol;
+
+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.Parser;
+import org.traccar.helper.PatternBuilder;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.util.regex.Pattern;
+
+public class RstProtocolDecoder extends BaseProtocolDecoder {
+
+ public RstProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .text("RST;")
+ .expression("([AL]);") // archive
+ .expression("([^,]+);") // model
+ .expression("(.{5});") // firmware
+ .number("(d{9});") // serial number
+ .number("(d+);") // index
+ .number("(d+);") // type
+ .number("(dd)-(dd)-(dddd) ") // event date
+ .number("(dd):(dd):(dd);") // event time
+ .number("(dd)-(dd)-(dddd) ") // fix date
+ .number("(dd):(dd):(dd);") // fix time
+ .number("(-?d+.d+);") // latitude
+ .number("(-?d+.d+);") // longitude
+ .number("(d+);") // speed
+ .number("(d+);") // course
+ .number("(-?d+);") // altitude
+ .number("([01]);") // valid
+ .number("(d+);") // satellites
+ .number("(d+);") // hdop
+ .number("(xx);") // inputs 1
+ .number("(xx);") // inputs 2
+ .number("(xx);") // inputs 3
+ .number("(xx);") // outputs 1
+ .number("(xx);") // outputs 2
+ .number("(d+.d+);") // power
+ .number("(d+.d+);") // battery
+ .number("(d+);") // odometer
+ .number("(d+);") // rssi
+ .number("(xx);") // temperature
+ .number("x{4};") // sensors
+ .number("(xx);") // status 1
+ .number("(xx);") // status 2
+ .any()
+ .compile();
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ Parser parser = new Parser(PATTERN, (String) msg);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ String archive = parser.next();
+ String model = parser.next();
+ String firmware = parser.next();
+ String serial = parser.next();
+ int index = parser.nextInt();
+ int type = parser.nextInt();
+
+ if (channel != null && archive.equals("A")) {
+ String response = "RST;A;" + model + ";" + firmware + ";" + serial + ";" + index + ";" + type + ";FIM;";
+ channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
+ }
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, serial);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setDeviceTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
+ position.setFixTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
+ position.setLatitude(parser.nextDouble());
+ position.setLongitude(parser.nextDouble());
+ position.setSpeed(UnitsConverter.knotsFromKph(parser.nextInt()));
+ position.setCourse(parser.nextInt());
+ position.setAltitude(parser.nextInt());
+ position.setValid(parser.nextInt() > 0);
+
+ position.set(Position.KEY_SATELLITES, parser.nextInt());
+ position.set(Position.KEY_HDOP, parser.nextInt());
+ position.set(Position.PREFIX_IN + 1, parser.nextHexInt());
+ position.set(Position.PREFIX_IN + 2, parser.nextHexInt());
+ position.set(Position.PREFIX_IN + 3, parser.nextHexInt());
+ position.set(Position.PREFIX_OUT + 1, parser.nextHexInt());
+ position.set(Position.PREFIX_OUT + 2, parser.nextHexInt());
+ position.set(Position.KEY_POWER, parser.nextDouble());
+ position.set(Position.KEY_BATTERY, parser.nextDouble());
+ position.set(Position.KEY_ODOMETER, parser.nextInt());
+ position.set(Position.KEY_RSSI, parser.nextInt());
+ position.set(Position.PREFIX_TEMP + 1, (int) parser.nextHexInt().byteValue());
+ position.set(Position.KEY_STATUS, parser.nextHexInt() << 8 + parser.nextHexInt());
+
+ return position;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/RuptelaProtocol.java b/src/main/java/org/traccar/protocol/RuptelaProtocol.java
index a574293cd..b8f72336b 100644
--- a/src/main/java/org/traccar/protocol/RuptelaProtocol.java
+++ b/src/main/java/org/traccar/protocol/RuptelaProtocol.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.
@@ -37,7 +37,7 @@ public class RuptelaProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 2, 2, 0));
- pipeline.addLast(new RuptelaProtocolEncoder());
+ pipeline.addLast(new RuptelaProtocolEncoder(RuptelaProtocol.this));
pipeline.addLast(new RuptelaProtocolDecoder(RuptelaProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/RuptelaProtocolEncoder.java b/src/main/java/org/traccar/protocol/RuptelaProtocolEncoder.java
index 96d0da5a7..51967403d 100644
--- a/src/main/java/org/traccar/protocol/RuptelaProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/RuptelaProtocolEncoder.java
@@ -20,11 +20,16 @@ import io.netty.buffer.Unpooled;
import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
public class RuptelaProtocolEncoder extends BaseProtocolEncoder {
+ public RuptelaProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeContent(int type, ByteBuf content) {
ByteBuf buf = Unpooled.buffer();
diff --git a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java
index d7836b35d..f9c79fb5b 100644
--- a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 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.
@@ -16,6 +16,7 @@
package org.traccar.protocol;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.FullHttpRequest;
@@ -25,7 +26,9 @@ import org.traccar.DeviceSession;
import org.traccar.Protocol;
import org.traccar.helper.DataConverter;
import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Network;
import org.traccar.model.Position;
+import org.traccar.model.WifiAccessPoint;
import javax.json.Json;
import javax.json.JsonObject;
@@ -46,8 +49,11 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder {
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
FullHttpRequest request = (FullHttpRequest) msg;
- JsonObject json = Json.createReader(new StringReader(URLDecoder.decode(
- request.content().toString(StandardCharsets.UTF_8).split("=")[0], "UTF-8"))).readObject();
+ String content = request.content().toString(StandardCharsets.UTF_8);
+ if (!content.startsWith("{")) {
+ content = URLDecoder.decode(content.split("=")[0], "UTF-8");
+ }
+ JsonObject json = Json.createReader(new StringReader(content)).readObject();
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, json.getString("device"));
if (deviceSession == null) {
@@ -58,32 +64,101 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
- position.setTime(new Date(json.getInt("time") * 1000L));
-
- ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(json.getString("data")));
- try {
- int type = buf.readUnsignedByte() >> 4;
- if (type == 0) {
-
- position.setValid(true);
- position.setLatitude(buf.readIntLE() * 0.0000001);
- position.setLongitude(buf.readIntLE() * 0.0000001);
- position.setCourse(buf.readUnsignedByte() * 2);
- position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
-
- position.set(Position.KEY_BATTERY, buf.readUnsignedByte() * 0.025);
-
- } else {
-
- getLastLocation(position, position.getDeviceTime());
+ if (json.containsKey("time")) {
+ position.setTime(new Date(json.getInt("time") * 1000L));
+ } else {
+ position.setTime(new Date());
+ }
+ if (json.containsKey("location")) {
+
+ JsonObject location = json.getJsonObject("location");
+
+ position.setValid(true);
+ position.setLatitude(location.getJsonNumber("lat").doubleValue());
+ position.setLongitude(location.getJsonNumber("lng").doubleValue());
+
+ } else {
+
+ String data = json.getString(json.containsKey("data") ? "data" : "payload");
+ ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(data));
+ try {
+ int event = buf.readUnsignedByte();
+ if (event >> 4 == 0) {
+
+ position.setValid(true);
+ position.setLatitude(buf.readIntLE() * 0.0000001);
+ position.setLongitude(buf.readIntLE() * 0.0000001);
+ position.setCourse(buf.readUnsignedByte() * 2);
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+
+ position.set(Position.KEY_BATTERY, buf.readUnsignedByte() * 0.025);
+
+ } else {
+
+ position.set(Position.KEY_EVENT, event);
+ if (event == 0x22 || event == 0x62) {
+ position.set(Position.KEY_ALARM, Position.ALARM_SOS);
+ }
+
+ while (buf.isReadable()) {
+ int type = buf.readUnsignedByte();
+ switch (type) {
+ case 0x01:
+ position.setValid(true);
+ position.setLatitude(buf.readMedium());
+ position.setLongitude(buf.readMedium());
+ break;
+ case 0x02:
+ position.setValid(true);
+ position.setLatitude(buf.readFloat());
+ position.setLongitude(buf.readFloat());
+ break;
+ case 0x03:
+ position.set(Position.PREFIX_TEMP + 1, buf.readByte() * 0.5);
+ break;
+ case 0x04:
+ position.set(Position.KEY_BATTERY, buf.readUnsignedByte() * 0.1);
+ break;
+ case 0x05:
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ break;
+ case 0x06:
+ String mac = ByteBufUtil.hexDump(buf.readSlice(6)).replaceAll("(..)", "$1:");
+ position.setNetwork(new Network(WifiAccessPoint.from(
+ mac.substring(0, mac.length() - 1), buf.readUnsignedByte())));
+ break;
+ case 0x07:
+ buf.skipBytes(10); // wifi extended
+ break;
+ case 0x08:
+ buf.skipBytes(6); // accelerometer
+ break;
+ case 0x09:
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+ break;
+ default:
+ buf.readUnsignedByte(); // fence number
+ break;
+ }
+ }
+
+ }
+ } finally {
+ buf.release();
}
- } finally {
- buf.release();
}
- position.set(Position.KEY_RSSI, json.getJsonNumber("rssi").doubleValue());
- position.set(Position.KEY_INDEX, json.getInt("seqNumber"));
+ if (position.getLatitude() == 0 && position.getLongitude() == 0) {
+ getLastLocation(position, position.getDeviceTime());
+ }
+
+ if (json.containsKey("rssi")) {
+ position.set(Position.KEY_RSSI, json.getJsonNumber("rssi").doubleValue());
+ }
+ if (json.containsKey("seqNumber")) {
+ position.set(Position.KEY_INDEX, json.getInt("seqNumber"));
+ }
sendResponse(channel, HttpResponseStatus.OK);
return position;
diff --git a/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java b/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java
index ed5f81c1c..bad6f03a9 100644
--- a/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 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.
@@ -34,21 +34,7 @@ import java.util.regex.Pattern;
public class StarLinkProtocolDecoder extends BaseProtocolDecoder {
- private String[] dataTags;
- private DateFormat dateFormat;
-
- public StarLinkProtocolDecoder(Protocol protocol) {
- super(protocol);
-
- String format = Context.getConfig().getString(
- getProtocolName() + ".format", "#EDT#,#EID#,#PDT#,#LAT#,#LONG#,#SPD#,#HEAD#,#ODO#,"
- + "#IN1#,#IN2#,#IN3#,#IN4#,#OUT1#,#OUT2#,#OUT3#,#OUT4#,#LAC#,#CID#,#VIN#,#VBAT#,#DEST#,#IGN#,#ENG#");
- dataTags = format.split(",");
-
- dateFormat = new SimpleDateFormat(
- Context.getConfig().getString(getProtocolName() + ".dateFormat", "yyMMddHHmmss"));
- dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- }
+ public static final int MSG_EVENT_REPORT = 6;
private static final Pattern PATTERN = new PatternBuilder()
.expression(".") // protocol head
@@ -61,7 +47,27 @@ public class StarLinkProtocolDecoder extends BaseProtocolDecoder {
.number("xx") // checksum
.compile();
- public static final int MSG_EVENT_REPORT = 6;
+ private String[] dataTags;
+ private DateFormat dateFormat;
+
+ public StarLinkProtocolDecoder(Protocol protocol) {
+ super(protocol);
+
+ setFormat(Context.getConfig().getString(
+ getProtocolName() + ".format", "#EDT#,#EID#,#PDT#,#LAT#,#LONG#,#SPD#,#HEAD#,#ODO#,"
+ + "#IN1#,#IN2#,#IN3#,#IN4#,#OUT1#,#OUT2#,#OUT3#,#OUT4#,#LAC#,#CID#,#VIN#,#VBAT#,#DEST#,#IGN#,#ENG#"));
+
+ setDateFormat(Context.getConfig().getString(getProtocolName() + ".dateFormat", "yyMMddHHmmss"));
+ }
+
+ public void setFormat(String format) {
+ dataTags = format.split(",");
+ }
+
+ public void setDateFormat(String dateFormat) {
+ this.dateFormat = new SimpleDateFormat(dateFormat);
+ this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
private double parseCoordinate(String value) {
int minutesIndex = value.indexOf('.') - 2;
@@ -151,31 +157,19 @@ public class StarLinkProtocolDecoder extends BaseProtocolDecoder {
position.setCourse(Integer.parseInt(data[i]));
break;
case "#ODO#":
- position.set(Position.KEY_ODOMETER, Long.parseLong(data[i]) * 1000);
+ position.set(Position.KEY_ODOMETER, (long) (Double.parseDouble(data[i]) * 1000));
break;
case "#IN1#":
- position.set(Position.PREFIX_IN + 1, Integer.parseInt(data[i]));
- break;
case "#IN2#":
- position.set(Position.PREFIX_IN + 2, Integer.parseInt(data[i]));
- break;
case "#IN3#":
- position.set(Position.PREFIX_IN + 3, Integer.parseInt(data[i]));
- break;
case "#IN4#":
- position.set(Position.PREFIX_IN + 4, Integer.parseInt(data[i]));
+ position.set(Position.PREFIX_IN + dataTags[i].charAt(3), Integer.parseInt(data[i]));
break;
case "#OUT1#":
- position.set(Position.PREFIX_OUT + 1, Integer.parseInt(data[i]));
- break;
case "#OUT2#":
- position.set(Position.PREFIX_OUT + 2, Integer.parseInt(data[i]));
- break;
case "#OUT3#":
- position.set(Position.PREFIX_OUT + 3, Integer.parseInt(data[i]));
- break;
case "#OUT4#":
- position.set(Position.PREFIX_OUT + 4, Integer.parseInt(data[i]));
+ position.set(Position.PREFIX_OUT + dataTags[i].charAt(3), Integer.parseInt(data[i]));
break;
case "#LAC#":
if (!data[i].isEmpty()) {
diff --git a/src/main/java/org/traccar/protocol/SuntechProtocol.java b/src/main/java/org/traccar/protocol/SuntechProtocol.java
index 48d6e81c1..7e2c20e6f 100644
--- a/src/main/java/org/traccar/protocol/SuntechProtocol.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocol.java
@@ -39,7 +39,7 @@ public class SuntechProtocol extends BaseProtocol {
pipeline.addLast(new SuntechFrameDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new SuntechProtocolEncoder());
+ pipeline.addLast(new SuntechProtocolEncoder(SuntechProtocol.this));
pipeline.addLast(new SuntechProtocolDecoder(SuntechProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
index bd485ca70..e40096a77 100644
--- a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
@@ -50,7 +50,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
public int getProtocolType(long deviceId) {
return Context.getIdentityManager().lookupAttributeInteger(
- deviceId, getProtocolName() + ".protocolType", protocolType, true);
+ deviceId, getProtocolName() + ".protocolType", protocolType, false, true);
}
public void setHbm(boolean hbm) {
@@ -59,7 +59,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
public boolean isHbm(long deviceId) {
return Context.getIdentityManager().lookupAttributeBoolean(
- deviceId, getProtocolName() + ".hbm", hbm, true);
+ deviceId, getProtocolName() + ".hbm", hbm, false, true);
}
public void setIncludeAdc(boolean includeAdc) {
@@ -68,7 +68,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
public boolean isIncludeAdc(long deviceId) {
return Context.getIdentityManager().lookupAttributeBoolean(
- deviceId, getProtocolName() + ".includeAdc", includeAdc, true);
+ deviceId, getProtocolName() + ".includeAdc", includeAdc, false, true);
}
public void setIncludeRpm(boolean includeRpm) {
@@ -77,7 +77,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
public boolean isIncludeRpm(long deviceId) {
return Context.getIdentityManager().lookupAttributeBoolean(
- deviceId, getProtocolName() + ".includeRpm", includeRpm, true);
+ deviceId, getProtocolName() + ".includeRpm", includeRpm, false, true);
}
public void setIncludeTemp(boolean includeTemp) {
@@ -86,7 +86,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
public boolean isIncludeTemp(long deviceId) {
return Context.getIdentityManager().lookupAttributeBoolean(
- deviceId, getProtocolName() + ".includeTemp", includeTemp, true);
+ deviceId, getProtocolName() + ".includeTemp", includeTemp, false, true);
}
private Position decode9(
@@ -326,12 +326,40 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
case "UEX":
int remaining = Integer.parseInt(values[index++]);
while (remaining > 0) {
- String value = values[index++];
- String[] pair = value.split("=");
- if (pair.length >= 2) {
- position.set(pair[0].toLowerCase(), pair[1].trim());
+ String attribute = values[index++];
+ if (attribute.startsWith("CabAVL")) {
+ String[] data = attribute.split(",");
+ double fuel1 = Double.parseDouble(data[2]);
+ if (fuel1 > 0) {
+ position.set("fuel1", fuel1);
+ }
+ double fuel2 = Double.parseDouble(data[3]);
+ if (fuel2 > 0) {
+ position.set("fuel2", fuel2);
+ }
+ } else {
+ String[] pair = attribute.split("=");
+ if (pair.length >= 2) {
+ String value = pair[1].trim();
+ if (value.contains(".")) {
+ value = value.substring(0, value.indexOf('.'));
+ }
+ switch (pair[0].charAt(0)) {
+ case 't':
+ position.set(Position.PREFIX_TEMP + pair[0].charAt(2), Integer.parseInt(value, 16));
+ break;
+ case 'N':
+ position.set("fuel" + pair[0].charAt(2), Integer.parseInt(value, 16));
+ break;
+ case 'Q':
+ position.set("drivingQuality", Integer.parseInt(value, 16));
+ break;
+ default:
+ break;
+ }
+ }
}
- remaining -= value.length() + 1;
+ remaining -= attribute.length() + 1;
}
break;
default:
@@ -393,7 +421,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
String type = values[index++];
- if (!type.equals("STT")) {
+ if (!type.equals("STT") && !type.equals("ALT")) {
return null;
}
diff --git a/src/main/java/org/traccar/protocol/SuntechProtocolEncoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolEncoder.java
index 90fa4aa39..6dae42ad5 100644
--- a/src/main/java/org/traccar/protocol/SuntechProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocolEncoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2016 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,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class SuntechProtocolEncoder extends StringProtocolEncoder {
+ public SuntechProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/SviasProtocol.java b/src/main/java/org/traccar/protocol/SviasProtocol.java
index f01f28389..accfa173f 100644
--- a/src/main/java/org/traccar/protocol/SviasProtocol.java
+++ b/src/main/java/org/traccar/protocol/SviasProtocol.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.
@@ -42,7 +42,7 @@ public class SviasProtocol extends BaseProtocol {
pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, "]"));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new SviasProtocolEncoder());
+ pipeline.addLast(new SviasProtocolEncoder(SviasProtocol.this));
pipeline.addLast(new SviasProtocolDecoder(SviasProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/SviasProtocolEncoder.java b/src/main/java/org/traccar/protocol/SviasProtocolEncoder.java
index 8bfbef119..2607d7bd1 100644
--- a/src/main/java/org/traccar/protocol/SviasProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/SviasProtocolEncoder.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");
@@ -18,9 +18,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class SviasProtocolEncoder extends StringProtocolEncoder {
+ public SviasProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
switch (command.getType()) {
diff --git a/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java b/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java
index ba231a635..b75addfae 100644
--- a/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java
@@ -96,6 +96,19 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
.any()
.compile();
+ private static final Pattern PATTERN_GPIOP = new PatternBuilder()
+ .text("$GPIOP,")
+ .number("[01]{8},") // inputs
+ .number("[01]{8},") // outputs
+ .number("d+.d+,") // adc 1
+ .number("d+.d+,") // adc 2
+ .number("d+.d+,") // adc 3
+ .number("d+.d+,") // adc 4
+ .number("(d+.d+),") // power
+ .number("(d+.d+)") // battery
+ .any()
+ .compile();
+
private Position position = null;
private Position decodeGprmc(
@@ -103,7 +116,7 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
if (deviceSession != null && channel != null && !(channel instanceof DatagramChannel)
&& Context.getIdentityManager().lookupAttributeBoolean(
- deviceSession.getDeviceId(), getProtocolName() + ".ack", false, true)) {
+ deviceSession.getDeviceId(), getProtocolName() + ".ack", false, false, true)) {
channel.writeAndFlush(new NetworkMessage("OK1\r\n", remoteAddress));
}
@@ -225,6 +238,24 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private Position decodeGpiop(DeviceSession deviceSession, String sentence) {
+
+ Parser parser = new Parser(PATTERN_GPIOP, sentence);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
+
+ position.set(Position.KEY_POWER, parser.nextDouble());
+ position.set(Position.KEY_BATTERY, parser.nextDouble());
+
+ return position;
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -275,6 +306,8 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
return decodeGprma(deviceSession, sentence);
} else if (sentence.startsWith("$TRCCR") && deviceSession != null) {
return decodeTrccr(deviceSession, sentence);
+ } else if (sentence.startsWith("$GPIOP")) {
+ return decodeGpiop(deviceSession, sentence);
}
return null;
diff --git a/src/main/java/org/traccar/protocol/T800xProtocol.java b/src/main/java/org/traccar/protocol/T800xProtocol.java
index 85749d0cf..8b91265cb 100644
--- a/src/main/java/org/traccar/protocol/T800xProtocol.java
+++ b/src/main/java/org/traccar/protocol/T800xProtocol.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.
@@ -30,7 +30,7 @@ public class T800xProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 3, 2, -5, 0));
- pipeline.addLast(new T800xProtocolEncoder());
+ pipeline.addLast(new T800xProtocolEncoder(T800xProtocol.this));
pipeline.addLast(new T800xProtocolDecoder(T800xProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java b/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java
index 96fb7f96a..9b146ec90 100644
--- a/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java
@@ -31,19 +31,30 @@ import org.traccar.model.CellTower;
import org.traccar.model.Network;
import org.traccar.model.Position;
+import java.math.BigInteger;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
+import java.util.Date;
public class T800xProtocolDecoder extends BaseProtocolDecoder {
+ private short header = DEFAULT_HEADER;
+
+ public short getHeader() {
+ return header;
+ }
+
public T800xProtocolDecoder(Protocol protocol) {
super(protocol);
}
+ public static final short DEFAULT_HEADER = 0x2323;
+
public static final int MSG_LOGIN = 0x01;
public static final int MSG_GPS = 0x02;
public static final int MSG_HEARTBEAT = 0x03;
public static final int MSG_ALARM = 0x04;
+ public static final int MSG_NETWORK = 0x05;
public static final int MSG_COMMAND = 0x81;
private void sendResponse(Channel channel, short header, int type, int index, ByteBuf imei, int alarm) {
@@ -91,13 +102,24 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
}
}
+ private Date readDate(ByteBuf buf) {
+ return new DateBuilder()
+ .setYear(BcdUtil.readInteger(buf, 2))
+ .setMonth(BcdUtil.readInteger(buf, 2))
+ .setDay(BcdUtil.readInteger(buf, 2))
+ .setHour(BcdUtil.readInteger(buf, 2))
+ .setMinute(BcdUtil.readInteger(buf, 2))
+ .setSecond(BcdUtil.readInteger(buf, 2))
+ .getDate();
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
- short header = buf.readShort();
+ header = buf.readShort();
int type = buf.readUnsignedByte();
buf.readUnsignedShort(); // length
int index = buf.readUnsignedShort();
@@ -109,9 +131,32 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
return null;
}
+ if (type != MSG_GPS && type != MSG_ALARM) {
+ sendResponse(channel, header, type, index, imei, 0);
+ }
+
if (type == MSG_GPS || type == MSG_ALARM) {
- return decodePosition(channel, deviceSession, buf, header, type, index, imei);
+ return decodePosition(channel, deviceSession, buf, type, index, imei);
+
+ } else if (type == MSG_NETWORK) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, readDate(buf));
+
+ position.set(Position.KEY_OPERATOR, buf.readCharSequence(
+ buf.readUnsignedByte(), StandardCharsets.UTF_16LE).toString());
+ position.set("networkTechnology", buf.readCharSequence(
+ buf.readUnsignedByte(), StandardCharsets.US_ASCII).toString());
+ position.set("networkBand", buf.readCharSequence(
+ buf.readUnsignedByte(), StandardCharsets.US_ASCII).toString());
+ buf.readCharSequence(buf.readUnsignedByte(), StandardCharsets.US_ASCII); // imsi
+ position.set(Position.KEY_ICCID, buf.readCharSequence(
+ buf.readUnsignedByte(), StandardCharsets.US_ASCII).toString());
+
+ return position;
} else if (type == MSG_COMMAND) {
@@ -124,77 +169,77 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_RESULT, buf.toString(StandardCharsets.UTF_16LE));
- sendResponse(channel, header, type, index, imei, 0);
-
return position;
}
- sendResponse(channel, header, type, index, imei, 0);
-
return null;
}
private Position decodePosition(
Channel channel, DeviceSession deviceSession,
- ByteBuf buf, short header, int type, int index, ByteBuf imei) {
+ ByteBuf buf, int type, int index, ByteBuf imei) {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
position.set(Position.KEY_INDEX, index);
- buf.readUnsignedShort(); // acc on interval
- buf.readUnsignedShort(); // acc off interval
- buf.readUnsignedByte(); // angle compensation
- buf.readUnsignedShort(); // distance compensation
+ if (header != 0x2727) {
+
+ buf.readUnsignedShort(); // acc on interval
+ buf.readUnsignedShort(); // acc off interval
+ buf.readUnsignedByte(); // angle compensation
+ buf.readUnsignedShort(); // distance compensation
- position.set(Position.KEY_RSSI, BitUtil.to(buf.readUnsignedShort(), 7));
+ position.set(Position.KEY_RSSI, BitUtil.to(buf.readUnsignedShort(), 7));
+
+ }
int status = buf.readUnsignedByte();
position.set(Position.KEY_SATELLITES, BitUtil.to(status, 5));
- buf.readUnsignedByte(); // gsensor manager status
- buf.readUnsignedByte(); // other flags
- buf.readUnsignedByte(); // heartbeat
- buf.readUnsignedByte(); // relay status
- buf.readUnsignedShort(); // drag alarm setting
-
- int io = buf.readUnsignedShort();
- position.set(Position.KEY_IGNITION, BitUtil.check(io, 14));
- position.set("ac", BitUtil.check(io, 13));
- for (int i = 0; i <= 2; i++) {
- position.set(Position.PREFIX_OUT + (i + 1), BitUtil.check(io, 7 + i));
- }
+ if (header != 0x2727) {
- position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort());
- position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShort());
+ buf.readUnsignedByte(); // gsensor manager status
+ buf.readUnsignedByte(); // other flags
+ buf.readUnsignedByte(); // heartbeat
+ buf.readUnsignedByte(); // relay status
+ buf.readUnsignedShort(); // drag alarm setting
+
+ int io = buf.readUnsignedShort();
+ position.set(Position.KEY_IGNITION, BitUtil.check(io, 14));
+ position.set("ac", BitUtil.check(io, 13));
+ for (int i = 0; i <= 2; i++) {
+ position.set(Position.PREFIX_OUT + (i + 1), BitUtil.check(io, 7 + i));
+ }
+
+ position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort());
+ position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShort());
+
+ }
int alarm = buf.readUnsignedByte();
position.set(Position.KEY_ALARM, decodeAlarm(alarm));
- buf.readUnsignedByte(); // reserved
+ if (header != 0x2727) {
- position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+ buf.readUnsignedByte(); // reserved
- int battery = BcdUtil.readInteger(buf, 2);
- if (battery == 0) {
- battery = 100;
- }
- position.set(Position.KEY_BATTERY, battery);
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
- DateBuilder dateBuilder = new DateBuilder()
- .setYear(BcdUtil.readInteger(buf, 2))
- .setMonth(BcdUtil.readInteger(buf, 2))
- .setDay(BcdUtil.readInteger(buf, 2))
- .setHour(BcdUtil.readInteger(buf, 2))
- .setMinute(BcdUtil.readInteger(buf, 2))
- .setSecond(BcdUtil.readInteger(buf, 2));
+ int battery = BcdUtil.readInteger(buf, 2);
+ if (battery == 0) {
+ battery = 100;
+ }
+ position.set(Position.KEY_BATTERY, battery);
+
+ }
if (BitUtil.check(status, 6)) {
position.setValid(!BitUtil.check(status, 7));
- position.setTime(dateBuilder.getDate());
+ position.setTime(readDate(buf));
position.setAltitude(buf.readFloatLE());
position.setLongitude(buf.readFloatLE());
position.setLatitude(buf.readFloatLE());
@@ -203,7 +248,7 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
} else {
- getLastLocation(position, dateBuilder.getDate());
+ getLastLocation(position, readDate(buf));
int mcc = buf.readUnsignedShortLE();
int mnc = buf.readUnsignedShortLE();
@@ -219,8 +264,46 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
}
- if (buf.readableBytes() >= 2) {
+ if (header == 0x2727) {
+
+ byte[] accelerationBytes = new byte[5];
+ buf.readBytes(accelerationBytes);
+ long acceleration = new BigInteger(accelerationBytes).longValue();
+ double accelerationZ = BitUtil.between(acceleration, 8, 15) + BitUtil.between(acceleration, 4, 8) * 0.1;
+ if (!BitUtil.check(acceleration, 15)) {
+ accelerationZ = -accelerationZ;
+ }
+ double accelerationY = BitUtil.between(acceleration, 20, 27) + BitUtil.between(acceleration, 16, 20) * 0.1;
+ if (!BitUtil.check(acceleration, 27)) {
+ accelerationY = -accelerationY;
+ }
+ double accelerationX = BitUtil.between(acceleration, 28, 32) + BitUtil.between(acceleration, 32, 39) * 0.1;
+ if (!BitUtil.check(acceleration, 39)) {
+ accelerationX = -accelerationX;
+ }
+ position.set(Position.KEY_G_SENSOR, "[" + accelerationX + "," + accelerationY + "," + accelerationZ + "]");
+
+ position.set(Position.KEY_BATTERY_LEVEL, BcdUtil.readInteger(buf, 2));
+ position.set(Position.KEY_DEVICE_TEMP, (int) buf.readByte());
+ position.set("lightSensor", BcdUtil.readInteger(buf, 2) * 0.1);
+ position.set(Position.KEY_BATTERY, BcdUtil.readInteger(buf, 2) * 0.1);
+ position.set("solarPanel", BcdUtil.readInteger(buf, 2) * 0.1);
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+
+ int inputStatus = buf.readUnsignedShort();
+ position.set(Position.KEY_IGNITION, BitUtil.check(inputStatus, 2));
+ position.set(Position.KEY_RSSI, BitUtil.between(inputStatus, 4, 11));
+
+ buf.readUnsignedShort(); // ignition on upload interval
+ buf.readUnsignedInt(); // ignition off upload interval
+ buf.readUnsignedByte(); // angle upload interval
+ buf.readUnsignedShort(); // distance upload interval
+ buf.readUnsignedByte(); // heartbeat
+
+ } else if (buf.readableBytes() >= 2) {
+
position.set(Position.KEY_POWER, BcdUtil.readInteger(buf, 4) * 0.01);
+
}
sendResponse(channel, header, type, index, imei, alarm);
diff --git a/src/main/java/org/traccar/protocol/T800xProtocolEncoder.java b/src/main/java/org/traccar/protocol/T800xProtocolEncoder.java
index 34f30b147..74587c8b1 100644
--- a/src/main/java/org/traccar/protocol/T800xProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/T800xProtocolEncoder.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,9 +17,11 @@ package org.traccar.protocol;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.DataConverter;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
@@ -29,12 +31,15 @@ public class T800xProtocolEncoder extends BaseProtocolEncoder {
public static final int MODE_BROADCAST = 0x02;
public static final int MODE_FORWARD = 0x03;
- private ByteBuf encodeContent(Command command, String content) {
+ public T800xProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private ByteBuf encodeContent(Command command, short header, String content) {
ByteBuf buf = Unpooled.buffer();
- buf.writeByte('%');
- buf.writeByte('%');
+ buf.writeShort(header);
buf.writeByte(T800xProtocolDecoder.MSG_COMMAND);
buf.writeShort(7 + 8 + 1 + content.length());
buf.writeShort(1); // serial number
@@ -46,11 +51,16 @@ public class T800xProtocolEncoder extends BaseProtocolEncoder {
}
@Override
- protected Object encodeCommand(Command command) {
+ protected Object encodeCommand(Channel channel, Command command) {
+
+ short header = T800xProtocolDecoder.DEFAULT_HEADER;
+ if (channel != null) {
+ header = channel.pipeline().get(T800xProtocolDecoder.class).getHeader();
+ }
switch (command.getType()) {
case Command.TYPE_CUSTOM:
- return encodeContent(command, command.getString(Command.KEY_DATA));
+ return encodeContent(command, header, command.getString(Command.KEY_DATA));
default:
return null;
}
diff --git a/src/main/java/org/traccar/protocol/TechTltProtocol.java b/src/main/java/org/traccar/protocol/TechTltProtocol.java
index 69a12532c..0cffb452d 100644
--- a/src/main/java/org/traccar/protocol/TechTltProtocol.java
+++ b/src/main/java/org/traccar/protocol/TechTltProtocol.java
@@ -29,7 +29,7 @@ public class TechTltProtocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new Ardi01ProtocolDecoder(TechTltProtocol.this));
+ pipeline.addLast(new TechTltProtocolDecoder(TechTltProtocol.this));
}
});
}
diff --git a/src/main/java/org/traccar/protocol/TechTltProtocolDecoder.java b/src/main/java/org/traccar/protocol/TechTltProtocolDecoder.java
index bad289060..17f5c80fa 100644
--- a/src/main/java/org/traccar/protocol/TechTltProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TechTltProtocolDecoder.java
@@ -35,6 +35,15 @@ public class TechTltProtocolDecoder extends BaseProtocolDecoder {
super(protocol);
}
+ private static final Pattern PATTERN_STATUS = new PatternBuilder()
+ .number("(d+),") // id
+ .text("INFOGPRS,")
+ .number("V Bat=(d+.d),") // battery
+ .number("TEMP=(d+),") // temperature
+ .expression("[^,]*,")
+ .number("(d+)") // rssi
+ .compile();
+
private static final Pattern PATTERN_POSITION = new PatternBuilder()
.number("(d+)") // id
.text("*POS=Y,")
@@ -52,11 +61,33 @@ public class TechTltProtocolDecoder extends BaseProtocolDecoder {
.number("(d+)") // cid
.compile();
- @Override
- protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+ private Position decodeStatus(Channel channel, SocketAddress remoteAddress, String sentence) {
- Parser parser = new Parser(PATTERN_POSITION, (String) msg);
+ Parser parser = new Parser(PATTERN_STATUS, sentence);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
+
+ position.set(Position.KEY_BATTERY, parser.nextDouble());
+ position.set(Position.KEY_DEVICE_TEMP, parser.nextInt());
+ position.set(Position.KEY_RSSI, parser.nextInt());
+
+ return position;
+ }
+
+ private Position decodeLocation(Channel channel, SocketAddress remoteAddress, String sentence) {
+
+ Parser parser = new Parser(PATTERN_POSITION, sentence);
if (!parser.matches()) {
return null;
}
@@ -84,4 +115,18 @@ public class TechTltProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ String sentence = ((String) msg).trim();
+ if (sentence.contains("INFO")) {
+ return decodeStatus(channel, remoteAddress, sentence);
+ } else if (sentence.contains("POS")) {
+ return decodeLocation(channel, remoteAddress, sentence);
+ } else {
+ return null;
+ }
+ }
+
}
diff --git a/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java b/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java
index 6d5e8f21e..457687b2e 100644
--- a/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2014 - 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.
@@ -42,8 +42,8 @@ public class TelicProtocolDecoder extends BaseProtocolDecoder {
.number("(dd)(dd)(dd)") // date (ddmmyy)
.number("(dd)(dd)(dd),") // time (hhmmss)
.groupBegin()
- .number("(ddd)(dd)(dddd),") // longitude
- .number("(dd)(dd)(dddd),") // latitude
+ .number("(-?d{9}),") // longitude
+ .number("(-?d{8}),") // latitude
.or()
.number("(-?d+),") // longitude
.number("(-?d+),") // latitude
@@ -88,17 +88,16 @@ public class TelicProtocolDecoder extends BaseProtocolDecoder {
return null;
}
- Position position = new Position(getProtocolName());
-
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
if (deviceSession == null) {
return null;
}
+
+ Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
- int event = parser.nextInt(0);
+ int event = parser.nextInt();
position.set(Position.KEY_EVENT, event);
-
position.set(Position.KEY_ALARM, decodeAlarm(event));
if (event == 11) {
@@ -109,25 +108,22 @@ public class TelicProtocolDecoder extends BaseProtocolDecoder {
position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
- if (parser.hasNext(6)) {
- position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_MIN_MIN));
- position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_MIN_MIN));
+ if (parser.hasNext(2)) {
+ position.setLongitude(parser.nextDouble() / 1000000);
+ position.setLatitude(parser.nextDouble() / 1000000);
}
if (parser.hasNext(2)) {
- position.setLongitude(parser.nextDouble(0) / 10000);
- position.setLatitude(parser.nextDouble(0) / 10000);
+ position.setLongitude(parser.nextDouble() / 10000);
+ position.setLatitude(parser.nextDouble() / 10000);
}
- position.setValid(parser.nextInt(0) != 1);
- position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0)));
- position.setCourse(parser.nextDouble(0));
-
- if (parser.hasNext()) {
- position.set(Position.KEY_SATELLITES, parser.nextInt(0));
- }
+ position.setValid(parser.nextInt() != 1);
+ position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble()));
+ position.setCourse(parser.nextDouble());
- position.set(Position.KEY_BATTERY, parser.nextInt(0));
+ position.set(Position.KEY_SATELLITES, parser.nextInt());
+ position.set(Position.KEY_BATTERY, parser.nextInt());
return position;
}
diff --git a/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java b/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java
index 4d4d79d8d..c30fee6e3 100644
--- a/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 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.
@@ -29,12 +29,14 @@ public class TeltonikaFrameDecoder extends BaseFrameDecoder {
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception {
- // Check minimum length
+ while (buf.isReadable() && buf.getByte(buf.readerIndex()) == (byte) 0xff) {
+ buf.skipBytes(1);
+ }
+
if (buf.readableBytes() < MESSAGE_MINIMUM_LENGTH) {
return null;
}
- // Read packet
int length = buf.getUnsignedShort(buf.readerIndex());
if (length > 0) {
if (buf.readableBytes() >= (length + 2)) {
diff --git a/src/main/java/org/traccar/protocol/TeltonikaProtocol.java b/src/main/java/org/traccar/protocol/TeltonikaProtocol.java
index eef9662d7..5817b86be 100644
--- a/src/main/java/org/traccar/protocol/TeltonikaProtocol.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaProtocol.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.
@@ -29,14 +29,14 @@ public class TeltonikaProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new TeltonikaFrameDecoder());
- pipeline.addLast(new TeltonikaProtocolEncoder());
+ pipeline.addLast(new TeltonikaProtocolEncoder(TeltonikaProtocol.this));
pipeline.addLast(new TeltonikaProtocolDecoder(TeltonikaProtocol.this, false));
}
});
addServer(new TrackerServer(true, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new TeltonikaProtocolEncoder());
+ pipeline.addLast(new TeltonikaProtocolEncoder(TeltonikaProtocol.this));
pipeline.addLast(new TeltonikaProtocolDecoder(TeltonikaProtocol.this, true));
}
});
diff --git a/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java
index 485df833a..c634d2438 100644
--- a/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java
@@ -157,7 +157,19 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
}
if (readable) {
- position.set(Position.KEY_RESULT, buf.readSlice(length).toString(StandardCharsets.US_ASCII));
+ String data = buf.readSlice(length).toString(StandardCharsets.US_ASCII).trim();
+ if (data.startsWith("UUUUww") && data.endsWith("SSS")) {
+ String[] values = data.substring(6, data.length() - 4).split(";");
+ for (int i = 0; i < 8; i++) {
+ position.set("axle" + (i + 1), Double.parseDouble(values[i]));
+ }
+ position.set("loadTruck", Double.parseDouble(values[8]));
+ position.set("loadTrailer", Double.parseDouble(values[9]));
+ position.set("totalTruck", Double.parseDouble(values[10]));
+ position.set("totalTrailer", Double.parseDouble(values[11]));
+ } else {
+ position.set(Position.KEY_RESULT, data);
+ }
} else {
position.set(Position.KEY_RESULT, ByteBufUtil.hexDump(buf.readSlice(length)));
}
diff --git a/src/main/java/org/traccar/protocol/TeltonikaProtocolEncoder.java b/src/main/java/org/traccar/protocol/TeltonikaProtocolEncoder.java
index 5380cf3a0..8a614618a 100644
--- a/src/main/java/org/traccar/protocol/TeltonikaProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaProtocolEncoder.java
@@ -19,6 +19,7 @@ import org.traccar.BaseProtocolEncoder;
import org.traccar.helper.Checksum;
import org.traccar.helper.DataConverter;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@@ -27,6 +28,10 @@ import java.nio.charset.StandardCharsets;
public class TeltonikaProtocolEncoder extends BaseProtocolEncoder {
+ public TeltonikaProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private ByteBuf encodeContent(byte[] content) {
ByteBuf buf = Unpooled.buffer();
diff --git a/src/main/java/org/traccar/protocol/Tk103Protocol.java b/src/main/java/org/traccar/protocol/Tk103Protocol.java
index fa83133e2..ff0bedfb7 100644
--- a/src/main/java/org/traccar/protocol/Tk103Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tk103Protocol.java
@@ -1,6 +1,6 @@
/*
* Copyright 2017 Christoph Krey (c@ckrey.de)
- * 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.
@@ -51,7 +51,7 @@ public class Tk103Protocol extends BaseProtocol {
pipeline.addLast(new Tk103FrameDecoder());
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new Tk103ProtocolEncoder());
+ pipeline.addLast(new Tk103ProtocolEncoder(Tk103Protocol.this));
pipeline.addLast(new Tk103ProtocolDecoder(Tk103Protocol.this));
}
});
@@ -60,7 +60,7 @@ public class Tk103Protocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new Tk103ProtocolEncoder());
+ pipeline.addLast(new Tk103ProtocolEncoder(Tk103Protocol.this));
pipeline.addLast(new Tk103ProtocolDecoder(Tk103Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/Tk103ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Tk103ProtocolEncoder.java
index 98edc8cb5..a8aa84105 100644
--- a/src/main/java/org/traccar/protocol/Tk103ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Tk103ProtocolEncoder.java
@@ -1,6 +1,6 @@
/*
* Copyright 2017 Christoph Krey (c@ckrey.de)
- * 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.
@@ -19,16 +19,19 @@ package org.traccar.protocol;
import org.traccar.Context;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class Tk103ProtocolEncoder extends StringProtocolEncoder {
private final boolean forceAlternative;
- public Tk103ProtocolEncoder() {
+ public Tk103ProtocolEncoder(Protocol protocol) {
+ super(protocol);
this.forceAlternative = false;
}
- public Tk103ProtocolEncoder(boolean forceAlternative) {
+ public Tk103ProtocolEncoder(Protocol protocol, boolean forceAlternative) {
+ super(protocol);
this.forceAlternative = forceAlternative;
}
@@ -40,7 +43,7 @@ public class Tk103ProtocolEncoder extends StringProtocolEncoder {
protected Object encodeCommand(Command command) {
boolean alternative = forceAlternative || Context.getIdentityManager().lookupAttributeBoolean(
- command.getDeviceId(), "tk103.alternative", false, true);
+ command.getDeviceId(), getProtocolName() + ".alternative", false, false, true);
initDevicePassword(command, "123456");
diff --git a/src/main/java/org/traccar/protocol/TotemProtocol.java b/src/main/java/org/traccar/protocol/TotemProtocol.java
index 66e1ec4f1..f8cda8358 100644
--- a/src/main/java/org/traccar/protocol/TotemProtocol.java
+++ b/src/main/java/org/traccar/protocol/TotemProtocol.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.
@@ -35,7 +35,7 @@ public class TotemProtocol extends BaseProtocol {
pipeline.addLast(new TotemFrameDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new TotemProtocolEncoder());
+ pipeline.addLast(new TotemProtocolEncoder(TotemProtocol.this));
pipeline.addLast(new TotemProtocolDecoder(TotemProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/TotemProtocolEncoder.java b/src/main/java/org/traccar/protocol/TotemProtocolEncoder.java
index b5049859d..3bbb92031 100644
--- a/src/main/java/org/traccar/protocol/TotemProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/TotemProtocolEncoder.java
@@ -1,6 +1,6 @@
/*
* Copyright 2015 Irving Gonzalez
- * Copyright 2015 - 2016 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.
@@ -18,9 +18,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class TotemProtocolEncoder extends StringProtocolEncoder {
+ public TotemProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java b/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java
index aaaaccb60..e4c94dc77 100644
--- a/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TramigoFrameDecoder.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,7 +36,7 @@ public class TramigoFrameDecoder extends BaseFrameDecoder {
length = buf.getUnsignedShort(buf.readerIndex() + 6);
}
- if (length >= buf.readableBytes()) {
+ if (length <= buf.readableBytes()) {
return buf.readRetainedSlice(length);
}
diff --git a/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java b/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java
index b63385187..05312b820 100644
--- a/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TrvProtocolDecoder.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.
@@ -42,7 +42,8 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder {
private static final Pattern PATTERN = new PatternBuilder()
.expression("[A-Z]{2,3}")
- .number("APdd")
+ .expression("[A-Z]P")
+ .number("dd")
.number("(dd)(dd)(dd)") // date (yymmdd)
.expression("([AV])") // validity
.number("(dd)(dd.d+)") // latitude
@@ -57,7 +58,8 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder {
.number("(ddd)") // battery
.number("(d)") // acc
.number("(dd)") // arm status
- .number("(dd),") // working mode
+ .number("(dd)") // working mode
+ .number("(?:[0-2]{3})?,")
.number("(d+),") // mcc
.number("(d+),") // mnc
.number("(d+),") // lac
@@ -181,7 +183,7 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder {
return position;
- } else if (type.equals("AP01") || type.equals("AP10")) {
+ } else if (type.equals("AP01") || type.equals("AP10") || type.equals("YP03")) {
Parser parser = new Parser(PATTERN, sentence);
if (!parser.matches()) {
diff --git a/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java b/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java
index 87b44a4b2..4f6854098 100644
--- a/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.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.
@@ -23,6 +23,7 @@ import org.traccar.DeviceSession;
import org.traccar.Protocol;
import org.traccar.helper.BitUtil;
import org.traccar.helper.DateBuilder;
+import org.traccar.helper.UnitsConverter;
import org.traccar.model.CellTower;
import org.traccar.model.Network;
import org.traccar.model.Position;
@@ -67,7 +68,17 @@ public class TzoneProtocolDecoder extends BaseProtocolDecoder {
return false;
}
- position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
+ if (hardware == 0x413) {
+ buf.readUnsignedByte(); // status
+ } else {
+ position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
+ }
+
+ if (hardware == 0x413) {
+ position.setFixTime(new DateBuilder()
+ .setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
+ .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()).getDate());
+ }
double lat;
double lon;
@@ -80,25 +91,39 @@ public class TzoneProtocolDecoder extends BaseProtocolDecoder {
lon = buf.readUnsignedInt() / 100000.0 / 60.0;
}
- position.setFixTime(new DateBuilder()
- .setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
- .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()).getDate());
+ if (hardware == 0x413) {
- position.setSpeed(buf.readUnsignedShort() * 0.01);
+ position.set(Position.KEY_HDOP, buf.readUnsignedShort() * 0.1);
- position.set(Position.KEY_ODOMETER, buf.readUnsignedMedium());
+ position.setAltitude(buf.readUnsignedShort());
+ position.setCourse(buf.readUnsignedShort());
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort() * 0.1));
+
+ position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
+
+ } else {
+
+ position.setFixTime(new DateBuilder()
+ .setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
+ .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()).getDate());
+
+ position.setSpeed(buf.readUnsignedShort() * 0.01);
+
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedMedium());
+
+ int flags = buf.readUnsignedShort();
+ position.setCourse(BitUtil.to(flags, 9));
+ if (!BitUtil.check(flags, 10)) {
+ lat = -lat;
+ }
+ position.setLatitude(lat);
+ if (BitUtil.check(flags, 9)) {
+ lon = -lon;
+ }
+ position.setLongitude(lon);
+ position.setValid(BitUtil.check(flags, 11));
- int flags = buf.readUnsignedShort();
- position.setCourse(BitUtil.to(flags, 9));
- if (!BitUtil.check(flags, 10)) {
- lat = -lat;
- }
- position.setLatitude(lat);
- if (BitUtil.check(flags, 9)) {
- lon = -lon;
}
- position.setLongitude(lon);
- position.setValid(BitUtil.check(flags, 11));
buf.readerIndex(blockEnd);
diff --git a/src/main/java/org/traccar/protocol/UlbotechProtocolDecoder.java b/src/main/java/org/traccar/protocol/UlbotechProtocolDecoder.java
index 0a2a59e23..7fec0bf8b 100644
--- a/src/main/java/org/traccar/protocol/UlbotechProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/UlbotechProtocolDecoder.java
@@ -237,12 +237,13 @@ public class UlbotechProtocolDecoder extends BaseProtocolDecoder {
case DATA_GPS:
hasLocation = true;
- position.setValid(true);
position.setLatitude(buf.readInt() / 1000000.0);
position.setLongitude(buf.readInt() / 1000000.0);
position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort()));
position.setCourse(buf.readUnsignedShort());
- position.set(Position.KEY_HDOP, buf.readUnsignedShort());
+ int hdop = buf.readUnsignedShort();
+ position.setValid(hdop < 9999);
+ position.set(Position.KEY_HDOP, hdop * 0.01);
break;
case DATA_LBS:
diff --git a/src/main/java/org/traccar/protocol/UproProtocolDecoder.java b/src/main/java/org/traccar/protocol/UproProtocolDecoder.java
index dc7a9200d..873b22006 100644
--- a/src/main/java/org/traccar/protocol/UproProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/UproProtocolDecoder.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.
@@ -89,6 +89,13 @@ public class UproProtocolDecoder extends BaseProtocolDecoder {
}
}
+ private String decodeAlarm(int alarm) {
+ if (BitUtil.check(alarm, 2)) {
+ return Position.ALARM_TAMPERING;
+ }
+ return null;
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -160,9 +167,25 @@ public class UproProtocolDecoder extends BaseProtocolDecoder {
position.setSpeed(
Integer.parseInt(data.readSlice(4).toString(StandardCharsets.US_ASCII)) * 0.1);
break;
+ case 'G':
+ position.setAltitude(
+ Integer.parseInt(data.readSlice(6).toString(StandardCharsets.US_ASCII)) * 0.1);
+ break;
case 'K':
position.set("statusExtended", data.toString(StandardCharsets.US_ASCII));
break;
+ case 'M':
+ position.set(Position.KEY_BATTERY_LEVEL,
+ Integer.parseInt(data.readSlice(3).toString(StandardCharsets.US_ASCII)) * 0.1);
+ break;
+ case 'N':
+ position.set(Position.KEY_RSSI,
+ Integer.parseInt(data.readSlice(2).toString(StandardCharsets.US_ASCII)));
+ break;
+ case 'O':
+ position.set(Position.KEY_SATELLITES,
+ Integer.parseInt(data.readSlice(2).toString(StandardCharsets.US_ASCII)));
+ break;
case 'P':
if (data.readableBytes() >= 16) {
position.setNetwork(new Network(CellTower.from(
@@ -188,25 +211,53 @@ public class UproProtocolDecoder extends BaseProtocolDecoder {
case 'S':
position.set("obdTraffic", ByteBufUtil.hexDump(data));
break;
- case 'T':
- position.set(Position.KEY_BATTERY_LEVEL,
- Integer.parseInt(data.readSlice(2).toString(StandardCharsets.US_ASCII)));
- break;
case 'V':
position.set(Position.KEY_POWER,
Integer.parseInt(data.readSlice(4).toString(StandardCharsets.US_ASCII)) * 0.1);
break;
+ case 'W':
+ position.set(Position.KEY_ALARM,
+ decodeAlarm(Integer.parseInt(data.readSlice(2).toString(StandardCharsets.US_ASCII))));
+ break;
+ case 'X':
+ Network network = new Network();
+ int mcc = 0, mnc = 0;
+ String[] cells = data.toString(StandardCharsets.US_ASCII).split(";");
+ if (!cells[0].startsWith("(")) {
+ for (int i = 0; i < cells.length; i++) {
+ String[] values = cells[i].split(",");
+ int index = 0;
+ if (i == 0) {
+ mcc = Integer.parseInt(values[index++]);
+ mnc = Integer.parseInt(values[index++]);
+ }
+ network.addCellTower(CellTower.from(
+ mcc, mnc,
+ Integer.parseInt(values[index++]),
+ Integer.parseInt(values[index++]),
+ Integer.parseInt(values[index])));
+ }
+ position.setNetwork(network);
+ }
+ break;
+ case 'Y':
+ position.set(Position.KEY_POWER,
+ Integer.parseInt(data.readSlice(5).toString(StandardCharsets.US_ASCII)) * 0.001);
+ break;
default:
break;
}
}
- if (position.getLatitude() != 0 && position.getLongitude() != 0) {
- return position;
+ if (position.getLatitude() == 0 || position.getLongitude() == 0) {
+ if (position.getAttributes().isEmpty()) {
+ return null;
+ }
+ getLastLocation(position, position.getDeviceTime());
}
- return null;
+ return position;
}
}
diff --git a/src/main/java/org/traccar/protocol/WatchProtocol.java b/src/main/java/org/traccar/protocol/WatchProtocol.java
index fe285e70d..6dc3bf9fb 100644
--- a/src/main/java/org/traccar/protocol/WatchProtocol.java
+++ b/src/main/java/org/traccar/protocol/WatchProtocol.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.
@@ -44,7 +44,7 @@ public class WatchProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new WatchFrameDecoder());
- pipeline.addLast(new WatchProtocolEncoder());
+ pipeline.addLast(new WatchProtocolEncoder(WatchProtocol.this));
pipeline.addLast(new WatchProtocolDecoder(WatchProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java b/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java
index 70b207e9b..0647afdee 100644
--- a/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java
@@ -249,8 +249,7 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder {
}
}
- } else if (type.equals("UD") || type.equals("UD2") || type.equals("UD3")
- || type.equals("AL") || type.equals("WT")) {
+ } else if (type.startsWith("UD") || type.equals("AL") || type.equals("WT")) {
Position position = decodePosition(deviceSession, buf.toString(StandardCharsets.US_ASCII));
@@ -267,7 +266,10 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder {
sendResponse(channel, id, index, "TKQ");
- } else if (type.equals("PULSE") || type.equals("heart") || type.equals("bphrt")) {
+ } else if (type.equalsIgnoreCase("PULSE")
+ || type.equalsIgnoreCase("HEART")
+ || type.equalsIgnoreCase("BLOOD")
+ || type.equalsIgnoreCase("BPHRT")) {
if (buf.isReadable()) {
@@ -279,11 +281,14 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder {
String[] values = buf.toString(StandardCharsets.US_ASCII).split(",");
int valueIndex = 0;
- if (type.equals("bphrt")) {
+ if (type.equalsIgnoreCase("BPHRT") || type.equalsIgnoreCase("BLOOD")) {
position.set("pressureHigh", values[valueIndex++]);
position.set("pressureLow", values[valueIndex++]);
}
- position.set(Position.KEY_HEART_RATE, Integer.parseInt(values[valueIndex]));
+
+ if (valueIndex <= values.length - 1) {
+ position.set(Position.KEY_HEART_RATE, Integer.parseInt(values[valueIndex]));
+ }
return position;
diff --git a/src/main/java/org/traccar/protocol/WatchProtocolEncoder.java b/src/main/java/org/traccar/protocol/WatchProtocolEncoder.java
index 264aec81f..b433dfd2a 100644
--- a/src/main/java/org/traccar/protocol/WatchProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/WatchProtocolEncoder.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.
@@ -21,6 +21,7 @@ import io.netty.channel.Channel;
import org.traccar.StringProtocolEncoder;
import org.traccar.helper.DataConverter;
import org.traccar.model.Command;
+import org.traccar.Protocol;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
@@ -32,6 +33,10 @@ import java.util.TimeZone;
public class WatchProtocolEncoder extends StringProtocolEncoder implements StringProtocolEncoder.ValueFormatter {
+ public WatchProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
public String formatValue(String key, Object value) {
if (key.equals(Command.KEY_TIMEZONE)) {
diff --git a/src/main/java/org/traccar/protocol/WialonProtocol.java b/src/main/java/org/traccar/protocol/WialonProtocol.java
index 06b54dceb..fd183dd2c 100644
--- a/src/main/java/org/traccar/protocol/WialonProtocol.java
+++ b/src/main/java/org/traccar/protocol/WialonProtocol.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.
@@ -38,14 +38,31 @@ public class WialonProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new LineBasedFrameDecoder(4 * 1024));
- pipeline.addLast(new StringEncoder());
boolean utf8 = Context.getConfig().getBoolean(getName() + ".utf8");
if (utf8) {
+ pipeline.addLast(new StringEncoder(StandardCharsets.UTF_8));
pipeline.addLast(new StringDecoder(StandardCharsets.UTF_8));
} else {
+ pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
}
- pipeline.addLast(new WialonProtocolEncoder());
+ pipeline.addLast(new WialonProtocolEncoder(WialonProtocol.this));
+ pipeline.addLast(new WialonProtocolDecoder(WialonProtocol.this));
+ }
+ });
+ addServer(new TrackerServer(true, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new LineBasedFrameDecoder(4 * 1024));
+ boolean utf8 = Context.getConfig().getBoolean(getName() + ".utf8");
+ if (utf8) {
+ pipeline.addLast(new StringEncoder(StandardCharsets.UTF_8));
+ pipeline.addLast(new StringDecoder(StandardCharsets.UTF_8));
+ } else {
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ }
+ pipeline.addLast(new WialonProtocolEncoder(WialonProtocol.this));
pipeline.addLast(new WialonProtocolDecoder(WialonProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java b/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java
index 42ff3177e..8488ca2d1 100644
--- a/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java
@@ -38,6 +38,14 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
super(protocol);
}
+ private static final Pattern PATTERN_ANY = new PatternBuilder()
+ .expression("([^#]*)?") // imei
+ .text("#") // start byte
+ .expression("([^#]+)") // type
+ .text("#") // separator
+ .expression("(.*)") // message
+ .compile();
+
private static final Pattern PATTERN = new PatternBuilder()
.number("(dd)(dd)(dd);") // date (ddmmyy)
.number("(dd)(dd)(dd);") // time (hhmmss)
@@ -62,7 +70,8 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
private void sendResponse(Channel channel, SocketAddress remoteAddress, String type, Integer number) {
if (channel != null) {
StringBuilder response = new StringBuilder("#A");
- response.append(type.substring(1));
+ response.append(type);
+ response.append("#");
if (number != null) {
response.append(number);
}
@@ -71,9 +80,9 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
}
}
- private Position decodePosition(Channel channel, SocketAddress remoteAddress, String substring) {
+ private Position decodePosition(Channel channel, SocketAddress remoteAddress, String id, String substring) {
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id);
if (deviceSession == null) {
return null;
}
@@ -135,12 +144,20 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
String sentence = (String) msg;
- String type = sentence.substring(0, sentence.indexOf('#', 1) + 1);
+
+ Parser parser = new Parser(PATTERN_ANY, sentence);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ String id = parser.next();
+ String type = parser.next();
+ String data = parser.next();
switch (type) {
- case "#L#":
- String[] values = sentence.substring(3).split(";");
+ case "L":
+ String[] values = data.split(";");
String imei = values[0].indexOf('.') >= 0 ? values[1] : values[0];
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei);
@@ -149,14 +166,14 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
}
break;
- case "#P#":
+ case "P":
sendResponse(channel, remoteAddress, type, null); // heartbeat
break;
- case "#D#":
- case "#SD#":
+ case "D":
+ case "SD":
Position position = decodePosition(
- channel, remoteAddress, sentence.substring(sentence.indexOf('#', 1) + 1));
+ channel, remoteAddress, id, data);
if (position != null) {
sendResponse(channel, remoteAddress, type, 1);
@@ -164,12 +181,12 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
}
break;
- case "#B#":
- String[] messages = sentence.substring(sentence.indexOf('#', 1) + 1).split("\\|");
+ case "B":
+ String[] messages = data.split("\\|");
List<Position> positions = new LinkedList<>();
for (String message : messages) {
- position = decodePosition(channel, remoteAddress, message);
+ position = decodePosition(channel, remoteAddress, id, message);
if (position != null) {
position.set(Position.KEY_ARCHIVE, true);
positions.add(position);
@@ -182,14 +199,14 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
}
break;
- case "#M#":
- deviceSession = getDeviceSession(channel, remoteAddress);
+ case "M":
+ deviceSession = getDeviceSession(channel, remoteAddress, id);
if (deviceSession != null) {
position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
getLastLocation(position, new Date());
position.setValid(false);
- position.set(Position.KEY_RESULT, sentence.substring(sentence.indexOf('#', 1) + 1));
+ position.set(Position.KEY_RESULT, data);
sendResponse(channel, remoteAddress, type, 1);
return position;
}
diff --git a/src/main/java/org/traccar/protocol/WialonProtocolEncoder.java b/src/main/java/org/traccar/protocol/WialonProtocolEncoder.java
index 9ff1631eb..c45edf00d 100644
--- a/src/main/java/org/traccar/protocol/WialonProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/WialonProtocolEncoder.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");
@@ -18,9 +18,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class WialonProtocolEncoder extends StringProtocolEncoder {
+ public WialonProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
switch (command.getType()) {
diff --git a/src/main/java/org/traccar/protocol/WondexProtocol.java b/src/main/java/org/traccar/protocol/WondexProtocol.java
index 8c6283d66..035dd9160 100644
--- a/src/main/java/org/traccar/protocol/WondexProtocol.java
+++ b/src/main/java/org/traccar/protocol/WondexProtocol.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.
@@ -25,7 +25,6 @@ import io.netty.handler.codec.string.StringEncoder;
public class WondexProtocol extends BaseProtocol {
public WondexProtocol() {
- setTextCommandEncoder(new WondexProtocolEncoder());
setSupportedCommands(
Command.TYPE_GET_DEVICE_STATUS,
Command.TYPE_GET_MODEM_STATUS,
@@ -33,12 +32,13 @@ public class WondexProtocol extends BaseProtocol {
Command.TYPE_POSITION_SINGLE,
Command.TYPE_GET_VERSION,
Command.TYPE_IDENTIFICATION);
+ setTextCommandEncoder(new WondexProtocolEncoder(this));
addServer(new TrackerServer(false, getName()) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new WondexFrameDecoder());
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new WondexProtocolEncoder());
+ pipeline.addLast(new WondexProtocolEncoder(WondexProtocol.this));
pipeline.addLast(new WondexProtocolDecoder(WondexProtocol.this));
}
});
@@ -46,7 +46,7 @@ public class WondexProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new StringEncoder());
- pipeline.addLast(new WondexProtocolEncoder());
+ pipeline.addLast(new WondexProtocolEncoder(WondexProtocol.this));
pipeline.addLast(new WondexProtocolDecoder(WondexProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/WondexProtocolEncoder.java b/src/main/java/org/traccar/protocol/WondexProtocolEncoder.java
index f9e8eeb9b..e9bb23d15 100644
--- a/src/main/java/org/traccar/protocol/WondexProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/WondexProtocolEncoder.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.
@@ -17,9 +17,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class WondexProtocolEncoder extends StringProtocolEncoder {
+ public WondexProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/XexunProtocol.java b/src/main/java/org/traccar/protocol/XexunProtocol.java
index 0005270fb..401844e7b 100644
--- a/src/main/java/org/traccar/protocol/XexunProtocol.java
+++ b/src/main/java/org/traccar/protocol/XexunProtocol.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.
@@ -42,7 +42,7 @@ public class XexunProtocol extends BaseProtocol {
}
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new XexunProtocolEncoder());
+ pipeline.addLast(new XexunProtocolEncoder(XexunProtocol.this));
pipeline.addLast(new XexunProtocolDecoder(XexunProtocol.this, full));
}
});
diff --git a/src/main/java/org/traccar/protocol/XexunProtocolEncoder.java b/src/main/java/org/traccar/protocol/XexunProtocolEncoder.java
index 515cfbbd0..fc849fe15 100644
--- a/src/main/java/org/traccar/protocol/XexunProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/XexunProtocolEncoder.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.
@@ -17,9 +17,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class XexunProtocolEncoder extends StringProtocolEncoder {
+ public XexunProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/XirgoProtocol.java b/src/main/java/org/traccar/protocol/XirgoProtocol.java
index 4979fda5d..1be5b6c4b 100644
--- a/src/main/java/org/traccar/protocol/XirgoProtocol.java
+++ b/src/main/java/org/traccar/protocol/XirgoProtocol.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.
@@ -35,7 +35,7 @@ public class XirgoProtocol extends BaseProtocol {
pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, "##"));
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new XirgoProtocolEncoder());
+ pipeline.addLast(new XirgoProtocolEncoder(XirgoProtocol.this));
pipeline.addLast(new XirgoProtocolDecoder(XirgoProtocol.this));
}
});
@@ -44,7 +44,7 @@ public class XirgoProtocol extends BaseProtocol {
protected void addProtocolHandlers(PipelineBuilder pipeline) {
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new XirgoProtocolEncoder());
+ pipeline.addLast(new XirgoProtocolEncoder(XirgoProtocol.this));
pipeline.addLast(new XirgoProtocolDecoder(XirgoProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/XirgoProtocolDecoder.java b/src/main/java/org/traccar/protocol/XirgoProtocolDecoder.java
index 08809307f..4d0cc314b 100644
--- a/src/main/java/org/traccar/protocol/XirgoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/XirgoProtocolDecoder.java
@@ -266,7 +266,7 @@ public class XirgoProtocolDecoder extends BaseProtocolDecoder {
position.setValid(Integer.parseInt(values[i]) == 3);
break;
case "SI":
- position.set("iccid", values[i]);
+ position.set(Position.KEY_ICCID, values[i]);
break;
case "IG":
int ignition = Integer.parseInt(values[i]);
diff --git a/src/main/java/org/traccar/protocol/XirgoProtocolEncoder.java b/src/main/java/org/traccar/protocol/XirgoProtocolEncoder.java
index dd5e30cca..aa85e9e0e 100644
--- a/src/main/java/org/traccar/protocol/XirgoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/XirgoProtocolEncoder.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.
@@ -17,9 +17,14 @@ package org.traccar.protocol;
import org.traccar.StringProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class XirgoProtocolEncoder extends StringProtocolEncoder {
+ public XirgoProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
@Override
protected Object encodeCommand(Command command) {
diff --git a/src/main/java/org/traccar/protocol/Xrb28Protocol.java b/src/main/java/org/traccar/protocol/Xrb28Protocol.java
index b1f1c34fb..5d8af418b 100644
--- a/src/main/java/org/traccar/protocol/Xrb28Protocol.java
+++ b/src/main/java/org/traccar/protocol/Xrb28Protocol.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.
@@ -40,7 +40,7 @@ public class Xrb28Protocol extends BaseProtocol {
pipeline.addLast(new LineBasedFrameDecoder(1024));
pipeline.addLast(new StringEncoder(StandardCharsets.ISO_8859_1));
pipeline.addLast(new StringDecoder());
- pipeline.addLast(new Xrb28ProtocolEncoder());
+ pipeline.addLast(new Xrb28ProtocolEncoder(Xrb28Protocol.this));
pipeline.addLast(new Xrb28ProtocolDecoder(Xrb28Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/Xrb28ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Xrb28ProtocolEncoder.java
index 617639312..3e69af329 100644
--- a/src/main/java/org/traccar/protocol/Xrb28ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Xrb28ProtocolEncoder.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,9 +18,14 @@ package org.traccar.protocol;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolEncoder;
import org.traccar.model.Command;
+import org.traccar.Protocol;
public class Xrb28ProtocolEncoder extends BaseProtocolEncoder {
+ public Xrb28ProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
private String formatCommand(Command command, String content) {
return String.format("\u00ff\u00ff*SCOS,OM,%s,%s#\n", getUniqueId(command.getDeviceId()), content);
}
diff --git a/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java
index 819011a50..c132f194b 100644
--- a/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 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.
@@ -59,7 +59,7 @@ public class Xt2400ProtocolDecoder extends BaseProtocolDecoder {
0x26, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x57, 0x58, 0x59, 0x5a, 0x6b, 0x6f, 0x7A,
0x7B, 0x7C, 0x7d, 0x7E, 0x7F, 0x80, 0x81, 0x82,
- 0x83, 0x84, 0x85, 0x86
+ 0x83, 0x84, 0x85, 0x86, 0xc8
};
int[] l4 = {
0x03, 0x06, 0x07, 0x08, 0x0e, 0x0f, 0x10, 0x11,
@@ -80,12 +80,13 @@ public class Xt2400ProtocolDecoder extends BaseProtocolDecoder {
TAG_LENGTH_MAP.put(i, 4);
}
TAG_LENGTH_MAP.put(0x95, 24);
+ TAG_LENGTH_MAP.put(0xD0, 21);
}
private static int getTagLength(int tag) {
Integer length = TAG_LENGTH_MAP.get(tag);
if (length == null) {
- throw new IllegalArgumentException("Unknown tag: " + tag);
+ throw new IllegalArgumentException(String.format("Unknown tag: 0x%02X", tag));
}
return length;
}
@@ -93,7 +94,7 @@ public class Xt2400ProtocolDecoder extends BaseProtocolDecoder {
private Map<Short, byte[]> formats = new HashMap<>();
public void setConfig(String configString) {
- Pattern pattern = Pattern.compile(":wycfg pcr\\[\\d+\\] ([0-9a-fA-F]{2})[0-9a-fA-F]{2}([0-9a-fA-F]+)");
+ Pattern pattern = Pattern.compile(":wycfg pcr\\[\\d+] ([0-9a-fA-F]{2})[0-9a-fA-F]{2}([0-9a-fA-F]+)");
Matcher matcher = pattern.matcher(configString);
while (matcher.find()) {
formats.put(Short.parseShort(matcher.group(1), 16), DataConverter.parseHex(matcher.group(2)));
@@ -119,7 +120,8 @@ public class Xt2400ProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position(getProtocolName());
- for (byte tag : format) {
+ for (byte b : format) {
+ int tag = b & 0xFF;
switch (tag) {
case 0x03:
DeviceSession deviceSession = getDeviceSession(
@@ -177,6 +179,14 @@ public class Xt2400ProtocolDecoder extends BaseProtocolDecoder {
case 0x65:
position.set(Position.KEY_VIN, buf.readSlice(17).toString(StandardCharsets.US_ASCII));
break;
+ case 0x6C:
+ buf.readUnsignedByte(); // mil
+ int ecuCount = buf.readUnsignedByte();
+ for (int i = 0; i < ecuCount; i++) {
+ buf.readUnsignedByte(); // ecu id
+ buf.skipBytes(buf.readUnsignedByte() * 6);
+ }
+ break;
case 0x73:
position.set(Position.KEY_VERSION_FW, buf.readSlice(16).toString(StandardCharsets.US_ASCII).trim());
break;
diff --git a/src/main/java/org/traccar/reports/Stops.java b/src/main/java/org/traccar/reports/Stops.java
index 98c9cef00..2036b0641 100644
--- a/src/main/java/org/traccar/reports/Stops.java
+++ b/src/main/java/org/traccar/reports/Stops.java
@@ -43,7 +43,7 @@ public final class Stops {
private static Collection<StopReport> detectStops(long deviceId, Date from, Date to) throws SQLException {
boolean ignoreOdometer = Context.getDeviceManager()
- .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true);
+ .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true);
IdentityManager identityManager = Main.getInjector().getInstance(IdentityManager.class);
DeviceManager deviceManager = Main.getInjector().getInstance(DeviceManager.class);
diff --git a/src/main/java/org/traccar/reports/Summary.java b/src/main/java/org/traccar/reports/Summary.java
index 9810424d8..6d179a873 100644
--- a/src/main/java/org/traccar/reports/Summary.java
+++ b/src/main/java/org/traccar/reports/Summary.java
@@ -61,7 +61,7 @@ public final class Summary {
result.setMaxSpeed(position.getSpeed());
}
boolean ignoreOdometer = Context.getDeviceManager()
- .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true);
+ .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true);
result.setDistance(ReportUtils.calculateDistance(firstPosition, previousPosition, !ignoreOdometer));
result.setAverageSpeed(speedSum / positions.size());
result.setSpentFuel(ReportUtils.calculateFuel(firstPosition, previousPosition));
diff --git a/src/main/java/org/traccar/reports/Trips.java b/src/main/java/org/traccar/reports/Trips.java
index 3cda65553..7c0cd6921 100644
--- a/src/main/java/org/traccar/reports/Trips.java
+++ b/src/main/java/org/traccar/reports/Trips.java
@@ -42,7 +42,7 @@ public final class Trips {
private static Collection<TripReport> detectTrips(long deviceId, Date from, Date to) throws SQLException {
boolean ignoreOdometer = Context.getDeviceManager()
- .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, true);
+ .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true);
IdentityManager identityManager = Main.getInjector().getInstance(IdentityManager.class);
DeviceManager deviceManager = Main.getInjector().getInstance(DeviceManager.class);