Cayenne LPP Decoder

Hello All,

I am trying to build a decoder for Cayenne LPP but I am not successful. The longitude conversion is not correct, someone can help me where my mistake is.

decoded.latitude = (bytes[6]<<16 | bytes[7]<<8 | bytes[8])/10000;
decoded.longitude = ((bytes[9]<<16 | bytes[10]<<8 | bytes[11])/10000);

Decoder Test:

Payload : 0A02019014880323B6F0AFB302BF20

Thank you!

Why do you create your own decoder? If you set the payload format to cayenne lpp TTN will do the decoding for you.


How do I do that?

In the console on the screen where you define the payload decoder there is a dropdown that is currently set to custom. Change that to Cayenne LPP.

Thank you very much.

Of course, Kersing is always right. But just FYI: for (possibly) negative numbers, you need to make 32 bits available to JavaScript, using sign extension.

So, untested, and I did not peek into the LPP documentation, I’d assume:

// To support negative values, sign extend to 32 bits by shifting the MSB
// 8 bits too far to the left, followed by sign-propagating right-shift:
decoded.latitude = (bytes[i++]<<24>>8 | bytes[i++]<<8 | bytes[i++])/10000;
decoded.longitude = (bytes[i++]<<24>>8 | bytes[i++]<<8 | bytes[i++])/10000;

You’re right friend, make the change you told me and it’s working really well. Thank you very much.


Greetings from Queretaro, Mex.

Again I’ve not read the LPP documentation, but I’m quite sure you’ll need it for altitude too:

decoded.altitude = (bytes[i++]<<24>>8 | bytes[i++]<<8 | bytes[i++])/100;

Same goes for anything that can be negative, such as temperatures.

And if Cayenne has any 32 bits type that is not signed (unsigned, which cannot be negative) then you actually need to ensure JavaScript does not handle it as a “two’s complement number”. See uint32 in Abeeway Microtracker Decoder for one option to do that.

Also, one of the major selling points of LPP is its support for dynamic length payloads. So, you cannot use fixed array indexes, like bytes[6], in your while(i < bytes.length) loop. Instead, use the postfix-increment in bytes[i++]. (Even for fixed-position payloads, using i++ often makes the code less error prone anyway.)

Another selling point is that it allows for multiple readings of sensors of the same type, so you cannot use decoded.someName = ..., but need to add the “channel” number to the names, like, e.g., decoded['altitude_' + s_ch] = ....

But of course, you don’t need to worry about that when using TTN’s decoder.

Well, there are situations where you want to have control over what is happening :slight_smile: or when you need some flexibility, or higher complexity, etc. I like the idea.

In those situations I would use/define a more flexible format and stay away from the limited set of data types offered by Cayenne LPP. I like the platform for fast prototyping but regularly struggle when it comes to finding a suitable data type for measurements.