From 5e0a1d14b9e626f9b4fc4ef619effbc764ad03e7 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 21 Dec 2020 20:26:39 -0800 Subject: Finish FM IOTM implementation --- .../org/traccar/protocol/IotmProtocolDecoder.java | 117 ++++++++++++++++++++- .../traccar/protocol/IotmProtocolDecoderTest.java | 11 ++ 2 files changed, 125 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/traccar/protocol/IotmProtocolDecoder.java b/src/main/java/org/traccar/protocol/IotmProtocolDecoder.java index 1bf3e4a8d..9a3a4dee1 100644 --- a/src/main/java/org/traccar/protocol/IotmProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/IotmProtocolDecoder.java @@ -16,6 +16,7 @@ package org.traccar.protocol; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.channel.Channel; import io.netty.handler.codec.mqtt.MqttConnAckMessage; import io.netty.handler.codec.mqtt.MqttConnectMessage; @@ -26,8 +27,13 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; import org.traccar.NetworkMessage; import org.traccar.Protocol; +import org.traccar.model.Position; import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; public class IotmProtocolDecoder extends BaseProtocolDecoder { @@ -35,6 +41,58 @@ public class IotmProtocolDecoder extends BaseProtocolDecoder { super(protocol); } + private Object readValue(ByteBuf buf, int sensorType) { + switch (sensorType) { + case 0: + return false; + case 1: + return true; + case 3: + return 0; + case 4: + return buf.readUnsignedByte(); + case 5: + return buf.readUnsignedShortLE(); + case 6: + return buf.readUnsignedIntLE(); + case 7: + case 11: + return buf.readLongLE(); + case 8: + return buf.readByte(); + case 9: + return buf.readShortLE(); + case 10: + return buf.readIntLE(); + case 12: + return buf.readFloatLE(); + case 13: + return buf.readDoubleLE(); + case 32: + return buf.readCharSequence(buf.readUnsignedByte(), StandardCharsets.US_ASCII).toString(); + case 33: + return ByteBufUtil.hexDump(buf.readSlice(buf.readUnsignedByte())); + case 64: + return buf.readCharSequence(buf.readUnsignedShortLE(), StandardCharsets.US_ASCII).toString(); + case 65: + return ByteBufUtil.hexDump(buf.readSlice(buf.readUnsignedShortLE())); + case 2: + default: + return null; + } + } + + private String getKey(int sensorId) { + switch (sensorId) { + case 0x300C: + return Position.KEY_RPM; + case 0x4003: + return Position.KEY_ODOMETER; + default: + return null; + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -52,7 +110,9 @@ public class IotmProtocolDecoder extends BaseProtocolDecoder { MqttConnAckMessage response = MqttMessageBuilders.connAck().returnCode(returnCode).build(); - channel.writeAndFlush(new NetworkMessage(response, remoteAddress)); + if (channel != null) { + channel.writeAndFlush(new NetworkMessage(response, remoteAddress)); + } } else if (msg instanceof MqttPublishMessage) { @@ -61,10 +121,61 @@ public class IotmProtocolDecoder extends BaseProtocolDecoder { return null; } + List positions = new LinkedList<>(); + MqttPublishMessage message = (MqttPublishMessage) msg; - ByteBuf bug = message.payload(); + ByteBuf buf = message.payload(); + + buf.readUnsignedByte(); // structure version + + while (buf.readableBytes() > 1) { + int type = buf.readUnsignedByte(); + int length = buf.readUnsignedShortLE(); + if (type == 1) { + + ByteBuf record = buf.readSlice(length); + + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + position.setTime(new Date(record.readUnsignedIntLE())); + + while (record.readableBytes() > 0) { + int sensorType = record.readUnsignedByte(); + int sensorId = record.readUnsignedShortLE(); + if (sensorType == 14) { + + position.setValid(true); + position.setLatitude(record.readFloatLE()); + position.setLongitude(record.readFloatLE()); + position.setSpeed(record.readUnsignedShortLE()); + + position.set(Position.KEY_HDOP, record.readUnsignedByte()); + position.set(Position.KEY_SATELLITES, record.readUnsignedByte()); + + position.setCourse(record.readUnsignedShortLE()); + position.setAltitude(record.readShortLE()); + + } else { + + String key = getKey(sensorId); + Object value = readValue(record, sensorType); + if (key != null && value != null) { + position.getAttributes().put(key, value); + } + + } + } + + positions.add(position); + + } else { + buf.skipBytes(length); + } + } + + buf.readUnsignedByte(); // checksum - return null; + return positions.isEmpty() ? null : positions; } diff --git a/src/test/java/org/traccar/protocol/IotmProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/IotmProtocolDecoderTest.java index 65fdb82e8..1c783b355 100644 --- a/src/test/java/org/traccar/protocol/IotmProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/IotmProtocolDecoderTest.java @@ -1,5 +1,7 @@ package org.traccar.protocol; +import io.netty.handler.codec.mqtt.MqttMessageBuilders; +import io.netty.handler.codec.mqtt.MqttQoS; import org.junit.Test; import org.traccar.ProtocolTest; @@ -10,6 +12,15 @@ public class IotmProtocolDecoderTest extends ProtocolTest { IotmProtocolDecoder decoder = new IotmProtocolDecoder(null); + verifyNull(decoder, MqttMessageBuilders.connect().clientId( + "123456789012345").build()); + + verifyPositions(decoder, false, MqttMessageBuilders.publish().payload(binary( + "020208009188752DE7120300013A002000AD59050030B135030340030C300301A00302A00E00D0B9AB5B420334C04100001F060000320004072064008C000162002000C004476F6F440109002100AD59050030BA359B")).qos(MqttQoS.EXACTLY_ONCE).build()); + + verifyPositions(decoder, false, MqttMessageBuilders.publish().payload(binary( + "020208009188752DE71203000109002000AD590500309635F3")).qos(MqttQoS.EXACTLY_ONCE).build()); + } } -- cgit v1.2.3