From f29219396b4b2e7d04ccfbb7a290ea37e0d1d68d Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 7 Nov 2015 18:24:59 +0100 Subject: [PATCH] also calculate key for temporary message, keep initial leadingSeparator if it was passed true in decode() and decodeLastData(), use empty condition messagename for referencing scan result, added MessageMap::getScanMessage(), do not poll for scan message, store derived scan message by key only, removed unnecessary minIdLength determination --- src/lib/ebus/message.cpp | 102 +++++++++++++++++++++++---------------- src/lib/ebus/message.h | 31 ++++++++---- 2 files changed, 81 insertions(+), 52 deletions(-) diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index ae01371b..694c5f88 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -36,8 +36,8 @@ using namespace std; /** the maximum poll priority for a @a Message referred to by a @a Condition. */ #define POLL_PRIORITY_CONDITION 5 -Message::Message(const string circuit, const string name, const bool isWrite, - const bool isPassive, const string comment, +Message::Message(const string circuit, const string name, + const bool isWrite, const bool isPassive, const string comment, const unsigned char srcAddress, const unsigned char dstAddress, const vector id, DataField* data, const bool deleteData, @@ -76,7 +76,11 @@ Message::Message(const bool isWrite, const bool isPassive, { m_id.push_back(pb); m_id.push_back(sb); - m_key = 0; + unsigned long long key = (isPassive ? 0LL : 0x1fLL) << (8 * 7); + key |= (unsigned long long)SYN << (8 * 6); + key |= (unsigned long long)pb << (8 * 5); + key |= (unsigned long long)sb << (8 * 4); + m_key = key; } /** @@ -456,7 +460,7 @@ result_t Message::decode(SymbolString& masterData, SymbolString& slaveData, return result; bool empty = result == RESULT_EMPTY; offset = 0; - leadingSeparator = output.str().length() > startPos; + leadingSeparator |= output.str().length() > startPos; result = m_data->read(pt_slaveData, slaveData, offset, output, outputFormat, leadingSeparator, NULL, -1); if (result < RESULT_OK) return result; @@ -489,7 +493,7 @@ result_t Message::decodeLastData(ostringstream& output, OutputFormat outputForma return result; bool empty = result == RESULT_EMPTY; offset = 0; - leadingSeparator = output.str().length() > startPos; + leadingSeparator |= output.str().length() > startPos; result = m_data->read(pt_slaveData, m_lastSlaveData, offset, output, outputFormat, leadingSeparator, fieldName, fieldIndex); if (result < RESULT_OK) return result; @@ -655,11 +659,7 @@ result_t Condition::create(vector::iterator& it, const vector::i return RESULT_ERR_EOF; } string circuit = *(it++); // circuit - if (circuit.length()==0) - return RESULT_ERR_INVALID_ARG; string name = it==end ? "" : *(it++); // messagename - if (name.length()==0) - return RESULT_ERR_INVALID_ARG; it++; // comment string field = it==end ? "" : *(it++); // fieldname string zz = it==end ? "" : *(it++); // ZZ @@ -727,9 +727,14 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess { if (m_message!=NULL) return RESULT_OK; // already resolved - Message* message = messages->find(m_circuit, m_name, false); - if (!message) - message = messages->find(m_circuit, m_name, false, true); + Message* message; + if (m_name.length()==0) { + message = messages->getScanMessage(m_dstAddress); + } else { + message = messages->find(m_circuit, m_name, false); + if (!message) + message = messages->find(m_circuit, m_name, false, true); + } if (!message) { errorMessage << "condition " << m_circuit << " " << m_name << ": message not found"; return RESULT_ERR_NOTFOUND; @@ -766,7 +771,8 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess } m_message = message; message->setUsedByCondition(); - messages->addPollMessage(message, true); + if (m_name.length()>0) + messages->addPollMessage(message, true); return RESULT_OK; } @@ -817,7 +823,7 @@ bool CombinedCondition::isTrue() } -result_t MessageMap::add(Message* message) +result_t MessageMap::add(Message* message, bool storeByName) { unsigned long long key = message->getKey(); bool conditional = message->isConditional(); @@ -832,40 +838,40 @@ result_t MessageMap::add(Message* message) } } bool isPassive = message->isPassive(); - bool isWrite = message->isWrite(); - string circuit = strtolower(message->getCircuit()); - string name = strtolower(message->getName()); - string nameKey = string(isPassive ? "P" : (isWrite ? "W" : "R")) + circuit + FIELD_SEPARATOR + name; - if (!m_addAll) { + if (storeByName) { + bool isWrite = message->isWrite(); + string circuit = strtolower(message->getCircuit()); + string name = strtolower(message->getName()); + string nameKey = string(isPassive ? "P" : (isWrite ? "W" : "R")) + circuit + FIELD_SEPARATOR + name; + if (!m_addAll) { + map >::iterator nameIt = m_messagesByName.find(nameKey); + if (nameIt != m_messagesByName.end()) { + vector* messages = &nameIt->second; + if (!message->isConditional() || !messages->front()->isConditional()) + return RESULT_ERR_DUPLICATE_NAME; // duplicate key + } + } + m_messagesByName[nameKey].push_back(message); + + nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit map >::iterator nameIt = m_messagesByName.find(nameKey); - if (nameIt != m_messagesByName.end()) { + if (nameIt == m_messagesByName.end()) + m_messagesByName[nameKey].push_back(message); // always store first message without circuit (in order of circuit name) + else { vector* messages = &nameIt->second; - if (!message->isConditional() || !messages->front()->isConditional()) - return RESULT_ERR_DUPLICATE_NAME; // duplicate key + Message* first = messages->front(); + if (circuit < first->getCircuit()) + m_messagesByName[nameKey].at(0) = message; // always store first message without circuit (in order of circuit name) + else if (m_addAll || (conditional && first->isConditional())) + m_messagesByName[nameKey].push_back(message); // store further messages only if both are conditional or if storing everything } } - m_messagesByName[nameKey].push_back(message); m_messageCount++; if (conditional) m_conditionalMessageCount++; if (isPassive) m_passiveMessageCount++; - - nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit - map >::iterator nameIt = m_messagesByName.find(nameKey); - if (nameIt == m_messagesByName.end()) - m_messagesByName[nameKey].push_back(message); // always store first message without circuit (in order of circuit name) - else { - vector* messages = &nameIt->second; - Message* first = messages->front(); - if (circuit < first->getCircuit()) - m_messagesByName[nameKey].at(0) = message; // always store first message without circuit (in order of circuit name) - else if (m_addAll || (conditional && first->isConditional())) - m_messagesByName[nameKey].push_back(message); // store further messages only if both are conditional or if storing everything - } unsigned char idLength = (unsigned char)(message->getId().size() - 2); - if (idLength < m_minIdLength) - m_minIdLength = idLength; if (idLength > m_maxIdLength) m_maxIdLength = idLength; m_messagesByKey[key].push_back(message); @@ -989,6 +995,21 @@ result_t MessageMap::addFromFile(vector::iterator& begin, const vectorgetDerivedKey(dstAddress); + vector* msgs = getByKey(key); + if (msgs!=NULL) + return msgs->front(); + Message* message = m_scanMessage->derive(dstAddress); + add(message, false); + return message; +} + result_t MessageMap::resolveConditions(bool verbose) { result_t overallResult = RESULT_OK; for (map::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) { @@ -1102,14 +1123,12 @@ deque MessageMap::findAll(SymbolString& master) if (master.size() < 5) return ret; unsigned char maxIdLength = master[4]; - if (maxIdLength < m_minIdLength) - return ret; if (maxIdLength > m_maxIdLength) maxIdLength = m_maxIdLength; if (master.size() < 5+maxIdLength) return ret; - for (int idLength = maxIdLength; ret.size()==0 && idLength >= m_minIdLength; idLength--) { + for (int idLength = maxIdLength; ret.size()==0 && idLength >= 0; idLength--) { int exp = 7; unsigned long long key = (unsigned long long)idLength << (8 * exp + 5); key |= (unsigned long long)getMasterNumber(master[0]) << (8 * exp--); @@ -1207,7 +1226,6 @@ void MessageMap::clear() // clear messages by key m_messagesByKey.clear(); m_conditions.clear(); - m_minIdLength = 4; m_maxIdLength = 0; } diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index f3ab35ef..c76189f4 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -60,8 +60,8 @@ public: * @param pollPriority the priority for polling, or 0 for no polling at all. * @param condition the @a Condition for this message, or NULL. */ - Message(const string circuit, const string name, const bool isWrite, - const bool isPassive, const string comment, + Message(const string circuit, const string name, + const bool isWrite, const bool isPassive, const string comment, const unsigned char srcAddress, const unsigned char dstAddress, const vector id, DataField* data, const bool deleteData, @@ -502,8 +502,8 @@ public: /** * Construct a new instance. * @param circuit the circuit name. - * @param name the message name. - * @param dstAddress the override destination address, or @a SYN (only for @a Message without specific destination). + * @param name the message name, or empty for scan message. + * @param dstAddress the override destination address, or @a SYN (only for @a Message without specific destination as well as scan message). * @param field the field name. * @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check. */ @@ -539,10 +539,10 @@ private: /** the circuit name. */ const string m_circuit; - /** the message name. */ + /** the message name, or empty for scan message. */ const string m_name; - /** the override destination address, or @a SYN (only for @a Message without specific destination). */ + /** the override destination address, or @a SYN (only for @a Message without specific destination as well as scan message). */ const unsigned char m_dstAddress; /** the field name, or empty for first field. */ @@ -604,7 +604,10 @@ public: * @param addAll whether to add all messages, even if duplicate. */ MessageMap(const bool addAll=false) : FileReader::FileReader(true), - m_addAll(addAll), m_minIdLength(4), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0) {} + m_addAll(addAll), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0) + { + m_scanMessage = new Message(false, false, 0x07, 0x04, DataFieldSet::getIdentFields(), true); + } /** * Destructor. @@ -614,10 +617,11 @@ public: /** * Add a @a Message instance to this set. * @param message the @a Message instance to add. + * @param storeByName whether to store the @a Message by name. * @return @a RESULT_OK on success, or an error code. * Note: the caller may not free the added instance on success. */ - result_t add(Message* message); + result_t add(Message* message, bool storeByName=true); // @copydoc virtual result_t addDefaultFromFile(vector< vector >& defaults, vector& row, @@ -638,6 +642,13 @@ public: DataFieldTemplates* arg, vector< vector >* defaults, const string& filename, unsigned int lineNo); + /** + * Get the scan @a Message instance for the specified address. + * @param dstAddress the destination address, or @a SYN for the base scan @a Message. + * @return the scan @a Message instance, or NULL if the dstAddress is no slave. + */ + Message* getScanMessage(const unsigned char dstAddress=SYN); + /** * Resolve all @a Condition instances. * @param verbose whether to verbosely add all problems to the error message. @@ -767,8 +778,8 @@ private: /** whether to add all messages, even if duplicate. */ const bool m_addAll; - /** the minimum ID length used by any of the known @a Message instances. */ - unsigned char m_minIdLength; + /** the @a Message instance used for scanning. */ + Message* m_scanMessage; /** the maximum ID length used by any of the known @a Message instances. */ unsigned char m_maxIdLength;