Merge pull request #64 from lategoodbye/master

Fix decoding and 2nd address search
This commit is contained in:
Robert
2013-11-12 05:36:49 -08:00
22 changed files with 945 additions and 250 deletions

View File

@ -15,6 +15,35 @@
static int debug = 0; static int debug = 0;
//
// init slave to get really the beginning of the records
//
static int
init_slaves(mbus_handle *handle)
{
if (debug)
printf("%s: debug: sending init frame #1\n", __PRETTY_FUNCTION__);
if (mbus_send_ping_frame(handle, MBUS_ADDRESS_NETWORK_LAYER, 1) == -1)
{
return 0;
}
//
// resend SND_NKE, maybe the first get lost
//
if (debug)
printf("%s: debug: sending init frame #2\n", __PRETTY_FUNCTION__);
if (mbus_send_ping_frame(handle, MBUS_ADDRESS_NETWORK_LAYER, 1) == -1)
{
return 0;
}
return 1;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Scan for devices using secondary addressing. // Scan for devices using secondary addressing.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -79,15 +108,24 @@ main(int argc, char **argv)
if (mbus_connect(handle) == -1) if (mbus_connect(handle) == -1)
{ {
fprintf(stderr,"Failed to setup connection to M-bus gateway\n"); fprintf(stderr,"Failed to setup connection to M-bus gateway\n");
mbus_context_free(handle);
return 1; return 1;
} }
if (mbus_serial_set_baudrate(handle, baudrate) == -1) if (mbus_serial_set_baudrate(handle, baudrate) == -1)
{ {
fprintf(stderr,"Failed to set baud rate.\n"); fprintf(stderr,"Failed to set baud rate.\n");
mbus_disconnect(handle);
mbus_context_free(handle);
return 1; return 1;
} }
if (init_slaves(handle) == 0)
{
mbus_disconnect(handle);
mbus_context_free(handle);
return 1;
}
if (mbus_is_secondary_address(addr_str)) if (mbus_is_secondary_address(addr_str))
{ {
@ -100,36 +138,40 @@ main(int argc, char **argv)
if (ret == MBUS_PROBE_COLLISION) if (ret == MBUS_PROBE_COLLISION)
{ {
fprintf(stderr, "%s: Error: The address mask [%s] matches more than one device.\n", __PRETTY_FUNCTION__, addr_str); fprintf(stderr, "%s: Error: The address mask [%s] matches more than one device.\n", __PRETTY_FUNCTION__, addr_str);
mbus_disconnect(handle);
mbus_context_free(handle);
return 1; return 1;
} }
else if (ret == MBUS_PROBE_NOTHING) else if (ret == MBUS_PROBE_NOTHING)
{ {
fprintf(stderr, "%s: Error: The selected secondary address does not match any device [%s].\n", __PRETTY_FUNCTION__, addr_str); fprintf(stderr, "%s: Error: The selected secondary address does not match any device [%s].\n", __PRETTY_FUNCTION__, addr_str);
mbus_disconnect(handle);
mbus_context_free(handle);
return 1; return 1;
} }
else if (ret == MBUS_PROBE_ERROR) else if (ret == MBUS_PROBE_ERROR)
{ {
fprintf(stderr, "%s: Error: Failed to select secondary address [%s].\n", __PRETTY_FUNCTION__, addr_str); fprintf(stderr, "%s: Error: Failed to select secondary address [%s].\n", __PRETTY_FUNCTION__, addr_str);
mbus_disconnect(handle);
mbus_context_free(handle);
return 1; return 1;
} }
// else MBUS_PROBE_SINGLE // else MBUS_PROBE_SINGLE
if (mbus_send_request_frame(handle, MBUS_ADDRESS_NETWORK_LAYER) == -1) address = MBUS_ADDRESS_NETWORK_LAYER;
{
fprintf(stderr, "Failed to send M-Bus request frame.\n");
return 1;
}
} }
else else
{ {
// primary addressing // primary addressing
address = atoi(addr_str); address = atoi(addr_str);
if (mbus_send_request_frame(handle, address) == -1) }
{
fprintf(stderr, "Failed to send M-Bus request frame.\n"); if (mbus_send_request_frame(handle, address) == -1)
return 1; {
} fprintf(stderr, "Failed to send M-Bus request frame.\n");
mbus_disconnect(handle);
mbus_context_free(handle);
return 1;
} }
if (mbus_recv_frame(handle, &reply) != MBUS_RECV_RESULT_OK) if (mbus_recv_frame(handle, &reply) != MBUS_RECV_RESULT_OK)
@ -139,22 +181,32 @@ main(int argc, char **argv)
} }
// //
// parse data and print in XML format // dump hex data if debug is true
// //
if (debug) if (debug)
{ {
mbus_frame_print(&reply); mbus_frame_print(&reply);
} }
//
// parse data
//
if (mbus_frame_data_parse(&reply, &reply_data) == -1) if (mbus_frame_data_parse(&reply, &reply_data) == -1)
{ {
fprintf(stderr, "M-bus data parse error: %s\n", mbus_error_str()); fprintf(stderr, "M-bus data parse error: %s\n", mbus_error_str());
mbus_disconnect(handle);
mbus_context_free(handle);
return 1; return 1;
} }
//
// generate XML and print to standard output
//
if ((xml_result = mbus_frame_data_xml(&reply_data)) == NULL) 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()); fprintf(stderr, "Failed to generate XML representation of MBUS frame: %s\n", mbus_error_str());
mbus_disconnect(handle);
mbus_context_free(handle);
return 1; return 1;
} }

View File

