Coverage for custom_components/supernotify/const.py: 100%

225 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-09-25 14:29 +0000

1"""The Supernotify integration""" 

2 

3from typing import Final 

4 

5from homeassistant.const import ( 

6 ATTR_DEVICE_ID, 

7 ATTR_DOMAIN, 

8 ATTR_ENTITY_ID, 

9 ATTR_SERVICE, 

10 CONF_TARGET, 

11) 

12 

13CONF_ACTIONS: Final[str] = "actions" # not fully implemented 

14CONF_TITLE: Final[str] = "title" 

15CONF_URI: Final[str] = "uri" 

16CONF_RECIPIENTS: Final[str] = "recipients" 

17CONF_RECIPIENTS_DISCOVERY: Final[str] = "recipients_discovery" 

18CONF_TEMPLATE_PATH: Final[str] = "template_path" 

19CONF_MEDIA_PATH: Final[str] = "media_path" 

20CONF_MEDIA_URL_PREFIX: Final[str] = "media_url_prefix" 

21CONF_HOUSEKEEPING: Final[str] = "housekeeping" 

22CONF_HOUSEKEEPING_TIME: Final[str] = "housekeeping_time" 

23CONF_ARCHIVE_PATH: Final[str] = "file_path" 

24CONF_ARCHIVE: Final[str] = "archive" 

25CONF_ARCHIVE_DAYS: Final[str] = "file_retention_days" 

26CONF_ARCHIVE_MQTT_TOPIC: Final[str] = "mqtt_topic" 

27CONF_ARCHIVE_MQTT_QOS: Final[str] = "mqtt_qos" 

28CONF_ARCHIVE_MQTT_RETAIN: Final[str] = "mqtt_retain" 

29CONF_TEMPLATE: Final[str] = "template" 

30CONF_DELIVERY_DEFAULTS: Final[str] = "delivery_defaults" 

31CONF_LINKS: Final[str] = "links" 

32CONF_PERSON: Final[str] = "person" 

33CONF_USER_ID: Final[str] = "user_id" 

34CONF_TRANSPORT: Final[str] = "transport" 

35CONF_TRANSPORTS: Final[str] = "transports" 

36CONF_LOAD: Final[str] = "load" 

37CONF_DELIVERY: Final[str] = "delivery" 

38CONF_INCLUSION: Final[str] = "inclusion" 

39CONF_SELECTION: Final[str] = "selection" # deprecated, use CONF_INCLUSION 

40CONF_SELECTION_RANK: Final[str] = "selection_rank" 

41 

42 

43CONF_DATA: Final[str] = "data" 

44CONF_OPTIONS: Final[str] = "options" 

45CONF_MOBILE: Final[str] = "mobile" 

46CONF_NOTIFY: Final[str] = "notify" 

47 

48CONF_PRIORITY: Final[str] = "priority" 

49CONF_OCCUPANCY: Final[str] = "occupancy" 

50CONF_SCENARIOS: Final[str] = "scenarios" 

51CONF_SCENARIO_CONTROL: Final[str] = "scenario_control" 

52CONF_REFRESH_INTERVAL: Final[str] = "refresh_interval" 

53CONF_EXPOSE_STATE: Final[str] = "expose_state" 

54CONF_REFRESH: Final[str] = "refresh" 

55SCENARIO_STATE_REFRESH_DEFAULT: Final[int] = 60 

56CONF_MANUFACTURER: Final[str] = "manufacturer" 

57CONF_CLASS: Final[str] = "class" 

58 

59 

60CONF_MODEL: Final[str] = "model" 

61CONF_MESSAGE: Final[str] = "message" 

62CONF_TARGET_REQUIRED: Final[str] = "target_required" 

63CONF_MOBILE_DEVICES: Final[str] = "mobile_devices" 

64CONF_MOBILE_DISCOVERY: Final[str] = "mobile_discovery" 

65CONF_ACTION_TEMPLATE: Final[str] = "action_template" 

66CONF_ACTION_GROUPS: Final[str] = "action_groups" 

67CONF_TITLE_TEMPLATE: Final[str] = "title_template" 

68CONF_MEDIA: Final[str] = "media" 

69CONF_CAMERA: Final[str] = "camera" 

