Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
**/.piolibdeps/
**/lib/
**/src/
/build/
/devices/build/
**/platformio.ini
/secrets.yaml
/devices/secrets.yaml
# ESPHome rewrites this on every compile if it's missing; its rules are covered above
/devices/.gitignore
__pycache__/
*.py[cod]
*$py.class
Expand Down
26 changes: 14 additions & 12 deletions CLAUDE.md

Large diffs are not rendered by default.

51 changes: 27 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ Home Assistant is open source home automation that puts local control and privac


## Folder Structure
* `/` - Yaml files for my devices and other core files
* `/` - Repo level files (linting/formatting config, docs, license)
* `/components` - Custom components
* `/devices` - Yaml files for my devices; this is the folder mounted as the config folder in the ESPHome container
* `/devices/packages` - Shared packages used by my devices
* `/docs` - Detailed write-ups (photos, schematics, notes) for my more complex/custom devices
* `/images` - Misc pictures not tied to a specific device doc
* `/packages` - Shared packages used by my devices
* `/scripts` - Scripts for managing the repo

Because `/devices` is what the ESPHome container sees as `/config`, the custom components in `/components` are mounted alongside it so that `path: ../components` resolves from either the container or a local ESPHome CLI run.


## 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).
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 `/devices` folder (that for obvious reasons is not included in the repo).


## Custom Components
Expand All @@ -41,29 +44,29 @@ Detects per-side bed occupancy using resistive pressure sensors multiplexed onto
A single Home Assistant climate entity that manages a multi-zone Econet-connected furnace/AC, balancing airflow across zones when idle and syncing mode/temperature with the physical thermostat. Used by [HVAC](./docs/hvac/README.md). Details: [components/econet_zone_control/README.md](./components/econet_zone_control/README.md).

### High Temp Water Heater
Sits in front of an Econet water heater so any target temperature can be set from Home Assistant while the physical unit itself stays pinned at a fixed setting (150°F) — the physical control panel only lets you adjust it to values above 140°F, so this is how I get finer/lower control (useful for time-of-use electric rates). Used by [Water Heater](./water-heater.yaml). Details: [components/high_temp_water_heater/README.md](./components/high_temp_water_heater/README.md).
Sits in front of an Econet water heater so any target temperature can be set from Home Assistant while the physical unit itself stays pinned at a fixed setting (150°F) — the physical control panel only lets you adjust it to values above 140°F, so this is how I get finer/lower control (useful for time-of-use electric rates). Used by [Water Heater](./devices/water-heater.yaml). Details: [components/high_temp_water_heater/README.md](./components/high_temp_water_heater/README.md).


