mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 13:52:15 +01:00
fix: never leave radio TX suspended after a scan or aborted OTA
- endFrequencyScan always resumes TX; applying radio settings ends a scan. - Frequency scans time out after 5 minutes. - Reboot when an OTA upload is abandoned mid-transfer. - /sendRemoteCommand returns 503 when the radio can't take the frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e55d9e48f7
commit
2a54740f52
2 changed files with 43 additions and 6 deletions
|
|
@ -4553,6 +4553,10 @@ int currRSSI = -100;
|
|||
float markFreq = 433.0f;
|
||||
int markRSSI = -100;
|
||||
uint32_t lastScan = 0;
|
||||
static uint32_t scanStart = 0;
|
||||
// A scan nobody ended (closed browser tab) stops on its own after this long so
|
||||
// the radio doesn't stay unable to transmit.
|
||||
#define SCAN_MAX_MS 300000
|
||||
void Transceiver::beginFrequencyScan() {
|
||||
// The scan retunes the radio so nothing may transmit until it ends. This
|
||||
// also aborts a transmission in flight so the lock below is never held long.
|
||||
|
|
@ -4561,6 +4565,7 @@ void Transceiver::beginFrequencyScan() {
|
|||
if(this->config.enabled) {
|
||||
this->disableReceive();
|
||||
rxmode = 3;
|
||||
scanStart = millis();
|
||||
pinMode(this->config.RXPin, INPUT);
|
||||
interruptPin = digitalPinToInterrupt(this->config.RXPin);
|
||||
ELECHOUSE_cc1101.setRxBW(this->config.rxBandwidth); // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz.
|
||||
|
|
@ -4608,9 +4613,10 @@ void Transceiver::endFrequencyScan() {
|
|||
if(interruptPin > 0) detachInterrupt(interruptPin);
|
||||
interruptPin = 0;
|
||||
this->config.apply();
|
||||
this->resumeTx(TX_SUSPEND_SCAN);
|
||||
this->emitFrequencyScan();
|
||||
}
|
||||
// Even if something else already ended the scan, nothing may keep TX suspended.
|
||||
this->resumeTx(TX_SUSPEND_SCAN);
|
||||
}
|
||||
void Transceiver::emitFrequencyScan(uint8_t num) {
|
||||
JsonSockEvent *json = sockEmit.beginEmit("frequencyScan");
|
||||
|
|
@ -4770,7 +4776,8 @@ bool Transceiver::save() {
|
|||
}
|
||||
bool Transceiver::end() {
|
||||
// Nothing may transmit (and re-enable receive) after this. It is not
|
||||
// resumed since the only caller is OTA which always reboots.
|
||||
// resumed since the only caller is OTA, which reboots when the upload
|
||||
// completes, fails or is abandoned.
|
||||
this->suspendTx(TX_SUSPEND_OTA);
|
||||
RadioLock lock(portMAX_DELAY, true);
|
||||
this->disableReceive();
|
||||
|
|
@ -5011,7 +5018,13 @@ void transceiver_config_t::apply() {
|
|||
// be reconfigured. Queued frames are already encoded and go out with the
|
||||
// new settings.
|
||||
RadioLock lock(portMAX_DELAY, true);
|
||||
// Reconfiguring the radio ends a frequency scan so TX may resume.
|
||||
const bool wasScanning = rxmode == 3;
|
||||
somfy.transceiver.disableReceive();
|
||||
if(wasScanning) {
|
||||
somfy.transceiver.resumeTx(TX_SUSPEND_SCAN);
|
||||
somfy.transceiver.emitFrequencyScan();
|
||||
}
|
||||
bit_length = this->type;
|
||||
if(this->enabled) {
|
||||
bool radioInit = true;
|
||||
|
|
@ -5136,6 +5149,10 @@ void Transceiver::loop() {
|
|||
noiseCount = 0;
|
||||
}
|
||||
}
|
||||
if(rxmode == 3 && millis() - scanStart > SCAN_MAX_MS) {
|
||||
ESP_LOGW(TAG, "Frequency scan timed out");
|
||||
this->endFrequencyScan();
|
||||
}
|
||||
if(rxmode == 3) {
|
||||
if(this->receive(&rx))
|
||||
this->processFrequencyScan(true);
|
||||
|
|
|
|||
28
src/Web.cpp
28
src/Web.cpp
|
|
@ -64,10 +64,24 @@ static bool queueUnpairShade(SomfyShade *shade) {
|
|||
shade->paired = false;
|
||||
return true;
|
||||
}
|
||||
// The radio and MQTT are shut down once an upload starts and only a reboot
|
||||
// brings them back. The completion handler schedules it but never runs if the
|
||||
// client goes away mid-upload, so make sure the device reboots then too.
|
||||
static void onUploadDisconnect() {
|
||||
if(webServer.uploadSuccess || rebootDelay.reboot) return;
|
||||
ESP_LOGW(TAG, "Upload abandoned, rebooting");
|
||||
if(Update.isRunning()) Update.abort();
|
||||
rebootDelay.reboot = true;
|
||||
rebootDelay.rebootTime = millis() + 500;
|
||||
}
|
||||
// Sent when a command can't be handed to the main loop.
|
||||
static void sendQueueFull(AsyncWebServerRequest *request) {
|
||||
request->send(503, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Command queue full\"}"));
|
||||
}
|
||||
// Sent when the radio can't take a frame (suspended or queue full).
|
||||
static void sendRadioUnavailable(AsyncWebServerRequest *request) {
|
||||
request->send(503, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Radio TX unavailable\"}"));
|
||||
}
|
||||
|
||||
AsyncWebServer asyncServer(80);
|
||||
AsyncWebServer asyncApiServer(8081);
|
||||
|
|
@ -2136,6 +2150,7 @@ void Web::begin() {
|
|||
else {
|
||||
somfy.transceiver.end();
|
||||
mqtt.end();
|
||||
request->onDisconnect(onUploadDisconnect);
|
||||
}
|
||||
}
|
||||
if(len > 0) {
|
||||
|
|
@ -2201,6 +2216,7 @@ void Web::begin() {
|
|||
else {
|
||||
somfy.transceiver.end();
|
||||
mqtt.end();
|
||||
request->onDisconnect(onUploadDisconnect);
|
||||
}
|
||||
}
|
||||
if(len > 0) {
|
||||
|
|
@ -2331,8 +2347,10 @@ void Web::begin() {
|
|||
frame.cmd = translateSomfyCommand(scmd.c_str());
|
||||
}
|
||||
if(frame.remoteAddress > 0 && frame.rollingCode > 0) {
|
||||
somfy.sendFrame(frame, repeats);
|
||||
request->send(200, _encoding_json, F("{\"status\":\"SUCCESS\",\"desc\":\"Command Sent\"}"));
|
||||
if(somfy.sendFrame(frame, repeats))
|
||||
request->send(200, _encoding_json, F("{\"status\":\"SUCCESS\",\"desc\":\"Command Sent\"}"));
|
||||
else
|
||||
sendRadioUnavailable(request);
|
||||
}
|
||||
else
|
||||
request->send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"No address or rolling code provided\"}"));
|
||||
|
|
@ -2348,8 +2366,10 @@ void Web::begin() {
|
|||
if(asyncHasParam(request, "repeats")) repeats = atoi(asyncParam(request, "repeats").c_str());
|
||||
}
|
||||
if(frame.remoteAddress > 0 && frame.rollingCode > 0) {
|
||||
somfy.sendFrame(frame, repeats);
|
||||
request->send(200, _encoding_json, F("{\"status\":\"SUCCESS\",\"desc\":\"Command Sent\"}"));
|
||||
if(somfy.sendFrame(frame, repeats))
|
||||
request->send(200, _encoding_json, F("{\"status\":\"SUCCESS\",\"desc\":\"Command Sent\"}"));
|
||||
else
|
||||
sendRadioUnavailable(request);
|
||||
}
|
||||
else
|
||||
request->send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"No address or rolling code provided\"}"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue