aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2017-11-15 23:59:42 +1300
committerAnton Tananaev <anton.tananaev@gmail.com>2017-11-15 23:59:42 +1300
commit3c77c1287c494208200cfe53d56ffd4bed8ec5ce (patch)
tree1525e2a96b06c6c266a06cf930c4e92585037834
parent09ee4cc93d600edce023f414c9d373639c137975 (diff)
downloadtrackermap-server-3c77c1287c494208200cfe53d56ffd4bed8ec5ce.tar.gz
trackermap-server-3c77c1287c494208200cfe53d56ffd4bed8ec5ce.tar.bz2
trackermap-server-3c77c1287c494208200cfe53d56ffd4bed8ec5ce.zip
Implement GV65 CAN message support
-rw-r--r--src/org/traccar/protocol/Gl200TextProtocolDecoder.java132
-rw-r--r--test/org/traccar/protocol/Gl200TextProtocolDecoderTest.java9
2 files changed, 141 insertions, 0 deletions
diff --git a/src/org/traccar/protocol/Gl200TextProtocolDecoder.java b/src/org/traccar/protocol/Gl200TextProtocolDecoder.java
index 46a530efa..fb0023dba 100644
--- a/src/org/traccar/protocol/Gl200TextProtocolDecoder.java
+++ b/src/org/traccar/protocol/Gl200TextProtocolDecoder.java
@@ -31,8 +31,12 @@ import org.traccar.model.WifiAccessPoint;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;
+import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -523,6 +527,131 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private Object decodeCan(Channel channel, SocketAddress remoteAddress, String sentence) throws ParseException {
+ Position position = new Position();
+ position.setProtocol(getProtocolName());
+
+ int index = 0;
+ String[] values = sentence.split(",");
+
+ index += 1; // header
+ index += 1; // protocol version
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[index++]);
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ index += 1; // device name
+ index += 1; // report type
+ index += 1; // canbus state
+ long reportMask = Long.parseLong(values[index++], 16);
+
+ if (BitUtil.check(reportMask, 0)) {
+ position.set(Position.KEY_VIN, values[index++]);
+ }
+ if (BitUtil.check(reportMask, 1)) {
+ position.set(Position.KEY_IGNITION, Integer.parseInt(values[index++]) > 0);
+ }
+ if (BitUtil.check(reportMask, 2)) {
+ index += 1; // total distance
+ }
+ if (BitUtil.check(reportMask, 3)) {
+ position.set("totalFuelConsumption", Double.parseDouble(values[index++]));
+ }
+ if (BitUtil.check(reportMask, 5)) {
+ position.set(Position.KEY_RPM, Integer.parseInt(values[index++]));
+ }
+ if (BitUtil.check(reportMask, 4)) {
+ position.set(Position.KEY_OBD_SPEED, UnitsConverter.knotsFromKph(Integer.parseInt(values[index++])));
+ }
+ if (BitUtil.check(reportMask, 6)) {
+ position.set(Position.KEY_COOLANT_TEMP, Integer.parseInt(values[index++]));
+ }
+ if (BitUtil.check(reportMask, 7)) {
+ index += 1; // fuel consumption
+ }
+ if (BitUtil.check(reportMask, 8)) {
+ index += 1; // fuel level
+ }
+ if (BitUtil.check(reportMask, 9)) {
+ index += 1; // range
+ }
+ if (BitUtil.check(reportMask, 10)) {
+ if (!values[index++].isEmpty()) {
+ position.set(Position.KEY_THROTTLE, Integer.parseInt(values[index - 1]));
+ }
+ }
+ if (BitUtil.check(reportMask, 11)) {
+ position.set(Position.KEY_HOURS, Double.parseDouble(values[index++]));
+ }
+ if (BitUtil.check(reportMask, 12)) {
+ index += 1; // driving time
+ }
+ if (BitUtil.check(reportMask, 13)) {
+ index += 1; // idle time
+ }
+ if (BitUtil.check(reportMask, 14)) {
+ index += 1; // idle fuel
+ }
+ if (BitUtil.check(reportMask, 15)) {
+ index += 1; // axle weight
+ }
+ if (BitUtil.check(reportMask, 16)) {
+ index += 1; // tachograph info
+ }
+ if (BitUtil.check(reportMask, 17)) {
+ index += 1; // indicators
+ }
+ if (BitUtil.check(reportMask, 18)) {
+ index += 1; // lights
+ }
+ if (BitUtil.check(reportMask, 19)) {
+ index += 1; // doors
+ }
+ if (BitUtil.check(reportMask, 20)) {
+ index += 1; // total vehicle overspeed time
+ }
+ if (BitUtil.check(reportMask, 21)) {
+ index += 1; // total engine overspeed time
+ }
+ if (BitUtil.check(reportMask, 29)) {
+ index += 1; // expansion
+ }
+
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ if (BitUtil.check(reportMask, 30)) {
+ position.setValid(Integer.parseInt(values[index++]) > 0);
+ if (!values[index].isEmpty()) {
+ position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++])));
+ position.setCourse(Integer.parseInt(values[index++]));
+ position.setAltitude(Double.parseDouble(values[index++]));
+ position.setLongitude(Double.parseDouble(values[index++]));
+ position.setLatitude(Double.parseDouble(values[index++]));
+ position.setTime(dateFormat.parse(values[index++]));
+ } else {
+ index += 6; // no location
+ getLastLocation(position, null);
+ }
+ } else {
+ getLastLocation(position, null);
+ }
+
+ if (BitUtil.check(reportMask, 31)) {
+ index += 4; // cell
+ }
+
+ index += 1; // reserved
+
+ if (ignoreFixTime) {
+ position.setTime(dateFormat.parse(values[index]));
+ } else {
+ position.setDeviceTime(dateFormat.parse(values[index]));
+ }
+
+ return position;
+ }
+
private void decodeStatus(Position position, Parser parser) {
if (parser.hasNext(3)) {
int ignition = parser.nextHexInt(0);
@@ -869,6 +998,9 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
case "OBD":
result = decodeObd(channel, remoteAddress, sentence);
break;
+ case "CAN":
+ result = decodeCan(channel, remoteAddress, sentence);
+ break;
case "FRI":
result = decodeFri(channel, remoteAddress, sentence);
break;
diff --git a/test/org/traccar/protocol/Gl200TextProtocolDecoderTest.java b/test/org/traccar/protocol/Gl200TextProtocolDecoderTest.java
index d18897354..d9e36ef47 100644
--- a/test/org/traccar/protocol/Gl200TextProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/Gl200TextProtocolDecoderTest.java
@@ -10,6 +10,15 @@ public class Gl200TextProtocolDecoderTest extends ProtocolTest {
Gl200TextProtocolDecoder decoder = new Gl200TextProtocolDecoder(new Gl200Protocol());
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTCAN,310201,153759012347650,gv65,0,1,C03FFFFF,,2,H89394,63.14,200,0,87,,P43.60,0,0,17.53,11.61,5.92,0.00,0,0,4002,0,1,0.76,35.00,0,,,,0,0,,0000,0000,0000,0000,00,20040101000052,05A6$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTCAN,310603,863286023346480,gv65,00,1,C03FFFFF,,2,H2843820,373.76,1440,44,77,M23,P35.00,1810,,59.48,42.68,16.80,15.42,,,610,,0,,,0,42.7,263,27.2,-2.156478,51.899989,20171021151805,0234,0010,15D6,9AD2,00,20171021151807,0B28$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTCAN,310603,863286023346480,gv65,02,1,C03FFFFF,,0,H2843820,373.80,0,4,75,M12,,1800,,59.49,42.69,16.80,15.42,,,0,,0,,,0,0.7,75,24.3,-2.155148,51.899400,20171021151837,0234,0010,15D6,9AD2,00,20171021152355,0B2E$"));
+
verifyPositions(decoder, buffer(
"+RESP:GTERI,380603,869606020025833,gv65,00000002,12003,10,1,1,0.0,172,24.6,-81.931875,26.577439,20171002045352,0310,0260,72BD,8E5B,00,1052.1,01383:52:12,0,100,210700,2,1,28FF4560A3150483,1,05B0,20171002045402,9548$"));