@switchbot/homebridge-switchbot 2.0.0-beta.19 → 2.0.0-beta.20
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.
- package/CHANGELOG.md +6 -1
- package/README.md +1 -2
- package/config.schema.json +51 -32
- package/dist/device/bot.d.ts +32 -29
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +549 -575
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +33 -15
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +426 -341
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +16 -9
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +246 -208
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +21 -18
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +449 -449
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +22 -20
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +346 -324
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +22 -10
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +257 -178
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +21 -14
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +287 -239
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +23 -10
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +308 -190
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +17 -10
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +225 -193
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +24 -17
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +270 -267
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +36 -14
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +447 -299
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +7 -14
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +177 -169
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +3 -5
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +72 -57
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +3 -4
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +47 -33
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +3 -4
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +66 -48
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +3 -4
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +48 -47
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +3 -4
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +47 -33
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +10 -11
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +64 -48
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -12
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +52 -41
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +6 -11
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +52 -42
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +0 -4
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +44 -66
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +3 -3
- package/dist/settings.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/device/bot.ts +551 -589
- package/src/device/colorbulb.ts +441 -375
- package/src/device/contact.ts +249 -213
- package/src/device/curtain.ts +452 -461
- package/src/device/humidifier.ts +358 -365
- package/src/device/lock.ts +263 -179
- package/src/device/meter.ts +302 -253
- package/src/device/meterplus.ts +319 -194
- package/src/device/motion.ts +230 -199
- package/src/device/plug.ts +273 -274
- package/src/device/striplight.ts +460 -316
- package/src/irdevice/airconditioner.ts +181 -183
- package/src/irdevice/airpurifier.ts +70 -60
- package/src/irdevice/camera.ts +46 -36
- package/src/irdevice/fan.ts +64 -49
- package/src/irdevice/light.ts +47 -51
- package/src/irdevice/other.ts +46 -36
- package/src/irdevice/tv.ts +64 -51
- package/src/irdevice/vacuumcleaner.ts +52 -45
- package/src/irdevice/waterheater.ts +50 -45
- package/src/platform.ts +44 -68
- package/src/settings.ts +3 -3
package/src/device/bot.ts
CHANGED
|
@@ -40,9 +40,9 @@ export class Bot {
|
|
|
40
40
|
// BLE Others
|
|
41
41
|
connected?: boolean;
|
|
42
42
|
switchbot!: switchbot;
|
|
43
|
-
SwitchToOpenAPI?: boolean;
|
|
44
43
|
serviceData!: serviceData;
|
|
45
44
|
address!: ad['address'];
|
|
45
|
+
SwitchToOpenAPI?: boolean;
|
|
46
46
|
mode!: serviceData['mode'];
|
|
47
47
|
state!: serviceData['state'];
|
|
48
48
|
battery!: serviceData['battery'];
|
|
@@ -53,7 +53,6 @@ export class Bot {
|
|
|
53
53
|
scanDuration!: number;
|
|
54
54
|
deviceLogging!: string;
|
|
55
55
|
deviceRefreshRate!: number;
|
|
56
|
-
OpenAPI?: boolean;
|
|
57
56
|
|
|
58
57
|
// Others
|
|
59
58
|
doublePress!: number;
|
|
@@ -62,29 +61,20 @@ export class Bot {
|
|
|
62
61
|
botUpdateInProgress!: boolean;
|
|
63
62
|
doBotUpdate!: Subject<void>;
|
|
64
63
|
|
|
64
|
+
// Connection
|
|
65
|
+
private readonly BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'Both');
|
|
66
|
+
private readonly OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'Both');
|
|
67
|
+
|
|
65
68
|
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
|
|
66
69
|
// default placeholders
|
|
67
70
|
this.logs(device);
|
|
68
|
-
this.openAPI();
|
|
69
71
|
this.scan(device);
|
|
70
72
|
this.refreshRate(device);
|
|
71
73
|
this.PressOrSwitch(device);
|
|
72
74
|
this.allowPushChanges(device);
|
|
73
75
|
this.config(device);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
this.accessory.context.On = this.On;
|
|
77
|
-
} else {
|
|
78
|
-
this.On = this.accessory.context.On;
|
|
79
|
-
}
|
|
80
|
-
if (device.bot?.doublePress) {
|
|
81
|
-
this.doublePress = device.bot?.doublePress;
|
|
82
|
-
this.accessory.context.doublePress = this.doublePress;
|
|
83
|
-
} else {
|
|
84
|
-
this.doublePress = 1;
|
|
85
|
-
}
|
|
86
|
-
this.BatteryLevel = 100;
|
|
87
|
-
this.StatusLowBattery = 0;
|
|
76
|
+
this.context();
|
|
77
|
+
this.DoublePress(device);
|
|
88
78
|
|
|
89
79
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
90
80
|
this.doBotUpdate = new Subject();
|
|
@@ -122,7 +112,7 @@ export class Bot {
|
|
|
122
112
|
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Switch`);
|
|
123
113
|
|
|
124
114
|
this.switchService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
125
|
-
this.switchService.getCharacteristic(this.platform.Characteristic.On).onSet(this.
|
|
115
|
+
this.switchService.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
126
116
|
} else if (device.bot?.deviceType === 'garagedoor') {
|
|
127
117
|
this.removeFanService(accessory);
|
|
128
118
|
this.removeLockService(accessory);
|
|
@@ -141,7 +131,7 @@ export class Bot {
|
|
|
141
131
|
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Garage Door Opener`);
|
|
142
132
|
|
|
143
133
|
this.garageDoorService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
144
|
-
this.garageDoorService.getCharacteristic(this.platform.Characteristic.TargetDoorState).onSet(this.
|
|
134
|
+
this.garageDoorService.getCharacteristic(this.platform.Characteristic.TargetDoorState).onSet(this.OnSet.bind(this));
|
|
145
135
|
this.garageDoorService.setCharacteristic(this.platform.Characteristic.ObstructionDetected, false);
|
|
146
136
|
} else if (device.bot?.deviceType === 'door') {
|
|
147
137
|
this.removeFanService(accessory);
|
|
@@ -168,7 +158,7 @@ export class Bot {
|
|
|
168
158
|
maxValue: 100,
|
|
169
159
|
minStep: 100,
|
|
170
160
|
})
|
|
171
|
-
.onSet(this.
|
|
161
|
+
.onSet(this.OnSet.bind(this));
|
|
172
162
|
this.doorService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
173
163
|
} else if (device.bot?.deviceType === 'window') {
|
|
174
164
|
this.removeFanService(accessory);
|
|
@@ -195,7 +185,7 @@ export class Bot {
|
|
|
195
185
|
maxValue: 100,
|
|
196
186
|
minStep: 100,
|
|
197
187
|
})
|
|
198
|
-
.onSet(this.
|
|
188
|
+
.onSet(this.OnSet.bind(this));
|
|
199
189
|
this.windowService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
200
190
|
} else if (device.bot?.deviceType === 'windowcovering') {
|
|
201
191
|
this.removeFanService(accessory);
|
|
@@ -223,7 +213,7 @@ export class Bot {
|
|
|
223
213
|
maxValue: 100,
|
|
224
214
|
minStep: 100,
|
|
225
215
|
})
|
|
226
|
-
.onSet(this.
|
|
216
|
+
.onSet(this.OnSet.bind(this));
|
|
227
217
|
this.windowCoveringService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
228
218
|
} else if (device.bot?.deviceType === 'lock') {
|
|
229
219
|
this.removeFanService(accessory);
|
|
@@ -242,7 +232,7 @@ export class Bot {
|
|
|
242
232
|
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Lock`);
|
|
243
233
|
|
|
244
234
|
this.lockService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
245
|
-
this.lockService.getCharacteristic(this.platform.Characteristic.LockTargetState).onSet(this.
|
|
235
|
+
this.lockService.getCharacteristic(this.platform.Characteristic.LockTargetState).onSet(this.OnSet.bind(this));
|
|
246
236
|
} else if (device.bot?.deviceType === 'faucet') {
|
|
247
237
|
this.removeFanService(accessory);
|
|
248
238
|
this.removeLockService(accessory);
|
|
@@ -260,7 +250,7 @@ export class Bot {
|
|
|
260
250
|
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Faucet`);
|
|
261
251
|
|
|
262
252
|
this.faucetService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
263
|
-
this.faucetService.getCharacteristic(this.platform.Characteristic.Active).onSet(this.
|
|
253
|
+
this.faucetService.getCharacteristic(this.platform.Characteristic.Active).onSet(this.OnSet.bind(this));
|
|
264
254
|
} else if (device.bot?.deviceType === 'fan') {
|
|
265
255
|
this.removeLockService(accessory);
|
|
266
256
|
this.removeDoorService(accessory);
|
|
@@ -278,7 +268,7 @@ export class Bot {
|
|
|
278
268
|
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Fan`);
|
|
279
269
|
|
|
280
270
|
this.fanService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
281
|
-
this.fanService.getCharacteristic(this.platform.Characteristic.On).onSet(this.
|
|
271
|
+
this.fanService.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
282
272
|
} else if (device.bot?.deviceType === 'stateful') {
|
|
283
273
|
this.removeFanService(accessory);
|
|
284
274
|
this.removeLockService(accessory);
|
|
@@ -300,7 +290,7 @@ export class Bot {
|
|
|
300
290
|
this.statefulProgrammableSwitchService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
301
291
|
this.statefulProgrammableSwitchService
|
|
302
292
|
.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState)
|
|
303
|
-
.onSet(this.
|
|
293
|
+
.onSet(this.OnSet.bind(this));
|
|
304
294
|
} else {
|
|
305
295
|
this.removeFanService(accessory);
|
|
306
296
|
this.removeLockService(accessory);
|
|
@@ -318,15 +308,15 @@ export class Bot {
|
|
|
318
308
|
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Outlet`);
|
|
319
309
|
|
|
320
310
|
this.outletService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
321
|
-
this.outletService.getCharacteristic(this.platform.Characteristic.On).onSet(this.
|
|
311
|
+
this.outletService.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
322
312
|
}
|
|
323
313
|
|
|
324
314
|
// Battery Service
|
|
325
|
-
if (!
|
|
315
|
+
if (!this.BLE) {
|
|
326
316
|
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Battery Service`);
|
|
327
317
|
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
328
318
|
accessory.removeService(this.batteryService!);
|
|
329
|
-
} else if (
|
|
319
|
+
} else if (this.BLE && !this.batteryService) {
|
|
330
320
|
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Battery Service`);
|
|
331
321
|
(this.batteryService = this.accessory.getService(this.platform.Service.Battery) || this.accessory.addService(this.platform.Service.Battery)),
|
|
332
322
|
`${accessory.displayName} Battery`;
|
|
@@ -347,30 +337,25 @@ export class Bot {
|
|
|
347
337
|
});
|
|
348
338
|
|
|
349
339
|
// Watch for Bot change events
|
|
350
|
-
// We put in a debounce of
|
|
340
|
+
// We put in a debounce of 1000ms so we don't make duplicate calls
|
|
351
341
|
this.doBotUpdate
|
|
352
342
|
.pipe(
|
|
353
343
|
tap(() => {
|
|
354
344
|
this.botUpdateInProgress = true;
|
|
355
345
|
}),
|
|
356
|
-
debounceTime(
|
|
346
|
+
debounceTime(this.platform.config.options!.pushRate! * 1000),
|
|
357
347
|
)
|
|
358
348
|
.subscribe(async () => {
|
|
359
349
|
try {
|
|
360
|
-
interval(
|
|
350
|
+
interval(15000)
|
|
361
351
|
.pipe(take(this.doublePress!))
|
|
362
352
|
.subscribe(async () => {
|
|
363
353
|
await this.pushChanges();
|
|
364
354
|
});
|
|
365
355
|
} catch (e: any) {
|
|
366
|
-
this.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
+ ` Error Message: ${superStringify(e.message)}`);
|
|
370
|
-
}
|
|
371
|
-
if (this.platform.debugMode) {
|
|
372
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges,` + ` Error: ${superStringify(e)}`);
|
|
373
|
-
}
|
|
356
|
+
this.apiError(e);
|
|
357
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
|
|
358
|
+
+ ` Error Message: ${superStringify(e.message)}`);
|
|
374
359
|
}
|
|
375
360
|
this.botUpdateInProgress = false;
|
|
376
361
|
});
|
|
@@ -380,15 +365,19 @@ export class Bot {
|
|
|
380
365
|
* Parse the device status from the SwitchBot api
|
|
381
366
|
*/
|
|
382
367
|
async parseStatus(): Promise<void> {
|
|
383
|
-
if (this.
|
|
368
|
+
if (this.BLE && !this.SwitchToOpenAPI) {
|
|
369
|
+
await this.BLEparseStatus();
|
|
370
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
371
|
+
this.SwitchToOpenAPI = false;
|
|
384
372
|
await this.openAPIparseStatus();
|
|
385
373
|
} else {
|
|
386
|
-
|
|
374
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
375
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
387
376
|
}
|
|
388
377
|
}
|
|
389
378
|
|
|
390
379
|
async BLEparseStatus(): Promise<void> {
|
|
391
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
380
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
392
381
|
// BLEmode (true if Switch Mode) | (false if Press Mode)
|
|
393
382
|
if (this.mode) {
|
|
394
383
|
this.accessory.context.On = this.On;
|
|
@@ -415,37 +404,35 @@ export class Bot {
|
|
|
415
404
|
}
|
|
416
405
|
|
|
417
406
|
async openAPIparseStatus(): Promise<void> {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
407
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
408
|
+
if (this.botMode === 'press') {
|
|
409
|
+
this.On = false;
|
|
410
|
+
this.accessory.context.On = this.On;
|
|
411
|
+
} else {
|
|
412
|
+
this.accessory.context.On = this.On;
|
|
413
|
+
if (this.On === undefined) {
|
|
424
414
|
this.On = false;
|
|
425
|
-
this.accessory.context.On = this.On;
|
|
426
|
-
} else {
|
|
427
|
-
this.accessory.context.On = this.On;
|
|
428
|
-
if (this.On === undefined) {
|
|
429
|
-
this.On = false;
|
|
430
|
-
}
|
|
431
415
|
}
|
|
432
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
433
416
|
}
|
|
417
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
434
418
|
}
|
|
435
419
|
|
|
436
420
|
/**
|
|
437
421
|
* Asks the SwitchBot API for the latest device information
|
|
438
422
|
*/
|
|
439
423
|
async refreshStatus(): Promise<void> {
|
|
440
|
-
if (this.
|
|
424
|
+
if (this.BLE) {
|
|
441
425
|
await this.BLERefreshStatus();
|
|
442
|
-
} else {
|
|
426
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
443
427
|
await this.openAPIRefreshStatus();
|
|
428
|
+
} else {
|
|
429
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
430
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
444
431
|
}
|
|
445
432
|
}
|
|
446
433
|
|
|
447
434
|
async BLERefreshStatus(): Promise<void> {
|
|
448
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
435
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
|
|
449
436
|
const switchbot = await this.platform.connectBLE();
|
|
450
437
|
// Convert to BLE Address
|
|
451
438
|
this.device.bleMac = this.device
|
|
@@ -455,157 +442,113 @@ export class Bot {
|
|
|
455
442
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
456
443
|
this.getCustomBLEAddress(switchbot);
|
|
457
444
|
// Start to monitor advertisement packets
|
|
458
|
-
if (switchbot
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
})
|
|
466
|
-
.then(() => {
|
|
445
|
+
if (switchbot !== false) {
|
|
446
|
+
switchbot
|
|
447
|
+
.startScan({
|
|
448
|
+
model: 'H',
|
|
449
|
+
id: this.device.bleMac,
|
|
450
|
+
})
|
|
451
|
+
.then(() => {
|
|
467
452
|
// Set an event hander
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
453
|
+
switchbot.onadvertisement = (ad: ad) => {
|
|
454
|
+
this.address = ad.address;
|
|
455
|
+
if (this.deviceLogging.includes('debug')) {
|
|
456
|
+
this.infoLog(this.address);
|
|
457
|
+
this.infoLog(this.device.bleMac);
|
|
458
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
|
|
459
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
|
|
460
|
+
}
|
|
461
|
+
this.serviceData = ad.serviceData;
|
|
462
|
+
this.mode = ad.serviceData.mode;
|
|
463
|
+
this.state = ad.serviceData.state;
|
|
464
|
+
this.battery = ad.serviceData.battery;
|
|
465
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${superStringify(ad.serviceData)}`);
|
|
466
|
+
this.debugLog(
|
|
467
|
+
`${this.device.deviceType}: ${this.accessory.displayName}, model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName},` +
|
|
483
468
|
` mode: ${ad.serviceData.mode}, state: ${ad.serviceData.state}, battery: ${ad.serviceData.battery}`,
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
if (this.serviceData) {
|
|
472
|
+
this.connected = true;
|
|
473
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
474
|
+
} else {
|
|
475
|
+
this.connected = false;
|
|
476
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
// Wait 2 seconds
|
|
480
|
+
return switchbot.wait(this.scanDuration * 1000);
|
|
481
|
+
})
|
|
482
|
+
.then(async () => {
|
|
498
483
|
// Stop to monitor
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
if (this.platform.config.credentials?.token) {
|
|
506
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
507
|
-
this.SwitchToOpenAPI = true;
|
|
508
|
-
await this.openAPIRefreshStatus();
|
|
484
|
+
switchbot.stopScan();
|
|
485
|
+
if (this.connected) {
|
|
486
|
+
this.parseStatus();
|
|
487
|
+
this.updateHomeKitCharacteristics();
|
|
488
|
+
} else {
|
|
489
|
+
await this.BLEconnection(switchbot);
|
|
509
490
|
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
this.
|
|
516
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
|
|
517
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
if (this.platform.config.credentials?.token) {
|
|
521
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
522
|
-
this.SwitchToOpenAPI = true;
|
|
523
|
-
await this.openAPIRefreshStatus();
|
|
524
|
-
}
|
|
525
|
-
this.apiError(e);
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
async getCustomBLEAddress(switchbot: any) {
|
|
530
|
-
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
531
|
-
(async () => {
|
|
532
|
-
// Start to monitor advertisement packets
|
|
533
|
-
await switchbot.startScan({
|
|
534
|
-
model: 'H',
|
|
491
|
+
})
|
|
492
|
+
.catch(async (e: any) => {
|
|
493
|
+
this.apiError(e);
|
|
494
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
|
|
495
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
496
|
+
await this.BLEconnection(switchbot);
|
|
535
497
|
});
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
|
|
539
|
-
};
|
|
540
|
-
await switchbot.wait(10000);
|
|
541
|
-
// Stop to monitor
|
|
542
|
-
switchbot.stopScan();
|
|
543
|
-
})();
|
|
498
|
+
} else {
|
|
499
|
+
await this.BLEconnection(switchbot);
|
|
544
500
|
}
|
|
545
501
|
}
|
|
546
502
|
|
|
547
503
|
async openAPIRefreshStatus(): Promise<void> {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
this.debugLog(`d: ${d}`);
|
|
576
|
-
});
|
|
577
|
-
res.on('end', () => {
|
|
578
|
-
try {
|
|
579
|
-
this.deviceStatus = JSON.parse(rawData);
|
|
580
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
581
|
-
this.power = this.deviceStatus.body.power;
|
|
582
|
-
this.parseStatus();
|
|
583
|
-
this.updateHomeKitCharacteristics();
|
|
584
|
-
} catch (e: any) {
|
|
585
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
586
|
-
}
|
|
587
|
-
});
|
|
504
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
505
|
+
try {
|
|
506
|
+
const t = Date.now();
|
|
507
|
+
const nonce = 'requestID';
|
|
508
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
509
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
510
|
+
const sign = signTerm.toString('base64');
|
|
511
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
512
|
+
const options = {
|
|
513
|
+
hostname: HostDomain,
|
|
514
|
+
port: 443,
|
|
515
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
516
|
+
method: 'GET',
|
|
517
|
+
headers: {
|
|
518
|
+
Authorization: this.platform.config.credentials?.token,
|
|
519
|
+
sign: sign,
|
|
520
|
+
nonce: nonce,
|
|
521
|
+
t: t,
|
|
522
|
+
'Content-Type': 'application/json',
|
|
523
|
+
},
|
|
524
|
+
};
|
|
525
|
+
const req = https.request(options, (res) => {
|
|
526
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
|
|
527
|
+
let rawData = '';
|
|
528
|
+
res.on('data', (d) => {
|
|
529
|
+
rawData += d;
|
|
530
|
+
this.debugLog(`d: ${d}`);
|
|
588
531
|
});
|
|
589
|
-
|
|
590
|
-
|
|
532
|
+
res.on('end', () => {
|
|
533
|
+
try {
|
|
534
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
535
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
536
|
+
this.power = this.deviceStatus.body.power;
|
|
537
|
+
this.parseStatus();
|
|
538
|
+
this.updateHomeKitCharacteristics();
|
|
539
|
+
} catch (e: any) {
|
|
540
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
541
|
+
}
|
|
591
542
|
});
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
if (this.platform.debugMode) {
|
|
602
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
|
|
603
|
-
+ ` Error: ${superStringify(e)}`);
|
|
604
|
-
}
|
|
605
|
-
this.apiError(e);
|
|
606
|
-
}
|
|
607
|
-
} else {
|
|
608
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI is disabled, commands will not be sent.`);
|
|
543
|
+
});
|
|
544
|
+
req.on('error', (e: any) => {
|
|
545
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
546
|
+
});
|
|
547
|
+
req.end();
|
|
548
|
+
} catch (e: any) {
|
|
549
|
+
this.apiError(e);
|
|
550
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
551
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
609
552
|
}
|
|
610
553
|
}
|
|
611
554
|
|
|
@@ -617,10 +560,13 @@ export class Bot {
|
|
|
617
560
|
* Bot - "command" "press" "default" = trigger press
|
|
618
561
|
*/
|
|
619
562
|
async pushChanges(): Promise<void> {
|
|
620
|
-
if (this.
|
|
621
|
-
await this.
|
|
622
|
-
} else {
|
|
563
|
+
if (this.BLE) {
|
|
564
|
+
await this.BLERefreshStatus();
|
|
565
|
+
} else if (this.OpenAPI) {
|
|
623
566
|
await this.openAPIpushChanges();
|
|
567
|
+
} else {
|
|
568
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
569
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
624
570
|
}
|
|
625
571
|
interval(5000)
|
|
626
572
|
.pipe(take(1))
|
|
@@ -630,9 +576,9 @@ export class Bot {
|
|
|
630
576
|
}
|
|
631
577
|
|
|
632
578
|
async BLEpushChanges(): Promise<void> {
|
|
633
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
579
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
634
580
|
if (this.On !== this.accessory.context.On || this.allowPush) {
|
|
635
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
581
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
|
|
636
582
|
const switchbot = await this.platform.connectBLE();
|
|
637
583
|
// Convert to BLE Address
|
|
638
584
|
this.device.bleMac = this.device
|
|
@@ -662,22 +608,13 @@ export class Bot {
|
|
|
662
608
|
}, 500);
|
|
663
609
|
})
|
|
664
610
|
.catch(async (e: any) => {
|
|
665
|
-
this.
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
670
|
-
);
|
|
671
|
-
}
|
|
672
|
-
if (this.platform.debugMode) {
|
|
673
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
|
|
674
|
-
+ ` Error: ${superStringify(e)}`);
|
|
675
|
-
}
|
|
676
|
-
if (this.platform.config.credentials?.token) {
|
|
611
|
+
this.apiError(e);
|
|
612
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
613
|
+
+ ` Connection & botMode: ${this.botMode}, Error Message: ${superStringify(e.message)}`);
|
|
614
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
677
615
|
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
678
616
|
await this.openAPIpushChanges();
|
|
679
617
|
}
|
|
680
|
-
this.apiError(e);
|
|
681
618
|
});
|
|
682
619
|
} else if (this.botMode === 'switch') {
|
|
683
620
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode: ${this.botMode}`);
|
|
@@ -692,127 +629,145 @@ export class Bot {
|
|
|
692
629
|
this.accessory.context.On = this.On;
|
|
693
630
|
})
|
|
694
631
|
.catch(async (e: any) => {
|
|
695
|
-
this.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
700
|
-
);
|
|
701
|
-
}
|
|
702
|
-
if (this.platform.debugMode) {
|
|
703
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
|
|
704
|
-
+ ` Error: ${superStringify(e)}`);
|
|
705
|
-
}
|
|
706
|
-
if (this.platform.config.credentials?.token) {
|
|
632
|
+
this.apiError(e);
|
|
633
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
634
|
+
+ ` Connection & botMode: ${this.botMode}, Error Message: ${superStringify(e.message)}`);
|
|
635
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
707
636
|
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
708
637
|
await this.openAPIpushChanges();
|
|
709
638
|
}
|
|
710
|
-
this.apiError(e);
|
|
711
639
|
});
|
|
712
640
|
} else {
|
|
713
|
-
|
|
641
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
714
642
|
}
|
|
643
|
+
} else {
|
|
644
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, `
|
|
645
|
+
+`OnCached: ${this.accessory.context.On}`);
|
|
715
646
|
}
|
|
716
|
-
this.accessory.context.On = this.On;
|
|
717
647
|
}
|
|
718
648
|
|
|
719
|
-
async
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
649
|
+
async openAPIpushChanges(): Promise<void> {
|
|
650
|
+
try {
|
|
651
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
652
|
+
if (this.On !== this.accessory.context.On || this.allowPush) {
|
|
653
|
+
// Make Push On request to the API
|
|
654
|
+
const t = Date.now();
|
|
655
|
+
const nonce = 'requestID';
|
|
656
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
657
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
658
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
659
|
+
.digest();
|
|
660
|
+
const sign = signTerm.toString('base64');
|
|
661
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
662
|
+
let command = '';
|
|
663
|
+
if (this.botMode === 'switch' && this.On) {
|
|
664
|
+
command = 'turnOn';
|
|
665
|
+
this.On = true;
|
|
666
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
|
|
667
|
+
} else if (this.botMode === 'switch' && !this.On) {
|
|
668
|
+
command = 'turnOff';
|
|
669
|
+
this.On = false;
|
|
670
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
|
|
671
|
+
} else if (this.botMode === 'press') {
|
|
672
|
+
command = 'press';
|
|
673
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode`);
|
|
674
|
+
this.On = false;
|
|
725
675
|
} else {
|
|
726
|
-
|
|
676
|
+
throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
|
|
727
677
|
}
|
|
728
|
-
|
|
729
|
-
|
|
678
|
+
const body = superStringify({
|
|
679
|
+
'command': `${command}`,
|
|
680
|
+
'parameter': 'default',
|
|
681
|
+
'commandType': 'command',
|
|
682
|
+
});
|
|
683
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
684
|
+
const options = {
|
|
685
|
+
hostname: HostDomain,
|
|
686
|
+
port: 443,
|
|
687
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
688
|
+
method: 'POST',
|
|
689
|
+
headers: {
|
|
690
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
691
|
+
'sign': sign,
|
|
692
|
+
'nonce': nonce,
|
|
693
|
+
't': t,
|
|
694
|
+
'Content-Type': 'application/json',
|
|
695
|
+
'Content-Length': body.length,
|
|
696
|
+
},
|
|
697
|
+
};
|
|
698
|
+
const req = https.request(options, res => {
|
|
699
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
|
|
700
|
+
this.statusCode({ res });
|
|
701
|
+
res.on('data', d => {
|
|
702
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
req.on('error', (e: any) => {
|
|
706
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
707
|
+
});
|
|
708
|
+
req.write(body);
|
|
709
|
+
req.end();
|
|
710
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges: ${superStringify(req)}`);
|
|
711
|
+
} else {
|
|
712
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `On: ${this.On}, `
|
|
713
|
+
+`OnCached: ${this.accessory.context.On}`);
|
|
714
|
+
}
|
|
715
|
+
} catch (e: any) {
|
|
716
|
+
this.apiError(e);
|
|
717
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
718
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`,
|
|
719
|
+
);
|
|
720
|
+
}
|
|
730
721
|
}
|
|
731
722
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
.update(Buffer.from(data, 'utf-8'))
|
|
743
|
-
.digest();
|
|
744
|
-
const sign = signTerm.toString('base64');
|
|
745
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
746
|
-
let command = '';
|
|
747
|
-
if (this.botMode === 'switch' && this.On) {
|
|
748
|
-
command = 'turnOn';
|
|
749
|
-
this.On = true;
|
|
750
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
|
|
751
|
-
} else if (this.botMode === 'switch' && !this.On) {
|
|
752
|
-
command = 'turnOff';
|
|
753
|
-
this.On = false;
|
|
754
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
|
|
755
|
-
} else if (this.botMode === 'press') {
|
|
756
|
-
command = 'press';
|
|
757
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode`);
|
|
758
|
-
this.On = false;
|
|
759
|
-
} else {
|
|
760
|
-
throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
|
|
761
|
-
}
|
|
762
|
-
const body = superStringify({
|
|
763
|
-
'command': `${command}`,
|
|
764
|
-
'parameter': 'default',
|
|
765
|
-
'commandType': 'command',
|
|
766
|
-
});
|
|
767
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
768
|
-
const options = {
|
|
769
|
-
hostname: HostDomain,
|
|
770
|
-
port: 443,
|
|
771
|
-
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
772
|
-
method: 'POST',
|
|
773
|
-
headers: {
|
|
774
|
-
'Authorization': this.platform.config.credentials?.token,
|
|
775
|
-
'sign': sign,
|
|
776
|
-
'nonce': nonce,
|
|
777
|
-
't': t,
|
|
778
|
-
'Content-Type': 'application/json',
|
|
779
|
-
'Content-Length': body.length,
|
|
780
|
-
},
|
|
781
|
-
};
|
|
782
|
-
const req = https.request(options, res => {
|
|
783
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
784
|
-
this.statusCode({ res });
|
|
785
|
-
res.on('data', d => {
|
|
786
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
787
|
-
});
|
|
788
|
-
});
|
|
789
|
-
req.on('error', (e: any) => {
|
|
790
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
791
|
-
});
|
|
792
|
-
req.write(body);
|
|
793
|
-
req.end();
|
|
794
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges: ${superStringify(req)}`);
|
|
795
|
-
this.accessory.context.On = this.On;
|
|
796
|
-
}
|
|
797
|
-
} catch (e: any) {
|
|
798
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
799
|
-
if (this.deviceLogging.includes('debug')) {
|
|
800
|
-
this.errorLog(
|
|
801
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
|
|
802
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
803
|
-
);
|
|
804
|
-
}
|
|
805
|
-
if (this.platform.debugMode) {
|
|
806
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
|
|
807
|
-
+ ` Error: ${superStringify(e)}`);
|
|
808
|
-
}
|
|
809
|
-
this.apiError(e);
|
|
723
|
+
/**
|
|
724
|
+
* Handle requests to set the "On" characteristic
|
|
725
|
+
*/
|
|
726
|
+
async OnSet(value: CharacteristicValue): Promise<void> {
|
|
727
|
+
if (this.device.bot?.deviceType === 'garagedoor') {
|
|
728
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetDoorState: ${value}`);
|
|
729
|
+
if (value === this.platform.Characteristic.TargetDoorState.CLOSED) {
|
|
730
|
+
this.On = false;
|
|
731
|
+
} else {
|
|
732
|
+
this.On = true;
|
|
810
733
|
}
|
|
811
|
-
} else
|
|
812
|
-
|
|
813
|
-
|
|
734
|
+
} else if (
|
|
735
|
+
this.device.bot?.deviceType === 'door' ||
|
|
736
|
+
this.device.bot?.deviceType === 'window' ||
|
|
737
|
+
this.device.bot?.deviceType === 'windowcovering'
|
|
738
|
+
) {
|
|
739
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
|
|
740
|
+
if (value === 0) {
|
|
741
|
+
this.On = false;
|
|
742
|
+
} else {
|
|
743
|
+
this.On = true;
|
|
744
|
+
}
|
|
745
|
+
} else if (this.device.bot?.deviceType === 'lock') {
|
|
746
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
|
|
747
|
+
if (value === this.platform.Characteristic.LockTargetState.SECURED) {
|
|
748
|
+
this.On = false;
|
|
749
|
+
} else {
|
|
750
|
+
this.On = true;
|
|
751
|
+
}
|
|
752
|
+
} else if (this.device.bot?.deviceType === 'faucet') {
|
|
753
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Active: ${value}`);
|
|
754
|
+
if (value === this.platform.Characteristic.Active.INACTIVE) {
|
|
755
|
+
this.On = false;
|
|
756
|
+
} else {
|
|
757
|
+
this.On = true;
|
|
814
758
|
}
|
|
759
|
+
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
760
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ProgrammableSwitchOutputState: ${value}`);
|
|
761
|
+
if (value === 0) {
|
|
762
|
+
this.On = false;
|
|
763
|
+
} else {
|
|
764
|
+
this.On = true;
|
|
765
|
+
}
|
|
766
|
+
} else {
|
|
767
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
|
|
768
|
+
this.On = value;
|
|
815
769
|
}
|
|
770
|
+
this.doBotUpdate.next();
|
|
816
771
|
}
|
|
817
772
|
|
|
818
773
|
/**
|
|
@@ -996,7 +951,7 @@ export class Bot {
|
|
|
996
951
|
}
|
|
997
952
|
}
|
|
998
953
|
this.accessory.context.On = this.On;
|
|
999
|
-
if (this.
|
|
954
|
+
if (this.BLE) {
|
|
1000
955
|
if (this.BatteryLevel === undefined) {
|
|
1001
956
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
1002
957
|
} else {
|
|
@@ -1014,137 +969,143 @@ export class Bot {
|
|
|
1014
969
|
}
|
|
1015
970
|
}
|
|
1016
971
|
|
|
1017
|
-
async
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
this.
|
|
1022
|
-
} else if (this.device.bot?.deviceType === 'door') {
|
|
1023
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1024
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1025
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1026
|
-
} else if (this.device.bot?.deviceType === 'window') {
|
|
1027
|
-
this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1028
|
-
this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1029
|
-
this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1030
|
-
} else if (this.device.bot?.deviceType === 'windowcovering') {
|
|
1031
|
-
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1032
|
-
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1033
|
-
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1034
|
-
} else if (this.device.bot?.deviceType === 'lock') {
|
|
1035
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
1036
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
1037
|
-
} else if (this.device.bot?.deviceType === 'faucet') {
|
|
1038
|
-
this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active, e);
|
|
1039
|
-
} else if (this.device.bot?.deviceType === 'fan') {
|
|
1040
|
-
this.fanService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1041
|
-
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
1042
|
-
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent, e);
|
|
1043
|
-
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, e);
|
|
1044
|
-
} else if (this.device.bot?.deviceType === 'switch') {
|
|
1045
|
-
this.switchService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1046
|
-
} else {
|
|
1047
|
-
this.outletService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
972
|
+
async removeOutletService(accessory: PlatformAccessory): Promise<void> {
|
|
973
|
+
// If outletService still pressent, then remove first
|
|
974
|
+
this.outletService = this.accessory.getService(this.platform.Service.Outlet);
|
|
975
|
+
if (this.outletService) {
|
|
976
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Outlet Service`);
|
|
1048
977
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
978
|
+
accessory.removeService(this.outletService!);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
async removeGarageDoorService(accessory: PlatformAccessory): Promise<void> {
|
|
982
|
+
// If garageDoorService still pressent, then remove first
|
|
983
|
+
this.garageDoorService = this.accessory.getService(this.platform.Service.GarageDoorOpener);
|
|
984
|
+
if (this.garageDoorService) {
|
|
985
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Garage Door Service`);
|
|
1052
986
|
}
|
|
1053
|
-
|
|
987
|
+
accessory.removeService(this.garageDoorService!);
|
|
1054
988
|
}
|
|
1055
989
|
|
|
1056
|
-
async
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
case 152:
|
|
1062
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
|
|
1063
|
-
break;
|
|
1064
|
-
case 160:
|
|
1065
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
|
|
1066
|
-
break;
|
|
1067
|
-
case 161:
|
|
1068
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
|
|
1069
|
-
this.offlineOff();
|
|
1070
|
-
break;
|
|
1071
|
-
case 171:
|
|
1072
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
1073
|
-
this.offlineOff();
|
|
1074
|
-
break;
|
|
1075
|
-
case 190:
|
|
1076
|
-
this.errorLog(
|
|
1077
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
1078
|
-
` Or command: ${superStringify(res)} format is invalid`,
|
|
1079
|
-
);
|
|
1080
|
-
break;
|
|
1081
|
-
case 100:
|
|
1082
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
|
|
1083
|
-
break;
|
|
1084
|
-
default:
|
|
1085
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
|
|
990
|
+
async removeDoorService(accessory: PlatformAccessory): Promise<void> {
|
|
991
|
+
// If doorService still pressent, then remove first
|
|
992
|
+
this.doorService = this.accessory.getService(this.platform.Service.Door);
|
|
993
|
+
if (this.doorService) {
|
|
994
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Door Service`);
|
|
1086
995
|
}
|
|
996
|
+
accessory.removeService(this.doorService!);
|
|
1087
997
|
}
|
|
1088
998
|
|
|
1089
|
-
async
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
} else {
|
|
1095
|
-
this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
1096
|
-
}
|
|
999
|
+
async removeLockService(accessory: PlatformAccessory): Promise<void> {
|
|
1000
|
+
// If lockService still pressent, then remove first
|
|
1001
|
+
this.lockService = this.accessory.getService(this.platform.Service.LockMechanism);
|
|
1002
|
+
if (this.lockService) {
|
|
1003
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Lock Service`);
|
|
1097
1004
|
}
|
|
1005
|
+
accessory.removeService(this.lockService!);
|
|
1098
1006
|
}
|
|
1099
1007
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
this.device.
|
|
1114
|
-
|
|
1115
|
-
)
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1008
|
+
async removeFaucetService(accessory: PlatformAccessory): Promise<void> {
|
|
1009
|
+
// If faucetService still pressent, then remove first
|
|
1010
|
+
this.faucetService = this.accessory.getService(this.platform.Service.Faucet);
|
|
1011
|
+
if (this.faucetService) {
|
|
1012
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Faucet Service`);
|
|
1013
|
+
}
|
|
1014
|
+
accessory.removeService(this.faucetService!);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
async removeFanService(accessory: PlatformAccessory): Promise<void> {
|
|
1018
|
+
// If fanService still pressent, then remove first
|
|
1019
|
+
this.fanService = this.accessory.getService(this.platform.Service.Fan);
|
|
1020
|
+
if (this.fanService) {
|
|
1021
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Fan Service`);
|
|
1022
|
+
}
|
|
1023
|
+
accessory.removeService(this.fanService!);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
async removeWindowService(accessory: PlatformAccessory): Promise<void> {
|
|
1027
|
+
// If windowService still pressent, then remove first
|
|
1028
|
+
this.windowService = this.accessory.getService(this.platform.Service.Window);
|
|
1029
|
+
if (this.windowService) {
|
|
1030
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Service`);
|
|
1031
|
+
}
|
|
1032
|
+
accessory.removeService(this.windowService!);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
async removeWindowCoveringService(accessory: PlatformAccessory): Promise<void> {
|
|
1036
|
+
// If windowCoveringService still pressent, then remove first
|
|
1037
|
+
this.windowCoveringService = this.accessory.getService(this.platform.Service.WindowCovering);
|
|
1038
|
+
if (this.windowCoveringService) {
|
|
1039
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Covering Service`);
|
|
1040
|
+
}
|
|
1041
|
+
accessory.removeService(this.windowCoveringService!);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
async removeStatefulProgrammableSwitchService(accessory: PlatformAccessory): Promise<void> {
|
|
1045
|
+
// If statefulProgrammableSwitchService still pressent, then remove first
|
|
1046
|
+
this.statefulProgrammableSwitchService = this.accessory.getService(this.platform.Service.StatefulProgrammableSwitch);
|
|
1047
|
+
if (this.statefulProgrammableSwitchService) {
|
|
1048
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
|
|
1049
|
+
}
|
|
1050
|
+
accessory.removeService(this.statefulProgrammableSwitchService!);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
async removeSwitchService(accessory: PlatformAccessory): Promise<void> {
|
|
1054
|
+
// If switchService still pressent, then remove first
|
|
1055
|
+
this.switchService = this.accessory.getService(this.platform.Service.Switch);
|
|
1056
|
+
if (this.switchService) {
|
|
1057
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Switch Service`);
|
|
1058
|
+
}
|
|
1059
|
+
accessory.removeService(this.switchService!);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
private DoublePress(device: device & devicesConfig) {
|
|
1063
|
+
if (device.bot?.doublePress) {
|
|
1064
|
+
this.doublePress = device.bot?.doublePress;
|
|
1065
|
+
this.accessory.context.doublePress = this.doublePress;
|
|
1143
1066
|
} else {
|
|
1144
|
-
this.
|
|
1145
|
-
|
|
1067
|
+
this.doublePress = 1;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
async getCustomBLEAddress(switchbot: any) {
|
|
1072
|
+
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
1073
|
+
(async () => {
|
|
1074
|
+
// Start to monitor advertisement packets
|
|
1075
|
+
await switchbot.startScan({
|
|
1076
|
+
model: 'H',
|
|
1077
|
+
});
|
|
1078
|
+
// Set an event handler
|
|
1079
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
1080
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
|
|
1081
|
+
};
|
|
1082
|
+
await switchbot.wait(10000);
|
|
1083
|
+
// Stop to monitor
|
|
1084
|
+
switchbot.stopScan();
|
|
1085
|
+
})();
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
async BLEconnection(switchbot: any): Promise<void> {
|
|
1090
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
1091
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
1092
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
1093
|
+
this.SwitchToOpenAPI = true;
|
|
1094
|
+
await this.openAPIRefreshStatus();
|
|
1146
1095
|
}
|
|
1147
|
-
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
async turnOnOff(device_list: any): Promise<any> {
|
|
1099
|
+
return await this.retry({
|
|
1100
|
+
max: await this.maxRetry(),
|
|
1101
|
+
fn: () => {
|
|
1102
|
+
if (this.On) {
|
|
1103
|
+
return device_list[0].turnOn({ id: this.device.bleMac });
|
|
1104
|
+
} else {
|
|
1105
|
+
return device_list[0].turnOff({ id: this.device.bleMac });
|
|
1106
|
+
}
|
|
1107
|
+
},
|
|
1108
|
+
});
|
|
1148
1109
|
}
|
|
1149
1110
|
|
|
1150
1111
|
async retry({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
|
|
@@ -1169,80 +1130,125 @@ export class Bot {
|
|
|
1169
1130
|
return maxRetry;
|
|
1170
1131
|
}
|
|
1171
1132
|
|
|
1172
|
-
async
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
if (device.
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
if (device.
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
}
|
|
1186
|
-
if (device.refreshRate !== undefined) {
|
|
1187
|
-
config['refreshRate'] = device.refreshRate;
|
|
1188
|
-
}
|
|
1189
|
-
if (device.scanDuration !== undefined) {
|
|
1190
|
-
config['scanDuration'] = device.scanDuration;
|
|
1191
|
-
}
|
|
1192
|
-
if (device.offline !== undefined) {
|
|
1193
|
-
config['offline'] = device.offline;
|
|
1194
|
-
}
|
|
1195
|
-
if (Object.entries(config).length !== 0) {
|
|
1196
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
1201
|
-
if (device.refreshRate) {
|
|
1202
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
1203
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1204
|
-
} else if (this.platform.config.options!.refreshRate) {
|
|
1205
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
1206
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1133
|
+
async PressOrSwitch(device: device & devicesConfig): Promise<void> {
|
|
1134
|
+
if (!device.bot?.mode) {
|
|
1135
|
+
this.botMode = 'switch';
|
|
1136
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} does not have bot mode set in the Plugin's SwitchBot Device Settings,`);
|
|
1137
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} is defaulting to "${this.botMode}" mode, you may experience issues.`);
|
|
1138
|
+
} else if (device.bot?.mode === 'switch') {
|
|
1139
|
+
this.botMode = 'switch';
|
|
1140
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1141
|
+
} else if (device.bot?.mode === 'press') {
|
|
1142
|
+
this.botMode = 'press';
|
|
1143
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1144
|
+
} else {
|
|
1145
|
+
throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
1207
1146
|
}
|
|
1208
1147
|
}
|
|
1209
1148
|
|
|
1210
|
-
async
|
|
1211
|
-
if (
|
|
1212
|
-
this.
|
|
1149
|
+
async allowPushChanges(device: device & devicesConfig): Promise<void> {
|
|
1150
|
+
if (device.bot?.allowPush) {
|
|
1151
|
+
this.allowPush = true;
|
|
1213
1152
|
} else {
|
|
1214
|
-
this.
|
|
1153
|
+
this.allowPush = false;
|
|
1215
1154
|
}
|
|
1216
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
1155
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Allowing Push Changes: ${this.allowPush}`);
|
|
1217
1156
|
}
|
|
1218
1157
|
|
|
1219
1158
|
async scan(device: device & devicesConfig): Promise<void> {
|
|
1220
1159
|
if (device.scanDuration) {
|
|
1221
1160
|
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
1222
|
-
if (
|
|
1161
|
+
if (this.BLE) {
|
|
1223
1162
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
1224
1163
|
}
|
|
1225
1164
|
} else {
|
|
1226
1165
|
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
1227
|
-
if (this.
|
|
1166
|
+
if (this.BLE) {
|
|
1228
1167
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
1229
1168
|
}
|
|
1230
1169
|
}
|
|
1231
1170
|
}
|
|
1232
1171
|
|
|
1233
|
-
async
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1172
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
1173
|
+
switch (res.statusCode) {
|
|
1174
|
+
case 151:
|
|
1175
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
1176
|
+
break;
|
|
1177
|
+
case 152:
|
|
1178
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
|
|
1179
|
+
break;
|
|
1180
|
+
case 160:
|
|
1181
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
|
|
1182
|
+
break;
|
|
1183
|
+
case 161:
|
|
1184
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
|
|
1185
|
+
this.offlineOff();
|
|
1186
|
+
break;
|
|
1187
|
+
case 171:
|
|
1188
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
1189
|
+
this.offlineOff();
|
|
1190
|
+
break;
|
|
1191
|
+
case 190:
|
|
1192
|
+
this.errorLog(
|
|
1193
|
+
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
1194
|
+
` Or command: ${superStringify(res)} format is invalid`,
|
|
1195
|
+
);
|
|
1196
|
+
break;
|
|
1197
|
+
case 100:
|
|
1198
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
|
|
1199
|
+
break;
|
|
1200
|
+
default:
|
|
1201
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
async offlineOff(): Promise<void> {
|
|
1206
|
+
if (this.device.offline) {
|
|
1207
|
+
this.On = false;
|
|
1208
|
+
if (this.device.bot?.deviceType === 'switch') {
|
|
1209
|
+
this.switchService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
1210
|
+
} else {
|
|
1211
|
+
this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
1212
|
+
}
|
|
1213
|
+
await this.updateHomeKitCharacteristics();
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
async apiError(e: any): Promise<void> {
|
|
1218
|
+
if (this.device.bot?.deviceType === 'garagedoor') {
|
|
1219
|
+
this.garageDoorService?.updateCharacteristic(this.platform.Characteristic.TargetDoorState, e);
|
|
1220
|
+
this.garageDoorService?.updateCharacteristic(this.platform.Characteristic.CurrentDoorState, e);
|
|
1221
|
+
this.garageDoorService?.updateCharacteristic(this.platform.Characteristic.ObstructionDetected, e);
|
|
1222
|
+
} else if (this.device.bot?.deviceType === 'door') {
|
|
1223
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1224
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1225
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1226
|
+
} else if (this.device.bot?.deviceType === 'window') {
|
|
1227
|
+
this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1228
|
+
this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1229
|
+
this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1230
|
+
} else if (this.device.bot?.deviceType === 'windowcovering') {
|
|
1231
|
+
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1232
|
+
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1233
|
+
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1234
|
+
} else if (this.device.bot?.deviceType === 'lock') {
|
|
1235
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
1236
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
1237
|
+
} else if (this.device.bot?.deviceType === 'faucet') {
|
|
1238
|
+
this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active, e);
|
|
1239
|
+
} else if (this.device.bot?.deviceType === 'fan') {
|
|
1240
|
+
this.fanService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1241
|
+
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
1242
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent, e);
|
|
1243
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, e);
|
|
1244
|
+
} else if (this.device.bot?.deviceType === 'switch') {
|
|
1245
|
+
this.switchService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1243
1246
|
} else {
|
|
1244
|
-
this.
|
|
1245
|
-
|
|
1247
|
+
this.outletService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1248
|
+
}
|
|
1249
|
+
if (this.BLE) {
|
|
1250
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
|
|
1251
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
|
|
1246
1252
|
}
|
|
1247
1253
|
}
|
|
1248
1254
|
|
|
@@ -1262,119 +1268,75 @@ export class Bot {
|
|
|
1262
1268
|
return FirmwareRevision;
|
|
1263
1269
|
}
|
|
1264
1270
|
|
|
1265
|
-
|
|
1266
|
-
if (
|
|
1267
|
-
this.
|
|
1268
|
-
this.
|
|
1269
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} is defaulting to "${this.botMode}" mode, you may experience issues.`);
|
|
1270
|
-
} else if (device.bot?.mode === 'switch') {
|
|
1271
|
-
this.botMode = 'switch';
|
|
1272
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1273
|
-
} else if (device.bot?.mode === 'press') {
|
|
1274
|
-
this.botMode = 'press';
|
|
1275
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1271
|
+
private context() {
|
|
1272
|
+
if (this.On === undefined) {
|
|
1273
|
+
this.On = false;
|
|
1274
|
+
this.accessory.context.On = this.On;
|
|
1276
1275
|
} else {
|
|
1277
|
-
|
|
1276
|
+
this.On = this.accessory.context.On;
|
|
1278
1277
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
async allowPushChanges(device: device & devicesConfig): Promise<void> {
|
|
1282
|
-
if (device.bot?.allowPush) {
|
|
1283
|
-
this.allowPush = true;
|
|
1278
|
+
if (this.BatteryLevel === undefined) {
|
|
1279
|
+
this.BatteryLevel = 100;
|
|
1284
1280
|
} else {
|
|
1285
|
-
this.
|
|
1281
|
+
this.BatteryLevel = this.accessory.context.BatteryLevel;
|
|
1286
1282
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
this.outletService = this.accessory.getService(this.platform.Service.Outlet);
|
|
1293
|
-
if (this.outletService) {
|
|
1294
|
-
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Outlet Service`);
|
|
1283
|
+
if (this.StatusLowBattery === undefined) {
|
|
1284
|
+
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
1285
|
+
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
1286
|
+
} else {
|
|
1287
|
+
this.StatusLowBattery = this.accessory.context.StatusLowBattery;
|
|
1295
1288
|
}
|
|
1296
|
-
accessory.removeService(this.outletService!);
|
|
1297
1289
|
}
|
|
1298
1290
|
|
|
1299
|
-
async
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1291
|
+
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
1292
|
+
if (device.refreshRate) {
|
|
1293
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
1294
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1295
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
1296
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
1297
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1304
1298
|
}
|
|
1305
|
-
accessory.removeService(this.garageDoorService!);
|
|
1306
1299
|
}
|
|
1307
1300
|
|
|
1308
|
-
async
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Door Service`);
|
|
1301
|
+
async config(device: device & devicesConfig): Promise<void> {
|
|
1302
|
+
let config = {};
|
|
1303
|
+
if (device.bot) {
|
|
1304
|
+
config = device.bot;
|
|
1313
1305
|
}
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
async removeLockService(accessory: PlatformAccessory): Promise<void> {
|
|
1318
|
-
// If lockService still pressent, then remove first
|
|
1319
|
-
this.lockService = this.accessory.getService(this.platform.Service.LockMechanism);
|
|
1320
|
-
if (this.lockService) {
|
|
1321
|
-
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Lock Service`);
|
|
1306
|
+
if (device.connectionType !== undefined) {
|
|
1307
|
+
config['connectionType'] = device.connectionType;
|
|
1322
1308
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
async removeFaucetService(accessory: PlatformAccessory): Promise<void> {
|
|
1327
|
-
// If faucetService still pressent, then remove first
|
|
1328
|
-
this.faucetService = this.accessory.getService(this.platform.Service.Faucet);
|
|
1329
|
-
if (this.faucetService) {
|
|
1330
|
-
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Faucet Service`);
|
|
1309
|
+
if (device.logging !== undefined) {
|
|
1310
|
+
config['logging'] = device.logging;
|
|
1331
1311
|
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
async removeFanService(accessory: PlatformAccessory): Promise<void> {
|
|
1336
|
-
// If fanService still pressent, then remove first
|
|
1337
|
-
this.fanService = this.accessory.getService(this.platform.Service.Fan);
|
|
1338
|
-
if (this.fanService) {
|
|
1339
|
-
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Fan Service`);
|
|
1312
|
+
if (device.refreshRate !== undefined) {
|
|
1313
|
+
config['refreshRate'] = device.refreshRate;
|
|
1340
1314
|
}
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
async removeWindowService(accessory: PlatformAccessory): Promise<void> {
|
|
1345
|
-
// If windowService still pressent, then remove first
|
|
1346
|
-
this.windowService = this.accessory.getService(this.platform.Service.Window);
|
|
1347
|
-
if (this.windowService) {
|
|
1348
|
-
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Service`);
|
|
1315
|
+
if (device.scanDuration !== undefined) {
|
|
1316
|
+
config['scanDuration'] = device.scanDuration;
|
|
1349
1317
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
async removeWindowCoveringService(accessory: PlatformAccessory): Promise<void> {
|
|
1354
|
-
// If windowCoveringService still pressent, then remove first
|
|
1355
|
-
this.windowCoveringService = this.accessory.getService(this.platform.Service.WindowCovering);
|
|
1356
|
-
if (this.windowCoveringService) {
|
|
1357
|
-
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Covering Service`);
|
|
1318
|
+
if (device.offline !== undefined) {
|
|
1319
|
+
config['offline'] = device.offline;
|
|
1358
1320
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
async removeStatefulProgrammableSwitchService(accessory: PlatformAccessory): Promise<void> {
|
|
1363
|
-
// If statefulProgrammableSwitchService still pressent, then remove first
|
|
1364
|
-
this.statefulProgrammableSwitchService = this.accessory.getService(this.platform.Service.StatefulProgrammableSwitch);
|
|
1365
|
-
if (this.statefulProgrammableSwitchService) {
|
|
1366
|
-
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
|
|
1321
|
+
if (Object.entries(config).length !== 0) {
|
|
1322
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
|
|
1367
1323
|
}
|
|
1368
|
-
accessory.removeService(this.statefulProgrammableSwitchService!);
|
|
1369
1324
|
}
|
|
1370
1325
|
|
|
1371
|
-
async
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1326
|
+
async logs(device: device & devicesConfig): Promise<void> {
|
|
1327
|
+
if (this.platform.debugMode) {
|
|
1328
|
+
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
1329
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
1330
|
+
} else if (device.logging) {
|
|
1331
|
+
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
1332
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
1333
|
+
} else if (this.platform.config.options?.logging) {
|
|
1334
|
+
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
1335
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
1336
|
+
} else {
|
|
1337
|
+
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
1338
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
1376
1339
|
}
|
|
1377
|
-
accessory.removeService(this.switchService!);
|
|
1378
1340
|
}
|
|
1379
1341
|
|
|
1380
1342
|
/**
|