From 2a45dba37aa9dedc4d6fea21330e8d531df1e873 Mon Sep 17 00:00:00 2001 From: cjkas Date: Sun, 11 Oct 2026 12:46:40 +0200 Subject: [PATCH] fix: cap repeats per radio job to keep loop under the WDT The radio task bit-bangs a whole job on loop()'s core at a higher priority. A job with 127+ repeats ran for 18-36s without loop() ever running and the 15s task watchdog rebooted the device. Limit a job to 50 repeats (about 7s) in encodeTxJob, which every send path goes through, and advance the 80-bit repeat counter by the number of frames actually queued. Co-Authored-By: Claude Opus 5.5 --- src/Somfy.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Somfy.cpp b/src/Somfy.cpp index 23a1eac..b5def87 100644 --- a/src/Somfy.cpp +++ b/src/Somfy.cpp @@ -38,6 +38,10 @@ uint8_t rxmode = 0; // Indicates whether the radio is in receive mode. Just to #define SETMY_REPEATS 35 #define TILT_REPEATS 15 +// The radio task bit-bangs a whole job on loop()'s core at a higher priority +// so loop() only runs between jobs. A frame takes about 140ms so this keeps a +// job around 7s, well inside the 15s task watchdog loop() is subscribed to. +#define TX_MAX_REPEATS 50 #define TX_QUEUE_DELAY 100 #define TX_TASK_PRIORITY 5 #define TX_TASK_STACK 4096 @@ -110,6 +114,10 @@ static void encodeTxJob(somfy_tx_job_t &job, somfy_frame_t &frame, uint8_t repea job.tx.hwsync = frame.bitLength == 56 ? 2 : 12; job.tx.bit_length = frame.bitLength; job.frame = frame; + if(repeat > TX_MAX_REPEATS) { + ESP_LOGW(TAG, "Limiting %u repeats to %u", repeat, TX_MAX_REPEATS); + repeat = TX_MAX_REPEATS; + } job.repeats = repeat; } // Commands that can set a shade moving. @@ -4074,8 +4082,8 @@ bool SomfyRemote::repeatFrame(uint8_t repeat) { job.firstRepeat = this->lastFrame.repeats + 2; // Only advance the counter for frames that will go on air. if(!somfy.transceiver.queueTx(job)) return false; - this->lastFrame.repeats += repeat + 1; this->lastBackTxSeq = job.seq; + this->lastFrame.repeats += job.repeats + 1; //somfy.processFrame(this->lastFrame, true); return true; }