70CONF_CLIP_URL: Final[str] = "clip_url" 

71CONF_PTZ_DELAY: Final[str] = "ptz_delay" 

72CONF_SNAP_WAIT: Final[str] = "snap_wait" 

73CONF_PTZ_METHOD: Final[str] = "ptz_method" 

74CONF_PTZ_CAMERA: Final[str] = "ptz_camera" 

75CONF_PTZ_PRESET_DEFAULT: Final[str] = "ptz_default_preset" 

76CONF_ALT_CAMERA: Final[str] = "alt_camera" 

77CONF_CAMERAS: Final[str] = "cameras" 

78CONF_ARCHIVE_PURGE_INTERVAL: Final[str] = "purge_interval" 

79CONF_ARCHIVE_EVENT_NAME: Final[str] = "event_name" 

80CONF_ARCHIVE_EVENT_SELECTION: Final[str] = "event_selection" 

81CONF_ARCHIVE_DIAGNOSTICS: Final[str] = "diagnostics" 

82CONF_MEDIA_STORAGE_DAYS: Final[str] = "media_storage_days" 

83 

84PLATFORM_FRIGATE = "frigate" 

85 

86OCCUPANCY_ANY_IN = "any_in" 

87OCCUPANCY_ANY_OUT = "any_out" 

88OCCUPANCY_ALL_IN = "all_in" 

89OCCUPANCY_ALL = "all" 

90OCCUPANCY_NONE = "none" 

91OCCUPANCY_ALL_OUT = "all_out" 

92OCCUPANCY_ONLY_IN = "only_in" 

93OCCUPANCY_ONLY_OUT = "only_out" 

94 

95ATTR_ENABLED = "enabled" 

96ATTR_TRANSPORT_ENABLED = "transport_enabled" 

97ATTR_PRIORITY = "priority" 

98ATTR_ACTION = "action" 

99ATTR_REPLY_TEXT = "reply_text" 

100ATTR_SCENARIOS_REQUIRE = "require_scenarios" 

101ATTR_SCENARIOS_APPLY = "apply_scenarios" 

102ATTR_FORCE_RESEND: Final[str] = "force_resend" 

103ATTR_SCENARIOS_CONSTRAIN = "constrain_scenarios" 

104ATTR_DELIVERY = "delivery" 

105ATTR_DEFAULT = "default" 

106ATTR_NOTIFICATION_ID = "notification_id" 

107ATTR_DELIVERY_SELECTION = "delivery_selection" 

108# supernotify.notify's free-form delivery field, merged into `delivery` with the delivery dropdown 

109ATTR_DELIVERY_CONTROL = "delivery_control" 

110ATTR_RECIPIENTS = "recipients" 

111ATTR_CUSTOM_TARGET = "custom_target" 

112ATTR_DATA = "data" 

113ATTR_EXTRA_DATA: Final[str] = "extra_data" 

114ATTR_MEDIA = "media" 

115ATTR_TITLE = "title" 

116ATTR_IMAGE = "image" 

117ATTR_VIDEO = "video" 

118ATTR_MEDIA_SNAPSHOT_URL = "snapshot_url" 

119ATTR_MEDIA_CAMERA_ENTITY_ID = "camera_entity_id" 

120ATTR_MEDIA_CAMERA_DELAY = "camera_delay" 

121ATTR_MEDIA_CAMERA_PTZ_PRESET = "camera_ptz_preset" 

122ATTR_MEDIA_CLIP_URL = "clip_url" 

123ATTR_MEDIA_SNAPSHOT_PATH = "snapshot_image_path" 

124ATTR_TOPIC = "topic" 

125ATTR_DISCORD_CHANNEL = "discord_channel" 

126ATTR_MATRIX_ROOM = "matrix_room" 

127ATTR_ACTION_GROUPS = "action_groups" 

128CONF_ACTION_GROUP_NAMES = "action_groups" 

129ATTR_ACTION_URL = "action_url" 

130ATTR_ACTION_URL_TITLE = "action_url_title" 

131ATTR_MESSAGE_HTML = "message_html" 

132ATTR_JPEG_OPTS = "jpeg_opts" 

133ATTR_PNG_OPTS = "png_opts" 

