257 lines
12 KiB
Python
257 lines
12 KiB
Python
"""Air treatment — purifiers, ACs and HRV/ventilation filters.
|
|
|
|
Data module of the suggested-setups signature catalog — see
|
|
``helpers/signatures/_model.py`` for the direction semantics and the
|
|
method contract (every entry cites and is verified against the
|
|
integration's source; drift-probed weekly)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from ._model import ConsumableSignature, IntegrationSignature
|
|
|
|
SIGNATURES: dict[str, IntegrationSignature] = {
|
|
"hass_dyson": IntegrationSignature(
|
|
name="Dyson",
|
|
verified="2026-07-18 @ cmgrayb/hass-dyson main",
|
|
source=(
|
|
"cmgrayb/hass-dyson sensor.py DysonFilterLifeSensor "
|
|
"(translation_key 'filter_life' for BOTH hepa and carbon "
|
|
"instances, PERCENTAGE) — one any-low task covers both filters."
|
|
),
|
|
tasks=(ConsumableSignature(("filter_life",), "Replace Filter", "percent_left"),),
|
|
),
|
|
"dreo": IntegrationSignature(
|
|
name="Dreo",
|
|
verified="2026-07-18 @ JeffSteinbok/hass-dreo main",
|
|
source=(
|
|
"JeffSteinbok/hass-dreo sensor.py (translation_key 'filter_life', unit '%', humidifiers with FILTERTIME support)."
|
|
),
|
|
tasks=(ConsumableSignature(("filter_life",), "Replace Filter", "percent_left"),),
|
|
),
|
|
"vesync": IntegrationSignature(
|
|
name="VeSync (Levoit)",
|
|
verified="2026-07-19 @ core/dev vesync/sensor.py",
|
|
source="core vesync: tk 'filter_life', PERCENTAGE, MEASUREMENT (Levoit purifiers).",
|
|
tasks=(ConsumableSignature(("filter_life",), "Replace Filter", "percent_left"),),
|
|
),
|
|
"daikin": IntegrationSignature(
|
|
name="Daikin AC",
|
|
verified="2026-07-18 @ home-assistant/core dev",
|
|
source=(
|
|
"home-assistant/core homeassistant/components/daikin/climate.py "
|
|
"(climate platform verified present; AC-only integration, so the "
|
|
"climate entity IS an air conditioner). Runtime on the hvac_action "
|
|
"ATTRIBUTE — the state only reports the standby mode. Interval per Daikin's official guidance (clean filters every 2 weeks; ≈100 runtime-hours at typical in-season use)."
|
|
),
|
|
tasks=(
|
|
ConsumableSignature(
|
|
(),
|
|
"Filter Cleaning",
|
|
"runtime_hours",
|
|
delta_units=100,
|
|
entity_domain="climate",
|
|
attribute="hvac_action",
|
|
on_states=("cooling", "heating", "fan", "drying"),
|
|
),
|
|
),
|
|
),
|
|
"gree": IntegrationSignature(
|
|
name="Gree AC",
|
|
verified="2026-07-18 @ home-assistant/core dev",
|
|
source=(
|
|
"home-assistant/core homeassistant/components/gree/climate.py "
|
|
"(climate platform verified present; AC-only integration, so the "
|
|
"climate entity IS an air conditioner). Runtime on the hvac_action "
|
|
"ATTRIBUTE — the state only reports the standby mode. Interval per Daikin's official guidance (clean filters every 2 weeks; ≈100 runtime-hours at typical in-season use)."
|
|
),
|
|
tasks=(
|
|
ConsumableSignature(
|
|
(),
|
|
"Filter Cleaning",
|
|
"runtime_hours",
|
|
delta_units=100,
|
|
entity_domain="climate",
|
|
attribute="hvac_action",
|
|
on_states=("cooling", "heating", "fan", "drying"),
|
|
),
|
|
),
|
|
),
|
|
"comfoconnect": IntegrationSignature(
|
|
name="Zehnder ComfoAirQ",
|
|
verified="2026-07-19 @ core/dev comfoconnect/sensor.py",
|
|
source=("core comfoconnect: key 'days_to_replace_filter', UnitOfTime.DAYS (name-style, no tk → suffix match)."),
|
|
tasks=(
|
|
# 168 canonical hours = warn at 7 days remaining (unit 'd' → ÷24).
|
|
ConsumableSignature(("days_to_replace_filter",), "Replace Ventilation Filter", "duration_left", below_hours=168),
|
|
),
|
|
),
|
|
"renson": IntegrationSignature(
|
|
name="Renson Endura Delta",
|
|
verified="2026-07-19 @ core/dev renson/sensor.py",
|
|
source="core renson: tk 'filter_change', DURATION, DAYS, MEASUREMENT.",
|
|
tasks=(ConsumableSignature(("filter_change",), "Replace Ventilation Filter", "duration_left", below_hours=168),),
|
|
),
|
|
"philips_airpurifier_coap": IntegrationSignature(
|
|
name="Philips AirPurifier (CoAP)",
|
|
verified="2026-07-19 @ kongo09/philips-airpurifier-coap master sensor.py+const.py",
|
|
source=(
|
|
"HACS philips-airpurifier-coap: PhilipsFilterSensor reports "
|
|
"PERCENT when the filter total is known, else HOURS remaining — "
|
|
"the LG dual-unit pattern, split per direction. tks: pre_filter "
|
|
"(cleaning cycle), hepa_filter / active_carbon_filter / "
|
|
"nanoprotect_filter (replacements), wick (humidifier "
|
|
"evaporation wick)."
|
|
),
|
|
tasks=(
|
|
ConsumableSignature(("pre_filter",), "Filter Cleaning", "percent_left"),
|
|
ConsumableSignature(("pre_filter",), "Filter Cleaning", "duration_left", below_hours=72),
|
|
ConsumableSignature(
|
|
("hepa_filter", "active_carbon_filter", "nanoprotect_filter"),
|
|
"Replace Filter",
|
|
"percent_left",
|
|
),
|
|
ConsumableSignature(
|
|
("hepa_filter", "active_carbon_filter", "nanoprotect_filter"),
|
|
"Replace Filter",
|
|
"duration_left",
|
|
below_hours=72,
|
|
),
|
|
# Humidifier models: the evaporation wick (tk 'wick'), same
|
|
# dual-unit shape as the filters.
|
|
ConsumableSignature(("wick",), "Replace Wick", "percent_left"),
|
|
ConsumableSignature(("wick",), "Replace Wick", "duration_left", below_hours=72),
|
|
),
|
|
),
|
|
"dirigera_platform": IntegrationSignature(
|
|
name="IKEA DIRIGERA (STARKVIND)",
|
|
verified="2026-07-19 @ sanjoyg/dirigera_platform main sensor.py",
|
|
source=(
|
|
"HACS dirigera_platform: STARKVIND 'Filter Elapsed Time' sensor "
|
|
"(suffix filter_elapsed_time, MINUTES, DURATION) counts UP and "
|
|
"resets on IKEA's filter-change reset -> usage_above at 4,320 h "
|
|
"(= IKEA's 259,200-minute filter lifetime). The sibling "
|
|
"'Filter Lifetime' sensor is the constant total — unusable."
|
|
),
|
|
tasks=(ConsumableSignature(("filter_elapsed_time",), "Replace Filter", "usage_above", above_hours=4320),),
|
|
),
|
|
"ha_blueair": IntegrationSignature(
|
|
name="Blueair",
|
|
verified="2026-07-19 @ dahlb/ha_blueair master sensor.py (HACS default)",
|
|
source=(
|
|
"HACS ha_blueair: name-derived 'Filter Life' / 'Wick Life' / "
|
|
"'Water Refresher Life' (PERCENTAGE). Verified % REMAINING: the "
|
|
"device-aws coordinator returns 100 - filter_usage_percentage. "
|
|
"A filter_expired problem binary also exists (adoption path)."
|
|
),
|
|
tasks=(
|
|
ConsumableSignature(("filter_life",), "Replace Filter", "percent_left"),
|
|
ConsumableSignature(("wick_life",), "Replace Wick", "percent_left"),
|
|
ConsumableSignature(("water_refresher_life",), "Replace Water Refresher", "percent_left"),
|
|
),
|
|
),
|
|
"coway": IntegrationSignature(
|
|
name="Coway IoCare",
|
|
verified="2026-07-19 @ robertd502/home-assistant-iocare main sensor.py (HACS default)",
|
|
source=(
|
|
"HACS coway: name-derived entities, % remaining — 'Pre filter' "
|
|
"(AIRMEGA odor variant: 'Charcoal filter') and 'MAX2 filter' "
|
|
"(AP-1512HHS EU/UK models: 'HEPA filter'); both name variants "
|
|
"listed as keys."
|
|
),
|
|
tasks=(
|
|
ConsumableSignature(("pre_filter", "charcoal_filter"), "Filter Cleaning", "percent_left"),
|
|
ConsumableSignature(("max2_filter", "hepa_filter"), "Replace Filter", "percent_left"),
|
|
),
|
|
),
|
|
"winix": IntegrationSignature(
|
|
name="Winix",
|
|
verified="2026-07-19 @ iprak/winix master sensor.py (HACS default)",
|
|
source=(
|
|
"HACS winix: tk 'filter_life' (PERCENTAGE) — % remaining derived "
|
|
"device-side from filter hours vs the model's "
|
|
"filter_alarm_duration."
|
|
),
|
|
tasks=(ConsumableSignature(("filter_life",), "Replace Filter", "percent_left"),),
|
|
),
|
|
"duco": IntegrationSignature(
|
|
name="Duco ventilation",
|
|
verified="2026-07-20 @ home-assistant/core dev",
|
|
source=("core duco: tk 'filter_remaining' (DURATION, DAYS) — the box's own filter countdown."),
|
|
tasks=(ConsumableSignature(("filter_remaining",), "Replace Ventilation Filter", "duration_left", below_hours=168),),
|
|
),
|
|
"flexit_bacnet": IntegrationSignature(
|
|
name="Flexit Nordic",
|
|
verified="2026-07-20 @ home-assistant/core dev",
|
|
source=(
|
|
"core flexit_bacnet: tk 'air_filter_operating_time' "
|
|
"(TOTAL_INCREASING, HOURS — counts UP, reset on filter change) → "
|
|
"usage_above at 4380 h (Flexit: change the filter every 6-12 "
|
|
"months). An 'air_filter_polluted' problem binary also exists "
|
|
"(adoption path)."
|
|
),
|
|
tasks=(
|
|
ConsumableSignature(
|
|
("air_filter_operating_time",),
|
|
"Replace Ventilation Filter",
|
|
"usage_above",
|
|
above_hours=4380,
|
|
),
|
|
),
|
|
),
|
|
"tradfri": IntegrationSignature(
|
|
name="IKEA Trådfri (STARKVIND)",
|
|
verified="2026-07-20 @ home-assistant/core dev",
|
|
source=(
|
|
"core tradfri: tk 'filter_life_remaining' (MEASUREMENT, HOURS "
|
|
"remaining) — STARKVIND purifiers on the NATIVE IKEA gateway "
|
|
"(the DIRIGERA path is covered separately)."
|
|
),
|
|
tasks=(ConsumableSignature(("filter_life_remaining",), "Replace Filter", "duration_left", below_hours=72),),
|
|
),
|
|
"dyson_local": IntegrationSignature(
|
|
name="Dyson (local)",
|
|
verified="2026-07-20 @ libdyson-wg/ha-dyson main sensor.py (HACS default)",
|
|
source=(
|
|
"HACS dyson_local (libdyson-wg — the maintained fork): "
|
|
"name-derived 'Filter Life' (HOURS remaining) and 'Filter Life "
|
|
"Percentage' / 'Carbon Filter Life' / 'HEPA Filter Life' / "
|
|
"'Combined Filter Life' (PERCENTAGE, value/4300 h budget). The "
|
|
"percent suffixes end in _filter_life too — the unit-aware "
|
|
"matcher routes each entity to the right direction (the "
|
|
"lg_thinq dual-unit pattern)."
|
|
),
|
|
tasks=(
|
|
# The Pure Cool "combined" sensor is NAMED plain 'Filter Life'
|
|
# (suffix _filter_life) but reports PERCENT, while older models'
|
|
# 'Filter Life' reports HOURS — the same suffix appears in BOTH
|
|
# key tuples and the unit check routes each entity.
|
|
ConsumableSignature(
|
|
(
|
|
"filter_life_percentage",
|
|
"carbon_filter_life",
|
|
"hepa_filter_life",
|
|
"filter_life",
|
|
),
|
|
"Replace Filter",
|
|
"percent_left",
|
|
),
|
|
ConsumableSignature(("filter_life",), "Replace Filter", "duration_left", below_hours=72),
|
|
),
|
|
),
|
|
"venstar": IntegrationSignature(
|
|
name="Venstar thermostat",
|
|
verified="2026-07-20 @ home-assistant/core dev",
|
|
source=(
|
|
"core venstar CONSUMABLE_ENTITIES: key 'filterHours' carries tk "
|
|
"'filter_install_time' (HOURS of filter RUNTIME, counts UP, "
|
|
"user-reset on change) — 300 h ≈ the typical 1-3-month "
|
|
"furnace-filter guidance. The sibling 'filterDays'/tk "
|
|
"'filter_usage' (CALENDAR days since install) ships alongside it "
|
|
"and is skipped: same duty, weaker wear proxy, and two "
|
|
"same-direction signatures of one task name would collide in "
|
|
"discovery's per-device dedupe."
|
|
),
|
|
tasks=(ConsumableSignature(("filter_install_time",), "Replace Filter", "usage_above", above_hours=300),),
|
|
),
|
|
}
|