Everything works fine but I’d like to simplifiy the payload a lot as follows:
‘Temperature’: 21.8
‘Humidity’: 62
…
without the nested structure:
let result = {
'err': 0, 'payload': bytes, 'valid': true, messages: []
}
I find the code somewhat difficult to read, could maybe someone help me edit the payload decoder? Here is a sample payload:
04640101010B000A05A00100DA3E000000240000000201000000000025E8
Hi! I’ve recently made a PR that simplifies a little the decoded payload, but the structure that Seeed is using in these devices is still annoying.
Ideally, we will just add a normalizeUplink function to achieve this (Uplink | The Things Stack for LoRaWAN), think of it as an extra/optional step that takes the output of the decodeUplink function and beautifies/standardizes it. But the normalized payload format is still young and does not yet support the UV Index and Rain Gauge fields provided by this device. Anyway, if you don’t want to touch the original decodeUplink function and don’t mind losing the unsupported fields, adding this function will be a solution:
// Be aware of corner cases
function normalizeUplink(input) {
var data = { air: {}, wind: {} };
for (var i = 0; i < input.data.messages.length; i++) {
var msg = input.data.messages[i];
switch (msg.measurementId) {
case "4097":
data.air.temperature = msg.measurementValue;
break;
case "4098":
data.air.relativeHumidity = msg.measurementValue;
break;
case "4099":
data.air.lightIntensity = msg.measurementValue;
break;
case "4101":
data.air.pressure = msg.measurementValue / 100; // convert to hPa
break;
case "4104":
data.wind.direction = msg.measurementValue;
break;
case "4105":
data.wind.speed = msg.measurementValue;
break;
default:
break;
}
}
return {data};
}
Sadly, this won’t work for you just yet, while these fields are supported in the schema, air.lightIntensity hasn’t yet been added to the validation code of The Things Stack. I have a patched version running locally and this works fine, I will try to prepare a PR as soon as possible so that everyone can use these fields in the normalized format. For now, you can just remove the lightIntensity case from the switch statement.
I will let you know with updates on using this approach.
I don’t like the hacky approach of patching the original decodeUplink function, so I’m willing to take the long route here of making a useful and easy to use format for all.
Bit scary that TTI are prepared to take PR’s from people who don’t work for the vendor - it raises all sorts of complications - if a new version of the device comes out and is registered along with a new PF, what then? Is the PF actually open-source that anyone can amend in an important publishing platform like TTS?
I fully appreciate the intent to clean up the mess that too many vendors produce after they’ve hacked an initial payload structure together that is the work of insanity. But this may well have some serious unintended consequences - and potential legal consequences should be explored.
I mencioned Seeed’s employee that submitted the original code so that they could apply that fix to their own repo and wherever they rely on the old behavior in their internal infrastructure and tools (e.g., SenseCAP Mate App). I would also have expected a response from him before the PR was merged, but I guess that this change does not break any of their other services. It just affects those relying on TTS, and I don’t know about you, but I don’t want to rely on a crazy format, I’m glad that TTI adopts fixes quickly.
If the vendor updates the decoder in TTS to a new version, and they haven’t synced the changes made in TTS with their own repo, there would be merge conflicts to solve, but that’s not the end of the world.
Regarding legal issues, I don’t see why, when submitting the decoders the vendors agree to the license of the repository and sign the CLA, just like every other contributor.
For anybody still searching for this, I have put together a nice simple one - which I think is correct, but happy to take feedback as the WS hasn’t been in the field very long yet
Edit: anybody know how to only return a payload if it is on fport 3?
function Decoder(bytes, port) {
var decoded = {};
// Decode the payload into separate fields
var Temperature = (bytes[1] << 8) + bytes[2];
var Humidity = bytes[3];
var Light = (bytes[4] << 24) + (bytes[5] << 16) + (bytes[6] << 8) + bytes[7];
var UV = bytes[8];
var WindSp = (bytes[9] << 8) + bytes[10];
var WindDir = (bytes[12] << 8) + bytes[13];
var RainInt = (bytes[14] << 24) + (bytes[15] << 16) + (bytes[16] << 8) + bytes[17];
var Pressure = (bytes[18] << 8) + bytes[19];
var Battery = bytes[21];
// Apply the maths to bring the figures back to original
decoded.Temperature = Temperature/10;
decoded.Humidity = Humidity;
decoded.Light = Light;
decoded.UV = UV/10;
decoded.WindSp = WindSp/10;
decoded.WindDir = WindDir;
decoded.RainInt = RainInt / 1000;
decoded.Pressure = Pressure / 10;
decoded.Battery = Battery;
return decoded;
}