Skip to content

Commit

Permalink
yasolr_init_relays()
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieucarbou committed Dec 31, 2024
1 parent 31bec2c commit c5d0f41
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 88 deletions.
9 changes: 5 additions & 4 deletions include/yasolr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
7 changes: 7 additions & 0 deletions lib/MycilaRouter/MycilaRouterRelay.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
49 changes: 1 addition & 48 deletions src/todo/yasolr_router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<float> voltage = grid.getVoltage();

Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
}
6 changes: 4 additions & 2 deletions src/yasolr_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
23 changes: 12 additions & 11 deletions src/yasolr_dashboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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()));
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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

Expand Down
11 changes: 7 additions & 4 deletions src/yasolr_display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -103,13 +106,13 @@ void yasolr_init_display() {
display->home.printf("Grid Power: %5d W\n", static_cast<int>(round(grid.getPower().orElse(0))));
display->home.printf("Routed Power: %5d W\n", static_cast<int>(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;
}

Expand Down
9 changes: 9 additions & 0 deletions src/yasolr_ds18.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ void yasolr_init_ds18() {
});
} else {
logger.error(TAG, "DS18 system probe failed to initialize!");
ds18Sys->end();
delete ds18Sys;
ds18Sys = nullptr;
}
}

Expand All @@ -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;
}
}

Expand All @@ -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;
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/yasolr_jsy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion src/yasolr_lights.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
18 changes: 10 additions & 8 deletions src/yasolr_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
});

Expand Down Expand Up @@ -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));
Expand Down
6 changes: 6 additions & 0 deletions src/yasolr_pzem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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;
}
}

Expand Down
Loading

0 comments on commit c5d0f41

Please sign in to comment.