From 3d89fef6aecd52f8a9dc4bbf323dfc09d8adae30 Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 13 Dec 2014 00:01:31 +0100 Subject: [PATCH] added scanning and collection of seen bus addresses --- src/ebusd/bushandler.cpp | 104 +++++++++++++++++++++++++++++++++------ src/ebusd/bushandler.h | 92 +++++++++++++++++++++++++++++++--- 2 files changed, 175 insertions(+), 21 deletions(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index aab4ff7c..f4ef53b3 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -28,6 +28,7 @@ #include #include #include +#include using namespace std; @@ -79,6 +80,27 @@ void PollRequest::notify(result_t result) L.log(bus, event, "poll %s: %s", m_message->getName().c_str(), output.str().c_str()); } + +result_t ScanRequest::prepare(unsigned char ownMasterAddress, unsigned char dstAddress) +{ + 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()); + return result; +} + +void ScanRequest::notify(result_t result) +{ + if (result == RESULT_OK) { + 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)); +} + + ActiveBusRequest::ActiveBusRequest(SymbolString& master, SymbolString& slave) : BusRequest(master, slave, false), m_finished(false), m_result(RESULT_SYN) { @@ -131,7 +153,7 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) result_t result = RESULT_SYN; ActiveBusRequest* request = new ActiveBusRequest(master, slave); - for (int sendRetries=m_failedSendRetries+1, lostRetries=m_busLostRetries+1; sendRetries>=0; sendRetries--) { + for (int sendRetries=m_failedSendRetries+1; sendRetries>=0; sendRetries--) { m_requests.add(request); bool success = request->wait(1); // 1 second is still 3 times the theoretical worst-case request duration if (success == false) @@ -141,18 +163,11 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) if (result == RESULT_OK) break; - if (result == RESULT_ERR_BUS_LOST) { - if (--lostRetries > 0) { - sendRetries++; // try to get lock again, do not decrement send retries - L.log(bus, error, " %s, retry bus loss", getResultCode(result)); - continue; - } - lostRetries = m_busLostRetries+1; // send retry: reset lock retries - } L.log(bus, error, " %s, %s", getResultCode(result), sendRetries>0 ? "retry send" : "give up"); + request->m_busLostRetries = 0; } - delete request; + delete request; // TODO may be unsave while run() is using the request return result; } @@ -541,12 +556,24 @@ result_t BusHandler::handleSymbol() result_t BusHandler::setState(BusState state, result_t result, bool firstRepetition) { if (m_request != NULL) { - if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) { + if (result == RESULT_ERR_BUS_LOST && m_request->m_busLostRetries < m_busLostRetries) { + L.log(bus, error, " %s, retry", getResultCode(result)); + m_request->m_busLostRetries++; + m_requests.add(m_request); // repeat + m_request = NULL; + } 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); m_request->notify(result); - if (m_request->m_isPoll == true) + 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; + } delete m_request; + } m_request = NULL; } } @@ -576,12 +603,16 @@ void BusHandler::receiveCompleted() unsigned char dstAddress = m_command[1]; bool master = isMaster(dstAddress); + m_seenAddresses[m_command[0]] = true; if (dstAddress == BROADCAST) L.log(bus, trace, "received BC %s", m_command.getDataStr().c_str()); - else if (master == true) + else if (master == true) { L.log(bus, trace, "received MM %s", m_command.getDataStr().c_str()); - else + m_seenAddresses[dstAddress] = true; + } else { L.log(bus, trace, "received MS %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); + m_seenAddresses[dstAddress] = true; + } Message* message = m_messages->find(m_command); if (message != NULL) { @@ -599,3 +630,48 @@ void BusHandler::receiveCompleted() } } } + +result_t BusHandler::startScan(bool full) +{ + Message* scanMessage = m_scanMessage; + if (scanMessage == NULL) { + scanMessage = m_messages->find("", "scan", false); + } + if (scanMessage == NULL) { + DataFieldSet* identFields = DataFieldSet::createIdentFields(); + scanMessage = m_scanMessage = new Message(false, false, 0x07, 0x04, identFields); + } + if (scanMessage == NULL) + return RESULT_ERR_NOTFOUND; + + if (full == true) + m_scanResults.clear(); + + for (unsigned int slave=0; slave<=255; slave++) { + if (isValidAddress(slave, false) == false || isMaster(slave) == true) + continue; + if (full == false && m_seenAddresses[slave] == false) { + unsigned int master = slave+(256-5); // check if we saw the corresponding master already + if (isMaster(master) == false || m_seenAddresses[slave] == false) + continue; + } + + ScanRequest* request = new ScanRequest(m_response, scanMessage); + result_t result = request->prepare(m_ownMasterAddress, slave); + if (result != RESULT_OK) { + delete request; + return result; + } + m_requests.add(request); + } + return RESULT_OK; +} + +void BusHandler::formatScanResult(ostringstream& output) +{ + for (unsigned int slave=0; slave<=255; slave++) { + map::iterator it = m_scanResults.find(slave); + if (it != m_scanResults.end()) + output << it->second << endl; + } +} diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index cf4151e2..2f835986 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -31,6 +31,7 @@ #include #include #include +#include using namespace std; @@ -72,10 +73,11 @@ public: * @brief Constructor. * @param master the master data @a SymbolString to send. * @param slave the slave data @a SymbolString received. - * @param isPoll whether this is a poll request. + * @param deleteOnFinish whether to automatically delete this @a BusRequest when finished. */ - BusRequest(SymbolString& master, SymbolString& slave, bool isPoll) - : m_master(master), m_slave(slave), m_isPoll(isPoll) {} + BusRequest(SymbolString& master, SymbolString& slave, bool deleteOnFinish) + : m_master(master), m_slave(slave), m_busLostRetries(0), + m_deleteOnFinish(deleteOnFinish) {} /** * @brief Destructor. @@ -96,8 +98,11 @@ protected: /** the slave data @a SymbolString received. */ SymbolString& m_slave; - /** whether this is a poll request. */ - bool m_isPoll; + /** the number of times a send is repeated due to lost arbitration. */ + unsigned int m_busLostRetries; + + /** whether to automatically delete this @a BusRequest when finished. */ + bool m_deleteOnFinish; }; @@ -144,6 +149,52 @@ private: }; +/** + * @brief A scan @a BusRequest handled by @a BusHandler itself. + */ +class ScanRequest : public BusRequest +{ + friend class BusHandler; +public: + + /** + * @brief Constructor. + * @param slave the slave data @a SymbolString received. + * @param message the associated @a Message. + */ + ScanRequest(SymbolString& slave, Message* message) + : BusRequest(m_master, slave, true), m_message(message) {} + + /** + * @brief Destructor. + */ + virtual ~ScanRequest() {} + + /** + * @brief Prepare the master data. + * @param masterAddress the master bus address to use. + * @param dstAddress the destination address to set. + * @return the result code. + */ + result_t prepare(unsigned char masterAddress, unsigned char dstAddress); + + // @copydoc + virtual void notify(result_t result); + +private: + + /** the master data @a SymbolString. */ + SymbolString m_master; + + /** the associated @a Message. */ + Message* m_message; + + /** the formatted scan result. */ + ostringstream m_scanResult; + +}; + + /** * @brief An active @a BusRequest that can be waited for. */ @@ -224,12 +275,18 @@ public: m_pollInterval(pollInterval), m_lastPoll(0), m_request(NULL), m_nextSendPos(0), m_state(bs_skip), m_repeat(false), - m_commandCrcValid(false), m_responseCrcValid(false) {} + m_commandCrcValid(false), m_responseCrcValid(false), + m_scanMessage(NULL) { + memset(m_seenAddresses, 0, sizeof(m_seenAddresses)); + } /** * @brief Destructor. */ - virtual ~BusHandler() {} + virtual ~BusHandler() { + if (m_scanMessage != NULL) + delete m_scanMessage; + } /** * @brief Send a message on the bus and wait for the answer. @@ -250,6 +307,18 @@ public: */ string getReceivedData(Message* message); + /** + * @brief Initiate a scan of the slave addresses. + * @param full true for a full scan (all slaves), false for scanning only already seen slaves. + */ + result_t startScan(bool full=false); + + /** + * @brief Format the scan result to the @a ostringstream. + * @param output the @a ostringstream to format the scan result to. + */ + void formatScanResult(ostringstream& output); + private: /** @@ -339,6 +408,15 @@ private: /** whether the response CRC is valid. */ bool m_responseCrcValid; + /** the participating bus addresses seen so far. */ + bool m_seenAddresses[256]; + + /** the @a Message instance used for scanning. */ + Message* m_scanMessage; + + /** the scan results by slave address. */ + map m_scanResults; + };