From 0dbb1da2bf03a5a3ed3dd145b2c50e851444f42d Mon Sep 17 00:00:00 2001 From: cjkas Date: Mon, 30 Mar 2026 09:22:22 +0200 Subject: [PATCH] Tsury noise detection --- data-src/index.html | 4 + data-src/index.js | 2 +- src/ConfigFile.cpp | 6 +- src/Somfy.cpp | 34 ++++++++- src/SomfyController.ino.cpp | 147 ++++++++++++++++++++++++++++++++++++ src/Web.cpp | 1 + 6 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 src/SomfyController.ino.cpp diff --git a/data-src/index.html b/data-src/index.html index 616a1c2..e46ab30 100644 --- a/data-src/index.html +++ b/data-src/index.html @@ -913,6 +913,10 @@ +
+ + +
diff --git a/data-src/index.js b/data-src/index.js index d2400e8..46f0a39 100644 --- a/data-src/index.js +++ b/data-src/index.js @@ -1954,7 +1954,7 @@ class Somfy { this.loadPins('input', document.getElementById('selTransRXPin')); //this.loadSomfy(); ui.toElement(document.getElementById('divTransceiverSettings'), { - transceiver: { config: { proto: 0, SCKPin: 18, CSNPin: 5, MOSIPin: 23, MISOPin: 19, TXPin: 12, RXPin: 13, frequency: 433.42, rxBandwidth: 97.96, type: 56, deviation: 11.43, txPower: 10, enabled: false } } + transceiver: { config: { proto: 0, SCKPin: 18, CSNPin: 5, MOSIPin: 23, MISOPin: 19, TXPin: 12, RXPin: 13, frequency: 433.42, rxBandwidth: 97.96, type: 56, deviation: 11.43, txPower: 10, enabled: false, noiseDetection: false } } }); this.loadPins('out', document.getElementById('selShadeGPIOUp')); this.loadPins('out', document.getElementById('selShadeGPIODown')); diff --git a/src/ConfigFile.cpp b/src/ConfigFile.cpp index d496632..5dc1801 100644 --- a/src/ConfigFile.cpp +++ b/src/ConfigFile.cpp @@ -708,7 +708,8 @@ bool ShadeConfigFile::readTransRecord(transceiver_config_t &cfg) { cfg.frequency = this->readFloat(cfg.frequency); cfg.rxBandwidth = this->readFloat(cfg.rxBandwidth); cfg.deviation = this->readFloat(cfg.deviation); - cfg.txPower = this->readInt8(cfg.txPower); + cfg.txPower = this->readInt8(cfg.txPower); + cfg.noiseDetection = this->readBool(false); if(this->file.position() != startPos + this->header.transRecordSize) { ESP_LOGD(TAG, "Reading to end of transceiver record"); this->seekChar(CFG_REC_END); @@ -1065,7 +1066,8 @@ bool ShadeConfigFile::writeTransRecord(transceiver_config_t &cfg) { this->writeFloat(cfg.frequency, 3); this->writeFloat(cfg.rxBandwidth, 2); this->writeFloat(cfg.deviation, 2); - this->writeInt8(cfg.txPower, CFG_REC_END); + this->writeInt8(cfg.txPower); + this->writeBool(cfg.noiseDetection, CFG_REC_END); return true; } bool ShadeConfigFile::exists() { return LittleFS.exists("/shades.cfg"); } diff --git a/src/Somfy.cpp b/src/Somfy.cpp index 7a8ad51..c5c3e31 100644 --- a/src/Somfy.cpp +++ b/src/Somfy.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "driver/gpio.h" #include "esp_log.h" #include "Utils.h" #include "ConfigSettings.h" @@ -45,6 +46,9 @@ int sort_asc(const void *cmp1, const void *cmp2) { } static int interruptPin = 0; +static volatile bool noiseDetected = false; +static volatile unsigned long noiseStart = 0; +static volatile uint32_t noiseCount = 0; static uint8_t bit_length = 56; somfy_commands translateSomfyCommand(const String& string) { if (string.equalsIgnoreCase("My")) return somfy_commands::My; @@ -4187,6 +4191,21 @@ void Transceiver::sendFrame(byte *frame, uint8_t sync, uint8_t bitLength) { } } void RECEIVE_ATTR Transceiver::handleReceive() { + if (noiseDetected) return; + if (somfy.transceiver.config.noiseDetection) { + unsigned long now = millis(); + if (noiseStart == 0) noiseStart = now; + if (now - noiseStart >= 10000) { + noiseStart = now; + noiseCount = 0; + } + noiseCount++; + if (noiseCount > 100) { + gpio_intr_disable((gpio_num_t)interruptPin); + noiseDetected = true; + return; + } + } static unsigned long last_time = 0; const long time = micros(); const unsigned int duration = time - last_time; @@ -4358,7 +4377,7 @@ void Transceiver::processFrequencyScan(bool received) { currRSSI = -100; } - if(millis() - lastScan > 100 && somfy_rx.status == waiting_synchro) { + if(millis() - lastScan > 100 && (somfy_rx.status == waiting_synchro || noiseDetected)) { lastScan = millis(); this->emitFrequencyScan(); currFreq += 0.01f; @@ -4538,6 +4557,7 @@ void transceiver_config_t::fromJSON(JsonObject& obj) { if(!obj["enabled"].isNull()) this->enabled = obj["enabled"]; if(!obj["txPower"].isNull()) this->txPower = obj["txPower"]; if(!obj["proto"].isNull()) this->proto = static_cast(obj["proto"].as()); + if(!obj["noiseDetection"].isNull()) this->noiseDetection = obj["noiseDetection"]; /* if (!obj["internalCCMode"].isNull()) this->internalCCMode = obj["internalCCMode"]; if (!obj["modulationMode"].isNull()) this->modulationMode = obj["modulationMode"]; @@ -4625,7 +4645,8 @@ void transceiver_config_t::save() { pref.putBool("radioInit", true); pref.putChar("txPower", this->txPower); pref.putChar("proto", static_cast(this->proto)); - + pref.putBool("noiseDetect", this->noiseDetection); + /* pref.putBool("internalCCMode", this->internalCCMode); pref.putUChar("modulationMode", this->modulationMode); @@ -4724,6 +4745,7 @@ void transceiver_config_t::load() { this->txPower = pref.getChar("txPower", this->txPower); this->rxBandwidth = pref.getFloat("rxBandwidth", this->rxBandwidth); this->proto = static_cast(pref.getChar("proto", static_cast(this->proto))); + this->noiseDetection = pref.getBool("noiseDetect", false); this->removeNVSKey("internalCCMode"); this->removeNVSKey("modulationMode"); this->removeNVSKey("channel"); @@ -4857,6 +4879,14 @@ bool Transceiver::begin() { } void Transceiver::loop() { somfy_rx_t rx; + if (noiseDetected && rxmode != 3 && this->config.noiseDetection) { + if (millis() - noiseStart > 100) { + gpio_intr_enable((gpio_num_t)interruptPin); + noiseDetected = false; + noiseStart = 0; + noiseCount = 0; + } + } if(rxmode == 3) { if(this->receive(&rx)) this->processFrequencyScan(true); diff --git a/src/SomfyController.ino.cpp b/src/SomfyController.ino.cpp new file mode 100644 index 0000000..ce50111 --- /dev/null +++ b/src/SomfyController.ino.cpp @@ -0,0 +1,147 @@ +# 1 "C:\\Users\\oem\\AppData\\Local\\Temp\\tmpahrx2jqr" +#include +# 1 "C:/Users/oem/Documents/PlatformIO/Projects/ESPSomfy-RTS/src/SomfyController.ino" +#include "esp_log.h" +#include +#include +#include +#include "ConfigSettings.h" +#include "ESPNetwork.h" +#include "Web.h" +#include "Sockets.h" +#include "Utils.h" +#include "Somfy.h" +#include "MQTT.h" +#include "GitOTA.h" +#include "esp_core_dump.h" + +static const char *TAG = "Main"; + +ConfigSettings settings; +Web webServer; +SocketEmitter sockEmit; +ESPNetwork net; +rebootDelay_t rebootDelay; +SomfyShadeController somfy; +MQTTClass mqtt; +GitUpdater git; + +uint32_t oldheap = 0; +void listDir(const char *dirname, uint8_t levels); +void setup(); +void loop(); +#line 28 "C:/Users/oem/Documents/PlatformIO/Projects/ESPSomfy-RTS/src/SomfyController.ino" +void listDir(const char *dirname, uint8_t levels) { + ESP_LOGI(TAG, "Listing: %s", dirname); + File root = LittleFS.open(dirname); + if (!root || !root.isDirectory()) { + ESP_LOGE(TAG, "Failed to open directory"); + return; + } + File file = root.openNextFile(); + while (file) { + if (file.isDirectory()) { + ESP_LOGI(TAG, " DIR : %s", file.name()); + if (levels) listDir(file.path(), levels - 1); + } else { + ESP_LOGI(TAG, " FILE: %-30s %d bytes", file.name(), file.size()); + } + file = root.openNextFile(); + } +} + +void setup() { + Serial.begin(115200); + ESP_LOGI(TAG, "Startup/Boot...."); + esp_core_dump_summary_t summary; + if (esp_core_dump_get_summary(&summary) == ESP_OK) { + ESP_LOGW(TAG, "*** Previous crash coredump found ***"); + ESP_LOGW(TAG, " Task: %s", summary.exc_task); + ESP_LOGW(TAG, " PC: 0x%08x", summary.exc_pc); +#ifdef CONFIG_IDF_TARGET_ARCH_XTENSA + ESP_LOGW(TAG, " Cause: %d", summary.ex_info.exc_cause); + char bt_buf[256] = {0}; + int pos = 0; + for (int i = 0; i < summary.exc_bt_info.depth; i++) { + pos += snprintf(bt_buf + pos, sizeof(bt_buf) - pos, " 0x%08x", summary.exc_bt_info.bt[i]); + } + ESP_LOGW(TAG, " Backtrace:%s", bt_buf); +#elif CONFIG_IDF_TARGET_ARCH_RISCV + ESP_LOGW(TAG, " Cause: %d", summary.ex_info.mcause); + ESP_LOGW(TAG, " MTVAL: 0x%08x RA: 0x%08x SP: 0x%08x", + summary.ex_info.mtval, summary.ex_info.ra, summary.ex_info.sp); +#endif + } + ESP_LOGI(TAG, "Mounting File System..."); + + + if (LittleFS.begin()) { + ESP_LOGI(TAG, "Total: %d bytes", LittleFS.totalBytes()); + ESP_LOGI(TAG, "Used: %d bytes", LittleFS.usedBytes()); + ESP_LOGI(TAG, "Free: %d bytes", LittleFS.totalBytes() - LittleFS.usedBytes()); + listDir("/", 3); + } else { + ESP_LOGE(TAG, "LittleFS mount failed!"); + } + + if(LittleFS.begin()) ESP_LOGI(TAG, "File system mounted successfully"); + else ESP_LOGE(TAG, "Error mounting file system"); + settings.begin(); + if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true); + delay(10); + webServer.startup(); + webServer.begin(); + delay(1000); + net.setup(); + somfy.begin(); + +#if ESP_ARDUINO_VERSION_MAJOR >= 3 + const esp_task_wdt_config_t wdt_config = { .timeout_ms = 15000, .idle_core_mask = 1, .trigger_panic = true }; + esp_task_wdt_init(&wdt_config); +#else + esp_task_wdt_init(15, true); +#endif + esp_task_wdt_add(NULL); + +} + +void loop() { + + + if(rebootDelay.reboot && millis() > rebootDelay.rebootTime) { + ESP_LOGI(TAG, "Rebooting after %lums", rebootDelay.rebootTime); + net.end(); + ESP.restart(); + return; + } + uint32_t timing = millis(); + + net.loop(); + if(millis() - timing > 100) ESP_LOGD(TAG, "Timing Net: %ldms", millis() - timing); + timing = millis(); + esp_task_wdt_reset(); + somfy.loop(); + if(millis() - timing > 100) ESP_LOGD(TAG, "Timing Somfy: %ldms", millis() - timing); + timing = millis(); + esp_task_wdt_reset(); + if(net.connected() || net.softAPOpened) { + if(!rebootDelay.reboot && net.connected() && !net.softAPOpened) { + git.loop(); + esp_task_wdt_reset(); + } + webServer.loop(); + esp_task_wdt_reset(); + if(millis() - timing > 100) ESP_LOGD(TAG, "Timing WebServer: %ldms", millis() - timing); + esp_task_wdt_reset(); + timing = millis(); + sockEmit.loop(); + if(millis() - timing > 100) ESP_LOGD(TAG, "Timing Socket: %ldms", millis() - timing); + esp_task_wdt_reset(); + timing = millis(); + } + if(rebootDelay.reboot && millis() > rebootDelay.rebootTime) { + net.end(); + ESP.restart(); + } + esp_task_wdt_reset(); +} \ No newline at end of file diff --git a/src/Web.cpp b/src/Web.cpp index 907f40f..ca40c14 100644 --- a/src/Web.cpp +++ b/src/Web.cpp @@ -374,6 +374,7 @@ static void serializeTransceiverConfig(JsonFormatter &json) { json.addElem("txPower", cfg.txPower); json.addElem("proto", static_cast(cfg.proto)); json.addElem("enabled", cfg.enabled); + json.addElem("noiseDetection", cfg.noiseDetection); json.addElem("radioInit", cfg.radioInit); } static void serializeAppVersion(JsonFormatter &json, appver_t &ver) {