Javascript codec compiler ES5 or ES6

Hi everyone,
i’m trying to decode a great radiator thermostat actuator in lorawan.
this one get lot of information has it control a motor. nevertheless i get the JS decoder on the fabricant website.
This one not compile in the codec section of the Aapplication Server .
i try to downgrade the JS code to ES5 with babeljs.io . a web compiler…
It replace let by var and some function … but it still blocking on the Object.assign(…) method.
some one could help me?

let see the JS decoder: I have replaced the function name to meet the AS- codec requirements

let deviceData = {};
function Decode(fport,bytes) {
    const toBool = value => value == '1';
    let decbin = (number) => {
        if (number < 0) {
            number = 0xFFFFFFFF + number + 1
        }
        return parseInt(number, 10).toString(2)
    }

    const handleKeepAliveData = (byteArray) => {
        let tmp = ("0" + byteArray[6].toString(16)).substr(-2);
        let motorRange1 = tmp[1];
        let motorRange2 = ("0" + byteArray[5].toString(16)).substr(-2);
        let motorRange = parseInt(`0x${motorRange1}${motorRange2}`, 16);

        let motorPos2 = ("0" + byteArray[4].toString(16)).substr(-2);
        let motorPos1 = tmp[0];
        let motorPosition = parseInt(`0x${motorPos1}${motorPos2}`, 16);

        let batteryTmp = ("0" + byteArray[7].toString(16)).substr(-2)[0];
        let batteryVoltageCalculated = 2 + parseInt(`0x${batteryTmp}`, 16) * 0.1;

        let byteBin = decbin(byteArray[7]);
        let openWindow = byteBin.substr(4, 1);
        let childLockBin = decbin(byteArray[8]);
        let childLock = childLockBin.charAt(0);
        let highMotorConsumption = byteBin.substr(-2, 1);
        let lowMotorConsumption = byteBin.substr(-3, 1);
        let brokenSensor = byteBin.substr(-4, 1);

        let keepaliveData = {
            reason: byteArray[0],
            targetTemperature: byteArray[1],
            sensorTemperature: (byteArray[2] * 165) / 256 - 40,
            relativeHumidity: (byteArray[3] * 100) / 256,
            motorRange: motorRange,
            motorPosition: motorPosition,
            batteryVoltage: batteryVoltageCalculated,
            openWindow: toBool(openWindow),
            childLock: toBool(childLock),
            highMotorConsumption: toBool(highMotorConsumption),
            lowMotorConsumption: toBool(lowMotorConsumption),
            brokenSensor: toBool(brokenSensor),
            rssi: rssi
        }

        Object.assign(deviceData, { ...deviceData }, { ...keepaliveData })
    }


    if (bytes) {
        let byteArray = bytes.match(/.{1,2}/g).map(byte => { return parseInt(byte, 16) })
        if (byteArray[0] == 1) {
            // its a keeapalive
            handleKeepAliveData(byteArray);
        } else {
            let resultToPass = {};
            let data = bytes.slice(0, -18);
            let commands = data.match(/.{1,2}/g);
            
            // console.log(data)
            
            commands.map((command, i) => {
                switch (command) {
                    case '15':
                        {   
                            let data = { temperatureRangeSettings: { min: parseInt(commands[i + 1], 16), max: parseInt(commands[i + 2], 16) } };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });
                        }
                    break;

                    case '14':
                        {
                            let data = { childLock: toBool(parseInt(commands[i + 1], 16)) };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });
                        }
                    break;
                    
                    case '12':
                        {
                            let data = { keepAliveTime: parseInt(commands[i + 1], 16) };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });
                        }
                    break;
                    
                    case '13':
                        {
                            let enabled = toBool(parseInt(commands[i + 1], 16));
                            let duration = parseInt(commands[i + 2], 16) * 5;
                            let tmp = ("0" + commands[i + 4].toString(16)).substr(-2);
                            let motorPos2 = ("0" + commands[i + 3].toString(16)).substr(-2);
                            let motorPos1 = tmp[0];
                            let motorPosition = parseInt(`0x${motorPos1}${motorPos2}`, 16);
                            let delta = Number(tmp[1]);

                            let data = { openWindowParams: { enabled: enabled, duration: duration, motorPosition: motorPosition, delta: delta } };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });

                        }
                    break;
                    
                    case '18':
                        {
                            let data = { operationalMode: (commands[i + 1]).toString() };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });
                        }
                    break;
                    
                    case '16':
                        {
                            let data = { internalAlgoParams: {period: parseInt(commands[i + 1], 16), pFirstLast: parseInt(commands[i + 2], 16), pNext: parseInt(commands[i + 3], 16)} };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });
                        }
                    break;
                    
                    case '17':
                        {
                            let data = { internalAlgoTdiffParams: {warm: parseInt(commands[i + 1], 16), cold: parseInt(commands[i + 2], 16)} };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });
                        }
                    break;

                    case '1b':
                        {
                            let data = { uplinkType: commands[i + 1] };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });
                        }
                    break;

                    case '19':
                        {
                            let commandResponse = parseInt(commands[i + 1], 16);
                            let periodInMinutes = (commandResponse * 5) / 60;
                            let data = { joinRetryPeriod: periodInMinutes };
                            Object.assign(resultToPass, { ...resultToPass }, { ...data });
                        }
                    break;

                    
                }

            })

            Object.assign(deviceData, { ...deviceData }, { ...resultToPass });

            // get only keepalive from device response
            let keepaliveData = bytes.slice(-18);
            let dataToPass = keepaliveData.match(/.{1,2}/g).map(byte => { return parseInt(byte, 16) });

            handleKeepAliveData(dataToPass);
        }
         
        return deviceData;
    }

}

I can’t speak to your JavaScript syntax (I don’t touch the stuff), but my understanding is that the Otto JS engine used in the application server targets ES5:

https://pkg.go.dev/github.com/robertkrimen/otto

Nice, thanks for your answer.
That have helped me.
and i have now a working decoder. I just inform the fabricant and transmit me a new decoder…

You might find our tool helpful: https://gitlab.com/wobcom/salamander
It integrates over MQTT and might help you out finding errors in the decoder. It also uses the same lib as the Application-Server (otto)

2 Likes