aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--schema/changelog-3.10.xml48
-rw-r--r--setup/default.xml1
-rw-r--r--src/org/traccar/api/resource/CommandResource.java2
-rw-r--r--src/org/traccar/protocol/AquilaProtocolDecoder.java75
-rw-r--r--src/org/traccar/protocol/Gl200ProtocolDecoder.java37
-rw-r--r--src/org/traccar/protocol/MxtProtocolDecoder.java21
-rw-r--r--src/org/traccar/protocol/PricolProtocol.java43
-rw-r--r--src/org/traccar/protocol/PricolProtocolDecoder.java96
-rw-r--r--src/org/traccar/protocol/SuntechProtocolDecoder.java166
-rw-r--r--src/org/traccar/protocol/TeltonikaProtocolDecoder.java52
-rw-r--r--test/org/traccar/protocol/AquilaProtocolDecoderTest.java6
-rw-r--r--test/org/traccar/protocol/Gl200ProtocolDecoderTest.java2
-rw-r--r--test/org/traccar/protocol/PricolProtocolDecoderTest.java21
-rw-r--r--test/org/traccar/protocol/SuntechProtocolDecoderTest.java9
14 files changed, 481 insertions, 98 deletions
diff --git a/schema/changelog-3.10.xml b/schema/changelog-3.10.xml
index c4d9b7b18..4c64373e9 100644
--- a/schema/changelog-3.10.xml
+++ b/schema/changelog-3.10.xml
@@ -34,11 +34,11 @@
<addForeignKeyConstraint baseTableName="user_calendar" baseColumnNames="userid" constraintName="fk_user_calendar_userid" referencedTableName="users" referencedColumnNames="id" onDelete="CASCADE" />
<addForeignKeyConstraint baseTableName="user_calendar" baseColumnNames="calendarid" constraintName="fk_user_calendar_geofenceid" referencedTableName="calendars" referencedColumnNames="id" onDelete="CASCADE" />
-
+
<addColumn tableName="geofences">
<column name="calendarid" type="INT" />
</addColumn>
-
+
<addForeignKeyConstraint baseColumnNames="calendarid" baseTableName="geofences" constraintName="fk_geofence_calendar_calendarid" onDelete="SET NULL" onUpdate="RESTRICT" referencedColumnNames="id" referencedTableName="calendars"/>
<addColumn tableName="positions">
@@ -62,12 +62,12 @@
</createTable>
<addForeignKeyConstraint baseTableName="user_user" baseColumnNames="userid" constraintName="fk_user_user_userid" referencedTableName="users" referencedColumnNames="id" onDelete="CASCADE" />
- <addForeignKeyConstraint baseTableName="user_user" baseColumnNames="manageduserid" constraintName="fk_user_user_manageduserid" referencedTableName="users" referencedColumnNames="id" onDelete="CASCADE" />
<update tableName="users">
<column name="devicelimit" valueNumeric="-1" />
<where>devicelimit = 0</where>
</update>
+ <dropDefaultValue tableName="users" columnName="devicelimit" />
<addDefaultValue tableName="users" columnName="devicelimit" defaultValueNumeric="-1" />
<addColumn tableName="users">
@@ -75,4 +75,46 @@
</addColumn>
</changeSet>
+
+ <changeSet author="author" id="changelog-3.10-notmssql">
+
+ <preConditions onFail="MARK_RAN">
+ <not>
+ <dbms type="mssql" />
+ </not>
+ </preConditions>
+ <addForeignKeyConstraint baseTableName="user_user" baseColumnNames="manageduserid" constraintName="fk_user_user_manageduserid" referencedTableName="users" referencedColumnNames="id" onDelete="CASCADE" />
+
+ </changeSet>
+
+ <changeSet author="author" id="changelog-3.10-mssql">
+
+ <preConditions onFail="MARK_RAN">
+ <dbms type="mssql" />
+ </preConditions>
+ <sql>
+ CREATE TRIGGER tg_users_delete
+ ON users FOR DELETE
+ AS BEGIN
+ DELETE FROM user_user WHERE manageduserid IN (SELECT deleted.id FROM deleted)
+ END
+ </sql>
+
+ </changeSet>
+
+ <changeSet author="author" id="changelog-3.7-mssql">
+
+ <preConditions onFail="MARK_RAN">
+ <dbms type="mssql" />
+ </preConditions>
+ <sql>
+ CREATE TRIGGER tg_groups_delete
+ ON groups FOR DELETE
+ AS BEGIN
+ UPDATE groups SET groupid = NULL WHERE groupid IN (SELECT deleted.id FROM deleted)
+ END
+ </sql>
+
+ </changeSet>
+
</databaseChangeLog>
diff --git a/setup/default.xml b/setup/default.xml
index d2c1c8fa8..7cbf9dab6 100644
--- a/setup/default.xml
+++ b/setup/default.xml
@@ -501,5 +501,6 @@
<entry key='gt30.port'>5131</entry>
<entry key='tmg.port'>5132</entry>
<entry key='pretrace.port'>5133</entry>
+ <entry key='pricol.port'>5134</entry>
</properties>
diff --git a/src/org/traccar/api/resource/CommandResource.java b/src/org/traccar/api/resource/CommandResource.java
index cce2dac2b..e13ae9de8 100644
--- a/src/org/traccar/api/resource/CommandResource.java
+++ b/src/org/traccar/api/resource/CommandResource.java
@@ -33,6 +33,8 @@ public class CommandResource extends BaseResource {
@POST
public Response add(Command entity) {
+ Context.getPermissionsManager().checkReadonly(getUserId());
+ Context.getPermissionsManager().checkDeviceReadonly(getUserId());
Context.getPermissionsManager().checkDevice(getUserId(), entity.getDeviceId());
Context.getConnectionManager().getActiveDevice(entity.getDeviceId()).sendCommand(entity);
return Response.ok(entity).build();
diff --git a/src/org/traccar/protocol/AquilaProtocolDecoder.java b/src/org/traccar/protocol/AquilaProtocolDecoder.java
index 60a9c4708..e1cebd20d 100644
--- a/src/org/traccar/protocol/AquilaProtocolDecoder.java
+++ b/src/org/traccar/protocol/AquilaProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 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.
@@ -46,6 +46,7 @@ public class AquilaProtocolDecoder extends BaseProtocolDecoder {
.number("(d+),") // gsm
.number("(d+),") // speed
.number("(d+),") // distance
+ .groupBegin()
.number("d+,") // driver code
.number("(d+),") // fuel
.number("([01]),") // io 1
@@ -65,8 +66,36 @@ public class AquilaProtocolDecoder extends BaseProtocolDecoder {
.number("([01]),") // course bit 1
.number("([01]),") // course bit 2
.number("([01]),") // course bit 3
+ .or()
+ .number("(d+),") // course
+ .number("(?:d+,){3}") // reserved
+ .number("[01],") // over speed start
+ .number("[01],") // over speed end
+ .number("(?:d+,){3}") // reserved
+ .number("([01]),") // power status
+ .number("(?:d+,){2}") // reserved
+ .number("[01],") // ignition on event
+ .number("([01]),") // ignition
+ .number("[01],") // ignition off event
+ .number("(?:d+,){5}") // reserved
+ .number("[01],") // low battery
+ .number("[01],") // corner packet
+ .number("(?:d+,){6}") // reserved
+ .number("[01],") // hard acceleration
+ .number("[01],") // hard breaking
+ .number("[01],[01],[01],[01],") // course bits
+ .number("(d+),") // external voltage
+ .number("(d+),") // internal voltage
+ .number("(?:d+,){6}") // reserved
+ .expression("P([^,]+),") // obd
+ .expression("D([^,]+),") // dtcs
+ .number("-?d+,") // accelerometer x
+ .number("-?d+,") // accelerometer y
+ .number("-?d+,") // accelerometer z
+ .number("d+,") // delta distance
+ .groupEnd()
.text("*")
- .number("(xx)") // checksum
+ .number("xx") // checksum
.compile();
@Override
@@ -78,13 +107,13 @@ public class AquilaProtocolDecoder extends BaseProtocolDecoder {
return null;
}
- Position position = new Position();
- position.setProtocol(getProtocolName());
-
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
if (deviceSession == null) {
return null;
}
+
+ Position position = new Position();
+ position.setProtocol(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
position.set(Position.KEY_EVENT, parser.nextInt());
@@ -104,16 +133,36 @@ public class AquilaProtocolDecoder extends BaseProtocolDecoder {
position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble()));
position.set(Position.KEY_ODOMETER, parser.next());
- position.set(Position.KEY_FUEL, parser.next());
- position.set(Position.PREFIX_IO + 1, parser.next());
- position.set(Position.KEY_CHARGE, parser.next());
- position.set(Position.PREFIX_IO + 2, parser.next());
- position.set(Position.KEY_IGNITION, parser.nextInt() == 1);
+ if (parser.hasNext(9)) {
+
+ position.set(Position.KEY_FUEL, parser.next());
+ position.set(Position.PREFIX_IO + 1, parser.next());
+ position.set(Position.KEY_CHARGE, parser.next());
+ position.set(Position.PREFIX_IO + 2, parser.next());
+
+ position.set(Position.KEY_IGNITION, parser.nextInt() == 1);
+
+ int course = (parser.nextInt() << 3) + (parser.nextInt() << 2) + (parser.nextInt() << 1) + parser.nextInt();
+ if (course > 0 && course <= 8) {
+ position.setCourse((course - 1) * 45);
+ }
+
+ } else {
+
+ position.setCourse(parser.nextInt());
+
+ position.set(Position.KEY_CHARGE, parser.next());
+ position.set(Position.KEY_IGNITION, parser.nextInt() == 1);
+ position.set(Position.KEY_POWER, parser.nextInt());
+ position.set(Position.KEY_BATTERY, parser.nextInt());
+
+ String obd = parser.next();
+ position.set("obd", obd.substring(1, obd.length() - 1));
+
+ String dtcs = parser.next();
+ position.set(Position.KEY_DTCS, dtcs.substring(1, dtcs.length() - 1).replace('|', ' '));
- int course = (parser.nextInt() << 3) + (parser.nextInt() << 2) + (parser.nextInt() << 1) + parser.nextInt();
- if (course > 0 && course <= 8) {
- position.setCourse((course - 1) * 45);
}
return position;
diff --git a/src/org/traccar/protocol/Gl200ProtocolDecoder.java b/src/org/traccar/protocol/Gl200ProtocolDecoder.java
index ab6507122..59f013313 100644
--- a/src/org/traccar/protocol/Gl200ProtocolDecoder.java
+++ b/src/org/traccar/protocol/Gl200ProtocolDecoder.java
@@ -278,11 +278,15 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder {
.number("(d{1,3}.d)?,") // speed
.number("(d{1,3})?,") // course
.number("(-?d{1,5}.d)?,") // altitude
- .number("(-?d{1,3}.d{6}),") // longitude
- .number("(-?d{1,2}.d{6}),") // latitude
+ .number("(-?d{1,3}.d{6})?,") // longitude
+ .number("(-?d{1,2}.d{6})?,") // latitude
.number("(dddd)(dd)(dd)") // date
- .number("(dd)(dd)(dd)") // time
+ .number("(dd)(dd)(dd)").optional(2) // time
.text(",")
+ .number("(0ddd),") // mcc
+ .number("(0ddd),") // mnc
+ .number("(xxxx),") // lac
+ .number("(xxxx),").optional(4) // cell
.any()
.number("(dddd)(dd)(dd)") // date
.number("(dd)(dd)(dd)").optional(2) // time
@@ -703,17 +707,28 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder {
position.setCourse(parser.nextDouble());
position.setAltitude(parser.nextDouble());
- position.setValid(true);
- position.setLongitude(parser.nextDouble());
- position.setLatitude(parser.nextDouble());
+ if (parser.hasNext(2)) {
+ position.setValid(true);
+ position.setLongitude(parser.nextDouble());
+ position.setLatitude(parser.nextDouble());
+ } else {
+ getLastLocation(position, null);
+ }
- DateBuilder dateBuilder = new DateBuilder()
- .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt())
- .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
- position.setTime(dateBuilder.getDate());
+ if (parser.hasNext(6)) {
+ DateBuilder dateBuilder = new DateBuilder()
+ .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt())
+ .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ position.setTime(dateBuilder.getDate());
+ }
+
+ if (parser.hasNext(4)) {
+ position.setNetwork(new Network(CellTower.from(
+ parser.nextInt(), parser.nextInt(), parser.nextInt(16), parser.nextInt(16))));
+ }
if (parser.hasNext(6)) {
- dateBuilder = new DateBuilder()
+ DateBuilder dateBuilder = new DateBuilder()
.setDate(parser.nextInt(), parser.nextInt(), parser.nextInt())
.setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
if (!position.getOutdated() && position.getFixTime().after(dateBuilder.getDate())) {
diff --git a/src/org/traccar/protocol/MxtProtocolDecoder.java b/src/org/traccar/protocol/MxtProtocolDecoder.java
index c9eba5bed..eaeeacc97 100644
--- a/src/org/traccar/protocol/MxtProtocolDecoder.java
+++ b/src/org/traccar/protocol/MxtProtocolDecoder.java
@@ -27,6 +27,7 @@ import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
import java.net.SocketAddress;
+import java.nio.ByteOrder;
public class MxtProtocolDecoder extends BaseProtocolDecoder {
@@ -40,16 +41,26 @@ public class MxtProtocolDecoder extends BaseProtocolDecoder {
private static void sendResponse(Channel channel, int device, long id, int crc) {
if (channel != null) {
- ChannelBuffer response = ChannelBuffers.dynamicBuffer();
- response.writeByte(0x01); // header
+ ChannelBuffer response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 0);
response.writeByte(device);
response.writeByte(MSG_ACK);
response.writeInt((int) id);
response.writeShort(crc);
response.writeShort(Checksum.crc16(
- Checksum.CRC16_CCITT_FALSE, response.toByteBuffer(0, response.readableBytes())));
- response.writeByte(0x04); // ending
- channel.write(response);
+ Checksum.CRC16_XMODEM, response.toByteBuffer()));
+
+ ChannelBuffer encoded = ChannelBuffers.dynamicBuffer();
+ encoded.writeByte(0x01); // header
+ while (response.readable()) {
+ int b = response.readByte();
+ if (b == 0x01 || b == 0x04 || b == 0x10 || b == 0x11 || b == 0x13) {
+ encoded.writeByte(0x10);
+ b += 0x20;
+ }
+ encoded.writeByte(b);
+ }
+ encoded.writeByte(0x04); // ending
+ channel.write(encoded);
}
}
diff --git a/src/org/traccar/protocol/PricolProtocol.java b/src/org/traccar/protocol/PricolProtocol.java
new file mode 100644
index 000000000..924c7c1d6
--- /dev/null
+++ b/src/org/traccar/protocol/PricolProtocol.java
@@ -0,0 +1,43 @@
+/*
+ * 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.FixedLengthFrameDecoder;
+import org.traccar.BaseProtocol;
+import org.traccar.TrackerServer;
+
+import java.util.List;
+
+public class PricolProtocol extends BaseProtocol {
+
+ public PricolProtocol() {
+ super("pricol");
+ }
+
+ @Override
+ public void initTrackerServers(List<TrackerServer> serverList) {
+ serverList.add(new TrackerServer(new ServerBootstrap(), getName()) {
+ @Override
+ protected void addSpecificHandlers(ChannelPipeline pipeline) {
+ pipeline.addLast("frameDecoder", new FixedLengthFrameDecoder(64));
+ pipeline.addLast("objectDecoder", new PricolProtocolDecoder(PricolProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/org/traccar/protocol/PricolProtocolDecoder.java b/src/org/traccar/protocol/PricolProtocolDecoder.java
new file mode 100644
index 000000000..52b68cca6
--- /dev/null
+++ b/src/org/traccar/protocol/PricolProtocolDecoder.java
@@ -0,0 +1,96 @@
+/*
+ * 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.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.DateBuilder;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+
+public class PricolProtocolDecoder extends BaseProtocolDecoder {
+
+ public PricolProtocolDecoder(PricolProtocol protocol) {
+ super(protocol);
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ChannelBuffer buf = (ChannelBuffer) msg;
+
+ buf.readUnsignedByte(); // header
+
+ DeviceSession deviceSession = getDeviceSession(
+ channel, remoteAddress, buf.readBytes(7).toString(StandardCharsets.US_ASCII));
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position();
+ position.setProtocol(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ buf.readUnsignedByte(); // event type
+ buf.readUnsignedByte(); // packet version
+ buf.readUnsignedByte(); // device status
+ buf.readUnsignedByte(); // gsm status
+ buf.readUnsignedByte(); // gps status
+
+ position.setTime(new DateBuilder()
+ .setDateReverse(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
+ .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()).getDate());
+
+ position.setValid(true);
+
+ double lat = buf.getUnsignedShort(buf.readerIndex()) / 100;
+ lat += (buf.readUnsignedShort() % 100 * 10000 + buf.readUnsignedShort()) / 600000.0;
+ position.setLatitude(buf.readUnsignedByte() == 'S' ? -lat : lat);
+
+ double lon = buf.getUnsignedMedium(buf.readerIndex()) / 100;
+ lon += (buf.readUnsignedMedium() % 100 * 10000 + buf.readUnsignedShort()) / 600000.0;
+ position.setLongitude(buf.readUnsignedByte() == 'W' ? -lon : lon);
+
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+
+ position.set(Position.KEY_INPUT, buf.readUnsignedShort());
+ position.set(Position.KEY_OUTPUT, buf.readUnsignedByte());
+
+ buf.readUnsignedByte(); // analog alerts
+ buf.readUnsignedShort(); // custom alert types
+
+ for (int i = 1; i <= 5; i++) {
+ position.set(Position.PREFIX_ADC + i, buf.readUnsignedShort());
+ }
+
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedMedium());
+ position.set(Position.KEY_RPM, buf.readUnsignedShort());
+
+ if (channel != null) {
+ channel.write(ChannelBuffers.copiedBuffer("ACK", StandardCharsets.US_ASCII));
+ }
+
+ return position;
+ }
+
+}
diff --git a/src/org/traccar/protocol/SuntechProtocolDecoder.java b/src/org/traccar/protocol/SuntechProtocolDecoder.java
index c9235f47f..d081cb901 100644
--- a/src/org/traccar/protocol/SuntechProtocolDecoder.java
+++ b/src/org/traccar/protocol/SuntechProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2015 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 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.
@@ -17,85 +17,157 @@ package org.traccar.protocol;
import org.jboss.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.Context;
import org.traccar.DeviceSession;
-import org.traccar.helper.DateBuilder;
-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;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
public class SuntechProtocolDecoder extends BaseProtocolDecoder {
+ private int protocolType;
+
public SuntechProtocolDecoder(SuntechProtocol protocol) {
super(protocol);
+
+ protocolType = Context.getConfig().getInteger(getProtocolName() + ".protocolType");
}
- private static final Pattern PATTERN = new PatternBuilder()
- .expression("S.")
- .number("ddd")
- .expression("(?:[A-Z]{3})?;") // header
- .expression("([^;]+);").optional() // type
- .number("(d{6,});") // device id
- .number("d+;").optional()
- .number("(d+);") // version
- .number("(dddd)(dd)(dd);") // date
- .number("(dd):(dd):(dd);") // time
- .number("(x+);").optional() // cell
- .number("([-+]dd.d+);") // latitude
- .number("([-+]ddd.d+);") // longitude
- .number("(ddd.ddd);") // speed
- .number("(ddd.dd);") // course
- .number("d+;").optional()
- .number("(d+.d+)?") // battery
- .any() // full format
- .compile();
+ public void setProtocolType(int protocolType) {
+ this.protocolType = protocolType;
+ }
- @Override
- protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+ private Position decode9(
+ Channel channel, SocketAddress remoteAddress, String[] values) throws ParseException {
+ int index = 1;
+
+ String type = values[index++];
+
+ if (!type.equals("Location") && !type.equals("Emergency") && !type.equals("Alert")) {
+ return null;
+ }
+
+ Position position = new Position();
+ position.setProtocol(getProtocolName());
+
+ if (type.equals("Emergency") || type.equals("Alert")) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ }
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[index++]);
+ if (deviceSession == null) {
+ return null;
+ }
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.set(Position.KEY_VERSION, values[index++]);
+
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHH:mm:ss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ position.setTime(dateFormat.parse(values[index++] + values[index++]));
+
+ if (protocolType == 1) {
+ index += 1; // cell
+ }
+
+ position.setLatitude(Double.parseDouble(values[index++]));
+ position.setLongitude(Double.parseDouble(values[index++]));
+ position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++])));
+ position.setCourse(Double.parseDouble(values[index++]));
+
+ position.setValid(values[index++].equals("1"));
+
+ if (protocolType == 1) {
+ position.set(Position.KEY_ODOMETER, Integer.parseInt(values[index]));
+ }
+
+ return position;
+ }
- Parser parser = new Parser(PATTERN, (String) msg);
- if (!parser.matches()) {
+ private Position decode23(
+ Channel channel, SocketAddress remoteAddress, String protocol, String[] values) throws ParseException {
+ int index = 0;
+
+ String type = values[index++].substring(5);
+
+ if (!type.equals("STT") && !type.equals("EMG") && !type.equals("EVT") && !type.equals("ALT")) {
return null;
}
Position position = new Position();
position.setProtocol(getProtocolName());
- if (parser.hasNext()) {
- String type = parser.next();
- if (type.equals("Alert") || type.equals("Emergency")) {
- position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
- }
+ if (type.equals("EMG") || type.equals("ALT")) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
}
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[index++]);
if (deviceSession == null) {
return null;
}
position.setDeviceId(deviceSession.getDeviceId());
- position.set(Position.KEY_VERSION, parser.next());
+ if (protocol.equals("ST300")) {
+ index += 1; // model
+ }
+
+ position.set(Position.KEY_VERSION, values[index++]);
+
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHH:mm:ss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ position.setTime(dateFormat.parse(values[index++] + values[index++]));
+
+ index += 1; // cell
+
+ position.setLatitude(Double.parseDouble(values[index++]));
+ position.setLongitude(Double.parseDouble(values[index++]));
+ position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++])));
+ position.setCourse(Double.parseDouble(values[index++]));
- DateBuilder dateBuilder = new DateBuilder()
- .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt())
- .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
- position.setTime(dateBuilder.getDate());
+ position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++]));
- parser.next(); // location code + bsic
+ position.setValid(values[index++].equals("1"));
- position.setValid(true);
- position.setLatitude(parser.nextDouble());
- position.setLongitude(parser.nextDouble());
- position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble()));
- position.setCourse(parser.nextDouble());
+ position.set(Position.KEY_ODOMETER, Integer.parseInt(values[index++]));
+ position.set(Position.KEY_POWER, Double.parseDouble(values[index++]));
- position.set(Position.KEY_BATTERY, parser.next());
+ position.set(Position.PREFIX_IO + 1, values[index++]);
+
+ index += 1; // mode
+
+ if (type.equals("STT")) {
+ position.set(Position.KEY_INDEX, Integer.parseInt(values[index++]));
+ }
+
+ if (index < values.length) {
+ position.set(Position.KEY_HOURS, Integer.parseInt(values[index++]));
+ }
+
+ if (index < values.length) {
+ position.set(Position.KEY_BATTERY, Double.parseDouble(values[index]));
+ }
return position;
}
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ String[] values = ((String) msg).split(";");
+
+ String protocol = values[0].substring(0, 5);
+
+ if (protocol.equals("ST910")) {
+ return decode9(channel, remoteAddress, values);
+ } else {
+ return decode23(channel, remoteAddress, protocol, values);
+ }
+ }
+
}
diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
index 6f3af0bb2..411915400 100644
--- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
+++ b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
@@ -71,28 +71,48 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
}
- private void decodeParameter(Position position, int id, long value) {
+ private void decodeParameter(Position position, int id, ChannelBuffer buf, int length) {
switch (id) {
case 9:
- position.set(Position.PREFIX_ADC + 1, value);
+ position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort());
break;
case 66:
- position.set(Position.KEY_POWER, value);
+ position.set(Position.KEY_POWER, buf.readUnsignedShort() + "mV");
break;
- case 68:
- position.set(Position.KEY_BATTERY, value);
+ case 67:
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShort() + "mV");
break;
- case 85:
- position.set(Position.KEY_RPM, value);
+ case 72:
+ position.set(Position.PREFIX_TEMP + 1, buf.readInt() * 0.1);
break;
- case 182:
- position.set(Position.KEY_HDOP, value);
+ case 73:
+ position.set(Position.PREFIX_TEMP + 2, buf.readInt() * 0.1);
+ break;
+ case 74:
+ position.set(Position.PREFIX_TEMP + 3, buf.readInt() * 0.1);
break;
- case 239:
- position.set(Position.KEY_IGNITION, value == 1);
+ case 78:
+ position.set(Position.KEY_RFID, buf.readLong());
+ break;
+ case 182:
+ position.set(Position.KEY_HDOP, buf.readUnsignedShort() * 0.1);
break;
default:
- position.set(Position.PREFIX_IO + id, value);
+ switch (length) {
+ case 1:
+ position.set(Position.PREFIX_IO + id, buf.readUnsignedByte());
+ break;
+ case 2:
+ position.set(Position.PREFIX_IO + id, buf.readUnsignedShort());
+ break;
+ case 4:
+ position.set(Position.PREFIX_IO + id, buf.readUnsignedInt());
+ break;
+ case 8:
+ default:
+ position.set(Position.PREFIX_IO + id, buf.readLong());
+ break;
+ }
break;
}
}
@@ -183,7 +203,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(globalMask, 1)) {
int cnt = buf.readUnsignedByte();
for (int j = 0; j < cnt; j++) {
- decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedByte());
+ decodeParameter(position, buf.readUnsignedByte(), buf, 1);
}
}
@@ -191,7 +211,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(globalMask, 2)) {
int cnt = buf.readUnsignedByte();
for (int j = 0; j < cnt; j++) {
- decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedShort());
+ decodeParameter(position, buf.readUnsignedByte(), buf, 2);
}
}
@@ -199,7 +219,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(globalMask, 3)) {
int cnt = buf.readUnsignedByte();
for (int j = 0; j < cnt; j++) {
- decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedInt());
+ decodeParameter(position, buf.readUnsignedByte(), buf, 4);
}
}
@@ -207,7 +227,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (codec == CODEC_FM4X00) {
int cnt = buf.readUnsignedByte();
for (int j = 0; j < cnt; j++) {
- decodeParameter(position, buf.readUnsignedByte(), buf.readLong());
+ decodeParameter(position, buf.readUnsignedByte(), buf, 8);
}
}
diff --git a/test/org/traccar/protocol/AquilaProtocolDecoderTest.java b/test/org/traccar/protocol/AquilaProtocolDecoderTest.java
index a62e20e1e..3e823d74d 100644
--- a/test/org/traccar/protocol/AquilaProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/AquilaProtocolDecoderTest.java
@@ -11,6 +11,12 @@ public class AquilaProtocolDecoderTest extends ProtocolTest {
AquilaProtocolDecoder decoder = new AquilaProtocolDecoder(new AquilaProtocol());
verifyPosition(decoder, text(
+ "$$CLIENT_1ZF,130329214,1,12.962985,77.576484,140127165433,A,22,0,0,140,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1253,420,1,0,1,0,0,1,P(01:410104000102|05:410521|0C:410C0000|0D:410D65|21:4121161C),D(P0121|B2105),-895,745,-145,300,*26"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1NS,101010119,1,22.845943,75.949059,170202184000,A,27,0,0,120,31141,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,399,3709,0,0,0,0,0,0,P(01:|04:|05:|0B:|0C:|0D:|10:|1C:|21:|23:|30:|31:|1F:|11:|00:|00:|),D(),-89,44,-1062,0,*49"));
+
+ verifyPosition(decoder, text(
"$$CLIENT_1DT,151028368,1,19.108438,72.925308,160628154920,A,22,0,0,131,3503,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,*1D"));
verifyNothing(decoder, text(
diff --git a/test/org/traccar/protocol/Gl200ProtocolDecoderTest.java b/test/org/traccar/protocol/Gl200ProtocolDecoderTest.java
index 51c4950f5..a4b8985f1 100644
--- a/test/org/traccar/protocol/Gl200ProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/Gl200ProtocolDecoderTest.java
@@ -22,7 +22,7 @@ public class Gl200ProtocolDecoderTest extends ProtocolTest {
verifyAttributes(decoder, text(
"+RESP:GTSTR,400201,862365030034957,GL500,0,0,2,23.1,5,2,0.2,0,36.0,0.623089,51.582744,20161129174625,0234,0015,03C3,3550,,,,20161129174625,0026$"));
- verifyNothing(decoder, text(
+ verifyNotNull(decoder, text(
"+RESP:GTSTR,400201,862365030034957,GL500,0,1,2,21.8,100,0,,,,,,,0234,0015,03C3,3550,,,,20161129174009,0023$"));
verifyAttributes(decoder, text(
diff --git a/test/org/traccar/protocol/PricolProtocolDecoderTest.java b/test/org/traccar/protocol/PricolProtocolDecoderTest.java
new file mode 100644
index 000000000..3826d56c4
--- /dev/null
+++ b/test/org/traccar/protocol/PricolProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class PricolProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ PricolProtocolDecoder decoder = new PricolProtocolDecoder(new PricolProtocol());
+
+ verifyNotNull(decoder, binary(
+ "3c544553303030324b02000000000000000000000000000000000000000000000000000000037c01f4000000000000000000000000000000000000000000003e"));
+
+ verifyPosition(decoder, binary(
+ "3c4944303030303150FFFFFFFF1C050C121D38045D09FA4e001DE815F4452FFFFFFFFFFF03FF03FF03FF03FF03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF113e"));
+
+ }
+
+}
diff --git a/test/org/traccar/protocol/SuntechProtocolDecoderTest.java b/test/org/traccar/protocol/SuntechProtocolDecoderTest.java
index 78e1fb1de..0adc0f2b7 100644
--- a/test/org/traccar/protocol/SuntechProtocolDecoderTest.java
+++ b/test/org/traccar/protocol/SuntechProtocolDecoderTest.java
@@ -11,7 +11,7 @@ public class SuntechProtocolDecoderTest extends ProtocolTest {
SuntechProtocolDecoder decoder = new SuntechProtocolDecoder(new SuntechProtocol());
verifyPosition(decoder, text(
- "ST910;Location;560266;500;20161207;21:33:11;af910be101;-25.504234;-049.278003;000.080;000.00;1;10054889;70;1;1;1311;02;724;06;-317;3041;2;10;92"));
+ "SA200STT;638947;803;20170117;07:40:44;5d309;-01.287213;-047.917462;000.035;000.00;10;1;2036194;12.57;000000;1;0376;010360;4.2;1"));
verifyPosition(decoder, text(
"ST300ALT;205174410;14;712;20110101;00:00:07;00000;+20.593923;-100.336716;000.000;000.00;0;0;0;16.57;000000;81;000000;4.0;0;0.00;0000;0000;0;0"));
@@ -21,7 +21,7 @@ public class SuntechProtocolDecoderTest extends ProtocolTest {
verifyPosition(decoder, text(
"ST910;Alert;123456;410;20141018;18:30:12;+37.478774;+126.889690;000.000;000.00;0;4.0;1;6002"),
- position("2014-10-18 18:30:12.000", true, 37.47877, 126.88969));
+ position("2014-10-18 18:30:12.000", false, 37.47877, 126.88969));
verifyPosition(decoder, text(
"ST910;Alert;123456;410;20141018;18:30:12;+37.478774;+126.889690;000.000;000.00;0;4.0;1;6002;02;0;0310000100;450;01;-282;70;255;3;0"));
@@ -60,6 +60,11 @@ public class SuntechProtocolDecoderTest extends ProtocolTest {
verifyPosition(decoder, text(
"ST910;Emergency;205283272;500;20150716;19:12:01;-23.659019;-046.695403;000.602;000.00;0;4.2;1;1;02;10820;2fdb090736;724;05;0;2311;255;0;100"));
+ decoder.setProtocolType(1);
+
+ verifyPosition(decoder, text(
+ "ST910;Location;560266;500;20161207;21:33:11;af910be101;-25.504234;-049.278003;000.080;000.00;1;10054889;70;1;1;1311;02;724;06;-317;3041;2;10;92"));
+
}
}