We've succeeded to export our data from the application server to our own application. 1
We've done nothing with this data yet, but this is the first step to our journey to build a complete 2
IoT platform. 3
So later in this course, this application will be called an IoT platform. 4
So far we've just received a simple JSON object representing the content of the uplink data sent by 5
the end device. 6
In this JSON object, the uplink message is stored in a field usually called frame payload. 7
The content of this field is written in base 64 because it's a very convenient way to optimize the representation 8
of binary data. 9
But what does this data represent? 10
Is it the value of a temperature sensor humidity sensor? 11
Is it the character or a number? 12
We absolutely don't know. 13
To decode the binary data received, we need to read the entire end-device documentation and check 14
the meaning of each byte. 15
It can be a very long and difficult process. 16
That's why some IoT platform have device registry, and in this device registry, there are many ready-to-use 17
decoder for the major LoRaWAN device manufacturers. 18
So decoding means: having new fields in the JSON object with the name and corresponding values of all 19
data present in the payload. 20
So, the application server first generate JSON object with a frame payload field containing all the binary 21
data, in base 64. 22
Then, if we now use a decoder, the application server will add an explicit field usually called 23
"decoded payload" in this JSON object. 24
And that will be very helpful. 25
The process is exactly the same for downlink. From our application, 26
the downlink message sent by our HTTP client or our MQTT publisher is a JSON object with a field called 27
frame payload. 28
And again, this field is written in base 64 and describes the raw binary data we want to transmit to 29
our device. 30
During our previous demonstration, when we wanted to send the LED on or off command, 31
we had to find a corresponding base 64 values. 32
For example, the JSON object to send for an LED off command was this one, this 64 base value doesn't help 33
to have a clear representation of our command. 34
We would rather provide a JSON object with a decoded payload field. 35
Indeed, it's much clearer to write the explicit LED value in the message. 36
That means to send this kind of JSON object. 37
So let's recap. 38
When we receive binary data, we need to decode their meaning to produce a clear JSON object. 39
And when we send a clear JSON object, we need to encode it to produce the corresponding binary data. 40
So, the first possibility is to do this decoding and coding on the IoT platform. 41
But there is a second solution all LoRaWAN application server provide a tool to decode the message. 42
That can be very useful in some situation and I would like to present this option. 43
We will see that it works in both ways uplink and downlink. 44
Does it mean that for each sensor I need to write a specific decoder and encoder? 45
Yes. 46
Yes, 47
If they have their own data representation. 48
And in that case, we'll have to dive into the end device documentation, and that could be very time 49
consuming. 50
There are some existing payload structures like Cayenne, Low Power Payload: LPP, and of course they 51
can be used. 52
But if the device manufacturer has built its own payload structure, then yes, we'll have to decode 53
it by ourselves. 54
However, there is a good news. 55
Since 2022, the LoRaWAN alliance has standardized the way the decoder and the encoder works. 56
It means that if we have a decoding function for one device, it should work on all application servers. 57
Great. 58
Let's try it. 59
For this demonstration, I will use TTN as a LoRaWAN server, MQTT for the connection and node-red for 60
my application. 61
As I said earlier, if the application server we use follows the LoRaWAN standard, the decoding and 62
encoding code should be the same on any other application server. 63
So the demonstration here is not specific to TTN. 64
However, it's specific to the device we're using. 65
First, let's have a look at the uplink JSON object message received. 66
When my end device sends an uplink frame in my network application, I need to find the field frame payload. 67
I. 68
I Just remind you that my device sends a simulated temperature between 20 and 25 degrees. 69
I can check that if I get this value and I convert it from the base 64 format into a decimal format. 70
Then in that case, I've got 21 degree. 71
Ok, now what I want is to have the same JSON object here, but with an explicit field for the temperature 72
it represents. 73
Because I know that it's a temperature. 74
So here I want to fill called temperature as well as its value: 75
21. 76
So I go on the TTN application server. 77
I select my device and I choose the payload formatters tab for uplink. 78
In this section, I will be able to write a custom JavaScript code to decode my payload. 79
I'm not going to explain how JavaScript works because it's completely outside of the scope of this course. 80
However, the good news is that we can easily play with the code example proposed here. 81
The only thing we need to know is that input is a JSON object and it contains two fields, one field 82
called "fPort" representing the port number used, and one field called "bytes", which is an array of all 83
bytes received during the transmission. 84
So for example, when my device sends a temperature of, let's say, 21 degrees on port 15, then the 85
input argument of the decode uplink function is actually like this: 86
fPort is equal to 15 and bytes is an array with the unique value 21. 87
So the temperature here is at the first index of the array named bytes, so it's "input.bytes[0]". 88
And the purpose of the decode uplink function here is just to return a new JSON object called data that 89
only contains the field we want to display. 90
So in my case, I just want field called temperature and the corresponding value is, as I said, 91
input.bytes[0]. 92
Sometimes on LoRaWAN server you can even try out your decode uplink function. 93
And that's the case in TTN. 94
We need to enter the payload in hexadecimal format. 95
So 21 degrees in hexadecimal is 15 and our port number is 15. 96
We launched the decoder and here we go. 97
Now, in our JSON object that will be sent to my application, there will be the same frame payload 98
as before in base 64, but there will be also a new field called temperature with the right decimal 99
value. 100
So now if I go back on node-red, I can test that for real. 101
I send an uplink with my device. 102
And there I can find the decoded payload field corresponding to my temperature. 103
We see here it's much easier to read than this frame Payload above. 104
So that was for the uplink. 105
Now, there is exactly the same process for downlink. 106
So in the payload formatted tab, I now choose the downlink section. 107
I'll be able to write a custom JavaScript function that will handle the JSON object received from my 108
application. 109
And it will generate the binary data to send to the device. 110
The only thing we need to know is that the input is a JSON object and it contains two fields: one field 111
called data representing the object sent by our application, and fPort representing the application port 112
number. 113
So for example, when my application sends a command on port 15 to turn on or off the LED, then the 114
input argument of the encode downlink function is actually like this: data is a JSON object {"led" : 1} and fPort 115
is obviously 15. 116
In my case, if I want to send a binary data equal to one when the JSON LED value is one, then my binary 117
data has to be equal to the value: input.data.led. 118
And the purpose of the encode downlink function is just to return a new JSON object with a field called 119
byte. 120
It's an array corresponding to the value to send, and the other field is fPort. 121
So in my case, as I said byte text value: "input.data.led" because I want a binary that are equal 122
to 1 when led is equal to 1, and the binary data equal to 0 when the LED is equal to 0. 123
And finally, fport takes the value "input.fPort" again before testing it 124
for real, we can simulate the proper operation of this function. 125
I will provide a JSON object with the following content: led : 1. 126
The input object is created, the encoded downlink function is executed and the data JSON object generated. 127
There will be a field called byte, which the content is displayed here. 128
Yes, it works. 129
When we provide 1 for the LED, it sends the binary data 1 and if I provide 0, 130
It sends 0. 131
Okay, let's try it out now with node-red. 132
I copy this node. 133
I will call it: LED ON Decoded. 134
Because this node was previously sending this JSON object. 135
It was the frame payload in 64 base format. 136
Now I need to provide a decoded payload. 137
So I erase this field and I replace it by decoded payload LED 1. 138
When the application server will receive this command, it will run the ENCODE downlink function and 139
generate the binary data to send. 140
So I send an LED ON decoded command from my application. 141
First there is a good news, it's that my application server understood my command because it tells me that 142
this downlink message has been queued. 143
Now I go on my device. 144
And if I want to receive the downlink message, I know that I need to send an uplink. 145
So I press the push button. 146
And yes, I've received the binary data 1, and my device application turned on the LED. 147
Everything works perfectly. 148
One more thing. 149
If I have a look at the application server. 150
Previously I saw the binary value displayed in the log console. 151
But now I can see that for an uplink, the JSON object created is displayed with the temperature field. 152
And same thing for downlink. 153
I've got the JSON object with the LED value. 154
Things are much clearer now and it will be very helpful to know which data we exactly send and receive. 155
Fine. 156
I hope it helps. 157
That's the end of this chapter. 158
Now we'll even go deeper in the LoRaWAN world and build our own LoRaWAN 159
private network server and application server.