From d9f6e0fa8ae131574436cf4375d7feb2d7ff76a7 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 15 Oct 2015 14:21:08 +1300 Subject: Clean up some text protocols --- src/org/traccar/helper/Parser.java | 42 +++- .../traccar/protocol/AplicomProtocolDecoder.java | 257 ++++++++++----------- .../traccar/protocol/AquilaProtocolDecoder.java | 130 +++++------ src/org/traccar/protocol/BoxProtocolDecoder.java | 82 +++---- .../traccar/protocol/GoSafeProtocolDecoder.java | 60 ++--- 5 files changed, 271 insertions(+), 300 deletions(-) (limited to 'src/org') diff --git a/src/org/traccar/helper/Parser.java b/src/org/traccar/helper/Parser.java index e89104094..2fd615ca5 100644 --- a/src/org/traccar/helper/Parser.java +++ b/src/org/traccar/helper/Parser.java @@ -20,7 +20,7 @@ import java.util.regex.Pattern; public class Parser { - private int position = 1; + private int position; private Matcher matcher; public Parser(Pattern pattern, String input) { @@ -28,9 +28,15 @@ public class Parser { } public boolean matches() { + position = 1; return matcher.matches(); } + public boolean find() { + position = 1; + return matcher.find(); + } + public boolean hasNext() { if (matcher.group(position) != null) { return true; @@ -64,15 +70,37 @@ public class Parser { } } - // Format: (degrees)(minutes)(hemisphere) - public double nextCoordinate() { - double coordinate = nextDouble(); - coordinate += nextDouble() / 60; - String hemisphere = next(); - if (hemisphere.equals("S") || hemisphere.equals("W")) { + public enum CoordinateFormat { + DEG_MIN_HEM, + HEM_DEG + } + + public double nextCoordinate(CoordinateFormat format) { + double coordinate; + String hemisphere; + + switch (format) { + case HEM_DEG: + hemisphere = next(); + coordinate = nextDouble(); + break; + case DEG_MIN_HEM: + default: + coordinate = nextDouble(); + coordinate += nextDouble() / 60; + hemisphere = next(); + break; + } + + if (hemisphere != null && (hemisphere.equals("S") || hemisphere.equals("W"))) { coordinate = -coordinate; } + return coordinate; } + public double nextCoordinate() { + return nextCoordinate(CoordinateFormat.DEG_MIN_HEM); + } + } diff --git a/src/org/traccar/protocol/AplicomProtocolDecoder.java b/src/org/traccar/protocol/AplicomProtocolDecoder.java index 9e0bddfcb..4f081b2eb 100644 --- a/src/org/traccar/protocol/AplicomProtocolDecoder.java +++ b/src/org/traccar/protocol/AplicomProtocolDecoder.java @@ -25,6 +25,7 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.Context; import org.traccar.helper.ChannelBufferTools; import org.traccar.helper.Checksum; +import org.traccar.helper.Log; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; import org.traccar.model.Position; @@ -78,10 +79,120 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { private static final int EVENT_DATA = 119; + private void decodeEventData(int event, ChannelBuffer buf) { + switch (event) { + case 2: + case 40: + buf.readUnsignedByte(); + break; + case 9: + buf.readUnsignedMedium(); + break; + case 31: + case 32: + buf.readUnsignedShort(); + break; + case 38: + buf.skipBytes(4 * 9); + break; + case 113: + buf.readUnsignedInt(); + buf.readUnsignedByte(); + break; + case 121: + case 142: + buf.readLong(); + break; + case 130: + buf.readUnsignedInt(); // incorrect + break; + default: + break; + } + } + + private void decodeCanData(ChannelBuffer buf, Position position) { + + buf.readUnsignedMedium(); // packet identifier + buf.readUnsignedByte(); // version + int count = buf.readUnsignedByte(); + buf.readUnsignedByte(); // batch count + buf.readUnsignedShort(); // selector bit + buf.readUnsignedInt(); // timestamp + + buf.skipBytes(8); + + ArrayList values = new ArrayList<>(count); + + for (int i = 0; i < count; i++) { + values.add(buf.readBytes(8)); + } + + for (int i = 0; i < count; i++) { + ChannelBuffer value = values.get(i); + switch (buf.readInt()) { + case 0x20D: + position.set(Event.KEY_RPM, ChannelBuffers.swapShort(value.readShort())); + position.set("diesel-temperature", ChannelBuffers.swapShort(value.readShort()) * 0.1); + position.set("battery-voltage", ChannelBuffers.swapShort(value.readShort()) * 0.01); + position.set("supply-air-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); + break; + case 0x30D: + position.set("active-alarm", ChannelBufferTools.readHexString(value, 16)); + break; + case 0x40C: + position.set("air-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); + position.set("air-temp-dep2", ChannelBuffers.swapShort(value.readShort()) * 0.1); + break; + case 0x40D: + position.set("cold-unit-state", ChannelBufferTools.readHexString(value, 16)); + break; + case 0x50C: + position.set("defrost-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); + position.set("defrost-temp-dep2", ChannelBuffers.swapShort(value.readShort()) * 0.1); + break; + case 0x50D: + position.set("condenser-pressure", ChannelBuffers.swapShort(value.readShort()) * 0.1); + position.set("suction-pressure", ChannelBuffers.swapShort(value.readShort()) * 0.1); + break; + case 0x58C: + value.readByte(); + value.readShort(); // index + switch (value.readByte()) { + case 0x01: + position.set("setpoint-zone1", ChannelBuffers.swapInt(value.readInt()) * 0.1); + break; + case 0x02: + position.set("setpoint-zone2", ChannelBuffers.swapInt(value.readInt()) * 0.1); + break; + case 0x05: + position.set("unit-type", ChannelBuffers.swapInt(value.readInt())); + break; + case 0x13: + position.set("diesel-hours", ChannelBuffers.swapInt(value.readInt()) / 60 / 60); + break; + case 0x14: + position.set("electric-hours", ChannelBuffers.swapInt(value.readInt()) / 60 / 60); + break; + case 0x17: + position.set("service-indicator", ChannelBuffers.swapInt(value.readInt())); + break; + case 0x18: + position.set("software-version", ChannelBuffers.swapInt(value.readInt()) * 0.01); + break; + default: + break; + } + break; + default: + Log.warning(new UnsupportedOperationException()); + break; + } + } + } + @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) - throws Exception { + protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; @@ -97,13 +208,11 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedShort(); // length - // Selector - int selector = DEFAULT_SELECTOR; // default selector + int selector = DEFAULT_SELECTOR; if ((version & 0x40) != 0) { selector = buf.readUnsignedMedium(); } - // Create new position Position position = new Position(); position.setProtocol(getProtocolName()); if (!identify(imei, channel)) { @@ -112,24 +221,20 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(getDeviceId()); - // Event int event = buf.readUnsignedByte(); position.set(Event.KEY_EVENT, event); buf.readUnsignedByte(); - // Validity if ((selector & 0x0008) != 0) { position.setValid((buf.readUnsignedByte() & 0x40) != 0); } else { return null; // no location data } - // Time if ((selector & 0x0004) != 0) { buf.skipBytes(4); // snapshot time } - // Location if ((selector & 0x0008) != 0) { position.setTime(new Date(buf.readUnsignedInt() * 1000)); position.setLatitude(buf.readInt() / 1000000.0); @@ -137,19 +242,16 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { position.set(Event.KEY_SATELLITES, buf.readUnsignedByte()); } - // Speed and heading if ((selector & 0x0010) != 0) { position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); buf.readUnsignedByte(); // maximum speed position.setCourse(buf.readUnsignedByte() * 2.0); } - // Input if ((selector & 0x0040) != 0) { position.set(Event.KEY_INPUT, buf.readUnsignedByte()); } - // ADC if ((selector & 0x0020) != 0) { position.set(Event.PREFIX_ADC + 1, buf.readUnsignedShort()); position.set(Event.PREFIX_ADC + 2, buf.readUnsignedShort()); @@ -157,7 +259,6 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { position.set(Event.PREFIX_ADC + 4, buf.readUnsignedShort()); } - // Power if ((selector & 0x8000) != 0) { position.set(Event.KEY_POWER, buf.readUnsignedShort() / 1000.0); position.set(Event.KEY_BATTERY, buf.readUnsignedShort()); @@ -175,160 +276,50 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedInt(); } - // Trip 1 if ((selector & 0x0080) != 0) { position.set("trip1", buf.readUnsignedInt()); } - // Trip 2 if ((selector & 0x0100) != 0) { position.set("trip2", buf.readUnsignedInt()); } - // Output if ((selector & 0x0040) != 0) { position.set(Event.KEY_OUTPUT, buf.readUnsignedByte()); } - // Button if ((selector & 0x0200) != 0) { - buf.skipBytes(6); + buf.skipBytes(6); // button } - // Keypad if ((selector & 0x0400) != 0) { - buf.readUnsignedByte(); + buf.readUnsignedByte(); // Keypad } - // Altitude if ((selector & 0x0800) != 0) { position.setAltitude(buf.readShort()); } - // Snapshot counter if ((selector & 0x2000) != 0) { - buf.readUnsignedShort(); + buf.readUnsignedShort(); // snapshot counter } - // State flags if ((selector & 0x4000) != 0) { - buf.skipBytes(8); + buf.skipBytes(8); // state flags } - // Cell info if ((selector & 0x80000) != 0) { - buf.skipBytes(11); + buf.skipBytes(11); // cell info } - // Event specific data if ((selector & 0x1000) != 0) { - switch (event) { - case 2: - case 40: - buf.readUnsignedByte(); - break; - case 9: - buf.readUnsignedMedium(); - break; - case 31: - case 32: - buf.readUnsignedShort(); - break; - case 38: - buf.skipBytes(4 * 9); - break; - case 113: - buf.readUnsignedInt(); - buf.readUnsignedByte(); - break; - case 121: - case 142: - buf.readLong(); - break; - case 130: - buf.readUnsignedInt(); // incorrect - break; - default: - break; - } + decodeEventData(event, buf); } - if (Context.getConfig().getBoolean(getProtocolName() + ".can") && - buf.readable() && (selector & 0x1000) != 0 && event == EVENT_DATA) { - - buf.readUnsignedMedium(); // packet identifier - buf.readUnsignedByte(); // version - int count = buf.readUnsignedByte(); - buf.readUnsignedByte(); // batch count - buf.readUnsignedShort(); // selector bit - buf.readUnsignedInt(); // timestamp - - buf.skipBytes(8); + if (Context.getConfig().getBoolean(getProtocolName() + ".can") + && buf.readable() && (selector & 0x1000) != 0 && event == EVENT_DATA) { - ArrayList values = new ArrayList<>(count); - - for (int i = 0; i < count; i++) { - values.add(buf.readBytes(8)); - } - - for (int i = 0; i < count; i++) { - ChannelBuffer value = values.get(i); - switch (buf.readInt()) { - case 0x20D: - position.set(Event.KEY_RPM, ChannelBuffers.swapShort(value.readShort())); - position.set("diesel-temperature", ChannelBuffers.swapShort(value.readShort()) * 0.1); - position.set("battery-voltage", ChannelBuffers.swapShort(value.readShort()) * 0.01); - position.set("supply-air-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); - break; - case 0x30D: - position.set("active-alarm", ChannelBufferTools.readHexString(value, 16)); - break; - case 0x40C: - position.set("air-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); - position.set("air-temp-dep2", ChannelBuffers.swapShort(value.readShort()) * 0.1); - break; - case 0x40D: - position.set("cold-unit-state", ChannelBufferTools.readHexString(value, 16)); - break; - case 0x50C: - position.set("defrost-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); - position.set("defrost-temp-dep2", ChannelBuffers.swapShort(value.readShort()) * 0.1); - break; - case 0x50D: - position.set("condenser-pressure", ChannelBuffers.swapShort(value.readShort()) * 0.1); - position.set("suction-pressure", ChannelBuffers.swapShort(value.readShort()) * 0.1); - break; - case 0x58C: - value.readByte(); - value.readShort(); // index - switch (value.readByte()) { - case 0x01: - position.set("setpoint-zone1", ChannelBuffers.swapInt(value.readInt()) * 0.1); - break; - case 0x02: - position.set("setpoint-zone2", ChannelBuffers.swapInt(value.readInt()) * 0.1); - break; - case 0x05: - position.set("unit-type", ChannelBuffers.swapInt(value.readInt())); - break; - case 0x13: - position.set("diesel-hours", ChannelBuffers.swapInt(value.readInt()) / 60 / 60); - break; - case 0x14: - position.set("electric-hours", ChannelBuffers.swapInt(value.readInt()) / 60 / 60); - break; - case 0x17: - position.set("service-indicator", ChannelBuffers.swapInt(value.readInt())); - break; - case 0x18: - position.set("software-version", ChannelBuffers.swapInt(value.readInt()) * 0.01); - break; - default: - break; - } - break; - } - } + decodeCanData(buf, position); } return position; diff --git a/src/org/traccar/protocol/AquilaProtocolDecoder.java b/src/org/traccar/protocol/AquilaProtocolDecoder.java index b2bbf6f93..9bdaeac10 100644 --- a/src/org/traccar/protocol/AquilaProtocolDecoder.java +++ b/src/org/traccar/protocol/AquilaProtocolDecoder.java @@ -16,12 +16,12 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; -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.Event; import org.traccar.model.Position; @@ -32,48 +32,47 @@ public class AquilaProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private static final Pattern PATTERN = Pattern.compile( - "\\$\\$" + - "[^,]+," + // Client - "(\\d+)," + // Device serial number - "(\\d+)," + // Event - "(-?\\d+\\.\\d+)," + // Latitude - "(-?\\d+\\.\\d+)," + // Longitude - "(\\d{2})(\\d{2})(\\d{2})" + // Date (YYMMDD) - "(\\d{2})(\\d{2})(\\d{2})," + // Time (HHMMSS) - "([AV])," + // Validity - "(\\d+)," + // GSM - "(\\d+)," + // Speed - "(\\d+)," + // Distance - "\\d+," + // Driver code - "(\\d+)," + // Fuel - "([01])," + // IO 1 - "[01]," + // Case open switch - "[01]," + // Over speed start - "[01]," + // Over speed end - "(?:\\d+,){3}" + // Reserved - "([01])," + // Power status - "([01])," + // IO 2 - "\\d+," + // Reserved - "([01])," + // Ignition - "[01]," + // Ignition off event - "(?:\\d+,){7}" + // Reserved - "[01]," + // Corner packet - "(?:\\d+,){8}" + // Reserved - "([01])," + // Course bit 0 - "([01])," + // Course bit 1 - "([01])," + // Course bit 2 - "([01])," + // Course bit 3 - "\\*(\\p{XDigit}{2})"); // Checksum + private static final Pattern PATTERN = new PatternBuilder() + .txt("$$") + .nxt(",") // client + .num("(d+),") // device serial number + .num("(d+),") // event + .num("(-?d+.d+),") // latitude + .num("(-?d+.d+),") // longitude + .num("(dd)(dd)(dd)") // date (yymmdd) + .num("(dd)(dd)(dd),") // time (hhmmss) + .xpr("([AV]),") // validity + .num("(d+),") // gsm + .num("(d+),") // speed + .num("(d+),") // distance + .num("d+,") // driver code + .num("(d+),") // fuel + .num("([01]),") // io 1 + .num("[01],") // case open switch + .num("[01],") // over speed start + .num("[01],") // over speed end + .num("(?:d+,){3}") // reserved + .num("([01]),") // power status + .num("([01]),") // io 2 + .num("d+,") // reserved + .num("([01]),") // ignition + .num("[01],") // ignition off event + .num("(?:d+,){7}") // reserved + .num("[01],") // corner packet + .num("(?:d+,){8}") // reserved + .num("([01]),") // course bit 0 + .num("([01]),") // course bit 1 + .num("([01]),") // course bit 2 + .num("([01]),") // course bit 3 + .txt("*") + .num("(xx)") // checksum + .compile(); @Override protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) - throws Exception { + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - String sentence = (String) msg; - - Matcher parser = PATTERN.matcher(sentence); + Parser parser = new Parser(PATTERN, (String) msg); if (!parser.matches()) { return null; } @@ -81,49 +80,36 @@ public class AquilaProtocolDecoder extends BaseProtocolDecoder { Position position = new Position(); position.setProtocol(getProtocolName()); - Integer index = 1; - - String id = parser.group(index++); - if (!identify(id, channel)) { + if (!identify(parser.next(), channel)) { return null; } position.setDeviceId(getDeviceId()); - position.set(Event.KEY_EVENT, Integer.parseInt(parser.group(index++))); - - position.setLatitude(Double.parseDouble(parser.group(index++))); - position.setLongitude(Double.parseDouble(parser.group(index++))); + position.set(Event.KEY_EVENT, parser.nextInt()); - 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()); + position.setLatitude(parser.nextDouble()); + position.setLongitude(parser.nextDouble()); - position.setValid(parser.group(index++).equals("A")); + DateBuilder dateBuilder = new DateBuilder() + .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt()) + .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); + position.setTime(dateBuilder.getDate()); - position.set(Event.KEY_GSM, Integer.parseInt(parser.group(index++))); + position.setValid(parser.next().equals("A")); - position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(parser.group(index++)))); + position.set(Event.KEY_GSM, parser.nextInt()); - position.set(Event.KEY_ODOMETER, parser.group(index++)); - position.set(Event.KEY_FUEL, parser.group(index++)); - position.set(Event.PREFIX_IO + 1, parser.group(index++)); - position.set(Event.KEY_CHARGE, parser.group(index++)); - position.set(Event.PREFIX_IO + 2, parser.group(index++)); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble())); - position.set(Event.KEY_IGNITION, parser.group(index++).equals("1")); + position.set(Event.KEY_ODOMETER, parser.next()); + position.set(Event.KEY_FUEL, parser.next()); + position.set(Event.PREFIX_IO + 1, parser.next()); + position.set(Event.KEY_CHARGE, parser.next()); + position.set(Event.PREFIX_IO + 2, parser.next()); - int course = - (Integer.parseInt(parser.group(index++)) << 3) + - (Integer.parseInt(parser.group(index++)) << 2) + - (Integer.parseInt(parser.group(index++)) << 1) + - (Integer.parseInt(parser.group(index++))); + position.set(Event.KEY_IGNITION, parser.nextInt() == 1); + int course = (parser.nextInt() << 3) + (parser.nextInt() << 2) + (parser.nextInt() << 1) + parser.nextInt(); if (course > 0 && course <= 8) { position.setCourse((course - 1) * 45); } diff --git a/src/org/traccar/protocol/BoxProtocolDecoder.java b/src/org/traccar/protocol/BoxProtocolDecoder.java index 056677c53..f0586520c 100644 --- a/src/org/traccar/protocol/BoxProtocolDecoder.java +++ b/src/org/traccar/protocol/BoxProtocolDecoder.java @@ -16,12 +16,12 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; -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.Event; import org.traccar.model.Position; @@ -32,24 +32,24 @@ public class BoxProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private static final Pattern PATTERN = Pattern.compile( - "L," + - "(\\d{2})(\\d{2})(\\d{2})" + // Date - "(\\d{2})(\\d{2})(\\d{2})," + // Time - "G," + - "(-?\\d+\\.\\d+)," + // Latitude - "(-?\\d+\\.\\d+)," + // Longitude - "(\\d+\\.?\\d*)," + // Speed - "(\\d+\\.?\\d*)," + // Course - "(\\d+\\.?\\d*)," + // Distance - "(\\d+)," + // Event - "(\\d+)" + // Status - ".*"); + private static final Pattern PATTERN = new PatternBuilder() + .txt("L,") + .num("(dd)(dd)(dd)") // date + .num("(dd)(dd)(dd),") // time + .txt("G,") + .num("(-?d+.d+),") // latitude + .num("(-?d+.d+),") // longitude + .num("(d+.?d*),") // speed + .num("(d+.?d*),") // course + .num("(d+.?d*),") // distance + .num("(d+),") // event + .num("(d+)") // status + .any() + .compile(); @Override protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) - throws Exception { + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { String sentence = (String) msg; @@ -67,46 +67,32 @@ public class BoxProtocolDecoder extends BaseProtocolDecoder { } else if (sentence.startsWith("L,") && hasDeviceId()) { - // 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.setDeviceId(getDeviceId()); position.setProtocol(getProtocolName()); - Integer index = 1; - - // 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()); - - // Location - position.setLatitude(Double.parseDouble(parser.group(index++))); - position.setLongitude(Double.parseDouble(parser.group(index++))); - position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(parser.group(index++)))); - position.setCourse(Double.parseDouble(parser.group(index++))); - - // Distance - position.set(Event.KEY_ODOMETER, parser.group(index++)); - - // Event - position.set(Event.KEY_EVENT, parser.group(index++)); - - // Status - int status = Integer.parseInt(parser.group(index++)); + DateBuilder dateBuilder = new DateBuilder() + .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt()) + .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); + position.setTime(dateBuilder.getDate()); + + position.setLatitude(parser.nextDouble()); + position.setLongitude(parser.nextDouble()); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble())); + position.setCourse(parser.nextDouble()); + + position.set(Event.KEY_ODOMETER, parser.next()); + position.set(Event.KEY_EVENT, parser.next()); + + int status = parser.nextInt(); position.setValid((status & 0x04) == 0); position.set(Event.KEY_STATUS, status); + return position; } diff --git a/src/org/traccar/protocol/GoSafeProtocolDecoder.java b/src/org/traccar/protocol/GoSafeProtocolDecoder.java index 920f6dc36..d32322d48 100644 --- a/src/org/traccar/protocol/GoSafeProtocolDecoder.java +++ b/src/org/traccar/protocol/GoSafeProtocolDecoder.java @@ -19,12 +19,12 @@ import java.net.SocketAddress; import java.util.Date; import java.util.LinkedList; import java.util.List; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.helper.BitUtil; 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; @@ -96,44 +96,29 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder { .groupEnd(true) .compile(); - private Position decodePosition(Matcher parser, Date time) { + private Position decodePosition(Parser parser, Date time) { Position position = new Position(); position.setDeviceId(getDeviceId()); position.setTime(time); - Integer index = 1; + position.set(Event.KEY_EVENT, parser.next()); - position.set(Event.KEY_EVENT, parser.group(index++)); + position.setValid(parser.next().equals("A")); + position.set(Event.KEY_SATELLITES, parser.next()); - // Validity - position.setValid(parser.group(index++).equals("A")); - position.set(Event.KEY_SATELLITES, parser.group(index++)); + position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG)); + position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG)); + position.setSpeed(parser.nextDouble()); + position.setCourse(parser.nextDouble()); + position.setAltitude(parser.nextDouble()); - // Latitude - String hemisphere = parser.group(index++); - Double latitude = Double.parseDouble(parser.group(index++)); - if (hemisphere.equals("S")) latitude = -latitude; - position.setLatitude(latitude); + position.set(Event.KEY_HDOP, parser.next()); + position.set(Event.KEY_ODOMETER, parser.next()); + position.set(Event.KEY_POWER, parser.next()); + position.set(Event.KEY_BATTERY, parser.next()); - // 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(Event.KEY_POWER, parser.group(index++)); - position.set(Event.KEY_BATTERY, parser.group(index++)); - - String status = parser.group(index++); + String status = parser.next(); if (status != null) { position.set(Event.KEY_IGNITION, BitUtil.check(Integer.parseInt(status, 16), 13)); position.set(Event.KEY_STATUS, status); @@ -146,30 +131,25 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder { protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - String sentence = (String) msg; - if (channel != null) { channel.write("1234"); } - Matcher parser = PATTERN.matcher(sentence); + Parser parser = new Parser(PATTERN, (String) msg); if (!parser.matches()) { return null; } - Integer index = 1; - - if (!identify(parser.group(index++), channel, remoteAddress)) { + if (!identify(parser.next(), channel, remoteAddress)) { return null; } DateBuilder dateBuilder = new DateBuilder() - .setTime(parser.group(index++), parser.group(index++), parser.group(index++)) - .setDateReverse(parser.group(index++), parser.group(index++), parser.group(index++)); + .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()) + .setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()); List positions = new LinkedList<>(); - Matcher itemParser = PATTERN_ITEM.matcher(parser.group(index++)); - + Parser itemParser = new Parser(PATTERN_ITEM, parser.next()); while (itemParser.find()) { positions.add(decodePosition(itemParser, dateBuilder.getDate())); } -- cgit v1.2.3