From 4e82a2e0e6e8ea2fa09435e51392e9614d869677 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 9 Oct 2015 17:09:54 +1300 Subject: Refactor GoSafe decoder implementation --- src/org/traccar/helper/PatternBuilder.java | 12 ++ src/org/traccar/model/Event.java | 1 + .../traccar/protocol/GoSafeProtocolDecoder.java | 158 +++++++++++++++------ 3 files changed, 125 insertions(+), 46 deletions(-) diff --git a/src/org/traccar/helper/PatternBuilder.java b/src/org/traccar/helper/PatternBuilder.java index e8f5c605a..0105bf7a6 100644 --- a/src/org/traccar/helper/PatternBuilder.java +++ b/src/org/traccar/helper/PatternBuilder.java @@ -21,6 +21,10 @@ public class PatternBuilder { private final StringBuilder pattern = new StringBuilder(); + public interface Builder { + void build(PatternBuilder builder); + } + public PatternBuilder xpr(String s) { pattern.append(s); return this; @@ -60,6 +64,14 @@ public class PatternBuilder { return not(s).txt(s); } + public PatternBuilder groupBegin() { + return xpr("(?:"); + } + + public PatternBuilder groupEnd(boolean optional) { + return xpr(optional ? ")?" : ")"); + } + public Pattern compile() { return Pattern.compile(pattern.toString(), Pattern.DOTALL); } diff --git a/src/org/traccar/model/Event.java b/src/org/traccar/model/Event.java index 2e4d82c0b..586885c4a 100644 --- a/src/org/traccar/model/Event.java +++ b/src/org/traccar/model/Event.java @@ -49,6 +49,7 @@ public abstract class Event extends Extensible { public static final String KEY_DISTANCE = "distance"; public static final String KEY_DOOR = "door"; public static final String KEY_RPM = "rpm"; + public static final String KEY_HOURS = "hours"; public static final String KEY_OBD_SPEED = "obd-speed"; public static final String KEY_OBD_ODOMETER = "obd-odometer"; diff --git a/src/org/traccar/protocol/GoSafeProtocolDecoder.java b/src/org/traccar/protocol/GoSafeProtocolDecoder.java index 225070b26..bd88eda27 100644 --- a/src/org/traccar/protocol/GoSafeProtocolDecoder.java +++ b/src/org/traccar/protocol/GoSafeProtocolDecoder.java @@ -16,12 +16,12 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; -import java.util.TimeZone; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; +import org.traccar.helper.PatternBuilder; import org.traccar.model.Event; import org.traccar.model.Position; @@ -31,21 +31,110 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private static final Pattern PATTERN = Pattern.compile( - "\\*[^,]+," + - "(\\d+)," + // IMEI - "(\\d{2})(\\d{2})(\\d{2})" + // Time - "(\\d{2})(\\d{2})(\\d{2})," + // Date - ".*," + - "GPS.([AV]);" + // Validity - "\\d+;" + - "([NS])(\\d+\\.\\d+);" + // Latitude - "([EW])(\\d+\\.\\d+);" + // Longitude - "(\\d+);" + // Speed - "(\\d+);" + // Course - "(\\d+);" + // Altitude - "(\\d+\\.\\d+)" + // HDOP - ".*"); + private static final Pattern PATTERN = new PatternBuilder() + .txt("*GS") // header + .num("d+,") // protocol version + .num("(d+),") // imei + .num("(dd)(dd)(dd)") // time + .num("(dd)(dd)(dd),") // date + .xpr("(.*)#?") // data + .compile(); + + private static final Pattern PATTERN_ITEM = new PatternBuilder() + .num("(x+)?,") // event + .groupBegin() + .txt("SYS:") + .nxt(",") + .groupEnd(true) + .groupBegin() + .txt("GPS:") + .xpr("([AV]);") // validity + .num("(d+);") // satellites + .num("([NS])(d+.d+);") // latitude + .num("([EW])(d+.d+);") // longitude + .num("(d+);") // speed + .num("(d+);") // course + .num("(d+);") // altitude + .num("(d+.d+)") // hdop + .opn(";d+.d+") // vdop + .xpr(",?") + .groupEnd(false) + .groupBegin() + .txt("COT:") + .num("(d+);") // odometer + .not("(d+):d+:d+") // engine hours + .xpr(",?") + .groupEnd(true) + .groupBegin() + .txt("ADC:") + .num("(d+.d+);") // power + .num("(d+.d+)") // battery + .xpr(",?") + .groupEnd(true) + .groupBegin() + .txt("DTT:") + .not(",") + .xpr(",?") + .groupEnd(true) + .groupBegin() + .txt("ETD:") + .not(",") + .xpr(",?") + .groupEnd(true) + .groupBegin() + .txt("OBD:") + .not(",") + .xpr(",?") + .groupEnd(true) + .groupBegin() + .txt("FUL:") + .not(",") + .xpr(",?") + .groupEnd(true) + .groupBegin() + .txt("TRU:") + .not(",") + .xpr(",?") + .groupEnd(true) + .compile(); + + private Position decodePosition(Matcher parser, Date time) { + + Position position = new Position(); + position.setDeviceId(getDeviceId()); + position.setTime(time); + + Integer index = 1; + + position.set(Event.KEY_EVENT, parser.group(index++)); + + // Validity + position.setValid(parser.group(index++).equals("A")); + position.set(Event.KEY_SATELLITES, parser.group(index++)); + + // Latitude + String hemisphere = parser.group(index++); + Double latitude = Double.parseDouble(parser.group(index++)); + if (hemisphere.equals("S")) latitude = -latitude; + position.setLatitude(latitude); + + // Longitude + hemisphere = parser.group(index++); + Double longitude = Double.parseDouble(parser.group(index++)); + if (hemisphere.equals("W")) longitude = -longitude; + position.setLongitude(longitude); + + // Other + position.setSpeed(Double.parseDouble(parser.group(index++))); + position.setCourse(Double.parseDouble(parser.group(index++))); + position.setAltitude(Double.parseDouble(parser.group(index++))); + position.set(Event.KEY_HDOP, parser.group(index++)); + + position.set(Event.KEY_ODOMETER, parser.group(index++)); + position.set("hours", parser.group(index++)); + + return position; + } @Override protected Object decode( @@ -58,25 +147,17 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder { channel.write("1234"); } - // Parse message Matcher parser = PATTERN.matcher(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, remoteAddress)) { return null; } - position.setDeviceId(getDeviceId()); - // Date Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parser.group(index++))); @@ -85,30 +166,15 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder { 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++))); - position.setTime(time.getTime()); - - // Validity - position.setValid(parser.group(index++).compareTo("A") == 0); - - // Latitude - String hemisphere = parser.group(index++); - Double latitude = Double.parseDouble(parser.group(index++)); - if (hemisphere.compareTo("S") == 0) latitude = -latitude; - position.setLatitude(latitude); - // Longitude - hemisphere = parser.group(index++); - Double longitude = Double.parseDouble(parser.group(index++)); - if (hemisphere.compareTo("W") == 0) longitude = -longitude; - position.setLongitude(longitude); + List positions = new LinkedList<>(); + Matcher itemParser = PATTERN_ITEM.matcher(parser.group(index++)); - // Other - position.setSpeed(Double.parseDouble(parser.group(index++))); - position.setCourse(Double.parseDouble(parser.group(index++))); - position.setAltitude(Double.parseDouble(parser.group(index++))); - position.set(Event.KEY_HDOP, parser.group(index++)); + while (itemParser.find()) { + positions.add(decodePosition(itemParser, time.getTime())); + } - return position; + return positions; } } -- cgit v1.2.3