Suntech Protocol - Module Battery Information.

Turbovix6 days ago

Hello everyone, does anyone know if the Suntech protocol decoder can decode the module battery value? Below is what the module reports to the platform.

ST300STT;999999999;145;403;20250116;07:37:38;1b7326;-20.336503;-040.285532;000.000;058.41;11;1;71408838;12.68;000010;1;2397;105537;4.1;1

The module battery value is 4.1, that is, the penultimate value.

When trying to retrieve the value of the "battery" attribute using computed attributes, I receive the following error:

org.traccar.handler.ComputedAttributesHandler.computeAttribute:137@1:1 variable 'battery' is undefined - Variable (ComputedAttributesHandler:138 < AttributeResource:63 < ... < OverrideFilter:49 < ...)

However, using "power" I receive the vehicle's battery value correctly.

Turbovix6 days ago

Looking at the protocol code, shouldn't the battery value be interpreted directly in the "case "STT" on line 406, instead of in the " if (getHbm(deviceSession.getDeviceId()) == 1)" ?

Turbovix6 days ago

I made the following change and now the module battery value is displayed.

switch (type) {
    case "STT" -> {
        position.set(Position.KEY_STATUS, Integer.parseInt(values[index++]));
        
        position.set(Position.KEY_INDEX, Integer.parseInt(values[index++]));

        // Skip the next intermediate value        
        index++; 

        // KEY_BATTERY
        if (index < values.length) {
            position.set(Position.KEY_BATTERY, Double.parseDouble(values[index++]));
        }    
    }
    case "EMG" -> position.addAlarm(decodeEmergency(Integer.parseInt(values[index++])));
    case "EVT" -> position.set(Position.KEY_EVENT, Integer.parseInt(values[index++]));
    case "ALT" -> position.addAlarm(decodeAlert(Integer.parseInt(values[index++])));
    case "UEX" -> index = decodeSerialData(position, values, index);
}
Anton Tananaev6 days ago

I believe other types also support it and it should be only included with HBM = 1, so the original code looks correct and what you have is incorrect. But maybe you have some other protocol documentation that you didn't share.

Turbovix6 days ago

Anton, there are 7 decoding methods in SuntechProtocolDecoder.java, which determines that the information received from a specific module is decoded by method A or B...? In my case, I have modules ST340, ST340UR, ST340RB, ST310UC2.

Based on the documentation and table provided by suntech, I implemented it like this, the internal battery they call batteryBackup.

if (protocol.startsWith("ST3") || protocol.equals("ST500") || protocol.equals("ST600")) {
            index += 1; // model
            // implementado por Junior Melo 11/06/2024
            String batteryBackup; // battery internal in volt


            if (type.equals("ALT") || type.equals("EMG") && values.length == 20) {


                batteryBackup = values[18];

                double voltage = Double.parseDouble(batteryBackup);

                double batteryPercentage = 0;

                if (voltage >= 4.06) {
                    batteryPercentage = 100;
                } else if (voltage >= 3.97) {
                    batteryPercentage = 90;
                } else if (voltage >= 3.89) {
                    batteryPercentage = 80;
                } else if (voltage >= 3.83) {
                    batteryPercentage = 70;
                } else if (voltage >= 3.77) {
                    batteryPercentage = 60;
                } else if (voltage >= 3.75) {
                    batteryPercentage = 50;
                } else if (voltage >= 3.73) {
                    batteryPercentage = 40;
                } else if (voltage >= 3.66) {
                    batteryPercentage = 30;
                } else if (voltage >= 3.53) {
                    batteryPercentage = 20;
                } else if (voltage >= 3.49) {
                    batteryPercentage = 10;
                } else {
                    batteryPercentage = 0;
                }

                position.set(Position.KEY_BATTERY_LEVEL, batteryPercentage);
            }

            if (type.equals("STT") && values.length == 21) {
                batteryBackup = values[19];

                double voltage = Double.parseDouble(batteryBackup);

                double batteryPercentage = 0;

                if (voltage >= 4.06) {
                    batteryPercentage = 100;
                } else if (voltage >= 3.97) {
                    batteryPercentage = 90;
                } else if (voltage >= 3.89) {
                    batteryPercentage = 80;
                } else if (voltage >= 3.83) {
                    batteryPercentage = 70;
                } else if (voltage >= 3.77) {
                    batteryPercentage = 60;
                } else if (voltage >= 3.75) {
                    batteryPercentage = 50;
                } else if (voltage >= 3.73) {
                    batteryPercentage = 40;
                } else if (voltage >= 3.66) {
                    batteryPercentage = 30;
                } else if (voltage >= 3.53) {
                    batteryPercentage = 20;
                } else if (voltage >= 3.49) {
                    batteryPercentage = 10;
                } else {
                    batteryPercentage = 0;
                }

                position.set(Position.KEY_BATTERY_LEVEL, batteryPercentage);
            }


        }

Image Icon BatteryLevel

Turbovix16 hours ago

@AntonioJunior, I think this approach is perfect. I will try it. Thanks for sharing.