134ATTR_TIMESTAMP = "timestamp" 

135ATTR_SPOKEN_MESSAGE = "spoken_message" 

136ATTR_DEBUG = "debug" 

137ATTR_ACTIONS = "actions" 

138ATTR_USER_ID = "user_id" 

139ATTR_PERSON_ID = "person_id" 

140ATTR_MOBILE_APP_ID = "mobile_app_id" 

141ATTR_EMAIL = "email" 

142ATTR_PHONE = "phone" 

143ATTR_ALIAS = "alias" 

144 

145DELIVERY_SELECTION_IMPLICIT = "implicit" 

146DELIVERY_SELECTION_EXPLICIT = "explicit" 

147DELIVERY_SELECTION_FIXED = "fixed" 

148 

149DELIVERY_SELECTION_VALUES = [DELIVERY_SELECTION_EXPLICIT, DELIVERY_SELECTION_FIXED, DELIVERY_SELECTION_IMPLICIT] 

150PTZ_METHOD_ONVIF = "onvif" 

151PTZ_METHOD_FRIGATE = "frigate" 

152PTZ_METHOD_VALUES = [PTZ_METHOD_ONVIF, PTZ_METHOD_FRIGATE] 

153PTZ_DELAY_DEFAULT = 10 

154SNAP_WAIT_DEFAULT = 15 

155 

156INCLUSION_FALLBACK_ON_ERROR = "fallback_on_error" 

157INCLUSION_FALLBACK = "fallback" 

158INCLUSION_BY_SCENARIO = "scenario" 

159INCLUSION_DEFAULT = "default" 

160INCLUSION_EXPLICIT = "explicit" 

161INCLUSION_VALUES = [ 

162 INCLUSION_FALLBACK_ON_ERROR, 

163 INCLUSION_EXPLICIT, 

164 INCLUSION_BY_SCENARIO, 

165 INCLUSION_DEFAULT, 

166 INCLUSION_FALLBACK, 

167] 

168 

169OCCUPANCY_VALUES = [ 

170 OCCUPANCY_ALL_IN, 

171 OCCUPANCY_ALL_OUT, 

172 OCCUPANCY_ANY_IN, 

173 OCCUPANCY_ANY_OUT, 

174 OCCUPANCY_ONLY_IN, 

175 OCCUPANCY_ONLY_OUT, 

176 OCCUPANCY_ALL, 

177 OCCUPANCY_NONE, 

178] 

179 

180PRIORITY_CRITICAL = "critical" 

181PRIORITY_HIGH = "high" 

182PRIORITY_MEDIUM = "medium" 

183PRIORITY_LOW = "low" 

184PRIORITY_MINIMUM = "minimum" 

185 

186PRIORITY_VALUES: dict[str, int] = { 

187 PRIORITY_MINIMUM: 1, 

188 PRIORITY_LOW: 2, 

189 PRIORITY_MEDIUM: 3, 

190 PRIORITY_HIGH: 4, 

191 PRIORITY_CRITICAL: 5, 

192} 

193 

194CONF_TARGET_USAGE = "target_usage" 

195TARGET_USE_ON_NO_DELIVERY_TARGETS = "no_delivery" 

196TARGET_USE_ON_NO_ACTION_TARGETS = "no_action" 

197TARGET_USE_FIXED = "fixed" 

198TARGET_USE_MERGE_ALWAYS = "merge_always" 

199TARGET_USE_MERGE_ON_DELIVERY_TARGETS = "merge_delivery" 

200 

201# Options constants have been moved to `options.py` 

202 

203RE_DEVICE_ID = r"^[0-9a-f]{32}$" 

204RE_MEDIA_PLAYER_ENTITY_ID = r"^media_player\.[A-Za-z0-9_]+$" 

205RE_NOTIFY_ENTITY_ID = r"^notify\.[A-Za-z0-9_]+$" 

206 

207RESERVED_DELIVERY_NAMES: list[str] = ["ALL"] 

208RESERVED_SCENARIO_NAMES: list[str] = ["NO_SCENARIO", "NULL"] 

209RESERVED_DATA_KEYS: list[str] = [ATTR_DOMAIN, ATTR_SERVICE, "action"] 

210 

