From ad4d307b571d4dcaeed7adccb637173cadab10d1 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 29 May 2012 19:15:52 +0200 Subject: [PATCH 1/7] Fixed endless loop in receive function in case of a incomplete frame (limit = 3 timeouts) --- mbus/mbus-serial.c | 17 +++++++++++++++-- mbus/mbus-tcp.c | 15 ++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/mbus/mbus-serial.c b/mbus/mbus-serial.c index ec6b112..34e1e8b 100644 --- a/mbus/mbus-serial.c +++ b/mbus/mbus-serial.c @@ -223,7 +223,7 @@ int mbus_serial_recv_frame(mbus_serial_handle *handle, mbus_frame *frame) { char buff[PACKET_BUFF_SIZE]; - int len, remaining, nread; + int len, remaining, nread, timeouts; if (handle == NULL || frame == NULL) { @@ -238,6 +238,7 @@ mbus_serial_recv_frame(mbus_serial_handle *handle, mbus_frame *frame) // remaining = 1; // start by reading 1 byte len = 0; + timeouts = 0; do { //printf("%s: Attempt to read %d bytes [len = %d]\n", __PRETTY_FUNCTION__, remaining, len); @@ -249,7 +250,19 @@ mbus_serial_recv_frame(mbus_serial_handle *handle, mbus_frame *frame) return -1; } -// printf("%s: Got %d byte [remaining %d, len %d]\n", __PRETTY_FUNCTION__, nread, remaining, len); +// printf("%s: Got %d byte [remaining %d, len %d]\n", __PRETTY_FUNCTION__, nread, remaining, len); + + if (nread == 0) + { + timeouts++; + + if (timeouts >= 3) + { + // abort to avoid endless loop + fprintf(stderr, "%s: Timeout\n", __PRETTY_FUNCTION__); + break; + } + } len += nread; diff --git a/mbus/mbus-tcp.c b/mbus/mbus-tcp.c index 17150fb..53cfbd1 100644 --- a/mbus/mbus-tcp.c +++ b/mbus/mbus-tcp.c @@ -165,7 +165,7 @@ int mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame) { char buff[PACKET_BUFF_SIZE]; - int len, remaining, nread; + int len, remaining, nread, timeouts; if (handle == NULL || frame == NULL) { @@ -180,6 +180,7 @@ mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame) // remaining = 1; // start by reading 1 byte len = 0; + timeouts = 0; do { @@ -188,6 +189,18 @@ mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame) mbus_error_str_set("M-Bus tcp transport layer failed to read data."); return -1; } + + if (nread == 0) + { + timeouts++; + + if (timeouts >= 3) + { + // abort to avoid endless loop + fprintf(stderr, "%s: Timeout\n", __PRETTY_FUNCTION__); + break; + } + } len += nread; From 9fd35b781b1606bac5a58f19407a3add935d94ef Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 29 May 2012 19:39:56 +0200 Subject: [PATCH 2/7] Improved collision detection for scan --- mbus/mbus-serial.c | 2 +- mbus/mbus-tcp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mbus/mbus-serial.c b/mbus/mbus-serial.c index 34e1e8b..71b90c2 100644 --- a/mbus/mbus-serial.c +++ b/mbus/mbus-serial.c @@ -280,7 +280,7 @@ mbus_serial_recv_frame(mbus_serial_handle *handle, mbus_frame *frame) if (_mbus_recv_event) _mbus_recv_event(MBUS_HANDLE_TYPE_SERIAL, buff, len); - if (remaining < 0) + if (remaining != 0) { // Would be OK when e.g. scanning the bus, otherwise it is a failure. // printf("%s: M-Bus layer failed to receive complete data.\n", __PRETTY_FUNCTION__); diff --git a/mbus/mbus-tcp.c b/mbus/mbus-tcp.c index 53cfbd1..f29e8ce 100644 --- a/mbus/mbus-tcp.c +++ b/mbus/mbus-tcp.c @@ -218,7 +218,7 @@ mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame) if (_mbus_recv_event) _mbus_recv_event(MBUS_HANDLE_TYPE_TCP, buff, len); - if (remaining < 0) + if (remaining != 0) { mbus_error_str_set("M-Bus layer failed to parse data."); return -2; From 0cb23161e78fbd6cce6fa942942da38578d3ea92 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 29 May 2012 20:17:05 +0200 Subject: [PATCH 3/7] Added receive timestamp for each data record in XML output --- mbus/mbus-protocol-aux.c | 15 ++++++++++++--- mbus/mbus-protocol.c | 10 ++++++++++ mbus/mbus-protocol.h | 3 +++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c index 6fd052c..aa0cf39 100644 --- a/mbus/mbus-protocol-aux.c +++ b/mbus/mbus-protocol-aux.c @@ -1367,6 +1367,8 @@ mbus_disconnect(mbus_handle * handle) int mbus_recv_frame(mbus_handle * handle, mbus_frame *frame) { + int result = 0; + if (handle == NULL) { MBUS_ERROR("%s: Invalid M-Bus handle for receive.\n", __PRETTY_FUNCTION__); @@ -1375,13 +1377,20 @@ mbus_recv_frame(mbus_handle * handle, mbus_frame *frame) if (handle->is_serial) { - return mbus_serial_recv_frame(handle->m_serial_handle, frame); + result = mbus_serial_recv_frame(handle->m_serial_handle, frame); } else { - return mbus_tcp_recv_frame(handle->m_tcp_handle, frame); + result = mbus_tcp_recv_frame(handle->m_tcp_handle, frame); } - return 0; + + if (frame != NULL) + { + /* set timestamp to receive time */ + time(&(frame->timestamp)); + } + + return result; } int diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index f7fff71..3289ac6 100644 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -2563,6 +2563,9 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data) // clean up... return (-2); } + + // copy timestamp + memcpy((void *)&(record->timestamp), (void *)&(frame->timestamp), sizeof(time_t)); // read and parse DIB (= DIF + DIFE) @@ -3275,6 +3278,8 @@ mbus_data_variable_record_xml(mbus_data_record *record, int record_cnt, int fram static char buff[8192]; char str_encoded[768]; size_t len = 0; + struct tm * timeinfo; + char timestamp[21]; int val; if (record) @@ -3314,6 +3319,11 @@ mbus_data_variable_record_xml(mbus_data_record *record, int record_cnt, int fram mbus_str_xml_encode(str_encoded, mbus_data_record_value(record), sizeof(str_encoded)); len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + + timeinfo = gmtime ( &(record->timestamp) ); + strftime(timestamp,20,"%Y-%m-%dT%H:%M:%S",timeinfo); + len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", timestamp); + len += snprintf(&buff[len], sizeof(buff) - len, " \n\n"); return buff; diff --git a/mbus/mbus-protocol.h b/mbus/mbus-protocol.h index 70b6847..6a7d515 100644 --- a/mbus/mbus-protocol.h +++ b/mbus/mbus-protocol.h @@ -83,6 +83,7 @@ typedef struct _mbus_frame { size_t data_size; int type; + time_t timestamp; //mbus_frame_data frame_data; @@ -145,6 +146,8 @@ typedef struct _mbus_data_record { u_char data[234]; size_t data_len; + time_t timestamp; + void *next; } mbus_data_record; From 989eada28ab42fa366f2984047883645237ec656 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 29 May 2012 20:33:09 +0200 Subject: [PATCH 4/7] Improved model mapping - initialize result buffer - added new mappings - added und fixed man codes --- mbus/mbus-protocol.c | 49 ++++++++++++++++++++++++++++++-------------- mbus/mbus-protocol.h | 3 ++- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index 3289ac6..b1027c1 100644 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -754,6 +754,8 @@ mbus_data_product_name(mbus_data_variable_header *header) static char buff[128]; unsigned int manufacturer; + memset(buff, 0, sizeof(buff)); + if (header) { manufacturer = (header->manufacturer[1] << 8) + header->manufacturer[0]; @@ -782,6 +784,15 @@ mbus_data_product_name(mbus_data_variable_header *header) break; } } + else if (manufacturer == MBUS_VARIABLE_DATA_MAN_EFE) + { + switch (header->version) + { + case 0x01: + strcpy(buff,"Engelmann SensoStar 2C"); + break; + } + } else if (manufacturer == MBUS_VARIABLE_DATA_MAN_SLB) { switch (header->version) @@ -821,18 +832,6 @@ mbus_data_product_name(mbus_data_variable_header *header) break; } } - else if (manufacturer == MBUS_VARIABLE_DATA_MAN_ZRM) - { - switch (header->version) - { - case 0x81: - strcpy(buff,"Minol Minocal C2"); - break; - case 0x82: - strcpy(buff,"Minol Minocal WR3"); - break; - } - } else if (manufacturer == MBUS_VARIABLE_DATA_MAN_SVM) { switch (header->version) @@ -868,6 +867,7 @@ mbus_data_product_name(mbus_data_variable_header *header) switch (header->version) { case 0x31: + case 0x34: strcpy(buff,"Sensus PolluTherm"); break; } @@ -908,11 +908,30 @@ mbus_data_product_name(mbus_data_variable_header *header) break; } } - - return buff; + else if (manufacturer == MBUS_VARIABLE_DATA_MAN_TCH) + { + switch (header->version) + { + case 0x26: + strcpy(buff,"Techem m-bus S"); + break; + } + } + else if (manufacturer == MBUS_VARIABLE_DATA_MAN_ZRM) + { + switch (header->version) + { + case 0x81: + strcpy(buff,"Minol Minocal C2"); + break; + case 0x82: + strcpy(buff,"Minol Minocal WR3"); + break; + } + } } - return ""; + return buff; } //------------------------------------------------------------------------------ diff --git a/mbus/mbus-protocol.h b/mbus/mbus-protocol.h index 6a7d515..5fa5298 100644 --- a/mbus/mbus-protocol.h +++ b/mbus/mbus-protocol.h @@ -465,6 +465,7 @@ typedef struct _mbus_data_secondary_address { #define MBUS_VARIABLE_DATA_MAN_ACW 0x0477 #define MBUS_VARIABLE_DATA_MAN_ABB 0x0442 #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_EMH 0x15A8 #define MBUS_VARIABLE_DATA_MAN_HYD 0x2324 @@ -478,7 +479,7 @@ typedef struct _mbus_data_secondary_address { #define MBUS_VARIABLE_DATA_MAN_SON 0x4DEE #define MBUS_VARIABLE_DATA_MAN_SPX 0x4E18 #define MBUS_VARIABLE_DATA_MAN_SVM 0x4ECD -#define MBUS_VARIABLE_DATA_MAN_TCM 0x5068 +#define MBUS_VARIABLE_DATA_MAN_TCH 0x5068 #define MBUS_VARIABLE_DATA_MAN_ZRM 0x6A4D // From c2f7c0d48e087d0aaa1a0093adb662f08f1e24ba Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 29 May 2012 20:51:34 +0200 Subject: [PATCH 5/7] Improved wildcard search results (still not all meters were found) - sleep 1 second after each init frame - select secondary address with enabled FCB bit --- bin/mbus-serial-scan-secondary.c | 2 ++ mbus/mbus-protocol.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/mbus-serial-scan-secondary.c b/bin/mbus-serial-scan-secondary.c index 92dc3d3..61be9af 100644 --- a/bin/mbus-serial-scan-secondary.c +++ b/bin/mbus-serial-scan-secondary.c @@ -137,6 +137,7 @@ main(int argc, char **argv) } (void) mbus_recv_frame(handle, &reply); + sleep(1); frame->control = MBUS_CONTROL_MASK_SND_NKE | MBUS_CONTROL_MASK_DIR_M2S; frame->address = 0xFF; @@ -149,6 +150,7 @@ main(int argc, char **argv) } (void) mbus_recv_frame(handle, &reply); + sleep(1); mbus_scan_2nd_address_range(handle, 0, addr_mask); diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index b1027c1..bd7d38f 100644 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -3762,7 +3762,7 @@ mbus_frame_select_secondary_pack(mbus_frame *frame, char *address) return -1; } - frame->control = MBUS_CONTROL_MASK_SND_UD | MBUS_CONTROL_MASK_DIR_M2S; + frame->control = MBUS_CONTROL_MASK_SND_UD | MBUS_CONTROL_MASK_DIR_M2S | MBUS_CONTROL_MASK_FCB; frame->address = 253; // for addressing secondary slaves frame->control_information = 0x52; // mode 1 From bf12395af9cb4b3b899da4a99c1ea29dfefc7255 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 29 May 2012 21:24:30 +0200 Subject: [PATCH 6/7] Fixed segmentation fault in case of much XML output Because of the multi telegrams it is impossible to use a fixed buffer for XML output on the stack. Now the buffer is allocated on the heap. These also leads to a change in return behaviour for all XML functions, because it's possible that the buffer is NULL. For variable data this buffer grows every time there are less than 1024 bytes left for a new record. --- bin/mbus-serial-request-data-multi-reply.c | 2 + bin/mbus-serial-request-data.c | 13 +- mbus/mbus-protocol-aux.c | 42 ++++-- mbus/mbus-protocol.c | 146 ++++++++++++++------- test/mbus_parse.c | 11 +- test/mbus_parse_hex.c | 12 +- 6 files changed, 157 insertions(+), 69 deletions(-) diff --git a/bin/mbus-serial-request-data-multi-reply.c b/bin/mbus-serial-request-data-multi-reply.c index 35eb473..9dd1648 100644 --- a/bin/mbus-serial-request-data-multi-reply.c +++ b/bin/mbus-serial-request-data-multi-reply.c @@ -169,7 +169,9 @@ main(int argc, char **argv) fprintf(stderr, "Failed to generate XML representation of MBUS frames: %s\n", mbus_error_str()); return 1; } + printf("%s", xml_result); + free(xml_result); mbus_disconnect(handle); return 0; diff --git a/bin/mbus-serial-request-data.c b/bin/mbus-serial-request-data.c index 5816c3c..d60a777 100644 --- a/bin/mbus-serial-request-data.c +++ b/bin/mbus-serial-request-data.c @@ -29,7 +29,7 @@ main(int argc, char **argv) mbus_frame_data reply_data; mbus_handle *handle = NULL; - char *device, *addr_str; + char *device, *addr_str, *xml_result; int address, baudrate = 9600; if (argc == 3) @@ -145,8 +145,15 @@ main(int argc, char **argv) fprintf(stderr, "M-bus data parse error.\n"); return 1; } - - printf("%s", mbus_frame_data_xml(&reply_data)); + + if ((xml_result = mbus_frame_data_xml(&reply_data)) == NULL) + { + fprintf(stderr, "Failed to generate XML representation of MBUS frame: %s\n", mbus_error_str()); + return 1; + } + + printf("%s", xml_result); + free(xml_result); // manual free if (reply_data.data_var.record) diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c index aa0cf39..2323bec 100644 --- a/mbus/mbus-protocol-aux.c +++ b/mbus/mbus-protocol-aux.c @@ -1214,44 +1214,58 @@ mbus_data_variable_xml_normalized(mbus_data_variable *data) { mbus_data_record *record; mbus_record *norm_record; - static char buff[8192]; + char *buff = NULL; char str_encoded[768]; - size_t len = 0; + size_t len = 0, buff_size = 8192; size_t i; if (data) { - len += snprintf(&buff[len], sizeof(buff) - len, "\n\n"); + buff = (char*) malloc(buff_size); - len += snprintf(&buff[len], sizeof(buff) - len, "%s", mbus_data_variable_header_xml(&(data->header))); + if (buff == NULL) + return NULL; + + len += snprintf(&buff[len], buff_size - len, "\n\n"); + + len += snprintf(&buff[len], buff_size - len, "%s", mbus_data_variable_header_xml(&(data->header))); for (record = data->record, i = 0; record; record = record->next, i++) { norm_record = mbus_parse_variable_record(record); - len += snprintf(&buff[len], sizeof(buff) - len, " \n", i); + if ((buff_size - len) < 1024) + { + buff_size *= 2; + buff = (char*) realloc(buff,buff_size); + + if (buff == NULL) + return NULL; + } + + len += snprintf(&buff[len], buff_size - len, " \n", i); if (norm_record != NULL) { mbus_str_xml_encode(str_encoded, norm_record->function_medium, sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); mbus_str_xml_encode(str_encoded, norm_record->unit, sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); mbus_str_xml_encode(str_encoded, norm_record->quantity, sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); if (norm_record->is_numeric) { - len += snprintf(&buff[len], sizeof(buff) - len, " %f\n", norm_record->value.real_val); + len += snprintf(&buff[len], buff_size - len, " %f\n", norm_record->value.real_val); } else { mbus_str_xml_encode(str_encoded, norm_record->value.str_val.value, sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); } mbus_record_free(norm_record); @@ -1260,15 +1274,15 @@ mbus_data_variable_xml_normalized(mbus_data_variable *data) { } - len += snprintf(&buff[len], sizeof(buff) - len, " \n\n"); + len += snprintf(&buff[len], buff_size - len, " \n\n"); } - len += snprintf(&buff[len], sizeof(buff) - len, "\n"); + len += snprintf(&buff[len], buff_size - len, "\n"); return buff; } - return ""; + return NULL; } //------------------------------------------------------------------------------ @@ -1290,7 +1304,7 @@ mbus_frame_data_xml_normalized(mbus_frame_data *data) } } - return ""; + return NULL; } mbus_handle * diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index bd7d38f..af5118b 100644 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -3358,29 +3358,42 @@ char * mbus_data_variable_xml(mbus_data_variable *data) { mbus_data_record *record; - static char buff[8192]; - char str_encoded[768]; - size_t len = 0; + char *buff = NULL; + size_t len = 0, buff_size = 8192; int i; if (data) { - len += snprintf(&buff[len], sizeof(buff) - len, "\n\n"); + buff = (char*) malloc(buff_size); - len += snprintf(&buff[len], sizeof(buff) - len, "%s", + if (buff == NULL) + return NULL; + + len += snprintf(&buff[len], buff_size - len, "\n\n"); + + len += snprintf(&buff[len], buff_size - len, "%s", mbus_data_variable_header_xml(&(data->header))); for (record = data->record, i = 0; record; record = record->next, i++) { - len += snprintf(&buff[len], sizeof(buff) - len, "%s", + if ((buff_size - len) < 1024) + { + buff_size *= 2; + buff = (char*) realloc(buff,buff_size); + + if (buff == NULL) + return NULL; + } + + len += snprintf(&buff[len], buff_size - len, "%s", mbus_data_variable_record_xml(record, i, -1, &(data->header))); } - len += snprintf(&buff[len], sizeof(buff) - len, "\n"); + len += snprintf(&buff[len], buff_size - len, "\n"); return buff; } - return ""; + return NULL; } //------------------------------------------------------------------------------ @@ -3389,64 +3402,69 @@ mbus_data_variable_xml(mbus_data_variable *data) char * mbus_data_fixed_xml(mbus_data_fixed *data) { - static char buff[8192]; + char *buff = NULL; char str_encoded[256]; - size_t len = 0; + size_t len = 0, buff_size = 8192; if (data) { - len += snprintf(&buff[len], sizeof(buff) - len, "\n\n"); + buff = (char*) malloc(buff_size); + + if (buff == NULL) + return NULL; - len += snprintf(&buff[len], sizeof(buff) - len, " \n"); - len += snprintf(&buff[len], sizeof(buff) - len, " %d\n", (int)mbus_data_bcd_decode(data->id_bcd, 4)); + len += snprintf(&buff[len], buff_size - len, "\n\n"); + + len += snprintf(&buff[len], buff_size - len, " \n"); + len += snprintf(&buff[len], buff_size - len, " %d\n", (int)mbus_data_bcd_decode(data->id_bcd, 4)); mbus_str_xml_encode(str_encoded, mbus_data_fixed_medium(data), sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); - len += snprintf(&buff[len], sizeof(buff) - len, " %d\n", data->tx_cnt); - len += snprintf(&buff[len], sizeof(buff) - len, " %.2X\n", data->status); - len += snprintf(&buff[len], sizeof(buff) - len, " \n\n"); + len += snprintf(&buff[len], buff_size - len, " %d\n", data->tx_cnt); + len += snprintf(&buff[len], buff_size - len, " %.2X\n", data->status); + len += snprintf(&buff[len], buff_size - len, " \n\n"); - len += snprintf(&buff[len], sizeof(buff) - len, " \n"); + len += snprintf(&buff[len], buff_size - len, " \n"); mbus_str_xml_encode(str_encoded, mbus_data_fixed_function(data->status), sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); mbus_str_xml_encode(str_encoded, mbus_data_fixed_unit(data->cnt1_type), sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD) { - len += snprintf(&buff[len], sizeof(buff) - len, " %d\n", (int)mbus_data_bcd_decode(data->cnt1_val, 4)); + len += snprintf(&buff[len], buff_size - len, " %d\n", (int)mbus_data_bcd_decode(data->cnt1_val, 4)); } else { - len += snprintf(&buff[len], sizeof(buff) - len, " %d\n", mbus_data_int_decode(data->cnt1_val, 4)); + len += snprintf(&buff[len], buff_size - len, " %d\n", mbus_data_int_decode(data->cnt1_val, 4)); } - len += snprintf(&buff[len], sizeof(buff) - len, " \n\n"); + len += snprintf(&buff[len], buff_size - len, " \n\n"); - len += snprintf(&buff[len], sizeof(buff) - len, " \n"); + len += snprintf(&buff[len], buff_size - len, " \n"); mbus_str_xml_encode(str_encoded, mbus_data_fixed_function(data->status), sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); mbus_str_xml_encode(str_encoded, mbus_data_fixed_unit(data->cnt2_type), sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD) { - len += snprintf(&buff[len], sizeof(buff) - len, " %d\n", (int)mbus_data_bcd_decode(data->cnt2_val, 4)); + len += snprintf(&buff[len], buff_size - len, " %d\n", (int)mbus_data_bcd_decode(data->cnt2_val, 4)); } else { - len += snprintf(&buff[len], sizeof(buff) - len, " %d\n", mbus_data_int_decode(data->cnt2_val, 4)); + len += snprintf(&buff[len], buff_size - len, " %d\n", mbus_data_int_decode(data->cnt2_val, 4)); } - len += snprintf(&buff[len], sizeof(buff) - len, " \n\n"); + len += snprintf(&buff[len], buff_size - len, " \n\n"); - len += snprintf(&buff[len], sizeof(buff) - len, "\n"); + len += snprintf(&buff[len], buff_size - len, "\n"); return buff; } - return ""; + return NULL; } //------------------------------------------------------------------------------ @@ -3455,20 +3473,25 @@ mbus_data_fixed_xml(mbus_data_fixed *data) char * mbus_data_error_xml(int error) { - static char buff[512]; + char *buff = NULL; char str_encoded[256]; - size_t len = 0; - - len += snprintf(&buff[len], sizeof(buff) - len, "\n\n"); + size_t len = 0, buff_size = 8192; - len += snprintf(&buff[len], sizeof(buff) - len, " \n"); + buff = (char*) malloc(buff_size); + + if (buff == NULL) + return NULL; + + len += snprintf(&buff[len], buff_size - len, "\n\n"); + + len += snprintf(&buff[len], buff_size - len, " \n"); mbus_str_xml_encode(str_encoded, mbus_data_error_lookup(error), sizeof(str_encoded)); - len += snprintf(&buff[len], sizeof(buff) - len, " %s\n", str_encoded); + len += snprintf(&buff[len], buff_size - len, " %s\n", str_encoded); - len += snprintf(&buff[len], sizeof(buff) - len, " \n\n"); + len += snprintf(&buff[len], buff_size - len, " \n\n"); - len += snprintf(&buff[len], sizeof(buff) - len, "\n"); + len += snprintf(&buff[len], buff_size - len, "\n"); return buff; } @@ -3497,7 +3520,7 @@ mbus_frame_data_xml(mbus_frame_data *data) } } - return ""; + return NULL; } @@ -3511,9 +3534,9 @@ mbus_frame_xml(mbus_frame *frame) mbus_frame *iter; mbus_data_record *record; - static char buff[8192]; + char *buff = NULL; - size_t len = 0; + size_t len = 0, buff_size = 8192; int record_cnt = 0, frame_cnt; if (frame) @@ -3544,25 +3567,39 @@ mbus_frame_xml(mbus_frame *frame) { // // generate XML for a sequence of variable data frames - // + // + + buff = (char*) malloc(buff_size); + + if (buff == NULL) + return NULL; // include frame counter in XML output if more than one frame // is available (frame_cnt = -1 => not included in output) frame_cnt = (frame->next == NULL) ? -1 : 0; - len += snprintf(&buff[len], sizeof(buff) - len, "\n\n"); + len += snprintf(&buff[len], buff_size - len, "\n\n"); // only print the header info for the first frame (should be // the same for each frame in a sequence of a multi-telegram // transfer. - len += snprintf(&buff[len], sizeof(buff) - len, "%s", + len += snprintf(&buff[len], buff_size - len, "%s", mbus_data_variable_header_xml(&(frame_data.data_var.header))); // loop through all records in the current frame, using a global // record count as record ID in the XML output for (record = frame_data.data_var.record; record; record = record->next, record_cnt++) { - len += snprintf(&buff[len], sizeof(buff) - len, "%s", + if ((buff_size - len) < 1024) + { + buff_size *= 2; + buff = (char*) realloc(buff,buff_size); + + if (buff == NULL) + return NULL; + } + + len += snprintf(&buff[len], buff_size - len, "%s", mbus_data_variable_record_xml(record, record_cnt, frame_cnt, &(frame_data.data_var.header))); } @@ -3586,7 +3623,16 @@ mbus_frame_xml(mbus_frame *frame) // record count as record ID in the XML output for (record = frame_data.data_var.record; record; record = record->next, record_cnt++) { - len += snprintf(&buff[len], sizeof(buff) - len, "%s", + if ((buff_size - len) < 1024) + { + buff_size *= 2; + buff = (char*) realloc(buff,buff_size); + + if (buff == NULL) + return NULL; + } + + len += snprintf(&buff[len], buff_size - len, "%s", mbus_data_variable_record_xml(record, record_cnt, frame_cnt, &(frame_data.data_var.header))); } @@ -3595,15 +3641,15 @@ mbus_frame_xml(mbus_frame *frame) { mbus_data_record_free(frame_data.data_var.record); } - } + } - len += snprintf(&buff[len], sizeof(buff) - len, "\n"); + len += snprintf(&buff[len], buff_size - len, "\n"); return buff; } } - return ""; + return NULL; } diff --git a/test/mbus_parse.c b/test/mbus_parse.c index 69499b2..f55eb5e 100644 --- a/test/mbus_parse.c +++ b/test/mbus_parse.c @@ -28,6 +28,7 @@ main(int argc, char *argv[]) u_char buf[1024]; mbus_frame reply; mbus_frame_data frame_data; + char *xml_result = NULL; if (argc != 2) { @@ -51,7 +52,15 @@ main(int argc, char *argv[]) mbus_parse(&reply, buf, len); mbus_frame_data_parse(&reply, &frame_data); mbus_frame_print(&reply); - printf("%s", mbus_frame_data_xml(&frame_data)); + + if ((xml_result = mbus_frame_data_xml(&frame_data)) == NULL) + { + fprintf(stderr, "Failed to generate XML representation of MBUS frame: %s\n", mbus_error_str()); + return 1; + } + printf("%s", xml_result); + free(xml_result); + return 0; } diff --git a/test/mbus_parse_hex.c b/test/mbus_parse_hex.c index 41b9278..75f819d 100644 --- a/test/mbus_parse_hex.c +++ b/test/mbus_parse_hex.c @@ -28,6 +28,7 @@ main(int argc, char *argv[]) u_char raw_buff[4096], buff[4096], *ptr, *endptr; mbus_frame reply; mbus_frame_data frame_data; + char *xml_result = NULL; if (argc != 2) { @@ -89,7 +90,16 @@ main(int argc, char *argv[]) //mbus_frame_print(&reply); //mbus_frame_data_print(&frame_data); - printf("%s", mbus_frame_data_xml(&frame_data)); + + if ((xml_result = mbus_frame_data_xml(&frame_data)) == NULL) + { + fprintf(stderr, "Failed to generate XML representation of MBUS frame: %s\n", mbus_error_str()); + return 1; + } + printf("%s", xml_result); + free(xml_result); + + return 0; } From 49b49d077b0e631bd2a87f0d7b0cdbe4a824d146 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 29 May 2012 21:34:20 +0200 Subject: [PATCH 7/7] Sync behaviour from serial to TCP connections --- bin/mbus-tcp-request-data-multi-reply.c | 33 +++++++++++++++++-- bin/mbus-tcp-request-data.c | 12 +++++-- bin/mbus-tcp-scan-secondary.c | 44 +++++++++++++++++++++++-- bin/mbus-tcp-scan.c | 40 ++++++++++++++++++---- 4 files changed, 117 insertions(+), 12 deletions(-) diff --git a/bin/mbus-tcp-request-data-multi-reply.c b/bin/mbus-tcp-request-data-multi-reply.c index e85e8e1..e06c022 100644 --- a/bin/mbus-tcp-request-data-multi-reply.c +++ b/bin/mbus-tcp-request-data-multi-reply.c @@ -20,12 +20,12 @@ static int debug = 0; //------------------------------------------------------------------------------ -// Execution starts here: +// Scan for devices using secondary addressing. //------------------------------------------------------------------------------ int main(int argc, char **argv) { - mbus_frame reply, *reply_iter; + mbus_frame *frame, reply; mbus_frame_data reply_data; mbus_handle *handle = NULL; @@ -67,6 +67,33 @@ main(int argc, char **argv) fprintf(stderr, "Failed to setup connection to M-bus gateway\n"); return 1; } + + // + // init slave to get really the beginning of the records + // + + frame = mbus_frame_new(MBUS_FRAME_TYPE_SHORT); + + if (frame == NULL) + { + fprintf(stderr, "Failed to allocate mbus frame.\n"); + return 1; + } + + frame->control = MBUS_CONTROL_MASK_SND_NKE | MBUS_CONTROL_MASK_DIR_M2S; + frame->address = MBUS_ADDRESS_BROADCAST_NOREPLY; + + if (debug) + printf("%s: debug: sending init frame\n", __PRETTY_FUNCTION__); + + if (mbus_send_frame(handle, frame) == -1) + { + fprintf(stderr, "Failed to send mbus frame.\n"); + mbus_frame_free(frame); + return 1; + } + + mbus_recv_frame(handle, &reply); if (strlen(addr_str) == 16) { @@ -125,7 +152,9 @@ main(int argc, char **argv) fprintf(stderr, "Failed to generate XML representation of MBUS frames: %s\n", mbus_error_str()); return 1; } + printf("%s", xml_result); + free(xml_result); mbus_disconnect(handle); return 0; diff --git a/bin/mbus-tcp-request-data.c b/bin/mbus-tcp-request-data.c index 6f91be4..7b40f28 100644 --- a/bin/mbus-tcp-request-data.c +++ b/bin/mbus-tcp-request-data.c @@ -29,7 +29,7 @@ main(int argc, char **argv) mbus_frame_data reply_data; mbus_handle *handle = NULL; - char *host, *addr_str, matching_addr[16]; + char *host, *addr_str, matching_addr[16], *xml_result; int port, address; memset((void *)&reply, 0, sizeof(mbus_frame)); @@ -130,7 +130,15 @@ main(int argc, char **argv) fprintf(stderr, "M-bus data parse error.\n"); return 1; } - printf("%s", mbus_frame_data_xml(&reply_data)); + + if ((xml_result = mbus_frame_data_xml(&reply_data)) == NULL) + { + fprintf(stderr, "Failed to generate XML representation of MBUS frame: %s\n", mbus_error_str()); + return 1; + } + + printf("%s", xml_result); + free(xml_result); // manual free if (reply_data.data_var.record) diff --git a/bin/mbus-tcp-scan-secondary.c b/bin/mbus-tcp-scan-secondary.c index ff6cb84..e2cca2a 100644 --- a/bin/mbus-tcp-scan-secondary.c +++ b/bin/mbus-tcp-scan-secondary.c @@ -17,8 +17,7 @@ #include #include -static mbus_handle *handle = NULL; - +static int debug = 0; //------------------------------------------------------------------------------ // Execution starts here: @@ -28,6 +27,10 @@ main(int argc, char **argv) { char *host, *addr_mask; int port; + mbus_handle *handle = NULL; + mbus_frame *frame = NULL, reply; + + memset((void *)&reply, 0, sizeof(mbus_frame)); if (argc != 4 && argc != 3) { @@ -59,6 +62,43 @@ main(int argc, char **argv) fprintf(stderr, "Failed to setup connection to M-bus gateway: %s\n", mbus_error_str()); return 1; } + + frame = mbus_frame_new(MBUS_FRAME_TYPE_SHORT); + + if (frame == NULL) + { + fprintf(stderr, "Failed to allocate mbus frame.\n"); + return 1; + } + + // + // init slaves + // + frame->control = MBUS_CONTROL_MASK_SND_NKE | MBUS_CONTROL_MASK_DIR_M2S; + frame->address = 0xFD; + + if (mbus_send_frame(handle, frame) == -1) + { + fprintf(stderr, "Failed to send SND_NKE #1.\n"); + mbus_frame_free(frame); + return 1; + } + + (void) mbus_recv_frame(handle, &reply); + sleep(1); + + frame->control = MBUS_CONTROL_MASK_SND_NKE | MBUS_CONTROL_MASK_DIR_M2S; + frame->address = 0xFF; + + if (mbus_send_frame(handle, frame) == -1) + { + fprintf(stderr, "Failed to send SND_NKE #2.\n"); + mbus_frame_free(frame); + return 1; + } + + (void) mbus_recv_frame(handle, &reply); + sleep(1); mbus_scan_2nd_address_range(handle, 0, addr_mask); diff --git a/bin/mbus-tcp-scan.c b/bin/mbus-tcp-scan.c index 1d412c8..d6dcee4 100644 --- a/bin/mbus-tcp-scan.c +++ b/bin/mbus-tcp-scan.c @@ -27,6 +27,7 @@ main(int argc, char **argv) mbus_handle *handle; char *host; int port, address, debug = 0; + int ret; if (argc == 3) { @@ -59,11 +60,13 @@ main(int argc, char **argv) if (debug) printf("Scanning primary addresses:\n"); - - for (address = 0; address < 254; address++) + + for (address = 0; address <= 250; address++) { mbus_frame reply; + memset((void *)&reply, 0, sizeof(mbus_frame)); + if (debug) { printf("%d ", address); @@ -75,16 +78,41 @@ main(int argc, char **argv) printf("Scan failed. Could not send ping frame: %s\n", mbus_error_str()); return 1; } + + ret = mbus_recv_frame(handle, &reply); - if (mbus_recv_frame(handle, &reply) == -1) + if (ret == -1) { continue; - } + } + + if (debug) + printf("\n"); + + if (ret == -2) + { + /* check for more data (collision) */ + while (mbus_recv_frame(handle, &reply) != -1); + + printf("Collision at address %d\n", address); + + continue; + } if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK) { - if (debug) - printf("\n"); + /* check for more data (collision) */ + while (mbus_recv_frame(handle, &reply) != -1) + { + ret = -2; + } + + if (ret == -2) + { + printf("Collision at address %d\n", address); + + continue; + } printf("Found a M-Bus device at address %d\n", address); }