@switchbot/homebridge-switchbot 4.0.0-beta.0 → 4.0.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.
@@ -42,10 +42,21 @@ export class Bot extends deviceBase {
42
42
  // Updates
43
43
  botUpdateInProgress;
44
44
  doBotUpdate;
45
+ /**
46
+ * Constructs a new instance of the Bot device.
47
+ *
48
+ * @param {SwitchBotPlatform} platform - The platform instance.
49
+ * @param {PlatformAccessory} accessory - The platform accessory.
50
+ * @param {device & devicesConfig} device - The device configuration.
51
+ *
52
+ * Initializes the Bot device, sets up the battery service, maps the device type to the appropriate HomeKit service,
53
+ * removes unnecessary services, retrieves initial values, registers event handlers, and starts update intervals.
54
+ *
55
+ * @constructor
56
+ */
45
57
  constructor(platform, accessory, device) {
46
58
  super(platform, accessory, device);
47
59
  this.platform = platform;
48
- // default placeholders
49
60
  this.getBotConfigSettings(device);
50
61
  // this is subject we use to track when we need to POST changes to the SwitchBot API
51
62
  this.doBotUpdate = new Subject();
@@ -61,270 +72,69 @@ export class Bot extends deviceBase {
61
72
  accessory.context.Battery = this.Battery;
62
73
  // Initialize Battery Characteristics
63
74
  this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name).setCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery).setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
64
- // deviceType
65
- if (this.botDeviceType === 'switch') {
66
- // Set category
67
- accessory.category = 8 /* this.hap.Categories.SWITCH */;
68
- // Initialize Switch Service
69
- accessory.context.Switch = accessory.context.Switch ?? {};
70
- this.Switch = {
71
- Name: accessory.displayName,
72
- Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch),
73
- };
74
- accessory.context.Switch = this.Switch;
75
- this.debugLog('Displaying as Switch');
76
- // Initialize Switch Characteristics
77
- this.Switch.Service.setCharacteristic(this.hap.Characteristic.Name, this.Switch.Name).getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
78
- // Remove other services
79
- this.removeFanService(accessory);
80
- this.removeLockService(accessory);
81
- this.removeDoorService(accessory);
82
- this.removeFaucetService(accessory);
83
- this.removeOutletService(accessory);
84
- this.removeWindowService(accessory);
85
- this.removeGarageDoorService(accessory);
86
- this.removeWindowCoveringService(accessory);
87
- this.removeStatefulProgrammableSwitchService(accessory);
88
- }
89
- else if (this.botDeviceType === 'garagedoor') {
90
- // Set category
91
- accessory.category = 4 /* this.hap.Categories.GARAGE_DOOR_OPENER */;
92
- // Initialize GarageDoor Service
93
- accessory.context.GarageDoor = accessory.context.GarageDoor ?? {};
94
- this.GarageDoor = {
95
- Name: accessory.displayName,
96
- Service: accessory.getService(this.hap.Service.GarageDoorOpener) ?? accessory.addService(this.hap.Service.GarageDoorOpener),
97
- };
98
- accessory.context.GarageDoor = this.GarageDoor;
99
- this.debugLog('Displaying as Garage Door Opener');
100
- // Initialize GarageDoor Characteristics
101
- this.GarageDoor.Service.setCharacteristic(this.hap.Characteristic.Name, this.GarageDoor.Name).setCharacteristic(this.hap.Characteristic.ObstructionDetected, false).getCharacteristic(this.hap.Characteristic.TargetDoorState).setProps({
102
- validValues: [0, 100],
103
- minValue: 0,
104
- maxValue: 100,
105
- minStep: 100,
106
- }).onSet(this.OnSet.bind(this));
107
- // Remove other services
108
- this.removeFanService(accessory);
109
- this.removeLockService(accessory);
110
- this.removeDoorService(accessory);
111
- this.removeFaucetService(accessory);
112
- this.removeOutletService(accessory);
113
- this.removeSwitchService(accessory);
114
- this.removeWindowService(accessory);
115
- this.removeWindowCoveringService(accessory);
116
- this.removeStatefulProgrammableSwitchService(accessory);
117
- }
118
- else if (this.botDeviceType === 'door') {
119
- // Set category
120
- accessory.category = 12 /* this.hap.Categories.DOOR */;
121
- // Initialize Door Service
122
- accessory.context.Door = accessory.context.Door ?? {};
123
- this.Door = {
124
- Name: accessory.displayName,
125
- Service: accessory.getService(this.hap.Service.Door) ?? accessory.addService(this.hap.Service.Door),
126
- };
127
- accessory.context.Door = this.Door;
128
- this.debugLog('Displaying as Door');
129
- // Initialize Door Characteristics
130
- this.Door.Service.setCharacteristic(this.hap.Characteristic.Name, this.Door.Name).setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED).getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
131
- validValues: [0, 100],
132
- minValue: 0,
133
- maxValue: 100,
134
- minStep: 100,
135
- }).onSet(this.OnSet.bind(this));
136
- // Remove other services
137
- this.removeFanService(accessory);
138
- this.removeLockService(accessory);
139
- this.removeOutletService(accessory);
140
- this.removeFaucetService(accessory);
141
- this.removeSwitchService(accessory);
142
- this.removeWindowService(accessory);
143
- this.removeGarageDoorService(accessory);
144
- this.removeWindowCoveringService(accessory);
145
- this.removeStatefulProgrammableSwitchService(accessory);
146
- }
147
- else if (this.botDeviceType === 'window') {
148
- // Set category
149
- accessory.category = 13 /* this.hap.Categories.WINDOW */;
150
- // Initialize Window Service
151
- accessory.context.Window = accessory.context.Window ?? {};
152
- this.Window = {
153
- Name: accessory.displayName,
154
- Service: accessory.getService(this.hap.Service.Window) ?? accessory.addService(this.hap.Service.Window),
155
- };
156
- accessory.context.Window = this.Window;
157
- this.debugLog('Displaying as Window');
158
- // Initialize Window Characteristics
159
- this.Window.Service.setCharacteristic(this.hap.Characteristic.Name, this.Window.Name).setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED).getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
160
- validValues: [0, 100],
161
- minValue: 0,
162
- maxValue: 100,
163
- minStep: 100,
164
- }).onSet(this.OnSet.bind(this));
165
- // Remove other services
166
- this.removeFanService(accessory);
167
- this.removeLockService(accessory);
168
- this.removeDoorService(accessory);
169
- this.removeOutletService(accessory);
170
- this.removeFaucetService(accessory);
171
- this.removeSwitchService(accessory);
172
- this.removeGarageDoorService(accessory);
173
- this.removeWindowCoveringService(accessory);
174
- this.removeStatefulProgrammableSwitchService(accessory);
175
- }
176
- else if (this.botDeviceType === 'windowcovering') {
177
- // Set category
178
- accessory.category = 14 /* this.hap.Categories.WINDOW_COVERING */;
179
- // Initialize WindowCovering Service
180
- accessory.context.WindowCovering = accessory.context.WindowCovering ?? {};
181
- this.WindowCovering = {
182
- Name: accessory.displayName,
183
- Service: accessory.getService(this.hap.Service.WindowCovering) ?? accessory.addService(this.hap.Service.WindowCovering),
184
- };
185
- accessory.context.WindowCovering = this.WindowCovering;
186
- this.debugLog('Displaying as Window Covering');
187
- // Initialize WindowCovering Characteristics
188
- this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name).setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED).getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
189
- validValues: [0, 100],
190
- minValue: 0,
191
- maxValue: 100,
192
- minStep: 100,
193
- }).onSet(this.OnSet.bind(this));
194
- // Remove other services
195
- this.removeFanService(accessory);
196
- this.removeLockService(accessory);
197
- this.removeDoorService(accessory);
198
- this.removeOutletService(accessory);
199
- this.removeFaucetService(accessory);
200
- this.removeSwitchService(accessory);
201
- this.removeWindowService(accessory);
202
- this.removeGarageDoorService(accessory);
203
- this.removeStatefulProgrammableSwitchService(accessory);
204
- }
205
- else if (this.botDeviceType === 'lock') {
206
- // Set category
207
- accessory.category = 6 /* this.hap.Categories.DOOR_LOCK */;
208
- // Initialize Lock Service
209
- accessory.context.LockMechanism = accessory.context.LockMechanism ?? {};
210
- this.LockMechanism = {
211
- Name: accessory.displayName,
212
- Service: accessory.getService(this.hap.Service.LockMechanism) ?? accessory.addService(this.hap.Service.LockMechanism),
213
- };
214
- accessory.context.LockMechanism = this.LockMechanism;
215
- this.debugLog('Displaying as Lock');
216
- // Initialize Lock Characteristics
217
- this.LockMechanism.Service.setCharacteristic(this.hap.Characteristic.Name, this.LockMechanism.Name).setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED).getCharacteristic(this.hap.Characteristic.LockTargetState).onSet(this.OnSet.bind(this));
218
- // Remove other services
219
- this.removeFanService(accessory);
220
- this.removeDoorService(accessory);
221
- this.removeOutletService(accessory);
222
- this.removeSwitchService(accessory);
223
- this.removeFaucetService(accessory);
224
- this.removeWindowService(accessory);
225
- this.removeGarageDoorService(accessory);
226
- this.removeWindowCoveringService(accessory);
227
- this.removeStatefulProgrammableSwitchService(accessory);
228
- }
229
- else if (this.botDeviceType === 'faucet') {
230
- // Set category
231
- accessory.category = 29 /* this.hap.Categories.FAUCET */;
232
- // Initialize Faucet Service
233
- accessory.context.Faucet = accessory.context.Faucet ?? {};
234
- this.Faucet = {
235
- Name: accessory.displayName,
236
- Service: accessory.getService(this.hap.Service.Faucet) ?? accessory.addService(this.hap.Service.Faucet),
237
- };
238
- accessory.context.Faucet = this.Faucet;
239
- this.debugLog('Displaying as Faucet');
240
- // Initialize Faucet Characteristics
241
- this.Faucet.Service.setCharacteristic(this.hap.Characteristic.Name, this.Faucet.Name).getCharacteristic(this.hap.Characteristic.Active).onSet(this.OnSet.bind(this));
242
- // Remove other services
243
- this.removeFanService(accessory);
244
- this.removeLockService(accessory);
245
- this.removeDoorService(accessory);
246
- this.removeOutletService(accessory);
247
- this.removeSwitchService(accessory);
248
- this.removeWindowService(accessory);
249
- this.removeGarageDoorService(accessory);
250
- this.removeWindowCoveringService(accessory);
251
- this.removeStatefulProgrammableSwitchService(accessory);
252
- }
253
- else if (this.botDeviceType === 'fan') {
254
- // Set category
255
- accessory.category = 3 /* this.hap.Categories.FAN */;
256
- // Initialize Fan Service
257
- accessory.context.Fan = accessory.context.Fan ?? {};
258
- this.Fan = {
259
- Name: accessory.displayName,
260
- Service: accessory.getService(this.hap.Service.Fanv2) ?? accessory.addService(this.hap.Service.Fanv2),
261
- };
262
- accessory.context.Fan = this.Fan;
263
- this.debugLog('Displaying as Fan');
264
- // Initialize Fan Characteristics
265
- this.Fan.Service.setCharacteristic(this.hap.Characteristic.Name, this.Fan.Name).getCharacteristic(this.hap.Characteristic.Active).onSet(this.OnSet.bind(this));
266
- // Remove other services
267
- this.removeLockService(accessory);
268
- this.removeDoorService(accessory);
269
- this.removeFaucetService(accessory);
270
- this.removeOutletService(accessory);
271
- this.removeSwitchService(accessory);
272
- this.removeWindowService(accessory);
273
- this.removeGarageDoorService(accessory);
274
- this.removeWindowCoveringService(accessory);
275
- this.removeStatefulProgrammableSwitchService(accessory);
276
- }
277
- else if (this.botDeviceType === 'stateful') {
278
- // Set category
279
- accessory.category = 15 /* this.hap.Categories.PROGRAMMABLE_SWITCH */;
280
- // Initialize StatefulProgrammableSwitch Service
281
- accessory.context.StatefulProgrammableSwitch = accessory.context.StatefulProgrammableSwitch ?? {};
282
- this.StatefulProgrammableSwitch = {
283
- Name: accessory.displayName,
284
- Service: accessory.getService(this.hap.Service.StatefulProgrammableSwitch) ?? accessory.addService(this.hap.Service.StatefulProgrammableSwitch),
285
- };
286
- accessory.context.StatefulProgrammableSwitch = this.StatefulProgrammableSwitch;
287
- this.debugLog('Displaying as Stateful Programmable Switch');
288
- // Initialize StatefulProgrammableSwitch Characteristics
289
- this.StatefulProgrammableSwitch.Service.setCharacteristic(this.hap.Characteristic.Name, this.StatefulProgrammableSwitch.Name).getCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState).onSet(this.OnSet.bind(this));
290
- // Remove other services
291
- this.removeFanService(accessory);
292
- this.removeLockService(accessory);
293
- this.removeDoorService(accessory);
294
- this.removeFaucetService(accessory);
295
- this.removeOutletService(accessory);
296
- this.removeSwitchService(accessory);
297
- this.removeWindowService(accessory);
298
- this.removeGarageDoorService(accessory);
299
- this.removeWindowCoveringService(accessory);
300
- }
301
- else if (this.botDeviceType === 'outlet') {
75
+ /**
76
+ * A mapping of device types to their corresponding HomeKit categories, services, and characteristics.
77
+ *
78
+ * Each key represents a device type and maps to an object containing:
79
+ * - `category`: The HomeKit category for the device.
80
+ * - `service`: The HomeKit service associated with the device.
81
+ * - `characteristic`: The HomeKit characteristic for the device.
82
+ */
83
+ const deviceTypeMap = {
84
+ switch: { category: 8 /* this.hap.Categories.SWITCH */, service: this.hap.Service.Switch, characteristic: this.hap.Characteristic.On },
85
+ garagedoor: { category: 4 /* this.hap.Categories.GARAGE_DOOR_OPENER */, service: this.hap.Service.GarageDoorOpener, characteristic: this.hap.Characteristic.TargetDoorState },
86
+ door: { category: 12 /* this.hap.Categories.DOOR */, service: this.hap.Service.Door, characteristic: this.hap.Characteristic.TargetPosition },
87
+ window: { category: 13 /* this.hap.Categories.WINDOW */, service: this.hap.Service.Window, characteristic: this.hap.Characteristic.TargetPosition },
88
+ windowcovering: { category: 14 /* this.hap.Categories.WINDOW_COVERING */, service: this.hap.Service.WindowCovering, characteristic: this.hap.Characteristic.TargetPosition },
89
+ lock: { category: 6 /* this.hap.Categories.DOOR_LOCK */, service: this.hap.Service.LockMechanism, characteristic: this.hap.Characteristic.LockTargetState },
90
+ faucet: { category: 29 /* this.hap.Categories.FAUCET */, service: this.hap.Service.Faucet, characteristic: this.hap.Characteristic.Active },
91
+ fan: { category: 3 /* this.hap.Categories.FAN */, service: this.hap.Service.Fanv2, characteristic: this.hap.Characteristic.Active },
92
+ stateful: { category: 15 /* this.hap.Categories.PROGRAMMABLE_SWITCH */, service: this.hap.Service.StatefulProgrammableSwitch, characteristic: this.hap.Characteristic.ProgrammableSwitchOutputState },
93
+ outlet: { category: 7 /* this.hap.Categories.OUTLET */, service: this.hap.Service.Outlet, characteristic: this.hap.Characteristic.On },
94
+ };
95
+ /**
96
+ * The type of the device, determined by mapping the botDeviceType to a value in the deviceTypeMap.
97
+ */
98
+ const deviceType = deviceTypeMap[this.botDeviceType];
99
+ if (deviceType) {
302
100
  // Set category
303
- accessory.category = 7 /* this.hap.Categories.OUTLET */;
304
- // Initialize Switch property
305
- accessory.context.Outlet = accessory.context.Outlet ?? {};
306
- this.Outlet = {
101
+ accessory.category = deviceType.category;
102
+ // Initialize Service
103
+ const contextKey = this.botDeviceType.charAt(0).toUpperCase() + this.botDeviceType.slice(1);
104
+ accessory.context[contextKey] = accessory.context[contextKey] ?? {};
105
+ this[this.botDeviceType.charAt(0).toUpperCase() + this.botDeviceType.slice(1)] = {
307
106
  Name: accessory.displayName,
308
- Service: accessory.getService(this.hap.Service.Outlet) ?? accessory.addService(this.hap.Service.Outlet),
107
+ Service: accessory.getService(deviceType.service) ?? accessory.addService(deviceType.service),
309
108
  };
310
- accessory.context.Outlet = this.Outlet;
311
- this.debugLog('Displaying as Outlet');
312
- // Initialize Outlet Characteristics
313
- this.Outlet.Service.setCharacteristic(this.hap.Characteristic.Name, this.Outlet.Name).getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
314
- // Remove other services
315
- this.removeFanService(accessory);
316
- this.removeLockService(accessory);
317
- this.removeDoorService(accessory);
318
- this.removeFaucetService(accessory);
319
- this.removeSwitchService(accessory);
320
- this.removeWindowService(accessory);
321
- this.removeGarageDoorService(accessory);
322
- this.removeWindowCoveringService(accessory);
323
- this.removeStatefulProgrammableSwitchService(accessory);
109
+ accessory.context[contextKey] = this[this.botDeviceType.charAt(0).toUpperCase() + this.botDeviceType.slice(1)];
110
+ this.debugLog(`Displaying as ${contextKey}`);
111
+ // Initialize Characteristics
112
+ this[this.botDeviceType.charAt(0).toUpperCase() + this.botDeviceType.slice(1)].Service.setCharacteristic(this.hap.Characteristic.Name, this[this.botDeviceType.charAt(0).toUpperCase() + this.botDeviceType.slice(1)].Name).getCharacteristic(deviceType.characteristic).onSet(this.OnSet.bind(this));
324
113
  }
325
114
  else {
326
115
  this.errorLog('Device Type not set');
327
116
  }
117
+ /**
118
+ * An array of service removal functions that should be executed based on the current state of the device.
119
+ * Each element in the array is a function that removes a specific service if the corresponding condition is met.
120
+ */
121
+ const servicesToRemove = [
122
+ !this.StatefulProgrammableSwitch && this.removeStatefulProgrammableSwitchService,
123
+ !this.Outlet && this.removeOutletService,
124
+ !this.Window && this.removeWindowService,
125
+ !this.GarageDoor && this.removeGarageDoorService,
126
+ this.WindowCovering && this.removeWindowCoveringService,
127
+ !this.Switch && this.removeSwitchService,
128
+ !this.Faucet && this.removeFaucetService,
129
+ !this.Door && this.removeDoorService,
130
+ !this.LockMechanism && this.removeLockService,
131
+ !this.Fan && this.removeFanService,
132
+ ].filter(Boolean);
133
+ for (const removeService of servicesToRemove) {
134
+ if (typeof removeService === 'function') {
135
+ removeService.call(this, accessory);
136
+ }
137
+ }
328
138
  // Retrieve initial values and updateHomekit
329
139
  try {
330
140
  this.debugLog('Retrieve initial values and update Homekit');
@@ -390,7 +200,7 @@ export class Bot extends deviceBase {
390
200
  // BLEmode (true if Switch Mode) | (false if Press Mode)
391
201
  this.On = this.serviceData.mode ? this.serviceData.state : false;
392
202
  const mode = this.serviceData.mode ? 'Switch' : 'Press';
393
- await this.debugLog(`${mode} Mode, On: ${this.accessory.context.On}`);
203
+ await this.debugLog(`${mode} Mode, On: ${this.On}`);
394
204
  this.accessory.context.On = this.On;
395
205
  // BatteryLevel
396
206
  this.Battery.BatteryLevel = this.serviceData.battery;
@@ -409,8 +219,8 @@ export class Bot extends deviceBase {
409
219
  await this.debugLog(`(power, battery, deviceMode) = API:(${this.deviceStatus.power}, ${this.deviceStatus.battery}, ${this.botMode}), current:(${this.accessory.context.On}, ${this.Battery.BatteryLevel}, ${this.botMode})`);
410
220
  // On
411
221
  this.On = this.botMode === 'press' ? false : this.deviceStatus.power === 'on';
222
+ await this.debugLog(`On: ${this.On}`);
412
223
  this.accessory.context.On = this.On;
413
- await this.debugLog(`openAPI On: ${this.accessory.context.On}`);
414
224
  // Battery Level
415
225
  this.Battery.BatteryLevel = this.deviceStatus.battery;
416
226
  await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
@@ -431,7 +241,7 @@ export class Bot extends deviceBase {
431
241
  .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
432
242
  .updateValue(deviceVersion);
433
243
  this.accessory.context.version = deviceVersion;
434
- await this.debugLog(`version: ${this.accessory.context.version}`);
244
+ await this.debugLog(`version: ${deviceVersion}`);
435
245
  }
436
246
  }
437
247
  async parseStatusWebhook() {
@@ -594,7 +404,7 @@ export class Bot extends deviceBase {
594
404
  }
595
405
  async BLEpushChanges() {
596
406
  await this.debugLog('BLEpushChanges');
597
- if (this.On !== this.accessory.context.On || this.allowPush) {
407
+ if ((this.On !== this.accessory.context.On) || this.allowPush) {
598
408
  await this.debugLog(`BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
599
409
  const switchBotBLE = this.platform.switchBotBLE;
600
410
  try {
@@ -677,7 +487,7 @@ export class Bot extends deviceBase {
677
487
  if (this.multiPressCount > 0) {
678
488
  await this.debugLog(`${this.multiPressCount} request(s) queued.`);
679
489
  }
680
- if (this.On !== this.accessory.context.On || this.allowPush || this.multiPressCount > 0) {
490
+ if ((this.On !== this.accessory.context.On) || this.allowPush || this.multiPressCount > 0) {
681
491
  let command = '';
682
492
  if (this.botMode === 'switch') {
683
493
  command = this.On ? 'turnOn' : 'turnOff';
@@ -699,7 +509,7 @@ export class Bot extends deviceBase {
699
509
  this.debugLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)},`);
700
510
  try {
701
511
  const { body } = await this.pushChangeRequest(bodyChange);
702
- const deviceStatus = await body;
512
+ const deviceStatus = body;
703
513
  await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
704
514
  if (await this.successfulStatusCodes(deviceStatus)) {
705
515
  await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -730,71 +540,27 @@ export class Bot extends deviceBase {
730
540
  * Handle requests to set the "On" characteristic
731
541
  */
732
542
  async OnSet(value) {
733
- this.On = this.accessory.context.On ?? false;
734
- this.accessory.context.On = this.On;
543
+ this.debugLog(`value: ${value}`);
735
544
  const deviceTypeActions = {
736
- switch: async () => {
737
- if (this.Switch) {
738
- await this.debugLog(`Set On: ${value}`);
739
- this.On = value !== false;
740
- }
741
- },
742
- garagedoor: async () => {
743
- if (this.GarageDoor) {
744
- await this.debugLog(`Set TargetDoorState: ${value}`);
745
- this.On = value !== this.hap.Characteristic.TargetDoorState.CLOSED;
746
- }
747
- },
748
- door: async () => {
749
- if (this.Door) {
750
- await this.debugLog(`Set TargetPosition: ${value}`);
751
- this.On = value !== 0;
752
- }
753
- },
754
- window: async () => {
755
- if (this.Window) {
756
- await this.debugLog(`Set TargetPosition: ${value}`);
757
- this.On = value !== 0;
758
- }
759
- },
760
- windowcovering: async () => {
761
- if (this.WindowCovering) {
762
- await this.debugLog(`Set TargetPosition: ${value}`);
763
- this.On = value !== 0;
764
- }
765
- },
766
- lock: async () => {
767
- if (this.LockMechanism) {
768
- await this.debugLog(`Set LockTargetState: ${value}`);
769
- this.On = value !== this.hap.Characteristic.LockTargetState.SECURED;
770
- }
771
- },
772
- faucet: async () => {
773
- if (this.Faucet) {
774
- await this.debugLog(`Set Active: ${value}`);
775
- this.On = value !== this.hap.Characteristic.Active.INACTIVE;
776
- }
777
- },
778
- stateful: async () => {
779
- if (this.StatefulProgrammableSwitch) {
780
- await this.debugLog(`Set ProgrammableSwitchOutputState: ${value}`);
781
- this.On = value !== 0;
782
- }
783
- },
784
- default: async () => {
785
- if (this.Outlet) {
786
- await this.debugLog(`Set On: ${value}`);
787
- this.On = value !== false;
788
- }
545
+ switch: () => this.On = value !== false,
546
+ garagedoor: () => this.On = value !== this.hap.Characteristic.TargetDoorState.CLOSED,
547
+ door: () => this.On = value !== 0,
548
+ window: () => this.On = value !== 0,
549
+ windowcovering: () => this.On = value !== 0,
550
+ lock: () => this.On = value !== this.hap.Characteristic.LockTargetState.SECURED,
551
+ faucet: () => this.On = value !== this.hap.Characteristic.Active.INACTIVE,
552
+ fan: () => this.On = value !== 0,
553
+ stateful: () => this.On = value !== 0,
554
+ default: () => {
555
+ this.On = value !== false;
789
556
  if (this.device.mode === 'multipress' && this.On) {
790
557
  this.multiPressCount++;
791
- await this.debugLog(`multiPressCount: ${this.multiPressCount}`);
558
+ this.debugLog(`multiPressCount: ${this.multiPressCount}`);
792
559
  }
793
560
  },
794
561
  };
795
562
  const action = deviceTypeActions[this.botDeviceType] || deviceTypeActions.default;
796
- await action();
797
- this.accessory.context.On = this.On;
563
+ action();
798
564
  this.doBotUpdate.next();
799
565
  }
800
566
  /**
@@ -821,283 +587,106 @@ export class Bot extends deviceBase {
821
587
  await this.debugLog(`updateCharacteristic StatusLowBattery: ${this.Battery.StatusLowBattery}`);
822
588
  }
823
589
  // State
824
- if (this.botDeviceType === 'switch' && this.Switch) {
825
- if (this.On === undefined) {
826
- await this.debugLog(`On: ${this.On}`);
827
- }
828
- else {
829
- this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, this.On);
830
- await this.debugLog(`updateCharacteristic On: ${this.On}`);
831
- }
832
- }
833
- else if (this.botDeviceType === 'garagedoor' && this.GarageDoor) {
834
- if (this.On === undefined) {
835
- await this.debugLog(`On: ${this.On}`);
836
- }
837
- else {
838
- if (this.On) {
839
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.OPEN);
840
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.OPEN);
841
- await this.debugLog(`updateCharacteristic TargetDoorState: Open, CurrentDoorState: Open (${this.On})`);
842
- }
843
- else {
844
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.CLOSED);
845
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.CLOSED);
846
- await this.debugLog(`updateCharacteristicc TargetDoorState: Closed, CurrentDoorState: Closed (${this.On})`);
847
- }
848
- }
849
- await this.debugLog(`Garage Door On: ${this.On}`);
850
- }
851
- else if (this.botDeviceType === 'door' && this.Door) {
852
- if (this.On === undefined) {
853
- await this.debugLog(`On: ${this.On}`);
854
- }
855
- else {
856
- if (this.On) {
857
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
858
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
859
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
860
- await this.debugLog(`updateCharacteristicc TargetPosition: 100, CurrentPosition: 100 (${this.On})`);
861
- }
862
- else {
863
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
864
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
865
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
866
- await this.debugLog(`updateCharacteristicc TargetPosition: 0, CurrentPosition: 0 (${this.On})`);
867
- }
868
- }
869
- await this.debugLog(`Door On: ${this.On}`);
870
- }
871
- else if (this.botDeviceType === 'window' && this.Window) {
872
- if (this.On === undefined) {
873
- await this.debugLog(`On: ${this.On}`);
874
- }
875
- else {
876
- if (this.On) {
877
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
878
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
879
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
880
- await this.debugLog(`updateCharacteristicc TargetPosition: 100, CurrentPosition: 100 (${this.On})`);
881
- }
882
- else {
883
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
884
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
885
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
886
- await this.debugLog(`updateCharacteristicc TargetPosition: 0, CurrentPosition: 0 (${this.On})`);
887
- }
888
- }
889
- await this.debugLog(`Window On: ${this.On}`);
890
- }
891
- else if (this.botDeviceType === 'windowcovering' && this.WindowCovering) {
892
- if (this.On === undefined) {
893
- await this.debugLog(`On: ${this.On}`);
894
- }
895
- else {
896
- if (this.On) {
897
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
898
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
899
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
900
- await this.debugLog(`updateCharacteristicc TargetPosition: 100, CurrentPosition: 100 (${this.On})`);
901
- }
902
- else {
903
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
904
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
905
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
906
- await this.debugLog(`updateCharacteristicc TargetPosition: 0, CurrentPosition: 0 (${this.On})`);
907
- }
908
- }
909
- await this.debugLog(`Window Covering On: ${this.On}`);
910
- }
911
- else if (this.botDeviceType === 'lock' && this.LockMechanism) {
912
- if (this.On === undefined) {
913
- await this.debugLog(`On: ${this.On}`);
914
- }
915
- else {
916
- if (this.On) {
917
- this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.UNSECURED);
918
- this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.UNSECURED);
919
- await this.debugLog(`updateCharacteristicc LockTargetState: UNSECURED, LockCurrentState: UNSECURED (${this.On})`);
920
- }
921
- else {
922
- this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
923
- this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
924
- await this.debugLog(`updateCharacteristic LockTargetState: SECURED, LockCurrentState: SECURED (${this.On})`);
925
- }
926
- }
927
- await this.debugLog(`Lock On: ${this.On}`);
928
- }
929
- else if (this.botDeviceType === 'faucet' && this.Faucet) {
930
- if (this.On === undefined) {
931
- await this.debugLog(`On: ${this.On}`);
932
- }
933
- else {
934
- if (this.On) {
935
- this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.ACTIVE);
936
- await this.debugLog(`updateCharacteristic Active: ${this.On}`);
590
+ const updateCharacteristic = async (service, characteristic, value, logMessage) => {
591
+ service.updateCharacteristic(characteristic, value);
592
+ await this.debugLog(logMessage);
593
+ };
594
+ const stateActions = {
595
+ switch: async () => this.Switch && await updateCharacteristic(this.Switch.Service, this.hap.Characteristic.On, this.On, `updateCharacteristic On: ${this.On}`),
596
+ garagedoor: async () => {
597
+ if (this.GarageDoor) {
598
+ const targetState = this.On ? this.hap.Characteristic.TargetDoorState.OPEN : this.hap.Characteristic.TargetDoorState.CLOSED;
599
+ const currentState = this.On ? this.hap.Characteristic.CurrentDoorState.OPEN : this.hap.Characteristic.CurrentDoorState.CLOSED;
600
+ await updateCharacteristic(this.GarageDoor.Service, this.hap.Characteristic.TargetDoorState, targetState, `updateCharacteristic TargetDoorState: ${targetState}, CurrentDoorState: ${currentState} (${this.On})`);
601
+ await updateCharacteristic(this.GarageDoor.Service, this.hap.Characteristic.CurrentDoorState, currentState, '');
937
602
  }
938
- else {
939
- this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
940
- await this.debugLog(`updateCharacteristic Active: ${this.On}`);
603
+ },
604
+ door: async () => {
605
+ if (this.Door) {
606
+ const position = this.On ? 100 : 0;
607
+ await updateCharacteristic(this.Door.Service, this.hap.Characteristic.TargetPosition, position, `updateCharacteristic TargetPosition: ${position}, CurrentPosition: ${position} (${this.On})`);
608
+ await updateCharacteristic(this.Door.Service, this.hap.Characteristic.CurrentPosition, position, '');
609
+ await updateCharacteristic(this.Door.Service, this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED, '');
941
610
  }
942
- }
943
- await this.debugLog(`Faucet On: ${this.On}`);
944
- }
945
- else if (this.botDeviceType === 'fan' && this.Fan) {
946
- if (this.On === undefined) {
947
- await this.debugLog(`On: ${this.On}`);
948
- }
949
- else {
950
- if (this.On) {
951
- this.Fan.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.ACTIVE);
952
- await this.debugLog(`updateCharacteristic Active: ${this.On}`);
611
+ },
612
+ window: async () => {
613
+ if (this.Window) {
614
+ const position = this.On ? 100 : 0;
615
+ await updateCharacteristic(this.Window.Service, this.hap.Characteristic.TargetPosition, position, `updateCharacteristic TargetPosition: ${position}, CurrentPosition: ${position} (${this.On})`);
616
+ await updateCharacteristic(this.Window.Service, this.hap.Characteristic.CurrentPosition, position, '');
617
+ await updateCharacteristic(this.Window.Service, this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED, '');
953
618
  }
954
- else {
955
- this.Fan.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
956
- await this.debugLog(`updateCharacteristic Active: ${this.On}`);
619
+ },
620
+ windowcovering: async () => {
621
+ if (this.WindowCovering) {
622
+ const position = this.On ? 100 : 0;
623
+ await updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.TargetPosition, position, `updateCharacteristic TargetPosition: ${position}, CurrentPosition: ${position} (${this.On})`);
624
+ await updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentPosition, position, '');
625
+ await updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED, '');
957
626
  }
958
- }
959
- await this.debugLog(`Fan On: ${this.On}`);
960
- }
961
- else if (this.botDeviceType === 'stateful' && this.StatefulProgrammableSwitch) {
962
- if (this.On === undefined) {
963
- await this.debugLog(`On: ${this.On}`);
964
- }
965
- else {
966
- if (this.On) {
967
- this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent, this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
968
- this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 1);
969
- await this.debugLog(`updateCharacteristic ProgrammableSwitchEvent: ProgrammableSwitchOutputState: (${this.On})`);
627
+ },
628
+ lock: async () => {
629
+ if (this.LockMechanism) {
630
+ const targetState = this.On ? this.hap.Characteristic.LockTargetState.UNSECURED : this.hap.Characteristic.LockTargetState.SECURED;
631
+ const currentState = this.On ? this.hap.Characteristic.LockCurrentState.UNSECURED : this.hap.Characteristic.LockCurrentState.SECURED;
632
+ await updateCharacteristic(this.LockMechanism.Service, this.hap.Characteristic.LockTargetState, targetState, `updateCharacteristic LockTargetState: ${targetState}, LockCurrentState: ${currentState} (${this.On})`);
633
+ await updateCharacteristic(this.LockMechanism.Service, this.hap.Characteristic.LockCurrentState, currentState, '');
970
634
  }
971
- else {
972
- this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent, this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
973
- this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 0);
974
- await this.debugLog(`updateCharacteristic ProgrammableSwitchEvent: ProgrammableSwitchOutputState: (${this.On})`);
635
+ },
636
+ faucet: async () => this.Faucet && await updateCharacteristic(this.Faucet.Service, this.hap.Characteristic.Active, this.On ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE, `updateCharacteristic Active: ${this.On}`),
637
+ fan: async () => this.Fan && await updateCharacteristic(this.Fan.Service, this.hap.Characteristic.Active, this.On ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE, `updateCharacteristic Active: ${this.On}`),
638
+ stateful: async () => {
639
+ if (this.StatefulProgrammableSwitch) {
640
+ await updateCharacteristic(this.StatefulProgrammableSwitch.Service, this.hap.Characteristic.ProgrammableSwitchEvent, this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS, `updateCharacteristic ProgrammableSwitchEvent: SINGLE_PRESS (${this.On})`);
641
+ await updateCharacteristic(this.StatefulProgrammableSwitch.Service, this.hap.Characteristic.ProgrammableSwitchOutputState, this.On ? 1 : 0, `updateCharacteristic ProgrammableSwitchOutputState: ${this.On ? 1 : 0}`);
975
642
  }
976
- }
977
- await this.debugLog(`StatefulProgrammableSwitch On: ${this.On}`);
978
- }
979
- else if (this.botDeviceType === 'outlet' && this.Outlet) {
980
- if (this.On === undefined) {
981
- await this.debugLog(`On: ${this.On}`);
982
- }
983
- else {
984
- this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, this.On);
985
- await this.debugLog(`updateCharacteristic On: ${this.On}`);
986
- }
987
- }
988
- else {
989
- await this.errorLog(`botDeviceType: ${this.botDeviceType}, On: ${this.On}`);
990
- }
643
+ },
644
+ outlet: async () => this.Outlet && await updateCharacteristic(this.Outlet.Service, this.hap.Characteristic.On, this.On, `updateCharacteristic On: ${this.On}`),
645
+ default: async () => await this.errorLog(`botDeviceType: ${this.botDeviceType}, On: ${this.On}`),
646
+ };
647
+ const action = stateActions[this.botDeviceType] || stateActions.default;
648
+ await action();
991
649
  }
992
- async removeOutletService(accessory) {
993
- // If outletService still present, then remove first
994
- accessory.context.Outlet = accessory.context.Outlet ?? {};
995
- this.Outlet = {
996
- Name: accessory.context.Outlet.Name ?? accessory.displayName,
997
- Service: accessory.getService(this.hap.Service.Outlet),
650
+ async removeService(accessory, serviceType, serviceName) {
651
+ const contextKey = serviceName.charAt(0).toUpperCase() + serviceName.slice(1);
652
+ accessory.context[contextKey] = accessory.context[contextKey] ?? {};
653
+ this[contextKey] = {
654
+ Name: accessory.context[contextKey].Name ?? accessory.displayName,
655
+ Service: accessory.getService(this.hap.Service[serviceType]),
998
656
  };
999
- accessory.context.Outlet = this.Outlet;
1000
- await this.debugWarnLog('Removing any leftover Outlet Service');
1001
- accessory.removeService(this.Outlet.Service);
657
+ accessory.context[contextKey] = this[contextKey];
658
+ await this.debugWarnLog(`Removing any leftover ${contextKey} Service`);
659
+ accessory.removeService(this[contextKey].Service);
660
+ }
661
+ async removeOutletService(accessory) {
662
+ await this.removeService(accessory, 'Outlet', 'outlet');
1002
663
  }
1003
664
  async removeGarageDoorService(accessory) {
1004
- // If garageDoorService still present, then remove first
1005
- accessory.context.GarageDoor = accessory.context.GarageDoor ?? {};
1006
- this.GarageDoor = {
1007
- Name: accessory.context.GarageDoor.Name ?? accessory.displayName,
1008
- Service: accessory.getService(this.hap.Service.GarageDoorOpener),
1009
- };
1010
- accessory.context.GarageDoor = this.GarageDoor;
1011
- await this.debugWarnLog('Removing any leftover Garage Door Service');
1012
- accessory.removeService(this.GarageDoor.Service);
665
+ await this.removeService(accessory, 'GarageDoorOpener', 'garageDoor');
1013
666
  }
1014
667
  async removeDoorService(accessory) {
1015
- // If doorService still present, then remove first
1016
- accessory.context.Door = accessory.context.Door ?? {};
1017
- this.Door = {
1018
- Name: accessory.context.Door.Name ?? accessory.displayName,
1019
- Service: accessory.getService(this.hap.Service.Door),
1020
- };
1021
- accessory.context.Door = this.Door;
1022
- await this.debugWarnLog('Removing any leftover Door Service');
1023
- accessory.removeService(this.Door.Service);
668
+ await this.removeService(accessory, 'Door', 'door');
1024
669
  }
1025
670
  async removeLockService(accessory) {
1026
- // If lockService still present, then remove first
1027
- accessory.context.LockMechanism = accessory.context.LockMechanism ?? {};
1028
- this.LockMechanism = {
1029
- Name: accessory.context.LockMechanism.Name ?? accessory.displayName,
1030
- Service: accessory.getService(this.hap.Service.LockMechanism),
1031
- };
1032
- accessory.context.LockMechanism = this.LockMechanism;
1033
- await this.debugWarnLog('Removing any leftover Lock Service');
1034
- accessory.removeService(this.LockMechanism.Service);
671
+ await this.removeService(accessory, 'LockMechanism', 'lockMechanism');
1035
672
  }
1036
673
  async removeFaucetService(accessory) {
1037
- // If faucetService still present, then remove first
1038
- accessory.context.Faucet = accessory.context.Faucet ?? {};
1039
- this.Faucet = {
1040
- Name: accessory.context.Faucet.Name ?? accessory.displayName,
1041
- Service: accessory.getService(this.hap.Service.Valve),
1042
- };
1043
- accessory.context.Faucet = this.Faucet;
1044
- await this.debugWarnLog('Removing any leftover Faucet Service');
1045
- accessory.removeService(this.Faucet.Service);
674
+ await this.removeService(accessory, 'Valve', 'faucet');
1046
675
  }
1047
676
  async removeFanService(accessory) {
1048
- // If fanService still present, then remove first
1049
- accessory.context.Fan = accessory.context.Fan ?? {};
1050
- this.Fan = {
1051
- Name: accessory.context.Fan.Name ?? accessory.displayName,
1052
- Service: accessory.getService(this.hap.Service.Fan),
1053
- };
1054
- accessory.context.Fan = this.Fan;
1055
- await this.debugWarnLog('Removing any leftover Fan Service');
1056
- accessory.removeService(this.Fan.Service);
677
+ await this.removeService(accessory, 'Fan', 'fan');
1057
678
  }
1058
679
  async removeWindowService(accessory) {
1059
- // If windowService still present, then remove first
1060
- accessory.context.Window = accessory.context.Window ?? {};
1061
- this.Window = {
1062
- Name: accessory.context.Window.Name ?? accessory.displayName,
1063
- Service: accessory.getService(this.hap.Service.Window),
1064
- };
1065
- accessory.context.Window = this.Window;
1066
- await this.debugWarnLog('Removing any leftover Window Service');
1067
- accessory.removeService(this.Window.Service);
680
+ await this.removeService(accessory, 'Window', 'window');
1068
681
  }
1069
682
  async removeWindowCoveringService(accessory) {
1070
- // If windowCoveringService still present, then remove first
1071
- accessory.context.WindowCovering = accessory.context.WindowCovering ?? {};
1072
- this.WindowCovering = {
1073
- Name: accessory.context.WindowCovering.Name ?? accessory.displayName,
1074
- Service: accessory.getService(this.hap.Service.WindowCovering),
1075
- };
1076
- accessory.context.WindowCovering = this.WindowCovering;
1077
- await this.debugWarnLog('Removing any leftover Window Covering Service');
1078
- accessory.removeService(this.WindowCovering.Service);
683
+ await this.removeService(accessory, 'WindowCovering', 'windowCovering');
1079
684
  }
1080
685
  async removeStatefulProgrammableSwitchService(accessory) {
1081
- // If statefulProgrammableSwitchService still present, then remove first
1082
- accessory.context.StatefulProgrammableSwitch = accessory.context.StatefulProgrammableSwitch ?? {};
1083
- this.StatefulProgrammableSwitch = {
1084
- Name: accessory.context.StatefulProgrammableSwitch.Name ?? accessory.displayName,
1085
- Service: accessory.getService(this.hap.Service.StatefulProgrammableSwitch),
1086
- };
1087
- accessory.context.StatefulProgrammableSwitch = this.StatefulProgrammableSwitch;
1088
- await this.debugWarnLog('Removing any leftover Stateful Programmable Switch Service');
1089
- accessory.removeService(this.StatefulProgrammableSwitch.Service);
686
+ await this.removeService(accessory, 'StatefulProgrammableSwitch', 'statefulProgrammableSwitch');
1090
687
  }
1091
688
  async removeSwitchService(accessory) {
1092
- // If switchService still present, then remove first
1093
- accessory.context.Switch = accessory.context.Switch ?? {};
1094
- this.Switch = {
1095
- Name: accessory.context.Switch.Name ?? accessory.displayName,
1096
- Service: accessory.getService(this.hap.Service.Switch),
1097
- };
1098
- accessory.context.Switch = this.Switch;
1099
- await this.debugWarnLog('Removing any leftover Switch Service');
1100
- accessory.removeService(this.Switch.Service);
689
+ await this.removeService(accessory, 'Switch', 'switch');
1101
690
  }
1102
691
  async getBotConfigSettings(device) {
1103
692
  // Bot Device Type
@@ -1128,21 +717,18 @@ export class Bot extends deviceBase {
1128
717
  ? `Using Double Press: ${this.doublePress}`
1129
718
  : `No Double Press Set, Using default Double Press: ${this.doublePress}`;
1130
719
  await this.debugWarnLog(doublePress);
1131
- this.accessory.context.doublePress = this.doublePress;
1132
720
  // Bot Press PushRate
1133
721
  this.pushRatePress = device.pushRatePress ?? 15;
1134
722
  const pushRatePress = device.pushRatePress
1135
723
  ? `Using Bot Push Rate Press: ${this.pushRatePress}`
1136
724
  : `No Push Rate Press Set, Using default Push Rate Press: ${this.pushRatePress}`;
1137
725
  await this.debugWarnLog(pushRatePress);
1138
- this.accessory.context.pushRatePress = this.pushRatePress;
1139
726
  // Bot Allow Push
1140
727
  this.allowPush = device.allowPush ?? false;
1141
728
  const allowPush = device.allowPush
1142
729
  ? `Using Allow Push: ${this.allowPush}`
1143
730
  : `No Allow Push Set, Using default Allow Push: ${this.allowPush}`;
1144
731
  await this.debugWarnLog(allowPush);
1145
- this.accessory.context.allowPush = this.allowPush;
1146
732
  // Bot Multi Press Count
1147
733
  this.multiPressCount = 0;
1148
734
  await this.debugWarnLog(`Multi Press Count: ${this.multiPressCount}`);
@@ -1162,130 +748,52 @@ export class Bot extends deviceBase {
1162
748
  }
1163
749
  async offlineOff() {
1164
750
  if (this.device.offline) {
1165
- if (this.botDeviceType === 'garagedoor') {
1166
- if (this.GarageDoor) {
1167
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.CLOSED);
1168
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.CLOSED);
1169
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, false);
1170
- }
1171
- }
1172
- else if (this.botDeviceType === 'door') {
1173
- if (this.Door) {
1174
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
1175
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
1176
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1177
- }
1178
- }
1179
- else if (this.botDeviceType === 'window') {
1180
- if (this.Window) {
1181
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
1182
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
1183
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1184
- }
1185
- }
1186
- else if (this.botDeviceType === 'windowcovering') {
1187
- if (this.WindowCovering) {
1188
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
1189
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
1190
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1191
- }
1192
- }
1193
- else if (this.botDeviceType === 'lock') {
1194
- if (this.LockMechanism) {
1195
- this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
1196
- this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
1197
- }
1198
- }
1199
- else if (this.botDeviceType === 'faucet') {
1200
- if (this.Faucet) {
1201
- this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
1202
- }
1203
- }
1204
- else if (this.botDeviceType === 'fan') {
1205
- if (this.Fan) {
1206
- this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, false);
1207
- }
1208
- }
1209
- else if (this.botDeviceType === 'stateful') {
1210
- if (this.StatefulProgrammableSwitch) {
1211
- this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent, this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
1212
- this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 0);
1213
- }
1214
- }
1215
- else if (this.botDeviceType === 'switch') {
1216
- if (this.Switch) {
1217
- this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, false);
1218
- }
1219
- }
1220
- else {
1221
- if (this.Outlet) {
1222
- this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, false);
751
+ const updateCharacteristics = (service, characteristics) => {
752
+ for (const [characteristic, value] of Object.entries(characteristics)) {
753
+ service.updateCharacteristic(this.hap.Characteristic[characteristic], value);
1223
754
  }
755
+ };
756
+ const characteristicsMap = {
757
+ garagedoor: { TargetDoorState: 'CLOSED', CurrentDoorState: 'CLOSED', ObstructionDetected: false },
758
+ door: { TargetPosition: 0, CurrentPosition: 0, PositionState: 'STOPPED' },
759
+ window: { TargetPosition: 0, CurrentPosition: 0, PositionState: 'STOPPED' },
760
+ windowcovering: { TargetPosition: 0, CurrentPosition: 0, PositionState: 'STOPPED' },
761
+ lock: { LockTargetState: 'SECURED', LockCurrentState: 'SECURED' },
762
+ faucet: { Active: 'INACTIVE' },
763
+ fan: { On: false },
764
+ stateful: { ProgrammableSwitchEvent: 'SINGLE_PRESS', ProgrammableSwitchOutputState: 0 },
765
+ switch: { On: false },
766
+ outlet: { On: false },
767
+ };
768
+ const service = this[this.botDeviceType.charAt(0).toUpperCase() + this.botDeviceType.slice(1)]?.Service;
769
+ if (service) {
770
+ updateCharacteristics(service, characteristicsMap[this.botDeviceType]);
1224
771
  }
1225
772
  }
1226
773
  }
1227
774
  async apiError(e) {
775
+ const updateCharacteristics = (service, characteristics) => {
776
+ for (const [characteristic] of Object.entries(characteristics)) {
777
+ service.updateCharacteristic(this.hap.Characteristic[characteristic], e);
778
+ }
779
+ };
780
+ const characteristicsMap = {
781
+ garagedoor: { TargetDoorState: e, CurrentDoorState: e, ObstructionDetected: e },
782
+ door: { TargetPosition: e, CurrentPosition: e, PositionState: e },
783
+ window: { TargetPosition: e, CurrentPosition: e, PositionState: e },
784
+ windowcovering: { TargetPosition: e, CurrentPosition: e, PositionState: e },
785
+ lock: { LockTargetState: e, LockCurrentState: e },
786
+ faucet: { Active: e },
787
+ fan: { On: e },
788
+ stateful: { ProgrammableSwitchEvent: e, ProgrammableSwitchOutputState: e },
789
+ switch: { On: e },
790
+ outlet: { On: e },
791
+ };
1228
792
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
1229
793
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
1230
- if (this.botDeviceType === 'garagedoor') {
1231
- if (this.GarageDoor) {
1232
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, e);
1233
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, e);
1234
- this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, e);
1235
- }
1236
- }
1237
- else if (this.botDeviceType === 'door') {
1238
- if (this.Door) {
1239
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1240
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1241
- this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1242
- }
1243
- }
1244
- else if (this.botDeviceType === 'window') {
1245
- if (this.Window) {
1246
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1247
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1248
- this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1249
- }
1250
- }
1251
- else if (this.botDeviceType === 'windowcovering') {
1252
- if (this.WindowCovering) {
1253
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1254
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1255
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1256
- }
1257
- }
1258
- else if (this.botDeviceType === 'lock') {
1259
- if (this.LockMechanism) {
1260
- this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, e);
1261
- this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e);
1262
- }
1263
- }
1264
- else if (this.botDeviceType === 'faucet') {
1265
- if (this.Faucet) {
1266
- this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, e);
1267
- }
1268
- }
1269
- else if (this.botDeviceType === 'fan') {
1270
- if (this.Fan) {
1271
- this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, e);
1272
- }
1273
- }
1274
- else if (this.botDeviceType === 'stateful') {
1275
- if (this.StatefulProgrammableSwitch) {
1276
- this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent, e);
1277
- this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, e);
1278
- }
1279
- }
1280
- else if (this.botDeviceType === 'switch') {
1281
- if (this.Switch) {
1282
- this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, e);
1283
- }
1284
- }
1285
- else {
1286
- if (this.Outlet) {
1287
- this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, e);
1288
- }
794
+ const service = this[this.botDeviceType.charAt(0).toUpperCase() + this.botDeviceType.slice(1)]?.Service;
795
+ if (service) {
796
+ updateCharacteristics(service, characteristicsMap[this.botDeviceType]);
1289
797
  }
1290
798
  }
1291
799
  }