Coverage for custom_components/appliance_autonotify/const.py: 100%
73 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-10-12 15:40 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-10-12 15:40 +0000
1"""Constants for Appliance Auto Notify"""
3from typing import Final
5DOMAIN: Final[str] = "appliance_autonotify"
6SUPERNOTIFY_DOMAIN: Final[str] = "supernotify"
8CONF_START_TITLE: Final[str] = "start_title"
9CONF_START_MESSAGE: Final[str] = "start_message"
10CONF_END_TITLE: Final[str] = "end_title"
11CONF_END_MESSAGE: Final[str] = "end_message"
12# notify entities, used only without Supernotify
13CONF_TARGETS: Final[str] = "targets"
14# as the `target` and `custom_target` of supernotify.notify
15CONF_TARGET: Final[str] = "target"
16CONF_CUSTOM_TARGET: Final[str] = "custom_target"
17CONF_DELIVERIES: Final[str] = "deliveries"
18# whether progress is told with ordinary notifications, the Live Activity is kept up to date regardless
19CONF_NOTIFY_PROGRESS: Final[str] = "notify_progress"
20# whether the start and the end are told with ordinary notifications, the Live Activity is opened and closed regardless
21CONF_NOTIFY_START: Final[str] = "notify_start"
22CONF_NOTIFY_END: Final[str] = "notify_end"
23# whether the end of a phase, such as an oven getting up to heat, is told with an ordinary notification
24CONF_NOTIFY_PHASE: Final[str] = "notify_phase"
25# path of the dashboard opened by a tap on a notification, the app is opened where it was last if there's none
26CONF_DASHBOARD: Final[str] = "dashboard"
27LOVELACE_DOMAIN: Final[str] = "lovelace"
28# the dashboard Home Assistant starts with has no path of its own in the list of them
29DEFAULT_DASHBOARD: Final[str] = "lovelace"
30DEFAULT_DASHBOARD_TITLE: Final[str] = "Overview"
31# the one entry that isn't an appliance, holding whether appliances found are set up without asking
32TYPE_DISCOVERY: Final[str] = "discovery"
33CONF_AUTO_DISCOVER: Final[str] = "auto_discover"
34# an appliance with no integration of its own, known only by the power it draws
35TYPE_POWER: Final[str] = "power"
36CONF_POWER_ENTITY: Final[str] = "power_entity"
37CONF_THRESHOLD: Final[str] = "threshold"
38CONF_GRACE_PERIOD: Final[str] = "grace_period"
39CONF_MIN_DURATION: Final[str] = "min_duration"
40# watts above which the appliance is running
41DEFAULT_THRESHOLD: Final[float] = 1
42# seconds at or below the threshold before the cycle is over, so short drop outs are ignored
43DEFAULT_GRACE_PERIOD: Final[float] = 60
44# seconds above the threshold before it counts as a cycle, so a door opened or a button pressed isn't one
45DEFAULT_MIN_DURATION: Final[float] = 0
47# English only for the MVP
48DISCOVERY_TITLE: Final[str] = "Automatic discovery"
49NAME_PLACEHOLDER: Final[str] = "{name}"
50DEFAULT_TITLE: Final[str] = "{name}"
51DEFAULT_START_MESSAGE: Final[str] = "{name} started"
52DEFAULT_END_MESSAGE: Final[str] = "{name} is finished"
53PROGRESS_MESSAGE: Final[str] = "{progress}% complete"
54# the text of the Android status bar chip, which shows it in full only up to about 7 characters
55PROGRESS_CHIP: Final[str] = "{progress}%"
56PREHEAT_PHASE: Final[str] = "Pre-heating"
57FAST_PREHEAT_PHASE: Final[str] = "Fast pre-heat"
58PREHEAT_MESSAGE: Final[str] = "{phase}, {current} of {target}{unit}"
59PREHEATED_MESSAGE: Final[str] = "{name} is pre-heated"
60# what an oven up to heat is doing, and how hot it is
61OVEN_MESSAGE: Final[str] = "{program}, {current}{unit}"
62SUPERNOTIFY_PRESENT: Final[str] = "Supernotify is installed, so mobile apps will show a Live Activity for each cycle."
63SUPERNOTIFY_MISSING: Final[str] = (
64 "**Supernotify is not installed.** Only a plain start and end notification can be sent, to every phone with the "
65 "Home Assistant app, with no Live Activity. Install Supernotify from HACS for the full experience."
66)
68# translation key, per vendor platform, of the entity whose state follows the appliance cycle
69CYCLE_KEYS: Final[dict[str, str]] = {"home_connect": "operation_state"}
70PROGRESS_KEY: Final[str] = "program_progress"
71FINISH_TIME_KEY: Final[str] = "program_finish_time"
72# selects, unlike the others, of the program under way, and of the one chosen, which is all an oven reports
73PROGRAM_KEYS: Final[tuple[str, ...]] = ("active_program", "selected_program")
74# an oven warming up has no progress of its own, only how hot it is and how hot it's to be
75TARGET_TEMPERATURE_KEY: Final[str] = "setpoint_temperature"
76CAVITY_TEMPERATURE_KEY: Final[str] = "oven_current_cavity_temperature"
77PREHEAT_FINISHED_KEYS: Final[tuple[str, ...]] = ("preheat_finished", "regular_preheat_finished")
78FAST_PREHEAT_KEY: Final[str] = "fast_pre_heat"
79# domain, by translation key, of each entity of an appliance that's made use of
80ENTITY_DOMAINS: Final[dict[str, str]] = {
81 PROGRESS_KEY: "sensor",
82 FINISH_TIME_KEY: "sensor",
83 **dict.fromkeys(PROGRAM_KEYS, "select"),
84 TARGET_TEMPERATURE_KEY: "number",
85 CAVITY_TEMPERATURE_KEY: "sensor",
86 **dict.fromkeys(PREHEAT_FINISHED_KEYS, "sensor"),
87 FAST_PREHEAT_KEY: "switch",
88}
89# degrees between Live Activity updates of an oven up to heat, whose temperature never stops wandering
90TEMPERATURE_STEP: Final[float] = 5
91# seconds before an oven saying it's up to heat is believed, since one switched off says so too, just before it's off
92PREHEAT_SETTLE: Final[float] = 3
93# an event sensor is `off` until whatever it tells of has happened
94STATES_EVENT_ON: Final[tuple[str, ...]] = ("present", "confirmed", "on")
96STATE_RUN: Final[str] = "run"
97# a cycle already under way, so not a new start when `run` follows
98STATES_ACTIVE: Final[tuple[str, ...]] = ("run", "pause", "actionrequired")
99# the cycle is over, an oven switched off goes straight from `run` to `inactive` without ever being `finished`
100STATES_FINISHED: Final[tuple[str, ...]] = ("finished", "inactive")
101# over too unless `run` soon follows, an oven being `ready` for a moment as it starts or has its settings changed
102STATES_SETTLING: Final[tuple[str, ...]] = ("ready",)
103# seconds an appliance is left to settle before the cycle is over
104CYCLE_SETTLE: Final[float] = 10
105# the cycle is over without finishing, so the Live Activity goes without an end notification
106STATES_ABANDONED: Final[tuple[str, ...]] = ("error", "aborting")
108# percentage points between Live Activity updates, since mobile platforms throttle frequent ones
109PROGRESS_STEP: Final[int] = 10
110# from here on the end is in sight and the bar is being watched, so it's kept closer to the appliance
111PROGRESS_FINAL: Final[int] = 90
112PROGRESS_FINAL_STEP: Final[int] = 2
114MOBILE_PUSH_TRANSPORT: Final[str] = "mobile_push"
115# Android notification channel of its own, made with sound on the first notification, since a Live Update in the
116# app's default channel arrives without a sound
117ANDROID_CHANNEL: Final[str] = "Appliances"
118# platform of the notify entities used when there's no Supernotify and none have been chosen
119MOBILE_APP_PLATFORM: Final[str] = "mobile_app"
121DEFAULT_ICON: Final[str] = "mdi:progress-clock"
122TYPE_OVEN: Final[str] = "oven"
123# the type of a Home Connect appliance, by how its programs are named
124APPLIANCE_TYPES: Final[dict[str, str]] = {
125 "dishcare_dishwasher_program_": "dishwasher",
126 "laundry_care_washer_program_": "washer",
127 "laundry_care_washer_dryer_program_": "washer_dryer",
128 "laundry_care_dryer_program_": "dryer",
129 "cooking_oven_program_": TYPE_OVEN,
130 "cooking_hob_program_": "hob",
131 "cooking_common_program_hood_": "hood",
132 "consumer_products_coffee_maker_program_": "coffee_maker",
133 "consumer_products_cleaning_robot_program_": "cleaning_robot",
134 "heating_ventilation_air_conditioning_air_conditioner_program_": "air_conditioner",
135}
136TYPE_ICONS: Final[dict[str, str]] = {
137 "dishwasher": "mdi:dishwasher",
138 "washer": "mdi:washing-machine",
139 "washer_dryer": "mdi:washing-machine",
140 "dryer": "mdi:tumble-dryer",
141 TYPE_OVEN: "mdi:stove",
142 "hob": "mdi:pot-steam",
143 "hood": "mdi:fan",
144 "coffee_maker": "mdi:coffee-maker",
145 "cleaning_robot": "mdi:robot-vacuum",
146 "air_conditioner": "mdi:air-conditioner",
147}
148# the types whose phases are worth a notification unless it's turned off, an oven up to heat being waited
149# for where a dishwasher starting to rinse isn't
150PHASES_NOTIFIED: Final[tuple[str, ...]] = (TYPE_OVEN,)
151# matched against the device name where the type isn't known, first hit wins
152ICONS: Final[dict[str, str]] = {
153 "dishwasher": "mdi:dishwasher",
154 # Italian names
155 "lavastoviglie": "mdi:dishwasher",
156 "lavasciuga": "mdi:washing-machine",
157 "lavatrice": "mdi:washing-machine",
158 "asciugatrice": "mdi:tumble-dryer",
159 "microonde": "mdi:microwave",
160 "forno": "mdi:stove",
161 "caffè": "mdi:coffee-maker",
162 "caffe": "mdi:coffee-maker",
163 "cappa": "mdi:fan",
164 "piano cottura": "mdi:pot-steam",
165 "aspirapolvere": "mdi:robot-vacuum",
166 "bollitore": "mdi:kettle",
167 "dryer": "mdi:tumble-dryer",
168 "wash": "mdi:washing-machine",
169 "oven": "mdi:stove",
170 "microwave": "mdi:microwave",
171 "coffee": "mdi:coffee-maker",
172 "hood": "mdi:fan",
173 "hob": "mdi:pot-steam",
174 "vacuum": "mdi:robot-vacuum",
175 "kettle": "mdi:kettle",
176}