mirror of
https://github.com/nuttytree/ESPHome-Devices.git
synced 2024-08-30 18:12:19 +00:00
F/pool pumps refactor (#22)
This commit is contained in:
parent
cb0da23b6f
commit
c5b88c0c6f
25
README.md
25
README.md
@ -9,8 +9,22 @@ ESPHome is a system to control your ESP8266/ESP32 by simple yet powerful configu
|
||||
Home Assistant is open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server. For more information check out [Home-Assistant.io](https://www.home-assistant.io/).
|
||||
|
||||
|
||||
## Folder Structure
|
||||
* `build` - Technically not included in the repo but all of my devices are configured with this as their build path
|
||||
* `components` - Custom components
|
||||
* `custom` - Other custom code that are not components
|
||||
* `devices` - Yaml files for my devices
|
||||
* `other` - Other misc files
|
||||
* `packages` - Shared packages used by my devices
|
||||
* `scripts` - Couple of PowerShell scripts for managing the repo
|
||||
|
||||
|
||||
## Secrets Management
|
||||
You will notice that throughout the various folders I have secrets.yaml files. These files all do an include of the secrets.yaml file in the root folder (that for obvious reasons is not included in the repo). On my computer the secrets.yaml file in the root folder is a [symlink](https://en.wikipedia.org/wiki/Symbolic_link) to a file in my OneDrive folder. This way I have multiple backups of this file and don't have to worry about losing it and getting locked out of all my devices.
|
||||
|
||||
|
||||
## Custom Components
|
||||
I have been working on updating most of my custom code into components that can easily be pulled directly from GitHub into your device configuration using the [external components](https://esphome.io/components/external_components.html) component. I have run into frequent issues with changes in ESPHome breaking my components so I am now tagging my repo with the version of ESPHome it is compatible with. I generally upgrade pretty quickly so as soon as I have confirmed things are working and/or made the neccessary changes I will add a tag for the new version of ESPHome.
|
||||
I have been working on updating most of my custom code into components that can easily be pulled directly from GitHub into your device configuration using the [external components](https://esphome.io/components/external_components.html) component. I have run into frequent issues with changes in ESPHome breaking my components so I am now tagging my repo with the version of ESPHome it is compatible with. I generally upgrade pretty quickly so as soon as I have confirmed things are working and/or made the neccessary changes I will add a tag for the new version of ESPHome. While I primarily design these components for my own personal use cases I hope that at least some of them are useful for others. If you are using one of my components and have an enhancement/feature you would like to see feel free to add an issue and I will see what I can do to get it added.
|
||||
|
||||
### Binary Light With Power
|
||||
This an enhanced version of the standard [binary light](https://esphome.io/components/light/binary.html) component that adds an option to include a sensor to report current power usage based on a configured wattage of the light(s) it controls. More details on how to use this component are available [here](./components/binary_light_with_power/README.md).
|
||||
@ -18,14 +32,17 @@ This an enhanced version of the standard [binary light](https://esphome.io/compo
|
||||
### GPIO Light With Power
|
||||
This an enhanced version of the standard [gpio switch](https://esphome.io/components/switch/gpio.html) component that adds an option to include a sensor to report current power usage based on a configured wattage of the device(s) it controls. More details on how to use this component are available [here](./components/gpio_switch_with_power/README.md).
|
||||
|
||||
### Pool Controller
|
||||
This is component is curently running on a [Shelly 2.5 Double Relay Switch](https://shelly.cloud/products/shelly-25-smart-home-automation-relay/) and is used to control the main pump and the auxiliary pump (that runs a pool cleaner) on my pool. Eventually I want to expand this to run on an ESP32 and manage all aspects of my pool (pumps, lights, heat, fill, drain, pH, ORP, etc.). More details on how to use this component are available [here](./components/pool_controller/README.md).
|
||||
|
||||
### TREO LED Pool Light
|
||||
This is a custom light component that works with [TREO LED Pool Lights](https://www.srsmith.com/en-us/products/pool-lighting/treo-led-pool-light/) and exposes the different colors as "effects" so thay can be selected from Home Assistant. More details on how to use this component are available [here](./components/treo_led_pool_light/README.md).
|
||||
|
||||
### Tuya Dimmer as Fan
|
||||
This a modified version of the [Tuya fan](https://esphome.io/components/fan/tuya.html) component I use with [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1) (but it will likely work with other Tuya dimmers) to control bathroom fans and adds several features. I created this component because I couldn't find a regular on/off switch with the same look and feel as the Feit dimmers so I decided to use the Feit dimmers but use this component to prevent "dimming" the fan. More details on features and how to use this component are available [here](./components/tuya_dimmer_as_fan/README.md).
|
||||
This a modified version of the [Tuya fan](https://esphome.io/components/fan/tuya.html) component I use with [Feit Dimmers](https://www.feit.com/product/smart-wi-fi-dimmer/) (but it will likely work with other Tuya dimmers) to control bathroom fans and adds several features. I created this component because I couldn't find a regular on/off switch with the same look and feel as the Feit dimmers so I decided to use the Feit dimmers but use this component to prevent "dimming" the fan. More details on features and how to use this component are available [here](./components/tuya_dimmer_as_fan/README.md).
|
||||
|
||||
### Tuya Light Plus
|
||||
This an enhanced version of the standard [Tuya light](https://esphome.io/components/light/tuya.html) component that adds a bunch of extra features. I use this component with [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1) but it will likely work with other Tuya dimmers. More details on features and how to use this component are available [here](./components/tuya_light_plus/README.md).
|
||||
This an enhanced version of the standard [Tuya light](https://esphome.io/components/light/tuya.html) component that adds a bunch of extra features. I use this component with [Feit Dimmers](https://www.feit.com/product/smart-wi-fi-dimmer/) but it will likely work with other Tuya dimmers. More details on features and how to use this component are available [here](./components/tuya_light_plus/README.md).
|
||||
|
||||
### ESPSense
|
||||
This excellent component is not mine and doesn't live in this repository but most of my devices are using it so I felt it was worthy of a mention here. More details are available [here](https://github.com/cbpowell/ESPSense).
|
||||
@ -51,7 +68,7 @@ This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK/ref=ppx_yo_dt_b
|
||||
This is a [WEMOS D1 Mini Pro](https://www.amazon.com/gp/product/B07G9HZ5LM/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is connected to a [relay](https://www.amazon.com/gp/product/B00VRUAHLE/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) to control the power to the landscape lights around my patio. I used the WEMOS D1 Mini Pro because it has an external antenna. I initially used a [WEMOS D1 Mini clone](https://www.amazon.com/gp/product/B076F52NQD/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) but the power supply for my lights was to far from the house and I kept having connectivity issues.
|
||||
|
||||
### [Pool Pumps](./devices/pool_pumps.yaml)
|
||||
This is a [Shelly 2.5 Double Relay Switch](https://www.amazon.com/gp/product/B07RRD13DJ/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is controlling the main pump on my pool and the auxillary pump that runs the pool cleaner. It turns the pump on and off through out the day and off at night (when we are least likely to be using the pool and when you get the most heat/water loss if the pump is running) and turns on the cleaner for a couple of hours in the morning. It also has some modes for Off (during the winter) and Continous when I need extra cleaning.
|
||||
This is a [Shelly 2.5 Double Relay Switch](https://shelly.cloud/products/shelly-25-smart-home-automation-relay/) that is controlling the main pump on my pool and the auxillary pump that runs the pool cleaner via my custom [Pool Controller Component](./components/pool_controller/README.md).
|
||||
|
||||
### [Scripture of the Day Melissa](./devices/scripture_of_the_day_melissa.yaml)/[Scripture of the Day Mayson](./devices/scripture_of_the_day_mayson.yaml)
|
||||
This project was one of the first projects I have done that I would call woodworking. I made 2 of these as Christmas presents for my wife and son. They consist of an [ESP32 e-Paper Panel Driver Board](https://www.waveshare.com/product/displays/e-paper-esp32-driver-board.htm) powered by a [lithium battery](https://www.amazon.com/dp/B0867KDMY7/?coliid=IE0LBNACFHG4U&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and [TP4056 lithium battery charger module](https://www.amazon.com/dp/B06XQRQR3Q/?coliid=I1B2ELKKLLKAK0&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and driving a [Waveshare 7.5inch 800×480 E-Ink display](https://www.waveshare.com/7.5inch-e-paper.htm). The ESP32 sits in deep-sleep most of the time but wakes up every night, grabs a random scripture from the [Our Manna Daily Verses API](http://www.ourmanna.com/verses/api/), updates the display with the verse, and goes back to sleep.
|
||||
|
49
components/pool_controller/README.md
Normal file
49
components/pool_controller/README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Pool Controller Component
|
||||
## Overview
|
||||
This is component is curently running on a [Shelly 2.5 Double Relay Switch](https://shelly.cloud/products/shelly-25-smart-home-automation-relay/) and is used to control the main pump and the auxiliary pump (that runs a pool cleaner) on my pool. Eventually I want to expand this to run on an ESP32 and manage all aspects of my pool (pumps, lights, heat, fill, drain, pH, ORP, etc.). Right now it is providing the followong features:
|
||||
* Provides different modes/schedules for the main pump: Off, Normal (on a schedule), Always Except Peak (all day except during the peak electric rate times), and Always
|
||||
* Provides different modes/schedules for the auxilary (cleaner) pump: Off, Normal (2 hours in the morning), and When Pump Is On (anytime the main pump is running)
|
||||
* Prevents the auxillary pump from running unless the main pump has been running for at least 5 seconds to prevent sucking chlorine into the auxillary pump
|
||||
* Prevents the main pump from shutting down unless the auxillary pump has been off for at least 5 seconds to prevent sucking chlorine into the auxillary pump
|
||||
* Prevents quick cycling of the pumps
|
||||
* Doesn't automatically turn the pumps on unless they have been off for at least 5 minutes so that you can turn them off during a scheduled run time to empty filters, etc without having them come right back on
|
||||
* Monitors the electric current of the pumps and shuts them down if they are out of the normal range (which likely indicates an issue with the pump or a valve that was accidentally left closed)
|
||||
|
||||
|
||||
## Setup
|
||||
Using the [External Components](https://esphome.io/components/external_components.html) feature in ESPHome you can add this component to your devices directly from my GitHub repo.
|
||||
```yaml
|
||||
external_components:
|
||||
- source: github://nuttytree/esphome
|
||||
components: [ pool_controller ]
|
||||
```
|
||||
|
||||
Add and configure the Pool COntroller Component
|
||||
```yaml
|
||||
pool_controller:
|
||||
pump:
|
||||
switch_id: pool_pump
|
||||
current_id: pool_pump_current
|
||||
min_current: 6.50
|
||||
max_current: 6.70
|
||||
max_out_of_range_duration: 5s
|
||||
cleaner:
|
||||
switch_id: pool_cleaner
|
||||
current_id: pool_cleaner_current
|
||||
min_current: 4.55
|
||||
max_current: 5.10
|
||||
max_out_of_range_duration: 5s
|
||||
|
||||
```
|
||||
|
||||
## Configuration Variables
|
||||
* pump.switch_id (Required, Switch) The ID of the switch controlling the main pump
|
||||
* pump.current_id (Required, Sensor) The ID of the current sensor for the main pump
|
||||
* pump.min_current (Required, float) The minimum expected current of the main pump
|
||||
* pump.max_current (Required, float) The maximum expected current of the main pump
|
||||
* pump.max_out_of_range_duration (Required, Time) The maximum time the current of the main pump can be out of range before shutting off the pump
|
||||
* cleaner.switch_id (Required, Switch) The ID of the switch controlling the cleaner pump
|
||||
* cleaner.current_id (Required, Sensor) The ID of the current sensor for the cleaner pump
|
||||
* cleaner.min_current (Required, float) The minimum expected current of the cleaner pump
|
||||
* cleaner.max_current (Required, float) The maximum expected current of the cleaner pump
|
||||
* cleaner.max_out_of_range_duration (Required, Time) The maximum time the current of the cleaner pump can be out of range before shutting off the pump
|
71
components/pool_controller/__init__.py
Normal file
71
components/pool_controller/__init__.py
Normal file
@ -0,0 +1,71 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import time, select, sensor, switch
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_TIME_ID,
|
||||
CONF_NAME,
|
||||
CONF_ICON,
|
||||
ICON_THERMOMETER,
|
||||
CONF_DISABLED_BY_DEFAULT,
|
||||
CONF_MAX_CURRENT,
|
||||
)
|
||||
|
||||
DEPENDENCIES = ["time"]
|
||||
AUTO_LOAD = ["select"]
|
||||
|
||||
pool_controller_ns = cg.esphome_ns.namespace("pool_controller")
|
||||
PoolController = pool_controller_ns.class_("PoolController", cg.PollingComponent)
|
||||
|
||||
CONF_PUMP = "pump"
|
||||
CONF_CLEANER = "cleaner"
|
||||
CONF_SWITCH_ID = "switch_id"
|
||||
CONF_CURRENT_ID = "current_id"
|
||||
CONF_MIN_CURRENT = "min_current"
|
||||
CONF_MAX_OUT_OF_RANGE_DURATION = "max_out_of_range_duration"
|
||||
|
||||
PUMP_SWITCH_CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_SWITCH_ID): cv.use_id(switch.Switch),
|
||||
cv.Required(CONF_CURRENT_ID): cv.use_id(sensor.Sensor),
|
||||
cv.Required(CONF_MIN_CURRENT): cv.positive_float,
|
||||
cv.Required(CONF_MAX_CURRENT): cv.positive_float,
|
||||
cv.Required(CONF_MAX_OUT_OF_RANGE_DURATION): cv.positive_time_period_milliseconds,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_ID): cv.declare_id(PoolController),
|
||||
cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock),
|
||||
cv.Required(CONF_PUMP): PUMP_SWITCH_CONFIG_SCHEMA,
|
||||
cv.Required(CONF_CLEANER): PUMP_SWITCH_CONFIG_SCHEMA,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
time_ = await cg.get_variable(config[CONF_TIME_ID])
|
||||
cg.add(var.set_time(time_))
|
||||
|
||||
pump_config = config[CONF_PUMP]
|
||||
|
||||
pump_switch = await cg.get_variable(pump_config[CONF_SWITCH_ID])
|
||||
cg.add(var.set_pump_switch(pump_switch))
|
||||
|
||||
pump_current = await cg.get_variable(pump_config[CONF_CURRENT_ID])
|
||||
cg.add(var.set_pump_current_monitoring(pump_current, pump_config[CONF_MIN_CURRENT], pump_config[CONF_MAX_CURRENT], pump_config[CONF_MAX_OUT_OF_RANGE_DURATION]))
|
||||
|
||||
cleaner_config = config[CONF_CLEANER]
|
||||
|
||||
cleaner_switch = await cg.get_variable(cleaner_config[CONF_SWITCH_ID])
|
||||
cg.add(var.set_cleaner_switch(cleaner_switch))
|
||||
|
||||
cleaner_current = await cg.get_variable(cleaner_config[CONF_CURRENT_ID])
|
||||
cg.add(var.set_cleaner_current_monitoring(cleaner_current, cleaner_config[CONF_MIN_CURRENT], cleaner_config[CONF_MAX_CURRENT], cleaner_config[CONF_MAX_OUT_OF_RANGE_DURATION]))
|
181
components/pool_controller/pool_controller.cpp
Normal file
181
components/pool_controller/pool_controller.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
#include "esphome/components/time/automation.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/base_automation.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "pool_controller.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pool_controller {
|
||||
|
||||
static const char *const TAG = "pool_controller";
|
||||
|
||||
static const uint32_t RUNTIME_30_MINUTES_PER_HALF_HOUR = UINT32_MAX;
|
||||
static const uint32_t RUNTIME_15_MINUTES_PER_HALF_HOUR = 900000;
|
||||
static const uint32_t RUNTIME_10_MINUTES_PER_HALF_HOUR = 600000;
|
||||
|
||||
// Minimum time the pump needs to be off before the automation will turn it back on (300000 = 5 minutes)
|
||||
static const uint32_t MINIMUM_AUTOMATION_PUMP_OFF_TIME = 300000;
|
||||
|
||||
// Minimum time the pump needs to be on before the automation will turn it back off (300000 = 5 minutes)
|
||||
static const uint32_t MINIMUM_AUTOMATION_PUMP_ON_TIME = 300000;
|
||||
|
||||
PoolController::PoolController() {
|
||||
ESP_LOGD(TAG, "Creating pump mode select component");
|
||||
this->pump_select_ = new PoolSelect();
|
||||
App.register_component(this->pump_select_);
|
||||
App.register_select(this->pump_select_);
|
||||
this->pump_select_->set_name("Pool Pump Mode");
|
||||
this->pump_select_->traits.set_icon("mdi:pump");
|
||||
this->pump_select_->traits.set_options({"Off", "Normal", "Always Except Peak", "Always"});
|
||||
this->pump_select_->add_on_state_callback([this](std::string value) -> void {
|
||||
auto options = this->pump_select_->traits.get_options();
|
||||
size_t index = std::find(options.begin(), options.end(), value) - options.begin();
|
||||
this->pump_mode_ = static_cast<PumpMode>(index);
|
||||
});
|
||||
|
||||
ESP_LOGD(TAG, "Creating cleaner mode select component");
|
||||
this->cleaner_select_ = new PoolSelect();
|
||||
App.register_component(this->cleaner_select_);
|
||||
App.register_select(this->cleaner_select_);
|
||||
this->cleaner_select_->set_name("Pool Cleaner Mode");
|
||||
this->cleaner_select_->traits.set_icon("mdi:robot-vacuum");
|
||||
this->cleaner_select_->traits.set_options({"Off", "Normal", "When Pump Is On"});
|
||||
this->pump_select_->add_on_state_callback([this](std::string value) -> void {
|
||||
auto options = this->cleaner_select_->traits.get_options();
|
||||
size_t index = std::find(options.begin(), options.end(), value) - options.begin();
|
||||
this->cleaner_mode_ = static_cast<CleanerMode>(index);
|
||||
});
|
||||
|
||||
// this->heat_select_ = new PoolSelect();
|
||||
// App.register_component(this->heat_select_);
|
||||
// App.register_select(this->heat_select_);
|
||||
// this->heat_select_->set_name("Pool Heat Mode");
|
||||
// this->heat_select_->traits.set_icon("mdi:thermometer");
|
||||
// this->heat_select_->traits.set_options({"Off", "Normal", "Always"});
|
||||
}
|
||||
|
||||
void PoolController::set_time(time::RealTimeClock *time) {
|
||||
this->time_ = time;
|
||||
|
||||
ESP_LOGD(TAG, "Adding cron trigger");
|
||||
auto cron_trigger = new time::CronTrigger(time);
|
||||
cron_trigger->add_second(0);
|
||||
cron_trigger->add_minutes({0, 30});
|
||||
cron_trigger->add_hours({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23});
|
||||
cron_trigger->add_days_of_month({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31});
|
||||
cron_trigger->add_months({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
|
||||
cron_trigger->add_days_of_week({1, 2, 3, 4, 5, 6, 7});
|
||||
App.register_component(cron_trigger);
|
||||
auto lambda_action = new LambdaAction<>([=]() -> void {
|
||||
this->pump_switch_->reset_runtime();
|
||||
this->cleaner_switch_->reset_runtime();
|
||||
});
|
||||
auto automation = new Automation<>(cron_trigger);
|
||||
automation->add_actions({lambda_action});
|
||||
}
|
||||
|
||||
void PoolController::set_pump_switch(switch_::Switch *pump_switch) {
|
||||
this->pump_switch_ = new PumpSwitch(pump_switch);
|
||||
App.register_component(this->pump_switch_);
|
||||
App.register_switch(this->pump_switch_);
|
||||
this->pump_switch_->add_turn_off_check([this]() -> bool {
|
||||
ESP_LOGD(TAG, "Pump switch turn off check is checking the state of %s", this->get_name().c_str());
|
||||
if (this->cleaner_switch_->state) {
|
||||
this->cleaner_switch_->turn_off();
|
||||
}
|
||||
return this->cleaner_switch_->get_current_off_time() > 5000;
|
||||
});
|
||||
}
|
||||
|
||||
void PoolController::set_cleaner_switch(switch_::Switch *cleaner_switch) {
|
||||
this->cleaner_switch_ = new PumpSwitch(cleaner_switch);
|
||||
App.register_component(this->cleaner_switch_);
|
||||
App.register_switch(this->cleaner_switch_);
|
||||
this->cleaner_switch_->add_turn_on_check([this]() {
|
||||
ESP_LOGD(TAG, "Cleaner switch turn on check is checking the state of %s", this->get_name().c_str());
|
||||
if (!this->pump_switch_->state) {
|
||||
this->pump_switch_->turn_on();
|
||||
}
|
||||
return this->pump_switch_->get_current_on_time() > 5000;
|
||||
});
|
||||
}
|
||||
|
||||
void PoolController::setup() {
|
||||
}
|
||||
|
||||
void PoolController::loop() {
|
||||
manage_pump_();
|
||||
|
||||
manage_cleaner_();
|
||||
}
|
||||
|
||||
void PoolController::manage_pump_() {
|
||||
uint32_t desired_runtime = 0;
|
||||
int hour = this->time_->now().hour;
|
||||
switch (this->pump_mode_) {
|
||||
case PumpMode::PUMP_MODE_OFF:
|
||||
if (this->pump_switch_->state) {
|
||||
this->pump_switch_->turn_off();
|
||||
}
|
||||
break;
|
||||
|
||||
case PumpMode::PUMP_MODE_NORMAL:
|
||||
if (hour >= 4 && hour < 6) {
|
||||
desired_runtime = RUNTIME_30_MINUTES_PER_HALF_HOUR; // normal cleaner run time
|
||||
} else if (hour >= 6 && hour < 15) {
|
||||
desired_runtime = RUNTIME_15_MINUTES_PER_HALF_HOUR;
|
||||
} else if (hour >= 15 && hour < 20) {
|
||||
desired_runtime = RUNTIME_10_MINUTES_PER_HALF_HOUR; // peak electric rate
|
||||
}
|
||||
break;
|
||||
|
||||
case PumpMode::PUMP_MODE_ALWAYS_EXCEPT_PEAK:
|
||||
if (hour < 15 && hour >= 20) {
|
||||
desired_runtime = RUNTIME_30_MINUTES_PER_HALF_HOUR;
|
||||
}
|
||||
break;
|
||||
|
||||
case PumpMode::PUMP_MODE_ALWAYS:
|
||||
desired_runtime = RUNTIME_30_MINUTES_PER_HALF_HOUR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this->pump_switch_->state && desired_runtime > this->pump_switch_->get_runtime() && this->pump_switch_->get_current_off_time() > MINIMUM_AUTOMATION_PUMP_OFF_TIME) {
|
||||
this->pump_switch_->turn_on();
|
||||
} else if (this->pump_switch_->state && desired_runtime < this->pump_switch_->get_runtime() && this->pump_switch_->get_current_on_time() > MINIMUM_AUTOMATION_PUMP_ON_TIME) {
|
||||
this->pump_switch_->turn_off();
|
||||
}
|
||||
}
|
||||
|
||||
void PoolController::manage_cleaner_() {
|
||||
bool desired_state = false;
|
||||
int hour = this->time_->now().hour;
|
||||
switch (this->cleaner_mode_) {
|
||||
case CleanerMode::CLEANER_MODE_OFF:
|
||||
if (this->cleaner_switch_->state) {
|
||||
this->cleaner_switch_->turn_off();
|
||||
}
|
||||
break;
|
||||
|
||||
case CleanerMode::CLEANER_MODE_NORMAL:
|
||||
if (hour >= 4 && hour < 6) {
|
||||
desired_state = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case CleanerMode::CLEANER_MODE_WHEN_PUMP_IS_ON:
|
||||
if (this->pump_switch_->state) {
|
||||
desired_state = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->cleaner_switch_->state && desired_state && this->cleaner_switch_->get_current_off_time() > MINIMUM_AUTOMATION_PUMP_OFF_TIME) {
|
||||
this->cleaner_switch_->turn_on();
|
||||
} else if (this->cleaner_switch_->state && !desired_state && this->cleaner_switch_->get_current_on_time() > MINIMUM_AUTOMATION_PUMP_ON_TIME) {
|
||||
this->cleaner_switch_->turn_off();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pool_controller
|
||||
} // namespace esphome
|
58
components/pool_controller/pool_controller.h
Normal file
58
components/pool_controller/pool_controller.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/select/select.h"
|
||||
#include "esphome/components/switch/switch.h"
|
||||
#include "esphome/components/time/real_time_clock.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/preferences.h"
|
||||
#include "pool_select.h"
|
||||
#include "pump_switch.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pool_controller {
|
||||
|
||||
enum PumpMode : size_t {
|
||||
PUMP_MODE_OFF = 0,
|
||||
PUMP_MODE_NORMAL,
|
||||
PUMP_MODE_ALWAYS_EXCEPT_PEAK,
|
||||
PUMP_MODE_ALWAYS,
|
||||
};
|
||||
|
||||
enum CleanerMode : size_t {
|
||||
CLEANER_MODE_OFF = 0,
|
||||
CLEANER_MODE_NORMAL,
|
||||
CLEANER_MODE_WHEN_PUMP_IS_ON,
|
||||
};
|
||||
|
||||
class PoolController : public Component {
|
||||
public:
|
||||
PoolController();
|
||||
void set_time(time::RealTimeClock *time);
|
||||
void set_pump_switch(switch_::Switch *pump_switch);
|
||||
void set_pump_current_monitoring(sensor::Sensor *sensor, float min_current, float max_current, uint32_t max_out_of_range_time) {
|
||||
this->pump_switch_->set_current_monitoring(sensor, min_current, max_current, max_out_of_range_time);
|
||||
}
|
||||
void set_cleaner_switch(switch_::Switch *cleaner_switch);
|
||||
void set_cleaner_current_monitoring(sensor::Sensor *sensor, float min_current, float max_current, uint32_t max_out_of_range_time) {
|
||||
this->cleaner_switch_->set_current_monitoring(sensor, min_current, max_current, max_out_of_range_time);
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
|
||||
protected:
|
||||
void manage_pump_();
|
||||
void manage_cleaner_();
|
||||
|
||||
time::RealTimeClock *time_;
|
||||
PoolSelect *pump_select_;
|
||||
PumpSwitch *pump_switch_;
|
||||
PoolSelect *cleaner_select_;
|
||||
PumpSwitch *cleaner_switch_;
|
||||
|
||||
PumpMode pump_mode_;
|
||||
CleanerMode cleaner_mode_;
|
||||
};
|
||||
|
||||
} // namespace pool_controller
|
||||
} // namespace esphome
|
32
components/pool_controller/pool_select.cpp
Normal file
32
components/pool_controller/pool_select.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "pool_select.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pool_controller {
|
||||
|
||||
static const char *const TAG = "pool_select";
|
||||
|
||||
void PoolSelect::setup() {
|
||||
std::string value;
|
||||
size_t index;
|
||||
this->pref_ = global_preferences.make_preference<size_t>(this->get_object_id_hash());
|
||||
if (!this->pref_.load(&index)) {
|
||||
value = "Off";
|
||||
ESP_LOGD(TAG, "State from initial (could not load): %s", value.c_str());
|
||||
} else {
|
||||
value = this->traits.get_options().at(index);
|
||||
ESP_LOGD(TAG, "State from restore: %s", value.c_str());
|
||||
}
|
||||
this->publish_state(value);
|
||||
}
|
||||
|
||||
void PoolSelect::control(const std::string &value) {
|
||||
this->publish_state(value);
|
||||
|
||||
auto options = this->traits.get_options();
|
||||
size_t index = std::find(options.begin(), options.end(), value) - options.begin();
|
||||
this->pref_.save(&index);
|
||||
}
|
||||
|
||||
} // namespace pool_controller
|
||||
} // namespace esphome
|
22
components/pool_controller/pool_select.h
Normal file
22
components/pool_controller/pool_select.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/select/select.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/preferences.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pool_controller {
|
||||
|
||||
class PoolSelect : public select::Select, public Component {
|
||||
public:
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
void setup() override;
|
||||
|
||||
protected:
|
||||
void control(const std::string &value) override;
|
||||
|
||||
ESPPreferenceObject pref_;
|
||||
};
|
||||
|
||||
} // namespace pool_controller
|
||||
} // namespace esphome
|
162
components/pool_controller/pump_switch.cpp
Normal file
162
components/pool_controller/pump_switch.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
#include "pump_switch.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pool_controller {
|
||||
|
||||
// Minimum time the pump needs to be on, turning off before this will result in a delayed turn off (10000 = 10 seconds)
|
||||
static const uint32_t MINIMUM_PUMP_ON_TIME = 10000;
|
||||
|
||||
// Minimum time the pump needs to be off, turning on before this will result in a delayed turn on (10000 = 10 seconds)
|
||||
static const uint32_t MINIMUM_PUMP_OFF_TIME = 10000;
|
||||
|
||||
static const uint32_t FORTY_EIGHT_HOURS = 172800000;
|
||||
|
||||
PumpSwitch::PumpSwitch(switch_::Switch *physical_switch) {
|
||||
this->set_name(physical_switch->get_name());
|
||||
this->set_icon(physical_switch->get_icon());
|
||||
this->set_update_interval(10000);
|
||||
|
||||
physical_switch->set_internal(true);
|
||||
physical_switch->add_on_state_callback([this](bool state) -> void {
|
||||
if (state) {
|
||||
uint32_t now = millis();
|
||||
this->turned_on_at_ = now;
|
||||
this->last_runtime_update_ = now;
|
||||
if (!this->state) {
|
||||
this->physical_switch_->turn_off();
|
||||
}
|
||||
} else {
|
||||
uint32_t now = millis();
|
||||
this->turned_off_at_ = now;
|
||||
this->runtime_ += now - this->last_runtime_update_;
|
||||
this->last_runtime_update_ = now;
|
||||
if (this->state) {
|
||||
this->turn_off();
|
||||
}
|
||||
}
|
||||
});
|
||||
this->physical_switch_ = physical_switch;
|
||||
}
|
||||
|
||||
void PumpSwitch::setup() {
|
||||
this->turn_off();
|
||||
this->physical_switch_->turn_off();
|
||||
}
|
||||
|
||||
void PumpSwitch::loop() {
|
||||
this->update_physical_switch_();
|
||||
this->check_current_();
|
||||
}
|
||||
|
||||
void PumpSwitch::update() {
|
||||
if (this->physical_switch_->state) {
|
||||
uint32_t now = millis();
|
||||
this->runtime_ += now - this->last_runtime_update_;
|
||||
this->last_runtime_update_ = now;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t PumpSwitch::get_current_on_time() {
|
||||
if (!this->physical_switch_->state) {
|
||||
return 0;
|
||||
} else {
|
||||
return millis() - this->turned_on_at_;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t PumpSwitch::get_current_off_time() {
|
||||
if (this->physical_switch_->state) {
|
||||
return 0;
|
||||
} else {
|
||||
return millis() - this->turned_off_at_;
|
||||
}
|
||||
}
|
||||
|
||||
void PumpSwitch::set_is_disabled(bool is_disabled) {
|
||||
this->is_disabled_ = is_disabled;
|
||||
if (is_disabled && this->state) {
|
||||
this->turn_off();
|
||||
}
|
||||
}
|
||||
|
||||
void PumpSwitch::emergency_stop() {
|
||||
this->physical_switch_->turn_off();
|
||||
this->set_is_disabled(true);
|
||||
}
|
||||
|
||||
void PumpSwitch::write_state(bool state) {
|
||||
if (state && this->is_disabled_) {
|
||||
state = false;
|
||||
}
|
||||
|
||||
this->state = state;
|
||||
this->publish_state(state);
|
||||
this->update_physical_switch_();
|
||||
}
|
||||
|
||||
void PumpSwitch::update_physical_switch_() {
|
||||
if (this->state == this->physical_switch_->state) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->state) {
|
||||
if (millis() - this->turned_off_at_ < MINIMUM_PUMP_OFF_TIME) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check any other registered conditions
|
||||
for (auto &check : this->turn_on_checks_) {
|
||||
if (!check()){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->physical_switch_->turn_on();
|
||||
} else {
|
||||
if (millis() - this->turned_on_at_ < MINIMUM_PUMP_ON_TIME) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check any other registered conditions
|
||||
for (auto &check : this->turn_off_checks_) {
|
||||
if (!check()){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->physical_switch_->turn_off();
|
||||
}
|
||||
}
|
||||
|
||||
void PumpSwitch::check_current_() {
|
||||
if (!this->current_sensor_->has_state()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto now = millis();
|
||||
|
||||
// If we haven't had another out of range event in 48 hours it was probably an anomaly so reset
|
||||
if (this->last_current_out_of_range_at_ != 0 && now - this->last_current_out_of_range_at_ > FORTY_EIGHT_HOURS) {
|
||||
this->last_current_out_of_range_at_ = 0;
|
||||
}
|
||||
|
||||
float current = this->current_sensor_->get_state();
|
||||
if (current == 0 || (current >= this->min_current_ && current <= this->max_current_)) {
|
||||
if (this->current_out_of_range_at_ != 0) {
|
||||
this->current_out_of_range_at_ = 0;
|
||||
}
|
||||
} else {
|
||||
if (this->current_out_of_range_at_ == 0) {
|
||||
this->current_out_of_range_at_ = now;
|
||||
} else if (now - this->current_out_of_range_at_ > this->max_current_out_of_range_time_) {
|
||||
this->physical_switch_->turn_off();
|
||||
if (this->last_current_out_of_range_at_ != 0) {
|
||||
this->is_disabled_ = true;
|
||||
}
|
||||
this->last_current_out_of_range_at_ = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pool_controller
|
||||
} // namespace esphome
|
56
components/pool_controller/pump_switch.h
Normal file
56
components/pool_controller/pump_switch.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/select/select.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/switch/switch.h"
|
||||
#include "esphome/components/time/real_time_clock.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/preferences.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pool_controller {
|
||||
|
||||
class PumpSwitch : public switch_::Switch, public PollingComponent {
|
||||
public:
|
||||
PumpSwitch(switch_::Switch *physical_switch);
|
||||
void add_turn_on_check(std::function<bool()> &&turn_on_check) { this->turn_on_checks_.push_back(std::move(turn_on_check)); }
|
||||
void add_turn_off_check(std::function<bool()> &&turn_off_check) { this->turn_off_checks_.push_back(std::move(turn_off_check)); }
|
||||
void set_current_monitoring(sensor::Sensor *sensor, float min_current, float max_current, uint32_t max_out_of_range_time) {
|
||||
this->current_sensor_ = sensor; this->min_current_ = min_current; this->max_current_ = max_current; this->max_current_out_of_range_time_ = max_out_of_range_time;
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void update() override;
|
||||
|
||||
uint32_t get_current_on_time();
|
||||
uint32_t get_current_off_time();
|
||||
uint32_t get_runtime() { return this->runtime_; }
|
||||
void reset_runtime() { this->runtime_ = 0; }
|
||||
void set_is_disabled(bool is_disabled);
|
||||
void emergency_stop();
|
||||
|
||||
protected:
|
||||
void write_state(bool state) override;
|
||||
|
||||
void update_physical_switch_();
|
||||
void check_current_();
|
||||
|
||||
switch_::Switch *physical_switch_;
|
||||
sensor::Sensor *current_sensor_;
|
||||
std::vector<std::function<bool()>> turn_on_checks_;
|
||||
std::vector<std::function<bool()>> turn_off_checks_;
|
||||
float min_current_;
|
||||
float max_current_;
|
||||
uint32_t max_current_out_of_range_time_;
|
||||
bool is_disabled_{false};
|
||||
uint32_t turned_on_at_{0};
|
||||
uint32_t turned_off_at_{0};
|
||||
uint32_t runtime_{0};
|
||||
uint32_t last_runtime_update_{0};
|
||||
uint32_t current_out_of_range_at_{0};
|
||||
uint32_t last_current_out_of_range_at_{0};
|
||||
};
|
||||
|
||||
} // namespace pool_controller
|
||||
} // namespace esphome
|
@ -12,6 +12,12 @@ packages:
|
||||
device_base: !include ../packages/device_base.yaml
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../components
|
||||
components: [ pool_controller ]
|
||||
- source: github://esphome/esphome@dev
|
||||
components: [ total_daily_energy ]
|
||||
- source: github://cbpowell/ESPSense
|
||||
components: [ espsense ]
|
||||
|
||||
@ -30,6 +36,20 @@ i2c:
|
||||
sda: GPIO12
|
||||
scl: GPIO14
|
||||
|
||||
pool_controller:
|
||||
pump:
|
||||
switch_id: pool_pump
|
||||
current_id: pool_pump_current
|
||||
min_current: 6.50
|
||||
max_current: 6.70
|
||||
max_out_of_range_duration: 5s
|
||||
cleaner:
|
||||
switch_id: pool_cleaner
|
||||
current_id: pool_cleaner_current
|
||||
min_current: 4.55
|
||||
max_current: 5.10
|
||||
max_out_of_range_duration: 5s
|
||||
|
||||
sensor:
|
||||
- platform: ade7953
|
||||
voltage:
|
||||
@ -41,44 +61,12 @@ sensor:
|
||||
name: Pool Cleaner Current
|
||||
id: pool_cleaner_current
|
||||
filters:
|
||||
- lambda: |-
|
||||
// Filter the initial high current spike when the motor starts to prevent tripping the on_value_range logic
|
||||
static float last_cleaner_current = 0.0;
|
||||
if (isnan(x))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
if (last_cleaner_current <= 7 && x > 7)
|
||||
{
|
||||
last_cleaner_current = x;
|
||||
return {};
|
||||
}
|
||||
return last_cleaner_current = x < .1 ? 0.0 : x;
|
||||
on_value_range:
|
||||
above: 7
|
||||
then:
|
||||
- switch.turn_off: pool_cleaner
|
||||
- lambda: "return x < .1 ? 0 : x;"
|
||||
current_b:
|
||||
name: Pool Pump Current
|
||||
id: pool_pump_current
|
||||
filters:
|
||||
- lambda: |-
|
||||
// Filter the initial high current spike when the motor starts to prevent tripping the on_value_range logic
|
||||
static float last_pump_current = 0.0;
|
||||
if (isnan(x))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
if (last_pump_current <= 8 && x > 8)
|
||||
{
|
||||
last_pump_current = x;
|
||||
return {};
|
||||
}
|
||||
return last_pump_current = x < .1 ? 0.0 : x;
|
||||
on_value_range:
|
||||
above: 8
|
||||
then:
|
||||
- switch.turn_off: pool_pump
|
||||
- lambda: "return x < .1 ? 0 : x;"
|
||||
active_power_a:
|
||||
name: Pool Cleaner Power
|
||||
id: pool_cleaner_power
|
||||
@ -89,13 +77,14 @@ sensor:
|
||||
id: pool_pump_power
|
||||
filters:
|
||||
- lambda: "return abs(x) < .1 ? 0 : abs(x) * 2;"
|
||||
update_interval: 2s
|
||||
update_interval: 1s
|
||||
- platform: ntc
|
||||
sensor: temp_resistance_reading
|
||||
name: ${device_name} Temperature
|
||||
unit_of_measurement: "°C"
|
||||
accuracy_decimals: 1
|
||||
icon: "mdi:thermometer"
|
||||
state_class: measurement
|
||||
calibration:
|
||||
b_constant: 3350
|
||||
reference_resistance: 10kOhm
|
||||
@ -108,10 +97,6 @@ sensor:
|
||||
- platform: adc
|
||||
id: temp_analog_reading
|
||||
pin: A0
|
||||
- platform: template
|
||||
name: "Pool Mode Id"
|
||||
id: pool_mode_id
|
||||
internal: true
|
||||
- platform: total_daily_energy
|
||||
name: "Pool Pump Total Daily Energy"
|
||||
power_id: pool_pump_power
|
||||
@ -134,143 +119,14 @@ switch:
|
||||
name: "Pool Pump"
|
||||
id: pool_pump
|
||||
icon: mdi:pump
|
||||
on_turn_off:
|
||||
then:
|
||||
- switch.turn_off: pool_cleaner
|
||||
restore_mode: Always Off
|
||||
- platform: gpio
|
||||
pin: GPIO15
|
||||
name: "Pool Cleaner"
|
||||
id: pool_cleaner
|
||||
icon: mdi:robot-vacuum
|
||||
on_turn_on:
|
||||
then:
|
||||
- switch.turn_on: pool_pump
|
||||
|
||||
text_sensor:
|
||||
- platform: homeassistant
|
||||
name: "Pool Mode Text"
|
||||
entity_id: input_select.pool_mode
|
||||
on_value:
|
||||
then:
|
||||
- sensor.template.publish:
|
||||
id: pool_mode_id
|
||||
state: !lambda 'return x == "Off" ? 0 : x == "Normal" ? 1 : x == "Continuous Without Heat" ? 2 : x == "Continuous With Heat" ? 3 : id(pool_mode_id).state;'
|
||||
restore_mode: Always Off
|
||||
|
||||
time:
|
||||
- platform: homeassistant
|
||||
id: the_time
|
||||
on_time:
|
||||
seconds: 0
|
||||
minutes: 0,15,30,45
|
||||
then:
|
||||
lambda: |-
|
||||
if (id(pool_mode_id).state == 0)
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_off");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
id(pool_cleaner).turn_off();
|
||||
id(pool_pump).turn_off();
|
||||
}
|
||||
else if (id(pool_mode_id).state == 1)
|
||||
{
|
||||
auto now = id(the_time).now();
|
||||
int hour = now.hour;
|
||||
int minute = now.minute;
|
||||
|
||||
if (hour == 3 && minute == 45)
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_off");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
id(pool_cleaner).turn_off();
|
||||
id(pool_pump).turn_on();
|
||||
}
|
||||
else if (hour >= 4 && hour <= 5)
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_off");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
if (id(pool_pump).state)
|
||||
{
|
||||
id(pool_cleaner).turn_on();
|
||||
}
|
||||
else
|
||||
{
|
||||
id(pool_pump).turn_on();
|
||||
}
|
||||
}
|
||||
else if (hour == 6)
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_on");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
id(pool_cleaner).turn_off();
|
||||
id(pool_pump).turn_on();
|
||||
}
|
||||
else if (hour >= 7 && hour <= 20 && (minute == 0 || minute == 30))
|
||||
{
|
||||
id(pool_pump).turn_off();
|
||||
}
|
||||
else if (hour >= 8 && hour <= 20 && (minute == 15 || minute == 45))
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_on");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
id(pool_cleaner).turn_off();
|
||||
id(pool_pump).turn_on();
|
||||
}
|
||||
else if (hour == 21 && minute == 0)
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_off");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
id(pool_cleaner).turn_off();
|
||||
id(pool_pump).turn_on();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_off");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
id(pool_cleaner).turn_off();
|
||||
id(pool_pump).turn_off();
|
||||
}
|
||||
}
|
||||
else if (id(pool_mode_id).state == 2)
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_off");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
if (id(pool_pump).state)
|
||||
{
|
||||
id(pool_cleaner).turn_on();
|
||||
}
|
||||
else
|
||||
{
|
||||
id(pool_pump).turn_on();
|
||||
}
|
||||
}
|
||||
else if (id(pool_mode_id).state == 3)
|
||||
{
|
||||
auto ha_service = new api::HomeAssistantServiceCallAction<>(api_apiserver, false);
|
||||
ha_service->set_service("switch.turn_on");
|
||||
ha_service->add_data("entity_id", "switch.pool_heater");
|
||||
ha_service->play();
|
||||
if (id(pool_pump).state)
|
||||
{
|
||||
id(pool_cleaner).turn_on();
|
||||
}
|
||||
else
|
||||
{
|
||||
id(pool_pump).turn_on();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user