Improve BCD decoding (#167)

* Introduce mbus_data_bcd_decode_hex

The convert function mbus_data_bcd_decode (BCD to decimal) suffers from
information loss in case of hexacimal digits. So introduce a new function
mbus_data_bcd_decode_hex (BCD to hexadecimal), which isn't affected and
use this for default XML output. But keep mbus_data_bcd_decode for
normalized output.
This commit is contained in:
Stefan Wahren 2020-06-28 10:28:40 +02:00 committed by GitHub
parent 1e25cf1096
commit 17a73287c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 58 additions and 33 deletions

View File

@ -490,7 +490,7 @@ mbus_data_bcd_encode(unsigned char *bcd_data, size_t bcd_data_size, int value)
//------------------------------------------------------------------------------
///
/// Decode BCD data
/// Decode BCD data (decimal)
///
//------------------------------------------------------------------------------
long long
@ -525,6 +525,30 @@ mbus_data_bcd_decode(unsigned char *bcd_data, size_t bcd_data_size)
return -1;
}
//------------------------------------------------------------------------------
///
/// Decode BCD data (hexadecimal)
///
//------------------------------------------------------------------------------
long long
mbus_data_bcd_decode_hex(unsigned char *bcd_data, size_t bcd_data_size)
{
long long val = 0;
size_t i;
if (bcd_data)
{
for (i = bcd_data_size; i > 0; i--)
{
val = (val << 8) | bcd_data[i-1];
}
return val;
}
return -1;
}
//------------------------------------------------------------------------------
///
/// Decode INTEGER data
@ -2730,8 +2754,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x09: // 2 digit BCD (8 bit)
int_val = (int)mbus_data_bcd_decode(record->data, 1);
snprintf(buff, sizeof(buff), "%d", int_val);
int_val = (int)mbus_data_bcd_decode_hex(record->data, 1);
snprintf(buff, sizeof(buff), "%X", int_val);
if (debug)
printf("%s: DIF 0x%.2x was decoded using 2 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2740,8 +2764,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0A: // 4 digit BCD (16 bit)
int_val = (int)mbus_data_bcd_decode(record->data, 2);
snprintf(buff, sizeof(buff), "%d", int_val);
int_val = (int)mbus_data_bcd_decode_hex(record->data, 2);
snprintf(buff, sizeof(buff), "%X", int_val);
if (debug)
printf("%s: DIF 0x%.2x was decoded using 4 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2750,8 +2774,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0B: // 6 digit BCD (24 bit)
int_val = (int)mbus_data_bcd_decode(record->data, 3);
snprintf(buff, sizeof(buff), "%d", int_val);
int_val = (int)mbus_data_bcd_decode_hex(record->data, 3);
snprintf(buff, sizeof(buff), "%X", int_val);
if (debug)
printf("%s: DIF 0x%.2x was decoded using 6 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2760,8 +2784,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0C: // 8 digit BCD (32 bit)
int_val = (int)mbus_data_bcd_decode(record->data, 4);
snprintf(buff, sizeof(buff), "%d", int_val);
int_val = (int)mbus_data_bcd_decode_hex(record->data, 4);
snprintf(buff, sizeof(buff), "%X", int_val);
if (debug)
printf("%s: DIF 0x%.2x was decoded using 8 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -2770,8 +2794,8 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0E: // 12 digit BCD (48 bit)
long_long_val = mbus_data_bcd_decode(record->data, 6);
snprintf(buff, sizeof(buff), "%lld", long_long_val);
long_long_val = mbus_data_bcd_decode_hex(record->data, 6);
snprintf(buff, sizeof(buff), "%llX", long_long_val);
if (debug)
printf("%s: DIF 0x%.2x was decoded using 12 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@ -3761,8 +3785,8 @@ mbus_data_variable_header_print(mbus_data_variable_header *header)
{
if (header)
{
printf("%s: ID = %lld\n", __PRETTY_FUNCTION__,
mbus_data_bcd_decode(header->id_bcd, 4));
printf("%s: ID = %llX\n", __PRETTY_FUNCTION__,
mbus_data_bcd_decode_hex(header->id_bcd, 4));
printf("%s: Manufacturer = 0x%.2X%.2X\n", __PRETTY_FUNCTION__,
header->manufacturer[1], header->manufacturer[0]);
@ -3863,7 +3887,7 @@ mbus_data_fixed_print(mbus_data_fixed *data)
if (data)
{
printf("%s: ID = %lld\n", __PRETTY_FUNCTION__, mbus_data_bcd_decode(data->id_bcd, 4));
printf("%s: ID = %llX\n", __PRETTY_FUNCTION__, mbus_data_bcd_decode_hex(data->id_bcd, 4));
printf("%s: Access # = 0x%.2X\n", __PRETTY_FUNCTION__, data->tx_cnt);
printf("%s: Status = 0x%.2X\n", __PRETTY_FUNCTION__, data->status);
printf("%s: Function = %s\n", __PRETTY_FUNCTION__, mbus_data_fixed_function(data->status));
@ -3872,7 +3896,7 @@ 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 = %lld\n", __PRETTY_FUNCTION__, mbus_data_bcd_decode(data->cnt1_val, 4));
printf("%s: Counter1 = %llX\n", __PRETTY_FUNCTION__, mbus_data_bcd_decode_hex(data->cnt1_val, 4));
}
else
{
@ -3884,7 +3908,7 @@ mbus_data_fixed_print(mbus_data_fixed *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 = %lld\n", __PRETTY_FUNCTION__, mbus_data_bcd_decode(data->cnt2_val, 4));
printf("%s: Counter2 = %llX\n", __PRETTY_FUNCTION__, mbus_data_bcd_decode_hex(data->cnt2_val, 4));
}
else
{
@ -4015,7 +4039,7 @@ mbus_data_variable_header_xml(mbus_data_variable_header *header)
{
len += snprintf(&buff[len], sizeof(buff) - len, " <SlaveInformation>\n");
len += snprintf(&buff[len], sizeof(buff) - len, " <Id>%lld</Id>\n", mbus_data_bcd_decode(header->id_bcd, 4));
len += snprintf(&buff[len], sizeof(buff) - len, " <Id>%llX</Id>\n", mbus_data_bcd_decode_hex(header->id_bcd, 4));
len += snprintf(&buff[len], sizeof(buff) - len, " <Manufacturer>%s</Manufacturer>\n",
mbus_decode_manufacturer(header->manufacturer[0], header->manufacturer[1]));
len += snprintf(&buff[len], sizeof(buff) - len, " <Version>%d</Version>\n", header->version);
@ -4193,7 +4217,7 @@ mbus_data_fixed_xml(mbus_data_fixed *data)
len += snprintf(&buff[len], buff_size - len, "<MBusData>\n\n");
len += snprintf(&buff[len], buff_size - len, " <SlaveInformation>\n");
len += snprintf(&buff[len], buff_size - len, " <Id>%lld</Id>\n", mbus_data_bcd_decode(data->id_bcd, 4));
len += snprintf(&buff[len], buff_size - len, " <Id>%llX</Id>\n", mbus_data_bcd_decode_hex(data->id_bcd, 4));
mbus_str_xml_encode(str_encoded, mbus_data_fixed_medium(data), sizeof(str_encoded));
len += snprintf(&buff[len], buff_size - len, " <Medium>%s</Medium>\n", str_encoded);
@ -4211,7 +4235,7 @@ 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>%lld</Value>\n", mbus_data_bcd_decode(data->cnt1_val, 4));
len += snprintf(&buff[len], buff_size - len, " <Value>%llX</Value>\n", mbus_data_bcd_decode_hex(data->cnt1_val, 4));
}
else
{
@ -4230,7 +4254,7 @@ 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>%lld</Value>\n", mbus_data_bcd_decode(data->cnt2_val, 4));
len += snprintf(&buff[len], buff_size - len, " <Value>%llX</Value>\n", mbus_data_bcd_decode_hex(data->cnt2_val, 4));
}
else
{
@ -4589,9 +4613,9 @@ mbus_frame_get_secondary_address(mbus_frame *frame)
return NULL;
}
id = (unsigned long) mbus_data_bcd_decode(data->data_var.header.id_bcd, 4);
id = (unsigned long) mbus_data_bcd_decode_hex(data->data_var.header.id_bcd, 4);
snprintf(addr, sizeof(addr), "%08lu%02X%02X%02X%02X",
snprintf(addr, sizeof(addr), "%08lX%02X%02X%02X%02X",
id,
data->data_var.header.manufacturer[0],
data->data_var.header.manufacturer[1],

View File

@ -627,6 +627,7 @@ 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);
long long mbus_data_bcd_decode_hex(unsigned char *bcd_data, size_t bcd_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);

View File

@ -6,7 +6,7 @@
<Manufacturer>EFE</Manufacturer>
<Version>0</Version>
<ProductName>Engelmann WaterStar</ProductName>
<Medium>Hot water</Medium>
<Medium>Warm water (30-90°C)</Medium>
<AccessNumber>12</AccessNumber>
<Status>27</Status>
<Signature>0000</Signature>

View File

@ -48,14 +48,14 @@
<Function>Value during error state</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (W)</Unit>
<Value>144445223</Value>
<Value>DDDDEBBD</Value>
</DataRecord>
<DataRecord id="5">
<Function>Value during error state</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume flow (m m^3/h)</Unit>
<Value>1445223</Value>
<Value>DDEBBD</Value>
</DataRecord>
<DataRecord id="6">

View File

@ -58,7 +58,7 @@
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Temperature Difference (1e-2 deg C)</Unit>
<Value>1500018</Value>
<Value>F00018</Value>
</DataRecord>
<DataRecord id="7">

View File

@ -30,14 +30,14 @@
<Function>Value during error state</Function>
<StorageNumber>0</StorageNumber>
<Unit>Power (1e-1 W)</Unit>
<Value>144521543</Value>
<Value>DDEBB4DD</Value>
</DataRecord>
<DataRecord id="3">
<Function>Value during error state</Function>
<StorageNumber>0</StorageNumber>
<Unit>Volume flow (1e-4 m^3/h)</Unit>
<Value>1521543</Value>
<Value>EBB4DD</Value>
</DataRecord>
<DataRecord id="4">

View File

@ -2,7 +2,7 @@
<MBusData>
<SlaveInformation>
<Id>5000244</Id>
<Id>500023E</Id>
<Manufacturer>SBC</Manufacturer>
<Version>18</Version>
<ProductName></ProductName>

View File

@ -2,7 +2,7 @@
<MBusData>
<SlaveInformation>
<Id>5000345</Id>
<Id>50002E5</Id>
<Manufacturer>@@@</Manufacturer>
<Version>18</Version>
<ProductName></ProductName>

View File

@ -72,7 +72,7 @@
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Temperature Difference (1e-1 deg C)</Unit>
<Value>1500002</Value>
<Value>F00002</Value>
</DataRecord>
<DataRecord id="9">

View File

@ -6,7 +6,7 @@
<Manufacturer>LSE</Manufacturer>
<Version>153</Version>
<ProductName>Siemens WFH21</ProductName>
<Medium>Hot water</Medium>
<Medium>Warm water (30-90°C)</Medium>
<AccessNumber>235</AccessNumber>
<Status>00</Status>
<Signature>0000</Signature>

View File

@ -6,7 +6,7 @@
<Manufacturer>LSE</Manufacturer>
<Version>153</Version>
<ProductName>Siemens WFH21</ProductName>
<Medium>Hot water</Medium>
<Medium>Warm water (30-90°C)</Medium>
<AccessNumber>218</AccessNumber>
<Status>00</Status>
<Signature>0000</Signature>