Dear Sensebox members,
i want to bring up this post again as we still struggle with our fine dust sensor.
Uptil now, we succeeded in using a lora connection via TTN to display our temperature and humidity values. But the fine dust values are not in the correct format as seen here (https://opensensemap.org/explore/5dd3c45c4ec04e001ae4aef7):
No way the actual dust level is 4096.1 µg/m³ !!!
It is mentioned in the docs that a JSON profile should be used to format the PM values in the right way. As a result, in TTN one should create a decoder to format the payload. I have used this payload format in the console of TTN, but to no avail:
function Decoder(bytes, port) {
// bytes is of type Buffer.
'use strict';
var TEMPSENSOR_ID="5dce6d08306947001ae15f4e",
HUMISENSOR_ID="5dce6d08306947001ae15f4d",
PM10_ID="5dd27c104ec04e001a8596eb",
PM25_ID="5dd27c104ec04e001a8596ea";
var lat = 0,lng = 0;
var bytesToInt = function (bytes) {
var i = 0;
for (var x = 0; x < bytes.length; x++) {
i |= +(bytes[x] << (x * 8));
}
return i;
};
var latLng = function(bytes) {
if (bytes.length !== latLng.BYTES) {
throw new Error('Lat/Long must have exactly 8 bytes');
}
lat = (bytesToInt(bytes.slice(0, latLng.BYTES / 2))/1e2)/10000;
lng = (bytesToInt(bytes.slice(latLng.BYTES / 2, latLng.BYTES))/1e2)/10000;
};
latLng.BYTES = 8;
var uint8 = function (bytes) {
if (bytes.length !== uint8.BYTES) {
throw new Error('int must have exactly 1 byte');
}
return bytesToInt(bytes);
};
uint8.BYTES = 1;
var uint16 = function (bytes) {
if (bytes.length !== uint16.BYTES) {
throw new Error('int must have exactly 2 bytes');
}
return bytesToInt(bytes);
};
uint16.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 / 1e2;
};
humidity.BYTES = 2;
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;
}, {});
};
var bytesToSenseBoxJson = function (bytes) {
var json;
try {
json = decode(bytes,
[
uint16,
humidity,
uint16,
uint16,
latLng,
uint16,
uint16,
uint16,
uint16,
uint16,
uint16
],
[
TEMPSENSOR_ID,
HUMISENSOR_ID,
PM10_ID,
PM25_ID,
"location",
"year",
"month",
"day",
"hour",
"minute",
"second",
]);
if(json['month'] === 0){
json['month'] = 1;
}
if(json['day'] === 0){
json['day'] = 1;
}
//temp
json[TEMPSENSOR_ID] = [String(parseFloat(((json[TEMPSENSOR_ID] / 771) - 18).toFixed(1))),String(json["year"])+"-"+String(("0" + json["month"]).slice(-2))+"-"+String(("0" + json["day"]).slice(-2))+"T"+String(("0" + json["hour"]).slice(-2))+":"+String(("0" + json["minute"]).slice(-2))+":"+String(("0" + json["second"]).slice(-2))+"Z",[lng,lat]];
//hum
json[HUMISENSOR_ID] = [String(parseFloat(json[HUMISENSOR_ID].toFixed(1))),String(json["year"])+"-"+String(("0" + json["month"]).slice(-2))+"-"+String(("0" + json["day"]).slice(-2))+"T"+String(("0" + json["hour"]).slice(-2))+":"+String(("0" + json["minute"]).slice(-2))+":"+String(("0" + json["second"]).slice(-2))+"Z",[lng,lat]];
// pm10
json[PM10_ID] = [String(parseFloat((json[PM10_ID] / 10).toFixed(1))),String(json["year"])+"-"+String(("0" + json["month"]).slice(-2))+"-"+String(("0" + json["day"]).slice(-2))+"T"+String(("0" + json["hour"]).slice(-2))+":"+String(("0" + json["minute"]).slice(-2))+":"+String(("0" + json["second"]).slice(-2))+"Z",[lng,lat]];
// pm25
json[PM25_ID] = [String(parseFloat((json[PM25_ID] / 10).toFixed(1))),String(json["year"])+"-"+String(("0" + json["month"]).slice(-2))+"-"+String(("0" + json["day"]).slice(-2))+"T"+String(("0" + json["hour"]).slice(-2))+":"+String(("0" + json["minute"]).slice(-2))+":"+String(("0" + json["second"]).slice(-2))+"Z",[lng,lat]];
delete json.year;
delete json.month;
delete json.day;
delete json.hour;
delete json.minute;
delete json.second;
} catch (e) {
json = { payload: bytes };
}
return json;
};
return bytesToSenseBoxJson(bytes);
}
Any one has a clue on where the problem is?