diff --git a/src/MBUSPayload.cpp b/src/MBUSPayload.cpp index 15bca42..2123b3b 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; @@ -202,13 +202,125 @@ 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); - if ((len < 1) || (4 < len)) { - _error = MBUS_ERROR::UNSUPPORTED_CODING; - return 0; - } + uint8_t difLeast4bit = (dif & 0x0F); + uint8_t difFunctionField = ((dif & 0x30) >> 4); + 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; + + } + 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) { + index++; + dife = false; + dife = ((buffer[index-1] & 0x80) == 0x80); //check if after the DIFE another DIFE is following + } + // End of DIFE handling + + // Get VIF(E) uint32_t vif = 0; do { @@ -225,6 +337,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) { @@ -233,25 +352,140 @@ 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); + } + 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 + ); + 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: + 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. #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