homebridge-dummy 1.0.0-alpha.3 → 1.0.0-alpha.4

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 (50) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +47 -10
  3. package/config.schema.json +68 -15
  4. package/dist/accessory/base.d.ts +9 -8
  5. package/dist/accessory/base.js +19 -7
  6. package/dist/accessory/base.js.map +1 -1
  7. package/dist/accessory/group.d.ts +14 -0
  8. package/dist/accessory/group.js +39 -0
  9. package/dist/accessory/group.js.map +1 -0
  10. package/dist/accessory/helpers.d.ts +5 -0
  11. package/dist/accessory/helpers.js +22 -0
  12. package/dist/accessory/helpers.js.map +1 -0
  13. package/dist/accessory/lightbulb.d.ts +7 -7
  14. package/dist/accessory/lightbulb.js +21 -15
  15. package/dist/accessory/lightbulb.js.map +1 -1
  16. package/dist/accessory/lock.d.ts +15 -0
  17. package/dist/accessory/lock.js +63 -0
  18. package/dist/accessory/lock.js.map +1 -0
  19. package/dist/accessory/onoff.d.ts +4 -5
  20. package/dist/accessory/onoff.js +16 -15
  21. package/dist/accessory/onoff.js.map +1 -1
  22. package/dist/accessory/outlet.d.ts +5 -0
  23. package/dist/accessory/outlet.js +8 -0
  24. package/dist/accessory/outlet.js.map +1 -0
  25. package/dist/accessory/sensor.d.ts +19 -0
  26. package/dist/accessory/sensor.js +68 -0
  27. package/dist/accessory/sensor.js.map +1 -0
  28. package/dist/accessory/switch.d.ts +3 -6
  29. package/dist/accessory/switch.js +3 -5
  30. package/dist/accessory/switch.js.map +1 -1
  31. package/dist/homebridge/platform.js +6 -16
  32. package/dist/homebridge/platform.js.map +1 -1
  33. package/dist/homebridge-ui/public/index.html +1 -1
  34. package/dist/i18n/en.d.ts +50 -1
  35. package/dist/i18n/en.js +50 -1
  36. package/dist/i18n/en.js.map +1 -1
  37. package/dist/i18n/i18n.d.ts +50 -1
  38. package/dist/i18n/template.d.ts +50 -1
  39. package/dist/i18n/zz.d.ts +50 -1
  40. package/dist/model/types.d.ts +36 -6
  41. package/dist/model/types.js +22 -0
  42. package/dist/model/types.js.map +1 -1
  43. package/dist/tools/configMigration.d.ts +2 -2
  44. package/dist/tools/configMigration.js +1 -1
  45. package/dist/tools/configMigration.js.map +1 -1
  46. package/dist/tools/storage.d.ts +2 -2
  47. package/dist/tools/storage.js +2 -2
  48. package/dist/tools/storage.js.map +1 -1
  49. package/package.json +1 -1
  50. package/src/homebridge-ui/public/index.html +0 -35
package/CHANGELOG.md CHANGED
@@ -6,7 +6,7 @@ All notable changes to homebridge-dummy will be documented in this file.
6
6
 
7
7
  Please report any issues you encounter here: https://github.com/mpatfield/homebridge-dummy/issues
8
8
 
9
- ## 1.0.0-alpha.3 (2025-07-01)
9
+ ## 1.0.0-alpha.4 (2025-07-03)
10
10
 
11
11
  ### ‼️ BREAKING This version is a complete code rewrite. Automations using Homebridge Dummy accessories will need to be reconfigured.
12
12
 
package/README.md CHANGED
@@ -71,7 +71,7 @@ The first thing the flow does is create a backup called `config.json.bak` in you
71
71
 
72
72
  With this plugin, you can create any number of fake accessories that will do nothing when triggered. This can be very useful for advanced automation with HomeKit scenes.
73
73
 
74
- Currently, only Lightbulbs and Switches are supported but we plan to add more options over the coming months.
74
+ Currently, only Lightbulbs, Locks, Outlets, and Switches are supported. If there is a particular device you'd like to see supported, please [create an issue](https://github.com/mpatfield/homebridge-dummy/issues/new?template=new-issue.md).
75
75
 
76
76
  ## Configuration
77
77
 