@ -21,7 +21,7 @@ int ping_address(mbus_handle *handle, mbus_frame *reply, int address)
memset((void *)reply, 0, sizeof(mbus_frame)); memset((void *)reply, 0, sizeof(mbus_frame));
for (i = 0; i <= handle->max_retry; i++) for (i = 0; i <= handle->max_search_retry; i++)
{ {
if (debug) if (debug)
{ {
@ -126,7 +126,7 @@ main(int argc, char **argv)
return 1; return 1;
} }
if (mbus_context_set_option(handle, MBUS_OPTION_MAX_RETRY, retries) == -1) if (mbus_context_set_option(handle, MBUS_OPTION_MAX_SEARCH_RETRY, retries) == -1)
{ {
fprintf(stderr,"Failed to set retry count\n"); fprintf(stderr,"Failed to set retry count\n");
return 1; return 1;

View File

@ -21,7 +21,7 @@ int ping_address(mbus_handle *handle, mbus_frame *reply, int address)
memset((void *)reply, 0, sizeof(mbus_frame)); memset((void *)reply, 0, sizeof(mbus_frame));
for (i = 0; i <= handle->max_retry; i++) for (i = 0; i <= handle->max_search_retry; i++)
{ {
if (debug) if (debug)
{ {
@ -112,7 +112,7 @@ main(int argc, char **argv)
return 1; return 1;
} }
if (mbus_context_set_option(handle, MBUS_OPTION_MAX_RETRY, retries) == -1) if (mbus_context_set_option(handle, MBUS_OPTION_MAX_SEARCH_RETRY, retries) == -1)
{ {
fprintf(stderr,"Failed to set retry count\n"); fprintf(stderr,"Failed to set retry count\n");
return 1; return 1;

View File

@ -214,9 +214,17 @@ mbus_variable_vif vif_table[] = {
/* E111 1010 Bus Address */ /* E111 1010 Bus Address */
{ 0x7A, 1.0, "", "Bus Address" }, { 0x7A, 1.0, "", "Bus Address" },
/* Manufacturer specific: 7Fh / FF */ /* Any VIF: 7Eh */
{ 0x7E, 1.0, "", "Any VIF" },
/* Manufacturer specific: 7Fh */
{ 0x7F, 1.0, "", "Manufacturer specific" }, { 0x7F, 1.0, "", "Manufacturer specific" },
/* Any VIF: 7Eh */
{ 0xFE, 1.0, "", "Any VIF" },
/* Manufacturer specific: FFh */
{ 0xFF, 1.0, "", "Manufacturer specific" }, { 0xFF, 1.0, "", "Manufacturer specific" },
@ -567,32 +575,22 @@ mbus_variable_vif vif_table[] = {
{ 0x235, 1.0e0, "Reserved", "Reserved" }, { 0x235, 1.0e0, "Reserved", "Reserved" },
{ 0x236, 1.0e0, "Reserved", "Reserved" }, { 0x236, 1.0e0, "Reserved", "Reserved" },
{ 0x237, 1.0e0, "Reserved", "Reserved" }, { 0x237, 1.0e0, "Reserved", "Reserved" },
{ 0x238, 1.0e0, "Reserved", "Reserved" },
/* E101 10nn Flow Temperature 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */ { 0x239, 1.0e0, "Reserved", "Reserved" },
{ 0x238, 1.0e-3, "<EFBFBD>F", "Flow temperature" }, { 0x23A, 1.0e0, "Reserved", "Reserved" },
{ 0x239, 1.0e-2, "<EFBFBD>F", "Flow temperature" }, { 0x23B, 1.0e0, "Reserved", "Reserved" },
{ 0x23A, 1.0e-1, "<EFBFBD>F", "Flow temperature" }, { 0x23C, 1.0e0, "Reserved", "Reserved" },
{ 0x23B, 1.0e0, "<EFBFBD>F", "Flow temperature" }, { 0x23D, 1.0e0, "Reserved", "Reserved" },
{ 0x23E, 1.0e0, "Reserved", "Reserved" },
/* E101 11nn Return Temperature 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */ { 0x23F, 1.0e0, "Reserved", "Reserved" },
{ 0x23C, 1.0e-3, "<EFBFBD>F", "Return temperature" }, { 0x240, 1.0e0, "Reserved", "Reserved" },
{ 0x23D, 1.0e-2, "<EFBFBD>F", "Return temperature" }, { 0x241, 1.0e0, "Reserved", "Reserved" },
{ 0x23E, 1.0e-1, "<EFBFBD>F", "Return temperature" }, { 0x242, 1.0e0, "Reserved", "Reserved" },
{ 0x23F, 1.0e0, "<EFBFBD>F", "Return temperature" }, { 0x243, 1.0e0, "Reserved", "Reserved" },
{ 0x244, 1.0e0, "Reserved", "Reserved" },
/* E110 00nn Temperature Difference 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */ { 0x245, 1.0e0, "Reserved", "Reserved" },
{ 0x240, 1.0e-3, "<EFBFBD>F", "Temperature difference" }, { 0x246, 1.0e0, "Reserved", "Reserved" },
{ 0x241, 1.0e-2, "<EFBFBD>F", "Temperature difference" }, { 0x247, 1.0e0, "Reserved", "Reserved" },
{ 0x242, 1.0e-1, "<EFBFBD>F", "Temperature difference" },
{ 0x243, 1.0e0, "<EFBFBD>F", "Temperature difference" },
/* E110 01nn External Temperature 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */
{ 0x244, 1.0e-3, "<EFBFBD>F", "External temperature" },
{ 0x245, 1.0e-2, "<EFBFBD>F", "External temperature" },
{ 0x246, 1.0e-1, "<EFBFBD>F", "External temperature" },
{ 0x247, 1.0e0, "<EFBFBD>F", "External temperature" },
/* E110 1nnn Reserved */
{ 0x248, 1.0e0, "Reserved", "Reserved" }, { 0x248, 1.0e0, "Reserved", "Reserved" },
{ 0x249, 1.0e0, "Reserved", "Reserved" }, { 0x249, 1.0e0, "Reserved", "Reserved" },
{ 0x24A, 1.0e0, "Reserved", "Reserved" }, { 0x24A, 1.0e0, "Reserved", "Reserved" },
@ -601,28 +599,70 @@ mbus_variable_vif vif_table[] = {
{ 0x24D, 1.0e0, "Reserved", "Reserved" }, { 0x24D, 1.0e0, "Reserved", "Reserved" },
{ 0x24E, 1.0e0, "Reserved", "Reserved" }, { 0x24E, 1.0e0, "Reserved", "Reserved" },
{ 0x24F, 1.0e0, "Reserved", "Reserved" }, { 0x24F, 1.0e0, "Reserved", "Reserved" },
{ 0x250, 1.0e0, "Reserved", "Reserved" },
{ 0x251, 1.0e0, "Reserved", "Reserved" },
{ 0x252, 1.0e0, "Reserved", "Reserved" },
{ 0x253, 1.0e0, "Reserved", "Reserved" },
{ 0x254, 1.0e0, "Reserved", "Reserved" },
{ 0x255, 1.0e0, "Reserved", "Reserved" },
{ 0x256, 1.0e0, "Reserved", "Reserved" },
{ 0x257, 1.0e0, "Reserved", "Reserved" },
/* E101 10nn Flow Temperature 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */
{ 0x258, 1.0e-3, "<EFBFBD>F", "Flow temperature" },
{ 0x259, 1.0e-2, "<EFBFBD>F", "Flow temperature" },
{ 0x25A, 1.0e-1, "<EFBFBD>F", "Flow temperature" },
{ 0x25B, 1.0e0, "<EFBFBD>F", "Flow temperature" },
/* E101 11nn Return Temperature 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */
{ 0x25C, 1.0e-3, "<EFBFBD>F", "Return temperature" },
{ 0x25D, 1.0e-2, "<EFBFBD>F", "Return temperature" },
{ 0x25E, 1.0e-1, "<EFBFBD>F", "Return temperature" },
{ 0x25F, 1.0e0, "<EFBFBD>F", "Return temperature" },
/* E110 00nn Temperature Difference 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */
{ 0x260, 1.0e-3, "<EFBFBD>F", "Temperature difference" },
{ 0x261, 1.0e-2, "<EFBFBD>F", "Temperature difference" },
{ 0x262, 1.0e-1, "<EFBFBD>F", "Temperature difference" },
{ 0x263, 1.0e0, "<EFBFBD>F", "Temperature difference" },
/* E110 01nn External Temperature 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */
{ 0x264, 1.0e-3, "<EFBFBD>F", "External temperature" },
{ 0x265, 1.0e-2, "<EFBFBD>F", "External temperature" },
{ 0x266, 1.0e-1, "<EFBFBD>F", "External temperature" },
{ 0x267, 1.0e0, "<EFBFBD>F", "External temperature" },
/* E110 1nnn Reserved */
{ 0x268, 1.0e0, "Reserved", "Reserved" },
{ 0x269, 1.0e0, "Reserved", "Reserved" },
{ 0x26A, 1.0e0, "Reserved", "Reserved" },
{ 0x26B, 1.0e0, "Reserved", "Reserved" },
{ 0x26C, 1.0e0, "Reserved", "Reserved" },
{ 0x26D, 1.0e0, "Reserved", "Reserved" },
{ 0x26E, 1.0e0, "Reserved", "Reserved" },
{ 0x26F, 1.0e0, "Reserved", "Reserved" },
/* E111 00nn Cold / Warm Temperature Limit 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */ /* E111 00nn Cold / Warm Temperature Limit 10(nn-3) <20>F 0.001<EFBFBD>F to 1<>F */
{ 0x250, 1.0e-3, "<EFBFBD>F", "Cold / Warm Temperature Limit" }, { 0x270, 1.0e-3, "<EFBFBD>F", "Cold / Warm Temperature Limit" },
{ 0x251, 1.0e-2, "<EFBFBD>F", "Cold / Warm Temperature Limit" }, { 0x271, 1.0e-2, "<EFBFBD>F", "Cold / Warm Temperature Limit" },
{ 0x252, 1.0e-1, "<EFBFBD>F", "Cold / Warm Temperature Limit" }, { 0x272, 1.0e-1, "<EFBFBD>F", "Cold / Warm Temperature Limit" },
{ 0x253, 1.0e0, "<EFBFBD>F", "Cold / Warm Temperature Limit" }, { 0x273, 1.0e0, "<EFBFBD>F", "Cold / Warm Temperature Limit" },
/* E111 01nn Cold / Warm Temperature Limit 10(nn-3) <20>C 0.001<EFBFBD>C to 1<>C */ /* E111 01nn Cold / Warm Temperature Limit 10(nn-3) <20>C 0.001<EFBFBD>C to 1<>C */
{ 0x254, 1.0e-3, "<EFBFBD>C", "Cold / Warm Temperature Limit" }, { 0x274, 1.0e-3, "<EFBFBD>C", "Cold / Warm Temperature Limit" },
{ 0x255, 1.0e-2, "<EFBFBD>C", "Cold / Warm Temperature Limit" }, { 0x275, 1.0e-2, "<EFBFBD>C", "Cold / Warm Temperature Limit" },
{ 0x256, 1.0e-1, "<EFBFBD>C", "Cold / Warm Temperature Limit" }, { 0x276, 1.0e-1, "<EFBFBD>C", "Cold / Warm Temperature Limit" },
{ 0x257, 1.0e0, "<EFBFBD>C", "Cold / Warm Temperature Limit" }, { 0x277, 1.0e0, "<EFBFBD>C", "Cold / Warm Temperature Limit" },
/* E111 1nnn cumul. count max power <20> 10(nnn-3) W 0.001W to 10000W */ /* E111 1nnn cumul. count max power <20> 10(nnn-3) W 0.001W to 10000W */
{ 0x258, 1.0e-3, "W", "Cumul count max power" }, { 0x278, 1.0e-3, "W", "Cumul count max power" },
{ 0x259, 1.0e-3, "W", "Cumul count max power" }, { 0x279, 1.0e-3, "W", "Cumul count max power" },
{ 0x25A, 1.0e-1, "W", "Cumul count max power" }, { 0x27A, 1.0e-1, "W", "Cumul count max power" },
{ 0x25B, 1.0e0, "W", "Cumul count max power" }, { 0x27B, 1.0e0, "W", "Cumul count max power" },
{ 0x25C, 1.0e1, "W", "Cumul count max power" }, { 0x27C, 1.0e1, "W", "Cumul count max power" },
{ 0x25D, 1.0e2, "W", "Cumul count max power" }, { 0x27D, 1.0e2, "W", "Cumul count max power" },
{ 0x25E, 1.0e3, "W", "Cumul count max power" }, { 0x27E, 1.0e3, "W", "Cumul count max power" },
{ 0x25F, 1.0e4, "W", "Cumul count max power" }, { 0x27F, 1.0e4, "W", "Cumul count max power" },
/* End of array */ /* End of array */
{ 0xFFFF, 0.0, "", "" }, { 0xFFFF, 0.0, "", "" },
@ -794,6 +834,9 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
int result = 0; int result = 0;
unsigned char vif, vife; unsigned char vif, vife;
struct tm time; struct tm time;
int value_out_int;
long value_out_long;
long long value_out_long_long;
*value_out_real = 0.0; *value_out_real = 0.0;
*value_out_str = NULL; *value_out_str = NULL;
*value_out_str_size = 0; *value_out_str_size = 0;
@ -806,7 +849,7 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
vif = (record->drh.vib.vif & MBUS_DIB_VIF_WITHOUT_EXTENSION); vif = (record->drh.vib.vif & MBUS_DIB_VIF_WITHOUT_EXTENSION);
vife = (record->drh.vib.vife[0] & MBUS_DIB_VIF_WITHOUT_EXTENSION); vife = (record->drh.vib.vife[0] & MBUS_DIB_VIF_WITHOUT_EXTENSION);
switch (record->drh.dib.dif & 0x0F) switch (record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_DATA)
{ {
case 0x00: /* no data */ case 0x00: /* no data */
if ((*value_out_str = (char*) malloc(1)) == NULL) if ((*value_out_str = (char*) malloc(1)) == NULL)
@ -819,8 +862,8 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
break; break;
case 0x01: /* 1 byte integer (8 bit) */ case 0x01: /* 1 byte integer (8 bit) */
*value_out_real = mbus_data_int_decode(record->data, 1); result = mbus_data_int_decode(record->data, 1, &value_out_int);
result = 0; *value_out_real = value_out_int;
break; break;
case 0x02: /* 2 byte integer (16 bit) */ case 0x02: /* 2 byte integer (16 bit) */
@ -837,18 +880,18 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
(time.tm_year + 2000), (time.tm_year + 2000),
(time.tm_mon + 1), (time.tm_mon + 1),
time.tm_mday); time.tm_mday);
result = 0;
} }
else // normal integer else // normal integer
{ {
*value_out_real = mbus_data_int_decode(record->data, 2); result = mbus_data_int_decode(record->data, 2, &value_out_int);
*value_out_real = value_out_int;
} }
result = 0;
break; break;
case 0x03: /* 3 byte integer (24 bit) */ case 0x03: /* 3 byte integer (24 bit) */
*value_out_real = mbus_data_int_decode(record->data, 3); result = mbus_data_int_decode(record->data, 3, &value_out_int);
result = 0; *value_out_real = value_out_int;
break; break;
case 0x04: /* 4 byte integer (32 bit) */ case 0x04: /* 4 byte integer (32 bit) */
@ -872,12 +915,13 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
time.tm_hour, time.tm_hour,
time.tm_min, time.tm_min,
time.tm_sec); time.tm_sec);
result = 0;
} }
else // normal integer else // normal integer
{ {
*value_out_real = mbus_data_int_decode(record->data, 4); result = mbus_data_int_decode(record->data, 4, &value_out_int);
*value_out_real = value_out_int;
} }
result = 0;
break; break;
case 0x05: /* 32b real */ case 0x05: /* 32b real */
@ -886,13 +930,13 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
break; break;
case 0x06: /* 6 byte integer (48 bit) */ case 0x06: /* 6 byte integer (48 bit) */
*value_out_real = mbus_data_long_long_decode(record->data, 6); result = mbus_data_long_long_decode(record->data, 6, &value_out_long_long);
result = 0; *value_out_real = value_out_long_long;
break; break;
case 0x07: /* 8 byte integer (64 bit) */ case 0x07: /* 8 byte integer (64 bit) */
*value_out_real = mbus_data_long_long_decode(record->data, 8); result = mbus_data_long_long_decode(record->data, 8, &value_out_long_long);
result = 0; *value_out_real = value_out_long_long;
break; break;
case 0x09: /* 2 digit BCD (8 bit) */ case 0x09: /* 2 digit BCD (8 bit) */
@ -1112,6 +1156,9 @@ mbus_record_new()
record->unit = NULL; record->unit = NULL;
record->function_medium = NULL; record->function_medium = NULL;
record->quantity = NULL; record->quantity = NULL;
record->device = -1;
record->tariff = -1;
record->storage_number = 0;
return record; return record;
} }
@ -1177,7 +1224,7 @@ mbus_parse_fixed_record(char status_byte, char medium_unit, unsigned char *data)
} }
else else
{ {
value = mbus_data_int_decode(data, 4); mbus_data_long_decode(data, 4, &value);
} }
record->unit = NULL; record->unit = NULL;
@ -1213,6 +1260,10 @@ mbus_parse_variable_record(mbus_data_record *data)
MBUS_ERROR("%s: memory allocation error\n", __PRETTY_FUNCTION__); MBUS_ERROR("%s: memory allocation error\n", __PRETTY_FUNCTION__);
return NULL; return NULL;
} }
record->storage_number = mbus_data_record_storage_number(data);
record->tariff = mbus_data_record_tariff(data);
record->device = mbus_data_record_device(data);
if ((data->drh.dib.dif == MBUS_DIB_DIF_MANUFACTURER_SPECIFIC) || if ((data->drh.dib.dif == MBUS_DIB_DIF_MANUFACTURER_SPECIFIC) ||
(data->drh.dib.dif == MBUS_DIB_DIF_MORE_RECORDS_FOLLOW)) /* MBUS_DIB_DIF_VENDOR_SPECIFIC */ (data->drh.dib.dif == MBUS_DIB_DIF_MORE_RECORDS_FOLLOW)) /* MBUS_DIB_DIF_VENDOR_SPECIFIC */
@ -1351,6 +1402,14 @@ mbus_data_variable_xml_normalized(mbus_data_variable *data)
{ {
mbus_str_xml_encode(str_encoded, norm_record->function_medium, sizeof(str_encoded)); mbus_str_xml_encode(str_encoded, norm_record->function_medium, sizeof(str_encoded));
len += snprintf(&buff[len], buff_size - len, " <Function>%s</Function>\n", str_encoded); len += snprintf(&buff[len], buff_size - len, " <Function>%s</Function>\n", str_encoded);
len += snprintf(&buff[len], buff_size - len, " <StorageNumber>%ld</StorageNumber>\n", norm_record->storage_number);
if (norm_record->tariff >= 0)
{
len += snprintf(&buff[len], buff_size - len, " <Tariff>%ld</Tariff>\n", norm_record->tariff);
len += snprintf(&buff[len], buff_size - len, " <Device>%d</Device>\n", norm_record->device);
}
mbus_str_xml_encode(str_encoded, norm_record->unit, sizeof(str_encoded)); mbus_str_xml_encode(str_encoded, norm_record->unit, sizeof(str_encoded));
@ -1430,7 +1489,8 @@ mbus_context_serial(const char *device)
return NULL; return NULL;
} }
handle->max_retry = 3; handle->max_data_retry = 3;
handle->max_search_retry = 1;
handle->is_serial = 1; handle->is_serial = 1;
handle->purge_first_frame = MBUS_FRAME_PURGE_M2S; handle->purge_first_frame = MBUS_FRAME_PURGE_M2S;
handle->auxdata = serial_data; handle->auxdata = serial_data;
@ -1477,7 +1537,8 @@ mbus_context_tcp(const char *host, uint16_t port)
return NULL; return NULL;
} }
handle->max_retry = 3; handle->max_data_retry = 3;
handle->max_search_retry = 1;
handle->is_serial = 0; handle->is_serial = 0;
handle->purge_first_frame = MBUS_FRAME_PURGE_M2S; handle->purge_first_frame = MBUS_FRAME_PURGE_M2S;
handle->auxdata = tcp_data; handle->auxdata = tcp_data;
@ -1549,10 +1610,17 @@ mbus_context_set_option(mbus_handle * handle, mbus_context_option option, long v
switch (option) switch (option)
{ {
case MBUS_OPTION_MAX_RETRY: case MBUS_OPTION_MAX_DATA_RETRY:
if ((value >= 0) && (value <= 9)) if ((value >= 0) && (value <= 9))
{ {
handle->max_retry = value; handle->max_data_retry = value;
return 0;
}
break;
case MBUS_OPTION_MAX_SEARCH_RETRY:
if ((value >= 0) && (value <= 9))
{
handle->max_search_retry = value;
return 0; return 0;
} }
break; break;
@ -1934,7 +2002,7 @@ mbus_sendrecv_request(mbus_handle *handle, int address, mbus_frame *reply, int m
while (more_frames) while (more_frames)
{ {
if (retry > handle->max_retry) if (retry > handle->max_data_retry)
{ {
// Give up // Give up
retval = 1; retval = 1;
@ -2155,7 +2223,7 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask)
int int
mbus_probe_secondary_address(mbus_handle *handle, const char *mask, char *matching_addr) mbus_probe_secondary_address(mbus_handle *handle, const char *mask, char *matching_addr)
{ {
int ret; int ret, i;
mbus_frame reply; mbus_frame reply;
if (mask == NULL || matching_addr == NULL || strlen(mask) != 16) if (mask == NULL || matching_addr == NULL || strlen(mask) != 16)
@ -2164,68 +2232,77 @@ mbus_probe_secondary_address(mbus_handle *handle, const char *mask, char *matchi
return MBUS_PROBE_ERROR; return MBUS_PROBE_ERROR;
} }
ret = mbus_select_secondary_address(handle, mask); for (i = 0; i <= handle->max_search_retry; i++)
if (ret == MBUS_PROBE_SINGLE)
{ {
/* send a data request command to find out the full address */ ret = mbus_select_secondary_address(handle, mask);
if (mbus_send_request_frame(handle, MBUS_ADDRESS_NETWORK_LAYER) == -1)
{
MBUS_ERROR("%s: Failed to send request to selected secondary device [mask %s]: %s.\n",
__PRETTY_FUNCTION__,
mask,
mbus_error_str());
return MBUS_PROBE_ERROR;
}
memset((void *)&reply, 0, sizeof(mbus_frame)); if (ret == MBUS_PROBE_SINGLE)
ret = mbus_recv_frame(handle, &reply); {
/* send a data request command to find out the full address */
if (mbus_send_request_frame(handle, MBUS_ADDRESS_NETWORK_LAYER) == -1)
{
MBUS_ERROR("%s: Failed to send request to selected secondary device [mask %s]: %s.\n",
__PRETTY_FUNCTION__,
mask,
mbus_error_str());
return MBUS_PROBE_ERROR;
}
if (ret == MBUS_RECV_RESULT_TIMEOUT) memset((void *)&reply, 0, sizeof(mbus_frame));
{ ret = mbus_recv_frame(handle, &reply);
return MBUS_PROBE_NOTHING;
}
if (ret == MBUS_RECV_RESULT_INVALID) if (ret == MBUS_RECV_RESULT_TIMEOUT)
{
/* check for more data (collision) */
mbus_purge_frames(handle);
return MBUS_PROBE_COLLISION;
}
/* check for more data (collision) */
if (mbus_purge_frames(handle))
{
return MBUS_PROBE_COLLISION;
}
if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_LONG)
{
char *addr = mbus_frame_get_secondary_address(&reply);
if (addr == NULL)
{ {
// show error message, but procede with scan
MBUS_ERROR("Failed to generate secondary address from M-Bus reply frame: %s\n", mbus_error_str());
return MBUS_PROBE_NOTHING; return MBUS_PROBE_NOTHING;
} }
snprintf(matching_addr, 17, "%s", addr); if (ret == MBUS_RECV_RESULT_INVALID)
if (handle->found_event)
{ {
handle->found_event(handle,&reply); /* check for more data (collision) */
} mbus_purge_frames(handle);
return MBUS_PROBE_COLLISION;
}
return MBUS_PROBE_SINGLE; /* check for more data (collision) */
} if (mbus_purge_frames(handle))
else {
{ return MBUS_PROBE_COLLISION;
MBUS_ERROR("%s: Unexpected reply for address [mask %s]. Expected long frame.\n", }
__PRETTY_FUNCTION__, mask);
return MBUS_PROBE_NOTHING; if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_LONG)
} {
} char *addr = mbus_frame_get_secondary_address(&reply);
if (addr == NULL)
{
// show error message, but procede with scan
MBUS_ERROR("Failed to generate secondary address from M-Bus reply frame: %s\n",
mbus_error_str());
return MBUS_PROBE_NOTHING;
}
snprintf(matching_addr, 17, "%s", addr);
if (handle->found_event)
{
handle->found_event(handle,&reply);
}
return MBUS_PROBE_SINGLE;
}
else
{
MBUS_ERROR("%s: Unexpected reply for address [mask %s]. Expected long frame.\n",
__PRETTY_FUNCTION__, mask);
return MBUS_PROBE_NOTHING;
}
}
else if ((ret == MBUS_PROBE_ERROR) ||
(ret == MBUS_PROBE_COLLISION))
{
break;
}
}
return ret; return ret;
} }
@ -2252,7 +2329,6 @@ int mbus_read_slave(mbus_handle * handle, mbus_address *address, mbus_frame * re
{ {
/* secondary addressing */ /* secondary addressing */
int probe_ret; int probe_ret;
char matching_addr[16];
if (address->secondary == NULL) if (address->secondary == NULL)
{ {
@ -2261,7 +2337,7 @@ int mbus_read_slave(mbus_handle * handle, mbus_address *address, mbus_frame * re
return -1; return -1;
} }
probe_ret = mbus_probe_secondary_address(handle, address->secondary, matching_addr); probe_ret = mbus_select_secondary_address(handle, address->secondary);
if (probe_ret == MBUS_PROBE_COLLISION) if (probe_ret == MBUS_PROBE_COLLISION)
{ {
@ -2338,6 +2414,7 @@ mbus_scan_2nd_address_range(mbus_handle * handle, int pos, char *addr_mask)
if (mask[pos] == 'f' || mask[pos] == 'F') if (mask[pos] == 'f' || mask[pos] == 'F')
{ {
// mask[pos] is a wildcard -> enumerate all 0..9 at this position
i_start = 0; i_start = 0;
i_end = 9; i_end = 9;
} }
@ -2345,44 +2422,50 @@ mbus_scan_2nd_address_range(mbus_handle * handle, int pos, char *addr_mask)
{ {
if (pos < 15) if (pos < 15)
{ {
// mask[pos] is not a wildcard -> don't iterate, recursively check pos+1
mbus_scan_2nd_address_range(handle, pos+1, mask); mbus_scan_2nd_address_range(handle, pos+1, mask);
} }
else else
{ {
// .. except if we're at the last pos (==15) and this isn't a wildcard we still need to send the probe
i_start = (int)(mask[pos] - '0'); i_start = (int)(mask[pos] - '0');
i_end = (int)(mask[pos] - '0'); i_end = (int)(mask[pos] - '0');
} }
} }
for (i = 0; i <= 9; i++) // skip the scanning if we're returning from the (pos < 15) case above
if (mask[pos] == 'f' || mask[pos] == 'F' || pos == 15)
{ {
mask[pos] = '0'+i; for (i = i_start; i <= i_end; i++)
if (handle->scan_progress)
handle->scan_progress(handle,mask);
probe_ret = mbus_probe_secondary_address(handle, mask, matching_mask);
if (probe_ret == MBUS_PROBE_SINGLE)
{ {
if (!handle->found_event) mask[pos] = '0'+i;
if (handle->scan_progress)
handle->scan_progress(handle,mask);
probe_ret = mbus_probe_secondary_address(handle, mask, matching_mask);
if (probe_ret == MBUS_PROBE_SINGLE)
{ {
printf("Found a device on secondary address %s [using address mask %s]\n", matching_mask, mask); if (!handle->found_event)
{
printf("Found a device on secondary address %s [using address mask %s]\n", matching_mask, mask);
}
}
else if (probe_ret == MBUS_PROBE_COLLISION)
{
// collision, more than one device matching, restrict the search mask further
mbus_scan_2nd_address_range(handle, pos+1, mask);
}
else if (probe_ret == MBUS_PROBE_NOTHING)
{
// nothing... move on to next address mask
}
else // MBUS_PROBE_ERROR
{
MBUS_ERROR("%s: Failed to probe secondary address [%s].\n", __PRETTY_FUNCTION__, mask);
return -1;
} }
}
else if (probe_ret == MBUS_PROBE_COLLISION)
{
// collision, more than one device matching, restrict the search mask further
mbus_scan_2nd_address_range(handle, pos+1, mask);
}
else if (probe_ret == MBUS_PROBE_NOTHING)
{
// nothing... move on to next address mask
}
else // MBUS_PROBE_ERROR
{
MBUS_ERROR("%s: Failed to probe secondary address [%s].\n", __PRETTY_FUNCTION__, mask);
return -1;
} }
} }

View File

@ -85,7 +85,8 @@ extern "C" {
*/ */
typedef struct _mbus_handle { typedef struct _mbus_handle {
int fd; int fd;
int max_retry; int max_data_retry;
int max_search_retry;
char purge_first_frame; char purge_first_frame;
char is_serial; /**< _handle type (non zero for serial) */ char is_serial; /**< _handle type (non zero for serial) */
int (*open) (struct _mbus_handle *handle); int (*open) (struct _mbus_handle *handle);
@ -142,13 +143,17 @@ typedef struct _mbus_record {
char *unit; /**< Quantity unit (e.g. Wh) */ char *unit; /**< Quantity unit (e.g. Wh) */
char *function_medium; /**< Quantity medium or function (e.g. Electricity) */ char *function_medium; /**< Quantity medium or function (e.g. Electricity) */
char *quantity; /**< Quantity type (e.g. Energy) */ char *quantity; /**< Quantity type (e.g. Energy) */
int device; /**< Quantity device */
long tariff; /**< Quantity tariff */
long storage_number; /**< Quantity storage number */
} mbus_record; } mbus_record;
/** /**
* MBus handle option enumeration * MBus handle option enumeration
*/ */
typedef enum _mbus_context_option { typedef enum _mbus_context_option {
MBUS_OPTION_MAX_RETRY, /**< option defines the maximum attempts of data retransmission */ MBUS_OPTION_MAX_DATA_RETRY, /**< option defines the maximum attempts of data request retransmission */
MBUS_OPTION_MAX_SEARCH_RETRY, /**< option defines the maximum attempts of search request retransmission */
MBUS_OPTION_PURGE_FIRST_FRAME /**< option controls the echo cancelation for mbus_recv_frame */ MBUS_OPTION_PURGE_FIRST_FRAME /**< option controls the echo cancelation for mbus_recv_frame */
} mbus_context_option; } mbus_context_option;

View File

@ -480,60 +480,105 @@ mbus_data_bcd_decode(unsigned char *bcd_data, size_t bcd_data_size)
/// ///
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int int
mbus_data_int_decode(unsigned char *int_data, size_t int_data_size) mbus_data_int_decode(unsigned char *int_data, size_t int_data_size, int *value)
{ {
int val = 0;
size_t i; size_t i;
int neg;
*value = 0;
if (int_data) if (!int_data || (int_data_size < 1))
{ {
for (i = int_data_size; i > 0; i--) return -1;
{ }
val = (val << 8) + int_data[i-1];
} neg = int_data[int_data_size-1] & 0x80;
return val; for (i = int_data_size; i > 0; i--)
{
if (neg)
{
*value = (*value << 8) + (int_data[i-1] ^ 0xFF);
}
else
{
*value = (*value << 8) + int_data[i-1];
}
} }
return -1; if (neg)
{
*value = *value * -1 - 1;
}
return 0;
} }
long int
mbus_data_long_decode(unsigned char *int_data, size_t int_data_size) mbus_data_long_decode(unsigned char *int_data, size_t int_data_size, long *value)
{ {
long val = 0;
size_t i; size_t i;
int neg;
*value = 0;
if (int_data) if (!int_data || (int_data_size < 1))
{ {
for (i = int_data_size; i > 0; i--) return -1;
{ }
val = (val << 8) + int_data[i-1];
} neg = int_data[int_data_size-1] & 0x80;
return val; for (i = int_data_size; i > 0; i--)
{
if (neg)
{
*value = (*value << 8) + (int_data[i-1] ^ 0xFF);
}
else
{
*value = (*value << 8) + int_data[i-1];
}
} }
return -1; if (neg)
{
*value = *value * -1 - 1;
}
return 0;
} }
long long int
mbus_data_long_long_decode(unsigned char *int_data, size_t int_data_size) mbus_data_long_long_decode(unsigned char *int_data, size_t int_data_size, long long *value)
{ {
long long val = 0;
size_t i; size_t i;
int neg;
*value = 0;
if (int_data) if (!int_data || (int_data_size < 1))
{ {
for (i = int_data_size; i > 0; i--) return -1;
{ }
val = (val << 8) + int_data[i-1];
} neg = int_data[int_data_size-1] & 0x80;
return val; for (i = int_data_size; i > 0; i--)
{
if (neg)
{
*value = (*value << 8) + (int_data[i-1] ^ 0xFF);
}
else
{
*value = (*value << 8) + int_data[i-1];
}
} }
return -1; if (neg)
{
*value = *value * -1 - 1;
}
return 0;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -742,7 +787,7 @@ mbus_decode_manufacturer(unsigned char byte1, unsigned char byte2)
m_str[0] = byte1; m_str[0] = byte1;
m_str[1] = byte2; m_str[1] = byte2;
m_id = mbus_data_int_decode(m_str, 2); mbus_data_int_decode(m_str, 2, &m_id);
m_str[0] = (char)(((m_id>>10) & 0x001F) + 64); m_str[0] = (char)(((m_id>>10) & 0x001F) + 64);
m_str[1] = (char)(((m_id>>5) & 0x001F) + 64); m_str[1] = (char)(((m_id>>5) & 0x001F) + 64);
@ -830,6 +875,15 @@ mbus_data_product_name(mbus_data_variable_header *header)
break; break;
} }
} }
else if (manufacturer == MBUS_VARIABLE_DATA_MAN_GMC)
{
switch (header->version)
{
case 0xE6:
strcpy(buff,"GMC-I A230 EMMOD 206");
break;
}
}
else if (manufacturer == MBUS_VARIABLE_DATA_MAN_SLB) else if (manufacturer == MBUS_VARIABLE_DATA_MAN_SLB)
{ {
switch (header->version) switch (header->version)
@ -869,6 +923,15 @@ mbus_data_product_name(mbus_data_variable_header *header)
break; break;
} }
} }
else if (manufacturer == MBUS_VARIABLE_DATA_MAN_RAM)
{
switch (header->version)
{
case 0x03:
strcpy(buff, "Rossweiner ETK/ETW Modularis");
break;
}
}
else if (manufacturer == MBUS_VARIABLE_DATA_MAN_RKE) else if (manufacturer == MBUS_VARIABLE_DATA_MAN_RKE)
{ {
switch (header->version) switch (header->version)
@ -1540,14 +1603,14 @@ mbus_unit_prefix(int exp)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/// Look up the data lenght from a VIF field in the data record. /// Look up the data length from a DIF field in the data record.
/// ///
/// See the table on page 41 the M-BUS specification. /// See the table on page 41 the M-BUS specification.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
unsigned char unsigned char
mbus_dif_datalength_lookup(unsigned char dif) mbus_dif_datalength_lookup(unsigned char dif)
{ {
switch (dif&0x0F) switch (dif & MBUS_DATA_RECORD_DIF_MASK_DATA)
{ {
case 0x0: case 0x0:
return 0; return 0;
@ -2149,16 +2212,16 @@ mbus_data_record_decode(mbus_data_record *record)
if (record) if (record)
{ {
int val; int int_val;
float val3; float float_val;
long long val4; long long long_long_val;
struct tm time; struct tm time;
// ignore extension bit // ignore extension bit
vif = (record->drh.vib.vif & MBUS_DIB_VIF_WITHOUT_EXTENSION); vif = (record->drh.vib.vif & MBUS_DIB_VIF_WITHOUT_EXTENSION);
vife = (record->drh.vib.vife[0] & MBUS_DIB_VIF_WITHOUT_EXTENSION); vife = (record->drh.vib.vife[0] & MBUS_DIB_VIF_WITHOUT_EXTENSION);
switch (record->drh.dib.dif & 0x0F) switch (record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_DATA)
{ {
case 0x00: // no data case 0x00: // no data
@ -2168,9 +2231,9 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x01: // 1 byte integer (8 bit) case 0x01: // 1 byte integer (8 bit)
val = mbus_data_int_decode(record->data, 1); mbus_data_int_decode(record->data, 1, &int_val);
snprintf(buff, sizeof(buff), "%d", val); snprintf(buff, sizeof(buff), "%d", int_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 1 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 1 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2191,8 +2254,8 @@ mbus_data_record_decode(mbus_data_record *record)
} }
else // 2 byte integer else // 2 byte integer
{ {
val = mbus_data_int_decode(record->data, 2); mbus_data_int_decode(record->data, 2, &int_val);
snprintf(buff, sizeof(buff), "%d", val); snprintf(buff, sizeof(buff), "%d", int_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 2 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 2 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2202,9 +2265,9 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x03: // 3 byte integer (24 bit) case 0x03: // 3 byte integer (24 bit)
val = mbus_data_int_decode(record->data, 3); mbus_data_int_decode(record->data, 3, &int_val);
snprintf(buff, sizeof(buff), "%d", val); snprintf(buff, sizeof(buff), "%d", int_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 3 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 3 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2231,8 +2294,8 @@ mbus_data_record_decode(mbus_data_record *record)
} }
else // 4 byte integer else // 4 byte integer
{ {
val = mbus_data_int_decode(record->data, 4); mbus_data_int_decode(record->data, 4, &int_val);
snprintf(buff, sizeof(buff), "%d", val); snprintf(buff, sizeof(buff), "%d", int_val);
} }
if (debug) if (debug)
@ -2242,9 +2305,9 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x05: // 4 Byte Real (32 bit) case 0x05: // 4 Byte Real (32 bit)
val3 = mbus_data_float_decode(record->data); float_val = mbus_data_float_decode(record->data);
snprintf(buff, sizeof(buff), "%f", val3); snprintf(buff, sizeof(buff), "%f", float_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 4 byte Real\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 4 byte Real\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2253,9 +2316,9 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x06: // 6 byte integer (48 bit) case 0x06: // 6 byte integer (48 bit)
val4 = mbus_data_long_long_decode(record->data, 6); mbus_data_long_long_decode(record->data, 6, &long_long_val);
snprintf(buff, sizeof(buff), "%lld", val4); snprintf(buff, sizeof(buff), "%lld", long_long_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 6 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 6 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2264,9 +2327,9 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x07: // 8 byte integer (64 bit) case 0x07: // 8 byte integer (64 bit)
val4 = mbus_data_long_long_decode(record->data, 8); mbus_data_long_long_decode(record->data, 8, &long_long_val);
snprintf(buff, sizeof(buff), "%lld", val4); snprintf(buff, sizeof(buff), "%lld", long_long_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 8 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 8 byte integer\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2277,8 +2340,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x09: // 2 digit BCD (8 bit) case 0x09: // 2 digit BCD (8 bit)
val = (int)mbus_data_bcd_decode(record->data, 1); int_val = (int)mbus_data_bcd_decode(record->data, 1);
snprintf(buff, sizeof(buff), "%d", val); snprintf(buff, sizeof(buff), "%d", int_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 2 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 2 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2287,8 +2350,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0A: // 4 digit BCD (16 bit) case 0x0A: // 4 digit BCD (16 bit)
val = (int)mbus_data_bcd_decode(record->data, 2); int_val = (int)mbus_data_bcd_decode(record->data, 2);
snprintf(buff, sizeof(buff), "%d", val); snprintf(buff, sizeof(buff), "%d", int_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 4 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 4 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2297,8 +2360,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0B: // 6 digit BCD (24 bit) case 0x0B: // 6 digit BCD (24 bit)
val = (int)mbus_data_bcd_decode(record->data, 3); int_val = (int)mbus_data_bcd_decode(record->data, 3);
snprintf(buff, sizeof(buff), "%d", val); snprintf(buff, sizeof(buff), "%d", int_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 6 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 6 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2307,8 +2370,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0C: // 8 digit BCD (32 bit) case 0x0C: // 8 digit BCD (32 bit)
val = (int)mbus_data_bcd_decode(record->data, 4); int_val = (int)mbus_data_bcd_decode(record->data, 4);
snprintf(buff, sizeof(buff), "%d", val); snprintf(buff, sizeof(buff), "%d", int_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 8 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 8 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2317,8 +2380,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0E: // 12 digit BCD (48 bit) case 0x0E: // 12 digit BCD (48 bit)
val4 = mbus_data_bcd_decode(record->data, 6); long_long_val = mbus_data_bcd_decode(record->data, 6);
snprintf(buff, sizeof(buff), "%lld", val4); snprintf(buff, sizeof(buff), "%lld", long_long_val);
if (debug) if (debug)
printf("%s: DIF 0x%.2x was decoded using 12 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif); printf("%s: DIF 0x%.2x was decoded using 12 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2385,6 +2448,78 @@ mbus_data_record_value(mbus_data_record *record)
return NULL; return NULL;
} }
//------------------------------------------------------------------------------
/// Return the storage number for a variable-length data record
//------------------------------------------------------------------------------
long mbus_data_record_storage_number(mbus_data_record *record)
{
int bit_index;
long result = 0;
int i;
if (record)
{
result |= (record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_STORAGE_NO) >> 6;
bit_index++;
for (i=0; i<record->drh.dib.ndife; i++)
{
result |= (record->drh.dib.dife[i] & MBUS_DATA_RECORD_DIFE_MASK_STORAGE_NO) << bit_index;
bit_index += 4;
}
return result;
}
return 0;
}
//------------------------------------------------------------------------------
/// Return the tariff for a variable-length data record
//------------------------------------------------------------------------------
long mbus_data_record_tariff(mbus_data_record *record)
{
int bit_index;
long result = 0;
int i;
if (record && (record->drh.dib.ndife > 0))
{
for (i=0; i<record->drh.dib.ndife; i++)
{
result |= ((record->drh.dib.dife[i] & MBUS_DATA_RECORD_DIFE_MASK_TARIFF) >> 4) << bit_index;
bit_index += 2;
}
return result;
}
return -1;
}
//------------------------------------------------------------------------------
/// Return device unit for a variable-length data record
//------------------------------------------------------------------------------
int mbus_data_record_device(mbus_data_record *record)
{
int bit_index;
int result = 0;
int i;
if (record && (record->drh.dib.ndife > 0))
{
for (i=0; i<record->drh.dib.ndife; i++)
{
result |= ((record->drh.dib.dife[i] & MBUS_DATA_RECORD_DIFE_MASK_DEVICE) >> 6) << bit_index;
bit_index++;
}
return result;
}
return -1;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/// Return a string containing the function description /// Return a string containing the function description
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -2827,7 +2962,7 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
} }
// re-calculate data length, if of variable length type // re-calculate data length, if of variable length type
if ((record->drh.dib.dif & 0x0F) == 0x0D) // flag for variable length data if ((record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_DATA) == 0x0D) // flag for variable length data
{ {
if(frame->data[i] <= 0xBF) if(frame->data[i] <= 0xBF)
record->data_len = frame->data[i++]; record->data_len = frame->data[i++];
@ -3270,10 +3405,11 @@ mbus_data_variable_print(mbus_data_variable *data)
for (record = data->record; record; record = record->next) for (record = data->record; record; record = record->next)
{ {
// DIF // DIF
printf("DIF = %.2X\n", record->drh.dib.dif); printf("DIF = %.2X\n", record->drh.dib.dif);
printf("DIF.Extension = %s\n", (record->drh.dib.dif & MBUS_DIB_DIF_EXTENSION_BIT) ? "Yes":"No"); printf("DIF.Extension = %s\n", (record->drh.dib.dif & MBUS_DIB_DIF_EXTENSION_BIT) ? "Yes":"No");
printf("DIF.Function = %s\n", (record->drh.dib.dif & 0x30) ? "Minimum value" : "Instantaneous value" ); printf("DIF.StorageNumber = %d\n", (record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_STORAGE_NO) >> 6);
printf("DIF.Data = %.2X\n", record->drh.dib.dif & 0x0F); printf("DIF.Function = %s\n", (record->drh.dib.dif & 0x30) ? "Minimum value" : "Instantaneous value" );
printf("DIF.Data = %.2X\n", record->drh.dib.dif & 0x0F);
// VENDOR SPECIFIC // VENDOR SPECIFIC
if ((record->drh.dib.dif == MBUS_DIB_DIF_MANUFACTURER_SPECIFIC) || if ((record->drh.dib.dif == MBUS_DIB_DIF_MANUFACTURER_SPECIFIC) ||
@ -3301,10 +3437,11 @@ mbus_data_variable_print(mbus_data_variable *data)
{ {
unsigned char dife = record->drh.dib.dife[j]; unsigned char dife = record->drh.dib.dife[j];
printf("DIFE[%zd] = %.2X\n", j, dife); printf("DIFE[%zd] = %.2X\n", j, dife);
printf("DIFE[%zd].Extension = %s\n", j, (dife & MBUS_DIB_DIF_EXTENSION_BIT) ? "Yes" : "No"); printf("DIFE[%zd].Extension = %s\n", j, (dife & MBUS_DATA_RECORD_DIFE_MASK_EXTENSION) ? "Yes" : "No");
printf("DIFE[%zd].Function = %s\n", j, (dife & 0x30) ? "Minimum value" : "Instantaneous value" ); printf("DIFE[%zd].Device = %d\n", j, (dife & MBUS_DATA_RECORD_DIFE_MASK_DEVICE) >> 6 );
printf("DIFE[%zd].Data = %.2X\n", j, dife & 0x0F); printf("DIFE[%zd].Tariff = %d\n", j, (dife & MBUS_DATA_RECORD_DIFE_MASK_TARIFF) >> 4 );
printf("DIFE[%zd].StorageNumber = %.2X\n", j, dife & MBUS_DATA_RECORD_DIFE_MASK_STORAGE_NO);
} }
// VIF // VIF
@ -3332,6 +3469,8 @@ mbus_data_variable_print(mbus_data_variable *data)
int int
mbus_data_fixed_print(mbus_data_fixed *data) mbus_data_fixed_print(mbus_data_fixed *data)
{ {
int val;
if (data) if (data)
{ {
printf("%s: ID = %d\n", __PRETTY_FUNCTION__, (int)mbus_data_bcd_decode(data->id_bcd, 4)); printf("%s: ID = %d\n", __PRETTY_FUNCTION__, (int)mbus_data_bcd_decode(data->id_bcd, 4));
@ -3343,23 +3482,26 @@ mbus_data_fixed_print(mbus_data_fixed *data)
printf("%s: Unit1 = %s\n", __PRETTY_FUNCTION__, mbus_data_fixed_unit(data->cnt1_type)); printf("%s: Unit1 = %s\n", __PRETTY_FUNCTION__, mbus_data_fixed_unit(data->cnt1_type));
if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD) if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD)
{ {
printf("%s: Counter1 = %d\n", __PRETTY_FUNCTION__, (int)mbus_data_bcd_decode(data->cnt1_val, 4)); val = mbus_data_bcd_decode(data->cnt1_val, 4);
} }
else else
{ {
printf("%s: Counter1 = %d\n", __PRETTY_FUNCTION__, mbus_data_int_decode(data->cnt1_val, 4)); mbus_data_int_decode(data->cnt1_val, 4, &val);
} }
printf("%s: Counter1 = %d\n", __PRETTY_FUNCTION__, val);
printf("%s: Medium2 = %s\n", __PRETTY_FUNCTION__, mbus_data_fixed_medium(data)); printf("%s: Medium2 = %s\n", __PRETTY_FUNCTION__, mbus_data_fixed_medium(data));
printf("%s: Unit2 = %s\n", __PRETTY_FUNCTION__, mbus_data_fixed_unit(data->cnt2_type)); printf("%s: Unit2 = %s\n", __PRETTY_FUNCTION__, mbus_data_fixed_unit(data->cnt2_type));
if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD) if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD)
{ {
printf("%s: Counter2 = %d\n", __PRETTY_FUNCTION__, (int)mbus_data_bcd_decode(data->cnt2_val, 4)); val = mbus_data_bcd_decode(data->cnt2_val, 4);
} }
else else
{ {
printf("%s: Counter2 = %d\n", __PRETTY_FUNCTION__, mbus_data_int_decode(data->cnt2_val, 4)); mbus_data_int_decode(data->cnt2_val, 4, &val);
} }
printf("%s: Counter2 = %d\n", __PRETTY_FUNCTION__, val);
} }
return -1; return -1;
@ -3515,6 +3657,7 @@ mbus_data_variable_record_xml(mbus_data_record *record, int record_cnt, int fram
size_t len = 0; size_t len = 0;
struct tm * timeinfo; struct tm * timeinfo;
char timestamp[21]; char timestamp[21];
long tariff;
if (record) if (record)
{ {
@ -3545,6 +3688,19 @@ mbus_data_variable_record_xml(mbus_data_record *record, int record_cnt, int fram
mbus_str_xml_encode(str_encoded, mbus_data_record_function(record), sizeof(str_encoded)); mbus_str_xml_encode(str_encoded, mbus_data_record_function(record), sizeof(str_encoded));
len += snprintf(&buff[len], sizeof(buff) - len, len += snprintf(&buff[len], sizeof(buff) - len,
" <Function>%s</Function>\n", str_encoded); " <Function>%s</Function>\n", str_encoded);
len += snprintf(&buff[len], sizeof(buff) - len,
" <StorageNumber>%ld</StorageNumber>\n",
mbus_data_record_storage_number(record));
if ((tariff = mbus_data_record_tariff(record)) >= 0)
{
len += snprintf(&buff[len], sizeof(buff) - len, " <Tariff>%ld</Tariff>\n",
tariff);
len += snprintf(&buff[len], sizeof(buff) - len, " <Device>%d</Device>\n",
mbus_data_record_device(record));
}
mbus_str_xml_encode(str_encoded, mbus_data_record_unit(record), sizeof(str_encoded)); mbus_str_xml_encode(str_encoded, mbus_data_record_unit(record), sizeof(str_encoded));
len += snprintf(&buff[len], sizeof(buff) - len, len += snprintf(&buff[len], sizeof(buff) - len,
@ -3629,6 +3785,7 @@ mbus_data_fixed_xml(mbus_data_fixed *data)
char *buff = NULL; char *buff = NULL;
char str_encoded[256]; char str_encoded[256];
size_t len = 0, buff_size = 8192; size_t len = 0, buff_size = 8192;
int val;
if (data) if (data)
{ {
@ -3658,12 +3815,14 @@ mbus_data_fixed_xml(mbus_data_fixed *data)
len += snprintf(&buff[len], buff_size - len, " <Unit>%s</Unit>\n", str_encoded); len += snprintf(&buff[len], buff_size - len, " <Unit>%s</Unit>\n", str_encoded);
if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD) if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD)
{ {
len += snprintf(&buff[len], buff_size - len, " <Value>%d</Value>\n", (int)mbus_data_bcd_decode(data->cnt1_val, 4)); val = mbus_data_bcd_decode(data->cnt1_val, 4);
} }
else else
{ {
len += snprintf(&buff[len], buff_size - len, " <Value>%d</Value>\n", mbus_data_int_decode(data->cnt1_val, 4)); mbus_data_int_decode(data->cnt1_val, 4, &val);
} }
len += snprintf(&buff[len], buff_size - len, " <Value>%d</Value>\n", val);
len += snprintf(&buff[len], buff_size - len, " </DataRecord>\n\n"); len += snprintf(&buff[len], buff_size - len, " </DataRecord>\n\n");
len += snprintf(&buff[len], buff_size - len, " <DataRecord id=\"1\">\n"); len += snprintf(&buff[len], buff_size - len, " <DataRecord id=\"1\">\n");
@ -3675,12 +3834,14 @@ mbus_data_fixed_xml(mbus_data_fixed *data)
len += snprintf(&buff[len], buff_size - len, " <Unit>%s</Unit>\n", str_encoded); len += snprintf(&buff[len], buff_size - len, " <Unit>%s</Unit>\n", str_encoded);
if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD) if ((data->status & MBUS_DATA_FIXED_STATUS_FORMAT_MASK) == MBUS_DATA_FIXED_STATUS_FORMAT_BCD)
{ {
len += snprintf(&buff[len], buff_size - len, " <Value>%d</Value>\n", (int)mbus_data_bcd_decode(data->cnt2_val, 4)); val = mbus_data_bcd_decode(data->cnt2_val, 4);
} }
else else
{ {
len += snprintf(&buff[len], buff_size - len, " <Value>%d</Value>\n", mbus_data_int_decode(data->cnt2_val, 4)); mbus_data_int_decode(data->cnt2_val, 4, &val);
} }
len += snprintf(&buff[len], buff_size - len, " <Value>%d</Value>\n", val);
len += snprintf(&buff[len], buff_size - len, " </DataRecord>\n\n"); len += snprintf(&buff[len], buff_size - len, " </DataRecord>\n\n");
len += snprintf(&buff[len], buff_size - len, "</MBusData>\n"); len += snprintf(&buff[len], buff_size - len, "</MBusData>\n");

View File

@ -445,6 +445,11 @@ typedef struct _mbus_data_secondary_address {
#define MBUS_DATA_RECORD_DIF_MASK_EXTENTION 0x80 #define MBUS_DATA_RECORD_DIF_MASK_EXTENTION 0x80
#define MBUS_DATA_RECORD_DIF_MASK_NON_DATA 0xF0 #define MBUS_DATA_RECORD_DIF_MASK_NON_DATA 0xF0
#define MBUS_DATA_RECORD_DIFE_MASK_STORAGE_NO 0x0F
#define MBUS_DATA_RECORD_DIFE_MASK_TARIFF 0x30
#define MBUS_DATA_RECORD_DIFE_MASK_DEVICE 0x40
#define MBUS_DATA_RECORD_DIFE_MASK_EXTENSION 0x80
// //
// GENERAL APPLICATION ERRORS // GENERAL APPLICATION ERRORS
// //
@ -494,6 +499,7 @@ typedef struct _mbus_data_secondary_address {
#define MBUS_VARIABLE_DATA_MAN_ELS 0x1593 #define MBUS_VARIABLE_DATA_MAN_ELS 0x1593
#define MBUS_VARIABLE_DATA_MAN_ELV 0x1596 #define MBUS_VARIABLE_DATA_MAN_ELV 0x1596
#define MBUS_VARIABLE_DATA_MAN_EMH 0x15A8 #define MBUS_VARIABLE_DATA_MAN_EMH 0x15A8
#define MBUS_VARIABLE_DATA_MAN_GMC 0x1DA3
#define MBUS_VARIABLE_DATA_MAN_HYD 0x2324 #define MBUS_VARIABLE_DATA_MAN_HYD 0x2324
#define MBUS_VARIABLE_DATA_MAN_KAM 0x2C2D #define MBUS_VARIABLE_DATA_MAN_KAM 0x2C2D
#define MBUS_VARIABLE_DATA_MAN_LSE 0x3265 #define MBUS_VARIABLE_DATA_MAN_LSE 0x3265
@ -501,6 +507,7 @@ typedef struct _mbus_data_secondary_address {
#define MBUS_VARIABLE_DATA_MAN_NZR 0x3B52 #define MBUS_VARIABLE_DATA_MAN_NZR 0x3B52
#define MBUS_VARIABLE_DATA_MAN_PAD 0x4024 #define MBUS_VARIABLE_DATA_MAN_PAD 0x4024
#define MBUS_VARIABLE_DATA_MAN_QDS 0x4493 #define MBUS_VARIABLE_DATA_MAN_QDS 0x4493
#define MBUS_VARIABLE_DATA_MAN_RAM 0x482D
#define MBUS_VARIABLE_DATA_MAN_RKE 0x4965 #define MBUS_VARIABLE_DATA_MAN_RKE 0x4965
#define MBUS_VARIABLE_DATA_MAN_SEN 0x4CAE #define MBUS_VARIABLE_DATA_MAN_SEN 0x4CAE
#define MBUS_VARIABLE_DATA_MAN_SLB 0x4D82 #define MBUS_VARIABLE_DATA_MAN_SLB 0x4D82
@ -559,6 +566,9 @@ int mbus_frame_internal_pack(mbus_frame *frame, mbus_frame_data *frame_data);
// //
const char *mbus_data_record_function(mbus_data_record *record); const char *mbus_data_record_function(mbus_data_record *record);
const char *mbus_data_fixed_function(int status); const char *mbus_data_fixed_function(int status);
long mbus_data_record_storage_number(mbus_data_record *record);
long mbus_data_record_tariff(mbus_data_record *record);
int mbus_data_record_device(mbus_data_record *record);
// //
// M-Bus frame data struct access/write functions // M-Bus frame data struct access/write functions
@ -613,9 +623,9 @@ int mbus_data_bcd_encode(unsigned char *bcd_data, size_t bcd_data_size, int valu
int mbus_data_int_encode(unsigned char *int_data, size_t int_data_size, int value); int mbus_data_int_encode(unsigned char *int_data, size_t int_data_size, int value);
long long mbus_data_bcd_decode(unsigned char *bcd_data, size_t bcd_data_size); long long mbus_data_bcd_decode(unsigned char *bcd_data, size_t bcd_data_size);
int mbus_data_int_decode(unsigned char *int_data, size_t int_data_size); int mbus_data_int_decode(unsigned char *int_data, size_t int_data_size, int *value);
long mbus_data_long_decode(unsigned char *int_data, size_t int_data_size); int mbus_data_long_decode(unsigned char *int_data, size_t int_data_size, long *value);
long long mbus_data_long_long_decode(unsigned char *int_data, size_t int_data_size); int mbus_data_long_long_decode(unsigned char *int_data, size_t int_data_size, long long *value);
float mbus_data_float_decode(unsigned char *float_data); float mbus_data_float_decode(unsigned char *float_data);

View File

@ -13,78 +13,97 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>5272</Value> <Value>5272</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume (1e-2 m^3)</Unit> <Unit>Volume (1e-2 m^3)</Unit>
<Value>120427</Value> <Value>120427</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Volume (1e-2 m^3)</Unit> <Unit>Volume (1e-2 m^3)</Unit>
<Value>91769</Value> <Value>91769</Value>
</DataRecord> </DataRecord>
<DataRecord id="3"> <DataRecord id="3">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Flow temperature (deg C)</Unit> <Unit>Flow temperature (deg C)</Unit>
<Value>28</Value> <Value>28</Value>
</DataRecord> </DataRecord>
<DataRecord id="4"> <DataRecord id="4">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Return temperature (deg C)</Unit> <Unit>Return temperature (deg C)</Unit>
<Value>34</Value> <Value>34</Value>
</DataRecord> </DataRecord>
<DataRecord id="5"> <DataRecord id="5">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Temperature Difference (1e-1 deg C)</Unit> <Unit>Temperature Difference (1e-1 deg C)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="6"> <DataRecord id="6">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>On time (hours)</Unit> <Unit>On time (hours)</Unit>
<Value>41393</Value> <Value>41393</Value>
</DataRecord> </DataRecord>
<DataRecord id="7"> <DataRecord id="7">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Operating time (hours)</Unit> <Unit>Operating time (hours)</Unit>
<Value>41393</Value> <Value>41393</Value>
</DataRecord> </DataRecord>
<DataRecord id="8"> <DataRecord id="8">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume flow (m m^3/h)</Unit> <Unit>Volume flow (m m^3/h)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="9"> <DataRecord id="9">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="10"> <DataRecord id="10">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Time Point (time &amp; date)</Unit> <Unit>Time Point (time &amp; date)</Unit>
<Value>2013-06-29T12:12:00</Value> <Value>2013-06-29T12:12:00</Value>
</DataRecord> </DataRecord>
<DataRecord id="11"> <DataRecord id="11">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Units for H.C.A.</Unit> <Unit>Units for H.C.A.</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="12"> <DataRecord id="12">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>2</Device>
<Unit>Units for H.C.A.</Unit> <Unit>Units for H.C.A.</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>

View File

@ -91,6 +91,7 @@
<DataRecord id="13"> <DataRecord id="13">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Operating time (hours)</Unit> <Unit>Operating time (hours)</Unit>
<Value>86553</Value> <Value>86553</Value>
</DataRecord> </DataRecord>

View File

@ -13,54 +13,63 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Energy (10 kWh)</Unit> <Unit>Energy (10 kWh)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume (1e-1 m^3)</Unit> <Unit>Volume (1e-1 m^3)</Unit>
<Value>3</Value> <Value>3</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (kW)</Unit> <Unit>Power (kW)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="3"> <DataRecord id="3">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume flow (m m^3/h)</Unit> <Unit>Volume flow (m m^3/h)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="4"> <DataRecord id="4">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Flow temperature (1e-1 deg C)</Unit> <Unit>Flow temperature (1e-1 deg C)</Unit>
<Value>1288</Value> <Value>1288</Value>
</DataRecord> </DataRecord>
<DataRecord id="5"> <DataRecord id="5">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Return temperature (1e-1 deg C)</Unit> <Unit>Return temperature (1e-1 deg C)</Unit>
<Value>516</Value> <Value>516</Value>
</DataRecord> </DataRecord>
<DataRecord id="6"> <DataRecord id="6">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Temperature Difference (1e-2 deg C)</Unit> <Unit>Temperature Difference (1e-2 deg C)</Unit>
<Value>7723</Value> <Value>7723</Value>
</DataRecord> </DataRecord>
<DataRecord id="7"> <DataRecord id="7">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Time Point (date)</Unit> <Unit>Time Point (date)</Unit>
<Value>2012-01-12</Value> <Value>2012-01-12</Value>
</DataRecord> </DataRecord>
<DataRecord id="8"> <DataRecord id="8">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Operating time (days)</Unit> <Unit>Operating time (days)</Unit>
<Value>3383</Value> <Value>3383</Value>
</DataRecord> </DataRecord>

View File

@ -13,120 +13,156 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>1</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>1252</Value> <Value>1252</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>2</StorageNumber>
<Tariff>1</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>1252</Value> <Value>1252</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>2</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>1774433</Value> <Value>1774433</Value>
</DataRecord> </DataRecord>
<DataRecord id="3"> <DataRecord id="3">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>2</StorageNumber>
<Tariff>2</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>1774433</Value> <Value>1774433</Value>
</DataRecord> </DataRecord>
<DataRecord id="4"> <DataRecord id="4">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit> V</Unit> <Unit> V</Unit>
<Value>237</Value> <Value>237</Value>
</DataRecord> </DataRecord>
<DataRecord id="5"> <DataRecord id="5">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-1 A</Unit> <Unit>1e-1 A</Unit>
<Value>32</Value> <Value>32</Value>
</DataRecord> </DataRecord>
<DataRecord id="6"> <DataRecord id="6">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>79</Value> <Value>79</Value>
</DataRecord> </DataRecord>
<DataRecord id="7"> <DataRecord id="7">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>65518</Value> <Value>-18</Value>
</DataRecord> </DataRecord>
<DataRecord id="8"> <DataRecord id="8">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit> V</Unit> <Unit> V</Unit>
<Value>231</Value> <Value>231</Value>
</DataRecord> </DataRecord>
<DataRecord id="9"> <DataRecord id="9">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-1 A</Unit> <Unit>1e-1 A</Unit>
<Value>35</Value> <Value>35</Value>
</DataRecord> </DataRecord>
<DataRecord id="10"> <DataRecord id="10">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>81</Value> <Value>81</Value>
</DataRecord> </DataRecord>
<DataRecord id="11"> <DataRecord id="11">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>65521</Value> <Value>-15</Value>
</DataRecord> </DataRecord>
<DataRecord id="12"> <DataRecord id="12">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit> V</Unit> <Unit> V</Unit>
<Value>228</Value> <Value>228</Value>
</DataRecord> </DataRecord>
<DataRecord id="13"> <DataRecord id="13">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-1 A</Unit> <Unit>1e-1 A</Unit>
<Value>69</Value> <Value>69</Value>
</DataRecord> </DataRecord>
<DataRecord id="14"> <DataRecord id="14">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>160</Value> <Value>160</Value>
</DataRecord> </DataRecord>
<DataRecord id="15"> <DataRecord id="15">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>65504</Value> <Value>-32</Value>
</DataRecord> </DataRecord>
<DataRecord id="16"> <DataRecord id="16">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Manufacturer specific</Unit> <Unit>Manufacturer specific</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="17"> <DataRecord id="17">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>320</Value> <Value>320</Value>
</DataRecord> </DataRecord>
<DataRecord id="18"> <DataRecord id="18">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>65471</Value> <Value>-65</Value>
</DataRecord> </DataRecord>
<DataRecord id="19"> <DataRecord id="19">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Manufacturer specific</Unit> <Unit>Manufacturer specific</Unit>
<Value>4</Value> <Value>4</Value>
</DataRecord> </DataRecord>

View File

@ -13,120 +13,156 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>1</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>254</Value> <Value>254</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>2</StorageNumber>
<Tariff>1</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>254</Value> <Value>254</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>2</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>444128</Value> <Value>444128</Value>
</DataRecord> </DataRecord>
<DataRecord id="3"> <DataRecord id="3">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>2</StorageNumber>
<Tariff>2</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>444128</Value> <Value>444128</Value>
</DataRecord> </DataRecord>
<DataRecord id="4"> <DataRecord id="4">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit> V</Unit> <Unit> V</Unit>
<Value>233</Value> <Value>233</Value>
</DataRecord> </DataRecord>
<DataRecord id="5"> <DataRecord id="5">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-1 A</Unit> <Unit>1e-1 A</Unit>
<Value>1</Value> <Value>1</Value>
</DataRecord> </DataRecord>
<DataRecord id="6"> <DataRecord id="6">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="7"> <DataRecord id="7">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="8"> <DataRecord id="8">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit> V</Unit> <Unit> V</Unit>
<Value>234</Value> <Value>234</Value>
</DataRecord> </DataRecord>
<DataRecord id="9"> <DataRecord id="9">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-1 A</Unit> <Unit>1e-1 A</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="10"> <DataRecord id="10">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="11"> <DataRecord id="11">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="12"> <DataRecord id="12">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit> V</Unit> <Unit> V</Unit>
<Value>235</Value> <Value>235</Value>
</DataRecord> </DataRecord>
<DataRecord id="13"> <DataRecord id="13">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-1 A</Unit> <Unit>1e-1 A</Unit>
<Value>1</Value> <Value>1</Value>
</DataRecord> </DataRecord>
<DataRecord id="14"> <DataRecord id="14">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="15"> <DataRecord id="15">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="16"> <DataRecord id="16">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Manufacturer specific</Unit> <Unit>Manufacturer specific</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="17"> <DataRecord id="17">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="18"> <DataRecord id="18">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (10 W)</Unit> <Unit>Power (10 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="19"> <DataRecord id="19">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Manufacturer specific</Unit> <Unit>Manufacturer specific</Unit>
<Value>4</Value> <Value>4</Value>
</DataRecord> </DataRecord>

View File

@ -13,30 +13,35 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume (m m^3)</Unit> <Unit>Volume (m m^3)</Unit>
<Value>1234567</Value> <Value>1234567</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Time Point (time &amp; date)</Unit> <Unit>Time Point (time &amp; date)</Unit>
<Value>2007-02-06T13:58:00</Value> <Value>2007-02-06T13:58:00</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Unit>Time Point (date)</Unit> <Unit>Time Point (date)</Unit>
<Value>2007-01-01</Value> <Value>2007-01-01</Value>
</DataRecord> </DataRecord>
<DataRecord id="3"> <DataRecord id="3">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Unit>Volume (m m^3)</Unit> <Unit>Volume (m m^3)</Unit>
<Value>456951</Value> <Value>456951</Value>
</DataRecord> </DataRecord>
<DataRecord id="4"> <DataRecord id="4">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Unit>Time Point (date)</Unit> <Unit>Time Point (date)</Unit>
<Value>2008-01-01</Value> <Value>2008-01-01</Value>
</DataRecord> </DataRecord>

View File

@ -13,72 +13,86 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Digital input (binary)</Unit> <Unit>Digital input (binary)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-2 %RH</Unit> <Unit>1e-2 %RH</Unit>
<Value>4564</Value> <Value>4564</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Minimum value</Function> <Function>Minimum value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-2 %RH</Unit> <Unit>1e-2 %RH</Unit>
<Value>4552</Value> <Value>4552</Value>
</DataRecord> </DataRecord>
<DataRecord id="3"> <DataRecord id="3">
<Function>Maximum value</Function> <Function>Maximum value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-2 %RH</Unit> <Unit>1e-2 %RH</Unit>
<Value>5812</Value> <Value>5812</Value>
</DataRecord> </DataRecord>
<DataRecord id="4"> <DataRecord id="4">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>External temperature (1e-2 deg C)</Unit> <Unit>External temperature (1e-2 deg C)</Unit>
<Value>2256</Value> <Value>2256</Value>
</DataRecord> </DataRecord>
<DataRecord id="5"> <DataRecord id="5">
<Function>Minimum value</Function> <Function>Minimum value</Function>
<StorageNumber>0</StorageNumber>
<Unit>External temperature (1e-2 deg C)</Unit> <Unit>External temperature (1e-2 deg C)</Unit>
<Value>2160</Value> <Value>2160</Value>
</DataRecord> </DataRecord>
<DataRecord id="6"> <DataRecord id="6">
<Function>Maximum value</Function> <Function>Maximum value</Function>
<StorageNumber>0</StorageNumber>
<Unit>External temperature (1e-2 deg C)</Unit> <Unit>External temperature (1e-2 deg C)</Unit>
<Value>2339</Value> <Value>2339</Value>
</DataRecord> </DataRecord>
<DataRecord id="7"> <DataRecord id="7">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Averaging Duration (hours)</Unit> <Unit>Averaging Duration (hours)</Unit>
<Value>24</Value> <Value>24</Value>
</DataRecord> </DataRecord>
<DataRecord id="8"> <DataRecord id="8">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Unit>External temperature (1e-2 deg C)</Unit> <Unit>External temperature (1e-2 deg C)</Unit>
<Value>2276</Value> <Value>2276</Value>
</DataRecord> </DataRecord>
<DataRecord id="9"> <DataRecord id="9">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>2</StorageNumber>
<Tariff>0</Tariff>
<Device>0</Device>
<Unit>External temperature (1e-2 deg C)</Unit> <Unit>External temperature (1e-2 deg C)</Unit>
<Value>2269</Value> <Value>2269</Value>
</DataRecord> </DataRecord>
<DataRecord id="10"> <DataRecord id="10">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Fabrication number</Unit> <Unit>Fabrication number</Unit>
<Value>54000834</Value> <Value>54000834</Value>
</DataRecord> </DataRecord>
<DataRecord id="11"> <DataRecord id="11">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Software version</Unit> <Unit>Software version</Unit>
<Value>262144</Value> <Value>262144</Value>
</DataRecord> </DataRecord>

View File

@ -13,18 +13,25 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>1</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>409</Value> <Value>409</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Tariff>0</Tariff>
<Device>0</Device>
<Unit>Power (1e-1 W)</Unit> <Unit>Power (1e-1 W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Error flags</Unit> <Unit>Error flags</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>

View File

@ -0,0 +1 @@
68 91 91 68 08 03 72 78 56 34 12 A3 1D E6 02 02 00 00 00 82 40 FD 48 60 03 82 80 40 FD 48 BF 03 82 C0 40 FD 48 20 04 82 40 FD 59 BD 03 82 80 40 FD 59 1F 04 82 C0 40 FD 59 7E 04 82 40 2B E0 00 82 40 2B 36 FF 84 10 04 94 28 00 00 84 20 04 98 3A 00 00 84 50 04 BF 4E 00 00 84 60 04 A8 61 00 00 84 90 40 04 8B 75 00 00 84 A0 40 04 B8 88 00 00 84 D0 40 04 2D 9D 00 00 84 E0 40 04 C8 AF 00 00 82 41 2B E0 00 82 42 2B 00 00 82 43 2B 00 00 82 44 2B CA 00 42 16

View File

@ -0,0 +1,194 @@
<MBusData>
<SlaveInformation>
<Id>12345678</Id>
<Manufacturer>GMC</Manufacturer>
<Version>230</Version>
<ProductName>GMC-I A230 EMMOD 206</ProductName>
<Medium>Electricity</Medium>
<AccessNumber>2</AccessNumber>
<Status>00</Status>
<Signature>0000</Signature>
</SlaveInformation>
<DataRecord id="0">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>1e-1 V</Unit>
<Value>864</Value>
</DataRecord>
<DataRecord id="1">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>2</Device>
<Unit>1e-1 V</Unit>
<Value>959</Value>
</DataRecord>
<DataRecord id="2">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>3</Device>
<Unit>1e-1 V</Unit>
<Value>1056</Value>
</DataRecord>
<DataRecord id="3">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>m A</Unit>
<Value>957</Value>
</DataRecord>
<DataRecord id="4">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>2</Device>
<Unit>m A</Unit>
<Value>1055</Value>
</DataRecord>
<DataRecord id="5">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>3</Device>
<Unit>m A</Unit>
<Value>1150</Value>
</DataRecord>
<DataRecord id="6">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (W)</Unit>
<Value>224</Value>
</DataRecord>
<DataRecord id="7">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (W)</Unit>
<Value>-202</Value>
</DataRecord>
<DataRecord id="8">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>1</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit>
<Value>10388</Value>
</DataRecord>
<DataRecord id="9">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>2</Tariff>
<Device>0</Device>
<Unit>Energy (10 Wh)</Unit>
<Value>15000</Value>
</DataRecord>
<DataRecord id="10">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>1</Tariff>
<Device>1</Device>
<Unit>Energy (10 Wh)</Unit>
<Value>20159</Value>
</DataRecord>
<DataRecord id="11">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>2</Tariff>
<Device>1</Device>
<Unit>Energy (10 Wh)</Unit>
<Value>25000</Value>
</DataRecord>
<DataRecord id="12">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>1</Tariff>
<Device>2</Device>
<Unit>Energy (10 Wh)</Unit>
<Value>30091</Value>
</DataRecord>
<DataRecord id="13">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>2</Tariff>
<Device>2</Device>
<Unit>Energy (10 Wh)</Unit>
<Value>35000</Value>
</DataRecord>
<DataRecord id="14">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>1</Tariff>
<Device>3</Device>
<Unit>Energy (10 Wh)</Unit>
<Value>40237</Value>
</DataRecord>
<DataRecord id="15">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>2</Tariff>
<Device>3</Device>
<Unit>Energy (10 Wh)</Unit>
<Value>45000</Value>
</DataRecord>
<DataRecord id="16">
<Function>Instantaneous value</Function>
<StorageNumber>2</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (W)</Unit>
<Value>224</Value>
</DataRecord>
<DataRecord id="17">
<Function>Instantaneous value</Function>
<StorageNumber>4</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (W)</Unit>
<Value>0</Value>
</DataRecord>
<DataRecord id="18">
<Function>Instantaneous value</Function>
<StorageNumber>6</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (W)</Unit>
<Value>0</Value>
</DataRecord>
<DataRecord id="19">
<Function>Instantaneous value</Function>
<StorageNumber>8</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Power (W)</Unit>
<Value>202</Value>
</DataRecord>
</MBusData>

View File

@ -13,162 +13,209 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Fabrication number</Unit> <Unit>Fabrication number</Unit>
<Value>6855817</Value> <Value>6855817</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>37351</Value> <Value>37351</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume (1e-2 m^3)</Unit> <Unit>Volume (1e-2 m^3)</Unit>
<Value>56108</Value> <Value>56108</Value>
</DataRecord> </DataRecord>
<DataRecord id="3"> <DataRecord id="3">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>On time (hours)</Unit> <Unit>On time (hours)</Unit>
<Value>985</Value> <Value>985</Value>
</DataRecord> </DataRecord>
<DataRecord id="4"> <DataRecord id="4">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Flow temperature (1e-2 deg C)</Unit> <Unit>Flow temperature (1e-2 deg C)</Unit>
<Value>10169</Value> <Value>10169</Value>
</DataRecord> </DataRecord>
<DataRecord id="5"> <DataRecord id="5">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Return temperature (1e-2 deg C)</Unit> <Unit>Return temperature (1e-2 deg C)</Unit>
<Value>4616</Value> <Value>4616</Value>
</DataRecord> </DataRecord>
<DataRecord id="6"> <DataRecord id="6">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Temperature Difference (1e-2 deg C)</Unit> <Unit>Temperature Difference (1e-2 deg C)</Unit>
<Value>5553</Value> <Value>5553</Value>
</DataRecord> </DataRecord>
<DataRecord id="7"> <DataRecord id="7">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (100 W)</Unit> <Unit>Power (100 W)</Unit>
<Value>347</Value> <Value>347</Value>
</DataRecord> </DataRecord>
<DataRecord id="8"> <DataRecord id="8">
<Function>Maximum value</Function> <Function>Maximum value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (100 W)</Unit> <Unit>Power (100 W)</Unit>
<Value>448</Value> <Value>448</Value>
</DataRecord> </DataRecord>
<DataRecord id="9"> <DataRecord id="9">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume flow (m m^3/h)</Unit> <Unit>Volume flow (m m^3/h)</Unit>
<Value>543</Value> <Value>543</Value>
</DataRecord> </DataRecord>
<DataRecord id="10"> <DataRecord id="10">
<Function>Maximum value</Function> <Function>Maximum value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume flow (m m^3/h)</Unit> <Unit>Volume flow (m m^3/h)</Unit>
<Value>628</Value> <Value>628</Value>
</DataRecord> </DataRecord>
<DataRecord id="11"> <DataRecord id="11">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>1</Tariff>
<Device>0</Device>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="12"> <DataRecord id="12">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>2</Tariff>
<Device>0</Device>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="13"> <DataRecord id="13">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Volume (1e-2 m^3)</Unit> <Unit>Volume (1e-2 m^3)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="14"> <DataRecord id="14">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>2</Device>
<Unit>Volume (1e-2 m^3)</Unit> <Unit>Volume (1e-2 m^3)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="15"> <DataRecord id="15">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>0</Tariff>
<Device>3</Device>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="16"> <DataRecord id="16">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Time Point (time &amp; date)</Unit> <Unit>Time Point (time &amp; date)</Unit>
<Value>2011-01-05T15:26:00</Value> <Value>2011-01-05T15:26:00</Value>
</DataRecord> </DataRecord>
<DataRecord id="17"> <DataRecord id="17">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>33361</Value> <Value>33361</Value>
</DataRecord> </DataRecord>
<DataRecord id="18"> <DataRecord id="18">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Unit>Volume (1e-2 m^3)</Unit> <Unit>Volume (1e-2 m^3)</Unit>
<Value>50098</Value> <Value>50098</Value>
</DataRecord> </DataRecord>
<DataRecord id="19"> <DataRecord id="19">
<Function>Maximum value</Function> <Function>Maximum value</Function>
<StorageNumber>1</StorageNumber>
<Unit>Power (100 W)</Unit> <Unit>Power (100 W)</Unit>
<Value>550</Value> <Value>550</Value>
</DataRecord> </DataRecord>
<DataRecord id="20"> <DataRecord id="20">
<Function>Maximum value</Function> <Function>Maximum value</Function>
<StorageNumber>1</StorageNumber>
<Unit>Volume flow (m m^3/h)</Unit> <Unit>Volume flow (m m^3/h)</Unit>
<Value>1027</Value> <Value>1027</Value>
</DataRecord> </DataRecord>
<DataRecord id="21"> <DataRecord id="21">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Tariff>1</Tariff>
<Device>0</Device>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="22"> <DataRecord id="22">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Tariff>2</Tariff>
<Device>0</Device>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="23"> <DataRecord id="23">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Tariff>0</Tariff>
<Device>1</Device>
<Unit>Volume (1e-2 m^3)</Unit> <Unit>Volume (1e-2 m^3)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="24"> <DataRecord id="24">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Tariff>0</Tariff>
<Device>2</Device>
<Unit>Volume (1e-2 m^3)</Unit> <Unit>Volume (1e-2 m^3)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="25"> <DataRecord id="25">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Tariff>0</Tariff>
<Device>3</Device>
<Unit>Energy (kWh)</Unit> <Unit>Energy (kWh)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="26"> <DataRecord id="26">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>1</StorageNumber>
<Unit>Time Point (date)</Unit> <Unit>Time Point (date)</Unit>
<Value>2010-12-31</Value> <Value>2010-12-31</Value>
</DataRecord> </DataRecord>

View File

@ -13,18 +13,25 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume (m m^3)</Unit> <Unit>Volume (m m^3)</Unit>
<Value>12565</Value> <Value>12565</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Maximum value</Function> <Function>Maximum value</Function>
<StorageNumber>5</StorageNumber>
<Tariff>0</Tariff>
<Device>0</Device>
<Unit>Volume flow (m m^3/h)</Unit> <Unit>Volume flow (m m^3/h)</Unit>
<Value>113</Value> <Value>113</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Tariff>2</Tariff>
<Device>1</Device>
<Unit>Energy (10 Wh)</Unit> <Unit>Energy (10 Wh)</Unit>
<Value>21837</Value> <Value>21837</Value>
</DataRecord> </DataRecord>

View File

@ -13,6 +13,7 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Fabrication number</Unit> <Unit>Fabrication number</Unit>
<Value>1020304</Value> <Value>1020304</Value>
</DataRecord> </DataRecord>

View File

@ -13,36 +13,42 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Energy (Wh)</Unit> <Unit>Energy (Wh)</Unit>
<Value>1274</Value> <Value>1274</Value>
</DataRecord> </DataRecord>
<DataRecord id="1"> <DataRecord id="1">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Energy (Wh)</Unit> <Unit>Energy (Wh)</Unit>
<Value>1274</Value> <Value>1274</Value>
</DataRecord> </DataRecord>
<DataRecord id="2"> <DataRecord id="2">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-1 V</Unit> <Unit>1e-1 V</Unit>
<Value>2372</Value> <Value>2372</Value>
</DataRecord> </DataRecord>
<DataRecord id="3"> <DataRecord id="3">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>1e-1 A</Unit> <Unit>1e-1 A</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="4"> <DataRecord id="4">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (W)</Unit> <Unit>Power (W)</Unit>
<Value>0</Value> <Value>0</Value>
</DataRecord> </DataRecord>
<DataRecord id="5"> <DataRecord id="5">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Fabrication number</Unit> <Unit>Fabrication number</Unit>
<Value>30100608</Value> <Value>30100608</Value>
</DataRecord> </DataRecord>

View File

@ -13,6 +13,7 @@
<DataRecord id="0"> <DataRecord id="0">
<Function>Instantaneous value</Function> <Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Energy (Wh)</Unit> <Unit>Energy (Wh)</Unit>
<Value>5000</Value> <Value>5000</Value>
</DataRecord> </DataRecord>