diff options
-rw-r--r-- | src/org/traccar/protocol/WialonProtocolDecoder.java | 146 | ||||
-rw-r--r-- | test/org/traccar/protocol/WialonProtocolDecoderTest.java | 3 | ||||
-rwxr-xr-x | tools/hex.sh | 2 |
3 files changed, 93 insertions, 58 deletions
diff --git a/src/org/traccar/protocol/WialonProtocolDecoder.java b/src/org/traccar/protocol/WialonProtocolDecoder.java index 1ece527d8..6ed597d2f 100644 --- a/src/org/traccar/protocol/WialonProtocolDecoder.java +++ b/src/org/traccar/protocol/WialonProtocolDecoder.java @@ -16,6 +16,8 @@ package org.traccar.protocol; 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; @@ -36,7 +38,6 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { } private static final Pattern pattern = Pattern.compile( - "#S?D#" + "(\\d{2})(\\d{2})(\\d{2});" + // Date (DDMMYY) "(\\d{2})(\\d{2})(\\d{2});" + // Time (HHMMSS) "(\\d{2})(\\d{2}\\.\\d+);" + // Latitude (DDMM.MMMM) @@ -45,7 +46,7 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { "([EW]);" + "(\\d+\\.?\\d*);" + // Speed "(\\d+\\.?\\d*);" + // Course - "(\\d+\\.?\\d*);" + // Altitude + "(?:(\\d+\\.?\\d*)|NA);" + // Altitude "(\\d+)" + // Satellites ".*"); // Full format @@ -59,6 +60,69 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { channel.write(response.toString()); } } + + private Position decodePosition(String substring) { + + // Parse message + Matcher parser = pattern.matcher(substring); + if (deviceId == null || !parser.matches()) { + return null; + } + + // Create new position + Position position = new Position(); + ExtendedInfoFormatter extendedInfo = new ExtendedInfoFormatter("wialon"); + position.setDeviceId(deviceId); + + Integer index = 1; + + // Date and Time + Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + time.clear(); + time.set(Calendar.DAY_OF_MONTH, Integer.valueOf(parser.group(index++))); + time.set(Calendar.MONTH, Integer.valueOf(parser.group(index++)) - 1); + time.set(Calendar.YEAR, 2000 + Integer.valueOf(parser.group(index++))); + time.set(Calendar.HOUR_OF_DAY, Integer.valueOf(parser.group(index++))); + time.set(Calendar.MINUTE, Integer.valueOf(parser.group(index++))); + time.set(Calendar.SECOND, Integer.valueOf(parser.group(index++))); + position.setTime(time.getTime()); + + // Latitude + Double latitude = Double.valueOf(parser.group(index++)); + latitude += Double.valueOf(parser.group(index++)) / 60; + if (parser.group(index++).compareTo("S") == 0) latitude = -latitude; + position.setLatitude(latitude); + + // Longitude + Double longitude = Double.valueOf(parser.group(index++)); + longitude += Double.valueOf(parser.group(index++)) / 60; + if (parser.group(index++).compareTo("W") == 0) longitude = -longitude; + position.setLongitude(longitude); + + // Speed + position.setSpeed(Double.valueOf(parser.group(index++)) * 0.539957); + + // Course + position.setCourse(Double.valueOf(parser.group(index++))); + + // Altitude + String altitude = parser.group(index++); + if (altitude != null) { + position.setAltitude(Double.valueOf(altitude)); + } else { + position.setAltitude(0.0); + } + + // Satellites + int satellites = Integer.valueOf(parser.group(index++)); + position.setValid(satellites >= 3); + extendedInfo.set("satellites", satellites); + + // Extended info + position.setExtendedInfo(extendedInfo.toString()); + + return position; + } @Override protected Object decode( @@ -84,65 +148,33 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { } // Parse message - else if ((sentence.startsWith("#SD#") || sentence.startsWith("#D#")) && deviceId != null) { + else if (sentence.startsWith("#SD#") || sentence.startsWith("#D#")) { - // Parse message - Matcher parser = pattern.matcher(sentence); - if (!parser.matches()) { - return null; - } + Position position = decodePosition( + sentence.substring(sentence.indexOf('#', 1) + 1)); - // Create new position - Position position = new Position(); - ExtendedInfoFormatter extendedInfo = new ExtendedInfoFormatter("wialon"); - position.setDeviceId(deviceId); - - Integer index = 1; - - // Date and Time - Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - time.clear(); - time.set(Calendar.DAY_OF_MONTH, Integer.valueOf(parser.group(index++))); - time.set(Calendar.MONTH, Integer.valueOf(parser.group(index++)) - 1); - time.set(Calendar.YEAR, 2000 + Integer.valueOf(parser.group(index++))); - time.set(Calendar.HOUR_OF_DAY, Integer.valueOf(parser.group(index++))); - time.set(Calendar.MINUTE, Integer.valueOf(parser.group(index++))); - time.set(Calendar.SECOND, Integer.valueOf(parser.group(index++))); - position.setTime(time.getTime()); - - // Latitude - Double latitude = Double.valueOf(parser.group(index++)); - latitude += Double.valueOf(parser.group(index++)) / 60; - if (parser.group(index++).compareTo("S") == 0) latitude = -latitude; - position.setLatitude(latitude); - - // Longitude - Double longitude = Double.valueOf(parser.group(index++)); - longitude += Double.valueOf(parser.group(index++)) / 60; - if (parser.group(index++).compareTo("W") == 0) longitude = -longitude; - position.setLongitude(longitude); - - // Speed - position.setSpeed(Double.valueOf(parser.group(index++)) * 0.539957); - - // Course - position.setCourse(Double.valueOf(parser.group(index++))); - - // Altitude - position.setAltitude(Double.valueOf(parser.group(index++))); - - // Satellites - int satellites = Integer.valueOf(parser.group(index++)); - position.setValid(satellites >= 3); - extendedInfo.set("satellites", satellites); + if (position != null) { + sendResponse(channel, "#AD#", 1); + return position; + } + } + + else if (sentence.startsWith("#B#")) { - // Extended info - position.setExtendedInfo(extendedInfo.toString()); - - // Send response - sendResponse(channel, "#AD#", 1); + String[] messages = sentence.substring(sentence.indexOf('#', 1) + 1).split("\\|"); + List<Position> positions = new LinkedList<Position>(); + + for (String message : messages) { + Position position = decodePosition(message); + if (position != null) { + positions.add(position); + } + } - return position; + if (!positions.isEmpty()) { + sendResponse(channel, "#AB#", positions.size()); + return positions; + } } return null; diff --git a/test/org/traccar/protocol/WialonProtocolDecoderTest.java b/test/org/traccar/protocol/WialonProtocolDecoderTest.java index 7b85dbd65..678126df0 100644 --- a/test/org/traccar/protocol/WialonProtocolDecoderTest.java +++ b/test/org/traccar/protocol/WialonProtocolDecoderTest.java @@ -28,6 +28,9 @@ public class WialonProtocolDecoderTest { verify(decoder.decode(null, null, "#D#190114;051312;4459.6956;N;04105.9930;E;35;306;204.000000;12;NA;452986639;NA;106.000000;NA;sats_gps:1:9,sats_glonass:1:3,balance:2:12123.000000,stay_balance:1:0")); + verify(decoder.decode(null, null, + "#B#080914;073235;5027.50625;N;03026.19321;E;0.700;0.000;NA;4;NA;NA;NA;;NA;Батарея:3:100 %|080914;073420;5027.50845;N;03026.18854;E;1.996;292.540;NA;4;NA;NA;NA;;NA;Батарея:3:100 %")); + } } diff --git a/tools/hex.sh b/tools/hex.sh index 7571531fe..2c3faa1ab 100755 --- a/tools/hex.sh +++ b/tools/hex.sh @@ -1,2 +1,2 @@ -echo 504f5354202f20485454502f312e310d0a436f6e74656e742d4c656e6774683a203133330d0a436f6e74656e742d547970653a206170706c69636174696f6e2f782d7777772d666f726d2d75726c656e636f6465640d0a486f73743a2064656d6f2e747261636361722e6f72673a353035350d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a557365722d4167656e743a20416e64726f69640d0a0d0a6c61743d33342e303532323334266c6f6e3d2d3131382e3234333638322674696d657374616d703d31333936383334373930267265715f74696d657374616d703d313339363833343739302661636375726163793d312e3026616c7469747564653d36352e302669643d313233343536373839266f66667365743d25324231322533413030 | perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie' | nc -v -w 10 localhost 5055 +echo 2342233038303931343b3037333233353b353032372e35303632353b4e3b30333032362e31393332313b453b302e3730303b302e3030303b4e413b343b4e413b4e413b4e413b3b4e413bd091d0b0d182d0b0d180d0b5d18f3a333a31303020257c3038303931343b3037333432303b353032372e35303834353b4e3b30333032362e31383835343b453b312e3939363b3239322e3534303b4e413b343b4e413b4e413b4e413b3b4e413bd091d0b0d182d0b0d180d0b5d18f3a333a31303020250d0a | perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie' | nc -v -w 10 localhost 5039 #echo -n -e "\x0f\x00\x00\x00\x4e\x52\x30\x39\x46\x30\x34\x31\x35\x35\x00" >/dev/udp/localhost/5053 |