@@ -83,15 +83,18 @@ Using the Homebridge Config UI is the easiest way to set up this plugin. However
83
83
  "accessories": [
84
84
  {
85
85
  "name": "string",
86
- "type": "Lightbulb | Switch",
86
+ "type": "Lightbulb | LockMechanism | Outlet | Switch",
87
87
  "timer": {
88
- "delay": 1,
88
+ "delay": number,
89
89
  "units": "SECONDS | MINUTES | HOURS",
90
- "random": false
90
+ "random": true | false
91
91
  },
92
- "defaultOn": false,
93
- "defaultBrightness": 100,
94
- "disableLogging": false
92
+ "defaultOnOff": 1 | 0,
93
+ "defaultBrightness": 0-100,
94
+ "defaultLockState": 0 | 1,
95
+ "sensor": "CarbonDioxideSensor | CarbonMonoxideSensor | ContactSensor | LeakSensor | MotionSensor | OccupancySensor | SmokeSensor",
96
+ "resetOnRestart": true | false,
97
+ "disableLogging": true | false
95
98
  }
96
99
  // ...additional accessories...
97
100
  ],
@@ -102,16 +105,24 @@ Using the Homebridge Config UI is the easiest way to set up this plugin. However
102
105
  All fields are optional unless noted with an asterisk (*)
103
106
 
104
107
  - `name`* - The display name for the accessory in HomeKit
105
- - `type`* - The type of accessory, currently `Lightbulb` and `Switch` are supported
108
+ - `type`* - The type of accessory, currently `Lightbulb`, `LockMechanism`, `Outlet`, and `Switch` are supported
106
109
 
107
110
  - `timer.delay` — If defined, the switch will automatically toggle after this many seconds/minutes/hours
108
111
  - `timer.units` — The units to use for delay above (`SECONDS`, `MINUTES`, or `HOURS`). *Required if delay is set.
109
112
  - `timer.random` — If true, the delay will be randomized with a maximum value of `timer.delay`
110
113
 
111
- - `defaultOn` — If true, the states are reversed so that the default state is _on_. Only applicable to Switches.
114
+ - `defaultOnOff` — Initial value. Default _ON_ = 1, default _OFF_ = 0
112
115
 
113
116
  - `defaultBrightness` — If set, lightbulb will have additional dimmer settings with this default brightness percentage
114
117
 
118
+ - `defaultLockState` - The initial value for the lock. UNSECURED (Unlocked) = 0, SECURED (Locked) = 1
119
+
120
+ - `sensor` - Optionally attach a sensor that mirrors the state of the parent accessory
121
+ - Only works with `Lightbulb`, `Outlet`, and `Switch`
122
+ - Valid values are `CarbonDioxideSensor`, `CarbonMonoxideSensor`, `ContactSensor`, `LeakSensor`, `MotionSensor`, `OccupancySensor`, or `SmokeSensor`
123
+
124
+ - `resetOnRestart` _ If true, all values return to defaults when Homebridge restarts. Ignored when timer is defined.
125
+
115
126
  - `disableLogging` — If true, state changes will not be logged
116
127
 
117
128
  ## Examples
@@ -145,7 +156,7 @@ All fields are optional unless noted with an asterisk (*)
145
156
  "delay": 5,
146
157
  "units": "SECONDS"
147
158
  },
148
- "defaultOn": true
159
+ "defaultOnOff": true
149
160
  }
150
161
  ```
151
162
 
@@ -183,6 +194,32 @@ All fields are optional unless noted with an asterisk (*)
183
194
  }
184
195
  ```
185
196
 
197
+ ### Lock
198
+ ```json
199
+ {
200
+ "name": "Lock",
201
+ "type": "LockMechanism",
202
+ "timer": {
203
+ "delay": 10,
204
+ "units": "MINUTES"
205
+ },
206
+ "defaultLockState": 0
207
+ }
208
+ ```
209
+
210
+ ### Motion Sensor Switch
211
+ ```json
212
+ {
213
+ "name": "Motion Switch",
214
+ "type": "Switch",
215
+ "timer": {
216
+ "delay": 3,
217
+ "units": "MINUTES"
218
+ },
219
+ "sensor": "MotionSensor"
220
+ }
221
+ ```
222
+
186
223
  ## Credits
187
224
 
188
225
  Special thanks to [@nfarina](https://github.com/nfarina) for creating the original version of this plugin and maintaining it for almost 10 (!!!) years
@@ -47,8 +47,8 @@
47
47
  "type": {
48
48
  "type": "string",
49
49
  "title": "${config.title.type}",
50
- "enum": ["Lightbulb", "Switch"],
51
- "enumNames": ["${config.enumNames.lightbulb}", "${config.enumNames.switch}"],
50
+ "enum": ["Lightbulb", "LockMechanism", "Outlet", "Switch"],
51
+ "enumNames": ["${config.enumNames.lightbulb}", "${config.enumNames.lockMechanism}", "${config.enumNames.outlet}", "${config.enumNames.switch}"],
52
52
  "required": true
53
53
  },
54
54
  "timer": { "$ref": "#/definitions/timer" },
@@ -58,9 +58,27 @@
58
58
  "maximum": 100,
59
59
  "title": "${config.title.defaultBrightness}"
60
60
  },
