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