Hi All,
I've made a small test flow and fiddling with decoding my MQTT payload and it still won't work
My goal is to get a output like this:
{
"protocol_version": 2,
"device_id": 3547,
"battery_voltage": {
"displayName": "Battery voltage",
"value": 2.685,
"unit": "V"
},
"air_temperature": {
"displayName": "Air temperature",
"value": 22.74357213702602,
"unit": "°C"
},
"air_humidity": {
"displayName": "Air humidity",
"value": 36.939040207522694,
"unit": "%"...........etc...etc...
This is my test flow, Base64 payload is converted to a buffer:
[{"id":"d78ead4c.b75c2","type":"inject","z":"66cdaed7.72f43","name":"","topic":"","payload":"Ag3bAH8Kf2F5ZFHDSgAtABGBuAAAlcwAAAAw","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":450,"y":380,"wires":[["ec2ad8ba.e6dc88"]]},{"id":"ec2ad8ba.e6dc88","type":"base64","z":"66cdaed7.72f43","name":"","action":"","property":"payload","x":580,"y":380,"wires":[["3d41820e.8e929e","9e58a89e.c8dc78"]]},{"id":"3d41820e.8e929e","type":"function","z":"66cdaed7.72f43","name":"decode","func":"var decentlab_decoder = {\n PROTOCOL_VERSION: 2,\n SENSORS: [\n {length: 1,\n values: [{name: 'battery_voltage',\n displayName: 'Battery voltage',\n convert: function (x) { return x[0] / 1000; },\n unit: 'V'}]},\n {length: 2,\n values: [{name: 'air_temperature',\n displayName: 'Air temperature',\n convert: function (x) { return 175 * x[0] / 65535 - 45; },\n unit: '°C'},\n {name: 'air_humidity',\n displayName: 'Air humidity',\n convert: function (x) { return 100 * x[1] / 65535; },\n unit: '%'}]},\n {length: 1,\n values: [{name: 'barometric_pressure',\n displayName: 'Barometric pressure',\n convert: function (x) { return x[0] * 2; },\n unit: 'Pa'}]},\n {length: 2,\n values: [{name: 'ambient_light_visible_infrared',\n displayName: 'Ambient light (visible + infrared)',\n convert: function (x) { return x[0]; }},\n {name: 'ambient_light_infrared',\n displayName: 'Ambient light (infrared)',\n convert: function (x) { return x[1]; }},\n {name: 'illuminance',\n displayName: 'Illuminance',\n convert: function (x) { return Math.max(Math.max(1.0 * x[0] - 1.64 * x[1], 0.59 * x[0] - 0.86 * x[1]), 0) * 1.5504; },\n unit: 'lx'}]},\n {length: 3,\n values: [{name: 'co2_concentration',\n displayName: 'CO2 concentration',\n convert: function (x) { return x[0] - 32768; },\n unit: 'ppm'},\n {name: 'co2_sensor_status',\n displayName: 'CO2 sensor status',\n convert: function (x) { return x[1]; }},\n {name: 'raw_ir_reading',\n displayName: 'Raw IR reading',\n convert: function (x) { return x[2]; }}]},\n {length: 1,\n values: [{name: 'activity_counter',\n displayName: 'Activity counter',\n convert: function (x) { return x[0]; }}]},\n {length: 1,\n values: [{name: 'total_voc',\n displayName: 'Total VOC',\n convert: function (x) { return x[0]; },\n unit: 'ppb'}]}\n ],\n\n read_int: function (bytes, pos) {\n return (bytes[pos] << 8) + bytes[pos + 1];\n },\n\n decode: function (msg) {\n var bytes = msg;\n var i, j;\n if (typeof msg === 'string') {\n bytes = [];\n for (i = 0; i < msg.length; i += 2) {\n bytes.push(parseInt(msg.substring(i, i + 2), 16));\n }\n }\n\n var version = bytes[0];\n if (version != this.PROTOCOL_VERSION) {\n return {error: \"protocol version \" + version + \" doesn't match v2\"};\n }\n\n var deviceId = this.read_int(bytes, 1);\n var flags = this.read_int(bytes, 3);\n var result = {'protocol_version': version, 'device_id': deviceId};\n // decode payload\n var pos = 5;\n for (i = 0; i < this.SENSORS.length; i++, flags >>= 1) {\n if ((flags & 1) !== 1)\n continue;\n\n var sensor = this.SENSORS[i];\n var x = [];\n // convert data to 16-bit integer array\n for (j = 0; j < sensor.length; j++) {\n x.push(this.read_int(bytes, pos));\n pos += 2;\n }\n\n // decode sensor values\n for (j = 0; j < sensor.values.length; j++) {\n var value = sensor.values[j];\n if ('convert' in value) {\n result[value.name] = {displayName: value.displayName,\n value: value.convert.bind(this)(x)};\n if ('unit' in value)\n result[value.name]['unit'] = value.unit;\n }\n }\n }\n return result;\n }\n};\n","outputs":1,"noerr":0,"x":760,"y":380,"wires":[["72cafe26.799e1"]]},{"id":"9e58a89e.c8dc78","type":"debug","z":"66cdaed7.72f43","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":750,"y":300,"wires":[]},{"id":"72cafe26.799e1","type":"debug","z":"66cdaed7.72f43","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":950,"y":380,"wires":[]}]
This is the payload from my MQTT node, which is injected into the test flow
Here is the function from my device:
var decentlab_decoder = {
PROTOCOL_VERSION: 2,
SENSORS: [
{length: 1,
values: [{name: 'battery_voltage',
displayName: 'Battery voltage',
convert: function (x) { return x[0] / 1000; },
unit: 'V'}]},
{length: 2,
values: [{name: 'air_temperature',
displayName: 'Air temperature',
convert: function (x) { return 175 * x[0] / 65535 - 45; },
unit: '°C'},
{name: 'air_humidity',
displayName: 'Air humidity',
convert: function (x) { return 100 * x[1] / 65535; },
unit: '%'}]},
{length: 1,
values: [{name: 'barometric_pressure',
displayName: 'Barometric pressure',
convert: function (x) { return x[0] * 2; },
unit: 'Pa'}]},
{length: 2,
values: [{name: 'ambient_light_visible_infrared',
displayName: 'Ambient light (visible + infrared)',
convert: function (x) { return x[0]; }},
{name: 'ambient_light_infrared',
displayName: 'Ambient light (infrared)',
convert: function (x) { return x[1]; }},
{name: 'illuminance',
displayName: 'Illuminance',
convert: function (x) { return Math.max(Math.max(1.0 * x[0] - 1.64 * x[1], 0.59 * x[0] - 0.86 * x[1]), 0) * 1.5504; },
unit: 'lx'}]},
{length: 3,
values: [{name: 'co2_concentration',
displayName: 'CO2 concentration',
convert: function (x) { return x[0] - 32768; },
unit: 'ppm'},
{name: 'co2_sensor_status',
displayName: 'CO2 sensor status',
convert: function (x) { return x[1]; }},
{name: 'raw_ir_reading',
displayName: 'Raw IR reading',
convert: function (x) { return x[2]; }}]},
{length: 1,
values: [{name: 'activity_counter',
displayName: 'Activity counter',
convert: function (x) { return x[0]; }}]},
{length: 1,
values: [{name: 'total_voc',
displayName: 'Total VOC',
convert: function (x) { return x[0]; },
unit: 'ppb'}]}
],
read_int: function (bytes, pos) {
return (bytes[pos] << 8) + bytes[pos + 1];
},
decode: function (msg) {
var bytes = msg;
var i, j;
if (typeof msg === 'string') {
bytes = [];
for (i = 0; i < msg.length; i += 2) {
bytes.push(parseInt(msg.substring(i, i + 2), 16));
}
}
var version = bytes[0];
if (version != this.PROTOCOL_VERSION) {
return {error: "protocol version " + version + " doesn't match v2"};
}
var deviceId = this.read_int(bytes, 1);
var flags = this.read_int(bytes, 3);
var result = {'protocol_version': version, 'device_id': deviceId};
// decode payload
var pos = 5;
for (i = 0; i < this.SENSORS.length; i++, flags >>= 1) {
if ((flags & 1) !== 1)
continue;
var sensor = this.SENSORS[i];
var x = [];
// convert data to 16-bit integer array
for (j = 0; j < sensor.length; j++) {
x.push(this.read_int(bytes, pos));
pos += 2;
}
// decode sensor values
for (j = 0; j < sensor.values.length; j++) {
var value = sensor.values[j];
if ('convert' in value) {
result[value.name] = {displayName: value.displayName,
value: value.convert.bind(this)(x)};
if ('unit' in value)
result[value.name]['unit'] = value.unit;
}
}
}
return result;
}
};
It would be nice if I could get some help with this.