211CONF_DUPE_CHECK: Final[str] = "dupe_check" 

212CONF_DUPE_POLICY: Final[str] = "dupe_policy" 

213CONF_TTL: Final[str] = "ttl" 

214CONF_SIZE: Final[str] = "size" 

215ATTR_DUPE_POLICY_MTSLP: Final[str] = "dupe_policy_message_title_same_or_lower_priority" 

216ATTR_DUPE_POLICY_MT: Final[str] = "dupe_policy_message_title_same" 

217ATTR_DUPE_POLICY_NONE: Final[str] = "dupe_policy_none" 

218CONF_MOBILE_APP_ID: Final[str] = "mobile_app_id" 

219CONF_TRANSPORT_DATA: Final[str] = "transport_data" 

220 

221 

222CONF_DEVICE_TRACKER: Final[str] = "device_tracker" 

223 

224 

225CONF_DEVICE_NAME: Final[str] = "device_name" 

226CONF_DEVICE_LABELS: Final[str] = "device_labels" 

227 

228MANUFACTURER_APPLE = "Apple" 

229 

230TARGET_REQUIRE_ALWAYS = "always" 

231TARGET_REQUIRE_NEVER = "never" 

232TARGET_REQUIRE_OPTIONAL = "optional" 

233 

234## Transports 

235# Defined here rather than transports.py so that the strings can be imported 

236# without the transports, and avoid circular references or heavier imports 

237TRANSPORT_SMS = "sms" 

238TRANSPORT_TTS = "tts" 

239TRANSPORT_MQTT = "mqtt" 

240TRANSPORT_EMAIL = "email" 

241TRANSPORT_ALEXA = "alexa_devices" 

242TRANSPORT_ALEXA_MEDIA_PLAYER = "alexa_media_player" 

243TRANSPORT_MOBILE_PUSH = "mobile_push" 

244TRANSPORT_MEDIA = "media" 

245TRANSPORT_CHIME = "chime" 

246TRANSPORT_GENERIC = "generic" 

247TRANSPORT_NOTIFY_ENTITY = "notify_entity" 

248TRANSPORT_PERSISTENT = "persistent" 

249TRANSPORT_NTFY = "ntfy" 

250TRANSPORT_GOTIFY = "gotify" 

251TRANSPORT_TELEGRAM = "telegram" 

252TRANSPORT_LAMETRIC = "lametric" 

253TRANSPORT_PUSHOVER = "pushover" 

254TRANSPORT_HTML5 = "html5" 

255TRANSPORT_MATRIX = "matrix" 

256TRANSPORT_KODI = "kodi" 

257TRANSPORT_DISCORD = "discord" 

258TRANSPORT_VALUES = [ 

259 TRANSPORT_SMS, 

260 TRANSPORT_MQTT, 

261 TRANSPORT_ALEXA, 

262 TRANSPORT_ALEXA_MEDIA_PLAYER, 

263 TRANSPORT_MOBILE_PUSH, 

264 TRANSPORT_CHIME, 

265 TRANSPORT_EMAIL, 

266 TRANSPORT_MEDIA, 

267 TRANSPORT_PERSISTENT, 

268 TRANSPORT_TTS, 

269 TRANSPORT_GENERIC, 

270 TRANSPORT_NOTIFY_ENTITY, 

271 TRANSPORT_NTFY, 

272 TRANSPORT_GOTIFY, 

273 TRANSPORT_TELEGRAM, 

274 TRANSPORT_LAMETRIC, 

275 TRANSPORT_PUSHOVER, 

276 TRANSPORT_HTML5, 

277 TRANSPORT_MATRIX, 

278 TRANSPORT_KODI, 

279 TRANSPORT_DISCORD, 

280] 

281 

282# The master list of target category names, independent of any one transport - both 

283# `Target` (for qualifying a target, e.g. `topic:my/topic` or `target: {topic: ...}`) 

284# and `Transport.target_categories` (for declaring which categories a transport accepts) 

285# reference this same list, rather than transports and targets each keeping their own. 

286TARGET_CATEGORY_VALUES = [ 

287 ATTR_ENTITY_ID, 

288 ATTR_DEVICE_ID, 

289 ATTR_EMAIL, 

290 ATTR_PHONE, 

291 ATTR_MOBILE_APP_ID, 

292 ATTR_TOPIC, 

293 ATTR_DISCORD_CHANNEL, 

294 ATTR_MATRIX_ROOM, 

295] 

