From c6b5f8d5092398f813b87ba98117e8548d31aa93 Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 18 May 2025 18:22:16 +0800 Subject: [PATCH 1/3] feat: add third party vendor watteco sensor tics'o --- vendors/watteco/devices.json | 17 + vendors/watteco/tics'o/tics'o-codec.json | 79 + vendors/watteco/tics'o/tics'o-decoder.js | 2058 ++++++++++++++++++++++ vendors/watteco/tics'o/tics'o-encoder.js | 4 + 4 files changed, 2158 insertions(+) create mode 100644 vendors/watteco/devices.json create mode 100644 vendors/watteco/tics'o/tics'o-codec.json create mode 100644 vendors/watteco/tics'o/tics'o-decoder.js create mode 100644 vendors/watteco/tics'o/tics'o-encoder.js diff --git a/vendors/watteco/devices.json b/vendors/watteco/devices.json new file mode 100644 index 0000000..47f44df --- /dev/null +++ b/vendors/watteco/devices.json @@ -0,0 +1,17 @@ +{ + "version": "1.0.0", + "devices": [ + { + "id": "tics'o", + "name": "TICS'O", + "description": "Transforms ENEDIS meter into LoRaWAN", + "catalog": "tics'o", + "sn": "", + "deveui": "", + "device_profile": ["ClassC-OTAA"], + "codec": "vendors/watteco/tics'o/tics'o-codec.json", + "decoder_script": "vendors/watteco/tics'o/tics'o-decoder.js", + "encoder_script": "vendors/watteco/tics'o/tics'o-encoder.js" + } + ] +} \ No newline at end of file diff --git a/vendors/watteco/tics'o/tics'o-codec.json b/vendors/watteco/tics'o/tics'o-codec.json new file mode 100644 index 0000000..4dd72f3 --- /dev/null +++ b/vendors/watteco/tics'o/tics'o-codec.json @@ -0,0 +1,79 @@ +{ + "version": "1.0.0", + "bytes": "110a00540000411300000001038000200f00000000000100000230", + "object": [ + { + "id": "ISOUSC", + "name": "Subscribed Current", + "value": "15", + "unit": "A", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "UINT8", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 3, + "bacnet_unit_type": "UNITS_AMPERES" + }, + { + "id": "IINST1", + "name": "Instantaneous Current Phase 1", + "value": "0", + "unit": "A", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "UINT16", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 3, + "bacnet_unit_type": "UNITS_AMPERES" + }, + { + "id": "IINST2", + "name": "Instantaneous Current Phase 2", + "value": "0", + "unit": "A", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "UINT16", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 3, + "bacnet_unit_type": "UNITS_AMPERES" + }, + { + "id": "IINST3", + "name": "Instantaneous Current Phase 3", + "value": "1", + "unit": "A", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "UINT16", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 3, + "bacnet_unit_type": "UNITS_AMPERES" + }, + { + "id": "PAPP", + "name": "Apparent Power", + "value": "560", + "unit": "VA", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "UINT32", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 8, + "bacnet_unit_type": "UNITS_VOLT_AMPERES" + }, + { + "id": "_TICFrameType", + "name": "TIC Frame Type", + "value": "CBE/Historique", + "unit": "", + "access_mode": "R", + "data_type": "TEXT", + "value_type": "STRING", + "max_length": 20, + "bacnet_type": "character_string_value_object", + "bacnet_unit_type_id": 95, + "bacnet_unit_type": "UNITS_NO_UNITS" + } + ] +} \ No newline at end of file diff --git a/vendors/watteco/tics'o/tics'o-decoder.js b/vendors/watteco/tics'o/tics'o-decoder.js new file mode 100644 index 0000000..1bfb5c1 --- /dev/null +++ b/vendors/watteco/tics'o/tics'o-decoder.js @@ -0,0 +1,2058 @@ +function UintToInt(Uint, Size) { + if (Size === 1) { + if ((Uint & 0x80) > 0) { + Uint = Uint - 0x100; + } + } + if (Size === 2) { + if ((Uint & 0x8000) > 0) { + Uint = Uint - 0x10000; + } + } + if (Size === 3) { + if ((Uint & 0x800000) > 0) { + Uint = Uint - 0x1000000; + } + } + if (Size === 4) { + if ((Uint & 0x80000000) > 0) { + Uint = Uint - 0x100000000; + } + } + + + return Uint; +} + +function Bytes2Float32(bytes) { + var sign = (bytes & 0x80000000) ? -1 : 1; + var exponent = ((bytes >> 23) & 0xFF) - 127; + var significand = (bytes & ~(-1 << 23)); + + if (exponent == 128) + return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY); + + if (exponent == -127) { + if (significand == 0) return sign * 0.0; + exponent = -126; + significand /= (1 << 23); + } else significand = (significand | (1 << 23)) / (1 << 23); + + return sign * significand * Math.pow(2, exponent); +} + +// ---------------------------------------------------------------- +// ----------------------- FUNCTIONS PART ------------------------- +// ---------------------------------------------------------------- + +/* +* Int conversion directly from buffer with start index and required endianess +* +* Type must be : U8,I8,U16,I16,U24,I24,U32,I32,U40,I40,...,U56,I56,I64 +* LittleEndian if true either big endian +*/ +function BytesToInt64(InBytes, StartIndex, Type,LittleEndian) +{ + if( typeof(LittleEndian) == 'undefined' ) LittleEndian = false; + +var Signed = (Type.substr(0,1) != "U"); +var BytesNb = parseInt(Type.substr(1,2), 10)/8; +var inc, start; +var nb = BytesNb; + +if (LittleEndian) +{ + inc = -1; + start = StartIndex + BytesNb - 1; +} +else +{ + inc = 1; start = StartIndex ; +} + +tmpInt64 = 0; +for (j=start; nb > 0;(j+=inc,nb--)) +{ + tmpInt64 = (tmpInt64 << 8) + InBytes[j]; +} + +if ((Signed) && (BytesNb < 8) && (InBytes[start] & 0x80)) + tmpInt64 = tmpInt64 - (0x01 << (BytesNb * 8)); + + return tmpInt64; +} + +/* +* Float32 conversion directly from buffer with start index and required endianess +* +* LittleEndian if true either big endian +*/ +function BytesToFloat32(InBytes,StartIndex,LittleEndian) { + +if( typeof(LittleEndian) == 'undefined' ) LittleEndian = false; + +var buf = InBytes.slice(StartIndex,StartIndex+4); +if (! LittleEndian) buf.reverse(); +var f32a = new Float32Array((new Int8Array(buf)).buffer); +return f32a[0]; +} + + +function decimalToHex(d, padding) { + var hex = Number(d).toString(16).toUpperCase(); + padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; + + while (hex.length < padding) { + hex = "0" + hex; + } + + return "0x" + hex; +} + +function parseHexString(str) { + var result = []; + while (str.length >= 2) { + result.push(parseInt(str.substring(0, 2), 16)); + + str = str.substring(2, str.length); + } + + return result; +} + +function byteToHex(b) { +var hexChar = ["0", "1", "2", "3", "4", "5", "6", "7","8", "9", "A", "B", "C", "D", "E", "F"]; +return hexChar[(b >> 4) & 0x0f] + hexChar[b & 0x0f]; +} + +function BytesToHexStr(buff) { +var hexOctets = []; + for (i = 0; i < buff.length; ++i) { + hexOctets.push( byteToHex(buff[i],2) ); +} + return hexOctets.join(""); +} + +function zeroPad(num, places) { +return( String(num).padStart(places, '0') ); +} + + + +/* +* =============================================================================== +* TIC specific part +* =============================================================================== +*/ + + +function TIC_Decode(ClusterID,AttributeID,BytesAfterSize) +{ +var data = {}; +// GENERIC ENUMs Management +//------------------------- +var E_DIV = + ["!?!", "*", "", + " ACTIF", "ACTIF", "CONSO", "CONTROLE", "DEP", "INACTIF", "PROD", "TEST", "kVA", "kW"]; +var E_PT = + ["!?!", "*", "", + " ? ", "000", "HC", "HCD", "HCE", "HCH", "HH", "HH ", "HP", "HP ", "HPD", "HPE", "HPH", "JA", "JA ", "P", "P ", "PM", "PM ", "XXX"]; +var E_CONTRAT = + ["!?!", "*", "", + "BT 4 SUP36", "BT 5 SUP36", "HTA 5 ", "HTA 8 ", + "TJ EJP ", "TJ EJP-HH ", "TJ EJP-PM ", "TJ EJP-SD ", "TJ LU ", + "TJ LU-CH ", "TJ LU-P ", "TJ LU-PH ", "TJ LU-SD ", "TJ MU ", + "TV A5 BASE", "TV A8 BASE", + "BASE","H PLEINE-CREUSE","HPHC","HC","HC et Week-End","EJP","PRODUCTEUR"]; +var E_STD_PT = + ["!?!", "*", "", + " ? ", + "000", "HC", "HCD", "HCE", "HCH", "HH", "HH ", "HP", "HP ", + "HPD", "HPE","HPH", "JA", "JA ", "P","P ", "PM", "PM ", "XXX", + "INDEX NON CONSO","BASE","HEURE CREUSE","HEURE PLEINE","HEURE NORMALE","HEURE POINTE", + "HC BLEU","BUHC","HP BLEU","BUHP","HC BLANC","BCHC","HP BLANC","BCHP", "HC ROUGE","RHC","HP ROUGE","RHP", + "HEURE WEEK-END" ]; +var E_STD_CONTRAT = + ["!?!", "*", "", + "BT 4 SUP36", "BT 5 SUP36", "HTA 5 ", "HTA 8 ", + "TJ EJP ", "TJ EJP-HH ", "TJ EJP-PM ", "TJ EJP-SD ", "TJ LU ", + "TJ LU-CH ", "TJ LU-P ", "TJ LU-PH ", "TJ LU-SD ", "TJ MU ", + "TV A5 BASE", "TV A8 BASE", + "BASE","H PLEINE-CREUSE","HPHC","HC","HC et Week-End","EJP","PRODUCTEUR" + /* Todo: Add necessary Enums when known */ + ]; + +function TICParseEnum(Bytes,i,Enums) { + var x = {}; + if ((Bytes[i] & 0x80) == 0) { // Really Enum + iEnum = Bytes[i] & 0x7F; + + // Palliatif Anomalie 3.5.0.4852 à 3.5.0.5339 (Cf http://support.nke-watteco.com/tic/) + // Ligne à commenter si le capteur PMEPMI a une version firmware différente de ci-dessus + iEnum++; + + x = Enums[iEnum]; i+=1; + } else { // NString + sz = Bytes[i] & 0x7F; i += 1; + if (sz > 0) { + x = String.fromCharCode.apply(null, Bytes.slice(i, i+sz)); i += sz; + } else { + x = ""; + } + } + return { x: x, i: i }; +} + +// DESCRIPTOR Parser +//------------------ +function TICParseDescToIndexes(DescIn) { + + var Indexes = []; + + var DescHeader = DescIn[0]; + var DescSize = (DescHeader & 0x1F); + if (DescSize == 0) { + DescSize = 8; // Historical fixed size Descriptor + } + IsVarIndexes = ((DescHeader & 0x20) != 0); + + if (IsVarIndexes) { + for (i=1; i < DescSize; i++) { + Indexes.push(DescIn[i]); + } + } else { + // is VarBitfields + iField = 0; + // TODO if historical: 7 LSbit of first byte should be used ... TODO + for (var i=DescSize; i > 1; i--) { + for (b = 0; b < 8; b++) { + if ((DescIn[i-1] >> b) & 0x01) { + Indexes.push(iField); + } + iField++; + } + } + } + + return { DescSize : DescSize, Indexes: Indexes }; + } + +function TICParseDMYhms(b,i) { + x = zeroPad(BytesToInt64(b,i,"U8"),2) + "/"+ zeroPad(BytesToInt64(b,i+1,"U8"),2) + "/"+ zeroPad(BytesToInt64(b,i+2,"U8"),2) + " " + + zeroPad(BytesToInt64(b,i+3,"U8"),2) + ":"+ zeroPad(BytesToInt64(b,i+4,"U8"),2) + ":"+ zeroPad(BytesToInt64(b,i+5,"U8"),2); + i+=6; + return { x: x, i: i }; +} + +function TICParseTimeStamp(b,i,LittleEndian) { + // EPOCH TIC: 01/01/2000 00:00:00 + // EPOCH UNIX: 01/01/1970 00:00:00 + ts = BytesToInt64(b,i,"U32",LittleEndian); i += 4; + ts += (new Date("2000/01/01 00:00:00").getTime()/1000) + ts += 3600; //TODO: find a way to beter manage this 1h shift due to TZ and DST of running computer + var a = new Date( ts * 1000); + var x = + zeroPad(a.getDate(),2) + '/' + zeroPad(a.getMonth(), 2) + '/' + a.getFullYear() + ' ' + + zeroPad(a.getHours(),2) + ':' + zeroPad(a.getMinutes(),2) + ':' + zeroPad(a.getSeconds(),2) ; + return { x: x, i: i };; +} + +function TICParseCString(b,i) { + eos = b.slice(i).indexOf(0); + x = String.fromCharCode.apply(null, b.slice(i, i + eos)); i += (eos + 1); + return { x: x, i: i }; +} + +function TICParseNString(b,i, n) { + x = String.fromCharCode.apply(null, b.slice(i, i+n)); i+=n; + return { x: x, i: i }; +} + + + +// --------------------------------------------------------- +// FIELD PARSING +function TYPE_EMPTY(b,i) { return {b:b,i:i}; } +function TYPE_CHAR(b,i) { + x = String.fromCharCode.apply(null, b.slice(0,1)); i+=1; + return { x: x, i: i }; +} +function TYPE_CSTRING(b,i) { return TICParseCString(b,i); } +function TYPE_U8(b,i) { x = BytesToInt64(b,i,"U8"); i+=1; return { x: x, i: i }; } +function TYPE_U16(b,i) { x = BytesToInt64(b,i,"U16"); i+=2; return { x: x, i: i }; } +function TYPE_I16(b,i) { x = BytesToInt64(b,i,"I16"); i+=2; return { x: x, i: i }; } +function TYPE_U24CSTRING(b,i) { + var x = {}; + x["Value"] = BytesToInt64(b,i,"U24"); i += 3; + s = TICParseCString(b,i); + x["Label"] = s.x; i = s.i; + return { x: x, i: i }; +}; +function TYPE_U24(b,i) { x = BytesToInt64(b,i,"U24"); i+=3; return { x: x, i: i }; } +function TYPE_4U24(b,i) { + var x = {}; + for (i=1;i<=4;i++) { x["Value_"+i] = BytesToInt64(b,i,"U24"); i += 3; } + return { x: x, i: i }; +}; +function TYPE_6U24(b,i) { + var x = {}; + for (i=1;i<=4;i++) { x["Value_"+i] = BytesToInt64(b,i,"U24"); i += 3; } + return { x: x, i: i }; +} +function TYPE_U32(b,i) { x = BytesToInt64(b,i,"U32"); i+=4; return { x: x, i: i }; } +function TYPE_FLOAT(b,i) { x = BytesToFloat32(b,i); i+=4; return { x: x, i: i }; } +function TYPE_DMYhms(b,i) { return TICParseDMYhms(b,i); } +function TYPE_tsDMYhms(b,i){ return TICParseTimeStamp(b,i); }; +function TYPE_DMYhmsCSTRING(b,i) { + var x = {}; + var d = TICParseDMYhms(b,i); x["Date"]=d.x; ; + var s = TICParseCString(b,d.i);x["Label"]=s.x; + i = s.i; + return { x: x, i: i };; +} +function TYPE_E_PT(b,i) { return TICParseEnum(b,i,E_PT); } +function TYPE_E_STD_PT(b,i) { return TICParseEnum(b,i,E_STD_PT); } +function TYPE_tsDMYhms_E_PT(b,i) { + var x = {}; + var d = TICParseTimeStamp(b,i); + var e = TICParseEnum(b,d.i,E_PT); + i = e.i; + return { x: x, i: i }; +} +function TYPE_hmDM(b,i) { + var x = {}; + h = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + m = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + D = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + M = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + x = D + "/" + M + " " + h + ":" + m; + return { x: x, i: i }; +} +function TYPE_DMh(b,i) { + var x = {}; + D = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + M = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + h = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + x = D + "/" + M + " " + h ; + return { x: x, i: i }; +} +function TYPE_hm(b,i) { + var x = {}; + h = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + m = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + x = h + ":" + m; + return { x: x, i: i }; +} +function TYPE_SDMYhms(b,i) { + var x = {}; + s = TICParseNString(b,i, 1); + d = TICParseDMYhms(b,s.i); + x["S"]=s.x; + x["Date"]=d.x; + i=d.i; + return { x: x, i: i }; +} +function TYPE_SDMYhmsU8(b,i) { + var x = {}; + s = TICParseNString(b,i, 1); + d = TICParseDMYhms(b,s.i); + n = BytesToInt64(b,i,"U8"); i = d.i + 1; + x["S"]=s.x; + x["Date"]=d.x; + x["Value"]=n; + return { x: x, i: i }; +} +function TYPE_SDMYhmsU16(b,i) { + var x = {}; + s = TICParseNString(b,i, 1); + d = TICParseDMYhms(b,s.i); + n = BytesToInt64(b,i,"U16"); i = d.i + 1; + x["S"]=s.x; + x["Date"]=d.x; + x["Value"]=n; + return { x: x, i: i }; +} +function TYPE_SDMYhmsU24(b,i) { + var x = {}; + s = TICParseNString(b,i, 1); + d = TICParseDMYhms(b,s.i); + n = BytesToInt64(b,i,"U24"); i = d.i + 1; + x["S"]=s.x; + x["Date"]=d.x; + x["Value"]=n; + return { x: x, i: i }; +} +function TYPE_BF32xbe(b,i) { + var x = BytesToHexStr(b.slice(i,2)); i+=4; + i+=4 + return { x: x, i: i }; +} /* Bitfield 32 bits heXa Big Endian */ +function TYPE_HEXSTRING(b,i) { + var x = BytesToHexStr(b.slice(i+1,i+1+b[i])); + i+=b[i]+1; + return { x: x, i: i }; +} +function TYPE_E_DIV(b,i) { return TICParseEnum(b,i,E_DIV); } +function TYPE_U24_E_DIV(b,i) { + var x = {}; + dd = BytesToInt64(b,i,"U24"); i += 3; + x.Value = dd; + e = TICParseEnum(b,i,E_DIV); + x.Label = e.x; i = e.i; + return { x: x, i: i }; +} +function TYPE_E_CONTRAT(b,i) { return TICParseEnum(b,i,E_CONTRAT); } +function TYPE_E_STD_CONTRAT(b,i) { return TICParseEnum(b,i,E_STD_CONTRAT); } +function TYPE_11hhmmSSSS(b,i) { + var x = [] + for (var j = 0 ; j < 11; j++) { + y = {}; + h = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + if (h == 0xFF) { + y["Status"] = "NONUTILE" + } else { + m = zeroPad(BytesToInt64(b,i,"U8"),2); i++; + s = BytesToHexStr(b.slice(i,2)); i++; + y["Time"] = h + ":" + m; + y["Status"] = s; + i+=b[i]+1; + } + x.push(y); + } + return { x: x, i: i }; +} /* New type for PJOURF+1 / PPOINTE of Linky. */ + /* 11 Blocs of 8 Bytes (hhmmSSSS) space separated values are compressed as follow */ + /* hh 1 byte Hour, mm 1 byte Minute, SSSS two bytes bitfield */ + /* Notes: */ + /* - Delta comparison: */ + /* hh and mm are usual for delta comparison */ + /* SSSS is compared as bitfield each bit set may trig an event if changed */ + /* - An unused field is defined as follow: */ + /* hh = 0xFF and No other bytes used in the binarized form */ + /* "NONUTILE" string in the TIC ASCII format */ +function TYPE_BF8d(b,i) { + x = BytesToInt64(b,i,"U8"); i++; + return { x: x, i: i }; +} /* Bitfield de 8 bit with TIC decimal representation (0 à 255) */ + + + +// --------------------------------------------------------- +// OUTPUT FORMATS +// TODO ... At the moment format are not used (Cf c language TIC decoder) +function FMT_UNDEF(x) { return(x); }; + +function FMT_s(x) { return(x); }; // %s +function FMT_PREAVIS_PT(x) { return(x); }; // TD-%s +function FMT_c(x) { return(x); }; // %c +function FMT_02X(x) { return(x); }; // %02x +function FMT_d(x) { return(x); }; // %d +function FMT_ld(x) { return(x); }; // %ld + +function FMT_02d(x) { return(x); }; // %02d +function FMT_03d(x) { return(x); }; // %03d +function FMT_05d(x) { return(x); }; // %05d +/* +function FMT_07d(x) { return(x); // %07d +function FMT_09d(x) { return(x); // %09d +*/ +function FMT_05ld(x) { return(x); }; // %05d +function FMT_06ld(x) { return(x); }; // %06d +function FMT_07ld(x) { return(x); }; // %07d +function FMT_09ld(x) { return(x); }; // %09d + +function FMT_d_percent(x) { return(x); }; // %d%% + +function FMT_d_s(x) { return(x); }; //%ds + +function FMT_d_kW(x) { return(x); }; // %dkW +function FMT_d_kvar(x) { return(x); }; // %dkvar + +function FMT_05d_kwh(x) { return(x); }; // %05ldkwh +function FMT_ld_Wh(x) { return(x); }; // %ldWh +function FMT_05ld_Wh(x) { return(x); }; // 05ldWh +function FMT_05ld_varh(x) { return(x); }; // %05ldvarh +function FMT_ld_varh(x) { return(x); }; // %ldvarh +function FMT_ld_VAh(x) { return(x); }; // %ldVAh + +function FMT_d_V(x) { return(x); }; // %dV + +function FMT_d_kWh(x) { return(x); }; // %dkWh +function FMT_ld_kWh(x) { return(x); }; // %07ldkWh +function FMT_d_kvarh(x) { return(x); }; // %dkvarh +function FMT_ld_kvarh(x) { return(x); }; // %07ldkvarh + +function FMT_05_2f(x) { return(x); }; // %05.2f" + +// ============================================ +// PROFILS DEFINITION +// ============================================ + +// ClusterID: 0x0053, Attribute ID : 0xii00 +//----------------------------------------- +var ICE_General = [ + ["CONTRAT", TYPE_CSTRING,0,FMT_s], + ["DATECOUR",TYPE_DMYhms,0,FMT_UNDEF], + ["DATE",TYPE_DMYhms,0,FMT_UNDEF], + ["EA", TYPE_U24,0,FMT_05ld_Wh], + ["ERP", TYPE_U24,0,FMT_05ld_varh], + ["PTCOUR", TYPE_CSTRING,0,FMT_s], + ["PREAVIS", TYPE_CSTRING,0,FMT_s], + ["MODE", TYPE_EMPTY,0,FMT_s], + // Byte 1 + ["DATEPA1", TYPE_DMYhms,0,FMT_UNDEF], + ["PA1", TYPE_U16,0,FMT_d_kW], + ["DATEPA2", TYPE_DMYhms,0,FMT_UNDEF], + ["PA2", TYPE_U16,0,FMT_d_kW], + ["DATEPA3", TYPE_DMYhms,0,FMT_UNDEF], + ["PA3", TYPE_U16,0,FMT_d_kW], + ["DATEPA4", TYPE_DMYhms,0,FMT_UNDEF], + ["PA4", TYPE_U16,0,FMT_d_kW], + // Byte 2 + ["DATEPA5", TYPE_DMYhms,0,FMT_UNDEF], + ["PA5", TYPE_U16,0,FMT_d_kW], + ["DATEPA6", TYPE_DMYhms,0,FMT_UNDEF], + ["PA6", TYPE_U16,0,FMT_d_kW], + ["*p*", TYPE_U24,0,FMT_05ld], + //["*p*", TYPE_U24,ATTRIBUTE_NOT_MANAGED_FIELD,FMT_05ld], + ["KDC", TYPE_U8,0,FMT_d_percent], + ["KDCD", TYPE_U8,0,FMT_d_percent], + ["TGPHI", TYPE_FLOAT,0,FMT_05_2f], + // Byte 3 + ["PSP", TYPE_U16,0,FMT_d_kW], + ["PSPM", TYPE_U16,0,FMT_d_kW], + ["PSHPH", TYPE_U16,0,FMT_d_kW], + ["PSHPD", TYPE_U16,0,FMT_d_kW], + ["PSHCH", TYPE_U16,0,FMT_d_kW], + ["PSHCD", TYPE_U16,0,FMT_d_kW], + ["PSHPE", TYPE_U16,0,FMT_d_kW], + ["PSHCE", TYPE_U16,0,FMT_d_kW], + // Byte 4 + ["PSJA", TYPE_U16,0,FMT_d_kW], + ["PSHH", TYPE_U16,0,FMT_d_kW], + ["PSHD", TYPE_U16,0,FMT_d_kW], + ["PSHM", TYPE_U16,0,FMT_d_kW], + ["PSDSM", TYPE_U16,0,FMT_d_kW], + ["PSSCM", TYPE_U16,0,FMT_d_kW], + ["MODE", TYPE_EMPTY,0,FMT_s], + ["PA1MN", TYPE_U16,0,FMT_d_kW], + // Byte 5 + ["PA10MN", TYPE_U16,0,FMT_d_kW], + ["PREA1MN", TYPE_I16,0,FMT_d_kvar], + ["PREA10MN",TYPE_I16,0,FMT_d_kvar], + ["TGPHI", TYPE_FLOAT,0,FMT_05_2f], + ["U10MN", TYPE_U16,0,FMT_d_V] +]; + +// ClusterID: 0x0053, Attribute ID : 0xii01 +//----------------------------------------- +var ICE_p = [ + //Byte 0 + ["DEBUTp", TYPE_DMYhms,0,FMT_UNDEF,0], + ["FINp", TYPE_DMYhms,0,FMT_UNDEF,6], + ["CAFp", TYPE_U16,0,FMT_05d,12], + + ["DATEEAp",TYPE_DMYhms,0,FMT_UNDEF,14], + ["EApP", TYPE_U24,0,FMT_ld_kWh,20], + ["EApPM", TYPE_U24,0,FMT_ld_kWh,23], + ["EApHCE", TYPE_U24,0,FMT_ld_kWh,26], + ["EApHCH", TYPE_U24,0,FMT_ld_kWh,29], + //Byte 1 + ["EApHH", TYPE_U24,0,FMT_ld_kWh,32], + ["EApHCD", TYPE_U24,0,FMT_ld_kWh,35], + ["EApHD", TYPE_U24,0,FMT_ld_kWh,38], + ["EApJA", TYPE_U24,0,FMT_ld_kWh,41], + ["EApHPE", TYPE_U24,0,FMT_ld_kWh,44], + ["EApHPH", TYPE_U24,0,FMT_ld_kWh,47], + ["EApHPD", TYPE_U24,0,FMT_ld_kWh,50], + ["EApSCM", TYPE_U24,0,FMT_ld_kWh,53], + // Byte 2 + ["EApHM", TYPE_U24,0,FMT_ld_kWh,56], + ["EApDSM", TYPE_U24,0,FMT_ld_kWh,59], + + ["DATEERPp",TYPE_DMYhms,0,FMT_UNDEF,62], + ["ERPpP", TYPE_U24,0,FMT_ld_kvarh,68], + ["ERPpPM", TYPE_U24,0,FMT_ld_kvarh,71], + ["ERPpHCE", TYPE_U24,0,FMT_ld_kvarh,74], + ["ERPpHCH", TYPE_U24,0,FMT_ld_kvarh,77], + ["ERPpHH", TYPE_U24,0,FMT_ld_kvarh,80], + // Byte 3 + ["ERPpHCD", TYPE_U24,0,FMT_ld_kvarh,83], + ["ERPpHD", TYPE_U24,0,FMT_ld_kvarh,86], + ["ERPpJA", TYPE_U24,0,FMT_ld_kvarh,89], + ["ERPpHPE", TYPE_U24,0,FMT_ld_kvarh,92], + ["ERPpHPH", TYPE_U24,0,FMT_ld_kvarh,95], + ["ERPpHPD", TYPE_U24,0,FMT_ld_kvarh,98], + ["ERPpSCM", TYPE_U24,0,FMT_ld_kvarh,101], + ["ERPpHM", TYPE_U24,0,FMT_ld_kvarh,104], + // Byte 4 + ["ERPpDSM", TYPE_U24,0,FMT_ld_kvarh,107], + + ["DATEERNp",TYPE_DMYhms,0,FMT_UNDEF,110], + ["ERNpP", TYPE_U24,0,FMT_ld_kvarh,116], + ["ERNpPM", TYPE_U24,0,FMT_ld_kvarh,119], + ["ERNpHCE", TYPE_U24,0,FMT_ld_kvarh,122], + ["ERNpHCH", TYPE_U24,0,FMT_ld_kvarh,125], + ["ERNpHH", TYPE_U24,0,FMT_ld_kvarh,128], + ["ERNpHCD", TYPE_U24,0,FMT_ld_kvarh,131], + // Byte 5 + ["ERNpHD", TYPE_U24,0,FMT_ld_kvarh,134], + ["ERNpJA", TYPE_U24,0,FMT_ld_kvarh,137], + ["ERNpHPE", TYPE_U24,0,FMT_ld_kvarh,140], + ["ERNpHPH", TYPE_U24,0,FMT_ld_kvarh,143], + ["ERNpHPD", TYPE_U24,0,FMT_ld_kvarh,146], + ["ERNpSCM", TYPE_U24,0,FMT_ld_kvarh,149], + ["ERNpHM", TYPE_U24,0,FMT_ld_kvarh,152], + ["ERNpDSM", TYPE_U24,0,FMT_ld_kvarh,155] + // Byte 6 +]; + +// ClusterID: 0x0053, Attribute ID : 0xii02 +//----------------------------------------- +var ICE_p1 = [ + //Byte 0 + ["DEBUTp1", TYPE_DMYhms,0,FMT_UNDEF,0], + ["FINp1", TYPE_DMYhms,0,FMT_UNDEF,6], + ["CAFp1", TYPE_U16,0,FMT_05d,12], + + ["DATEEAp1",TYPE_DMYhms,0,FMT_UNDEF,14], + ["EAp1P", TYPE_U24,0,FMT_ld_kWh,20], + ["EAp1PM", TYPE_U24,0,FMT_ld_kWh,23], + ["EAp1HCE", TYPE_U24,0,FMT_ld_kWh,26], + ["EAp1HCH", TYPE_U24,0,FMT_ld_kWh,29], + //Byte 1 + ["EAp1HH", TYPE_U24,0,FMT_ld_kWh,32], + ["EAp1HCD", TYPE_U24,0,FMT_ld_kWh,35], + ["EAp1HD", TYPE_U24,0,FMT_ld_kWh,38], + ["EAp1JA", TYPE_U24,0,FMT_ld_kWh,41], + ["EAp1HPE", TYPE_U24,0,FMT_ld_kWh,44], + ["EAp1HPH", TYPE_U24,0,FMT_ld_kWh,47], + ["EAp1HPD", TYPE_U24,0,FMT_ld_kWh,50], + ["EAp1SCM", TYPE_U24,0,FMT_ld_kWh,53], + // Byte 2 + ["EAp1HM", TYPE_U24,0,FMT_ld_kWh,56], + ["EAp1DSM", TYPE_U24,0,FMT_ld_kWh,59], + + ["DATEERPp1",TYPE_DMYhms,0,FMT_UNDEF,62], + ["ERPp1P", TYPE_U24,0,FMT_ld_kvarh,68], + ["ERPp1PM", TYPE_U24,0,FMT_ld_kvarh,71], + ["ERPp1HCE",TYPE_U24,0,FMT_ld_kvarh,74], + ["ERPp1HCH",TYPE_U24,0,FMT_ld_kvarh,77], + ["ERPp1HH", TYPE_U24,0,FMT_ld_kvarh,80], + // Byte 3 + ["ERPp1HCD",TYPE_U24,0,FMT_ld_kvarh,83], + ["ERPp1HD", TYPE_U24,0,FMT_ld_kvarh,86], + ["ERPp1JA", TYPE_U24,0,FMT_ld_kvarh,89], + ["ERPp1HPE",TYPE_U24,0,FMT_ld_kvarh,92], + ["ERPp1HPH",TYPE_U24,0,FMT_ld_kvarh,95], + ["ERPp1HPD",TYPE_U24,0,FMT_ld_kvarh,98], + ["ERPp1SCM",TYPE_U24,0,FMT_ld_kvarh,101], + ["ERPp1HM", TYPE_U24,0,FMT_ld_kvarh,104], + // Byte 4 + ["ERPp1DSM",TYPE_U24,0,FMT_ld_kvarh,107], + + ["DATEERNp1",TYPE_DMYhms,0,FMT_UNDEF,110], + ["ERNp1P", TYPE_U24,0,FMT_ld_kvarh,116], + ["ERNp1PM", TYPE_U24,0,FMT_ld_kvarh,119], + ["ERNp1HCE",TYPE_U24,0,FMT_ld_kvarh,122], + ["ERNp1HCH",TYPE_U24,0,FMT_ld_kvarh,125], + ["ERNp1HH", TYPE_U24,0,FMT_ld_kvarh,128], + ["ERNp1HCD",TYPE_U24,0,FMT_ld_kvarh,131], + // Byte 5 + ["ERNp1HD", TYPE_U24,0,FMT_ld_kvarh,134], + ["ERNp1JA", TYPE_U24,0,FMT_ld_kvarh,137], + ["ERNp1HPE",TYPE_U24,0,FMT_ld_kvarh,140], + ["ERNp1HPH",TYPE_U24,0,FMT_ld_kvarh,143], + ["ERNp1HPD",TYPE_U24,0,FMT_ld_kvarh,146], + ["ERNp1SCM",TYPE_U24,0,FMT_ld_kvarh,149], + ["ERNp1HM", TYPE_U24,0,FMT_ld_kvarh,152], + ["ERNp1DSM",TYPE_U24,0,FMT_ld_kvarh,155] + // Byte 6 +]; + + +// ClusterID: 0x0054, Attribute ID : 0xii00 +//----------------------------------------- +var CBE = [ + // Byte 0 + ["ADIR1", TYPE_U16,0,FMT_03d], + ["ADIR2", TYPE_U16,0,FMT_03d], + ["ADIR3", TYPE_U16,0,FMT_03d], + ["ADCO", TYPE_CSTRING,0,FMT_s], + ["OPTARIF", TYPE_CSTRING,0,FMT_s], + ["ISOUSC", TYPE_U8,0,FMT_02d], + ["BASE", TYPE_U32,0,FMT_09ld], + ["HCHC", TYPE_U32,0,FMT_09ld], + // Byte 1 + ["HCHP", TYPE_U32,0,FMT_09ld], + ["EJPHN", TYPE_U32,0,FMT_09ld], + ["EJPHPM", TYPE_U32,0,FMT_09ld], + ["BBRHCJB", TYPE_U32,0,FMT_09ld], + ["BBRHPJB", TYPE_U32,0,FMT_09ld], + ["BBRHCJW", TYPE_U32,0,FMT_09ld], + ["BBRHPJW", TYPE_U32,0,FMT_09ld], + ["BBRHCJR", TYPE_U32,0,FMT_09ld], + // Byte 2 + ["BBRHPJR", TYPE_U32,0,FMT_09ld], + ["PEJP", TYPE_U8,0,FMT_02d], + ["GAZ", TYPE_U32,0,FMT_07ld], + ["AUTRE", TYPE_U32,0,FMT_07ld], + ["PTEC", TYPE_CSTRING,0,FMT_s], + ["DEMAIN", TYPE_CSTRING,0,FMT_s], + ["IINST", TYPE_U16,0,FMT_03d], + ["IINST1", TYPE_U16,0,FMT_03d], + // Byte 3 + ["IINST2", TYPE_U16,0,FMT_03d], + ["IINST3", TYPE_U16,0,FMT_03d], + ["ADPS", TYPE_U16,0,FMT_03d], + ["IMAX", TYPE_U16,0,FMT_03d], + ["IMAX1", TYPE_U16,0,FMT_03d], + ["IMAX2", TYPE_U16,0,FMT_03d], + ["IMAX3", TYPE_U16,0,FMT_03d], + ["PMAX", TYPE_U32,0,FMT_05ld], + // Byte 4 + ["PAPP", TYPE_U32,0,FMT_05ld], + ["HHPHC", TYPE_CHAR,0,FMT_c], + ["MOTDETAT",TYPE_CSTRING,0,FMT_s], + ["PPOT", TYPE_U8,0,FMT_02X] +]; + + +// ClusterID: 0x0055, Attribute ID : 0xii00 +//----------------------------------------- +var CJE = [ + // Byte 0 + ["JAUNE", TYPE_hmDM,0,FMT_UNDEF], // [hh:mn:jj:mm]:pt:dp:abcde:kp + ["JAUNE", TYPE_CSTRING,0,FMT_s], // pt + ["JAUNE", TYPE_CSTRING,0,FMT_s], // dp + ["JAUNE", TYPE_U24,0,FMT_05ld], // abcde + ["JAUNE", TYPE_U8,0,FMT_02d], // kp + ["ENERG", TYPE_6U24,0,FMT_06ld], // 111111:222222:...:666666 + ["ENERG", TYPE_U24,0,FMT_06ld], // 222222 + ["ENERG", TYPE_U24,0,FMT_06ld], // 333333 + // Byte 1 + ["ENERG", TYPE_U24,0,FMT_06ld], // 444444 + ["ENERG", TYPE_U24,0,FMT_06ld], // 555555 + ["ENERG", TYPE_U24,0,FMT_06ld], // 666666 + ["PERCC", TYPE_DMh,0,FMT_UNDEF], // jj:mm:hh[:cg] + ["PERCC", TYPE_U8,0,FMT_02d], // cg + ["PMAXC", TYPE_4U24,0,FMT_05ld], // 11111:22222:...:44444 + ["PMAXC", TYPE_U24,0,FMT_05ld], // 22222 + ["PMAXC", TYPE_U24,0,FMT_05ld], // 33333 + // Byte 2 + ["PMAXC", TYPE_U24,0,FMT_05ld], // 44444 + ["TDEPA", TYPE_4U24,0,FMT_05ld], // 11111:22222:...:44444 + ["TDEPA", TYPE_U24,0,FMT_05ld], // 22222 + ["TDEPA", TYPE_U24,0,FMT_05ld], // 33333 + ["TDEPA", TYPE_U24,0,FMT_05ld], // 44444 + ["PERCP", TYPE_DMh,0,FMT_UNDEF], // [jj:mm:hh]:cg + ["PERCP", TYPE_U8,0,FMT_02d], // cg + ["PMAXP", TYPE_4U24,0,FMT_05ld], // 11111:22222:...:44444 + // Byte 3 + ["PMAXP", TYPE_U24,0,FMT_05ld], // 22222 + ["PMAXP", TYPE_U24,0,FMT_05ld], // 33333 + ["PMAXP", TYPE_U24,0,FMT_05ld], // 44444 + ["PSOUSC", TYPE_4U24,0,FMT_05ld], // 11111:22222:...:44444 + ["PSOUSC", TYPE_U24,0,FMT_05ld], // 22222 + ["PSOUSC", TYPE_U24,0,FMT_05ld], // 33333 + ["PSOUSC", TYPE_U24,0,FMT_05ld], // 44444 + ["PSOUSP", TYPE_4U24,0,FMT_05ld], // 11111:22222:...:44444 + // Byte 4 + ["PSOUSP", TYPE_U24,0,FMT_05ld], // 22222 + ["PSOUSP", TYPE_U24,0,FMT_05ld], // 33333 + ["PSOUSP", TYPE_U24,0,FMT_05ld], // 44444 + ["FCOU", TYPE_hm,0,FMT_UNDEF], // [hh:mn]:dd + ["FCOU", TYPE_U8,0,FMT_02d] // dd +]; + + +// ClusterID: 0x0056, Attribute ID : 0xii00 +//----------------------------------------- +var STD = [ + // Byte 0 + ["ADSC", TYPE_CSTRING,0,FMT_s], + ["VTIC", TYPE_U8,0,FMT_02d], + ["DATE", TYPE_SDMYhms,0,FMT_UNDEF], + ["NGTF", TYPE_E_STD_CONTRAT,0,FMT_s], + ["LTARF", TYPE_E_STD_PT,0,FMT_s], + ["EAST", TYPE_U32,0,FMT_09ld], + ["EASF01", TYPE_U32,0,FMT_09ld], + ["EASF02", TYPE_U32,0,FMT_09ld], + // Byte 1 + ["EASF03", TYPE_U32,0,FMT_09ld], + ["EASF04", TYPE_U32,0,FMT_09ld], + ["EASF05", TYPE_U32,0,FMT_09ld], + ["EASF06", TYPE_U32,0,FMT_09ld], + ["EASF07", TYPE_U32,0,FMT_09ld], + ["EASF08", TYPE_U32,0,FMT_09ld], + ["EASF09", TYPE_U32,0,FMT_09ld], + ["EASF10", TYPE_U32,0,FMT_09ld], + // Byte 2 + ["EASD01", TYPE_U32,0,FMT_09ld], + ["EASD02", TYPE_U32,0,FMT_09ld], + ["EASD03", TYPE_U32,0,FMT_09ld], + ["EASD04", TYPE_U32,0,FMT_09ld], + ["EAIT", TYPE_U32,0,FMT_09ld], + ["ERQ1", TYPE_U32,0,FMT_09ld], + ["ERQ2", TYPE_U32,0,FMT_09ld], + ["ERQ3", TYPE_U32,0,FMT_09ld], + // Byte 3 + ["ERQ4", TYPE_U32,0,FMT_09ld], + ["IRMS1", TYPE_U16,0,FMT_03d], + ["IRMS2", TYPE_U16,0,FMT_03d], + ["IRMS3", TYPE_U16,0,FMT_03d], + ["URMS1", TYPE_U16,0,FMT_03d], + ["URMS2", TYPE_U16,0,FMT_03d], + ["URMS3", TYPE_U16,0,FMT_03d], + ["PREF", TYPE_U8,0,FMT_02d], + // Byte 4 + ["PCOUP", TYPE_U8,0,FMT_02d], + ["SINSTS", TYPE_U24,0,FMT_05ld], + ["SINSTS1", TYPE_U24,0,FMT_05ld], + ["SINSTS2", TYPE_U24,0,FMT_05ld], + ["SINSTS3", TYPE_U24,0,FMT_05ld], + ["SMAXSN", TYPE_SDMYhmsU24,0,FMT_05ld], + ["SMAXSN1", TYPE_SDMYhmsU24,0,FMT_05ld], + ["SMAXSN2", TYPE_SDMYhmsU24,0,FMT_05ld], + // Byte 5 + ["SMAXSN3", TYPE_SDMYhmsU24,0,FMT_05ld], + ["SMAXSN?1", TYPE_SDMYhmsU24,0,FMT_05ld], + ["SMAXSN1?1",TYPE_SDMYhmsU24,0,FMT_05ld], + ["SMAXSN2?1",TYPE_SDMYhmsU24,0,FMT_05ld], + ["SMAXSN3?1",TYPE_SDMYhmsU24,0,FMT_05ld], + ["SINSTI", TYPE_U24,0,FMT_05ld], + ["SMAXIN", TYPE_SDMYhmsU24,0,FMT_05ld], + ["SMAXIN-1",TYPE_SDMYhmsU24,0,FMT_05ld], + // Byte 6 + ["CCASN", TYPE_SDMYhmsU24,0,FMT_05ld], + ["CCASN?1", TYPE_SDMYhmsU24,0,FMT_05ld], + ["CCAIN", TYPE_SDMYhmsU24,0,FMT_05ld], + ["CCAIN?1", TYPE_SDMYhmsU24,0,FMT_05ld], + ["UMOY1", TYPE_SDMYhmsU16,0,FMT_03d], + ["UMOY2", TYPE_SDMYhmsU16,0,FMT_03d], + ["UMOY3", TYPE_SDMYhmsU16,0,FMT_03d], + ["STGE", TYPE_BF32xbe,0,FMT_UNDEF], + // Byte 7 + ["DPM1", TYPE_SDMYhmsU8,0,FMT_02d], + ["FPM1", TYPE_SDMYhmsU8,0,FMT_02d], + ["DPM2", TYPE_SDMYhmsU8,0,FMT_02d], + ["FPM2", TYPE_SDMYhmsU8,0,FMT_02d], + ["DPM3", TYPE_SDMYhmsU8,0,FMT_02d], + ["FPM3", TYPE_SDMYhmsU8,0,FMT_02d], + ["MSG1", TYPE_CSTRING,0,FMT_s], + ["MSG2", TYPE_CSTRING,0,FMT_s], + // Byte 8 + ["PRM", TYPE_CSTRING,0,FMT_s ], + ["RELAIS", TYPE_BF8d,0,FMT_03d ], + ["NTARF", TYPE_U8,0,FMT_02d ], + ["NJOURF", TYPE_U8,0,FMT_02d ], + ["NJOURF+1",TYPE_U8,0,FMT_02d ], + ["PJOURF+1",TYPE_11hhmmSSSS,0,FMT_UNDEF ], + ["PPOINTE", TYPE_11hhmmSSSS,0,FMT_UNDEF ] +]; + +// ClusterID: 0x0057, Attribute ID : 0xii00 +//----------------------------------------- +var PMEPMI = [ + //Byte 0 + ["TRAME", TYPE_E_DIV,0,FMT_s], /* Uniquement Palier 2013 */ + ["ADS", TYPE_HEXSTRING,0,FMT_UNDEF], /* Uniquement Palier 2013 */ + ["MESURES1",TYPE_E_CONTRAT,0,FMT_s], + ["DATE", TYPE_DMYhms,0,FMT_UNDEF], + ["EA_s", TYPE_U24,0,FMT_ld_Wh], + ["ER+_s", TYPE_U24,0,FMT_ld_varh], + ["ER-_s", TYPE_U24,0,FMT_ld_varh], + ["EAPP_s", TYPE_U24,0,FMT_ld_VAh], + //Byte 1 + ["EA_i", TYPE_U24,0,FMT_ld_Wh], + ["ER+_i", TYPE_U24,0,FMT_ld_varh], + ["ER-_i", TYPE_U24,0,FMT_ld_varh], + ["EAPP_i", TYPE_U24,0,FMT_ld_VAh], + ["PTCOUR1", TYPE_E_PT,0,FMT_s], + ["TARIFDYN",TYPE_E_DIV,0,FMT_s], + ["ETATDYN1",TYPE_E_PT,0,FMT_s], + ["PREAVIS1",TYPE_E_PT,0,FMT_PREAVIS_PT], + //Byte 2 + ["TDYN1CD", TYPE_tsDMYhms_E_PT,0,FMT_UNDEF], + ["TDYN1CF", TYPE_tsDMYhms_E_PT,0,FMT_UNDEF], + ["TDYN1FD", TYPE_tsDMYhms_E_PT,0,FMT_UNDEF], + ["TDYN1FF", TYPE_tsDMYhms_E_PT,0,FMT_UNDEF], + ["MODE", TYPE_E_DIV,0,FMT_s], + ["CONFIG", TYPE_E_DIV,0,FMT_s], + ["DATEPA1", TYPE_DMYhms,0,FMT_UNDEF], + ["PA1_s", TYPE_U16,0,FMT_d_kW], + // Byte 3 + ["PA1_i", TYPE_U16,0,FMT_d_kW], + ["DATEPA2", TYPE_tsDMYhms,0,FMT_UNDEF], + ["PA2_s", TYPE_U16,0,FMT_d_kW], + ["PA2_i", TYPE_U16,0,FMT_d_kW], + ["DATEPA3", TYPE_tsDMYhms,0,FMT_UNDEF], + ["PA3_s", TYPE_U16,0,FMT_d_kW], + ["PA3_i", TYPE_U16,0,FMT_d_kW], + ["DATEPA4", TYPE_tsDMYhms,0,FMT_UNDEF], + //Byte 4 + ["PA4_s", TYPE_U16,0,FMT_d_kW], + ["PA4_i", TYPE_U16,0,FMT_d_kW], + ["DATEPA5", TYPE_tsDMYhms,0,FMT_UNDEF], + ["PA5_s", TYPE_U16,0,FMT_d_kW], + ["PA5_i", TYPE_U16,0,FMT_d_kW], + ["DATEPA6", TYPE_tsDMYhms,0,FMT_UNDEF], + ["PA6_s", TYPE_U16,0,FMT_d_kW], + ["PA6_i", TYPE_U16,0,FMT_d_kW], + //Byte 5 + ["DebP", TYPE_tsDMYhms,0,FMT_UNDEF], + ["EAP_s", TYPE_U24,0,FMT_d_kWh], + ["EAP_i", TYPE_U24,0,FMT_d_kWh], + ["ER+P_s", TYPE_U24,0,FMT_d_kvarh], + ["ER-P_s", TYPE_U24,0,FMT_d_kvarh], + ["ER+P_i", TYPE_U24,0,FMT_d_kvarh], + ["ER-P_i", TYPE_U24,0,FMT_d_kvarh], + ["DebP-1", TYPE_tsDMYhms,0,FMT_UNDEF], + //Byte 6 + ["FinP-1", TYPE_tsDMYhms,0,FMT_UNDEF], + ["EaP-1_s", TYPE_U24,0,FMT_d_kWh], + ["EaP-1_i", TYPE_U24,0,FMT_d_kWh], + ["ER+P-1_s",TYPE_U24,0,FMT_d_kvarh], + ["ER-P-1_s",TYPE_U24,0,FMT_d_kvarh], + ["ER+P-1_i",TYPE_U24,0,FMT_d_kvarh], + ["ER-P-1_i",TYPE_U24,0,FMT_d_kvarh], + ["PS", TYPE_U24_E_DIV,0,FMT_UNDEF], + //Byte 7 + ["PREAVIS", TYPE_E_DIV,0,FMT_s], + ["PA1MN", TYPE_U16,0,FMT_d_kW], + ["PMAX_s", TYPE_U24_E_DIV,0,FMT_UNDEF], + ["PMAX_i", TYPE_U24_E_DIV,0,FMT_UNDEF], + ["TGPHI_s", TYPE_FLOAT,0,FMT_05_2f], + ["TGPHI_i", TYPE_FLOAT,0,FMT_05_2f], + ["MESURES2",TYPE_E_CONTRAT,0,FMT_s], + ["PTCOUR2", TYPE_E_PT,0,FMT_s], + //Byte 8 + ["ETATDYN2",TYPE_E_PT,0,FMT_s], + ["PREAVIS2",TYPE_E_PT,0,FMT_PREAVIS_PT], + ["TDYN2CD", TYPE_tsDMYhms_E_PT,0,FMT_UNDEF], + ["TDYN2CF", TYPE_tsDMYhms_E_PT,0,FMT_UNDEF], + ["TDYN2FD", TYPE_tsDMYhms_E_PT,0,FMT_UNDEF], + ["TDYN2FF", TYPE_tsDMYhms_E_PT,0,FMT_UNDEF], + ["DebP_2", TYPE_tsDMYhms,0,FMT_UNDEF], + ["EaP_s2", TYPE_U24,0,FMT_d_kWh], + //Byte 9 + ["DebP-1_2",TYPE_tsDMYhms,0,FMT_UNDEF], + ["FinP-1_2",TYPE_tsDMYhms,0,FMT_UNDEF], + ["EaP-1_s2",TYPE_U24,0,FMT_d_kWh], + ["_DDMES1_",TYPE_U24,0,FMT_d_s] +]; + + +// ============================================ +// ============================================ +// DECODING PART +// ============================================ +// ============================================ + +// Init object container for decoded fields +data = [] + +// Select PROFIL according to cluster/attribute +if (ClusterID == 0x0053) { + if (attributeID & 0x00FF == 0) { + profil = ICE_General; + data["_TICFrameType"]="ICE Generale"; + } else if (attributeID & 0x00FF == 1) { + profil = ICE_p; + data["_TICFrameType"]="ICE Periode P"; + } else if (attributeID & 0x0001 == 2) { + profil = ICE_p1; + data["_TICFrameType"]="ICE Periode P moins 1"; + } else { + return data; + } +} else if (ClusterID == 0x0054) { + profil = CBE; + data["_TICFrameType"]="CBE/Historique"; +} else if (ClusterID == 0x0055) { + profil = CJE; + data["_TICFrameType"]="CJE"; +} else if (ClusterID == 0x0056) { + profil = STD; + data["_TICFrameType"]="Standard"; +} else if (ClusterID == 0x0057) { + profil = PMEPMI; + data["_TICFrameType"]="PMEPMI"; +} else { + return data; + data["_TICFrameType"]="Unexpected"; +} + +// Start Decoding descriptor + var result = TICParseDescToIndexes(BytesAfterSize); + var DescSize = result.DescSize; + var Indexes = result.Indexes; + +var DescBytes = BytesAfterSize.slice(0,DescSize); +var x = {} +if ((DescBytes[0] & 0x80) == 0x80) { + x.Obsolete = true; +} +x.Bytes = BytesToHexStr(DescBytes); +x.Indexes = Indexes; +data["_Descriptor"]= x; + +// Start effective fields decodings +var bytesIndex = DescSize; +for (var j=0; j> 5) | ((bytes[0] & 0x06) << 2); + //command ID + cmdID = bytes[1]; + decoded.zclheader.cmdID = decimalToHex(cmdID, 2); + //Cluster ID + clusterdID = bytes[2] * 256 + bytes[3]; + decoded.zclheader.clusterdID = decimalToHex(clusterdID, 4); + + // decode report and read atrtribut response + if ((cmdID === 0x0a) | (cmdID === 0x8a) | (cmdID === 0x01)) { + //Attribut ID + attributID = bytes[4] * 256 + bytes[5]; + decoded.zclheader.attributID = decimalToHex(attributID, 4); + + if (cmdID === 0x8a) decoded.zclheader.alarm = 1; + //data index start + if ((cmdID === 0x0a) | (cmdID === 0x8a)) { + decoded.zclheader.attribut_type = bytes[6]; + index = 7; + } + if (cmdID === 0x01) { + decoded.zclheader.status = bytes[6]; + decoded.zclheader.attribut_type = bytes[7]; + index = 8; + } + + //temperature + if ((clusterdID === 0x0402) & (attributID === 0x0000)) + decoded.temperature = (UintToInt(bytes[index] * 256 + bytes[index + 1], 2)) / 100; + //humidity + if ((clusterdID === 0x0405) & (attributID === 0x0000)) + decoded.humidity = (bytes[index] * 256 + bytes[index + 1]) / 100; + //binary input counter + if ((clusterdID === 0x000f) & (attributID === 0x0402)) + decoded.counter = + bytes[index] * 256 * 256 * 256 + + bytes[index + 1] * 256 * 256 + + bytes[index + 2] * 256 + + bytes[index + 3]; + // binary input present value + if ((clusterdID === 0x000f) & (attributID === 0x0055)) + decoded.pin_state = !(!bytes[index]); + //multistate output + if ((clusterdID === 0x0013) & (attributID === 0x0055)) + decoded.value = bytes[index]; + // on/off present value + if ((clusterdID === 0x0006) & (attributID === 0x0000)) { + state = bytes[index]; + if (state === 1) decoded.state = "ON"; + else decoded.state = "OFF"; + } + //differential pressure + if ((clusterdID === 0x8008) & (attributID === 0x0000)) + decoded.differential_pressure = bytes[index] * 256 + bytes[index + 1]; + // multibinary input present value + if ((clusterdID === 0x8005) & (attributID === 0x0000)) { + decoded.pin_state_1 = (bytes[index + 1] & 0x01) === 0x01; + decoded.pin_state_2 = (bytes[index + 1] & 0x02) === 0x02; + decoded.pin_state_3 = (bytes[index + 1] & 0x04) === 0x04; + decoded.pin_state_4 = (bytes[index + 1] & 0x08) === 0x08; + decoded.pin_state_5 = (bytes[index + 1] & 0x10) === 0x10; + decoded.pin_state_6 = (bytes[index + 1] & 0x20) === 0x20; + decoded.pin_state_7 = (bytes[index + 1] & 0x40) === 0x40; + decoded.pin_state_8 = (bytes[index + 1] & 0x80) === 0x80; + decoded.pin_state_9 = (bytes[index] & 0x01) === 0x01; + decoded.pin_state_10 = (bytes[index] & 0x02) === 0x02; + } + // Number + if ((clusterdID === 0x800E) & (attributID === 0x0000)) { + switch (decoded.zclheader.attribut_type) { + // UInt 8/16/24/32 + case 0x20: + decoded.UInt8 = bytes[index]; + break; + case 0x21: + decoded.UInt16 = bytes[index] * 256 + bytes[index + 1]; + break; + case 0x22: + decoded.UInt24 = + bytes[index] * 256 * 256 + bytes[index + 1] * 256 + bytes[index + 2]; + break; + case 0x23: + decoded.UInt32 = + bytes[index] * 256 * 256 * 256 + + bytes[index + 1] * 256 * 256 + + bytes[index + 2] * 256 + + bytes[index + 3]; + break; + + // Int 8/16/24/32 + case 0x28: + decoded.UInt8 = UintToInt(bytes[index], 1); + break; + case 0x29: + decoded.UInt16 = UintToInt(bytes[index] * 256 + bytes[index + 1], 2); + break; + case 0x2a: + decoded.UInt24 = UintToInt( + bytes[index] * 256 * 256 + bytes[index + 1] * 256 + bytes[index + 2], + 3 + ); + break; + case 0x2b: + decoded.UInt32 = UintToInt( + bytes[index] * 256 * 256 * 256 + + bytes[index + 1] * 256 * 256 + + bytes[index + 2] * 256 + + bytes[index + 3], + 4 + ); + break; + + // Float + case 0x39: + decoded.Float = Bytes2Float32( + bytes[index] * 256 * 256 * 256 + + bytes[index + 1] * 256 * 256 + + bytes[index + 2] * 256 + + bytes[index + 3] + ); + break; + + default: + decoded.value = NaN; + } + } + //analog input + if (clusterdID === 0x000c) { + if (attributID === 0x0055) { + decoded.analog = Bytes2Float32( + bytes[index] * 256 * 256 * 256 + + bytes[index + 1] * 256 * 256 + + bytes[index + 2] * 256 + + bytes[index + 3] + ); + } + if (attributID === 0x8003) { + decoded.power_duration = bytes[index] * 256 + bytes[index + 1]; + } + if (attributID === 0x8004) { + o = (decoded.chock_parameters = {}); + + tmp = (bytes[index] & 0xc0) >> 6; + o.mode = tmp == 0 ? "Idle" : tmp == 1 ? "Chock" : tmp == 2 ? "Click" : "Undef"; + + tmp = (bytes[index] & 0x3c) >> 2; + freqs = [0, 1, 10, 25, 50, 100, 200, 400, 1620, 5376]; + o.sampling_frequency_hz = freqs[tmp]; + + tmp = bytes[index] & 0x03; + range_lbl = ["+/-2g", "+/-4g", "+/-8g", "+/-16g"]; + resol = [16, 32, 62, 186]; + o.range = range_lbl[tmp]; + + tmp2 = bytes[index + 1] & 0x7f; + o.threshold_mg = tmp2 * resol[tmp]; + } + } + + //modbus + if ((clusterdID === 0x8007) & (attributID === 0x0001)) { + decoded.payload = ""; + decoded.modbus_payload = ""; + decoded.size = bytes[index]; + decoded.modbus_float = 0; // 0: pas de décodage float 1: décodage float 2: décodage float 2word inversé + for (var j = 0; j < decoded.size; j++) { + temp_hex_str = bytes[index + j + 1].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.payload += temp_hex_str; + + if (j == 0) { + decoded.modbus_address = bytes[index + j + 1]; + } else if (j == 1) { + decoded.modbus_commandID = bytes[index + j + 1]; + } else if (j == 2) { + decoded.modbus_size = bytes[index + j + 1]; + } else { + decoded.modbus_payload += temp_hex_str; + if (decoded.modbus_float == 1) { + // big endian + if (j == 3) + decoded.fregister_00 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 7) + decoded.fregister_01 = Bytes2Float32( + bytes[index + j + 1] * 256 * ensk * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 11) + decoded.fregister_02 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 15) + decoded.fregister_03 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 19) + decoded.fregister_04 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 23) + decoded.fregister_05 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 27) + decoded.fregister_06 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 31) + decoded.fregister_07 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 35) + decoded.fregister_08 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + if (j == 35) + decoded.fregister_09 = Bytes2Float32( + bytes[index + j + 1] * 256 * 256 * 256 + + bytes[index + j + 1 + 1] * 256 * 256 + + bytes[index + j + 1 + 2] * 256 + + bytes[index + j + 1 + 3] + ); + } + if (decoded.modbus_float == 2) { + // float little endian 2 word + if (j == 3) + decoded.fregister_00 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 7) + decoded.fregister_01 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 11) + decoded.fregister_02 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 15) + decoded.fregister_03 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 19) + decoded.fregister_04 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 23) + decoded.fregister_05 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 27) + decoded.fregister_06 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 31) + decoded.fregister_07 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 35) + decoded.fregister_08 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + if (j == 35) + decoded.fregister_09 = Bytes2Float32( + bytes[index + j + 1] * 256 + + bytes[index + j + 1 + 1] + + bytes[index + j + 1 + 2] * 256 * 256 * 256 + + bytes[index + j + 1 + 3] * 256 * 256 + ); + } + } + } + } + + //multimodbus + if ((clusterdID === 0x8009) & (attributID === 0x0000)) { + decoded.payloads = ""; + decoded.size = bytes[index]; + decoded.multimodbus_frame_series_sent = bytes[index + 1]; + decoded.multimodbus_frame_number_in_serie = (bytes[index + 2] & 0xe0) >> 5; + decoded.multimodbus_last_frame_of_serie = (bytes[index + 2] & 0x1c) >> 2; + decoded.multimodbus_EP9 = (bytes[index + 2] & 0x01) === 0x01; + decoded.multimodbus_EP8 = (bytes[index + 2] & 0x02) === 0x02; + decoded.multimodbus_EP7 = (bytes[index + 3] & 0x80) === 0x80; + decoded.multimodbus_EP6 = (bytes[index + 3] & 0x40) === 0x40; + decoded.multimodbus_EP5 = (bytes[index + 3] & 0x20) === 0x20; + decoded.multimodbus_EP4 = (bytes[index + 3] & 0x10) === 0x10; + decoded.multimodbus_EP3 = (bytes[index + 3] & 0x08) === 0x08; + decoded.multimodbus_EP2 = (bytes[index + 3] & 0x04) === 0x04; + decoded.multimodbus_EP1 = (bytes[index + 3] & 0x02) === 0x02; + decoded.multimodbus_EP0 = (bytes[index + 3] & 0x01) === 0x01; + index2 = index + 4; + without_header = 0; + + if (decoded.multimodbus_EP0 === true) { + if (without_header === 0) { + decoded.multimodbus_EP0_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP0_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP0_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP0_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP0_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP0_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP0_datasize; + } + + if (decoded.multimodbus_EP1 === true) { + if (without_header === 0) { + decoded.multimodbus_EP1_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP1_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP1_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP1_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP1_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP1_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP1_datasize; + } + if (decoded.multimodbus_EP2 === true) { + if (without_header === 0) { + decoded.multimodbus_EP2_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP2_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP2_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP2_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP2_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP2_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP2_datasize; + } + if (decoded.multimodbus_EP3 === true) { + if (without_header === 0) { + decoded.multimodbus_EP3_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP3_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP3_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP3_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP3_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP3_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP3_datasize; + } + if (decoded.multimodbus_EP4 === true) { + if (without_header === 0) { + decoded.multimodbus_EP4_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP4_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP4_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP4_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP4_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP4_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP4_datasize; + } + if (decoded.multimodbus_EP5 === true) { + if (without_header === 0) { + decoded.multimodbus_EP5_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP5_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP5_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP5_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP5_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP5_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP5_datasize; + } + if (decoded.multimodbus_EP6 === true) { + if (without_header === 0) { + decoded.multimodbus_EP6_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP6_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP6_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP6_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP6_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP6_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP6_datasize; + } + if (decoded.multimodbus_EP7 === true) { + if (without_header === 0) { + decoded.multimodbus_EP7_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP7_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP7_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP7_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP7_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP7_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP7_datasize; + } + if (decoded.multimodbus_EP8 === true) { + if (without_header === 0) { + decoded.multimodbus_EP8_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP8_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP8_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP8_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP8_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP8_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP8_datasize; + } + if (decoded.multimodbus_EP9 === true) { + if (without_header === 0) { + decoded.multimodbus_EP6_slaveID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP6_fnctID = bytes[index2]; + index2 = index2 + 1; + decoded.multimodbus_EP6_datasize = bytes[index2]; + index2 = index2 + 1; + } + decoded.multimodbus_EP6_payload = ""; + if (bytes[index2] === undefined) return decoded; + for (var j = 0; j < decoded.multimodbus_EP6_datasize; j++) { + temp_hex_str = bytes[index2 + j].toString(16).toUpperCase(); + if (temp_hex_str.length == 1) { + temp_hex_str = "0" + temp_hex_str; + } + decoded.multimodbus_EP6_payload += temp_hex_str; + } + index2 = index2 + decoded.multimodbus_EP6_datasize; + } + } + + //simple metering + if ((clusterdID === 0x0052) & (attributID === 0x0000)) { + decoded.active_energy_Wh = UintToInt( + bytes[index + 1] * 256 * 256 + bytes[index + 2] * 256 + bytes[index + 3], + 3 + ); + decoded.reactive_energy_Varh = UintToInt( + bytes[index + 4] * 256 * 256 + bytes[index + 5] * 256 + bytes[index + 6], + 3 + ); + decoded.nb_samples = bytes[index + 7] * 256 + bytes[index + 8]; + decoded.active_power_W = UintToInt( + bytes[index + 9] * 256 + bytes[index + 10], + 2 + ); + decoded.reactive_power_VAR = UintToInt( + bytes[index + 11] * 256 + bytes[index + 12], + 2 + ); + } + // TIC: "TELE INFORMATION CLIENT" + if ( + clusterdID === 0x0053 || + clusterdID === 0x0054 || + clusterdID === 0x0055 || + clusterdID === 0x0056 || + clusterdID === 0x0057 + ) { + var ticData = TIC_Decode(clusterdID, attributID, bytes.slice(index + 1)); + for (var key in ticData) { + if (ticData.hasOwnProperty(key)) { + decoded[key] = ticData[key]; + } + } + } + // lorawan message type + if ((clusterdID === 0x8004) & (attributID === 0x0000)) { + if (bytes[index] === 1) decoded.message_type = "confirmed"; + if (bytes[index] === 0) decoded.message_type = "unconfirmed"; + } + + // lorawan retry + if ((clusterdID === 0x8004) & (attributID === 0x0001)) { + decoded.nb_retry = bytes[index]; + } + + // lorawan reassociation + if ((clusterdID === 0x8004) & (attributID === 0x0002)) { + decoded.period_in_minutes = bytes[index + 1] * 256 + bytes[index + 2]; + decoded.nb_err_frames = bytes[index + 3] * 256 + bytes[index + 4]; + } + // configuration node power desc + if ((clusterdID === 0x0050) & (attributID === 0x0006)) { + index2 = index + 3; + if ((bytes[index + 2] & 0x01) === 0x01) { + decoded.main_or_external_voltage = + (bytes[index2] * 256 + bytes[index2 + 1]) / 1000; + index2 = index2 + 2; + } + if ((bytes[index + 2] & 0x02) === 0x02) { + decoded.rechargeable_battery_voltage = + (bytes[index2] * 256 + bytes[index2 + 1]) / 1000; + index2 = index2 + 2; + } + if ((bytes[index + 2] & 0x04) === 0x04) { + decoded.disposable_battery_voltage = + (bytes[index2] * 256 + bytes[index2 + 1]) / 1000; + index2 = index2 + 2; + } + if ((bytes[index + 2] & 0x08) === 0x08) { + decoded.solar_harvesting_voltage = + (bytes[index2] * 256 + bytes[index2 + 1]) / 1000; + index2 = index2 + 2; + } + if ((bytes[index + 2] & 0x10) === 0x10) { + decoded.tic_harvesting_voltage = + (bytes[index2] * 256 + bytes[index2 + 1]) / 1000; + index2 = index2 + 2; + } + } + //energy and power metering + if ((clusterdID === 0x800a) & (attributID === 0x0000)) { + index2 = index; + decoded.sum_positive_active_energy_Wh = UintToInt( + bytes[index2 + 1] * 256 * 256 * 256 + + bytes[index2 + 2] * 256 * 256 + + bytes[index2 + 3] * 256 + + bytes[index2 + 4], + 4 + ); + index2 = index2 + 4; + decoded.sum_negative_active_energy_Wh = UintToInt( + bytes[index2 + 1] * 256 * 256 * 256 + + bytes[index2 + 2] * 256 * 256 + + bytes[index2 + 3] * 256 + + bytes[index2 + 4], + 4 + ); + index2 = index2 + 4; + decoded.sum_positive_reactive_energy_Wh = UintToInt( + bytes[index2 + 1] * 256 * 256 * 256 + + bytes[index2 + 2] * 256 * 256 + + bytes[index2 + 3] * 256 + + bytes[index2 + 4], + 4 + ); + index2 = index2 + 4; + decoded.sum_negative_reactive_energy_Wh = UintToInt( + bytes[index2 + 1] * 256 * 256 * 256 + + bytes[index2 + 2] * 256 * 256 + + bytes[index2 + 3] * 256 + + bytes[index2 + 4], + 4 + ); + index2 = index2 + 4; + decoded.positive_active_power_W = UintToInt( + bytes[index2 + 1] * 256 * 256 * 256 + + bytes[index2 + 2] * 256 * 256 + + bytes[index2 + 3] * 256 + + bytes[index2 + 4], + 4 + ); + index2 = index2 + 4; + decoded.negative_active_power_W = UintToInt( + bytes[index2 + 1] * 256 * 256 * 256 + + bytes[index2 + 2] * 256 * 256 + + bytes[index2 + 3] * 256 + + bytes[index2 + 4], + 4 + ); + index2 = index2 + 4; + decoded.positive_reactive_power_W = UintToInt( + bytes[index2 + 1] * 256 * 256 * 256 + + bytes[index2 + 2] * 256 * 256 + + bytes[index2 + 3] * 256 + + bytes[index2 + 4], + 4 + ); + index2 = index2 + 4; + decoded.negative_reactive_power_W = UintToInt( + bytes[index2 + 1] * 256 * 256 * 256 + + bytes[index2 + 2] * 256 * 256 + + bytes[index2 + 3] * 256 + + bytes[index2 + 4], + 4 + ); + } + + //energy and power multi metering + if ((clusterdID === 0x8010) & (attributID === 0x0000)) { + decoded.ActiveEnergyWhPhaseA = Int32UnsignedToSigned( + bytes[index + 1] * 256 * 256 * 256 + + bytes[index + 2] * 256 * 256 + + bytes[index + 3] * 256 + + bytes[index + 4] + ); + decoded.ReactiveEnergyWhPhaseA = Int32UnsignedToSigned( + bytes[index + 5] * 256 * 256 * 256 + + bytes[index + 6] * 256 * 256 + + bytes[index + 7] * 256 + + bytes[index + 8] + ); + decoded.ActiveEnergyWhPhaseB = Int32UnsignedToSigned( + bytes[index + 9] * 256 * 256 * 256 + + bytes[index + 10] * 256 * 256 + + bytes[index + 11] * 256 + + bytes[index + 12] + ); + decoded.ReactiveEnergyWhPhaseB = Int32UnsignedToSigned( + bytes[index + 13] * 256 * 256 * 256 + + bytes[index + 14] * 256 * 256 + + bytes[index + 15] * 256 + + bytes[index + 16] + ); + decoded.ActiveEnergyWhPhaseC = Int32UnsignedToSigned( + bytes[index + 17] * 256 * 256 * 256 + + bytes[index + 18] * 256 * 256 + + bytes[index + 19] * 256 + + bytes[index + 20] + ); + decoded.ReactiveEnergyWhPhaseC = Int32UnsignedToSigned( + bytes[index + 21] * 256 * 256 * 256 + + bytes[index + 22] * 256 * 256 + + bytes[index + 23] * 256 + + bytes[index + 24] + ); + decoded.ActiveEnergyWhPhaseABC = Int32UnsignedToSigned( + bytes[index + 25] * 256 * 256 * 256 + + bytes[index + 26] * 256 * 256 + + bytes[index + 27] * 256 + + bytes[index + 28] + ); + decoded.ReactiveEnergyWhPhaseABC = Int32UnsignedToSigned( + bytes[index + 29] * 256 * 256 * 256 + + bytes[index + 30] * 256 * 256 + + bytes[index + 31] * 256 + + bytes[index + 32] + ); + } else if ((clusterdID === 0x8010) & (attributID === 0x0001)) { + decoded.ActivePowerWPhaseA = Int32UnsignedToSigned( + bytes[index + 1] * 256 * 256 * 256 + + bytes[index + 2] * 256 * 256 + + bytes[index + 3] * 256 + + bytes[index + 4] + ); + decoded.ReactivePowerWPhaseA = Int32UnsignedToSigned( + bytes[index + 5] * 256 * 256 * 256 + + bytes[index + 6] * 256 * 256 + + bytes[index + 7] * 256 + + bytes[index + 8] + ); + decoded.ActivePowerWPhaseB = Int32UnsignedToSigned( + bytes[index + 9] * 256 * 256 * 256 + + bytes[index + 10] * 256 * 256 + + bytes[index + 11] * 256 + + bytes[index + 12] + ); + decoded.ReactivePowerWPhaseB = Int32UnsignedToSigned( + bytes[index + 13] * 256 * 256 * 256 + + bytes[index + 14] * 256 * 256 + + bytes[index + 15] * 256 + + bytes[index + 16] + ); + decoded.ActivePowerWPhaseC = Int32UnsignedToSigned( + bytes[index + 17] * 256 * 256 * 256 + + bytes[index + 18] * 256 * 256 + + bytes[index + 19] * 256 + + bytes[index + 20] + ); + decoded.ReactivePowerWPhaseC = Int32UnsignedToSigned( + bytes[index + 21] * 256 * 256 * 256 + + bytes[index + 22] * 256 * 256 + + bytes[index + 23] * 256 + + bytes[index + 24] + ); + decoded.ActivePowerWPhaseABC = Int32UnsignedToSigned( + bytes[index + 25] * 256 * 256 * 256 + + bytes[index + 26] * 256 * 256 + + bytes[index + 27] * 256 + + bytes[index + 28] + ); + decoded.ReactivePowerWPhaseABC = Int32UnsignedToSigned( + bytes[index + 29] * 256 * 256 * 256 + + bytes[index + 30] * 256 * 256 + + bytes[index + 31] * 256 + + bytes[index + 32] + ); + } + + //energy and power metering + if ((clusterdID === 0x800b) & (attributID === 0x0000)) { + index2 = index; + decoded.Vrms = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) / 10; + index2 = index2 + 2; + decoded.Irms = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) / 10; + index2 = index2 + 2; + decoded.phase_angle = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2); + } + + //voltage current multi metering + if ((clusterdID === 0x800d) & (attributID === 0x0000)) { + decoded.VrmsA = UintToInt(bytes[index + 1] * 256 + bytes[index + 2], 2) / 10; + decoded.IrmsA = UintToInt(bytes[index + 3] * 256 + bytes[index + 4], 2) / 10; + decoded.PhaseA = UintToInt(bytes[index + 5] * 256 + bytes[index + 6], 2); + decoded.VrmsB = UintToInt(bytes[index + 7] * 256 + bytes[index + 8], 2) / 10; + decoded.IrmsB = UintToInt(bytes[index + 9] * 256 + bytes[index + 10], 2) / 10; + decoded.PhaseB = UintToInt(bytes[index + 11] * 256 + bytes[index + 12], 2); + decoded.VrmsC = UintToInt(bytes[index + 13] * 256 + bytes[index + 14], 2) / 10; + decoded.IrmsC = UintToInt(bytes[index + 15] * 256 + bytes[index + 16], 2) / 10; + decoded.PhaseC = UintToInt(bytes[index + 17] * 256 + bytes[index + 18], 2); + } + + //concentration + if ((clusterdID === 0x800c) & (attributID === 0x0000)) { + decoded.Concentration = bytes[index] * 256 + bytes[index + 1]; + } + //illuminance + if ((clusterdID === 0x0400) & (attributID === 0x0000)) { + decoded.Illuminance = bytes[index] * 256 + bytes[index + 1]; + } + //Pressure + if ((clusterdID === 0x0403) & (attributID === 0x0000)) { + decoded.Pressure = UintToInt(bytes[index] * 256 + bytes[index + 1], 2); + } + //Occupancy + if ((clusterdID === 0x0406) & (attributID === 0x0000)) { + decoded.Occupancy = !(!bytes[index]); + } + // power quality by WattSense + if ((clusterdID === 0x8052) & (attributID === 0x0000)) { + index2 = index; + decoded.frequency = + (UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) + 22232) / 1000; + index2 = index2 + 2; + decoded.frequency_min = + (UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) + 22232) / 1000; + index2 = index2 + 2; + decoded.frequency_max = + (UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) + 22232) / 1000; + index2 = index2 + 2; + decoded.Vrms = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) / 10; + index2 = index2 + 2; + decoded.Vrms_min = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) / 10; + index2 = index2 + 2; + decoded.Vrms_max = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) / 10; + index2 = index2 + 2; + decoded.Vpeak = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) / 10; + index2 = index2 + 2; + decoded.Vpeak_min = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) / 10; + index2 = index2 + 2; + decoded.Vpeak_max = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2) / 10; + index2 = index2 + 2; + decoded.over_voltage = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2); + index2 = index2 + 2; + decoded.sag_voltage = UintToInt(bytes[index2 + 1] * 256 + bytes[index2 + 2], 2); + } + + //XYZ Acceleration : Last on XYZ + if (clusterdID === 0x800f) { + i = index + 1; + if (attributID === 0x0000) { + o = (decoded.Last = {}); + o.NbTriggedAcq = BytesToInt64(bytes, i, "U32"); + i += 4; + o.Mean_X_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.Max_X_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.Dt_X_ms = BytesToInt64(bytes, i, "U16"); + i += 2; + o.Mean_Y_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.Max_Y_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.Dt_Y_ms = BytesToInt64(bytes, i, "U16"); + i += 2; + o.Mean_Z_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.Max_Z_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.Dt_Z_ms = BytesToInt64(bytes, i, "U16"); + } else if (attributID === 0x0001 || attributID === 0x0002 || attributID === 0x0003) { + ext = attributID === 0x0001 ? "Stats_X" : attributID === 0x0002 ? "Stats_Y" : "Stats_Z"; + o = (decoded[ext] = {}); + o.NbAcq = BytesToInt64(bytes, i, "U16"); + i += 2; + o.MinMean_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.MinMax_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.MinDt = BytesToInt64(bytes, i, "U16"); + i += 2; + o.MeanMean_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.MeanMax_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.MeanDt = BytesToInt64(bytes, i, "U16"); + i += 2; + o.MaxMean_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.MaxMax_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.MaxDt = BytesToInt64(bytes, i, "U16"); + i += 2; + } else if (attributID === 0x8000) { + o = (decoded.Params = {}); + o.WaitFreq_Hz = BytesToInt64(bytes, i, "U16") / 10.0; + i += 2; + o.AcqFreq_Hz = BytesToInt64(bytes, i, "U16") / 10.0; + i += 2; + delay = BytesToInt64(bytes, i, "U16"); + i += 2; + if (delay & 0x8000) delay = (delay & ~0x8000) * 60; + o.NewWaitDelay_s = delay & 0x8000 ? (delay = (delay & ~0x8000) * 60) : delay; + o.MaxAcqDuration_ms = BytesToInt64(bytes, i, "U16"); + i += 2; + o.Threshold_X_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.Threshold_Y_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.Threshold_Z_G = BytesToInt64(bytes, i, "U16") / 100.0; + i += 2; + o.OverThrsh_Dt_ms = BytesToInt64(bytes, i, "U16"); + i += 2; + o.UnderThrsh_Dt_ms = BytesToInt64(bytes, i, "U16"); + i += 2; + o.Range_G = BytesToInt64(bytes, i, "U16") / 100; + i += 2; + o.FilterSmoothCoef = BytesToInt64(bytes, i, "U8"); + i += 1; + o.FilterGainCoef = BytesToInt64(bytes, i, "U8"); + i += 1; + o = (decoded.Params.WorkingModes = {}); + o.SignalEachAcq = bytes[i] & 0x80 ? "true" : "false"; + o.RstAftStdRpt_X = bytes[i] & 0x01 ? "true" : "false"; + o.RstAftStdRpt_Y = bytes[i] & 0x02 ? "true" : "false"; + o.RstAftStdRpt_7 = bytes[i] & 0x04 ? "true" : "false"; + } + } + } + + //decode configuration response + if (cmdID === 0x07) { + //AttributID + attributID = bytes[6] * 256 + bytes[7]; + decoded.zclheader.attributID = decimalToHex(attributID, 4); + //status + decoded.zclheader.status = bytes[4]; + //batch + decoded.zclheader.batch = bytes[5]; + } + + //decode read configuration response + if (cmdID === 0x09) { + //AttributID + attributID = bytes[6] * 256 + bytes[7]; + decoded.zclheader.attributID = decimalToHex(attributID, 4); + //status + decoded.zclheader.status = bytes[4]; + //batch + decoded.zclheader.batch = bytes[5]; + + //AttributType + decoded.zclheader.attribut_type = bytes[8]; + //min + decoded.zclheader.min = {}; + if ((bytes[9] & 0x80) === 0x80) { + decoded.zclheader.min.value = (bytes[9] - 0x80) * 256 + bytes[10]; + decoded.zclheader.min.unity = "minutes"; + } else { + decoded.zclheader.min.value = bytes[9] * 256 + bytes[10]; + decoded.zclheader.min.unity = "seconds"; + } + //max + decoded.zclheader.max = {}; + if ((bytes[11] & 0x80) === 0x80) { + decoded.zclheader.max.value = (bytes[11] - 0x80) * 256 + bytes[12]; + decoded.zclheader.max.unity = "minutes"; + } else { + decoded.zclheader.max.value = bytes[11] * 256 + bytes[12]; + decoded.zclheader.max.unity = "seconds"; + } + decoded.lora.payload = ""; + } + } else { + decoded.batch = {}; + decoded.batch.report = "batch"; + } + } + + return decoded; +} \ No newline at end of file diff --git a/vendors/watteco/tics'o/tics'o-encoder.js b/vendors/watteco/tics'o/tics'o-encoder.js new file mode 100644 index 0000000..25d8112 --- /dev/null +++ b/vendors/watteco/tics'o/tics'o-encoder.js @@ -0,0 +1,4 @@ +function Encode(fPort, obj) { + var encoded = []; + return encoded; +} \ No newline at end of file From 44d34259eff5bc1e5067be8ea9cbb0f11cd1e77d Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 19 May 2025 21:01:42 +0800 Subject: [PATCH 2/3] feat: add watteco as vendor --- vendors.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/vendors.json b/vendors.json index e724098..f702dcf 100644 --- a/vendors.json +++ b/vendors.json @@ -8,6 +8,15 @@ "description": "Make Sensing Matter", "oui": "24e124", "devices": "vendors/milesight-iot/devices.json" + }, + { + "id": "watteco", + "name": "Watteco", + "logo": "", + "website": "", + "description": "", + "oui": "", + "devices": "vendors/watteco/devices.json" } ] } From 27dd3f2d115588f8a9b70a560dd8f86ebf44593b Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 25 Mar 2026 15:13:48 +0800 Subject: [PATCH 3/3] feat: add Elvaco cmi41xx --- vendors.json | 9 + vendors/Elvaco/CMi41xx/cmi41xx-codec.json | 120 +++++ vendors/Elvaco/CMi41xx/cmi41xx-decoder.js | 524 ++++++++++++++++++++++ vendors/Elvaco/CMi41xx/cmi41xx-encoder.js | 4 + 4 files changed, 657 insertions(+) create mode 100644 vendors/Elvaco/CMi41xx/cmi41xx-codec.json create mode 100644 vendors/Elvaco/CMi41xx/cmi41xx-decoder.js create mode 100644 vendors/Elvaco/CMi41xx/cmi41xx-encoder.js diff --git a/vendors.json b/vendors.json index f702dcf..dba9de0 100644 --- a/vendors.json +++ b/vendors.json @@ -17,6 +17,15 @@ "description": "", "oui": "", "devices": "vendors/watteco/devices.json" + }, + { + "id": "elvaco", + "name": "Elvaco", + "logo": "", + "website": "", + "description": "", + "oui": "", + "devices": "vendors/Elvaco/devices.json" } ] } diff --git a/vendors/Elvaco/CMi41xx/cmi41xx-codec.json b/vendors/Elvaco/CMi41xx/cmi41xx-codec.json new file mode 100644 index 0000000..7363bc6 --- /dev/null +++ b/vendors/Elvaco/CMi41xx/cmi41xx-codec.json @@ -0,0 +1,120 @@ +{ + "version": "1.0.0", + "bytes": "000c07925407000c15465375010b2e2800000b3b9093000a5a99060a5e72060c789800627002fd170000", + "object": [ + { + "id": "message_format", + "name": "Message Format", + "value": "00", + "unit": "", + "access_mode": "R", + "data_type": "TEXT", + "value_type": "STRING", + "max_length": 2, + "bacnet_type": "character_string_value_object", + "bacnet_unit_type_id": 95, + "bacnet_unit_type": "UNITS_NO_UNITS" + }, + { + "id": "energy", + "name": "Energy", + "value": "754.92", + "unit": "MWh", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "FLOAT", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 24, + "bacnet_unit_type": "UNITS_MEGAWATT_HOURS" + }, + { + "id": "volume", + "name": "Volume", + "value": "175534.6", + "unit": "m³", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "FLOAT", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 37, + "bacnet_unit_type": "UNITS_CUBIC_METERS" + }, + { + "id": "power", + "name": "Power", + "value": "28", + "unit": "kW", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "FLOAT", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 22, + "bacnet_unit_type": "UNITS_KILOWATTS" + }, + { + "id": "flow", + "name": "Flow", + "value": "9.39", + "unit": "m³/h", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "FLOAT", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 124, + "bacnet_unit_type": "UNITS_CUBIC_METERS_PER_HOUR" + }, + { + "id": "forward_temperature", + "name": "Forward Temperature", + "value": "69.9", + "unit": "°C", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "FLOAT", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 62, + "bacnet_unit_type": "UNITS_DEGREES_CELSIUS" + }, + { + "id": "return_temperature", + "name": "Return Temperature", + "value": "67.2", + "unit": "°C", + "access_mode": "R", + "data_type": "NUMBER", + "value_type": "FLOAT", + "bacnet_type": "analog_input_object", + "bacnet_unit_type_id": 62, + "bacnet_unit_type": "UNITS_DEGREES_CELSIUS" + }, + { + "id": "meter_id", + "name": "Meter ID", + "value": "70620098", + "unit": "", + "access_mode": "R", + "data_type": "TEXT", + "value_type": "STRING", + "max_length": 10, + "bacnet_type": "character_string_value_object", + "bacnet_unit_type_id": 95, + "bacnet_unit_type": "UNITS_NO_UNITS" + }, + { + "id": "error_flags", + "name": "Error Flags", + "value": "0", + "unit": "", + "access_mode": "R", + "data_type": "BOOL", + "value_type": "UINT8", + "values": [ + { "value": 0, "name": "No Error" }, + { "value": 1, "name": "Error" } + ], + "bacnet_type": "binary_input_object", + "bacnet_unit_type_id": 95, + "bacnet_unit_type": "UNITS_NO_UNITS" + } + ] +} \ No newline at end of file diff --git a/vendors/Elvaco/CMi41xx/cmi41xx-decoder.js b/vendors/Elvaco/CMi41xx/cmi41xx-decoder.js new file mode 100644 index 0000000..edd41ed --- /dev/null +++ b/vendors/Elvaco/CMi41xx/cmi41xx-decoder.js @@ -0,0 +1,524 @@ +var packetTypes = { + 0: ["CMi4110", "Standard", "Landis+Gyr"], + 1: ["CMi4110", "Compact", "Landis+Gyr"], + 2: ["CMi4110", "JSON", "Landis+Gyr"], + 3: ["CMi4110", "Scheduled Daily Redundant", "Landis+Gyr", ["", "", "", "accAt24", ""]], + 4: ["CMi4110", "Scheduled Extended", "Landis+Gyr"], + 63: ["CMi4110", "Scheduled Extended+", "Landis+Gyr", ["", "tariff1", "tariff2", "tariff3", "", ""]], + 64: ["CMi4110", "Scheduled Extended+ 2", "Landis+Gyr"], + 65: ["CMi4110", "Compact Tariff", "Landis+Gyr", ["", "tariff1", "tariff2", "tariff3", "", ""]], + 70: ["CMi4110", "Maximum Flow", "Landis+Gyr"], + 71: ["CMi4110", "Scheduled Daily Redundant Tariff", "Landis+Gyr", ["at24", "", "", "", "", ""]], + 72: ["CMi4110", "Scheduled Daily Redundant Tariff 2", "Landis+Gyr"], + 73: ["CMi4110", "Scheduled Monthly", "Landis+Gyr"], + 74: ["CMi4110", "Scheduled Daily", "Landis+Gyr", ["at24", "", "", "", "", ""]], + 5: ["CMi4111", "Standard", "Landis+Gyr"], + 6: ["CMi4111", "Compact", "Landis+Gyr"], + 7: ["CMi4111", "JSON", "Landis+Gyr"], + 8: ["CMi4111", "Scheduled - Daily redundant", "Landis+Gyr", ["", "", "", "", "", "accAt24"]], + 9: ["CMi4111", "Scheduled - Extended", "Landis+Gyr"], + 10: ["CMi4111", "Combined heat/cooling", "Landis+Gyr"], + 11: ["CMi4111", "Simple billing", "Landis+Gyr"], + 12: ["CMi4111", "Plausibility check", "Landis+Gyr"], + 13: ["CMi4111", "Monitoring", "Landis+Gyr"], + 15: ["CMi4130", "Standard", "Itron"], + 16: ["CMi4130", "Compact", "Itron"], + 17: ["CMi4130", "JSON", "Itron"], + 18: ["CMi4130", "Scheduled - Daily redundant", "Itron", ["", "", "", "", "", "accAt24"]], + 19: ["CMi4130", "Scheduled - Extended", "Itron"], + 20: ["CMi4130", "Combined heat/cooling", "Itron"], + 21: ["CMi4140", "Standard", "Kamstrup"], + 22: ["CMi4140", "Compact", "Kamstrup"], + 23: ["CMi4140", "JSON", "Kamstrup"], + 24: ["CMi4140", "Scheduled Daily Redundant", "Kamstrup"], + 25: ["CMi4140", "Scheduled Extended", "Kamstrup"], + 26: ["CMi4140", "Combined heating/cooling", "Kamstrup"], + 27: ["CMi4140", "Heat Intelligence", "Kamstrup", ["E1", "E3", "", "", "", ""]], + 59: ["CMi4140", "Scheduled Extended+", "Kamstrup"], + 60: ["CMi4140", "Scheduled Extended+ 2", "Kamstrup"], + 28: ["CMi4140", "Pulse", "Kamstrup"], + 29: ["CMi4140", "Pulse 2", "Kamstrup"], + 77: ["CMi4140", "Pulse Extended", "Kamstrup"], + 78: ["CMi4140", "Pulse Extended 2", "Kamstrup"], + 79: ["CMi4140", "DR0 message", "Kamstrup"], + 30: ["CMi4160", "Standard", "Diehl"], + 31: ["CMi4160", "Compact", "Diehl"], + 32: ["CMi4160", "JSON", "Diehl"], + 33: ["CMi4160", "Scheduled - Daily redundant", "Diehl"], + 34: ["CMi4160", "Scheduled - Extended", "Diehl"], + 35: ["CMi4160", "Combined heat/cooling", "Diehl"], + 61: ["CMi4160", "Scheduled Extended+", "Diehl"], + 62: ["CMi4160", "Scheduled Extended+ 2", "Diehl"], + 36: ["CMi4170", "Standard", "Engelmann"], + 37: ["CMi4170", "Compact", "Engelmann"], + 38: ["CMi4170", "JSON", "Engelmann"], + 39: ["CMi4170", "Scheduled - daily redundant", "Engelmann"], + 40: ["CMi4170", "Scheduled - Extended", "Engelmann"], + 41: ["CMi4170", "Combined heat/cooling", "Engelmann"], + 44: ["CMi4170", "Engelmann", "Engelmann"], + 45: ["CMi4170", "Engelmann 2", "Engelmann"], + 80: ["CMi4170", "DR0 message", "Engelmann"] +}; + +var valueMap = { + "0x0400": ["energy", "Wh", 0.001], + "0x0401": ["energy", "Wh", 0.01], + "0x0402": ["energy", "Wh", 0.1], + "0x0403": ["energy", "Wh", 1], + "0x0404": ["energy", "Wh", 10], + "0x0405": ["energy", "Wh", 100], + "0x0406": ["energy", "kWh", 1], + "0x0407": ["energy", "kWh", 10], + "0x0408": ["energy", "J", 1], + "0x0409": ["energy", "J", 10], + "0x040a": ["energy", "J", 100], + "0x040b": ["energy", "J", 1000], + "0x040c": ["energy", "J", 10000], + "0x040d": ["energy", "J", 100000], + "0x040e": ["energy", "MJ", 1], + "0x040f": ["energy", "MJ", 10], + "0x04fb": { + "0x0d": ["energy", "MCal", 1], + "0x0e": ["energy", "MCal", 10], + "0x0f": ["energy", "MCal", 100], + "0x8d": ["coolingEnergy", "MCal", 1], + "0x8e": ["coolingEnergy", "MCal", 10], + "0x8f": ["coolingEnergy", "MCal", 100] + }, + "0x4400": ["accumulatedEnergy", "Wh", 0.001], + "0x4401": ["accumulatedEnergy", "Wh", 0.01], + "0x4402": ["accumulatedEnergy", "Wh", 0.1], + "0x4403": ["accumulatedEnergy", "Wh", 1], + "0x4404": ["accumulatedEnergy", "Wh", 10], + "0x4405": ["accumulatedEnergy", "Wh", 100], + "0x4406": ["accumulatedEnergy", "kWh", 1], + "0x4407": ["accumulatedEnergy", "kWh", 10], + "0x440e": ["accumulatedEnergy", "MJ", 1], + "0x440f": ["accumulatedEnergy", "MJ", 10], + "0x44fb": { + "0x0d": ["accumulatedEnergy", "MCal", 1], + "0x0e": ["accumulatedEnergy", "MCal", 10], + "0x0f": ["accumulatedEnergy", "MCal", 100] + }, + "0x0480": ["coolingEnergy", "Wh", 0.001], + "0x0481": ["coolingEnergy", "Wh", 0.01], + "0x0482": ["coolingEnergy", "Wh", 0.1], + "0x0483": ["coolingEnergy", "Wh", 1], + "0x0484": ["coolingEnergy", "Wh", 10], + "0x0485": ["coolingEnergy", "Wh", 100], + "0x0486": ["coolingEnergy", "kWh", 1], + "0x0487": ["coolingEnergy", "kWh", 10], + "0x048e": ["coolingEnergy", "MJ", 1], + "0x048f": ["coolingEnergy", "MJ", 10], + "0x04ff": { + "0x07": ["energyE8", "m³*°C", 1], + "0x08": ["energyE9", "m³*°C", 1] + }, + "0x0410": ["volume", "m³", 0.000001], + "0x0411": ["volume", "m³", 0.00001], + "0x0412": ["volume", "m³", 0.0001], + "0x0413": ["volume", "m³", 0.001], + "0x0414": ["volume", "m³", 0.01], + "0x0415": ["volume", "m³", 0.1], + "0x0416": ["volume", "m³", 1], + "0x0417": ["volume", "m³", 10], + "0x0228": ["power", "W", 0.001], + "0x0229": ["power", "W", 0.01], + "0x022a": ["power", "W", 0.1], + "0x022b": ["power", "W", 1], + "0x022c": ["power", "W", 10], + "0x022d": ["power", "W", 100], + "0x022e": ["power", "kW", 1], + "0x022f": ["power", "kW", 10], + "0x023b": ["flow", "m³/h", 0.001], + "0x023c": ["flow", "m³/h", 0.01], + "0x023d": ["flow", "m³/h", 0.1], + "0x023e": ["flow", "m³/h", 1], + "0x023f": ["flow", "m³/h", 10], + "0x1258": ["maxForwardTemperature", "°C", 0.001], + "0x1259": ["maxForwardTemperature", "°C", 0.01], + "0x125a": ["maxForwardTemperature", "°C", 0.1], + "0x125b": ["maxForwardTemperature", "°C", 1], + "0x0258": ["forwardTemperature", "°C", 0.001], + "0x0259": ["forwardTemperature", "°C", 0.01], + "0x025a": ["forwardTemperature", "°C", 0.1], + "0x025b": ["forwardTemperature", "°C", 1], + "0x125c": ["maxReturnTemperature", "°C", 0.001], + "0x125d": ["maxReturnTemperature", "°C", 0.01], + "0x125e": ["maxReturnTemperature", "°C", 0.1], + "0x125f": ["maxReturnTemperature", "°C", 1], + "0x025c": ["returnTemperature", "°C", 0.001], + "0x025d": ["returnTemperature", "°C", 0.01], + "0x025e": ["returnTemperature", "°C", 0.1], + "0x025f": ["returnTemperature", "°C", 1], + "0x07ff": { + "0xa0": ["powerFlows", null, null], + "0x21": ["meterInfo", null, null] + }, + "0x0a58": ["forwardTemperature", "°C", 0.001], + "0x0a59": ["forwardTemperature", "°C", 0.01], + "0x0a5a": ["forwardTemperature", "°C", 0.1], + "0x0a5b": ["forwardTemperature", "°C", 1], + "0x0a5c": ["returnTemperature", "°C", 0.001], + "0x0a5d": ["returnTemperature", "°C", 0.01], + "0x0a5e": ["returnTemperature", "°C", 0.1], + "0x0a5f": ["returnTemperature", "°C", 1], + "0x0b2b": ["power", "kW", 0.001], + "0x0b2c": ["power", "kW", 0.01], + "0x0b2d": ["power", "kW", 0.1], + "0x0b2e": ["power", "kW", 1], + "0x0b3b": ["flow", "m³/h", 0.001], + "0x0b3c": ["flow", "m³/h", 0.01], + "0x0b3d": ["flow", "m³/h", 0.1], + "0x0b3e": ["flow", "m³/h", 1], + "0x0c06": ["energy", "kWh", 1], + "0x0c07": ["energy", "MWh", 0.01], + "0x0cfb": { + "0x00": ["energy", "MWh", 0.1], + "0x01": ["energy", "MWh", 1], + "0x08": ["energy", "GJ", 0.1], + "0x09": ["energy", "GJ", 1] + }, + "0x0c0e": ["energy", "GJ", 0.001], + "0x0c0f": ["energy", "GJ", 0.01], + "0x0c14": ["volume", "m³", 0.01], + "0x0c15": ["volume", "m³", 0.1], + "0x0c16": ["volume", "m³", 1], + "0x8402": { + "0x03": ["tarif2energy", "Wh", 1] + }, + "0x8403": { + "0x03": ["tarif3energy", "Wh", 1] + }, + "0x8440": { + "0x13": ["pulse1volume", "m³", 0.001], + "0x14": ["pulse1volume", "m³", 0.01], + "0x15": ["pulse1volume", "m³", 0.1], + "0x06": ["pulse1energy", "MWh", 0.001], + "0x07": ["pulse1energy", "MWh", 0.01] + }, + "0x8480": { + "0x04": { + "0x13": ["pulse2volume", "m³", 0.001], + "0x14": ["pulse2volume", "m³", 0.01], + "0x15": ["pulse2volume", "m³", 0.1], + "0x06": ["pulse2energy", "MWh", 0.001], + "0x07": ["pulse2energy", "MWh", 0.01] + } + }, + "0x84c0": { + "0x04": { + "0x13": ["pulse3volume", "m³", 0.001], + "0x14": ["pulse3volume", "m³", 0.01], + "0x15": ["pulse3volume", "m³", 0.1], + "0x06": ["pulse3energy", "MWh", 0.001], + "0x07": ["pulse3energy", "MWh", 0.01] + } + }, + "0x8c01": { + "0x06": ["energyAtDueDate", "kWh", 1] + }, + "0x8c10": ["tariff1energy", null, 1], + "0x8c20": ["tariff2energy", null, 1], + "0x9b01": { + "0x3b": ["maxFlow", "m³/h", 0.001] + }, + "0x4c06": ["energy", "kWh", 1], + "0x4c07": ["energy", "MWh", 0.01], + "0x4c0e": ["energy", "GJ", 0.001], + "0x4c0f": ["energy", "GJ", 0.01], + "0x4c14": ["volume", "m³", 0.01], + "0x4c15": ["volume", "m³", 0.1], + "0x4c16": ["volume", "m³", 1], + "0xb401": { + "0x00": ["previousMonthEnergy", "Wh", 0.001], + "0x01": ["previousMonthEnergy", "Wh", 0.01], + "0x02": ["previousMonthEnergy", "Wh", 0.1], + "0x03": ["previousMonthEnergy", "Wh", 1], + "0x04": ["previousMonthEnergy", "Wh", 10], + "0x05": ["previousMonthEnergy", "Wh", 100], + "0x06": ["previousMonthEnergy", "kWh", 1], + "0x07": ["previousMonthEnergy", "kWh", 10], + "0x0e": ["previousMonthEnergy", "MJ", 1], + "0x0f": ["previousMonthEnergy", "MJ", 10] + }, + "0x0420": ["S", "s", 1], + "0x0421": ["Min", "min", 1], + "0x0422": ["H", "h", 1], + "0x0423": ["Days", "days", 1], + "0xcc10": { + "0x07": ["at24tariff1energy", null, 1] + }, + "0xcc20": { + "0x07": ["at24tariff2energy", null, 1] + }, + "0x0c78": ["meterId", null, null], + "0x0c79": ["customerMeterId", null, null], + "0x06ff": { + "0x21": ["meterId", null, null] + }, + "0x0779": ["enhancedMeterId", null, null], + "0x01fd": { + "0x17": ["errorFlags", null, 1] + }, + "0x02fd": { + "0x17": ["errorFlags", null, 1] + }, + "0x04fd": { + "0x17": ["errorFlags", null, 1] + } +}; + +function readUInt16BE(bytes, pos) { + return (bytes[pos] << 8) + bytes[pos + 1]; +} + +function readInt16LE(bytes, pos) { + var value = (bytes[pos + 1] << 8) + bytes[pos]; + return value > 0x7fff ? value - 0x10000 : value; +} + +function readUInt32LE(bytes, pos) { + return (bytes[pos + 3] << 24) + (bytes[pos + 2] << 16) + (bytes[pos + 1] << 8) + bytes[pos]; +} + +function readInt32LE(bytes, pos) { + var value = readUInt32LE(bytes, pos); + return value > 0x7fffffff ? value - 0x100000000 : value; +} + +function readUInt8(bytes, pos) { + return bytes[pos]; +} + +function readBCD(bytes, pos, size) { + var value = 0; + var i; + for (i = size - 1; i >= 0; i--) { + var byte = bytes[pos + i]; + var high = (byte >> 4) & 0x0f; + var low = byte & 0x0f; + value = value * 100 + high * 10 + low; + } + return value; +} + +function padZero(str, len) { + while (str.length < len) { + str = "0" + str; + } + return str; +} + +function decodeUplink(input) { + var r = input.bytes; + var pos = 0; + var measurementNo = 0; + var data = {}; + var traces = []; + var trace = {}; + var debug = input.debug || false; + var i; + + try { + data.messageFormat = readUInt8(r, pos); + pos++; + var packetInfo = packetTypes[data.messageFormat]; + if (typeof packetInfo === "undefined") { + throw new Error("Unsupported message format 0x" + data.messageFormat.toString(16)); + } + + data.messageFormatInfo = packetInfo.slice(0, 3); + + if (data.messageFormatInfo[1] === "JSON") { + var jsonString = String.fromCharCode.apply(null, r.slice(1)); + var measurements = JSON.parse(jsonString); + var unified = { + messageFormat: data.messageFormat.toString(16), + energy: measurements.E, + energyUnit: measurements.U, + meterId: measurements.ID + }; + + if (debug) { + traces.push({ + headerStart: 0, + headerInfo: jsonString, + dataStart: 1, + dataEnd: r.length - 2 + }); + } + + var result = { + data: {}, + payload: "", + traces: traces, + warnings: [], + errors: [] + }; + for (i in data) { + result.data[i] = data[i]; + } + for (i in unified) { + result.data[i] = unified[i]; + } + var payload = []; + for (i = 0; i < r.length; i++) { + payload.push(padZero(r[i].toString(16), 2)); + } + result.payload = payload.join(""); + return result; + } + + while (pos < r.length) { + var dif = readUInt16BE(r, pos); + var size = r[pos] & 0x0f; + trace = { + headerStart: pos + }; + pos += 2; + + if (dif === 0x046d || dif === 0x346d) { + trace.dataStart = pos; + var ts = r.slice(pos, pos + 4); + pos += 4; + if (!(ts[1] & 0x01)) { + var year = 1900 + 100 * (ts[1] >> 5); + year += ((ts[3] >> 4) << 3) | (ts[2] >> 5); + data.timeStamp = year + "-" + + ("0" + (ts[3] & 0x0f)).slice(-2) + "-" + + ("0" + (ts[2] & 0x1f)).slice(-2) + "T" + + ("0" + (ts[1] & 0x1f)).slice(-2) + ":" + + ("0" + (ts[0] & 0x7f)).slice(-2) + "Z"; + } + if (debug) { + var traceCopy = {}; + for (i in trace) { + traceCopy[i] = trace[i]; + } + traceCopy.headerInfo = ["timeStamp", null, null]; + traceCopy.dataStart = trace.dataStart; + traceCopy.dataEnd = pos - 1; + traces.push(traceCopy); + } + measurementNo++; + continue; + } + + var mapKey = (dif >> 12) === 0x03 ? (dif & 0xfff).toString(16) : dif.toString(16); + var map = valueMap["0x" + ("0000" + mapKey).slice(-4)]; + if (typeof map === "undefined") { + dif &= 0x0fff; + throw new Error("Unknown measurement " + dif.toString(16)); + } + + while (!Array.isArray(map)) { + var subType = readUInt8(r, pos); + pos++; + var subMap = map["0x" + ("00" + subType.toString(16)).slice(-2)]; + if (typeof subMap === "undefined") { + throw new Error("Unknown measurement " + dif.toString(16) + " subtype " + subType.toString(16)); + } + map = subMap; + } + + var name = (packetInfo.length === 3) ? map[0] : packetInfo[3][measurementNo] + map[0]; + + if (name === "coolingEnergy") { + var flag = readInt16LE(r, pos); + if (flag === 0xff02) { + pos += 2; + } else if (flag === 0xff03) { + name = "error" + name; + pos += 2; + } + } + + trace.headerInfo = [name, map[1], map[2]]; + trace.dataStart = pos; + + var value = 0; + switch (size) { + case 0x1: + value = readUInt8(r, pos); + break; + case 0x2: + value = readInt16LE(r, pos); + break; + case 0x4: + value = readInt32LE(r, pos); + break; + case 0xa: + value = readBCD(r, pos, 2); + size = 2; + break; + case 0xb: + value = readBCD(r, pos, 3); + size = 3; + break; + case 0xc: + value = readBCD(r, pos, 4); + size = 4; + break; + default: + throw new Error("Unsupported size: " + size); + } + pos += size; + + if (map[1] !== null) { + data[name + "Unit"] = map[1]; + } + + if (map[2] !== null) { + value *= map[2]; + } + + if ((dif >> 12) === 0x3) { + data[name + "Error"] = true; + } + + data[name] = (typeof value === "number" && value % 1 === 0) ? value : parseFloat(value.toFixed(8)); + measurementNo++; + + trace.dataEnd = pos - 1; + + if (debug) { + traces.push(trace); + } + } + } catch (e) { + traces.push(trace); + data.messageFormat = "0x" + data.messageFormat.toString(16); + var errorResult = { + data: data, + payload: "", + traces: traces, + errors: [e.message] + }; + var errorPayload = []; + for (i = 0; i < r.length; i++) { + errorPayload.push(padZero(r[i].toString(16), 2)); + } + errorResult.payload = errorPayload.join(""); + return errorResult; + } + + data.messageFormat = data.messageFormat.toString(16); + var finalResult = { + data: data, + payload: "", + traces: traces, + warnings: [], + errors: [] + }; + var finalPayload = []; + for (i = 0; i < r.length; i++) { + finalPayload.push(padZero(r[i].toString(16), 2)); + } + finalResult.payload = finalPayload.join(""); + return finalResult; +} + +function Decode(fPort, bytes) { + return decodeUplink({ bytes: bytes, debug: false }); +} \ No newline at end of file diff --git a/vendors/Elvaco/CMi41xx/cmi41xx-encoder.js b/vendors/Elvaco/CMi41xx/cmi41xx-encoder.js new file mode 100644 index 0000000..25d8112 --- /dev/null +++ b/vendors/Elvaco/CMi41xx/cmi41xx-encoder.js @@ -0,0 +1,4 @@ +function Encode(fPort, obj) { + var encoded = []; + return encoded; +} \ No newline at end of file