Add TOU winter peak-shaving; parameterize by season (v3)
Pepco MD TOU-P has different on-peak windows by season: summer (Jun-Sep) 14:00-19:00, winter (Oct-May) 06:00-09:00 and 17:00-21:00. Heat is gas, so winter electric peak logic is cooling-only. * pre-cool: bounded to summer (Jun-Sep); winter has no pre-cool. * peak-setback (hold) and peak-ends (return): unified across seasons via a season self-select (month -> season; triggers carry id: summer/winter and act only when trigger.id == season) plus a params map for setpoints. Summer forces cool + 82 / returns 74 daily; winter sets 82 / returns 74 ONLY when already in cool mode, so it never disturbs the gas furnace. * new ac_winter_morning_kill: 06:00 winter work days, if in cool mode set hvac_mode off to dodge the 6-9am winter peak. No auto-resume yet (planned). Decision logic verified as a truth table via the template engine across summer/winter x cooling x workday before commit. Deployed in place (existing ids unchanged); new id ac_winter_morning_kill added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1e3c1001d0
commit
7a0d75d9db
5 changed files with 190 additions and 84 deletions
|
|
@ -4,6 +4,17 @@ 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.
|
||||
|
||||
## Utility rate context (Pepco MD, TOU-P, eff. 2026-02-01)
|
||||
|
||||
| Season (rate) | Months | On-peak window(s), weekdays only | On-peak | Off-peak |
|
||||
|---|---|---|---|---|
|
||||
| **Summer** | Jun–Sep | **14:00–19:00** (2–7 PM) | $0.42 | $0.17 |
|
||||
| **Winter** | Oct–May | **06:00–09:00** and **17:00–21:00** | $0.32 | $0.13 |
|
||||
|
||||
Weekends and **federal** holidays are always off-peak — handled by
|
||||
`binary_sensor.workday_sensor` (with a Mon–Fri fallback). Heating is **gas**
|
||||
(not on this electric peak logic), so the winter rules are **cooling-only**.
|
||||
|
||||
## Identity model (how a file becomes a live automation)
|
||||
|
||||
```
|
||||
|
|
@ -22,67 +33,77 @@ reached only through its REST config API — HA never sees these files directly.
|
|||
| **`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`.
|
||||
`entity_id` derives from `alias`, not `id`. Reference automations elsewhere in
|
||||
HA by their `entity_id`.
|
||||
|
||||
## Deploying
|
||||
|
||||
```bash
|
||||
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 # deploy every automations/*.yaml (in place, by id)
|
||||
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.
|
||||
## Parameterization (the "params map" model)
|
||||
|
||||
Rather than duplicate summer vs winter rules, each phase is **one self-selecting
|
||||
automation**:
|
||||
|
||||
- A `variables:` block computes `season` from the month
|
||||
(`summer` = {6,7,8,9}, else `winter`).
|
||||
- Time triggers carry `id: summer` / `id: winter`; the body only acts when
|
||||
`trigger.id == season`, so the off-season time is a harmless no-op.
|
||||
- Setpoints come from a `params` map
|
||||
(`{'summer': {'hold':82,'ret':74}, 'winter': {'hold':82,'ret':74}}`) so the
|
||||
two seasons can diverge later by editing one line. (Both are equal today.)
|
||||
The map is repeated in `ac_peak_setback` and `ac_peak_ends`; keep them in sync.
|
||||
|
||||
## The rules
|
||||
|
||||
All act on `climate.t6_pro_z_wave_programmable_thermostat_with_smartstart`.
|
||||
The "peak" window is **14:00–19:00 (2–7 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)* |
|
||||
### 1. `ac_precool_before_peak` — Pre-cool before peak (summer only)
|
||||
- **12:00**, summer work days. Fetches today's forecast high and pre-cools:
|
||||
≥90→68, ≥85→70, ≥80→71, <80→no pre-cool.
|
||||
- Winter has no pre-cool (marginal for an evening peak).
|
||||
- **Fallbacks:** workday sensor broken → Mon–Fri; 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).
|
||||
→ 70°F (`continue_on_error` + `fc is defined and is mapping` guard).
|
||||
|
||||
### 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 → Mon–Fri.
|
||||
### 2. `ac_peak_setback` — Peak setback to 82 (both seasons)
|
||||
- **14:00** (summer) / **17:00** (winter), work days.
|
||||
- Summer: forces `cool` and sets **82**.
|
||||
- Winter: **cooling-only** — sets 82 *only if already in `cool` mode* (never
|
||||
forces mode, never touches gas heat).
|
||||
|
||||
### 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.
|
||||
### 3. `ac_peak_ends` — Peak ends, return to 74 (both seasons)
|
||||
- **19:00** (summer) / **21:00** (winter). Sets **74**.
|
||||
- Summer returns daily; winter returns only if in `cool` mode.
|
||||
|
||||
### 4. `ac_winter_morning_kill` — Winter morning peak kill (new in v3)
|
||||
- **06:00**, winter work days. If in `cool` mode, sets `hvac_mode: off` to dodge
|
||||
the 6–9 AM winter peak. **No auto-resume yet** (add later). Cooling-only.
|
||||
|
||||
## 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` | Mon–Fri |
|
||||
| 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) |
|
||||
| Wrong-season trigger fires | `trigger.id != season` | `applies = trigger.id == season` guard | no-op |
|
||||
| Winter, not cooling (e.g. gas heat on) | `is_state(climate,'cool')` false | cooling-only guard | no-op (furnace safe) |
|
||||
|
||||
Verified empirically on 2026-07-09 by forcing each failure against the live
|
||||
automations and reading their execution traces (workday → `unavailable` still
|
||||
ran the Mon–Fri branch; missing weather entity → `today_high=88`, setpoint 70,
|
||||
`script_execution: finished`).
|
||||
Fallback and season/cooling logic verified via HA's template engine and
|
||||
execution traces before each deploy.
|
||||
|
||||
## 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.
|
||||
- **2026-07-09 — v2**: added workday + weather fallbacks to pre-cool and setback;
|
||||
removed throwaway debug automations (three `TEST` spoofs + `ac_flap_1758_1820`).
|
||||
- **2026-07-09 — v3**: TOU winter support. Pre-cool bounded to summer (Jun–Sep).
|
||||
`ac_peak_setback` and `ac_peak_ends` unified across seasons via a season
|
||||
self-select + `params` map (summer 14:00/19:00, winter 17:00/21:00), winter
|
||||
cooling-only. Added `ac_winter_morning_kill` (6 AM winter, cooling→off, no
|
||||
resume yet).
|
||||
|
|
|
|||
|
|
@ -1,29 +1,46 @@
|
|||
# ac_peak_ends — end of the utility peak, return the house to comfort
|
||||
# ac_peak_ends — end of the on-peak window, return the house to comfort (both seasons)
|
||||
#
|
||||
# id / entity : ac_peak_ends -> automation.ac_peak_ends_return_to_74
|
||||
# trigger : 19:00 local (America/New_York), EVERY day
|
||||
# purpose : Return the thermostat to 74F after the peak window.
|
||||
# triggers : 19:00 (id: summer) and 21:00 (id: winter), local time
|
||||
# purpose : Return the AC to 74F after the on-peak window ends.
|
||||
#
|
||||
# Runs daily on purpose (no workday gate): you always want comfort back in the
|
||||
# evening, weekend or holiday included. It has no external dependencies (no
|
||||
# weather, no workday sensor), so there is nothing to fall back on — it is a
|
||||
# plain, robust setpoint write.
|
||||
# Self-selecting by season (peak *ends* at 19:00 summer, 21:00 winter). A trigger
|
||||
# only acts when trigger.id == the current season.
|
||||
#
|
||||
# v2 (2026-07-09): no behavior change; documented + version-controlled.
|
||||
# Summer returns to 74 every day (comfort), matching the original behavior.
|
||||
# Winter is COOLING-ONLY: it only returns to 74 when the thermostat is already in
|
||||
# `cool`, so it never disturbs the gas furnace.
|
||||
#
|
||||
# Setpoints come from the `params` map (shared shape with ac_peak_setback).
|
||||
#
|
||||
# v3 (2026-07-09): unified summer+winter, season params map, winter cooling-only.
|
||||
id: ac_peak_ends
|
||||
alias: AC - Peak ends, return to 74
|
||||
description: >-
|
||||
v2 (2026-07-09). At 7pm every day, returns the thermostat to 74F after the
|
||||
peak window. Intentionally runs daily (no workday gate) and has no external
|
||||
dependencies. Managed in git; see AUTOMATIONS.md.
|
||||
v3 (2026-07-09). Returns the AC to 74F after the on-peak window: summer 7pm,
|
||||
winter 9pm. Summer returns daily; winter is cooling-only (never touches gas
|
||||
heat). Managed in git; see AUTOMATIONS.md.
|
||||
mode: single
|
||||
triggers:
|
||||
- trigger: time
|
||||
at: "19:00:00"
|
||||
id: summer
|
||||
- trigger: time
|
||||
at: "21:00:00"
|
||||
id: winter
|
||||
conditions: []
|
||||
actions:
|
||||
- action: climate.set_temperature
|
||||
target:
|
||||
entity_id: climate.t6_pro_z_wave_programmable_thermostat_with_smartstart
|
||||
data:
|
||||
temperature: 74
|
||||
- variables:
|
||||
season: "{{ 'summer' if now().month in [6,7,8,9] else 'winter' }}"
|
||||
cooling: "{{ is_state('climate.t6_pro_z_wave_programmable_thermostat_with_smartstart','cool') }}"
|
||||
params: "{{ {'summer': {'hold': 82, 'ret': 74}, 'winter': {'hold': 82, 'ret': 74}} }}"
|
||||
applies: "{{ trigger.id == season }}"
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ applies and (season == 'summer' or cooling) }}"
|
||||
then:
|
||||
- action: climate.set_temperature
|
||||
target:
|
||||
entity_id: climate.t6_pro_z_wave_programmable_thermostat_with_smartstart
|
||||
data:
|
||||
temperature: "{{ params[season]['ret'] }}"
|
||||
|
|
|
|||
|
|
@ -1,41 +1,62 @@
|
|||
# ac_peak_setback — let the house drift during the utility peak window
|
||||
# ac_peak_setback — hold the house warm during the on-peak window (both seasons)
|
||||
#
|
||||
# id / entity : ac_peak_setback -> automation.ac_peak_setback_to_82
|
||||
# trigger : 14:00 local (America/New_York)
|
||||
# purpose : On work days, set cool 82F to coast through the 14:00-19:00 peak.
|
||||
# triggers : 14:00 (id: summer) and 17:00 (id: winter), local time
|
||||
# purpose : Coast through the utility on-peak by setting the AC to 82F.
|
||||
#
|
||||
# Graceful degradation (v2):
|
||||
# * workday sensor unavailable/unknown -> fall back to a plain Mon-Fri check
|
||||
# (a broken holiday sensor must not silently cancel the setback).
|
||||
# The original used a blocking `condition` on the workday sensor, which would
|
||||
# skip the run whenever the sensor was unavailable; that is the bug this fixes.
|
||||
# Self-selecting by season (Pepco MD TOU-P peak windows):
|
||||
# * summer (Jun-Sep): on-peak 14:00-19:00 -> the 14:00 trigger applies.
|
||||
# * winter (Oct-May): evening on-peak 17:00-21:00 -> the 17:00 trigger applies.
|
||||
# A trigger only acts when trigger.id == the current season, so the "wrong"
|
||||
# time is a no-op.
|
||||
#
|
||||
# v2 (2026-07-09): workday fallback added. See AUTOMATIONS.md.
|
||||
# Safety: winter is COOLING-ONLY. Heat is gas (not on this electric peak logic),
|
||||
# so winter never forces cool mode — it only nudges the setpoint when the
|
||||
# thermostat is already in `cool`. Summer forces cool mode as before.
|
||||
#
|
||||
# Fallbacks: workday sensor unavailable -> Mon-Fri (see is_workday).
|
||||
#
|
||||
# Setpoints come from the `params` map so summer/winter can diverge later.
|
||||
#
|
||||
# v3 (2026-07-09): unified summer+winter, season params map, winter cooling-only.
|
||||
id: ac_peak_setback
|
||||
alias: AC - Peak setback to 82
|
||||
description: >-
|
||||
v2 (2026-07-09). At 2pm on work days, sets the thermostat to cool/82F to coast
|
||||
through the 2-7pm peak. Falls back to Mon-Fri if the workday sensor fails.
|
||||
Managed in git; see AUTOMATIONS.md.
|
||||
v3 (2026-07-09). On work days, sets the AC to 82F to coast through the on-peak
|
||||
window: summer 2pm (14:00-19:00 peak) and winter 5pm (17:00-21:00 peak).
|
||||
Winter is cooling-only (never touches gas heat). Falls back to Mon-Fri if the
|
||||
workday sensor fails. Managed in git; see AUTOMATIONS.md.
|
||||
mode: single
|
||||
triggers:
|
||||
- trigger: time
|
||||
at: "14:00:00"
|
||||
id: summer
|
||||
- trigger: time
|
||||
at: "17:00:00"
|
||||
id: winter
|
||||
conditions: []
|
||||
actions:
|
||||
- variables:
|
||||
season: "{{ 'summer' if now().month in [6,7,8,9] else 'winter' }}"
|
||||
is_workday: "{% set wd = states('binary_sensor.workday_sensor') %}{% if wd in ['on','off'] %}{{ wd == 'on' }}{% else %}{{ now().weekday() < 5 }}{% endif %}"
|
||||
cooling: "{{ is_state('climate.t6_pro_z_wave_programmable_thermostat_with_smartstart','cool') }}"
|
||||
params: "{{ {'summer': {'hold': 82, 'ret': 74}, 'winter': {'hold': 82, 'ret': 74}} }}"
|
||||
applies: "{{ trigger.id == season }}"
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ is_workday }}"
|
||||
value_template: "{{ applies and is_workday and (season == 'summer' or cooling) }}"
|
||||
then:
|
||||
- action: climate.set_hvac_mode
|
||||
target:
|
||||
entity_id: climate.t6_pro_z_wave_programmable_thermostat_with_smartstart
|
||||
data:
|
||||
hvac_mode: cool
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ season == 'summer' }}"
|
||||
then:
|
||||
- action: climate.set_hvac_mode
|
||||
target:
|
||||
entity_id: climate.t6_pro_z_wave_programmable_thermostat_with_smartstart
|
||||
data:
|
||||
hvac_mode: cool
|
||||
- action: climate.set_temperature
|
||||
target:
|
||||
entity_id: climate.t6_pro_z_wave_programmable_thermostat_with_smartstart
|
||||
data:
|
||||
temperature: 82
|
||||
temperature: "{{ params[season]['hold'] }}"
|
||||
|
|
|
|||
|
|
@ -1,28 +1,31 @@
|
|||
# ac_precool_before_peak — pre-cool the house before the utility peak window
|
||||
# ac_precool_before_peak — pre-cool the house before the summer on-peak window
|
||||
#
|
||||
# id / entity : ac_precool_before_peak -> automation.ac_pre_cool_before_peak
|
||||
# trigger : 12:00 local (America/New_York)
|
||||
# purpose : On work days, pre-cool before the 14:00-19:00 peak, harder when
|
||||
# the forecast high is hotter (>=90 -> 68, >=85 -> 70, >=80 -> 71,
|
||||
# below 80 -> no pre-cool).
|
||||
# purpose : On summer work days, pre-cool before the 14:00-19:00 peak,
|
||||
# harder when the forecast high is hotter (>=90 -> 68, >=85 -> 70,
|
||||
# >=80 -> 71, below 80 -> no pre-cool).
|
||||
#
|
||||
# Graceful degradation (v2) — a broken dependency must NOT skip pre-cooling:
|
||||
# Summer only: pre-cooling for the WINTER evening peak (17:00-21:00) is marginal
|
||||
# (the daily high has already passed by then), so winter is hold+return only and
|
||||
# has no pre-cool. This automation self-gates on season == 'summer'.
|
||||
#
|
||||
# Graceful degradation (a broken dependency must NOT skip pre-cooling):
|
||||
# * workday sensor unavailable/unknown -> fall back to a plain Mon-Fri check.
|
||||
# * weather forecast fails or returns nothing -> assume a regular hot day
|
||||
# (high 88F -> 70F). weather.get_forecasts runs with continue_on_error so a
|
||||
# hard service error can't abort the run; the `fc is defined and is mapping`
|
||||
# guard catches the soft-failure (empty/None) case.
|
||||
# (88F -> 70F). continue_on_error covers a hard service error; the
|
||||
# `fc is defined and is mapping` guard covers an empty/None response.
|
||||
#
|
||||
# NOTE: templates are kept on single lines on purpose — YAML folded scalars can
|
||||
# inject stray whitespace/newlines into Jinja. Readability lives in this header.
|
||||
# NOTE: templates are single-line on purpose (YAML folding can corrupt Jinja).
|
||||
#
|
||||
# v2 (2026-07-09): added workday + weather fallbacks. See AUTOMATIONS.md.
|
||||
# v3 (2026-07-09): bounded to summer (Jun-Sep). v2 added the fallbacks.
|
||||
id: ac_precool_before_peak
|
||||
alias: AC - Pre-cool before peak
|
||||
description: >-
|
||||
v2 (2026-07-09). Pre-cools before the 2-7pm peak on work days. Falls back to
|
||||
Mon-Fri if the workday sensor fails, and to a regular pre-cool (assume 88F high
|
||||
-> 70F) if the weather forecast fails. Managed in git; see AUTOMATIONS.md.
|
||||
v3 (2026-07-09). Summer-only. Pre-cools before the 2-7pm peak on work days.
|
||||
Falls back to Mon-Fri if the workday sensor fails, and to a regular pre-cool
|
||||
(assume 88F high -> 70F) if the weather forecast fails. Managed in git; see
|
||||
AUTOMATIONS.md.
|
||||
mode: single
|
||||
triggers:
|
||||
- trigger: time
|
||||
|
|
@ -37,12 +40,13 @@ actions:
|
|||
type: daily
|
||||
response_variable: fc
|
||||
- variables:
|
||||
season: "{{ 'summer' if now().month in [6,7,8,9] else 'winter' }}"
|
||||
is_workday: "{% set wd = states('binary_sensor.workday_sensor') %}{% if wd in ['on','off'] %}{{ wd == 'on' }}{% else %}{{ now().weekday() < 5 }}{% endif %}"
|
||||
today_high: "{% if fc is defined and fc is mapping and 'weather.forecast_4315aspenhill' in fc and fc['weather.forecast_4315aspenhill'].forecast | default([]) | length > 0 %}{% set today = now().date() %}{% set entries = fc['weather.forecast_4315aspenhill'].forecast | selectattr('datetime') | list %}{% set match = entries | selectattr('datetime','search', today | string) | list %}{{ (match[0].temperature if match else entries[0].temperature) | float(88) }}{% else %}88{% endif %}"
|
||||
setpoint: "{% set h = today_high | float(88) %}{% if h >= 90 %}68{% elif h >= 85 %}70{% elif h >= 80 %}71{% else %}none{% endif %}"
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ is_workday and setpoint != 'none' }}"
|
||||
value_template: "{{ season == 'summer' and is_workday and setpoint != 'none' }}"
|
||||
then:
|
||||
- action: climate.set_hvac_mode
|
||||
target:
|
||||
|
|
|
|||
43
automations/ac_winter_morning_kill.yaml
Normal file
43
automations/ac_winter_morning_kill.yaml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# ac_winter_morning_kill — stop the AC at the winter morning on-peak start
|
||||
#
|
||||
# id / entity : ac_winter_morning_kill -> automation.ac_winter_morning_kill
|
||||
# trigger : 06:00 local (America/New_York)
|
||||
# purpose : Winter has a 6-9 AM on-peak. If the AC is running at 6am, stop
|
||||
# it. (Rare — only the mild May/October days when AC runs.)
|
||||
#
|
||||
# Cooling-only and gas-heat-safe: only acts when the thermostat is in `cool`
|
||||
# mode, so it never turns off the gas furnace. Turns the unit fully OFF (per the
|
||||
# chosen "stop" behavior). There is intentionally NO auto-resume yet — a resume
|
||||
# automation can be added later.
|
||||
#
|
||||
# Fallback: workday sensor unavailable -> Mon-Fri (weekends/holidays are
|
||||
# off-peak, so no kill then).
|
||||
#
|
||||
# v3 (2026-07-09): new.
|
||||
id: ac_winter_morning_kill
|
||||
alias: AC - Winter morning peak kill
|
||||
description: >-
|
||||
v3 (2026-07-09). At 6am on winter (Oct-May) work days, turns the thermostat
|
||||
OFF if it is currently cooling, to avoid the 6-9am winter on-peak. Cooling-only
|
||||
(never touches gas heat). No auto-resume yet. Managed in git; see
|
||||
AUTOMATIONS.md.
|
||||
mode: single
|
||||
triggers:
|
||||
- trigger: time
|
||||
at: "06:00:00"
|
||||
id: winter
|
||||
conditions: []
|
||||
actions:
|
||||
- variables:
|
||||
season: "{{ 'summer' if now().month in [6,7,8,9] else 'winter' }}"
|
||||
is_workday: "{% set wd = states('binary_sensor.workday_sensor') %}{% if wd in ['on','off'] %}{{ wd == 'on' }}{% else %}{{ now().weekday() < 5 }}{% endif %}"
|
||||
cooling: "{{ is_state('climate.t6_pro_z_wave_programmable_thermostat_with_smartstart','cool') }}"
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ season == 'winter' and is_workday and cooling }}"
|
||||
then:
|
||||
- action: climate.set_hvac_mode
|
||||
target:
|
||||
entity_id: climate.t6_pro_z_wave_programmable_thermostat_with_smartstart
|
||||
data:
|
||||
hvac_mode: "off"
|
||||
Loading…
Reference in a new issue