diff options
-rw-r--r-- | src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java | 216 | ||||
-rw-r--r-- | src/test/java/org/traccar/protocol/TranSyncProtocolDecoderTest.java | 7 |
2 files changed, 98 insertions, 125 deletions
diff --git a/src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java b/src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java index d5a69dbe2..d07b70365 100644 --- a/src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2013 - 2023 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 io.netty.buffer.ByteBuf; @@ -6,6 +21,7 @@ import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.Protocol; import org.traccar.helper.BitUtil; +import org.traccar.helper.DateBuilder; import org.traccar.helper.UnitsConverter; import org.traccar.model.CellTower; import org.traccar.model.Network; @@ -13,206 +29,166 @@ import org.traccar.model.Position; import org.traccar.session.DeviceSession; import java.net.SocketAddress; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; +import java.util.Arrays; public class TranSyncProtocolDecoder extends BaseProtocolDecoder { + private static final byte[] STX = new byte[]{0x3a, 0x3a}; + public TranSyncProtocolDecoder(Protocol protocol) { super(protocol); } - public Date getDatefromIntegerParameters(int year, int month, int day, int hours, int minutes, int seconds) { - - String dataString = ""+year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds; - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); - simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - try { - return simpleDateFormat.parse(dataString); - - } catch (ParseException e) { - e.printStackTrace(); - } - return null; - } - - protected void setDeviceAlert(Position position, int alert) { - switch (alert) { + protected void decodeAlarm(Position position, int value) { + switch (value) { case 10: - position.set(Position.ALARM_SOS, true); + position.set(Position.KEY_ALARM, Position.ALARM_SOS); break; case 11: - position.set(Position.ALARM_SOS, false); + position.set(Position.KEY_EVENT, 11); break; case 16: position.set(Position.KEY_EVENT, 16); break; case 3: - position.set("distressCutOff", true); + position.set(Position.KEY_ALARM, 3); break; case 22: - position.set("tilt", true); + position.set(Position.KEY_ALARM, 22); break; case 9: position.set(Position.KEY_EVENT, 9); case 17: - position.set(Position.ALARM_OVERSPEED, true); + position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED); break; case 13: - position.set(Position.ALARM_BRAKING, true); + position.set(Position.KEY_ALARM, Position.ALARM_BRAKING); break; case 14: - position.set(Position.ALARM_ACCELERATION, true); + position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION); break; case 15: position.set(Position.KEY_EVENT, 15); break; case 23: - position.set(Position.ALARM_ACCIDENT, true); + position.set(Position.KEY_ALARM, Position.ALARM_ACCIDENT); break; case 12: position.set(Position.KEY_EVENT, 12); break; case 6: - position.set(Position.ALARM_POWER_RESTORED, true); + position.set(Position.KEY_ALARM, Position.ALARM_POWER_RESTORED); break; case 4: - position.set(Position.ALARM_LOW_BATTERY, true); + position.set(Position.KEY_ALARM, Position.ALARM_LOW_BATTERY); break; case 5: position.set(Position.KEY_EVENT, 5); break; - } - - } - - private void setNetwork(Position position, int lacInt, int cellIdInt, int mobileNetworkCode, int gsmSignalStrength){ - CellTower cellTower = CellTower.fromLacCid(getConfig(), lacInt, cellIdInt); - cellTower.setMobileNetworkCode(mobileNetworkCode); - cellTower.setSignalStrength(gsmSignalStrength); - position.setNetwork(new Network(cellTower)); - } - private String getTrackerModel(int mask){ + private void decodePowerEngineParameters(Position position, int value){ - switch (mask) { - case 1: - return "basic"; - case 2: - return "asset"; - case 3: - return "bike"; + position.set(Position.PREFIX_OUT + 1, BitUtil.check(value, 7)); + position.set(Position.PREFIX_OUT + 2, BitUtil.check(value, 6)); + position.set(Position.PREFIX_IN + 3, BitUtil.check(value, 5)); + if (BitUtil.check(value, 4)) position.set(Position.KEY_ALARM, Position.ALARM_POWER_OFF); + position.set(Position.KEY_IGNITION, BitUtil.check(value, 3)); + position.set("gpsFix", BitUtil.check(value, 0)); - case 4: - return "serial"; + } - case 5: - return "obd"; - case 6: - return "l1"; - case 7: - return "ais"; - default: - return "unknown"; + private void decodeTrackerStatusParameters(Position position, int value){ + if (BitUtil.check(value, 7)) position.set("restored", true); + if (BitUtil.check(value, 5)) { + position.set(Position.KEY_ALARM, Position.ALARM_GPS_ANTENNA_CUT); } - } - private Position parseData(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { - if (ByteBufUtil.hexDump(buf, 0, 2).equalsIgnoreCase("3A3A")) { + @Override + protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + ByteBuf buf = (ByteBuf) msg; + if (Arrays.equals(ByteBufUtil.getBytes(buf, 0, 2), STX)) { buf.readUnsignedShort(); } - int packetLength = buf.readByte(); - int lacInt = buf.readUnsignedShort(); - String deviceId = ByteBufUtil.hexDump(buf, buf.readerIndex(), 8).toUpperCase().trim().replaceFirst("^0+(?!$)", ""); - buf.readBytes(8); - int informationSerialNumber = buf.readUnsignedShort(); - int protocolNumber = buf.readUnsignedByte(); + buf.readByte(); //packetLength + + int locationAreaCode = buf.readUnsignedShort(); + String deviceId = ByteBufUtil.hexDump(buf.readSlice(8)); + + buf.readUnsignedShort(); //informationSerialNumber + buf.readUnsignedByte(); //protocolNumber + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, deviceId); if (deviceSession == null) { return null; } - Position position = new Position(getProtocolName()); - long devicesessionId = deviceSession.getDeviceId(); - - position.setDeviceId(devicesessionId) ; + position.setDeviceId(deviceSession.getDeviceId()); position.setValid(true); - int year = buf.readUnsignedByte(); - int month = buf.readUnsignedByte(); - int day = buf.readUnsignedByte(); - int hour = buf.readUnsignedByte(); - int minute = buf.readUnsignedByte(); - int second = buf.readUnsignedByte(); - position.setTime(getDatefromIntegerParameters(year, month, day, hour, minute, second)); + position.setTime(new DateBuilder() + .setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()) + .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()) + .getDate()); position.setLatitude(buf.readUnsignedInt() / 1800000.0); position.setLongitude(buf.readUnsignedInt() / 1800000.0); position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); position.setCourse(buf.readUnsignedShort()); + int mobileNetworkCode = buf.readUnsignedByte(); - int cellIdInt = buf.readUnsignedShort(); - int zeroByte = buf.readUnsignedByte(); - position.set(Position.PREFIX_OUT + 1, BitUtil.check(zeroByte, 0)); - position.set(Position.PREFIX_OUT + 2, BitUtil.check(zeroByte, 1)); - position.set(Position.PREFIX_IN + 3, BitUtil.check(zeroByte, 2)); - if (BitUtil.check(zeroByte, 3)) position.set(Position.ALARM_POWER_OFF, true); - position.set(Position.KEY_IGNITION, BitUtil.check(zeroByte, 4)); - position.set("gpsFix", BitUtil.check(zeroByte, 7)); - int oneByte = buf.readUnsignedByte(); - int deviceAlert = buf.readUnsignedByte(); - if (deviceAlert > 0) { setDeviceAlert(position, deviceAlert); } - int threeByte = buf.readUnsignedByte(); - if (!((threeByte & 0b10000000) == 0)) position.set("restored", true); - if ((threeByte & 0b00100000) != 0) { - position.set(Position.ALARM_GPS_ANTENNA_CUT, true); - position.set("gpsAlert", true); - } - position.set("model", getTrackerModel(threeByte & 0b00001111)); + int cellTowerId = buf.readUnsignedShort(); + + decodePowerEngineParameters(position, buf.readUnsignedByte()); + + buf.readUnsignedByte(); // not in use + + decodeAlarm(position, buf.readUnsignedByte()); + + decodeTrackerStatusParameters(position, buf.readUnsignedByte()); + int gsmSignalStrength = buf.readUnsignedByte(); + position.set(Position.KEY_BATTERY, (double) (buf.readUnsignedByte() / 10)); position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); position.set(Position.KEY_HDOP, buf.readUnsignedByte()); position.set(Position.PREFIX_ADC + 1, (short) buf.readUnsignedShort()); - boolean isOptionalParameters = (buf.readableBytes() > 2); - setNetwork(position, lacInt, cellIdInt, mobileNetworkCode, gsmSignalStrength); - if (isOptionalParameters) { // Always True - int odometerIndex = buf.readUnsignedByte(); + + CellTower cellTower = CellTower.fromLacCid(getConfig(), locationAreaCode, cellTowerId); + cellTower.setMobileNetworkCode(mobileNetworkCode); + cellTower.setSignalStrength(gsmSignalStrength); + + position.setNetwork(new Network(cellTower)); + + if (buf.readableBytes() > 2) { + buf.readUnsignedByte(); // odometerIndex int odometerLength = buf.readUnsignedByte(); if (odometerLength > 0) { - String odometerReading = ByteBufUtil.hexDump(buf, buf.readerIndex(), odometerLength).toUpperCase().trim().replaceFirst("^0+(?!$)", ""); - int odometer = Integer.parseInt(odometerReading); - buf.readBytes(odometerLength); + int odometer = buf.readBytes(odometerLength).readInt(); position.set(Position.KEY_ODOMETER, odometer); } if ((buf.readableBytes() > 2)) { - int rfidIndex = buf.readUnsignedByte(); - int rfidLength = buf.readUnsignedByte(); - if(rfidLength > 0) { - String rfidTagName = ByteBufUtil.hexDump(buf, buf.readerIndex(), rfidLength).toUpperCase().trim(); - buf.readBytes(rfidLength); - position.set("tag", rfidTagName); + buf.readUnsignedByte(); // tagIndex + int tagLength = buf.readUnsignedByte(); + if (tagLength > 0) { + position.set("tag", ByteBufUtil.hexDump(buf.readSlice(tagLength))); } } if ((buf.readableBytes() > 5)) { - int adcTwoIndex = buf.readUnsignedByte(); - int adcTwoLength = buf.readUnsignedByte(); - if (adcTwoLength > 0){ + buf.readUnsignedByte(); // adc2Index + int adc2Length = buf.readUnsignedByte(); + if (adc2Length > 0) { position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShort()); } } + if ((buf.readableBytes() > 5)) { + buf.readUnsignedByte(); // adc2Index + int adc2Length = buf.readUnsignedByte(); + if (adc2Length > 0 && adc2Length <= buf.readableBytes() - 2) { + position.set(Position.PREFIX_ADC + 3, buf.readUnsignedShort()); + } + } } - return position; } - - @Override - protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - ByteBuf buffer = (ByteBuf) msg; - return parseData(channel, remoteAddress, buffer); - } - } diff --git a/src/test/java/org/traccar/protocol/TranSyncProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TranSyncProtocolDecoderTest.java index 1b90566d4..6cf2d0c1f 100644 --- a/src/test/java/org/traccar/protocol/TranSyncProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/TranSyncProtocolDecoderTest.java @@ -1,6 +1,5 @@ package org.traccar.protocol; - import org.junit.jupiter.api.Test; import org.traccar.ProtocolTest; @@ -11,12 +10,10 @@ public class TranSyncProtocolDecoderTest extends ProtocolTest { var decoder = inject(new TranSyncProtocolDecoder(null)); - verifyPosition(decoder, binary( - "3a3a2b583f086065705154043900801017050b11190f01623ef40887dff00000c25e9ff707000007152a2d0000000105004794916902050000000000050252ee060200822323")); + "3a3a2b583f086065705154043900801017050b11190f01623ef40887dff00000c25e9ff707000007152a2d0000000105004794916902050000100000050252ee060200822323")); verifyAttributes(decoder, binary( - "3a3a2b583f086065705154043900801017050b11190f01623ef40887dff00000c25e9ff707000007152a2d0000000105004794916902050000000000050252ee060200822323") - ); + "3a3a2b583f086065705154043900801017050b11190f01623ef40887dff00000c25e9ff707000007152a2d0000000105004794916902050000000000050252ee060200822323")); } } |