use optional comment and unit for first field when deriving a DataFieldSet, use name only for singular template reference, also trim split parts, documentation
This commit is contained in:
+17
-14
@@ -183,16 +183,16 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
bool hasPartStr = false;
|
bool hasPartStr = false;
|
||||||
string token;
|
string token;
|
||||||
|
|
||||||
// templates: name,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
// template: name,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
||||||
// normal: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
// std: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
||||||
const string name = *it++;
|
const string name = *it++; // name
|
||||||
if (it == end)
|
if (it == end)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (isTemplate)
|
if (isTemplate)
|
||||||
partType = pt_any;
|
partType = pt_any;
|
||||||
else {
|
else {
|
||||||
const char* partStr = (*it++).c_str();
|
const char* partStr = (*it++).c_str(); // part
|
||||||
hasPartStr = partStr[0] != 0;
|
hasPartStr = partStr[0] != 0;
|
||||||
if (it == end) {
|
if (it == end) {
|
||||||
if (!name.empty() || hasPartStr)
|
if (!name.empty() || hasPartStr)
|
||||||
@@ -219,7 +219,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
firstComment = comment;
|
firstComment = comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string typeStr = *it++;
|
const string typeStr = *it++; // type[:len]
|
||||||
if (typeStr.empty()) {
|
if (typeStr.empty()) {
|
||||||
if (!name.empty() || hasPartStr)
|
if (!name.empty() || hasPartStr)
|
||||||
result = RESULT_ERR_MISSING_TYPE;
|
result = RESULT_ERR_MISSING_TYPE;
|
||||||
@@ -228,13 +228,14 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
|
|
||||||
map<unsigned int, string> values;
|
map<unsigned int, string> values;
|
||||||
if (it != end) {
|
if (it != end) {
|
||||||
const string divisorStr = *it++;
|
const string divisorStr = *it++; // [divisor|values]
|
||||||
if (!divisorStr.empty()) {
|
if (!divisorStr.empty()) {
|
||||||
if (divisorStr.find('=') == string::npos)
|
if (divisorStr.find('=') == string::npos)
|
||||||
divisor = parseSignedInt(divisorStr.c_str(), 10, -MAX_DIVISOR, MAX_DIVISOR, result);
|
divisor = parseSignedInt(divisorStr.c_str(), 10, -MAX_DIVISOR, MAX_DIVISOR, result);
|
||||||
else {
|
else {
|
||||||
istringstream stream(divisorStr);
|
istringstream stream(divisorStr);
|
||||||
while (getline(stream, token, VALUE_SEPARATOR) != 0) {
|
while (getline(stream, token, VALUE_SEPARATOR) != 0) {
|
||||||
|
DataFieldTemplates::trim(token);
|
||||||
const char* str = token.c_str();
|
const char* str = token.c_str();
|
||||||
char* strEnd = NULL;
|
char* strEnd = NULL;
|
||||||
unsigned long int id;
|
unsigned long int id;
|
||||||
@@ -258,7 +259,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
if (it == end)
|
if (it == end)
|
||||||
unit = "";
|
unit = "";
|
||||||
else {
|
else {
|
||||||
const string str = *it++;
|
const string str = *it++; // [unit]
|
||||||
if (strcasecmp(str.c_str(), NULL_VALUE) == 0)
|
if (strcasecmp(str.c_str(), NULL_VALUE) == 0)
|
||||||
unit = "";
|
unit = "";
|
||||||
else
|
else
|
||||||
@@ -268,7 +269,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
if (it == end)
|
if (it == end)
|
||||||
comment = "";
|
comment = "";
|
||||||
else {
|
else {
|
||||||
const string str = *it++;
|
const string str = *it++; // [comment]
|
||||||
if (strcasecmp(str.c_str(), NULL_VALUE) == 0)
|
if (strcasecmp(str.c_str(), NULL_VALUE) == 0)
|
||||||
comment = "";
|
comment = "";
|
||||||
else
|
else
|
||||||
@@ -278,6 +279,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
bool firstType = true;
|
bool firstType = true;
|
||||||
istringstream stream(typeStr);
|
istringstream stream(typeStr);
|
||||||
while (result == RESULT_OK && getline(stream, token, VALUE_SEPARATOR) != 0) {
|
while (result == RESULT_OK && getline(stream, token, VALUE_SEPARATOR) != 0) {
|
||||||
|
DataFieldTemplates::trim(token);
|
||||||
DataField* templ = templates->get(token);
|
DataField* templ = templates->get(token);
|
||||||
unsigned char length;
|
unsigned char length;
|
||||||
if (templ == NULL) {
|
if (templ == NULL) {
|
||||||
@@ -297,12 +299,12 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
else if (result == RESULT_OK)
|
else if (result == RESULT_OK)
|
||||||
result = RESULT_ERR_NOTFOUND; // type not found
|
result = RESULT_ERR_NOTFOUND; // type not found
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
result = templ->derive(firstType ? name : "", firstType ? comment : "", firstType ? unit : "", partType, divisor, values, fields);
|
bool lastType = stream.eof();
|
||||||
|
result = templ->derive((firstType && lastType) ? name : "", firstType ? comment : "", firstType ? unit : "", partType, divisor, values, fields);
|
||||||
|
}
|
||||||
firstType = false;
|
firstType = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (it != end && result == RESULT_OK);
|
} while (it != end && result == RESULT_OK);
|
||||||
|
|
||||||
if (result != RESULT_OK) {
|
if (result != RESULT_OK) {
|
||||||
@@ -1256,11 +1258,12 @@ result_t DataFieldSet::derive(string name, string comment,
|
|||||||
{
|
{
|
||||||
if (!values.empty())
|
if (!values.empty())
|
||||||
return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive
|
return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive
|
||||||
|
bool first = true;
|
||||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||||
result_t result = (*it)->derive("", "", "", partType, divisor, values, fields);
|
result_t result = (*it)->derive("", first?comment:"", first?unit:"", partType, divisor, values, fields);
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
|
|||||||
+1
-1
@@ -190,7 +190,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive a new @a DataField from this field.
|
* Derive a new @a DataField from this field.
|
||||||
* @param name the field name.
|
* @param name the field name, or empty to use this fields name.
|
||||||
* @param comment the field comment, or empty to use this fields comment.
|
* @param comment the field comment, or empty to use this fields comment.
|
||||||
* @param unit the value unit, or empty to use this fields unit (if applicable).
|
* @param unit the value unit, or empty to use this fields unit (if applicable).
|
||||||
* @param partType the message part in which the field is stored.
|
* @param partType the message part in which the field is stored.
|
||||||
|
|||||||
+13
-11
@@ -91,7 +91,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
|||||||
vector< vector<string> >* defaultsRows,
|
vector< vector<string> >* defaultsRows,
|
||||||
DataFieldTemplates* templates, vector<Message*>& messages)
|
DataFieldTemplates* templates, vector<Message*>& messages)
|
||||||
{
|
{
|
||||||
// [type],[circuit],name,[comment],[QQ[;QQ]*],[ZZ],id,fields...
|
// [type],[circuit],name,[comment],[QQ[;QQ]*],[ZZ],[PBSB],[ID],fields...
|
||||||
result_t result;
|
result_t result;
|
||||||
bool isWrite = false, isPassive = false;
|
bool isWrite = false, isPassive = false;
|
||||||
string defaultName;
|
string defaultName;
|
||||||
@@ -100,7 +100,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
|||||||
if (it == end)
|
if (it == end)
|
||||||
return RESULT_ERR_EOF;
|
return RESULT_ERR_EOF;
|
||||||
|
|
||||||
const char* str = (*it++).c_str();
|
const char* str = (*it++).c_str(); // [type]
|
||||||
if (it == end)
|
if (it == end)
|
||||||
return RESULT_ERR_EOF;
|
return RESULT_ERR_EOF;
|
||||||
size_t len = strlen(str);
|
size_t len = strlen(str);
|
||||||
@@ -137,22 +137,22 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string circuit = getDefault(*it++, defaults, defaultPos++);
|
string circuit = getDefault(*it++, defaults, defaultPos++); // [circuit]
|
||||||
if (it == end)
|
if (it == end)
|
||||||
return RESULT_ERR_EOF;
|
return RESULT_ERR_EOF;
|
||||||
|
|
||||||
string name = *it++;
|
string name = *it++; // name
|
||||||
if (it == end)
|
if (it == end)
|
||||||
return RESULT_ERR_EOF;
|
return RESULT_ERR_EOF;
|
||||||
if (name.length() == 0)
|
if (name.length() == 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // empty name
|
return RESULT_ERR_INVALID_ARG; // empty name
|
||||||
defaultPos++;
|
defaultPos++;
|
||||||
|
|
||||||
string comment = getDefault(*it++, defaults, defaultPos++);
|
string comment = getDefault(*it++, defaults, defaultPos++); // [comment]
|
||||||
if (it == end)
|
if (it == end)
|
||||||
return RESULT_ERR_EOF;
|
return RESULT_ERR_EOF;
|
||||||
|
|
||||||
str = getDefault(*it++, defaults, defaultPos++).c_str();
|
str = getDefault(*it++, defaults, defaultPos++).c_str(); // [QQ[;QQ]*]
|
||||||
if (it == end)
|
if (it == end)
|
||||||
return RESULT_ERR_EOF;
|
return RESULT_ERR_EOF;
|
||||||
unsigned char srcAddress;
|
unsigned char srcAddress;
|
||||||
@@ -166,7 +166,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
|||||||
return RESULT_ERR_INVALID_ADDR;
|
return RESULT_ERR_INVALID_ADDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = getDefault(*it++, defaults, defaultPos++).c_str();
|
str = getDefault(*it++, defaults, defaultPos++).c_str(); // [ZZ]
|
||||||
if (it == end)
|
if (it == end)
|
||||||
return RESULT_ERR_EOF;
|
return RESULT_ERR_EOF;
|
||||||
vector<unsigned char> dstAddresses;
|
vector<unsigned char> dstAddresses;
|
||||||
@@ -178,6 +178,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
|||||||
string token;
|
string token;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
while (getline(stream, token, VALUE_SEPARATOR) != 0) {
|
while (getline(stream, token, VALUE_SEPARATOR) != 0) {
|
||||||
|
DataFieldTemplates::trim(token);
|
||||||
unsigned char dstAddress = (unsigned char)parseInt(token.c_str(), 16, 0, 0xff, result);
|
unsigned char dstAddress = (unsigned char)parseInt(token.c_str(), 16, 0, 0xff, result);
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -195,7 +196,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
|||||||
|
|
||||||
vector<unsigned char> id;
|
vector<unsigned char> id;
|
||||||
bool useDefaults = true;
|
bool useDefaults = true;
|
||||||
for (int pos = 0; pos < 2 && it != end; pos++) { // message id (PBSB, optional master data)
|
for (int pos = 0; pos < 2 && it != end; pos++) { // [PBSB],[ID] (optional master data)
|
||||||
string token = *it++;
|
string token = *it++;
|
||||||
if (useDefaults) {
|
if (useDefaults) {
|
||||||
if (pos == 0 && token.size() > 0)
|
if (pos == 0 && token.size() > 0)
|
||||||
@@ -212,7 +213,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
|||||||
token.clear();
|
token.clear();
|
||||||
token.push_back((char)input.get());
|
token.push_back((char)input.get());
|
||||||
if (input.eof()) {
|
if (input.eof()) {
|
||||||
return RESULT_ERR_INVALID_ARG; // too short hex
|
return RESULT_ERR_INVALID_ARG; // to short hex
|
||||||
}
|
}
|
||||||
token.push_back((char)input.get());
|
token.push_back((char)input.get());
|
||||||
|
|
||||||
@@ -223,12 +224,12 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
|||||||
id.push_back(value);
|
id.push_back(value);
|
||||||
}
|
}
|
||||||
if (pos == 0 && id.size() != 2)
|
if (pos == 0 && id.size() != 2)
|
||||||
return RESULT_ERR_INVALID_ARG; // missing/too short/too PBSB
|
return RESULT_ERR_INVALID_ARG; // missing/to short/to long PBSB
|
||||||
|
|
||||||
defaultPos++;
|
defaultPos++;
|
||||||
}
|
}
|
||||||
if (id.size() < 2 || id.size() > 6) {
|
if (id.size() < 2 || id.size() > 6) {
|
||||||
return RESULT_ERR_INVALID_ARG; // missing/too short/too long ID
|
return RESULT_ERR_INVALID_ARG; // missing/to short/to long ID
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string>::iterator realEnd = end;
|
vector<string>::iterator realEnd = end;
|
||||||
@@ -565,6 +566,7 @@ result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<s
|
|||||||
string type;
|
string type;
|
||||||
vector<Message*> messages;
|
vector<Message*> messages;
|
||||||
while (getline(stream, type, VALUE_SEPARATOR) != 0) {
|
while (getline(stream, type, VALUE_SEPARATOR) != 0) {
|
||||||
|
DataFieldTemplates::trim(type);
|
||||||
*restart = type;
|
*restart = type;
|
||||||
begin = restart;
|
begin = restart;
|
||||||
messages.clear();
|
messages.clear();
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ void verify(bool expectFailMatch, string type, string input,
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// message= [type];circuit;name;[comment];[QQ[;QQ]*];ZZ;PBSB;fields...
|
// message: [type],[circuit],name,[comment],[QQ[;QQ]*],[ZZ],[PBSB],[ID],fields...
|
||||||
// field= name;[pos];type[;[divisor|values][;[unit][;[comment]]]]
|
// field: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
||||||
|
// template: name,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
||||||
string checks[][5] = {
|
string checks[][5] = {
|
||||||
// "message", "decoded", "master", "slave", "flags"
|
// "message", "decoded", "master", "slave", "flags"
|
||||||
{"date,HDA:3,,,Datum", "", "", "", "t"},
|
{"date,HDA:3,,,Datum", "", "", "", "t"},
|
||||||
@@ -54,7 +55,10 @@ int main()
|
|||||||
{"temp2,D2B,,°C,Temperatur", "", "", "", "t"},
|
{"temp2,D2B,,°C,Temperatur", "", "", "", "t"},
|
||||||
{"power,UCH,,kW", "", "", "", "t"},
|
{"power,UCH,,kW", "", "", "", "t"},
|
||||||
{"sensor,UCH,0=ok;85=circuit;170=cutoff,,Fühlerstatus", "", "", "", "t"},
|
{"sensor,UCH,0=ok;85=circuit;170=cutoff,,Fühlerstatus", "", "", "", "t"},
|
||||||
{"tempsensor,temp;sensor", "", "", "", "t"},
|
{"tempsensor,temp;sensor,,Temperatursensor", "", "", "", "t"},
|
||||||
|
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor", "temp=-14.00 Temperatursensor [Temperatur];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||||
|
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||||
|
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,temp,,field unit,field comment,,,sensor", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||||
{"u,,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
{"u,,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
||||||
{"u,broadcast,hwStatus,,,fe,b505,27,,,UCH,,,,,,UCH,,,,,,UCH,,,", "0;19;0", "10feb505042700130097", "00", ""},
|
{"u,broadcast,hwStatus,,,fe,b505,27,,,UCH,,,,,,UCH,,,,,,UCH,,,", "0;19;0", "10feb505042700130097", "00", ""},
|
||||||
{"w,,first,,,15,b509,0400,date,,bda", "26.10.2014", "ff15b50906040026100614", "00", "m"},
|
{"w,,first,,,15,b509,0400,date,,bda", "26.10.2014", "ff15b50906040026100614", "00", "m"},
|
||||||
@@ -97,7 +101,8 @@ int main()
|
|||||||
bool dontMap = flags.find('m') != string::npos;
|
bool dontMap = flags.find('m') != string::npos;
|
||||||
bool onlyMap = flags.find('M') != string::npos;
|
bool onlyMap = flags.find('M') != string::npos;
|
||||||
bool failedCreate = flags.find('c') != string::npos;
|
bool failedCreate = flags.find('c') != string::npos;
|
||||||
bool decode = flags.find('d') != string::npos;
|
bool decodeVerbose = flags.find('D') != string::npos;
|
||||||
|
bool decode = decodeVerbose || (flags.find('d') != string::npos);
|
||||||
bool failedPrepare = flags.find('p') != string::npos;
|
bool failedPrepare = flags.find('p') != string::npos;
|
||||||
bool failedPrepareMatch = flags.find('P') != string::npos;
|
bool failedPrepareMatch = flags.find('P') != string::npos;
|
||||||
bool multi = flags.find('*') != string::npos;
|
bool multi = flags.find('*') != string::npos;
|
||||||
@@ -209,7 +214,7 @@ int main()
|
|||||||
|
|
||||||
if (message->isPassive() || decode) {
|
if (message->isPassive() || decode) {
|
||||||
ostringstream output;
|
ostringstream output;
|
||||||
result = message->decode(mstr, sstr, output);
|
result = message->decode(mstr, sstr, output, decodeVerbose?OF_VERBOSE:0);
|
||||||
if (result != RESULT_OK) {
|
if (result != RESULT_OK) {
|
||||||
cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: "
|
cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: "
|
||||||
<< getResultCode(result) << endl;
|
<< getResultCode(result) << endl;
|
||||||
|
|||||||
Reference in New Issue
Block a user