From c2c3462134477c9eec93dadfa09bfa2444bc46d8 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 18 Oct 2015 12:11:12 +0200 Subject: [PATCH] allow querying for first field in hasField(), support cloning message for conditions with specific destination address, support message seen check in condition, fix for parsing destination address in condition, more error messages --- src/lib/ebus/message.cpp | 100 ++++++++++++++++++++++++++------------- src/lib/ebus/message.h | 21 ++++++-- 2 files changed, 84 insertions(+), 37 deletions(-) diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index ef8a79d5..cfc7acb6 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -294,6 +294,15 @@ result_t Message::create(vector::iterator& it, const vector::ite return RESULT_OK; } +Message* Message::derive(const unsigned char dstAddress) +{ + return new Message(m_circuit, m_name, m_isWrite, + m_isPassive, m_comment, + m_srcAddress, dstAddress, + m_id, m_data, false, + m_pollPriority, m_condition); +} + bool Message::setPollPriority(unsigned char priority) { if (priority == m_pollPriority || m_isPassive) @@ -631,24 +640,31 @@ string strtolower(const string& str) result_t Condition::create(vector::iterator& it, const vector::iterator end, SimpleCondition*& returnValue) { // name,circuit,messagename,[comment],[fieldname],[ZZ],values (name already skipped by caller) - if (it+6>end) { + if (it+2>end) { // at least everything including messagename it = end; // for error reporting return RESULT_ERR_EOF; } string circuit = *(it++); // circuit if (circuit.length()==0) return RESULT_ERR_INVALID_ARG; - string name = *(it++); // messagename + string name = it==end ? "" : *(it++); // messagename if (name.length()==0) return RESULT_ERR_INVALID_ARG; it++; // comment - string field = *(it++); // fieldname - string zz = *(it++); // ZZ -//TODO use ZZ as optional param for ident, create ident message if necessary - istringstream stream(*(it++)); + string field = it==end ? "" : *(it++); // fieldname + string zz = it==end ? "" : *(it++); // ZZ + unsigned char dstAddress = SYN; + result_t result = RESULT_OK; + if (zz.length()>0) { + dstAddress = (unsigned char)parseInt(zz.c_str(), 16, 0, 0xff, result); + if (result != RESULT_OK) + return result; + if (dstAddress!=SYN && !isValidAddress(dstAddress, false)) + return RESULT_ERR_INVALID_ADDR; + } + istringstream stream(it==end ? "" : *(it++)); string str; vector valueRanges; - result_t result; while (getline(stream, str, VALUE_SEPARATOR) != 0) { DataFieldTemplates::trim(str); if (str.length()==0) @@ -685,10 +701,8 @@ result_t Condition::create(vector::iterator& it, const vector::i valueRanges.push_back(val); // single value } } - if (valueRanges.empty()) - return RESULT_ERR_INVALID_LIST; - returnValue = new SimpleCondition(circuit, name, field, valueRanges); + returnValue = new SimpleCondition(circuit, name, dstAddress, field, valueRanges); return RESULT_OK; } @@ -710,8 +724,21 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess errorMessage << "condition " << m_circuit << " " << m_name << ": message not found"; return RESULT_ERR_NOTFOUND; } - if (m_field.length()>0) { - if (!message->hasField(m_field.c_str(), true)) { + if (message->getDstAddress()==SYN) { + if (message->isPassive()) { + errorMessage << "condition " << m_circuit << " " << m_name << ": invalid passive message"; + return RESULT_ERR_INVALID_ARG; + } + if (m_dstAddress==SYN) { + errorMessage << "condition " << m_circuit << " " << m_name << ": destination address missing"; + return RESULT_ERR_INVALID_ADDR; + } + // clone the message with dedicated dstAddress + message = message->derive(m_dstAddress); + } + + if (!m_valueRanges.empty()) { + if (!message->hasField(m_field.length()>0 ? m_field.c_str() : NULL, true)) { errorMessage << "condition " << m_circuit << " " << m_name << ": numeric field " << m_field << " not found"; return RESULT_ERR_NOTFOUND; } @@ -727,14 +754,16 @@ bool SimpleCondition::isTrue() if (!m_message) return false; if (m_message->getLastChangeTime()>m_lastCheckTime) { - unsigned int value = 0; - result_t result = m_message->decodeLastDataField(value, m_field.length()==0 ? NULL : m_field.c_str()); - bool isTrue = false; - if (result==RESULT_OK) { - for (size_t i=0; i+1decodeLastDataField(value, m_field.length()==0 ? NULL : m_field.c_str()); + if (result==RESULT_OK) { + for (size_t i=0; i+1::iterator it = m_conditions.begin(); it!=m_conditions.end(); it++) { Condition* condition = *it; - result_t ret = condition->resolve(messages, errorMessage); + result_t ret = condition->resolve(messages, dummy); if (ret!=RESULT_OK) return ret; } @@ -825,13 +855,13 @@ result_t MessageMap::addDefaultFromFile(vector< vector >& defaults, vect string type = row[0]; if (type.length()>0 && type[0]=='[' && type[type.length()-1]==']') { // condition - type.erase(0, 1); - type.resize(type.length()-1); + type = type.substr(1, type.length()-2); string key = filename+":"+type; map::iterator it = m_conditions.find(key); - if (it != m_conditions.end()) + if (it != m_conditions.end()) { + m_lastError = "condition "+type+" already defined"; return RESULT_ERR_DUPLICATE_NAME; - + } if (row.size()>1 && defaultCircuit.length()>0 && row[1].length()==0) row[1] = defaultCircuit; // set default circuit SimpleCondition* condition = NULL; @@ -839,6 +869,7 @@ result_t MessageMap::addDefaultFromFile(vector< vector >& defaults, vect if (result!=RESULT_OK) { if (condition) delete condition; + m_lastError = "invalid condition"; return result; } if (!condition) @@ -865,8 +896,10 @@ result_t MessageMap::readConditions(string& types, const string& filename, Condi // simple condition string key = filename+":"+types.substr(1, pos-1); map::iterator it = m_conditions.find(key); - if (it==m_conditions.end()) + if (it==m_conditions.end()) { + m_lastError = "condition "+types.substr(1, pos-1)+" not defined"; return RESULT_ERR_NOTFOUND; + } if (condition) { condition = condition->combineAnd(it->second); store = true; @@ -930,21 +963,24 @@ result_t MessageMap::addFromFile(vector::iterator& begin, const vector::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) { Condition* condition = it->second; + ostringstream error; result_t result = condition->resolve(this, error); if (result!=RESULT_OK) { - if (verbose) { + string errorMessage = error.str(); + if (errorMessage.length()>0) { + if (m_lastError.length()>0) + m_lastError += ", "; + m_lastError += errorMessage; + } + if (verbose) overallResult = result; - error << ", "; - } else { - m_lastError = error.str(); + else { return result; } } } - m_lastError = error.str(); return overallResult; } diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index a5098217..ac356846 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -105,6 +105,13 @@ public: vector< vector >* defaultsRows, Condition* condition, const string& filename, DataFieldTemplates* templates, vector& messages); + /** + * Derive a new @a Message from this message. + * @param dstAddress the new destination address. + * @return the derived @a Message instance. + */ + Message* derive(const unsigned char dstAddress); + /** * Get the optional circuit name. * @return the optional circuit name. @@ -192,7 +199,7 @@ public: /** * Return whether the field is available. - * @param fieldName the name of the field to find. + * @param fieldName the name of the field to find, or NULL for any. * @param numeric true for a numeric field, false for a string field. * @return true if the field is available. */ @@ -490,12 +497,13 @@ 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 field the field name. - * @param valueRanges the valid value ranges (pairs of from/to inclusive). + * @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check. */ - SimpleCondition(const string circuit, const string name, const string field, const vector valueRanges) + SimpleCondition(const string circuit, const string name, const unsigned char dstAddress, const string field, const vector valueRanges) : Condition(), - m_circuit(circuit), m_name(name), m_field(field), m_valueRanges(valueRanges), + m_circuit(circuit), m_name(name), m_dstAddress(dstAddress), m_field(field), m_valueRanges(valueRanges), m_message(NULL) { } /** @@ -528,10 +536,13 @@ private: /** the message name. */ const string m_name; + /** the override destination address, or @a SYN (only for @a Message without specific destination). */ + const unsigned char m_dstAddress; + /** the field name, or empty for first field. */ const string m_field; - /** the valid value ranges (pairs of from/to inclusive). */ + /** the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check. */ const vector m_valueRanges; /** the resolved @a Message instance, or NULL. */