From b695512a083200f762d9944c58dd55900cc560c7 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 19 Feb 2017 12:56:07 +0100 Subject: [PATCH] added -s QQ option to read/write/hex commands --- src/ebusd/bushandler.cpp | 8 ++-- src/ebusd/bushandler.h | 4 +- src/ebusd/mainloop.cpp | 90 +++++++++++++++++++++++++++------------- src/ebusd/mainloop.h | 3 +- 4 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 534cba5d..6a7f1cec 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -340,13 +340,15 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) { return result; } -result_t BusHandler::readFromBus(Message* message, string inputStr, const unsigned char dstAddress) { +result_t BusHandler::readFromBus(Message* message, string inputStr, const unsigned char dstAddress, + const unsigned char srcAddress) { + unsigned char masterAddress = srcAddress == SYN ? m_ownMasterAddress : srcAddress; result_t ret = RESULT_EMPTY; SymbolString master(true); SymbolString slave(false); for (unsigned char index = 0; index < message->getCount(); index++) { istringstream input(inputStr); - ret = message->prepareMaster(m_ownMasterAddress, master, input, UI_FIELD_SEPARATOR, dstAddress, index); + ret = message->prepareMaster(masterAddress, master, input, UI_FIELD_SEPARATOR, dstAddress, index); if (ret != RESULT_OK) { logError(lf_bus, "prepare message part %d: %s", index, getResultCode(ret)); break; @@ -447,7 +449,7 @@ result_t BusHandler::handleSymbol() { } } if (startRequest != NULL) { // initiate arbitration - sendSymbol = m_ownMasterAddress; + sendSymbol = startRequest->m_master[0]; sending = true; } } diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index d20cd154..353a0b72 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -409,9 +409,11 @@ class BusHandler : public WaitThread { * @param message the @a Message instance. * @param inputStr the input @a string from which to read master values (if any). * @param dstAddress the destination address to set, or @a SYN to keep the address defined during construction. + * @param srcAddress the source address to set, or @a SYN for the own master address. * @return the result code. */ - result_t readFromBus(Message* message, string inputStr, const unsigned char dstAddress = SYN); + result_t readFromBus(Message* message, string inputStr, const unsigned char dstAddress = SYN, + const unsigned char srcAddress = SYN); /** * Main thread entry. diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index 0ae4b576..adead1ca 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -472,7 +472,8 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn return "ERR: command not found"; } -result_t MainLoop::parseHexMaster(vector &args, size_t argPos, SymbolString& master) { +result_t MainLoop::parseHexMaster(vector &args, size_t argPos, SymbolString& master, + unsigned char srcAddress) { ostringstream msg; while (argPos < args.size()) { if ((args[argPos].length() % 2) != 0) { @@ -488,7 +489,7 @@ result_t MainLoop::parseHexMaster(vector &args, size_t argPos, SymbolStr if (ret == RESULT_OK && (4+length)*2 != msg.str().size()) { return RESULT_ERR_INVALID_ARG; } - ret = master.push_back(m_address, false); + ret = master.push_back(srcAddress == SYN ? m_address : srcAddress, false); if (ret == RESULT_OK) { ret = master.parseHex(msg.str()); } @@ -518,7 +519,7 @@ string MainLoop::executeRead(vector &args, const string levels) { OutputFormat verbosity = 0; time_t maxAge = 5*60; string circuit, params; - unsigned char dstAddress = SYN, pollPriority = 0; + unsigned char srcAddress = SYN, dstAddress = SYN, pollPriority = 0; while (args.size() > argPos && args[argPos][0] == '-') { if (args[argPos] == "-h") { hex = true; @@ -562,17 +563,23 @@ string MainLoop::executeRead(vector &args, const string levels) { break; } circuit = args[argPos]; - } else if (args[argPos] == "-d") { + } else if (args[argPos] == "-s" || args[argPos] == "-d") { argPos++; if (argPos >= args.size()) { argPos = 0; // print usage break; } + bool dest = args[argPos] == "-d"; result_t ret; - dstAddress = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret); - if (ret != RESULT_OK || !isValidAddress(dstAddress) || isMaster(dstAddress)) { + unsigned char address = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret); + if (ret != RESULT_OK || !isValidAddress(address, dest) || dest == isMaster(address)) { return getResultCode(RESULT_ERR_INVALID_ADDR); } + if (dest) { + dstAddress = address; + } else { + srcAddress = address == m_address ? SYN : address; + } } else if (args[argPos] == "-p") { argPos++; if (argPos >= args.size()) { @@ -607,7 +614,7 @@ string MainLoop::executeRead(vector &args, const string levels) { if (hex && argPos > 0) { SymbolString cacheMaster(false); - result_t ret = parseHexMaster(args, argPos, cacheMaster); + result_t ret = parseHexMaster(args, argPos, cacheMaster, srcAddress); if (ret != RESULT_OK) { return getResultCode(ret); } @@ -631,7 +638,9 @@ string MainLoop::executeRead(vector &args, const string levels) { if (circuit.length() > 0 && circuit != message->getCircuit()) { return getResultCode(RESULT_ERR_INVALID_ARG); // non-matching circuit } - if (message->getLastUpdateTime() + maxAge > now || (message->isPassive() && message->getLastUpdateTime() != 0)) { + if (srcAddress == SYN + && (message->getLastUpdateTime() + maxAge > now + || (message->isPassive() && message->getLastUpdateTime() != 0))) { SymbolString& slave = message->getLastSlaveData(); logNotice(lf_main, "hex read %s %s from cache", message->getCircuit().c_str(), message->getName().c_str()); return slave.getDataStr(true, false); @@ -663,13 +672,14 @@ string MainLoop::executeRead(vector &args, const string levels) { return getResultCode(ret); } if (argPos == 0 || args.size() < argPos + 1 || args.size() > argPos + 2) { - return "usage: read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*] NAME" - " [FIELD[.N]]\n" - " or: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n" + return "usage: read [-f] [-m SECONDS] [-s QQ] [-d ZZ] [-c CIRCUIT] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*]" + " NAME [FIELD[.N]]\n" + " or: read [-f] [-m SECONDS] [-s QQ] [-c CIRCUIT] -h ZZPBSBNNDx\n" " Read value(s) or hex message.\n" " -f force reading from the bus (same as '-m 0')\n" " -m SECONDS only return cached value if age is less than SECONDS [300]\n" " -c CIRCUIT limit to messages of CIRCUIT\n" + " -s QQ override source address QQ\n" " -d ZZ override destination address ZZ\n" " -p PRIO set the message poll priority (1-9)\n" " -v increase verbosity (include names/units/comments)\n" @@ -707,7 +717,7 @@ string MainLoop::executeRead(vector &args, const string levels) { m_messages->addPollMessage(message); } - if (dstAddress == SYN && maxAge > 0 && params.length() == 0) { + if (srcAddress == SYN && dstAddress == SYN && maxAge > 0 && params.length() == 0) { Message* cacheMessage = m_messages->find(circuit, args[argPos], levels, false, true); bool hasCache = cacheMessage != NULL; if (!hasCache || (message != NULL && message->getLastUpdateTime() > cacheMessage->getLastUpdateTime())) { @@ -745,7 +755,7 @@ string MainLoop::executeRead(vector &args, const string levels) { return getResultCode(RESULT_ERR_INVALID_ADDR); } // read directly from bus - result_t ret = m_busHandler->readFromBus(message, params, dstAddress); + result_t ret = m_busHandler->readFromBus(message, params, dstAddress, srcAddress); if (ret != RESULT_OK) { return getResultCode(ret); } @@ -772,21 +782,27 @@ string MainLoop::executeWrite(vector &args, const string levels) { size_t argPos = 1; bool hex = false; string circuit; - unsigned char dstAddress = SYN; + unsigned char srcAddress = SYN, dstAddress = SYN; while (args.size() > argPos && args[argPos][0] == '-') { if (args[argPos] == "-h") { hex = true; - } else if (args[argPos] == "-d") { + } else if (args[argPos] == "-s" || args[argPos] == "-d") { argPos++; if (argPos >= args.size()) { argPos = 0; // print usage break; } + bool dest = args[argPos] == "-d"; result_t ret; - dstAddress = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret); - if (ret != RESULT_OK || !isValidAddress(dstAddress) || isMaster(dstAddress)) { + unsigned char address = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret); + if (ret != RESULT_OK || !isValidAddress(address, dest) || dest == isMaster(address)) { return getResultCode(RESULT_ERR_INVALID_ADDR); } + if (dest) { + dstAddress = address; + } else { + srcAddress = address == m_address ? SYN : address; + } } else if (args[argPos] == "-c") { argPos++; if (argPos >= args.size()) { @@ -807,7 +823,7 @@ string MainLoop::executeWrite(vector &args, const string levels) { if (hex && argPos > 0) { SymbolString cacheMaster(false); - result_t ret = parseHexMaster(args, argPos, cacheMaster); + result_t ret = parseHexMaster(args, argPos, cacheMaster, srcAddress); if (ret != RESULT_OK) { return getResultCode(ret); } @@ -862,9 +878,10 @@ string MainLoop::executeWrite(vector &args, const string levels) { } if (argPos == 0 || circuit.empty() || (args.size() != argPos + 2 && args.size() != argPos + 1)) { - return "usage: write [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n" - " or: write [-c CIRCUIT] -h ZZPBSBNNDx\n" + return "usage: write [-s QQ] [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n" + " or: write [-s QQ] [-c CIRCUIT] -h ZZPBSBNNDx\n" " Write value(s) or hex message.\n" + " -s QQ override source address QQ\n" " -d ZZ override destination address ZZ\n" " -c CIRCUIT CIRCUIT of the message to send\n" " NAME NAME of the message to send\n" @@ -884,7 +901,8 @@ string MainLoop::executeWrite(vector &args, const string levels) { return getResultCode(RESULT_ERR_INVALID_ADDR); } // allow missing values - result_t ret = m_busHandler->readFromBus(message, args.size() == argPos + 1 ? "" : args[argPos + 1], dstAddress); + result_t ret = m_busHandler->readFromBus(message, args.size() == argPos + 1 ? "" : args[argPos + 1], dstAddress, + srcAddress); if (ret != RESULT_OK) { logError(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret)); @@ -921,13 +939,28 @@ string MainLoop::executeWrite(vector &args, const string levels) { string MainLoop::executeHex(vector &args) { size_t argPos = 1; + unsigned char srcAddress = SYN; + if (args.size() > argPos && args[argPos] == "-s") { + argPos++; + if (argPos >= args.size()) { + argPos = 0; // print usage + } else { + result_t ret; + unsigned char address = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret); + if (ret != RESULT_OK || !isValidAddress(address, false) || !isMaster(address)) { + return getResultCode(RESULT_ERR_INVALID_ADDR); + } + srcAddress = address == m_address ? SYN : address; + } + argPos++; + } if (args.size() < argPos + 1 || (args.size() > argPos && args[argPos][0] == '-')) { argPos = 0; // print usage } if (argPos > 0) { SymbolString cacheMaster(false); - result_t ret = parseHexMaster(args, argPos, cacheMaster); + result_t ret = parseHexMaster(args, argPos, cacheMaster, srcAddress); if (ret != RESULT_OK) { return getResultCode(ret); } @@ -952,8 +985,9 @@ string MainLoop::executeHex(vector &args) { return getResultCode(ret); } - return "usage: hex ZZPBSBNNDx\n" + return "usage: hex [-s QQ] ZZPBSBNNDx\n" " Send arbitrary data in hex (only if enabled).\n" + " -s QQ override source address QQ\n" " ZZ destination address\n" " PB SB primary/secondary command byte\n" " NN number of following data bytes\n" @@ -1403,13 +1437,13 @@ string MainLoop::executeQuit(vector &args, bool& connected) { string MainLoop::executeHelp() { return "usage:\n" - " read|r Read value(s): read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n]" + " read|r Read value(s): read [-f] [-m SECONDS] [-s QQ] [-d ZZ] [-c CIRCUIT] [-p PRIO] [-v|-V] [-n]" " [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n" - " Read hex message: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n" - " write|w Write value(s): write [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n" - " Write hex message: write [-c CIRCUIT] -h ZZPBSBNNDx\n" + " Read hex message: read [-f] [-m SECONDS] [-s QQ] [-c CIRCUIT] -h ZZPBSBNNDx\n" + " write|w Write value(s): write [-s QQ] [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n" + " Write hex message: write [-s QQ] [-c CIRCUIT] -h ZZPBSBNNDx\n" " auth|a Authenticate user: auth USER SECRET\n" - " hex Send hex data: hex ZZPBSBNNDx\n" + " hex Send hex data: hex [-s QQ] ZZPBSBNNDx\n" " find|f Find message(s): find [-v|-V] [-r] [-w] [-p] [-a] [-d] [-h] [-i ID] [-f] [-F COL[,COL]*] [-e]" " [-c CIRCUIT] [-l LEVEL] [NAME]\n" " listen|l Listen for updates: listen [stop]\n" diff --git a/src/ebusd/mainloop.h b/src/ebusd/mainloop.h index fc7882a1..e6d0f581 100644 --- a/src/ebusd/mainloop.h +++ b/src/ebusd/mainloop.h @@ -146,9 +146,10 @@ class MainLoop : public Thread, DeviceListener { * @param args the arguments passed to the command. * @param argPos the index of the first argument to parse. * @param master the master @a SymbolString to write the data to. + * @param srcAddress the source address to set, or @a SYN for the own master address. * @return the result from parsing the arguments. */ - result_t parseHexMaster(vector &args, size_t argPos, SymbolString& master); + result_t parseHexMaster(vector &args, size_t argPos, SymbolString& master, unsigned char srcAddress = SYN); /** * Get the access levels associated with the specified user name.