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

1"""Constants for Appliance Auto Notify""" 

2 

3from typing import Final 

4 

5DOMAIN: Final[str] = "appliance_autonotify" 

6SUPERNOTIFY_DOMAIN: Final[str] = "supernotify" 

7 

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 

46 

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) 

67 

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") 

95 

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") 

107 

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 

113 

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" 

120 

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}