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/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/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); } diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c index 6fd052c..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 * @@ -1367,6 +1381,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 +1391,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..af5118b 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; } //------------------------------------------------------------------------------ @@ -2563,6 +2582,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 +3297,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 +3338,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; @@ -3329,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; } //------------------------------------------------------------------------------ @@ -3360,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; } //------------------------------------------------------------------------------ @@ -3426,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; } @@ -3468,7 +3520,7 @@ mbus_frame_data_xml(mbus_frame_data *data) } } - return ""; + return NULL; } @@ -3482,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) @@ -3515,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))); } @@ -3557,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))); } @@ -3566,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; } @@ -3733,7 +3808,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 diff --git a/mbus/mbus-protocol.h b/mbus/mbus-protocol.h index 70b6847..5fa5298 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; @@ -462,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 @@ -475,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 // diff --git a/mbus/mbus-serial.c b/mbus/mbus-serial.c index ec6b112..71b90c2 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; @@ -267,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 17150fb..f29e8ce 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; @@ -205,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; 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; }