From c5d0f41b0b59850740a7cfe3310bdadbc2eeef7e Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 31 Dec 2024 01:07:17 +0100 Subject: [PATCH] yasolr_init_relays() --- include/yasolr.h | 9 +-- lib/MycilaRouter/MycilaRouterRelay.h | 7 +++ src/main.cpp | 1 + src/todo/yasolr_router.cpp | 49 +-------------- src/yasolr_config.cpp | 6 +- src/yasolr_dashboard.cpp | 23 +++---- src/yasolr_display.cpp | 11 ++-- src/yasolr_ds18.cpp | 9 +++ src/yasolr_jsy.cpp | 3 + src/yasolr_lights.cpp | 2 +- src/yasolr_mqtt.cpp | 18 +++--- src/yasolr_pzem.cpp | 6 ++ src/yasolr_relay.cpp | 94 ++++++++++++++++++++++++++++ src/yasolr_web_server.cpp | 24 ++++--- 14 files changed, 174 insertions(+), 88 deletions(-) create mode 100644 src/yasolr_relay.cpp diff --git a/include/yasolr.h b/include/yasolr.h index 707b327e..6d7f488e 100644 --- a/include/yasolr.h +++ b/include/yasolr.h @@ -137,18 +137,19 @@ extern void yasolr_init_system(); // Trial extern void yasolr_init_trial(); +// Relays +extern Mycila::RouterRelay* relay1; +extern Mycila::RouterRelay* relay2; +extern void yasolr_init_relays(); + // router extern Mycila::Dimmer dimmerO1; extern Mycila::Dimmer dimmerO2; extern Mycila::PID pidController; extern Mycila::Relay bypassRelayO1; extern Mycila::Relay bypassRelayO2; -extern Mycila::Relay relay1; -extern Mycila::Relay relay2; extern Mycila::Router router; extern Mycila::RouterOutput output1; extern Mycila::RouterOutput output2; -extern Mycila::RouterRelay routerRelay1; -extern Mycila::RouterRelay routerRelay2; extern void yasolr_divert(); extern void yasolr_init_router(); diff --git a/lib/MycilaRouter/MycilaRouterRelay.h b/lib/MycilaRouter/MycilaRouterRelay.h index 7ab5ad26..e0187fae 100644 --- a/lib/MycilaRouter/MycilaRouterRelay.h +++ b/lib/MycilaRouter/MycilaRouterRelay.h @@ -13,6 +13,7 @@ namespace Mycila { void setLoad(uint16_t load) { _load = load; } + bool isEnabled() const { return _relay->isEnabled(); } bool isAutoRelayEnabled() const { return _relay->isEnabled() && _load > 0; } bool tryRelayState(bool state, uint32_t duration = 0); @@ -21,6 +22,12 @@ namespace Mycila { bool isOn() const { return _relay->isOn(); } bool isOff() const { return _relay->isOff(); } + uint64_t getSwitchCount() const { return _relay->getSwitchCount(); } + +#ifdef MYCILA_JSON_SUPPORT + void toJson(const JsonObject& root) const { _relay->toJson(root); } +#endif + private: Mycila::Relay* _relay; uint16_t _load = 0; diff --git a/src/main.cpp b/src/main.cpp index 0b2bed9a..6bfa9da9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ void setup() { yasolr_init_mqtt(); yasolr_init_network(); yasolr_init_pzem(); + yasolr_init_relays(); yasolr_init_trial(); yasolr_init_web_server(); yasolr_init_zcd(); diff --git a/src/todo/yasolr_router.cpp b/src/todo/yasolr_router.cpp index 31999f05..743c3cd6 100644 --- a/src/todo/yasolr_router.cpp +++ b/src/todo/yasolr_router.cpp @@ -13,34 +13,11 @@ Mycila::Dimmer dimmerO1; Mycila::Dimmer dimmerO2; Mycila::Relay bypassRelayO1; Mycila::Relay bypassRelayO2; -Mycila::Relay relay1; -Mycila::Relay relay2; -Mycila::RouterRelay routerRelay1(relay1); -Mycila::RouterRelay routerRelay2(relay2); Mycila::RouterOutput output1("output1", dimmerO1, bypassRelayO1); Mycila::RouterOutput output2("output2", dimmerO2, bypassRelayO2); Mycila::Task calibrationTask("Calibration", [](void* params) { router.calibrate(); }); -Mycila::Task relayTask("Relay", [](void* params) { - if (grid.getPower().isAbsent()) - return; - - Mycila::Router::Metrics routerMetrics; - router.getRouterMeasurements(routerMetrics); - - float virtualGridPower = grid.getPower().get() - routerMetrics.power; - - if (routerRelay1.tryRelayStateAuto(true, virtualGridPower)) - return; - if (routerRelay2.tryRelayStateAuto(true, virtualGridPower)) - return; - if (routerRelay2.tryRelayStateAuto(false, virtualGridPower)) - return; - if (routerRelay1.tryRelayStateAuto(false, virtualGridPower)) - return; -}); - Mycila::Task routerTask("Router", [](void* params) { std::optional voltage = grid.getVoltage(); @@ -123,14 +100,6 @@ void yasolr_init_router() { bypassRelayO1.begin(config.getLong(KEY_PIN_OUTPUT1_RELAY), config.isEqual(KEY_OUTPUT1_RELAY_TYPE, YASOLR_RELAY_TYPE_NC) ? Mycila::RelayType::NC : Mycila::RelayType::NO); if (config.getBool(KEY_ENABLE_OUTPUT2_RELAY)) bypassRelayO2.begin(config.getLong(KEY_PIN_OUTPUT2_RELAY), config.isEqual(KEY_OUTPUT2_RELAY_TYPE, YASOLR_RELAY_TYPE_NC) ? Mycila::RelayType::NC : Mycila::RelayType::NO); - if (config.getBool(KEY_ENABLE_RELAY1)) - relay1.begin(config.getLong(KEY_PIN_RELAY1), config.isEqual(KEY_RELAY1_TYPE, YASOLR_RELAY_TYPE_NC) ? Mycila::RelayType::NC : Mycila::RelayType::NO); - if (config.getBool(KEY_ENABLE_RELAY2)) - relay2.begin(config.getLong(KEY_PIN_RELAY2), config.isEqual(KEY_RELAY2_TYPE, YASOLR_RELAY_TYPE_NC) ? Mycila::RelayType::NC : Mycila::RelayType::NO); - - // Relays - routerRelay1.setLoad(config.getLong(KEY_RELAY1_LOAD)); - routerRelay2.setLoad(config.getLong(KEY_RELAY2_LOAD)); // Router router.addOutput(output1); @@ -146,32 +115,16 @@ void yasolr_init_router() { if (mqttPublishTask) mqttPublishTask->requestEarlyRun(); }); - relay1.listen([](bool state) { - logger.info(TAG, "Relay 1 changed to %s", state ? "ON" : "OFF"); - if (mqttPublishTask) - mqttPublishTask->requestEarlyRun(); - }); - relay2.listen([](bool state) { - logger.info(TAG, "Relay 2 changed to %s", state ? "ON" : "OFF"); - if (mqttPublishTask) - mqttPublishTask->requestEarlyRun(); - }); // coreTaskManager calibrationTask.setEnabledWhen([]() { return router.isCalibrationRunning(); }); calibrationTask.setInterval(1 * Mycila::TaskDuration::SECONDS); calibrationTask.setManager(coreTaskManager); - relayTask.setEnabledWhen([]() { return !router.isCalibrationRunning() && (routerRelay1.isAutoRelayEnabled() || routerRelay2.isAutoRelayEnabled()); }); - relayTask.setInterval(7 * Mycila::TaskDuration::SECONDS); - relayTask.setManager(coreTaskManager); - routerTask.setEnabledWhen([]() { return !router.isCalibrationRunning(); }); routerTask.setInterval(500 * Mycila::TaskDuration::MILLISECONDS); routerTask.setManager(coreTaskManager); - if (config.getBool(KEY_ENABLE_DEBUG)) { + if (config.getBool(KEY_ENABLE_DEBUG)) calibrationTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS); - relayTask.enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS); - } } diff --git a/src/yasolr_config.cpp b/src/yasolr_config.cpp index c7883553..0637aab6 100644 --- a/src/yasolr_config.cpp +++ b/src/yasolr_config.cpp @@ -130,10 +130,12 @@ void yasolr_init_config() { const std::string key = k; if (key == KEY_RELAY1_LOAD) { - routerRelay1.setLoad(config.getLong(KEY_RELAY1_LOAD)); + if (relay1) + relay1->setLoad(config.getLong(KEY_RELAY1_LOAD)); } else if (key == KEY_RELAY2_LOAD) { - routerRelay2.setLoad(config.getLong(KEY_RELAY2_LOAD)); + if (relay2) + relay2->setLoad(config.getLong(KEY_RELAY2_LOAD)); } else if (key == KEY_OUTPUT1_RESISTANCE) { output1.config.calibratedResistance = config.getFloat(KEY_OUTPUT1_RESISTANCE); diff --git a/src/yasolr_dashboard.cpp b/src/yasolr_dashboard.cpp index 62430017..d1471e87 100644 --- a/src/yasolr_dashboard.cpp +++ b/src/yasolr_dashboard.cpp @@ -319,8 +319,8 @@ void YaSolR::Website::begin() { _outputBypassSwitch(_output2Bypass, output2); _outputDimmerSlider(_output2DimmerSlider, output2); - _relaySwitch(_relay1Switch, routerRelay1); - _relaySwitch(_relay2Switch, routerRelay2); + _relaySwitch(_relay1Switch, *relay1); + _relaySwitch(_relay2Switch, *relay2); _output1PZEMSync.onChange([](bool value) { pzemO1PairingTask->resume(); @@ -958,8 +958,8 @@ void YaSolR::Website::initCards() { const uint16_t load1 = config.getInt(KEY_RELAY1_LOAD); const uint16_t load2 = config.getInt(KEY_RELAY2_LOAD); - const bool relay1Enabled = config.getBool(KEY_ENABLE_RELAY1) && relay1.isEnabled(); - const bool relay2Enabled = config.getBool(KEY_ENABLE_RELAY2) && relay2.isEnabled(); + const bool relay1Enabled = config.getBool(KEY_ENABLE_RELAY1) && relay1 && relay1->isEnabled(); + const bool relay2Enabled = config.getBool(KEY_ENABLE_RELAY2) && relay2 && relay2->isEnabled(); _relaysTab.setDisplay(relay1Enabled || relay2Enabled); _relay1Switch.setDisplay(relay1Enabled && load1 <= 0); _relay1SwitchRO.setDisplay(relay1Enabled && load1 > 0); @@ -1045,8 +1045,8 @@ void YaSolR::Website::initCards() { _status(_led, KEY_ENABLE_LIGHTS, lights.isEnabled()); _status(_output1Relay, KEY_ENABLE_OUTPUT1_RELAY, bypassRelayO1.isEnabled()); _status(_output2Relay, KEY_ENABLE_OUTPUT2_RELAY, bypassRelayO2.isEnabled()); - _status(_relay1, KEY_ENABLE_RELAY1, relay1.isEnabled()); - _status(_relay2, KEY_ENABLE_RELAY2, relay2.isEnabled()); + _status(_relay1, KEY_ENABLE_RELAY1, relay1 && relay1->isEnabled()); + _status(_relay2, KEY_ENABLE_RELAY2, relay2 && relay2->isEnabled()); // Hardware Config @@ -1184,8 +1184,8 @@ void YaSolR::Website::updateCards() { _gridFrequency.setValue(yasolr_frequency()); _networkWiFiRSSI.setValue(espConnect.getWiFiRSSI()); _networkWiFiSignal.setValue(espConnect.getWiFiSignalQuality()); - _relay1SwitchCount.setValue(relay1.getSwitchCount()); - _relay2SwitchCount.setValue(relay2.getSwitchCount()); + _relay1SwitchCount.setValue(relay1 ? relay1->getSwitchCount() : 0); + _relay2SwitchCount.setValue(relay2 ? relay2->getSwitchCount() : 0); _udpMessageRateBuffer.setValue(udpMessageRateBuffer ? udpMessageRateBuffer->rate() : 0); _time.setValue(Mycila::Time::getLocalStr()); _uptime.setValue(Mycila::Time::toDHHMMSS(Mycila::System::getUptime())); @@ -1252,8 +1252,8 @@ void YaSolR::Website::updateCards() { // relay - _relay1Switch.setValue(relay1.isOn()); - _relay2Switch.setValue(relay2.isOn()); + _relay1Switch.setValue(relay1 && relay1->isOn()); + _relay2Switch.setValue(relay1 && relay2->isOn()); // Hardware (config) @@ -1290,7 +1290,8 @@ void YaSolR::Website::updateCards() { // relays - _relay1SwitchRO.setFeedback(YASOLR_STATE(relay1.isOn()), relay1.isOn() ? dash::Status::SUCCESS : dash::Status::IDLE); + _relay1SwitchRO.setFeedback(YASOLR_STATE(relay1 && relay1->isOn()), relay1 && relay1->isOn() ? dash::Status::SUCCESS : dash::Status::IDLE); + _relay2SwitchRO.setFeedback(YASOLR_STATE(relay2 && relay2->isOn()), relay2 && relay2->isOn() ? dash::Status::SUCCESS : dash::Status::IDLE); // Hardware diff --git a/src/yasolr_display.cpp b/src/yasolr_display.cpp index 94df0a92..80a2f1b4 100644 --- a/src/yasolr_display.cpp +++ b/src/yasolr_display.cpp @@ -38,6 +38,9 @@ void yasolr_init_display() { if (!display->isEnabled()) { logger.error(TAG, "Display failed to initialize!"); + display->end(); + delete display; + display = nullptr; return; } @@ -103,13 +106,13 @@ void yasolr_init_display() { display->home.printf("Grid Power: %5d W\n", static_cast(round(grid.getPower().orElse(0)))); display->home.printf("Routed Power: %5d W\n", static_cast(round(routerMetrics.power))); if (config.getLong(KEY_RELAY1_LOAD)) - display->home.printf(relay1.isOn() ? "Relay 1: on %6ld W\n" : "Relay 1: off %6ld W\n", config.getLong(KEY_RELAY1_LOAD)); + display->home.printf(relay1 && relay1->isOn() ? "Relay 1: on %6ld W\n" : "Relay 1: off %6ld W\n", config.getLong(KEY_RELAY1_LOAD)); else - display->home.printf(relay1.isOn() ? "Relay 1: on\n" : "Relay 1: off\n"); + display->home.printf(relay1 && relay1->isOn() ? "Relay 1: on\n" : "Relay 1: off\n"); if (config.getLong(KEY_RELAY2_LOAD)) - display->home.printf(relay2.isOn() ? "Relay 2: on %6ld W\n" : "Relay 2: off %6ld W\n", config.getLong(KEY_RELAY2_LOAD)); + display->home.printf(relay2 && relay2->isOn() ? "Relay 2: on %6ld W\n" : "Relay 2: off %6ld W\n", config.getLong(KEY_RELAY2_LOAD)); else - display->home.printf(relay2.isOn() ? "Relay 2: on\n" : "Relay 2: off\n"); + display->home.printf(relay2 && relay2->isOn() ? "Relay 2: on\n" : "Relay 2: off\n"); break; } diff --git a/src/yasolr_ds18.cpp b/src/yasolr_ds18.cpp index e316c94a..f2f1cf92 100644 --- a/src/yasolr_ds18.cpp +++ b/src/yasolr_ds18.cpp @@ -30,6 +30,9 @@ void yasolr_init_ds18() { }); } else { logger.error(TAG, "DS18 system probe failed to initialize!"); + ds18Sys->end(); + delete ds18Sys; + ds18Sys = nullptr; } } @@ -51,6 +54,9 @@ void yasolr_init_ds18() { }); } else { logger.error(TAG, "DS18 output 1 probe failed to initialize!"); + ds18O1->end(); + delete ds18O1; + ds18O1 = nullptr; } } @@ -73,6 +79,9 @@ void yasolr_init_ds18() { ds18O2 = new Mycila::DS18(); } else { logger.error(TAG, "DS18 output 2 probe failed to initialize!"); + ds18O2->end(); + delete ds18O2; + ds18O2 = nullptr; } } diff --git a/src/yasolr_jsy.cpp b/src/yasolr_jsy.cpp index ec3c3cee..6ba3bc43 100644 --- a/src/yasolr_jsy.cpp +++ b/src/yasolr_jsy.cpp @@ -21,6 +21,9 @@ void yasolr_init_jsy() { if (!jsy->isEnabled()) { logger.error(TAG, "JSY failed to initialize!"); + jsy->end(); + delete jsy; + jsy = nullptr; return; } diff --git a/src/yasolr_lights.cpp b/src/yasolr_lights.cpp index cb233dad..e46bba4d 100644 --- a/src/yasolr_lights.cpp +++ b/src/yasolr_lights.cpp @@ -24,7 +24,7 @@ Mycila::Task lightsTask("Lights", [](void* params) { lights.setGreen(true); - lights.setYellow(relay1.isOn() || relay2.isOn() || bypassRelayO1.isOn() || bypassRelayO2.isOn() || dimmerO1.isOn() || dimmerO2.isOn()); + lights.setYellow((relay1 && relay1->isOn()) || (relay2 && relay2->isOn()) || bypassRelayO1.isOn() || bypassRelayO2.isOn() || dimmerO1.isOn() || dimmerO2.isOn()); if (!grid.isConnected()) { lights.setRed(true); diff --git a/src/yasolr_mqtt.cpp b/src/yasolr_mqtt.cpp index 5b9dec67..70498a06 100644 --- a/src/yasolr_mqtt.cpp +++ b/src/yasolr_mqtt.cpp @@ -73,27 +73,27 @@ void subscribe() { // relays mqtt->subscribe(baseTopic + "/router/relay1/set", [](const std::string& topic, const std::string_view& payload) { - if (relay1.isEnabled()) { + if (relay1 && relay1->isEnabled()) { const std::string_view state = payload.substr(0, payload.find("=")); if (state.empty()) return; if (state == YASOLR_ON) - routerRelay1.tryRelayState(true); + relay1->tryRelayState(true); else if (state == YASOLR_OFF) - routerRelay1.tryRelayState(false); + relay1->tryRelayState(false); } }); mqtt->subscribe(baseTopic + "/router/relay2/set", [](const std::string& topic, const std::string_view& payload) { - if (relay2.isEnabled()) { + if (relay2 && relay2->isEnabled()) { const std::string_view state = payload.substr(0, payload.find("=")); if (state.empty()) return; if (state == YASOLR_ON) - routerRelay2.tryRelayState(true); + relay2->tryRelayState(true); else if (state == YASOLR_OFF) - routerRelay2.tryRelayState(false); + relay2->tryRelayState(false); } }); @@ -277,8 +277,10 @@ void publishData() { mqtt->publish(baseTopic + "/router/lights", lights.toString()); mqtt->publish(baseTopic + "/router/power_factor", isnan(routerMeasurements.powerFactor) ? "0" : std::to_string(routerMeasurements.powerFactor)); mqtt->publish(baseTopic + "/router/power", std::to_string(routerMeasurements.power)); - mqtt->publish(baseTopic + "/router/relay1", YASOLR_STATE(relay1.isOn())); - mqtt->publish(baseTopic + "/router/relay2", YASOLR_STATE(relay2.isOn())); + if (relay1) + mqtt->publish(baseTopic + "/router/relay1", YASOLR_STATE(relay1->isOn())); + if (relay2) + mqtt->publish(baseTopic + "/router/relay2", YASOLR_STATE(relay2->isOn())); if (ds18Sys) mqtt->publish(baseTopic + "/router/temperature", std::to_string(ds18Sys->getTemperature().value_or(0))); mqtt->publish(baseTopic + "/router/thdi", isnan(routerMeasurements.thdi) ? "0" : std::to_string(routerMeasurements.thdi)); diff --git a/src/yasolr_pzem.cpp b/src/yasolr_pzem.cpp index 9f637ffb..96078ed3 100644 --- a/src/yasolr_pzem.cpp +++ b/src/yasolr_pzem.cpp @@ -85,6 +85,9 @@ void yasolr_init_pzem() { } else { logger.error(TAG, "Failed to initialize PZEM for Output 1!"); + pzemO1->end(); + delete pzemO1; + pzemO1 = nullptr; } } @@ -158,6 +161,9 @@ void yasolr_init_pzem() { } else { logger.error(TAG, "Failed to initialize PZEM for Output 2!"); + pzemO2->end(); + delete pzemO2; + pzemO2 = nullptr; } } diff --git a/src/yasolr_relay.cpp b/src/yasolr_relay.cpp new file mode 100644 index 00000000..a4b271e3 --- /dev/null +++ b/src/yasolr_relay.cpp @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + * Copyright (C) 2023-2024 Mathieu Carbou + */ +#include +#include + +Mycila::RouterRelay* relay1; +Mycila::RouterRelay* relay2; +Mycila::Task* relayTask; + +void yasolr_init_relays() { + logger.info(TAG, "Initialize relays..."); + uint8_t count = 0; + + if (config.getBool(KEY_ENABLE_RELAY1)) { + assert(!relay1); + + Mycila::Relay* relay = new Mycila::Relay(); + relay->begin(config.getLong(KEY_PIN_RELAY1), config.isEqual(KEY_RELAY1_TYPE, YASOLR_RELAY_TYPE_NC) ? Mycila::RelayType::NC : Mycila::RelayType::NO); + + if (relay->isEnabled()) { + count++; + + relay1 = new Mycila::RouterRelay(*relay); + relay1->setLoad(config.getLong(KEY_RELAY1_LOAD)); + + relay->listen([](bool state) { + logger.info(TAG, "Relay 1 changed to %s", state ? "ON" : "OFF"); + if (mqttPublishTask) + mqttPublishTask->requestEarlyRun(); + }); + + } else { + logger.error(TAG, "Relay 1 failed to initialize!"); + relay->end(); + delete relay1; + relay1 = nullptr; + } + } + + if (config.getBool(KEY_ENABLE_RELAY2)) { + assert(!relay2); + + Mycila::Relay* relay = new Mycila::Relay(); + relay->begin(config.getLong(KEY_PIN_RELAY2), config.isEqual(KEY_RELAY2_TYPE, YASOLR_RELAY_TYPE_NC) ? Mycila::RelayType::NC : Mycila::RelayType::NO); + + if (relay->isEnabled()) { + count++; + + relay2 = new Mycila::RouterRelay(*relay); + relay2->setLoad(config.getLong(KEY_RELAY2_LOAD)); + + relay->listen([](bool state) { + logger.info(TAG, "Relay 2 changed to %s", state ? "ON" : "OFF"); + if (mqttPublishTask) + mqttPublishTask->requestEarlyRun(); + }); + + } else { + logger.error(TAG, "Relay 2 failed to initialize!"); + relay->end(); + delete relay2; + relay2 = nullptr; + } + } + + if (count) { + relayTask = new Mycila::Task("Relay", [](void* params) { + if (grid.getPower().isAbsent()) + return; + + Mycila::Router::Metrics routerMetrics; + router.getRouterMeasurements(routerMetrics); + + float virtualGridPower = grid.getPower().get() - routerMetrics.power; + + if (relay1 && relay1->tryRelayStateAuto(true, virtualGridPower)) + return; + if (relay2 && relay2->tryRelayStateAuto(true, virtualGridPower)) + return; + if (relay2 && relay2->tryRelayStateAuto(false, virtualGridPower)) + return; + if (relay1 && relay1->tryRelayStateAuto(false, virtualGridPower)) + return; + }); + + relayTask->setEnabledWhen([]() { return !router.isCalibrationRunning() && ((relay1 && relay1->isAutoRelayEnabled()) || (relay2 && relay2->isAutoRelayEnabled())); }); + relayTask->setInterval(7 * Mycila::TaskDuration::SECONDS); + relayTask->setManager(coreTaskManager); + if (config.getBool(KEY_ENABLE_DEBUG)) + relayTask->enableProfiling(10, Mycila::TaskTimeUnit::MILLISECONDS); + } +} diff --git a/src/yasolr_web_server.cpp b/src/yasolr_web_server.cpp index 525353d0..885641e1 100644 --- a/src/yasolr_web_server.cpp +++ b/src/yasolr_web_server.cpp @@ -108,8 +108,10 @@ void rest_api() { pulseAnalyzer->toJson(root["pulse_analyzer"].to()); // relays - relay1.toJson(root["relay1"].to()); - relay2.toJson(root["relay2"].to()); + if (relay1) + relay1->toJson(root["relay1"].to()); + if (relay2) + relay2->toJson(root["relay2"].to()); // router router.toJson(root["router"].to(), voltage); @@ -366,24 +368,24 @@ void rest_api() { webServer .on("/api/router/relay1", HTTP_POST, [](AsyncWebServerRequest* request) { - if (relay1.isEnabled() && request->hasParam("state", true)) { + if (relay1 && relay1->isEnabled() && request->hasParam("state", true)) { std::string state = request->getParam("state", true)->value().c_str(); if (state == YASOLR_ON) - routerRelay1.tryRelayState(true); + relay1->tryRelayState(true); else if (state == YASOLR_OFF) - routerRelay1.tryRelayState(false); + relay1->tryRelayState(false); } request->send(200); }); webServer .on("/api/router/relay2", HTTP_POST, [](AsyncWebServerRequest* request) { - if (relay2.isEnabled() && request->hasParam("state", true)) { + if (relay2 && relay2->isEnabled() && request->hasParam("state", true)) { std::string state = request->getParam("state", true)->value().c_str(); if (state == YASOLR_ON) - routerRelay2.tryRelayState(true); + relay2->tryRelayState(true); else if (state == YASOLR_OFF) - routerRelay2.tryRelayState(false); + relay2->tryRelayState(false); } request->send(200); }); @@ -439,8 +441,10 @@ void rest_api() { router.getRouterMeasurements(routerMeasurements); root["lights"] = lights.toString(); - root["relay1"] = YASOLR_STATE(relay1.isOn()); - root["relay2"] = YASOLR_STATE(relay2.isOn()); + if (relay1) + root["relay1"] = YASOLR_STATE(relay1->isOn()); + if (relay2) + root["relay2"] = YASOLR_STATE(relay2->isOn()); if (ds18Sys) { float t = ds18Sys->getTemperature().value_or(NAN); if (!isnanf(t))