ESP32-PaxCounter/src/TTN/packed_decoder.js

204 lines
5.8 KiB
JavaScript
Raw Normal View History

2018-06-17 22:41:32 +02:00
// Decoder for device payload encoder "PACKED"
2018-06-17 13:24:20 +02:00
// copy&paste to TTN Console -> Applications -> PayloadFormat -> Decoder
function Decoder(bytes, port) {
var decoded = {};
if (port === 1) {
// only counter data, no gps
2018-06-18 13:13:13 +02:00
if (bytes.length === 4) {
2018-06-17 13:24:20 +02:00
return decode(bytes, [uint16, uint16], ['wifi', 'ble']);
}
// combined counter and gps data
2018-06-18 13:13:13 +02:00
if (bytes.length === 17) {
return decode(bytes, [uint16, uint16, latLng, latLng, uint8, hdop, uint16], ['wifi', 'ble', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']);
2018-06-17 13:24:20 +02:00
}
}
if (port === 2) {
// device status data
2018-09-17 21:57:01 +02:00
return decode(bytes, [uint16, uptime, uint8, uint32, uint8, uint8], ['voltage', 'uptime', 'cputemp', 'memory', 'reset0', 'reset1']);
2018-07-15 19:08:18 +02:00
}
if (port === 3) {
// device config data
2018-09-17 21:57:01 +02:00
return decode(bytes, [uint8, uint8, uint16, uint8, uint8, uint8, uint8, bitmap, version], ['lorasf', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags', 'version']);
2018-06-17 13:24:20 +02:00
}
2018-07-15 19:08:18 +02:00
if (port === 4) {
// gps data
return decode(bytes, [latLng, latLng, uint8, hdop, uint16], ['latitude', 'longitude', 'sats', 'hdop', 'altitude']);
}
if (port === 5) {
// button pressed
return decode(bytes, [uint8], ['button']);
}
if (port === 6) {
// beacon proximity alarm
return decode(bytes, [uint8, uint8], ['rssi', 'beacon']);
}
if (port === 7) {
// BME680 sensor data
return decode(bytes, [temperature, uint16, humidity, uint16], ['temperature', 'pressure', 'humidity', 'air']);
}
2018-06-17 13:24:20 +02:00
}
// ----- contents of /src/decoder.js --------------------------------------------
// https://github.com/thesolarnomad/lora-serialization/blob/master/src/decoder.js
var bytesToInt = function (bytes) {
var i = 0;
for (var x = 0; x < bytes.length; x++) {
2018-06-23 13:42:01 +02:00
i |= (bytes[x] << (x * 8));
2018-06-17 13:24:20 +02:00
}
return i;
};
2018-09-17 21:57:01 +02:00
var version = function (bytes) {
if (bytes.length !== version.BYTES) {
throw new Error('version must have exactly 10 bytes');
}
return String.fromCharCode.apply(null, bytes).split('\u0000')[0];
2018-09-17 22:03:03 +02:00
};
2018-09-17 21:57:01 +02:00
version.BYTES = 10;
2018-06-17 13:24:20 +02:00
var uint8 = function (bytes) {
if (bytes.length !== uint8.BYTES) {
throw new Error('uint8 must have exactly 1 byte');
2018-06-17 13:24:20 +02:00
}
return bytesToInt(bytes);
};
uint8.BYTES = 1;
var uint16 = function (bytes) {
if (bytes.length !== uint16.BYTES) {
throw new Error('uint16 must have exactly 2 bytes');
2018-06-17 13:24:20 +02:00
}
return bytesToInt(bytes);
};
uint16.BYTES = 2;
var uint32 = function (bytes) {
if (bytes.length !== uint32.BYTES) {
throw new Error('uint32 must have exactly 4 bytes');
}
return bytesToInt(bytes);
};
uint32.BYTES = 4;
2018-06-17 13:24:20 +02:00
var latLng = function (bytes) {
if (bytes.length !== latLng.BYTES) {
2018-06-18 13:13:13 +02:00
throw new Error('Lat/Long must have exactly 4 bytes');
2018-06-17 13:24:20 +02:00
}
2018-06-18 13:13:13 +02:00
return bytesToInt(bytes) / 1e6;
};
latLng.BYTES = 4;
2018-06-17 13:24:20 +02:00
2018-08-05 17:49:53 +02:00
var uptime = function (bytes) {
if (bytes.length !== uptime.BYTES) {
throw new Error('Uptime must have exactly 8 bytes');
}
return bytesToInt(bytes);
};
uptime.BYTES = 8;
2018-06-18 13:13:13 +02:00
var hdop = function (bytes) {
if (bytes.length !== hdop.BYTES) {
throw new Error('hdop must have exactly 2 bytes');
}
return bytesToInt(bytes) / 100;
2018-06-17 13:24:20 +02:00
};
2018-06-18 13:13:13 +02:00
hdop.BYTES = 2;
2018-06-17 13:24:20 +02:00
var temperature = function (bytes) {
if (bytes.length !== temperature.BYTES) {
throw new Error('Temperature must have exactly 2 bytes');
}
var isNegative = bytes[0] & 0x80;
var b = ('00000000' + Number(bytes[0]).toString(2)).slice(-8)
+ ('00000000' + Number(bytes[1]).toString(2)).slice(-8);
if (isNegative) {
var arr = b.split('').map(function (x) { return !Number(x); });
for (var i = arr.length - 1; i > 0; i--) {
arr[i] = !arr[i];
if (arr[i]) {
break;
}
}
b = arr.map(Number).join('');
}
var t = parseInt(b, 2);
if (isNegative) {
t = -t;
}
return +(t / 100).toFixed(1);
2018-06-17 13:24:20 +02:00
};
temperature.BYTES = 2;
var humidity = function (bytes) {
if (bytes.length !== humidity.BYTES) {
throw new Error('Humidity must have exactly 2 bytes');
}
var h = bytesToInt(bytes);
return +(h / 100).toFixed(1);
2018-06-17 13:24:20 +02:00
};
humidity.BYTES = 2;
var bitmap = function (byte) {
if (byte.length !== bitmap.BYTES) {
throw new Error('Bitmap must have exactly 1 byte');
}
var i = bytesToInt(byte);
var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean);
2018-06-18 13:13:13 +02:00
return ['adr', 'screensaver', 'screen', 'countermode', 'blescan', 'antenna', 'filter', 'gpsmode']
2018-06-17 13:24:20 +02:00
.reduce(function (obj, pos, index) {
2018-06-23 13:42:01 +02:00
obj[pos] = +bm[index];
2018-06-17 13:24:20 +02:00
return obj;
}, {});
};
bitmap.BYTES = 1;
var decode = function (bytes, mask, names) {
var maskLength = mask.reduce(function (prev, cur) {
return prev + cur.BYTES;
}, 0);
if (bytes.length < maskLength) {
throw new Error('Mask length is ' + maskLength + ' whereas input is ' + bytes.length);
}
names = names || [];
var offset = 0;
return mask
.map(function (decodeFn) {
var current = bytes.slice(offset, offset += decodeFn.BYTES);
return decodeFn(current);
})
.reduce(function (prev, cur, idx) {
prev[names[idx] || idx] = cur;
return prev;
}, {});
};
if (typeof module === 'object' && typeof module.exports !== 'undefined') {
module.exports = {
uint8: uint8,
uint16: uint16,
2018-08-05 17:49:53 +02:00
uint32: uint32,
uptime: uptime,
2018-06-17 13:24:20 +02:00
temperature: temperature,
humidity: humidity,
latLng: latLng,
2018-06-18 13:13:13 +02:00
hdop: hdop,
2018-06-17 13:24:20 +02:00
bitmap: bitmap,
2018-09-17 21:57:01 +02:00
version: version,
2018-06-17 13:24:20 +02:00
decode: decode
};
}