296 

297 

298CONF_CONNECTION: Final[str] = "connection" 

299CONF_ENCRYPTION: Final[str] = "encryption" 

300 

301CONF_DEVICE_DISCOVERY: Final[str] = "device_discovery" 

302CONF_DEVICE_DOMAIN: Final[str] = "device_domain" 

303CONF_DEVICE_MODEL_INCLUDE: Final[str] = "device_model_include" 

304CONF_DEVICE_MODEL_EXCLUDE: Final[str] = "device_model_exclude" 

305 

306# What a runtime override of a configured `enabled` flag can apply to - each also the unique_id 

307# prefix of the switch for it, e.g. switch unique_id "delivery_<name>" 

308OVERRIDE_KIND_SCENARIO: Final[str] = "scenario" 

309OVERRIDE_KIND_RECIPIENT: Final[str] = "recipient" 

310OVERRIDE_KIND_DELIVERY: Final[str] = "delivery" 

311OVERRIDE_KIND_TRANSPORT: Final[str] = "transport" 

312OVERRIDE_KINDS: Final[tuple[str, ...]] = ( 

313 OVERRIDE_KIND_SCENARIO, 

314 OVERRIDE_KIND_RECIPIENT, 

315 OVERRIDE_KIND_DELIVERY, 

316 OVERRIDE_KIND_TRANSPORT, 

317) 

318# Entity state attributes too large, or changing too often, to be worth keeping in history 

319DELIVERY_UNRECORDED_ATTRIBUTES: Final[frozenset[str]] = frozenset({CONF_OPTIONS, CONF_DATA, CONF_TARGET}) 

320TRANSPORT_UNRECORDED_ATTRIBUTES: Final[frozenset[str]] = frozenset({ 

321 CONF_DELIVERY_DEFAULTS, 

322 "action_titles", 

323 "action_title_failures", 

324 "cached_templates", 

325}) 

326 

327CONF_SNOOZE = "snooze" 

328CONF_SNOOZE_TIME = "snooze_time" 

329 

330# Config entry options for the LLM tools offered to Assist and MCP, see llm.py 

331CONF_LLM_TOOLS: Final[str] = "llm_tools" 

332CONF_LLM_ACTION_TOOLS: Final[str] = "action_tools" 

333CONF_LLM_DIAGNOSTIC_TOOLS: Final[str] = "diagnostic_tools" 

334# sentences for Home Assistant's built-in conversation agent, which can't use LLM tools, see sentences.py 

335CONF_SENTENCE_COMMANDS: Final[str] = "sentence_commands" 

336 

337# Config entry options giving deliveries their defaults, where neither they nor their transport set one 

338CONF_DELIVERY_CONTROL: Final[str] = "delivery_control" 

339CONF_DEFAULT_INCLUSION: Final[str] = "default_inclusion" 

340CONF_VOICE_OCCUPANCY: Final[str] = "voice_occupancy" 

341DEFAULT_INCLUSION_VALUES: Final[list[str]] = [INCLUSION_DEFAULT, INCLUSION_EXPLICIT, INCLUSION_BY_SCENARIO] 

342 

343# Idea - differentiate enabled as recipient vs as occupant, for ALL_IN etc check 

344# May need condition, and also enabled if delivery disabled 

345# CONF_OCCUPANCY="occupancy" 

346# OPTION_OCCUPANCY_DEFAULT="default" 

347# OPTIONS_OCCUPANCY=[OPTION_OCCUPANCY_DEFAULT,OPTION_OCCUPANCY_EXCLUDE] 

348# OPTION_OCCUPANCY_EXCLUDE="exclude" 

349 

350CONF_PHONE_NUMBER: str = "phone_number" 

351 

352 

353CONF_TUNE: Final[str] = "tune" 

354CONF_VOLUME: Final[str] = "volume" 

355CONF_DURATION: Final[str] = "duration" 

356 

357OPTIONS_CHIME_DOMAINS = ["media_player", "switch", "script", "rest_command", "siren", "alexa_devices"]