From 7d7abd1566ec21dcb07ff49089d45ff03846c0f9 Mon Sep 17 00:00:00 2001 From: LucHeart Date: Mon, 25 May 2026 17:23:15 +0200 Subject: [PATCH 1/3] implementation --- include/GatewayClient.h | 3 +++ include/GatewayConnectionManager.h | 2 ++ src/GatewayClient.cpp | 15 +++++++++++++++ src/GatewayConnectionManager.cpp | 10 ++++++++++ src/message_handlers/websocket/gateway/Ping.cpp | 1 + 5 files changed, 31 insertions(+) diff --git a/include/GatewayClient.h b/include/GatewayClient.h index 9d516723..49458438 100644 --- a/include/GatewayClient.h +++ b/include/GatewayClient.h @@ -28,6 +28,8 @@ namespace OpenShock { bool sendMessageTXT(std::string_view data); bool sendMessageBIN(tcb::span data); + void markPingReceived(); + bool loop(); private: @@ -37,5 +39,6 @@ namespace OpenShock { WebSocketsClient m_webSocket; GatewayClientState m_state; + int64_t m_lastPingTimestamp; }; } // namespace OpenShock diff --git a/include/GatewayConnectionManager.h b/include/GatewayConnectionManager.h index fdff763d..060c9228 100644 --- a/include/GatewayConnectionManager.h +++ b/include/GatewayConnectionManager.h @@ -19,5 +19,7 @@ namespace OpenShock::GatewayConnectionManager { bool SendMessageTXT(std::string_view data); bool SendMessageBIN(tcb::span data); + void MarkPingReceived(); + void Update(); } // namespace OpenShock::GatewayConnectionManager diff --git a/src/GatewayClient.cpp b/src/GatewayClient.cpp index 1a656a7f..d1458a72 100644 --- a/src/GatewayClient.cpp +++ b/src/GatewayClient.cpp @@ -14,11 +14,14 @@ const char* const TAG = "GatewayClient"; using namespace OpenShock; +const int64_t GATEWAY_PING_TIMEOUT = 90'000; + static bool s_bootStatusSent = false; GatewayClient::GatewayClient(const std::string& authToken) : m_webSocket() , m_state(GatewayClientState::Disconnected) + , m_lastPingTimestamp(0) { OS_LOGD(TAG, "Creating GatewayClient"); @@ -90,6 +93,11 @@ bool GatewayClient::sendMessageBIN(tcb::span data) return m_webSocket.sendBIN(data.data(), data.size()); } +void GatewayClient::markPingReceived() +{ + m_lastPingTimestamp = OpenShock::millis(); +} + bool GatewayClient::loop() { if (m_state == GatewayClientState::Disconnected) { @@ -104,6 +112,13 @@ bool GatewayClient::loop() return true; } + if (m_lastPingTimestamp != 0 && (OpenShock::millis() - m_lastPingTimestamp) > GATEWAY_PING_TIMEOUT) { + OS_LOGW(TAG, "No ping received from gateway for %lld ms, forcing reconnect", GATEWAY_PING_TIMEOUT); + m_webSocket.disconnect(); + _setState(GatewayClientState::Disconnected); + return false; + } + return true; } diff --git a/src/GatewayConnectionManager.cpp b/src/GatewayConnectionManager.cpp index bcfa35df..270fd6ea 100644 --- a/src/GatewayConnectionManager.cpp +++ b/src/GatewayConnectionManager.cpp @@ -194,6 +194,16 @@ bool GatewayConnectionManager::SendMessageBIN(tcb::span data) return client->sendMessageBIN(data); } +void GatewayConnectionManager::MarkPingReceived() +{ + auto client = GetClient(); + if (client == nullptr) { + return; + } + + client->markPingReceived(); +} + bool FetchHubInfo(std::string authToken) { // TODO: this function is very slow, should be optimized! diff --git a/src/message_handlers/websocket/gateway/Ping.cpp b/src/message_handlers/websocket/gateway/Ping.cpp index 55d5ddf8..7c1b8e9d 100644 --- a/src/message_handlers/websocket/gateway/Ping.cpp +++ b/src/message_handlers/websocket/gateway/Ping.cpp @@ -18,5 +18,6 @@ void _Private::HandlePing(const OpenShock::Serialization::Gateway::GatewayToHubM return; } + GatewayConnectionManager::MarkPingReceived(); Serialization::Gateway::SerializePongMessage(GatewayConnectionManager::SendMessageBIN); } From 2882d0f6351f0ab4b219e9981316bc27faf3eebd Mon Sep 17 00:00:00 2001 From: LucHeart Date: Mon, 25 May 2026 17:34:42 +0200 Subject: [PATCH 2/3] fix: timeout not resetting on connect --- src/GatewayClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/GatewayClient.cpp b/src/GatewayClient.cpp index d1458a72..4eca8c26 100644 --- a/src/GatewayClient.cpp +++ b/src/GatewayClient.cpp @@ -175,6 +175,7 @@ void GatewayClient::_handleEvent(WStype_t type, uint8_t* payload, std::size_t le _setState(GatewayClientState::Disconnected); break; case WStype_CONNECTED: + m_lastPingTimestamp = 0; _setState(GatewayClientState::Connected); _sendBootStatus(); break; From 962b9ab3c7df0a93947cdd70283570ee1e6fb284 Mon Sep 17 00:00:00 2001 From: LucHeart Date: Mon, 25 May 2026 17:44:29 +0200 Subject: [PATCH 3/3] chore: add changeset --- .changeset/keepalive-timeout-reconnect.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/keepalive-timeout-reconnect.md diff --git a/.changeset/keepalive-timeout-reconnect.md b/.changeset/keepalive-timeout-reconnect.md new file mode 100644 index 00000000..9b94d190 --- /dev/null +++ b/.changeset/keepalive-timeout-reconnect.md @@ -0,0 +1,5 @@ +--- +'firmware': minor +--- + +feat: add a keepalive ping timeout that forces a reconnect on backend connection loss \ No newline at end of file