diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 277bc9f9..ccd1d0fa 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -350,7 +350,7 @@ result_t BusHandler::readFromBus(Message* message, const string& inputStr, symbo return ret; } -void BusHandler::notifyProtocolStatus(ProtocolState state) { +void BusHandler::notifyProtocolStatus(ProtocolState state, result_t result) { if (state == ps_empty && m_pollInterval > 0) { // check for poll/scan time_t now; time(&now); diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index fe6527b7..7bc185db 100755 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -396,7 +396,7 @@ class BusHandler : public ProtocolListener { void setScanConfigLoaded(symbol_t address, const string& file); // @copydoc - void notifyProtocolStatus(ProtocolState state) override; + void notifyProtocolStatus(ProtocolState state, result_t result) override; // @copydoc result_t notifyProtocolAnswer(const MasterSymbolString& master, SlaveSymbolString* slave) override; diff --git a/src/lib/ebus/protocol.cpp b/src/lib/ebus/protocol.cpp index fa31bd4c..95157c92 100644 --- a/src/lib/ebus/protocol.cpp +++ b/src/lib/ebus/protocol.cpp @@ -32,6 +32,18 @@ using std::hex; using std::setfill; using std::setw; +const char* getProtocolStateCode(ProtocolState state) { + switch (state) { + case ps_noSignal: return "no signal"; + case ps_idle: return "idle"; + case ps_idleSYN: return "idle, SYN generator"; + case ps_recv: return "receive"; + case ps_send: return "send"; + case ps_empty: return "idle, empty"; + default: return "unknown"; + } +} + bool ActiveBusRequest::notify(result_t result, const SlaveSymbolString& slave) { if (result == RESULT_OK) { string str = slave.getStr(); diff --git a/src/lib/ebus/protocol.h b/src/lib/ebus/protocol.h index 1936d3ec..183826e1 100755 --- a/src/lib/ebus/protocol.h +++ b/src/lib/ebus/protocol.h @@ -89,9 +89,18 @@ typedef struct ebus_protocol_config { enum ProtocolState { ps_noSignal, //!< no signal on the bus ps_idle, //!< idle (after @a SYN symbol) + ps_idleSYN, //!< idle (after sent SYN symbol in acting as SYN generator) + ps_recv, //!< receiving + ps_send, //!< sending ps_empty, //!< idle, no more lock remaining, and no other request queued }; +/** + * Return the string corresponding to the @a ProtocolState. + * @param state the @a ProtocolState. + * @return the string corresponding to the @a ProtocolState. + */ +const char* getProtocolStateCode(ProtocolState state); class ProtocolHandler; @@ -208,8 +217,9 @@ class ProtocolListener { /** * Called to notify a status update from the protocol. * @param state the current protocol state. + * @param result the error code reason for the state change, or @a RESULT_OK. */ - virtual void notifyProtocolStatus(ProtocolState state) = 0; // abstract + virtual void notifyProtocolStatus(ProtocolState state, result_t result) = 0; // abstract /** * Called to notify a new valid seen address on the bus. @@ -253,7 +263,7 @@ class ProtocolHandler : public WaitThread, DeviceListener { ProtocolHandler(const ebus_protocol_config_t config, Device* device, ProtocolListener* listener) : WaitThread(), m_config(config), m_device(device), m_listener(listener), - m_reconnect(false), + m_listenerState(ps_noSignal), m_reconnect(false), m_ownMasterAddress(config.ownAddress), m_ownSlaveAddress(getSlaveAddress(config.ownAddress)), m_addressConflict(false), m_masterCount(config.readOnly ? 0 : 1), @@ -519,6 +529,9 @@ class ProtocolHandler : public WaitThread, DeviceListener { /** the @a ProtocolListener. */ ProtocolListener *m_listener; + /** the last state the listener was informed with. */ + ProtocolState m_listenerState; + /** set to @p true when the device shall be reconnected. */ bool m_reconnect; diff --git a/src/lib/ebus/protocol_direct.cpp b/src/lib/ebus/protocol_direct.cpp index 28fe84ab..6b789e23 100644 --- a/src/lib/ebus/protocol_direct.cpp +++ b/src/lib/ebus/protocol_direct.cpp @@ -135,7 +135,7 @@ result_t DirectProtocolHandler::handleSymbol() { if (!m_device->isArbitrating() && m_currentRequest == nullptr && m_remainLockCount == 0) { BusRequest* startRequest = m_nextRequests.peek(); if (startRequest == nullptr) { - m_listener->notifyProtocolStatus(ps_empty); + m_listener->notifyProtocolStatus(ps_empty, RESULT_OK); startRequest = m_nextRequests.peek(); } if (startRequest != nullptr) { // initiate arbitration @@ -677,9 +677,6 @@ result_t DirectProtocolHandler::setState(BusState state, result_t result, bool f } if (state == bs_noSignal) { // notify all requests - if (m_state != bs_noSignal) { - m_listener->notifyProtocolStatus(ps_idle); - } m_response.clear(); // notify with empty response while ((m_currentRequest = m_nextRequests.pop()) != nullptr) { bool restart = m_currentRequest->notify(RESULT_ERR_NO_SIGNAL, m_response); @@ -692,12 +689,13 @@ result_t DirectProtocolHandler::setState(BusState state, result_t result, bool f m_finishedRequests.push(m_currentRequest); } } - } else if (m_state == bs_noSignal) { - m_listener->notifyProtocolStatus(ps_noSignal); } m_escape = 0; if (state == m_state) { + if (m_listener && result != RESULT_OK) { + m_listener->notifyProtocolStatus(m_listenerState, result); + } return result; } if ((result < RESULT_OK && !(result == RESULT_ERR_TIMEOUT && state == bs_skip && m_state == bs_ready)) @@ -718,6 +716,16 @@ result_t DirectProtocolHandler::setState(BusState state, result_t result, bool f logNotice(lf_bus, "signal acquired"); } } + if (m_listener) { + ProtocolState pstate = protocolStateByBusState[state]; + if (pstate == ps_idle && m_generateSynInterval == SYN_INTERVAL) { + pstate = ps_idleSYN; + } + if (result != RESULT_OK || pstate != m_listenerState) { + m_listener->notifyProtocolStatus(pstate, result); + m_listenerState = pstate; + } + } m_state = state; if (state == bs_ready || state == bs_skip) {