extended Message::create to allow specifying multiple destinations (class is then suffixed with .0, .1 etc.)

This commit is contained in:
john30
2015-03-08 14:04:03 +01:00
parent 491b107635
commit 6257327aaf
3 changed files with 101 additions and 45 deletions
+50 -22
View File
@@ -36,12 +36,13 @@ using namespace std;
Message::Message(const string clazz, const string name, const bool isWrite, Message::Message(const string clazz, const string name, const bool isWrite,
const bool isPassive, const string comment, const bool isPassive, const string comment,
const unsigned char srcAddress, const unsigned char dstAddress, const unsigned char srcAddress, const unsigned char dstAddress,
const vector<unsigned char> id, DataField* data, const vector<unsigned char> id, DataField* data, const bool deleteData,
const unsigned char pollPriority) const unsigned char pollPriority)
: m_class(clazz), m_name(name), m_isWrite(isWrite), : m_class(clazz), m_name(name), m_isWrite(isWrite),
m_isPassive(isPassive), m_comment(comment), m_isPassive(isPassive), m_comment(comment),
m_srcAddress(srcAddress), m_dstAddress(dstAddress), m_srcAddress(srcAddress), m_dstAddress(dstAddress),
m_id(id), m_data(data), m_pollPriority(pollPriority), m_id(id), m_data(data), m_deleteData(deleteData),
m_pollPriority(pollPriority),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0)
{ {
int exp = 7; int exp = 7;
@@ -62,7 +63,7 @@ Message::Message(const bool isWrite, const bool isPassive,
: m_class(), m_name(), m_isWrite(isWrite), : m_class(), m_name(), m_isWrite(isWrite),
m_isPassive(isPassive), m_comment(), m_isPassive(isPassive), m_comment(),
m_srcAddress(SYN), m_dstAddress(SYN), m_srcAddress(SYN), m_dstAddress(SYN),
m_data(data), m_pollPriority(0), m_data(data), m_deleteData(true), m_pollPriority(0),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0)
{ {
m_id.push_back(pb); m_id.push_back(pb);
@@ -88,7 +89,7 @@ string getDefault(const string value, vector<string>* defaults, size_t pos)
result_t Message::create(vector<string>::iterator& it, const vector<string>::iterator end, result_t Message::create(vector<string>::iterator& it, const vector<string>::iterator end,
vector< vector<string> >* defaultsRows, vector< vector<string> >* defaultsRows,
DataFieldTemplates* templates, Message*& returnValue) DataFieldTemplates* templates, vector<Message*>& messages)
{ {
// [type],[class],name,[comment],[QQ],[ZZ],id,fields... // [type],[class],name,[comment],[QQ],[ZZ],id,fields...
result_t result; result_t result;
@@ -167,15 +168,28 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
str = getDefault(*it++, defaults, defaultPos++).c_str(); str = getDefault(*it++, defaults, defaultPos++).c_str();
if (it == end) if (it == end)
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
unsigned char dstAddress; vector<unsigned char> dstAddresses;
if (*str == 0) bool isBroadcastOrMasterDestination = false;
dstAddress = SYN; // no specific destination if (*str == 0) {
else { dstAddresses.push_back(SYN); // no specific destination
dstAddress = (unsigned char)parseInt(str, 16, 0, 0xff, result); } else {
if (result != RESULT_OK) istringstream stream(str);
return result; string token;
if (!isValidAddress(dstAddress)) bool first = true;
return RESULT_ERR_INVALID_ADDR; while (getline(stream, token, VALUE_SEPARATOR) != 0) {
unsigned char dstAddress = (unsigned char)parseInt(token.c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK)
return result;
if (!isValidAddress(dstAddress))
return RESULT_ERR_INVALID_ADDR;
bool broadcastOrMaster = (dstAddress == BROADCAST) || isMaster(dstAddress);
if (first) {
isBroadcastOrMasterDestination = broadcastOrMaster;
first = false;
} else if (isBroadcastOrMasterDestination != broadcastOrMaster)
return RESULT_ERR_INVALID_ADDR;
dstAddresses.push_back(dstAddress);
}
} }
vector<unsigned char> id; vector<unsigned char> id;
@@ -240,7 +254,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
} }
} }
DataField* data = NULL; DataField* data = NULL;
result = DataField::create(it, realEnd, templates, data, isWrite, dstAddress==SYN ? ESC : dstAddress); result = DataField::create(it, realEnd, templates, data, isWrite, false, isBroadcastOrMasterDestination);
if (result != RESULT_OK) { if (result != RESULT_OK) {
return result; return result;
} }
@@ -249,7 +263,18 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
delete data; delete data;
return RESULT_ERR_INVALID_POS; return RESULT_ERR_INVALID_POS;
} }
returnValue = new Message(clazz, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data, pollPriority); size_t index = 0;
bool multiple = dstAddresses.size()>1;
char num[10];
for (vector<unsigned char>::iterator it = dstAddresses.begin(); it != dstAddresses.end(); it++, index++) {
unsigned char dstAddress = *it;
string useClass = clazz;
if (multiple) {
sprintf(num, ".%ld", index);
useClass = useClass + num;
}
messages.push_back(new Message(useClass, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data, pollPriority, index==0));
}
return RESULT_OK; return RESULT_OK;
} }
@@ -516,18 +541,21 @@ result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<s
istringstream stream(types); istringstream stream(types);
string type; string type;
vector<Message*> messages;
while (getline(stream, type, VALUE_SEPARATOR) != 0) { while (getline(stream, type, VALUE_SEPARATOR) != 0) {
*restart = type; *restart = type;
begin = restart; begin = restart;
Message* message = NULL; messages.clear();
result = Message::create(begin, end, defaults, arg, message); result = Message::create(begin, end, defaults, arg, messages);
for (vector<Message*>::iterator it = messages.begin(); it != messages.end(); it++) {
Message* message = *it;
if (result == RESULT_OK)
result = add(message);
if (result != RESULT_OK)
delete message; // delete all remaining messages on error
}
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
result = add(message);
if (result != RESULT_OK) {
delete message;
return result;
}
begin = restart; begin = restart;
} }
return result; return result;
+10 -6
View File
@@ -54,12 +54,13 @@ public:
* @param dstAddress the destination address, or @a SYN for any (set later). * @param dstAddress the destination address, or @a SYN for any (set later).
* @param id the primary, secondary, and optional further ID bytes. * @param id the primary, secondary, and optional further ID bytes.
* @param data the @a DataField for encoding/decoding the message. * @param data the @a DataField for encoding/decoding the message.
* @param deleteData whether to delete the @a DataField during destruction.
* @param pollPriority the priority for polling, or 0 for no polling at all. * @param pollPriority the priority for polling, or 0 for no polling at all.
*/ */
Message(const string clazz, const string name, const bool isWrite, Message(const string clazz, const string name, const bool isWrite,
const bool isPassive, const string comment, const bool isPassive, const string comment,
const unsigned char srcAddress, const unsigned char dstAddress, const unsigned char srcAddress, const unsigned char dstAddress,
const vector<unsigned char> id, DataField* data, const vector<unsigned char> id, DataField* data, const bool deleteData,
const unsigned char pollPriority); const unsigned char pollPriority);
/** /**
@@ -78,21 +79,21 @@ public:
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Message() { delete m_data; } virtual ~Message() { if (m_deleteData) delete m_data; }
/** /**
* Factory method for creating a new instance. * Factory method for creating new instances.
* @param it the iterator to traverse for the definition parts. * @param it the iterator to traverse for the definition parts.
* @param end the iterator pointing to the end of the definition parts. * @param end the iterator pointing to the end of the definition parts.
* @param defaultsRows a @a vector with rows containing defaults, or NULL. * @param defaultsRows a @a vector with rows containing defaults, or NULL.
* @param templates the @a DataFieldTemplates to be referenced by name, or NULL. * @param templates the @a DataFieldTemplates to be referenced by name, or NULL.
* @param returnValue the variable in which to store the created instance. * @param messages the @a vector to which to add created instances.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
* Note: the caller needs to free the created instance. * Note: the caller needs to free the created instances.
*/ */
static result_t create(vector<string>::iterator& it, const vector<string>::iterator end, static result_t create(vector<string>::iterator& it, const vector<string>::iterator end,
vector< vector<string> >* defaultsRows, vector< vector<string> >* defaultsRows,
DataFieldTemplates* templates, Message*& returnValue); DataFieldTemplates* templates, vector<Message*>& messages);
/** /**
* Get the optional device class. * Get the optional device class.
@@ -286,6 +287,9 @@ private:
/** the @a DataField for encoding/decoding the message. */ /** the @a DataField for encoding/decoding the message. */
DataField* m_data; DataField* m_data;
/** whether to delete the @a DataField during destruction. */
const bool m_deleteData;
/** the priority for polling, or 0 for no polling at all. */ /** the priority for polling, or 0 for no polling at all. */
const unsigned char m_pollPriority; const unsigned char m_pollPriority;
+41 -17
View File
@@ -59,6 +59,8 @@ int main()
{"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"},
{"r,ehp,time,,,08,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md"}, {"r,ehp,time,,,08,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md"},
{"r,ehp,time,,,08;10,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "c"},
{"r,ehp,time,,,08;09,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md*"},
{"r,ehp,date,,,08,b509,0d2900,,,date", "23.11.2014", "ff08b509030d2900", "03170b0e", "md"}, {"r,ehp,date,,,08,b509,0d2900,,,date", "23.11.2014", "ff08b509030d2900", "03170b0e", "md"},
{"u,ehp,ActualEnvironmentPower,Energiebezug,,08,B509,29BA00,,s,IGN:2,,,,,s,power", "8", "1008b5090329ba00", "03ba0008", "pm"}, {"u,ehp,ActualEnvironmentPower,Energiebezug,,08,B509,29BA00,,s,IGN:2,,,,,s,power", "8", "1008b5090329ba00", "03ba0008", "pm"},
{"uw,ehp,test,Test,,08,B5de,ab,,,power,,,,,s,hex:1", "8;39", "1008b5de02ab08", "0139", "pm"}, {"uw,ehp,test,Test,,08,B5de,ab,,,power,,,,,s,hex:1", "8;39", "1008b5de02ab08", "0139", "pm"},
@@ -72,7 +74,7 @@ int main()
MessageMap* messages = new MessageMap(); MessageMap* messages = new MessageMap();
Message* message = NULL; Message* message = NULL;
Message* deleteMessage = NULL; vector<Message*> deleteMessages;
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) { for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
string check[5] = checks[i]; string check[5] = checks[i];
istringstream isstr(check[0]); istringstream isstr(check[0]);
@@ -97,15 +99,19 @@ int main()
bool decode = flags.find('d') != string::npos; bool decode = 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;
string item; string item;
vector<string> entries; vector<string> entries;
while (getline(isstr, item, FIELD_SEPARATOR) != 0) while (getline(isstr, item, FIELD_SEPARATOR) != 0)
entries.push_back(item); entries.push_back(item);
if (deleteMessage != NULL) { if (deleteMessages.size()>0) {
delete deleteMessage; for (vector<Message*>::iterator it = deleteMessages.begin(); it!=deleteMessages.end(); it++) {
deleteMessage = NULL; Message* deleteMessage = *it;
delete deleteMessage;
}
deleteMessages.clear();
} }
if (isTemplate) { if (isTemplate) {
// store new template // store new template
@@ -138,7 +144,8 @@ int main()
} }
else { else {
vector<string>::iterator it = entries.begin(); vector<string>::iterator it = entries.begin();
result = Message::create(it, entries.end(), NULL, templates, deleteMessage);
result = Message::create(it, entries.end(), NULL, templates, deleteMessages);
if (failedCreate) { if (failedCreate) {
if (result == RESULT_OK) if (result == RESULT_OK)
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl; cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
@@ -152,7 +159,7 @@ int main()
printErrorPos(entries.begin(), entries.end(), it, "", 0, result); printErrorPos(entries.begin(), entries.end(), it, "", 0, result);
continue; continue;
} }
if (deleteMessage == NULL) { if (deleteMessages.size()==0) {
cout << "\"" << check[0] << "\": create error: NULL" << endl; cout << "\"" << check[0] << "\": create error: NULL" << endl;
continue; continue;
} }
@@ -160,17 +167,31 @@ int main()
cout << "\"" << check[0] << "\": create error: trailing input" << endl; cout << "\"" << check[0] << "\": create error: trailing input" << endl;
continue; continue;
} }
if (multi && deleteMessages.size()==1) {
cout << "\"" << check[0] << "\": create error: single message instead of multiple" << endl;
continue;
}
if (!multi && deleteMessages.size()>1) {
cout << "\"" << check[0] << "\": create error: multiple messages instead of single" << endl;
continue;
}
cout << "\"" << check[0] << "\": create OK" << endl; cout << "\"" << check[0] << "\": create OK" << endl;
if (!dontMap) { if (!dontMap) {
result_t result = messages->add(deleteMessage); result_t result = RESULT_OK;
if (result != RESULT_OK) { for (vector<Message*>::iterator it = deleteMessages.begin(); it!=deleteMessages.end(); it++) {
cout << "\"" << check[0] << "\": add error: " Message* deleteMessage = *it;
<< getResultCode(result) << endl; result_t result = messages->add(deleteMessage);
continue; if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": add error: "
<< getResultCode(result) << endl;
break;
}
} }
if (result!=RESULT_OK)
continue;
cout << " map OK" << endl; cout << " map OK" << endl;
message = deleteMessage; message = deleteMessages.front();
deleteMessage = NULL; deleteMessages.clear();
if (onlyMap) if (onlyMap)
continue; continue;
Message* foundMessage = messages->find(mstr); Message* foundMessage = messages->find(mstr);
@@ -182,7 +203,7 @@ int main()
cout << " find error: different" << endl; cout << " find error: different" << endl;
} }
else else
message = deleteMessage; message = deleteMessages.front();
} }
if (message->isPassive() || decode) { if (message->isPassive() || decode) {
@@ -222,9 +243,12 @@ int main()
} }
} }
if (deleteMessage != NULL) { if (deleteMessages.size()>0) {
delete deleteMessage; for (vector<Message*>::iterator it = deleteMessages.begin(); it!=deleteMessages.end(); it++) {
deleteMessage = NULL; Message* deleteMessage = *it;
delete deleteMessage;
}
deleteMessages.clear();
} }
delete templates; delete templates;