homebridge-dummy 1.1.0-beta.0 → 1.1.0-beta.2

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 (46) hide show
  1. package/CHANGELOG.md +16 -14
  2. package/README.md +68 -10
  3. package/config.schema.json +218 -83
  4. package/dist/accessory/base.d.ts +6 -4
  5. package/dist/accessory/base.js +15 -17
  6. package/dist/accessory/base.js.map +1 -1
  7. package/dist/accessory/helpers.js +3 -0
  8. package/dist/accessory/helpers.js.map +1 -1
  9. package/dist/accessory/lock.d.ts +2 -1
  10. package/dist/accessory/lock.js +12 -5
  11. package/dist/accessory/lock.js.map +1 -1
  12. package/dist/accessory/onoff/onoff.d.ts +2 -1
  13. package/dist/accessory/onoff/onoff.js +10 -3
  14. package/dist/accessory/onoff/onoff.js.map +1 -1
  15. package/dist/accessory/position/position.d.ts +2 -1
  16. package/dist/accessory/position/position.js +11 -4
  17. package/dist/accessory/position/position.js.map +1 -1
  18. package/dist/accessory/thermostat.d.ts +28 -0
  19. package/dist/accessory/thermostat.js +147 -0
  20. package/dist/accessory/thermostat.js.map +1 -0
  21. package/dist/homebridge-ui/public/index.html +1 -1
  22. package/dist/i18n/en.d.ts +31 -1
  23. package/dist/i18n/en.js +36 -6
  24. package/dist/i18n/en.js.map +1 -1
  25. package/dist/i18n/i18n.d.ts +31 -1
  26. package/dist/i18n/template.d.ts +31 -1
  27. package/dist/i18n/zz.d.ts +31 -1
  28. package/dist/model/timer.d.ts +9 -5
  29. package/dist/model/timer.js +33 -30
  30. package/dist/model/timer.js.map +1 -1
  31. package/dist/model/trigger.d.ts +18 -0
  32. package/dist/model/trigger.js +92 -0
  33. package/dist/model/trigger.js.map +1 -0
  34. package/dist/model/types.d.ts +31 -0
  35. package/dist/model/types.js +18 -0
  36. package/dist/model/types.js.map +1 -1
  37. package/dist/tools/storage.d.ts +1 -0
  38. package/dist/tools/storage.js +1 -0
  39. package/dist/tools/storage.js.map +1 -1
  40. package/dist/tools/temperature.d.ts +3 -0
  41. package/dist/tools/temperature.js +14 -0
  42. package/dist/tools/temperature.js.map +1 -0
  43. package/dist/tools/time.d.ts +5 -0
  44. package/dist/tools/time.js +15 -0
  45. package/dist/tools/time.js.map +1 -0
  46. package/package.json +3 -1
package/CHANGELOG.md CHANGED
@@ -1,25 +1,27 @@
1
- ## ‼️ WARNING - READ BEFORE CONTINUING ‼️
2
-
3
- If upgrading from v0.9.2 or earlier, automations and scenes using Homebridge Dummy accessories will need to be reconfigured.
4
-
5
- ## ⚠️ IMPORTANT ⚠️
6
-
7
- After installing v1.0, you must **RESTART HOMEBRIDGE SERVICE & UI** (not just *RESTART HOMEBRIDGE*) before continuing or you will experience issues with Homebridge Dummy configuration.
1
+ # Change Log
8
2
 
9
- Once you have restarted both Homebridge and the UI, you will need to open the Homebridge Dummy plugin settings to run the accessory migration helper.
3
+ All notable changes to homebridge-dummy will be documented in this file.
10
4
 