## Misc Devices
### [Coffee Maker](./coffee-maker.yaml)
### [Coffee Maker](./devices/coffee-maker.yaml)
This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK) that I installed in my [Cuisinart Coffee Maker](https://www.amazon.com/gp/product/B01N6T5QNO). It has GPIO's connected to the indicator lights for the bold setting and power and has a couple of [relays](https://www.amazon.com/gp/product/B0057OC6D8) connected to the bold setting button and the power button.

### [Fire Pit and Fountain](./fire-pit-fountain.yaml)
### [Fire Pit and Fountain](./devices/fire-pit-fountain.yaml)
This is a [WEMOS D1 Mini Pro](https://www.amazon.com/gp/product/B07G9HZ5LM) that is connected to a couple of [relays](https://www.amazon.com/gp/product/B0057OC6D8) and a couple of water proof push buttons [red](https://www.amazon.com/gp/product/B079GNNSRP) and [blue](https://www.amazon.com/gp/product/B079GK565N). The multi-click config on the fire pit switch is so that any press will turn it off but to turn it on you have to press it for 3 seconds (to try and prevent kids from turning it on). This is used to control the combination fire pit and fountain in my backyard. I just got this hooked up and is working good other then the fire pit doesn't always come on on the first try (I think I am getting some bounce in the switch but haven't had a chance to troubleshoot further).

### [Garage Fridge](./garage-fridge.yaml)
### [Garage Fridge](./devices/garage-fridge.yaml)
A [M5Stack ATOM HUB SwitchD](https://shop.m5stack.com/products/atom-hub-switchd-2-relay-kit) with power and temperature monitoring plus PID-controlled freeze-protection heaters. Full write-up and photos: [docs/garage-fridge](./docs/garage-fridge/README.md).

### [HVAC](./hvac.yaml)
### [HVAC](./devices/hvac.yaml)
A [M5Stack ATOMIC RS485 Base](https://shop.m5stack.com/products/atomic-rs485-base) with an ESP32 connected to a 3-zone Rheem furnace/AC system (Main Floor, Upstairs, Basement) integrated via [ESPHome Econet](https://github.com/esphome-econet/esphome-econet) and the custom [Econet Zone Control](./components/econet_zone_control/README.md) component, which presents all zones as a single Home Assistant climate entity and balances airflow across zones when idle. Full write-up: [docs/hvac](./docs/hvac/README.md).

### [Master Bed](./master-bed.yaml)
### [Master Bed](./devices/master-bed.yaml)
A [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK) under the mattress that detects per-side occupancy using a pair of Force Sensitive Resistors and the custom [bed_sensor](./components/bed_sensor/README.md) component. Full write-up: [docs/master-bed](./docs/master-bed/README.md).

### [Pool](./pool.yaml)
### [Pool](./devices/pool.yaml)
A [Waveshare ESP32-S3 7" Touch LCD B](https://www.waveshare.com/product/esp32-s3-lcd-7b.htm) running the custom [Pool Controller](./components/pool_controller/README.md) and [PZEM-6L24](./components/pzem6l24/README.md) components to manage pump scheduling, water chemistry, and (eventually) heat/fill/drain. Full write-up: [docs/pool](./docs/pool/README.md).

### [Water Heater](./water-heater.yaml)
### [Water Heater](./devices/water-heater.yaml)
A [M5Stack ATOMIC RS485 Base](https://shop.m5stack.com/products/atomic-rs485-base) with an ESP32 connected to a Rheem hybrid water heater managed through the [ESPHome Econet](https://github.com/esphome-econet/esphome-econet) component. The custom [High Temp Water Heater](./components/high_temp_water_heater/README.md) component sits in front of it so I can set any target temperature I want (e.g. 140°F during peak electric rate hours) while the physical water heater setting itself stays fixed at 150°F — the physical control panel only lets you adjust it to values above 140°F.


Expand All @@ -75,37 +78,37 @@ This device is sinificantly cheaper then a Sense Energy Monitor, can monitor 16
## Smart Plugs
### [TOPGREENER TGWF115PQM Smart Plugs](https://www.amazon.com/gp/product/B07D8ZVJN2)
I have a bunch of these smart plugs that I use for various things where I want to monitor the power consumption and/or be able to completely turn off the power (because they have a significant standby power draw). The TOPGREENER units are cheap, can be flashed with [Tuya-Convert](https://github.com/ct-Open-Source/tuya-convert) (or they could last time I bought one), and have power monitoring.
* [Basement Fridge](./basement-fridge.yaml)
* [Basement TV](./basement-tv.yaml)
* [Family Room TV](./family-room-tv.yaml)
* [Kitchen Fridge](./kitchen-fridge.yaml)
* [Network Equipment](./network-equipment.yaml)
* [Sump Pump](./sump-pump.yaml)
* [Washing Machine](./washing-machine.yaml)
* [Basement Fridge](./devices/basement-fridge.yaml)
* [Basement TV](./devices/basement-tv.yaml)
* [Family Room TV](./devices/family-room-tv.yaml)
* [Kitchen Fridge](./devices/kitchen-fridge.yaml)
* [Network Equipment](./devices/network-equipment.yaml)
* [Sump Pump](./devices/sump-pump.yaml)
* [Washing Machine](./devices/washing-machine.yaml)


## Switches
### [SANA Dual Switch](https://www.amazon.com/gp/product/B07QC5ZCHP)
My basement bathroom has a single gang box (and not enough room to swith to dual gang) for the switches to control the shower light and heat lamps so this is a perfect fit. The price is right, the buttons feel solid, and I was able to flash it using [Tuya-Convert](https://github.com/ct-Open-Source/tuya-convert). It does seem to have corners that are squarer then typical so I had a little bit of trouble getting a standard cover to fit but nothing I couldn't fix with a file.
* [Basement Bathroom Shower Light and Heater](./basement-bath-shower-light-heat.yaml)
* [Basement Bathroom Shower Light and Heater](./devices/basement-bath-shower-light-heat.yaml)

### [SANA Triple Switch](https://www.amazon.com/gp/product/B07Q5XPRKD)
This is installed in place of the switch that controled my [TREO LED Pool Lights](https://www.srsmith.com/en-us/products/pool-lighting/treo-led-pool-light/). These lights have the option to select different colors by briefly turning them off and back on again and they do remember the last color when turned on again. The custom [Treo Led Pool Lights](./components/treo_led_pool_light/README.md) component handles tracking the current color and exposes custom "effects" for each of the colors to [Home Assistant](https://www.home-assistant.io/). I have this configured to turn the lights on/off with the top/bottum buttons and use the middle button to change colors.
* [Pool Lights](./pool-lights.yaml)
* [Pool Lights](./devices/pool-lights.yaml)

### [Shelly 1L](https://shelly.cloud/products/shelly-1l-single-wire-smart-home-automation-relay/)
My garage lights are not dimmable so I decided to try out a Shelly device, I have this connected to a [Leviton 5657-2W Momentary Center-Off Decora Rocker](https://www.amazon.com/gp/product/B000U3BU56). Overall I am fairly happy with it I just wish the rocker switch wasn't so expensive or there was another similar option.
* [Garage Lights](./garage-lights.yaml)
* [Garage Lights](./devices/garage-lights.yaml)


## Garage Doors
### [Ratgdo](https://paulwieland.github.io/ratgdo/)
Both garage door openers are controlled by [ratgdo](https://paulwieland.github.io/ratgdo/) boards running the [esphome-ratgdo](https://github.com/ratgdo/esphome-ratgdo) external package, which taps into the opener's built-in security+2.0 wall panel/dry-contact wiring instead of a relay-across-the-button hack.
* [Main Garage Door](./main-garage-door.yaml) — v2.5i board variant connected to a Chambelain MyQ opener
* [Second Garage Door](./second-garage-door.yaml) — dry-contact variant connected to an old opener
* [Main Garage Door](./devices/main-garage-door.yaml) — v2.5i board variant connected to a Chambelain MyQ opener
* [Second Garage Door](./devices/second-garage-door.yaml) — dry-contact variant connected to an old opener


## Network
### Bluetooth Proxy
An ESP32 running ESPHome's [Bluetooth Proxy](https://esphome.io/components/bluetooth_proxy.html) to extend Home Assistant's Bluetooth range.
* [Basement Bluetooth Proxy](./bt-proxy-basement.yaml)
* [Basement Bluetooth Proxy](./devices/bt-proxy-basement.yaml)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion hvac.yaml → devices/hvac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ substitutions:
external_components:
- source:
type: local
path: ./components
path: ../components
components: [ econet_zone_control ]

packages:
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion master-bed.yaml → devices/master-bed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ packages:
external_components:
- source:
type: local
path: ./components
path: ../components
components: [ bed_sensor ]

sensor:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion pool-lights.yaml → devices/pool-lights.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ packages:
external_components:
- source:
type: local
path: ./components
path: ../components
components: [ treo_led_pool_light ]

# Required to allow the Treo light to register the color reset service
Expand Down
2 changes: 1 addition & 1 deletion pool.yaml → devices/pool.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ packages:
external_components:
- source:
type: local
path: ./components
path: ../components
components: [pool_controller, pzem6l24]

esphome:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion water-heater.yaml → devices/water-heater.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ substitutions:
external_components:
- source:
type: local
path: ./components
path: ../components
components: [ high_temp_water_heater ]

packages:
Expand Down
2 changes: 1 addition & 1 deletion docs/garage-fridge/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Garage Fridge

## Overview
This is a [M5Stack ATOM HUB SwitchD](https://shop.m5stack.com/products/atom-hub-switchd-2-relay-kit) mounted in a [box](https://www.amazon.com/gp/product/B07ZBRK5NL) on the side of the garage fridge, paired with a [PZEM-004T](https://www.amazon.com/gp/product/B0855T6VHT) for power monitoring and 2 [Inkbird IBS-TH1 sensors](https://www.amazon.com/gp/product/B0774BGBHS) for temperature in the fridge and freezer sections. Configuration lives in [garage-fridge.yaml](../../garage-fridge.yaml).
This is a [M5Stack ATOM HUB SwitchD](https://shop.m5stack.com/products/atom-hub-switchd-2-relay-kit) mounted in a [box](https://www.amazon.com/gp/product/B07ZBRK5NL) on the side of the garage fridge, paired with a [PZEM-004T](https://www.amazon.com/gp/product/B0855T6VHT) for power monitoring and 2 [Inkbird IBS-TH1 sensors](https://www.amazon.com/gp/product/B0774BGBHS) for temperature in the fridge and freezer sections. Configuration lives in [garage-fridge.yaml](../../devices/garage-fridge.yaml).

## Freeze Protection
One of the relays on the M5Stack ATOM HUB SwitchD controls a pair of [heaters](https://www.amazon.com/gp/product/B07GXSDMR2) inside the fridge to keep it from dropping below freezing (frozen beer is no fun), using ESPHome's [PID climate controller](https://esphome.io/components/climate/pid.html).
Expand Down
2 changes: 1 addition & 1 deletion docs/hvac/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# HVAC

## Overview
The house HVAC (a Rheem furnace + air conditioner) is a 3-zone system (Main Floor, Upstairs, Basement) integrated with Home Assistant via the [ESPHome Econet](https://github.com/esphome-econet/esphome-econet) component, plus a custom [Econet Zone Control](../../components/econet_zone_control/README.md) component. Configuration lives in [hvac.yaml](../../hvac.yaml).
The house HVAC (a Rheem furnace + air conditioner) is a 3-zone system (Main Floor, Upstairs, Basement) integrated with Home Assistant via the [ESPHome Econet](https://github.com/esphome-econet/esphome-econet) component, plus a custom [Econet Zone Control](../../components/econet_zone_control/README.md) component. Configuration lives in [hvac.yaml](../../devices/hvac.yaml).

## Why a Custom Component
Rather than 3 independent thermostats, the goals were:
Expand Down
2 changes: 1 addition & 1 deletion docs/master-bed/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Master Bed

## Overview
This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK) installed under the bed, connected to a pair of [Force Sensitive Resistors](https://www.adafruit.com/product/1071) placed between the mattress and box spring — one per side. Configuration lives in [master-bed.yaml](../../master-bed.yaml), and the sensor logic is implemented in the custom [bed_sensor](../../components/bed_sensor/README.md) component.
This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK) installed under the bed, connected to a pair of [Force Sensitive Resistors](https://www.adafruit.com/product/1071) placed between the mattress and box spring — one per side. Configuration lives in [master-bed.yaml](../../devices/master-bed.yaml), and the sensor logic is implemented in the custom [bed_sensor](../../components/bed_sensor/README.md) component.

## Hardware Notes
The ESP8266 only has one analog input, so transistors on pins D0 and D1 select which FSR is connected to the A0 analog input. The `bed_sensor` component handles switching between the FSRs and reading their values.
Expand Down
2 changes: 1 addition & 1 deletion docs/pool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Work in progress — this device is actively being expanded. The sections marked `TODO` below are placeholders waiting on details, photos, and schematics.

## Overview
The pool is controlled by a [Waveshare ESP32-S3 7" Touch LCD B](https://www.waveshare.com/product/esp32-s3-lcd-7b.htm) running a touchscreen UI (LVGL) plus the custom [Pool Controller](../../components/pool_controller/README.md) and [PZEM-6L24](../../components/pzem6l24/README.md) components. Configuration lives in [pool.yaml](../../pool.yaml).
The pool is controlled by a [Waveshare ESP32-S3 7" Touch LCD B](https://www.waveshare.com/product/esp32-s3-lcd-7b.htm) running a touchscreen UI (LVGL) plus the custom [Pool Controller](../../components/pool_controller/README.md) and [PZEM-6L24](../../components/pzem6l24/README.md) components. Configuration lives in [pool.yaml](../../devices/pool.yaml).

## Hardware
- Controller board: Waveshare ESP32-S3 7" Touch LCD B (`esp32s3`), MIPI RGB display + GT911 touch
Expand Down
13 changes: 7 additions & 6 deletions scripts/tag_esphome_version.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
"""Tag the current commit with the lowest ESPHome version every device is confirmed running.

Reads .esphome/.device-builder-devices.json (local Device Builder state) and, once every
device yaml at the repo root reports a deployed_version with a deployed_config_hash matching
Reads devices/.esphome/.device-builder-devices.json (local Device Builder state) and, once
every device yaml in devices/ reports a deployed_version with a deployed_config_hash matching
its expected_config_hash, tags the current commit with the lowest of those versions -- unless
a tag at or above that version already exists. Intended to run as a post-commit hook so HEAD
is the commit being tagged. Never pushes; run `git push --follow-tags` (or push the tag
Expand All @@ -16,8 +16,9 @@
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent.parent
DEVICES_JSON = REPO_ROOT / ".esphome" / ".device-builder-devices.json"
EXCLUDED_ROOT_YAML = {"secrets.yaml"}
DEVICES_DIR = REPO_ROOT / "devices"
DEVICES_JSON = DEVICES_DIR / ".esphome" / ".device-builder-devices.json"
EXCLUDED_DEVICE_YAML = {"secrets.yaml"}

VERSION_RE = re.compile(r"^\d+(?:\.\d+)*")

Expand All @@ -32,8 +33,8 @@ def version_key(version):
def device_yaml_files():
return sorted(
p.name
for p in REPO_ROOT.glob("*.yaml")
if p.name not in EXCLUDED_ROOT_YAML and not p.name.startswith(".")
for p in DEVICES_DIR.glob("*.yaml")
if p.name not in EXCLUDED_DEVICE_YAML and not p.name.startswith(".")
)


Expand Down
Loading