61
- "defaultOn": {
61
+ "defaultOnOff": {
62
+ "type": "number",
63
+ "title": "${config.title.defaultState}",
64
+ "enum": [1, 0],
65
+ "enumNames": ["${config.enumNames.on}", "${config.enumNames.off}"]
66
+ },
67
+ "defaultLockState": {
68
+ "type": "number",
69
+ "title": "${config.title.defaultState}",
70
+ "enum": [1, 0],
71
+ "enumNames": ["${config.enumNames.secured}", "${config.enumNames.unsecured}"]
72
+ },
73
+ "sensor": {
74
+ "type": "string",
75
+ "title": "${config.title.sensor}",
76
+ "enum": ["CarbonDioxideSensor", "CarbonMonoxideSensor", "ContactSensor", "LeakSensor", "MotionSensor", "OccupancySensor", "SmokeSensor"],
77
+ "enumNames": ["${config.enumNames.carbonDioxideSensor}", "${config.enumNames.carbonMonoxideSensor}", "${config.enumNames.contactSensor}", "${config.enumNames.leakSensor}", "${config.enumNames.motionSensor}", "${config.enumNames.occupancySensor}", "${config.enumNames.smokeSensor}"]
78
+ },
79
+ "resetOnRestart": {
62
80
  "type": "boolean",
63
- "title": "${config.title.defaultOn}"
81
+ "title": "${config.title.resetOnRestart}"
64
82
  },
65
83
  "disableLogging": {
66
84
  "title": "${config.title.disableLogging}",
@@ -102,7 +120,7 @@
102
120
  "title": "${config.title.timer}",
103
121
  "description": "${config.description.timer}",
104
122
  "condition": {
105
- "functionBody": "return model.accessories?.[arguments[1]]?.type;"
123
+ "functionBody": "return model.accessories?.[arguments[1]]?.type !== undefined;"
106
124
  },
107
125
  "items": [
108
126
  {
@@ -132,30 +150,65 @@
132
150
  "type": "fieldset",
133
151
  "title": "${config.title.options}",
134
152
  "condition": {
135
- "functionBody": "return ['Lightbulb','Switch'].includes(model.accessories?.[arguments[1]]?.type);"
153
+ "functionBody": "return model.accessories?.[arguments[1]]?.type !== undefined;"
136
154
  },
137
155
  "items": [
138
156
  {
139
157
  "type": "div",
140
158
  "displayFlex": true,
141
159
  "flex-direction": "row",
160
+ "condition": {
161
+ "functionBody": "return ['Lightbulb','Outlet','Switch'].includes(model.accessories?.[arguments[1]]?.type);"
162
+ },
142
163
  "items": [
143
164
  {
144
- "key": "accessories[].defaultOn",
145
- "flex": "1 1 0"
165
+ "key": "accessories[].defaultOnOff",
166
+ "flex": "0 0 25%"
146
167
  },
147
168
  {
148
- "key": "accessories[].disableLogging",
149
- "flex": "1 1 0"
150
- }
169
+ "key": "accessories[].sensor",
170
+ "flex": "0 0 25%"
171
+ },
172
+ {
173
+ "key": "accessories[].defaultBrightness",
174
+ "flex": "0 0 25%",
175
+ "condition": {
176
+ "functionBody": "return ['Lightbulb'].includes(model.accessories?.[arguments[1]]?.type);"
177
+ }
178
+ }
151
179
  ]
152
180
  },
153
181
  {
154
- "key": "accessories[].defaultBrightness",
155
- "flex": "1 1 0",
182
+ "type": "div",
183
+ "displayFlex": true,
184
+ "flex-direction": "row",
156
185
  "condition": {
157
- "functionBody": "return ['Lightbulb'].includes(model.accessories?.[arguments[1]]?.type);"
158
- }
186
+ "functionBody": "return ['LockMechanism'].includes(model.accessories?.[arguments[1]]?.type);"
187
+ },
188
+ "items": [
189
+ {
190
+ "key": "accessories[].defaultLockState",
191
+ "flex": "0 0 25%"
192
+ }
193
+ ]
194
+ },
195
+ {
196
+ "type": "div",
197
+ "displayFlex": true,
198
+ "flex-direction": "row",
199
+ "items": [
200
+ {
201
+ "key": "accessories[].disableLogging",
202
+ "flex": "0 1 25%"
203
+ },
204
+ {
205
+ "key": "accessories[].resetOnRestart",
206
+ "flex": "0 1 25%",
207
+ "condition": {
208
+ "functionBody": "return model.accessories?.[arguments[1]]?.timer?.delay === undefined;"
209
+ }
210
+ }
211
+ ]
159
212
  }
160
213
  ]
161
214
  }
@@ -1,23 +1,24 @@
1
1
  import { PlatformAccessory, Service } from 'homebridge';
2
- import { CharacteristicType, DummyAccessoryConfig, ServiceType } from '../model/types.js';
2
+ import { AccessoryType, CharacteristicType, DummyConfig, ServiceType } from '../model/types.js';
3
3
  import { Log } from '../tools/log.js';
4
- export declare abstract class DummyAccessory {
4
+ export declare abstract class DummyAccessory<C extends DummyConfig> {
5
5
  protected readonly Service: ServiceType;
6
6
  protected readonly Characteristic: CharacteristicType;
7
7
  protected readonly accessory: PlatformAccessory;
8
- protected readonly config: DummyAccessoryConfig;
8
+ protected readonly config: C;
9
9
  protected readonly log: Log;
10
10
  protected readonly persistPath: string;
11
- private readonly caller;
12
- static identifier(config: DummyAccessoryConfig): string;
11
+ static identifier(config: DummyConfig): string;
13
12
  protected readonly accessoryService: Service;
14
13
  private readonly timer;
15
- constructor(Service: ServiceType, Characteristic: CharacteristicType, accessory: PlatformAccessory, config: DummyAccessoryConfig, log: Log, persistPath: string, caller: string);
16
- protected abstract getAccessoryService(): Service;
14
+ constructor(Service: ServiceType, Characteristic: CharacteristicType, accessory: PlatformAccessory, config: C, log: Log, persistPath: string, isGrouped: boolean);
15
+ protected abstract getAccessoryType(): AccessoryType;
17
16
  teardown(): void;
18
17
  protected get identifier(): string;
18
+ protected get isStateful(): boolean;
19
+ protected get defaultStateStorageKey(): string;
19
20
  protected startTimer(callback: () => Promise<void>): void;
20
21
  protected cancelTimer(): void;
21
- protected assert(...keys: (keyof any)[]): boolean;
22
+ protected assert(...keys: (keyof C)[]): boolean;
22
23
  protected logIfDesired(message: string, ...parameters: string[]): void;
23
24
  }
@@ -2,6 +2,7 @@ import { PLATFORM_NAME, PLUGIN_ALIAS } from '../homebridge/settings.js';
2
2
  import getVersion from '../tools/version.js';
3
3
  import { Timer } from '../model/timer.js';
4
4
  import { assert } from '../tools/validation.js';
5
+ import { STORAGE_KEY_SUFFIX_DEFAULT_STATE } from '../tools/storage.js';
5
6
  export class DummyAccessory {
6
7
  Service;
7
8
  Characteristic;
@@ -9,28 +10,34 @@ export class DummyAccessory {
9
10
  config;
10
11
  log;
11
12
  persistPath;
12
- caller;
13
13
  static identifier(config) {
14
14
  return `${PLATFORM_NAME}:${config.type}:${config.name.replace(/\s+/g, '')}`;
15
15
  }
16
16
  accessoryService;
17
17
  timer;
18
- constructor(Service, Characteristic, accessory, config, log, persistPath, caller) {
18
+ constructor(Service, Characteristic, accessory, config, log, persistPath, isGrouped) {
19
19
  this.Service = Service;
20
20
  this.Characteristic = Characteristic;
21
21
  this.accessory = accessory;
22
22
  this.config = config;
23
23
  this.log = log;
24
24
  this.persistPath = persistPath;
25
- this.caller = caller;
26
25
  this.timer = new Timer(config.name, config.disableLogging ? undefined : log);
26
+ const serviceInstance = Service[this.getAccessoryType()];
27
+ if (isGrouped) {
28
+ this.accessoryService =
29
+ accessory.getServiceById(serviceInstance, this.identifier) ||
30
+ accessory.addService(serviceInstance, config.name, this.identifier);
31
+ return;
32
+ }
27
33
  accessory.getService(Service.AccessoryInformation)
28
34
  .setCharacteristic(Characteristic.Name, config.name)
29
35
  .setCharacteristic(Characteristic.ConfiguredName, config.name)
30
36
  .setCharacteristic(Characteristic.Manufacturer, PLUGIN_ALIAS)
31
- .setCharacteristic(Characteristic.Model, caller)
37
+ .setCharacteristic(Characteristic.Model, config.type)
38
+ .setCharacteristic(Characteristic.SerialNumber, accessory.UUID)
32
39
  .setCharacteristic(Characteristic.FirmwareRevision, getVersion());
33
- this.accessoryService = this.getAccessoryService();
40
+ this.accessoryService = accessory.getService(serviceInstance) || accessory.addService(serviceInstance);
34
41
  }
35
42
  teardown() {
36
43
  this.timer.teardown();
@@ -38,11 +45,17 @@ export class DummyAccessory {
38
45
  get identifier() {
39
46
  return DummyAccessory.identifier(this.config);
40
47
  }
48
+ get isStateful() {
49
+ return this.config.timer?.delay === undefined && !this.config.resetOnRestart;
50
+ }
51
+ get defaultStateStorageKey() {
52
+ return `${this.identifier}:${STORAGE_KEY_SUFFIX_DEFAULT_STATE}`;
53
+ }
41
54
  startTimer(callback) {
42
55
  if (!this.config.timer?.delay) {
43
56
  return;
44
57
  }
45
- if (!assert(this.log, this.caller, this.config.timer, 'units')) {
58
+ if (!assert(this.log, this.config.name, this.config.timer, 'units')) {
46
59
  return;
47
60
  }
48
61
  this.timer.start(this.config.timer, callback);
@@ -50,7 +63,6 @@ export class DummyAccessory {
50
63
  cancelTimer() {
51
64
  this.timer.cancel();
52
65
  }
53
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
66
  assert(...keys) {
55
67
  return assert(this.log, this.config.name, this.config, ...keys);
56
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/accessory/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/accessory/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { PlatformAccessory } from 'homebridge';
2
+ import { CharacteristicType, GroupConfig, ServiceType } from '../model/types.js';
3
+ import { Log } from '../tools/log.js';
4
+ export declare class GroupAccessory {
5
+ protected readonly Service: ServiceType;
6
+ protected readonly Characteristic: CharacteristicType;
7
+ protected readonly accessory: PlatformAccessory;
8
+ protected readonly config: GroupConfig;
9
+ protected readonly log: Log;
10
+ protected readonly persistPath: string;
11
+ private readonly accessories;
12
+ constructor(Service: ServiceType, Characteristic: CharacteristicType, accessory: PlatformAccessory, config: GroupConfig, log: Log, persistPath: string);
13
+ teardown(): void;
14
+ }
@@ -0,0 +1,39 @@
1
+ import { createAccessory } from './helpers.js';
2
+ import { PLUGIN_ALIAS } from '../homebridge/settings.js';
3
+ import getVersion from '../tools/version.js';
4
+ export class GroupAccessory {
5
+ Service;
6
+ Characteristic;
7
+ accessory;
8
+ config;
9
+ log;
10
+ persistPath;
11
+ accessories = [];
12
+ constructor(Service, Characteristic, accessory, config, log, persistPath) {
13
+ this.Service = Service;
14
+ this.Characteristic = Characteristic;
15
+ this.accessory = accessory;
16
+ this.config = config;
17
+ this.log = log;
18
+ this.persistPath = persistPath;
19
+ accessory.getService(Service.AccessoryInformation)
20
+ .setCharacteristic(Characteristic.Manufacturer, PLUGIN_ALIAS)
21
+ .setCharacteristic(Characteristic.Model, GroupAccessory.name)
22
+ .setCharacteristic(Characteristic.SerialNumber, accessory.UUID)
23
+ .setCharacteristic(Characteristic.FirmwareRevision, getVersion());
24
+ for (const dummyConfig of config.accessories) {
25
+ const dummyAccessory = createAccessory(this.Service, this.Characteristic, accessory, dummyConfig, this.log, persistPath, true);
26
+ if (!dummyAccessory) {
27
+ continue;
28
+ }
29
+ this.accessories.push(dummyAccessory);
30
+ }
31
+ ;
32
+ }
33
+ teardown() {
34
+ this.accessories.forEach(accessory => {
35
+ accessory.teardown();
36
+ });
37
+ }
38
+ }
39
+ //# sourceMappingURL=group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group.js","sourceRoot":"","sources":["../../src/accessory/group.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAK/C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAE7C,MAAM,OAAO,cAAc;IAKJ;IACA;IACA;IACA;IACA;IACA;IARJ,WAAW,GAAoC,EAAE,CAAC;IAEnE,YACqB,OAAoB,EACpB,cAAkC,EAClC,SAA4B,EAC5B,MAAmB,EACnB,GAAQ,EACR,WAAmB;QALnB,YAAO,GAAP,OAAO,CAAa;QACpB,mBAAc,GAAd,cAAc,CAAoB;QAClC,cAAS,GAAT,SAAS,CAAmB;QAC5B,WAAM,GAAN,MAAM,CAAa;QACnB,QAAG,GAAH,GAAG,CAAK;QACR,gBAAW,GAAX,WAAW,CAAQ;QAGtC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,oBAAoB,CAAE;aAChD,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,YAAY,CAAC;aAC5D,iBAAiB,CAAC,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC;aAC5D,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,CAAC;aAC9D,iBAAiB,CAAC,cAAc,CAAC,gBAAgB,EAAE,UAAU,EAAE,CAAC,CAAC;QAEpE,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YAE7C,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;YAC/H,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,SAAS;YACX,CAAC;YAED,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxC,CAAC;QAAA,CAAC;IACJ,CAAC;IAEM,QAAQ;QACb,IAAI,CAAC,WAAW,CAAC,OAAO,CAAE,SAAS,CAAC,EAAE;YACpC,SAAS,CAAC,QAAQ,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ import { PlatformAccessory } from 'homebridge';
2
+ import { DummyAccessory } from './base.js';
3
+ import * as Types from '../model/types.js';
4
+ import { Log } from '../tools/log.js';
5
+ export declare function createAccessory(Service: Types.ServiceType, Characteristic: Types.CharacteristicType, accessory: PlatformAccessory, config: Types.DummyConfig, log: Log, persistPath: string, isGrouped?: boolean): DummyAccessory<Types.DummyConfig> | null;
@@ -0,0 +1,22 @@
1
+ import { LightbulbAccessory } from './lightbulb.js';
2
+ import { LockAccessory } from './lock.js';
3
+ import { OutletAccessory } from './outlet.js';
4
+ import { SwitchAccessory } from './switch.js';
5
+ import { strings } from '../i18n/i18n.js';
6
+ import * as Types from '../model/types.js';
7
+ export function createAccessory(Service, Characteristic, accessory, config, log, persistPath, isGrouped = false) {
8
+ switch (config.type) {
9
+ case Types.AccessoryType.Lightbulb:
10
+ return new LightbulbAccessory(Service, Characteristic, accessory, config, log, persistPath, isGrouped);
11
+ case Types.AccessoryType.LockMechanism:
12
+ return new LockAccessory(Service, Characteristic, accessory, config, log, persistPath, isGrouped);
13
+ case Types.AccessoryType.Outlet:
14
+ return new OutletAccessory(Service, Characteristic, accessory, config, log, persistPath, isGrouped);
15
+ case Types.AccessoryType.Switch:
16
+ return new SwitchAccessory(Service, Characteristic, accessory, config, log, persistPath, isGrouped);
17
+ default:
18
+ log.error(strings.startup.unsupportedType, `'${config.type}'`);
19
+ return null;
20
+ }
21
+ }
22
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/accessory/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAI3C,MAAM,UAAU,eAAe,CAC7B,OAA0B,EAC1B,cAAwC,EACxC,SAA4B,EAC5B,MAAyB,EACzB,GAAQ,EACR,WAAmB,EACnB,YAAqB,KAAK;IAG1B,QAAO,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,KAAK,CAAC,aAAa,CAAC,SAAS;YAChC,OAAO,IAAI,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAA+B,EAAE,GAAG,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QAClI,KAAK,KAAK,CAAC,aAAa,CAAC,aAAa;YACpC,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAA0B,EAAE,GAAG,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QACxH,KAAK,KAAK,CAAC,aAAa,CAAC,MAAM;YAC7B,OAAO,IAAI,eAAe,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAA4B,EAAE,GAAG,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QAC5H,KAAK,KAAK,CAAC,aAAa,CAAC,MAAM;YAC7B,OAAO,IAAI,eAAe,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAA4B,EAAE,GAAG,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QAC5H;YACE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,EAAE,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;YAC/D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -1,14 +1,14 @@
1
- import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
1
+ import { CharacteristicValue, PlatformAccessory } from 'homebridge';
2
2
  import { OnOffAccessory } from './onoff.js';
3
- import { CharacteristicType, LightbulbConfig, ServiceType } from '../model/types.js';
3
+ import { AccessoryType, CharacteristicType, LightbulbConfig, ServiceType } from '../model/types.js';
4
4
  import { Log } from '../tools/log.js';
5
- export declare class LightbulbAccessory extends OnOffAccessory {
6
- private isDimmer;
5
+ export declare class LightbulbAccessory extends OnOffAccessory<LightbulbConfig> {
7
6
  private brightness;
8
- constructor(Service: ServiceType, Characteristic: CharacteristicType, accessory: PlatformAccessory, lightbulbConfig: LightbulbConfig, log: Log, persistPath: string);
9
- private get brightnessStorageKey();
7
+ constructor(Service: ServiceType, Characteristic: CharacteristicType, accessory: PlatformAccessory, config: LightbulbConfig, log: Log, persistPath: string, isGrouped: boolean);
8
+ private get isDimmer();
9
+ private get defaultBrightnessStorageKey();
10
+ protected getAccessoryType(): AccessoryType;
10
11
  private initializeBrightness;
11
- protected getAccessoryService(): Service;
12
12
  logOnState(value: CharacteristicValue): void;
13
13
  protected getBrightness(): Promise<CharacteristicValue>;
14
14
  protected setBrightness(value: CharacteristicValue): Promise<void>;
@@ -1,31 +1,35 @@
1
1
  import { OnOffAccessory } from './onoff.js';
2
2
  import { strings } from '../i18n/i18n.js';
3
- import { STORAGE_KEY_SUFFIX_BRIGHTNESS, storageGet, storageSet } from '../tools/storage.js';
4
- const DEFAULT_BRIGHTNESS = 0;
3
+ import { AccessoryType } from '../model/types.js';
4
+ import { STORAGE_KEY_SUFFIX_DEFAULT_BRIGHTNESS, storageGet, storageSet } from '../tools/storage.js';
5
+ const NO_BRIGHTNESS = -1;
5
6
  export class LightbulbAccessory extends OnOffAccessory {
6
- isDimmer;
7
- brightness = DEFAULT_BRIGHTNESS;
8
- constructor(Service, Characteristic, accessory, lightbulbConfig, log, persistPath) {
9
- super(Service, Characteristic, accessory, lightbulbConfig, log, persistPath, LightbulbAccessory.name);
10
- this.isDimmer = lightbulbConfig.defaultBrightness !== undefined;
7
+ brightness;
8
+ constructor(Service, Characteristic, accessory, config, log, persistPath, isGrouped) {
9
+ super(Service, Characteristic, accessory, config, log, persistPath, isGrouped);
10
+ this.brightness = this.config.defaultBrightness ?? NO_BRIGHTNESS;
11
11
  if (this.isDimmer) {
12
- this.brightness = lightbulbConfig.defaultBrightness;
13
12
  this.accessoryService.getCharacteristic(this.Characteristic.Brightness)
14
13
  .onGet(this.getBrightness.bind(this))
15
14
  .onSet(this.setBrightness.bind(this));
16
15
  this.initializeBrightness();
17
16
  }
18
17
  }
19
- get brightnessStorageKey() {
20
- return `${this.identifier}:${STORAGE_KEY_SUFFIX_BRIGHTNESS}`;
18
+ get isDimmer() {
19
+ return this.brightness !== NO_BRIGHTNESS;
20
+ }
21
+ get defaultBrightnessStorageKey() {
22
+ return `${this.identifier}:${STORAGE_KEY_SUFFIX_DEFAULT_BRIGHTNESS}`;
23
+ }
24
+ getAccessoryType() {
25
+ return AccessoryType.Lightbulb;
21
26
  }
22
27
  async initializeBrightness() {
23
- this.brightness = await storageGet(this.persistPath, this.brightnessStorageKey) ?? this.brightness;
28
+ if (this.isStateful) {
29
+ this.brightness = await storageGet(this.persistPath, this.defaultBrightnessStorageKey) ?? this.brightness;
30
+ }
24
31
  this.accessoryService.updateCharacteristic(this.Characteristic.Brightness, this.brightness);
25
32
  }
26
- getAccessoryService() {
27
- return this.accessory.getService(this.Service.Lightbulb) || this.accessory.addService(this.Service.Lightbulb);
28
- }
29
33
  logOnState(value) {
30
34
  if (this.isDimmer && value) {
31
35
  this.logIfDesired(strings.accessory.lightbulb.stateOn, this.config.name, this.brightness.toLocaleString());
@@ -43,7 +47,9 @@ export class LightbulbAccessory extends OnOffAccessory {
43
47
  }
44
48
  this.brightness = value;
45
49
  this.logIfDesired(strings.accessory.lightbulb.brightness, this.config.name, this.brightness.toString());
46
- await storageSet(this.persistPath, this.brightnessStorageKey, this.brightness);
50
+ if (this.isStateful) {
51
+ await storageSet(this.persistPath, this.defaultBrightnessStorageKey, this.brightness);
52
+ }
47
53
  this.accessoryService.updateCharacteristic(this.Characteristic.Brightness, this.brightness);
48
54
  }
49
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lightbulb.js","sourceRoot":"","sources":["../../src/accessory/lightbulb.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lightbulb.js","sourceRoot":"","sources":["../../src/accessory/lightbulb.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { CharacteristicValue, PlatformAccessory } from 'homebridge';
2
+ import { DummyAccessory } from './base.js';
3
+ import { AccessoryType, CharacteristicType, LockConfig, ServiceType } from '../model/types.js';
4
+ import { Log } from '../tools/log.js';
5
+ export declare class LockAccessory extends DummyAccessory<LockConfig> {
6
+ private state;
7
+ constructor(Service: ServiceType, Characteristic: CharacteristicType, accessory: PlatformAccessory, config: LockConfig, log: Log, persistPath: string, isGrouped: boolean);
8
+ private initializeState;
9
+ protected getAccessoryType(): AccessoryType;
10
+ private get defaultState();
11
+ protected getState(): Promise<CharacteristicValue>;
12
+ protected setState(value: CharacteristicValue): Promise<void>;
13
+ private flip;
14
+ protected logLockStateState(value: CharacteristicValue): void;
15
+ }
@@ -0,0 +1,63 @@
1
+ import { DummyAccessory } from './base.js';
2
+ import { strings } from '../i18n/i18n.js';
3
+ import { AccessoryType } from '../model/types.js';
4
+ import { storageGet, storageSet } from '../tools/storage.js';
5
+ export class LockAccessory extends DummyAccessory {
6
+ state;
7
+ constructor(Service, Characteristic, accessory, config, log, persistPath, isGrouped) {
8
+ super(Service, Characteristic, accessory, config, log, persistPath, isGrouped);
9
+ this.state = this.defaultState;
10
+ this.accessoryService.getCharacteristic(Characteristic.LockTargetState)
11
+ .onGet(this.getState.bind(this))
12
+ .onSet(this.setState.bind(this));
13
+ this.accessoryService.getCharacteristic(Characteristic.LockCurrentState)
14
+ .onGet(this.getState.bind(this));
15
+ this.initializeState();
16
+ }
17
+ async initializeState() {
18
+ if (this.isStateful) {
19
+ this.state = await storageGet(this.persistPath, this.defaultStateStorageKey) ?? this.state;
20
+ }
21
+ this.accessoryService.updateCharacteristic(this.Characteristic.LockTargetState, this.state);
22
+ this.accessoryService.updateCharacteristic(this.Characteristic.LockCurrentState, this.state);
23
+ }
24
+ getAccessoryType() {
25
+ return AccessoryType.LockMechanism;
26
+ }
27
+ get defaultState() {
28
+ return this.config.defaultLockState === undefined ? this.Characteristic.LockTargetState.SECURED : this.config.defaultLockState;
29
+ }
30
+ async getState() {
31
+ return this.state;
32
+ }
33
+ async setState(value) {
34
+ if (this.state !== value) {
35
+ this.logLockStateState(value);
36
+ }
37
+ this.state = value;
38
+ if (this.isStateful) {
39
+ await storageSet(this.persistPath, this.defaultStateStorageKey, this.state);
40
+ }
41
+ else {
42
+ if (this.state !== this.defaultState) {
43
+ this.startTimer(this.flip.bind(this));
44
+ }
45
+ else {
46
+ this.cancelTimer();
47
+ }
48
+ }
49
+ this.accessoryService.updateCharacteristic(this.Characteristic.LockTargetState, this.state);
50
+ this.accessoryService.updateCharacteristic(this.Characteristic.LockCurrentState, this.state);
51
+ }
52
+ async flip() {
53
+ const opposite = this.state === this.Characteristic.LockTargetState.SECURED ?
54
+ this.Characteristic.LockTargetState.UNSECURED : this.Characteristic.LockTargetState.SECURED;
55
+ await this.setState(opposite);
56
+ }
57
+ logLockStateState(value) {
58
+ const message = value === this.Characteristic.LockTargetState.SECURED ?
59
+ strings.accessory.lock.secured : strings.accessory.lock.unsecured;
60
+ this.logIfDesired(message, this.config.name);
61
+ }
62
+ }
63
+ //# sourceMappingURL=lock.js.map