aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debug.xml1
-rw-r--r--src/org/traccar/Main.java4
-rw-r--r--src/org/traccar/WebDataHandler.java4
-rw-r--r--src/org/traccar/database/DataManager.java1
-rw-r--r--src/org/traccar/protocol/H02ProtocolDecoder.java28
-rw-r--r--src/org/traccar/protocol/TeltonikaProtocolDecoder.java69
-rw-r--r--src/org/traccar/protocol/Tk103ProtocolDecoder.java5
-rw-r--r--src/org/traccar/protocol/TytanProtocolDecoder.java14
-rw-r--r--src/org/traccar/protocol/UlbotechProtocolDecoder.java4
-rw-r--r--src/org/traccar/web/CommandServlet.java15
-rw-r--r--src/org/traccar/web/ConsoleServlet.java52
-rw-r--r--src/org/traccar/web/WebServer.java13
-rw-r--r--test/org/traccar/ProtocolDecoderTest.java12
-rw-r--r--test/org/traccar/protocol/H02ProtocolDecoderTest.java6
-rw-r--r--test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java3
-rw-r--r--test/org/traccar/protocol/Tk103ProtocolDecoderTest.java3
-rw-r--r--test/org/traccar/protocol/TytanProtocolDecoderTest.java9
-rw-r--r--test/org/traccar/protocol/UlbotechFrameDecoderTest.java20
-rw-r--r--test/org/traccar/protocol/UlbotechProtocolDecoderTest.java3
19 files changed, 203 insertions, 63 deletions
diff --git a/debug.xml b/debug.xml
index 426dadc4c..0f6e49baf 100644
--- a/debug.xml
+++ b/debug.xml
@@ -13,6 +13,7 @@
<entry key='web.old'>true</entry>-->
<entry key='web.path'>web</entry>
<entry key='web.debug'>true</entry>
+ <entry key='web.console'>true</entry>
<entry key='geocoder.enable'>true</entry>
<entry key='geocoder.type'>nominatim</entry>
diff --git a/src/org/traccar/Main.java b/src/org/traccar/Main.java
index a51fa80bf..7ff93fda6 100644
--- a/src/org/traccar/Main.java
+++ b/src/org/traccar/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2013 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2012 - 2015 Anton Tananaev (anton.tananaev@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,11 +34,11 @@ public final class Main {
Context.getWebServer().start();
}
- // Shutdown server properly
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
Log.info("Shutting down server...");
+
if (Context.getWebServer() != null) {
Context.getWebServer().stop();
}
diff --git a/src/org/traccar/WebDataHandler.java b/src/org/traccar/WebDataHandler.java
index 332fc5222..f40d49a6d 100644
--- a/src/org/traccar/WebDataHandler.java
+++ b/src/org/traccar/WebDataHandler.java
@@ -101,8 +101,8 @@ public class WebDataHandler extends BaseDataHandler {
.replace("{protocol}", String.valueOf(position.getProtocol()))
.replace("{deviceTime}", String.valueOf(position.getDeviceTime().getTime()))
.replace("{fixTime}", String.valueOf(position.getFixTime().getTime()))
- .replace("{valid}", String.valueOf(position.getLatitude()))
- .replace("{latitude}", String.valueOf(position.getValid()))
+ .replace("{valid}", String.valueOf(position.getValid()))
+ .replace("{latitude}", String.valueOf(position.getLatitude()))
.replace("{longitude}", String.valueOf(position.getLongitude()))
.replace("{altitude}", String.valueOf(position.getAltitude()))
.replace("{speed}", String.valueOf(position.getSpeed()))
diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java
index c98a5ede7..31d7155d3 100644
--- a/src/org/traccar/database/DataManager.java
+++ b/src/org/traccar/database/DataManager.java
@@ -103,6 +103,7 @@ public class DataManager implements IdentityManager {
ds.setPassword(config.getString("database.password"));
ds.setIdleConnectionTestPeriod(600);
ds.setTestConnectionOnCheckin(true);
+ ds.setMaxStatementsPerConnection(config.getInteger("database.maxStatements"));
int maxPoolSize = config.getInteger("database.maxPoolSize");
if (maxPoolSize != 0) {
ds.setMaxPoolSize(maxPoolSize);
diff --git a/src/org/traccar/protocol/H02ProtocolDecoder.java b/src/org/traccar/protocol/H02ProtocolDecoder.java
index d245fbdc8..31bdd9aa9 100644
--- a/src/org/traccar/protocol/H02ProtocolDecoder.java
+++ b/src/org/traccar/protocol/H02ProtocolDecoder.java
@@ -122,9 +122,17 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder {
.any()
.number("(dd)(dd)(dd),") // time
.expression("([AV])?,") // validity
- .number("-?(d+)-?(dd.d+),") // latitude
+ .groupBegin()
+ .number("(d+)(dd.d+),") // latitude
+ .or()
+ .number("-(d+)-(d+.d+),") // latitude
+ .groupEnd()
.expression("([NS]),")
- .number("-?(d+)-?(dd.d+),") // longitude
+ .groupBegin()
+ .number("(d+)(dd.d+),") // longitude
+ .or()
+ .number("-(d+)-(d+.d+),") // longitude
+ .groupEnd()
.expression("([EW]),")
.number("(d+.?d*),") // speed
.number("(d+.?d*)?,") // course
@@ -155,8 +163,20 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder {
position.setValid(parser.next().equals("A"));
}
- position.setLatitude(parser.nextCoordinate());
- position.setLongitude(parser.nextCoordinate());
+ if (parser.hasNext(2)) {
+ position.setLatitude(parser.nextCoordinate());
+ }
+ if (parser.hasNext(2)) {
+ position.setLatitude(parser.nextCoordinate());
+ }
+
+ if (parser.hasNext(2)) {
+ position.setLongitude(parser.nextCoordinate());
+ }
+ if (parser.hasNext(2)) {
+ position.setLongitude(parser.nextCoordinate());
+ }
+
position.setSpeed(parser.nextDouble());
position.setCourse(parser.nextDouble());
diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
index 2217b5ce4..e82425a54 100644
--- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
+++ b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
@@ -81,49 +81,54 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
long time = buf.readUnsignedInt() & 0x3fffffff;
time += 1167609600; // 2007-01-01 00:00:00
- position.setTime(new Date(time * 1000));
globalMask = buf.readUnsignedByte();
- if (!BitUtil.check(globalMask, 0)) {
- return null;
- }
+ if (BitUtil.check(globalMask, 0)) {
- int locationMask = buf.readUnsignedByte();
+ position.setTime(new Date(time * 1000));
- if (BitUtil.check(locationMask, 0)) {
- position.setLatitude(buf.readFloat());
- position.setLongitude(buf.readFloat());
- }
+ int locationMask = buf.readUnsignedByte();
- if (BitUtil.check(locationMask, 1)) {
- position.setAltitude(buf.readUnsignedShort());
- }
+ if (BitUtil.check(locationMask, 0)) {
+ position.setLatitude(buf.readFloat());
+ position.setLongitude(buf.readFloat());
+ }
- if (BitUtil.check(locationMask, 2)) {
- position.setCourse(buf.readUnsignedByte() * 360.0 / 256);
- }
+ if (BitUtil.check(locationMask, 1)) {
+ position.setAltitude(buf.readUnsignedShort());
+ }
- if (BitUtil.check(locationMask, 3)) {
- position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
- }
+ if (BitUtil.check(locationMask, 2)) {
+ position.setCourse(buf.readUnsignedByte() * 360.0 / 256);
+ }
- if (BitUtil.check(locationMask, 4)) {
- int satellites = buf.readUnsignedByte();
- position.set(Event.KEY_SATELLITES, satellites);
- position.setValid(satellites >= 3);
- }
+ if (BitUtil.check(locationMask, 3)) {
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+ }
- if (BitUtil.check(locationMask, 5)) {
- position.set(Event.KEY_LAC, buf.readUnsignedShort());
- position.set(Event.KEY_CID, buf.readUnsignedShort());
- }
+ if (BitUtil.check(locationMask, 4)) {
+ int satellites = buf.readUnsignedByte();
+ position.set(Event.KEY_SATELLITES, satellites);
+ position.setValid(satellites >= 3);
+ }
- if (BitUtil.check(locationMask, 6)) {
- position.set(Event.KEY_GSM, buf.readUnsignedByte());
- }
+ if (BitUtil.check(locationMask, 5)) {
+ position.set(Event.KEY_LAC, buf.readUnsignedShort());
+ position.set(Event.KEY_CID, buf.readUnsignedShort());
+ }
+
+ if (BitUtil.check(locationMask, 6)) {
+ position.set(Event.KEY_GSM, buf.readUnsignedByte());
+ }
+
+ if (BitUtil.check(locationMask, 7)) {
+ position.set("operator", buf.readUnsignedInt());
+ }
+
+ } else {
+
+ getLastLocation(position, new Date(time * 1000));
- if (BitUtil.check(locationMask, 7)) {
- position.set("operator", buf.readUnsignedInt());
}
} else {
diff --git a/src/org/traccar/protocol/Tk103ProtocolDecoder.java b/src/org/traccar/protocol/Tk103ProtocolDecoder.java
index 6fa4edb06..e8d0d210d 100644
--- a/src/org/traccar/protocol/Tk103ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Tk103ProtocolDecoder.java
@@ -154,6 +154,11 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder {
}
position.setDeviceId(getDeviceId());
+ int alarm = sentence.indexOf("BO01");
+ if (alarm != -1) {
+ position.set(Event.KEY_ALARM, Integer.parseInt(sentence.substring(alarm + 4, alarm + 5)));
+ }
+
DateBuilder dateBuilder = new DateBuilder();
if (parser.next() == null) {
dateBuilder.setDate(parser.nextInt(), parser.nextInt(), parser.nextInt());
diff --git a/src/org/traccar/protocol/TytanProtocolDecoder.java b/src/org/traccar/protocol/TytanProtocolDecoder.java
index b0c1d243b..40861bacb 100644
--- a/src/org/traccar/protocol/TytanProtocolDecoder.java
+++ b/src/org/traccar/protocol/TytanProtocolDecoder.java
@@ -18,10 +18,8 @@ package org.traccar.protocol;
import java.net.SocketAddress;
import java.nio.charset.Charset;
import java.util.Date;
-import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
@@ -81,16 +79,8 @@ public class TytanProtocolDecoder extends BaseProtocolDecoder {
position.set("authorized", ChannelBuffers.hexDump(buf.readBytes(8)));
break;
case 24:
- Set<Integer> temps = new LinkedHashSet<>();
- int temp = buf.readUnsignedByte();
- for (int i = 3; i >= 0; i--) {
- n = (temp >> (2 * i)) & 0x03;
- if (!temps.contains(n)) {
- temps.add(n);
- }
- }
- for (int i : temps) {
- position.set(Event.PREFIX_TEMP + i, buf.readUnsignedByte());
+ for (int i = 0; i < length / 2; i++) {
+ position.set(Event.PREFIX_TEMP + buf.readUnsignedByte(), buf.readByte());
}
break;
case 28:
diff --git a/src/org/traccar/protocol/UlbotechProtocolDecoder.java b/src/org/traccar/protocol/UlbotechProtocolDecoder.java
index 5d882ffd8..dd6fb1593 100644
--- a/src/org/traccar/protocol/UlbotechProtocolDecoder.java
+++ b/src/org/traccar/protocol/UlbotechProtocolDecoder.java
@@ -204,7 +204,9 @@ public class UlbotechProtocolDecoder extends BaseProtocolDecoder {
case DATA_EVENT:
position.set(Event.KEY_EVENT, buf.readUnsignedByte());
- position.set("event-mask", buf.readUnsignedInt());
+ if (length > 1) {
+ position.set("event-mask", buf.readUnsignedInt());
+ }
break;
default:
diff --git a/src/org/traccar/web/CommandServlet.java b/src/org/traccar/web/CommandServlet.java
index be2d50ccc..d307913df 100644
--- a/src/org/traccar/web/CommandServlet.java
+++ b/src/org/traccar/web/CommandServlet.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * 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.web;
import javax.json.Json;
diff --git a/src/org/traccar/web/ConsoleServlet.java b/src/org/traccar/web/ConsoleServlet.java
new file mode 100644
index 000000000..b219eaba4
--- /dev/null
+++ b/src/org/traccar/web/ConsoleServlet.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * 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.web;
+
+import org.h2.server.web.ConnectionInfo;
+import org.h2.server.web.WebServlet;
+import org.traccar.Context;
+import org.traccar.helper.Log;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class ConsoleServlet extends WebServlet {
+
+ @Override
+ public void init() {
+ super.init();
+
+ try {
+ Field field = WebServlet.class.getDeclaredField("server");
+ field.setAccessible(true);
+ org.h2.server.web.WebServer server = (org.h2.server.web.WebServer) field.get(this);
+
+ ConnectionInfo connectionInfo = new ConnectionInfo("Traccar|"
+ + Context.getConfig().getString("database.driver") + "|"
+ + Context.getConfig().getString("database.url") + "|"
+ + Context.getConfig().getString("database.user"));
+
+ Method method = org.h2.server.web.WebServer.class.getDeclaredMethod("updateSetting", ConnectionInfo.class);
+ method.setAccessible(true);
+ method.invoke(server, connectionInfo);
+
+ } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ Log.warning(e);
+ }
+ }
+
+}
diff --git a/src/org/traccar/web/WebServer.java b/src/org/traccar/web/WebServer.java
index 146dee613..0f9bf8181 100644
--- a/src/org/traccar/web/WebServer.java
+++ b/src/org/traccar/web/WebServer.java
@@ -61,6 +61,9 @@ public class WebServer {
break;
case "new":
initApi();
+ if (config.getBoolean("web.console")) {
+ initConsole();
+ }
initWebApp();
break;
case "old":
@@ -118,12 +121,10 @@ public class WebServer {
handlers.addHandler(servletHandler);
}
- private void initRestApi() {
- ResourceConfig resourceConfig = new ResourceConfig();
- resourceConfig.packages("org.traccar.api");
- ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
- ServletHolder servletHolder = new ServletHolder(new ServletContainer(resourceConfig));
- servletHandler.addServlet(servletHolder, "/rest/*");
+ private void initConsole() {
+ ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ servletHandler.setContextPath("/console");
+ servletHandler.addServlet(new ServletHolder(new ConsoleServlet()), "/*");
handlers.addHandler(servletHandler);
}
diff --git a/test/org/traccar/ProtocolDecoderTest.java b/test/org/traccar/ProtocolDecoderTest.java
index 8f7ed628b..5d2acdda1 100644
--- a/test/org/traccar/ProtocolDecoderTest.java
+++ b/test/org/traccar/ProtocolDecoderTest.java
@@ -119,21 +119,25 @@ public class ProtocolDecoderTest {
}
protected void verifyPositions(BaseProtocolDecoder decoder, Object object) throws Exception {
- verifyDecodedList(decoder.decode(null, null, object), null);
+ verifyDecodedList(decoder.decode(null, null, object), true, null);
+ }
+
+ protected void verifyPositions(BaseProtocolDecoder decoder, boolean checkLocation, Object object) throws Exception {
+ verifyDecodedList(decoder.decode(null, null, object), checkLocation, null);
}
protected void verifyPositions(BaseProtocolDecoder decoder, Object object, Position position) throws Exception {
- verifyDecodedList(decoder.decode(null, null, object), position);
+ verifyDecodedList(decoder.decode(null, null, object), true, position);
}
- private void verifyDecodedList(Object decodedObject, Position expected) {
+ private void verifyDecodedList(Object decodedObject, boolean checkLocation, Position expected) {
Assert.assertNotNull("list is null", decodedObject);
Assert.assertTrue("not a list", decodedObject instanceof List);
Assert.assertFalse("list if empty", ((List) decodedObject).isEmpty());
for (Object item : (List) decodedObject) {
- verifyDecodedPosition(item, true, false, expected);
+ verifyDecodedPosition(item, checkLocation, false, expected);
}
}
diff --git a/test/org/traccar/protocol/H02ProtocolDecoderTest.java b/test/org/traccar/protocol/H02ProtocolDecoderTest.java
index b7d2b07b0..be503cc65 100644
--- a/test/org/traccar/protocol/H02ProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/H02ProtocolDecoderTest.java
@@ -10,6 +10,12 @@ public class H02ProtocolDecoderTest extends ProtocolDecoderTest {
public void testDecode() throws Exception {
H02ProtocolDecoder decoder = new H02ProtocolDecoder(new H02Protocol());
+
+ verifyPosition(decoder, buffer(
+ "*HQ,1451316485,V1,121557,A,-23-3.3408,S,-48-2.8926,W,0.1,158,241115,FFFFFFFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,1451316485,V1,121557,A,-23-35.3408,S,-48-2.8926,W,0.1,158,241115,FFFFFFFF#"));
verifyPosition(decoder, buffer(
"*HQ,355488020119695,V1,050418,,2827.61232,N,07703.84822,E,0.00,0,031015,FFFEFBFF#"),
diff --git a/test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java b/test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java
index 7e3f7cb35..9e3c9a377 100644
--- a/test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java
@@ -16,6 +16,9 @@ public class TeltonikaProtocolDecoderTest extends ProtocolDecoderTest {
verifyNothing(decoder, binary(
"000F313233343536373839303132333435"));
+ verifyPositions(decoder, false, binary(
+ "0000000000000055070450aa14320201f00150aa17f3031f42332a4c4193d68c008d00020901f00150aa1b6a031f423383f54193624f009d00000a01f00150aa1c230fc01a0000552b040164f400dd00f0010143100c0105000000050400006846"));
+
verifyPositions(decoder, binary(
"000000000000003508010000014f8e016420002141bbaf0f4e96a7fffa0000120000000602010047030242669c92000002c7000000009100000000000100002df3"));
diff --git a/test/org/traccar/protocol/Tk103ProtocolDecoderTest.java b/test/org/traccar/protocol/Tk103ProtocolDecoderTest.java
index 2bffbcd9a..c05d546ff 100644
--- a/test/org/traccar/protocol/Tk103ProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/Tk103ProtocolDecoderTest.java
@@ -10,6 +10,9 @@ public class Tk103ProtocolDecoderTest extends ProtocolDecoderTest {
Tk103ProtocolDecoder decoder = new Tk103ProtocolDecoder(new Tk103Protocol());
+ verifyPosition(decoder, text(
+ "(013612345678BO012061830A2934.0133N10627.2544E040.0080331309.6200000000L000770AD"));
+
verifyAttributes(decoder, text(
"(088047194605BZ00,510,010,36e6,932c,43,36e6,766b,36,36e6,7668,32"));
diff --git a/test/org/traccar/protocol/TytanProtocolDecoderTest.java b/test/org/traccar/protocol/TytanProtocolDecoderTest.java
index d291baa6e..bfbc01f52 100644
--- a/test/org/traccar/protocol/TytanProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/TytanProtocolDecoderTest.java
@@ -13,6 +13,15 @@ public class TytanProtocolDecoderTest extends ProtocolDecoderTest {
TytanProtocolDecoder decoder = new TytanProtocolDecoder(new TytanProtocol());
verifyPositions(decoder, binary(
+ "B500192000001405125652CA9B1A325FC98D11A9990018020118FC0D"));
+
+ verifyPositions(decoder, binary(
+ "B500197800007422125652D7AC32325FD08D11A69900180200188280"));
+
+ verifyPositions(decoder, binary(
+ "B500181000001405115652DEEB2A325FC68D11A7D00005012A2AE1"));
+
+ verifyPositions(decoder, binary(
"B5005690000068494F561CEAE932325FD28D11A299000702000063045532030066013567018768014B6901286B0240396C04030785986D013E7F040000A7CE81040000A76C82027EAB83080FA01068FFFF0F3C880202583156"));
verifyPositions(decoder, binary(
diff --git a/test/org/traccar/protocol/UlbotechFrameDecoderTest.java b/test/org/traccar/protocol/UlbotechFrameDecoderTest.java
new file mode 100644
index 000000000..76e4f799d
--- /dev/null
+++ b/test/org/traccar/protocol/UlbotechFrameDecoderTest.java
@@ -0,0 +1,20 @@
+package org.traccar.protocol;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.traccar.ProtocolDecoderTest;
+
+public class UlbotechFrameDecoderTest extends ProtocolDecoderTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ UlbotechFrameDecoder decoder = new UlbotechFrameDecoder();
+
+ Assert.assertEquals(
+ binary("f8010108679650230646339de69054010e015ee17506bde2c60000000000ac0304024000000404000009f705060390181422170711310583410c0000310d00312f834131018608040003130a100101136cf8"),
+ decoder.decode(null, null, binary("f8010108679650230646339de69054010e015ee17506bde2c60000000000ac0304024000000404000009f70005060390181422170711310583410c0000310d00312f834131018608040003130a100101136cf8")));
+
+ }
+
+}
diff --git a/test/org/traccar/protocol/UlbotechProtocolDecoderTest.java b/test/org/traccar/protocol/UlbotechProtocolDecoderTest.java
index 30e040e3d..4dd061f1c 100644
--- a/test/org/traccar/protocol/UlbotechProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/UlbotechProtocolDecoderTest.java
@@ -13,6 +13,9 @@ public class UlbotechProtocolDecoderTest extends ProtocolDecoderTest {
UlbotechProtocolDecoder decoder = new UlbotechProtocolDecoder(new UlbotechProtocol());
verifyPosition(decoder, binary(
+ "f8010108679650230646339de69054010e015ee17506bde2c60000000000ac0304024000000404000009f705060390181422170711310583410c0000310d00312f834131018608040003130a100101136cf8"));
+
+ verifyPosition(decoder, binary(
"f8010108679650230651689dc8e45b010e01194a26fbd47fa6001f003c0054030402420000040400024d7b0506037c18692212071131057f410c0ee0310d1b312f41413112ef0804000dd59fcc32f8"));
verifyPosition(decoder, binary(