Files
home-assistant-blueprints/CO2_Ventilation_Alert.yaml
T
2026-09-20 00:12:41 +01:00

200 lines
6.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
blueprint:
name: CO₂ ventilation alert – Apollo R PRO-1 (LED + buzzer)
description: >-
Visual and audible CO₂ alerts on an Apollo R PRO-1.
**LED**: off below the "ventilation recommended" level. From that level
it turns yellow and fades towards red as CO₂ approaches the "ventilation
needed" level; at or above it, it is solid red.
**Buzzer**: at or above the "start beeping" level the beep action is
repeated at the chosen interval, but only while CO₂ is NOT dropping.
"Dropping" means the newest CO₂ reading is lower than the reading about
one minute earlier (taken from a Statistics helper, see the
"CO₂ change" input). Beeping stops as soon as CO₂ is falling, at any level.
domain: automation
input:
co2_sensor:
name: CO₂ sensor
description: The R PRO-1 CO₂ sensor (ppm).
selector:
entity:
filter:
- domain: sensor
device_class: carbon_dioxide
change_sensor:
name: CO₂ change over the last minute
description: >-
A Statistics helper based on the CO₂ sensor above. Settings: State
characteristic = "Change", Max age = 1 minute (use 90 s if your
sensor reports slower than every ~20 s). Its state is newest reading
minus oldest reading in the window, so a negative value means CO₂ is
dropping.
selector:
entity:
filter:
- domain: sensor
led:
name: R PRO-1 RGB LED
description: The light entity of the R PRO-1 RGB LED.
selector:
entity:
filter:
- domain: light
beep_action:
name: Beep action
description: >-
Action(s) that make the R PRO-1 beep. Use the ESPHome action of your
device, for example `esphome.<your_device>_play_buzzer` with data
`song_str: "co2:d=8,o=6,b=180:c,p,c"`. Keep the tune short, it is
repeated at the beep interval.
default: []
selector:
action: {}
recommended_level:
name: Ventilation recommended (ppm)
description: LED turns on (yellow) at this level.
default: 1000
selector:
number:
min: 400
max: 5000
step: 50
unit_of_measurement: ppm
mode: box
needed_level:
name: Ventilation needed (ppm)
description: LED is fully red at this level.
default: 1500
selector:
number:
min: 400
max: 5000
step: 50
unit_of_measurement: ppm
mode: box
beep_level:
name: Start beeping (ppm)
description: Beeping starts at this level (unless CO₂ is dropping).
default: 2000
selector:
number:
min: 400
max: 10000
step: 50
unit_of_measurement: ppm
mode: box
min_drop:
name: Minimum drop to count as "dropping" (ppm)
description: >-
0 = any decrease stops the beeping. Raise to 5–10 if sensor jitter
makes the beeping stop and start at a plateau.
default: 0
selector:
number:
min: 0
max: 100
step: 1
unit_of_measurement: ppm
mode: box
beep_interval:
name: Beep repeat interval
default: "/30"
selector:
select:
options:
- label: Every 10 seconds
value: "/10"
- label: Every 15 seconds
value: "/15"
- label: Every 20 seconds
value: "/20"
- label: Every 30 seconds
value: "/30"
brightness:
name: LED brightness (%)
default: 60
selector:
number:
min: 1
max: 100
step: 1
unit_of_measurement: "%"
mode: slider
led_off_when_ok:
name: Turn LED off below "recommended"
description: >-
If enabled, the LED is switched off when CO₂ is below the
recommended level. Disable if you use the LED for other things.
default: true
selector:
boolean: {}
mode: queued
max: 10
max_exceeded: silent
variables:
co2_sensor: !input co2_sensor
change_sensor: !input change_sensor
rec_level: !input recommended_level
need_level: !input needed_level
beep_level: !input beep_level
min_drop: !input min_drop
led_brightness: !input brightness
led_off_when_ok: !input led_off_when_ok
triggers:
- trigger: state
entity_id: !input co2_sensor
id: reading
- trigger: time_pattern
seconds: !input beep_interval
id: beep_tick
actions:
- variables:
co2: "{{ states(co2_sensor) | float(none) }}"
change: "{{ states(change_sensor) | float(0) }}"
dropping: "{{ change < -(min_drop | float(0)) }}"
span: "{{ [need_level - rec_level, 1] | max }}"
frac: >-
{{ ([[(co2 - rec_level) / span, 0] | max, 1] | min)
if co2 is not none else 0 }}
hue: "{{ (60 * (1 - frac)) | round(0) | int }}"
- condition: template
value_template: "{{ co2 is not none }}"
- choose:
# --- LED: update on every new CO2 reading -------------------------
- conditions:
- condition: trigger
id: reading
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ co2 >= rec_level }}"
sequence:
- action: light.turn_on
target:
entity_id: !input led
data:
hs_color: "{{ [hue, 100] }}"
brightness_pct: "{{ led_brightness | int }}"
- conditions:
- condition: template
value_template: "{{ led_off_when_ok }}"
sequence:
- action: light.turn_off
target:
entity_id: !input led
# --- Buzzer: repeat while high AND not dropping -------------------
- conditions:
- condition: trigger
id: beep_tick
- condition: template
value_template: "{{ co2 >= beep_level and not dropping }}"
sequence: !input beep_action