@digital-alchemy/hass 24.9.4 → 24.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +1 -1
  2. package/dist/helpers/notify.helper.d.ts +2 -2
  3. package/package.json +16 -14
  4. package/scripts/mock-assistant.sh +5 -0
  5. package/scripts/run-e2e.sh +7 -0
  6. package/scripts/test.sh +2 -0
  7. package/src/dynamic.ts +4254 -0
  8. package/src/extensions/area.extension.ts +118 -0
  9. package/src/extensions/backup.extension.ts +63 -0
  10. package/src/extensions/call-proxy.extension.ts +113 -0
  11. package/src/extensions/config.extension.ts +119 -0
  12. package/src/extensions/conversation.extension.ts +46 -0
  13. package/src/extensions/device.extension.ts +56 -0
  14. package/src/extensions/entity.extension.ts +344 -0
  15. package/src/extensions/events.extension.ts +25 -0
  16. package/src/extensions/fetch-api.extension.ts +269 -0
  17. package/src/extensions/floor.extension.ts +76 -0
  18. package/src/extensions/id-by.extension.ts +157 -0
  19. package/src/extensions/index.ts +16 -0
  20. package/src/extensions/internal.extension.ts +145 -0
  21. package/src/extensions/label.extension.ts +83 -0
  22. package/src/extensions/reference.extension.ts +330 -0
  23. package/src/extensions/registry.extension.ts +44 -0
  24. package/src/extensions/websocket-api.extension.ts +554 -0
  25. package/src/extensions/zone.extension.ts +69 -0
  26. package/src/hass.module.ts +217 -0
  27. package/src/helpers/backup.helper.ts +11 -0
  28. package/src/helpers/constants.helper.ts +30 -0
  29. package/src/helpers/device.helper.ts +25 -0
  30. package/src/helpers/entity-state.helper.ts +171 -0
  31. package/src/helpers/features.helper.ts +580 -0
  32. package/src/helpers/fetch/calendar.ts +54 -0
  33. package/src/helpers/fetch/configuration.ts +75 -0
  34. package/src/helpers/fetch/index.ts +5 -0
  35. package/src/helpers/fetch/server-log.ts +28 -0
  36. package/src/helpers/fetch/service-list.ts +64 -0
  37. package/src/helpers/fetch/weather-forecasts.ts +86 -0
  38. package/src/helpers/fetch.helper.ts +328 -0
  39. package/src/helpers/id-by.helper.ts +53 -0
  40. package/src/helpers/index.ts +13 -0
  41. package/src/helpers/interfaces.helper.ts +340 -0
  42. package/src/helpers/manifest.helper.ts +0 -0
  43. package/src/helpers/notify.helper.ts +302 -0
  44. package/src/helpers/registry.ts +281 -0
  45. package/src/helpers/utility.helper.ts +147 -0
  46. package/src/helpers/websocket.helper.ts +117 -0
  47. package/src/index.ts +5 -0
  48. package/src/mock_assistant/extensions/area.extension.ts +62 -0
  49. package/src/mock_assistant/extensions/config.extension.ts +33 -0
  50. package/src/mock_assistant/extensions/device.extension.ts +44 -0
  51. package/src/mock_assistant/extensions/entity-registry.extension.ts +41 -0
  52. package/src/mock_assistant/extensions/entity.extension.ts +114 -0
  53. package/src/mock_assistant/extensions/events.extension.ts +37 -0
  54. package/src/mock_assistant/extensions/fetch.extension.ts +3 -0
  55. package/src/mock_assistant/extensions/fixtures.extension.ts +79 -0
  56. package/src/mock_assistant/extensions/floor.extension.ts +64 -0
  57. package/src/mock_assistant/extensions/index.ts +12 -0
  58. package/src/mock_assistant/extensions/label.extension.ts +64 -0
  59. package/src/mock_assistant/extensions/services.extension.ts +25 -0
  60. package/src/mock_assistant/extensions/websocket-api.extension.ts +84 -0
  61. package/src/mock_assistant/extensions/zone.extension.ts +65 -0
  62. package/src/mock_assistant/helpers/fixtures.ts +22 -0
  63. package/src/mock_assistant/helpers/index.ts +1 -0
  64. package/src/mock_assistant/index.ts +3 -0
  65. package/src/mock_assistant/main.ts +46 -0
  66. package/src/mock_assistant/mock-assistant.module.ts +90 -0
  67. package/src/quickboot.module.ts +23 -0
  68. package/src/testing/area.spec.ts +189 -0
  69. package/src/testing/backup.spec.ts +157 -0
  70. package/src/testing/config.spec.ts +188 -0
  71. package/src/testing/device.spec.ts +89 -0
  72. package/src/testing/entity.spec.ts +171 -0
  73. package/src/testing/events.spec.ts +78 -0
  74. package/src/testing/fetch-api.spec.ts +410 -0
  75. package/src/testing/fixtures.spec.ts +158 -0
  76. package/src/testing/floor.spec.ts +186 -0
  77. package/src/testing/id-by.spec.ts +140 -0
  78. package/src/testing/label.spec.ts +186 -0
  79. package/src/testing/ref-by.spec.ts +300 -0
  80. package/src/testing/websocket.spec.ts +63 -0
  81. package/src/testing/workflow.spec.ts +195 -0
  82. package/src/testing/zone.spec.ts +109 -0
