LoRaWAN Connection
Info | ||
---|---|---|
| ||
Some of the features listed here (LoRaWAN 1.1, Remote Configuration, ...) are only implemented for recent versions of our firmware. For the Lobaro Sensor this starts with v0.2.1, for the Keller Sensor it starts with v0.3.0. If possible, you should update your devices to our most recent firmware. |
The connection to the LoRaWAN network is defined by multiple configuration parameters. This need to be set according to your LoRaWAN network and the way your device is supposed to be attached to it, or the device will not be able to send any data.
For a detailed introduction into how this values need to be configured, please refer to the chapter LoRaWAN configuration in our LoRaWAN background article.
Name | Description | Type | Values |
---|---|---|---|
OTAA | Activation: OTAA or ABP | bool | true = use OTAA, false = use ABP |
DevEUI | DevEUI used to identify the Device | byte[8] | e.g. 0123456789abcdef |
JoinEUI | Used for OTAA (called AppEUI in v1.0) | byte[8] | e.g. 0123456789abcdef |
AppKey | Key used for OTAA (v1.0 and v1.1) | byte[16] | |
NwkKey | Key used for OTAA (v1.1 only) | byte[16] | |
SF | Initial / maximum Spreading Factor | int | 7 - 12 |
ADR | Use Adaptive Data Rate | bool | true = use ADR, false = don't |
TimeSync | Days after which to sync time | int | days, 0 =don't sync time |
RndDelay | Random delay before sending | int | max seconds |
RemoteConf | Support Remote Configuration | bool | true =allow, false =deactivate |
LostReboot | Days without downlink before reboot | int | days, 0 =don't reboot |
Configuration
Configuration values defining the behaviour of the device. The Min and Max values will be preconfigured when receiving the device. In case of using "Restore Default" they will be reset to standard values and have to be set again using the values printed on the sensor or given separately.
name | description | example value |
---|---|---|
sendCron | Cron expression defining when to read and send | 0 0/15 * * * * for every 15 minutes |
rangeMin | min range in mh2o | in most cases 0 |
rangeMax | max range in mh2o | in most cases 15 |
outputMin | min digital output value of the sensor | in most cases 819 |
outputMax | max digital output value of the sensor | in most cases 11664 |
See also our Introduction to Cron expressions.
Payload Format
Data Message
Port: 1, Payload: 8 Bytes
Temperature is transmitted in 1/100°C, battery voltage in Millivolt and pressure in Bar.
PRESSURE | Temperature | Battery Voltage | |||||
---|---|---|---|---|---|---|---|
float32 | float32 | float32 | float32 | int16 | int16 | int16 | int16 |
Byte 0 | Byte 1 | Byte 2 | Byte 3 | LSB | MSB | LSB | MSB |
Status message
Port: 64, Payload: 13 Bytes
The Status Message communicates information about the device itself (starting with firmware 0.3.0). It contains information like the internal temperature of the device and the reason for the latest reboot.
For instructions how to parse the status message, please take a look at the reference parser implementation.
Payload Parser
Element-IoT: https://github.com/ZennerIoT/element-parsers/blob/master/lib/lobaro_pressure26d.ex
The Things Network
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
/* Helper functions used by this parser */ function signed(val, bits) { if ((val & 1 << (bits-1)) > 0) { // value is negative (16bit 2's complement) val = (~val & ((1 << bits) - 1)) + 1; // invert all bits & add 1 => now positive value val = val * -1; } return val; } function uint40_BE(bytes, idx) { bytes = bytes.slice(idx || 0); return bytes[0] << 32 | bytes[1] << 24 | bytes[2] << 16 | bytes[3] << 8 | bytes[4] << 0; } function uint32_BE(bytes, idx) { bytes = bytes.slice(idx || 0); return bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3] << 0; } function uint16_BE(bytes, idx) { bytes = bytes.slice(idx || 0); return bytes[0] << 8 | bytes[1] << 0; } function uint32_LE(bytes, idx) { bytes = bytes.slice(idx || 0); return bytes[0] << 0 | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24; } function uint16_LE(bytes, idx) { bytes = bytes.slice(idx || 0); return bytes[0] << 0 | bytes[1] << 8; } function int40_BE(bytes, idx) { return signed(uint40_BE(bytes, idx), 40); } function int32_BE(bytes, idx) { return signed(uint32_BE(bytes, idx), 32); } function int16_BE(bytes, idx) { return signed(uint16_BE(bytes, idx), 16); } function int32_LE(bytes, idx) { return signed(uint32_LE(bytes, idx), 32); } function int16_LE(bytes, idx) { return signed(uint16_LE(bytes, idx), 16); } function float32(bytes) { var sign = (bytes & 0x80000000) ? -1 : 1; var exponent = ((bytes >> 23) & 0xFF) - 127; var significand = (bytes & ~(-1 << 23)); if (exponent === 128) return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY); if (exponent === -127) { if (significand === 0) return sign * 0.0; exponent = -126; significand /= (1 << 22); } else significand = (significand | (1 << 23)) / (1 << 23); return sign * significand * Math.pow(2, exponent); } function readVersion(bytes, i) { if (bytes.length < 3) { return null; } return "v" + bytes[i] + "." + bytes[i + 1] + "." + bytes[i + 2]; } /* Port 1: Data */ function Decoder_Data(bytes) { return { pressure: float32(int32_LE(bytes, 0)), temp: int16_LE(bytes,4) / 100, voltage: int16_LE(bytes,6) / 1000, } } /** * Decode status/error codes from GPS-Tracker to human readable tags. */ function decode_status_code(code) { switch (code) { case 0: return "OK"; case 101: return "PROBE_ERROR"; default: return "UNKNOWN"; } } /** * Decode reboot reason explaining last reboot of device. */ function decode_reboot_reason(code) { // STM reboot code from our HAL: switch (code) { case 1: return "LOW_POWER_RESET"; case 2: return "WINDOW_WATCHDOG_RESET"; case 3: return "INDEPENDENT_WATCHDOG_RESET"; case 4: return "SOFTWARE_RESET"; case 5: return "POWER_ON_RESET"; case 6: return "EXTERNAL_RESET_PIN_RESET"; case 7: return "OBL_RESET"; default: return "UNKNOWN"; } } /* Port 64: Status */ function Decoder_Status(bytes) { var firmware = String.fromCharCode.apply(null, bytes.slice(0, 3)); var version = readVersion(bytes, 3); var status_code = bytes[6]; var status_text = decode_status_code(status_code); var reboot_code = bytes[7]; var reboot_reason = decode_reboot_reason(reboot_code); var final_code = bytes[8]; var vcc = (int16_BE(bytes, 9) / 1000) || 0.0; var temp = (int16_BE(bytes, 11) / 10) || -0x8000; var app_data = bytes.slice(13); return { "firmware": firmware, "version": version, "status_code": status_code, "status_text": status_text, "reboot_code": reboot_code, "reboot_reason": reboot_reason, "final_code": final_code, "temperature": temp, "voltage": vcc, "app_data": app_data }; } // TTN compatible decoder function: function Decoder(bytes, port) { // Decode an uplink message from a buffer // (array) of bytes to an object of fields switch (port) { case 1: // date message: return Decoder_Data(bytes); case 64: // lobaro unified status telegram return Decoder_Status(bytes); case 128: case 129: case 130: case 131: // remote config responses return {}; default: // unsupported port: return null; } } function UpdateDevice(decoded) { if (!Device || !Device.setProperty) { // not in Lobaro Platform parser return; } var keys = ["firmware", "version", "status_code", "status_text", "reboot_code", "reboot_reason", "final_code", "final_words", "app_data", "temperature", "voltage"]; for (var i=0; i< keys.length; i++) { var key = keys[i]; if (decoded[key]) { Device.setProperty(key, decoded[key]); } } } // Wrapper for Lobaro Platform (not used in TTN) function Parse(input) { // Decode an incoming message to an object of fields. var b = bytes(atob(input.data)); // use TTN decoder: var decoded = Decoder(b, input.fPort); // Update values in device properties UpdateDevice(decoded); return decoded; } |
Device & Probe Dimensions
CE Declaration of Conformity
CE Declaration of Conformity (pdf).