Rak10701 L Payload for Datacake over Actility

Did anybody integrate the lora tester to datacake with acitility payload?

{"DevEUI_uplink":{"Time":"2024-09-08T16:29:48.272+00:00","DevEUI":"AC1F09FFFE10518F","FPort":"1","FCntUp":"103","LostUplinksAS":"0","ADRbit":"1","MType":"4","FCntDn":"100","payload_hex":"2222428a279e0533080b","mic_hex":"00f00af0","Lrcid":"00000201","LrrRSSI":"-91.000000","LrrSNR":"9.750000","LrrESP":"-91.437256","SpFact":"7","SubBand":"G2","Channel":"LC8","Lrrid":"10003CC9","Late":"0","LrrLAT":"48.305290","LrrLON":"14.284930","Lrrs":{"Lrr":[{"Lrrid":"10003CC9","Chain":"0","LrrRSSI":"-91.000000","LrrSNR":"9.750000","LrrESP":"-91.437256"},{"Lrrid":"10003CD1","Chain":"0","LrrRSSI":"-95.000000","LrrSNR":"9.500000","LrrESP":"-95.461838"},{"Lrrid":"10003CB7","Chain":"0","LrrRSSI":"-96.000000","LrrSNR":"9.250000","LrrESP":"-96.487717"},{"Lrrid":"10003CC0","Chain":"0","LrrRSSI":"-98.000000","LrrSNR":"8.750000","LrrESP":"-98.543648"},{"Lrrid":"1000493A","Chain":"0","LrrRSSI":"-101.000000","LrrSNR":"3.000000","LrrESP":"-102.764351"},{"Lrrid":"10006614","Chain":"0","LrrRSSI":"-107.000000","LrrSNR":"1.250000","LrrESP":"-109.430115"}]},"DevLrrCnt":"6","CustomerID":"100053662","CustomerData":{"loc":null,"alr":{"pro":"RAKW/WI631","ver":"1"},"tags":[],"doms":[],"name":"Lora-Tester"},"ModelCfg":"*:tbx","DriverCfg":{"mod":{"pId":"rakwirel","mId":"rak4631","ver":"1"}},"DevAddr":"FC016AA8","TxPower":"8.000000","NbTrans":"1","Frequency":"867.90","DynamicClass":"A","downlinkUrl":",[object Object]

my current state - not 100% working

function Decoder(bytes, fPort) {
    var decoded = [];

    // Convert hex string to byte array inside the function
    function hexToBytes(hex) {
        var bytes = [];
        for (var i = 0; i < hex.length; i += 2) {
            bytes.push(parseInt(hex.substr(i, 2), 16));
        }
        return bytes;
    }

    // Get the payload_hex from normalizedPayload
    var payloadHex = normalizedPayload.payload_hex;
    bytes = hexToBytes(payloadHex); // Convert hex string to bytes array

    // Process only for fPort 1
    if (fPort === 1) {
        var lonSign = (bytes[0] >> 7) & 0x01 ? -1 : 1;
        var latSign = (bytes[0] >> 6) & 0x01 ? -1 : 1;

        var encLat = ((bytes[0] & 0x3f) << 17) +
            (bytes[1] << 9) +
            (bytes[2] << 1) +
            (bytes[3] >> 7);

        var encLon = ((bytes[3] & 0x7f) << 16) +
            (bytes[4] << 8) +
            bytes[5];

        var hdop = bytes[8] / 10;
        var sats = bytes[9];

        var maxHdop = 2;
        var minSats = 5;

        // Calculate the latitude, longitude, and altitude
        var latitude = latSign * (encLat * 108 + 53) / 10000000;
        var longitude = lonSign * (encLon * 215 + 107) / 10000000;
        var altitude = ((bytes[6] << 8) + bytes[7]) - 1000;
        var accuracy = (hdop * 5 + 5) / 10;

        // Add decoded values to the array
        decoded.push({ field: "LATITUDE", value: latitude });
        decoded.push({ field: "longitude", value: longitude });
        decoded.push({ field: "altitude", value: altitude });
        decoded.push({ field: "accuracy", value: accuracy });
        decoded.push({ field: "hdop", value: hdop });
        decoded.push({ field: "sats", value: sats });

        // Check if position quality is acceptable
        if ((hdop >= maxHdop) || (sats < minSats)) {
            decoded.push({
                field: "error",
                value: "Need more GPS precision (hdop <" + maxHdop + " & sats >= " + minSats + "). Current hdop: " + hdop + " & sats: " + sats
            });
        }

        // Process gateways if necessary
        var num_gw = normalizedPayload.Lrrs.Lrr.length;
        decoded.push({ field: "num_gw", value: num_gw });

        // Set RSSI and SNR values for gateways
        var rssiValues = normalizedPayload.Lrrs.Lrr.map(function (lrr) {
            return parseFloat(lrr.LrrRSSI);
        });
        var snrValues = normalizedPayload.Lrrs.Lrr.map(function (lrr) {
            return parseFloat(lrr.LrrSNR);
        });

        var minRSSI = Math.min.apply(null, rssiValues);
        var maxRSSI = Math.max.apply(null, rssiValues);
        var minSNR = Math.min.apply(null, snrValues);
        var maxSNR = Math.max.apply(null, snrValues);

        decoded.push({ field: "minRSSI", value: minRSSI });
        decoded.push({ field: "maxRSSI", value: maxRSSI });
        decoded.push({ field: "minSNR", value: minSNR });
        decoded.push({ field: "maxSNR", value: maxSNR });

        // Calculate the distance between gateways and decoded location (if required)
        var distanceToGW = [];
        for (var idx = 0; idx < num_gw; idx++) {
            var gw_lat = parseFloat(normalizedPayload.Lrrs.Lrr[idx].LrrLAT);
            var gw_lon = parseFloat(normalizedPayload.Lrrs.Lrr[idx].LrrLON);
            var dist = distance(gw_lat, gw_lon, latitude, longitude);
            distanceToGW.push(dist);
        }

        var minDistance = Math.min.apply(null, distanceToGW) * 1000; // in meters
        var maxDistance = Math.max.apply(null, distanceToGW) * 1000; // in meters

        decoded.push({ field: "minDistance", value: minDistance });
        decoded.push({ field: "maxDistance", value: maxDistance });
    }

    return decoded; // Return the single array without additional wrapping
}

// Distance calculation function
function distance(lat1, lon1, lat2, lon2) {
    if ((lat1 == lat2) && (lon1 == lon2)) {
        return 0;
    } else {
        var radlat1 = Math.PI * lat1 / 180;
        var radlat2 = Math.PI * lat2 / 180;
        var theta = lon1 - lon2;
        var radtheta = Math.PI * theta / 180;
        var dist = Math.sin(radlat1) * Math.sin(radlat2) +
                   Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        if (dist > 1) {
            dist = 1;
        }
        dist = Math.acos(dist);
        dist = dist * 180 / Math.PI;
        dist = dist * 60 * 1.1515;
        dist = dist * 1.609344; // Convert to kilometers
        return dist;
    }
}

// Example usage with normalizedPayload
var normalizedPayload = {
    payload_hex: "2222448a279a054c0e07",
    Lrrs: {
        Lrr: [
            {
                Lrrid: "10003CC9",
                LrrRSSI: "-92.000000",
                LrrSNR: "-4.000000",
                LrrLAT: "48.305290",
                LrrLON: "14.284930"
            },
            {
                Lrrid: "1000493A",
                LrrRSSI: "-104.000000",
                LrrSNR: "-7.500000",
                LrrLAT: "48.305100",
                LrrLON: "14.284800"
            }
        ]
    }
};

// Now you can use this code and call Decoder
var fPort = 1;
var decodedData = Decoder(null, fPort);
console.log(decodedData);

Would be cool if somebody can share there experience