Skip to content

Commit 43f504a

Browse files
committed
Routine update
1 parent a076757 commit 43f504a

38 files changed

Lines changed: 4743 additions & 1987 deletions
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
tags:
3+
- article
4+
- automation
5+
- python
6+
- architecture
7+
date: 2026-01-21
8+
status: published
9+
---
10+
11+
# Redesigning Area Automation: From YAML to Python
12+
13+
**Date:** January 21, 2026
14+
**Author:** EvisHomeLab Architect
15+
**Tags:** `automation`, `python`, `pyscript`
16+
17+
## The Problem with YAML
18+
19+
For years, our "Room Manager" relied on complex YAML packages with heavy use of `trigger_variables`, `choose` blocks, and limited state tracking. It worked, but it was fragile. Adding a simple feature like "Dim lights before turning off" required modifying multiple automation blocks and risking breaking the entire flow.
20+
21+
We faced specific challenges:
22+
1. **Race Conditions:** If you re-entered a room *exactly* as the lights were turning off, the system often got confused.
23+
2. **Rigidity:** Adding a "Manual Mode" (don't automate lights, but track presence) was nearly impossible.
24+
3. **Maintenance:** The YAML file grew to 1000+ lines of repetitive code.
25+
26+
## The Solution: A Decoupled Architecture
27+
28+
We completely rewrote the system using **Pyscript**, fully embracing a "State Machine" design pattern.
29+
30+
### 1. Separation of Concerns
31+
We split the logic into two distinct layers:
32+
* **Presence Layer (`area_presence.py`):** Determines the "Truth" of the room. Is it Occupied? Idle? Asleep?
33+
* **Automation Layer (`area_automations.py`):** Reacts to the Truth. "Oh, the room is Occupied? The mode is 'Presence Control'? Okay, I'll turn on the lights."
34+
35+
### 2. The Power of Python
36+
Moving to Python allowed us to implement features that were redundant in YAML:
37+
38+
* **Smart Off Delay:** When you leave a room, the lights don't just snap off. They enter a "Warning" state (dimming) for 2 minutes. The system intelligently checks *if the lights are actually on* before doing this, preventing ghost lights at night.
39+
* **Dynamic Timers:** We can now see exactly how many seconds are left before a room goes "Idle" directly on the dashboard.
40+
* **Time-of-Day Scenes:** The code automatically looks up `select.area_living_room_[period]_scene`. If it's Morning, you get the Morning scene. If it's Night, you get the Night scene. No hardcoding.
41+
42+
## Configuration via MQTT
43+
44+
Everything is configured via MQTT Discovery. This means we can "spawn" a new Area just by running a script. The definitions in `area_manager.yaml` generate:
45+
* `binary_sensor.area_x_occupancy`
46+
* `select.area_x_mode` (Presence, Absence, Manual)
47+
* `number.area_x_idle_time`
48+
* `switch.area_x_dnd`
49+
50+
## Conclusion
51+
52+
The new system is faster, more robust, and significantly easier to debug. By treating our home automation as a software engineering problem—using State Machines and Event Listeners—we've gained stability and flexibility that YAML simply couldn't provide.
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
title: Home Assistant Area Management & Automation
3+
date: 2026-01-18
4+
draft: true
5+
highlight: false
6+
tags:
7+
- smart-home
8+
- automation
9+
- home-assistant
10+
description: Comprehensive guide to Custom Area Management & Automation system for presence-based home automation.
11+
---
12+
13+
# Area Management & Automation
14+
15+
This article documents the complete Area Management & Automation system, which enables intelligent presence-based control of lights, climate, and other devices throughout the home.
16+
17+
## Overview
18+
19+
The system consists of two main components:
20+
21+
1. **Area Manager** (`area_manager.yaml`) — Dynamically creates and manages area entities via MQTT
22+
2. **Area Logic** (`pyscript/area_logic.py`) — State machine that processes occupancy changes
23+
3. **Area Automations** (`area_automations.yaml`) — Executes actions based on state transitions *(planned)*
24+
25+
---
26+
27+
## Automation Modes
28+
29+
Each area can operate in one of four modes, controlling how the system responds to presence:
30+
31+
| Mode | Description |
32+
|------|-------------|
33+
| `presence-control` | Full automation: responds to all state changes (occupied, idle, absence, sleep) |
34+
| `absence-detection` | Only responds to absence — useful for "turn off when empty" without auto-on |
35+
| `manual-control` | No automatic actions — area state still tracked but no automations fire |
36+
| `schedule-mode` | Actions based on time schedule rather than presence *(future)* |
37+
38+
---
39+
40+
## Mode-Based Filtering
41+
42+
The automation mode controls which state transitions trigger actions:
43+
44+
| Mode | Occupied | Idle | Absence | Sleep |
45+
|------|:--------:|:----:|:-------:|:-----:|
46+
| `presence-control` |||||
47+
| `absence-detection` |||||
48+
| `schedule-mode` |||||
49+
| `manual-control` |||||
50+
51+
> [!NOTE]
52+
> The `schedule-mode` uses time-based rules instead of presence triggers.
53+
54+
---
55+
56+
## State Machine Flow
57+
58+
When presence is detected, areas transition through the following states:
59+
60+
```mermaid
61+
stateDiagram-v2
62+
direction LR
63+
64+
[*] --> Absence : Initial
65+
66+
Absence --> Occupied : Motion Detected
67+
Occupied --> Idle : Motion Stops
68+
Idle --> Occupied : Motion Detected
69+
Idle --> Absence : Idle Timer Expires
70+
Absence --> [*] : Shutdown Event
71+
72+
Occupied --> Sleep : Bed Sensor ON\n(after entry delay)
73+
Sleep --> Occupied : Bed Sensor OFF\n(after exit delay)
74+
```
75+
76+
### State Descriptions
77+
78+
| State | Description | Triggered By |
79+
|-------|-------------|--------------|
80+
| **Occupied** | Active presence detected | Occupancy sensor turns ON |
81+
| **Idle** | No motion but grace period active | Occupancy sensor turns OFF |
82+
| **Absence** | Area confirmed empty | Idle timer expires |
83+
| **Sleep** | Occupant is sleeping | Bed sensor ON + entry delay |
84+
| **DND** | Do Not Disturb (manual override) | User sets manually |
85+
86+
---
87+
88+
## Key Entities
89+
90+
When an area is initialized, the following entities are created via MQTT discovery:
91+
92+
### Configuration Entities
93+
94+
| Entity Pattern | Type | Purpose |
95+
|----------------|------|---------|
96+
| `select.area_{slug}_automation_mode` | Select | Sets the automation mode |
97+
| `select.area_{slug}_occupancy_source` | Select | Physical sensor for presence |
98+
| `select.area_{slug}_bed_sensor` | Select | Physical sensor for sleep detection |
99+
| `switch.area_{slug}_automation` | Switch | Master enable/disable for this area |
100+
101+
### Timer Settings
102+
103+
| Entity Pattern | Type | Default | Purpose |
104+
|----------------|------|---------|---------|
105+
| `number.area_{slug}_presence_idle_time` | Number | 15s | Time before Occupied → Idle |
106+
| `number.area_{slug}_lights_presence_delay` | Number | 120s | Time before Idle → Absence (shutdown) |
107+
| `number.area_{slug}_sleep_entry_delay` | Number | 300s | Time in bed before Sleep state |
108+
| `number.area_{slug}_sleep_exit_delay` | Number | 60s | Time out of bed before leaving Sleep |
109+
110+
### State Entities
111+
112+
| Entity Pattern | Type | Purpose |
113+
|----------------|------|---------|
114+
| `select.area_{slug}_state` | Select | Current area state (Occupied/Idle/Absence/Sleep/DND) |
115+
| `binary_sensor.area_{slug}_occupancy` | Binary Sensor | Computed occupancy (ON when state is not Absence) |
116+
| `sensor.area_{slug}_timer` | Sensor | Countdown timer display |
117+
118+
---
119+
120+
## Events Fired
121+
122+
The system fires events that automations can listen to:
123+
124+
| Event | When Fired | Data |
125+
|-------|------------|------|
126+
| `event_area_{slug}_wakeup` | Area transitions TO "Occupied" | `area: {slug}` |
127+
| `event_area_{slug}_shutdown` | Absence delay timer expires | `area: {slug}` |
128+
129+
### Example Automation Trigger
130+
131+
```yaml
132+
automation:
133+
- alias: "Office: Turn off lights on shutdown"
134+
trigger:
135+
- platform: event
136+
event_type: event_area_office_shutdown
137+
action:
138+
- service: light.turn_off
139+
target:
140+
area_id: office
141+
```
142+
143+
---
144+
145+
## Time-Based Actions (Planned)
146+
147+
Area automations will support different actions based on time of day using the [Home Time Modes](../packages/home_time_modes.md) package:
148+
149+
| Time Mode | Typical Use |
150+
|-----------|-------------|
151+
| `Morning` | Bright, energizing lights |
152+
| `Day` | Full brightness, productivity focus |
153+
| `Evening` | Warm, relaxed lighting |
154+
| `Night` | Minimal lighting, sleep-friendly |
155+
156+
### Example Configuration
157+
158+
```yaml
159+
occupied:
160+
- when: [morning, evening]
161+
action: turn_on
162+
scene: cozy
163+
- when: [day]
164+
action: turn_on
165+
scene: bright
166+
- when: [night]
167+
action: turn_on
168+
scene: dim
169+
170+
absence:
171+
- when: [always]
172+
action: turn_off
173+
```
174+
175+
---
176+
177+
## Related Documentation
178+
179+
- [Area Manager Package](../packages/area_manager.md) — Technical YAML configuration
180+
- [Home Time Modes](../packages/home_time_modes.md) — Time-of-day scheduling
181+
- [Area Occupancy Sensor](area-occupancy-sensor.md) — Physical presence sensors

docs/articles/self-healing-tailscale-nodes.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,39 @@ To ensure the pulse is consistent, we schedule the script to run every minute us
184184
* * * * * /usr/local/bin/ts-heartbeat.sh
185185
```
186186

187+
## Troubleshooting: DNS Conflicts
188+
189+
If you see **"Health check: System DNS config not ideal"** or `connection reset by peer` errors in your logs, Proxmox and Tailscale are likely fighting over `/etc/resolv.conf`.
190+
191+
Proxmox LXCs overwrite this file on every reboot to match the host settings, which breaks Tailscale's internal MagicDNS routing. To fix this, you must tell Proxmox to stop managing this specific file:
192+
193+
```bash
194+
# Run this inside the LXC
195+
touch /etc/.pve-ignore.resolv.conf
196+
reboot
197+
```
198+
199+
After rebooting, verify the fix:
200+
```bash
201+
cat /etc/resolv.conf
202+
# Output should start with: "# resolv.conf(5) file generated by tailscale"
203+
```
204+
205+
### Network Stability (Connection Reset Errors)
206+
207+
If you see `read: connection reset by peer` errors in your logs (especially from AdGuard Home or other DNS servers), the LXC's virtual network driver is likely corrupting packets due to aggressive hardware offloading.
208+
209+
**The Fix:** Disable checksum offloading on the LXC interface.
210+
211+
```bash
212+
# 1. Install ethtool
213+
apt update && apt install -y ethtool
214+
215+
# 2. Add this command to your heartbeat script (/usr/local/bin/ts-heartbeat.sh)
216+
# This prevents the virtual NIC from trying to calculate checksums (which fails for NAT/VPN traffic)
217+
/usr/sbin/ethtool -K eth0 tx off rx off gso off gro off > /dev/null 2>&1
218+
```
219+
187220
## Home Assistant Integration (The Package)
188221

189222
Instead of scattered sensors, we bundle the logic into a single Home Assistant Package. This includes a template binary sensor, a maintenance toggle, and the self-healing automation.

docs/articles/virtual-fireplace.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ tags:
1919
<source src="../virtual-fireplace/virtual-fireplace.mp4" type="video/mp4">
2020
</video>
2121

22+
> [!INFO] "Technical Reference"
23+
> This article covers the **hardware build**. For the live automation logic and YAML configuration, see the **[Fireplace Automation Package](../smart-home/packages/fireplace_automation.md)**.
24+
2225
## WLED
2326

2427
check these

docs/articles/zigbee-network.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: Zigbee Network / Sonoff ZBDongle-E
3+
date: 2026-01-17
4+
description: Build a custom wall mount for your Philips Hue motion sensor.
5+
image: ambilight-2012-2022/ambilight.jpg
6+
draft: true
7+
highlight: false
8+
tags:
9+
- zigbee
10+
- sonoff
11+
- zbdongle-e
12+
---
13+
14+
# Zigbee Network / Sonoff ZBDongle-E
15+
16+
This focuses more on the Sonoff ZBDongle-E and how to use it to create a Zigbee network, and fix problems I run into.
17+
18+
My Zigbee network is currently experiencing a lot of "buffer overflow" and "Broadcast Failed", and I am
19+
20+
<br/>
21+
22+
## Solutions
23+
24+
* Flashing the firmware (with Hardware Flow Control)
25+
* Using a USB extension cable to connect the ZBDongle-E to my Raspberry Pi running Zigbee2MQTT
26+
* Enabling the Hardware Flow Control
27+
* Increasing the baudrate from 115200 to 460800
28+
* "Hard Mesh Reser"
29+
30+
```YAML
31+
serial:
32+
port: /dev/ttyACM0
33+
adapter: ember
34+
baudrate: 460800 # Matches the firmware you just flashed
35+
rtscts: true # Enables the Hardware Flow Control
36+
```
37+
38+
<br/>
39+
40+
## Hard Mesh Reset
41+
42+
Because Zigbee routers (lights and switches) cache routing paths, a simple software restart won't clear a stuck broadcast queue. You need to force the entire mesh to forget the deadlocked paths.
43+
44+
1. Stop the Zigbee2MQTT container.
45+
2. Unplug the Zigbee Coordinator from the Pi.
46+
3. Kill the power to your Zigbee Routers: Turn off the circuit breakers for your Kitchen, Bathroom, and Bedroom lights for at least 30 seconds.
47+
4. Plug the Coordinator back in (Ensure it is on a USB 2.0 extension cable).
48+
5. Start Zigbee2MQTT.
49+
6. Restore power to the lights.
50+
51+
This forces every device to re-announce itself and rebuild the routing table from scratch.
52+
53+
<br/>
54+
55+
## Flashing the firmware
56+
57+
* Download the latest firmware from the [Sonoff ZBDongle-E](https://sonoff.tech/sonoff-zbdongle-e/)
58+
* Flash the firmware using the [Sonoff ZBDongle-E](https://sonoff.tech/sonoff-zbdongle-e/)
59+
60+
Firmware: Ensure you are running EmberZNet 7.4.x or newer. If your firmware is from 2024 or earlier, it may have a bug regarding buffer management that was fixed in late 2025.
61+
62+
<br/>
63+
64+
## Raspberry Pi 5 USB ports
65+
66+
Your setup (RPi 5 + long extension cable) is perfect, but there is one final trick:
67+
68+
Use the USB 2.0 (Black) ports on the Pi 5.
69+
70+
The Blue (USB 3.0) ports on the Pi 5 generate a massive amount of 2.4GHz noise right at the port, which can travel down the shielding of even a long cable. Using the black port removes this interference entirely.
71+
72+
73+
74+
## Chatty Devices Fooling the Coordinator
75+
76+
* Aqara W500
77+
* Washing Machine plug
78+
79+
absolutely flooding your network
80+
81+
The "Spam" Analysis
82+
Look at the timestamps:
83+
84+
Aqara W500: It is sending double updates (sometimes two at the exact same second: 9:16:49, 9:16:55, 9:16:59). In just 30 seconds, it sent over 12 massive JSON payloads.
85+
86+
Washing Machine Plug: It is reporting tiny power fluctuations (0.2 to 0.3 watts) every few seconds.
87+
88+
### Throttle the Aqara W500
89+
Aqara devices are notorious for "double-reporting." We can fix this in the Z2M Frontend or configuration.yaml.
90+
91+
* Frontend: Go to the device Settings (Specific) tab.
92+
* The Setting: Look for debounce. Set this to 2.
93+
* The Setting: Look for min_report_interval. Set this to 60.
94+
95+
Why: This tells Z2M: "If you get multiple messages in 2 seconds, only keep the last one. And don't give me a temperature update more than once a minute."
96+
97+
## Firmware Update
98+
99+
https://darkxst.github.io/silabs-firmware-builder/
100+

0 commit comments

Comments
 (0)