2021-04-10 15:32:56 +00:00
<!doctype html>
< html >
< head >
< title > AttNode v3 Payload Decoder Generator< / title >
< meta name = "description" content = "AttNode v3 Payload Decoder Generator" >
< meta name = "author" content = "Stefan Brand" >
< style >
body {
background-color: #e9eaec;
font-family: Roboto, sans-serif;
font-size: 1em;
padding: 24px;
}
div {
background: #f8f8f8;
border: 1px solid #ccc;
padding: 1em 2em;
margin-bottom: 40px;
}
pre {
border: 1px solid black;
font-family: monospace, monospace;
font-size: 1em;
padding: 4px;
}
< / style >
< / head >
< body >
< div class = "title" >
< h1 > AttNode v3 Payload Decoder Generator< / h1 >
< / div >
< div class = "header" >
< p > Please choose the Sensors that you have enabled in the Firmware. The Payload Decoder code below will change accordingly.< / p >
< p > Notes:< / p >
< ul >
< li > You can set arbitary combinations of Sensors here. Not all of them are useable / technically possible< / li >
< li > Enable only the sensors in the decoder, which are enabled in the firmware for a particular device. The Decoder does not detect which sensors are present in the LoRa paket. You can set a payload decoder per device in TTN v3 to have nodes with different sensors in one application< / li >
< li > The Payload Decoder shown here is for TTN v3 / The Things Stack v3. If you use other LoRa Stacks you may have to change the < b > decodeUplink< / b > function and its return value.< / li >
< / ul >
< / div >
< div class = "chooser" >
< h3 > Sensors:< / h3 >
< form id = "chooserForm" >
< label >
< input type = "checkbox" value = "mhz19c" onchange = "updateDecoder();" >
MH-Z19C
< / label >
< label >
< input type = "checkbox" value = "sg112a" onchange = "updateDecoder();" >
SG112A
< / label >
< label >
< input type = "checkbox" value = "sensairs8" onchange = "updateDecoder();" >
Sensair S8
< / label >
< label >
< input type = "checkbox" value = "scd30" onchange = "updateDecoder();" >
SCD30
< / label >
< label >
< input type = "checkbox" value = "bme280" onchange = "updateDecoder();" >
BME280
< / label >
< label >
< input type = "checkbox" value = "sht21" onchange = "updateDecoder();" >
SHT21
< / label >
2021-07-06 16:02:36 +00:00
< label >
< input type = "checkbox" value = "sps30" onchange = "updateDecoder();" >
SPS30
< / label >
2021-05-02 15:11:48 +00:00
< label >
< input type = "checkbox" value = "hm330x" onchange = "updateDecoder();" >
HM330x
< / label >
2021-06-07 16:25:04 +00:00
< label >
< input type = "checkbox" value = "brightness" onchange = "updateDecoder();" >
Brightness
< / label >
2021-04-10 15:32:56 +00:00
< label >
< input type = "checkbox" value = "ds18b20" onchange = "updateDecoder();" >
DS18B20
< / label >
< / form >
< h3 > Payload Decoder:< / h3 >
< pre id = "pd" >
< / pre >
< / div >
2021-04-10 16:08:46 +00:00
< a href = "https://www.attno.de/" > Back to attno.de Main Page< / a >
2021-04-10 15:32:56 +00:00
< script >
var sensors = {
"mhz19c": [
{ "name": "co2ppm", "type": "UInt16", "factor": 1, "multi": false },
],
"sg112a": [
{ "name": "co2ppm", "type": "UInt16", "factor": 1, "multi": false },
],
"sensairs8": [
{ "name": "co2ppm", "type": "UInt16", "factor": 1, "multi": false },
],
"scd30": [
{ "name": "co2ppm", "type": "UInt16", "factor": 1, "multi": false },
{ "name": "temperature", "type": "Int16", "factor": 100, "multi": false },
{ "name": "humidity", "type": "UInt16", "factor": 100, "multi": false },
],
"bme280": [
{ "name": "temperature", "type": "Int32", "factor": 100, "multi": false },
{ "name": "humidity", "type": "Int32", "factor": 100, "multi": false },
{ "name": "pressure", "type": "Int32", "factor": 100, "multi": false },
],
"sht21": [
{ "name": "temperature", "type": "Int32", "factor": 100, "multi": false },
{ "name": "humidity", "type": "Int32", "factor": 100, "multi": false },
],
2021-07-06 16:02:36 +00:00
"sps30": [
{ "name": "pm1", "type": "UInt16", "factor": 1, "multi": false },
{ "name": "pm2_5", "type": "UInt16", "factor": 1, "multi": false },
{ "name": "pm4", "type": "UInt16", "factor": 1, "multi": false },
{ "name": "pm10", "type": "UInt16", "factor": 1, "multi": false },
{ "name": "typPMsize", "type": "UInt16", "factor": 1, "multi": false },
],
2021-05-02 15:11:48 +00:00
"hm330x": [
{ "name": "pm1", "type": "UInt16", "factor": 1, "multi": false },
{ "name": "pm2_5", "type": "UInt16", "factor": 1, "multi": false },
{ "name": "pm10", "type": "UInt16", "factor": 1, "multi": false },
],
2021-06-07 16:25:04 +00:00
"brightness": [
{ "name": "brightness", "type": "UInt16", "factor": 1, "multi": false },
],
2021-04-10 15:32:56 +00:00
"ds18b20": [
{ "name": "t", "type": "Int16", "factor": 100, "multi": true },
]
};
var typelen = {"Int32": "4", "Int16": "2", "UInt16": "2"};
function updateDecoder() {
var output = document.getElementById("pd");
output.innerHTML = "function bytesToInt16(bytes, start) {\n";
output.innerHTML += " var out = ((bytes[start]) | (bytes[start+1] < < 8 ) ) ; \ n " ;
output.innerHTML += " var sign = bytes[start+1] & (1 < < 7 ) ; \ n " ;
output.innerHTML += " if (sign)\n";
output.innerHTML += " out = 0xFFFF0000 | out;\n";
output.innerHTML += " return out;\n";
output.innerHTML += "}\n\n";
output.innerHTML += "function bytesToUInt16(bytes, start) {\n";
output.innerHTML += " return ((bytes[start]) | (bytes[start+1] < < 8 ) ) ; \ n " ;
output.innerHTML += "}\n\n";
output.innerHTML += "function bytesToInt32(bytes, start) {\n";
output.innerHTML += " return ((bytes[start]) | (bytes[start+1] < < 8 ) | ( bytes [ start + 2 ] < < 16 ) | ( bytes [ start + 3 ] < < 24 ) ) ; \ n " ;
output.innerHTML += "}\n\n";
output.innerHTML += "function decodeUplink(input) {\n";
output.innerHTML += " var decoded = {};\n";
output.innerHTML += " /* Battery Voltage, always enabled */\n";
output.innerHTML += " decoded.v = (input.bytes[0] * 20) / 1000.0;\n\n";
output.innerHTML += " var i = 1;\n";
var elements = document.getElementById("chooserForm").elements;
for (var i = 0, element; element = elements[i++];) {
if (element.type === "checkbox")
if (element.checked) {
sensors[element.value].forEach(sensor => {
if (sensor.multi) {
output.innerHTML += " var n = 1;\n";
output.innerHTML += " for (var j = i; j < input.bytes.length-1 ; j + = 2 ) { \ n " ;
if (sensor.factor > 1) {
output.innerHTML += " decoded['" + sensor.name + "' + n] = bytesTo" + sensor.type + " (input.bytes, j);\n";
} else {
output.innerHTML += " decoded['" + sensor.name + "' + n] = bytesTo" + sensor.type + " (input.bytes, j)/" + sensor.factor + ";\n";
}
output.innerHTML += " n++;\n";
output.innerHTML += " }\n";
} else {
if (sensor.factor > 1) {
output.innerHTML += " decoded." + sensor.name + " = bytesTo" + sensor.type + "(input.bytes, i)/" + sensor.factor + ";\n";
} else {
output.innerHTML += " decoded." + sensor.name + " = bytesTo" + sensor.type + "(input.bytes, i);\n";
}
output.innerHTML += " i += " + typelen[sensor.type] + ";\n";
}
});
}
}
output.innerHTML += "\n\n return {\n";
output.innerHTML += " data: decoded,\n";
output.innerHTML += " warnings: [],\n";
output.innerHTML += " errors: []\n";
output.innerHTML += " };\n";
output.innerHTML += "}\n";
}
< / script >
< / body >
< / html >