...
Code Block |
---|
# Example of a successful measurement '000211001a0e2a' '00' -> Successful readout '0211' -> 529 -> 0.529 mH2O '001a' -> 26 -> 26°C (inside Box) '0e2a' -> 3626 -> 3626 mV / 3.626 V |
Reference Parser (Both variants)
Keller PR26X
Configuration
Connected pressure sensor probe from Keller Druckmesstechnik PR26X series.
Parameter | Value | Comment |
---|---|---|
WAN | lorawan | For LoRaWAN OTAA usage. |
PlFmt | 5 | Sets the payload to a short format. |
MbCmd | 0 0 * * * *:R,9600,8N1:010300020002,010300080002 | Reads four Registers: 2 + 3 (Float, Pressure in Bar) and 8 + 9 (Float, Probe Temperature) |
PowerOnDelay | 1500 | Battery variant only. Sets time (in ms) between activating sensor power and reading value (time for sensor to be ready). |
Example Modbus response
Hex to float converter: https://gregstoll.com/~gregstoll/floattohex/
Pressure (0x3f75f07b):
Temperature (0x41b5c079):
Data Uplink (Port 20)
Code Block |
---|
Bytes | 0 . | 1 . 2 . 3 . 4 . | 5 . 6 . 7 . 8 . | 9 . 10 . |
------+--------+-----------------+-----------------+----------+
Field | Header | Pressure | Temperature | Voltage | |
All values are encoded big-endian
Field | Type | Value |
---|---|---|
Header | uint8 | 0x00 on success, 0x80 if an error occurred |
Pressure | float32 | Pressure in Bar , ffffffff on error. |
Temperature | float32 | Temperature in |
Voltage | uint16 | Voltage in mV, ffff on error |
Reference Parser (All variants)
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
/**
* Parser for Lobaro Pressure Probe via LoRaWAN (hybrid gateway).
* Usable for Pressure Probe as or with Presure+Temperature Probe.
* Works with TTN, ChirpStack, or the Lobaro Platform.
*/
function signed(val, bits | ||||||
Code Block | ||||||
| ||||||
/** * Parser for Lobaro Pressure Probe via LoRaWAN (hybrid gateway). * Usable for Pressure Probe as or with Presure+Temperature Probe. * Works with TTN, ChirpStack, or the Lobaro Platform. */ function signed(val, bits) { // max positive value possible for signed int with bits: var mx = Math.pow(2, bits-1); if (val < mx) { // max positive value //possible isfor positivesigned value,int justwith returnbits: var mx = return valMath.pow(2, bits-1); if (val }< elsemx) { // is negativepositive value, convert to neg:just return return val - (2 * mx); } } function int16_BE(bytes, idx) { bytes = bytes.slice(idx || 0); } else { return signed(bytes[0] << 8 | bytes[1] << 0, 2*8); } function uint16_BE(bytes, idx) { bytes = bytes.slice(idx || 0// is negative value, convert to neg: return val - (2 * mx); return bytes[0] << 8 | bytes[1] << 0;} } function uint32int16_BE(bytes, idx) { bytes = bytes.slice(idx || 0); return bytes[0] << 24 | bytes[1] << 16 | bytes[2 return signed(bytes[0] << 8 | bytes[31] << 0, 2*8); } function float32FromInt(asIntuint16_BE(bytes, idx) { varbytes sign = bytes.slice(asIntidx &|| 0x80000000) ? -1 : 10); var exponent = ((asInt >> 23) & 0xFF) - 127; var significand = (asInt & ~(-1 << 23)); if (exponent === 128) return null; // return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY)return bytes[0] << 8 | bytes[1] << 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 float32FromInt(asInt) { var sign = (asInt & 0x80000000) ? -1 : 1; ifvar (exponent === -127) { ((asInt >> 23) & 0xFF) - 127; var if (significand === 0)(asInt return sign * 0.0& ~(-1 << 23)); if (exponent = -126;== 128) significand /= (1 << 22)return null; } else significand = (significand// |return (1sign <<* 23((significand)) / (1 << 23? Number.NaN : Number.POSITIVE_INFINITY); return sign * significand * Math.pow(2, exponent); } function float32_BE(bytes, idx) { return float32FromInt(uint32_BE(bytes, idx)); } /** * TTN decoder function. */ function Decoder(bytes, port) { var vals = {}if (exponent === -127) { if (significand === 0) return sign * 0.0; exponent = -126; if( port == 20 ){ significand /= (1 << 22); } else significand if= (bytes.length==5) { // Pressure Probe without temperature sensor and Bridges internal Temperature vals["error"] = !!(bytes[0]&0x80); vals["pressure"] = int16_BE(bytes, 1)/1000;significand | (1 << 23)) / (1 << 23); return sign * significand * Math.pow(2, exponent); } function float32_BE(bytes, idx) { return float32FromInt(uint32_BE(bytes, idx)); } /** * TTN decoder function. */ function Decoder(bytes, port) { var vals = {}; if( port == 20 ){ if vals["temperature"] = int16_BE(bytes, 3); (bytes.length==5) { // Pressure }Probe without temperature sensor elseand if (bytes.length==7) {Bridges internal Temperature vals["error"] = !!(bytes[0]&0x80); vals["pressure"] = int16_BE(bytes, 1)/1000; vals["temperature"] = int16_BE(bytes, 3); vals["voltagetemperature"] = uint16int16_BE(bytes, 53) / 1000; } else if (bytes.length==97) { vals["error"] = !!(bytes[0]&0x80); // pressure in mH2O vals["pressure"] = float32int16_BE(bytes, 1)/1000; // temperature in Degree Celsiusvals["temperature"] = int16_BE(bytes, 3); vals["temperaturevoltage"] = float32uint16_BE(bytes, 5) / 1000; } else if (bytes.length==119) { vals["error"] = !!(bytes[0]&0x80); // pressure in mH2O pressure in mH2O vals["pressure"] = float32_BE(bytes, 1); // temperature in Degree Celsius vals["pressuretemperature"] = float32_BE(bytes, 15); } else // temperature in Degree Celsiusif (bytes.length==11) { vals["temperatureerror"] = float32_BE!!(bytes, 5[0]&0x80); // pressure in mH2O vals["voltagepressure"] = uint16float32_BE(bytes, 91) / 1000; } // temperature in Degree Celsius } vals["temperature"] = if (port === 64 && bytes.length == 13) { // status packet float32_BE(bytes, 5); vals["Firmware Identifiervoltage"] = String.fromCharCode(bytes[0]) + String.fromCharCode(bytes[1]) + String.fromCharCode(bytes[2]);uint16_BE(bytes, 9) / 1000; } } vals["FirmwareVersion"] if (port = bytes[3] + '.' + bytes[4] + '.' + bytes[5]; == 64 && bytes.length == 13) { // status packet vals["statusFirmware Identifier"] = String.fromCharCode(bytes[0]) + String.fromCharCode(bytes[6]; 1]) + String.fromCharCode(bytes[2]); vals["reboot reasonFirmwareVersion"] = bytes[73]; + '.' + vals["final words"] =bytes[4] + '.' + bytes[85]; vals["voltage [V]status"] = uint16_BE(bytes,9)/1000.0bytes[6]; vals["temperaturereboot [°C]reason"] = int16_BE(bytes,11)/10.0bytes[7]; } return vals; } /** * TTN V3 Wrapper */ function decodeUplink(input) { return {vals["final words"] = bytes[8]; vals["voltage [V]"] = uint16_BE(bytes,9)/1000.0 data: { vals["temperature [°C]"] = values: Decoderint16_BE(input.bytes, input.fPort)11)/10.0; }, warnings: [], errors: [] return }vals; } /** * ChirpStackTTN decoderV3 function.Wrapper */ function Decode(fPort, bytes) { decodeUplink(input) { return { data: { values: Decoder(input.bytes, input.fPort) // wrap TTN Decoder: }, warnings: [], errors: return Decoder(bytes, fPort)[] }; } /** * Lobaro PlatformChirpStack decoder function. */ function Parse(inputDecode(fPort, bytes) { var data = bytes(atob(input.data)); var port = input.fPort;// wrap TTN Decoder: return Decoder(databytes, portfPort); } |
Keller PR26X
Configuration
Connected pressure sensor probe from Keller Druckmesstechnik PR26X series.
...
Example response
Hex to float converter: https://gregstoll.com/~gregstoll/floattohex/
- Pressure in Bar: 0x3f75e3d2
- Temperature in °C: 0x41b61c20
Parser
...
/**
* Lobaro Platform decoder function.
*/
function Parse(input) {
var data = bytes(atob(input.data));
var port = input.fPort;
return Decoder(data, port);
} |