mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 22:02:17 +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;
|
float markFreq = 433.0f;
|
||||||
int markRSSI = -100;
|
int markRSSI = -100;
|
||||||
uint32_t lastScan = 0;
|
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() {
|
void Transceiver::beginFrequencyScan() {
|
||||||
// The scan retunes the radio so nothing may transmit until it ends. This
|
// 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.
|
// 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) {
|
if(this->config.enabled) {
|
||||||
this->disableReceive();
|
this->disableReceive();
|
||||||
rxmode = 3;
|
rxmode = 3;
|
||||||
|
scanStart = millis();
|
||||||
pinMode(this->config.RXPin, INPUT);
|
pinMode(this->config.RXPin, INPUT);
|
||||||
interruptPin = digitalPinToInterrupt(this->config.RXPin);
|
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.
|
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);
|
if(interruptPin > 0) detachInterrupt(interruptPin);
|
||||||
interruptPin = 0;
|
interruptPin = 0;
|
||||||
this->config.apply();
|
this->config.apply();
|
||||||
this->resumeTx(TX_SUSPEND_SCAN);
|
|
||||||
this->emitFrequencyScan();
|
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) {
|
void Transceiver::emitFrequencyScan(uint8_t num) {
|
||||||
JsonSockEvent *json = sockEmit.beginEmit("frequencyScan");
|
JsonSockEvent *json = sockEmit.beginEmit("frequencyScan");
|
||||||
|
|
@ -4770,7 +4776,8 @@ bool Transceiver::save() {
|
||||||
}
|
}
|
||||||
bool Transceiver::end() {
|
bool Transceiver::end() {
|
||||||
// Nothing may transmit (and re-enable receive) after this. It is not
|
// 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);
|
this->suspendTx(TX_SUSPEND_OTA);
|
||||||
RadioLock lock(portMAX_DELAY, true);
|
RadioLock lock(portMAX_DELAY, true);
|
||||||
this->disableReceive();
|
this->disableReceive();
|
||||||
|
|
@ -5011,7 +5018,13 @@ void transceiver_config_t::apply() {
|
||||||
// be reconfigured. Queued frames are already encoded and go out with the
|
// be reconfigured. Queued frames are already encoded and go out with the
|
||||||
// new settings.
|
// new settings.
|
||||||
RadioLock lock(portMAX_DELAY, true);
|
RadioLock lock(portMAX_DELAY, true);
|
||||||
|
// Reconfiguring the radio ends a frequency scan so TX may resume.
|
||||||
|
const bool wasScanning = rxmode == 3;
|
||||||
somfy.transceiver.disableReceive();
|
somfy.transceiver.disableReceive();
|
||||||
|
if(wasScanning) {
|
||||||
|
somfy.transceiver.resumeTx(TX_SUSPEND_SCAN);
|
||||||
|
somfy.transceiver.emitFrequencyScan();
|
||||||
|
}
|
||||||
bit_length = this->type;
|
bit_length = this->type;
|
||||||
if(this->enabled) {
|
if(this->enabled) {
|
||||||
bool radioInit = true;
|
bool radioInit = true;
|
||||||
|
|
@ -5136,6 +5149,10 @@ void Transceiver::loop() {
|
||||||
noiseCount = 0;
|
noiseCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(rxmode == 3 && millis() - scanStart > SCAN_MAX_MS) {
|
||||||
|
ESP_LOGW(TAG, "Frequency scan timed out");
|
||||||
|
this->endFrequencyScan();
|
||||||
|
}
|
||||||
if(rxmode == 3) {
|
if(rxmode == 3) {
|
||||||
if(this->receive(&rx))
|
if(this->receive(&rx))
|
||||||
this->processFrequencyScan(true);
|
this->processFrequencyScan(true);
|
||||||
|
|
|
||||||
24
src/Web.cpp
24
src/Web.cpp
|
|
@ -64,10 +64,24 @@ static bool queueUnpairShade(SomfyShade *shade) {
|
||||||
shade->paired = false;
|
shade->paired = false;
|
||||||
return true;
|
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.
|
// Sent when a command can't be handed to the main loop.
|
||||||
static void sendQueueFull(AsyncWebServerRequest *request) {
|
static void sendQueueFull(AsyncWebServerRequest *request) {
|
||||||
request->send(503, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Command queue full\"}"));
|
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 asyncServer(80);
|
||||||
AsyncWebServer asyncApiServer(8081);
|
AsyncWebServer asyncApiServer(8081);
|
||||||
|
|
@ -2136,6 +2150,7 @@ void Web::begin() {
|
||||||
else {
|
else {
|
||||||
somfy.transceiver.end();
|
somfy.transceiver.end();
|
||||||
mqtt.end();
|
mqtt.end();
|
||||||
|
request->onDisconnect(onUploadDisconnect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
|
|
@ -2201,6 +2216,7 @@ void Web::begin() {
|
||||||
else {
|
else {
|
||||||
somfy.transceiver.end();
|
somfy.transceiver.end();
|
||||||
mqtt.end();
|
mqtt.end();
|
||||||
|
request->onDisconnect(onUploadDisconnect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
|
|
@ -2331,8 +2347,10 @@ void Web::begin() {
|
||||||
frame.cmd = translateSomfyCommand(scmd.c_str());
|
frame.cmd = translateSomfyCommand(scmd.c_str());
|
||||||
}
|
}
|
||||||
if(frame.remoteAddress > 0 && frame.rollingCode > 0) {
|
if(frame.remoteAddress > 0 && frame.rollingCode > 0) {
|
||||||
somfy.sendFrame(frame, repeats);
|
if(somfy.sendFrame(frame, repeats))
|
||||||
request->send(200, _encoding_json, F("{\"status\":\"SUCCESS\",\"desc\":\"Command Sent\"}"));
|
request->send(200, _encoding_json, F("{\"status\":\"SUCCESS\",\"desc\":\"Command Sent\"}"));
|
||||||
|
else
|
||||||
|
sendRadioUnavailable(request);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
request->send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"No address or rolling code provided\"}"));
|
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(asyncHasParam(request, "repeats")) repeats = atoi(asyncParam(request, "repeats").c_str());
|
||||||
}
|
}
|
||||||
if(frame.remoteAddress > 0 && frame.rollingCode > 0) {
|
if(frame.remoteAddress > 0 && frame.rollingCode > 0) {
|
||||||
somfy.sendFrame(frame, repeats);
|
if(somfy.sendFrame(frame, repeats))
|
||||||
request->send(200, _encoding_json, F("{\"status\":\"SUCCESS\",\"desc\":\"Command Sent\"}"));
|
request->send(200, _encoding_json, F("{\"status\":\"SUCCESS\",\"desc\":\"Command Sent\"}"));
|
||||||
|
else
|
||||||
|
sendRadioUnavailable(request);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
request->send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"No address or rolling code provided\"}"));
|
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