From 9f6ab9f7934cec76247e1a3e0b0ae4a0f099a5d9 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 17 May 2019 23:04:31 -0700 Subject: Decode additional BCE attributes --- .../org/traccar/protocol/BceProtocolDecoder.java | 187 +++++++++++++++------ .../traccar/protocol/BceProtocolDecoderTest.java | 3 + 2 files changed, 142 insertions(+), 48 deletions(-) diff --git a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java index ed810bebb..ad7271f2f 100644 --- a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 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. @@ -47,6 +47,130 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { public static final int MSG_OUTPUT_CONTROL = 0x41; public static final int MSG_OUTPUT_CONTROL_ACK = 0xC1; + private void decodeMask1(ByteBuf buf, int mask, Position position) { + + if (BitUtil.check(mask, 0)) { + position.setValid(true); + position.setLongitude(buf.readFloatLE()); + position.setLatitude(buf.readFloatLE()); + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); + + int status = buf.readUnsignedByte(); + position.set(Position.KEY_SATELLITES, BitUtil.to(status, 4)); + position.set(Position.KEY_HDOP, BitUtil.from(status, 4)); + + position.setCourse(buf.readUnsignedByte() * 2); + position.setAltitude(buf.readUnsignedShortLE()); + + position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE()); + } + + if (BitUtil.check(mask, 1)) { + position.set(Position.KEY_INPUT, buf.readUnsignedShortLE()); + } + + for (int i = 1; i <= 8; i++) { + if (BitUtil.check(mask, i + 1)) { + position.set(Position.PREFIX_ADC + i, buf.readUnsignedShortLE()); + } + } + + if (BitUtil.check(mask, 10)) { + buf.skipBytes(4); + } + if (BitUtil.check(mask, 11)) { + buf.skipBytes(4); + } + if (BitUtil.check(mask, 12)) { + buf.skipBytes(2); + } + if (BitUtil.check(mask, 13)) { + buf.skipBytes(2); + } + + if (BitUtil.check(mask, 14)) { + position.setNetwork(new Network(CellTower.from( + buf.readUnsignedShortLE(), buf.readUnsignedByte(), + buf.readUnsignedShortLE(), buf.readUnsignedShortLE(), + buf.readUnsignedByte()))); + buf.readUnsignedByte(); + } + } + + private void decodeMask2(ByteBuf buf, int mask, Position position) { + + if (BitUtil.check(mask, 0)) { + buf.readUnsignedShortLE(); // wheel speed + } + if (BitUtil.check(mask, 1)) { + buf.readUnsignedByte(); // acceleration pedal + } + if (BitUtil.check(mask, 2)) { + buf.readUnsignedIntLE(); // total fuel used + } + if (BitUtil.check(mask, 3)) { + buf.readUnsignedByte(); // fuel level + } + if (BitUtil.check(mask, 4)) { + buf.readUnsignedShortLE(); // engine speed + } + if (BitUtil.check(mask, 5)) { + buf.readUnsignedIntLE(); // total hours + } + if (BitUtil.check(mask, 6)) { + buf.readUnsignedIntLE(); // total distance + } + if (BitUtil.check(mask, 7)) { + buf.readUnsignedByte(); // engine coolant + } + if (BitUtil.check(mask, 8)) { + buf.readUnsignedByte(); // fuel level 2 + } + if (BitUtil.check(mask, 9)) { + buf.readUnsignedByte(); // engine load + } + if (BitUtil.check(mask, 10)) { + buf.readUnsignedShortLE(); // service distance + } + if (BitUtil.check(mask, 11)) { + buf.skipBytes(8); // sensors + } + if (BitUtil.check(mask, 12)) { + buf.readUnsignedShortLE(); // ambient air temperature + } + if (BitUtil.check(mask, 13)) { + buf.skipBytes(8); // trailer id + } + if (BitUtil.check(mask, 14)) { + buf.readUnsignedShortLE(); // fuel rate + } + } + + private void decodeMask3(ByteBuf buf, int mask, Position position) { + + if (BitUtil.check(mask, 0)) { + buf.readUnsignedShortLE(); // fuel economy + } + if (BitUtil.check(mask, 1)) { + buf.readUnsignedIntLE(); // fuel consumption + } + if (BitUtil.check(mask, 2)) { + buf.readUnsignedMediumLE(); // axle weight + } + if (BitUtil.check(mask, 3)) { + buf.readUnsignedByte(); // mil status + } + if (BitUtil.check(mask, 4)) { + buf.skipBytes(20); // dtc + } + if (BitUtil.check(mask, 5)) { + buf.readUnsignedShortLE(); + } + if (BitUtil.check(mask, 6)) { + position.set(Position.KEY_DRIVER_UNIQUE_ID, String.valueOf(buf.readLongLE())); + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -95,60 +219,27 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { } while (BitUtil.check(mask, 15)); mask = masks.get(0); + decodeMask1(buf, mask, position); - if (BitUtil.check(mask, 0)) { - position.setValid(true); - position.setLongitude(buf.readFloatLE()); - position.setLatitude(buf.readFloatLE()); - position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); - - int status = buf.readUnsignedByte(); - position.set(Position.KEY_SATELLITES, BitUtil.to(status, 4)); - position.set(Position.KEY_HDOP, BitUtil.from(status, 4)); - - position.setCourse(buf.readUnsignedByte() * 2); - position.setAltitude(buf.readUnsignedShortLE()); - - position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE()); - } - - if (BitUtil.check(mask, 1)) { - position.set(Position.KEY_INPUT, buf.readUnsignedShortLE()); + if (masks.size() >= 2) { + mask = masks.get(1); + decodeMask2(buf, mask, position); } - for (int i = 1; i <= 8; i++) { - if (BitUtil.check(mask, i + 1)) { - position.set(Position.PREFIX_ADC + i, buf.readUnsignedShortLE()); - } - } - - if (BitUtil.check(mask, 10)) { - buf.skipBytes(4); - } - if (BitUtil.check(mask, 11)) { - buf.skipBytes(4); - } - if (BitUtil.check(mask, 12)) { - buf.skipBytes(2); - } - if (BitUtil.check(mask, 13)) { - buf.skipBytes(2); - } - - if (BitUtil.check(mask, 14)) { - position.setNetwork(new Network(CellTower.from( - buf.readUnsignedShortLE(), buf.readUnsignedByte(), - buf.readUnsignedShortLE(), buf.readUnsignedShortLE(), - buf.readUnsignedByte()))); - buf.readUnsignedByte(); - } - - if (BitUtil.check(mask, 0)) { - positions.add(position); + if (masks.size() >= 3) { + mask = masks.get(2); + decodeMask3(buf, mask, position); } } buf.readerIndex(structEnd); + + if (position.getValid()) { + positions.add(position); + } else if (!position.getAttributes().isEmpty()) { + getLastLocation(position, null); + positions.add(position); + } } // Send response diff --git a/src/test/java/org/traccar/protocol/BceProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/BceProtocolDecoderTest.java index 400ba7e12..40ffbe5a5 100644 --- a/src/test/java/org/traccar/protocol/BceProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/BceProtocolDecoderTest.java @@ -13,6 +13,9 @@ public class BceProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, binary( "3ab90b71bc1503000300c10bff11")); + verifyPositions(decoder, false, binary( + "76145792c61603003402a59b59a7f722aa8ac00080c086000121800000280f9401056804d181006222ea4201000000000000008081008081008081008081000022ea4201000000000000ffffffffffff00000000ffffffffffff00000000ffffffffffff000059f7f722aa8ac00080c086000121800000260f9401056804d181006222ea4201000000000000008081008081008081008081000022ea4201000000000000ffffffffffff00000000ffffffffffff00000000ffffffffffff00000a16f822aa6f07534352325917f822aa8ac00080c086000120800000190f9401056804d181006222ea4201000000000000008081008081008081008081000022ea4201000000000000ffffffffffff00000000ffffffffffff00000000ffffffffffff00005957f822aa8ac00080c086000121800000240f9401056804d181006222ea4201000000000000008081008081008081008081000022ea4201000000000000ffffffffffff00000000ffffffffffff00000000ffffffffffff00000a66f822aa6f07534352325967f822aa8ac00080c086000121a00000160f9401056804d181006222ea4201000000000000008081008081008081008081000022ea4201000000000000ffffffffffff00000000ffffffffffff00000000ffffffffffff000059b7f822aa8ac00080c086000121800000170f9401056804d181006222ea4201000000000000008081008081008081008081000022ea4201000000000000ffffffffffff00000000ffffffffffff00000000ffffffffffff0000ef")); + verifyPositions(decoder, binary( "789622d1cb1303003401a53365b70f4a9babc0ffd700c04400f0b6c741e63933428f1c431c015468de43f18221341b007e0ae20001430a698f003f008d000000000031f85900000000f0831c018400000000000000000000000000000000000209000000000000000000000000000000030065f70f4a9babc0ffd700c0440069bcc741e73733427f1c431a01a9378343f1829c391b00a80be2000170056da7003e007c000000000031c04e00000000f0831c01810000000000000000000000000000000000060100000000000000000000000000000003006537104a9babc0ffd700c0440051c1c74129363342721c421801e4809543f18210341b00710ae2000170056da7003e0072000000000031c04800000000b8841c017e00000000000000000000000000000000000306000000000000000000000000000000030069")); -- cgit v1.2.3