From a09654ab3c4b540d1c4c768ad4c7ec7c1404332d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 12 May 2019 22:17:40 -0700 Subject: Support modular messages --- .../traccar/protocol/CellocatorFrameDecoder.java | 9 +- .../protocol/CellocatorProtocolDecoder.java | 188 ++++++++++++++------- 2 files changed, 131 insertions(+), 66 deletions(-) (limited to 'src/main/java/org/traccar/protocol') diff --git a/src/main/java/org/traccar/protocol/CellocatorFrameDecoder.java b/src/main/java/org/traccar/protocol/CellocatorFrameDecoder.java index 7d5499d92..ee2adde6d 100644 --- a/src/main/java/org/traccar/protocol/CellocatorFrameDecoder.java +++ b/src/main/java/org/traccar/protocol/CellocatorFrameDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2013 - 2019 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,11 +46,14 @@ public class CellocatorFrameDecoder extends BaseFrameDecoder { break; case CellocatorProtocolDecoder.MSG_CLIENT_SERIAL: if (buf.readableBytes() >= 19) { - length = 19 + buf.getUnsignedShortLE(16); + length = 19 + buf.getUnsignedShortLE(buf.readerIndex() + 16); } break; case CellocatorProtocolDecoder.MSG_CLIENT_MODULAR: - length = 15 + buf.getUnsignedByte(13); + length = 15 + buf.getUnsignedByte(buf.readerIndex() + 13); + break; + case CellocatorProtocolDecoder.MSG_CLIENT_MODULAR_EXT: + length = 16 + buf.getUnsignedShortLE(buf.readerIndex() + 13); break; default: break; diff --git a/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java index d23f76a93..f53c01234 100644 --- a/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java @@ -39,6 +39,7 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { static final int MSG_CLIENT_SERIAL_LOG = 7; static final int MSG_CLIENT_SERIAL = 8; static final int MSG_CLIENT_MODULAR = 9; + static final int MSG_CLIENT_MODULAR_EXT = 11; public static final int MSG_SERVER_ACKNOWLEDGE = 4; @@ -82,93 +83,154 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { } } - @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + private Position decodeStatus(ByteBuf buf, DeviceSession deviceSession, boolean alternative) { - ByteBuf buf = (ByteBuf) msg; + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); - boolean alternative = buf.getByte(buf.readerIndex() + 3) != 'P'; + position.set(Position.KEY_VERSION_HW, buf.readUnsignedByte()); + position.set(Position.KEY_VERSION_FW, buf.readUnsignedByte()); + buf.readUnsignedByte(); // protocol version - buf.skipBytes(4); // system code - int type = buf.readUnsignedByte(); - long deviceUniqueId = buf.readUnsignedIntLE(); + position.set(Position.KEY_STATUS, buf.readUnsignedByte() & 0x0f); - if (type != MSG_CLIENT_SERIAL) { - buf.readUnsignedShortLE(); // communication control + buf.readUnsignedByte(); // operator / configuration flags + buf.readUnsignedByte(); // reason data + position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedByte())); + + position.set("mode", buf.readUnsignedByte()); + position.set(Position.KEY_INPUT, buf.readUnsignedIntLE()); + + if (alternative) { + buf.readUnsignedByte(); // input + position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShortLE()); + position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShortLE()); + } else { + buf.readUnsignedByte(); // operator + position.set(Position.PREFIX_ADC + 1, buf.readUnsignedIntLE()); } - byte packetNumber = buf.readByte(); - sendReply(channel, remoteAddress, deviceUniqueId, packetNumber); + position.set(Position.KEY_ODOMETER, buf.readUnsignedMediumLE()); - if (type == MSG_CLIENT_STATUS) { + buf.skipBytes(6); // multi-purpose data + buf.readUnsignedShortLE(); // fix time + buf.readUnsignedByte(); // location status + buf.readUnsignedByte(); // mode 1 + buf.readUnsignedByte(); // mode 2 - Position position = new Position(getProtocolName()); + position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(deviceUniqueId)); - if (deviceSession == null) { - return null; - } - position.setDeviceId(deviceSession.getDeviceId()); + position.setValid(true); - position.set(Position.KEY_VERSION_HW, buf.readUnsignedByte()); - position.set(Position.KEY_VERSION_FW, buf.readUnsignedByte()); - buf.readUnsignedByte(); // protocol version + if (alternative) { + position.setLongitude(buf.readIntLE() / 10000000.0); + position.setLatitude(buf.readIntLE() / 10000000.0); + } else { + position.setLongitude(buf.readIntLE() / Math.PI * 180 / 100000000); + position.setLatitude(buf.readIntLE() / Math.PI * 180 / 100000000); + } - position.set(Position.KEY_STATUS, buf.readUnsignedByte() & 0x0f); + position.setAltitude(buf.readIntLE() * 0.01); - buf.readUnsignedByte(); // operator / configuration flags - buf.readUnsignedByte(); // reason data - position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedByte())); + if (alternative) { + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedIntLE())); + position.setCourse(buf.readUnsignedShortLE() / 1000.0); + } else { + position.setSpeed(UnitsConverter.knotsFromMps(buf.readUnsignedIntLE() * 0.01)); + position.setCourse(buf.readUnsignedShortLE() / Math.PI * 180.0 / 1000.0); + } - position.set("mode", buf.readUnsignedByte()); - position.set(Position.KEY_INPUT, buf.readUnsignedIntLE()); + DateBuilder dateBuilder = new DateBuilder() + .setTimeReverse(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()) + .setDateReverse(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedShortLE()); + position.setTime(dateBuilder.getDate()); + + return position; + } - if (alternative) { - buf.readUnsignedByte(); // input - position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShortLE()); - position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShortLE()); - } else { - buf.readUnsignedByte(); // operator - position.set(Position.PREFIX_ADC + 1, buf.readUnsignedIntLE()); + private Position decodeModular(ByteBuf buf, DeviceSession deviceSession) { + + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + buf.readUnsignedByte(); // packet control + buf.readUnsignedShortLE(); // length + buf.readUnsignedShortLE(); // reserved + buf.readUnsignedShortLE(); // reserved + + while (buf.readableBytes() > 3) { + + int moduleType = buf.readUnsignedByte(); + int endIndex = buf.readUnsignedShortLE() + buf.readerIndex(); + + switch (moduleType) { + case 2: + buf.readUnsignedShortLE(); // operator id + buf.readUnsignedIntLE(); // pl signature + int count = buf.readUnsignedByte(); + for (int i = 0; i < count; i++) { + int id = buf.readUnsignedShortLE(); + buf.readUnsignedByte(); // variable length + position.set(Position.PREFIX_IO + id, buf.readUnsignedIntLE()); + } + break; + case 6: + buf.readUnsignedByte(); // hdop + buf.readUnsignedByte(); // mode 1 + buf.readUnsignedByte(); // mode 2 + buf.readUnsignedByte(); // satellites + position.setLongitude(buf.readIntLE() / Math.PI * 180 / 100000000); + position.setLatitude(buf.readIntLE() / Math.PI * 180 / 100000000); + position.setAltitude(buf.readIntLE() * 0.01); + position.setSpeed(UnitsConverter.knotsFromMps(buf.readUnsignedByte() * 0.01)); + position.setCourse(buf.readUnsignedShortLE() / Math.PI * 180.0 / 1000.0); + break; + case 7: + buf.readUnsignedByte(); // valid + DateBuilder dateBuilder = new DateBuilder() + .setTimeReverse(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()) + .setDateReverse(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()); + position.setTime(dateBuilder.getDate()); + break; + default: + break; } - position.set(Position.KEY_ODOMETER, buf.readUnsignedMediumLE()); + buf.readerIndex(endIndex); - buf.skipBytes(6); // multi-purpose data - buf.readUnsignedShortLE(); // fix time - buf.readUnsignedByte(); // location status - buf.readUnsignedByte(); // mode 1 - buf.readUnsignedByte(); // mode 2 + } - position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); + return position; + } - position.setValid(true); + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - if (alternative) { - position.setLongitude(buf.readIntLE() / 10000000.0); - position.setLatitude(buf.readIntLE() / 10000000.0); - } else { - position.setLongitude(buf.readIntLE() / Math.PI * 180 / 100000000); - position.setLatitude(buf.readIntLE() / Math.PI * 180 / 100000000); - } + ByteBuf buf = (ByteBuf) msg; - position.setAltitude(buf.readIntLE() * 0.01); + boolean alternative = buf.getByte(buf.readerIndex() + 3) != 'P'; - if (alternative) { - position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedIntLE())); - position.setCourse(buf.readUnsignedShortLE() / 1000.0); - } else { - position.setSpeed(UnitsConverter.knotsFromMps(buf.readUnsignedIntLE() * 0.01)); - position.setCourse(buf.readUnsignedShortLE() / Math.PI * 180.0 / 1000.0); - } + buf.skipBytes(4); // system code + int type = buf.readUnsignedByte(); - DateBuilder dateBuilder = new DateBuilder() - .setTimeReverse(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()) - .setDateReverse(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedShortLE()); - position.setTime(dateBuilder.getDate()); + long deviceUniqueId = buf.readUnsignedIntLE(); + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(deviceUniqueId)); + if (deviceSession == null) { + return null; + } + + if (type != MSG_CLIENT_SERIAL) { + buf.readUnsignedShortLE(); // communication control + } + byte packetNumber = buf.readByte(); - return position; + sendReply(channel, remoteAddress, deviceUniqueId, packetNumber); + + if (type == MSG_CLIENT_STATUS) { + return decodeStatus(buf, deviceSession, alternative); + } else if (type == MSG_CLIENT_MODULAR_EXT) { + return decodeModular(buf, deviceSession); } return null; -- cgit v1.2.3