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
commit 0102dc6ae5
22 changed files with 945 additions and 250 deletions

View File

@ -15,6 +15,35 @@
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.
//------------------------------------------------------------------------------
@ -79,15 +108,24 @@ main(int argc, char **argv)
if (mbus_connect(handle) == -1)
{
fprintf(stderr,"Failed to setup connection to M-bus gateway\n");
mbus_context_free(handle);
return 1;
}
if (mbus_serial_set_baudrate(handle, baudrate) == -1)
{
fprintf(stderr,"Failed to set baud rate.\n");
mbus_disconnect(handle);
mbus_context_free(handle);
return 1;
}
if (init_slaves(handle) == 0)
{
mbus_disconnect(handle);
mbus_context_free(handle);
return 1;
}
if (mbus_is_secondary_address(addr_str))
{
@ -100,36 +138,40 @@ main(int argc, char **argv)
if (ret == MBUS_PROBE_COLLISION)
{
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;
}
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);
mbus_disconnect(handle);
mbus_context_free(handle);
return 1;
}
else if (ret == MBUS_PROBE_ERROR)
{
fprintf(stderr, "%s: Error: Failed to select secondary address [%s].\n", __PRETTY_FUNCTION__, addr_str);
mbus_disconnect(handle);
mbus_context_free(handle);
return 1;
}
// else MBUS_PROBE_SINGLE
if (mbus_send_request_frame(handle, MBUS_ADDRESS_NETWORK_LAYER) == -1)
{
fprintf(stderr, "Failed to send M-Bus request frame.\n");
return 1;
}
address = MBUS_ADDRESS_NETWORK_LAYER;
}
else
{
// primary addressing
address = atoi(addr_str);
if (mbus_send_request_frame(handle, address) == -1)
{
fprintf(stderr, "Failed to send M-Bus request frame.\n");
return 1;
}
}
if (mbus_send_request_frame(handle, address) == -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)
@ -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)
{
mbus_frame_print(&reply);
}
//
// parse data
//
if (mbus_frame_data_parse(&reply, &reply_data) == -1)
{
fprintf(stderr, "M-bus data parse error: %s\n", mbus_error_str());
mbus_disconnect(handle);
mbus_context_free(handle);
return 1;
}
//
// generate XML and print to standard output
//
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());
mbus_disconnect(handle);
mbus_context_free(handle);
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));
for (i = 0; i <= handle->max_retry; i++)
for (i = 0; i <= handle->max_search_retry; i++)
{
if (debug)
{
@ -126,7 +126,7 @@ main(int argc, char **argv)
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");
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));
for (i = 0; i <= handle->max_retry; i++)
for (i = 0; i <= handle->max_search_retry; i++)
{
if (debug)
{
@ -112,7 +112,7 @@ main(int argc, char **argv)
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");
return 1;

View File

@ -214,9 +214,17 @@ mbus_variable_vif vif_table[] = {
/* E111 1010 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" },
/* Any VIF: 7Eh */
{ 0xFE, 1.0, "", "Any VIF" },
/* Manufacturer specific: FFh */
{ 0xFF, 1.0, "", "Manufacturer specific" },
@ -567,32 +575,22 @@ mbus_variable_vif vif_table[] = {
{ 0x235, 1.0e0, "Reserved", "Reserved" },
{ 0x236, 1.0e0, "Reserved", "Reserved" },
{ 0x237, 1.0e0, "Reserved", "Reserved" },
/* E101 10nn Flow Temperature 10(nn-3) °F 0.001°F to 1°F */
{ 0x238, 1.0e-3, "°F", "Flow temperature" },
{ 0x239, 1.0e-2, "°F", "Flow temperature" },
{ 0x23A, 1.0e-1, "°F", "Flow temperature" },
{ 0x23B, 1.0e0, "°F", "Flow temperature" },
/* E101 11nn Return Temperature 10(nn-3) °F 0.001°F to 1°F */
{ 0x23C, 1.0e-3, "°F", "Return temperature" },
{ 0x23D, 1.0e-2, "°F", "Return temperature" },
{ 0x23E, 1.0e-1, "°F", "Return temperature" },
{ 0x23F, 1.0e0, "°F", "Return temperature" },
/* E110 00nn Temperature Difference 10(nn-3) °F 0.001°F to 1°F */
{ 0x240, 1.0e-3, "°F", "Temperature difference" },
{ 0x241, 1.0e-2, "°F", "Temperature difference" },
{ 0x242, 1.0e-1, "°F", "Temperature difference" },
{ 0x243, 1.0e0, "°F", "Temperature difference" },
/* E110 01nn External Temperature 10(nn-3) °F 0.001°F to 1°F */
{ 0x244, 1.0e-3, "°F", "External temperature" },
{ 0x245, 1.0e-2, "°F", "External temperature" },
{ 0x246, 1.0e-1, "°F", "External temperature" },
{ 0x247, 1.0e0, "°F", "External temperature" },
/* E110 1nnn Reserved */
{ 0x238, 1.0e0, "Reserved", "Reserved" },
{ 0x239, 1.0e0, "Reserved", "Reserved" },
{ 0x23A, 1.0e0, "Reserved", "Reserved" },
{ 0x23B, 1.0e0, "Reserved", "Reserved" },
{ 0x23C, 1.0e0, "Reserved", "Reserved" },
{ 0x23D, 1.0e0, "Reserved", "Reserved" },
{ 0x23E, 1.0e0, "Reserved", "Reserved" },
{ 0x23F, 1.0e0, "Reserved", "Reserved" },
{ 0x240, 1.0e0, "Reserved", "Reserved" },
{ 0x241, 1.0e0, "Reserved", "Reserved" },
{ 0x242, 1.0e0, "Reserved", "Reserved" },
{ 0x243, 1.0e0, "Reserved", "Reserved" },
{ 0x244, 1.0e0, "Reserved", "Reserved" },
{ 0x245, 1.0e0, "Reserved", "Reserved" },
{ 0x246, 1.0e0, "Reserved", "Reserved" },
{ 0x247, 1.0e0, "Reserved", "Reserved" },
{ 0x248, 1.0e0, "Reserved", "Reserved" },
{ 0x249, 1.0e0, "Reserved", "Reserved" },
{ 0x24A, 1.0e0, "Reserved", "Reserved" },
@ -601,28 +599,70 @@ mbus_variable_vif vif_table[] = {
{ 0x24D, 1.0e0, "Reserved", "Reserved" },
{ 0x24E, 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) °F 0.001°F to 1°F */
{ 0x258, 1.0e-3, "°F", "Flow temperature" },
{ 0x259, 1.0e-2, "°F", "Flow temperature" },
{ 0x25A, 1.0e-1, "°F", "Flow temperature" },
{ 0x25B, 1.0e0, "°F", "Flow temperature" },
/* E101 11nn Return Temperature 10(nn-3) °F 0.001°F to 1°F */
{ 0x25C, 1.0e-3, "°F", "Return temperature" },
{ 0x25D, 1.0e-2, "°F", "Return temperature" },
{ 0x25E, 1.0e-1, "°F", "Return temperature" },
{ 0x25F, 1.0e0, "°F", "Return temperature" },
/* E110 00nn Temperature Difference 10(nn-3) °F 0.001°F to 1°F */
{ 0x260, 1.0e-3, "°F", "Temperature difference" },
{ 0x261, 1.0e-2, "°F", "Temperature difference" },
{ 0x262, 1.0e-1, "°F", "Temperature difference" },
{ 0x263, 1.0e0, "°F", "Temperature difference" },
/* E110 01nn External Temperature 10(nn-3) °F 0.001°F to 1°F */
{ 0x264, 1.0e-3, "°F", "External temperature" },
{ 0x265, 1.0e-2, "°F", "External temperature" },
{ 0x266, 1.0e-1, "°F", "External temperature" },
{ 0x267, 1.0e0, "°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) °F 0.001°F to 1°F */
{ 0x250, 1.0e-3, "°F", "Cold / Warm Temperature Limit" },
{ 0x251, 1.0e-2, "°F", "Cold / Warm Temperature Limit" },
{ 0x252, 1.0e-1, "°F", "Cold / Warm Temperature Limit" },
{ 0x253, 1.0e0, "°F", "Cold / Warm Temperature Limit" },
{ 0x270, 1.0e-3, "°F", "Cold / Warm Temperature Limit" },
{ 0x271, 1.0e-2, "°F", "Cold / Warm Temperature Limit" },
{ 0x272, 1.0e-1, "°F", "Cold / Warm Temperature Limit" },
{ 0x273, 1.0e0, "°F", "Cold / Warm Temperature Limit" },
/* E111 01nn Cold / Warm Temperature Limit 10(nn-3) °C 0.001°C to 1°C */
{ 0x254, 1.0e-3, "°C", "Cold / Warm Temperature Limit" },
{ 0x255, 1.0e-2, "°C", "Cold / Warm Temperature Limit" },
{ 0x256, 1.0e-1, "°C", "Cold / Warm Temperature Limit" },
{ 0x257, 1.0e0, "°C", "Cold / Warm Temperature Limit" },
{ 0x274, 1.0e-3, "°C", "Cold / Warm Temperature Limit" },
{ 0x275, 1.0e-2, "°C", "Cold / Warm Temperature Limit" },
{ 0x276, 1.0e-1, "°C", "Cold / Warm Temperature Limit" },
{ 0x277, 1.0e0, "°C", "Cold / Warm Temperature Limit" },
/* E111 1nnn cumul. count max power § 10(nnn-3) W 0.001W to 10000W */
{ 0x258, 1.0e-3, "W", "Cumul count max power" },
{ 0x259, 1.0e-3, "W", "Cumul count max power" },
{ 0x25A, 1.0e-1, "W", "Cumul count max power" },
{ 0x25B, 1.0e0, "W", "Cumul count max power" },
{ 0x25C, 1.0e1, "W", "Cumul count max power" },
{ 0x25D, 1.0e2, "W", "Cumul count max power" },
{ 0x25E, 1.0e3, "W", "Cumul count max power" },
{ 0x25F, 1.0e4, "W", "Cumul count max power" },
{ 0x278, 1.0e-3, "W", "Cumul count max power" },
{ 0x279, 1.0e-3, "W", "Cumul count max power" },
{ 0x27A, 1.0e-1, "W", "Cumul count max power" },
{ 0x27B, 1.0e0, "W", "Cumul count max power" },
{ 0x27C, 1.0e1, "W", "Cumul count max power" },
{ 0x27D, 1.0e2, "W", "Cumul count max power" },
{ 0x27E, 1.0e3, "W", "Cumul count max power" },
{ 0x27F, 1.0e4, "W", "Cumul count max power" },
/* End of array */
{ 0xFFFF, 0.0, "", "" },
@ -794,6 +834,9 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
int result = 0;
unsigned char vif, vife;
struct tm time;
int value_out_int;
long value_out_long;
long long value_out_long_long;
*value_out_real = 0.0;
*value_out_str = NULL;
*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);
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 */
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;
case 0x01: /* 1 byte integer (8 bit) */
*value_out_real = mbus_data_int_decode(record->data, 1);
result = 0;
result = mbus_data_int_decode(record->data, 1, &value_out_int);
*value_out_real = value_out_int;
break;
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_mon + 1),
time.tm_mday);
result = 0;
}
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;
case 0x03: /* 3 byte integer (24 bit) */
*value_out_real = mbus_data_int_decode(record->data, 3);
result = 0;
result = mbus_data_int_decode(record->data, 3, &value_out_int);
*value_out_real = value_out_int;
break;
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_min,
time.tm_sec);
result = 0;
}
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;
case 0x05: /* 32b real */
@ -886,13 +930,13 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
break;
case 0x06: /* 6 byte integer (48 bit) */
*value_out_real = mbus_data_long_long_decode(record->data, 6);
result = 0;
result = mbus_data_long_long_decode(record->data, 6, &value_out_long_long);
*value_out_real = value_out_long_long;
break;
case 0x07: /* 8 byte integer (64 bit) */
*value_out_real = mbus_data_long_long_decode(record->data, 8);
result = 0;
result = mbus_data_long_long_decode(record->data, 8, &value_out_long_long);
*value_out_real = value_out_long_long;
break;
case 0x09: /* 2 digit BCD (8 bit) */
@ -1112,6 +1156,9 @@ mbus_record_new()
record->unit = NULL;
record->function_medium = NULL;
record->quantity = NULL;
record->device = -1;
record->tariff = -1;
record->storage_number = 0;
return record;
}
@ -1177,7 +1224,7 @@ mbus_parse_fixed_record(char status_byte, char medium_unit, unsigned char *data)
}
else
{
value = mbus_data_int_decode(data, 4);
mbus_data_long_decode(data, 4, &value);
}
record->unit = NULL;
@ -1213,6 +1260,10 @@ mbus_parse_variable_record(mbus_data_record *data)
MBUS_ERROR("%s: memory allocation error\n", __PRETTY_FUNCTION__);
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) ||
(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));
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));
@ -1430,7 +1489,8 @@ mbus_context_serial(const char *device)
return NULL;
}
handle->max_retry = 3;
handle->max_data_retry = 3;
handle->max_search_retry = 1;
handle->is_serial = 1;
handle->purge_first_frame = MBUS_FRAME_PURGE_M2S;
handle->auxdata = serial_data;
@ -1477,7 +1537,8 @@ mbus_context_tcp(const char *host, uint16_t port)
return NULL;
}
handle->max_retry = 3;
handle->max_data_retry = 3;
handle->max_search_retry = 1;
handle->is_serial = 0;
handle->purge_first_frame = MBUS_FRAME_PURGE_M2S;
handle->auxdata = tcp_data;
@ -1549,10 +1610,17 @@ mbus_context_set_option(mbus_handle * handle, mbus_context_option option, long v
switch (option)
{
case MBUS_OPTION_MAX_RETRY:
case MBUS_OPTION_MAX_DATA_RETRY:
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;
}
break;
@ -1934,7 +2002,7 @@ mbus_sendrecv_request(mbus_handle *handle, int address, mbus_frame *reply, int m
while (more_frames)
{
if (retry > handle->max_retry)
if (retry > handle->max_data_retry)
{
// Give up
retval = 1;
@ -2155,7 +2223,7 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask)
int
mbus_probe_secondary_address(mbus_handle *handle, const char *mask, char *matching_addr)
{
int ret;
int ret, i;
mbus_frame reply;
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;
}
ret = mbus_select_secondary_address(handle, mask);
if (ret == MBUS_PROBE_SINGLE)
for (i = 0; i <= handle->max_search_retry; i++)
{
/* 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;
}
ret = mbus_select_secondary_address(handle, mask);
memset((void *)&reply, 0, sizeof(mbus_frame));
ret = mbus_recv_frame(handle, &reply);
if (ret == MBUS_PROBE_SINGLE)
{
/* 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)
{
return MBUS_PROBE_NOTHING;
}
memset((void *)&reply, 0, sizeof(mbus_frame));
ret = mbus_recv_frame(handle, &reply);
if (ret == MBUS_RECV_RESULT_INVALID)
{
/* 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)
if (ret == MBUS_RECV_RESULT_TIMEOUT)
{
// 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)
if (ret == MBUS_RECV_RESULT_INVALID)
{
handle->found_event(handle,&reply);
}
/* check for more data (collision) */
mbus_purge_frames(handle);
return MBUS_PROBE_COLLISION;
}
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;
}
}
/* 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;
}
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;
}
@ -2252,7 +2329,6 @@ int mbus_read_slave(mbus_handle * handle, mbus_address *address, mbus_frame * re
{
/* secondary addressing */
int probe_ret;
char matching_addr[16];
if (address->secondary == NULL)
{
@ -2261,7 +2337,7 @@ int mbus_read_slave(mbus_handle * handle, mbus_address *address, mbus_frame * re
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)
{
@ -2338,6 +2414,7 @@ mbus_scan_2nd_address_range(mbus_handle * handle, int pos, char *addr_mask)
if (mask[pos] == 'f' || mask[pos] == 'F')
{
// mask[pos] is a wildcard -> enumerate all 0..9 at this position
i_start = 0;
i_end = 9;
}
@ -2345,44 +2422,50 @@ mbus_scan_2nd_address_range(mbus_handle * handle, int pos, char *addr_mask)
{
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);
}
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_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;
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)
for (i = i_start; i <= i_end; i++)
{
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 {
int fd;
int max_retry;
int max_data_retry;
int max_search_retry;
char purge_first_frame;
char is_serial; /**< _handle type (non zero for serial) */
int (*open) (struct _mbus_handle *handle);
@ -142,13 +143,17 @@ typedef struct _mbus_record {
char *unit; /**< Quantity unit (e.g. Wh) */
char *function_medium; /**< Quantity medium or function (e.g. Electricity) */
char *quantity; /**< Quantity type (e.g. Energy) */
int device; /**< Quantity device */
long tariff; /**< Quantity tariff */
long storage_number; /**< Quantity storage number */
} mbus_record;
/**
* MBus handle option enumeration
*/
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_context_option;

View File

@ -480,60 +480,105 @@ 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)
mbus_data_int_decode(unsigned char *int_data, size_t int_data_size, int *value)
{
int val = 0;
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--)
{
val = (val << 8) + int_data[i-1];
}
return val;
return -1;
}
neg = int_data[int_data_size-1] & 0x80;
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
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 val = 0;
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--)
{
val = (val << 8) + int_data[i-1];
}
return val;
return -1;
}
neg = int_data[int_data_size-1] & 0x80;
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
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)
{
long long val = 0;
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--)
{
val = (val << 8) + int_data[i-1];
}
return val;
return -1;
}
neg = int_data[int_data_size-1] & 0x80;
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[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[1] = (char)(((m_id>>5) & 0x001F) + 64);
@ -830,6 +875,15 @@ mbus_data_product_name(mbus_data_variable_header *header)
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)
{
switch (header->version)
@ -869,6 +923,15 @@ mbus_data_product_name(mbus_data_variable_header *header)
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)
{
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.
//------------------------------------------------------------------------------
unsigned char
mbus_dif_datalength_lookup(unsigned char dif)
{
switch (dif&0x0F)
switch (dif & MBUS_DATA_RECORD_DIF_MASK_DATA)
{
case 0x0:
return 0;
@ -2149,16 +2212,16 @@ mbus_data_record_decode(mbus_data_record *record)
if (record)
{
int val;
float val3;
long long val4;
int int_val;
float float_val;
long long long_long_val;
struct tm time;
// ignore extension bit
vif = (record->drh.vib.vif & 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
@ -2168,9 +2231,9 @@ mbus_data_record_decode(mbus_data_record *record)
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)
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
{
val = mbus_data_int_decode(record->data, 2);
snprintf(buff, sizeof(buff), "%d", val);
mbus_data_int_decode(record->data, 2, &int_val);
snprintf(buff, sizeof(buff), "%d", int_val);
if (debug)
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)
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)
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
{
val = mbus_data_int_decode(record->data, 4);
snprintf(buff, sizeof(buff), "%d", val);
mbus_data_int_decode(record->data, 4, &int_val);
snprintf(buff, sizeof(buff), "%d", int_val);
}
if (debug)
@ -2242,9 +2305,9 @@ mbus_data_record_decode(mbus_data_record *record)
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)
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)
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)
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)
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)
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)
val = (int)mbus_data_bcd_decode(record->data, 1);
snprintf(buff, sizeof(buff), "%d", val);
int_val = (int)mbus_data_bcd_decode(record->data, 1);
snprintf(buff, sizeof(buff), "%d", int_val);
if (debug)
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)
val = (int)mbus_data_bcd_decode(record->data, 2);
snprintf(buff, sizeof(buff), "%d", val);
int_val = (int)mbus_data_bcd_decode(record->data, 2);
snprintf(buff, sizeof(buff), "%d", int_val);
if (debug)
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)
val = (int)mbus_data_bcd_decode(record->data, 3);
snprintf(buff, sizeof(buff), "%d", val);
int_val = (int)mbus_data_bcd_decode(record->data, 3);
snprintf(buff, sizeof(buff), "%d", int_val);
if (debug)
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)
val = (int)mbus_data_bcd_decode(record->data, 4);
snprintf(buff, sizeof(buff), "%d", val);
int_val = (int)mbus_data_bcd_decode(record->data, 4);
snprintf(buff, sizeof(buff), "%d", int_val);
if (debug)
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)
val4 = mbus_data_bcd_decode(record->data, 6);
snprintf(buff, sizeof(buff), "%lld", val4);
long_long_val = mbus_data_bcd_decode(record->data, 6);
snprintf(buff, sizeof(buff), "%lld", long_long_val);
if (debug)
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 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
//------------------------------------------------------------------------------
@ -2827,7 +2962,7 @@ mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data)
}
// 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)
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)
{
// 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.Function = %s\n", (record->drh.dib.dif & 0x30) ? "Minimum value" : "Instantaneous value" );
printf("DIF.Data = %.2X\n", record->drh.dib.dif & 0x0F);
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.StorageNumber = %d\n", (record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_STORAGE_NO) >> 6);
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
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];
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].Function = %s\n", j, (dife & 0x30) ? "Minimum value" : "Instantaneous value" );
printf("DIFE[%zd].Data = %.2X\n", j, dife & 0x0F);
printf("DIFE[%zd] = %.2X\n", j, dife);
printf("DIFE[%zd].Extension = %s\n", j, (dife & MBUS_DATA_RECORD_DIFE_MASK_EXTENSION) ? "Yes" : "No");
printf("DIFE[%zd].Device = %d\n", j, (dife & MBUS_DATA_RECORD_DIFE_MASK_DEVICE) >> 6 );
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
@ -3332,6 +3469,8 @@ mbus_data_variable_print(mbus_data_variable *data)
int
mbus_data_fixed_print(mbus_data_fixed *data)
{
int val;
if (data)
{
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));
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
{
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: 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)
{
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
{
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;
@ -3515,6 +3657,7 @@ mbus_data_variable_record_xml(mbus_data_record *record, int record_cnt, int fram
size_t len = 0;
struct tm * timeinfo;
char timestamp[21];
long tariff;
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));
len += snprintf(&buff[len], sizeof(buff) - len,
" <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));
len += snprintf(&buff[len], sizeof(buff) - len,
@ -3629,6 +3785,7 @@ mbus_data_fixed_xml(mbus_data_fixed *data)
char *buff = NULL;
char str_encoded[256];
size_t len = 0, buff_size = 8192;
int val;
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);
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
{
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 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);
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
{
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, "</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_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
//
@ -494,6 +499,7 @@ typedef struct _mbus_data_secondary_address {
#define MBUS_VARIABLE_DATA_MAN_ELS 0x1593
#define MBUS_VARIABLE_DATA_MAN_ELV 0x1596
#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_KAM 0x2C2D
#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_PAD 0x4024
#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_SEN 0x4CAE
#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_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
@ -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);
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);
long mbus_data_long_decode(unsigned char *int_data, size_t int_data_size);
long long mbus_data_long_long_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);
int mbus_data_long_decode(unsigned char *int_data, size_t int_data_size, long *value);
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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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