From 93a682de494751da90af24028008f328f5ffa36c Mon Sep 17 00:00:00 2001 From: Zeppelin500 <90451866+Zeppelin500@users.noreply.github.com> Date: Sun, 22 Oct 2023 08:06:20 +0200 Subject: [PATCH 1/6] add DIFE handling --- src/MBUSPayload.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/MBUSPayload.cpp b/src/MBUSPayload.cpp index 15bca42..f586e02 100644 --- a/src/MBUSPayload.cpp +++ b/src/MBUSPayload.cpp @@ -204,6 +204,17 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { uint8_t dif = buffer[index++]; bool bcd = ((dif & 0x08) == 0x08); uint8_t len = (dif & 0x07); + + // handle DIFE to prevent stumble if a DIFE is used + bool dife = ((dif & 0x80) == 0x80); //check if the first bit of DIF marked as "DIFE is following" + while(dife) { + index++; + client.publish(String("busino/debug/decodeDIFE" + String(index-1)), String(buffer[index-1]).c_str()); + dife = false; + dife = ((buffer[index-1] & 0x80) == 0x80); //check if after the DIFE another DIFE is following + } + // End of DIFE handling + if ((len < 1) || (4 < len)) { _error = MBUS_ERROR::UNSUPPORTED_CODING; return 0; @@ -551,4 +562,4 @@ uint32_t MBUSPayload::_getVIF(uint8_t code, int8_t scalar) { return 0xFF; // this is not a valid VIF -} \ No newline at end of file +} From 654916d4e13a1f2bcb9ebe9d2fd5d217c5ab80ef Mon Sep 17 00:00:00 2001 From: Zeppelin500 <90451866+Zeppelin500@users.noreply.github.com> Date: Sun, 22 Oct 2023 08:40:26 +0200 Subject: [PATCH 2/6] delete debug message --- src/MBUSPayload.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/MBUSPayload.cpp b/src/MBUSPayload.cpp index f586e02..681bce7 100644 --- a/src/MBUSPayload.cpp +++ b/src/MBUSPayload.cpp @@ -209,7 +209,6 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { bool dife = ((dif & 0x80) == 0x80); //check if the first bit of DIF marked as "DIFE is following" while(dife) { index++; - client.publish(String("busino/debug/decodeDIFE" + String(index-1)), String(buffer[index-1]).c_str()); dife = false; dife = ((buffer[index-1] & 0x80) == 0x80); //check if after the DIFE another DIFE is following } From 6a7bc42aecb4d937c9e503fc24694fdc1a9dd8bf Mon Sep 17 00:00:00 2001 From: Zeppelin500 <90451866+Zeppelin500@users.noreply.github.com> Date: Fri, 27 Oct 2023 20:35:37 +0200 Subject: [PATCH 3/6] some improfments negativ values (2 Bytes), less decode errors --- src/MBUSPayload.cpp | 70 ++++++++++++++++++++++++++++++++++++--------- src/MBUSPayload.h | 23 +++++++++------ 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/MBUSPayload.cpp b/src/MBUSPayload.cpp index 681bce7..bb732f3 100644 --- a/src/MBUSPayload.cpp +++ b/src/MBUSPayload.cpp @@ -171,7 +171,7 @@ uint8_t MBUSPayload::addField(uint8_t code, float value) { bool valid = (_getVIF(code, scalar) != 0xFF); // Now move down - uint32_t scaled = round(value); + int32_t scaled = round(value); while ((scaled % 10) == 0) { scalar++; scaled /= 10; @@ -213,6 +213,10 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { dife = ((buffer[index-1] & 0x80) == 0x80); //check if after the DIFE another DIFE is following } // End of DIFE handling + + if(len==5){ // DIF len 5 = 4 Byte gleitkommazahl + len=4; + } if ((len < 1) || (4 < len)) { _error = MBUS_ERROR::UNSUPPORTED_CODING; @@ -243,17 +247,37 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { } // read value - uint32_t value = 0; - if (bcd) { - for (uint8_t i = 0; i> 4) * 10) + (byte & 0x0F); - } - } else { - for (uint8_t i = 0; i> 4) * 10) + (byte & 0x0F); + } + } + else { + for (uint8_t i = 0; i> 4) * 10) + (byte & 0x0F); + } + } + else { + for (uint8_t i = 0; i. #include #include -#define MBUS_DEFAULT_BUFFER_SIZE 32 +#define MBUS_DEFAULT_BUFFER_SIZE 510 #define ARDUINO_FLOAT_MIN 1e-6 // Assume 0 if less than this #define ARDUINO_FLOAT_DECIMALS 6 // 6 decimals is just below the limit for Arduino float maths @@ -57,8 +57,8 @@ enum MBUS_CODE { TEMPERATURE_DIFF_K, EXTERNAL_TEMPERATURE_C, PRESSURE_BAR, - //TIME_POINT_DATE, - //TIME_POINT_DATETIME, + TIME_POINT_DATE, + TIME_POINT_DATETIME, //HCA, AVG_DURATION_S, AVG_DURATION_MIN, @@ -81,7 +81,7 @@ enum MBUS_CODE { MODEL_VERSION, HARDWARE_VERSION, FIRMWARE_VERSION, - //SOFTWARE_VERSION, + SOFTWARE_VERSION, //CUSTOMER_LOCATION, CUSTOMER, //ACCESS_CODE_USER, @@ -114,6 +114,9 @@ enum MBUS_CODE { TEMPERATURE_LIMIT_F, TEMPERATURE_LIMIT_C, MAX_POWER_W, + + // VIFE 0xFC + UNSUPPORTED_X, }; @@ -141,7 +144,7 @@ enum MBUS_ERROR { // VIF codes -#define MBUS_VIF_DEF_NUM 73 +#define MBUS_VIF_DEF_NUM 77 typedef struct { uint8_t code; @@ -176,8 +179,8 @@ static const vif_def_type vif_defs[MBUS_VIF_DEF_NUM] = { { MBUS_CODE::TEMPERATURE_DIFF_K , 0x60 , 4, -3}, { MBUS_CODE::EXTERNAL_TEMPERATURE_C , 0x64 , 4, -3}, { MBUS_CODE::PRESSURE_BAR , 0x68 , 4, -3}, - //{ MBUS_CODE::TIME_POINT_DATE , 0x6C , 1, 0}, - //{ MBUS_CODE::TIME_POINT_DATETIME , 0x6D , 1, 0}, + { MBUS_CODE::TIME_POINT_DATE , 0x6C , 1, 0}, + { MBUS_CODE::TIME_POINT_DATETIME , 0x6D , 1, 0}, //{ MBUS_CODE::HCA , 0x6E , 1, 0}, { MBUS_CODE::AVG_DURATION_S , 0x70 , 1, 0}, { MBUS_CODE::AVG_DURATION_MIN , 0x71 , 1, 0}, @@ -203,7 +206,7 @@ static const vif_def_type vif_defs[MBUS_VIF_DEF_NUM] = { { MBUS_CODE::MODEL_VERSION , 0xFD0C , 1, 0}, { MBUS_CODE::HARDWARE_VERSION , 0xFD0D , 1, 0}, { MBUS_CODE::FIRMWARE_VERSION , 0xFD0E , 1, 0}, - //{ MBUS_CODE::SOFTWARE_VERSION , 0xFD0F , 1, 0}, + { MBUS_CODE::SOFTWARE_VERSION , 0xFD0F , 1, 0}, //neu //{ MBUS_CODE::CUSTOMER_LOCATION , 0xFD10 , 1, 0}, { MBUS_CODE::CUSTOMER , 0xFD11 , 1, 0}, //{ MBUS_CODE::ACCESS_CODE_USER , 0xFD12 , 1, 0}, @@ -244,6 +247,9 @@ static const vif_def_type vif_defs[MBUS_VIF_DEF_NUM] = { { MBUS_CODE::TEMPERATURE_LIMIT_C , 0xFB74 , 4, -3}, { MBUS_CODE::MAX_POWER_W , 0xFB78 , 8, -3}, + // VIFE 0xFC + { MBUS_CODE::UNSUPPORTED_X , 0xFC00 , 254, 0} + }; class MBUSPayload { @@ -278,5 +284,4 @@ class MBUSPayload { uint8_t _error = NO_ERROR; }; - #endif From cc6b51c72d8bce1bb82109b779e28c53d4a7b2a8 Mon Sep 17 00:00:00 2001 From: Zeppelin500 <90451866+Zeppelin500@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:54:59 +0100 Subject: [PATCH 4/6] fix TimePoint decoding change the whole logic of data decoding to get formatet dates. --- src/MBUSPayload.cpp | 263 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 221 insertions(+), 42 deletions(-) diff --git a/src/MBUSPayload.cpp b/src/MBUSPayload.cpp index bb732f3..b1dd937 100644 --- a/src/MBUSPayload.cpp +++ b/src/MBUSPayload.cpp @@ -202,8 +202,97 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { // Decode DIF uint8_t dif = buffer[index++]; - bool bcd = ((dif & 0x08) == 0x08); - uint8_t len = (dif & 0x07); + uint8_t difLeast4bit = (dif & 0x0F); + uint8_t len = 0; + uint8_t dataCodingType = 0; + /* + 0 --> no Data + 1 --> integer + 2 --> bcd + 3 --> real + 4 --> variable lengs + 5 --> special functions + 6 --> TimePoint Date&Time Typ F + 7 --> TimePoint Date Typ G + + Length in Bit Code Meaning Code Meaning + 0 0000 No data 1000 Selection for Readout + 8 0001 8 Bit Integer 1001 2 digit BCD + 16 0010 16 Bit Integer 1010 4 digit BCD + 24 0011 24 Bit Integer 1011 6 digit BCD + 32 0100 32 Bit Integer 1100 8 digit BCD + 32 / N 0101 32 Bit Real 1101 variable length + 48 0110 48 Bit Integer 1110 12 digit BCD + 64 0111 64 Bit Integer 1111 Special Functions + */ + + switch(difLeast4bit){ + case 0x00: //No data + len = 0; + dataCodingType = 0; + break; + case 0x01: //0001 8 Bit Integer + len = 1; + dataCodingType = 1; + break; + case 0x02: //0010 16 Bit Integer + len = 2; + dataCodingType = 1; + break; + case 0x03: //0011 24 Bit Integer + len = 3; + dataCodingType = 1; + break; + case 0x04: //0100 32 Bit Integer + len = 4; + dataCodingType = 1; + break; + case 0x05: //0101 32 Bit Real + len = 4; + dataCodingType = 3; + break; + case 0x06: //0110 48 Bit Integer + len = 6; + dataCodingType = 1; + break; + case 0x07: //0111 64 Bit Integer + len = 8; + dataCodingType = 1; + break; + case 0x08: //not supported + len = 0; + dataCodingType = 0; + break; + case 0x09: //1001 2 digit BCD + len = 1; + dataCodingType = 2; + break; + case 0x0A: //1010 4 digit BCD + len = 2; + dataCodingType = 2; + break; + case 0x0B: //1011 6 digit BCD + len = 3; + dataCodingType = 2; + break; + case 0x0C: //1100 8 digit BCD + len = 4; + dataCodingType = 2; + break; + case 0x0D: //1101 variable length + len = 0; + dataCodingType = 4; + break; + case 0x0E: //1110 12 digit BCD + len = 6; + dataCodingType = 2; + break; + case 0x0F: //1111 Special Functions + len = 0; + dataCodingType = 5; + break; + + } // handle DIFE to prevent stumble if a DIFE is used bool dife = ((dif & 0x80) == 0x80); //check if the first bit of DIF marked as "DIFE is following" @@ -213,16 +302,8 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { dife = ((buffer[index-1] & 0x80) == 0x80); //check if after the DIFE another DIFE is following } // End of DIFE handling + - if(len==5){ // DIF len 5 = 4 Byte gleitkommazahl - len=4; - } - - if ((len < 1) || (4 < len)) { - _error = MBUS_ERROR::UNSUPPORTED_CODING; - return 0; - } - // Get VIF(E) uint32_t vif = 0; do { @@ -239,6 +320,13 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { _error = MBUS_ERROR::UNSUPPORTED_VIF; return 0; } + + if((vif & 0x6D) == 0x6D){ // TimePoint Date&Time TypF + dataCodingType = 6; + } + else if((vif & 0x6C) == 0x6C){ // TimePoint Date TypG + dataCodingType = 7; + } // Check buffer overflow if (index + len > size) { @@ -247,45 +335,135 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { } // read value - int16_t value16 = 0; // int16_t to notice negative values at 2 byte data - int32_t value = 0; - - if (len == 2){ - if (bcd) { - for (uint8_t i = 0; i> 4) * 10) + (byte & 0x0F); + int16_t value16 = 0; // int16_t to notice negative values at 2 byte data + int32_t value32 = 0; // int32_t to notice negative values at 4 byte data + int64_t value = 0; + + float valueFloat = 0; + + + uint8_t date[len] ={0}; + char datestring[12] = {0}; + char datestring2[24] = {0}; + int out_len = 0; + + switch(dataCodingType){ + case 0: //no Data + + break; + case 1: //integer + if(len==2){ + for (uint8_t i = 0; i> 4) * 10) + (byte & 0x0F); + break; + case 2: //bcd + if(len==2){ + for (uint8_t i = 0; i> 4) * 10) + (byte & 0x0F); } - } - else { + value = (int64_t)value16; + } + else if(len==4){ + for (uint8_t i = 0; i> 4) * 10) + (byte & 0x0F); + } + value = (int64_t)value32; + } + else{ + for (uint8_t i = 0; i> 4) * 10) + (byte & 0x0F); + } + } + break; + case 3: //real for (uint8_t i = 0; i> 5) | ((date[3] & 0xF0) >> 1), // year + date[3] & 0x0F, // mon + date[2] & 0x1F, // mday + date[1] & 0x1F, // hour + date[0] & 0x3F // sec + ); + + out_len = snprintf(datestring2, 24, "%02d-%02d-%02dT%02d:%02d:00", + ((date[2] & 0xE0) >> 5) | ((date[3] & 0xF0) >> 1), // year + date[3] & 0x0F, // mon + date[2] & 0x1F, // mday + date[1] & 0x1F, // hour + date[0] & 0x3F // sec + ); + value = atof( datestring); + break; + case 7: //TimePoint Date Typ G + for (uint8_t i = 0; i 12) { // Time valid ? + //out_len = snprintf(output, output_size, "invalid"); + break; + }*/ + out_len = snprintf(datestring, 10, "%02d%02d%02d", + ((date[0] & 0xE0) >> 5) | ((date[1] & 0xF0) >> 1), // year + date[1] & 0x0F, // mon + date[0] & 0x1F // mday + ); + value = atof( datestring); + break; + default: + break; + } + index += len; // scaled value - int8_t scalar = vif_defs[def].scalar + vif - vif_defs[def].base; - double scaled = value; - for (int8_t i=0; i Date: Mon, 13 Nov 2023 13:37:00 +0100 Subject: [PATCH 5/6] add json string for date --- src/MBUSPayload.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/MBUSPayload.cpp b/src/MBUSPayload.cpp index b1dd937..6b37541 100644 --- a/src/MBUSPayload.cpp +++ b/src/MBUSPayload.cpp @@ -436,15 +436,20 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { date[i] = buffer[index + i]; } -/* if ((date[1] & 0x0F) > 12) { // Time valid ? + if ((date[1] & 0x0F) > 12) { // Time valid ? //out_len = snprintf(output, output_size, "invalid"); break; - }*/ + } out_len = snprintf(datestring, 10, "%02d%02d%02d", ((date[0] & 0xE0) >> 5) | ((date[1] & 0xF0) >> 1), // year date[1] & 0x0F, // mon date[0] & 0x1F // mday ); + out_len = snprintf(datestring2, 10, "%02d-%02d-%02d", + ((date[0] & 0xE0) >> 5) | ((date[1] & 0xF0) >> 1), // year + date[1] & 0x0F, // mon + date[0] & 0x1F // mday + ); value = atof( datestring); break; default: From cadc5e2c463de134ae1a05817b94efc88fb286c1 Mon Sep 17 00:00:00 2001 From: Zeppelin500 <90451866+Zeppelin500@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:26:11 +0100 Subject: [PATCH 6/6] add difFunctionField --- src/MBUSPayload.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/MBUSPayload.cpp b/src/MBUSPayload.cpp index 6b37541..2123b3b 100644 --- a/src/MBUSPayload.cpp +++ b/src/MBUSPayload.cpp @@ -203,6 +203,7 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { // Decode DIF uint8_t dif = buffer[index++]; uint8_t difLeast4bit = (dif & 0x0F); + uint8_t difFunctionField = ((dif & 0x30) >> 4); uint8_t len = 0; uint8_t dataCodingType = 0; /* @@ -293,7 +294,23 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { break; } - + char stringFunctionField[5]; + switch(difFunctionField){ + case 0: + strcpy(stringFunctionField, ""); //current + break; + case 1: + strcpy(stringFunctionField, "_max"); + break; + case 2: + strcpy(stringFunctionField, "_min"); + break; + case 3: + strcpy(stringFunctionField, "_err"); + break; + } + + // handle DIFE to prevent stumble if a DIFE is used bool dife = ((dif & 0x80) == 0x80); //check if the first bit of DIF marked as "DIFE is following" while(dife) { @@ -477,8 +494,8 @@ uint8_t MBUSPayload::decode(uint8_t *buffer, uint8_t size, JsonArray& root) { data["value_raw"] = value; data["value_scaled"] = scaled; data["units"] = String(getCodeUnits(vif_defs[def].code)); - data["name"] = String(getCodeName(vif_defs[def].code)); - data["date"] = String(datestring2); + data["name"] = String(getCodeName(vif_defs[def].code)+String(stringFunctionField)); + // data["date"] = String(datestring2); formatted dates, optional }