diff options
-rw-r--r-- | schema/changelog-3.10.xml | 48 | ||||
-rw-r--r-- | setup/default.xml | 1 | ||||
-rw-r--r-- | src/org/traccar/api/resource/CommandResource.java | 2 | ||||
-rw-r--r-- | src/org/traccar/protocol/AquilaProtocolDecoder.java | 75 | ||||
-rw-r--r-- | src/org/traccar/protocol/Gl200ProtocolDecoder.java | 37 | ||||
-rw-r--r-- | src/org/traccar/protocol/MxtProtocolDecoder.java | 21 | ||||
-rw-r--r-- | src/org/traccar/protocol/PricolProtocol.java | 43 | ||||
-rw-r--r-- | src/org/traccar/protocol/PricolProtocolDecoder.java | 96 | ||||
-rw-r--r-- | src/org/traccar/protocol/SuntechProtocolDecoder.java | 166 | ||||
-rw-r--r-- | src/org/traccar/protocol/TeltonikaProtocolDecoder.java | 52 | ||||
-rw-r--r-- | test/org/traccar/protocol/AquilaProtocolDecoderTest.java | 6 | ||||
-rw-r--r-- | test/org/traccar/protocol/Gl200ProtocolDecoderTest.java | 2 | ||||
-rw-r--r-- | test/org/traccar/protocol/PricolProtocolDecoderTest.java | 21 | ||||
-rw-r--r-- | test/org/traccar/protocol/SuntechProtocolDecoderTest.java | 9 |
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")); + } } |