Copy // V3.0 10.05.2022, DS
// V4.0, 06.07.2022, FU
// V5.0 , 11.07.2022, PA
//var medium_table = {
// "Gas": "03",
// "Electricity": "02",
// "Heat: Outlet": "04",
// "Heat: Inlet": "0C",
// "Water": "07",
// "Cold water": "16",
// "Other": "00",
// "Warm water (30-90ðC)": "06",
//};
//Code entry
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 scale = metadata .ss_scale;
//various info that can be extracted
var length = bytes[ 0 ];
var msgType = bytes[ 1 ];
var slaveCount = bytes[ 2 ];
var startCharacter1 = bytes[ 3 ];
var length1 = bytes[ 4 ];
var length2 = bytes[ 5 ];
var startCharacter2 = bytes[ 6 ];
var c = bytes[ 7 ];
var a = bytes[ 8 ];
//72 or 76 -> variable; 73 or 77 -> fixed
var ciField = bytes[ 9 ];
var medium = data .substr ( 34 , 2 );
var checkSum = bytes[ 36 ];
//Different medium IDs, register positions vary
if (medium == "02" ) {
var volume = data .substr ( 72 , 2 ) + data .substr ( 70 ,
2 ) + data .substr ( 68 , 2 ) + data .substr ( 66 , 2 );
decoded .electricityMeterEnergyHt = parseInt (volume ,
16 ) * scale;
volume = data .substr ( 88 , 2 ) + data .substr ( 86 , 2 ) +
data .substr ( 84 , 2 ) + data .substr ( 82 , 2 );
decoded .electricityMeterEnergyNt = parseInt (volume ,
16 ) * scale;
}
if (medium == "03" ) {
var volume = data .substr ( 66 , 2 ) + data .substr ( 64 ,
2 ) + data .substr ( 62 , 2 ) + data .substr ( 60 , 2 );
decoded .gasMeterVolume = parseInt (volume) * scale;
}
if (medium == "16" ) {
var volume = data .substr ( 54 , 2 ) + data .substr ( 52 ,
2 ) + data .substr ( 50 , 2 ) + data .substr ( 48 , 2 );
decoded .waterMeter = parseInt (volume , 16 ) * scale;
}
/* PA
if (medium == "07") {
var volume = data.substr(54, 2) + data.substr(52,
2) + data.substr(50, 2) + data.substr(48, 2);
decoded.waterMeter = parseInt(volume, 16) * scale;
}
*/
if (medium == "07" ) {
var volume = data .substr ( 66 , 2 ) + data .substr ( 64 ,
2 ) + data .substr ( 62 , 2 ) + data .substr ( 60 , 2 );
var gwf_scale = 1 ;
switch ( data .substr ( 58 , 2 )) {
case "13" :
gwf_scale = 0.001 ;
break ;
case "14" :
gwf_scale = 0.01 ;
break ;
case "15" :
gwf_scale = 0.1 ;
break ;
case "16" :
gwf_scale = 1 ;
break ;
case "17" :
gwf_scale = 10 ;
break ;
default :
break ;
}
decoded .waterMeter = volume * gwf_scale;
}
if (medium == "04" ) {
var volume = data .substr ( 54 , 2 ) + data .substr ( 52 ,
2 ) + data .substr ( 50 , 2 ) + data .substr ( 48 , 2 );
decoded .waterMeter = parseInt (volume , 16 ) * scale;
}
return decoded;
}
//Helper functions
function parseHexString (hex) {
for ( var bytes = [] , c = 0 ; c < hex . length ; c += 2 )
bytes .push ( parseInt ( hex .substr (c , 2 ) , 16 ));
return bytes;
}
function decodeBattery (byte) {
if (byte == 0 ) {
return 'External power source' ;
} else if (byte > 0 && byte < 255 ) {
return byte / 254 * 100 ;
} else {
return 'Unknown battery state' ;
}
}
function parseFloat (str) {
var float = 0 ,
sign , order , mantissa , exp ,
int = 0 ,
multi = 1 ;
if ( / ^ 0x/ .exec (str)) {
int = parseInt (str , 16 );
} else {
for ( var i = str . length - 1 ; i >= 0 ; i -= 1 ) {
if ( str .charCodeAt (i) > 255 ) {
console .log ( 'Wrong string parameter' );
return false ;
}
int += str .charCodeAt (i) * multi;
multi *= 256 ;
}
}
sign = (int >>> 31 ) ? - 1 : 1 ;
exp = (int >>> 23 & 0xff ) - 127 ;
mantissa = ((int & 0x7fffff ) + 0x800000 ) .toString ( 2 );
for (i = 0 ; i < mantissa . length ; i += 1 ) {
float += parseInt (mantissa[i]) ? Math .pow ( 2 , exp) :
0 ;
exp -- ;
}
return float * sign;
}