From 6eab4f86d1622987b8dd77c19d07e2ba3b409e0c Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 00:14:11 +0100 Subject: [PATCH 1/7] also collect participant addressed actively --- src/ebusd/bushandler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index f4ef53b3..dd62ff66 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -564,10 +564,12 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit } else if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) { L.log(bus, debug, "notify request: %s", getResultCode(result)); m_request->m_slave = SymbolString(m_response, false, false); + unsigned char dstAddress = m_request->m_master[1]; + if (result == RESULT_OK && isValidAddress(dstAddress, false) == true) + m_seenAddresses[dstAddress] = true; m_request->notify(result); if (m_request->m_deleteOnFinish == true) { if (result == RESULT_OK && typeid(*m_request) == typeid(ScanRequest)) { - unsigned char dstAddress = m_request->m_master[1]; string res = ((ScanRequest*)m_request)->m_scanResult.str(); L.log(bus, debug, " scan result %x: %s", dstAddress, res.c_str()); m_scanResults[dstAddress] = res; From cda96e6e3b452bcacfae886f58579e02d73d16fd Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 11:07:18 +0100 Subject: [PATCH 2/7] extraced FileReader to separate .h and added support for quoted CSV --- src/lib/ebus/data.cpp | 16 +-- src/lib/ebus/data.h | 83 +-------------- src/lib/ebus/filereader.h | 163 +++++++++++++++++++++++++++++ src/lib/ebus/message.cpp | 6 +- src/lib/ebus/message.h | 2 +- src/lib/ebus/test/test_message.cpp | 2 +- 6 files changed, 181 insertions(+), 91 deletions(-) create mode 100644 src/lib/ebus/filereader.h diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index adbc296d..b18916a3 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -105,13 +105,14 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co return ret; } -void printErrorPos(vector::iterator begin, const vector::iterator end, vector::iterator pos) +void printErrorPos(vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result) { + if (pos > begin) + pos--; + cout << "Error reading \"" << filename << "\" line " << static_cast(pos.base()-begin.base()) << " value \"" << *pos << "\": " << getResultCode(result) << endl; cout << "Erroneous item is here:" << endl; bool first = true; int cnt = 0; - if (pos > begin) - pos--; while (begin != end) { if (first == true) first = false; @@ -122,9 +123,12 @@ void printErrorPos(vector::iterator begin, const vector::iterato } } if (begin < pos) { - cnt += (*begin).length(); + cnt += 1+(*begin).length()+1; + } else if (begin == pos) { + cnt++; } - cout << (*begin++); + string item = *begin++; + cout << TEXT_SEPARATOR << item << TEXT_SEPARATOR; } cout << endl; cout << setw(cnt) << " " << setw(0) << "^" << endl; @@ -1221,7 +1225,7 @@ result_t DataFieldTemplates::add(DataField* field, bool replace) return RESULT_OK; } -result_t DataFieldTemplates::addFromFile(vector& row, void* arg, vector< vector >* defaults) +result_t DataFieldTemplates::addFromFile(vector& row, void* arg, vector< vector >* defaults, const string& filename, unsigned int lineNo) { DataField* field = NULL; vector::iterator it = row.begin(); diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index 985d2e2d..078efad7 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -22,6 +22,7 @@ #include "symbol.h" #include "result.h" +#include "filereader.h" #include #include #include @@ -31,9 +32,6 @@ using namespace std; -/** the separator character used between fields (in CSV only). */ -#define FIELD_SEPARATOR ',' - /** the separator character used between multiple values (in CSV only). */ #define VALUE_SEPARATOR ';' @@ -103,7 +101,7 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co * @param pos the iterator with the erroneous position. * @param separator the character to place between items. */ -void printErrorPos(vector::iterator begin, const vector::iterator end, vector::iterator pos); +void printErrorPos(vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result); class DataFieldTemplates; @@ -585,81 +583,6 @@ private: }; -/** - * @brief An abstract class that support reading definitions from a file. - */ -template -class FileReader -{ -public: - - /** - * @brief Constructs a new instance. - */ - FileReader(bool supportsDefaults) - : m_supportsDefaults(supportsDefaults) {} - /** - * @brief Destructor. - */ - virtual ~FileReader() {} - /** - * @brief Reads the definitions from a file. - * @param filename the name (and path) of the file to read. - * @return @a RESULT_OK on success, or an error code. - */ - virtual result_t readFromFile(string filename, T arg=NULL) - { - ifstream ifs; - ifs.open(filename.c_str(), ifstream::in); - if (ifs.is_open() == false) - return RESULT_ERR_NOTFOUND; - - string line; - unsigned int lineNo = 0; - vector row; - string token; - vector< vector > defaults; - while (getline(ifs, line) != 0) { - lineNo++; - // skip empty lines and comments - if (line.length() == 0 || line.substr(0, 1) == "#" || line.substr(0, 2) == "//") - continue; - istringstream isstr(line); - row.clear(); - while (getline(isstr, token, FIELD_SEPARATOR) != 0) - row.push_back(token); - - if (m_supportsDefaults == true && line.substr(0, 1) == "*") { - row[0] = row[0].substr(1); - defaults.push_back(row); - continue; - } - result_t result = addFromFile(row, arg, m_supportsDefaults == true ? &defaults : NULL); - if (result != RESULT_OK) { - cerr << "error reading \"" << filename << "\" line " << static_cast(lineNo) << ": " << getResultCode(result) << endl; - ifs.close(); - return result; - } - } - - ifs.close(); - return RESULT_OK; - } - /** - * @brief Adds a definition that was read from a file. - * @param row the definition row read from the file. - * @param defaults all previously read default rows (initial star char removed), or NULL if not supported. - * @return @a RESULT_OK on success, or an error code. - */ - virtual result_t addFromFile(vector& row, T arg, vector< vector >* defaults) = 0; - -private: - /** whether this instance supports rows with defaults (starting with a star). */ - bool m_supportsDefaults; - -}; - - /** * @brief A map of template @a DataField instances. */ @@ -688,7 +611,7 @@ public: */ result_t add(DataField* message, bool replace=false); // @copydoc - virtual result_t addFromFile(vector& row, void* arg, vector< vector >* defaults); + virtual result_t addFromFile(vector& row, void* arg, vector< vector >* defaults, const string& filename, unsigned int lineNo); /** * @brief Gets the template @a DataField instance with the specified name. * @return the template @a DataField instance, or NULL. diff --git a/src/lib/ebus/filereader.h b/src/lib/ebus/filereader.h new file mode 100644 index 00000000..62a9b738 --- /dev/null +++ b/src/lib/ebus/filereader.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) John Baier 2014 + * + * This file is part of ebusd. + * + * ebusd is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ebusd is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ebusd. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef LIBEBUS_FILEREADER_H_ +#define LIBEBUS_FILEREADER_H_ + +#include "symbol.h" +#include "result.h" +#include +#include +#include +#include +#include +#include + +using namespace std; + + +/** the separator character used between fields. */ +#define FIELD_SEPARATOR ',' + +/** the separator character used to quote text having the @a FIELD_SEPARATOR in it. */ +#define TEXT_SEPARATOR '"' + + +/** + * @brief An abstract class that support reading definitions from a file. + */ +template +class FileReader +{ +public: + + /** + * @brief Constructs a new instance. + */ + FileReader(bool supportsDefaults) + : m_supportsDefaults(supportsDefaults) {} + + /** + * @brief Destructor. + */ + virtual ~FileReader() {} + + /** + * @brief Reads the definitions from a file. + * @param filename the name (and path) of the file to read. + * @return @a RESULT_OK on success, or an error code. + */ + virtual result_t readFromFile(const string filename, T arg=NULL) + { + ifstream ifs; + ifs.open(filename.c_str(), ifstream::in); + if (ifs.is_open() == false) + return RESULT_ERR_NOTFOUND; + + string line; + unsigned int lineNo = 0; + vector row; + string token; + vector< vector > defaults; + while (getline(ifs, line) != 0) { + lineNo++; + // skip empty lines and comments + size_t length = line.length(); + if (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/')) + continue; + + row.clear(); + bool quotedText = false; + ostringstream field; + char prev = FIELD_SEPARATOR; + for (size_t pos = 0; pos < length; pos++) { + char ch = line[pos]; + switch (ch) + { + case FIELD_SEPARATOR: + if (quotedText == true) + field << ch; + else { + row.push_back(field.str()); + field.str(""); + } + break; + case TEXT_SEPARATOR: + if (quotedText == true) { + quotedText = false; + } + else if (prev == TEXT_SEPARATOR) { // double dquote + quotedText = true; + field << ch; + } + else if (prev == FIELD_SEPARATOR) { + quotedText = true; + } + else + field << ch; + break; + case '\r': + break; + default: + field << ch; + break; + } + prev = ch; + } + row.push_back(field.str()); + + result_t result; + if (m_supportsDefaults == true) { + if (line[0] == '*') { + row[0] = row[0].substr(1); + defaults.push_back(row); + continue; + } + result = addFromFile(row, arg, &defaults, filename, lineNo); + } + else + result = addFromFile(row, arg, NULL, filename, lineNo); + + if (result != RESULT_OK) { + cerr << "error reading \"" << filename << "\" line " << static_cast(lineNo) << ": " << getResultCode(result) << endl; + ifs.close(); + return result; + } + } + + ifs.close(); + return RESULT_OK; + } + + /** + * @brief Adds a definition that was read from a file. + * @param row the definition row read from the file. + * @param defaults all previously read default rows (initial star char removed), or NULL if not supported. + * @return @a RESULT_OK on success, or an error code. + */ + virtual result_t addFromFile(vector& row, T arg, vector< vector >* defaults, const string& filename, unsigned int lineNo) = 0; + +private: + + /** whether this instance supports rows with defaults (starting with a star). */ + bool m_supportsDefaults; + +}; + +#endif // LIBEBUS_FILEREADER_H_ diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index 27dfa633..01d421e9 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -369,7 +369,7 @@ result_t MessageMap::add(Message* message) return RESULT_OK; } -result_t MessageMap::addFromFile(vector& row, DataFieldTemplates* arg, vector< vector >* defaults) +result_t MessageMap::addFromFile(vector& row, DataFieldTemplates* arg, vector< vector >* defaults, const string& filename, unsigned int lineNo) { Message* message = NULL; string types = row[0]; @@ -384,8 +384,8 @@ result_t MessageMap::addFromFile(vector& row, DataFieldTemplates* arg, v vector::iterator it = row.begin(); result = Message::create(it, row.end(), defaults, arg, message); if (result != RESULT_OK) { - printErrorPos(row.begin(), row.end(), it); - return result; + printErrorPos(row.begin(), row.end(), it, filename, lineNo, result); + continue; } result = add(message); if (result != RESULT_OK) { diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index 9dea47d9..27430019 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -264,7 +264,7 @@ public: */ result_t add(Message* message); // @copydoc - virtual result_t addFromFile(vector& row, DataFieldTemplates* arg, vector< vector >* defaults); + virtual result_t addFromFile(vector& row, DataFieldTemplates* arg, vector< vector >* defaults, const string& filename, unsigned int lineNo); /** * @brief Find the @a Message instance for the specified class and name. * @param class the optional device class. diff --git a/src/lib/ebus/test/test_message.cpp b/src/lib/ebus/test/test_message.cpp index 8e79957d..eac50086 100644 --- a/src/lib/ebus/test/test_message.cpp +++ b/src/lib/ebus/test/test_message.cpp @@ -113,7 +113,7 @@ int main() if (result != RESULT_OK) { cout << "\"" << check[0] << "\": create error: " << getResultCode(result) << endl; - printErrorPos(entries.begin(), entries.end(), it); + printErrorPos(entries.begin(), entries.end(), it, "", 0, result); continue; } if (deleteMessage == NULL) { From 169c6a946086a06fcec9104404986183e9bd4557 Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 12:01:14 +0100 Subject: [PATCH 3/7] switched to read/write instead of get/set and added force option to read (automatically picks up updated value if available), nicer response messages for BaseLoop, renamed area cyc to upd --- src/ebusd/baseloop.cpp | 212 +++++++++++++++++++-------------------- src/ebusd/baseloop.h | 12 +-- src/ebusd/ebusd.cpp | 2 +- src/lib/utils/logger.cpp | 2 +- src/lib/utils/logger.h | 2 +- 5 files changed, 114 insertions(+), 116 deletions(-) diff --git a/src/ebusd/baseloop.cpp b/src/ebusd/baseloop.cpp index 21ccf129..375230fb 100644 --- a/src/ebusd/baseloop.cpp +++ b/src/ebusd/baseloop.cpp @@ -195,35 +195,57 @@ void BaseLoop::logRaw(const unsigned char byte, bool received) { string BaseLoop::decodeMessage(const string& data) { ostringstream result; - string cycdata, polldata; // prepare data string token; istringstream stream(data); - vector cmd; - Message* message; + vector args; while (getline(stream, token, ' ') != 0) - cmd.push_back(token); + args.push_back(token); - if (cmd.size() == 0) + if (args.size() == 0) return "command missing"; - switch (getCase(cmd[0])) { + size_t argPos = 1; + bool force = false; + + switch (getCase(args[0])) { case ct_invalid: result << "command not found"; break; - case ct_get: - if (cmd.size() < 2 || cmd.size() > 4) { - result << "usage: 'get [class] cmd' or 'get class cmd sub'"; + case ct_read: { + if (args.size() > argPos && args[argPos] == "-f") { + force = true; + argPos++; + } + if (args.size() < argPos + 1 || args.size() > argPos + 3) { + result << "usage: 'read [-f] [class] cmd' or 'read [-f] class cmd sub'"; break; } - if (cmd.size() == 2) - message = m_messages->find("", cmd[1], false); + Message* updateMessage = NULL; + if (force == 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 (token.empty() == false) { + result << token; + break; + } // else try to read directly from bus + } + } + + Message* message; + if (args.size() == argPos + 1) + message = m_messages->find("", args[argPos], false); else - message = m_messages->find(cmd[1], cmd[2], false); + message = m_messages->find(args[argPos], args[argPos + 1], false); if (message != NULL) { @@ -232,10 +254,8 @@ string BaseLoop::decodeMessage(const string& data) token = message->getLastValue(); if (token.empty() == false) { result << token; - } else { - result << "no data stored"; - } - break; + break; + } // else: read directly from bus } SymbolString master; @@ -261,23 +281,24 @@ string BaseLoop::decodeMessage(const string& data) result << getResultCode(ret); } + } else if (updateMessage != NULL) { + result << "no data stored"; } else { - result << "get command not found"; + result << "message not defined"; } break; - - case ct_set: - if (cmd.size() != 4) { - result << "usage: 'set class cmd value'"; + } + case ct_write: { + if (args.size() != argPos + 3) { + result << "usage: 'write class cmd value[;value]*'"; break; } - message = m_messages->find(cmd[1], cmd[2], true); + Message* message = m_messages->find(args[argPos], args[argPos + 1], true); if (message != NULL) { - SymbolString master; - istringstream input(cmd[3]); + istringstream input(args[argPos + 2]); result_t ret = message->prepareMaster(m_ownAddress, master, input); if (ret != RESULT_OK) { L.log(bas, error, " prepare write: %s", getResultCode(ret)); @@ -305,71 +326,50 @@ string BaseLoop::decodeMessage(const string& data) } } else { - result << "set command not found"; + result << "message not defined"; } - break; - - case ct_cyc: - if (cmd.size() < 2 || cmd.size() > 3) { - result << "usage: 'cyc [class] cmd'"; - break; - } - - if (cmd.size() == 2) - message = m_messages->find("", cmd[1], false, true); - else - message = m_messages->find(cmd[1], cmd[2], false, true); - - if (message != NULL) { - token = message->getLastValue(); - if (token.empty() == false) { - result << token; - } else { - result << "no data stored"; - } - } else { - result << "cyc command not found"; - } - - break; - - case ct_hex: - if (cmd.size() != 2) { + } + case ct_hex: { + if (args.size() < argPos + 1) { result << "usage: 'hex value' (value: ZZPBSBNNDx)"; break; } - { - cmd[1].erase(remove_if(cmd[1].begin(), cmd[1].end(), ::isspace), cmd[1].end()); - string src; - ostringstream msg; - msg << hex << setw(2) << setfill('0') << static_cast(m_ownAddress); - msg << cmd[1]; - SymbolString master(msg.str()); - L.log(bas, event, " hex msg: %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(); + 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; } - if (ret != RESULT_OK) { - L.log(bas, error, " hex: %s", getResultCode(ret)); - result << getResultCode(ret); - } - + msg << args[argPos++]; } + if (msg.str().length() == 0) + break; + SymbolString master(msg.str()); + L.log(bas, event, " hex msg: %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 (cmd.size() == 1) { + } + case ct_scan: { + if (args.size() == argPos) { result_t ret = m_busHandler->startScan(); if (ret != RESULT_OK) { L.log(bas, error, " scan: %s", getResultCode(ret)); @@ -380,7 +380,7 @@ string BaseLoop::decodeMessage(const string& data) break; } - if (strcasecmp(cmd[1].c_str(), "FULL") == 0) { + if (strcasecmp(args[argPos].c_str(), "FULL") == 0) { result_t ret = m_busHandler->startScan(true); if (ret != RESULT_OK) { L.log(bas, error, " full scan: %s", getResultCode(ret)); @@ -391,7 +391,7 @@ string BaseLoop::decodeMessage(const string& data) break; } - if (strcasecmp(cmd[1].c_str(), "RESULT") == 0) { + if (strcasecmp(args[argPos].c_str(), "RESULT") == 0) { m_busHandler->formatScanResult(result); break; } @@ -400,52 +400,53 @@ string BaseLoop::decodeMessage(const string& data) << " 'scan full'" << endl << " 'scan result'"; break; - - case ct_log: - if (cmd.size() != 3 ) { - result << "usage: 'log areas area,area,..' (areas: bas|net|bus|cyc|all)" << endl + } + case ct_log: { + if (args.size() != 3 ) { + result << "usage: 'log areas area,area,..' (areas: bas|net|bus|upd|all)" << endl << " 'log level level' (level: error|event|trace|debug)"; break; } // TODO: check for possible areas and level - if (strcasecmp(cmd[1].c_str(), "AREAS") == 0) { - L.getSink(0)->setAreas(calcAreas(cmd[2])); + if (strcasecmp(args[argPos].c_str(), "AREAS") == 0) { + L.getSink(0)->setAreas(calcAreas(args[argPos + 1])); result << "done"; break; } - if (strcasecmp(cmd[1].c_str(), "LEVEL") == 0) { - L.getSink(0)->setLevel(calcLevel(cmd[2])); + if (strcasecmp(args[argPos].c_str(), "LEVEL") == 0) { + L.getSink(0)->setLevel(calcLevel(args[argPos + 1])); result << "done"; break; } - result << "usage: 'log areas area,area,..' (areas: bas|net|bus|cyc|all)" << endl + result << "usage: 'log areas area,area,..' (areas: bas|net|bus|upd|all)" << endl << " 'log level level' (level: error|event|trace|debug)"; - break; - - case ct_raw: - if (cmd.size() != 1) { + } + case ct_raw: { + if (args.size() != 1) { result << "usage: 'raw'"; break; } - m_port->setLogRaw(!m_port->getLogRaw()); - result << "done"; + bool enabled = !m_port->getLogRaw(); + m_port->setLogRaw(enabled); + result << (enabled ? "raw output enabled" : "raw output disabled"); break; - - case ct_dump: - if (cmd.size() != 1) { + } + case ct_dump: { + if (args.size() != 1) { result << "usage: 'dump'"; break; } - m_port->setDumpRaw(!m_port->getDumpRaw()); - result << "done"; + bool enabled = !m_port->getDumpRaw(); + m_port->setDumpRaw(enabled); + result << (enabled ? "dump enabled" : "dump disabled"); break; - + } /*case ct_reload: if (cmd.size() != 1) { result << "usage: 'reload'"; @@ -470,14 +471,13 @@ string BaseLoop::decodeMessage(const string& data) case ct_help: result << "commands:" << endl - << " get - fetch ebus data 'get [class] cmd (sub)'" << endl - << " set - set ebus values 'set class cmd value'" << endl - << " cyc - fetch cycle data 'cyc [class] cmd (sub)'" << endl + << " read - read ebus values 'read [-f] [class] cmd [sub]'" << 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 << " - scan ebus all addresses 'scan full'" << endl << " - show results 'scan result'" << endl << endl - << " log - change log areas 'log areas area,area,..' (areas: bas|net|bus|cyc|all)" << 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 << " dump - toggle dump state 'dump'" << endl << endl diff --git a/src/ebusd/baseloop.h b/src/ebusd/baseloop.h index 79343201..9a8cacba 100644 --- a/src/ebusd/baseloop.h +++ b/src/ebusd/baseloop.h @@ -30,10 +30,9 @@ using namespace std; /** possible client commands */ enum CommandType { - ct_get, /*!< get ebus data */ - ct_set, /*!< set ebus value */ - ct_cyc, /*!< fetch cycle data */ - ct_hex, /*!< send hex value */ + 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 */ @@ -118,9 +117,8 @@ private: */ CommandType getCase(const string& item) { - if (strcasecmp(item.c_str(), "GET") == 0) return ct_get; - if (strcasecmp(item.c_str(), "SET") == 0) return ct_set; - if (strcasecmp(item.c_str(), "CYC") == 0) return ct_cyc; + 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; diff --git a/src/ebusd/ebusd.cpp b/src/ebusd/ebusd.cpp index 61749241..0fed09f6 100644 --- a/src/ebusd/ebusd.cpp +++ b/src/ebusd/ebusd.cpp @@ -89,7 +89,7 @@ void define_args() "\tlog file name (/var/log/ebusd.log)"); A.addOption("logareas", "", OptVal("all"), dt_string, ot_mandatory, - "\tlog areas - bas|net|bus|cyc|all (all)"); + "\tlog areas - bas|net|bus|upd|all (all)"); A.addOption("loglevel", "", OptVal("trace"), dt_string, ot_mandatory, "\tlog level - error|event|trace|debug (event)"); diff --git a/src/lib/utils/logger.cpp b/src/lib/utils/logger.cpp index 04442631..9262bcc0 100644 --- a/src/lib/utils/logger.cpp +++ b/src/lib/utils/logger.cpp @@ -31,7 +31,7 @@ using namespace std; /** static char array with logging area names */ -static const char* AreaNames[Size_of_Areas] = { "bas", "net", "bus", "cyc" }; +static const char* AreaNames[Size_of_Areas] = { "bas", "net", "bus", "upd" }; /** static char array with logging level names */ static const char* LevelNames[Size_of_Level] = { "error", "event", "trace", "debug" }; diff --git a/src/lib/utils/logger.h b/src/lib/utils/logger.h index daf2d75f..e1d07795 100644 --- a/src/lib/utils/logger.h +++ b/src/lib/utils/logger.h @@ -37,7 +37,7 @@ enum AreasType { bas=1, /*!< basis */ net=2, /*!< network */ bus=4, /*!< ebus */ - cyc=8, /*!< cycle */ + upd=8, /*!< updates found while listening to the bus */ all=15, /*!< type for all subsystems */ Size_of_Areas=4 /*!< number of possible areas */ }; From 45c739228c540d67da1fcba6dc10462253bc13a5 Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 12:03:12 +0100 Subject: [PATCH 4/7] corrected log area for update messages --- src/ebusd/bushandler.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index dd62ff66..a8e67bec 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -607,12 +607,12 @@ void BusHandler::receiveCompleted() m_seenAddresses[m_command[0]] = true; if (dstAddress == BROADCAST) - L.log(bus, trace, "received BC %s", m_command.getDataStr().c_str()); + L.log(upd, trace, "received BC %s", m_command.getDataStr().c_str()); else if (master == true) { - L.log(bus, trace, "received MM %s", m_command.getDataStr().c_str()); + L.log(upd, trace, "received MM %s", m_command.getDataStr().c_str()); m_seenAddresses[dstAddress] = true; } else { - L.log(bus, trace, "received MS %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); + L.log(upd, trace, "received MS %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); m_seenAddresses[dstAddress] = true; } @@ -625,10 +625,10 @@ void BusHandler::receiveCompleted() if (result == RESULT_OK && dstAddress != BROADCAST && master == false) result = message->decode(pt_slaveData, m_response, output, output.str().empty() == false); if (result != RESULT_OK) - L.log(bus, error, "unable to parse %s %s from %s / %s: %s", clazz.c_str(), name.c_str(), m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result)); + L.log(upd, error, "unable to parse %s %s from %s / %s: %s", clazz.c_str(), name.c_str(), m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result)); else { string data = output.str(); - L.log(bus, event, "%s %s: %s", clazz.c_str(), name.c_str(), data.c_str()); + L.log(upd, event, "%s %s: %s", clazz.c_str(), name.c_str(), data.c_str()); } } } From 5d2b28f3db3f46c84719a850957b846129dfbe44 Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 14:42:47 +0100 Subject: [PATCH 5/7] fixed ostringstream formatting (again) --- src/lib/ebus/data.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index b18916a3..8cfcc3e8 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -482,19 +482,6 @@ result_t StringDataField::readSymbols(SymbolString& input, incr = -1; } - switch (m_dataType.type) // initialize output - { - case bt_hexstr: - output << setw(2) << hex << setfill('0'); - break; - case bt_dat: - case bt_tim: - output << setw(2) << dec << setfill('0'); - break; - default: - output << setw(0) << dec; - } - for (size_t offset = start, i = 0; i < count; offset += incr, i++) { if (m_length == 4 && i == 2 && m_dataType.type == bt_dat) continue; // skip weekday in between @@ -509,7 +496,7 @@ result_t StringDataField::readSymbols(SymbolString& input, case bt_hexstr: if (i > 0) output << ' '; - output << static_cast(ch); + output << setw(2) << hex << setfill('0') << static_cast(ch); break; case bt_dat: if (i + 1 == m_length) @@ -517,7 +504,7 @@ result_t StringDataField::readSymbols(SymbolString& input, else if (ch < 1 || (i == 0 && ch > 31) || (i == 1 && ch > 12)) return RESULT_ERR_OUT_OF_RANGE; // invalid date else - output << static_cast(ch) << "."; + output << setw(2) << dec << setfill('0') << static_cast(ch) << "."; break; case bt_tim: if (m_dataType.replacement != 0 && ch == m_dataType.replacement) { @@ -543,12 +530,12 @@ result_t StringDataField::readSymbols(SymbolString& input, return RESULT_ERR_OUT_OF_RANGE; // invalid time if (i > 0) output << ":"; - output << static_cast(ch); + output << setw(2) << dec << setfill('0') << static_cast(ch); break; default: if (ch < 0x20) ch = m_dataType.replacement; - output << static_cast(ch); + output << setw(0) << dec << static_cast(ch); break; } last = ch; From e4f9306ddecbff1ad691512c19c1873744bb1b8b Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 14:55:52 +0100 Subject: [PATCH 6/7] unified logging --- src/ebusd/baseloop.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ebusd/baseloop.cpp b/src/ebusd/baseloop.cpp index 375230fb..2dd15159 100644 --- a/src/ebusd/baseloop.cpp +++ b/src/ebusd/baseloop.cpp @@ -262,11 +262,11 @@ string BaseLoop::decodeMessage(const string& data) istringstream input; result_t ret = message->prepareMaster(m_ownAddress, master, input); if (ret != RESULT_OK) { - L.log(bas, error, " prepare read: %s", getResultCode(ret)); + L.log(bas, error, "prepare read: %s", getResultCode(ret)); result << getResultCode(ret); break; } - L.log(bas, event, " read msg: %s", master.getDataStr().c_str()); + L.log(bas, event, "read cmd: %s", master.getDataStr().c_str()); // send message SymbolString slave; @@ -277,7 +277,7 @@ string BaseLoop::decodeMessage(const string& data) ret = message->decode(pt_slaveData, slave, result); // decode data } if (ret != RESULT_OK) { - L.log(bas, error, " read: %s", getResultCode(ret)); + L.log(bas, error, "read: %s", getResultCode(ret)); result << getResultCode(ret); } @@ -301,11 +301,11 @@ string BaseLoop::decodeMessage(const string& data) istringstream input(args[argPos + 2]); result_t ret = message->prepareMaster(m_ownAddress, master, input); if (ret != RESULT_OK) { - L.log(bas, error, " prepare write: %s", getResultCode(ret)); + L.log(bas, error, "prepare write: %s", getResultCode(ret)); result << getResultCode(ret); break; } - L.log(bas, event, " write msg: %s", master.getDataStr().c_str()); + L.log(bas, event, "write cmd: %s", master.getDataStr().c_str()); // send message SymbolString slave; @@ -321,7 +321,7 @@ string BaseLoop::decodeMessage(const string& data) } } if (ret != RESULT_OK) { - L.log(bas, error, " write: %s", getResultCode(ret)); + L.log(bas, error, "write: %s", getResultCode(ret)); result << getResultCode(ret); } @@ -350,7 +350,7 @@ string BaseLoop::decodeMessage(const string& data) break; SymbolString master(msg.str()); - L.log(bas, event, " hex msg: %s", master.getDataStr().c_str()); + L.log(bas, event, "hex cmd: %s", master.getDataStr().c_str()); // send message SymbolString slave; @@ -363,7 +363,7 @@ string BaseLoop::decodeMessage(const string& data) result << slave.getDataStr(); } if (ret != RESULT_OK) { - L.log(bas, error, " hex: %s", getResultCode(ret)); + L.log(bas, error, "hex: %s", getResultCode(ret)); result << getResultCode(ret); } break; @@ -372,7 +372,7 @@ string BaseLoop::decodeMessage(const string& data) if (args.size() == argPos) { result_t ret = m_busHandler->startScan(); if (ret != RESULT_OK) { - L.log(bas, error, " scan: %s", getResultCode(ret)); + L.log(bas, error, "scan: %s", getResultCode(ret)); result << getResultCode(ret); } else @@ -383,7 +383,7 @@ string BaseLoop::decodeMessage(const string& data) if (strcasecmp(args[argPos].c_str(), "FULL") == 0) { result_t ret = m_busHandler->startScan(true); if (ret != RESULT_OK) { - L.log(bas, error, " full scan: %s", getResultCode(ret)); + L.log(bas, error, "full scan: %s", getResultCode(ret)); result << getResultCode(ret); } else From 1f116aada7be1ec8286245377476405b14e8b3e0 Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 14:56:19 +0100 Subject: [PATCH 7/7] unified logging --- src/ebusd/bushandler.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index a8e67bec..c583b576 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 msg: %s", m_master.getDataStr().c_str()); + L.log(bus, event, "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 msg: %s", m_master.getDataStr().c_str()); + L.log(bus, event, "scan cmd: %s", m_master.getDataStr().c_str()); return result; } @@ -96,8 +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, error, "scan %x failed: %s", m_master[1], getResultCode(result)); + if (result == RESULT_OK) + L.log(bus, event, "scan result: %s", m_scanResult.str().c_str()); + else + L.log(bus, error, "scan %2.2x failed: %s", m_master[1], getResultCode(result)); } @@ -138,6 +140,9 @@ 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()); + pthread_mutex_lock(&m_mutex); m_result = result; @@ -163,7 +168,7 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) if (result == RESULT_OK) break; - L.log(bus, error, " %s, %s", getResultCode(result), sendRetries>0 ? "retry send" : "give up"); + L.log(bus, error, "%s, %s", getResultCode(result), sendRetries>0 ? "retry send" : "give up"); request->m_busLostRetries = 0; } @@ -218,7 +223,7 @@ result_t BusHandler::handleSymbol() PollRequest* request = new PollRequest(m_response, message); result_t ret = request->prepare(m_ownMasterAddress); if (ret != RESULT_OK) { - L.log(bus, error, " prepare poll message: %s", getResultCode(ret)); + L.log(bus, error, "prepare poll message: %s", getResultCode(ret)); delete request; } else { @@ -557,7 +562,7 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit { if (m_request != NULL) { if (result == RESULT_ERR_BUS_LOST && m_request->m_busLostRetries < m_busLostRetries) { - L.log(bus, error, " %s, retry", getResultCode(result)); + L.log(bus, error, "%s, retry", getResultCode(result)); m_request->m_busLostRetries++; m_requests.add(m_request); // repeat m_request = NULL; @@ -571,7 +576,6 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit if (m_request->m_deleteOnFinish == true) { if (result == RESULT_OK && typeid(*m_request) == typeid(ScanRequest)) { string res = ((ScanRequest*)m_request)->m_scanResult.str(); - L.log(bus, debug, " scan result %x: %s", dstAddress, res.c_str()); m_scanResults[dstAddress] = res; } delete m_request; @@ -584,9 +588,9 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit return result; if (result < RESULT_OK || (result != RESULT_OK && state == bs_skip)) - L.log(bus, debug, " %s during %s, switching to %s", getResultCode(result), getStateCode(m_state), getStateCode(state)); + L.log(bus, debug, "%s during %s, switching to %s", getResultCode(result), getStateCode(m_state), getStateCode(state)); else if (m_request != NULL || state == bs_sendCmd || state==bs_sendResAck || state==bs_sendSyn) - L.log(bus, debug, " switching from %s to %s", getStateCode(m_state), getStateCode(state)); + L.log(bus, debug, "switching from %s to %s", getStateCode(m_state), getStateCode(state)); m_state = state; if (state == bs_ready || state == bs_skip) { @@ -607,12 +611,12 @@ void BusHandler::receiveCompleted() m_seenAddresses[m_command[0]] = true; if (dstAddress == BROADCAST) - L.log(upd, trace, "received BC %s", m_command.getDataStr().c_str()); + L.log(upd, trace, "update BC cmd: %s", m_command.getDataStr().c_str()); else if (master == true) { - L.log(upd, trace, "received MM %s", m_command.getDataStr().c_str()); + L.log(upd, trace, "update MM cmd: %s", m_command.getDataStr().c_str()); m_seenAddresses[dstAddress] = true; } else { - L.log(upd, trace, "received MS %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); + L.log(upd, trace, "update MS cmd: %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); m_seenAddresses[dstAddress] = true; } @@ -628,7 +632,7 @@ void BusHandler::receiveCompleted() L.log(upd, error, "unable to parse %s %s from %s / %s: %s", clazz.c_str(), name.c_str(), m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result)); else { string data = output.str(); - L.log(upd, event, "%s %s: %s", clazz.c_str(), name.c_str(), data.c_str()); + L.log(upd, event, "update %s %s: %s", clazz.c_str(), name.c_str(), data.c_str()); } } }