diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index 4b15a433..9b69c8f3 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -27,6 +27,22 @@ using namespace std; +/** the known column names (pairs of full length name and short length name). */ +static const char* columnNames[] = { + "type", "t", + "circuit", "c", + "name", "n", + "comment", "co", + "qq", "q", + "zz", "z", + "pbsb", "p", + "id", "i", + "fields", "f", +}; + +/** the number of known column names. */ +static const size_t columnCount = sizeof(columnNames) / sizeof(char*); + MainLoop::MainLoop(const struct options opt, Device *device, DataFieldTemplates* templates, MessageMap* messages) : m_device(device), m_templates(templates), m_messages(messages), m_address(opt.address) { @@ -542,6 +558,7 @@ string MainLoop::executeFind(vector &args) { size_t argPos = 1; bool verbose = false, configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true, onlyWithData = false; + vector columns; string circuit; short pb = -1; while (args.size() > argPos && args[argPos][0] == '-') { @@ -549,7 +566,33 @@ string MainLoop::executeFind(vector &args) verbose = true; else if (args[argPos] == "-f") configFormat = true; - else if (args[argPos] == "-e") + else if (args[argPos] == "-F") { + argPos++; + if (argPos >= args.size()) { + argPos = 0; // print usage + break; + } + istringstream input(args[argPos]); + string column; + while (getline(input, column, ',') != 0) { + size_t idx = columnCount; + for (size_t i = 0; i < columnCount; i++) { + if (strcasecmp(columnNames[i], column.c_str()) == 0) { + idx = i; + break; + } + } + if (idx==columnCount) { + argPos = 0; // print usage + break; + } + columns.push_back(idx/2); + } + if (columns.empty()) { + argPos = 0; // print usage + break; + } + } else if (args[argPos] == "-e") exact = true; else if (args[argPos] == "-r") { if (first) { @@ -605,18 +648,20 @@ string MainLoop::executeFind(vector &args) argPos++; } if (argPos == 0 || args.size() < argPos || args.size() > argPos + 1) - return "usage: find [-v] [-r] [-w] [-p] [-d] [-i PB] [-f] [-e] [-c CIRCUIT] [NAME]\n" + return "usage: find [-v] [-r] [-w] [-p] [-d] [-i PB] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n" " Find message(s).\n" - " -v be verbose (append destination address and update time)\n" - " -r limit to active read messages (default: read + passive)\n" - " -w limit to active write messages (default: read + passive)\n" - " -p limit to passive messages (default: read + passive)\n" - " -d only include messages with actual data\n" - " -i PB limit to messages with primary command byte PB ('0xPB' for hex)\n" - " -f list messages in CSV configuration file format\n" - " -e match NAME and optional CIRCUIT exactly (ignoring case)\n" - " -c CIRCUIT limit to messages of CIRCUIT (or a part thereof without '-e')\n" - " NAME the NAME of the messages to find (or a part thereof without '-e')"; + " -v be verbose (append destination address and update time)\n" + " -r limit to active read messages (default: read + passive)\n" + " -w limit to active write messages (default: read + passive)\n" + " -p limit to passive messages (default: read + passive)\n" + " -d only include messages with actual data\n" + " -i PB limit to messages with primary command byte PB ('0xPB' for hex)\n" + " -f list messages in CSV configuration file format\n" + " -F COL[,COL]* list messages in the specified format\n" + " (COL: type,circuit,name,comment,qq,zz,pbsb,id,fields)\n" + " -e match NAME and optional CIRCUIT exactly (ignoring case)\n" + " -c CIRCUIT limit to messages of CIRCUIT (or a part thereof without '-e')\n" + " NAME the NAME of the messages to find (or a part thereof without '-e')"; deque messages; if (args.size() == argPos) @@ -636,6 +681,10 @@ string MainLoop::executeFind(vector &args) if (found) result << endl; message->dump(result); + } else if (!columns.empty()) { + if (found) + result << endl; + message->dump(result, columns); } else { unsigned char dstAddress = message->getDstAddress(); if (dstAddress == SYN) @@ -869,7 +918,7 @@ string MainLoop::executeHelp() " Read hex message: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n" " write|w Write value(s): write [-c] CIRCUIT NAME [VALUE[;VALUE]*]\n" " Write hex message: write -h ZZPBSBNNDx\n" - " find|f Find message(s): find [-v] [-r] [-w] [-p] [-d] [-i PB] [-f] [-c CIRCUIT] [NAME]\n" + " find|f Find message(s): find [-v] [-r] [-w] [-p] [-d] [-i PB] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n" " listen|l Listen for updates: listen [stop]\n" " state|s Report bus state\n" " grab|g Grab unknown messages: grab [stop]\n" diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index 6580b581..9a226cdf 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -508,6 +508,67 @@ void Message::dump(ostream& output) m_data->dump(output); } +void Message::dump(ostream& output, vector& columns) +{ + bool first = true; + unsigned int cnt = 0; + for (vector::const_iterator it = columns.begin(); it < columns.end(); it++) { + if (first) { + first = false; + } else { + output << FIELD_SEPARATOR; + } + size_t column = *it; + switch (column) { + case 0: // type + if (m_isPassive) { + output << "u"; + if (m_isWrite) + output << "w"; + } else if (m_isWrite) + output << "w"; + else { + output << "r"; + if (m_pollPriority>0) + output << static_cast(m_pollPriority); + } + break; + case 1: // circuit + DataField::dumpString(output, m_circuit, false); + break; + case 2: // name + DataField::dumpString(output, m_name, false); + break; + case 3: // comment + DataField::dumpString(output, m_comment, false); + break; + case 4: // QQ + if (m_srcAddress != SYN) + output << hex << setw(2) << setfill('0') << static_cast(m_srcAddress); + break; + case 5: // ZZ + if (m_dstAddress != SYN) + output << hex << setw(2) << setfill('0') << static_cast(m_dstAddress); + break; + case 6: // PBSB + case 7: // ID + for (vector::const_iterator it = m_id.begin(); it < m_id.end(); it++) { + cnt++; + if (column == 6) { + if (cnt == 2) + break; + } else if (cnt < 2) { + continue; + } + output << hex << setw(2) << setfill('0') << static_cast(*it); + } + break; + case 8: // fields + m_data->dump(output); + break; + } + } +} string strtolower(const string& str) { diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index 47e46758..27192246 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -260,6 +260,13 @@ public: */ void dump(ostream& output); + /** + * Write parts of the message definition to the @a ostream. + * @param output the @a ostream to append the formatted value to. + * @param columns the list of column indexes to write. + */ + void dump(ostream& output, vector& columns); + private: /** the optional circuit name. */