home-assistant/AUTOMATIONS.md
jm 1e3c1001d0 Harden AC rules with workday+weather fallbacks (v2)
Replace the three live AC automations in place (same ids -> same entity_ids,
continuous history/traces):

* pre-cool & peak-setback: the workday check moves out of a blocking
  `condition` into template logic that falls back to a plain Mon-Fri test when
  binary_sensor.workday_sensor is unavailable/unknown. Previously a dead sensor
  silently skipped the run.
* pre-cool: weather.get_forecasts now uses continue_on_error, and a
  `fc is defined and is mapping` guard falls back to an assumed 88F high (->70F
  regular pre-cool) when the forecast hard-errors or returns nothing.
* peak-ends: unchanged behavior (runs daily), documented only.

Add AUTOMATIONS.md (identity model, per-rule spec, failure-mode table, deploy
steps) and deploy.py (pushes automations/*.yaml to the HA config API by id).

Fallbacks verified empirically against the live automations via execution
traces before this commit. Also removed throwaway server-side debug automations
(three TEST spoofs + the ac_flap_1758_1820 experiment).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 21:09:48 -04:00

4.1 KiB
Raw Blame History

Home Assistant automations

Source of truth for the AC peak-shaving automations on the HA server (192.168.128.3:8123). This repo is authoritative; HA is a deploy target reached only through its REST config API — HA never sees these files directly.

Identity model (how a file becomes a live automation)

 file (git)                        Home Assistant
 automations/ac_peak_setback.yaml  ──deploy.py──▶  POST /api/config/automation/
   id:    ac_peak_setback              (by id)         config/ac_peak_setback
   alias: "AC - Peak setback to 82"                        │
   ...                                                     ▼ registers entity
                                                  automation.ac_peak_setback_to_82
Identifier Example Set by Used by Change it?
file name ac_peak_setback.yaml you git only (HA never sees it) freely
id ac_peak_setback you (in YAML) config API URL, traces, automation.trigger never (primary key)
alias AC - Peak setback to 82 you (in YAML) UI name; seeds entity_id at first create rarely
entity_id automation.ac_peak_setback_to_82 HA, from slugify(alias) dashboards, other automations, scripts sticky once registered

Key point: entity_id derives from alias, not id. Reference automations elsewhere in HA by their entity_id.

Deploying

source ~/.bashrc                 # provides HA_API_KEY (long-lived token)
python3 deploy.py --check        # parse only, no writes
python3 deploy.py                # replace all three in place (same ids)
python3 deploy.py ac_peak_ends   # deploy just one by id

deploy.py POSTs each file to /api/config/automation/config/<id>. Same id = in-place replacement, so entity_id, run history, and traces stay continuous.

The rules

All act on climate.t6_pro_z_wave_programmable_thermostat_with_smartstart. The "peak" window is 14:0019:00 (27 PM) local (America/New_York).

1. ac_precool_before_peak — Pre-cool before peak

  • 12:00, work days. Fetches today's daily forecast high and pre-cools:
    forecast high setpoint
    ≥ 90°F 68
    ≥ 85°F 70
    ≥ 80°F 71
    < 80°F (no pre-cool)
  • Fallbacks: workday sensor broken → MonFri; forecast broken → assume 88°F high → 70°F (continue_on_error covers a hard error, the fc is defined and is mapping guard covers an empty/None response).

2. ac_peak_setback — Peak setback to 82

  • 14:00, work days. Sets cool / 82°F to coast through the peak.
  • Fallback: workday sensor broken → MonFri.

3. ac_peak_ends — Peak ends, return to 74

  • 19:00, every day (intentionally not workday-gated). Sets 74°F.
  • No external dependencies, so nothing to fall back on.

Failure-mode design

Two independent dependencies, each handled so a failure keeps sensible defaults instead of skipping:

Failure Symptom Handled by Default taken
Workday/holiday sensor unavailable states()on/off {% if wd in ['on','off'] %}…{% else %} now().weekday()<5 MonFri
Weather service raises action would abort continue_on_error: true run continues
Weather returns empty/None fc undefined / not a mapping {% if fc is defined and fc is mapping %}…{% else %} 88 regular pre-cool (88→70)

Verified empirically on 2026-07-09 by forcing each failure against the live automations and reading their execution traces (workday → unavailable still ran the MonFri branch; missing weather entity → today_high=88, setpoint 70, script_execution: finished).

Changelog

  • 2026-07-09 — v1 baseline: imported the three live automations as-is.
  • 2026-07-09 — v2: added workday + weather fallbacks to pre-cool and setback (a broken sensor/forecast no longer skips the run). Peak-ends unchanged. Removed throwaway debug automations from the server: the three TEST - … (spoof, every 1 min) rules and the ac_flap_1758_1820 (85/90 flap) experiment.