From 1d31ebe88f2674252fc2ab043349b900db5e5e2d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 19 Apr 2023 08:52:10 -0700 Subject: Support BS51 messages --- .../org/traccar/protocol/Tk103ProtocolDecoder.java | 119 ++++++++++++++------- .../traccar/protocol/Tk103ProtocolDecoderTest.java | 3 + 2 files changed, 84 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java index 2b50e55c2..6c926da90 100644 --- a/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java @@ -463,47 +463,90 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder { getLastLocation(position, null); - ByteBuf buf = Unpooled.wrappedBuffer( - DataConverter.parseHex(sentence.substring(1 + 12 + 4, sentence.length() - 1))); - - buf.readUnsignedByte(); - buf.readUnsignedByte(); - buf.readUnsignedByte(); // header - - int batteryCount = buf.readUnsignedByte(); - for (int i = 1; i <= 24; i++) { - int voltage = buf.readUnsignedShortLE(); - if (i <= batteryCount) { - position.set("battery" + i, voltage * 0.001); + String payload = sentence.substring(1 + 12 + 4, sentence.length() - 1); + + if (sentence.startsWith("BS50", 1 + 12)) { + + ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(payload)); + + buf.readUnsignedByte(); + buf.readUnsignedByte(); + buf.readUnsignedByte(); // header + + int batteryCount = buf.readUnsignedByte(); + for (int i = 1; i <= 24; i++) { + int voltage = buf.readUnsignedShortLE(); + if (i <= batteryCount) { + position.set("battery" + i, voltage * 0.001); + } } - } - position.set(Position.KEY_CHARGE, buf.readUnsignedByte() == 0); - position.set("current", buf.readUnsignedShortLE() * 0.1); - position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.01); - position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte()); - position.set("batteryOverheat", buf.readUnsignedByte() > 0); - position.set("chargeProtection", buf.readUnsignedByte() > 0); - position.set("dischargeProtection", buf.readUnsignedByte() > 0); - buf.readUnsignedByte(); // drop line - buf.readUnsignedByte(); // balanced - position.set("cycles", buf.readUnsignedShortLE()); - position.set("faultAlarm", buf.readUnsignedByte()); - - buf.skipBytes(6); - - int temperatureCount = buf.readUnsignedByte(); - position.set("powerTemp", buf.readUnsignedByte() - 40); - position.set("equilibriumTemp", buf.readUnsignedByte() - 40); - for (int i = 1; i <= 7; i++) { - int temperature = buf.readUnsignedByte() - 40; - if (i <= temperatureCount) { - position.set("batteryTemp" + i, temperature); + position.set(Position.KEY_CHARGE, buf.readUnsignedByte() == 0); + position.set("current", buf.readUnsignedShortLE() * 0.1); + position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.01); + position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte()); + position.set("batteryOverheat", buf.readUnsignedByte() > 0); + position.set("chargeProtection", buf.readUnsignedByte() > 0); + position.set("dischargeProtection", buf.readUnsignedByte() > 0); + buf.readUnsignedByte(); // drop line + buf.readUnsignedByte(); // balanced + position.set("cycles", buf.readUnsignedShortLE()); + position.set("faultAlarm", buf.readUnsignedByte()); + + buf.skipBytes(6); + + int temperatureCount = buf.readUnsignedByte(); + position.set("powerTemp", buf.readUnsignedByte() - 40); + position.set("equilibriumTemp", buf.readUnsignedByte() - 40); + for (int i = 1; i <= 7; i++) { + int temperature = buf.readUnsignedByte() - 40; + if (i <= temperatureCount) { + position.set("batteryTemp" + i, temperature); + } } - } - position.set("calibrationCapacity", buf.readUnsignedShortLE() * 0.01); - position.set("dischargeCapacity", buf.readUnsignedIntLE()); + position.set("calibrationCapacity", buf.readUnsignedShortLE() * 0.01); + position.set("dischargeCapacity", buf.readUnsignedIntLE()); + + } else { + + String[] values = payload.split(","); + for (String value : values) { + String[] pair = value.split(":"); + int key = Integer.parseInt(pair[0], 16); + ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(pair[1])); + switch (key) { + case 0x90: + position.set("cumulativeVoltage", buf.readUnsignedShortLE() * 0.1); + position.set("gatherVoltage", buf.readUnsignedShortLE() * 0.1); + position.set("current", (buf.readUnsignedShortLE() - 30000) * 0.1); + position.set("soc", buf.readUnsignedShortLE() * 0.1); + break; + case 0x91: + position.set("maxCellVoltage", buf.readUnsignedShortLE() * 0.001); + position.set("maxCellVoltageCount", buf.readUnsignedByte()); + position.set("minCellVoltage", buf.readUnsignedShortLE() * 0.001); + position.set("minCellVoltageCount", buf.readUnsignedByte()); + break; + case 0x92: + position.set("maxTemp", buf.readUnsignedByte() - 40); + position.set("maxTempCount", buf.readUnsignedByte()); + position.set("minTemp", buf.readUnsignedByte() - 40); + position.set("minTempCount", buf.readUnsignedByte()); + break; + case 0x96: + buf.readUnsignedByte(); // frame + while (buf.isReadable()) { + position.set("cellTemp" + buf.readerIndex(), buf.readUnsignedByte() - 40); + } + break; + default: + break; + } + + } + + } return position; } @@ -537,7 +580,7 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder { return decodeLbsWifi(channel, remoteAddress, sentence); } else if (sentence.contains("BV00")) { return decodeVin(channel, remoteAddress, sentence); - } else if (sentence.contains("BS50")) { + } else if (sentence.contains("BS50") || sentence.contains("BS51")) { return decodeBms(channel, remoteAddress, sentence); } diff --git a/src/test/java/org/traccar/protocol/Tk103ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Tk103ProtocolDecoderTest.java index 1631ab051..a3b3fa86b 100644 --- a/src/test/java/org/traccar/protocol/Tk103ProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/Tk103ProtocolDecoderTest.java @@ -11,6 +11,9 @@ public class Tk103ProtocolDecoderTest extends ProtocolTest { var decoder = inject(new Tk103ProtocolDecoder(null)); + verifyAttributes(decoder, text( + "(007030201454BS5190:02150000753001DC,91:0EE8060EDC0A01DC,92:42014201DC0A01DC,93:00010127000037C8,94:0E01000002000000,95:020EE10EE20EE800030EE40EE00EE700040EDD0EE40EE400050EDC0EDF0EE400,96:0142000000000000,97:0000000000000000,98:0000000000000000)")); + verifyAttribute(decoder, text( "(352602014867BS500064FF0EF10FF10FF00FF20FF30FF20FF20FF40FF20FF40FF40FF20FF30FF20F0000000000000000000000000000000000000000000000001663000000010004000000000000000002444444420000000000A00FA000000000000000200000000315E2000000)"), "batteryTemp2", 26); -- cgit v1.2.3