aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2015-10-25 11:06:34 +1300
committerAnton Tananaev <anton.tananaev@gmail.com>2015-10-25 11:06:34 +1300
commit957740cfb5d74098971a8d4186eda4f9383774d8 (patch)
treed8fb3df0658a9a0ca45ee8a073aca3e82740eb1b
parent8fe177bd27196a3924e4ef8e835ba9dac14975c3 (diff)
downloadtraccar-server-957740cfb5d74098971a8d4186eda4f9383774d8.tar.gz
traccar-server-957740cfb5d74098971a8d4186eda4f9383774d8.tar.bz2
traccar-server-957740cfb5d74098971a8d4186eda4f9383774d8.zip
Refactor Totem protocol decoder
-rw-r--r--src/org/traccar/helper/DateBuilder.java19
-rw-r--r--src/org/traccar/helper/PatternBuilder.java11
-rw-r--r--src/org/traccar/protocol/TotemProtocolDecoder.java224
-rw-r--r--test/org/traccar/helper/PatternBuilderTest.java3
-rw-r--r--test/org/traccar/protocol/TotemProtocolDecoderTest.java9
5 files changed, 90 insertions, 176 deletions
diff --git a/src/org/traccar/helper/DateBuilder.java b/src/org/traccar/helper/DateBuilder.java
index 094dfff16..77c6821aa 100644
--- a/src/org/traccar/helper/DateBuilder.java
+++ b/src/org/traccar/helper/DateBuilder.java
@@ -60,16 +60,6 @@ public class DateBuilder {
return setDate(year, month, day);
}
- @Deprecated
- public DateBuilder setDate(String year, String month, String day) {
- return setDate(Integer.parseInt(year), Integer.parseInt(month), Integer.parseInt(day));
- }
-
- @Deprecated
- public DateBuilder setDateReverse(String day, String month, String year) {
- return setDate(year, month, day);
- }
-
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));
@@ -104,19 +94,10 @@ public class DateBuilder {
return setHour(hour).setMinute(minute).setSecond(second);
}
- @Deprecated
- public DateBuilder setTime(String hour, String minute, String second) {
- return setTime(Integer.parseInt(hour), Integer.parseInt(minute), Integer.parseInt(second));
- }
-
public DateBuilder setTime(int hour, int minute, int second, int millis) {
return setHour(hour).setMinute(minute).setSecond(second).setMillis(millis);
}
- public DateBuilder setDateTime(int year, int month, int day, int hour, int minute, int second) {
- return setDate(year, month, day).setTime(hour, minute, second);
- }
-
public Date getDate() {
return calendar.getTime();
}
diff --git a/src/org/traccar/helper/PatternBuilder.java b/src/org/traccar/helper/PatternBuilder.java
index 5d9d3afa8..4ce4295dd 100644
--- a/src/org/traccar/helper/PatternBuilder.java
+++ b/src/org/traccar/helper/PatternBuilder.java
@@ -33,6 +33,8 @@ public class PatternBuilder {
}
public PatternBuilder expression(String s) {
+ s = s.replaceAll("\\|$", "\\\\|"); // special case for delimiter
+
fragments.add(s);
return this;
}
@@ -63,6 +65,11 @@ public class PatternBuilder {
return this;
}
+ public PatternBuilder or() {
+ fragments.add("|");
+ return this;
+ }
+
public PatternBuilder groupBegin() {
return expression("(?:");
}
@@ -75,10 +82,6 @@ public class PatternBuilder {
return expression(")" + s);
}
- public PatternBuilder or() {
- return expression("|");
- }
-
public Pattern compile() {
return Pattern.compile(toString(), Pattern.DOTALL);
}
diff --git a/src/org/traccar/protocol/TotemProtocolDecoder.java b/src/org/traccar/protocol/TotemProtocolDecoder.java
index 60285d360..556a9fa1e 100644
--- a/src/org/traccar/protocol/TotemProtocolDecoder.java
+++ b/src/org/traccar/protocol/TotemProtocolDecoder.java
@@ -22,6 +22,8 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jboss.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.helper.DateBuilder;
+import org.traccar.helper.Parser;
import org.traccar.helper.PatternBuilder;
import org.traccar.model.Event;
import org.traccar.model.Position;
@@ -65,32 +67,33 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
.any()
.compile();
- private static final Pattern PATTERN2 = Pattern.compile(
- "\\$\\$" + // Header
- "\\p{XDigit}{2}" + // Length
- "(\\d+)\\|" + // IMEI
- "(..)" + // Alarm Type
- "(\\d{2})(\\d{2})(\\d{2})" + // Date (DDMMYY)
- "(\\d{2})(\\d{2})(\\d{2})\\|" + // Time (HHMMSS)
- "([AV])\\|" + // Validity
- "(\\d+)(\\d{2}\\.\\d+)\\|" + // Latitude (DDMM.MMMM)
- "([NS])\\|" +
- "(\\d+)(\\d{2}\\.\\d+)\\|" + // Longitude (DDDMM.MMMM)
- "([EW])\\|" +
- "(\\d+\\.\\d+)?\\|" + // Speed
- "(\\d+)?\\|" + // Course
- "(\\d+\\.\\d+)\\|" + // HDOP
- "(\\d+)\\|" + // IO Status
- "\\d" + // Charged
- "(\\d{2})" + // Battery
- "(\\d{2})\\|" + // External Power
- "(\\d+)\\|" + // ADC
- "(\\p{XDigit}{8})\\|" + // Location Code
- "(\\d+)\\|" + // Temperature
- "(\\d+.\\d+)\\|" + // Odometer
- "\\d+\\|" + // Serial Number
- "\\p{XDigit}{4}" + // Checksum
- "\r?\n?");
+ private static final Pattern PATTERN2 = new PatternBuilder()
+ .text("$$") // header
+ .number("xx") // length
+ .number("(d+)|") // imei
+ .expression("(..)") // alarm type
+ .number("(dd)(dd)(dd)") // date (ddmmyy)
+ .number("(dd)(dd)(dd)|") // time
+ .expression("([AV])|") // validity
+ .number("(d+)(dd.d+)|") // latitude
+ .expression("([NS])|")
+ .number("(d+)(dd.d+)|") // longitude
+ .expression("([EW])|")
+ .number("(d+.d+)?|") // speed
+ .number("(d+)?|") // course
+ .number("(d+.d+)|") // hdop
+ .number("(d+)|") // io status
+ .number("d") // charged
+ .number("(dd)") // battery
+ .number("(dd)|") // external power
+ .number("(d+)|") // adc
+ .number("(x{8})|") // location code
+ .number("(d+)|") // temperature
+ .number("(d+.d+)|") // odometer
+ .number("d+|") // serial number
+ .number("xxxx") // checksum
+ .any()
+ .compile();
private static final Pattern PATTERN3 = new PatternBuilder()
.text("$$") // header
@@ -138,164 +141,85 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
}
}
- // Parse message
- Matcher parser = pattern.matcher(sentence);
+ Parser parser = new Parser(pattern, sentence);
if (!parser.matches()) {
return null;
}
- // Create new position
Position position = new Position();
position.setProtocol(getProtocolName());
- Integer index = 1;
-
- // Get device by IMEI
- if (!identify(parser.group(index++), channel)) {
+ if (!identify(parser.next(), channel)) {
return null;
}
position.setDeviceId(getDeviceId());
- // Alarm type
- position.set(Event.KEY_ALARM, parser.group(index++));
+ position.set(Event.KEY_ALARM, parser.next());
if (pattern == PATTERN1 || pattern == PATTERN2) {
- // Time
- Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- time.clear();
+ DateBuilder dateBuilder = new DateBuilder();
int year = 0;
if (pattern == PATTERN2) {
- time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++)));
- time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1);
- year = Integer.parseInt(parser.group(index++));
- time.set(Calendar.YEAR, 2000 + year);
- }
- time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parser.group(index++)));
- time.set(Calendar.MINUTE, Integer.parseInt(parser.group(index++)));
- time.set(Calendar.SECOND, Integer.parseInt(parser.group(index++)));
-
- // Validity
- position.setValid(parser.group(index++).compareTo("A") == 0);
-
- // Latitude
- Double latitude = Double.parseDouble(parser.group(index++));
- latitude += Double.parseDouble(parser.group(index++)) / 60;
- if (parser.group(index++).compareTo("S") == 0) latitude = -latitude;
- position.setLatitude(latitude);
-
- // Longitude
- Double longitude = Double.parseDouble(parser.group(index++));
- longitude += Double.parseDouble(parser.group(index++)) / 60;
- if (parser.group(index++).compareTo("W") == 0) longitude = -longitude;
- position.setLongitude(longitude);
-
- // Speed
- String speed = parser.group(index++);
- if (speed != null) {
- position.setSpeed(Double.parseDouble(speed));
+ dateBuilder.setDay(parser.nextInt()).setMonth(parser.nextInt());
+ year = parser.nextInt();
+ dateBuilder.setYear(year);
}
+ dateBuilder.setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
- // Course
- String course = parser.group(index++);
- if (course != null) {
- position.setCourse(Double.parseDouble(course));
- }
+ position.setValid(parser.next().equals("A"));
+ position.setLatitude(parser.nextCoordinate());
+ position.setLongitude(parser.nextCoordinate());
+ position.setSpeed(parser.nextDouble());
+ position.setCourse(parser.nextDouble());
- // Date
if (pattern == PATTERN1) {
- time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++)));
- time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1);
- year = Integer.parseInt(parser.group(index++));
- time.set(Calendar.YEAR, 2000 + year);
+ dateBuilder.setDay(parser.nextInt()).setMonth(parser.nextInt());
+ year = parser.nextInt();
+ dateBuilder.setYear(year);
}
if (year == 0) {
return null; // ignore invalid data
}
- position.setTime(time.getTime());
-
- // Accuracy
- position.set(Event.KEY_HDOP, parser.group(index++));
-
- // IO Status
- position.set(Event.PREFIX_IO + 1, parser.group(index++));
-
- // Power
- position.set(Event.KEY_BATTERY, parser.group(index++));
- position.set(Event.KEY_POWER, Double.parseDouble(parser.group(index++)));
-
- // ADC
- position.set(Event.PREFIX_ADC + 1, parser.group(index++));
-
- // Location Code
- position.set(Event.KEY_LAC, parser.group(index++));
+ position.setTime(dateBuilder.getDate());
- // Temperature
- position.set(Event.PREFIX_TEMP + 1, parser.group(index++));
-
- // Odometer
- position.set(Event.KEY_ODOMETER, parser.group(index++));
+ position.set(Event.KEY_HDOP, parser.next());
+ position.set(Event.PREFIX_IO + 1, parser.next());
+ position.set(Event.KEY_BATTERY, parser.next());
+ position.set(Event.KEY_POWER, parser.nextDouble());
+ position.set(Event.PREFIX_ADC + 1, parser.next());
+ position.set(Event.KEY_LAC, parser.next());
+ position.set(Event.PREFIX_TEMP + 1, parser.next());
+ position.set(Event.KEY_ODOMETER, parser.next());
} else if (pattern == PATTERN3) {
- // Time
- Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- time.clear();
- time.set(Calendar.YEAR, 2000 + Integer.parseInt(parser.group(index++)));
- time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1);
- time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++)));
- time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parser.group(index++)));
- time.set(Calendar.MINUTE, Integer.parseInt(parser.group(index++)));
- time.set(Calendar.SECOND, Integer.parseInt(parser.group(index++)));
- position.setTime(time.getTime());
-
- // IO Status
- position.set(Event.PREFIX_IO + 1, parser.group(index++));
-
- // Power
- position.set(Event.KEY_BATTERY, Double.parseDouble(parser.group(index++)) / 10);
- position.set(Event.KEY_POWER, Double.parseDouble(parser.group(index++)));
-
- // ADC
- position.set(Event.PREFIX_ADC + 1, parser.group(index++));
- position.set(Event.PREFIX_ADC + 2, parser.group(index++));
-
- // Temperature
- position.set(Event.PREFIX_TEMP + 1, parser.group(index++));
- position.set(Event.PREFIX_TEMP + 2, parser.group(index++));
-
- // Location Code
- position.set(Event.KEY_LAC, parser.group(index++));
-
- // Validity
- position.setValid(parser.group(index++).compareTo("A") == 0);
-
- // Satellites
- position.set(Event.KEY_SATELLITES, parser.group(index++));
+ DateBuilder dateBuilder = new DateBuilder()
+ .setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt())
+ .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ position.setTime(dateBuilder.getDate());
- // Course
- position.setCourse(Double.parseDouble(parser.group(index++)));
+ position.set(Event.PREFIX_IO + 1, parser.next());
+ position.set(Event.KEY_BATTERY, parser.nextDouble() / 10);
+ position.set(Event.KEY_POWER, parser.nextDouble());
+ position.set(Event.PREFIX_ADC + 1, parser.next());
+ position.set(Event.PREFIX_ADC + 2, parser.next());
+ position.set(Event.PREFIX_TEMP + 1, parser.next());
+ position.set(Event.PREFIX_TEMP + 2, parser.next());
+ position.set(Event.KEY_LAC, parser.next());
- // Speed
- position.setSpeed(Double.parseDouble(parser.group(index++)));
+ position.setValid(parser.next().equals("A"));
+ position.set(Event.KEY_SATELLITES, parser.next());
- // PDOP
- position.set("pdop", parser.group(index++));
+ position.setCourse(parser.nextDouble());
+ position.setSpeed(parser.nextDouble());
- // Odometer
- position.set(Event.KEY_ODOMETER, parser.group(index++));
+ position.set("pdop", parser.next());
- // Latitude
- Double latitude = Double.parseDouble(parser.group(index++));
- latitude += Double.parseDouble(parser.group(index++)) / 60;
- if (parser.group(index++).compareTo("S") == 0) latitude = -latitude;
- position.setLatitude(latitude);
+ position.set(Event.KEY_ODOMETER, parser.next());
- // Longitude
- Double longitude = Double.parseDouble(parser.group(index++));
- longitude += Double.parseDouble(parser.group(index++)) / 60;
- if (parser.group(index++).compareTo("W") == 0) longitude = -longitude;
- position.setLongitude(longitude);
+ position.setLatitude(parser.nextCoordinate());
+ position.setLongitude(parser.nextCoordinate());
}
diff --git a/test/org/traccar/helper/PatternBuilderTest.java b/test/org/traccar/helper/PatternBuilderTest.java
index 427161758..10621693e 100644
--- a/test/org/traccar/helper/PatternBuilderTest.java
+++ b/test/org/traccar/helper/PatternBuilderTest.java
@@ -10,6 +10,9 @@ public class PatternBuilderTest {
Assert.assertEquals("\\$GPRMC", new PatternBuilder().text("$GPRMC").toString());
Assert.assertEquals("(\\d{2}\\.\\p{XDigit}+)", new PatternBuilder().number("(dd.x+)").toString());
Assert.assertEquals("a(?:bc)?", new PatternBuilder().text("a").text("b").text("c").optional(2).toString());
+ Assert.assertEquals("a|b", new PatternBuilder().expression("a|b").toString());
+ Assert.assertEquals("ab\\|", new PatternBuilder().expression("ab|").toString());
+ Assert.assertEquals("|", new PatternBuilder().or().toString());
}
}
diff --git a/test/org/traccar/protocol/TotemProtocolDecoderTest.java b/test/org/traccar/protocol/TotemProtocolDecoderTest.java
index 11bf03c85..373fbd6d1 100644
--- a/test/org/traccar/protocol/TotemProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/TotemProtocolDecoderTest.java
@@ -14,10 +14,12 @@ public class TotemProtocolDecoderTest extends ProtocolDecoderTest {
// $$0108AA864244026063437|1A0000001401010101014111000027BA0E57003100000000.000000000000.0000N00000.0000E048156
verifyPosition(decoder, text(
- "$$BE863771024392112|AA$GPRMC,044704.000,A,1439.3334,N,12059.1417,E,0.00,0.00,200815,,,A*67|01.7|00.8|01.4|000000000000|20150820044704|14291265|00000000|4EECBF8B31|0000|0.0000|0002|00000|56E7"));
+ "$$BE863771024392112|AA$GPRMC,044704.000,A,1439.3334,N,12059.1417,E,0.00,0.00,200815,,,A*67|01.7|00.8|01.4|000000000000|20150820044704|14291265|00000000|4EECBF8B31|0000|0.0000|0002|00000|56E7"),
+ position("2015-08-20 04:47:04.000", true, 14.65556, 120.98570));
verifyPosition(decoder, text(
- "$$AE860990002922822|AA$GPRMC,051002.00,A,0439.26245,N,10108.94448,E,0.023,,140315,,,A*71|02.98|01.95|02.26|000000000000|20150314051003|13841157|105A3B1C|0000|0.0000|0005|5324"));
+ "$$AE860990002922822|AA$GPRMC,051002.00,A,0439.26245,N,10108.94448,E,0.023,,140315,,,A*71|02.98|01.95|02.26|000000000000|20150314051003|13841157|105A3B1C|0000|0.0000|0005|5324"),
+ position("2015-03-14 05:10:02.000", true, 4.65437, 101.14907));
verifyPosition(decoder, text(
"$$AE860990002922822|AA$GPRMC,051002.00,A,0439.26245,N,10108.94448,E,0.023,,140315,,,A*71|02.98|01.95|02.26|000000000000|20150314051003|13841157|105A3B1C|0000|0.0000|0005|5324\r"));
@@ -32,7 +34,8 @@ public class TotemProtocolDecoderTest extends ProtocolDecoderTest {
"$$B2359772032984289|AA$GPRMC,104446.000,A,5011.3944,N,01439.6637,E,0.00,,290212,,,A*7D|01.8|00.9|01.5|000000100000|20120229104446|14151221|00050000|046D085E|0000|0.0000|1170|29A7"));
verifyPosition(decoder, text(
- "$$8B862170017861566|AA180613080657|A|2237.1901|N|11402.1369|E|1.579|178|8.70|100000001000|13811|00000000|253162F5|00000000|0.0000|0014|2B16"));
+ "$$8B862170017861566|AA180613080657|A|2237.1901|N|11402.1369|E|1.579|178|8.70|100000001000|13811|00000000|253162F5|00000000|0.0000|0014|2B16"),
+ position("2013-06-18 08:06:57.000", true, 22.61984, 114.03562));
verifyPosition(decoder, text(
"$$72862170017856731|3913090911165280000370000000000000000019BD508A0400000003.400000093644.9817N01012.9944E00506F2E"));