Copy // var msg = {
// "data2" : "29 44 B4 25 33 98 00 20 10 07 7A 0B 00 0020 04 13 35 00 00 00 84 10 13 03 00 00 00 02 5A F1 00 02 FD 17 00 00 02 FD 74 FE 15",
// "data": "3e 44 b425 11111111 10 07 7af8 00 3025 04 13 b70b0000 8410 13 00000000 02 5a 0000 02 FD17 0108 02 fd74 d016",
// "data3": "2944B4253398002010077A4620002004139FB400008410130B000000025AF20002FD17080002FD74E415",
// "data4": "2944B4253398002010077A4620002004139FB400008410130B000000025AF200 02FD17 FF7F 02FD74E415",
// "data5": "2944 B425 3498 0020 1007 7A45 0000 20 0413D67F000084101317000000025AA50002FD17000002FD74E415",
// "data6": "780413600B0000841013CD000000025AB90002FD17000002FD740815"
// }
var decodedMsg = msg;
if (msg && msg .data) {
decodedMsg = main ( msg .data)
}
return {
msg : decodedMsg ,
metadata : metadata ,
msgType : msgType
};
// console.log(decodedMsg)
function main (data) {
var CI_FIELD = '78' ;
var ADDRESS_INDEX_START = 4 ;
var ADDRESS_INDEX_END = 7 ;
var VERSION_INDEX = 8 ;
var MEDIUM_FIELD = 'Water' ;
var MANUFACTURER_FIELD = 'IMT' ;
var VALUE_DIF_VIF = {
waterMeter : '04 13' ,
reverseWaterMeter : '84 10 13' ,
flowTemperature : '02 5a' ,
errorCodes : '02 fd 17' ,
batteryLifetime : '02 fd 74'
}
var STATUS_AND_EVENT_LIST_FIELD = [
// Don,t remove those following empty fields.
// Those are required since this full list is required for a 16-bit incoming status and event handling data
'' , '' ,
'configMaxWaterTemperature' ,
'configLimitMinWaterTemperature' ,
'alarmDry' ,
'alarmOverFlow' ,
'alarmReverseFlow' ,
'alarmBatteryLow' ,
'alarmNoConsumption' ,
'alarmOverTemperature' ,
'alarmHeat' ,
'alarmFrost' ,
'alarmLeak' ,
'alarmBurst' ,
'alarmAirBubble' ,
''
]
var ERROR_LIST_FIELD = [
'dry' ,
'overFlow' ,
'reverseFlow' ,
'batteryLow' ,
'noConsumption' ,
'overTemperature' ,
'heat' ,
'frost' ,
'leak' ,
'burst' ,
'airBubble'
]
if ( ! String . prototype .includes) {
String . prototype . includes = function (search , start) {
'use strict' ;
if ( typeof start !== 'number' ) {
start = 0 ;
}
if (start + search . length > this . length ) {
return false ;
} else {
return this .indexOf (search , start) !== - 1 ;
}
};
}
function format (value) {
var bytes = value .replaceAll ( ' ' , '' ) .toLowerCase ();
var byteArr = []
for ( var i = 0 ; i < bytes . length ; i += 2 ) {
byteArr .push (bytes[i] + "" + bytes[i + 1 ])
}
return byteArr;
}
function isUnparsed (value) {
return value && !! value . length && value[ 0 ] === CI_FIELD ;
}
function getBodyPayloadStr (value) {
var payloadStartIndex = isUnparsed (value) ? 1 : 15 ;
if ( value . length > payloadStartIndex) {
return value .slice (payloadStartIndex) .join ( ' ' );
}
return '' ;
}
function getRevHexValue (value , startIndex , endIndex , convertToDecimal , devider) {
endIndex = endIndex || startIndex;
convertToDecimal = convertToDecimal || false ;
devider = devider || 1 ;
var result = Array.isArray(value) && !!value.length && value.slice(startIndex, endIndex + 1).reverse().join('') || null;
if ( !! result && convertToDecimal) {
result = parseInt (result , 16 ) / devider
}
return result;
}
function getAddressAndHeaders (value) {
var res = {};
if ( isUnparsed (value)) {
res .ciField = CI_FIELD ;
} else {
res = {
secondaryAddress : getRevHexValue (value , ADDRESS_INDEX_START , ADDRESS_INDEX_END ) ,
medium : MEDIUM_FIELD ,
length : getRevHexValue (value , 0 , 0 , true ) ,
manufacturer : MANUFACTURER_FIELD ,
version : getRevHexValue (value , VERSION_INDEX , VERSION_INDEX , true )
}
}
return res
}
function getDeviceValue (key) {
var result = 1 ;
if (key === 'waterMeter' || key === 'reverseWaterMeter' ) {
result = 1000 ;
} else if (key === 'flowTemperature' ) {
result = 10 ;
}
return result;
}
function getValuesByDifVif (valueStr , result) {
result = result || {};
if ( ! valueStr) {
return result;
}
var newValueStr;
var foundResKey;
for ( var key in VALUE_DIF_VIF ) {
if ( valueStr .startsWith ( VALUE_DIF_VIF [key])) {
foundResKey = key;
break ;
}
}
if ( !! foundResKey) {
var difVifArr = VALUE_DIF_VIF [foundResKey] .split ( ' ' );
if (foundResKey === 'reverseWaterMeter' ) {
difVifArr[ 0 ] = '04'
}
var dataIndexLength = parseInt (difVifArr[ 0 ]);
var payloadLength = difVifArr . length + dataIndexLength;
result[foundResKey] = getRevHexValue (
valueStr .split ( ' ' ) ,
payloadLength-dataIndexLength, payloadLength-1, foundResKey !== 'errorCodes', getDeviceValue(foundResKey));
newValueStr = valueStr .split ( ' ' ) .slice (payloadLength) .join ( ' ' );
return getValuesByDifVif (newValueStr , result);
}
newValueStr = valueStr .split ( ' ' ) .slice ( 1 ) .join ( ' ' );
return getValuesByDifVif (newValueStr , result);
}
function getDeviceValues (value) {
var bodyPayloadStr = getBodyPayloadStr (value);
return getValuesByDifVif (bodyPayloadStr);
}
function getStatusAndEvents (errorCode) {
var errorCodeInt = parseInt (errorCode , 16 );
var errorCodeBin = errorCodeInt .toString ( 2 )
if ( errorCodeBin . length < 16 ) {
}
var shortLength = 16 - errorCodeBin . length ;
for ( var i = 0 ; i < shortLength; i ++ ) {
errorCodeBin = '0' + errorCodeBin;
}
var result = {
error : !! errorCodeInt ,
errors : ''
}
for ( var index = 0 ; index <= STATUS_AND_EVENT_LIST_FIELD . length ; index ++ ) {
var field = STATUS_AND_EVENT_LIST_FIELD [index];
if ( !! field) {
result[field] = index <= 3 ? parseInt (errorCodeBin[index]) : !! parseInt (errorCodeBin[index]);
var errorVal;
if ( !! result[field]) {
for ( var j = 0 ; j < ERROR_LIST_FIELD . length ; j ++ ) {
if ( field .toLowerCase () .includes ( ERROR_LIST_FIELD [j] .toLowerCase ())) {
errorVal = ERROR_LIST_FIELD [j];
result .errors += !! errorVal ? !! result .errors ? ', ' + errorVal : errorVal : '' ;
break ;
}
}
}
}
}
return result;
}
function decode (rowValue) {
var formattedValue = format (rowValue);
var addressAndHeaders = getAddressAndHeaders (formattedValue);
var deviceValues = getDeviceValues (formattedValue);
var statusAndEvents = getStatusAndEvents ( deviceValues .errorCodes)
return Object .assign ({} , addressAndHeaders , deviceValues , statusAndEvents);
}
return decode (data);
}