diff options
author | Ivan Muratov <binakot@gmail.com> | 2017-10-26 08:28:34 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-26 08:28:34 +0300 |
commit | 74cea90707321c775c11e9cfb91269f63ab4476f (patch) | |
tree | c6f3e9d02c43eb28ac8506e198e137ca57b1f102 | |
parent | db02157dbb29539dda4b51a5e8b317293cfc536c (diff) | |
parent | dcc7e0c6ed949604af5e62c671e293f582146bc0 (diff) | |
download | trackermap-server-74cea90707321c775c11e9cfb91269f63ab4476f.tar.gz trackermap-server-74cea90707321c775c11e9cfb91269f63ab4476f.tar.bz2 trackermap-server-74cea90707321c775c11e9cfb91269f63ab4476f.zip |
Merge branch 'master' into master
-rw-r--r-- | setup/default.xml | 5 | ||||
-rw-r--r-- | src/org/traccar/protocol/DwayProtocol.java | 47 | ||||
-rw-r--r-- | src/org/traccar/protocol/DwayProtocolDecoder.java | 109 | ||||
-rw-r--r-- | src/org/traccar/protocol/FlespiProtocol.java | 46 | ||||
-rw-r--r-- | src/org/traccar/protocol/FlespiProtocolDecoder.java | 116 | ||||
-rw-r--r-- | src/org/traccar/protocol/GenxProtocolDecoder.java | 19 | ||||
-rw-r--r-- | src/org/traccar/protocol/MeitrackProtocolDecoder.java | 165 | ||||
-rw-r--r-- | src/org/traccar/protocol/TotemProtocolDecoder.java | 256 | ||||
-rw-r--r-- | test/org/traccar/protocol/DwayProtocolDecoderTest.java | 30 | ||||
-rw-r--r-- | test/org/traccar/protocol/FlespiProtocolDecoderTest.java | 24 | ||||
-rw-r--r-- | test/org/traccar/protocol/GenxProtocolDecoderTest.java | 5 | ||||
-rw-r--r-- | test/org/traccar/protocol/MeitrackProtocolDecoderTest.java | 6 | ||||
-rw-r--r-- | test/org/traccar/protocol/TotemProtocolDecoderTest.java | 6 | ||||
-rw-r--r-- | test/org/traccar/protocol/WatchFrameDecoderTest.java | 5 |
14 files changed, 700 insertions, 139 deletions
diff --git a/setup/default.xml b/setup/default.xml index 53ef5f4e3..d33e6dd27 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -217,6 +217,9 @@ <entry key='tlv.port'>5146</entry> <entry key='esky.port'>5147</entry> <entry key='genx.port'>5148</entry> - <entry key='arnavi4.port'>5149</entry> + <entry key='flespi.port'>5149</entry> + <entry key='dway.port'>5150</entry> + <entry key='arnavi4.port'>5151</entry> + </properties> diff --git a/src/org/traccar/protocol/DwayProtocol.java b/src/org/traccar/protocol/DwayProtocol.java new file mode 100644 index 000000000..151d3fe01 --- /dev/null +++ b/src/org/traccar/protocol/DwayProtocol.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.protocol; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.handler.codec.frame.LineBasedFrameDecoder; +import org.jboss.netty.handler.codec.string.StringDecoder; +import org.jboss.netty.handler.codec.string.StringEncoder; +import org.traccar.BaseProtocol; +import org.traccar.TrackerServer; + +import java.util.List; + +public class DwayProtocol extends BaseProtocol { + + public DwayProtocol() { + super("dway"); + } + + @Override + public void initTrackerServers(List<TrackerServer> serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(1024)); + pipeline.addLast("stringEncoder", new StringEncoder()); + pipeline.addLast("stringDecoder", new StringDecoder()); + pipeline.addLast("objectDecoder", new DwayProtocolDecoder(DwayProtocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/DwayProtocolDecoder.java b/src/org/traccar/protocol/DwayProtocolDecoder.java new file mode 100644 index 000000000..993aa91b2 --- /dev/null +++ b/src/org/traccar/protocol/DwayProtocolDecoder.java @@ -0,0 +1,109 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.protocol; + +import org.jboss.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.helper.Parser; +import org.traccar.helper.PatternBuilder; +import org.traccar.helper.UnitsConverter; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.util.regex.Pattern; + +public class DwayProtocolDecoder extends BaseProtocolDecoder { + + public DwayProtocolDecoder(DwayProtocol protocol) { + super(protocol); + } + + private static final Pattern PATTERN = new PatternBuilder() + .text("AA55,") + .number("d+,") // index + .number("(d+),") // imei + .number("d+,") // type + .number("(dd)(dd)(dd),") // date (yymmdd) + .number("(dd)(dd)(dd),") // time (hhmmss) + .number("(-?d+.d+),") // latitude + .number("(-?d+.d+),") // longitude + .number("(-?d+),") // altitude + .number("(d+.d+),") // speed + .number("(d+),") // course + .number("([01]{4}),") // input + .number("([01]{4}),") // output + .number("([01])([01])([01])([01]),") // flags + .number("(d+),") // battery + .number("(d+),") // adc1 + .number("(d+),") // adc2 + .number("(d+)") // driver + .compile(); + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + String sentence = (String) msg; + if (sentence.startsWith(">H")) { + if (channel != null) { + channel.write(">ALIVE\r\n"); + } + return null; + } + + Parser parser = new Parser(PATTERN, (String) msg); + if (!parser.matches()) { + return null; + } + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); + if (deviceSession == null) { + return null; + } + + Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setTime(parser.nextDateTime()); + position.setLatitude(parser.nextDouble()); + position.setLongitude(parser.nextDouble()); + position.setAltitude(parser.nextDouble(0)); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0))); + position.setCourse(parser.nextDouble(0)); + + position.set(Position.KEY_INPUT, parser.nextBinInt()); + position.set(Position.KEY_OUTPUT, parser.nextBinInt()); + + position.setValid(parser.next().equals("1")); + + position.set(Position.KEY_IGNITION, parser.next().equals("1")); + position.set(Position.KEY_CHARGE, parser.next().equals("1")); + + if (parser.next().equals("1")) { + position.set(Position.KEY_ALARM, Position.ALARM_SHOCK); + } + + position.set(Position.KEY_BATTERY, parser.nextInt() * 0.001); + position.set(Position.PREFIX_ADC + 1, parser.nextInt() * 0.001); + position.set(Position.PREFIX_ADC + 2, parser.nextInt() * 0.001); + position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next()); + + return position; + } + +} diff --git a/src/org/traccar/protocol/FlespiProtocol.java b/src/org/traccar/protocol/FlespiProtocol.java new file mode 100644 index 000000000..d22bd7ae0 --- /dev/null +++ b/src/org/traccar/protocol/FlespiProtocol.java @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.protocol; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.handler.codec.http.HttpChunkAggregator; +import org.jboss.netty.handler.codec.http.HttpRequestDecoder; +import org.jboss.netty.handler.codec.http.HttpResponseEncoder; +import org.traccar.BaseProtocol; +import org.traccar.TrackerServer; + +import java.util.List; + +public class FlespiProtocol extends BaseProtocol { + + public FlespiProtocol() { + super("flespi"); + } + + @Override + public void initTrackerServers(List<TrackerServer> serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("httpEncoder", new HttpResponseEncoder()); + pipeline.addLast("httpDecoder", new HttpRequestDecoder()); + pipeline.addLast("httpAggregator", new HttpChunkAggregator(Integer.MAX_VALUE)); + pipeline.addLast("objectDecoder", new FlespiProtocolDecoder(FlespiProtocol.this)); + } + }); + } +} diff --git a/src/org/traccar/protocol/FlespiProtocolDecoder.java b/src/org/traccar/protocol/FlespiProtocolDecoder.java new file mode 100644 index 000000000..799d78ecb --- /dev/null +++ b/src/org/traccar/protocol/FlespiProtocolDecoder.java @@ -0,0 +1,116 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.protocol; + +import org.jboss.netty.channel.Channel; +import org.jboss.netty.handler.codec.http.DefaultHttpResponse; +import org.jboss.netty.handler.codec.http.HttpRequest; +import org.jboss.netty.handler.codec.http.HttpResponse; +import org.jboss.netty.handler.codec.http.HttpResponseStatus; +import org.jboss.netty.handler.codec.http.HttpVersion; +import org.jboss.netty.handler.codec.http.HttpHeaders; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.model.Position; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonNumber; +import javax.json.JsonObject; +import javax.json.JsonString; +import java.io.StringReader; +import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.LinkedList; +import java.util.Date; + +public class FlespiProtocolDecoder extends BaseProtocolDecoder { + + public FlespiProtocolDecoder(FlespiProtocol protocol) { + super(protocol); + } + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + HttpRequest request = (HttpRequest) msg; + JsonArray result = Json.createReader(new StringReader(request.getContent().toString(StandardCharsets.UTF_8))) + .readArray(); + List<Position> positions = new LinkedList<>(); + for (int i = 0; i < result.size(); i++) { + JsonObject message = result.getJsonObject(i); + JsonString ident = message.getJsonString("ident"); + if (ident == null) { + continue; + } + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, ident.getString()); + if (deviceSession == null) { + continue; + } + Position position = new Position(); + position.setDeviceId(deviceSession.getDeviceId()); + decodePosition(message, position); + positions.add(position); + } + + sendResponse(channel, HttpResponseStatus.OK); + return positions; + } + + private void sendResponse(Channel channel, HttpResponseStatus status) { + if (channel != null) { + HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status); + response.headers().add(HttpHeaders.Names.CONTENT_LENGTH, 0); + channel.write(response); + } + } + + private void decodePosition(JsonObject object, Position position) { + position.setProtocol(getProtocolName()); + + Date deviceTime = new Date((long) object.getJsonNumber("timestamp").doubleValue() * 1000); + position.setTime(deviceTime); + JsonNumber lat = object.getJsonNumber("position.latitude"); + JsonNumber lon = object.getJsonNumber("position.longitude"); + if (lat != null && lon != null) { + position.setLatitude(lat.doubleValue()); + position.setLongitude(lon.doubleValue()); + } else { + getLastLocation(position, deviceTime); + } + JsonNumber speed = object.getJsonNumber("position.speed"); + if (speed != null) { + position.setSpeed(speed.doubleValue()); + } + JsonNumber course = object.getJsonNumber("position.direction"); + if (course != null) { + position.setCourse(course.doubleValue()); + } + JsonNumber altitude = object.getJsonNumber("position.altitude"); + if (altitude != null) { + position.setAltitude(altitude.doubleValue()); + } + + position.setValid(object.getBoolean("position.valid", true)); + position.set(Position.KEY_SATELLITES, object.getInt("position.satellites", 0)); + + if (object.getBoolean("alarm.event.trigger", false)) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } + } +} diff --git a/src/org/traccar/protocol/GenxProtocolDecoder.java b/src/org/traccar/protocol/GenxProtocolDecoder.java index 3b716796c..ebf6f2b53 100644 --- a/src/org/traccar/protocol/GenxProtocolDecoder.java +++ b/src/org/traccar/protocol/GenxProtocolDecoder.java @@ -19,6 +19,7 @@ import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; import org.traccar.DeviceSession; +import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; import java.net.SocketAddress; @@ -68,6 +69,24 @@ public class GenxProtocolDecoder extends BaseProtocolDecoder { case 4: position.setLongitude(Double.parseDouble(values[i])); break; + case 11: + position.set(Position.KEY_IGNITION, values[i].equals("ON")); + break; + case 13: + position.setSpeed(UnitsConverter.knotsFromKph(Integer.parseInt(values[i]))); + break; + case 17: + position.setCourse(Integer.parseInt(values[i])); + break; + case 23: + position.set(Position.KEY_ODOMETER, Double.parseDouble(values[i]) * 1000); + break; + case 27: + position.setAltitude(UnitsConverter.metersFromFeet(Integer.parseInt(values[i]))); + break; + case 46: + position.set(Position.KEY_SATELLITES, Integer.parseInt(values[i])); + break; default: break; } diff --git a/src/org/traccar/protocol/MeitrackProtocolDecoder.java b/src/org/traccar/protocol/MeitrackProtocolDecoder.java index efc9c24db..5b67aebe3 100644 --- a/src/org/traccar/protocol/MeitrackProtocolDecoder.java +++ b/src/org/traccar/protocol/MeitrackProtocolDecoder.java @@ -16,6 +16,7 @@ package org.traccar.protocol; import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; @@ -37,6 +38,8 @@ import java.util.regex.Pattern; public class MeitrackProtocolDecoder extends BaseProtocolDecoder { + private ChannelBuffer photo; + public MeitrackProtocolDecoder(MeitrackProtocol protocol) { super(protocol); } @@ -109,7 +112,7 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { } } - private Position decodeRegularMessage(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { + private Position decodeRegular(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { Parser parser = new Parser(PATTERN, buf.toString(StandardCharsets.US_ASCII)); if (!parser.matches()) { @@ -219,13 +222,13 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { if (parser.hasNext()) { for (String temp : parser.next().split("\\|")) { - int index = Integer.valueOf(temp.substring(0, 2), 16); + int index = Integer.parseInt(temp.substring(0, 2), 16); if (protocol >= 3) { - double value = Short.valueOf(temp.substring(2), 16); + double value = (short) Integer.parseInt(temp.substring(2), 16); position.set(Position.PREFIX_TEMP + index, value * 0.01); } else { - double value = Byte.valueOf(temp.substring(2, 4), 16); - value += (value < 0 ? -0.01 : 0.01) * Integer.valueOf(temp.substring(4), 16); + double value = Byte.parseByte(temp.substring(2, 4), 16); + value += (value < 0 ? -0.01 : 0.01) * Integer.parseInt(temp.substring(4), 16); position.set(Position.PREFIX_TEMP + index, value); } } @@ -234,7 +237,7 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { return position; } - private List<Position> decodeBinaryMessage(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { + private List<Position> decodeBinaryC(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { List<Position> positions = new LinkedList<>(); String flag = buf.toString(2, 1, StandardCharsets.US_ASCII); @@ -308,6 +311,108 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { return positions; } + private List<Position> decodeBinaryE(Channel channel, SocketAddress remoteAddress, ChannelBuffer buf) { + List<Position> positions = new LinkedList<>(); + + buf.readerIndex(buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) ',') + 1); + String imei = buf.readBytes(15).toString(StandardCharsets.US_ASCII); + buf.skipBytes(1 + 3 + 1); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); + if (deviceSession == null) { + return null; + } + + buf.readUnsignedInt(); // remaining cache + int count = buf.readUnsignedShort(); + + for (int i = 0; i < count; i++) { + Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + buf.readUnsignedShort(); // length + buf.readUnsignedShort(); // index + + int paramCount = buf.readUnsignedByte(); + for (int j = 0; j < paramCount; j++) { + int id = buf.readUnsignedByte(); + switch (id) { + case 0x01: + position.set(Position.KEY_EVENT, buf.readUnsignedByte()); + break; + case 0x05: + position.setValid(buf.readUnsignedByte() > 0); + break; + case 0x06: + position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); + break; + default: + buf.readUnsignedByte(); + break; + } + } + + paramCount = buf.readUnsignedByte(); + for (int j = 0; j < paramCount; j++) { + int id = buf.readUnsignedByte(); + switch (id) { + case 0x08: + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort())); + break; + case 0x09: + position.setCourse(buf.readUnsignedShort() * 0.1); + break; + case 0x0B: + position.setAltitude(buf.readShort()); + break; + default: + buf.readUnsignedShort(); + break; + } + } + + paramCount = buf.readUnsignedByte(); + for (int j = 0; j < paramCount; j++) { + int id = buf.readUnsignedByte(); + switch (id) { + case 0x02: + position.setLatitude(buf.readInt() * 0.000001); + break; + case 0x03: + position.setLongitude(buf.readInt() * 0.000001); + break; + case 0x04: + position.setTime(new Date((946684800 + buf.readUnsignedInt()) * 1000)); // 2000-01-01 + break; + default: + buf.readUnsignedInt(); + break; + } + } + + paramCount = buf.readUnsignedByte(); + for (int j = 0; j < paramCount; j++) { + buf.readUnsignedByte(); // id + buf.skipBytes(buf.readUnsignedByte()); // value + } + + positions.add(position); + } + + return positions; + } + + private void requestPhotoPacket(Channel channel, String imei, int index) { + if (channel != null) { + String content = "D00,camera_picture.jpg," + index; + int length = 1 + imei.length() + 1 + content.length() + 5; + String response = String.format("@@O%02d,%s,%s*", length, imei, content); + response += Checksum.sum(response) + "\r\n"; + channel.write(response); + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -315,25 +420,49 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { ChannelBuffer buf = (ChannelBuffer) msg; int index = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) ','); + String imei = buf.toString(index + 1, 15, StandardCharsets.US_ASCII); index = buf.indexOf(index + 1, buf.writerIndex(), (byte) ','); - String type = buf.toString(index + 1, 3, StandardCharsets.US_ASCII); + switch (type) { - case "D03": - if (channel != null) { - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - String imei = Context.getIdentityManager().getById(deviceSession.getDeviceId()).getUniqueId(); - String content = "D00,camera_picture.jpg,0"; - int length = 1 + imei.length() + 1 + content.length() + 5; - String response = String.format("@@O%02d,%s,%s*", length, imei, content); - response += Checksum.sum(response) + "\r\n"; - channel.write(response); + case "D00": + index = buf.indexOf(index + 1 + type.length() + 1, buf.writerIndex(), (byte) ',') + 1; + int endIndex = buf.indexOf(index, buf.writerIndex(), (byte) ','); + int total = Integer.parseInt(buf.toString(index, endIndex - index, StandardCharsets.US_ASCII)); + index = endIndex + 1; + endIndex = buf.indexOf(index, buf.writerIndex(), (byte) ','); + int current = Integer.parseInt(buf.toString(index, endIndex - index, StandardCharsets.US_ASCII)); + + buf.readerIndex(endIndex + 1); + photo.writeBytes(buf.readBytes(buf.readableBytes() - 1 - 2 - 2)); + + if (current == total - 1) { + Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(getDeviceSession(channel, remoteAddress, imei).getDeviceId()); + + getLastLocation(position, null); + + position.set(Position.KEY_IMAGE, Context.getMediaManager().writeFile(imei, photo, "jpg")); + photo = null; + + return position; + } else { + if ((current + 1) % 8 == 0) { + requestPhotoPacket(channel, imei, current + 1); + } + return null; } + case "D03": + photo = ChannelBuffers.dynamicBuffer(); + requestPhotoPacket(channel, imei, 0); return null; case "CCC": - return decodeBinaryMessage(channel, remoteAddress, buf); + return decodeBinaryC(channel, remoteAddress, buf); + case "CCE": + return decodeBinaryE(channel, remoteAddress, buf); default: - return decodeRegularMessage(channel, remoteAddress, buf); + return decodeRegular(channel, remoteAddress, buf); } } diff --git a/src/org/traccar/protocol/TotemProtocolDecoder.java b/src/org/traccar/protocol/TotemProtocolDecoder.java index 3c2dee8ec..a3e8c9921 100644 --- a/src/org/traccar/protocol/TotemProtocolDecoder.java +++ b/src/org/traccar/protocol/TotemProtocolDecoder.java @@ -131,7 +131,7 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { private static final Pattern PATTERN4 = new PatternBuilder() .text("$$") // header .number("dddd") // length - .text("AA") // type + .expression("A[ABC]") // type .number("(d+)|") // imei .number("(x{8})") // status .number("(dd)(dd)(dd)") // date (yymmdd) @@ -182,15 +182,138 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { } } + private boolean decode12(Position position, Parser parser, Pattern pattern) { + + if (parser.hasNext()) { + position.set(Position.KEY_ALARM, decodeAlarm(Short.parseShort(parser.next(), 16))); + } + DateBuilder dateBuilder = new DateBuilder(); + int year = 0, month = 0, day = 0; + if (pattern == PATTERN2) { + day = parser.nextInt(0); + month = parser.nextInt(0); + year = parser.nextInt(0); + } + dateBuilder.setTime(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0)); + + position.setValid(parser.next().equals("A")); + position.setLatitude(parser.nextCoordinate()); + position.setLongitude(parser.nextCoordinate()); + position.setSpeed(parser.nextDouble(0)); + position.setCourse(parser.nextDouble(0)); + + if (pattern == PATTERN1) { + day = parser.nextInt(0); + month = parser.nextInt(0); + year = parser.nextInt(0); + } + if (year == 0) { + return false; // ignore invalid data + } + dateBuilder.setDate(year, month, day); + position.setTime(dateBuilder.getDate()); + + if (pattern == PATTERN1) { + position.set(Position.KEY_PDOP, parser.nextDouble()); + position.set(Position.KEY_HDOP, parser.nextDouble()); + position.set(Position.KEY_VDOP, parser.nextDouble()); + } else { + position.set(Position.KEY_HDOP, parser.nextDouble()); + } + + position.set(Position.PREFIX_IO + 1, parser.next()); + if (pattern == PATTERN1) { + position.set(Position.KEY_BATTERY, parser.nextDouble(0) * 0.01); + } else { + position.set(Position.KEY_BATTERY, parser.nextDouble(0) * 0.1); + } + position.set(Position.KEY_POWER, parser.nextDouble(0)); + position.set(Position.PREFIX_ADC + 1, parser.next()); + + int lac = parser.nextHexInt(0); + int cid = parser.nextHexInt(0); + if (lac != 0 && cid != 0) { + position.setNetwork(new Network(CellTower.fromLacCid(lac, cid))); + } + + position.set(Position.PREFIX_TEMP + 1, parser.next()); + position.set(Position.KEY_ODOMETER, parser.nextDouble(0) * 1000); + + return true; + } + + private boolean decode3(Position position, Parser parser) { + + if (parser.hasNext()) { + position.set(Position.KEY_ALARM, decodeAlarm(Short.parseShort(parser.next(), 16))); + } + + position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS)); + + position.set(Position.PREFIX_IO + 1, parser.next()); + position.set(Position.KEY_BATTERY, parser.nextDouble(0) * 0.1); + position.set(Position.KEY_POWER, parser.nextDouble(0)); + position.set(Position.PREFIX_ADC + 1, parser.next()); + position.set(Position.PREFIX_ADC + 2, parser.next()); + position.set(Position.PREFIX_TEMP + 1, parser.next()); + position.set(Position.PREFIX_TEMP + 2, parser.next()); + + position.setNetwork(new Network( + CellTower.fromLacCid(parser.nextHexInt(0), parser.nextHexInt(0)))); + + position.setValid(parser.next().equals("A")); + position.set(Position.KEY_SATELLITES, parser.nextInt()); + position.setCourse(parser.nextDouble(0)); + position.setSpeed(parser.nextDouble(0)); + position.set(Position.KEY_PDOP, parser.nextDouble()); + position.set(Position.KEY_ODOMETER, parser.nextInt(0) * 1000); + + position.setLatitude(parser.nextCoordinate()); + position.setLongitude(parser.nextCoordinate()); + + return true; + } + + private boolean decode4(Position position, Parser parser) { + + position.set(Position.KEY_STATUS, parser.next()); + + position.setTime(parser.nextDateTime()); + + position.set(Position.KEY_BATTERY, parser.nextDouble(0) * 0.1); + position.set(Position.KEY_POWER, parser.nextDouble(0)); + + position.set(Position.PREFIX_ADC + 1, parser.next()); + position.set(Position.PREFIX_ADC + 2, parser.next()); + position.set(Position.PREFIX_ADC + 3, parser.next()); + position.set(Position.PREFIX_ADC + 4, parser.next()); + position.set(Position.PREFIX_TEMP + 1, parser.next()); + position.set(Position.PREFIX_TEMP + 2, parser.next()); + + CellTower cellTower = CellTower.fromLacCid(parser.nextHexInt(0), parser.nextHexInt(0)); + position.set(Position.KEY_SATELLITES, parser.nextInt(0)); + cellTower.setSignalStrength(parser.nextInt(0)); + position.setNetwork(new Network(cellTower)); + + position.setCourse(parser.nextDouble(0)); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0))); + position.set(Position.KEY_HDOP, parser.nextDouble(0)); + position.set(Position.KEY_ODOMETER, parser.nextInt(0) * 1000); + + position.setValid(true); + position.setLatitude(parser.nextCoordinate()); + position.setLongitude(parser.nextCoordinate()); + + return true; + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { String sentence = (String) msg; - - // Determine format Pattern pattern = PATTERN3; - if (sentence.indexOf("AA") == 6) { + if (sentence.indexOf("A") == 6) { pattern = PATTERN4; } else if (sentence.contains("$GPRMC")) { pattern = PATTERN1; @@ -215,123 +338,24 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { } position.setDeviceId(deviceSession.getDeviceId()); + boolean result; if (pattern == PATTERN1 || pattern == PATTERN2) { - if (parser.hasNext()) { - position.set(Position.KEY_ALARM, decodeAlarm(Short.parseShort(parser.next(), 16))); - } - DateBuilder dateBuilder = new DateBuilder(); - int year = 0, month = 0, day = 0; - if (pattern == PATTERN2) { - day = parser.nextInt(0); - month = parser.nextInt(0); - year = parser.nextInt(0); - } - dateBuilder.setTime(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0)); - - position.setValid(parser.next().equals("A")); - position.setLatitude(parser.nextCoordinate()); - position.setLongitude(parser.nextCoordinate()); - position.setSpeed(parser.nextDouble(0)); - position.setCourse(parser.nextDouble(0)); - - if (pattern == PATTERN1) { - day = parser.nextInt(0); - month = parser.nextInt(0); - year = parser.nextInt(0); - } - if (year == 0) { - return null; // ignore invalid data - } - dateBuilder.setDate(year, month, day); - position.setTime(dateBuilder.getDate()); - - if (pattern == PATTERN1) { - position.set(Position.KEY_PDOP, parser.nextDouble()); - position.set(Position.KEY_HDOP, parser.nextDouble()); - position.set(Position.KEY_VDOP, parser.nextDouble()); - } else { - position.set(Position.KEY_HDOP, parser.nextDouble()); - } - - position.set(Position.PREFIX_IO + 1, parser.next()); - if (pattern == PATTERN1) { - position.set(Position.KEY_BATTERY, parser.nextDouble(0) * 0.01); - } else { - position.set(Position.KEY_BATTERY, parser.nextDouble(0) * 0.1); - } - position.set(Position.KEY_POWER, parser.nextDouble(0)); - position.set(Position.PREFIX_ADC + 1, parser.next()); - - int lac = parser.nextHexInt(0); - int cid = parser.nextHexInt(0); - if (lac != 0 && cid != 0) { - position.setNetwork(new Network(CellTower.fromLacCid(lac, cid))); - } - - position.set(Position.PREFIX_TEMP + 1, parser.next()); - position.set(Position.KEY_ODOMETER, parser.nextDouble(0) * 1000); - + result = decode12(position, parser, pattern); } else if (pattern == PATTERN3) { - if (parser.hasNext()) { - position.set(Position.KEY_ALARM, decodeAlarm(Short.parseShort(parser.next(), 16))); - } - - position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS)); - - position.set(Position.PREFIX_IO + 1, parser.next()); - position.set(Position.KEY_BATTERY, parser.nextDouble(0) * 0.1); - position.set(Position.KEY_POWER, parser.nextDouble(0)); - position.set(Position.PREFIX_ADC + 1, parser.next()); - position.set(Position.PREFIX_ADC + 2, parser.next()); - position.set(Position.PREFIX_TEMP + 1, parser.next()); - position.set(Position.PREFIX_TEMP + 2, parser.next()); - - position.setNetwork(new Network( - CellTower.fromLacCid(parser.nextHexInt(0), parser.nextHexInt(0)))); - - position.setValid(parser.next().equals("A")); - position.set(Position.KEY_SATELLITES, parser.nextInt()); - position.setCourse(parser.nextDouble(0)); - position.setSpeed(parser.nextDouble(0)); - position.set(Position.KEY_PDOP, parser.nextDouble()); - position.set(Position.KEY_ODOMETER, parser.nextInt(0) * 1000); - - position.setLatitude(parser.nextCoordinate()); - position.setLongitude(parser.nextCoordinate()); - - } else if (pattern == PATTERN4) { - position.set(Position.KEY_STATUS, parser.next()); - - position.setTime(parser.nextDateTime()); - - position.set(Position.KEY_BATTERY, parser.nextDouble(0) * 0.1); - position.set(Position.KEY_POWER, parser.nextDouble(0)); - - position.set(Position.PREFIX_ADC + 1, parser.next()); - position.set(Position.PREFIX_ADC + 2, parser.next()); - position.set(Position.PREFIX_ADC + 3, parser.next()); - position.set(Position.PREFIX_ADC + 4, parser.next()); - position.set(Position.PREFIX_TEMP + 1, parser.next()); - position.set(Position.PREFIX_TEMP + 2, parser.next()); - - CellTower cellTower = CellTower.fromLacCid(parser.nextHexInt(0), parser.nextHexInt(0)); - position.set(Position.KEY_SATELLITES, parser.nextInt(0)); - cellTower.setSignalStrength(parser.nextInt(0)); - position.setNetwork(new Network(cellTower)); - - position.setCourse(parser.nextDouble(0)); - position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0))); - position.set(Position.KEY_HDOP, parser.nextDouble(0)); - position.set(Position.KEY_ODOMETER, parser.nextInt(0) * 1000); - - position.setValid(true); - position.setLatitude(parser.nextCoordinate()); - position.setLongitude(parser.nextCoordinate()); + result = decode3(position, parser); + } else { + result = decode4(position, parser); } + if (channel != null) { - channel.write("ACK OK\r\n"); + if (pattern == PATTERN4) { + channel.write("$$0014AA" + sentence.substring(sentence.length() - 6)); + } else { + channel.write("ACK OK\r\n"); + } } - return position; + + return result ? position : null; } } diff --git a/test/org/traccar/protocol/DwayProtocolDecoderTest.java b/test/org/traccar/protocol/DwayProtocolDecoderTest.java new file mode 100644 index 000000000..481382535 --- /dev/null +++ b/test/org/traccar/protocol/DwayProtocolDecoderTest.java @@ -0,0 +1,30 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class DwayProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + DwayProtocolDecoder decoder = new DwayProtocolDecoder(new DwayProtocol()); + + verifyNull(decoder, text( + "AA55,36,10024,1,171025,161055,36.0294,-79.7881,201, 2.5,111,1000,0000,00000,3578,0,0,0,D")); + + verifyNull(decoder, text( + "AA55,115,318,1,171024,195059,28.0153,-82.4761,3, 1.0,319,1000,0000,00000,4244,0,0,0,D")); + + verifyNull(decoder, text( + "AA55,117,318,1,171025,153758,28.0152,-82.4759,19, 0.6,319,1000,0000,10000,4242,0,0,0,D")); + + verifyPosition(decoder, text( + "AA55,1,123456,1,140101,101132,22.5500,113.6770,75,70.5,320,1100,0011,1110,3950,33000,24000,12345678")); + + verifyNull(decoder, text( + ">H12345678")); + + } + +} diff --git a/test/org/traccar/protocol/FlespiProtocolDecoderTest.java b/test/org/traccar/protocol/FlespiProtocolDecoderTest.java new file mode 100644 index 000000000..b23da024a --- /dev/null +++ b/test/org/traccar/protocol/FlespiProtocolDecoderTest.java @@ -0,0 +1,24 @@ +package org.traccar.protocol; + +import org.jboss.netty.handler.codec.http.HttpMethod; +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class FlespiProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + FlespiProtocolDecoder decoder = new FlespiProtocolDecoder(new FlespiProtocol()); + + verifyPositions(decoder, request(HttpMethod.POST, "/", + buffer("[{\"position.speed\":0,\"position.latitude\":53.90573,\"time.valid.status\":true,\"timestamp\":1506956075,\"position.satellites\":10,\"message.buffered.status\":false,\"business.mode.status\":true,\"gps.status\":true,\"position.longitude\":27.455848,\"position.direction\":0,\"ident\":\"605630\"},{\"siren.status\":false,\"business.mode.status\":true,\"position.satellites\":8,\"timestamp\":1506695785,\"led.status\":false,\"position.latitude\":53.905569,\"position.longitude\":27.455986,\"position.speed\":0,\"gradual.stop.status\":false,\"position.direction\":262.643854,\"hardware.version.enum\":223,\"vehicle.mileage\":160,\"message.buffered.status\":false,\"blinkers.status\":false,\"ident\":\"605630\",\"position.altitude\":233.48,\"immobilizer.status\":false}]"))); + + verifyPositions(decoder, request(HttpMethod.POST, "/", + buffer("[{\"geofence.inside.status\":false,\"position.valid\":false,\"ain#4\":0,\"rs232.sensor.value#1\":0,\"position.direction\":0,\"rs232.sensor.value#0\":0,\"position.speed\":0,\"position.latitude\":0,\"refrigerator.sensor.temperature#1\":62.5,\"gnss.antenna.cut.status\":true,\"din#4\":3,\"ain#3\":0,\"refrigerator.sensor.temperature#3\":71.4,\"position.altitude\":0,\"din#2\":3,\"shock.event.trigger\":false,\"alarm.mode.status\":false,\"ibutton.event.connect\":false,\"refrigerator.sensor.temperature#4\":66.7,\"internal.battery.voltage.limit.lower.status\":false,\"ain#2\":0,\"gsm.signal.level\":0,\"refrigerator.connection.status\":0,\"position.satellites\":0,\"din#1\":3,\"external.powersource.voltage.range.outside.status\":false,\"refrigerator.sensor.temperature#2\":68.2,\"incline.event.trigger\":false,\"alarm.event.trigger\":false,\"movement.status\":true,\"refrigerator.sensor.temperature#6\":68.9,\"ident\":\"50\",\"timestamp\":946684840,\"engine.ignition.status\":true,\"gsm.sim.status\":true,\"record.seqnum\":8165,\"external.powersource.voltage\":15.298,\"gnss.enum\":\"glonass\",\"position.longitude\":0,\"battery.voltage\":4.088,\"refrigerator.sensor.temperature#5\":71.3,\"din#3\":3,\"ain#1\":0,\"internal.bus.supply.voltage.range.outside.status\":false},{\"geofence.inside.status\":false,\"position.valid\":true,\"ain#4\":0,\"rs232.sensor.value#1\":0,\"position.direction\":0,\"rs232.sensor.value#0\":0,\"position.speed\":0,\"position.latitude\":57.986744,\"refrigerator.sensor.temperature#1\":74.1,\"gnss.antenna.cut.status\":false,\"din#4\":3,\"ain#3\":0,\"position.hdop\":21.1,\"refrigerator.sensor.temperature#3\":71.4,\"position.altitude\":219,\"din#2\":3,\"shock.event.trigger\":false,\"alarm.mode.status\":false,\"ibutton.event.connect\":false,\"refrigerator.sensor.temperature#4\":70.5,\"internal.battery.voltage.limit.lower.status\":false,\"ain#2\":0,\"gsm.signal.level\":0,\"refrigerator.connection.status\":0,\"position.satellites\":5,\"din#1\":3,\"external.powersource.voltage.range.outside.status\":false,\"refrigerator.sensor.temperature#2\":71.3,\"incline.event.trigger\":false,\"alarm.event.trigger\":false,\"movement.status\":true,\"refrigerator.sensor.temperature#6\":69.3,\"ident\":\"50\",\"timestamp\":1392272112,\"engine.ignition.status\":true,\"gsm.sim.status\":true,\"record.seqnum\":8174,\"external.powersource.voltage\":15.303,\"gnss.enum\":\"glonass\",\"position.longitude\":56.207576,\"battery.voltage\":3.934,\"refrigerator.sensor.temperature#5\":68.1,\"din#3\":3,\"ain#1\":0,\"internal.bus.supply.voltage.range.outside.status\":false}]"))); + + verifyPositions(decoder, request(HttpMethod.POST, "/", + buffer("[{\"ain#1\":1,\"ain#2\":0,\"ain#3\":0,\"ain#4\":0,\"alarm.event.trigger\":true,\"custom.SOS\":1,\"custom.dparam\":3.141593,\"custom.ign\":1,\"custom.iparam\":-55,\"custom.tparam\":\"lorem\",\"din#1\":false,\"din#10\":false,\"din#11\":false,\"din#12\":false,\"din#13\":false,\"din#14\":false,\"din#15\":false,\"din#16\":false,\"din#17\":false,\"din#18\":false,\"din#19\":false,\"din#2\":false,\"din#20\":false,\"din#21\":false,\"din#22\":false,\"din#23\":false,\"din#24\":false,\"din#25\":false,\"din#26\":false,\"din#27\":false,\"din#28\":false,\"din#29\":false,\"din#3\":false,\"din#30\":false,\"din#31\":false,\"din#32\":false,\"din#4\":false,\"din#5\":false,\"din#6\":false,\"din#7\":false,\"din#8\":false,\"din#9\":false,\"dout#1\":false,\"dout#10\":false,\"dout#11\":false,\"dout#12\":false,\"dout#13\":false,\"dout#14\":false,\"dout#15\":false,\"dout#16\":false,\"dout#17\":false,\"dout#18\":false,\"dout#19\":false,\"dout#2\":false,\"dout#20\":false,\"dout#21\":false,\"dout#22\":false,\"dout#23\":false,\"dout#24\":false,\"dout#25\":false,\"dout#26\":false,\"dout#27\":false,\"dout#28\":false,\"dout#29\":false,\"dout#3\":false,\"dout#30\":false,\"dout#31\":false,\"dout#32\":false,\"dout#4\":false,\"dout#5\":false,\"dout#6\":false,\"dout#7\":false,\"dout#8\":false,\"dout#9\":false,\"ident\":\"namo:namo\",\"position.altitude\":300,\"position.direction\":0,\"position.hdop\":1.1,\"position.latitude\":53.90821,\"position.longitude\":27.524165,\"position.satellites\":7,\"position.speed\":0,\"timestamp\":1508508510.013227}]"))); + } + +}
\ No newline at end of file diff --git a/test/org/traccar/protocol/GenxProtocolDecoderTest.java b/test/org/traccar/protocol/GenxProtocolDecoderTest.java index 43d9e7d6e..9c49839c4 100644 --- a/test/org/traccar/protocol/GenxProtocolDecoderTest.java +++ b/test/org/traccar/protocol/GenxProtocolDecoderTest.java @@ -16,11 +16,14 @@ public class GenxProtocolDecoderTest extends ProtocolTest { verifyPosition(decoder, text( "000036004130,08/31/2017 17:24:37,45.47257,-73.65506,3,0,117,1.14,124,ON,1489,0,5,N,0,0.000,-95.0,-1.0,0,0.0000,0.0000,0.000,0,0.00,0.00,0.00,NA,U,UUU,0,-95.0,U")); - decoder.setReportColumns("1,2,3,4"); + decoder.setReportColumns("1,2,3,4,13,17,10,23,27,11,7,8,46,56,59,70,74,75,77,89,90,93,99,107,112,113,114,176,175,178,181,182"); verifyPosition(decoder, text( "000036035855,04/16/2017 21:19:07,45.46485,-73.65424,24,32,61:213,342.51,157,ON,20984,0,12,O,18,0.000,95.0,24.0,1990,64.0894,0.0219,316.009,71,0.00,16.78,5.10,NA,U,UUU,0,-95.0,U")); + verifyPosition(decoder, text( + "000036004129,10/20/2017 00:54:27,43.44638,-79.68616,36,310,6,4954.40,321,ON,35377,0,12,O,13,0.000,85.6,36.0,1573,451.2514,0.0012,5260.953,0,0.00,122.48,33.17,NA,U,UUU,0,-95.0,U")); + } } diff --git a/test/org/traccar/protocol/MeitrackProtocolDecoderTest.java b/test/org/traccar/protocol/MeitrackProtocolDecoderTest.java index 07411dbc8..4ec2211bc 100644 --- a/test/org/traccar/protocol/MeitrackProtocolDecoderTest.java +++ b/test/org/traccar/protocol/MeitrackProtocolDecoderTest.java @@ -11,6 +11,12 @@ public class MeitrackProtocolDecoderTest extends ProtocolTest { MeitrackProtocolDecoder decoder = new MeitrackProtocolDecoder(new MeitrackProtocol()); + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "24245f3237382c3836353738393032313434373233322c4343452c5b00000003005000130006012305010608070d15001b0006080000091e010a09000b2e0019a1011af90106025c033300039be60c06044f6678210c6f1806000d48db06001c41000000010e0cf60113002005912b830001ff5000130006012305010608070d15001b0006080000091e010a09000b2e0019a0011af90106025c033300039be60c0604506678210c6f1806000d49db06001c41000000010e0cf60113002005912b830001ff5000130006012305010608070d15001b0006080000091e010a09000b2e0019a1011af90106025c033300039be60c0604516678210c6f1806000d4adb06001c41000000010e0cf60113002005912b830001ff2a37460d0a")); + + verifyPosition(decoder, buffer( + "$$V177,863835026871173,AAA,35,34.516428,10.470160,170915154043,A,9,12,68,74,0.9,9,1988259,525882,605|2|008C|0007B5A6,0200,0003|0000|0000|01A6|0571,00000001,,3,0000,06FB2E,360,511*74")); + verifyPosition(decoder, buffer( "$$V177,863835026871173,AAA,35,34.516428,10.470160,170915154043,A,9,12,68,74,0.9,9,1988259,525882,605|2|008C|0007B5A6,0200,0003|0000|0000|01A6|0571,00000001,,3,0000,010A92,360,511*74")); diff --git a/test/org/traccar/protocol/TotemProtocolDecoderTest.java b/test/org/traccar/protocol/TotemProtocolDecoderTest.java index 40d8d9eba..67c75e08d 100644 --- a/test/org/traccar/protocol/TotemProtocolDecoderTest.java +++ b/test/org/traccar/protocol/TotemProtocolDecoderTest.java @@ -11,6 +11,12 @@ public class TotemProtocolDecoderTest extends ProtocolTest { TotemProtocolDecoder decoder = new TotemProtocolDecoder(new TotemProtocol()); verifyPosition(decoder, text( + "$$0108AB863835028447675|5004C0001710250234064214059828A058AE121010604000.600000320304.7772N10134.8238E11625B")); + + verifyPosition(decoder, text( + "$$0108AA863835028447675|5004C0001710250234134114057728A058AE112108305100.600000660304.7787N10134.8719E116458")); + + verifyPosition(decoder, text( "$$0112AA864244026065291|180018001409160205244011000027BA0E57063100000001.200000002237.8119N11403.5075E05202D")); verifyPosition(decoder, text( diff --git a/test/org/traccar/protocol/WatchFrameDecoderTest.java b/test/org/traccar/protocol/WatchFrameDecoderTest.java index c705b24b3..664501a43 100644 --- a/test/org/traccar/protocol/WatchFrameDecoderTest.java +++ b/test/org/traccar/protocol/WatchFrameDecoderTest.java @@ -1,6 +1,5 @@ package org.traccar.protocol; -import org.junit.Assert; import org.junit.Test; import org.traccar.ProtocolTest; @@ -11,11 +10,11 @@ public class WatchFrameDecoderTest extends ProtocolTest { WatchFrameDecoder decoder = new WatchFrameDecoder(); - Assert.assertEquals( + verifyFrame( binary("5b33472a383330383430363237392a303030382a72636170747572655d"), decoder.decode(null, null, binary("5b33472a383330383430363237392a303030382a72636170747572655d"))); - Assert.assertEquals( + verifyFrame( binary("5b33472a383330383430363237392a303030392a4c4b2c302c302c38345d"), decoder.decode(null, null, binary("5b33472a383330383430363237392a303030392a4c4b2c302c302c38345d"))); |