LoRaWAN
Example on GitHub (opens in a new tab)
Model
Problem: Suppose you have a modem that provides a LoRaWAN connection to a server and transmits data from a Vega SI-11 pulse counter. All data comes in Base64 in the following format.
1 Packet with current readings
| Size | Field Description | Data Type | | -------- | ----------------------------------------------------------------------------------------- | ------------- | ------ | | 1 byte | Packet type, for this packet == 1 | uint8 | | 1 byte | Battery charge, % | uint8 | | 1 byte | Basic setting values (bit field) | uint8 | uint8 | | 4 bytes | Time of the readings transmitted in this packet (unixtime UTC) | uint32 | uint32 | | 1 byte | Temperature, β°C | int8 | | 4 bytes | Readings on input 1 (depending on type - number of pulses, or state 0 - open, 1 - closed) | uint32 | uint32 | | 4 bytes | Readings at input 2 (depending on type - number of pulses, or state 0 - open, 1 - closed) | | uint32 | | 4 bytes | Readings at input 3 (depending on type - number of pulses, or state 0 - open, 1 - closed) | uint32 | uint32 | | 4 bytes | Reading on input 4 (depending on type - number of pulses, or state 0 - open, 1 - closed) | uint32 | uint32 |
2 Alarm packet
| Size | Field Description | Data Type | | -------- | ------------------------------------------------------------------------------------------------ | ------------- | ------- | ------------------------------------------------------------------------------------------------- | | 1 byte | Packet type, for this packet == 2 | uint8 | | 1 byte | Battery charge, % | uint8 | | 1 byte | Basic setting values (bit field) | uint8 | uint8 | | 1 byte | Number of the input on which the alarm is detected | uint8 | | 4 bytes | Packet generation time (unixtime UTC) | uint32 | uint32 | | 4 bytes | Current reading on input 1 (depending on type - number of pulses, or state 0 - open, 1 - closed) | uint32 | uint32 | | 4 bytes | Current reading at input 2 (depending on type - number of pulses, or state 0 - open, 1 - closed) | uint32 | 4 bytes | Current reading at input 2 (depending on type - number of pulses, or state 0 - open, 1 - closed). | | 4 bytes | Current reading at input 3 (depending on type - number of pulses, or state 0 - open, 1 - closed) | uint32 | uint32 | | 4 bytes | Current reading at input 4 (depending on type - number of pulses, or state 0 - open, 1 - closed) | uint32 | uint32 |
Decoding of the bit field "Basic settings values"
Bit | Value |
---|---|
0 bit | Activation type 0 - OTAA, 1 - ABP |
1, 2, 3 bits | Communication period: |1 == 0|2==0|3==0| - 5 minutes |1 == 1|2==0|3==0| - 15 minutes |1 == 0|2==1|3==0| - 30 minutes |1 == 1|2==1|3==0| - 1 hour |1 == 0|2==0|3==1| - 6 hours |1 == 1|2==0|3==1| - 12 hours |1 == 0|2==1|3==1| - 24 hours |
4 bits | Type of the first input: 0 - pulse, 1 - guard |
5 bits | Second input type: 0 - pulse, 1 - guard |
6 bits | Type of the third input: 0 - pulse, 1 - guard |
7 bits | Type of the fourth input: 0 - pulse, 1 - guard |
In fields consisting of several bytes, the LE (little-endian - from the junior high school) order is used. LE order (little-endian - from youngest to oldest).
To connect the modem to the platform, create a LoRaWAN model for it.
The LoRaWan template model only has basic parameters.
You need to parse the data in the handler, and create the parameters in the model additionally.
For more information on LoRaWAN argument formation
See a preview of the object with the model you created by clicking the Show preview button. preview**.
If you wish, select an icon to display the object on the map, or upload your own image.
Model to import (opens in a new tab)
Object
Create an object for your modem. Select the model you just created. Then enter the DevEUI device identifier. Specify a name for the object.
Once saved, the instructions for configuring the device to the platform will open.
Click on the Edit tab. Select the frequency plan Frequency plan. Specify the AppKey application key and the Gateway Id. You can also specify the specific geo position of the modem in the Coordinates section, by specifying latitude and longitude, or you can select a point on the map. Then it will be stationary on the map even if there are no coordinates in the data packet.
Connection
To connect the modem to the platform, in its Packet Forwarder configurator, specify the following settings the following settings:
{
"gateway_conf": {
"gateway_ID": "<Gateway EUI>",
"server_address": "dev.rightech.io",
"serv_port_up": 1700,
"serv_port_down": 1700
}
}
Make sure that after saving the settings, data from the device is sent and is displayed in the interface.
Handlers
To parse the data received from the device via LoRaWAN protocol, use a handler.
Create a new handler.
Write code for your handler that takes data from payload as input, and returns the values from the sensor on the output.
const EVENT_PACKET = 1;
const EVENT_ALARM = 2;
/**
* Check if n-th bit set for number
* @param value {number} number value
* @param bit {number} bit position
*/
function bit(value, bit) {
return (value & (1 << bit)) !== 0;
}
/**
* Parse Vega SI-11 Payload
* https://en.iotvega.com/product/si11
*
* ```
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8-11 | 12-15 | 16-19 | 20-23
* 1 - EVENT_PACKET | type | bat | cfg | timestamp | t | in[0] | in[1] | in[2] | in[3]
* 2 - EVENT_ALARM | type | bat | cfg | i | timestamp | in[0] | in[1] | in[2] | in[3]
*
* ```
* @param payload {string} base64 encoded payload
*/
export function process(payload) {
const data = ric.base64.decode(payload);
let offset = 0;
/* - option 1 - parse binary payload from raw byte array */
const bytes = new Uint8Array(data.buffer);
const evtype = bytes[offset++];
const battery = bytes[offset++];
const configByte = bytes[offset++];
const config = {
activation: bit(configByte, 0) ? "abp" : "otaa",
inputs: [
+bit(configByte, 4),
+bit(configByte, 5),
+bit(configByte, 6),
+bit(configByte, 7),
],
};
const evin = evtype === EVENT_ALARM ? bytes[offset++] : undefined;
/* - option 2 - use JS `DataView` interface (like Node's `Buffer`) */
const evtime = data.getUint32(offset, true) * 1000;
offset += 4;
const temperature =
evtype === EVENT_PACKET ? data.getInt8(offset++) : undefined;
const inputs = [];
for (let i = 0; i < 4; i++) {
inputs[i] = data.getUint32(offset, true);
offset += 4;
}
return { evtype, battery, config, evin, evtime, temperature, inputs };
}
After saving the handler, check its operability in the testing mode on some typical packages. testing mode on some typical packages.
On the Objects tab, select your modem.
Match the input and output parameters of the handler with the arguments that were created in the model.
Now when packets are received from the device, information on the sensor parameters.