loconet: added timeouts for echo and reply
Dieser Commit ist enthalten in:
Ursprung
005d5ef1e9
Commit
ac445c37ad
@ -29,6 +29,9 @@ namespace LocoNet {
|
|||||||
|
|
||||||
struct Config
|
struct Config
|
||||||
{
|
{
|
||||||
|
static constexpr uint16_t echoTimeout = 500; //!< Wait for echo timeout in milliseconds
|
||||||
|
static constexpr uint16_t responseTimeout = 500; //!< Wait for response timeout in milliseconds
|
||||||
|
|
||||||
bool fastClockSyncEnabled;
|
bool fastClockSyncEnabled;
|
||||||
uint8_t fastClockSyncInterval; //!< Fast clock sync interval in seconds
|
uint8_t fastClockSyncInterval; //!< Fast clock sync interval in seconds
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,9 @@ Kernel::Kernel(const Config& config, bool simulation)
|
|||||||
: m_ioContext{1}
|
: m_ioContext{1}
|
||||||
, m_simulation{simulation}
|
, m_simulation{simulation}
|
||||||
, m_waitingForEcho{false}
|
, m_waitingForEcho{false}
|
||||||
|
, m_waitingForEchoTimer{m_ioContext}
|
||||||
, m_waitingForResponse{false}
|
, m_waitingForResponse{false}
|
||||||
|
, m_waitingForResponseTimer{m_ioContext}
|
||||||
, m_fastClockSyncTimer(m_ioContext)
|
, m_fastClockSyncTimer(m_ioContext)
|
||||||
, m_decoderController{nullptr}
|
, m_decoderController{nullptr}
|
||||||
, m_inputController{nullptr}
|
, m_inputController{nullptr}
|
||||||
@ -167,6 +169,8 @@ void Kernel::stop()
|
|||||||
m_ioContext.post(
|
m_ioContext.post(
|
||||||
[this]()
|
[this]()
|
||||||
{
|
{
|
||||||
|
m_waitingForEchoTimer.cancel();
|
||||||
|
m_waitingForResponseTimer.cancel();
|
||||||
m_fastClockSyncTimer.cancel();
|
m_fastClockSyncTimer.cancel();
|
||||||
m_ioHandler->stop();
|
m_ioHandler->stop();
|
||||||
});
|
});
|
||||||
@ -186,9 +190,10 @@ void Kernel::receive(const Message& message)
|
|||||||
EventLoop::call([this, msg=toString(message)](){ Log::log(m_logId, LogMessage::D2002_RX_X, msg); });
|
EventLoop::call([this, msg=toString(message)](){ Log::log(m_logId, LogMessage::D2002_RX_X, msg); });
|
||||||
|
|
||||||
bool isResponse = false;
|
bool isResponse = false;
|
||||||
if(m_waitingForEcho && message == m_sendQueue[m_sentMessagePriority].front())
|
if(m_waitingForEcho && message == lastSentMessage())
|
||||||
{
|
{
|
||||||
m_waitingForEcho = false;
|
m_waitingForEcho = false;
|
||||||
|
m_waitingForEchoTimer.cancel();
|
||||||
if(!m_waitingForResponse)
|
if(!m_waitingForResponse)
|
||||||
{
|
{
|
||||||
m_sendQueue[m_sentMessagePriority].pop();
|
m_sendQueue[m_sentMessagePriority].pop();
|
||||||
@ -197,7 +202,7 @@ void Kernel::receive(const Message& message)
|
|||||||
}
|
}
|
||||||
else if(m_waitingForResponse)
|
else if(m_waitingForResponse)
|
||||||
{
|
{
|
||||||
isResponse = isValidResponse(m_sendQueue[m_sentMessagePriority].front(), message);
|
isResponse = isValidResponse(lastSentMessage(), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(message.opCode)
|
switch(message.opCode)
|
||||||
@ -637,6 +642,7 @@ void Kernel::receive(const Message& message)
|
|||||||
if(m_waitingForResponse && isResponse)
|
if(m_waitingForResponse && isResponse)
|
||||||
{
|
{
|
||||||
m_waitingForResponse = false;
|
m_waitingForResponse = false;
|
||||||
|
m_waitingForResponseTimer.cancel();
|
||||||
m_sendQueue[m_sentMessagePriority].pop();
|
m_sendQueue[m_sentMessagePriority].pop();
|
||||||
sendNextMessage();
|
sendNextMessage();
|
||||||
}
|
}
|
||||||
@ -877,8 +883,17 @@ void Kernel::sendNextMessage()
|
|||||||
if(m_ioHandler->send(message))
|
if(m_ioHandler->send(message))
|
||||||
{
|
{
|
||||||
m_sentMessagePriority = static_cast<Priority>(priority);
|
m_sentMessagePriority = static_cast<Priority>(priority);
|
||||||
|
|
||||||
m_waitingForEcho = true;
|
m_waitingForEcho = true;
|
||||||
|
m_waitingForEchoTimer.expires_after(boost::asio::chrono::milliseconds(Config::echoTimeout));
|
||||||
|
m_waitingForEchoTimer.async_wait(std::bind(&Kernel::waitingForEchoTimerExpired, this, std::placeholders::_1));
|
||||||
|
|
||||||
m_waitingForResponse = hasResponse(message);
|
m_waitingForResponse = hasResponse(message);
|
||||||
|
if(m_waitingForResponse)
|
||||||
|
{
|
||||||
|
m_waitingForResponseTimer.expires_after(boost::asio::chrono::milliseconds(Config::responseTimeout));
|
||||||
|
m_waitingForResponseTimer.async_wait(std::bind(&Kernel::waitingForResponseTimerExpired, this, std::placeholders::_1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{} // log message and go to error state
|
{} // log message and go to error state
|
||||||
@ -887,6 +902,29 @@ void Kernel::sendNextMessage()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Kernel::waitingForEchoTimerExpired(const boost::system::error_code& ec)
|
||||||
|
{
|
||||||
|
if(ec)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EventLoop::call(
|
||||||
|
[this]()
|
||||||
|
{
|
||||||
|
Log::log(m_logId, LogMessage::E2018_TIMEOUT_NO_ECHO_WITHIN_X_MS, Config::echoTimeout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kernel::waitingForResponseTimerExpired(const boost::system::error_code& ec)
|
||||||
|
{
|
||||||
|
if(ec)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EventLoop::call(
|
||||||
|
[this]()
|
||||||
|
{
|
||||||
|
Log::log(m_logId, LogMessage::E2019_TIMEOUT_NO_RESPONSE_WITHIN_X_MS, Config::responseTimeout);
|
||||||
|
});
|
||||||
|
}
|
||||||
void Kernel::startFastClockSyncTimer()
|
void Kernel::startFastClockSyncTimer()
|
||||||
{
|
{
|
||||||
assert(m_config.fastClockSyncInterval > 0);
|
assert(m_config.fastClockSyncInterval > 0);
|
||||||
|
|||||||
@ -125,7 +125,9 @@ class Kernel
|
|||||||
std::array<SendQueue, 3> m_sendQueue;
|
std::array<SendQueue, 3> m_sendQueue;
|
||||||
Priority m_sentMessagePriority;
|
Priority m_sentMessagePriority;
|
||||||
bool m_waitingForEcho;
|
bool m_waitingForEcho;
|
||||||
|
boost::asio::steady_timer m_waitingForEchoTimer;
|
||||||
bool m_waitingForResponse;
|
bool m_waitingForResponse;
|
||||||
|
boost::asio::steady_timer m_waitingForResponseTimer;
|
||||||
|
|
||||||
TriState m_globalPower;
|
TriState m_globalPower;
|
||||||
std::function<void(bool)> m_onGlobalPowerChanged;
|
std::function<void(bool)> m_onGlobalPowerChanged;
|
||||||
@ -160,6 +162,11 @@ class Kernel
|
|||||||
|
|
||||||
void setIOHandler(std::unique_ptr<IOHandler> handler);
|
void setIOHandler(std::unique_ptr<IOHandler> handler);
|
||||||
|
|
||||||
|
inline const Message& lastSentMessage() const
|
||||||
|
{
|
||||||
|
return m_sendQueue[m_sentMessagePriority].front();
|
||||||
|
}
|
||||||
|
|
||||||
void send(const Message& message, Priority priority = NormalPriority);
|
void send(const Message& message, Priority priority = NormalPriority);
|
||||||
void send(uint16_t address, Message& message, uint8_t& slot);
|
void send(uint16_t address, Message& message, uint8_t& slot);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -169,6 +176,9 @@ class Kernel
|
|||||||
}
|
}
|
||||||
void sendNextMessage();
|
void sendNextMessage();
|
||||||
|
|
||||||
|
void waitingForEchoTimerExpired(const boost::system::error_code& ec);
|
||||||
|
void waitingForResponseTimerExpired(const boost::system::error_code& ec);
|
||||||
|
|
||||||
void startFastClockSyncTimer();
|
void startFastClockSyncTimer();
|
||||||
void stopFastClockSyncTimer();
|
void stopFastClockSyncTimer();
|
||||||
void fastClockSyncTimerExpired(const boost::system::error_code& ec);
|
void fastClockSyncTimerExpired(const boost::system::error_code& ec);
|
||||||
|
|||||||
@ -140,6 +140,8 @@ enum class LogMessage : uint32_t
|
|||||||
E2015_SERIAL_PORT_SET_STOP_BITS_FAILED_X = LogMessageOffset::error + 2015,
|
E2015_SERIAL_PORT_SET_STOP_BITS_FAILED_X = LogMessageOffset::error + 2015,
|
||||||
E2016_SERIAL_PORT_SET_PARITY_FAILED_X = LogMessageOffset::error + 2016,
|
E2016_SERIAL_PORT_SET_PARITY_FAILED_X = LogMessageOffset::error + 2016,
|
||||||
E2017_SERIAL_PORT_SET_FLOW_CONTROL_FAILED_X = LogMessageOffset::error + 2017,
|
E2017_SERIAL_PORT_SET_FLOW_CONTROL_FAILED_X = LogMessageOffset::error + 2017,
|
||||||
|
E2018_TIMEOUT_NO_ECHO_WITHIN_X_MS = LogMessageOffset::error + 2018,
|
||||||
|
E2019_TIMEOUT_NO_RESPONSE_WITHIN_X_MS = LogMessageOffset::error + 2019,
|
||||||
E9001_X_DURING_EXECUTION_OF_X_EVENT_HANDLER = LogMessageOffset::error + 9001,
|
E9001_X_DURING_EXECUTION_OF_X_EVENT_HANDLER = LogMessageOffset::error + 9001,
|
||||||
E9999_X = LogMessageOffset::error + 9999,
|
E9999_X = LogMessageOffset::error + 9999,
|
||||||
|
|
||||||
|
|||||||
@ -270,6 +270,8 @@ message:E2009=Socket receive failed (%1)
|
|||||||
message:E2010=Serial port open failed (%1)
|
message:E2010=Serial port open failed (%1)
|
||||||
message:E2011=Socket send failed (%1)
|
message:E2011=Socket send failed (%1)
|
||||||
message:E2012=Function number already in use
|
message:E2012=Function number already in use
|
||||||
|
message:E2018=Timeout, no echo within %1ms
|
||||||
|
message:E2019=Timeout, no response within %1ms
|
||||||
message:E9001=%1 (During execution of %2 event handler)
|
message:E9001=%1 (During execution of %2 event handler)
|
||||||
message:E9999=%1
|
message:E9999=%1
|
||||||
message:F1001=Opening TCP socket failed (%1)
|
message:F1001=Opening TCP socket failed (%1)
|
||||||
|
|||||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren