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)