[PATCH] Suntech (universal) add ignition, battery and power fields

Iván Ávalos2 years ago

I'll be sending in code contributions as patches, because I'm not using GitHub to maintain my fork. This patch adds support for ignition, battery and power fields in the Suntech Universal protocol. Please let me know if there's a better way I can send you patches.

From: ~avalos <avalos@git.sr.ht>
Date: Fri, 12 Aug 2022 14:54:27 -0500
Subject: [PATCH trackermap-server] Added ignition, battery and power fields
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset="utf-8"

From: Iván Ávalos <avalos@disroot.org>

---
 .../java/org/traccar/protocol/SuntechProtocolDecoder.java   | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
index 707e2d41b..cfcbf4324 100644
--- a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
@@ -575,6 +575,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
 
             if (BitUtil.check(mask, 17)) {
                 position.set(Position.KEY_INPUT, Integer.parseInt(values[index++]));
+                position.set(Position.KEY_IGNITION, values[index - 1].charAt(7) == '1');
             }
 
             if (BitUtil.check(mask, 18)) {
@@ -612,6 +613,11 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
                 for (int i = 0; i <= 30; i++) {
                     if (BitUtil.check(assignMask, i)) {
                         position.set(Position.PREFIX_IO + (i + 1), values[index++]);
+                        if ((i + 1) == 1) {
+                            position.set(Position.KEY_BATTERY, Double.parseDouble(values[index - 1]));
+                        } else if ((i + 1) == 2) {
+                            position.set(Position.KEY_POWER, Double.parseDouble(values[index - 1]));
+                        }
                     }
                 }
             }
-- 
2.34.2
Anton Tananaev2 years ago

Please provide protocol documentation.

Iván Ávalos2 years ago

Traccar, as it stands now, supports the “Normal (ASCII, variable length)” variant of the Universal protocol, documented in section 1.2 of the following document: https://nextcloud.avalos.me/index.php/s/NQfysH2Lk6LGW7x

The field IN_STATE specifies that bit 0 corresponds to ignition (1 = ON, 0 = OFF), which was properly implemented in this patch. Battery and power are not explicitly documented, but the ST4310 we're using seems to place them at S_ASSIGN1 and S_ASSIGN2 fields, which Traccar stores as Position.PREFIX_IO + (i + 1) using Bitutil to test ASSIGN_MAP, whose bits map the S_ASSIGN fields that are set.

Here's an example payload of the ST4310:

ALT;0413022067;BFFFFF;52;1.0.37;0;20220812;19:09:41;01B7FD02;334;20;5B11;34;[LAT REDACTED];[LNG REDACTED];0.00;0.00;15;1;00000000;00000000;31;1;;00000003;4.1;12.98

Where the last two fields correspont to (in order) the internal battery and the external power. The third last field is a 32 bit value that translates to 0000 0000 0000 0000 0000 0000 0000 0011 in binary. The last two bits correspond to the first two S_ASSIGN fields, which are set to 4.1 and 12.98.

Anton Tananaev2 years ago

This would be a problem:

Battery and power are not explicitly documented

We can only include it if it's officially documented somewhere.

By the way, we supports both text and binary versions of the protocol, as far as I know.

Iván Ávalos2 years ago

I checked again the documentation, and in section 16 (“Small Asign Headers”), there is a table that describes the purpose of each S_ASSIGN field. The first two are BCK_VOLT (Current Backup Battery Voltage) and PWR_VOLT (Current Main Power Voltage). Turns out they are actually explicitly documented!

By the way, we supports both text and binary versions of the protocol

I was talking specifically about the Universal variant of the Suntech protocol. I can't find the code for the fixed-length hex-encoded Zip variant of the Universal protocol.

Anton Tananaev2 years ago

There are 15 S_ASSIGN fields, but there are 20+ "Small Asign Headers". Can you please clarify how that works.

Iván Ávalos2 years ago

You are right, apparently the “Small Assign Headers” table describes the optional fields that can be placed inside S_ASSIGN headers (any of them). There are also tables for M_ASSIGN and L_ASSIGN in sections 17 and 18, respectively. There is no documentation of any mandatory mapping of fields into headers.

A possible alternative would be to use device attributes for this. Something like: suntech.battery-io = 1 and suntech.power-io = 2, so we can determine which fields correspond to which headers.

Anton Tananaev2 years ago

This is exactly what computed attributes are designed for.

Iván Ávalos2 years ago

Could you at least merge the ignition part?

Iván Ávalos2 years ago

Battery and power are often doubles, which Traccar doesn't seem to support (I tried and it failed with a NumberFormatException). The modern UI assigns them the number data type when creating the computed attribute. Should I submit a patch to traccar-web changing them to string, or is there something else I don't know?

Anton Tananaev2 years ago

Double is also a number. You have to convert a string to number.

Iván Ávalos2 years ago

How do I do that using JEXL. This syntax reference linked in the documentation doesn't say how. https://commons.apache.org/proper/commons-jexl/reference/syntax.html

Anton Tananaev2 years ago

Added ignition support:

https://github.com/traccar/traccar/commit/d8607eb0e840df9df7006f7ae2a15b8b082bf7bf

As for JEXL, I don't have an answer, but it should be possible.

Iván Ávalos2 years ago

Thank you very much. I think I figured out how to do the conversion:

new("java.lang.Double", io1)
Rastrecama year ago

hello

I know it's been a while but I would like some help with calculated attributes.
I receive information from the main energy in io1 and the battery in io2, however the power field is 0v I would like to point the io1 in the power field?