From cf297a56c35f26654d3e8efb45358b04e228d8b1 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 21 Oct 2012 10:55:48 +0200 Subject: [PATCH 1/6] New test frame for Elvaco temperature / humidity meter (from Jakob Skov-Pedersen) --- test/test-frames/elv_temp_humid.hex | 1 + test/test-frames/elv_temp_humid.xml | 104 ++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 test/test-frames/elv_temp_humid.hex create mode 100644 test/test-frames/elv_temp_humid.xml diff --git a/test/test-frames/elv_temp_humid.hex b/test/test-frames/elv_temp_humid.hex new file mode 100644 index 0000000..18b608b --- /dev/null +++ b/test/test-frames/elv_temp_humid.hex @@ -0,0 +1 @@ +68 53 53 68 08 05 72 34 08 00 54 96 15 32 00 F2 00 00 00 01 FD 1B 00 02 FC 03 48 52 25 74 D4 11 22 FC 03 48 52 25 74 C8 11 12 FC 03 48 52 25 74 B4 16 02 65 D0 08 22 65 70 08 12 65 23 09 01 72 18 42 65 E4 08 82 01 65 DD 08 0C 78 34 08 00 54 03 FD 0F 00 00 04 1F 5D 16 diff --git a/test/test-frames/elv_temp_humid.xml b/test/test-frames/elv_temp_humid.xml new file mode 100644 index 0000000..91ee7bb --- /dev/null +++ b/test/test-frames/elv_temp_humid.xml @@ -0,0 +1,104 @@ + + + + 54000834 + ELV + 50 + + Other + 242 + 00 + 0000 + + + + Instantaneous value + Digital input (binary) + 0 + 1970-01-01T00:00:00 + + + + Instantaneous value + 1e-2 %RH + 4564 + 1970-01-01T00:00:00 + + + + Minimum value + 1e-2 %RH + 4552 + 1970-01-01T00:00:00 + + + + Maximum value + 1e-2 %RH + 5812 + 1970-01-01T00:00:00 + + + + Instantaneous value + External temperature (1e-2 deg C) + 2256 + 1970-01-01T00:00:00 + + + + Minimum value + External temperature (1e-2 deg C) + 2160 + 1970-01-01T00:00:00 + + + + Maximum value + External temperature (1e-2 deg C) + 2339 + 1970-01-01T00:00:00 + + + + Instantaneous value + Averaging Duration (hours) + 24 + 1970-01-01T00:00:00 + + + + Instantaneous value + External temperature (1e-2 deg C) + 2276 + 1970-01-01T00:00:00 + + + + Instantaneous value + External temperature (1e-2 deg C) + 2269 + 1970-01-01T00:00:00 + + + + Instantaneous value + Fabrication number + 54000834 + 1970-01-01T00:00:00 + + + + Instantaneous value + Software version + 262144 + 1970-01-01T00:00:00 + + + + More records follow + + 1970-01-01T00:00:00 + + + From 99d48d27b2caab9ea609c8067a79342761009577 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 21 Oct 2012 11:05:08 +0200 Subject: [PATCH 2/6] Extended mbus_data_variable_print to print out VIF/VIFE --- mbus/mbus-protocol.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index e627091..dddebbe 100755 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -3145,7 +3145,7 @@ mbus_data_variable_print(mbus_data_variable *data) { // DIF printf("DIF = %.2X\n", record->drh.dib.dif); - printf("DIF.Extension = %s\n", (record->drh.dib.dif & MBUS_DIB_DIF_EXTENSION_BIT) ? "Yes":"No"); + printf("DIF.Extension = %s\n", (record->drh.dib.dif & MBUS_DIB_DIF_EXTENSION_BIT) ? "Yes":"No"); printf("DIF.Function = %s\n", (record->drh.dib.dif & 0x30) ? "Minimum value" : "Instantaneous value" ); printf("DIF.Data = %.2X\n", record->drh.dib.dif & 0x0F); @@ -3180,6 +3180,22 @@ mbus_data_variable_print(mbus_data_variable *data) printf("DIFE[%zd].Data = %.2X\n", j, dife & 0x0F); } + // VIF + printf("VIF = %.2X\n", record->drh.vib.vif); + printf("VIF.Extension = %s\n", (record->drh.vib.vif & MBUS_DIB_VIF_EXTENSION_BIT) ? "Yes":"No"); + printf("VIF.Value = %.2X\n", record->drh.vib.vif & 0x7F); + + // VIFE + for (j = 0; j < record->drh.vib.nvife; j++) + { + u_char vife = record->drh.vib.vife[j]; + + printf("VIFE[%zd] = %.2X\n", j, vife); + printf("VIFE[%zd].Extension = %s\n", j, (vife & MBUS_DIB_VIF_EXTENSION_BIT) ? "Yes" : "No"); + printf("VIFE[%zd].Value = %.2X\n", j, vife & 0x7F); + } + + printf("\n"); } } From 0c26bc17a78d93edf4e793062d28248073767b11 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 21 Oct 2012 11:09:21 +0200 Subject: [PATCH 3/6] Add VIF for digital input and output Correct some cases --- mbus/mbus-protocol.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index dddebbe..91957e7 100755 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -2055,12 +2055,22 @@ mbus_vib_unit_lookup(mbus_value_information_block *vib) // VIFE = E001 0001 Customer snprintf(buff, sizeof(buff), "Customer"); } - else if (vib->vife[0] == 0x9) + else if (vib->vife[0] == 0x1A) + { + // VIFE = E001 1010 Digital output (binary) + snprintf(buff, sizeof(buff), "Digital output (binary)"); + } + else if (vib->vife[0] == 0x1B) + { + // VIFE = E001 1011 Digital input (binary) + snprintf(buff, sizeof(buff), "Digital input (binary)"); + } + else if (vib->vife[0] == 0x09) { // VIFE = E001 0110 Password snprintf(buff, sizeof(buff), "Password"); } - else if (vib->vife[0] == 0x0b) + else if (vib->vife[0] == 0x0B) { // VIFE = E000 1011 Parameter set identification snprintf(buff, sizeof(buff), "Parameter set identification"); From bc2c85c3784c1a197218e33147baa498d0c11b14 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 21 Oct 2012 11:21:07 +0200 Subject: [PATCH 4/6] Add custom VIFE handling with a corrective factor (from Jakob Skov-Pedersen) --- mbus/mbus-protocol-aux.c | 41 ++++++++++++++++++++++++++++++++++++---- mbus/mbus-protocol.c | 32 +++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c index ec0f6f0..e655323 100755 --- a/mbus/mbus-protocol-aux.c +++ b/mbus/mbus-protocol-aux.c @@ -17,6 +17,7 @@ #include #include +#include #define MBUS_ERROR(...) fprintf (stderr, __VA_ARGS__) @@ -1024,14 +1025,15 @@ mbus_vib_unit_normalize(mbus_value_information_block *vib, double value, char ** return -1; } } - else if (vib->vif == 0x7C) + else if ((vib->vif == 0x7C) || + (vib->vif == 0xFC)) { // custom VIF *unit_out = strdup("-"); *quantity_out = strdup(vib->custom_vif); - *value_out = 0.0; - } - else + *value_out = value; + } + else { int code = (vib->vif) & 0x7f; if (0 != mbus_vif_unit_normalize(code, value, unit_out, value_out, quantity_out)) @@ -1041,6 +1043,37 @@ mbus_vib_unit_normalize(mbus_value_information_block *vib, double value, char ** } } } + + if ((vib->vif & MBUS_DIB_VIF_EXTENSION_BIT) && + (vib->vif != 0xFD) && + (vib->vif != 0xFB)) /* codes for VIF extention: see table 8.4.5 */ + { + int code = (vib->vif) & 0x7f; + switch (code) + { + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: /* Multiplicative correction factor: 10^nnn-6 */ + *value_out *= pow(10.0, (vib->vife[0] & 0x07) - 6); + break; + + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: /* Additive correction constant: 10^nn-3 unit of VIF (offset) */ + *value_out += pow(10.0, (vib->vife[0] & 0x03) - 3); + break; + + case 0x7D: /* Multiplicative correction factor: 10^3 */ + *value_out *= 1000.0; + break; + } + } return 0; } diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index 91957e7..3c94b16 100755 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -2104,6 +2104,13 @@ mbus_vib_unit_lookup(mbus_value_information_block *vib) snprintf(buff, sizeof(buff), "%s", vib->custom_vif); return buff; } + else if (vib->vif == 0xFC && (vib->vife[0] & 0x78) == 0x70) + { + // custom VIF + n = (vib->vife[0] & 0x07); + snprintf(buff, sizeof(buff), "%s %s", mbus_unit_prefix(n-6), vib->custom_vif); + return buff; + } return mbus_vif_unit_lookup(vib->vif); // no extention, use VIF } @@ -2686,21 +2693,30 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data) // read and parse VIB (= VIF + VIFE) // VIF - record->drh.vib.vif = frame->data[i]; - - if (record->drh.vib.vif == 0x7C) + record->drh.vib.vif = frame->data[i++]; + + if ((record->drh.vib.vif & 0x7F) == 0x7C) { // variable length VIF in ASCII format int var_vif_len; - i++; var_vif_len = frame->data[i++]; + if (i + var_vif_len > frame->data_size) + { + mbus_data_record_free(record); + return -1; + } mbus_data_str_decode(record->drh.vib.custom_vif, &(frame->data[i]), var_vif_len); i += var_vif_len; } - else + + // VIFE + record->drh.vib.nvife = 0; + + if (record->drh.vib.vif & MBUS_DIB_VIF_EXTENSION_BIT) { - // VIFE - record->drh.vib.nvife = 0; + record->drh.vib.vife[0] = frame->data[i]; + record->drh.vib.nvife++; + while (frame->data[i] & MBUS_DIB_VIF_EXTENSION_BIT && record->drh.vib.nvife < NITEMS(record->drh.vib.vife)) { @@ -2710,7 +2726,7 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data) record->drh.vib.nvife++; i++; } - i++; + i++; } // re-calculate data length, if of variable length type From 688f0d3bc0aff300842869fb79487acaebf75bda Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 21 Oct 2012 23:24:04 +0200 Subject: [PATCH 5/6] Added product name mapping for Elvaco meters --- mbus/mbus-protocol.c | 30 ++++++++++++++++++++++++++++++ mbus/mbus-protocol.h | 1 + 2 files changed, 31 insertions(+) diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index 3c94b16..1876444 100755 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -817,6 +817,36 @@ mbus_data_product_name(mbus_data_variable_header *header) break; } } + else if (manufacturer == MBUS_VARIABLE_DATA_MAN_ELV) + { + switch (header->version) + { + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + strcpy(buff, "Elvaco CMa10"); + break; + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + strcpy(buff,"Elvaco CMa11"); + break; + } + } else if (manufacturer == MBUS_VARIABLE_DATA_MAN_SLB) { switch (header->version) diff --git a/mbus/mbus-protocol.h b/mbus/mbus-protocol.h index c1473a3..f23d72c 100755 --- a/mbus/mbus-protocol.h +++ b/mbus/mbus-protocol.h @@ -476,6 +476,7 @@ typedef struct _mbus_data_secondary_address { #define MBUS_VARIABLE_DATA_MAN_AMT 0x05B4 #define MBUS_VARIABLE_DATA_MAN_EFE 0x14C5 #define MBUS_VARIABLE_DATA_MAN_ELS 0x1593 +#define MBUS_VARIABLE_DATA_MAN_ELV 0x1596 #define MBUS_VARIABLE_DATA_MAN_EMH 0x15A8 #define MBUS_VARIABLE_DATA_MAN_HYD 0x2324 #define MBUS_VARIABLE_DATA_MAN_KAM 0x2C2D From cfa35db086240ca07cc50e8fa9a9b7e6b16d4e03 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 22 Oct 2012 23:35:45 +0200 Subject: [PATCH 6/6] Fixed potential segmentation fault --- mbus/mbus-protocol-aux.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c index e655323..f91d246 100755 --- a/mbus/mbus-protocol-aux.c +++ b/mbus/mbus-protocol-aux.c @@ -1690,6 +1690,12 @@ mbus_sendrecv_request(mbus_handle *handle, int address, mbus_frame *reply, int m mbus_frame_data reply_data; mbus_frame *frame, *next_frame; int frame_count = 0, result; + + if (handle == NULL) + { + MBUS_ERROR("%s: Invalid M-Bus handle for request.\n", __PRETTY_FUNCTION__); + return 1; + } frame = mbus_frame_new(MBUS_FRAME_TYPE_SHORT);