Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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.


ParameterValueComment
WANlorawanFor LoRaWAN OTAA usage.
PlFmt5Sets the payload to a short format.
MbCmd0 0 * * * *:R,9600,8N1:010300020002,010300080002Reads four Registers: 2 + 3 (Float, Pressure in Bar) and 8 + 9 (Float, Probe Temperature)
PowerOnDelay1500Battery 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):

Image Added

Temperature (0x41b5c079):

Image Added

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

FieldTypeValue
Headeruint80x00 on success, 0x80 if an error occurred
Pressurefloat32Pressure in Bar, ffffffff on error.
Temperaturefloat32

Temperature in °C, ffffffff on error.

Voltageuint16Voltage in mV, ffff on error

Reference Parser (All variants)

Code Block
languagejs
titlePressure Probe Parser
linenumberstrue
/**
 * 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
languagejs
titlePressure Probe Parser
linenumberstrue
/**
 * 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

Image Removed

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);
}