From bcda9ae7068f010ce1ae2f71d25e36ea14554400 Mon Sep 17 00:00:00 2001 From: HeavenVR Date: Tue, 14 Apr 2026 18:22:18 +0200 Subject: [PATCH 1/2] Release 1.5.1 Hotfix release addressing a safety-critical E-Stop bypass. Shocker commands were still being transmitted after E-Stop activation because the estop state was only consulted on the transition edge in the RF transmit task, commands enqueued after activation fell through to a normal transmit. Two gates now bracket the RF queue: - CommandHandler::HandleCommand rejects commands up front when IsEStopped(), covering both the gateway (ShockerCommandList) and serial (rftransmit) entry paths. - RFTransmitter::TransmitTask immediately terminates in-flight sequences, then discards any further commands pulled from the queue until E-Stop is deactivated. The task goes dormant once the terminators have been sent. --- CHANGELOG.md | 13 +++++++++++++ frontend/package.json | 2 +- src/CommandHandler.cpp | 5 +++++ src/radio/RFTransmitter.cpp | 12 ++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a00972ea..2bed4e22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# Version 1.5.1 Release Notes + +Hotfix release addressing a safety-critical E-Stop bypass. + +### Bug Fixes + +- **E-Stop** - Fixed shocker commands being transmitted while E-Stop was active. Commands are now rejected at the entry point (`CommandHandler::HandleCommand`) and discarded in the RF transmit task's receive loop when E-Stop is engaged. + +**Full Changelog: [1.5.0 -> 1.5.1](https://github.com/OpenShock/Firmware/compare/1.5.0...1.5.1)** + + + + # Version 1.5.0 Release Notes This release is a major firmware update bringing a fully reworked RF transmitter pipeline for more reliable shocker communication, a new T330 shocker protocol, an RFC 8908-compliant captive portal, a rebuilt frontend (Svelte 5 + shadcn), and significant improvements to E-Stop handling and rate limiting. diff --git a/frontend/package.json b/frontend/package.json index e5967eb8..55bbfd2d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "frontend", - "version": "1.5.0", + "version": "1.5.1", "private": true, "type": "module", "scripts": { diff --git a/src/CommandHandler.cpp b/src/CommandHandler.cpp index d1150c57..21fc0145 100644 --- a/src/CommandHandler.cpp +++ b/src/CommandHandler.cpp @@ -293,6 +293,11 @@ gpio_num_t CommandHandler::GetRfTxPin() bool CommandHandler::HandleCommand(ShockerModelType model, uint16_t shockerId, ShockerCommandType type, uint8_t intensity, uint16_t durationMs) { + if (EStopManager::IsEStopped()) { + OS_LOGD(TAG, "Ignoring shocker command due to EmergencyStop being activated"); + return false; + } + ScopedReadLock lock__rf(&s_rfTransmitterMutex); if (s_rfTransmitter == nullptr) { diff --git a/src/radio/RFTransmitter.cpp b/src/radio/RFTransmitter.cpp index 8456931c..be1d0634 100644 --- a/src/radio/RFTransmitter.cpp +++ b/src/radio/RFTransmitter.cpp @@ -219,6 +219,17 @@ void RFTransmitter::TransmitTask() return; } + // Discard any command received while estopped + if (OpenShock::EStopManager::IsEStopped()) { + // Immidiatley break out to stop sequences, we cna empty queue later + if (!wasEstopped) { + break; + } + + // Discard next item in queue + continue; + } + if ((cmd.flags & kFlagOverwrite) != 0) { // Replace the sequence if it already exists if (modifySequence(sequences, cmd.modelType, cmd.shockerId, cmd.type, cmd.intensity, cmd.transmitEnd)) { @@ -231,6 +242,7 @@ void RFTransmitter::TransmitTask() } } + // Terminate all remaining sequences bool isEstopped = OpenShock::EStopManager::IsEStopped(); if (isEstopped != wasEstopped) { wasEstopped = isEstopped; From 0acd68b0083abae99a544ab69ae4e9abcf0ac593 Mon Sep 17 00:00:00 2001 From: HeavenVR Date: Tue, 14 Apr 2026 18:28:51 +0200 Subject: [PATCH 2/2] Update src/radio/RFTransmitter.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/radio/RFTransmitter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/radio/RFTransmitter.cpp b/src/radio/RFTransmitter.cpp index be1d0634..a78408d9 100644 --- a/src/radio/RFTransmitter.cpp +++ b/src/radio/RFTransmitter.cpp @@ -221,7 +221,7 @@ void RFTransmitter::TransmitTask() // Discard any command received while estopped if (OpenShock::EStopManager::IsEStopped()) { - // Immidiatley break out to stop sequences, we cna empty queue later + // Immediately break out to stop sequences; we can empty the queue later if (!wasEstopped) { break; }