I have strange and interesting behaviour of function node. Script in Function node is only to form payload. In most cases it gives correct payload, but sometimes gives error "TypeError: Cannot set properties of undefined (setting 'snr')". snr parameter is always present in same format and path. Script is following:
var device_id = msg.payload.end_device_ids.device_id;
var gateway_id=msg.payload.uplink_message.rx_metadata[0].gateway_ids.gateway_id
var snr=msg.payload.uplink_message.rx_metadata[0].snr
var rssi=msg.payload.uplink_message.rx_metadata[0].rssi
var sf=msg.payload.uplink_message.settings.data_rate.lora.spreading_factor
msg.payload.uplink_message.decoded_payload["snr"] = snr
msg.payload.uplink_message.decoded_payload["rssi"] = rssi
msg.payload.uplink_message.decoded_payload["sf"] = sf
msg.payload.uplink_message.decoded_payload["gateway_id"] = gateway_id
fields=msg.payload.uplink_message.decoded_payload
tags = {
// "timestamp" : timestamp,
"device_id" : device_id,
}
msg.payload=[fields, tags]
return msg;
This problem relates to snr value only.
Is there any reasonable explanation or solution to this error?
This is the first time you are accessing msg.payload.uplink_message.decoded_payload - so this suggests that property doesn't exist on the message the function has received.
Sorry, meant to post this sooner (before Nick posted). Contains a bit more info though so might still be useful.
I don't think that is true - if you comment out the msg.payload.uplink_message.decoded_payload["snr"] = snr line, I think you will find the next line errors.
My suspicion is that msg.payload.uplink_message.decoded_payload either does not exist or is not an object.
If you add a line before that section something like:
if (!msg?.payload?.uplink_message?.decoded_payload) {
msg.payload.uplink_message.decoded_payload = {}
}
That should fix it. The ?. are a forgiving way of checking property references. The code is a way of trying to make sure that the property exists. You might also have to add more checks if it is possible that
I agree with @TotallyInformation and with @knolleary - snr is problem, but if rssi will be on the first place, problem will be with rssi.
But just to have clear starting point - all parameters as well as payload already exists. As decoded_payload not have all necessary parameters, metadata snr, rssi, sf and gateway_id are added to usefull payload and converted into tabel with function node. Maybe I didn't make optimal solution to do this, but so far it works (any propose is welcome).
As proposed @Steve-Mcl , choice no. 2 sounds as the most appropriate for this case.
But it is still not clear to me why error not happening every time and I still haven't found out which condition causing error. @TotallyInformation , I'll check if msg.payload.uplink_message.decoded_payload exists in time of error
You are providing only tiny snippets of information from various things.
There is a "debug 41" in the flow image, but the debug message you show is from "debug 76"
The errors you show come from 2 different functions but only show the code from 1 function
The debug output you do show is an array & will never have .uplink_message.decoded_payload
The cold hard immutable fact is - when you get TypeError: Cannot set properties of undefined it means the thing you are trying to populate is undefined
i.e. msg.payload or msg.payload.uplink_message or msg.payload.uplink_messag.decode_payload is pure and simple undefined.
The reason is probably due to different payload shapes coming from the MQTT node, but as i stated earlier, you are providing only snippets of info. Does that MQTT node give types of payload?
Yes, msg.payload.uplink_message.rx_metadata[0].snr did indeed exist and had a value of 3.75.
But did msg.payload.uplink_message.decoded_payload exist, when you tried to assign the value to msg.payload.uplink_message.decoded_payload.snr ? Was it an object?
The error is not saying that device_id is not present, it is saying that msg.payload.uplink_message.decoded_payload is undefined, so it cannot set its device_id property.
Just to reinforce what everyone has already told you:
You are misunderstanding the error message.
It does not mean that device_id does not exist.
It means that msg.payload.uplink_message.decoded_payload does not exist (or it exists but is not an object)
In addition I find your code rather perplexing. msg.payload.uplink_message.decoded_payload["gateway_id"] = gateway_id
Why are you using quotes around gateway_id inside square brackets?
You appear to be trying to assign a value to msg.payload.uplink_message.decoded_payload.gateway_id
The dot notation should work fine, provided that msg.payload.uplink_message.decoded_payload already exists.
Thank you to all for all advices - I've found out two same devices, which beside normal uplink sends uplink without decoded_payload. In this case, error happens.
Is the best way to avoid such cases to use, for example, switch node - to not decode uplink message without decoded_payload?