@@ -0,0 +1,340 @@
1
+ import { TBlackHole } from "@digital-alchemy/core";
2
+ import EventEmitter from "events";
3
+ import WS from "ws";
4
+
5
+ import {
6
+ iCallService,
7
+ TAreaId,
8
+ TDeviceId,
9
+ TFloorId,
10
+ TLabelId,
11
+ TPlatformId,
12
+ TRawDomains,
13
+ TRawEntityIds,
14
+ TUniqueId,
15
+ TUniqueIDMapping,
16
+ } from "../dynamic";
17
+ import { BackupResponse, HomeAssistantBackup } from "./backup.helper";
18
+ import { DeviceDetails } from "./device.helper";
19
+ import { ByIdProxy } from "./entity-state.helper";
20
+ import { AreaCreate, AreaDetails, ConfigEntry, HassConfig, HassServiceDTO } from "./fetch";
21
+ import {
22
+ EditAliasOptions,
23
+ EditLabelOptions,
24
+ EntityRegistryItem,
25
+ FloorCreate,
26
+ FloorDetails,
27
+ LabelDefinition,
28
+ LabelOptions,
29
+ ManifestItem,
30
+ ToggleExpose,
31
+ UpdateCoreOptions,
32
+ ZoneDetails,
33
+ ZoneOptions,
34
+ } from "./registry";
35
+ import {
36
+ ALL_DOMAINS,
37
+ ALL_SERVICE_DOMAINS,
38
+ ANY_ENTITY,
39
+ ENTITY_STATE,
40
+ PICK_ENTITY,
41
+ PICK_FROM_AREA,
42
+ PICK_FROM_DEVICE,
43
+ PICK_FROM_FLOOR,
44
+ PICK_FROM_LABEL,
45
+ PICK_FROM_PLATFORM,
46
+ } from "./utility.helper";
47
+ import {
48
+ EntityHistoryDTO,
49
+ EntityHistoryResult,
50
+ OnHassEventOptions,
51
+ SocketMessageDTO,
52
+ SocketSubscribeOptions,
53
+ } from "./websocket.helper";
54
+
55
+ export type HassAreaService = {
56
+ apply: (
57
+ area: TAreaId,
58
+ entities: ANY_ENTITY[],
59
+ ) => Promise<{
60
+ updated: ANY_ENTITY[];
61
+ }>;
62
+ create: (details: AreaCreate) => Promise<void>;
63
+ current: AreaDetails[];
64
+ delete: (area_id: TAreaId) => Promise<void>;
65
+ list: () => Promise<AreaDetails[]>;
66
+ update: (details: AreaDetails) => Promise<void>;
67
+ };
68
+
69
+ export type HassZoneService = {
70
+ create: (options: ZoneOptions) => Promise<void>;
71
+ current: ZoneDetails[];
72
+ list: () => Promise<ZoneDetails[]>;
73
+ update: (zone_id: string, options: ZoneOptions) => Promise<void>;
74
+ };
75
+
76
+ export type HassLabelService = {
77
+ create: (details: LabelOptions) => Promise<void>;
78
+ current: LabelDefinition[];
79
+ delete: (label_id: TLabelId) => Promise<void>;
80
+ list: () => Promise<LabelDefinition[]>;
81
+ update: (details: LabelDefinition) => Promise<void>;
82
+ };
83
+
84
+ export type HassBackupService = {
85
+ download: (slug: string, destination: string) => Promise<void>;
86
+ generate: () => Promise<HomeAssistantBackup>;
87
+ list: () => Promise<BackupResponse>;
88
+ remove: (slug: string) => Promise<void>;
89
+ };
90
+
91
+ export type HassConfigService = {
92
+ getServices: () => HassServiceDTO[];
93
+ isService: <DOMAIN extends ALL_SERVICE_DOMAINS>(
94
+ domain: DOMAIN,
95
+ service: string,
96
+ ) => service is Extract<keyof iCallService[DOMAIN], string>;
97
+ loadServiceList: (recursion?: number) => Promise<void>;
98
+ };
99
+
100
+ export type HassWebsocketAPI = {
101
+ /**
102
+ * @internal
103
+ */
104
+ attachScheduledFunctions: () => void;
105
+ connection: WS;
106
+ /**
107
+ * the current state of the websocket
108
+ */
109
+ connectionState: ConnectionState;
110
+ /**
111
+ * can override as part of unit tests
112
+ */
113
+ createConnection: (url: string) => WS;
114
+ /**
115
+ * Convenient wrapper for sendMessage
116
+ */
117
+ fireEvent: (event_type: string, event_data?: object) => Promise<unknown>;
118
+ /**
119
+ * Set up a new websocket connection to home assistant
120
+ *
121
+ * This doesn't normally need to be called by applications, the extension self manages
122
+ */
123
+ init: () => Promise<void>;
124
+ /**
125
+ * run a callback when the socket finishes (re)connecting
126
+ */
127
+ onConnect: (callback: () => TBlackHole) => void;
128
+ /**
129
+ * Attach to the incoming stream of socket events. Do your own filtering and processing from there
130
+ *
131
+ * Returns removal function
132
+ */
133
+ onEvent: <DATA extends object>({
134
+ context,
135
+ event,
136
+ once,
137
+ exec,
138
+ }: OnHassEventOptions<DATA>) => () => void;
139
+ /**
140
+ * @internal
141
+ *
142
+ * for unit testing
143
+ */
144
+ onMessage: (message: SocketMessageDTO) => Promise<void>;
145
+ /**
146
+ * when true:
147
+ * - outgoing socket messages are blocked
148
+ * - entities don't emit updates
149
+ */
150
+ pauseMessages: boolean;
151
+ /**
152
+ * Send a message to home assistant via the socket connection
153
+ *
154
+ * Applications probably want a higher level function than this
155
+ */
156
+ sendMessage: <RESPONSE_VALUE extends unknown = unknown>(
157
+ data: {
158
+ type: string;
159
+ id?: number;
160
+ [key: string]: unknown;
161
+ },
162
+ waitForResponse?: boolean,
163
+ subscription?: () => void,
164
+ ) => Promise<RESPONSE_VALUE>;
165
+ /**
166
+ * internal
167
+ */
168
+ setConnectionState: (state: ConnectionState) => void;
169
+ /**
170
+ * internal
171
+ */
172
+ socketEvents: EventEmitter;
173
+ /**
174
+ * Subscribe to hass core registry updates.
175
+ *
176
+ * Not the same as `onEvent` (you probably want that)
177
+ */
178
+ subscribe: <EVENT extends string>({
179
+ event_type,
180
+ context,
181
+ exec,
182
+ }: SocketSubscribeOptions<EVENT>) => Promise<void>;
183
+ /**
184
+ * remove the current socket connection to home assistant
185
+ *
186
+ * will need to call init() again to start up
187
+ */
188
+ teardown: () => Promise<void>;
189
+ waitForReply: (id: number, data: object, sentAt: Date) => Promise<void>;
190
+ };
191
+
192
+ /* eslint-disable @typescript-eslint/no-magic-numbers */
193
+ export enum WebsocketConnectionState {
194
+ offline = 1,
195
+ connecting = 2,
196
+ connected = 3,
197
+ unknown = 4,
198
+ invalid = 5,
199
+ }
200
+ /* eslint-enable @typescript-eslint/no-magic-numbers */
201
+
202
+ export type ConnectionState = `${keyof typeof WebsocketConnectionState}`;
203
+
204
+ export type HassConversationService = {
205
+ addAlias: (options: EditAliasOptions) => Promise<void>;
206
+ removeAlias: (options: EditAliasOptions) => Promise<void>;
207
+ setConversational: (options: ToggleExpose) => Promise<void>;
208
+ };
209
+
210
+ export type HassDeviceService = {
211
+ current: DeviceDetails[];
212
+ list: () => Promise<DeviceDetails[]>;
213
+ };
214
+
215
+ export type HassEntityManagerRegistry = {
216
+ addLabel: ({ entity, label }: EditLabelOptions) => Promise<void>;
217
+ current: EntityRegistryItem<TRawEntityIds>[];
218
+ get: <ENTITY extends ANY_ENTITY>(entity_id: ENTITY) => Promise<EntityRegistryItem<ENTITY>>;
219
+ list: () => Promise<EntityRegistryItem<TRawEntityIds>[]>;
220
+ registryList: () => Promise<EntityRegistryItem<TRawEntityIds>[]>;
221
+ removeEntity: (entity_id: ANY_ENTITY | ANY_ENTITY[]) => Promise<void>;
222
+ removeLabel: ({ entity, label }: EditLabelOptions) => Promise<void>;
223
+ source: () => Promise<Record<TRawEntityIds, { domain: string }>>;
224
+ };
225
+
226
+ export type TMasterState = {
227
+ [DOMAIN in ALL_DOMAINS]: Record<string, ENTITY_STATE<PICK_ENTITY<DOMAIN>>>;
228
+ };
229
+
230
+ export type HassEntityManager = {
231
+ /**
232
+ * Internal library use only
233
+ */
234
+ _entityUpdateReceiver: <ENTITY extends ANY_ENTITY = TRawEntityIds>(
235
+ entity_id: ENTITY,
236
+ new_state: ENTITY_STATE<ENTITY>,
237
+ old_state: ENTITY_STATE<ENTITY>,
238
+ ) => void;
239
+ _masterState: () => Partial<TMasterState>;
240
+ /**
241
+ * Retrieves the current state of a given entity. This method returns
242
+ * raw data, offering a direct view of the entity's state at a given moment.
243
+ */
244
+ getCurrentState: <ENTITY_ID extends ANY_ENTITY>(entity_id: ENTITY_ID) => ENTITY_STATE<ENTITY_ID>;
245
+ /**
246
+ * Retrieves the historical state data of entities over a specified time
247
+ * period. Useful for analysis or tracking changes over time.
248
+ */
249
+ history: <ENTITES extends ANY_ENTITY[]>(
250
+ payload: Omit<EntityHistoryDTO<ENTITES>, "type">,
251
+ ) => Promise<{
252
+ [k: string]: EntityHistoryResult[];
253
+ }>;
254
+ /**
255
+ * Provides a simple listing of all entity IDs. Useful for enumeration
256
+ * and quick reference to all available entities.
257
+ */
258
+ listEntities: <DOMAIN extends ALL_DOMAINS = TRawDomains>(
259
+ domain?: DOMAIN,
260
+ ) => PICK_ENTITY<DOMAIN>[];
261
+ /**
262
+ * Returns the previous entity state (not a proxy)
263
+ */
264
+ previousState: (entity_id: ANY_ENTITY) => ENTITY_STATE<TRawEntityIds>;
265
+ /**
266
+ * Initiates a refresh of the current entity states. Useful for ensuring
267
+ * synchronization with the latest state data from Home Assistant.
268
+ */
269
+ refresh: (recursion?: number) => Promise<void>;
270
+ /**
271
+ * Interact with the entity registry
272
+ */
273
+ registry: HassEntityManagerRegistry;
274
+ /**
275
+ * @internal
276
+ */
277
+ warnEarly: (method: string) => void;
278
+ };
279
+
280
+ export type SimpleCallback = () => TBlackHole;
281
+
282
+ export type HassEventsService = {
283
+ onAreaRegistryUpdate: (callback: SimpleCallback) => void;
284
+ onDeviceRegistryUpdate: (callback: SimpleCallback) => void;
285
+ onEntityRegistryUpdate: (callback: SimpleCallback) => void;
286
+ onFloorRegistryUpdate: (callback: SimpleCallback) => void;
287
+ onLabelRegistryUpdate: (callback: SimpleCallback) => void;
288
+ onZoneRegistryUpdate: (callback: SimpleCallback) => void;
289
+ };
290
+
291
+ export type HassFloorService = {
292
+ create(details: FloorCreate): Promise<void>;
293
+ current: FloorDetails[];
294
+ delete(floor_id: TFloorId): Promise<void>;
295
+ list(): Promise<FloorDetails[]>;
296
+ update(details: FloorDetails): Promise<void>;
297
+ };
298
+
299
+ export type HassReferenceService = {
300
+ area: <AREA extends TAreaId, DOMAINS extends TRawDomains = TRawDomains>(
301
+ area: AREA,
302
+ ...domains: DOMAINS[]
303
+ ) => ByIdProxy<PICK_FROM_AREA<AREA, DOMAINS>>[];
304
+ device: <DEVICE extends TDeviceId, DOMAINS extends TRawDomains = TRawDomains>(
305
+ device: DEVICE,
306
+ ...domains: DOMAINS[]
307
+ ) => ByIdProxy<PICK_FROM_DEVICE<DEVICE, DOMAINS>>[];
308
+ domain: <DOMAIN extends TRawDomains = TRawDomains>(
309
+ domain: DOMAIN,
310
+ ) => ByIdProxy<PICK_ENTITY<DOMAIN>>[];
311
+ floor: <FLOOR extends TFloorId, DOMAINS extends TRawDomains = TRawDomains>(
312
+ floor: FLOOR,
313
+ ...domains: DOMAINS[]
314
+ ) => ByIdProxy<PICK_FROM_FLOOR<FLOOR, DOMAINS>>[];
315
+ id: <ENTITY_ID extends ANY_ENTITY>(entity_id: ENTITY_ID) => ByIdProxy<ENTITY_ID>;
316
+ label: <LABEL extends TLabelId, DOMAINS extends TRawDomains = TRawDomains>(
317
+ label: LABEL,
318
+ ...domains: DOMAINS[]
319
+ ) => ByIdProxy<PICK_FROM_LABEL<LABEL, DOMAINS>>[];
320
+ platform: <PLATFORM extends TPlatformId, DOMAINS extends TRawDomains = TRawDomains>(
321
+ platform: PLATFORM,
322
+ ...domains: DOMAINS[]
323
+ ) => ByIdProxy<PICK_FROM_PLATFORM<PLATFORM, DOMAINS>>[];
324
+ unique_id: <
325
+ UNIQUE_ID extends TUniqueId,
326
+ ENTITY_ID extends Extract<TUniqueIDMapping[UNIQUE_ID], ANY_ENTITY> = Extract<
327
+ TUniqueIDMapping[UNIQUE_ID],
328
+ ANY_ENTITY
329
+ >,
330
+ >(
331
+ unique_id: UNIQUE_ID,
332
+ ) => ByIdProxy<ENTITY_ID>;
333
+ };
334
+
335
+ export type HassRegistryService = {
336
+ getConfig: () => Promise<HassConfig>;
337
+ getConfigEntries: () => Promise<ConfigEntry[]>;
338
+ manifestList: () => Promise<ManifestItem[]>;
339
+ updateCore: (options: UpdateCoreOptions) => Promise<void>;
340
+ };
File without changes
@@ -0,0 +1,302 @@
1
+ export type AppleNotificationPush = {
2
+ /**
3
+ * **iOS | MacOS**
4
+ *
5
+ * The sound to play for the notification.
6
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#sounds)
7
+ *
8
+ * > default: "none"
9
+ */
10
+ sound?: string;
11
+
12
+ /**
13
+ * **iOS | MacOS**
14
+ *
15
+ * The badge number to display on the app icon.
16
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#badge)
17
+ */
18
+ badge?: number;
19
+
20
+ /**
21
+ * **iOS | MacOS**
22
+ *
23
+ * The interruption level of the notification.
24
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#interruption-level)
25
+ */
26
+ interruption_level?: "passive" | "active" | "time-sensitive" | "critical";
27
+
28
+ /**
29
+ * **iOS | MacOS**
30
+ *
31
+ * The presentation options for the notification.
32
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#presentation-options)
33
+ */
34
+ presentation_options?: ["alert" | "badge" | "sound"];
35
+ };
36
+
37
+ export type NotificationAction = {
38
+ /**
39
+ * Key passed back in events.
40
+ *
41
+ * ## REPLY
42
+ *
43
+ * When set to `REPLY`, you will be prompted for text to send with the event.
44
+ *
45
+ * ## URI
46
+ *
47
+ */
48
+ action: string;
49
+ /**
50
+ * Shown on the action button to the user.
51
+ */
52
+ title: string;
53
+ /**
54
+ * The URI to open when selected.
55
+ * Android requires setting the action string to `URI` to use this key. [More Info](https://companion.home-assistant.io/docs/notifications/actionable-notifications/#uri-values).
56
+ */
57
+ uri?: string;
58
+ };
59
+
60
+ export type AndroidNotificationActionOptions = Record<string, unknown>;
61
+
62
+ export type AppleNotificationActionOptions = {
63
+ /**
64
+ * **iOS | MacOS**
65
+ *
66
+ * Set to `foreground` to launch the app when tapped. Defaults to background which just fires the event.
67
+ * This is automatically set to foreground when providing a uri.
68
+ */
69
+ activationMode?: "foreground" | "background";
70
+ /**
71
+ * **iOS | MacOS**
72
+ *
73
+ * Set to `true` to require a password to fire the event.
74
+ */
75
+ authenticationRequired?: boolean;
76
+ /**
77
+ * **iOS | MacOS**
78
+ *
79
+ * Set to `true` to color the actions title red.
80
+ */
81
+ destructive?: boolean;
82
+ /**
83
+ * **iOS | MacOS**
84
+ *
85
+ * Set to `textInput` to prompt for text to return with the event. This also occurs when setting the action to `REPLY`.
86
+ */
87
+ behavior?: "textInput";
88
+ /**
89
+ * **iOS | MacOS**
90
+ *
91
+ * Title to use for text input for actions that prompt.
92
+ */
93
+ textInputButtonTitle?: string;
94
+ /**
95
+ * **iOS | MacOS**
96
+ *
97
+ * Placeholder to use for text input for actions that prompt.
98
+ */
99
+ textInputPlaceholder?: string;
100
+ /**
101
+ * **iOS | MacOS**
102
+ *
103
+ * The icon to use for the notification.
104
+ * * [More info](https://companion.home-assistant.io/docs/notifications/actionable-notifications#icon-values)
105
+ */
106
+ icon?: string;
107
+ };
108
+
109
+ export type AppleNotificationData = {
110
+ /**
111
+ * **iOS | MacOS**
112
+ *
113
+ * The URL to open when the notification is clicked.
114
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#opening-a-url)
115
+ */
116
+ url?: string;
117
+
118
+ /**
119
+ * **iOS | MacOS**
120
+ *
121
+ * The subtitle of the notification. Shows under the title.
122
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#subtitle--subject)
123
+ */
124
+ subtitle?: string;
125
+ push?: AppleNotificationPush;
126
+ /**
127
+ * iOS Supports ~10 actions.
128
+ */
129
+ actions?: Array<NotificationAction & AppleNotificationActionOptions>;
130
+ };
131
+
132
+ export type AndroidNotificationData = {
133
+ /**
134
+ * **Android**
135
+ *
136
+ * The action to perform when the notification is clicked.
137
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#opening-a-url)
138
+ */
139
+ clickAction?: string;
140
+
141
+ /**
142
+ * **Android**
143
+ *
144
+ * The subject of the notification.
145
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#subtitle--subject)
146
+ */
147
+ subject?: string;
148
+
149
+ /**
150
+ * **Android**
151
+ *
152
+ * The color of the notification.
153
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-color)
154
+ */
155
+ color?: string;
156
+
157
+ /**
158
+ * **Android**
159
+ *
160
+ * Whether the notification should be sticky (persistent).
161
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#sticky-notification)
162
+ */
163
+ sticky?: boolean;
164
+
165
+ /**
166
+ * **Android**
167
+ *
168
+ * The channel to which the notification belongs.
169
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-channels)
170
+ */
171
+ channel?: string;
172
+
173
+ /**
174
+ * **Android**
175
+ *
176
+ * The importance level of the notification.
177
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-channel-importance)
178
+ */
179
+ importance?: "none" | "min" | "low" | "default" | "high" | "max";
180
+
181
+ /**
182
+ * **Android**
183
+ *
184
+ * The vibration pattern of the notification.
185
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-vibration-pattern)
186
+ */
187
+ vibrationPattern?: string;
188
+
189
+ /**
190
+ * **Android**
191
+ *
192
+ * The LED color of the notification.
193
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-led-color)
194
+ */
195
+ ledColor?: string;
196
+
197
+ /**
198
+ * **Android**
199
+ *
200
+ * Whether the notification should be persistent.
201
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#persistent-notification)
202
+ */
203
+ persistent?: boolean;
204
+
205
+ /**
206
+ * **Android**
207
+ *
208
+ * The timeout duration of the notification.
209
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-timeout)
210
+ */
211
+ timeout?: number;
212
+
213
+ /**
214
+ * **Android**
215
+ *
216
+ * The URL of the notification icon.
217
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-icon)
218
+ */
219
+ icon_url?: string;
220
+
221
+ /**
222
+ * **Android**
223
+ *
224
+ * The visibility of the notification on the lock screen.
225
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-sensitivity--lock-screen-visibility)
226
+ */
227
+ visibility?: "public" | "private" | "secret";
228
+ /**
229
+ * **Android**
230
+ *
231
+ * The text to be spoken by text-to-speech notifications.
232
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#text-to-speech-notifications)
233
+ */
234
+ tts_text?: string;
235
+
236
+ /**
237
+ * **Android**
238
+ *
239
+ * The media stream to be played by the notification.
240
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#text-to-speech-notifications)
241
+ */
242
+ media_stream?: "alarm_stream" | "alarm_stream_max";
243
+
244
+ /**
245
+ * **Android**
246
+ *
247
+ * Whether the notification should display a chronometer.
248
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#chronometer-notifications)
249
+ */
250
+ chronometer?: boolean;
251
+
252
+ /**
253
+ * **Android**
254
+ *
255
+ * The timestamp to display in the notification.
256
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#chronometer-notifications)
257
+ */
258
+ when?: number;
259
+
260
+ /**
261
+ * **Android**
262
+ *
263
+ * Whether the notification should only alert once.
264
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#alert-once)
265
+ */
266
+ alert_once?: boolean;
267
+
268
+ /**
269
+ * **Android**
270
+ *
271
+ * The status bar icon of the notification.
272
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-status-bar-icon)
273
+ */
274
+ notification_icon?: string;
275
+
276
+ /**
277
+ * **Android**
278
+ *
279
+ * Whether the notification should be displayed in the car UI.
280
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#android-auto-visibility)
281
+ */
282
+ car_ui?: boolean;
283
+
284
+ /**
285
+ * Android Supports 3 actions.
286
+ */
287
+ actions?: Array<NotificationAction & AndroidNotificationActionOptions>;
288
+ };
289
+
290
+ export type NotificationData = {
291
+ /**
292
+ * The group to which the notification belongs.
293
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#grouping)
294
+ */
295
+ group?: string;
296
+
297
+ /**
298
+ * The tag to identify the notification for replacement by another.
299
+ * [More info](https://companion.home-assistant.io/docs/notifications/notifications-basic#replacing)
300
+ */
301
+ tag?: string;
302
+ };