Bunch of updates from the last year or so (#47)

This commit is contained in:
Chris Nussbaum 2024-07-22 18:34:02 -05:00 committed by GitHub
parent f1df2b3c0c
commit f00cbd65db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 317 additions and 292 deletions

View File

@ -11,7 +11,6 @@ Home Assistant is open source home automation that puts local control and privac
## Folder Structure
* `/` - Yaml files for my devices and other core files
* `/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
* `/images` - Pictures of some of my devices

View File

@ -2,10 +2,9 @@ substitutions:
device_id: basement-bath-shower-light-heat
device_name: Basement Bathroom Shower Light and Heater
board: esp01_1m
ip_address: !secret basement-bathroom-shower-light-heat-ip
ota_pwd: !secret basement-bathroom-shower-light-heat-ota-pwd
api_key: !secret basement-bathroom-shower-light-heat-key
ap_wifi_pwd: !secret basement-bathroom-shower-light-heat-ap-pwd
ip_address: !secret basement_bathroom_shower_light_heat_ip
api_key: !secret basement_bathroom_shower_light_heat_key
pwd: !secret basement_bathroom_shower_light_heat_pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml

View File

@ -2,10 +2,9 @@ substitutions:
device_id: basement-bathroom-light-fan
device_name: Basement Bathroom Light and Fan
board: esp01_1m
ip_address: !secret basement-bathroom-light-fan-ip
ota_pwd: !secret basement-bathroom-light-fan-ota-pwd
api_key: !secret basement-bathroom-light-fan-key
ap_wifi_pwd: !secret basement-bathroom-light-fan-ap-pwd
ip_address: !secret basement_bathroom_light_fan_ip
api_key: !secret basement_bathroom_light_fan_key
pwd: !secret basement_bathroom_light_fan_pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml

View File

@ -2,10 +2,9 @@ substitutions:
device_id: basement-bathroom-sensor
device_name: Basement Bathroom Sensor
board: d1_mini
ip_address: !secret basement-bathroom-sensor-ip
ota_pwd: !secret basement-bathroom-sensor-ota-pwd
api_key: !secret basement-bathroom-sensor-key
ap_wifi_pwd: !secret basement-bathroom-sensor-ap-pwd
ip_address: !secret basement_bathroom_sensor_ip
api_key: !secret basement_bathroom_sensor_key
pwd: !secret basement_bathroom_sensor_pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml
@ -166,7 +165,7 @@ output:
id: door_gnd
sensor:
- platform: bme280
- platform: bme280_i2c
temperature:
id: temperature
name: "Basement Bathroom Temperature"

View File

@ -1,10 +1,9 @@
substitutions:
device_id: basement-fridge
device_name: Basement Fridge
ip_address: !secret basement-fridge-ip
ota_pwd: !secret basement-fridge-ota-pwd
api_key: !secret basement-fridge-key
ap_wifi_pwd: !secret basement-fridge-ap-pwd
ip_address: !secret basement_fridge_ip
api_key: !secret basement_fridge_key
pwd: !secret basement_fridge_pwd
packages:
feit_dimmer: !include ./packages/topgreener_smart_plug.yaml

View File

@ -1,10 +1,9 @@
substitutions:
device_id: basement-tv
device_name: Basement TV
ip_address: !secret basement-tv-ip
ota_pwd: !secret basement-tv-ota-pwd
api_key: !secret basement-tv-key
ap_wifi_pwd: !secret basement-tv-ap-pwd
ip_address: !secret basement_tv_ip
api_key: !secret basement_tv_key
pwd: !secret basement_tv_pwd
packages:
feit_dimmer: !include ./packages/topgreener_smart_plug.yaml

View File

@ -2,10 +2,9 @@ substitutions:
device_id: coffee-maker
device_name: Coffee Maker
board: nodemcuv2
ip_address: !secret coffee-maker-ip
ota_pwd: !secret coffee-maker-ota-pwd
api_key: !secret coffee-maker-key
ap_wifi_pwd: !secret coffee-maker-ap-pwd
ip_address: !secret coffee_maker_ip
api_key: !secret coffee_maker_key
pwd: !secret coffee_maker_pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml

View File

@ -7,7 +7,7 @@ This an enhanced version of the standard [binary light](https://esphome.io/compo
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
- source: github://nuttytree/ESPHome-Devices
components: [ binary_light_with_power ]
```

View File

@ -82,7 +82,7 @@ class GarageDoorLock : public lock::Lock, public Component
class GarageDoor : public cover::Cover, public Component, public api::CustomAPIDevice {
public:
GarageDoor();
void set_name(const std::string &name) { Cover::set_name(name); this->lock_comp_->set_name(name); }
void set_name(const char *name) { Cover::set_name(name); this->lock_comp_->set_name(name); }
void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; }
void set_close_duration(uint32_t close_duration) { this->close_duration_ = close_duration; }
void set_control_output(output::BinaryOutput *control_output) { this->control_output_ = control_output; }

View File

@ -7,7 +7,7 @@ This an enhanced version of the standard [gpio switch](https://esphome.io/compon
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
- source: github://nuttytree/ESPHome-Devices
components: [ gpio_switch_with_power ]
```

View File

@ -14,7 +14,7 @@ This is component is curently running on a [Shelly 2.5 Double Relay Switch](http
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
- source: github://nuttytree/ESPHome-Devices
components: [ pool_controller ]
```

View File

@ -1,13 +1,9 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import time, select, sensor, switch
from esphome.components import time, sensor, switch
from esphome.const import (
CONF_ID,
CONF_TIME_ID,
CONF_NAME,
CONF_ICON,
ICON_THERMOMETER,
CONF_DISABLED_BY_DEFAULT,
CONF_MAX_CURRENT,
)
@ -19,6 +15,7 @@ PoolController = pool_controller_ns.class_("PoolController", cg.PollingComponent
CONF_PUMP = "pump"
CONF_CLEANER = "cleaner"
CONF_PUMP_SELECT = "pump_select"
CONF_SWITCH_ID = "switch_id"
CONF_CURRENT_ID = "current_id"
CONF_MIN_CURRENT = "min_current"

View File

@ -3,11 +3,12 @@
#include "esphome/core/application.h"
#include "esphome/core/base_automation.h"
#include "esphome/core/log.h"
#include "esphome/core/time.h"
namespace esphome {
namespace pool_controller {
static const char *const TAG = "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;
@ -20,24 +21,30 @@ static const uint32_t MINIMUM_AUTOMATION_PUMP_OFF_TIME = 300000;
static const uint32_t MINIMUM_AUTOMATION_PUMP_ON_TIME = 300000;
PoolController::PoolController() {
ESP_LOGD(TAG, "Creating pump mode select component");
ESP_LOGCONFIG(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_->set_object_id("pump_select");
this->pump_select_->set_icon("mdi:pump");
this->pump_select_->set_disabled_by_default(false);
this->pump_select_->traits.set_options({"Off", "Normal", "Always Except Peak", "Always"});
this->pump_select_->set_initial_option("Off");
this->pump_select_->add_on_state_callback([this](const std::string &value, size_t index) {
this->pump_mode_ = static_cast<PumpMode>(index);
});
ESP_LOGD(TAG, "Creating cleaner mode select component");
ESP_LOGCONFIG(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_->set_object_id("cleaner_select");
this->cleaner_select_->set_icon("mdi:robot-vacuum");
this->cleaner_select_->set_disabled_by_default(false);
this->cleaner_select_->traits.set_options({"Off", "Normal", "When Pump Is On"});
this->cleaner_select_->set_initial_option("Off");
this->cleaner_select_->add_on_state_callback([this](const std::string &value, size_t index) {
this->cleaner_mode_ = static_cast<CleanerMode>(index);
});
@ -72,8 +79,10 @@ void PoolController::set_time(time::RealTimeClock *time) {
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_->set_name("Pool Pump");
this->pump_switch_->set_object_id("controller_managed_pump_switch");
this->pump_switch_->set_icon("mdi:pump");
this->pump_switch_->add_turn_off_check([this]() -> bool {
ESP_LOGD(TAG, "Pump switch turn off check is checking the state of the pool cleaner");
if (this->cleaner_switch_->state) {
@ -81,12 +90,15 @@ void PoolController::set_pump_switch(switch_::Switch *pump_switch) {
}
return this->cleaner_switch_->get_current_off_time() > 5000;
});
App.register_component(this->pump_switch_);
}
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_->set_name("Pool Cleaner");
this->cleaner_switch_->set_object_id("controller_managed_cleaner_switch");
this->cleaner_switch_->set_icon("mdi:robot-vacuum");
this->cleaner_switch_->add_turn_on_check([this]() {
ESP_LOGD(TAG, "Cleaner switch turn on check is checking the state of the pool pump");
if (!this->pump_switch_->state) {
@ -94,6 +106,7 @@ void PoolController::set_cleaner_switch(switch_::Switch *cleaner_switch) {
}
return this->pump_switch_->get_current_on_time() > 5000;
});
App.register_component(this->cleaner_switch_);
}
void PoolController::setup() {
@ -107,7 +120,7 @@ void PoolController::loop() {
void PoolController::manage_pump_() {
uint32_t desired_runtime = 0;
time::ESPTime now = this->time_->now();
ESPTime now = this->time_->now();
uint8_t hour = now.hour;
uint8_t day_of_week = now.day_of_week;
switch (this->pump_mode_) {
@ -122,7 +135,7 @@ void PoolController::manage_pump_() {
desired_runtime = RUNTIME_30_MINUTES_PER_HALF_HOUR; // normal cleaner run time
} else if (day_of_week > 1 && day_of_week < 7 && hour >= 15 && hour < 20 ) {
desired_runtime = RUNTIME_10_MINUTES_PER_HALF_HOUR; // peak electric rate
} else if (hour >= 6 && hour < 20) {
} else if (hour >= 6 && hour < 22) {
desired_runtime = RUNTIME_15_MINUTES_PER_HALF_HOUR;
}
break;

View File

@ -1,12 +1,11 @@
#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"
#include "pool_select.h"
namespace esphome {
namespace pool_controller {
@ -36,7 +35,7 @@ class PoolController : public Component {
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; }
float get_setup_priority() const override { return setup_priority::LATE; }
void setup() override;
void loop() override;

View File

@ -4,29 +4,33 @@
namespace esphome {
namespace pool_controller {
static const char *const TAG = "pool_select";
static const char *const SELECT_TAG = "pool.select";
void PoolSelect::setup() {
std::string value;
ESP_LOGCONFIG(SELECT_TAG, "Setting up Pool Select");
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());
value = this->initial_option_;
ESP_LOGCONFIG(SELECT_TAG, "State from initial (could not load stored index): %s", value.c_str());
} else if (!this->has_index(index)) {
value = this->initial_option_;
ESP_LOGCONFIG(SELECT_TAG, "State from initial (restored index %d out of bounds): %s", index, value.c_str());
} else {
value = this->traits.get_options().at(index);
ESP_LOGD(TAG, "State from restore: %s", value.c_str());
value = this->at(index).value();
ESP_LOGCONFIG(SELECT_TAG, "State from restore: %s", value.c_str());
}
this->publish_state(value);
}
void PoolSelect::control(const std::string &value) {
ESP_LOGD(TAG, "%s changed to option %s", this->get_name().c_str(), value.c_str());
ESP_LOGD(SELECT_TAG, "%s changed to option %s", this->get_name().c_str(), value.c_str());
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);
auto index = this->index_of(value);
this->pref_.save(&index.value());
}
} // namespace pool_controller

View File

@ -1,6 +1,7 @@
#pragma once
#include "esphome/components/select/select.h"
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/preferences.h"
@ -11,9 +12,12 @@ class PoolSelect : public select::Select, public Component {
public:
float get_setup_priority() const override { return setup_priority::HARDWARE; }
void setup() override;
void set_initial_option(const std::string &initial_option) { this->initial_option_ = initial_option; }
protected:
void control(const std::string &value) override;
std::string initial_option_;
ESPPreferenceObject pref_;
};

View File

@ -3,6 +3,8 @@
namespace esphome {
namespace pool_controller {
static const char *const PUMP_SWITCH_TAG = "pool.pump.switch";
// 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;
@ -12,50 +14,21 @@ 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);
this->set_update_interval(1000);
this->set_restore_mode(switch_::SWITCH_ALWAYS_OFF);
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->on_physical_switch_state_change_(state);
});
this->physical_switch_ = physical_switch;
}
void PumpSwitch::setup() {
this->turn_off();
this->physical_switch_->turn_off();
}
void PumpSwitch::loop() {
void PumpSwitch::update() {
this->update_runtime_();
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;
@ -85,13 +58,31 @@ void PumpSwitch::emergency_stop() {
}
void PumpSwitch::write_state(bool state) {
if (state && this->is_disabled_) {
state = false;
}
state = state && !this->is_disabled_;
this->state = state;
this->publish_state(state);
this->update_physical_switch_();
}
void PumpSwitch::on_physical_switch_state_change_(bool state) {
if (state) {
uint32_t now = millis();
this->turned_on_at_ = now;
this->last_runtime_update_ = now;
ESP_LOGW(PUMP_SWITCH_TAG, "'%s': Physical switch turned on", this->get_name().c_str());
} else {
uint32_t now = millis();
this->turned_off_at_ = now;
this->runtime_ += now - this->last_runtime_update_;
ESP_LOGW(PUMP_SWITCH_TAG, "'%s': Physical switch turned off", this->get_name().c_str());
}
}
void PumpSwitch::update_runtime_() {
if (this->physical_switch_->state) {
uint32_t now = millis();
this->runtime_ += now - this->last_runtime_update_;
this->last_runtime_update_ = now;
}
}
void PumpSwitch::update_physical_switch_() {

View File

@ -1,12 +1,10 @@
#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/hal.h"
#include "esphome/core/preferences.h"
namespace esphome {
namespace pool_controller {
@ -19,9 +17,7 @@ class PumpSwitch : public switch_::Switch, public PollingComponent {
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;
float get_setup_priority() const override { return setup_priority::DATA; }
void update() override;
uint32_t get_current_on_time();
@ -34,6 +30,8 @@ class PumpSwitch : public switch_::Switch, public PollingComponent {
protected:
void write_state(bool state) override;
void on_physical_switch_state_change_(bool state);
void update_runtime_();
void update_physical_switch_();
void check_current_();

View File

@ -7,7 +7,7 @@ This is a custom light component that works with [TREO LED Pool Lights](https://
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
- source: github://nuttytree/ESPHome-Devices
components: [ treo_led_pool_light ]
```

View File

@ -10,7 +10,7 @@ This a modified version of the [Tuya fan](https://esphome.io/components/fan/tuya
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
- source: github://nuttytree/ESPHome-Devices
components: [ tuya_dimmer_as_fan ]
```

View File

@ -18,7 +18,7 @@ This an enhanced version of the standard [Tuya light](https://esphome.io/compone
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
- source: github://nuttytree/ESPHome-Devices
components: [ tuya_light_plus ]
```

View File

@ -2,19 +2,27 @@ substitutions:
device_id: emporia-vue2
device_name: Emporia Vue2 Power Monitor
board: esp32dev
ip_address: !secret emporia-vue2-ip
ota_pwd: !secret emporia-vue2-ota-pwd
api_key: !secret emporia-vue2-key
ap_wifi_pwd: !secret emporia-vue2-ap-pwd
ip_address: !secret emporia_vue2_ip
api_key: !secret emporia_vue2_key
pwd: !secret emporia_vue2_pwd
packages:
device_base: !include ./packages/device_base_esp32.yaml
wifi:
power_save_mode: light
api:
services:
- service: play_rtttl
variables:
song_str: string
then:
- rtttl.play:
rtttl: !lambda 'return song_str;'
preferences:
flash_write_interval: "48h"
external_components:
- source: github://flaviut/esphome@emporia-vue-2022.4.0
- source: github://emporia-vue-local/esphome@dev
components: [ emporia_vue ]
i2c:
@ -24,6 +32,17 @@ i2c:
frequency: 200kHz
id: i2c_a
output:
- platform: ledc
pin: GPIO12
id: buzzer
- platform: gpio
pin: GPIO27
id: buzzer_gnd
rtttl:
output: buzzer
# these are called references in YAML. They allow you to reuse
# this configuration in each sensor, while only defining it once
.defaultfilters:
@ -35,6 +54,12 @@ i2c:
window_size: 12
# we push a new value every 1.44 seconds
send_every: 6
- &throttle_avg
# average all raw readings together over a 5 second span before publishing
throttle_average: 5s
- &throttle_time
# only send the most recent measurement every 60 seconds
throttle: 60s
- &invert
# invert and filter out any values below 0.
lambda: 'return max(-x, 0.0f);'
@ -55,69 +80,116 @@ sensor:
# To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
voltage:
name: "Phase A Voltage"
filters: [*moving_avg, *pos]
filters: [*throttle_avg, *pos]
frequency:
name: "Power Frequency"
filters: [*throttle_avg, *pos]
- id: phase_b # Verify that this specific phase/leg is connected to correct input wire color on device listed below
input: RED # Vue device wire color
calibration: 0.022 # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
# To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
voltage:
name: "Phase B Voltage"
filters: [*moving_avg, *pos]
filters: [*throttle_avg, *pos]
ct_clamps:
# Do not specify a name for any of the power sensors here, only an id. This leaves the power sensors internal to ESPHome.
# Copy sensors will filter and then send power measurements to HA
# These non-throttled power sensors are used for accurately calculating energy
- phase_id: phase_a
input: "A" # Verify the CT going to this device input also matches the phase/leg
power:
name: "Phase A Power"
id: phase_a_power
device_class: power
filters: [*moving_avg, *pos]
filters: [*pos]
- phase_id: phase_b
input: "B" # Verify the CT going to this device input also matches the phase/leg
power:
name: "Phase B Power"
id: phase_b_power
device_class: power
filters: [*moving_avg, *pos]
filters: [*pos]
# Pay close attention to set the phase_id for each breaker by matching it to the phase/leg it connects to in the panel
- { phase_id: phase_b, input: "1", power: { name: "Furnace Power", id: cir1, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_b, input: "2", power: { name: "Dryer Power", id: cir2, filters: [ *moving_avg, *pos, multiply: 2 ] } }
- { phase_id: phase_b, input: "3", power: { name: "Garage 1 Power", id: cir3, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_b, input: "4", power: { name: "Hot Water Heater Power", id: cir4, filters: [ *moving_avg, *pos, multiply: 2 ] } }
# - { phase_id: phase_a, input: "5", power: { name: "Circuit 5 Power", id: cir5, filters: [ *moving_avg, *pos ] } }
# - { phase_id: phase_a, input: "6", power: { name: "Circuit 6 Power", id: cir6, filters: [ *moving_avg, *pos ] } }
# - { phase_id: phase_a, input: "7", power: { name: "Circuit 7 Power", id: cir7, filters: [ *moving_avg, *pos ] } }
# - { phase_id: phase_b, input: "8", power: { name: "Circuit 8 Power", id: cir8, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_a, input: "9", power: { name: "Fire Pit/Fountain Power", id: cir9, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_a, input: "10", power: { name: "Pool Accessories Total Power", id: cir10, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_a, input: "11", power: { name: "Garage 2 Power", id: cir11, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_a, input: "12", power: { name: "Air Conditioner Power", id: cir12, filters: [ *moving_avg, *pos, multiply: 2 ] } }
- { phase_id: phase_a, input: "13", power: { name: "Dish Washer Power", id: cir13, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_b, input: "14", power: { name: "Garbage Disposal Power", id: cir14, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_b, input: "15", power: { name: "Kitchen 1 Power", id: cir15, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_a, input: "16", power: { name: "Kitchen 2 Power", id: cir16, filters: [ *moving_avg, *pos ] } }
- { phase_id: phase_b, input: "1", power: { id: cir1, filters: [*pos] } }
- { phase_id: phase_b, input: "2", power: { id: cir2, filters: [*pos, multiply: 2] } }
- { phase_id: phase_b, input: "3", power: { id: cir3, filters: [*pos] } }
- { phase_id: phase_b, input: "4", power: { id: cir4, filters: [*pos, multiply: 2] } }
# - { phase_id: phase_a, input: "5", power: { id: cir5, filters: [*pos] } }
# - { phase_id: phase_a, input: "6", power: { id: cir6, filters: [*pos] } }
# - { phase_id: phase_a, input: "7", power: { id: cir7, filters: [*pos] } }
# - { phase_id: phase_b, input: "8", power: { id: cir8, filters: [*pos] } }
- { phase_id: phase_a, input: "9", power: { id: cir9, filters: [*pos] } }
- { phase_id: phase_a, input: "10", power: { id: cir10, filters: [*pos] } }
- { phase_id: phase_a, input: "11", power: { id: cir11, filters: [*pos] } }
- { phase_id: phase_a, input: "12", power: { id: cir12, filters: [*pos, multiply: 2] } }
- { phase_id: phase_a, input: "13", power: { id: cir13, filters: [*pos] } }
- { phase_id: phase_b, input: "14", power: { id: cir14, filters: [*pos] } }
- { phase_id: phase_b, input: "15", power: { id: cir15, filters: [*pos] } }
- { phase_id: phase_a, input: "16", power: { id: cir16, filters: [*pos] } }
on_update:
then:
- component.update: total_power
- component.update: balance_power
- platform: template
name: "Total Power"
lambda: return id(phase_a_power).state + id(phase_b_power).state;
update_interval: 1s
update_interval: never # will be updated after all power sensors update via on_update trigger
id: total_power
device_class: power
state_class: measurement
unit_of_measurement: "W"
- platform: total_daily_energy
name: "Total Daily Energy"
power_id: total_power
accuracy_decimals: 0
- { power_id: cir1, platform: total_daily_energy, accuracy_decimals: 0, name: "Furnace" }
- { power_id: cir2, platform: total_daily_energy, accuracy_decimals: 0, name: "Dryer" }
- { power_id: cir3, platform: total_daily_energy, accuracy_decimals: 0, name: "Garage 1" }
- { power_id: cir4, platform: total_daily_energy, accuracy_decimals: 0, name: "Hot Water Heater" }
# - { power_id: cir5, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 5 Daily Energy" }
# - { power_id: cir6, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 6 Daily Energy" }
# - { power_id: cir7, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 7 Daily Energy" }
# - { power_id: cir8, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 8 Daily Energy" }
- { power_id: cir9, platform: total_daily_energy, accuracy_decimals: 0, name: "Fire Pit/Fountain" }
- { power_id: cir10, platform: total_daily_energy, accuracy_decimals: 0, name: "Pool Accessories Total" }
- { power_id: cir11, platform: total_daily_energy, accuracy_decimals: 0, name: "Garage 2" }
- { power_id: cir12, platform: total_daily_energy, accuracy_decimals: 0, name: "Air Conditioner" }
- { power_id: cir13, platform: total_daily_energy, accuracy_decimals: 0, name: "Dish Washer" }
- { power_id: cir14, platform: total_daily_energy, accuracy_decimals: 0, name: "Garbage Disposal" }
- { power_id: cir15, platform: total_daily_energy, accuracy_decimals: 0, name: "Kitchen 1" }
- { power_id: cir16, platform: total_daily_energy, accuracy_decimals: 0, name: "Kitchen 2" }
- platform: template
lambda: !lambda |-
return max(0.0f, id(total_power).state -
id( cir1).state -
id( cir2).state -
id( cir3).state -
id( cir4).state -
id( cir9).state -
id(cir10).state -
id(cir11).state -
id(cir12).state -
id(cir13).state -
id(cir14).state -
id(cir15).state -
id(cir16).state);
update_interval: never # will be updated after all power sensors update via on_update trigger
id: balance_power
device_class: power
state_class: measurement
unit_of_measurement: "W"
# The copy sensors filter and send the power state to HA
- { platform: copy, source_id: phase_a_power, name: "Phase A Power", filters: *throttle_avg }
- { platform: copy, source_id: phase_b_power, name: "Phase B Power", filters: *throttle_avg }
- { platform: copy, source_id: total_power, name: "Total Power", filters: *throttle_avg }
- { platform: copy, source_id: balance_power, name: "Balance Power", filters: *throttle_avg }
- { platform: copy, source_id: cir1, name: "Furnace Power", filters: *throttle_avg }
- { platform: copy, source_id: cir2, name: "Dryer Power", filters: *throttle_avg }
- { platform: copy, source_id: cir3, name: "Garage 1 Power", filters: *throttle_avg }
- { platform: copy, source_id: cir4, name: "Hot Water Heater Power", filters: *throttle_avg }
# - { platform: copy, source_id: cir5, name: " Power", filters: *throttle_avg }
# - { platform: copy, source_id: cir6, name: " Power", filters: *throttle_avg }
# - { platform: copy, source_id: cir7, name: " Power", filters: *throttle_avg }
# - { platform: copy, source_id: cir8, name: " Power", filters: *throttle_avg }
- { platform: copy, source_id: cir9, name: "Fire Pit/Fountain Power", filters: *throttle_avg }
- { platform: copy, source_id: cir10, name: "Pool Accessories Total Power", filters: *throttle_avg }
- { platform: copy, source_id: cir11, name: "Garage 2 Power", filters: *throttle_avg }
- { platform: copy, source_id: cir12, name: "Air Conditioner Power", filters: *throttle_avg }
- { platform: copy, source_id: cir13, name: "Dish Washer Power", filters: *throttle_avg }
- { platform: copy, source_id: cir14, name: "Garbage Disposal Power", filters: *throttle_avg }
- { platform: copy, source_id: cir15, name: "Kitchen 1 Power", filters: *throttle_avg }
- { platform: copy, source_id: cir16, name: "Kitchen 2 Power", filters: *throttle_avg }
- { platform: total_daily_energy, power_id: total_power, accuracy_decimals: 0, restore: false, name: "Total Daily Energy", filters: *throttle_time }
- { platform: total_daily_energy, power_id: balance_power, accuracy_decimals: 0, restore: false, name: "Balance Daily Energy", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir1, accuracy_decimals: 0, restore: false, name: "Furnace", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir2, accuracy_decimals: 0, restore: false, name: "Dryer", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir3, accuracy_decimals: 0, restore: false, name: "Garage 1", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir4, accuracy_decimals: 0, restore: false, name: "Hot Water Heater", filters: *throttle_time }
# - { platform: total_daily_energy, power_id: cir5, accuracy_decimals: 0, restore: false, name: "", filters: *throttle_time }
# - { platform: total_daily_energy, power_id: cir6, accuracy_decimals: 0, restore: false, name: "", filters: *throttle_time }
# - { platform: total_daily_energy, power_id: cir7, accuracy_decimals: 0, restore: false, name: "", filters: *throttle_time }
# - { platform: total_daily_energy, power_id: cir8, accuracy_decimals: 0, restore: false, name: "", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir9, accuracy_decimals: 0, restore: false, name: "Fire Pit/Fountain", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir10, accuracy_decimals: 0, restore: false, name: "Pool Accessories Total", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir11, accuracy_decimals: 0, restore: false, name: "Garage 2", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir12, accuracy_decimals: 0, restore: false, name: "Air Conditioner", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir13, accuracy_decimals: 0, restore: false, name: "Dish Washer", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir14, accuracy_decimals: 0, restore: false, name: "Garbage Disposal", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir15, accuracy_decimals: 0, restore: false, name: "Kitchen 1", filters: *throttle_time }
- { platform: total_daily_energy, power_id: cir16, accuracy_decimals: 0, restore: false, name: "Kitchen 2", filters: *throttle_time }

View File

@ -1,10 +1,9 @@
substitutions:
device_id: family-room-tv
device_name: Family Room TV
ip_address: !secret family-room-tv-ip
ota_pwd: !secret family-room-tv-ota-pwd
api_key: !secret family-room-tv-key
ap_wifi_pwd: !secret family-room-tv-ap-pwd
ip_address: !secret family_room_tv_ip
api_key: !secret family_room_tv_key
pwd: !secret family_room_tv_pwd
packages:
feit_dimmer: !include ./packages/topgreener_smart_plug.yaml

View File

@ -2,10 +2,9 @@ substitutions:
device_id: fire-pit-fountain
device_name: Fire Pit and Fountain
board: d1_mini
ip_address: !secret fire-pit-fountain-ip
ota_pwd: !secret fire-pit-fountain-ota-pwd
api_key: !secret fire-pit-fountain-key
ap_wifi_pwd: !secret fire-pit-fountain-ap-pwd
ip_address: !secret fire_pit_fountain_ip
api_key: !secret fire_pit_fountain_key
pwd: !secret fire_pit_fountain_pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml
@ -17,6 +16,8 @@ binary_sensor:
number: D6
mode: INPUT_PULLUP
inverted: True
filters:
- delayed_on: 100ms
on_press:
then:
- switch.toggle: fountain
@ -26,6 +27,8 @@ binary_sensor:
number: D7
mode: INPUT_PULLUP
inverted: True
filters:
- delayed_on: 100ms
on_multi_click:
- timing:
- ON for at least 3s

View File

@ -2,10 +2,9 @@ substitutions:
device_id: garage-fridge
device_name: Garage Fridge
board: m5stack-atom
ip_address: !secret garage-fridge-ip
ota_pwd: !secret garage-fridge-ota-pwd
api_pwd: !secret garage-fridge-api-pwd
ap_wifi_pwd: !secret garage-fridge-ap-pwd
ip_address: !secret garage_fridge_ip
api_key: !secret garage_fridge_key
pwd: !secret garage_fridge_pwd
log_baud_rate: '0'
packages:
@ -34,9 +33,6 @@ climate:
max_integral: 0.5
esp32_ble_tracker:
scan_parameters:
interval: 1100ms
window: 1100ms
modbus:
@ -67,6 +63,9 @@ sensor:
name: Garage Freezer Humidity
battery_level:
name: Garage Freezer Sensor Battery Level
- platform: internal_temperature
name: "Garage Controller Temperature"
entity_category: diagnostic
- platform: pzemac
id: pzem
update_interval: 2s

View File

@ -1,10 +1,9 @@
substitutions:
device_id: garage-lights
device_name: Garage Lights
ip_address: !secret garage-lights-ip
ota_pwd: !secret garage-lights-ota-pwd
api_key: !secret garage-lights-key
ap_wifi_pwd: !secret garage-lights-ap-pwd
ip_address: !secret garage_lights_ip
api_key: !secret garage_lights_key
pwd: !secret garage_lights_pwd
light_wattage: '378'
packages:

View File

@ -1,10 +1,9 @@
substitutions:
device_id: kitchen-fridge
device_name: Kitchen Fridge
ip_address: !secret kitchen-fridge-ip
ota_pwd: !secret kitchen-fridge-ota-pwd
api_key: !secret kitchen-fridge-key
ap_wifi_pwd: !secret kitchen-fridge-ap-pwd
ip_address: !secret kitchen_fridge_ip
api_key: !secret kitchen_fridge_key
pwd: !secret kitchen_fridge_pwd
packages:
feit_dimmer: !include ./packages/topgreener_smart_plug.yaml

14
main-garage-door.yaml Normal file
View File

@ -0,0 +1,14 @@
substitutions:
device_id: "main-garage-door"
device_name: Main Garage Door
board: d1_mini
ip_address: !secret main_garage_door_ip
api_key: !secret main_garage_door_key
pwd: !secret main_garage_door_pwd
flash_write_interval: 5s
packages:
ratgdo.esphome: github://ratgdo/esphome-ratgdo/v25iboard.yaml@main
base: !include ./packages/device_base_esp8266.yaml
web_server: !remove

View File

@ -1,59 +0,0 @@
substitutions:
device_id: master-bath-hum-temp-sensor
device_name: Master Bathroom Humidity and Temperature Sensor
board: d1_mini
ip_address: !secret master-bath-hum-temp-sensor-ip
ota_pwd: !secret master-bath-hum-temp-sensor-ota-pwd
api_pwd: !secret master-bath-hum-temp-sensor-api-pwd
ap_wifi_pwd: !secret master-bath-hum-temp-sensor-ap-pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml
binary_sensor:
- platform: template
id: trigger_humidity
lambda: return (id(humidity).state - id(median_humidity).state) > 5;
filters:
- delayed_off: 5min
i2c:
sda: D2
scl: D1
scan: true
output:
- platform: gpio
pin: D3
id: bme_gnd
sensor:
- platform: bme280
temperature:
id: temperature
name: "Master Bathroom Temperature"
pressure:
id: pressure
name: "Master Bathroom Pressure"
humidity:
id: humidity
name: "Master Bathroom Humidity"
address: 0x76
update_interval: 15s
- platform: template
name: "Master Bathroom Median Humidity"
id: median_humidity
unit_of_measurement: '%'
icon: mdi:water-percent
lambda: return id(humidity).state;
update_interval: 60s
filters:
- median:
window_size: 360
send_every: 2
send_first_at: 2
status_led:
pin:
number: D4
inverted: true

View File

@ -2,10 +2,9 @@ substitutions:
device_id: master-bed
device_name: Master Bed
board: nodemcuv2
ip_address: !secret master-bed-ip
ota_pwd: !secret master-bed-ota-pwd
api_key: !secret master-bed-key
ap_wifi_pwd: !secret master-bed-ap-pwd
ip_address: !secret master_bed_ip
api_key: !secret master_bed_key
pwd: !secret master_bed_pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml

View File

@ -1,10 +1,9 @@
substitutions:
device_id: network-equipment
device_name: Network Equipment
ip_address: !secret network-equipment-ip
ota_pwd: !secret network-equipment-ota-pwd
api_key: !secret network-equipment-key
ap_wifi_pwd: !secret network-equipment-ap-pwd
ip_address: !secret network_equipment_ip
api_key: !secret network_equipment_key
pwd: !secret network_equipment_pwd
packages:
feit_dimmer: !include ./packages/topgreener_smart_plug.yaml

View File

@ -3,7 +3,7 @@ substitutions:
device_name: Dining Room Light
ip_address: !secret dining-room-light-ip
ota_pwd: !secret dining-room-light-ota-pwd
api_pwd: !secret dining-room-light-api-pwd
api_key: !secret dining-room-light-key
ap_wifi_pwd: !secret dining-room-light-ap-pwd
packages:

View File

@ -3,7 +3,7 @@ substitutions:
device_name: Living Room Lights
ip_address: !secret living-room-lights-ip
ota_pwd: !secret living-room-lights-ota-pwd
api_pwd: !secret living-room-lights-api-pwd
api_key: !secret living-room-lights-key
ap_wifi_pwd: !secret living-room-lights-ap-pwd
packages:

View File

@ -3,7 +3,7 @@ substitutions:
device_name: Office Light
ip_address: !secret office-light-ip
ota_pwd: !secret office-light-ota-pwd
api_pwd: !secret office-light-api-pwd
api_key: !secret office-light-key
ap_wifi_pwd: !secret office-light-ap-pwd
packages:

View File

@ -1,14 +1,16 @@
substitutions:
log_level: none
log_baud_rate: '115200'
wifi_ssid: !secret wifi-ssid
wifi_password: !secret wifi-password
ip_subnet: !secret ip-subnet
ip_gateway: !secret ip-gateway
wifi_ssid: !secret wifi_ssid
wifi_password: !secret wifi_password
ip_subnet: !secret ip_subnet
ip_gateway: !secret ip_gateway
flash_write_interval: 10min
esphome:
name: ${device_id}
friendly_name: ${device_name}
name_add_mac_suffix: false
build_path: ./build/${device_id}
${platform}:

View File

@ -1,2 +1,3 @@
ota:
password: ${ota_pwd}
platform: esphome
password: ${pwd}

View File

@ -1,14 +1,15 @@
wifi:
ssid: ${wifi_ssid}
password: ${wifi_password}
fast_connect: false
fast_connect: true
power_save_mode: none
manual_ip:
static_ip: ${ip_address}
subnet: ${ip_subnet}
gateway: ${ip_gateway}
# ap:
# ssid: ${device_id}
# password: ${ap_wifi_pwd}
ap:
ssid: ${device_id}
password: ${pwd}
ap_timeout: 5min
#captive_portal:
captive_portal:

View File

@ -2,10 +2,9 @@ substitutions:
device_id: patio-lights
device_name: Patio Lights
board: d1_mini
ip_address: !secret patio-lights-ip
ota_pwd: !secret patio-lights-ota-pwd
api_key: !secret patio-lights-key
ap_wifi_pwd: !secret patio-lights-ap-pwd
ip_address: !secret patio_lights_ip
api_key: !secret patio_lights_key
pwd: !secret patio_lights_pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml

View File

@ -2,10 +2,9 @@ substitutions:
device_id: pool-and-patio-lights
device_name: Pool and Patio Lights
board: esp01_1m
ip_address: !secret pool-and-patio-lights-ip
ota_pwd: !secret pool-and-patio-lights-ota-pwd
api_key: !secret pool-and-patio-lights-key
ap_wifi_pwd: !secret pool-and-patio-lights-ap-pwd
ip_address: !secret pool_and_patio_lights_ip
api_key: !secret pool_and_patio_lights_key
pwd: !secret pool_and_patio_lights_pwd
packages:
device_base: !include ./packages/device_base_esp8266.yaml

View File

@ -2,10 +2,10 @@ substitutions:
device_id: pool-pumps
device_name: Pool Pumps
board: modwifi
ip_address: !secret pool-pumps-ip
ota_pwd: !secret pool-pumps-ota-pwd
api_pwd: !secret pool-pumps-api-pwd
ap_wifi_pwd: !secret pool-pumps-ap-pwd
ip_address: !secret pool_pumps_ip
api_key: !secret pool_pumps_key
pwd: !secret pool_pumps_pwd
log_level: warn
packages:
device_base: !include ./packages/device_base_esp8266.yaml
@ -16,6 +16,14 @@ external_components:
path: ./components
components: [ pool_controller ]
binary_sensor:
# Prevent short circuit with "floating" pin!
- platform: gpio
pin: GPIO16
name: "ade7953 IRQ pin"
internal: true
i2c:
sda: GPIO12
scl: GPIO14
@ -35,7 +43,7 @@ pool_controller:
max_out_of_range_duration: 10s
sensor:
- platform: ade7953
- platform: ade7953_i2c
voltage:
name: ${device_name} Voltage
id: voltage
@ -106,11 +114,11 @@ switch:
pin: GPIO4
name: "Pool Pump"
id: pool_pump
icon: mdi:pump
restore_mode: Always Off
internal: true
- platform: gpio
pin: GPIO15
name: "Pool Cleaner"
id: pool_cleaner
icon: mdi:robot-vacuum
restore_mode: Always Off
internal: true

View File

@ -2,19 +2,17 @@ substitutions:
device_id: second-garage-door
device_name: Second Garage Door
board: d1_mini
ip_address: !secret second-garage-door-ip
ota_pwd: !secret second-garage-door-ota-pwd
api_pwd: !secret second-garage-door-api-pwd
ap_wifi_pwd: !secret second-garage-door-ap-pwd
log_level: debug
ip_address: !secret second_garage_door_ip
api_key: !secret second_garage_door_key
pwd: !secret second_garage_door_pwd
packages:
device_base: !include ../packages/device_base_esp8266.yaml
device_base: !include ./packages/device_base_esp8266.yaml
external_components:
- source:
type: local
path: ../components
path: ./components
components: [ garage_door ]
binary_sensor:
@ -78,10 +76,6 @@ cover:
last_close_time_sensor:
name: ${device_name} Last Close Time
logger:
logs:
sensor: NONE
output:
- platform: gpio
id: control_out
@ -99,7 +93,7 @@ sensor:
id: button_in
pin: A0
raw: true
update_interval: 75ms
update_interval: 100ms
status_led:
pin:

View File

@ -1,10 +1,9 @@
substitutions:
device_id: sump-pump
device_name: Sump Pump
ip_address: !secret sump-pump-ip
ota_pwd: !secret sump-pump-ota-pwd
api_key: !secret sump-pump-key
ap_wifi_pwd: !secret sump-pump-ap-pwd
ip_address: !secret sump_pump_ip
api_key: !secret sump_pump_key
pwd: !secret sump_pump_pwd
packages:
feit_dimmer: !include ./packages/topgreener_smart_plug.yaml

View File

@ -1,10 +1,9 @@
substitutions:
device_id: washing-machine
device_name: Washing Machine
ip_address: !secret washing-machine-ip
ota_pwd: !secret washing-machine-ota-pwd
api_key: !secret washing-machine-key
ap_wifi_pwd: !secret washing-machine-ap-pwd
ip_address: !secret washing_machine_ip
api_key: !secret washing_machine_key
pwd: !secret washing_machine_pwd
packages:
feit_dimmer: !include ./packages/topgreener_smart_plug.yaml