11
- Full details [here](https://github.com/mpatfield/homebridge-dummy?tab=readme-ov-file#v10-migration).
5
+ ## 1.1.0-beta.2 (2025-07-31)
12
6
 
13
- # Change Log
7
+ ### ‼️ WARNING — Read this if upgrading from v0.9.2 or earlier…
14
8
 
15
- All notable changes to homebridge-dummy will be documented in this file.
9
+ Automations and scenes using Homebridge Dummy accessories will need to be reconfigured. After upgrading, you must **RESTART HOMEBRIDGE SERVICE & UI** (not just *RESTART HOMEBRIDGE*). After restarting, open the Homebridge Dummy plugin settings to run the accessory migration helper. Full details [here](https://github.com/mpatfield/homebridge-dummy?tab=readme-ov-file#v10-migration).
16
10
 
17
- ## 1.1.0-beta.X (XXXX-XX-XX)
11
+ ---
18
12
 
19
13
  ### Added
20
-
21
14
  - Groups (Beta) - Items sharing the same group name will be collected together in the Home app UI
22
- - ⚠️ Adding/removing/changing the group name will require you to reconfigure any HomeKit scenes or automations
15
+ - ⚠️ Adding/removing/changing the group name for an accessory will require you to reconfigure any HomeKit scenes or automations
16
+ - Auto-Trigger feature to invoke accessory at a specified interval or times
17
+ - Support for Thermostats
18
+ - Manual control only, no auto-trigger or auto-reset functionality
19
+
20
+ ### Changed
21
+ - Reorganized plugin config UI and renamed "Timer" to "Auto-Reset"
22
+
23
+ ### Fixed
24
+ - Timers over 1 hour were logging incorrectly ([#143](https://github.com/mpatfield/homebridge-dummy/issues/143))
23
25
 
24
26
  ## 1.0.0 (2025-07-23)
25
27
 
package/README.md CHANGED
@@ -85,22 +85,35 @@ Using the Homebridge Config UI is the easiest way to set up this plugin. However
85
85
  {
86
86
  "id": "string",
87
87
  "name": "string",
88
+ "type": "Door | Lightbulb | LockMechanism | Outlet | Switch | Thermostat | Window | WindoCovering",
88
89
  "groupName": "string",
89
- "type": "Door | Lightbulb | LockMechanism | Outlet | Switch | Window | WindoCovering",
90
90
  "timer": {
91
91
  "delay": number,
92
92
  "units": "SECONDS | MINUTES | HOURS",
93
93
  "random": true | false
94
94
  },
95
+ "trigger": {
96
+ "type": "INTERVAL" | "CRON",
97
+ "interval": number,
98
+ "units": "SECONDS | MINUTES | HOURS",
99
+ "random": true | false,
100
+ "cron": "string"
101
+ },
95
102
  "sensor": "CarbonDioxideSensor | CarbonMonoxideSensor | ContactSensor | LeakSensor | MotionSensor | OccupancySensor | SmokeSensor",
103
+ "temperatureUnits": "C" | "F",
96
104
  "defaultOn": true | false,
97
105
  "defaultBrightness": 0-100,
98
106
  "defaultLockState": "locked" | "unlocked",
99
107
  "defaultPosition": "open" | "closed",
100
- "onCommand": "string",
101
- "offCommand": "string",
102
- "lockCommand": "string",
103
- "unlockCommand": "string",
108
+ "defaultThermostatState": "auto" | "heat" | "cool" | "off",
109
+ "defaultTemperature": number,
110
+ "commandOn": "string",
111
+ "commandOff": "string",
112
+ "commandLock": "string",
113
+ "commandUnlock": "string",
114
+ "commandOpen": "string",
115
+ "commandClose": "string",
116
+ "commandTemperature": "string",
104
117
  "resetOnRestart": true | false,
105
118
  "disableLogging": true | false
106
119
  }
@@ -115,7 +128,7 @@ All fields are optional unless noted with an asterisk (*)
115
128
  - `id`* - A unique identifier for the accessory. Changing this value will create a new accessory.
116
129
 
117
130
  - `name`* - The display name for the accessory in HomeKit
118
- - `type`* - The type of accessory: `Door`, `Lightbulb`, `LockMechanism`, `Outlet`, `Switch`, `Window`, or `WindowCovering`
131
+ - `type`* - The type of accessory: `Door`, `Lightbulb`, `LockMechanism`, `Outlet`, `Switch`, `Thermostat`, `Window`, or `WindowCovering`
119
132
 
120
133
  - `groupName` - (Beta) Items sharing the same group name will be collected together in the Home app UI
121
134
  - ⚠️ Adding/removing/changing the group name will require you to reconfigure any HomeKit scenes or automations
@@ -124,10 +137,19 @@ All fields are optional unless noted with an asterisk (*)
124
137
  - `timer.units` — The units to use for delay above (`SECONDS`, `MINUTES`, or `HOURS`). *Required if delay is set.
125
138
  - `timer.random` — If true, the delay will be randomized with a maximum value of `timer.delay`
126
139
 
140
+ - `trigger.type` — Automatically set the accessory to it's non-default value
141
+ - `trigger.interval` — Trigger the accessory after this many seconds/minutes/hours. *Required if `trigger.type` = `INTERVAL`
142
+ - `trigger.units` — The units to use for the interval (`SECONDS`, `MINUTES`, or `HOURS`) *Required if `trigger.type` = `INTERVAL`
143
+ - `trigger.random` — If true, the interval will be randomized with a maximum value of `trigger.interval`
144
+ - `trigger.cron` — The cron string for triggering the accessory. *Required if `trigger.type` = `CRON`
145
+ - See [crontab.guru](http://crontab.guru) for help
146
+
127
147
  - `sensor` - Optionally attach a sensor that mirrors the state of the parent accessory
128
148
  - Only works with `Lightbulb`, `Outlet`, and `Switch`
129
149
  - Valid values are `CarbonDioxideSensor`, `CarbonMonoxideSensor`, `ContactSensor`, `LeakSensor`, `MotionSensor`, `OccupancySensor`, or `SmokeSensor`
130
150
 
151
+ - `temperatureUnits` - Units to use for thermostats, either 'C' or 'F'
152
+
131
153
  - `defaultOn` — Initial value. Default _ON_ = true, default _OFF_ = false
132
154
 
133
155
  - `defaultBrightness` — If set, lightbulb will have additional dimmer settings with this default brightness percentage
@@ -136,13 +158,19 @@ All fields are optional unless noted with an asterisk (*)
136
158
 
137
159
  - `defaultPosition` — Initial position for the door/window/blinds, "open" or "closed"
138
160
 
139
- - `onCommand` - Arbitraty command to execute when lightbulb/outlet/switch turns on
140
- - `offCommand` - Arbitraty command to execute when lightbulb/outlet/switch turns off
161
+ - `defaultThermostatState` - The initial state for the thermostat, "auto", "heat", "cool", or "off"
162
+
163
+ - `defaultTemperature` - The default temperature for the thermostat in `temperatureUnits` defined above
164
+
165
+ - `onCommand` - Arbitraty command to execute when lightbulb/outlet/switch/thermostat turns on
166
+ - `offCommand` - Arbitraty command to execute when lightbulb/outlet/switch/thermostat turns off
141
167
 
142
168
  - `lockCommand` - Arbitraty command to execute when lock mechanism is locked
143
169
  - `unlockCommand` - Arbitraty command to execute when lock mechanism is unlocked
144
170
 
145
- - `resetOnRestart` _ If true, all values return to defaults when Homebridge restarts. Ignored when timer is defined.
171
+ - `commandTemperature` - Arbitrary command to execute when temperature changes
172
+
173
+ - `resetOnRestart` _ If true, accessory will return to default state when Homebridge restarts
146
174
 
147
175
  - `disableLogging` — If true, state changes will not be logged
148
176
 
@@ -273,10 +301,40 @@ All fields are optional unless noted with an asterisk (*)
273
301
  }
274
302
  ```
275
303
 
304
+ ### Hourly Trigger Switch
305
+ ```json
306
+ {
307
+ "name": "Hourly",
308
+ "type": "Switch",
309
+ "timer": {
310
+ "delay": 1,
311
+ "units": "SECONDS"
312
+ },
313
+ "trigger": {
314
+ "type": "INTERVAL",
315
+ "interval": 1,
316
+ "units": "HOURS"
317
+ }
318
+ }
319
+ ```
320
+
321
+ ### Thermostat
322
+ ```json
323
+ {
324
+ "name": "Thermostat",
325
+ "type": "Thermostat",
326
+ "temperatureUnits": "F",
327
+ "defaultThermostatState": "heat",
328
+ "defaultTemperature": 78
329
+ }
330
+ ```
331
+
276
332
  ## Credits
277
333
 
278
- Special thanks to [@nfarina](https://github.com/nfarina) for creating the original version of this plugin and maintaining it for almost 10 (!!!) years
334
+ Special thanks to [@nfarina](https://github.com/sponsors/nfarina) for creating the original version of this plugin and maintaining it for almost 10 (!!!) years
279
335
 
280
336
  [Keryan Belahcene](https://www.instagram.com/keryan.me) for creating the [Flume](https://github.com/homebridge-plugins/homebridge-flume) banner image which was adapted for use with this plugin
281
337
 
338
+ Auto-Trigger feature inspired by [Homebridge Schedule](https://github.com/kbrashears5/typescript-homebridge-schedule) by [@kbrashears5](https://github.com/sponsors/kbrashears5)
339
+
282
340
  And to the amazing creators/contributors of [Homebridge](https://homebridge.io) who made this plugin possible!
@@ -27,6 +27,40 @@
27
27
  "description": "${config.description.random}"
28
28
  }
29
29
  }
30
+ },
31
+ "trigger": {
32
+ "type": "object",
33
+ "properties": {
34
+ "type": {
35
+ "type": "string",
36
+ "title": "${config.title.type}",
37
+ "enum": [ "INTERVAL", "CRON"],
38
+ "enumNames": ["${config.enumNames.interval}", "${config.enumNames.cron}"]
39
+ },
40
+ "interval": {
41
+ "type": "integer",
42
+ "title": "${config.title.interval}",
43
+ "minimum": 1
44
+ },
45
+ "units": {
46
+ "type": "string",
47
+ "title": "${config.title.units}",
48
+ "enum": [ "SECONDS", "MINUTES", "HOURS"],
49
+ "enumNames": ["${config.enumNames.seconds}", "${config.enumNames.minutes}", "${config.enumNames.hours}"]
50
+ },
51
+ "random": {
52
+ "type": "boolean",
53
+ "title": "${config.title.random}",
54
+ "description": "${config.description.random}"
55
+ },
56
+ "cron": {
57
+ "type": "string",
58
+ "title": "${config.title.cron}",
59
+ "description": "${config.description.cron}",
60
+ "placeholder": "* * * * * *",
61
+ "minimum": 1
62
+ }
63
+ }
30
64
  }
31
65
  },
32
66
  "properties": {
@@ -50,20 +84,27 @@
50
84
  "type": {
51
85
  "type": "string",
52
86
  "title": "${config.title.type}",
53
- "enum": ["Door", "Lightbulb", "LockMechanism", "Outlet", "Switch", "Window", "WindowCovering"],
54
- "enumNames": ["${config.enumNames.door}", "${config.enumNames.lightbulb}", "${config.enumNames.lockMechanism}", "${config.enumNames.outlet}", "${config.enumNames.switch}", "${config.enumNames.window}", "${config.enumNames.windowCovering}"]
87
+ "enum": ["Door", "Lightbulb", "LockMechanism", "Outlet", "Switch", "Thermostat", "Window", "WindowCovering"],
88
+ "enumNames": ["${config.enumNames.door}", "${config.enumNames.lightbulb}", "${config.enumNames.lockMechanism}", "${config.enumNames.outlet}", "${config.enumNames.switch}", "${config.enumNames.thermostat}", "${config.enumNames.window}", "${config.enumNames.windowCovering}"]
55
89
  },
56
90
  "groupName": {
57
91
  "type": "string",
58
92
  "title": "${config.title.groupName}"
59
93
  },
60
94
  "timer": { "$ref": "#/definitions/timer" },
95
+ "trigger": { "$ref": "#/definitions/trigger" },
61
96
  "sensor": {
62
97
  "type": "string",
63
98
  "title": "${config.title.sensor}",
64
99
  "enum": ["CarbonDioxideSensor", "CarbonMonoxideSensor", "ContactSensor", "LeakSensor", "MotionSensor", "OccupancySensor", "SmokeSensor"],
65
100
  "enumNames": ["${config.enumNames.carbonDioxideSensor}", "${config.enumNames.carbonMonoxideSensor}", "${config.enumNames.contactSensor}", "${config.enumNames.leakSensor}", "${config.enumNames.motionSensor}", "${config.enumNames.occupancySensor}", "${config.enumNames.smokeSensor}"]
66
101
  },
102
+ "temperatureUnits": {
103
+ "type": "string",
104
+ "title": "${config.title.units}",
105
+ "enum": ["C", "F"],
106
+ "enumNames": ["${config.enumNames.celsius}", "${config.enumNames.fahrenheit}"]
107
+ },
67
108
  "defaultBrightness": {
68
109
  "type": "number",
69
110
  "title": "${config.title.defaultBrightness}",
@@ -88,6 +129,16 @@
88
129
  "enum": ["open", "closed"],
89
130
  "enumNames": ["${config.enumNames.open}", "${config.enumNames.closed}"]
90
131
  },
132
+ "defaultThermostatState": {
133
+ "type": "string",
134
+ "title": "${config.title.defaultState}",
135
+ "enum": ["auto", "heat", "cool", "off"],
136
+ "enumNames": ["${config.enumNames.auto}", "${config.enumNames.heat}", "${config.enumNames.cool}", "${config.enumNames.off}"]
137
+ },
138
+ "defaultTemperature": {
139
+ "type": "number",
140
+ "title": "${config.title.defaultTemperature}"
141
+ },
91
142
  "commandOn": {
92
143
  "type": "string",
93
144
  "title": "${config.title.commandOn}"
@@ -112,6 +163,10 @@
112
163
  "type": "string",
113
164
  "title": "${config.title.commandClose}"
114
165
  },
166
+ "commandTemperature": {
167
+ "type": "string",
168
+ "title": "${config.title.commandTemperature}"
169
+ },
115
170
  "resetOnRestart": {
116
171
  "type": "boolean",
117
172
  "title": "${config.title.resetOnRestart}"
@@ -143,88 +198,21 @@
143
198
  "items": [
144
199
  {
145
200
  "key": "accessories[].name",
146
- "flex": "1 1 0"
201
+ "flex": "1 1 33%"
147
202
  },
148
203
  {
149
204
  "key": "accessories[].type",
150
- "flex": "1 1 0"
205
+ "flex": "1 1 33%"
151
206
  },
152
207
  {
153
208
  "key": "accessories[].groupName",
154
- "flex": "1 1 0"
155
- }
156
- ]
157
- },
158
- {
159
- "type": "fieldset",
160
- "title": "${config.title.timer}",
161
- "description": "${config.description.timer}",
162
- "condition": {
163
- "functionBody": "return model.accessories?.[arguments[1]]?.type !== undefined;"
164
- },
165
- "items": [
166
- {
167
- "type": "div",
168
- "displayFlex": true,
169
- "flex-direction": "row",
170
- "items": [
171
- {
172
- "key": "accessories[].timer.delay",
173
- "flex": "1 1 0"
174
- },
175
- {
176
- "key": "accessories[].timer.units",
177
- "flex": "1 1 0"
178
- }
179
- ]
180
- },
181
- {
182
- "key": "accessories[].timer.random",
183
- "condition": {
184
- "functionBody": "return model.accessories?.[arguments[1]]?.timer?.delay !== undefined;"
185
- }
209
+ "flex": "1 1 33%"
186
210
  }
187
211
  ]
188
212
  },
189
213
  {
190
214
  "type": "fieldset",
191
- "title": "${config.title.commands}",
192
- "description": "${config.description.commands}",
193
- "condition": {
194
- "functionBody": "return ['Lightbulb','Outlet','Switch'].includes(model.accessories?.[arguments[1]]?.type);"
195
- },
196
- "items": [
197
- "accessories[].commandOn",
198
- "accessories[].commandOff"
199
- ]
200
- },
201
- {
202
- "type": "fieldset",
203
- "title": "${config.title.commands}",
204
- "description": "${config.description.commands}",
205
- "condition": {
206
- "functionBody": "return ['LockMechanism'].includes(model.accessories?.[arguments[1]]?.type);"
207
- },
208
- "items": [
209
- "accessories[].commandLock",
210
- "accessories[].commandUnlock"
211
- ]
212
- },
213
- {
214
- "type": "fieldset",
215
- "title": "${config.title.commands}",
216
- "description": "${config.description.commands}",
217
- "condition": {
218
- "functionBody": "return ['Door', 'Window', 'WindowCovering'].includes(model.accessories?.[arguments[1]]?.type);"
219
- },
220
- "items": [
221
- "accessories[].commandOpen",
222
- "accessories[].commandClose"
223
- ]
224
- },
225
- {
226
- "type": "fieldset",
227
- "title": "${config.title.options}",
215
+ "notitle": true,
228
216
  "condition": {
229
217
  "functionBody": "return model.accessories?.[arguments[1]]?.type !== undefined;"
230
218
  },
@@ -239,15 +227,15 @@
239
227
  "items": [
240
228
  {
241
229
  "key": "accessories[].defaultOn",
242
- "flex": "0 0 25%"
230
+ "flex": "0 0 33%"
243
231
  },
244
232
  {
245
233
  "key": "accessories[].sensor",
246
- "flex": "0 0 25%"
234
+ "flex": "0 0 33%"
247
235
  },
248
236
  {
249
237
  "key": "accessories[].defaultBrightness",
250
- "flex": "0 0 25%",
238
+ "flex": "0 0 33%",
251
239
  "condition": {
252
240
  "functionBody": "return ['Lightbulb'].includes(model.accessories?.[arguments[1]]?.type);"
253
241
  }
@@ -264,7 +252,7 @@
264
252
  "items": [
265
253
  {
266
254
  "key": "accessories[].defaultLockState",
267
- "flex": "0 0 25%"
255
+ "flex": "0 0 33%"
268
256
  }
269
257
  ]
270
258
  },
@@ -278,10 +266,32 @@
278
266
  "items": [
279
267
  {
280
268
  "key": "accessories[].defaultPosition",
281
- "flex": "0 0 25%"
269
+ "flex": "0 0 33%"
270
+ }
271
+ ]
272
+ },
273
+ {
274
+ "type": "div",
275
+ "displayFlex": true,
276
+ "flex-direction": "row",
277
+ "condition": {
278
+ "functionBody": "return ['Thermostat'].includes(model.accessories?.[arguments[1]]?.type);"
279
+ },
280
+ "items": [
281
+ {
282
+ "key": "accessories[].temperatureUnits",
283
+ "flex": "0 0 33%"
284
+ },
285
+ {
286
+ "key": "accessories[].defaultThermostatState",
287
+ "flex": "0 0 33%"
288
+ },
289
+ {
290
+ "key": "accessories[].defaultTemperature",
291
+ "flex": "0 0 33%"
282
292
  }
283
293
  ]
284
- },
294
+ },
285
295
  {
286
296
  "type": "div",
287
297
  "displayFlex": true,
@@ -289,19 +299,144 @@
289
299
  "items": [
290
300
  {
291
301
  "key": "accessories[].disableLogging",
292
- "flex": "0 1 25%"
302
+ "flex": "0 1 33%"
293
303
  },
294
304
  {
295
305
  "key": "accessories[].resetOnRestart",
296
- "flex": "0 1 25%",
306
+ "flex": "0 1 33%",
297
307
  "condition": {
298
308
  "functionBody": "return model.accessories?.[arguments[1]]?.timer?.delay === undefined;"
299
309
  }
300
- }
310
+ }
311
+ ]
312
+ }
313
+ ]
314
+ },
315
+ {
316
+ "type": "fieldset",
317
+ "title": "${config.title.trigger}",
318
+ "description": "${config.description.trigger}",
319
+ "condition": {
320
+ "functionBody": "const type = model.accessories?.[arguments[1]]?.type; return type !== undefined && type !== 'Thermostat';"
321
+ },
322
+ "items": [
323
+ {
324
+ "type": "div",
325
+ "displayFlex": true,
326
+ "flex-direction": "row",
327
+ "items": [
328
+ {
329
+ "key": "accessories[].trigger.type",
330
+ "flex": "1 1 33%"
331
+ },
332
+ {
333
+ "key": "accessories[].trigger.interval",
334
+ "flex": "1 1 33%",
335
+ "condition": {
336
+ "functionBody": "return model.accessories?.[arguments[1]]?.trigger?.type === 'INTERVAL';"
337
+ }
338
+ },
339
+ {
340
+ "key": "accessories[].trigger.units",
341
+ "flex": "1 1 33%",
342
+ "condition": {
343
+ "functionBody": "return model.accessories?.[arguments[1]]?.trigger?.type === 'INTERVAL';"
344
+ }
345
+ }
346
+ ]
347
+ },
348
+ {
349
+ "key": "accessories[].trigger.cron",
350
+ "condition": {
351
+ "functionBody": "return model.accessories?.[arguments[1]]?.trigger?.type === 'CRON';"
352
+ }
353
+ },
354
+ {
355
+ "key": "accessories[].trigger.random",
356
+ "condition": {
357
+ "functionBody": "return model.accessories?.[arguments[1]]?.trigger?.type === 'INTERVAL';"
358
+ }
359
+ }
360
+ ]
361
+ },
362
+ {
363
+ "type": "fieldset",
364
+ "title": "${config.title.timer}",
365
+ "description": "${config.description.timer}",
366
+ "condition": {
367
+ "functionBody": "const type = model.accessories?.[arguments[1]]?.type; return type !== undefined && type !== 'Thermostat';"
368
+ },
369
+ "items": [
370
+ {
371
+ "type": "div",
372
+ "displayFlex": true,
373
+ "flex-direction": "row",
374
+ "items": [
375
+ {
376
+ "key": "accessories[].timer.delay",
377
+ "flex": "1 1 33%"
378
+ },
379
+ {
380
+ "key": "accessories[].timer.units",
381
+ "flex": "1 1 33%"
382
+ },
383
+ {
384
+ "flex": "1 1 33%"
385
+ }
301
386
  ]
387
+ },
388
+ "accessories[].timer.random"
389
+ ]
390
+ },
391
+ {
392
+ "type": "fieldset",
393
+ "title": "${config.title.commands}",
394
+ "description": "${config.description.commands}",
395
+ "items": [
396
+ {
397
+ "key": "accessories[].commandOn",
398
+ "condition": {
399
+ "functionBody": "return ['Lightbulb','Outlet','Switch','Thermostat'].includes(model.accessories?.[arguments[1]]?.type);"
400
+ }
401
+ },
402
+ {
403
+ "key": "accessories[].commandOff",
404
+ "condition": {
405
+ "functionBody": "return ['Lightbulb','Outlet','Switch','Thermostat'].includes(model.accessories?.[arguments[1]]?.type);"
406
+ }
407
+ },
408
+ {
409
+ "key": "accessories[].commandLock",
410
+ "condition": {
411
+ "functionBody": "return ['LockMechanism'].includes(model.accessories?.[arguments[1]]?.type);"
412
+ }
413
+ },
414
+ {
415
+ "key": "accessories[].commandUnlock",
416
+ "condition": {
417
+ "functionBody": "return ['LockMechanism'].includes(model.accessories?.[arguments[1]]?.type);"
418
+ }
419
+ },
420
+ {
421
+ "key": "accessories[].commandOpen",
422
+ "condition": {
423
+ "functionBody": "return ['Door', 'Window', 'WindowCovering'].includes(model.accessories?.[arguments[1]]?.type);"
424
+ }
425
+ },
426
+ {
427
+ "key": "accessories[].commandClose",
428
+ "condition": {
429
+ "functionBody": "return ['Door', 'Window', 'WindowCovering'].includes(model.accessories?.[arguments[1]]?.type);"
430
+ }
431
+ },
432
+ {
433
+ "key": "accessories[].commandTemperature",
434
+ "condition": {
435
+ "functionBody": "return ['Thermostat'].includes(model.accessories?.[arguments[1]]?.type);"
436
+ }
302
437
  }
303
438
  ]
304
- }
439
+ }
305
440
  ]
306
441
  }
307
442
  ]
@@ -10,17 +10,19 @@ export declare abstract class DummyAccessory<C extends DummyConfig> {
10
10
  protected readonly persistPath: string;
11
11
  static identifier(config: DummyConfig): string;
12
12
  protected readonly accessoryService: Service;
13
- private readonly timer;
13
+ private readonly _timer?;
14
+ private readonly _trigger?;
14
15
  constructor(Service: ServiceType, Characteristic: CharacteristicType, accessory: PlatformAccessory, config: C, log: Log, persistPath: string, isGrouped: boolean);
15
16
  protected abstract getAccessoryType(): AccessoryType;
17
+ protected abstract trigger(): Promise<void>;
18
+ protected abstract reset(): Promise<void>;
16
19
  get subtype(): string | undefined;
17
20
  teardown(): void;
18
21
  protected get identifier(): string;
19
22
  protected get isStateful(): boolean;
20
23
  protected get defaultStateStorageKey(): string;
21
- protected startTimer(callback: () => Promise<void>): void;
24
+ protected startTimer(): void;
22
25
  protected cancelTimer(): void;
23
26
  protected executeCommand(command: string): void;
24
- protected assert(...keys: (keyof C)[]): boolean;
25
- protected logIfDesired(message: string, ...parameters: string[]): void;
27
+ protected logIfDesired(message: string, ...parameters: (string | number)[]): void;
26
28
  }