Merge pull request #7 from lategoodbye/master

Migrate all new features also to mbus-protocol-aux.c
This commit is contained in:
Robert Johansson 2012-05-06 23:53:33 -07:00
commit fd6e432213
3 changed files with 251 additions and 98 deletions

View File

@ -179,8 +179,8 @@ mbus_variable_vif vif_table[] = {
{ 0x6B, 1.0e0, "bar", "Pressure" }, { 0x6B, 1.0e0, "bar", "Pressure" },
/* E110 110n Time Point */ /* E110 110n Time Point */
{ 0x6C, 1.0e0, "-", "Time point" }, /* n = 0 date, data type G */ { 0x6C, 1.0e0, "-", "Time point (date)" }, /* n = 0 date, data type G */
{ 0x6D, 1.0e0, "-", "Time point" }, /* n = 1 time & date, data type F */ { 0x6D, 1.0e0, "-", "Time point (date & time)" }, /* n = 1 time & date, data type F */
/* E110 1110 Units for H.C.A. dimensionless */ /* E110 1110 Units for H.C.A. dimensionless */
{ 0x6E, 1.0e0, "Units for H.C.A.", "H.C.A." }, { 0x6E, 1.0e0, "Units for H.C.A.", "H.C.A." },
@ -749,15 +749,23 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
*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;
u_char vif, vife;
struct tm time;
if (record) if (record)
{ {
MBUS_DEBUG("coding = 0x%02X \n", record->drh.dib.dif); MBUS_DEBUG("coding = 0x%02X \n", record->drh.dib.dif);
// ignore extension bit
vif = (record->drh.vib.vif & 0x7F);
vife = (record->drh.vib.vife[0] & 0x7F);
switch (record->drh.dib.dif & 0x0F) switch (record->drh.dib.dif & 0x0F)
{ {
case 0x00: /* no data */ case 0x00: /* no data */
result = -1; *value_out_str = (char*) malloc(1);
*value_out_str_size = 0;
result = 0;
break; break;
case 0x01: /* 1 byte integer (8 bit) */ case 0x01: /* 1 byte integer (8 bit) */
@ -766,7 +774,21 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
break; break;
case 0x02: /* 2 byte integer (16 bit) */ case 0x02: /* 2 byte integer (16 bit) */
*value_out_real = mbus_data_int_decode(record->data, 2); // E110 1100 Time Point (date)
if (vif == 0x6C)
{
mbus_data_tm_decode(&time, record->data, 2);
*value_out_str = (char*) malloc(11);
*value_out_str_size = snprintf(*value_out_str, 11, "%04d-%02d-%02d",
(time.tm_year + 2000),
(time.tm_mon + 1),
time.tm_mday);
}
else // normal integer
{
*value_out_real = mbus_data_int_decode(record->data, 2);
}
result = 0; result = 0;
break; break;
@ -776,22 +798,42 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
break; break;
case 0x04: /* 4 byte integer (32 bit) */ case 0x04: /* 4 byte integer (32 bit) */
*value_out_real = mbus_data_int_decode(record->data, 4); // E110 1101 Time Point (date/time)
// E011 0000 Start (date/time) of tariff
// E111 0000 Date and time of battery change
if ( (vif == 0x6D) ||
((record->drh.vib.vif == 0xFD) && (vife == 0x30)) ||
((record->drh.vib.vif == 0xFD) && (vife == 0x70)))
{
mbus_data_tm_decode(&time, record->data, 4);
*value_out_str = (char*) malloc(20);
*value_out_str_size = snprintf(*value_out_str, 20, "%04d-%02d-%02dT%02d:%02d:%02d",
(time.tm_year + 2000),
(time.tm_mon + 1),
time.tm_mday,
time.tm_hour,
time.tm_min,
time.tm_sec);
}
else // normal integer
{
*value_out_real = mbus_data_int_decode(record->data, 4);
}
result = 0; result = 0;
break; break;
case 0x05: /* 32b real */ case 0x05: /* 32b real */
result = -2; *value_out_real = mbus_data_float_decode(record->data);
MBUS_ERROR("32b real not implemented yet\n"); result = 0;
break; break;
case 0x06: /* 6 byte integer (48 bit) */ case 0x06: /* 6 byte integer (48 bit) */
*value_out_real = mbus_data_long_decode(record->data, 6); *value_out_real = mbus_data_long_long_decode(record->data, 6);
result = 0; result = 0;
break; break;
case 0x07: /* 8 byte integer (64 bit) */ case 0x07: /* 8 byte integer (64 bit) */
*value_out_real = mbus_data_long_decode(record->data, 8); *value_out_real = mbus_data_long_long_decode(record->data, 8);
result = 0; result = 0;
break; break;
@ -830,13 +872,15 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
} }
case 0x0E: /* 12 digit BCD (40 bit) */ case 0x0E: /* 12 digit BCD (40 bit) */
result = -2; *value_out_real = mbus_data_bcd_decode(record->data, 6);
MBUS_ERROR("12 digit BCD (40 bit) not implemented yet\n"); result = 0;
break; break;
case 0x0F: /* Special functions */ case 0x0F: /* Special functions */
result = -2; *value_out_str = (char*) malloc(3 * record->data_len + 1);
MBUS_ERROR("Special functions not implemented yet"); *value_out_str_size = 3 * record->data_len;
mbus_data_bin_decode((u_char*)(*value_out_str), record->data, record->data_len, (3 * record->data_len + 1));
result = 0;
break; break;
default: default:
@ -847,6 +891,7 @@ int mbus_variable_value_decode(mbus_data_record *record, double *value_out_real,
} }
else else
{ {
MBUS_ERROR("record is null");
result = -3; result = -3;
} }
@ -864,58 +909,22 @@ mbus_vif_unit_normalize(int vif, double value, char **unit_out, double *value_ou
int i; int i;
switch (newVif) /* ignore the extension bit in this selection */ for(i=0; vif_table[i].vif < 0xfff; ++i)
{ {
/* E110 110n Time Point if (vif_table[i].vif == newVif)
n = 0 date {
n = 1 time & date *unit_out = strdup(vif_table[i].unit);
data type G *value_out = value * vif_table[i].exponent;
data type F */ *quantity_out = strdup(vif_table[i].quantity);
case 0x6C:
case 0x6C+1:
if (vif & 0x1)
{
*unit_out = strdup("Time Point (time & date)");
*quantity_out = strdup("Time Point (time & date)");
}
else
{
*unit_out = strdup("Time Point (date)");
*quantity_out = strdup("Time Point (date)");
}
break;
/* Manufacturer specific: 7Fh / FF */
case 0x7F:
case 0xFF:
*unit_out = strdup("Manufacturer specific");
*quantity_out = strdup("Manufacturer specific");
exponent = 0.0;
*value_out = 0.0;
return 0; return 0;
break; }
default:
for(i=0; vif_table[i].vif < 0xfff; ++i)
{
if (vif_table[i].vif == newVif)
{
*unit_out = strdup(vif_table[i].unit);
*value_out = value * vif_table[i].exponent;
*quantity_out = strdup(vif_table[i].quantity);
return 0;
}
}
*unit_out = strdup("Unknown (VIF=0x%.2X)");
*quantity_out = strdup("Unknown");
exponent = 0.0;
*value_out = 0.0;
return -1;
break;
} }
return -2; *unit_out = strdup("Unknown (VIF=0x%.2X)");
*quantity_out = strdup("Unknown");
exponent = 0.0;
*value_out = 0.0;
return -1;
} }
@ -952,7 +961,16 @@ mbus_vib_unit_normalize(mbus_value_information_block *vib, double value, char **
MBUS_ERROR("%s: Error mbus_vif_unit_normalize\n", __PRETTY_FUNCTION__); MBUS_ERROR("%s: Error mbus_vif_unit_normalize\n", __PRETTY_FUNCTION__);
return -1; return -1;
} }
} else { }
else if (vib->vif == 0x7C)
{
// custom VIF
*unit_out = strdup("-");
*quantity_out = strdup(vib->custom_vif);
*value_out = 0.0;
}
else
{
int code = (vib->vif) & 0x7f; int code = (vib->vif) & 0x7f;
if (0 != mbus_vif_unit_normalize(code, value, unit_out, value_out, quantity_out)) if (0 != mbus_vif_unit_normalize(code, value, unit_out, value_out, quantity_out))
{ {
@ -1057,6 +1075,10 @@ mbus_record *
mbus_parse_variable_record(mbus_data_record *data) mbus_parse_variable_record(mbus_data_record *data)
{ {
mbus_record * record = NULL; mbus_record * record = NULL;
double value_out_real = 0.0; /**< raw value */
char * value_out_str = NULL;
int value_out_str_size = 0;
double real_val = 0.0; /**< normalized value */
if (!(record = mbus_record_new())) if (!(record = mbus_record_new()))
{ {
@ -1066,20 +1088,42 @@ mbus_parse_variable_record(mbus_data_record *data)
if (data->drh.dib.dif == 0x0F || data->drh.dib.dif == 0x1F) /* MBUS_DIB_DIF_VENDOR_SPECIFIC */ if (data->drh.dib.dif == 0x0F || data->drh.dib.dif == 0x1F) /* MBUS_DIB_DIF_VENDOR_SPECIFIC */
{ {
record->function_medium = strdup("Manufacturer specific"); if (data->drh.dib.dif == 0x1F)
{
record->function_medium = strdup("More records follow");
}
else
{
record->function_medium = strdup("Manufacturer specific");
}
/* parsing of data not implemented yet /* parsing of data not implemented yet
manufacturer specific data structures to end of user data */ manufacturer specific data structures to end of user data */
if (mbus_variable_value_decode(data, &value_out_real, &value_out_str, &value_out_str_size) != 0)
{
MBUS_ERROR("%s: problem with mbus_variable_value_decode\n", __PRETTY_FUNCTION__);
mbus_record_free(record);
return NULL;
}
if (value_out_str != NULL)
{
record->is_numeric = 0;
(record->value).str_val.value = value_out_str;
(record->value).str_val.size = value_out_str_size;
}
else
{
record->is_numeric = 1;
(record->value).real_val = real_val;
}
} }
else else
{ {
record->function_medium = strdup(mbus_data_record_function(data)); record->function_medium = strdup(mbus_data_record_function(data));
MBUS_DEBUG("record->function_medium = %s \n", record->function_medium); MBUS_DEBUG("record->function_medium = %s \n", record->function_medium);
double value_out_real = 0.0; /**< raw value */
char * value_out_str = NULL;
int value_out_str_size = 0;
double real_val = 0.0; /**< normalized value */
if (mbus_variable_value_decode(data, &value_out_real, &value_out_str, &value_out_str_size) != 0) if (mbus_variable_value_decode(data, &value_out_real, &value_out_str, &value_out_str_size) != 0)
{ {
MBUS_ERROR("%s: problem with mbus_variable_value_decode\n", __PRETTY_FUNCTION__); MBUS_ERROR("%s: problem with mbus_variable_value_decode\n", __PRETTY_FUNCTION__);
@ -1110,9 +1154,96 @@ mbus_parse_variable_record(mbus_data_record *data)
(record->value).real_val = real_val; (record->value).real_val = real_val;
} }
} }
return record; return record;
} }
//------------------------------------------------------------------------------
/// Generate XML for variable-length data
//------------------------------------------------------------------------------
char *
mbus_data_variable_xml_normalized(mbus_data_variable *data)
{
mbus_data_record *record;
mbus_record *norm_record;
static char buff[8192];
char str_encoded[768];
size_t len = 0;
size_t i;
if (data)
{
len += snprintf(&buff[len], sizeof(buff) - len, "<MBusData>\n\n");
len += snprintf(&buff[len], sizeof(buff) - len, "%s", mbus_data_variable_header_xml(&(data->header)));
for (record = data->record, i = 0; record; record = record->next, i++)
{
norm_record = mbus_parse_variable_record(record);
len += snprintf(&buff[len], sizeof(buff) - len, " <DataRecord id=\"%zd\">\n", i);
if (norm_record != NULL)
{
mbus_str_xml_encode(str_encoded, norm_record->function_medium, sizeof(str_encoded));
len += snprintf(&buff[len], sizeof(buff) - len, " <Function>%s</Function>\n", str_encoded);
mbus_str_xml_encode(str_encoded, norm_record->unit, sizeof(str_encoded));
len += snprintf(&buff[len], sizeof(buff) - len, " <Unit>%s</Unit>\n", str_encoded);
mbus_str_xml_encode(str_encoded, norm_record->quantity, sizeof(str_encoded));
len += snprintf(&buff[len], sizeof(buff) - len, " <Quantity>%s</Quantity>\n", str_encoded);
if (norm_record->is_numeric)
{
len += snprintf(&buff[len], sizeof(buff) - len, " <Value>%f</Value>\n", norm_record->value.real_val);
}
else
{
mbus_str_xml_encode(str_encoded, norm_record->value.str_val.value, sizeof(str_encoded));
len += snprintf(&buff[len], sizeof(buff) - len, " <Value>%s</Value>\n", str_encoded);
}
mbus_record_free(norm_record);
}
else
{
}
len += snprintf(&buff[len], sizeof(buff) - len, " </DataRecord>\n\n");
}
len += snprintf(&buff[len], sizeof(buff) - len, "</MBusData>\n");
return buff;
}
return "";
}
//------------------------------------------------------------------------------
/// Return a string containing an XML representation of the M-BUS frame data.
//------------------------------------------------------------------------------
char *
mbus_frame_data_xml_normalized(mbus_frame_data *data)
{
if (data)
{
if (data->type == MBUS_DATA_TYPE_FIXED)
{
return mbus_data_fixed_xml(&(data->data_fix));
}
if (data->type == MBUS_DATA_TYPE_VARIABLE)
{
return mbus_data_variable_xml_normalized(&(data->data_var));
}
}
return "";
}
mbus_handle * mbus_handle *
mbus_connect_serial(const char * device) mbus_connect_serial(const char * device)

View File

@ -346,6 +346,24 @@ int mbus_vif_unit_normalize(int vif, double value, char **unit_out, double *valu
*/ */
int mbus_vib_unit_normalize(mbus_value_information_block *vib, double value, char **unit_out, double *value_out, char ** quantity_out); int mbus_vib_unit_normalize(mbus_value_information_block *vib, double value, char **unit_out, double *value_out, char ** quantity_out);
/**
* Generate XML for normalized variable-length data
*
* @param data variable-length data
*
* @return string with XML
*/
char * mbus_data_variable_xml_normalized(mbus_data_variable *data);
/**
* Return a string containing an XML representation of the normalized M-BUS frame data.
*
* @param data M-Bus frame data
*
* @return string with XML
*/
char * mbus_frame_data_xml_normalized(mbus_frame_data *data);
/** /**
* Iterate over secondary addresses, send a probe package to all addresses matching * Iterate over secondary addresses, send a probe package to all addresses matching
* the given addresses mask. * the given addresses mask.

View File

@ -2943,32 +2943,36 @@ mbus_str_xml_encode(u_char *dst, const u_char *src, size_t max_len)
i = 0; i = 0;
len = 0; len = 0;
while((len+6) < max_len) { if (src != NULL)
if (src[i] == '\0') {
while((len+6) < max_len)
{ {
break; if (src[i] == '\0')
} {
break;
}
switch (src[i]) switch (src[i])
{ {
case '&': case '&':
len += snprintf(&dst[len], max_len - len, "&amp;"); len += snprintf(&dst[len], max_len - len, "&amp;");
break; break;
case '<': case '<':
len += snprintf(&dst[len], max_len - len, "&lt;"); len += snprintf(&dst[len], max_len - len, "&lt;");
break; break;
case '>': case '>':
len += snprintf(&dst[len], max_len - len, "&gt;"); len += snprintf(&dst[len], max_len - len, "&gt;");
break; break;
case '"': case '"':
len += snprintf(&dst[len], max_len - len, "&quot;"); len += snprintf(&dst[len], max_len - len, "&quot;");
break; break;
default: default:
dst[len++] = src[i]; dst[len++] = src[i];
break; break;
} }
i++; i++;
}
} }
dst[len] = '\0'; dst[len] = '\0';