aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/traccar/protocol/TotemProtocolDecoder.java70
-rw-r--r--src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java3
2 files changed, 66 insertions, 7 deletions
diff --git a/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java b/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java
index cd7f684b8..b5398116d 100644
--- a/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2019 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2020 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.
@@ -171,6 +171,33 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
.any()
.compile();
+ private static final Pattern PATTERN_OBD = new PatternBuilder()
+ .text("$$") // header
+ .number("dddd") // length
+ .number("xx") // type
+ .number("(d+)|") // imei
+ .number("(dd)(dd)(dd)") // date (yymmdd)
+ .number("(dd)(dd)(dd),") // time (hhmmss)
+ .number("(-?d+.d+),") // longitude
+ .number("(-?d+.d+),") // latitude
+ .expression("[^,]*,") // obd version
+ .number("(d+),") // odometer
+ .number("(d+),") // fuel used
+ .number("(d+),") // fuel consumption
+ .number("(d+),") // power
+ .number("(d+),") // rpm
+ .number("(d+),") // speed
+ .number("(d+),") // intake flow
+ .number("(d+),") // intake pressure
+ .number("(d+),") // coolant temperature
+ .number("(d+),") // intake temperature
+ .number("(d+),") // engine load
+ .number("(d+),") // throttle
+ .number("(d+),") // fuel
+ .number("|xx") // checksum
+ .any()
+ .compile();
+
private String decodeAlarm123(int value) {
switch (value) {
case 0x01:
@@ -341,7 +368,6 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ALARM, BitUtil.check(status, 32 - 18) ? Position.ALARM_LOW_BATTERY : null);
position.set(Position.KEY_ALARM, BitUtil.check(status, 32 - 22) ? Position.ALARM_JAMMING : null);
-
position.setTime(parser.nextDateTime());
position.set(Position.KEY_BATTERY, parser.nextDouble() * 0.1);
@@ -385,13 +411,39 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
return true;
}
+ private boolean decodeObd(Position position, Parser parser) {
+
+ position.setValid(true);
+ position.setTime(parser.nextDateTime());
+ position.setLatitude(parser.nextDouble());
+ position.setLongitude(parser.nextDouble());
+
+ position.set(Position.KEY_ODOMETER, parser.nextLong());
+ position.set(Position.KEY_FUEL_USED, parser.nextInt());
+ position.set(Position.KEY_FUEL_CONSUMPTION, parser.nextInt());
+ position.set(Position.KEY_POWER, parser.nextInt() * 0.001);
+ position.set(Position.KEY_RPM, parser.nextInt());
+ position.set(Position.KEY_OBD_SPEED, parser.nextInt());
+ parser.nextInt(); // intake flow
+ parser.nextInt(); // intake pressure
+ position.set(Position.KEY_COOLANT_TEMP, parser.nextInt());
+ position.set("intakeTemp", parser.nextInt());
+ position.set(Position.KEY_ENGINE_LOAD, parser.nextInt());
+ position.set(Position.KEY_THROTTLE, parser.nextInt());
+ position.set(Position.KEY_FUEL_LEVEL, parser.nextInt());
+
+ return true;
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
String sentence = (String) msg;
Pattern pattern = PATTERN3;
- if (sentence.charAt(2) == '0') {
+ if (sentence.contains("$Cloud")) {
+ pattern = PATTERN_OBD;
+ } else if (sentence.charAt(2) == '0') {
pattern = PATTERN4;
} else if (sentence.contains("$GPRMC")) {
pattern = PATTERN1;
@@ -409,8 +461,10 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position(getProtocolName());
+ String type = null;
if (pattern == PATTERN4) {
- position.set(Position.KEY_ALARM, decodeAlarm4(parser.nextHexInt()));
+ type = parser.next();
+ position.set(Position.KEY_ALARM, decodeAlarm4(Integer.parseInt(type, 16)));
}
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
@@ -424,13 +478,15 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
result = decode12(position, parser, pattern);
} else if (pattern == PATTERN3) {
result = decode3(position, parser);
- } else {
+ } else if (pattern == PATTERN4) {
result = decode4(position, parser);
+ } else {
+ result = decodeObd(position, parser);
}
if (channel != null) {
- if (pattern == PATTERN4) {
- String response = "$$0014AA" + sentence.substring(sentence.length() - 6, sentence.length() - 2);
+ if (type != null) {
+ String response = "$$0014" + type + sentence.substring(sentence.length() - 6, sentence.length() - 2);
response += String.format("%02X", Checksum.xor(response)).toUpperCase();
channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
} else {
diff --git a/src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java
index 287c54968..fa56797be 100644
--- a/src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java
+++ b/src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java
@@ -11,6 +11,9 @@ public class TotemProtocolDecoderTest extends ProtocolTest {
TotemProtocolDecoder decoder = new TotemProtocolDecoder(null);
verifyPosition(decoder, text(
+ "$$0112E5864606045334223|201112223514,-68.923106,-22.455926,$Cloud,1738,621,730,12100,0,0,255,0,40,40,0,0,255,|13"));
+
+ verifyPosition(decoder, text(
"$$0113AA862010037348253|588040001901220851494212000000753AE901655121700100000.800000002632.6084S02803.3289E29497E"),
position("2019-01-22 08:51:49.000", true, -26.54347, 28.05548));