Coverage for custom_components/appliance_autonotify/const.py: 100%
89 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-14 15:14 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-14 15:14 +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# whether the program goes beside the name in the title of a Live Activity with a timer, for those short enough to fit
26CONF_PROGRAM_IN_TITLE: Final[str] = "program_in_title"
27# path of the dashboard opened by a tap on a notification, the app is opened where it was last if there's none
28CONF_DASHBOARD: Final[str] = "dashboard"
29LOVELACE_DOMAIN: Final[str] = "lovelace"
30# the dashboard Home Assistant starts with has no path of its own in the list of them
31DEFAULT_DASHBOARD: Final[str] = "lovelace"
32DEFAULT_DASHBOARD_TITLE: Final[str] = "Overview"
33# the one entry that isn't an appliance, holding whether appliances found are set up without asking
34TYPE_DISCOVERY: Final[str] = "discovery"
35CONF_AUTO_DISCOVER: Final[str] = "auto_discover"
36# an appliance with no integration of its own, known only by the power it draws
37TYPE_POWER: Final[str] = "power"
38CONF_POWER_ENTITY: Final[str] = "power_entity"
39CONF_THRESHOLD: Final[str] = "threshold"
40CONF_GRACE_PERIOD: Final[str] = "grace_period"
41CONF_MIN_DURATION: Final[str] = "min_duration"
42# the smart plug the appliance is on, offered as a button to switch off once it has finished
43CONF_SWITCH_ENTITY: Final[str] = "switch_entity"
44# whether that button is offered, for a plug chosen but better left on
45CONF_SWITCH_OFF_BUTTON: Final[str] = "switch_off_button"
46# watts above which the appliance is running
47DEFAULT_THRESHOLD: Final[float] = 1
48# seconds at or below the threshold before the cycle is over, so short drop outs are ignored
49DEFAULT_GRACE_PERIOD: Final[float] = 60
50# seconds above the threshold before it counts as a cycle, so a door opened or a button pressed isn't one
51DEFAULT_MIN_DURATION: Final[float] = 0
53# English only for the MVP
54DISCOVERY_TITLE: Final[str] = "Automatic discovery"
55NAME_PLACEHOLDER: Final[str] = "{name}"
56# the program under way, as Home Assistant shows it, and nothing at all for an appliance that reports none
57PROGRAM_PLACEHOLDER: Final[str] = "{program}"
58DEFAULT_TITLE: Final[str] = "{name}"
59DEFAULT_START_MESSAGE: Final[str] = "{name} started"
60DEFAULT_END_MESSAGE: Final[str] = "{name} is finished"
61PROGRESS_MESSAGE: Final[str] = "{progress}% complete"
63# minutes after which the end is told again, for as long as nobody says the appliance has been seen to
64CONF_REMINDER: Final[str] = "reminder"
65# how many times it's told again
66CONF_REMINDER_REPEATS: Final[str] = "reminder_repeats"
67DEFAULT_REMINDER_REPEATS: Final[int] = 3
68# minutes for Remind Later, when no reminder is set
69DEFAULT_SNOOZE: Final[int] = 30
70# buttons on the end notification, each followed by the entry id of the appliance
71ACTION_FINISHED: Final[str] = "APPLIANCE_FINISHED_"
72ACTION_REMIND: Final[str] = "APPLIANCE_REMIND_"
73ACTION_SWITCH_OFF: Final[str] = "APPLIANCE_SWITCH_OFF_"
74# by the language of Home Assistant, English for any other
75ACTION_TITLES: Final[dict[str, dict[str, str]]] = {
76 "en": {ACTION_FINISHED: "Finished", ACTION_REMIND: "Remind Later", ACTION_SWITCH_OFF: "Switch Off"},
77 "it": {ACTION_FINISHED: "Finito", ACTION_REMIND: "Ricordamelo dopo", ACTION_SWITCH_OFF: "Spegni presa"},
78}
79MOBILE_ACTION_EVENT: Final[str] = "mobile_app_notification_action"
80# the text of the Android status bar chip, which shows it in full only up to about 7 characters
81PROGRESS_CHIP: Final[str] = "{progress}%"
82PREHEAT_PHASE: Final[str] = "Pre-heating"
83FAST_PREHEAT_PHASE: Final[str] = "Fast pre-heat"
84PREHEAT_MESSAGE: Final[str] = "{phase}, {current} of {target}{unit}"
85PREHEATED_MESSAGE: Final[str] = "{name} is pre-heated"
86# the title of a Live Activity with a timer, which iOS shows on the Lock Screen in place of the message
87LIVE_TITLE: Final[str] = "{title} · {phase}"
88# what an oven up to heat is doing, and how hot it is
89OVEN_MESSAGE: Final[str] = "{program}, {current}{unit}"
90SUPERNOTIFY_PRESENT: Final[str] = "Supernotify is installed, so mobile apps will show a Live Activity for each cycle."
91SUPERNOTIFY_MISSING: Final[str] = (
92 "**Supernotify is not installed.** Only a plain start and end notification can be sent, to every phone with the "
93 "Home Assistant app, with no Live Activity. Install Supernotify from HACS for the full experience."
94)
96# translation key, per vendor platform, of the entity whose state follows the appliance cycle
97CYCLE_KEYS: Final[dict[str, str]] = {"home_connect": "operation_state"}
98PROGRESS_KEY: Final[str] = "program_progress"
99FINISH_TIME_KEY: Final[str] = "program_finish_time"
100# selects, unlike the others, of the program under way, and of the one chosen, which is all an oven reports
101PROGRAM_KEYS: Final[tuple[str, ...]] = ("active_program", "selected_program")
102# an oven warming up has no progress of its own, only how hot it is and how hot it's to be
103TARGET_TEMPERATURE_KEY: Final[str] = "setpoint_temperature"
104CAVITY_TEMPERATURE_KEY: Final[str] = "oven_current_cavity_temperature"
105PREHEAT_FINISHED_KEYS: Final[tuple[str, ...]] = ("preheat_finished", "regular_preheat_finished")
106FAST_PREHEAT_KEY: Final[str] = "fast_pre_heat"
107# domain, by translation key, of each entity of an appliance that's made use of
108ENTITY_DOMAINS: Final[dict[str, str]] = {
109 PROGRESS_KEY: "sensor",
110 FINISH_TIME_KEY: "sensor",
111 **dict.fromkeys(PROGRAM_KEYS, "select"),
112 TARGET_TEMPERATURE_KEY: "number",
113 CAVITY_TEMPERATURE_KEY: "sensor",
114 **dict.fromkeys(PREHEAT_FINISHED_KEYS, "sensor"),
115 FAST_PREHEAT_KEY: "switch",
116}
117# degrees between Live Activity updates of an oven up to heat, whose temperature never stops wandering
118TEMPERATURE_STEP: Final[float] = 5
119# seconds before an oven saying it's up to heat is believed, since one switched off says so too, just before it's off
120PREHEAT_SETTLE: Final[float] = 3
121# an event sensor is `off` until whatever it tells of has happened
122STATES_EVENT_ON: Final[tuple[str, ...]] = ("present", "confirmed", "on")
124STATE_RUN: Final[str] = "run"
125# a cycle already under way, so not a new start when `run` follows
126STATES_ACTIVE: Final[tuple[str, ...]] = ("run", "pause", "actionrequired")
127# the cycle is over, an oven switched off goes straight from `run` to `inactive` without ever being `finished`
128STATES_FINISHED: Final[tuple[str, ...]] = ("finished", "inactive")
129# over too unless `run` soon follows, an oven being `ready` for a moment as it starts or has its settings changed
130STATES_SETTLING: Final[tuple[str, ...]] = ("ready",)
131# seconds an appliance is left to settle before the cycle is over
132CYCLE_SETTLE: Final[float] = 10
133# seconds a Live Activity is left to open before anything more is sent to it, since a push sent straight after the
134# start can reach a phone ahead of it, and then be overwritten by the start, with no bar and no program
135LIVE_SETTLE: Final[float] = 5
136# the cycle is over without finishing, so the Live Activity goes without an end notification
137STATES_ABANDONED: Final[tuple[str, ...]] = ("error", "aborting")
139# percentage points between Live Activity updates, since mobile platforms throttle frequent ones
140PROGRESS_STEP: Final[int] = 5
141# percentage points between ordinary notifications of progress, where those are asked for
142PROGRESS_NOTIFY_STEP: Final[int] = 10
143# from here on the end is in sight and the bar is being watched, so it's kept closer to the appliance
144PROGRESS_FINAL: Final[int] = 90
145PROGRESS_FINAL_STEP: Final[int] = 2
147MOBILE_PUSH_TRANSPORT: Final[str] = "mobile_push"
148# Android notification channel of its own, made with sound on the first notification, since a Live Update in the
149# app's default channel arrives without a sound
150ANDROID_CHANNEL: Final[str] = "Appliances"
151# platform of the notify entities used when there's no Supernotify and none have been chosen
152MOBILE_APP_PLATFORM: Final[str] = "mobile_app"
154DEFAULT_ICON: Final[str] = "mdi:progress-clock"
155TYPE_OVEN: Final[str] = "oven"
156# the type of a Home Connect appliance, by how its programs are named
157APPLIANCE_TYPES: Final[dict[str, str]] = {
158 "dishcare_dishwasher_program_": "dishwasher",
159 "laundry_care_washer_program_": "washer",
160 "laundry_care_washer_dryer_program_": "washer_dryer",
161 "laundry_care_dryer_program_": "dryer",
162 "cooking_oven_program_": TYPE_OVEN,
163 "cooking_hob_program_": "hob",
164 "cooking_common_program_hood_": "hood",
165 "consumer_products_coffee_maker_program_": "coffee_maker",
166 "consumer_products_cleaning_robot_program_": "cleaning_robot",
167 "heating_ventilation_air_conditioning_air_conditioner_program_": "air_conditioner",
168}
169TYPE_ICONS: Final[dict[str, str]] = {
170 "dishwasher": "mdi:dishwasher",
171 "washer": "mdi:washing-machine",
172 "washer_dryer": "mdi:washing-machine",
173 "dryer": "mdi:tumble-dryer",
174 TYPE_OVEN: "mdi:stove",
175 "hob": "mdi:pot-steam",
176 "hood": "mdi:fan",
177 "coffee_maker": "mdi:coffee-maker",
178 "cleaning_robot": "mdi:robot-vacuum",
179 "air_conditioner": "mdi:air-conditioner",
180}
181# the types whose phases are worth a notification unless it's turned off, an oven up to heat being waited
182# for where a dishwasher starting to rinse isn't
183PHASES_NOTIFIED: Final[tuple[str, ...]] = (TYPE_OVEN,)
184# matched against the device name where the type isn't known, first hit wins
185ICONS: Final[dict[str, str]] = {
186 "dishwasher": "mdi:dishwasher",
187 # Italian names
188 "lavastoviglie": "mdi:dishwasher",
189 "lavasciuga": "mdi:washing-machine",
190 "lavatrice": "mdi:washing-machine",
191 "asciugatrice": "mdi:tumble-dryer",
192 "microonde": "mdi:microwave",
193 "forno": "mdi:stove",
194 "caffè": "mdi:coffee-maker",
195 "caffe": "mdi:coffee-maker",
196 "cappa": "mdi:fan",
197 "piano cottura": "mdi:pot-steam",
198 "aspirapolvere": "mdi:robot-vacuum",
199 "bollitore": "mdi:kettle",
200 "dryer": "mdi:tumble-dryer",
201 "wash": "mdi:washing-machine",
202 "oven": "mdi:stove",
203 "microwave": "mdi:microwave",
204 "coffee": "mdi:coffee-maker",
205 "hood": "mdi:fan",
206 "hob": "mdi:pot-steam",
207 "vacuum": "mdi:robot-vacuum",
208 "kettle": "mdi:kettle",
209}