From e37aa583985aee047d3a28190a1a8dab7ecd7d17 Mon Sep 17 00:00:00 2001 From: Emanuele Trabattoni Date: Wed, 6 Aug 2025 09:49:46 +0200 Subject: [PATCH] OTA fixes + enable when network connected and switch pressed --- include/pinlist.h | 44 +++++++++++++++++++++++++++++++++++++++++--- platformio.ini | 13 +++++-------- src/commands.cpp | 20 ++++++++++++-------- src/commands.h | 44 +++++++++++--------------------------------- src/main.cpp | 23 +++++++++++++---------- src/ota.cpp | 31 +++++++++++++++++++------------ src/ota.h | 1 + 7 files changed, 102 insertions(+), 74 deletions(-) diff --git a/include/pinlist.h b/include/pinlist.h index 62f6f8f..109ca24 100644 --- a/include/pinlist.h +++ b/include/pinlist.h @@ -1,3 +1,41 @@ -#define DI_CONFRESET 0 -#define DI_RESTART 1 -#define DI_OTAENABLE 7 \ No newline at end of file + +enum RO // relay output channels +{ + P1 = 0, + P2 = 1, + P3 = 2, + P4 = 3, + RO_4 = 4, + FST_FLOOR = 5, + GND_FLOOR = 6, + PUMP_HT = 7, + PUMP_IRR = 8, + ZONE1 = 9, + ZONE2 = 10, + ZONE3 = 11, + DRIP = 12, + RETURN = 13, + RO_14 = 14, + RO_15 = 15, + RO_MAX = 16 // unused to detect invalid values +}; + +enum DI // digital input channels +{ + CONFRESET = 0, + RESTART = 1, + DI_2 = 2, + DI_3 = 3, + DI_4 = 4, + DI_6 = 6, + OTAENABLE = 7, + PUMP_PRESSURE = 8, + RAIN = 9, + IRR_OVERRIDE = 10, + DI_11 = 11, + DI_12 = 12, + DI_13 = 13, + DI_14 = 14, + DI_15 = 15, + DI_MAX = 16 +}; // unused to detect invalid values diff --git a/platformio.ini b/platformio.ini index c71fdbb..d2c1644 100644 --- a/platformio.ini +++ b/platformio.ini @@ -31,12 +31,11 @@ upload_port = 10.0.2.139 platform = ${env:esp32-s3-waveshare8.platform} board = ${env:esp32-s3-waveshare8.board} framework = ${env:esp32-s3-waveshare8.framework} -lib_deps = - bblanchon/ArduinoJson@^7.4.2 - arduino-libraries/NTPClient@^3.2.1 - knolleary/PubSubClient@^2.8 - robtillaart/CRC@^1.0.3 - hideakitai/DebugLog@^0.8.4 +lib_deps = ${env:esp32-s3-waveshare8.lib_deps} + +board_build.filesystem = ffat +board_build.partitions = fatfs_partition.csv ; se stai usando uno custom + build_type = debug build_flags = -O0 @@ -47,5 +46,3 @@ build_flags = -fno-tree-sra -fno-builtin -board_build.filesystem = ffat -board_build.partitions = fatfs_partition.csv ; se stai usando uno custom diff --git a/src/commands.cpp b/src/commands.cpp index ecb98ff..ef44773 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -264,7 +264,7 @@ namespace commands { devices_t *dev = (devices_t *)pvTimerGetTimerID(th); LOG_INFO("setIrrigation shutdown pump"); - dev->io.digitalOutWrite(RO::IRR_PUMP, false); + dev->io.digitalOutWrite(RO::PUMP_IRR, false); s_irrigationPumpTimer = NULL; xTimerDelete(th, 0); // delete the timer on expiry } @@ -340,7 +340,7 @@ namespace commands if (!s_irrigationPumpTimer) // Pump has not yet started { s_irrigationPumpTimer = xTimerCreate("pumpTimer", pdMS_TO_TICKS(pumpTime), false, (void *)&dev, resetWaterPump); - dev.io.digitalOutWrite(RO::IRR_PUMP, true); + dev.io.digitalOutWrite(RO::PUMP_IRR, true); xTimerStart(s_irrigationPumpTimer, 0); // immediate start pump timer LOG_INFO("setIrrigation pump time", pumpTime); } @@ -412,13 +412,15 @@ namespace commands ArduinoJson::JsonDocument response; response["cmd"] = "getInputStatus"; const std::vector inStatus(dev.io.digitalInReadPort()); - if (inStatus.empty() || inStatus.size() != dev.io.getInNum()) { + if (inStatus.empty() || inStatus.size() != dev.io.getInNum()) + { response["values"] = "invalid"; return response; } uint8_t i(0); - for (auto s: inStatus){ - const std::string k("DI"+std::to_string(i)); + for (auto s : inStatus) + { + const std::string k("DI" + std::to_string(i)); response["values"][k.c_str()] = s; } LOG_INFO("getInputStatus ->", printBoolVec(inStatus).c_str()); @@ -429,13 +431,15 @@ namespace commands ArduinoJson::JsonDocument response; response["cmd"] = "getOutputStatus"; const std::vector inStatus(dev.io.digitalOutReadPort()); - if (inStatus.empty() || inStatus.size() != dev.io.getOutNum()) { + if (inStatus.empty() || inStatus.size() != dev.io.getOutNum()) + { response["values"] = "invalid"; return response; } uint8_t i(0); - for (auto s: inStatus){ - const std::string k("DO"+std::to_string(i)); + for (auto s : inStatus) + { + const std::string k("DO" + std::to_string(i)); response["values"][k.c_str()] = s; } LOG_INFO("getOutputStatus ->", printBoolVec(inStatus).c_str()); diff --git a/src/commands.h b/src/commands.h index 0cd0c19..276ad16 100644 --- a/src/commands.h +++ b/src/commands.h @@ -8,30 +8,10 @@ #include #include +#include namespace commands { - enum RO // relay output channels - { - P1, - P2, - P3, - P4, - NC_1, - FST_FLOOR, - GND_FLOOR, - PUMP_HT, - IRR_PUMP, - Z1, - Z2, - Z3, - AUX, - RETURN, - NC_3, - NC_4, - RO_MAX // unused to detect invalid values - }; - static const std::map c_hpLimitsMap = {{"P1", RO::P1}, {"P2", RO::P2}, {"P3", RO::P3}, @@ -43,10 +23,10 @@ namespace commands {"ground", RO::GND_FLOOR}}; static const std::map c_irrigationValveMap = {{"ricircolo", RO::RETURN}, - {"zone1", RO::Z1}, - {"zone2", RO::Z2}, - {"zone3", RO::Z3}, - {"rubinetti", RO::AUX}}; + {"zone1", RO::ZONE1}, + {"zone2", RO::ZONE2}, + {"zone3", RO::ZONE3}, + {"rubinetti", RO::DRIP}}; static std::map> c_irrigationTimerMap = {{"ricircolo", {"ricircolo", NULL}}, {"zone1", {"zone1", NULL}}, @@ -97,28 +77,26 @@ namespace commands }; static const std::map s_commandMap = { - + // TEST {"setBuzz", Commands::setBuzz}, - + // CONFIG {"setConfig", Commands::setConfig}, {"getConfig", Commands::getConfig}, - + // CRONJOBS {"loadCronJob", Commands::loadCronJob}, {"setCronJob", Commands::setCronJob}, {"getCronJob", Commands::getCronJob}, {"delCronJob", Commands::delCronJob}, {"storeCronJob", Commands::storeCronJob}, - + // SETTERS {"setHPlimit", Commands::setHPlimit}, {"setHeating", Commands::setHeating}, {"setIrrigation", Commands::setIrrigation}, - + // GETTERS {"getHPpower", Commands::getHPpower}, - {"setHeating", Commands::setHeating}, - {"getInputStatus", Commands::getInputStatus}, {"getOutputStatus", Commands::getOutputStatus}, - + // NTP and Time {"getTimeDrift", Commands::getTimeDrift}, {"setTimeNTP", Commands::setTimeNTP}, }; diff --git a/src/main.cpp b/src/main.cpp index 2a91722..8b5a470 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,14 +55,6 @@ void loop() LOG_INFO("Temperature sensors connected ->", sensors); // Initialize OTA updater if needed auto ota = OTA(devices); - if (io.digitalInRead(DI_OTAENABLE)) { - buzzer.beepRepeat(25,25, NOTE_A); - delay(1000); - if (io.digitalInRead(DI_OTAENABLE)) { // maintain keyPress for 1s - ota.begin(); - } - buzzer.beep(100, NOTE_G); - } //////////////// DEVICES //////////////// //////////////// MQTT //////////////// @@ -134,6 +126,17 @@ void loop() led.setColor(led.COLOR_RED); return; } + if (io.digitalInRead(DI::OTAENABLE)) // Initialize OTA, BLUE + { + buzzer.beepRepeat(25, 25, NOTE_A); + delay(1000); + if (io.digitalInRead(DI::OTAENABLE)) + { // maintain keyPress for 1s + ota.begin(); + } + buzzer.beep(100, NOTE_G); + delay(100); + } // Get RTC time at ethernet connection time_t ntpTime; uint8_t timeRetries(0); @@ -198,7 +201,7 @@ void loop() mqtt.publish(conf.m_mqttPublish["temperatures"], ti); }; - if (io.digitalInRead(DI_CONFRESET)) // ROSSO - Config Reset + if (io.digitalInRead(DI::CONFRESET)) // ROSSO - Config Reset { LOG_WARN("Config RESET!"); buzzer.beep(450, NOTE_E); @@ -206,7 +209,7 @@ void loop() conf.resetConfig(); } - if (io.digitalInRead(DI_RESTART)) // GIALLO - Restart + if (io.digitalInRead(DI::RESTART)) // GIALLO - Restart { LOG_WARN("RESTART!"); buzzer.beep(450, NOTE_D); diff --git a/src/ota.cpp b/src/ota.cpp index 134a4ba..e785143 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -3,7 +3,7 @@ #define STACK_DEPTH 4096 #define TASK_PRIORITY 2 -OTA::OTA(const devices_t &dev) : m_dev(dev), m_taskHandle(NULL), m_updating(false) +OTA::OTA(const devices_t &dev) : m_dev(dev), m_taskHandle(NULL), m_updating(false), m_prevPercent(0) { LOG_WARN("OTA begin, waiting for connection on [", dev.eth.localIP().toString().c_str(), "]"); } @@ -26,15 +26,16 @@ void OTA::begin() ArduinoOTA.onEnd(s_onEnd); ArduinoOTA.onProgress(s_onProgress); ArduinoOTA.onError(s_onError); - if (!xTaskCreate(handle, "otaUpdate", STACK_DEPTH, this, TASK_PRIORITY, &m_taskHandle) != pdPASS) + if (xTaskCreate(handle, "otaUpdate", STACK_DEPTH, this, TASK_PRIORITY, &m_taskHandle) != pdPASS) { m_taskHandle = NULL; LOG_ERROR("OTA failed to create handle task"); } - ArduinoOTA.begin(); // start the OTA server + ArduinoOTA.begin(); // start the OTA server + m_dev.led.blinkAlternate(100, 100, m_dev.led.COLOR_ORANGE, m_dev.led.COLOR_SKYBLUE); m_dev.led.setEnforce(true); // take unique control of the LED - m_dev.led.blinkAlternate(50, 50, m_dev.led.COLOR_GREEN, m_dev.led.COLOR_YELLOW); m_active = true; + LOG_WARN("OTA started"); return; } @@ -64,7 +65,12 @@ bool OTA::isActive() void OTA::onProgress(const uint32_t progress, const uint32_t total) { - LOG_INFO("OTA progress [", (progress * 100.0f) / total, "]%"); + float percent = (progress * 100.0f) / total; + if (percent > m_prevPercent + 5.0f) + { + LOG_INFO("OTA progress [", percent, "]%"); + m_prevPercent = percent; + } } void OTA::onStart() { @@ -73,6 +79,7 @@ void OTA::onStart() m_dev.led.setEnforce(false); m_dev.led.blinkAlternate(25, 50, m_dev.led.COLOR_BLUE, m_dev.led.COLOR_OFF); m_dev.led.setEnforce(true); + m_prevPercent = 0; } void OTA::onEnd() { @@ -87,26 +94,26 @@ void OTA::onError(const ota_error_t err) LOG_ERROR("OTA Error [", err, "]"); switch (err) { - case OTA_AUTH_ERROR: + case OTA_AUTH_ERROR: LOG_ERROR("OTA authentication error"); break; - case OTA_BEGIN_ERROR: + case OTA_BEGIN_ERROR: LOG_ERROR("OTA begin errror"); break; - case OTA_CONNECT_ERROR: + case OTA_CONNECT_ERROR: LOG_ERROR("OTA connection error"); break; - case OTA_RECEIVE_ERROR: + case OTA_RECEIVE_ERROR: LOG_ERROR("OTA receive error"); break; - case OTA_END_ERROR: + case OTA_END_ERROR: LOG_ERROR("OTA end error"); break; - default: + default: LOG_ERROR("OTA unknown error"); }; m_updating = false; - end(); //end ota on error + end(); // end ota on error } void OTA::handle(void *params) diff --git a/src/ota.h b/src/ota.h index c47efa2..621d20c 100644 --- a/src/ota.h +++ b/src/ota.h @@ -30,6 +30,7 @@ private: TaskHandle_t m_taskHandle; bool m_updating; bool m_active; + float m_prevPercent; private: // callbacks, do not init in code ArduinoOTAClass::THandlerFunction s_onStart = [this]()