From 10bd96dac0150d9b19623cd86369f8985bda802c Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 6 Nov 2015 18:44:43 +1300 Subject: Refactor TAIP protocol decoder --- src/org/traccar/helper/DateBuilder.java | 14 ++- src/org/traccar/helper/Parser.java | 6 +- src/org/traccar/protocol/TaipProtocolDecoder.java | 123 ++++++++------------- .../traccar/protocol/TaipProtocolDecoderTest.java | 6 +- 4 files changed, 71 insertions(+), 78 deletions(-) diff --git a/src/org/traccar/helper/DateBuilder.java b/src/org/traccar/helper/DateBuilder.java index 77c6821aa..0ad7a4d7b 100644 --- a/src/org/traccar/helper/DateBuilder.java +++ b/src/org/traccar/helper/DateBuilder.java @@ -25,13 +25,20 @@ public class DateBuilder { public DateBuilder() { this(TimeZone.getTimeZone("UTC")); + } + public DateBuilder(Date time) { + this(time, TimeZone.getTimeZone("UTC")); } public DateBuilder(TimeZone timeZone) { + this(new Date(0), timeZone); + } + + public DateBuilder(Date time, TimeZone timeZone) { calendar = Calendar.getInstance(timeZone); calendar.clear(); - calendar.setTimeInMillis(0); + calendar.setTimeInMillis(time.getTime()); } public DateBuilder setYear(int year) { @@ -90,6 +97,11 @@ public class DateBuilder { return this; } + public DateBuilder addMillis(long millis) { + calendar.setTimeInMillis(calendar.getTimeInMillis() + millis); + return this; + } + public DateBuilder setTime(int hour, int minute, int second) { return setHour(hour).setMinute(minute).setSecond(second); } diff --git a/src/org/traccar/helper/Parser.java b/src/org/traccar/helper/Parser.java index 8d6dd1a64..c5f5d2e37 100644 --- a/src/org/traccar/helper/Parser.java +++ b/src/org/traccar/helper/Parser.java @@ -87,6 +87,7 @@ public class Parser { } public enum CoordinateFormat { + DEG_DEG, DEG_HEM, DEG_MIN_HEM, DEG_MIN_MIN_HEM, @@ -98,9 +99,12 @@ public class Parser { public double nextCoordinate(CoordinateFormat format) { double coordinate; - String hemisphere; + String hemisphere = null; switch (format) { + case DEG_DEG: + coordinate = Double.parseDouble(next() + '.' + next()); + break; case DEG_HEM: coordinate = nextDouble(); hemisphere = next(); diff --git a/src/org/traccar/protocol/TaipProtocolDecoder.java b/src/org/traccar/protocol/TaipProtocolDecoder.java index 860dd4602..7f8c1a3c6 100644 --- a/src/org/traccar/protocol/TaipProtocolDecoder.java +++ b/src/org/traccar/protocol/TaipProtocolDecoder.java @@ -16,13 +16,13 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; import java.util.Date; -import java.util.TimeZone; -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.helper.UnitsConverter; import org.traccar.model.Position; @@ -35,44 +35,41 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { this.sendResponse = sendResponse; } - private static final Pattern PATTERN = Pattern.compile( - "(?:R[EP]V" + // Type - "(?:\\d{2}" + // Event index - "(\\d{4})" + // Week - "(\\d))?" + // Day - "(\\d{5})|" + // Seconds - "RGP" + // Type - "(\\d{2})(\\d{2})(\\d{2})" + // Date - "(\\d{2})(\\d{2})(\\d{2}))" + // Time - "([\\+\\-]\\d{2})(\\d{5})" + // Latitude - "([\\+\\-]\\d{3})(\\d{5})" + // Longitude - "(\\d{3})" + // Speed - "(\\d{3})" + // Course - "(\\d)" + // Fix mode - ".*\r?\n?"); + private static final Pattern PATTERN = new PatternBuilder() + .groupBegin() + .expression("R[EP]V") // type + .groupBegin() + .number("dd") // event index + .number("(dddd)") // week + .number("(d)") // day + .groupEnd("?") + .number("(d{5})") // seconds + .or() + .text("RGP") // type + .number("(dd)(dd)(dd)") // date + .number("(dd)(dd)(dd)") // time + .groupEnd() + .number("([-+]dd)(d{5})") // latitude + .number("([-+]ddd)(d{5})") // longitude + .number("(ddd)") // speed + .number("(ddd)") // course + .number("(d)") // fix mode + .any() + .compile(); private Date getTime(long week, long day, long seconds) { - Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - time.clear(); - time.set(Calendar.YEAR, 1980); - time.set(Calendar.MONTH, 0); - time.set(Calendar.DAY_OF_MONTH, 6); - - long millis = time.getTimeInMillis(); - millis += ((week * 7 + day) * 24 * 60 * 60 + seconds) * 1000; - - return new Date(millis); + DateBuilder dateBuilder = new DateBuilder() + .setDate(1980, 1, 6) + .addMillis(((week * 7 + day) * 24 * 60 * 60 + seconds) * 1000); + return dateBuilder.getDate(); } private Date getTime(long seconds) { - Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - time.set(Calendar.HOUR_OF_DAY, 0); - time.set(Calendar.MINUTE, 0); - time.set(Calendar.SECOND, 0); - time.set(Calendar.MILLISECOND, 0); - - long millis = time.getTimeInMillis() + seconds * 1000; + DateBuilder dateBuilder = new DateBuilder(new Date()) + .setTime(0, 0, 0, 0) + .addMillis(seconds * 1000); + long millis = dateBuilder.getDate().getTime(); long diff = System.currentTimeMillis() - millis; if (diff > 12 * 60 * 60 * 1000) { @@ -86,8 +83,7 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { @Override protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) - throws Exception { + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { String sentence = (String) msg; @@ -97,7 +93,7 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { sentence = sentence.substring(beginIndex + 1); } - // Find device ID + // Find device identifier beginIndex = sentence.indexOf(";ID="); if (beginIndex != -1) { beginIndex += 4; @@ -106,13 +102,11 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { endIndex = sentence.length(); } - // Find device in database String id = sentence.substring(beginIndex, endIndex); if (!identify(id, channel)) { return null; } - // Send response if (sendResponse && channel != null) { channel.write(id); } @@ -120,58 +114,39 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { return null; } - // 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()); position.setDeviceId(getDeviceId()); - Integer index = 1; - - // Time - String week = parser.group(index++); - String day = parser.group(index++); - String seconds = parser.group(index++); + String week = parser.next(); + String day = parser.next(); + String seconds = parser.next(); if (seconds != null) { if (week != null && day != null) { position.setTime(getTime(Integer.parseInt(week), Integer.parseInt(day), Integer.parseInt(seconds))); } else { position.setTime(getTime(Integer.parseInt(seconds))); } - index += 6; - } else { - Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - time.clear(); - time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++))); - time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1); - time.set(Calendar.YEAR, 2000 + 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()); } - // Latitude - String latitude = parser.group(index) + '.' + parser.group(index + 1); - index += 2; - position.setLatitude(Double.parseDouble(latitude)); - - // Latitude - String longitude = parser.group(index) + '.' + parser.group(index + 1); - index += 2; - position.setLongitude(Double.parseDouble(longitude)); + if (parser.hasNext(6)) { + DateBuilder dateBuilder = new DateBuilder() + .setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()) + .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); + position.setTime(dateBuilder.getDate()); + } - // Speed and Course - position.setSpeed(UnitsConverter.knotsFromMph(Double.parseDouble(parser.group(index++)))); - position.setCourse(Double.parseDouble(parser.group(index++))); + position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_DEG)); + position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_DEG)); + position.setSpeed(UnitsConverter.knotsFromMph(parser.nextDouble())); + position.setCourse(parser.nextDouble()); + position.setValid(parser.nextInt() != 0); - // Validity - position.setValid(Integer.parseInt(parser.group(index++)) != 0); return position; } diff --git a/test/org/traccar/protocol/TaipProtocolDecoderTest.java b/test/org/traccar/protocol/TaipProtocolDecoderTest.java index d9f74f33d..d0e800ec1 100644 --- a/test/org/traccar/protocol/TaipProtocolDecoderTest.java +++ b/test/org/traccar/protocol/TaipProtocolDecoderTest.java @@ -11,7 +11,8 @@ public class TaipProtocolDecoderTest extends ProtocolDecoderTest { TaipProtocolDecoder decoder = new TaipProtocolDecoder(new TaipProtocol(), false); verifyPosition(decoder, text( - ">RGP230615010248-2682523-065236820000003007F4101;ID=0005;#0002;*2A<")); + ">RGP230615010248-2682523-065236820000003007F4101;ID=0005;#0002;*2A<"), + position("2015-06-23 01:02:48.000", true, -26.82523, -65.23682)); verifyPosition(decoder, text( ">RGP190805211932-3457215-058493640000000FFBF0300;ID=8251;#2122;*54<")); @@ -23,7 +24,8 @@ public class TaipProtocolDecoderTest extends ProtocolDecoderTest { "\r\n>REV691615354941+3570173+1397742703203212;ID=Test")); verifyPosition(decoder, text( - ">REV481599462982+2578391-0802945201228512;ID=Test")); + ">REV481599462982+2578391-0802945201228512;ID=Test"), + position("2010-09-02 17:29:42.000", true, 25.78391, -80.29452)); verifyPosition(decoder, text( ">REV131756153215+3359479-0075299001031332;VO=10568798;IO=310;SV=10;BL=4190;CV09=0;AD=0;AL=+47;ID=356612021059680")); -- cgit v1.2.3