mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-08-10 12:12:15 +02:00
Fix: radio stays permanently disabled after an init hang
When the CC1101 init hangs and the watchdog reboots the ESP, the NVS "radioInit" flag is left false. transceiver_config_t::apply() then did "if(!radioInit) return;" on every subsequent boot without ever resetting the flag, so the radio was never re-initialized again. The web UI and the HA websocket keep working, but no RF is transmitted and shades stop responding - a reboot does not help because each boot reads false again. Only a /saveRadio POST recovered it. This retries init for up to 3 consecutive incomplete boots and only then gives up (booting cleanly with the radio off to avoid a hard boot loop). The counter resets on a successful init or a /saveRadio POST. Also stop advancing the rolling code while the radio is not initialized, otherwise commands issued during the dead window drift the stored code ahead of the motor and desync the remote once the radio recovers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
eb75868adb
commit
7aa869198d
1 changed files with 34 additions and 6 deletions
40
Somfy.cpp
40
Somfy.cpp
|
|
@ -4087,6 +4087,15 @@ bool SomfyShadeController::deleteGroup(uint8_t groupId) {
|
||||||
|
|
||||||
bool SomfyShadeController::loadShadesFile(const char *filename) { return ShadeConfigFile::load(this, filename); }
|
bool SomfyShadeController::loadShadesFile(const char *filename) { return ShadeConfigFile::load(this, filename); }
|
||||||
uint16_t SomfyRemote::getNextRollingCode() {
|
uint16_t SomfyRemote::getNextRollingCode() {
|
||||||
|
// Do not advance the rolling code when the radio is not initialized. Otherwise
|
||||||
|
// commands issued while the radio is down (see the radioInit recovery logic in
|
||||||
|
// transceiver_config_t::apply) keep incrementing the stored code without ever
|
||||||
|
// transmitting, which drifts it ahead of what the motor expects and desyncs the
|
||||||
|
// remote once the radio comes back.
|
||||||
|
if(!somfy.transceiver.config.radioInit) {
|
||||||
|
Serial.println("WARNING: Radio not initialized - rolling code NOT incremented");
|
||||||
|
return this->lastRollingCode > 0 ? this->lastRollingCode : 1;
|
||||||
|
}
|
||||||
pref.begin("ShadeCodes");
|
pref.begin("ShadeCodes");
|
||||||
uint16_t code = pref.getUShort(this->m_remotePrefId, 0);
|
uint16_t code = pref.getUShort(this->m_remotePrefId, 0);
|
||||||
code++;
|
code++;
|
||||||
|
|
@ -4840,6 +4849,7 @@ void transceiver_config_t::save() {
|
||||||
pref.putFloat("rxBandwidth", this->rxBandwidth); // float
|
pref.putFloat("rxBandwidth", this->rxBandwidth); // float
|
||||||
pref.putBool("enabled", this->enabled);
|
pref.putBool("enabled", this->enabled);
|
||||||
pref.putBool("radioInit", true);
|
pref.putBool("radioInit", true);
|
||||||
|
pref.putUChar("initCrashes", 0); // Saving config is an explicit user action - clear the crash counter.
|
||||||
pref.putChar("txPower", this->txPower);
|
pref.putChar("txPower", this->txPower);
|
||||||
pref.putChar("proto", static_cast<uint8_t>(this->proto));
|
pref.putChar("proto", static_cast<uint8_t>(this->proto));
|
||||||
|
|
||||||
|
|
@ -4961,14 +4971,31 @@ void transceiver_config_t::apply() {
|
||||||
somfy.transceiver.disableReceive();
|
somfy.transceiver.disableReceive();
|
||||||
bit_length = this->type;
|
bit_length = this->type;
|
||||||
if(this->enabled) {
|
if(this->enabled) {
|
||||||
bool radioInit = true;
|
|
||||||
pref.begin("CC1101");
|
pref.begin("CC1101");
|
||||||
radioInit = pref.getBool("radioInit", true);
|
bool radioInit = pref.getBool("radioInit", true);
|
||||||
// If the radio locks up then we can simply reboot and re-enable the radio.
|
uint8_t initCrashes = pref.getUChar("initCrashes", 0);
|
||||||
pref.putBool("radioInit", false);
|
// If a previous boot hung during CC1101 init the "radioInit" flag was left
|
||||||
|
// false. The original code returned here without ever resetting the flag, so
|
||||||
|
// EVERY subsequent boot skipped radio init -> the radio stayed dead until a
|
||||||
|
// /saveRadio POST. Instead we retry init for up to 3 consecutive crashes and
|
||||||
|
// only then give up (to avoid a hard boot loop with truly dead hardware).
|
||||||
|
// The counter is reset on a successful init or a /saveRadio POST.
|
||||||
|
if(!radioInit) {
|
||||||
|
initCrashes++;
|
||||||
|
if(initCrashes >= 3) {
|
||||||
|
pref.putUChar("initCrashes", initCrashes);
|
||||||
|
pref.end();
|
||||||
|
this->radioInit = false;
|
||||||
|
Serial.printf("CC1101 init skipped after %u consecutive crashes - POST /saveRadio to reset\n", initCrashes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Serial.printf("CC1101 init did not complete last boot (%u/3), retrying...\n", initCrashes);
|
||||||
|
}
|
||||||
|
else initCrashes = 0;
|
||||||
|
pref.putUChar("initCrashes", initCrashes);
|
||||||
|
pref.putBool("radioInit", false); // Mark init as in-progress; reset to true once it completes.
|
||||||
this->radioInit = false;
|
this->radioInit = false;
|
||||||
pref.end();
|
pref.end();
|
||||||
if(!radioInit) return;
|
|
||||||
Serial.print("Applying radio settings ");
|
Serial.print("Applying radio settings ");
|
||||||
Serial.printf("Setting Data Pins RX:%u TX:%u\n", this->RXPin, this->TXPin);
|
Serial.printf("Setting Data Pins RX:%u TX:%u\n", this->RXPin, this->TXPin);
|
||||||
//if(this->TXPin != this->RXPin)
|
//if(this->TXPin != this->RXPin)
|
||||||
|
|
@ -5027,8 +5054,9 @@ void transceiver_config_t::apply() {
|
||||||
}
|
}
|
||||||
pref.begin("CC1101");
|
pref.begin("CC1101");
|
||||||
pref.putBool("radioInit", true);
|
pref.putBool("radioInit", true);
|
||||||
|
pref.putUChar("initCrashes", 0); // Init completed - clear the crash counter.
|
||||||
pref.end();
|
pref.end();
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(this->radioInit) ELECHOUSE_cc1101.setSidle();
|
if(this->radioInit) ELECHOUSE_cc1101.setSidle();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue