diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c index f7c241b..0b472e4 100644 --- a/mbus/mbus-protocol-aux.c +++ b/mbus/mbus-protocol-aux.c @@ -148,17 +148,17 @@ mbus_variable_vif vif_table[] = { { 0x56, 1.0e3, "kg/h", "Mass flow" }, { 0x57, 1.0e4, "kg/h", "Mass flow" }, - /* E101 10nn Flow Temperature °C (0.001°C to 1°C) */ - { 0x58, 1.0e-3, "°C", "Flow temperature" }, - { 0x59, 1.0e-2, "°C", "Flow temperature" }, - { 0x5A, 1.0e-1, "°C", "Flow temperature" }, - { 0x5B, 1.0e0, "°C", "Flow temperature" }, + /* E101 10nn Flow Temperature �C (0.001�C to 1�C) */ + { 0x58, 1.0e-3, "�C", "Flow temperature" }, + { 0x59, 1.0e-2, "�C", "Flow temperature" }, + { 0x5A, 1.0e-1, "�C", "Flow temperature" }, + { 0x5B, 1.0e0, "�C", "Flow temperature" }, - /* E101 11nn Return Temperature °C (0.001°C to 1°C) */ - { 0x5C, 1.0e-3, "°C", "Return temperature" }, - { 0x5D, 1.0e-2, "°C", "Return temperature" }, - { 0x5E, 1.0e-1, "°C", "Return temperature" }, - { 0x5F, 1.0e0, "°C", "Return temperature" }, + /* E101 11nn Return Temperature �C (0.001�C to 1�C) */ + { 0x5C, 1.0e-3, "�C", "Return temperature" }, + { 0x5D, 1.0e-2, "�C", "Return temperature" }, + { 0x5E, 1.0e-1, "�C", "Return temperature" }, + { 0x5F, 1.0e0, "�C", "Return temperature" }, /* E110 00nn Temperature Difference K (mK to K) */ { 0x60, 1.0e-3, "K", "Temperature difference" }, @@ -166,11 +166,11 @@ mbus_variable_vif vif_table[] = { { 0x62, 1.0e-1, "K", "Temperature difference" }, { 0x63, 1.0e0, "K", "Temperature difference" }, - /* E110 01nn External Temperature °C (0.001°C to 1°C) */ - { 0x64, 1.0e-3, "°C", "External temperature" }, - { 0x65, 1.0e-2, "°C", "External temperature" }, - { 0x66, 1.0e-1, "°C", "External temperature" }, - { 0x67, 1.0e0, "°C", "External temperature" }, + /* E110 01nn External Temperature �C (0.001�C to 1�C) */ + { 0x64, 1.0e-3, "�C", "External temperature" }, + { 0x65, 1.0e-2, "�C", "External temperature" }, + { 0x66, 1.0e-1, "�C", "External temperature" }, + { 0x67, 1.0e0, "�C", "External temperature" }, /* E110 10nn Pressure bar (1mbar to 1000mbar) */ { 0x68, 1.0e-3, "bar", "Pressure" }, @@ -562,29 +562,29 @@ mbus_variable_vif vif_table[] = { { 0x236, 1.0e0, "Reserved", "Reserved" }, { 0x237, 1.0e0, "Reserved", "Reserved" }, - /* E101 10nn Flow Temperature 10(nn-3) °F 0.001°F to 1°F */ - { 0x238, 1.0e-3, "°F", "Flow temperature" }, - { 0x239, 1.0e-2, "°F", "Flow temperature" }, - { 0x23A, 1.0e-1, "°F", "Flow temperature" }, - { 0x23B, 1.0e0, "°F", "Flow temperature" }, + /* E101 10nn Flow Temperature 10(nn-3) �F 0.001�F to 1�F */ + { 0x238, 1.0e-3, "�F", "Flow temperature" }, + { 0x239, 1.0e-2, "�F", "Flow temperature" }, + { 0x23A, 1.0e-1, "�F", "Flow temperature" }, + { 0x23B, 1.0e0, "�F", "Flow temperature" }, - /* E101 11nn Return Temperature 10(nn-3) °F 0.001°F to 1°F */ - { 0x23C, 1.0e-3, "°F", "Return temperature" }, - { 0x23D, 1.0e-2, "°F", "Return temperature" }, - { 0x23E, 1.0e-1, "°F", "Return temperature" }, - { 0x23F, 1.0e0, "°F", "Return temperature" }, + /* E101 11nn Return Temperature 10(nn-3) �F 0.001�F to 1�F */ + { 0x23C, 1.0e-3, "�F", "Return temperature" }, + { 0x23D, 1.0e-2, "�F", "Return temperature" }, + { 0x23E, 1.0e-1, "�F", "Return temperature" }, + { 0x23F, 1.0e0, "�F", "Return temperature" }, - /* E110 00nn Temperature Difference 10(nn-3) °F 0.001°F to 1°F */ - { 0x240, 1.0e-3, "°F", "Temperature difference" }, - { 0x241, 1.0e-2, "°F", "Temperature difference" }, - { 0x242, 1.0e-1, "°F", "Temperature difference" }, - { 0x243, 1.0e0, "°F", "Temperature difference" }, + /* E110 00nn Temperature Difference 10(nn-3) �F 0.001�F to 1�F */ + { 0x240, 1.0e-3, "�F", "Temperature difference" }, + { 0x241, 1.0e-2, "�F", "Temperature difference" }, + { 0x242, 1.0e-1, "�F", "Temperature difference" }, + { 0x243, 1.0e0, "�F", "Temperature difference" }, - /* E110 01nn External Temperature 10(nn-3) °F 0.001°F to 1°F */ - { 0x244, 1.0e-3, "°F", "External temperature" }, - { 0x245, 1.0e-2, "°F", "External temperature" }, - { 0x246, 1.0e-1, "°F", "External temperature" }, - { 0x247, 1.0e0, "°F", "External temperature" }, + /* E110 01nn External Temperature 10(nn-3) �F 0.001�F to 1�F */ + { 0x244, 1.0e-3, "�F", "External temperature" }, + { 0x245, 1.0e-2, "�F", "External temperature" }, + { 0x246, 1.0e-1, "�F", "External temperature" }, + { 0x247, 1.0e0, "�F", "External temperature" }, /* E110 1nnn Reserved */ { 0x248, 1.0e0, "Reserved", "Reserved" }, @@ -596,19 +596,19 @@ mbus_variable_vif vif_table[] = { { 0x24E, 1.0e0, "Reserved", "Reserved" }, { 0x24F, 1.0e0, "Reserved", "Reserved" }, - /* E111 00nn Cold / Warm Temperature Limit 10(nn-3) °F 0.001°F to 1°F */ - { 0x250, 1.0e-3, "°F", "Cold / Warm Temperature Limit" }, - { 0x251, 1.0e-2, "°F", "Cold / Warm Temperature Limit" }, - { 0x252, 1.0e-1, "°F", "Cold / Warm Temperature Limit" }, - { 0x253, 1.0e0, "°F", "Cold / Warm Temperature Limit" }, + /* E111 00nn Cold / Warm Temperature Limit 10(nn-3) �F 0.001�F to 1�F */ + { 0x250, 1.0e-3, "�F", "Cold / Warm Temperature Limit" }, + { 0x251, 1.0e-2, "�F", "Cold / Warm Temperature Limit" }, + { 0x252, 1.0e-1, "�F", "Cold / Warm Temperature Limit" }, + { 0x253, 1.0e0, "�F", "Cold / Warm Temperature Limit" }, - /* E111 01nn Cold / Warm Temperature Limit 10(nn-3) °C 0.001°C to 1°C */ - { 0x254, 1.0e-3, "°C", "Cold / Warm Temperature Limit" }, - { 0x255, 1.0e-2, "°C", "Cold / Warm Temperature Limit" }, - { 0x256, 1.0e-1, "°C", "Cold / Warm Temperature Limit" }, - { 0x257, 1.0e0, "°C", "Cold / Warm Temperature Limit" }, + /* E111 01nn Cold / Warm Temperature Limit 10(nn-3) �C 0.001�C to 1�C */ + { 0x254, 1.0e-3, "�C", "Cold / Warm Temperature Limit" }, + { 0x255, 1.0e-2, "�C", "Cold / Warm Temperature Limit" }, + { 0x256, 1.0e-1, "�C", "Cold / Warm Temperature Limit" }, + { 0x257, 1.0e0, "�C", "Cold / Warm Temperature Limit" }, - /* E111 1nnn cumul. count max power § 10(nnn-3) W 0.001W to 10000W */ + /* E111 1nnn cumul. count max power � 10(nnn-3) W 0.001W to 10000W */ { 0x258, 1.0e-3, "W", "Cumul count max power" }, { 0x259, 1.0e-3, "W", "Cumul count max power" }, { 0x25A, 1.0e-1, "W", "Cumul count max power" }, @@ -684,7 +684,7 @@ mbus_variable_vif fixed_table[] = { { 0x36, 1.0e1, "m^3/h", "Volume flow" }, { 0x37, 1.0e2, "m^3/h", "Volume flow" }, - { 0x38, 1.0e-3, "°C", "Temperature" }, + { 0x38, 1.0e-3, "�C", "Temperature" }, { 0x39, 1.0e0, "Units for H.C.A.", "H.C.A." }, @@ -1426,7 +1426,7 @@ mbus_sendrecv_request(mbus_handle *handle, int address, mbus_frame *reply, int m // more records are available. // - if (reply_data.type == MBUS_DATA_TYPE_FIXED) + if (reply_data.type != MBUS_DATA_TYPE_VARIABLE) { // only single frame replies for FIXED type frames more_frames = 0; diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index 368ca7f..90e32b1 100644 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -1629,6 +1629,68 @@ mbus_vif_unit_lookup(u_char vif) return buff; } + +//------------------------------------------------------------------------------ +// Lookup the error message +// +// See section 6.6 Codes for general application errors in the M-BUS spec +//------------------------------------------------------------------------------ +const char * +mbus_data_error_lookup(int error) +{ + static char buff[256]; + + switch (error) + { + case MBUS_ERROR_DATA_UNSPECIFIED: + snprintf(buff, sizeof(buff), "Unspecified error"); + break; + + case MBUS_ERROR_DATA_UNIMPLEMENTED_CI: + snprintf(buff, sizeof(buff), "Unimplemented CI-Field"); + break; + + case MBUS_ERROR_DATA_BUFFER_TOO_LONG: + snprintf(buff, sizeof(buff), "Buffer too long, truncated"); + break; + + case MBUS_ERROR_DATA_TOO_MANY_RECORDS: + snprintf(buff, sizeof(buff), "Too many records"); + break; + + case MBUS_ERROR_DATA_PREMATURE_END: + snprintf(buff, sizeof(buff), "Premature end of record"); + break; + + case MBUS_ERROR_DATA_TOO_MANY_DIFES: + snprintf(buff, sizeof(buff), "More than 10 DIFE´s"); + break; + + case MBUS_ERROR_DATA_TOO_MANY_VIFES: + snprintf(buff, sizeof(buff), "More than 10 VIFE´s"); + break; + + case MBUS_ERROR_DATA_RESERVED: + snprintf(buff, sizeof(buff), "Reserved"); + break; + + case MBUS_ERROR_DATA_APPLICATION_BUSY: + snprintf(buff, sizeof(buff), "Application busy"); + break; + + case MBUS_ERROR_DATA_TOO_MANY_READOUTS: + snprintf(buff, sizeof(buff), "Too many readouts"); + break; + + default: + snprintf(buff, sizeof(buff), "Unknown error (0x%.2X)", error); + break; + } + + return buff; +} + + //------------------------------------------------------------------------------ /// Lookup the unit from the VIB (VIF or VIFE) // @@ -2391,21 +2453,50 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data) } //------------------------------------------------------------------------------ -/// Check the stype of the frame data (fixed or variable) and dispatch to the +/// Check the stype of the frame data (error, fixed or variable) and dispatch to the /// corresponding parser function. //------------------------------------------------------------------------------ int mbus_frame_data_parse(mbus_frame *frame, mbus_frame_data *data) { - if (frame && data && frame->data_size > 0) + if (frame && data) { - if (frame->control_information == MBUS_CONTROL_INFO_RESP_FIXED) + if (frame->control_information == MBUS_CONTROL_INFO_ERROR_GENERAL) { + data->type = MBUS_DATA_TYPE_ERROR; + + if (frame->data_size > 0) + { + data->error = (int) frame->data[0]; + } + else + { + data->error = 0; + } + + return 0; + } + else if (frame->control_information == MBUS_CONTROL_INFO_RESP_FIXED) + { + if (frame->data_size == 0) + { + snprintf(error_str, sizeof(error_str), "Got zero data_size."); + + return -1; + } + data->type = MBUS_DATA_TYPE_FIXED; return mbus_data_fixed_parse(frame, &(data->data_fix)); } else if (frame->control_information == MBUS_CONTROL_INFO_RESP_VARIABLE) { + if (frame->data_size == 0) + { + snprintf(error_str, sizeof(error_str), "Got zero data_size."); + + return -1; + } + data->type = MBUS_DATA_TYPE_VARIABLE; return mbus_data_variable_parse(frame, &(data->data_var)); } @@ -2417,7 +2508,7 @@ mbus_frame_data_parse(mbus_frame *frame, mbus_frame_data *data) } } - snprintf(error_str, sizeof(error_str), "Got null pointer to frame, data or zero data_size."); + snprintf(error_str, sizeof(error_str), "Got null pointer to frame or data."); return -1; } @@ -2544,6 +2635,12 @@ mbus_frame_internal_pack(mbus_frame *frame, mbus_frame_data *frame_data) switch (frame_data->type) { + case MBUS_DATA_TYPE_ERROR: + + frame->data[frame->data_size++] = (char) frame_data->error; + + return -2; + case MBUS_DATA_TYPE_FIXED: // @@ -2681,6 +2778,11 @@ mbus_frame_data_print(mbus_frame_data *data) { if (data) { + if (data->type == MBUS_DATA_TYPE_ERROR) + { + return mbus_data_error_print(data->error); + } + if (data->type == MBUS_DATA_TYPE_FIXED) { return mbus_data_fixed_print(&(data->data_fix)); @@ -2815,6 +2917,14 @@ mbus_data_fixed_print(mbus_data_fixed *data) return -1; } +int +mbus_data_error_print(int error) +{ + printf("%s: Error = %d\n", __PRETTY_FUNCTION__, error); + + return -1; +} + //------------------------------------------------------------------------------ // // XML RELATED FUNCTIONS @@ -3020,6 +3130,30 @@ mbus_data_fixed_xml(mbus_data_fixed *data) return ""; } +//------------------------------------------------------------------------------ +/// Generate XML representation of a general application error. +//------------------------------------------------------------------------------ +char * +mbus_data_error_xml(int error) +{ + static char buff[512]; + char str_encoded[256]; + size_t len = 0; + + len += snprintf(&buff[len], sizeof(buff) - len, "\n\n"); + + len += snprintf(&buff[len], sizeof(buff) - 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], sizeof(buff) - len, " \n\n"); + + len += snprintf(&buff[len], sizeof(buff) - len, "\n"); + + return buff; +} + //------------------------------------------------------------------------------ /// Return a string containing an XML representation of the M-BUS frame. //------------------------------------------------------------------------------ @@ -3028,6 +3162,11 @@ mbus_frame_data_xml(mbus_frame_data *data) { if (data) { + if (data->type == MBUS_DATA_TYPE_ERROR) + { + return mbus_data_error_xml(data->error); + } + if (data->type == MBUS_DATA_TYPE_FIXED) { return mbus_data_fixed_xml(&(data->data_fix)); diff --git a/mbus/mbus-protocol.h b/mbus/mbus-protocol.h index d0596da..6fdd3a6 100644 --- a/mbus/mbus-protocol.h +++ b/mbus/mbus-protocol.h @@ -214,16 +214,19 @@ typedef struct _mbus_data_fixed { } mbus_data_fixed; // -// ABSTRACT DATA FORMAT (either fixed or variable length) +// ABSTRACT DATA FORMAT (error, fixed or variable length) // #define MBUS_DATA_TYPE_FIXED 1 #define MBUS_DATA_TYPE_VARIABLE 2 +#define MBUS_DATA_TYPE_ERROR 3 + typedef struct _mbus_frame_data { mbus_data_variable data_var; mbus_data_fixed data_fix; int type; + int error; } mbus_frame_data; @@ -370,6 +373,14 @@ typedef struct _mbus_data_secondary_address { #define MBUS_CONTROL_INFO_EEPROM_READ 0xB4 #define MBUS_CONTROL_INFO_SW_TEST_START 0xB6 +//Mode 1 Mode 2 Application Definition in +// 70h report of general application errors Usergroup March 94 +// 71h report of alarm status Usergroup March 94 +// 72h 76h variable data respond EN1434-3 +// 73h 77h fixed data respond EN1434-3 +#define MBUS_CONTROL_INFO_ERROR_GENERAL 0x70 +#define MBUS_CONTROL_INFO_STATUS_ALARM 0x71 + #define MBUS_CONTROL_INFO_RESP_FIXED 0x73 #define MBUS_CONTROL_INFO_RESP_FIXED_MSB 0x77 @@ -397,6 +408,19 @@ typedef struct _mbus_data_secondary_address { #define MBUS_DATA_RECORD_DIF_MASK_STORAGE_NO 0x40 #define MBUS_DATA_RECORD_DIF_MASK_EXTENTION 0x80 +// +// GENERAL APPLICATION ERRORS +// +#define MBUS_ERROR_DATA_UNSPECIFIED 0x00 +#define MBUS_ERROR_DATA_UNIMPLEMENTED_CI 0x01 +#define MBUS_ERROR_DATA_BUFFER_TOO_LONG 0x02 +#define MBUS_ERROR_DATA_TOO_MANY_RECORDS 0x03 +#define MBUS_ERROR_DATA_PREMATURE_END 0x04 +#define MBUS_ERROR_DATA_TOO_MANY_DIFES 0x05 +#define MBUS_ERROR_DATA_TOO_MANY_VIFES 0x06 +#define MBUS_ERROR_DATA_RESERVED 0x07 +#define MBUS_ERROR_DATA_APPLICATION_BUSY 0x08 +#define MBUS_ERROR_DATA_TOO_MANY_READOUTS 0x09 // // FIXED DATA FLAGS @@ -488,6 +512,7 @@ void mbus_str_xml_encode(u_char *dst, const u_char *src, size_t max_len); char *mbus_data_xml(mbus_frame_data *data); char *mbus_data_variable_xml(mbus_data_variable *data); char *mbus_data_fixed_xml(mbus_data_fixed *data); +char *mbus_data_error_xml(int error); char *mbus_frame_data_xml(mbus_frame_data *data); char *mbus_data_variable_header_xml(mbus_data_variable_header *header); @@ -499,6 +524,7 @@ char *mbus_data_variable_header_xml(mbus_data_variable_header *header); int mbus_frame_print(mbus_frame *frame); int mbus_frame_data_print(mbus_frame_data *data); int mbus_data_fixed_print(mbus_data_fixed *data); +int mbus_data_error_print(int error); int mbus_data_variable_header_print(mbus_data_variable_header *header); int mbus_data_variable_print(mbus_data_variable *data); @@ -535,6 +561,7 @@ const char *mbus_data_fixed_unit(int medium_unit_byte); const char *mbus_data_variable_medium_lookup(u_char medium); const char *mbus_unit_prefix(int exp); +const char *mbus_data_error_lookup(int error); const char *mbus_vib_unit_lookup(mbus_value_information_block *vib); const char *mbus_vif_unit_lookup(u_char vif); diff --git a/test/error-frames/application_busy.hex b/test/error-frames/application_busy.hex new file mode 100644 index 0000000..b0509a1 --- /dev/null +++ b/test/error-frames/application_busy.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 08 81 16 diff --git a/test/error-frames/buffer_too_long.hex b/test/error-frames/buffer_too_long.hex new file mode 100644 index 0000000..f6d628a --- /dev/null +++ b/test/error-frames/buffer_too_long.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 02 7B 16 diff --git a/test/error-frames/error.hex b/test/error-frames/error.hex new file mode 100644 index 0000000..b52f514 --- /dev/null +++ b/test/error-frames/error.hex @@ -0,0 +1 @@ +68 03 03 68 08 01 70 79 16 \ No newline at end of file diff --git a/test/error-frames/premature_end_of_record.hex b/test/error-frames/premature_end_of_record.hex new file mode 100644 index 0000000..20d3f7c --- /dev/null +++ b/test/error-frames/premature_end_of_record.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 04 7D 16 diff --git a/test/error-frames/too_many_difes.hex b/test/error-frames/too_many_difes.hex new file mode 100644 index 0000000..d4baa57 --- /dev/null +++ b/test/error-frames/too_many_difes.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 05 7E 16 diff --git a/test/error-frames/too_many_readouts.hex b/test/error-frames/too_many_readouts.hex new file mode 100644 index 0000000..97f116c --- /dev/null +++ b/test/error-frames/too_many_readouts.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 09 82 16 diff --git a/test/error-frames/too_many_records.hex b/test/error-frames/too_many_records.hex new file mode 100644 index 0000000..9fcdbd6 --- /dev/null +++ b/test/error-frames/too_many_records.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 03 7C 16 diff --git a/test/error-frames/too_many_vifes.hex b/test/error-frames/too_many_vifes.hex new file mode 100644 index 0000000..9e5f0b4 --- /dev/null +++ b/test/error-frames/too_many_vifes.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 06 7F 16 diff --git a/test/error-frames/unimplemented_ci.hex b/test/error-frames/unimplemented_ci.hex new file mode 100644 index 0000000..1e80f81 --- /dev/null +++ b/test/error-frames/unimplemented_ci.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 01 7A 16 diff --git a/test/error-frames/unspecified_error.hex b/test/error-frames/unspecified_error.hex new file mode 100644 index 0000000..59aa068 --- /dev/null +++ b/test/error-frames/unspecified_error.hex @@ -0,0 +1 @@ +68 04 04 68 08 01 70 00 79 16 \ No newline at end of file