From 1378b4c1e452f23cfc9a3a35f8143c00fab22e3a Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 17:52:54 +0100 Subject: [PATCH 1/7] even nicer logging --- src/ebusd/baseloop.cpp | 4 ++-- src/ebusd/bushandler.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ebusd/baseloop.cpp b/src/ebusd/baseloop.cpp index 2dd15159..5dca20c6 100644 --- a/src/ebusd/baseloop.cpp +++ b/src/ebusd/baseloop.cpp @@ -266,7 +266,7 @@ string BaseLoop::decodeMessage(const string& data) result << getResultCode(ret); break; } - L.log(bas, event, "read cmd: %s", master.getDataStr().c_str()); + L.log(bas, trace, "read cmd: %s", master.getDataStr().c_str()); // send message SymbolString slave; @@ -305,7 +305,7 @@ string BaseLoop::decodeMessage(const string& data) result << getResultCode(ret); break; } - L.log(bas, event, "write cmd: %s", master.getDataStr().c_str()); + L.log(bas, trace, "write cmd: %s", master.getDataStr().c_str()); // send message SymbolString slave; diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index c583b576..946ad956 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -64,7 +64,7 @@ result_t PollRequest::prepare(unsigned char ownMasterAddress) istringstream input; result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input); if (result == RESULT_OK) - L.log(bus, event, "poll cmd: %s", m_master.getDataStr().c_str()); + L.log(bus, trace, "poll cmd: %s", m_master.getDataStr().c_str()); return result; } @@ -86,7 +86,7 @@ result_t ScanRequest::prepare(unsigned char ownMasterAddress, unsigned char dstA istringstream input; result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress); if (result == RESULT_OK) - L.log(bus, event, "scan cmd: %s", m_master.getDataStr().c_str()); + L.log(bus, trace, "scan cmd: %s", m_master.getDataStr().c_str()); return result; } @@ -96,10 +96,10 @@ void ScanRequest::notify(result_t result) m_scanResult << hex << setw(2) << setfill('0') << static_cast(m_master[1]) << UI_FIELD_SEPARATOR; result = m_message->decode(pt_slaveData, m_slave, m_scanResult); // decode data } - if (result == RESULT_OK) - L.log(bus, event, "scan result: %s", m_scanResult.str().c_str()); - else + if (result != RESULT_OK) L.log(bus, error, "scan %2.2x failed: %s", m_master[1], getResultCode(result)); + else + L.log(bus, event, "scan: %s", m_scanResult.str().c_str()); } @@ -141,7 +141,7 @@ bool ActiveBusRequest::wait(int timeout) void ActiveBusRequest::notify(result_t result) { if (result == RESULT_OK) - L.log(bus, trace, "read res: %s", m_slave.getDataStr().c_str()); + L.log(bus, event, "read res: %s", m_slave.getDataStr().c_str()); pthread_mutex_lock(&m_mutex); From a9a986558399e7b87acee44743c04eebdc4edcb0 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 14 Dec 2014 11:36:14 +0100 Subject: [PATCH 2/7] added verbose arg to decode() --- src/lib/ebus/message.cpp | 4 ++-- src/lib/ebus/message.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index 01d421e9..8d229e2a 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -293,7 +293,7 @@ result_t Message::prepareSlave(SymbolString& slaveData) } result_t Message::decode(const PartType partType, SymbolString& data, - ostringstream& output, bool leadingSeparator, char separator) + ostringstream& output, bool leadingSeparator, bool verbose, char separator) { unsigned char offset; if (partType == pt_masterData) @@ -301,7 +301,7 @@ result_t Message::decode(const PartType partType, SymbolString& data, else offset = 0; int startPos = output.str().length(); - result_t result = m_data->read(partType, data, offset, output, leadingSeparator, false, separator); + result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, separator); time(&m_lastUpdateTime); if (result != RESULT_OK) { m_lastValue.clear(); diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index 27430019..a3da24db 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -165,11 +165,13 @@ public: * @param data the unescaped data @a SymbolString for reading binary data. * @param output the @a ostringstream to append the formatted value to. * @param leadingSeparator whether to prepend a separator before the formatted value. + * @param verbose whether to prepend the name, append the unit (if present), and append + * the comment in square brackets (if present). * @param separator the separator character between multiple fields. * @return @a RESULT_OK on success, or an error code. */ result_t decode(const PartType partType, SymbolString& data, - ostringstream& output, bool leadingSeparator=false, char separator=UI_FIELD_SEPARATOR); + ostringstream& output, bool leadingSeparator=false, bool verbose=false, char separator=UI_FIELD_SEPARATOR); /** * @brief Get the last decoded value. From 83201eb287f1cc62661a750181d4a610f51fb747 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 14 Dec 2014 11:36:41 +0100 Subject: [PATCH 3/7] removed nonsense formatting in DataFieldSet::read --- src/lib/ebus/data.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index 8cfcc3e8..d378b963 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -1113,9 +1113,6 @@ result_t DataFieldSet::read(const PartType partType, ostringstream& output, bool leadingSeparator, bool verbose, char separator) { - if (verbose) - output << m_name << "={ "; - bool previousFullByteOffset = true; for (vector::iterator it = m_fields.begin(); it < m_fields.end(); it++) { SingleDataField* field = *it; @@ -1139,7 +1136,6 @@ result_t DataFieldSet::read(const PartType partType, if (verbose == true) { if (m_comment.length() > 0) output << " [" << m_comment << "]"; - output << "}"; } return RESULT_OK; From 0fc2396a12266206aed1e89339605cdabb43ab81 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 14 Dec 2014 11:37:14 +0100 Subject: [PATCH 4/7] added missing states in getStateCode --- src/ebusd/bushandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 946ad956..29f249ad 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -51,8 +51,8 @@ const char* getStateCode(BusState state) { case bs_sendResAck: return "send response ACK"; case bs_recvCmd: return "receive command"; case bs_recvResAck: return "receive response ACK"; -// case bs_sendRes: return "send response"; -// case bs_sendCmdAck: return "send command ACK"; + case bs_sendCmdAck: return "send command ACK"; + case bs_sendRes: return "send response"; case bs_sendSyn: return "send SYN"; default: return "unknown"; } From ad52a848333dacd10d77c83d7b43ef8ef9858e99 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 14 Dec 2014 11:43:04 +0100 Subject: [PATCH 5/7] implemented reload command, allow reading config from symlinks, added verbose and maxage (defaults to 5 minutes) options to read command, use "write -h" instead "hex" for hex commands --- src/ebusd/baseloop.cpp | 206 +++++++++++++++++++++++------------------ src/ebusd/baseloop.h | 9 +- 2 files changed, 124 insertions(+), 91 deletions(-) diff --git a/src/ebusd/baseloop.cpp b/src/ebusd/baseloop.cpp index 5dca20c6..751f8298 100644 --- a/src/ebusd/baseloop.cpp +++ b/src/ebusd/baseloop.cpp @@ -20,6 +20,7 @@ #include "baseloop.h" #include "logger.h" #include "appl.h" +#include "data.h" #include #include @@ -30,26 +31,10 @@ extern Appl& A; BaseLoop::BaseLoop() { - // create commands DB + // load messages and templates m_templates = new DataFieldTemplates(); m_messages = new MessageMap(); - - string confdir = A.getOptVal("ebusconfdir"); - L.log(bas, trace, "ebus configuration dir: %s", confdir.c_str()); - result_t result = m_templates->readFromFile(confdir+"/_types.csv"); - if (result == RESULT_OK) - L.log(bas, trace, "read templates"); - else - L.log(bas, error, "error reading templates: %s", getResultCode(result)); - result = readConfigFiles(confdir, ".csv"); - if (result == RESULT_OK) - L.log(bas, trace, "read config files"); - else - L.log(bas, error, "error reading config files: %s", getResultCode(result)); - - L.log(bas, event, "message DB: %d ", m_messages->size()); - L.log(bas, event, "updates DB: %d ", m_messages->size(true)); - L.log(bas, event, "polling DB: %d ", m_messages->sizePoll()); + loadMessages(); m_ownAddress = A.getOptVal("address") & 0xff; const bool answer = A.getOptVal("answer"); @@ -113,6 +98,31 @@ BaseLoop::~BaseLoop() delete m_templates; } +result_t BaseLoop::loadMessages() +{ + string confdir = A.getOptVal("ebusconfdir"); + L.log(bas, trace, "ebus configuration dir: %s", confdir.c_str()); + m_messages->clear(); + m_templates->clear(); + result_t result = m_templates->readFromFile(confdir+"/_types.csv"); + if (result == RESULT_OK) + L.log(bas, trace, "read templates"); + else + L.log(bas, error, "error reading templates: %s", getResultCode(result)); + + result = readConfigFiles(confdir, ".csv"); + if (result == RESULT_OK) { + L.log(bas, trace, "read config files"); + + L.log(bas, event, "message DB: %d ", m_messages->size()); + L.log(bas, event, "updates DB: %d ", m_messages->size(true)); + L.log(bas, event, "polling DB: %d ", m_messages->sizePoll()); + } else + L.log(bas, error, "error reading config files: %s", getResultCode(result)); + + return result; +} + result_t BaseLoop::readConfigFiles(const string path, const string extension) { DIR* dir = opendir(path.c_str()); @@ -132,7 +142,7 @@ result_t BaseLoop::readConfigFiles(const string path, const string extension) if (result != RESULT_OK) return result; } - } else if (d->d_type == DT_REG) { + } else if (d->d_type == DT_REG || d->d_type == DT_LNK) { string fn = d->d_name; if (fn.find(extension, (fn.length() - extension.length())) != string::npos @@ -208,7 +218,6 @@ string BaseLoop::decodeMessage(const string& data) return "command missing"; size_t argPos = 1; - bool force = false; switch (getCase(args[0])) { case ct_invalid: @@ -216,24 +225,51 @@ string BaseLoop::decodeMessage(const string& data) break; case ct_read: { - if (args.size() > argPos && args[argPos] == "-f") { - force = true; + unsigned int maxAge = 5*60; + bool verbose = false; + while (args.size() > argPos && args[argPos][0] == '-') { + if (args[argPos]== "-f") { + maxAge = 0; + } else if (args[argPos] == "-v") { + verbose = true; + } else if (args[argPos] == "-m") { + argPos++; + if (args.size() > argPos) { + result_t result; + maxAge = parseInt(args[argPos].c_str(), 10, 0, 24*60*60, result); + if (result != RESULT_OK) { + argPos = args.size(); // print usage + break; + } + } + else { + argPos = args.size(); // print usage + break; + } + } else { + argPos = args.size(); // print usage + break; + } argPos++; } if (args.size() < argPos + 1 || args.size() > argPos + 3) { - result << "usage: 'read [-f] [class] cmd' or 'read [-f] class cmd sub'"; + result << "usage: 'read [-f] [-v] [class] cmd'"; // TODO or 'read [-f] class cmd sub'"; break; } + + time_t now; + time(&now); + Message* updateMessage = NULL; - if (force == false) { + if (maxAge > 0 && verbose == false) { if (args.size() == argPos + 1) updateMessage = m_messages->find("", args[argPos], false, true); else updateMessage = m_messages->find(args[argPos], args[argPos + 1], false, true); - if (updateMessage != NULL) { - token = updateMessage->getLastValue(); + if (updateMessage != NULL && updateMessage->getLastUpdateTime() + maxAge > now) { + token = updateMessage->getLastValue(); // TODO switch from last value to last master/slave to support verbose cached/polled values as well if (token.empty() == false) { result << token; break; @@ -248,8 +284,8 @@ string BaseLoop::decodeMessage(const string& data) message = m_messages->find(args[argPos], args[argPos + 1], false); if (message != NULL) { - - if (m_pollActive == true && message->getPollPriority() > 0) { + if (maxAge > 0 && m_pollActive == true && message->getPollPriority() > 0 + && message->getLastUpdateTime() + maxAge > now) { // get polldata token = message->getLastValue(); if (token.empty() == false) { @@ -274,7 +310,7 @@ string BaseLoop::decodeMessage(const string& data) if (ret == RESULT_OK) { // TODO reduce to requested variable only - ret = message->decode(pt_slaveData, slave, result); // decode data + ret = message->decode(pt_slaveData, slave, result, false, verbose); // decode data } if (ret != RESULT_OK) { L.log(bas, error, "read: %s", getResultCode(ret)); @@ -289,8 +325,49 @@ string BaseLoop::decodeMessage(const string& data) break; } case ct_write: { + if (args.size() > argPos && args[argPos] == "-h") { + argPos++; + + if (args.size() < argPos + 1) { + result << "usage: 'write -h ZZPBSBNNDx'"; + break; + } + + ostringstream msg; + msg << hex << setw(2) << setfill('0') << static_cast(m_ownAddress) << setw(0); + while (argPos < args.size()) { + if ((args[argPos].length() % 2) != 0) { + result << "invalid hex string"; + msg.str(""); + break; + } + msg << args[argPos++]; + } + if (msg.str().length() == 0) + break; + + SymbolString master(msg.str()); + L.log(bas, event, "write hex cmd: %s", master.getDataStr().c_str()); + + // send message + SymbolString slave; + result_t ret = m_busHandler->sendAndWait(master, slave); + + if (ret == RESULT_OK) { + if (master[1] == BROADCAST || isMaster(master[1])) + result << "done"; + else + result << slave.getDataStr(); + } + if (ret != RESULT_OK) { + L.log(bas, error, "write hex: %s", getResultCode(ret)); + result << getResultCode(ret); + } + break; + } + if (args.size() != argPos + 3) { - result << "usage: 'write class cmd value[;value]*'"; + result << "usage: 'write class cmd value[;value]*' or 'write -h ZZPBSBNNDx'"; break; } @@ -330,44 +407,6 @@ string BaseLoop::decodeMessage(const string& data) } break; } - case ct_hex: { - if (args.size() < argPos + 1) { - result << "usage: 'hex value' (value: ZZPBSBNNDx)"; - break; - } - - ostringstream msg; - msg << hex << setw(2) << setfill('0') << static_cast(m_ownAddress) << setw(0); - while (argPos < args.size()) { - if ((args[argPos].length() % 2) != 0) { - result << "invalid hex string"; - msg.str(""); - break; - } - msg << args[argPos++]; - } - if (msg.str().length() == 0) - break; - - SymbolString master(msg.str()); - L.log(bas, event, "hex cmd: %s", master.getDataStr().c_str()); - - // send message - SymbolString slave; - result_t ret = m_busHandler->sendAndWait(master, slave); - - if (ret == RESULT_OK) { - if (master[1] == BROADCAST || isMaster(master[1])) - result << "done"; - else - result << slave.getDataStr(); - } - if (ret != RESULT_OK) { - L.log(bas, error, "hex: %s", getResultCode(ret)); - result << getResultCode(ret); - } - break; - } case ct_scan: { if (args.size() == argPos) { result_t ret = m_busHandler->startScan(); @@ -408,7 +447,6 @@ string BaseLoop::decodeMessage(const string& data) break; } - // TODO: check for possible areas and level if (strcasecmp(args[argPos].c_str(), "AREAS") == 0) { L.getSink(0)->setAreas(calcAreas(args[argPos + 1])); result << "done"; @@ -447,31 +485,23 @@ string BaseLoop::decodeMessage(const string& data) result << (enabled ? "dump enabled" : "dump disabled"); break; } - /*case ct_reload: - if (cmd.size() != 1) { + case ct_reload: { + if (args.size() != 1) { result << "usage: 'reload'"; break; } - { - // create commands DB - Commands* commands = ConfigCommands(A.getOptVal("ebusconfdir"), ft_csv).getCommands(); - L.log(bas, trace, "ebus configuration dir: %s", A.getOptVal("ebusconfdir")); - L.log(bas, event, "commands DB: %d ", m_commands->sizeCmdDB()); - L.log(bas, event, " cycle DB: %d ", m_commands->sizeCycDB()); - L.log(bas, event, " polling DB: %d ", m_commands->sizePollDB()); - - delete m_commands; - m_commands = commands; - m_busloop->reload(m_commands); - + // create commands DB + result_t ret = loadMessages(); + if (ret == RESULT_OK) result << "done"; - break; - }*/ - + else + result << getResultCode(ret); + break; + } case ct_help: result << "commands:" << endl - << " read - read ebus values 'read [-f] [class] cmd [sub]'" << endl + << " read - read ebus values 'read [-f] [-v] [class] cmd'" << endl << " write - write ebus values 'write class cmd value[;value]*'" << endl << " hex - send given hex value 'hex type value' (value: ZZPBSBNNDx)" << endl << endl << " scan - scan ebus kown addresses 'scan'" << endl @@ -487,8 +517,6 @@ string BaseLoop::decodeMessage(const string& data) << " help - print this page 'help'"; break; - default: - break; } return result.str(); diff --git a/src/ebusd/baseloop.h b/src/ebusd/baseloop.h index 9a8cacba..0a486a10 100644 --- a/src/ebusd/baseloop.h +++ b/src/ebusd/baseloop.h @@ -32,7 +32,6 @@ using namespace std; enum CommandType { ct_read, /*!< read ebus values */ ct_write, /*!< write ebus values */ - ct_hex, /*!< send hex data */ ct_scan, /*!< scan ebus */ ct_log, /*!< logger settings */ ct_raw, /*!< toggle log raw data */ @@ -59,10 +58,17 @@ public: */ ~BaseLoop(); + /** + * @brief Load the message definitions. + * @return the result code. + */ + result_t loadMessages(); + /** * @brief Read the configuration files from the specified path. * @param path the path from which to read the files. * @param extension the filename extension of the files to read. + * @return the result code. */ result_t readConfigFiles(const string path, const string extension); @@ -119,7 +125,6 @@ private: { if (strcasecmp(item.c_str(), "READ") == 0) return ct_read; if (strcasecmp(item.c_str(), "WRITE") == 0) return ct_write; - if (strcasecmp(item.c_str(), "HEX") == 0) return ct_hex; if (strcasecmp(item.c_str(), "SCAN") == 0) return ct_scan; if (strcasecmp(item.c_str(), "LOG") == 0) return ct_log; if (strcasecmp(item.c_str(), "RAW") == 0) return ct_raw; From 2c2ab1c031793b5aa338f5c522b4df864a55f7b4 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 14 Dec 2014 12:08:35 +0100 Subject: [PATCH 6/7] added option to read only a single field --- src/ebusd/baseloop.cpp | 15 ++++++++------- src/lib/ebus/data.cpp | 24 ++++++++++++++---------- src/lib/ebus/data.h | 14 ++++++++++---- src/lib/ebus/message.cpp | 6 ++++-- src/lib/ebus/message.h | 5 ++++- src/lib/ebus/result.cpp | 1 + src/lib/ebus/result.h | 1 + 7 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/ebusd/baseloop.cpp b/src/ebusd/baseloop.cpp index 751f8298..2b65b8fd 100644 --- a/src/ebusd/baseloop.cpp +++ b/src/ebusd/baseloop.cpp @@ -253,7 +253,7 @@ string BaseLoop::decodeMessage(const string& data) argPos++; } if (args.size() < argPos + 1 || args.size() > argPos + 3) { - result << "usage: 'read [-f] [-v] [class] cmd'"; // TODO or 'read [-f] class cmd sub'"; + result << "usage: 'read [-v] [-f] [-m seconds] [class] cmd' or 'read [-v] [-f] [-m seconds] class cmd sub'"; break; } @@ -309,8 +309,10 @@ string BaseLoop::decodeMessage(const string& data) ret = m_busHandler->sendAndWait(master, slave); if (ret == RESULT_OK) { - // TODO reduce to requested variable only - ret = message->decode(pt_slaveData, slave, result, false, verbose); // decode data + if (args.size() == argPos + 3) + ret = message->decode(pt_slaveData, slave, result, false, verbose, args[argPos + 2].c_str()); + else + ret = message->decode(pt_slaveData, slave, result, false, verbose); // decode data } if (ret != RESULT_OK) { L.log(bas, error, "read: %s", getResultCode(ret)); @@ -501,12 +503,11 @@ string BaseLoop::decodeMessage(const string& data) } case ct_help: result << "commands:" << endl - << " read - read ebus values 'read [-f] [-v] [class] cmd'" << endl - << " write - write ebus values 'write class cmd value[;value]*'" << endl - << " hex - send given hex value 'hex type value' (value: ZZPBSBNNDx)" << endl << endl + << " read - read ebus values 'read [-v] [-f] [-m seconds] [class] cmd' or 'read [-v] [-f] [-m seconds] class cmd sub'" << endl + << " write - write ebus values 'write class cmd value[;value]*' or 'write -h ZZPBSBNNDx'" << endl << " scan - scan ebus kown addresses 'scan'" << endl << " - scan ebus all addresses 'scan full'" << endl - << " - show results 'scan result'" << endl << endl + << " - show scan results 'scan result'" << endl << endl << " log - change log areas 'log areas area,area,..' (areas: bas|net|bus|upd|all)" << endl << " - change log level 'log level level' (level: error|event|trace|debug)" << endl << endl << " raw - toggle log raw data 'raw'" << endl diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index d378b963..e35b6644 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -373,7 +373,8 @@ void SingleDataField::dump(ostream& output) result_t SingleDataField::read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator, - bool verbose, char separator) + bool verbose, const char* filterName, + char separator) { if (partType != m_partType) return RESULT_OK; @@ -389,11 +390,11 @@ result_t SingleDataField::read(const PartType partType, default: return RESULT_ERR_INVALID_PART; } - if (isIgnored() == true) { + if (isIgnored() == true || (filterName != NULL && m_name != filterName)) { if (offset + m_length > data.size()) { return RESULT_ERR_INVALID_POS; } - return RESULT_OK; + return RESULT_EMPTY; } if (leadingSeparator == true) @@ -1111,9 +1112,10 @@ void DataFieldSet::dump(ostream& output) result_t DataFieldSet::read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator, - bool verbose, char separator) + bool verbose, const char* filterName, + char separator) { - bool previousFullByteOffset = true; + bool previousFullByteOffset = true, found = false; for (vector::iterator it = m_fields.begin(); it < m_fields.end(); it++) { SingleDataField* field = *it; if (partType != pt_any && field->getPartType() != partType) @@ -1122,15 +1124,17 @@ result_t DataFieldSet::read(const PartType partType, if (previousFullByteOffset == false && field->hasFullByteOffset(false) == false) offset--; -//cout<<"read "<getName().c_str()<<" in part "<(field->getPartType())<<" offset "<(offsets[field->getPartType()])<read(partType, data, offset, output, leadingSeparator, verbose, separator); + result_t result = field->read(partType, data, offset, output, leadingSeparator, verbose, filterName, separator); - if (result != RESULT_OK) + if (result < RESULT_OK) return result; offset += field->getLength(partType); previousFullByteOffset = field->hasFullByteOffset(true); - leadingSeparator |= field->isIgnored() == false; + if (result != RESULT_EMPTY) { + found = true; + leadingSeparator = true; + } } if (verbose == true) { @@ -1138,7 +1142,7 @@ result_t DataFieldSet::read(const PartType partType, output << " [" << m_comment << "]"; } - return RESULT_OK; + return found == true ? RESULT_OK : RESULT_EMPTY; } result_t DataFieldSet::write(istringstream& input, diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index 078efad7..e656ea97 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -183,13 +183,17 @@ public: * @param leadingSeparator whether to prepend a separator before the formatted value. * @param verbose whether to prepend the name, append the unit (if present), and append * the comment in square brackets (if present). + * @param filterName the optional name of a field to limit the output to. * @param separator the separator character between multiple fields. - * @return @a RESULT_OK on success (or if the partType does not match), or an error code. + * @return @a RESULT_OK on success (or if the partType does not match), + * or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a filterName), + * or an error code. */ virtual result_t read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator=false, - bool verbose=false, char separator=UI_FIELD_SEPARATOR) = 0; + bool verbose=false, const char* filterName=NULL, + char separator=UI_FIELD_SEPARATOR) = 0; /** * @brief Writes the value to the master or slave @a SymbolString. * @param input the @a istringstream to parse the formatted value from. @@ -270,7 +274,8 @@ public: virtual result_t read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator=false, - bool verbose=false, char separator=UI_FIELD_SEPARATOR); + bool verbose=false, const char* filterName=NULL, + char separator=UI_FIELD_SEPARATOR); // @copydoc virtual result_t write(istringstream& input, const PartType partType, SymbolString& data, @@ -569,7 +574,8 @@ public: virtual result_t read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator=false, - bool verbose=false, char separator=UI_FIELD_SEPARATOR); + bool verbose=false, const char* filterName=NULL, + char separator=UI_FIELD_SEPARATOR); // @copydoc virtual result_t write(istringstream& input, const PartType partType, SymbolString& data, diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index 8d229e2a..363dd133 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -293,7 +293,9 @@ result_t Message::prepareSlave(SymbolString& slaveData) } result_t Message::decode(const PartType partType, SymbolString& data, - ostringstream& output, bool leadingSeparator, bool verbose, char separator) + ostringstream& output, bool leadingSeparator, + bool verbose, const char* filterName, + char separator) { unsigned char offset; if (partType == pt_masterData) @@ -301,7 +303,7 @@ result_t Message::decode(const PartType partType, SymbolString& data, else offset = 0; int startPos = output.str().length(); - result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, separator); + result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, filterName, separator); time(&m_lastUpdateTime); if (result != RESULT_OK) { m_lastValue.clear(); diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index a3da24db..f8335d2c 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -167,11 +167,14 @@ public: * @param leadingSeparator whether to prepend a separator before the formatted value. * @param verbose whether to prepend the name, append the unit (if present), and append * the comment in square brackets (if present). + * @param filterName the optional name of a field to limit the output to. * @param separator the separator character between multiple fields. * @return @a RESULT_OK on success, or an error code. */ result_t decode(const PartType partType, SymbolString& data, - ostringstream& output, bool leadingSeparator=false, bool verbose=false, char separator=UI_FIELD_SEPARATOR); + ostringstream& output, bool leadingSeparator=false, + bool verbose=false, const char* filterName=NULL, + char separator=UI_FIELD_SEPARATOR); /** * @brief Get the last decoded value. diff --git a/src/lib/ebus/result.cpp b/src/lib/ebus/result.cpp index 43f850e2..15b8c0bc 100644 --- a/src/lib/ebus/result.cpp +++ b/src/lib/ebus/result.cpp @@ -27,6 +27,7 @@ const char* getResultCode(result_t resultCode) { case RESULT_OK: return "success"; case RESULT_IN_ESC: return "success: escape sequence received"; case RESULT_SYN: return "success: SYN received"; + case RESULT_EMPTY: return "success: empty"; case RESULT_ERR_GENERIC_IO: return "ERR: generic I/O error"; case RESULT_ERR_DEVICE: return "ERR: generic device error"; case RESULT_ERR_SEND: return "ERR: send error"; diff --git a/src/lib/ebus/result.h b/src/lib/ebus/result.h index f419e31b..774c04e1 100644 --- a/src/lib/ebus/result.h +++ b/src/lib/ebus/result.h @@ -24,6 +24,7 @@ static const int RESULT_OK = 0; // success static const int RESULT_IN_ESC = 1; // start of escape sequence received static const int RESULT_SYN = 2; // regular SYN after message received +static const int RESULT_EMPTY = 3; // empty result static const int RESULT_ERR_GENERIC_IO = -1; // generic I/O error (usually fatal) static const int RESULT_ERR_DEVICE = -2; // generic device error (usually fatal) From e507901d8fbdb0160329b6e41c5052adce449a5b Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 14 Dec 2014 12:15:40 +0100 Subject: [PATCH 7/7] optimized handling scan result and remove typeinfo dependency --- src/ebusd/bushandler.cpp | 22 ++++++++++++---------- src/ebusd/bushandler.h | 12 +++++++----- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 29f249ad..14e738b0 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -92,14 +92,20 @@ result_t ScanRequest::prepare(unsigned char ownMasterAddress, unsigned char dstA void ScanRequest::notify(result_t result) { + unsigned char dstAddress = m_master[1]; + ostringstream scanResult; if (result == RESULT_OK) { - m_scanResult << hex << setw(2) << setfill('0') << static_cast(m_master[1]) << UI_FIELD_SEPARATOR; - result = m_message->decode(pt_slaveData, m_slave, m_scanResult); // decode data + scanResult << hex << setw(2) << setfill('0') << static_cast(dstAddress) << UI_FIELD_SEPARATOR; + result = m_message->decode(pt_slaveData, m_slave, scanResult); // decode data } if (result != RESULT_OK) - L.log(bus, error, "scan %2.2x failed: %s", m_master[1], getResultCode(result)); - else - L.log(bus, event, "scan: %s", m_scanResult.str().c_str()); + L.log(bus, error, "scan %2.2x failed: %s", dstAddress, getResultCode(result)); + else { + string str = scanResult.str(); + L.log(bus, event, "scan: %s", str.c_str()); + if (m_scanResults != NULL) + (*m_scanResults)[dstAddress] = str; + } } @@ -574,10 +580,6 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit m_seenAddresses[dstAddress] = true; m_request->notify(result); if (m_request->m_deleteOnFinish == true) { - if (result == RESULT_OK && typeid(*m_request) == typeid(ScanRequest)) { - string res = ((ScanRequest*)m_request)->m_scanResult.str(); - m_scanResults[dstAddress] = res; - } delete m_request; } m_request = NULL; @@ -662,7 +664,7 @@ result_t BusHandler::startScan(bool full) continue; } - ScanRequest* request = new ScanRequest(m_response, scanMessage); + ScanRequest* request = new ScanRequest(m_response, scanMessage, &m_scanResults); result_t result = request->prepare(m_ownMasterAddress, slave); if (result != RESULT_OK) { delete request; diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index 2f835986..a1e5c1f6 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -31,7 +31,6 @@ #include #include #include -#include using namespace std; @@ -161,9 +160,12 @@ public: * @brief Constructor. * @param slave the slave data @a SymbolString received. * @param message the associated @a Message. + * @param scanResults the map in which to store the formatted scan result by slave address. */ - ScanRequest(SymbolString& slave, Message* message) - : BusRequest(m_master, slave, true), m_message(message) {} + ScanRequest(SymbolString& slave, Message* message, + map* scanResults) + : BusRequest(m_master, slave, true), m_message(message), + m_scanResults(scanResults) {} /** * @brief Destructor. @@ -189,8 +191,8 @@ private: /** the associated @a Message. */ Message* m_message; - /** the formatted scan result. */ - ostringstream m_scanResult; + /** the map in which to store the formatted scan result by slave address. */ + map* m_scanResults; };