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..a78408d9 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()) { + // Immediately break out to stop sequences; we can empty the 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;