From 911c44c63567dff7af58544d998adc22d23df672 Mon Sep 17 00:00:00 2001 From: Kostiantyn Luzan Date: Sun, 25 Feb 2018 02:33:06 +0200 Subject: Add support for OpenGTS compatible clients (GPSLogger for Android) Signed-off-by: Kostiantyn Luzan --- setup/default.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 2c4f45712..6be2c08e3 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -227,5 +227,6 @@ 5156 5157 5158 + 5159 -- cgit v1.2.3 From b2ab0b471591494523b12e5f1810a481b2cd1a65 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 12 Mar 2018 06:44:27 +1300 Subject: Cautela NMEA conversion protocol --- setup/default.xml | 1 + src/org/traccar/protocol/CautelaProtocol.java | 47 +++++++++++++ .../traccar/protocol/CautelaProtocolDecoder.java | 77 ++++++++++++++++++++++ .../protocol/CautelaProtocolDecoderTest.java | 18 +++++ 4 files changed, 143 insertions(+) create mode 100644 src/org/traccar/protocol/CautelaProtocol.java create mode 100644 src/org/traccar/protocol/CautelaProtocolDecoder.java create mode 100644 test/org/traccar/protocol/CautelaProtocolDecoderTest.java (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 6be2c08e3..81a3cd128 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -228,5 +228,6 @@ 5157 5158 5159 + 5160 diff --git a/src/org/traccar/protocol/CautelaProtocol.java b/src/org/traccar/protocol/CautelaProtocol.java new file mode 100644 index 000000000..89ab7a1d0 --- /dev/null +++ b/src/org/traccar/protocol/CautelaProtocol.java @@ -0,0 +1,47 @@ +/* + * Copyright 2018 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 CautelaProtocol extends BaseProtocol { + + public CautelaProtocol() { + super("cautela"); + } + + @Override + public void initTrackerServers(List 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 CautelaProtocolDecoder(CautelaProtocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/CautelaProtocolDecoder.java b/src/org/traccar/protocol/CautelaProtocolDecoder.java new file mode 100644 index 000000000..94ba35c91 --- /dev/null +++ b/src/org/traccar/protocol/CautelaProtocolDecoder.java @@ -0,0 +1,77 @@ +/* + * Copyright 2018 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.DateBuilder; +import org.traccar.helper.Parser; +import org.traccar.helper.PatternBuilder; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.util.regex.Pattern; + +public class CautelaProtocolDecoder extends BaseProtocolDecoder { + + public CautelaProtocolDecoder(CautelaProtocol protocol) { + super(protocol); + } + + private static final Pattern PATTERN = new PatternBuilder() + .number("(d+),") // type + .number("(d+),") // imei + .number("(dd),(dd),(dd),") // date (ddmmyy) + .number("(-?d+.d+),") // longitude + .number("(-?d+.d+),") // latitude + .number("(dd)(dd),") // time (hhmm) + .any() + .compile(); + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + Parser parser = new Parser(PATTERN, (String) msg); + if (!parser.matches()) { + return null; + } + + String type = parser.next(); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); + if (deviceSession == null) { + return null; + } + + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + DateBuilder dateBuilder = new DateBuilder(); + dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()); + + position.setValid(true); + position.setLongitude(parser.nextDouble()); + position.setLatitude(parser.nextDouble()); + + dateBuilder.setHour(parser.nextInt()).setMinute(parser.nextInt()); + position.setTime(dateBuilder.getDate()); + + return position; + } + +} diff --git a/test/org/traccar/protocol/CautelaProtocolDecoderTest.java b/test/org/traccar/protocol/CautelaProtocolDecoderTest.java new file mode 100644 index 000000000..4fd785c9f --- /dev/null +++ b/test/org/traccar/protocol/CautelaProtocolDecoderTest.java @@ -0,0 +1,18 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class CautelaProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + CautelaProtocolDecoder decoder = new CautelaProtocolDecoder(new CautelaProtocol()); + + verifyPosition(decoder, text( + "20,010907000000,14,02,18,16.816667,96.166667,1325,S,*2E")); + + } + +} -- cgit v1.2.3 From 2a30c9de983223a3af1070543975165ceb0710f9 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 14 Mar 2018 05:27:23 +1300 Subject: Option to ignore duplicate alarms --- setup/default.xml | 1 + src/org/traccar/events/AlertEventHandler.java | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 81a3cd128..8701ddc4c 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -19,6 +19,7 @@ ./logs/tracker-server.log true + true true ./media diff --git a/src/org/traccar/events/AlertEventHandler.java b/src/org/traccar/events/AlertEventHandler.java index 003ccb662..7db371c70 100644 --- a/src/org/traccar/events/AlertEventHandler.java +++ b/src/org/traccar/events/AlertEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2018 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. @@ -19,18 +19,34 @@ import java.util.Collections; import java.util.Map; import org.traccar.BaseEventHandler; +import org.traccar.Context; import org.traccar.model.Event; import org.traccar.model.Position; public class AlertEventHandler extends BaseEventHandler { + private final boolean ignoreDuplicateAlerts; + + public AlertEventHandler() { + ignoreDuplicateAlerts = Context.getConfig().getBoolean("event.ignoreDuplicateAlerts"); + } + @Override protected Map analyzePosition(Position position) { Object alarm = position.getAttributes().get(Position.KEY_ALARM); if (alarm != null) { - Event event = new Event(Event.TYPE_ALARM, position.getDeviceId(), position.getId()); - event.set(Position.KEY_ALARM, (String) alarm); - return Collections.singletonMap(event, position); + boolean ignoreAlert = false; + if (ignoreDuplicateAlerts) { + Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId()); + if (lastPosition != null && alarm.equals(lastPosition.getAttributes().get(Position.KEY_ALARM))) { + ignoreAlert = true; + } + } + if (!ignoreAlert) { + Event event = new Event(Event.TYPE_ALARM, position.getDeviceId(), position.getId()); + event.set(Position.KEY_ALARM, (String) alarm); + return Collections.singletonMap(event, position); + } } return null; } -- cgit v1.2.3 From 38c1ff9bccc1c417a0c2b412271aa7240a3b7db7 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 16 Mar 2018 22:57:59 +1300 Subject: Implement Continental RVS protocol --- setup/default.xml | 1 + src/org/traccar/protocol/ContinentalProtocol.java | 43 ++++++++++ .../protocol/ContinentalProtocolDecoder.java | 93 ++++++++++++++++++++++ .../protocol/ContinentalProtocolDecoderTest.java | 25 ++++++ 4 files changed, 162 insertions(+) create mode 100644 src/org/traccar/protocol/ContinentalProtocol.java create mode 100644 src/org/traccar/protocol/ContinentalProtocolDecoder.java create mode 100644 test/org/traccar/protocol/ContinentalProtocolDecoderTest.java (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 8701ddc4c..68465011e 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -230,5 +230,6 @@ 5158 5159 5160 + 5161 diff --git a/src/org/traccar/protocol/ContinentalProtocol.java b/src/org/traccar/protocol/ContinentalProtocol.java new file mode 100644 index 000000000..e2b1226cf --- /dev/null +++ b/src/org/traccar/protocol/ContinentalProtocol.java @@ -0,0 +1,43 @@ +/* + * Copyright 2018 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.LengthFieldBasedFrameDecoder; +import org.traccar.BaseProtocol; +import org.traccar.TrackerServer; + +import java.util.List; + +public class ContinentalProtocol extends BaseProtocol { + + public ContinentalProtocol() { + super("continental"); + } + + @Override + public void initTrackerServers(List serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 2, 2)); + pipeline.addLast("objectDecoder", new ContinentalProtocolDecoder(ContinentalProtocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/ContinentalProtocolDecoder.java b/src/org/traccar/protocol/ContinentalProtocolDecoder.java new file mode 100644 index 000000000..2138eb39e --- /dev/null +++ b/src/org/traccar/protocol/ContinentalProtocolDecoder.java @@ -0,0 +1,93 @@ +/* + * Copyright 2018 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.buffer.ChannelBuffer; +import org.jboss.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.helper.UnitsConverter; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.util.Date; + +public class ContinentalProtocolDecoder extends BaseProtocolDecoder { + + public ContinentalProtocolDecoder(ContinentalProtocol protocol) { + super(protocol); + } + + public static final int MSG_KEEPALIVE = 0x00; + public static final int MSG_STATUS = 0x02; + public static final int MSG_ACK = 0x06; + public static final int MSG_NACK = 0x15; + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ChannelBuffer buf = (ChannelBuffer) msg; + + buf.skipBytes(2); // header + buf.readUnsignedShort(); // length + buf.readUnsignedByte(); // software version + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(buf.readUnsignedInt())); + if (deviceSession == null) { + return null; + } + + buf.readUnsignedByte(); // product + + int type = buf.readUnsignedByte(); + + if (type == MSG_STATUS) { + + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setFixTime(new Date(buf.readUnsignedInt() * 1000L)); + + buf.readUnsignedByte(); + position.setLatitude(buf.readMedium() / 3600.0); + + buf.readUnsignedByte(); + position.setLongitude(buf.readMedium() / 3600.0); + + position.setCourse(buf.readUnsignedShort()); + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort())); + + position.setValid(buf.readUnsignedByte() > 0); + + position.setDeviceTime(new Date(buf.readUnsignedInt() * 1000L)); + + position.set(Position.KEY_EVENT, buf.readUnsignedShort()); + position.set(Position.KEY_INPUT, buf.readUnsignedShort()); + position.set(Position.KEY_OUTPUT, buf.readUnsignedShort()); + position.set(Position.KEY_BATTERY, buf.readUnsignedByte()); + position.set(Position.KEY_DEVICE_TEMP, buf.readByte()); + + buf.readUnsignedShort(); // reserved + + return position; + + } + + return null; + } + +} diff --git a/test/org/traccar/protocol/ContinentalProtocolDecoderTest.java b/test/org/traccar/protocol/ContinentalProtocolDecoderTest.java new file mode 100644 index 000000000..fbc7c3219 --- /dev/null +++ b/test/org/traccar/protocol/ContinentalProtocolDecoderTest.java @@ -0,0 +1,25 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class ContinentalProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + ContinentalProtocolDecoder decoder = new ContinentalProtocolDecoder(new ContinentalProtocol()); + + verifyPosition(decoder, binary( + "5356002A1100003039030243A68B5700FEB5AB00FD715F012700000143A68B57000E000000000C2F00000130"), + position("2005-12-19 10:28:39.000", true, -23.49027, -46.55138)); + + verifyPosition(decoder, binary( + "5356002a0d0010a12403025a9ea47f00feb48400fd6e63000c0000015a9ea480000e000100000c000000")); + + verifyPosition(decoder, binary( + "5356002a0d0010a1240302581b944100febed800fd9fa30139001300581c73fa000e000000000d000001")); + + } + +} -- cgit v1.2.3 From 3449aa51dc8250ba38772b39deb48f1f76be08c1 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 21 Mar 2018 11:36:45 +1300 Subject: Fix config issue --- setup/default.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 68465011e..1b106d2d0 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -230,6 +230,6 @@ 5158 5159 5160 - 5161 + 5161 -- cgit v1.2.3 From feaa6e2f2816efad85bdb3a29e40bd2313e65475 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 23 Mar 2018 05:38:03 +1300 Subject: Initial EGTS protocol implementation --- setup/default.xml | 1 + src/org/traccar/protocol/EgtsFrameDecoder.java | 45 +++++++ src/org/traccar/protocol/EgtsProtocol.java | 42 ++++++ src/org/traccar/protocol/EgtsProtocolDecoder.java | 149 +++++++++++++++++++++ .../org/traccar/protocol/EgtsFrameDecoderTest.java | 21 +++ .../traccar/protocol/EgtsProtocolDecoderTest.java | 27 ++++ 6 files changed, 285 insertions(+) create mode 100644 src/org/traccar/protocol/EgtsFrameDecoder.java create mode 100644 src/org/traccar/protocol/EgtsProtocol.java create mode 100644 src/org/traccar/protocol/EgtsProtocolDecoder.java create mode 100644 test/org/traccar/protocol/EgtsFrameDecoderTest.java create mode 100644 test/org/traccar/protocol/EgtsProtocolDecoderTest.java (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 1b106d2d0..912006bcf 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -231,5 +231,6 @@ 5159 5160 5161 + 5162 diff --git a/src/org/traccar/protocol/EgtsFrameDecoder.java b/src/org/traccar/protocol/EgtsFrameDecoder.java new file mode 100644 index 000000000..71ffc1811 --- /dev/null +++ b/src/org/traccar/protocol/EgtsFrameDecoder.java @@ -0,0 +1,45 @@ +/* + * Copyright 2018 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.buffer.ChannelBuffer; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.frame.FrameDecoder; + +public class EgtsFrameDecoder extends FrameDecoder { + + @Override + protected Object decode( + ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { + + if (buf.readableBytes() < 10) { + return null; + } + + int headerLength = buf.getUnsignedByte(buf.readerIndex() + 3); + int frameLength = buf.getUnsignedShort(buf.readerIndex() + 5); + + int length = headerLength + frameLength + (frameLength > 0 ? 2 : 0); + + if (buf.readableBytes() >= length) { + return buf.readBytes(length); + } + + return null; + } + +} diff --git a/src/org/traccar/protocol/EgtsProtocol.java b/src/org/traccar/protocol/EgtsProtocol.java new file mode 100644 index 000000000..0a57f0061 --- /dev/null +++ b/src/org/traccar/protocol/EgtsProtocol.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018 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.traccar.BaseProtocol; +import org.traccar.TrackerServer; + +import java.util.List; + +public class EgtsProtocol extends BaseProtocol { + + public EgtsProtocol() { + super("egts"); + } + + @Override + public void initTrackerServers(List serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new EgtsFrameDecoder()); + pipeline.addLast("objectDecoder", new EgtsProtocolDecoder(EgtsProtocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/EgtsProtocolDecoder.java b/src/org/traccar/protocol/EgtsProtocolDecoder.java new file mode 100644 index 000000000..f32f564ed --- /dev/null +++ b/src/org/traccar/protocol/EgtsProtocolDecoder.java @@ -0,0 +1,149 @@ +/* + * Copyright 2018 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.buffer.ChannelBuffer; +import org.jboss.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.helper.BitUtil; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +public class EgtsProtocolDecoder extends BaseProtocolDecoder { + + public EgtsProtocolDecoder(EgtsProtocol protocol) { + super(protocol); + } + + public static final int SERVICE_AUTH = 1; + public static final int SERVICE_TELEDATA = 2; + public static final int SERVICE_COMMANDS = 4; + public static final int SERVICE_FIRMWARE = 9; + public static final int SERVICE_ECALL = 10; + + public static final int MSG_RECORD_RESPONSE = 0; + public static final int MSG_TERM_IDENTITY = 1; + public static final int MSG_MODULE_DATA = 2; + public static final int MSG_VEHICLE_DATA = 3; + public static final int MSG_AUTH_PARAMS = 4; + public static final int MSG_AUTH_INFO = 5; + public static final int MSG_SERVICE_INFO = 6; + public static final int MSG_RESULT_CODE = 7; + public static final int MSG_POS_DATA = 16; + public static final int MSG_EXT_POS_DATA = 17; + public static final int MSG_AD_SENSORS_DATA = 18; + public static final int MSG_COUNTERS_DATA = 19; + public static final int MSG_STATE_DATA = 20; + public static final int MSG_LOOPIN_DATA = 22; + public static final int MSG_ABS_DIG_SENS_DATA = 23; + public static final int MSG_ABS_AN_SENS_DATA = 24; + public static final int MSG_ABS_CNTR_DATA = 25; + public static final int MSG_ABS_LOOPIN_DATA = 26; + public static final int MSG_LIQUID_LEVEL_SENSOR = 27; + public static final int MSG_PASSENGERS_COUNTERS = 28; + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ChannelBuffer buf = (ChannelBuffer) msg; + + buf.skipBytes(buf.getUnsignedByte(buf.readerIndex() + 3)); + + DeviceSession deviceSession = null; + List positions = new LinkedList<>(); + + while (buf.readableBytes() > 2) { + + int length = buf.readUnsignedShort(); + + buf.readUnsignedShort(); // index + + int flags = buf.readUnsignedByte(); + + if (BitUtil.check(flags, 0)) { + String deviceId = String.valueOf(buf.readUnsignedInt()); + if (deviceSession == null) { + deviceSession = getDeviceSession(channel, remoteAddress, deviceId); + } + } + + if (deviceSession == null) { + deviceSession = getDeviceSession(channel, remoteAddress); + } + + if (BitUtil.check(flags, 1)) { + buf.readUnsignedInt(); // event id + } + if (BitUtil.check(flags, 2)) { + buf.readUnsignedInt(); // time + } + + buf.readUnsignedByte(); // source service type + buf.readUnsignedByte(); // recipient service type + + int recordEnd = buf.readerIndex() + length; + + while (buf.readerIndex() < recordEnd) { + int type = buf.readUnsignedByte(); + int end = buf.readUnsignedShort() + buf.readerIndex(); + + if (type == MSG_POS_DATA) { + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setTime(new Date((buf.readUnsignedInt() + 1262304000) * 1000)); // since 2010-01-01 + position.setLatitude(buf.readUnsignedInt() * 90.0 / 0xFFFFFFFFL); + position.setLongitude(buf.readUnsignedInt() * 180.0 / 0xFFFFFFFFL); + + int positionFlags = buf.readUnsignedByte(); + position.setValid(BitUtil.check(positionFlags, 0)); + if (BitUtil.check(positionFlags, 5)) { + position.setLatitude(-position.getLatitude()); + } + if (BitUtil.check(positionFlags, 6)) { + position.setLongitude(-position.getLongitude()); + } + + int speed = buf.readUnsignedShort(); + position.setSpeed(BitUtil.to(speed, 14)); + position.setCourse(buf.readUnsignedByte() + (BitUtil.check(speed, 15) ? 0x100 : 0)); + + position.set(Position.KEY_ODOMETER, buf.readUnsignedMedium() * 100); + position.set(Position.KEY_INPUT, buf.readUnsignedByte()); + position.set(Position.KEY_EVENT, buf.readUnsignedByte()); + + if (BitUtil.check(positionFlags, 7)) { + position.setAltitude(buf.readMedium()); + } + + positions.add(position); + } + + buf.readerIndex(end); + } + + } + + return positions.isEmpty() ? null : positions; + } + +} diff --git a/test/org/traccar/protocol/EgtsFrameDecoderTest.java b/test/org/traccar/protocol/EgtsFrameDecoderTest.java new file mode 100644 index 000000000..91a53525e --- /dev/null +++ b/test/org/traccar/protocol/EgtsFrameDecoderTest.java @@ -0,0 +1,21 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +import java.nio.ByteOrder; + +public class EgtsFrameDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + EgtsFrameDecoder decoder = new EgtsFrameDecoder(); + + verifyFrame( + binary("0100020B0025003A5701C91A003A5701CD6E68490202101700CBB4740F7617FD924364104F116A0000000000010300001EC2"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "0100020B0025003A5701C91A003A5701CD6E68490202101700CBB4740F7617FD924364104F116A0000000000010300001EC2"))); + + } + +} diff --git a/test/org/traccar/protocol/EgtsProtocolDecoderTest.java b/test/org/traccar/protocol/EgtsProtocolDecoderTest.java new file mode 100644 index 000000000..9a3434bec --- /dev/null +++ b/test/org/traccar/protocol/EgtsProtocolDecoderTest.java @@ -0,0 +1,27 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +import java.nio.ByteOrder; + +public class EgtsProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + EgtsProtocolDecoder decoder = new EgtsProtocolDecoder(new EgtsProtocol()); + + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "0100020B0025003A5701C91A003A5701CD6E68490202101700CBB4740F7617FD924364104F116A0000000000010300001EC2"), + position("2018-03-21 05:38:19.000", true, 51.67569, 55.59189)); + + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "0100020B0079000000011F6A001424951CA5CB0F23B5740F020210180023B5740F0A301994DA9C524C9128000A000000100082000011040018110300120900000003150100E803001B0700010000340900001B0700420000000000001B0700430000000000001B0700440000000000001B0700450000000000001B0700460000000000008020")); + + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "0100020B00F200000001D66A001224951CA5CB0FFCB4740F0202101800FCB4740F502119943D9F524C9119805C000000100084000011040018110300120900000003150100E803001B0700410000000000001B0700420000000000001B0700430000000000001B0700440000000000001B0700450000000000001B0700460000000000006A001324951CA5CB0F05B5740F020210180005B5740F222519942D9E524C9100008B000000100083000011040018110300120900000003160100E803001B0700010000310900001B0700420000000000001B0700430000000000001B0700440000000000001B0700450000000000001B070046000000000000134E")); + + } + +} -- cgit v1.2.3 From 2fa162dd6043fb8b329d3ec7b306ade76d5007b8 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 24 Mar 2018 10:57:03 +1300 Subject: Enable future filtering by default --- setup/default.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 912006bcf..1788cb901 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -18,6 +18,9 @@ all ./logs/tracker-server.log + true + 3600 + true true true -- cgit v1.2.3 From a959b3d754a2bd9e0f8a3b73b01061c88fe46053 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 27 Mar 2018 05:55:40 +1300 Subject: Implement RoboTrack protocol --- setup/default.xml | 1 + .../traccar/protocol/RoboTrackFrameDecoder.java | 57 +++++++++ src/org/traccar/protocol/RoboTrackProtocol.java | 45 +++++++ .../traccar/protocol/RoboTrackProtocolDecoder.java | 130 +++++++++++++++++++++ .../protocol/RoboTrackFrameDecoderTest.java | 19 +++ .../protocol/RoboTrackProtocolDecoderTest.java | 18 +++ 6 files changed, 270 insertions(+) create mode 100644 src/org/traccar/protocol/RoboTrackFrameDecoder.java create mode 100644 src/org/traccar/protocol/RoboTrackProtocol.java create mode 100644 src/org/traccar/protocol/RoboTrackProtocolDecoder.java create mode 100644 test/org/traccar/protocol/RoboTrackFrameDecoderTest.java create mode 100644 test/org/traccar/protocol/RoboTrackProtocolDecoderTest.java (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 1788cb901..7996ce716 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -235,5 +235,6 @@ 5160 5161 5162 + 5163 diff --git a/src/org/traccar/protocol/RoboTrackFrameDecoder.java b/src/org/traccar/protocol/RoboTrackFrameDecoder.java new file mode 100644 index 000000000..af215103c --- /dev/null +++ b/src/org/traccar/protocol/RoboTrackFrameDecoder.java @@ -0,0 +1,57 @@ +/* + * Copyright 2018 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.buffer.ChannelBuffer; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.frame.FrameDecoder; + +public class RoboTrackFrameDecoder extends FrameDecoder { + + private int messageLength(ChannelBuffer buf) { + switch ((int) buf.getByte(buf.readerIndex())) { + case RoboTrackProtocolDecoder.MSG_ID: + return 69; + case RoboTrackProtocolDecoder.MSG_ACK: + return 3; + case RoboTrackProtocolDecoder.MSG_GPS: + case RoboTrackProtocolDecoder.MSG_GSM: + case RoboTrackProtocolDecoder.MSG_IMAGE_START: + return 24; + case RoboTrackProtocolDecoder.MSG_IMAGE_DATA: + return 8 + buf.getUnsignedShort(buf.readerIndex() + 1); + case RoboTrackProtocolDecoder.MSG_IMAGE_END: + return 6; + default: + return Integer.MAX_VALUE; + } + } + + @Override + protected Object decode( + ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { + + int length = messageLength(buf); + + if (buf.readableBytes() >= length) { + return buf.readBytes(length); + } + + return null; + } + +} diff --git a/src/org/traccar/protocol/RoboTrackProtocol.java b/src/org/traccar/protocol/RoboTrackProtocol.java new file mode 100644 index 000000000..382cb1c2f --- /dev/null +++ b/src/org/traccar/protocol/RoboTrackProtocol.java @@ -0,0 +1,45 @@ +/* + * Copyright 2018 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.traccar.BaseProtocol; +import org.traccar.TrackerServer; + +import java.nio.ByteOrder; +import java.util.List; + +public class RoboTrackProtocol extends BaseProtocol { + + public RoboTrackProtocol() { + super("robotrack"); + } + + @Override + public void initTrackerServers(List serverList) { + TrackerServer server = new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new RoboTrackFrameDecoder()); + pipeline.addLast("objectDecoder", new RoboTrackProtocolDecoder(RoboTrackProtocol.this)); + } + }; + server.setEndianness(ByteOrder.LITTLE_ENDIAN); + serverList.add(server); + } + +} diff --git a/src/org/traccar/protocol/RoboTrackProtocolDecoder.java b/src/org/traccar/protocol/RoboTrackProtocolDecoder.java new file mode 100644 index 000000000..2244ea716 --- /dev/null +++ b/src/org/traccar/protocol/RoboTrackProtocolDecoder.java @@ -0,0 +1,130 @@ +/* + * Copyright 2018 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.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.helper.BitUtil; +import org.traccar.helper.Checksum; +import org.traccar.helper.UnitsConverter; +import org.traccar.model.CellTower; +import org.traccar.model.Network; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Date; + +public class RoboTrackProtocolDecoder extends BaseProtocolDecoder { + + public RoboTrackProtocolDecoder(RoboTrackProtocol protocol) { + super(protocol); + } + + public static final int MSG_ID = 0x00; + public static final int MSG_ACK = 0x80; + public static final int MSG_GPS = 0x03; + public static final int MSG_GSM = 0x04; + public static final int MSG_IMAGE_START = 0x06; + public static final int MSG_IMAGE_DATA = 0x07; + public static final int MSG_IMAGE_END = 0x08; + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ChannelBuffer buf = (ChannelBuffer) msg; + + int type = buf.readUnsignedByte(); + + if (type == MSG_ID) { + + buf.skipBytes(16); // name + + String imei = buf.readBytes(15).toString(StandardCharsets.US_ASCII); + + if (getDeviceSession(channel, remoteAddress, imei) != null && channel != null) { + ChannelBuffer response = ChannelBuffers.dynamicBuffer(); + buf.writeByte(MSG_ACK); + buf.writeByte(0x01); // success + response.writeByte(Checksum.crc8(Checksum.CRC8_ROHC, response.toByteBuffer())); + channel.write(response); + } + + } else if (type == MSG_GPS || type == MSG_GSM) { + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession == null) { + return null; + } + + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setDeviceTime(new Date(buf.readUnsignedInt() * 1000)); + + if (type == MSG_GPS) { + + position.setValid(true); + position.setFixTime(position.getDeviceTime()); + position.setLatitude(buf.readInt() * 0.000001); + position.setLongitude(buf.readInt() * 0.000001); + position.setSpeed(UnitsConverter.knotsFromKph(buf.readByte())); + + } else { + + getLastLocation(position, position.getDeviceTime()); + + position.setNetwork(new Network(CellTower.from( + buf.readUnsignedShort(), buf.readUnsignedShort(), + buf.readUnsignedShort(), buf.readUnsignedShort()))); + + buf.readUnsignedByte(); // reserved + + } + + int value = buf.readUnsignedByte(); + + position.set(Position.KEY_SATELLITES, BitUtil.to(value, 4)); + position.set(Position.KEY_RSSI, BitUtil.between(value, 4, 7)); + position.set(Position.KEY_MOTION, BitUtil.check(value, 7)); + + value = buf.readUnsignedByte(); + + position.set(Position.KEY_CHARGE, BitUtil.check(value, 0)); + + for (int i = 1; i <= 4; i++) { + position.set(Position.PREFIX_IN + i, BitUtil.check(value, i)); + } + + position.set(Position.KEY_BATTERY_LEVEL, BitUtil.from(value, 5) * 100 / 7); + position.set(Position.KEY_DEVICE_TEMP, buf.readByte()); + + for (int i = 1; i <= 3; i++) { + position.set(Position.PREFIX_ADC + i, buf.readUnsignedShort()); + } + + return position; + + } + + return null; + } + +} diff --git a/test/org/traccar/protocol/RoboTrackFrameDecoderTest.java b/test/org/traccar/protocol/RoboTrackFrameDecoderTest.java new file mode 100644 index 000000000..2e3853f86 --- /dev/null +++ b/test/org/traccar/protocol/RoboTrackFrameDecoderTest.java @@ -0,0 +1,19 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class RoboTrackFrameDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + RoboTrackFrameDecoder decoder = new RoboTrackFrameDecoder(); + + verifyFrame( + binary("00524f424f545241434b00000000000000383638323034303032323533343136313233343536373839303132312e313261000000312e353761000000312e3030000000003e"), + decoder.decode(null, null, binary("00524f424f545241434b00000000000000383638323034303032323533343136313233343536373839303132312e313261000000312e353761000000312e3030000000003e"))); + + } + +} diff --git a/test/org/traccar/protocol/RoboTrackProtocolDecoderTest.java b/test/org/traccar/protocol/RoboTrackProtocolDecoderTest.java new file mode 100644 index 000000000..b65d9974b --- /dev/null +++ b/test/org/traccar/protocol/RoboTrackProtocolDecoderTest.java @@ -0,0 +1,18 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class RoboTrackProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + RoboTrackProtocolDecoder decoder = new RoboTrackProtocolDecoder(new RoboTrackProtocol()); + + verifyNull(decoder, binary( + "00524f424f545241434b00000000000000383638323034303032323533343136313233343536373839303132312e313261000000312e353761000000312e3030000000003e")); + + } + +} -- cgit v1.2.3 From b0a63981a99bbef156c8801ad40d29f3bb2aae8e Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 4 Apr 2018 02:21:48 +1200 Subject: Implement PT60 protocol --- setup/default.xml | 1 + src/org/traccar/protocol/Pt60Protocol.java | 47 ++++++++++++ src/org/traccar/protocol/Pt60ProtocolDecoder.java | 83 ++++++++++++++++++++++ .../traccar/protocol/Pt60ProtocolDecoderTest.java | 21 ++++++ 4 files changed, 152 insertions(+) create mode 100644 src/org/traccar/protocol/Pt60Protocol.java create mode 100644 src/org/traccar/protocol/Pt60ProtocolDecoder.java create mode 100644 test/org/traccar/protocol/Pt60ProtocolDecoderTest.java (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 7996ce716..6bab81401 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -236,5 +236,6 @@ 5161 5162 5163 + 5164 diff --git a/src/org/traccar/protocol/Pt60Protocol.java b/src/org/traccar/protocol/Pt60Protocol.java new file mode 100644 index 000000000..857790efd --- /dev/null +++ b/src/org/traccar/protocol/Pt60Protocol.java @@ -0,0 +1,47 @@ +/* + * Copyright 2018 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.string.StringDecoder; +import org.jboss.netty.handler.codec.string.StringEncoder; +import org.traccar.BaseProtocol; +import org.traccar.CharacterDelimiterFrameDecoder; +import org.traccar.TrackerServer; + +import java.util.List; + +public class Pt60Protocol extends BaseProtocol { + + public Pt60Protocol() { + super("pt60"); + } + + @Override + public void initTrackerServers(List serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new CharacterDelimiterFrameDecoder(1024, "@R#@")); + pipeline.addLast("stringEncoder", new StringEncoder()); + pipeline.addLast("stringDecoder", new StringDecoder()); + pipeline.addLast("objectDecoder", new Pt60ProtocolDecoder(Pt60Protocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/Pt60ProtocolDecoder.java b/src/org/traccar/protocol/Pt60ProtocolDecoder.java new file mode 100644 index 000000000..c87c22c5f --- /dev/null +++ b/src/org/traccar/protocol/Pt60ProtocolDecoder.java @@ -0,0 +1,83 @@ +/* + * Copyright 2018 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.model.Position; + +import java.net.SocketAddress; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.regex.Pattern; + +public class Pt60ProtocolDecoder extends BaseProtocolDecoder { + + public Pt60ProtocolDecoder(Pt60Protocol protocol) { + super(protocol); + } + + private static final Pattern PATTERN = new PatternBuilder() + .text("@G#@,") // header + .number("Vdd,") // protocol version + .number("d,") // type + .number("(d+),") // imei + .number("(d+),") // imsi + .number("(dddd)(dd)(dd)") // date (yyyymmdd) + .number("(dd)(dd)(dd),") // time (hhmmss) + .number("(-?d+.d+);") // latitude + .number("(-?d+.d+),") // longitude + .compile(); + + private void sendResponse(Channel channel) { + if (channel != null) { + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + channel.write("@G#@,V01,38," + dateFormat.format(new Date()) + ",@R#@"); + } + } + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + sendResponse(channel); + + Parser parser = new Parser(PATTERN, (String) msg); + if (!parser.matches()) { + return null; + } + + Position position = new Position(getProtocolName()); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next(), parser.next()); + if (deviceSession == null) { + return null; + } + position.setDeviceId(deviceSession.getDeviceId()); + + position.setValid(true); + position.setTime(parser.nextDateTime()); + position.setLatitude(parser.nextDouble()); + position.setLongitude(parser.nextDouble()); + + return position; + } + +} diff --git a/test/org/traccar/protocol/Pt60ProtocolDecoderTest.java b/test/org/traccar/protocol/Pt60ProtocolDecoderTest.java new file mode 100644 index 000000000..5bea875e8 --- /dev/null +++ b/test/org/traccar/protocol/Pt60ProtocolDecoderTest.java @@ -0,0 +1,21 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class Pt60ProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + Pt60ProtocolDecoder decoder = new Pt60ProtocolDecoder(new Pt60Protocol()); + + verifyPosition(decoder, text( + "@G#@,V01,6,111112222233333,8888888888888888,20150312010203,23.2014050;104.235212,")); + + verifyNull(decoder, text( + "@G#@,V01,1,353882080015633,9460025014649193,")); + + } + +} -- cgit v1.2.3