From 90aec91bff5d0337a42475f79d4fac1af3193c42 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 15 May 2012 22:57:03 +0200 Subject: [PATCH 1/4] Added frame tracing (hex format) via debug switch --- bin/mbus-serial-request-data-multi-reply.c | 6 ++ bin/mbus-serial-request-data.c | 6 ++ bin/mbus-serial-scan-secondary.c | 38 ++++++++++++- bin/mbus-serial-scan.c | 10 +++- bin/mbus-serial-select-secondary.c | 3 +- bin/mbus-tcp-request-data-multi-reply.c | 6 ++ bin/mbus-tcp-request-data.c | 6 ++ bin/mbus-tcp-scan.c | 6 ++ mbus/mbus-protocol.c | 65 +++++++++++++++++----- mbus/mbus-protocol.h | 12 ++-- 10 files changed, 137 insertions(+), 21 deletions(-) diff --git a/bin/mbus-serial-request-data-multi-reply.c b/bin/mbus-serial-request-data-multi-reply.c index 46bcbe5..eedc02a 100644 --- a/bin/mbus-serial-request-data-multi-reply.c +++ b/bin/mbus-serial-request-data-multi-reply.c @@ -66,6 +66,12 @@ main(int argc, char **argv) fprintf(stderr, " optional flag -b for selecting baudrate\n"); return 0; } + + if (debug) + { + mbus_register_send_event(&mbus_dump_send_event); + mbus_register_recv_event(&mbus_dump_recv_event); + } if ((handle = mbus_connect_serial(device)) == NULL) { diff --git a/bin/mbus-serial-request-data.c b/bin/mbus-serial-request-data.c index 336cc35..6d0826b 100644 --- a/bin/mbus-serial-request-data.c +++ b/bin/mbus-serial-request-data.c @@ -63,6 +63,12 @@ main(int argc, char **argv) fprintf(stderr, " optional flag -b for selecting baudrate\n"); return 0; } + + if (debug) + { + mbus_register_send_event(&mbus_dump_send_event); + mbus_register_recv_event(&mbus_dump_recv_event); + } if ((handle = mbus_connect_serial(device)) == NULL) { diff --git a/bin/mbus-serial-scan-secondary.c b/bin/mbus-serial-scan-secondary.c index 942f673..3909c49 100644 --- a/bin/mbus-serial-scan-secondary.c +++ b/bin/mbus-serial-scan-secondary.c @@ -17,6 +17,8 @@ #include #include +static int debug = 0; + //------------------------------------------------------------------------------ // Scan for devices using secondary addressing. //------------------------------------------------------------------------------ @@ -32,30 +34,64 @@ main(int argc, char **argv) device = argv[1]; addr_mask = strdup("FFFFFFFFFFFFFFFF"); } + else if (argc == 3 && strcmp(argv[1], "-d") == 0) + { + device = argv[2]; + addr_mask = strdup("FFFFFFFFFFFFFFFF"); + debug = 1; + } else if (argc == 3) { device = argv[1]; addr_mask = strdup(argv[2]); } + else if (argc == 4 && strcmp(argv[1], "-d") == 0) + { + device = argv[1]; + addr_mask = strdup(argv[2]); + debug = 1; + } else if (argc == 4 && strcmp(argv[1], "-b") == 0) { baudrate = atoi(argv[2]); device = argv[3]; addr_mask = strdup("FFFFFFFFFFFFFFFF"); } + else if (argc == 5 && strcmp(argv[1], "-d") == 0) + { + baudrate = atoi(argv[3]); + device = argv[4]; + addr_mask = strdup("FFFFFFFFFFFFFFFF"); + debug = 1; + } else if (argc == 5 && strcmp(argv[1], "-b") == 0) { baudrate = atoi(argv[2]); device = argv[3]; addr_mask = strdup(argv[4]); } + else if (argc == 6 && strcmp(argv[1], "-d") == 0) + { + baudrate = atoi(argv[3]); + device = argv[4]; + addr_mask = strdup(argv[5]); + debug = 1; + } else { - fprintf(stderr, "usage: %s [-b BAUDRATE] device [address-mask]\n", argv[0]); + fprintf(stderr, "usage: %s [-d] [-b BAUDRATE] device [address-mask]\n", argv[0]); + fprintf(stderr, "\toptional flag -d for debug printout\n"); + fprintf(stderr, "\toptional flag -b for selecting baudrate\n"); fprintf(stderr, "\trestrict the search by supplying an optional address mask on the form\n"); fprintf(stderr, "\t'FFFFFFFFFFFFFFFF' where F is a wildcard character\n"); return 0; } + + if (debug) + { + mbus_register_send_event(&mbus_dump_send_event); + mbus_register_recv_event(&mbus_dump_recv_event); + } if (strlen(addr_mask) != 16) { diff --git a/bin/mbus-serial-scan.c b/bin/mbus-serial-scan.c index 178cbbe..f0d1776 100644 --- a/bin/mbus-serial-scan.c +++ b/bin/mbus-serial-scan.c @@ -17,6 +17,8 @@ #include #include +static int debug = 0; + //------------------------------------------------------------------------------ // Primary addressing scanning of mbus devices. //------------------------------------------------------------------------------ @@ -25,7 +27,7 @@ main(int argc, char **argv) { mbus_handle *handle; char *device; - int address, baudrate = 9600, debug = 0; + int address, baudrate = 9600; if (argc == 2) { @@ -53,6 +55,12 @@ main(int argc, char **argv) return 0; } + if (debug) + { + mbus_register_send_event(&mbus_dump_send_event); + mbus_register_recv_event(&mbus_dump_recv_event); + } + if ((handle = mbus_connect_serial(device)) == NULL) { printf("Failed to setup connection to M-bus gateway\n"); diff --git a/bin/mbus-serial-select-secondary.c b/bin/mbus-serial-select-secondary.c index 98536ba..a5b7067 100644 --- a/bin/mbus-serial-select-secondary.c +++ b/bin/mbus-serial-select-secondary.c @@ -42,7 +42,8 @@ main(int argc, char **argv) } else { - fprintf(stderr, "usage: %s device secondary-mbus-address\n", argv[0]); + fprintf(stderr, "usage: %s [-b BAUDRATE] device secondary-mbus-address\n", argv[0]); + fprintf(stderr, " optional flag -b for selecting baudrate\n"); return 0; } diff --git a/bin/mbus-tcp-request-data-multi-reply.c b/bin/mbus-tcp-request-data-multi-reply.c index 91ea0c1..5ae94b0 100644 --- a/bin/mbus-tcp-request-data-multi-reply.c +++ b/bin/mbus-tcp-request-data-multi-reply.c @@ -56,6 +56,12 @@ main(int argc, char **argv) return 0; } + if (debug) + { + mbus_register_send_event(&mbus_dump_send_event); + mbus_register_recv_event(&mbus_dump_recv_event); + } + if ((handle = mbus_connect_tcp(host, port)) == NULL) { fprintf(stderr, "Failed to setup connection to M-bus gateway\n"); diff --git a/bin/mbus-tcp-request-data.c b/bin/mbus-tcp-request-data.c index 274829c..0d8db18 100644 --- a/bin/mbus-tcp-request-data.c +++ b/bin/mbus-tcp-request-data.c @@ -56,6 +56,12 @@ main(int argc, char **argv) return 0; } + if (debug) + { + mbus_register_send_event(&mbus_dump_send_event); + mbus_register_recv_event(&mbus_dump_recv_event); + } + if ((handle = mbus_connect_tcp(host, port)) == NULL) { fprintf(stderr, "Failed to setup connection to M-bus gateway\n"); diff --git a/bin/mbus-tcp-scan.c b/bin/mbus-tcp-scan.c index 7633b00..1d412c8 100644 --- a/bin/mbus-tcp-scan.c +++ b/bin/mbus-tcp-scan.c @@ -44,6 +44,12 @@ main(int argc, char **argv) printf("usage: %s [-d] host port\n", argv[0]); return 0; } + + if (debug) + { + mbus_register_send_event(&mbus_dump_send_event); + mbus_register_recv_event(&mbus_dump_recv_event); + } if ((handle = mbus_connect_tcp(host, port)) == NULL) { diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index e5296f3..2f0ffd8 100644 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -28,8 +28,23 @@ static mbus_slave_data slave_data[MBUS_MAX_PRIMARY_SLAVES]; // // init event callback // -void (*_mbus_recv_event)(u_char src_type) = NULL; -void (*_mbus_send_event)(u_char src_type) = NULL; +void (*_mbus_recv_event)(u_char src_type, const char *buff, size_t len) = NULL; +void (*_mbus_send_event)(u_char src_type, const char *buff, size_t len) = NULL; + +// +// trace callbacks +// +void +mbus_dump_recv_event(u_char src_type, const char *buff, size_t len) +{ + mbus_hex_dump("RECV", buff, len); +} + +void +mbus_dump_send_event(u_char src_type, const char *buff, size_t len) +{ + mbus_hex_dump("SEND", buff, len); +} //------------------------------------------------------------------------------ /// Register a function for receive events. @@ -44,7 +59,7 @@ mbus_register_recv_event(void (*event)(u_char src_type)) /// Register a function for send events. //------------------------------------------------------------------------------ void -mbus_register_send_event(void (*event)(u_char src_type)) +mbus_register_send_event(void (*event)(u_char src_type, const char *buff, size_t len)) { _mbus_send_event = event; } @@ -316,11 +331,11 @@ mbus_frame_verify(mbus_frame *frame) return -1; } - if ((frame->control != MBUS_CONTROL_MASK_SND_NKE) && - (frame->control != MBUS_CONTROL_MASK_REQ_UD1) && - (frame->control != MBUS_CONTROL_MASK_REQ_UD1 | MBUS_CONTROL_MASK_FCB) && - (frame->control != MBUS_CONTROL_MASK_REQ_UD2) && - (frame->control != MBUS_CONTROL_MASK_REQ_UD2 | MBUS_CONTROL_MASK_FCB)) + if ((frame->control != MBUS_CONTROL_MASK_SND_NKE) && + (frame->control != MBUS_CONTROL_MASK_REQ_UD1) && + (frame->control != (MBUS_CONTROL_MASK_REQ_UD1 | MBUS_CONTROL_MASK_FCB)) && + (frame->control != MBUS_CONTROL_MASK_REQ_UD2) && + (frame->control != (MBUS_CONTROL_MASK_REQ_UD2 | MBUS_CONTROL_MASK_FCB))) { snprintf(error_str, sizeof(error_str), "Unknown Control Code 0x%.2x", frame->control); @@ -339,12 +354,12 @@ mbus_frame_verify(mbus_frame *frame) return -1; } - if ((frame->control != MBUS_CONTROL_MASK_SND_UD) && - (frame->control != MBUS_CONTROL_MASK_SND_UD | MBUS_CONTROL_MASK_FCB) && - (frame->control != MBUS_CONTROL_MASK_RSP_UD) && - (frame->control != MBUS_CONTROL_MASK_RSP_UD | MBUS_CONTROL_MASK_DFC) && - (frame->control != MBUS_CONTROL_MASK_RSP_UD | MBUS_CONTROL_MASK_ACD) && - (frame->control != MBUS_CONTROL_MASK_RSP_UD | MBUS_CONTROL_MASK_DFC | MBUS_CONTROL_MASK_ACD)) + if ((frame->control != MBUS_CONTROL_MASK_SND_UD) && + (frame->control != (MBUS_CONTROL_MASK_SND_UD | MBUS_CONTROL_MASK_FCB)) && + (frame->control != MBUS_CONTROL_MASK_RSP_UD) && + (frame->control != (MBUS_CONTROL_MASK_RSP_UD | MBUS_CONTROL_MASK_DFC)) && + (frame->control != (MBUS_CONTROL_MASK_RSP_UD | MBUS_CONTROL_MASK_ACD)) && + (frame->control != (MBUS_CONTROL_MASK_RSP_UD | MBUS_CONTROL_MASK_DFC | MBUS_CONTROL_MASK_ACD))) { snprintf(error_str, sizeof(error_str), "Unknown Control Code 0x%.2x", frame->control); @@ -2942,6 +2957,28 @@ mbus_data_fixed_print(mbus_data_fixed *data) return -1; } +void +mbus_hex_dump(const char *label, const char *buff, size_t len) +{ + time_t rawtime; + struct tm * timeinfo; + char timestamp[21]; + size_t i; + + time ( &rawtime ); + timeinfo = gmtime ( &rawtime ); + + strftime(timestamp,20,"%Y-%m-%d %H:%M:%S",timeinfo); + fprintf(stderr, "[%s] %s (%03d):", timestamp, label, len); + + for (i = 0; i < len; i++) + { + fprintf(stderr, " %02X", (u_char) buff[i]); + } + + fprintf(stderr, "\n"); +} + int mbus_data_error_print(int error) { diff --git a/mbus/mbus-protocol.h b/mbus/mbus-protocol.h index 2c9cc50..d21adc9 100644 --- a/mbus/mbus-protocol.h +++ b/mbus/mbus-protocol.h @@ -462,14 +462,17 @@ typedef struct _mbus_data_secondary_address { // // Event callback functions // -extern void (*_mbus_recv_event)(u_char src_type); -extern void (*_mbus_send_event)(u_char src_type); +extern void (*_mbus_recv_event)(u_char src_type, const char *buff, size_t len); +extern void (*_mbus_send_event)(u_char src_type, const char *buff, size_t len); + +void mbus_dump_recv_event(u_char src_type, const char *buff, size_t len); +void mbus_dump_send_event(u_char src_type, const char *buff, size_t len); // // Event register functions // -void mbus_register_recv_event(void (*event)(u_char src_type)); -void mbus_register_send_event(void (*event)(u_char src_type)); +void mbus_register_recv_event(void (*event)(u_char src_type, const char *buff, size_t len)); +void mbus_register_send_event(void (*event)(u_char src_type, const char *buff, size_t len)); // // variable length records @@ -554,6 +557,7 @@ void mbus_error_str_set(char *message); void mbus_error_reset(); void mbus_parse_set_debug(int debug); +void mbus_hex_dump(const char *label, const char *buff, size_t len); // // data encode/decode functions From f7c644bee6d8d361f1610685c81c48b0eee57552 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 15 May 2012 23:06:14 +0200 Subject: [PATCH 2/4] Fixed output format of secondary address (always 16 digits, leading zeros) --- mbus/mbus-protocol.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index 9fd9bd0..8a717b4 100644 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -3496,6 +3496,7 @@ mbus_frame_get_secondary_address(mbus_frame *frame) { static char addr[32]; mbus_frame_data *data; + long id; if (frame == NULL || (data = mbus_frame_data_new()) == NULL) { @@ -3514,8 +3515,10 @@ mbus_frame_get_secondary_address(mbus_frame *frame) return NULL; } - snprintf(addr, sizeof(addr), "%.6d%.2X%.2X%.2X%.2X", - (int)mbus_data_bcd_decode(data->data_var.header.id_bcd, 4), + id = (long) mbus_data_bcd_decode(data->data_var.header.id_bcd, 4); + + snprintf(addr, sizeof(addr), "%08lu%02X%02X%02X%02X", + id, data->data_var.header.manufacturer[0], data->data_var.header.manufacturer[1], data->data_var.header.version, From 980bbb1862f2e7ac89b615d78811ef0b857486cd Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 15 May 2012 23:17:49 +0200 Subject: [PATCH 3/4] Fixed baud rate switching: - added missing call of tcsetattr - handle return values - adjust timeout correctly --- mbus/mbus-serial.c | 52 +++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/mbus/mbus-serial.c b/mbus/mbus-serial.c index ecb28e9..08c4d7d 100644 --- a/mbus/mbus-serial.c +++ b/mbus/mbus-serial.c @@ -75,7 +75,7 @@ mbus_serial_connect(char *device) // For 2400Bd this means (330 + 11) / 2400 + 0.05 = 188.75 ms (added 11 bit periods to receive first byte). // I.e. timeout of 0.2s seems appropriate for 2400Bd. - handle->t.c_cc[VTIME] = 2; + handle->t.c_cc[VTIME] = 2; // Timeout in 1/10 sec cfsetispeed(&(handle->t), B2400); cfsetospeed(&(handle->t), B2400); @@ -93,39 +93,61 @@ mbus_serial_connect(char *device) } //------------------------------------------------------------------------------ -// +// Set baud rate for serial connection //------------------------------------------------------------------------------ int mbus_serial_set_baudrate(mbus_serial_handle *handle, int baudrate) { + speed_t speed; + if (handle == NULL) return -1; switch (baudrate) { case 300: - cfsetispeed(&(handle->t), B300); - cfsetospeed(&(handle->t), B300); - return 0; + speed = B300; + handle->t.c_cc[VTIME] = 12; // Timeout in 1/10 sec + break; case 1200: - cfsetispeed(&(handle->t), B1200); - cfsetospeed(&(handle->t), B1200); - return 0; + speed = B1200; + handle->t.c_cc[VTIME] = 4; // Timeout in 1/10 sec + break; case 2400: - cfsetispeed(&(handle->t), B2400); - cfsetospeed(&(handle->t), B2400); - return 0; + speed = B2400; + handle->t.c_cc[VTIME] = 2; // Timeout in 1/10 sec + break; case 9600: - cfsetispeed(&(handle->t), B9600); - cfsetospeed(&(handle->t), B9600); - return 0; + speed = B9600; + handle->t.c_cc[VTIME] = 1; // Timeout in 1/10 sec + break; default: - return -1; // unsupported baudrate + return -1; // unsupported baudrate } + + // Set input baud rate + if (cfsetispeed(&(handle->t), speed) != 0) + { + return -1; + } + + // Set output baud rate + if (cfsetospeed(&(handle->t), speed) != 0) + { + return -1; + } + + // Change baud rate immediately + if (tcsetattr(handle->fd, TCSANOW, &(handle->t)) != 0) + { + return -1; + } + + return 0; } From f14b3beb84101c90c8eea0cc024f6ce658dea4ab Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 15 May 2012 23:30:55 +0200 Subject: [PATCH 4/4] Fixed bugs in wildcard search - init slaves before search - corrected return codes - handle collisions (possibly more bytes than expected) - sync recv frame (tcp vs serial) - add tracing --- bin/mbus-serial-scan-secondary.c | 37 ++++++++++++++++++++++++++++++++ mbus/mbus-protocol-aux.c | 23 +++++++++++++++++++- mbus/mbus-serial.c | 30 ++++++++++++++------------ mbus/mbus-tcp.c | 26 +++++++++++----------- 4 files changed, 89 insertions(+), 27 deletions(-) diff --git a/bin/mbus-serial-scan-secondary.c b/bin/mbus-serial-scan-secondary.c index 3909c49..c6e282e 100644 --- a/bin/mbus-serial-scan-secondary.c +++ b/bin/mbus-serial-scan-secondary.c @@ -28,6 +28,7 @@ main(int argc, char **argv) char *device, *addr_mask; int baudrate = 9600; mbus_handle *handle = NULL; + mbus_frame *frame = NULL, *reply = NULL; if (argc == 2) { @@ -111,6 +112,42 @@ main(int argc, char **argv) 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); + + 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); + mbus_scan_2nd_address_range(handle, 0, addr_mask); mbus_disconnect(handle); diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c index 52e336f..84ea5a5 100644 --- a/mbus/mbus-protocol-aux.c +++ b/mbus/mbus-protocol-aux.c @@ -1711,11 +1711,25 @@ mbus_probe_secondary_address(mbus_handle * handle, const char *mask, char *match if (ret == -2) { + /* check for more data (collision) */ + while (mbus_recv_frame(handle, &reply) != -1); + return MBUS_PROBE_COLLISION; } if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK) { + /* check for more data (collision) */ + while (mbus_recv_frame(handle, &reply) != -1) + { + ret = -2; + } + + if (ret == -2) + { + return MBUS_PROBE_COLLISION; + } + /* send a data request command to find out the full address */ if (mbus_send_request_frame(handle, 253) == -1) { @@ -1726,11 +1740,18 @@ mbus_probe_secondary_address(mbus_handle * handle, const char *mask, char *match return MBUS_PROBE_ERROR; } - if (mbus_recv_frame(handle, &reply) == -1) + ret = mbus_recv_frame(handle, &reply); + + if (ret == -1) { return MBUS_PROBE_NOTHING; } + if (ret == -2) + { + return MBUS_PROBE_COLLISION; + } + if (mbus_frame_type(&reply) != MBUS_FRAME_TYPE_ACK) { snprintf(matching_addr, 17, "%s", mbus_frame_get_secondary_address(&reply)); diff --git a/mbus/mbus-serial.c b/mbus/mbus-serial.c index 08c4d7d..784bfa0 100644 --- a/mbus/mbus-serial.c +++ b/mbus/mbus-serial.c @@ -205,7 +205,7 @@ mbus_serial_send_frame(mbus_serial_handle *handle, mbus_frame *frame) // call the send event function, if the callback function is registered // if (_mbus_send_event) - _mbus_send_event(MBUS_HANDLE_TYPE_SERIAL); + _mbus_send_event(MBUS_HANDLE_TYPE_SERIAL, buff, len); } else { @@ -236,17 +236,7 @@ mbus_serial_recv_frame(mbus_serial_handle *handle, mbus_frame *frame) do { //printf("%s: Attempt to read %d bytes [len = %d]\n", __PRETTY_FUNCTION__, remaining, len); - nread = read(handle->fd, &buff[len], remaining); - - if (nread > 0) - { - // - // call the receive event function, if the callback function is registered - // - if (_mbus_recv_event) - _mbus_recv_event(MBUS_HANDLE_TYPE_SERIAL); - } - else if (nread == -1) + if ((nread = read(handle->fd, &buff[len], remaining)) == -1) { // fprintf(stderr, "%s: aborting recv frame (remaining = %d, len = %d, nread = %d)\n", // __PRETTY_FUNCTION__, remaining, len, nread); @@ -258,12 +248,24 @@ mbus_serial_recv_frame(mbus_serial_handle *handle, mbus_frame *frame) len += nread; } while ((remaining = mbus_parse(frame, buff, len)) > 0); + + if (len == 0) + { + // No data received + return -1; + } + + // + // call the receive event function, if the callback function is registered + // + 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__); - return -1; + return -2; } if (len == -1) diff --git a/mbus/mbus-tcp.c b/mbus/mbus-tcp.c index 62d21e2..2911e89 100644 --- a/mbus/mbus-tcp.c +++ b/mbus/mbus-tcp.c @@ -144,7 +144,7 @@ mbus_tcp_send_frame(mbus_tcp_handle *handle, mbus_frame *frame) // call the send event function, if the callback function is registered // if (_mbus_send_event) - _mbus_send_event(MBUS_HANDLE_TYPE_TCP); + _mbus_send_event(MBUS_HANDLE_TYPE_TCP, buff, len); } else { @@ -176,17 +176,7 @@ mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame) do { - nread = read(handle->sock, &buff[len], remaining); - - if (nread > 0) - { - // - // call the receive event function, if the callback function is registered - // - if (_mbus_recv_event) - _mbus_recv_event(MBUS_HANDLE_TYPE_TCP); - } - else if (nread == -1) + if ((nread = read(handle->sock, &buff[len], remaining)) == -1) { mbus_error_str_set("M-Bus tcp transport layer failed to read data."); return -1; @@ -195,6 +185,18 @@ mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame) len += nread; } while ((remaining = mbus_parse(frame, buff, len)) > 0); + + if (len == 0) + { + // No data received + return -1; + } + + // + // call the receive event function, if the callback function is registered + // + if (_mbus_recv_event) + _mbus_recv_event(MBUS_HANDLE_TYPE_TCP, buff, len); if (remaining < 0) {