From d5ab17dc2e7782ca58b29c4d42bfc8daf7240efe Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 19 Feb 2017 11:38:03 +0100 Subject: [PATCH] added decode option to grab command --- src/ebusd/bushandler.cpp | 100 +++++++++++++++++++++++++++++++++++++-- src/ebusd/bushandler.h | 6 ++- src/ebusd/mainloop.cpp | 9 +++- 3 files changed, 108 insertions(+), 7 deletions(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 269044bc..534cba5d 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -192,7 +192,64 @@ void GrabbedMessage::setLastData(SymbolString& master, SymbolString& slave) { m_count++; } -bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first, ostringstream& output) { +/** + * Decode the input @a SymbolString with the specified @a DataType and length. + * @param type the @a DataType. + * @param input the unescaped @a SymbolString to read the binary value from. + * @param isMaster whether the @a SymbolString is the master part. + * @param baseOffset the base offset in the @a SymbolString. + * @param length the number of symbols to read. + * @param offsets the last offset to the baseOffset to read. + * @param output the ostringstream to append the formatted value to. + * @param firstOnly whether to read only the first non-erroneous offset. + * @return @a RESULT_OK on success, or an error code. + */ +bool decodeType(DataType* type, SymbolString *input, bool isMaster, unsigned char baseOffset, unsigned char length, + unsigned char offsets, ostringstream& output, bool firstOnly = false) { + bool first = true; + string in = input->getDataStr(true, true, baseOffset); + for (unsigned char offset = 0; offset <= offsets; offset++) { + ostringstream out; + result_t result = type->readSymbols(*input, isMaster, (unsigned char)(baseOffset+offset), (unsigned char)length, + out, 0); + if (result != RESULT_OK) { + continue; + } + if (type->isNumeric() && type->hasFlag(DAY)) { + unsigned int value = 0; + if (type->readRawValue(*input, (unsigned char)(baseOffset+offset), (unsigned char)length, value) == RESULT_OK) { + out.str(""); + out << DataField::getDayName(reinterpret_cast(type)->getMinValue()+value); + } + } + if (first) { + first = false; + output << endl << " "; + ostringstream::pos_type cnt = output.tellp(); + type->dump(output, length, false); + cnt = output.tellp() - cnt; + while (cnt < 5) { + output << " "; + cnt += 1; + } + } else { + output << ","; + } + output << " " << in.substr(offset*2, length*2); + if (type->isNumeric()) { + output << "=" << out.str(); + } else { + output << "=\"" << out.str() << "\""; + } + if (firstOnly) { + return true; // only the first offset with maximum length when adjustable maximum size is at least 8 bytes + } + } + return !first; +} + +bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first, ostringstream& output, + const bool decode) { Message* message = messages->find(m_lastMaster); if (unknown && message) { return false; @@ -209,6 +266,43 @@ bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first, if (message) { output << ": " << message->getCircuit() << " " << message->getName(); } + if (decode) { + DataTypeList *types = DataTypeList::getInstance(); + if (!types) { + return true; + } + bool master = isMaster(dstAddress) || dstAddress == BROADCAST || m_lastSlave.size() <= 1 || m_lastSlave[0] == 0; + SymbolString *input = master ? &m_lastMaster : &m_lastSlave; + unsigned char baseOffset = master ? 5 : 1; + unsigned char remain = input->size(); + if (remain <= baseOffset+1) { // excluding CRC + return true; + } + remain = (unsigned char)(remain-baseOffset-1); + for (map::const_iterator it = types->begin(); it != types->end(); it++) { + DataType* baseType = it->second; + if ((baseType->getBitCount() % 8) != 0 || baseType->isIgnored()) { // skip bit and ignored types + continue; + } + unsigned char maxLength = baseType->getBitCount()/8; + bool firstOnly = maxLength >= 8; + if (maxLength > remain) { + maxLength = remain; + } + if (baseType->isAdjustableLength()) { + for (unsigned char length = maxLength; length >= 1; length--) { + DataType* type = types->get(baseType->getId(), length); + if (decodeType(type, input, master, baseOffset, length, (unsigned char)(remain-length), output, firstOnly)) { + if (firstOnly) { + break; // only a single offset with maximum length when adjustable maximum size is at least 8 bytes + } + } + } + } else if (maxLength > 0) { + decodeType(baseType, input, master, baseOffset, maxLength, (unsigned char)(remain-maxLength), output); + } + } + } return true; } @@ -1112,14 +1206,14 @@ bool BusHandler::enableGrab(bool enable) { return true; } -void BusHandler::formatGrabResult(const bool unknown, ostringstream& output) { +void BusHandler::formatGrabResult(const bool unknown, ostringstream& output, const bool decode) { if (!m_grabMessages) { output << "grab disabled"; } else { bool first = true; for (map::iterator it = m_grabbedMessages.begin(); it != m_grabbedMessages.end(); it++) { - if (it->second.dump(unknown, m_messages, first, output)) { + if (it->second.dump(unknown, m_messages, first, output, decode)) { first = false; } } diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index ae80f77b..d20cd154 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -309,9 +309,10 @@ class GrabbedMessage { * @param messages the @a MessageMap instance for resolving known @a Message instances. * @param first whether this is the first message to be added to the output. * @param output the @a ostringstream to format the messages to. + * @param decode whether to add decoding hints. * @return whether the message was added to the output. */ - bool dump(const bool unknown, MessageMap* messages, bool first, ostringstream& output); + bool dump(const bool unknown, MessageMap* messages, bool first, ostringstream& output, const bool decode = false); private: @@ -468,8 +469,9 @@ class BusHandler : public WaitThread { * Format the grabbed messages to the @a ostringstream. * @param unknown whether to dump only unknown messages. * @param output the @a ostringstream to format the messages to. + * @param decode whether to add decoding hints. */ - void formatGrabResult(const bool unknown, ostringstream& output); + void formatGrabResult(const bool unknown, ostringstream& output, const bool decode = false); /** * Return true when a signal on the bus is available. diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index 5b1e8fcc..0ae4b576 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -1230,10 +1230,15 @@ string MainLoop::executeGrab(vector &args) { m_busHandler->formatGrabResult(args.size() == 2, result); return result.str(); } + if (args.size() == 3 || strcasecmp(args[2].c_str(), "decode") == 0) { // TODO remove strcasecmp + ostringstream result; + m_busHandler->formatGrabResult(true, result, true); + return result.str(); + } } return "usage: grab [stop]\n" - " or: grab result [all]\n" - " Start or stop grabbing, or report unknown or all grabbed messages."; + " or: grab result [all|decode]\n" + " Start or stop grabbing, or report/decode unknown or all grabbed messages."; } string MainLoop::executeScan(vector &args, string levels) {