From b14974fec3c529e4cc29db6f86372efddc87b959 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 30 Oct 2015 15:00:41 +1300 Subject: Refactor Wialon protocol decoder --- .../traccar/protocol/WialonProtocolDecoder.java | 138 +++++++-------------- .../protocol/WialonProtocolDecoderTest.java | 14 ++- 2 files changed, 56 insertions(+), 96 deletions(-) diff --git a/src/org/traccar/protocol/WialonProtocolDecoder.java b/src/org/traccar/protocol/WialonProtocolDecoder.java index 47158808c..e55702441 100644 --- a/src/org/traccar/protocol/WialonProtocolDecoder.java +++ b/src/org/traccar/protocol/WialonProtocolDecoder.java @@ -16,15 +16,15 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; import java.util.LinkedList; import java.util.List; -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.UnitsConverter; +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; @@ -34,25 +34,26 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private static final Pattern PATTERN = Pattern.compile( - "(\\d{2})(\\d{2})(\\d{2});" + // Date (DDMMYY) - "(\\d{2})(\\d{2})(\\d{2});" + // Time (HHMMSS) - "(\\d{2})(\\d{2}\\.\\d+);" + // Latitude (DDMM.MMMM) - "([NS]);" + - "(\\d{3})(\\d{2}\\.\\d+);" + // Longitude (DDDMM.MMMM) - "([EW]);" + - "(\\d+\\.?\\d*)?;" + // Speed - "(\\d+\\.?\\d*)?;" + // Course - "(?:NA|(\\d+\\.?\\d*));" + // Altitude - "(?:NA|(\\d+))" + // Satellites - "(?:;" + - "(?:NA|(\\d+\\.?\\d*));" + // hdop - "(?:NA|(\\d+));" + // inputs - "(?:NA|(\\d+));" + // outputs - "(?:NA|([^;]*));" + // adc - "(?:NA|([^;]*));" + // ibutton - "(?:NA|(.*))" + // params - ")?"); + private static final Pattern PATTERN = new PatternBuilder() + .number("(dd)(dd)(dd);") // date (ddmmyy) + .number("(dd)(dd)(dd);") // time + .number("(dd)(dd.d+);") // latitude + .expression("([NS]);") + .number("(ddd)(dd.d+);") // longitude + .expression("([EW]);") + .number("(d+.?d*)?;") // speed + .number("(d+.?d*)?;") // course + .number("(?:NA|(d+.?d*));") // altitude + .number("(?:NA|(d+))") // satellites + .groupBegin().text(";") + .number("(?:NA|(d+.?d*));") // hdop + .number("(?:NA|(d+));") // inputs + .number("(?:NA|(d+));") // outputs + .expression("(?:NA|([^;]*));") // adc + .expression("(?:NA|([^;]*));") // ibutton + .expression("(?:NA|(.*))") // params + .groupEnd("?") + .compile(); private void sendResponse(Channel channel, String prefix, Integer number) { if (channel != null) { @@ -67,90 +68,47 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { private Position decodePosition(String substring) { - // Parse message - Matcher parser = PATTERN.matcher(substring); + Parser parser = new Parser(PATTERN, substring); if (!hasDeviceId() || !parser.matches()) { return null; } - // Create new position Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); - Integer index = 1; - - // Date and Time - 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 - 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(UnitsConverter.knotsFromKph(Double.parseDouble(speed))); - } + DateBuilder dateBuilder = new DateBuilder() + .setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()) + .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); + position.setTime(dateBuilder.getDate()); - // Course - String course = parser.group(index++); - if (course != null) { - position.setCourse(Double.parseDouble(course)); - } + position.setLatitude(parser.nextCoordinate()); + position.setLongitude(parser.nextCoordinate()); + position.setSpeed(parser.nextDouble()); + position.setCourse(parser.nextDouble()); + position.setAltitude(parser.nextDouble()); - // Altitude - String altitude = parser.group(index++); - if (altitude != null) { - position.setAltitude(Double.parseDouble(altitude)); - } - - // Satellites - String satellites = parser.group(index++); - if (satellites != null) { - position.setValid(Integer.parseInt(satellites) >= 3); + if (parser.hasNext()) { + int satellites = parser.nextInt(); + position.setValid(satellites >= 3); position.set(Event.KEY_SATELLITES, satellites); - } else { - position.setValid(false); } - // Other - position.set(Event.KEY_HDOP, parser.group(index++)); - position.set(Event.KEY_INPUT, parser.group(index++)); - position.set(Event.KEY_OUTPUT, parser.group(index++)); + position.set(Event.KEY_HDOP, parser.next()); + position.set(Event.KEY_INPUT, parser.next()); + position.set(Event.KEY_OUTPUT, parser.next()); - // ADC - String adc = parser.group(index++); - if (adc != null) { - String[] values = adc.split(","); + if (parser.hasNext()) { + String[] values = parser.next().split(","); for (int i = 0; i < values.length; i++) { position.set(Event.PREFIX_ADC + (i + 1), values[i]); } } - // iButton - position.set(Event.KEY_RFID, parser.group(index++)); + position.set(Event.KEY_RFID, parser.next()); - // Params - String params = parser.group(index); - if (params != null) { - String[] values = params.split(","); + if (parser.hasNext()) { + String[] values = parser.next().split(","); for (String param : values) { Matcher paramParser = Pattern.compile("(.*):[1-3]:(.*)").matcher(param); if (paramParser.matches()) { @@ -164,14 +122,12 @@ public class WialonProtocolDecoder 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; if (sentence.startsWith("#L#")) { - // Detect device ID String imei = sentence.substring(3, sentence.indexOf(';')); if (identify(imei, channel)) { sendResponse(channel, "#AL#", 1); @@ -179,8 +135,7 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { } else if (sentence.startsWith("#P#")) { - // Heartbeat - sendResponse(channel, "#AP#", null); + sendResponse(channel, "#AP#", null); // heartbeat } else if (sentence.startsWith("#SD#") || sentence.startsWith("#D#")) { @@ -208,6 +163,7 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { if (!positions.isEmpty()) { return positions; } + } return null; diff --git a/test/org/traccar/protocol/WialonProtocolDecoderTest.java b/test/org/traccar/protocol/WialonProtocolDecoderTest.java index 3541ceb8d..5c3863a5e 100644 --- a/test/org/traccar/protocol/WialonProtocolDecoderTest.java +++ b/test/org/traccar/protocol/WialonProtocolDecoderTest.java @@ -10,15 +10,19 @@ public class WialonProtocolDecoderTest extends ProtocolDecoderTest { WialonProtocolDecoder decoder = new WialonProtocolDecoder(new WialonProtocol()); - verifyNothing(decoder, text( "#L#123456789012345;test")); + verifyNothing(decoder, text( + "#L#123456789012345;test")); - verifyNothing(decoder, text( "#L#2002;NA")); + verifyNothing(decoder, text( + "#L#2002;NA")); - verifyNothing(decoder, text( "#P#")); + verifyNothing(decoder, text( + "#P#")); verifyPosition(decoder, text( - "#SD#270413;205601;5544.6025;N;03739.6834;E;1;2;3;4")); - + "#SD#270413;205601;5544.6025;N;03739.6834;E;1;2;3;4"), + position("2013-04-27 20:56:01.000", true, 55.74338, 37.66139)); + verifyPosition(decoder, text( "#SD#021214;065947;2237.7552;N;11404.8851;E;0.000;;170.9;5")); -- cgit v1.2.3