diff --git a/addons/appdaemon/grow_monitor/Readme.MD b/addons/appdaemon/grow_monitor/Readme.MD
index 8f7fc41..d66e593 100644
--- a/addons/appdaemon/grow_monitor/Readme.MD
+++ b/addons/appdaemon/grow_monitor/Readme.MD
@@ -69,7 +69,13 @@ An intelligent AppDaemon-based monitoring system for cannabis grow rooms with AI
class: GrowRoomAIMonitor
openai_api_key: "sk-YOUR_OPENAI_API_KEY_HERE"
```
-3. Create Home Assistant Helper Entities (YAML)Copy and paste the following block into your Home Assistant configuration.yaml file (or a separate YAML file that you !include, like input_helpers.yaml). Then, restart Home Assistant (or Reload Input Helpers from Developer Tools).Replace YOUR_PREFIX_ with your desired prefix (e.g., f1_, grow_room_) and update the ENTITIES dictionary in grow_monitor.py accordingly.# In your configuration.yaml or a dedicated !include file for inputs
+
+### 3. Create Home Assistant Helper Entities (YAML)
+
+Copy and paste the following block into your Home Assistant `configuration.yaml` (or a separate YAML file that you `!include`, like `input_helpers.yaml`). Then restart Home Assistant (or **Reload Input Helpers** from Developer Tools).
+
+Replace `YOUR_PREFIX_` with your desired prefix (e.g. `f1_`, `grow_room_`) and update the `ENTITIES` dictionary in `grow_monitor.py` accordingly.
+
```yaml
input_datetime:
YOUR_PREFIX_lights_on_time:
@@ -269,9 +275,12 @@ input_number:
unit_of_measurement: "mS/cm"
icon: mdi:flash-outline
```
-4. Create Home Assistant Mute Script
-In your Home Assistant scripts.yaml file (or a separate file if you include a scripts directory), add the following script:
-```
+
+### 4. Create the Home Assistant Mute Script
+
+In your Home Assistant `scripts.yaml` (or a separate file if you use a scripts directory), add the following script:
+
+```yaml
grow_monitor_mute_sensor:
alias: "Grow Monitor Mute Sensor Action"
description: "Fires an event to mute a specific grow monitor sensor."
@@ -290,66 +299,71 @@ grow_monitor_mute_sensor:
mode: single
```
-Reload Home Assistant scripts (Developer Tools > YAML Configuration > Reload Scripts).
-5. Configure Entities in grow_monitor.py
-Open grow_monitor.py.
-At the top, find the ENTITIES dictionary.
-Update all entity IDs here to match your specific Home Assistant entities (sensors, and the helpers you just created with YOUR_PREFIX_).
-6. Restart AppDaemon
-After all files and entities are configured, restart the AppDaemon addon from the Home Assistant UI.
- Using the Monitor
-Automatic Operation: The script runs in the background.
-Notifications:
-
-When issues are detected and not suppressed by cooldowns or mutes, an AI-summarized notification is sent.
-Actions: "Mute [Sensor] (1h)", "Mute [Sensor] (6h)", "Pause ALL Alerts".
-
-
-Muting: Clicking a mute action silences that specific sensor for the chosen duration. The overall notification system will also enter a 6-hour quiet period (new critical alerts still come through).
-Global Pause: Toggle the alerts_paused input_boolean in HA or use the notification action.
- Alert Severity & Cooldowns
-Severity Levels: IGNORE, NORMAL, URGENT, CRITICAL (determined by violation duration and trend).
+Reload Home Assistant scripts (**Developer Tools → YAML → Reload Scripts**).
-A violation must typically last >= 60 seconds to become "NORMAL" severity.
+### 5. Configure Entities in `grow_monitor.py`
+Open `grow_monitor.py`, find the `ENTITIES` dictionary near the top, and update all
+entity IDs to match your Home Assistant entities (sensors, plus the `YOUR_PREFIX_`
+helpers you just created).
-Cooldowns:
+### 6. Restart AppDaemon
-Base: 1 hour between notifications.
-After Acknowledgment (Mute): 6 hours quiet period.
-New Critical Alerts: Bypass cooldowns.
+Once all files and entities are configured, restart the AppDaemon add-on from the
+Home Assistant UI.
+## Using the Monitor
- Data Persistence
-The script saves its state (muted sensors, last notification times) to grow_monitor_data.pkl in its app_dir (e.g., /config/apps/grow_monitor_data.pkl). This allows state to survive AppDaemon restarts.
- Troubleshooting
-No Notifications:
+- **Automatic operation:** the script runs in the background.
+- **Notifications:** when issues are detected and not suppressed by cooldowns or mutes,
+ an AI-summarised notification is sent. Actions: *Mute [Sensor] (1h)*,
+ *Mute [Sensor] (6h)*, *Pause ALL Alerts*.
+- **Muting:** clicking a mute action silences that sensor for the chosen duration; the
+ whole notification system also enters a 6-hour quiet period (new critical alerts still
+ come through).
+- **Global pause:** toggle the `alerts_paused` `input_boolean` in HA, or use the
+ notification action.
-Check AppDaemon logs for errors.
-Verify YOUR_PREFIX_environmental_alerts_paused is off.
-Confirm time_zone in appdaemon.yaml is correct.
-Ensure sensor values violate thresholds for sufficient duration (default >60s for "NORMAL").
-Delete grow_monitor_data.pkl and restart AppDaemon to clear stuck mutes.
-Test your notify service from HA Developer Tools.
+## Alert Severity & Cooldowns
+- **Severity levels:** IGNORE, NORMAL, URGENT, CRITICAL — determined by violation
+ duration and trend. A violation must typically last ≥ 60 seconds to reach NORMAL.
+- **Cooldowns:**
+ - Base 1 hour between notifications.
+ - 6-hour quiet period after acknowledgment (mute).
+ - New critical alerts bypass cooldowns.
-Mute Actions Not Working:
+## Data Persistence
-Ensure script.grow_monitor_mute_sensor exists and is correctly configured in HA.
-Verify EVENT_GROW_MONITOR_MUTE in grow_monitor.py matches the event: in the HA script.
+The script saves its state (muted sensors, last notification times) to
+`grow_monitor_data.pkl` in its `app_dir` (e.g. `/config/apps/grow_monitor_data.pkl`),
+so state survives AppDaemon restarts.
+## Troubleshooting
-AI Summary Issues:
+**No notifications**
+- Check AppDaemon logs for errors.
+- Verify `YOUR_PREFIX_environmental_alerts_paused` is off.
+- Confirm `time_zone` in `appdaemon.yaml` is correct.
+- Ensure sensor values violate thresholds for long enough (default > 60 s for NORMAL).
+- Delete `grow_monitor_data.pkl` and restart AppDaemon to clear stuck mutes.
+- Test your notify service from HA Developer Tools.
-Check openai_api_key in apps.yaml.
-Look for API errors in AppDaemon logs.
+**Mute actions not working**
+- Ensure `script.grow_monitor_mute_sensor` exists and is configured correctly.
+- Verify `EVENT_GROW_MONITOR_MUTE` in `grow_monitor.py` matches the `event:` in the HA script.
+**AI summary issues**
+- Check `openai_api_key` in `apps.yaml`.
+- Look for API errors in the AppDaemon logs.
-Log Timestamps Incorrect:
+**Log timestamps incorrect**
+- Ensure `time_zone` in the `appdaemon.yaml` that AppDaemon actually reads is set to your local timezone.
-Ensure time_zone in the appdaemon.yaml that AppDaemon is actually reading is set to your local timezone.
+---
+Monitor your grow environment effectively with intelligent, summarised, actionable alerts.
- Monitor your grow environment effectively with intelligent, summarized, and actionable alerts!Version: 3.1
-Last Updated: May 24, 2025
-Compatibility: Home Assistant 2023.x+, AppDaemon 4.x+
+- **Version:** 3.1
+- **Last updated:** 2025-05-24
+- **Compatibility:** Home Assistant 2023.x+, AppDaemon 4.x+
diff --git a/automations/co2_automation.MD b/automations/co2_automation.MD
index 198565f..1f39340 100644
--- a/automations/co2_automation.MD
+++ b/automations/co2_automation.MD
@@ -1,634 +1,102 @@
+# CO₂ Control and Alerts — import notes
-Blueprint import url: https://gist.github.com/JakeTheRabbit/41fbc01a62006cfef7172dc5b8534b60
+Import notes and logic overview for the CO₂ blueprint. The blueprint itself is the
+single source of truth:
-```mermaid
-graph TD
- Start[Start] -->|Trigger| WhichTrigger{Which Trigger?}
+**[`../blueprints/co2_control_and_alerts.yaml`](../blueprints/co2_control_and_alerts.yaml)**
- WhichTrigger -->|"CO2 Sensor State Change
co2_sensor_state_change"| CO2ControlLogic[CO2 Control Logic]
- WhichTrigger -->|"CO2 Target Input Change
co2_target_state_change"| CO2ControlLogic
- WhichTrigger -->|"CO2 Tolerance Input Change
co2_tolerance_state_change"| CO2ControlLogic
- WhichTrigger -->|"CO2 On Time Trigger
co2_on_time_trigger"| DaytimeAdjustment[Daytime CO2 Target Adjustment]
- WhichTrigger -->|"CO2 Off Time Trigger
co2_off_time_trigger"| NighttimeAdjustment[Nighttime CO2 Target Adjustment]
- WhichTrigger -->|"Low CO2 Alert Trigger
low_co2_alert_trigger"| LowCO2Alert[Low CO2 Alert]
- WhichTrigger -->|"High CO2 Alert Trigger
high_co2_alert_trigger"| HighCO2AlertPrimary[High CO2 Alert Primary Sensor]
- WhichTrigger -->|"High CO2 Alert Trigger Secondary
high_co2_alert_trigger_secondary"| HighCO2AlertSecondary[High CO2 Alert Secondary Sensor]
+> This file used to embed a full copy of the blueprint YAML. That copy drifted out
+> of date, so it has been removed — always import the blueprint file above rather
+> than any snippet pasted here. Requires **Home Assistant 2024.10+**.
- %% Daytime CO2 Target Adjustment
- DaytimeAdjustment --> GetDaytimeTarget[Get Daytime Target Value]
- GetDaytimeTarget --> ValidateDaytimeTarget{Is Target Value Valid?}
- ValidateDaytimeTarget -->|Yes| SetDaytimeTarget[Set CO2 Target Input Number]
- ValidateDaytimeTarget -->|No| End[End]
+## Import
- %% Nighttime CO2 Target Adjustment
- NighttimeAdjustment --> GetNighttimeTarget[Get Nighttime Target Value]
- GetNighttimeTarget --> ValidateNighttimeTarget{Is Target Value Valid?}
- ValidateNighttimeTarget -->|Yes| SetNighttimeTarget[Set CO2 Target Input Number]
- ValidateNighttimeTarget -->|No| End
+1. **Settings → Automations & Scenes → Blueprints → Import Blueprint**.
+2. Paste the raw URL of [`blueprints/co2_control_and_alerts.yaml`](https://github.com/JakeTheRabbit/HAGR/blob/main/blueprints/co2_control_and_alerts.yaml) and import.
+3. **Create automation** from it and fill in the inputs.
- %% Low CO2 Alert
- LowCO2Alert --> CheckLowCO2Time{Is Current Time Within Alert Window?}
- CheckLowCO2Time -->|Yes| ValidateLowCO2Value{Is CO2 Value Valid?}
- CheckLowCO2Time -->|No| End
- ValidateLowCO2Value -->|Yes| SendLowCO2Notification[Send Low CO2 Notification]
- SendLowCO2Notification --> AdjustLightsLow[Adjust Lights to Low Brightness]
- ValidateLowCO2Value -->|No| End
+For local development you can instead drop the file into
+`/blueprints/automation//` and reload.
- %% High CO2 Alert (Primary Sensor)
- HighCO2AlertPrimary --> ValidateHighCO2Primary{Is CO2 Level Valid?}
- ValidateHighCO2Primary -->|Yes| SendHighCO2NotificationPrimary[Send High CO2 Notification]
- SendHighCO2NotificationPrimary --> TurnOffControlSwitchPrimary[Turn Off CO2 Control Switch]
- TurnOffControlSwitchPrimary --> CreatePersistentNotificationPrimary[Create Persistent Notification]
- CreatePersistentNotificationPrimary --> SendTTSPMessagePrimary[Send TTS Message]
- ValidateHighCO2Primary -->|No| End
+## Helpers to create first
- %% High CO2 Alert (Secondary Sensor)
- HighCO2AlertSecondary --> CheckSecondarySensor{Is Secondary Sensor Defined?}
- CheckSecondarySensor -->|Yes| ValidateHighCO2Secondary{Is CO2 Level Valid?}
- CheckSecondarySensor -->|No| End
- ValidateHighCO2Secondary -->|Yes| SendHighCO2NotificationSecondary[Send High CO2 Notification]
- SendHighCO2NotificationSecondary --> TurnOffControlSwitchSecondary[Turn Off CO2 Control Switch]
- TurnOffControlSwitchSecondary --> CreatePersistentNotificationSecondary[Create Persistent Notification]
- CreatePersistentNotificationSecondary --> SendTTSPMessageSecondary[Send TTS Message]
- ValidateHighCO2Secondary -->|No| End
+Create these under **Settings → Devices & Services → Helpers** (or in YAML) before
+creating the automation:
- %% CO2 Control Logic
- CO2ControlLogic --> ValidateCO2Values{Are CO2 Values Valid?}
- ValidateCO2Values -->|Yes| CheckCO2LowerLimit{"Is CO2 Below Lower Limit
(co2_target - co2_tolerance)?"}
- ValidateCO2Values -->|No| End
- CheckCO2LowerLimit -->|Yes| CheckControlSwitchOff{Is CO2 Control Switch Off?}
- CheckControlSwitchOff -->|Yes| TurnOnControlSwitch[Turn On CO2 Control Switch]
- CheckControlSwitchOff -->|No| End
- CheckCO2LowerLimit -->|No| CheckCO2UpperLimit{"Is CO2 Above Upper Limit
(co2_target + co2_tolerance)?"}
- CheckCO2UpperLimit -->|Yes| CheckControlSwitchOn{Is CO2 Control Switch On?}
- CheckCO2UpperLimit -->|No| End
- CheckControlSwitchOn -->|Yes| TurnOffControlSwitch[Turn Off CO2 Control Switch]
- CheckControlSwitchOn -->|No| End
- CheckCO2UpperLimit -->|No| End
+```yaml
+input_number:
+ co2_target_input: { name: CO₂ Target Input, min: 0, max: 5000, step: 1, unit_of_measurement: ppm, mode: box }
+ co2_tolerance_input: { name: CO₂ Tolerance Input, min: 0, max: 1000, step: 1, unit_of_measurement: ppm, mode: box }
+ co2_day_target_input: { name: Daytime CO₂ Target Input, min: 0, max: 5000, step: 1, unit_of_measurement: ppm, mode: box }
+ co2_night_target_input:{ name: Nighttime CO₂ Target Input,min: 0, max: 5000, step: 1, unit_of_measurement: ppm, mode: box }
- End[End]
+input_datetime:
+ co2_on_time: { name: CO₂ Target On Time, has_time: true, has_date: false }
+ co2_off_time: { name: CO₂ Target Off Time, has_time: true, has_date: false }
+ low_co2_time_start: { name: Low CO₂ Alert Start Time, has_time: true, has_date: false }
+ low_co2_time_end: { name: Low CO₂ Alert End Time, has_time: true, has_date: false }
+ last_low_co2_alert: { name: Last Low CO₂ Alert Time, has_time: true, has_date: true }
+ last_high_co2_alert: { name: Last High CO₂ Alert Time, has_time: true, has_date: true }
```
-### **Explanation of the Diagram:**
-
-- **Start:** The automation begins when any of the specified triggers occur.
-
-- **Trigger Decision Point (B):** Determines which trigger activated the automation and directs the flow accordingly.
-
-#### **CO₂ Target Adjustments:**
-
-- **Daytime CO₂ Target Adjustment (D):**
- - Gets the daytime target value.
- - Checks if the value is valid.
- - Sets the CO₂ target input number if valid.
-
-- **Nighttime CO₂ Target Adjustment (E):**
- - Similar to daytime adjustment but uses the nighttime target value.
-
-#### **Low CO₂ Alert (F):**
-
-- Checks if the current time is within the low CO₂ alert window.
-- Validates the CO₂ sensor value.
-- If valid, sends a low CO₂ notification and adjusts lights to the specified low brightness.
-
-#### **High CO₂ Alert (Primary Sensor) (G):**
-
-- Validates the CO₂ level from the primary sensor.
-- If valid, performs the following actions:
- - Sends a high CO₂ notification with CO₂ levels.
- - Turns off the CO₂ control switch.
- - Creates a persistent notification.
- - Sends a TTS message.
-
-#### **High CO₂ Alert (Secondary Sensor) (H):**
-
-- Checks if the secondary sensor is defined.
-- Validates the CO₂ level from the secondary sensor.
-- If valid, performs similar actions as the primary sensor alert.
-
-#### **CO₂ Control Logic (C):**
-
-- Validates the CO₂ sensor values and input numbers.
-- Checks if the CO₂ level is below the lower limit (target minus tolerance):
- - If yes, and the CO₂ control switch is off, turns on the switch.
-- Checks if the CO₂ level is above the upper limit (target plus tolerance):
- - If yes, and the CO₂ control switch is on, turns off the switch.
-
-### **Notes:**
-
-- **Validation Steps:** At multiple points, the automation checks if values are valid (not `None`, `unknown`, or `unavailable`) before proceeding.
-
-- **End Nodes (I):** The automation ends if any conditions are not met or after actions are executed.
-
-- **Sequence Flow:** The diagram illustrates the flow of logic based on the triggers and conditions, helping to visualize how the automation processes each event.
-
-### **How to Use the Diagram:**
-
-- **Understanding Triggers:** Use the diagram to see what happens when each trigger occurs.
-
-- **Following the Logic:** Trace the path from the trigger through conditions and actions to understand the automation's behavior.
-
-- **Identifying Conditions:** The decision points (diamonds) show where the automation checks for specific conditions before proceeding.
-
-- **Actions:** Rectangular nodes represent actions taken by the automation.
-
-### **Additional Considerations:**
-- **Customizing the Automation:**
- - You can adjust thresholds, durations, and targets to fit your needs.
- - Ensure that any changes maintain the logical flow depicted in the diagram.
-
-- **Testing:**
- - Use the diagram as a reference when testing each part of the automation.
- - Confirm that triggers and actions occur as expected.
-
-
-Blueprint:
+The two `last_*_alert` datetimes back the alert cooldowns and must have both
+`has_time` and `has_date` set to `true`.
+
+## What it does
+
+The automation is one loop that runs on sensor changes, a 1-minute tick, the day/night
+schedule, and the safety triggers. Each run walks these independent steps:
+
+1. **Day/night target** — sets `co2_target_input` to the day or night value based on the
+ on/off times (handles windows that cross midnight; leaves the target unchanged if the
+ times are unavailable).
+2. **High-CO₂ safety** — if the primary sensor, or the optional backup sensor, is over its
+ threshold: close the CO₂ valve, notify (push + persistent + optional TTS), and stamp the
+ high-alert cooldown. The backup sensor is polled, so leaving it blank is safe.
+3. **Relay-stuck / empty-tank safety** — if the valve has been on longer than the max
+ runtime, force it closed and alert.
+4. **Low-CO₂ alert** — if the sensor is sustained-low inside the alert window and the
+ cooldown has elapsed: notify and (optionally) snapshot + dim the lights.
+5. **Low-CO₂ recovery** — when CO₂ climbs back, restore the lights to their pre-dim state.
+6. **Control loop** — hysteresis switching (`target ± tolerance`) with fail-safes: it will
+ not open the valve while either sensor reads high, closes the valve if the primary sensor
+ is unavailable, and treats a target of 0 (e.g. CO₂ off at night) as "hold closed".
+```mermaid
+graph TD
+ Triggers["Triggers: sensor change · 1-min tick · on/off time · low/high/recovered · valve-on too long · HA start"] --> Step1
+
+ Step1["1 · Day/night target adjust"] --> Step2
+ Step2{"2 · Either sensor over high threshold?"}
+ Step2 -->|Yes| HighAct["Close valve → notify + persistent + TTS → stamp cooldown"] --> Step3
+ Step2 -->|No| Step3
+
+ Step3{"3 · Valve on longer than max runtime?"}
+ Step3 -->|Yes| Stuck["Force valve closed → alert (empty tank / stuck relay)"] --> Step4
+ Step3 -->|No| Step4
+
+ Step4{"4 · Sustained low in window + cooldown ok?"}
+ Step4 -->|Yes| LowAct["Notify → snapshot + dim lights → stamp cooldown"] --> Step5
+ Step4 -->|No| Step5
+
+ Step5{"5 · Recovered trigger + snapshot exists?"}
+ Step5 -->|Yes| Restore["Restore lights to pre-dim brightness"] --> Step6
+ Step5 -->|No| Step6
+
+ Step6{"6 · Control loop"}
+ Step6 -->|Primary unavailable| Off1["Valve OFF (fail-safe)"]
+ Step6 -->|Target = 0| Off2["Valve OFF (night / disabled)"]
+ Step6 -->|"Below target − tolerance AND not high"| On["Valve ON"]
+ Step6 -->|Above target + tolerance| Off3["Valve OFF"]
```
-blueprint:
- name: CO₂ Control and Alerts
- description: >
- Controls CO₂ levels by adjusting targets at specified times, manages switches based on CO₂ readings,
- sends low and high CO₂ alerts, and adjusts lights accordingly.
-
- **Helpers to Add:**
- Copy and paste the following into your `configuration.yaml` to create the necessary helpers.
-
- ```yaml
- input_number:
- co2_target_input:
- name: CO₂ Target Input
- min: 0
- max: 5000
- step: 1
- unit_of_measurement: 'ppm'
- co2_tolerance_input:
- name: CO₂ Tolerance Input
- min: 0
- max: 1000
- step: 1
- unit_of_measurement: 'ppm'
- co2_day_target_input:
- name: Daytime CO₂ Target Input
- min: 0
- max: 5000
- step: 1
- unit_of_measurement: 'ppm'
- co2_night_target_input:
- name: Nighttime CO₂ Target Input
- min: 0
- max: 5000
- step: 1
- unit_of_measurement: 'ppm'
-
- input_datetime:
- co2_on_time:
- name: CO₂ Target On Time
- has_time: true
- has_date: false
- co2_off_time:
- name: CO₂ Target Off Time
- has_time: true
- has_date: false
- low_co2_time_start:
- name: Low CO₂ Alert Start Time
- has_time: true
- has_date: false
- low_co2_time_end:
- name: Low CO₂ Alert End Time
- has_time: true
- has_date: false
- ```
-
- **Explanation:**
-
- This blueprint performs the following functions:
-
- 1. **CO₂ Target Adjustment:**
- - Adjusts the CO₂ target at specified times using `input_datetime` helpers.
- - Daytime and nighttime targets are set using `input_number` helpers.
-
- 2. **CO₂ Control Logic:**
- - Monitors a CO₂ sensor and controls a switch based on CO₂ levels, target, and tolerance.
- - The switch turns on when CO₂ is below the lower limit and off when above the upper limit.
- 3. **Low CO₂ Alert:**
- - Sends notifications and dims specified lights when CO₂ levels are below a threshold during a specified time window.
+## Notes
- 4. **High CO₂ Alert:**
- - Sends notifications, turns off a switch, and sends a TTS message when CO₂ levels exceed certain thresholds.
- - Supports monitoring a secondary CO₂ sensor for high CO₂ alerts.
-
- **Features:**
-
- - **Dynamic Scheduling:** Adjusts CO₂ targets based on user-defined times.
- - **Customizable Thresholds:** Set your own CO₂ targets, tolerances, and alert thresholds.
- - **Notifications:** Receive alerts via multiple notification services.
- - **Light Control:** Automatically dims lights when CO₂ is low.
- - **Text-To-Speech Alerts:** Get audible alerts when CO₂ levels are high.
-
- **Limitations and Gotchas:**
-
- - **Ensure Helpers Exist:** All `input_number` and `input_datetime` helpers must be created as specified.
- - **Time Format:** `input_datetime` helpers must have `has_time: true` and `has_date: false`.
- - **Notification Services:** Must select valid notification and TTS services using entity selectors.
- - **Entity IDs:** Verify that all entity IDs used in the automation exist in your Home Assistant setup.
- - **Automation Mode:** The automation is set to `mode: restart` to ensure timely execution but may interrupt ongoing actions.
-
- **Usage:**
-
- - **Import the Blueprint:** Follow the instructions below to add this blueprint to your Home Assistant.
- - **Create an Automation:** Use the blueprint to create an automation, filling in all required fields.
- - **Adjust Helpers:** Set your desired CO₂ targets, tolerances, and times using the helpers.
- - **Test the Automation:** Verify that all parts of the automation work as expected.
-
- **Important Considerations:**
-
- - **Testing:** It's recommended to test each feature individually before relying on the automation.
- - **Time Zones:** Ensure your Home Assistant time zone settings are correct to avoid scheduling issues.
- - **Service Compatibility:** Ensure that your selected notification and TTS services support the data parameters used.
- - **Entity Verification:** Double-check that all entity IDs selected during blueprint instantiation exist and are correctly configured in your Home Assistant setup.
-
- domain: automation
- input:
- co2_sensor:
- name: CO₂ Sensor
- description: The primary CO₂ sensor entity to monitor.
- selector:
- entity:
- domain: sensor
- co2_sensor_secondary:
- name: Secondary CO₂ Sensor (Optional)
- description: >
- A secondary CO₂ sensor entity to monitor for high CO₂ alerts. Leave blank if not used.
- default: ''
- selector:
- entity:
- domain: sensor
- co2_target_input:
- name: CO₂ Target Input Number
- description: The input_number entity for the current CO₂ target.
- selector:
- entity:
- domain: input_number
- co2_tolerance_input:
- name: CO₂ Tolerance Input Number
- description: The input_number entity for CO₂ tolerance.
- selector:
- entity:
- domain: input_number
- co2_day_target_input:
- name: Daytime CO₂ Target Input Number
- description: The input_number entity for the daytime CO₂ target.
- selector:
- entity:
- domain: input_number
- co2_night_target_input:
- name: Nighttime CO₂ Target Input Number
- description: The input_number entity for the nighttime CO₂ target.
- selector:
- entity:
- domain: input_number
- co2_on_time:
- name: CO₂ Target On Time
- description: The input_datetime entity for when to set the daytime CO₂ target.
- selector:
- entity:
- domain: input_datetime
- co2_off_time:
- name: CO₂ Target Off Time
- description: The input_datetime entity for when to set the nighttime CO₂ target.
- selector:
- entity:
- domain: input_datetime
- co2_control_switch:
- name: CO₂ Control Switch
- description: The switch to control based on CO₂ levels.
- selector:
- entity:
- domain: switch
- low_co2_threshold:
- name: Low CO₂ Threshold
- description: The CO₂ level below which to trigger a low CO₂ alert.
- default: 600
- selector:
- number:
- min: 0
- max: 2000
- unit_of_measurement: ppm
- mode: box
- low_co2_duration:
- name: Low CO₂ Duration (Minutes)
- description: Duration for CO₂ level to be below threshold before alerting.
- default: 1
- selector:
- number:
- min: 0
- max: 60
- unit_of_measurement: minutes
- mode: box
- low_co2_lights:
- name: Lights to Adjust on Low CO₂
- description: Lights to dim when CO₂ is low.
- selector:
- target:
- entity:
- domain: light
- low_co2_brightness_pct:
- name: Low CO₂ Brightness Percentage
- description: Brightness percentage to set the lights to when CO₂ is low.
- default: 60
- selector:
- number:
- min: 0
- max: 100
- unit_of_measurement: "%"
- mode: slider
- low_co2_time_start:
- name: Low CO₂ Alert Start Time
- description: Input_datetime for the start time of low CO₂ alert period.
- selector:
- entity:
- domain: input_datetime
- low_co2_time_end:
- name: Low CO₂ Alert End Time
- description: Input_datetime for the end time of low CO₂ alert period.
- selector:
- entity:
- domain: input_datetime
- high_co2_threshold:
- name: High CO₂ Threshold
- description: The CO₂ level above which to trigger a high CO₂ alert.
- default: 1800
- selector:
- number:
- min: 0
- max: 5000
- unit_of_measurement: ppm
- mode: box
- high_co2_duration:
- name: High CO₂ Duration (Seconds)
- description: Duration for CO₂ level to be above threshold before alerting.
- default: 11
- selector:
- number:
- min: 0
- max: 600
- unit_of_measurement: seconds
- mode: box
- high_co2_threshold_secondary:
- name: High CO₂ Threshold (Secondary Sensor)
- description: The CO₂ level above which to trigger a high CO₂ alert from the secondary sensor.
- default: 2500
- selector:
- number:
- min: 0
- max: 5000
- unit_of_measurement: ppm
- mode: box
- high_co2_duration_secondary:
- name: High CO₂ Duration (Secondary Sensor) (Seconds)
- description: Duration for CO₂ level to be above threshold before alerting (secondary sensor).
- default: 11
- selector:
- number:
- min: 0
- max: 600
- unit_of_measurement: seconds
- mode: box
- notification_service:
- name: Notification Service
- description: The notification services to send alerts to.
- selector:
- entity:
- domain: notify
- multiple: true
- tts_notification_service:
- name: TTS Notification Service
- description: The TTS service to send audible alerts.
- selector:
- entity:
- domain: tts
- notification_title_low:
- name: Low CO₂ Notification Title
- description: Title for low CO₂ notifications.
- default: "CO₂ LOW"
- selector:
- text:
- notification_message_low:
- name: Low CO₂ Notification Message
- description: Message for low CO₂ notifications.
- default: "CO₂ is low, lights have been dimmed to {{ low_co2_brightness_pct }}%"
- selector:
- text:
- notification_title_high:
- name: High CO₂ Notification Title
- description: Title for high CO₂ notifications.
- default: "High CO₂ Alert"
- selector:
- text:
- notification_message_high:
- name: High CO₂ Notification Message
- description: Message for high CO₂ notifications.
- default: "High CO₂ levels detected."
- selector:
- text:
- tts_message_high:
- name: High CO₂ TTS Message
- description: Message for Text-To-Speech when high CO₂ detected.
- default: "Attention: CO₂ levels are high."
- selector:
- text:
-
-mode: restart
-max_exceeded: silent
-trigger:
- # CO₂ Sensor or Input Numbers Change (Control Logic)
- - platform: state
- entity_id: !input co2_sensor
- id: co2_sensor_state_change
- - platform: state
- entity_id: !input co2_target_input
- id: co2_target_state_change
- - platform: state
- entity_id: !input co2_tolerance_input
- id: co2_tolerance_state_change
- # Time Triggers for Target Adjustment
- - platform: time
- at: !input co2_on_time
- id: co2_on_time_trigger
- - platform: time
- at: !input co2_off_time
- id: co2_off_time_trigger
- # Low CO₂ Alert Trigger
- - platform: numeric_state
- entity_id: !input co2_sensor
- below: !input low_co2_threshold
- for:
- minutes: !input low_co2_duration
- id: low_co2_alert_trigger
- # High CO₂ Alert Trigger (Primary Sensor)
- - platform: numeric_state
- entity_id: !input co2_sensor
- above: !input high_co2_threshold
- for:
- seconds: !input high_co2_duration
- id: high_co2_alert_trigger
- # High CO₂ Alert Trigger (Secondary Sensor)
- - platform: numeric_state
- entity_id: !input co2_sensor_secondary
- above: !input high_co2_threshold_secondary
- for:
- seconds: !input high_co2_duration_secondary
- id: high_co2_alert_trigger_secondary
-conditions: []
-action:
- - choose:
- # Daytime CO₂ Target Adjustment
- - conditions:
- - condition: trigger
- id: co2_on_time_trigger
- sequence:
- - variables:
- target_value: "{{ states('!input co2_day_target_input') | float(0) }}"
- - condition: template
- value_template: "{{ target_value > 0 }}"
- - service: input_number.set_value
- target:
- entity_id: !input co2_target_input
- data:
- value: "{{ target_value }}"
- # Nighttime CO₂ Target Adjustment
- - conditions:
- - condition: trigger
- id: co2_off_time_trigger
- sequence:
- - variables:
- target_value: "{{ states('!input co2_night_target_input') | float(0) }}"
- - condition: template
- value_template: "{{ target_value > 0 }}"
- - service: input_number.set_value
- target:
- entity_id: !input co2_target_input
- data:
- value: "{{ target_value }}"
- # Low CO₂ Alert
- - conditions:
- - condition: trigger
- id: low_co2_alert_trigger
- - condition: template
- value_template: >
- {% set time_now = now().time() %}
- {% set time_start_str = states('!input low_co2_time_start') %}
- {% set time_end_str = states('!input low_co2_time_end') %}
- {% set time_start = strptime(time_start_str, '%H:%M') %}
- {% set time_end = strptime(time_end_str, '%H:%M') %}
- {% set start_time = time_start.time() %}
- {% set end_time = time_end.time() %}
- {{ start_time <= time_now <= end_time }}
- - condition: template
- value_template: "{{ states('!input co2_sensor') | float(0) < low_co2_threshold }}"
- sequence:
- - repeat:
- for_each: "{{ notification_service }}"
- sequence:
- - service: "{{ repeat.item }}"
- data:
- title: "{{ notification_title_low }}"
- message: "{{ notification_message_low }}"
- - service: light.turn_on
- target: !input low_co2_lights
- data:
- brightness_pct: "{{ low_co2_brightness_pct }}"
- # High CO₂ Alert (Primary Sensor)
- - conditions:
- - condition: trigger
- id: high_co2_alert_trigger
- sequence:
- - variables:
- co2_level: "{{ states('!input co2_sensor') | float(0) }}"
- co2_sensor_name: "{{ state_attr('!input co2_sensor', 'friendly_name') or '!input co2_sensor' }}"
- - condition: template
- value_template: "{{ co2_level > high_co2_threshold }}"
- - repeat:
- for_each: "{{ notification_service }}"
- sequence:
- - service: "{{ repeat.item }}"
- data:
- title: "{{ notification_title_high }}"
- message: >
- {{ co2_sensor_name }} CO₂ level: {{ co2_level }} ppm.
- - service: switch.turn_off
- target:
- entity_id: !input co2_control_switch
- - service: persistent_notification.create
- data:
- title: "{{ notification_title_high }}"
- message: "{{ co2_sensor_name }} CO₂ level: {{ co2_level }} ppm."
- - service: !input tts_notification_service
- data:
- message: "{{ tts_message_high }}"
- # High CO₂ Alert (Secondary Sensor)
- - conditions:
- - condition: trigger
- id: high_co2_alert_trigger_secondary
- - condition: template
- value_template: "{{ co2_sensor_secondary != '' }}"
- sequence:
- - variables:
- co2_level_secondary: "{{ states('!input co2_sensor_secondary') | float(0) }}"
- co2_sensor_secondary_name: "{{ state_attr('!input co2_sensor_secondary', 'friendly_name') or '!input co2_sensor_secondary' }}"
- - condition: template
- value_template: "{{ co2_level_secondary > high_co2_threshold_secondary }}"
- - repeat:
- for_each: "{{ notification_service }}"
- sequence:
- - service: "{{ repeat.item }}"
- data:
- title: "{{ notification_title_high }}"
- message: >
- {{ co2_sensor_secondary_name }} CO₂ level: {{ co2_level_secondary }} ppm.
- - service: switch.turn_off
- target:
- entity_id: !input co2_control_switch
- - service: persistent_notification.create
- data:
- title: "{{ notification_title_high }}"
- message: "{{ co2_sensor_secondary_name }} CO₂ level: {{ co2_level_secondary }} ppm."
- - service: !input tts_notification_service
- data:
- message: "{{ tts_message_high }}"
- default:
- # CO₂ Control Logic
- - variables:
- co2_value: "{{ states('!input co2_sensor') | float(0) }}"
- co2_target: "{{ states('!input co2_target_input') | float(0) }}"
- co2_tolerance: "{{ states('!input co2_tolerance_input') | float(0) }}"
- - condition: template
- value_template: >
- {{ co2_value > 0 and co2_target > 0 and co2_tolerance > 0 }}
- - variables:
- co2_lower_limit: "{{ co2_target - co2_tolerance }}"
- co2_upper_limit: "{{ co2_target + co2_tolerance }}"
- - choose:
- - conditions:
- - condition: template
- value_template: "{{ co2_value < co2_lower_limit }}"
- - condition: state
- entity_id: !input co2_control_switch
- state: 'off'
- sequence:
- - service: switch.turn_on
- target:
- entity_id: !input co2_control_switch
- - conditions:
- - condition: template
- value_template: "{{ co2_value > co2_upper_limit }}"
- - condition: state
- entity_id: !input co2_control_switch
- state: 'on'
- sequence:
- - service: switch.turn_off
- target:
- entity_id: !input co2_control_switch
-```
+- **Interface changed in the 2024.10 rewrite.** If you imported an earlier version,
+ re-import: `high_co2_duration_secondary` and `tts_service_name` were removed;
+ `max_co2_on_minutes` and a `tts_engine` entity were added; the lights input is now an
+ entity list (was a target); TTS uses `tts.speak` and notifications use
+ `notify.send_message`.
+- Enable **TTS** only after picking a `tts_engine` and media player, or leave it off.
+- See [`../blueprints/README.md`](../blueprints/README.md) for the full blueprint set and the
+ helpers each one needs.