Page cover image

RCM - LRW10

Product Datasheet

Device Profile for Tesenso IoT Cloud

Decoder/Payload Converter for Tesenso IoT Cloud

https://github.com/Tesenso-GmbH/Device-Decoder/blob/main/GWF_LRW10.js
// V 1.0 G.G. 09-06-2023 , Initial Version, Please don't confuse this decoder with GWF M-Bus or other decoder 

//..... Medium .....
//  0x03 -> Gas
//  0x06 -> Warm Water
//  0x07 -> Water

/*
For Testing 

{
    "ts": 1686317316027,
    "rssi": -40,
    "snr": 8.2,
    "toa": 98,
    "frequency": 867300000,
    "dr": "SF7 BW125 4/5",
    "data":"02e61e490902000734ffff162fa90000200028fb",
    "port": 2,
    "bat": 0
}
*/


if (msg.data) {
    var decoded = decodeFromHex(msg.data.toString());
    decoded.ts = msg.ts;
    decoded.rssi = msg.rssi;
    decoded.snr = msg.snr;
    decoded.toa = msg.toa;
    decoded.frequency = msg.frequency;
    decoded.dr = msg.dr;
    //decoded.bat = decodeBattery(msg.bat);
    decoded.hex = msg.data;

    return {
        msg: decoded,
        metadata: metadata,
        msgType: msgType
    };
} else {
    return {
        msg: msg,
        metadata: metadata,
        msgType: msgType
    };
}


function decodeFromHex(data) {
    // Decode uplink message
    var decoded = {};

    //Parse string as bytes
    var bytes = parseHexString(data);
    //scale to manage the different scales with none, one or more decimals on the meter.
  
  //var bytes = input.bytes;
  // Decode an uplink message from a buffer
  // (array) of bytes to an object of fields.

  // gwf protocol byte 0
  switch(bytes[0]){
    case 0x01:
      decoded.protocol="standard";
      break;
    case 0x02:
      decoded.protocol="noDueDate";
      break;
    default:
      decoded.protocol="unkown";
      break;
  }
  // manufacturer byte 1,2
  decoded.manufacturer=getManufacturer(bytes[1],bytes[2]);
  
  // meter id byte 3,4,5,6
  
  decoded.meterId=0;
  
  for(var i=3;i>=0;i--){
    decoded.meterId = decoded.meterId*100+decode(bytes[i+3])
  }
  
  
  //medium byte 7
  switch(bytes[7]){
    case 0x03:
      decoded.medium="Gas";
      break;
    case 0x06:
      decoded.medium="Hot Water";
      break;
    case 0x07:
      decoded.medium="Water";
      break;
    default:
      decoded.medium="Unkown";
  }
  
  
  decoded.badEncoder= (((bytes[8]&(1<<4))>>4)&((bytes[8]&(1<<6)))>>6)!==0;
  decoded.noEncoder=  (((bytes[8]&(1<<4))>>4)&((bytes[8]&(1<<5)))>>5)!==0;
  decoded.lowBattery= ((bytes[8]&(1<<2))>>2)==1;
  
  
  //actuality duration bytes 10,11
  decoded.actualityduration=bytes[10]*265+bytes[9]
  
  
  // register value, bytes 12,13,14,15
  var registerValue=0;
  var j=15;
  while(1){
    registerValue+=bytes[j]
    if(j==12) break;
    registerValue*=256;
    j--;
  }
  
  decoded.registerValue=registerValue;
  
  //byte 16
  
  decoded.reservedBit0=(bytes[16]&0x1)==1;
  decoded.continousFlow=(bytes[16]&0x2)==1;
  decoded.reservedBit2=(bytes[16]&0x4)==1;
  decoded.brokenPipe=(bytes[16]&0x8)==1;
  decoded.reservedBit4=(bytes[16]&0x10)==1;
  //decoded.lowBattery=(bytes[16]&0x20)==1;
  decoded.backFlow=(bytes[16]&0x40)==1;
  decoded.reservedBit7=(bytes[16]&0x80)==1;
  
  //byte 17
  decoded.batteryLifeSemesters=(bytes[17]&0xF8)>>3;
  decoded.linkError=(bytes[17]&0x04)!==0
  
  //byte 18-19
  decoded.crc = "0x"+(bytes[18]*256+bytes[19]).toString(16);
  

  return decoded;
}


function decode(b){
  return (b>>4)*10+(b&0xF);
}


function getManufacturer(lowByte,highByte){
  var valHB=parseInt(highByte);
  var valLB=parseInt(lowByte);
  var res=valHB*256+valLB;
  var firstLetterCC = res / 32 / 32 + 64;
  var firstLetter = String.fromCharCode(firstLetterCC);
  var secondLetterCC = (res / 32) % 32 + 64;
  var secondLetter = String.fromCharCode(secondLetterCC);
  var thirdLetterCC = res % 32 + 64;
  var thirdLetter = String.fromCharCode(thirdLetterCC);
  return firstLetter.concat(secondLetter, thirdLetter);
}


function parseHexString(hex) {
    for (var bytes = [], c = 0; c < hex.length; c += 2) {
        bytes.push(parseInt(hex.substr(c, 2), 16));
    }
    return bytes;
}

Last updated