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