Files
zorruno-homeassistant/packages/fridge_freezer_monitoring.yaml
T
2026-09-13 15:32:16 +12:00

981 lines
52 KiB
YAML

#:########################################################################################:#
# PACKAGE: Fridge and Freezer Monitoring
# FILE: packages/fridge_freezer_monitoring.yaml
# VERSION: v1.13.0 2026-09-03
# - Moves Downstairs Freezer temperature, humidity, and battery monitoring
# from X62TS to X70TS.
# - Moves shared Downstairs Fridge and Freezer power monitoring from X41PP to
# the metering-only X68PM GPO.
# - Reports an unavailable Main Kitchen Fridge battery monitor explicitly,
# rather than showing an unqualified issue.
# - Moves Main Kitchen Fridge temperature, humidity, and battery monitoring to
# X65TS and adds X64LS illuminance-based door monitoring.
# - v1.10.0 2026-08-29: Adds Downstairs Freezer temperature, battery, door, humidity, and shared
# Downstairs Fridge/Freezer plug monitoring.
# - Uses a four-hour sustained low-draw power-loss rule for all monitored
# fridges and freezers, including the shared Drinks Fridge/Freezer plug.
# - v1.8.4 2026-08-24: Flags a Drinks Fridge power loss only after six
# continuous hours below 1 W.
# - v1.8.3 2026-08-24: Excludes normal Drinks Fridge compressor-off cycles
# from power alerts.
# - v1.8.2 2026-08-24: Widens Drinks Fridge and Vertical Freezer adaptive
# temperature ceilings to accommodate confirmed normal compressor cycles.
# - v1.8.1 2026-08-24: Excludes normal Vertical Freezer compressor-off cycles
# from power alerts and widens its learned temperature allowance.
# - v1.8.0 2026-08-24: Adds Drinks Fridge and Vertical Freezer plug monitoring.
# - Adds illuminance-based door monitoring for the Downstairs Fridge.
# - Adds Drinks Fridge door detection from its illuminance sensor.
# - Makes an open door an issue after seven minutes and delays temperature
# alerts while the door is open or cooling recovers after closure.
# - v1.5.0 2026-08-22
# - Requires five minutes of sub-1 W draw before reporting Main Kitchen Fridge power loss.
# - Moved Main Kitchen Fridge power monitoring to the Zigbee X31PP plug.
# - v1.3.0 2026-08-17: Uses the calibrated Main Kitchen Fridge temperature entity throughout.
# - Uses the calibrated Main Kitchen Fridge temperature entity throughout.
# - Added adaptive temperature, battery, humidity, and power monitoring for
# the Downstairs Fridge.
# - v1.1.0 2026-08-16: Reduced the adaptive temperature margin and issue persistence time.
#:########################################################################################:#
# PURPOSE:
# Detect missing monitoring, low batteries, loss of Main Fridge power, and
# abnormal warming, including door-aware handling where a sensor is fitted.
#:########################################################################################:#
# BEHAVIOUR:
# - Learns a continuously rolling seven-day average and 95th percentile.
# - Limits each learned threshold with an appliance-specific safety maximum.
# - Measures the temperature change rate over a smoothed 30-minute window.
# - Requires an issue condition to persist for one minute, except Main Kitchen
# Fridge low-power draw, which persists for five minutes.
# - Treats the Main Kitchen, Drinks, and Downstairs Fridges as open at 10 lx or higher. An
# open door is an issue after seven minutes, while temperature alerting
# stays deferred through a 15-minute post-close recovery window.
# - Exposes one issue binary sensor per appliance and one summary sensor.
#:########################################################################################:#
# NOTES:
# - Learned thresholds use the lower of 95th percentile + 0.5 C or the fixed
# safety limit, so a cooling failure cannot gradually become normal.
# - A rise rate of at least 2 C/hour labels an over-temperature condition as
# possible open-door warming; slower warming is labelled loss of cooling.
# - Main Fridge power below 1 W is treated as loss only after five minutes to
# avoid normal compressor-off periods; unplugged or unavailable monitoring
# remains an issue after one minute.
# - Main Fridge X65TS temperature is adjusted by -0.84 C to match the
# reference thermometer.
# - Wine-fridge ESPHome telemetry is intentionally excluded.
#:########################################################################################:#
# DEPENDENCIES:
# - Seven configured fridge/freezer temperature and battery monitor pairs.
# - switch.upstairs_fridge_power_x31pp
# - sensor.upstairs_fridge_power_x31pp_power
# - sensor.downstairs_fridge_gpo_power_x68pm_power
# - switch.drinks_fridge_power_x59pm
# - sensor.drinks_fridge_power_x59pm_power
# - switch.vertical_freezer_power_x60pm
# - sensor.vertical_freezer_power_x60pm_power
# - sensor.drinks_fridge_light_sensor_x35ls_illuminance
# - sensor.downstairs_fridge_light_sensor_x58ls_illuminance
# - sensor.downstairs_freezer_light_sensor_x61ls_illuminance
# - sensor.main_kitchen_fridge_light_sensor_x64ls_illuminance
#:########################################################################################:#
sensor:
#:######################################################################################:#
# MAIN KITCHEN FRIDGE
#:######################################################################################:#
- platform: statistics
name: "Main Kitchen Fridge Temperature Average 7 Days"
unique_id: main_kitchen_fridge_temperature_average_7_days
entity_id: sensor.main_kitchen_fridge_temperature_calibrated
state_characteristic: average_step
max_age:
days: 7
precision: 1
- platform: statistics
name: "Main Kitchen Fridge Temperature 95th Percentile 7 Days"
unique_id: main_kitchen_fridge_temperature_95th_percentile_7_days
entity_id: sensor.main_kitchen_fridge_temperature_calibrated
state_characteristic: percentile
percentile: 95
max_age:
days: 7
precision: 1
- platform: derivative
name: "Main Kitchen Fridge Temperature Change Rate"
unique_id: main_kitchen_fridge_temperature_change_rate
source: sensor.main_kitchen_fridge_temperature_calibrated
unit_time: h
time_window: "00:30:00"
max_sub_interval: "00:05:00"
round: 1
#:######################################################################################:#
# DRINKS FRIDGE
#:######################################################################################:#
- platform: statistics
name: "Drinks Fridge Temperature Average 7 Days"
unique_id: drinks_fridge_temperature_average_7_days
entity_id: sensor.drinks_fridge_environment_lcd_btt01_temperature
state_characteristic: average_step
max_age:
days: 7
precision: 1
- platform: statistics
name: "Drinks Fridge Temperature 95th Percentile 7 Days"
unique_id: drinks_fridge_temperature_95th_percentile_7_days
entity_id: sensor.drinks_fridge_environment_lcd_btt01_temperature
state_characteristic: percentile
percentile: 95
max_age:
days: 7
precision: 1
- platform: derivative
name: "Drinks Fridge Temperature Change Rate"
unique_id: drinks_fridge_temperature_change_rate
source: sensor.drinks_fridge_environment_lcd_btt01_temperature
unit_time: h
time_window: "00:30:00"
max_sub_interval: "00:05:00"
round: 1
#:######################################################################################:#
# DOWNSTAIRS FRIDGE
#:######################################################################################:#
- platform: statistics
name: "Downstairs Fridge Temperature Average 7 Days"
unique_id: downstairs_fridge_temperature_average_7_days
entity_id: sensor.downstairs_fridge_temperature_x43ts_temperature
state_characteristic: average_step
max_age:
days: 7
precision: 1
- platform: statistics
name: "Downstairs Fridge Temperature 95th Percentile 7 Days"
unique_id: downstairs_fridge_temperature_95th_percentile_7_days
entity_id: sensor.downstairs_fridge_temperature_x43ts_temperature
state_characteristic: percentile
percentile: 95
max_age:
days: 7
precision: 1
- platform: derivative
name: "Downstairs Fridge Temperature Change Rate"
unique_id: downstairs_fridge_temperature_change_rate
source: sensor.downstairs_fridge_temperature_x43ts_temperature
unit_time: h
time_window: "00:30:00"
max_sub_interval: "00:05:00"
round: 1
#:######################################################################################:#
# DOWNSTAIRS FREEZER
#:######################################################################################:#
- platform: statistics
name: "Downstairs Freezer Temperature Average 7 Days"
unique_id: downstairs_freezer_temperature_average_7_days
entity_id: sensor.downstairs_freezer_temperature_x70ts_temperature
state_characteristic: average_step
max_age:
days: 7
precision: 1
- platform: statistics
name: "Downstairs Freezer Temperature 95th Percentile 7 Days"
unique_id: downstairs_freezer_temperature_95th_percentile_7_days
entity_id: sensor.downstairs_freezer_temperature_x70ts_temperature
state_characteristic: percentile
percentile: 95
max_age:
days: 7
precision: 1
- platform: derivative
name: "Downstairs Freezer Temperature Change Rate"
unique_id: downstairs_freezer_temperature_change_rate
source: sensor.downstairs_freezer_temperature_x70ts_temperature
unit_time: h
time_window: "00:30:00"
max_sub_interval: "00:05:00"
round: 1
#:######################################################################################:#
# WINE FRIDGE
#:######################################################################################:#
- platform: statistics
name: "Wine Fridge Temperature Average 7 Days"
unique_id: wine_fridge_temperature_average_7_days
entity_id: sensor.lcd_temp_humidity_btt04_temperature
state_characteristic: average_step
max_age:
days: 7
precision: 1
- platform: statistics
name: "Wine Fridge Temperature 95th Percentile 7 Days"
unique_id: wine_fridge_temperature_95th_percentile_7_days
entity_id: sensor.lcd_temp_humidity_btt04_temperature
state_characteristic: percentile
percentile: 95
max_age:
days: 7
precision: 1
- platform: derivative
name: "Wine Fridge Temperature Change Rate"
unique_id: wine_fridge_temperature_change_rate
source: sensor.lcd_temp_humidity_btt04_temperature
unit_time: h
time_window: "00:30:00"
max_sub_interval: "00:05:00"
round: 1
#:######################################################################################:#
# DRINKS FREEZER
#:######################################################################################:#
- platform: statistics
name: "Drinks Freezer Temperature Average 7 Days"
unique_id: drinks_freezer_temperature_average_7_days
entity_id: sensor.drinks_freezer_environment_lcd_btt02_temperature
state_characteristic: average_step
max_age:
days: 7
precision: 1
- platform: statistics
name: "Drinks Freezer Temperature 95th Percentile 7 Days"
unique_id: drinks_freezer_temperature_95th_percentile_7_days
entity_id: sensor.drinks_freezer_environment_lcd_btt02_temperature
state_characteristic: percentile
percentile: 95
max_age:
days: 7
precision: 1
- platform: derivative
name: "Drinks Freezer Temperature Change Rate"
unique_id: drinks_freezer_temperature_change_rate
source: sensor.drinks_freezer_environment_lcd_btt02_temperature
unit_time: h
time_window: "00:30:00"
max_sub_interval: "00:05:00"
round: 1
#:######################################################################################:#
# VERTICAL FREEZER
#:######################################################################################:#
- platform: statistics
name: "Vertical Freezer Temperature Average 7 Days"
unique_id: vertical_freezer_temperature_average_7_days
entity_id: sensor.lcd_temp_humidity_btt03_temperature
state_characteristic: average_step
max_age:
days: 7
precision: 1
- platform: statistics
name: "Vertical Freezer Temperature 95th Percentile 7 Days"
unique_id: vertical_freezer_temperature_95th_percentile_7_days
entity_id: sensor.lcd_temp_humidity_btt03_temperature
state_characteristic: percentile
percentile: 95
max_age:
days: 7
precision: 1
- platform: derivative
name: "Vertical Freezer Temperature Change Rate"
unique_id: vertical_freezer_temperature_change_rate
source: sensor.lcd_temp_humidity_btt03_temperature
unit_time: h
time_window: "00:30:00"
max_sub_interval: "00:05:00"
round: 1
template:
#:######################################################################################:#
# DOOR DETECTION
#:######################################################################################:#
- binary_sensor:
- name: "Main Kitchen Fridge Door Open"
unique_id: main_kitchen_fridge_door_open
device_class: door
state: >-
{{
has_value('sensor.main_kitchen_fridge_light_sensor_x64ls_illuminance')
and (states('sensor.main_kitchen_fridge_light_sensor_x64ls_illuminance') | float(0)) >= 10
}}
# Retain the grace period after closure so the fridge can start cooling.
- name: "Main Kitchen Fridge Temperature Recovery Grace"
unique_id: main_kitchen_fridge_temperature_recovery_grace
delay_off: "00:15:00"
state: "{{ is_state('binary_sensor.main_kitchen_fridge_door_open', 'on') }}"
- name: "Main Kitchen Fridge Door Open Too Long"
unique_id: main_kitchen_fridge_door_open_too_long
device_class: problem
delay_on: "00:07:00"
state: "{{ is_state('binary_sensor.main_kitchen_fridge_door_open', 'on') }}"
- name: "Drinks Fridge Door Open"
unique_id: drinks_fridge_door_open
device_class: door
state: >-
{{
has_value('sensor.drinks_fridge_light_sensor_x35ls_illuminance')
and (states('sensor.drinks_fridge_light_sensor_x35ls_illuminance') | float(0)) >= 10
}}
# Retain the grace period after closure so the fridge can start cooling.
- name: "Drinks Fridge Temperature Recovery Grace"
unique_id: drinks_fridge_temperature_recovery_grace
delay_off: "00:15:00"
state: "{{ is_state('binary_sensor.drinks_fridge_door_open', 'on') }}"
- name: "Drinks Fridge Door Open Too Long"
unique_id: drinks_fridge_door_open_too_long
device_class: problem
delay_on: "00:07:00"
state: "{{ is_state('binary_sensor.drinks_fridge_door_open', 'on') }}"
- name: "Downstairs Fridge Door Open"
unique_id: downstairs_fridge_door_open
device_class: door
state: >-
{{
has_value('sensor.downstairs_fridge_light_sensor_x58ls_illuminance')
and (states('sensor.downstairs_fridge_light_sensor_x58ls_illuminance') | float(0)) >= 10
}}
# Retain the grace period after closure so the fridge can start cooling.
- name: "Downstairs Fridge Temperature Recovery Grace"
unique_id: downstairs_fridge_temperature_recovery_grace
delay_off: "00:15:00"
state: "{{ is_state('binary_sensor.downstairs_fridge_door_open', 'on') }}"
- name: "Downstairs Fridge Door Open Too Long"
unique_id: downstairs_fridge_door_open_too_long
device_class: problem
delay_on: "00:07:00"
state: "{{ is_state('binary_sensor.downstairs_fridge_door_open', 'on') }}"
- name: "Downstairs Freezer Door Open"
unique_id: downstairs_freezer_door_open
device_class: door
state: >-
{{
has_value('sensor.downstairs_freezer_light_sensor_x61ls_illuminance')
and (states('sensor.downstairs_freezer_light_sensor_x61ls_illuminance') | float(0)) >= 10
}}
# Retain the grace period after closure so the freezer can start cooling.
- name: "Downstairs Freezer Temperature Recovery Grace"
unique_id: downstairs_freezer_temperature_recovery_grace
delay_off: "00:15:00"
state: "{{ is_state('binary_sensor.downstairs_freezer_door_open', 'on') }}"
- name: "Downstairs Freezer Door Open Too Long"
unique_id: downstairs_freezer_door_open_too_long
device_class: problem
delay_on: "00:07:00"
state: "{{ is_state('binary_sensor.downstairs_freezer_door_open', 'on') }}"
#:######################################################################################:#
# APPLIANCE ISSUE SENSORS
#:######################################################################################:#
- binary_sensor:
- name: "Main Kitchen Fridge Power Draw Lost"
unique_id: main_kitchen_fridge_power_draw_lost
device_class: problem
delay_on: "04:00:00"
state: >-
{{
is_state('switch.upstairs_fridge_power_x31pp', 'on')
and has_value('sensor.upstairs_fridge_power_x31pp_power')
and (states('sensor.upstairs_fridge_power_x31pp_power') | float(0)) < 1
}}
# A compressor-off interval is normal; measure the uninterrupted idle time
# explicitly so a template reload cannot restore this as an active fault.
- name: "Drinks Fridge Power Draw Lost"
unique_id: drinks_fridge_power_draw_lost
device_class: problem
state: >-
{% set power = states('sensor.drinks_fridge_power_x59pm_power') | float(none) %}
{% set changed = states.sensor.drinks_fridge_power_x59pm_power.last_changed %}
{{
is_state('switch.drinks_fridge_power_x59pm', 'on')
and power is not none
and power < 1
and (now() - changed).total_seconds() >= 4 * 60 * 60
}}
- name: "Downstairs Fridge Power Draw Lost"
unique_id: downstairs_fridge_power_draw_lost
device_class: problem
state: >-
{% set power = states('sensor.downstairs_fridge_gpo_power_x68pm_power') | float(none) %}
{% set changed = states.sensor.downstairs_fridge_gpo_power_x68pm_power.last_changed %}
{{
power is not none
and power < 1
and (now() - changed).total_seconds() >= 4 * 60 * 60
}}
- name: "Vertical Freezer Power Draw Lost"
unique_id: vertical_freezer_power_draw_lost
device_class: problem
state: >-
{% set power = states('sensor.vertical_freezer_power_x60pm_power') | float(none) %}
{% set changed = states.sensor.vertical_freezer_power_x60pm_power.last_changed %}
{{
is_state('switch.vertical_freezer_power_x60pm', 'on')
and power is not none
and power < 1
and (now() - changed).total_seconds() >= 4 * 60 * 60
}}
- name: "Main Kitchen Fridge Issue"
unique_id: main_kitchen_fridge_issue
device_class: problem
delay_on: "00:01:00"
state: >-
{% set temperature_missing = not has_value('sensor.main_kitchen_fridge_temperature_calibrated') %}
{% set battery_missing = not has_value('sensor.main_kitchen_fridge_temperature_x65ts_battery') %}
{% set illuminance_missing = not has_value('sensor.main_kitchen_fridge_light_sensor_x64ls_illuminance') %}
{% set power_missing = not has_value('sensor.upstairs_fridge_power_x31pp_power') %}
{% set percentile = states('sensor.main_kitchen_fridge_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [10, percentile + 0.5] | min if percentile is not none else 10 %}
{{
temperature_missing
or illuminance_missing
or battery_missing
or (
not battery_missing
and (states('sensor.main_kitchen_fridge_temperature_x65ts_battery') | float(0)) <= 20
)
or is_state('binary_sensor.main_kitchen_fridge_door_open_too_long', 'on')
or (
not temperature_missing
and not is_state('binary_sensor.main_kitchen_fridge_temperature_recovery_grace', 'on')
and (states('sensor.main_kitchen_fridge_temperature_calibrated') | float(0)) > threshold
)
or states('switch.upstairs_fridge_power_x31pp') != 'on'
or power_missing
or is_state('binary_sensor.main_kitchen_fridge_power_draw_lost', 'on')
}}
attributes:
appliance: "Main Kitchen Fridge"
issues: >-
{% set ns = namespace(items=[]) %}
{% set temperature_missing = not has_value('sensor.main_kitchen_fridge_temperature_calibrated') %}
{% set battery_missing = not has_value('sensor.main_kitchen_fridge_temperature_x65ts_battery') %}
{% set illuminance_missing = not has_value('sensor.main_kitchen_fridge_light_sensor_x64ls_illuminance') %}
{% set power_missing = not has_value('sensor.upstairs_fridge_power_x31pp_power') %}
{% set percentile = states('sensor.main_kitchen_fridge_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [10, percentile + 0.5] | min if percentile is not none else 10 %}
{% if temperature_missing %}
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
{% endif %}
{% if illuminance_missing %}
{% set ns.items = ns.items + ['Door monitor unavailable'] %}
{% endif %}
{% if battery_missing %}
{% set ns.items = ns.items + ['Battery monitor unavailable'] %}
{% elif (states('sensor.main_kitchen_fridge_temperature_x65ts_battery') | float(0)) <= 20 %}
{% set ns.items = ns.items + ['Low monitor battery'] %}
{% endif %}
{% if states('switch.upstairs_fridge_power_x31pp') in ['unknown', 'unavailable'] or power_missing %}
{% set ns.items = ns.items + ['Power monitoring unavailable'] %}
{% elif not is_state('switch.upstairs_fridge_power_x31pp', 'on') %}
{% set ns.items = ns.items + ['Power switched off'] %}
{% elif is_state('binary_sensor.main_kitchen_fridge_power_draw_lost', 'on') %}
{% set ns.items = ns.items + ['Power lost - no power draw'] %}
{% endif %}
{% if is_state('binary_sensor.main_kitchen_fridge_door_open_too_long', 'on') %}
{% set ns.items = ns.items + ['Door open too long'] %}
{% elif not temperature_missing and is_state('binary_sensor.main_kitchen_fridge_temperature_recovery_grace', 'on') %}
{% set ns.items = ns.items + ['Temperature alert delayed - door recently open'] %}
{% elif not temperature_missing and (states('sensor.main_kitchen_fridge_temperature_calibrated') | float(0)) > threshold %}
{% if (states('sensor.main_kitchen_fridge_temperature_change_rate') | float(0)) >= 2 %}
{% set ns.items = ns.items + ['Warming rapidly - possible open door'] %}
{% else %}
{% set ns.items = ns.items + ['Temperature too high - possible loss of cooling'] %}
{% endif %}
{% endif %}
{{ ns.items }}
temperature: "{{ states('sensor.main_kitchen_fridge_temperature_calibrated') }}"
average_7_days: "{{ states('sensor.main_kitchen_fridge_temperature_average_7_days') }}"
alert_threshold: >-
{% set percentile = states('sensor.main_kitchen_fridge_temperature_95th_percentile_7_days') | float(none) %}
{{ [10, percentile + 0.5] | min if percentile is not none else 10 }}
change_rate: "{{ states('sensor.main_kitchen_fridge_temperature_change_rate') }}"
humidity: "{{ states('sensor.main_kitchen_fridge_temperature_x65ts_humidity') }}"
battery: "{{ states('sensor.main_kitchen_fridge_temperature_x65ts_battery') }}"
power: "{{ states('sensor.upstairs_fridge_power_x31pp_power') }}"
door_open: "{{ is_state('binary_sensor.main_kitchen_fridge_door_open', 'on') }}"
illuminance: "{{ states('sensor.main_kitchen_fridge_light_sensor_x64ls_illuminance') }}"
- name: "Drinks Fridge Issue"
unique_id: drinks_fridge_issue
device_class: problem
delay_on: "00:01:00"
state: >-
{% set temperature_missing = not has_value('sensor.drinks_fridge_environment_lcd_btt01_temperature') %}
{% set battery_missing = not has_value('sensor.drinks_fridge_environment_lcd_btt01_battery') %}
{% set illuminance_missing = not has_value('sensor.drinks_fridge_light_sensor_x35ls_illuminance') %}
{% set power_missing = not has_value('sensor.drinks_fridge_power_x59pm_power') %}
{% set percentile = states('sensor.drinks_fridge_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [10, percentile + 3] | min if percentile is not none else 10 %}
{{
temperature_missing
or illuminance_missing
or (states('sensor.drinks_fridge_environment_lcd_btt01_battery') | float(-1)) <= 20
or states('switch.drinks_fridge_power_x59pm') != 'on'
or power_missing
or is_state('binary_sensor.drinks_fridge_power_draw_lost', 'on')
or is_state('binary_sensor.drinks_fridge_door_open_too_long', 'on')
or (
not temperature_missing
and not is_state('binary_sensor.drinks_fridge_temperature_recovery_grace', 'on')
and (states('sensor.drinks_fridge_environment_lcd_btt01_temperature') | float(0)) > threshold
)
}}
attributes:
appliance: "Drinks Fridge"
issues: >-
{% set ns = namespace(items=[]) %}
{% set temperature_missing = not has_value('sensor.drinks_fridge_environment_lcd_btt01_temperature') %}
{% set battery_missing = not has_value('sensor.drinks_fridge_environment_lcd_btt01_battery') %}
{% set illuminance_missing = not has_value('sensor.drinks_fridge_light_sensor_x35ls_illuminance') %}
{% set power_missing = not has_value('sensor.drinks_fridge_power_x59pm_power') %}
{% set percentile = states('sensor.drinks_fridge_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [10, percentile + 3] | min if percentile is not none else 10 %}
{% if temperature_missing %}
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
{% endif %}
{% if illuminance_missing %}
{% set ns.items = ns.items + ['Door monitor unavailable'] %}
{% endif %}
{% if not battery_missing and (states('sensor.drinks_fridge_environment_lcd_btt01_battery') | float(-1)) <= 20 %}
{% set ns.items = ns.items + ['Low monitor battery'] %}
{% endif %}
{% if states('switch.drinks_fridge_power_x59pm') in ['unknown', 'unavailable'] or power_missing %}
{% set ns.items = ns.items + ['Power monitoring unavailable'] %}
{% elif not is_state('switch.drinks_fridge_power_x59pm', 'on') %}
{% set ns.items = ns.items + ['Power switched off'] %}
{% elif is_state('binary_sensor.drinks_fridge_power_draw_lost', 'on') %}
{% set ns.items = ns.items + ['Power lost - no power draw for 4 hours'] %}
{% endif %}
{% if is_state('binary_sensor.drinks_fridge_door_open_too_long', 'on') %}
{% set ns.items = ns.items + ['Door open too long'] %}
{% elif not temperature_missing and is_state('binary_sensor.drinks_fridge_temperature_recovery_grace', 'on') %}
{% set ns.items = ns.items + ['Temperature alert delayed - door recently open'] %}
{% elif not temperature_missing and (states('sensor.drinks_fridge_environment_lcd_btt01_temperature') | float(0)) > threshold %}
{% if (states('sensor.drinks_fridge_temperature_change_rate') | float(0)) >= 2 %}
{% set ns.items = ns.items + ['Warming rapidly - possible open door'] %}
{% else %}
{% set ns.items = ns.items + ['Temperature too high - possible loss of cooling'] %}
{% endif %}
{% endif %}
{{ ns.items }}
temperature: "{{ states('sensor.drinks_fridge_environment_lcd_btt01_temperature') }}"
average_7_days: "{{ states('sensor.drinks_fridge_temperature_average_7_days') }}"
alert_threshold: >-
{% set percentile = states('sensor.drinks_fridge_temperature_95th_percentile_7_days') | float(none) %}
{{ [10, percentile + 3] | min if percentile is not none else 10 }}
change_rate: "{{ states('sensor.drinks_fridge_temperature_change_rate') }}"
battery: "{{ states('sensor.drinks_fridge_environment_lcd_btt01_battery') }}"
power: "{{ states('sensor.drinks_fridge_power_x59pm_power') }}"
door_open: "{{ is_state('binary_sensor.drinks_fridge_door_open', 'on') }}"
illuminance: "{{ states('sensor.drinks_fridge_light_sensor_x35ls_illuminance') }}"
- name: "Wine Fridge Issue"
unique_id: wine_fridge_issue
device_class: problem
delay_on: "00:01:00"
state: >-
{% set temperature_missing = not has_value('sensor.lcd_temp_humidity_btt04_temperature') %}
{% set battery_missing = not has_value('sensor.lcd_temp_humidity_btt04_battery') %}
{% set percentile = states('sensor.wine_fridge_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [9, percentile + 0.5] | min if percentile is not none else 9 %}
{{
temperature_missing
or (states('sensor.lcd_temp_humidity_btt04_battery') | float(-1)) <= 20
or (not temperature_missing and (states('sensor.lcd_temp_humidity_btt04_temperature') | float(0)) > threshold)
}}
attributes:
appliance: "Wine Fridge"
issues: >-
{% set ns = namespace(items=[]) %}
{% set temperature_missing = not has_value('sensor.lcd_temp_humidity_btt04_temperature') %}
{% set battery_missing = not has_value('sensor.lcd_temp_humidity_btt04_battery') %}
{% set percentile = states('sensor.wine_fridge_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [9, percentile + 0.5] | min if percentile is not none else 9 %}
{% if temperature_missing %}
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
{% endif %}
{% if not battery_missing and (states('sensor.lcd_temp_humidity_btt04_battery') | float(-1)) <= 20 %}
{% set ns.items = ns.items + ['Low monitor battery'] %}
{% endif %}
{% if not temperature_missing and (states('sensor.lcd_temp_humidity_btt04_temperature') | float(0)) > threshold %}
{% if (states('sensor.wine_fridge_temperature_change_rate') | float(0)) >= 2 %}
{% set ns.items = ns.items + ['Warming rapidly - possible open door'] %}
{% else %}
{% set ns.items = ns.items + ['Temperature too high - possible loss of cooling'] %}
{% endif %}
{% endif %}
{{ ns.items }}
temperature: "{{ states('sensor.lcd_temp_humidity_btt04_temperature') }}"
average_7_days: "{{ states('sensor.wine_fridge_temperature_average_7_days') }}"
alert_threshold: >-
{% set percentile = states('sensor.wine_fridge_temperature_95th_percentile_7_days') | float(none) %}
{{ [9, percentile + 0.5] | min if percentile is not none else 9 }}
change_rate: "{{ states('sensor.wine_fridge_temperature_change_rate') }}"
battery: "{{ states('sensor.lcd_temp_humidity_btt04_battery') }}"
- name: "Downstairs Fridge Issue"
unique_id: downstairs_fridge_issue
device_class: problem
delay_on: "00:01:00"
state: >-
{% set temperature_missing = not has_value('sensor.downstairs_fridge_temperature_x43ts_temperature') %}
{% set battery_missing = not has_value('sensor.downstairs_fridge_temperature_x43ts_battery') %}
{% set illuminance_missing = not has_value('sensor.downstairs_fridge_light_sensor_x58ls_illuminance') %}
{% set power_missing = not has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') %}
{% set percentile = states('sensor.downstairs_fridge_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [10, percentile + 0.5] | min if percentile is not none else 10 %}
{{
temperature_missing
or illuminance_missing
or (states('sensor.downstairs_fridge_temperature_x43ts_battery') | float(-1)) <= 20
or is_state('binary_sensor.downstairs_fridge_door_open_too_long', 'on')
or (
not temperature_missing
and not is_state('binary_sensor.downstairs_fridge_temperature_recovery_grace', 'on')
and (states('sensor.downstairs_fridge_temperature_x43ts_temperature') | float(0)) > threshold
)
or power_missing
or is_state('binary_sensor.downstairs_fridge_power_draw_lost', 'on')
}}
attributes:
appliance: "Downstairs Fridge"
issues: >-
{% set ns = namespace(items=[]) %}
{% set temperature_missing = not has_value('sensor.downstairs_fridge_temperature_x43ts_temperature') %}
{% set battery_missing = not has_value('sensor.downstairs_fridge_temperature_x43ts_battery') %}
{% set illuminance_missing = not has_value('sensor.downstairs_fridge_light_sensor_x58ls_illuminance') %}
{% set power_missing = not has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') %}
{% set percentile = states('sensor.downstairs_fridge_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [10, percentile + 0.5] | min if percentile is not none else 10 %}
{% if temperature_missing %}
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
{% endif %}
{% if illuminance_missing %}
{% set ns.items = ns.items + ['Door monitor unavailable'] %}
{% endif %}
{% if not battery_missing and (states('sensor.downstairs_fridge_temperature_x43ts_battery') | float(-1)) <= 20 %}
{% set ns.items = ns.items + ['Low monitor battery'] %}
{% endif %}
{% if power_missing %}
{% set ns.items = ns.items + ['Power monitoring unavailable'] %}
{% elif is_state('binary_sensor.downstairs_fridge_power_draw_lost', 'on') %}
{% set ns.items = ns.items + ['Power lost - no power draw for 4 hours'] %}
{% endif %}
{% if is_state('binary_sensor.downstairs_fridge_door_open_too_long', 'on') %}
{% set ns.items = ns.items + ['Door open too long'] %}
{% elif not temperature_missing and is_state('binary_sensor.downstairs_fridge_temperature_recovery_grace', 'on') %}
{% set ns.items = ns.items + ['Temperature alert delayed - door recently open'] %}
{% elif not temperature_missing and (states('sensor.downstairs_fridge_temperature_x43ts_temperature') | float(0)) > threshold %}
{% if (states('sensor.downstairs_fridge_temperature_change_rate') | float(0)) >= 2 %}
{% set ns.items = ns.items + ['Warming rapidly - possible open door'] %}
{% else %}
{% set ns.items = ns.items + ['Temperature too high - possible loss of cooling'] %}
{% endif %}
{% endif %}
{{ ns.items }}
temperature: "{{ states('sensor.downstairs_fridge_temperature_x43ts_temperature') }}"
humidity: "{{ states('sensor.downstairs_fridge_temperature_x43ts_humidity') }}"
average_7_days: "{{ states('sensor.downstairs_fridge_temperature_average_7_days') }}"
alert_threshold: >-
{% set percentile = states('sensor.downstairs_fridge_temperature_95th_percentile_7_days') | float(none) %}
{{ [10, percentile + 0.5] | min if percentile is not none else 10 }}
change_rate: "{{ states('sensor.downstairs_fridge_temperature_change_rate') }}"
battery: "{{ states('sensor.downstairs_fridge_temperature_x43ts_battery') }}"
power: "{{ states('sensor.downstairs_fridge_gpo_power_x68pm_power') }}"
door_open: "{{ is_state('binary_sensor.downstairs_fridge_door_open', 'on') }}"
illuminance: "{{ states('sensor.downstairs_fridge_light_sensor_x58ls_illuminance') }}"
- name: "Downstairs Freezer Issue"
unique_id: downstairs_freezer_issue
device_class: problem
delay_on: "00:01:00"
state: >-
{% set temperature_missing = not has_value('sensor.downstairs_freezer_temperature_x70ts_temperature') %}
{% set battery_missing = not has_value('sensor.downstairs_freezer_temperature_x70ts_battery') %}
{% set illuminance_missing = not has_value('sensor.downstairs_freezer_light_sensor_x61ls_illuminance') %}
{% set power_missing = not has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') %}
{% set percentile = states('sensor.downstairs_freezer_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [-5, percentile + 0.5] | min if percentile is not none else -5 %}
{{
temperature_missing
or illuminance_missing
or (states('sensor.downstairs_freezer_temperature_x70ts_battery') | float(-1)) <= 20
or is_state('binary_sensor.downstairs_freezer_door_open_too_long', 'on')
or (
not temperature_missing
and not is_state('binary_sensor.downstairs_freezer_temperature_recovery_grace', 'on')
and (states('sensor.downstairs_freezer_temperature_x70ts_temperature') | float(0)) > threshold
)
or power_missing
or is_state('binary_sensor.downstairs_fridge_power_draw_lost', 'on')
}}
attributes:
appliance: "Downstairs Freezer"
issues: >-
{% set ns = namespace(items=[]) %}
{% set temperature_missing = not has_value('sensor.downstairs_freezer_temperature_x70ts_temperature') %}
{% set battery_missing = not has_value('sensor.downstairs_freezer_temperature_x70ts_battery') %}
{% set illuminance_missing = not has_value('sensor.downstairs_freezer_light_sensor_x61ls_illuminance') %}
{% set power_missing = not has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') %}
{% set percentile = states('sensor.downstairs_freezer_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [-5, percentile + 0.5] | min if percentile is not none else -5 %}
{% if temperature_missing %}
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
{% endif %}
{% if illuminance_missing %}
{% set ns.items = ns.items + ['Door monitor unavailable'] %}
{% endif %}
{% if not battery_missing and (states('sensor.downstairs_freezer_temperature_x70ts_battery') | float(-1)) <= 20 %}
{% set ns.items = ns.items + ['Low monitor battery'] %}
{% endif %}
{% if power_missing %}
{% set ns.items = ns.items + ['Shared power monitoring unavailable'] %}
{% elif is_state('binary_sensor.downstairs_fridge_power_draw_lost', 'on') %}
{% set ns.items = ns.items + ['Shared power lost - no power draw for 4 hours'] %}
{% endif %}
{% if is_state('binary_sensor.downstairs_freezer_door_open_too_long', 'on') %}
{% set ns.items = ns.items + ['Door open too long'] %}
{% elif not temperature_missing and is_state('binary_sensor.downstairs_freezer_temperature_recovery_grace', 'on') %}
{% set ns.items = ns.items + ['Temperature alert delayed - door recently open'] %}
{% elif not temperature_missing and (states('sensor.downstairs_freezer_temperature_x70ts_temperature') | float(0)) > threshold %}
{% if (states('sensor.downstairs_freezer_temperature_change_rate') | float(0)) >= 2 %}
{% set ns.items = ns.items + ['Warming rapidly - possible open door'] %}
{% else %}
{% set ns.items = ns.items + ['Temperature too high - possible loss of cooling'] %}
{% endif %}
{% endif %}
{{ ns.items }}
temperature: "{{ states('sensor.downstairs_freezer_temperature_x70ts_temperature') }}"
humidity: "{{ states('sensor.downstairs_freezer_temperature_x70ts_humidity') }}"
average_7_days: "{{ states('sensor.downstairs_freezer_temperature_average_7_days') }}"
alert_threshold: >-
{% set percentile = states('sensor.downstairs_freezer_temperature_95th_percentile_7_days') | float(none) %}
{{ [-5, percentile + 0.5] | min if percentile is not none else -5 }}
change_rate: "{{ states('sensor.downstairs_freezer_temperature_change_rate') }}"
battery: "{{ states('sensor.downstairs_freezer_temperature_x70ts_battery') }}"
power: "{{ states('sensor.downstairs_fridge_gpo_power_x68pm_power') }}"
door_open: "{{ is_state('binary_sensor.downstairs_freezer_door_open', 'on') }}"
illuminance: "{{ states('sensor.downstairs_freezer_light_sensor_x61ls_illuminance') }}"
- name: "Drinks Freezer Issue"
unique_id: drinks_freezer_issue
device_class: problem
delay_on: "00:01:00"
state: >-
{% set temperature_missing = not has_value('sensor.drinks_freezer_environment_lcd_btt02_temperature') %}
{% set battery_missing = not has_value('sensor.drinks_freezer_environment_lcd_btt02_battery') %}
{% set power_missing = not has_value('sensor.drinks_fridge_power_x59pm_power') %}
{% set percentile = states('sensor.drinks_freezer_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [-5, percentile + 0.5] | min if percentile is not none else -5 %}
{{
temperature_missing
or (states('sensor.drinks_freezer_environment_lcd_btt02_battery') | float(-1)) <= 20
or states('switch.drinks_fridge_power_x59pm') != 'on'
or power_missing
or is_state('binary_sensor.drinks_fridge_power_draw_lost', 'on')
or (not temperature_missing and (states('sensor.drinks_freezer_environment_lcd_btt02_temperature') | float(0)) > threshold)
}}
attributes:
appliance: "Drinks Freezer"
issues: >-
{% set ns = namespace(items=[]) %}
{% set temperature_missing = not has_value('sensor.drinks_freezer_environment_lcd_btt02_temperature') %}
{% set battery_missing = not has_value('sensor.drinks_freezer_environment_lcd_btt02_battery') %}
{% set power_missing = not has_value('sensor.drinks_fridge_power_x59pm_power') %}
{% set percentile = states('sensor.drinks_freezer_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [-5, percentile + 0.5] | min if percentile is not none else -5 %}
{% if temperature_missing %}
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
{% endif %}
{% if not battery_missing and (states('sensor.drinks_freezer_environment_lcd_btt02_battery') | float(-1)) <= 20 %}
{% set ns.items = ns.items + ['Low monitor battery'] %}
{% endif %}
{% if states('switch.drinks_fridge_power_x59pm') in ['unknown', 'unavailable'] or power_missing %}
{% set ns.items = ns.items + ['Power monitoring unavailable'] %}
{% elif not is_state('switch.drinks_fridge_power_x59pm', 'on') %}
{% set ns.items = ns.items + ['Power switched off'] %}
{% elif is_state('binary_sensor.drinks_fridge_power_draw_lost', 'on') %}
{% set ns.items = ns.items + ['Power lost - no power draw for 4 hours'] %}
{% endif %}
{% if not temperature_missing and (states('sensor.drinks_freezer_environment_lcd_btt02_temperature') | float(0)) > threshold %}
{% if (states('sensor.drinks_freezer_temperature_change_rate') | float(0)) >= 2 %}
{% set ns.items = ns.items + ['Warming rapidly - possible open door'] %}
{% else %}
{% set ns.items = ns.items + ['Temperature too high - possible loss of cooling'] %}
{% endif %}
{% endif %}
{{ ns.items }}
temperature: "{{ states('sensor.drinks_freezer_environment_lcd_btt02_temperature') }}"
average_7_days: "{{ states('sensor.drinks_freezer_temperature_average_7_days') }}"
alert_threshold: >-
{% set percentile = states('sensor.drinks_freezer_temperature_95th_percentile_7_days') | float(none) %}
{{ [-5, percentile + 0.5] | min if percentile is not none else -5 }}
change_rate: "{{ states('sensor.drinks_freezer_temperature_change_rate') }}"
battery: "{{ states('sensor.drinks_freezer_environment_lcd_btt02_battery') }}"
power: "{{ states('sensor.drinks_fridge_power_x59pm_power') }}"
- name: "Vertical Freezer Issue"
unique_id: vertical_freezer_issue
device_class: problem
delay_on: "00:01:00"
state: >-
{% set temperature_missing = not has_value('sensor.lcd_temp_humidity_btt03_temperature') %}
{% set battery_missing = not has_value('sensor.lcd_temp_humidity_btt03_battery') %}
{% set power_missing = not has_value('sensor.vertical_freezer_power_x60pm_power') %}
{% set percentile = states('sensor.vertical_freezer_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [-10, percentile + 6] | min if percentile is not none else -10 %}
{{
temperature_missing
or (states('sensor.lcd_temp_humidity_btt03_battery') | float(-1)) <= 20
or states('switch.vertical_freezer_power_x60pm') != 'on'
or power_missing
or is_state('binary_sensor.vertical_freezer_power_draw_lost', 'on')
or (not temperature_missing and (states('sensor.lcd_temp_humidity_btt03_temperature') | float(0)) > threshold)
}}
attributes:
appliance: "Vertical Freezer"
issues: >-
{% set ns = namespace(items=[]) %}
{% set temperature_missing = not has_value('sensor.lcd_temp_humidity_btt03_temperature') %}
{% set battery_missing = not has_value('sensor.lcd_temp_humidity_btt03_battery') %}
{% set power_missing = not has_value('sensor.vertical_freezer_power_x60pm_power') %}
{% set percentile = states('sensor.vertical_freezer_temperature_95th_percentile_7_days') | float(none) %}
{% set threshold = [-10, percentile + 6] | min if percentile is not none else -10 %}
{% if temperature_missing %}
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
{% endif %}
{% if not battery_missing and (states('sensor.lcd_temp_humidity_btt03_battery') | float(-1)) <= 20 %}
{% set ns.items = ns.items + ['Low monitor battery'] %}
{% endif %}
{% if states('switch.vertical_freezer_power_x60pm') in ['unknown', 'unavailable'] or power_missing %}
{% set ns.items = ns.items + ['Power monitoring unavailable'] %}
{% elif not is_state('switch.vertical_freezer_power_x60pm', 'on') %}
{% set ns.items = ns.items + ['Power switched off'] %}
{% elif is_state('binary_sensor.vertical_freezer_power_draw_lost', 'on') %}
{% set ns.items = ns.items + ['Power lost - no power draw for 4 hours'] %}
{% endif %}
{% if not temperature_missing and (states('sensor.lcd_temp_humidity_btt03_temperature') | float(0)) > threshold %}
{% if (states('sensor.vertical_freezer_temperature_change_rate') | float(0)) >= 2 %}
{% set ns.items = ns.items + ['Warming rapidly - possible open door'] %}
{% else %}
{% set ns.items = ns.items + ['Temperature too high - possible loss of cooling'] %}
{% endif %}
{% endif %}
{{ ns.items }}
temperature: "{{ states('sensor.lcd_temp_humidity_btt03_temperature') }}"
average_7_days: "{{ states('sensor.vertical_freezer_temperature_average_7_days') }}"
alert_threshold: >-
{% set percentile = states('sensor.vertical_freezer_temperature_95th_percentile_7_days') | float(none) %}
{{ [-10, percentile + 6] | min if percentile is not none else -10 }}
change_rate: "{{ states('sensor.vertical_freezer_temperature_change_rate') }}"
battery: "{{ states('sensor.lcd_temp_humidity_btt03_battery') }}"
power: "{{ states('sensor.vertical_freezer_power_x60pm_power') }}"
#:######################################################################################:#
# SUMMARY STATUS
#:######################################################################################:#
- sensor:
- name: "Fridge Freezer Monitor Status"
unique_id: fridge_freezer_monitor_status
icon: mdi:fridge-alert-outline
state: >-
{{
'Issue'
if is_state('binary_sensor.main_kitchen_fridge_door_open_too_long', 'on')
or is_state('binary_sensor.drinks_fridge_door_open_too_long', 'on')
or is_state('binary_sensor.downstairs_fridge_door_open_too_long', 'on')
or is_state('binary_sensor.downstairs_freezer_door_open_too_long', 'on')
else 'Open'
if is_state('binary_sensor.main_kitchen_fridge_door_open', 'on')
or is_state('binary_sensor.drinks_fridge_door_open', 'on')
or is_state('binary_sensor.downstairs_fridge_door_open', 'on')
or is_state('binary_sensor.downstairs_freezer_door_open', 'on')
else 'Issue'
if expand(
'binary_sensor.main_kitchen_fridge_issue',
'binary_sensor.drinks_fridge_issue',
'binary_sensor.downstairs_fridge_issue',
'binary_sensor.downstairs_freezer_issue',
'binary_sensor.wine_fridge_issue',
'binary_sensor.drinks_freezer_issue',
'binary_sensor.vertical_freezer_issue'
)
| selectattr('state', 'eq', 'on')
| list
| count > 0
else 'OK'
}}
attributes:
issue_count: >-
{{
expand(
'binary_sensor.main_kitchen_fridge_issue',
'binary_sensor.drinks_fridge_issue',
'binary_sensor.downstairs_fridge_issue',
'binary_sensor.downstairs_freezer_issue',
'binary_sensor.wine_fridge_issue',
'binary_sensor.drinks_freezer_issue',
'binary_sensor.vertical_freezer_issue'
)
| selectattr('state', 'eq', 'on')
| list
| count
}}
open_count: >-
{{
[
is_state('binary_sensor.main_kitchen_fridge_door_open', 'on'),
is_state('binary_sensor.drinks_fridge_door_open', 'on'),
is_state('binary_sensor.downstairs_fridge_door_open', 'on'),
is_state('binary_sensor.downstairs_freezer_door_open', 'on')
]
| select
| list
| count
}}
issues: >-
{% set ns = namespace(items=[]) %}
{% set monitors = [
'binary_sensor.main_kitchen_fridge_issue',
'binary_sensor.drinks_fridge_issue',
'binary_sensor.downstairs_fridge_issue',
'binary_sensor.downstairs_freezer_issue',
'binary_sensor.wine_fridge_issue',
'binary_sensor.drinks_freezer_issue',
'binary_sensor.vertical_freezer_issue'
] %}
{% for monitor in monitors if is_state(monitor, 'on') %}
{% set appliance = state_attr(monitor, 'appliance') or state_attr(monitor, 'friendly_name') %}
{% set reasons = state_attr(monitor, 'issues') or ['Issue detected'] %}
{% for reason in reasons %}
{% set ns.items = ns.items + [appliance ~ ': ' ~ reason] %}
{% endfor %}
{% endfor %}
{{ ns.items }}