@switchbot/homebridge-switchbot 3.5.1-beta.9 → 3.5.2-beta.0
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 +7 -0
- package/config.schema.json +19 -3
- package/dist/device/blindtilt.d.ts +6 -4
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +61 -47
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +6 -3
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +60 -26
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +6 -3
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +48 -30
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +6 -3
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +54 -37
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +6 -3
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +46 -32
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +6 -4
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +42 -28
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +7 -4
- package/dist/device/device.d.ts.map +1 -1
- package/dist/device/device.js +61 -152
- package/dist/device/device.js.map +1 -1
- package/dist/device/fan.d.ts +6 -3
- package/dist/device/fan.d.ts.map +1 -1
- package/dist/device/fan.js +54 -33
- package/dist/device/fan.js.map +1 -1
- package/dist/device/hub.d.ts +6 -3
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +50 -31
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +6 -3
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +48 -29
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +6 -3
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +45 -28
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +6 -3
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +47 -29
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +6 -3
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +39 -26
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +6 -3
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +44 -28
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +6 -3
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +43 -28
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +6 -3
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +38 -25
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +6 -3
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +31 -18
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +6 -3
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +38 -23
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +6 -3
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +44 -27
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +2 -2
- package/dist/irdevice/airconditioner.d.ts +1 -3
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +67 -177
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +0 -1
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +24 -53
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +12 -17
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +22 -38
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +22 -10
- package/dist/irdevice/irdevice.d.ts.map +1 -1
- package/dist/irdevice/irdevice.js +94 -100
- package/dist/irdevice/irdevice.js.map +1 -1
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +20 -38
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +79 -77
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +38 -53
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +11 -16
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +11 -16
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +4 -6
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +564 -665
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +10 -8
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/dist/types/bledevicestatus.d.ts +2 -1
- package/dist/types/bledevicestatus.d.ts.map +1 -1
- package/dist/types/devicestatus.d.ts +1 -1
- package/dist/types/devicestatus.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/device/blindtilt.ts +65 -49
- package/src/device/bot.ts +80 -27
- package/src/device/ceilinglight.ts +58 -32
- package/src/device/colorbulb.ts +58 -44
- package/src/device/contact.ts +50 -32
- package/src/device/curtain.ts +52 -29
- package/src/device/device.ts +63 -135
- package/src/device/fan.ts +68 -34
- package/src/device/hub.ts +63 -34
- package/src/device/humidifier.ts +61 -34
- package/src/device/iosensor.ts +52 -31
- package/src/device/lightstrip.ts +53 -30
- package/src/device/lock.ts +56 -27
- package/src/device/meter.ts +61 -30
- package/src/device/meterplus.ts +57 -30
- package/src/device/motion.ts +51 -27
- package/src/device/plug.ts +39 -19
- package/src/device/robotvacuumcleaner.ts +54 -25
- package/src/device/waterdetector.ts +63 -29
- package/src/homebridge-ui/public/index.html +2 -2
- package/src/irdevice/airconditioner.ts +76 -165
- package/src/irdevice/airpurifier.ts +29 -49
- package/src/irdevice/camera.ts +13 -16
- package/src/irdevice/fan.ts +25 -35
- package/src/irdevice/irdevice.ts +97 -96
- package/src/irdevice/light.ts +21 -35
- package/src/irdevice/other.ts +79 -77
- package/src/irdevice/tv.ts +40 -51
- package/src/irdevice/vacuumcleaner.ts +12 -15
- package/src/irdevice/waterheater.ts +12 -15
- package/src/platform.ts +566 -696
- package/src/settings.ts +11 -8
- package/src/types/bledevicestatus.ts +4 -2
- package/src/types/devicestatus.ts +1 -1
package/src/device/curtain.ts
CHANGED
|
@@ -40,6 +40,15 @@ export class Curtain extends deviceBase {
|
|
|
40
40
|
CurrentAmbientLightLevel?: CharacteristicValue;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
// OpenAPI
|
|
44
|
+
deviceStatus!: curtainStatus;
|
|
45
|
+
|
|
46
|
+
//Webhook
|
|
47
|
+
webhookContext!: curtainWebhookContext | curtain3WebhookContext;
|
|
48
|
+
|
|
49
|
+
// BLE
|
|
50
|
+
serviceData!: curtainServiceData | curtain3ServiceData;
|
|
51
|
+
|
|
43
52
|
// Target
|
|
44
53
|
setNewTarget!: boolean;
|
|
45
54
|
setNewTargetTimer!: NodeJS.Timeout;
|
|
@@ -54,6 +63,8 @@ export class Curtain extends deviceBase {
|
|
|
54
63
|
device: device & devicesConfig,
|
|
55
64
|
) {
|
|
56
65
|
super(platform, accessory, device);
|
|
66
|
+
// Set category
|
|
67
|
+
accessory.category = this.hap.Categories.WINDOW_COVERING;
|
|
57
68
|
|
|
58
69
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
59
70
|
this.doCurtainUpdate = new Subject();
|
|
@@ -175,12 +186,11 @@ export class Curtain extends deviceBase {
|
|
|
175
186
|
}
|
|
176
187
|
|
|
177
188
|
// Retrieve initial values and updateHomekit
|
|
189
|
+
this.debugLog('Retrieve initial values and update Homekit');
|
|
178
190
|
this.refreshStatus();
|
|
179
191
|
|
|
180
|
-
// Update Homekit
|
|
181
|
-
this.updateHomeKitCharacteristics();
|
|
182
|
-
|
|
183
192
|
//regisiter webhook event handler
|
|
193
|
+
this.debugLog('Registering Webhook Event Handler');
|
|
184
194
|
this.registerWebhook();
|
|
185
195
|
|
|
186
196
|
// History
|
|
@@ -256,7 +266,7 @@ export class Curtain extends deviceBase {
|
|
|
256
266
|
});
|
|
257
267
|
const motion: Service =
|
|
258
268
|
this.accessory.getService(this.hap.Service.MotionSensor) ||
|
|
259
|
-
this.accessory.addService(this.hap.Service.MotionSensor,
|
|
269
|
+
this.accessory.addService(this.hap.Service.MotionSensor, 'Motion');
|
|
260
270
|
motion.addOptionalCharacteristic(this.platform.eve.Characteristics.LastActivation);
|
|
261
271
|
motion.getCharacteristic(this.platform.eve.Characteristics.LastActivation).onGet(() => {
|
|
262
272
|
const lastActivation = this.accessory.context.lastActivation
|
|
@@ -293,22 +303,24 @@ export class Curtain extends deviceBase {
|
|
|
293
303
|
}, 10 * 60 * 1000);
|
|
294
304
|
}
|
|
295
305
|
|
|
296
|
-
async BLEparseStatus(
|
|
306
|
+
async BLEparseStatus(): Promise<void> {
|
|
297
307
|
await this.debugLog('BLEparseStatus');
|
|
308
|
+
await this.debugLog(`(position, battery) = BLE:(${this.serviceData.position}, ${this.serviceData.battery}),`
|
|
309
|
+
+ ` current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
|
|
298
310
|
// CurrentPosition
|
|
299
|
-
this.WindowCovering.CurrentPosition = 100 -
|
|
311
|
+
this.WindowCovering.CurrentPosition = 100 -this.serviceData.position;
|
|
300
312
|
await this.getCurrentPostion();
|
|
301
313
|
// CurrentAmbientLightLevel
|
|
302
314
|
if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
|
|
303
315
|
const set_minLux = this.device.curtain?.set_minLux ?? 1;
|
|
304
316
|
const set_maxLux = this.device.curtain?.set_maxLux ?? 6001;
|
|
305
|
-
const lightLevel =
|
|
317
|
+
const lightLevel = this.serviceData.lightLevel;
|
|
306
318
|
this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 19);
|
|
307
|
-
this.debugLog(`LightLevel: ${serviceData.lightLevel},`
|
|
319
|
+
this.debugLog(`LightLevel: ${this.serviceData.lightLevel},`
|
|
308
320
|
+ ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
|
|
309
321
|
}
|
|
310
322
|
// BatteryLevel
|
|
311
|
-
this.Battery.BatteryLevel =
|
|
323
|
+
this.Battery.BatteryLevel = this.serviceData.battery;
|
|
312
324
|
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
313
325
|
// StatusLowBattery
|
|
314
326
|
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
@@ -316,16 +328,18 @@ export class Curtain extends deviceBase {
|
|
|
316
328
|
await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
317
329
|
}
|
|
318
330
|
|
|
319
|
-
async openAPIparseStatus(
|
|
331
|
+
async openAPIparseStatus(): Promise<void> {
|
|
320
332
|
await this.debugLog('openAPIparseStatus');
|
|
333
|
+
await this.debugLog(`(slidePosition, battery) = OpenAPI:(${this.deviceStatus.slidePosition}, ${this.deviceStatus.battery}),`
|
|
334
|
+
+ ` current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
|
|
321
335
|
// CurrentPosition
|
|
322
|
-
this.WindowCovering.CurrentPosition = 100 - deviceStatus.slidePosition;
|
|
336
|
+
this.WindowCovering.CurrentPosition = 100 - this.deviceStatus.slidePosition;
|
|
323
337
|
await this.setMinMax();
|
|
324
|
-
await this.debugLog(`
|
|
338
|
+
await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
325
339
|
if (this.setNewTarget) {
|
|
326
340
|
await this.infoLog('Checking Status ...');
|
|
327
341
|
}
|
|
328
|
-
if (this.setNewTarget && deviceStatus.moving) {
|
|
342
|
+
if (this.setNewTarget && this.deviceStatus.moving) {
|
|
329
343
|
await this.setMinMax();
|
|
330
344
|
if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
|
|
331
345
|
await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
@@ -351,25 +365,28 @@ export class Curtain extends deviceBase {
|
|
|
351
365
|
}
|
|
352
366
|
await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
|
|
353
367
|
+ ` PositionState: ${this.WindowCovering.PositionState},`);
|
|
368
|
+
|
|
354
369
|
// Brightness
|
|
355
370
|
if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
|
|
356
371
|
const set_minLux = this.device.curtain?.set_minLux ?? 1;
|
|
357
372
|
const set_maxLux = this.device.curtain?.set_maxLux ?? 6001;
|
|
358
|
-
const lightLevel = deviceStatus.lightLevel === 'bright' ? set_maxLux : set_minLux;
|
|
373
|
+
const lightLevel = this.deviceStatus.lightLevel === 'bright' ? set_maxLux : set_minLux;
|
|
359
374
|
this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 2);
|
|
360
|
-
await this.debugLog(
|
|
361
|
-
+ ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
|
|
375
|
+
await this.debugLog(`CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
|
|
362
376
|
}
|
|
377
|
+
|
|
363
378
|
// BatteryLevel
|
|
364
|
-
this.Battery.BatteryLevel =
|
|
379
|
+
this.Battery.BatteryLevel = this.deviceStatus.battery;
|
|
365
380
|
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
381
|
+
|
|
366
382
|
// StatusLowBattery
|
|
367
383
|
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
368
384
|
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
369
385
|
await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
386
|
+
|
|
370
387
|
// Firmware Version
|
|
371
|
-
if (deviceStatus.version) {
|
|
372
|
-
const version = deviceStatus.version.toString();
|
|
388
|
+
if (this.deviceStatus.version) {
|
|
389
|
+
const version = this.deviceStatus.version.toString();
|
|
373
390
|
await this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`);
|
|
374
391
|
const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0';
|
|
375
392
|
this.accessory
|
|
@@ -378,21 +395,24 @@ export class Curtain extends deviceBase {
|
|
|
378
395
|
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
379
396
|
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
380
397
|
.updateValue(deviceVersion);
|
|
381
|
-
this.accessory.context.
|
|
382
|
-
await this.debugSuccessLog(`
|
|
398
|
+
this.accessory.context.version = deviceVersion;
|
|
399
|
+
await this.debugSuccessLog(`version: ${this.accessory.context.version}`);
|
|
383
400
|
}
|
|
384
401
|
}
|
|
385
402
|
|
|
386
|
-
async parseStatusWebhook(
|
|
403
|
+
async parseStatusWebhook(): Promise<void> {
|
|
387
404
|
await this.debugLog('parseStatusWebhook');
|
|
388
|
-
await this.debugLog(`(slidePosition, battery) = Webhook:(${
|
|
405
|
+
await this.debugLog(`(slidePosition, battery) = Webhook:(${this.webhookContext.slidePosition}, ${this.webhookContext.battery}),`
|
|
389
406
|
+ ` current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
|
|
407
|
+
|
|
390
408
|
// CurrentPosition
|
|
391
|
-
this.WindowCovering.CurrentPosition = 100 -
|
|
409
|
+
this.WindowCovering.CurrentPosition = 100 - this.webhookContext.slidePosition;
|
|
392
410
|
await this.getCurrentPostion();
|
|
411
|
+
|
|
393
412
|
// BatteryLevel
|
|
394
|
-
this.Battery.BatteryLevel =
|
|
413
|
+
this.Battery.BatteryLevel = this.webhookContext.battery;
|
|
395
414
|
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
415
|
+
|
|
396
416
|
// StatusLowBattery
|
|
397
417
|
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
398
418
|
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
@@ -429,7 +449,8 @@ export class Curtain extends deviceBase {
|
|
|
429
449
|
// Update HomeKit
|
|
430
450
|
if ((serviceData.model === SwitchBotBLEModel.Curtain || SwitchBotBLEModel.Curtain3)
|
|
431
451
|
&& (serviceData.modelName === SwitchBotBLEModelName.Curtain || SwitchBotBLEModelName.Curtain3)) {
|
|
432
|
-
|
|
452
|
+
this.serviceData = serviceData;
|
|
453
|
+
await this.BLEparseStatus();
|
|
433
454
|
await this.updateHomeKitCharacteristics();
|
|
434
455
|
} else {
|
|
435
456
|
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
|
|
@@ -447,7 +468,8 @@ export class Curtain extends deviceBase {
|
|
|
447
468
|
await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);;
|
|
448
469
|
if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
|
|
449
470
|
await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
|
|
450
|
-
|
|
471
|
+
this.deviceStatus = deviceStatus.body;
|
|
472
|
+
await this.openAPIparseStatus();
|
|
451
473
|
await this.updateHomeKitCharacteristics();
|
|
452
474
|
} else {
|
|
453
475
|
await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
|
|
@@ -465,7 +487,8 @@ export class Curtain extends deviceBase {
|
|
|
465
487
|
this.platform.webhookEventHandler[this.device.deviceId] = async (context: curtainWebhookContext | curtain3WebhookContext) => {
|
|
466
488
|
try {
|
|
467
489
|
await this.debugLog(`received Webhook: ${JSON.stringify(context)}`);
|
|
468
|
-
|
|
490
|
+
this.webhookContext = context;
|
|
491
|
+
await this.parseStatusWebhook();
|
|
469
492
|
await this.updateHomeKitCharacteristics();
|
|
470
493
|
} catch (e: any) {
|
|
471
494
|
await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
@@ -682,7 +705,7 @@ export class Curtain extends deviceBase {
|
|
|
682
705
|
}
|
|
683
706
|
|
|
684
707
|
async BLERefreshConnection(switchbot: any): Promise<void> {
|
|
685
|
-
await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${
|
|
708
|
+
await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
686
709
|
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
687
710
|
await this.warnLog('Using OpenAPI Connection to Refresh Status');
|
|
688
711
|
await this.openAPIRefreshStatus();
|
package/src/device/device.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import { hostname } from 'os';
|
|
7
7
|
import { request } from 'undici';
|
|
8
|
-
import asyncmqtt from 'async-mqtt';
|
|
9
8
|
import { Devices } from '../settings.js';
|
|
10
9
|
import { BlindTiltMappingMode, sleep } from '../utils.js';
|
|
10
|
+
import { SwitchBotModel, SwitchBotBLEModel, SwitchBotBLEModelName, SwitchBotBLEModelFriendlyName } from 'node-switchbot';
|
|
11
11
|
|
|
12
12
|
import type { MqttClient } from 'mqtt';
|
|
13
13
|
import type { device } from '../types/devicelist.js';
|
|
@@ -15,7 +15,6 @@ import type { ad } from '../types/bledevicestatus.js';
|
|
|
15
15
|
import type { SwitchBotPlatform } from '../platform.js';
|
|
16
16
|
import type { SwitchBotPlatformConfig, devicesConfig } from '../settings.js';
|
|
17
17
|
import type { API, CharacteristicValue, HAP, Logging, PlatformAccessory, Service } from 'homebridge';
|
|
18
|
-
import { SwitchBotModel, SwitchBotBLEModel, SwitchBotBLEModelName, SwitchBotBLEModelFriendlyName } from 'node-switchbot';
|
|
19
18
|
|
|
20
19
|
export abstract class deviceBase {
|
|
21
20
|
public readonly api: API;
|
|
@@ -39,6 +38,11 @@ export abstract class deviceBase {
|
|
|
39
38
|
protected deviceModel!: SwitchBotModel;
|
|
40
39
|
protected deviceBLEModel!: SwitchBotBLEModel;
|
|
41
40
|
|
|
41
|
+
// MQTT
|
|
42
|
+
protected deviceMqttURL!: string;
|
|
43
|
+
protected deviceMqttOptions!: any;
|
|
44
|
+
protected deviceMqttPubOptions!: any;
|
|
45
|
+
|
|
42
46
|
// BLE
|
|
43
47
|
protected scanDuration!: number;
|
|
44
48
|
|
|
@@ -65,93 +69,54 @@ export abstract class deviceBase {
|
|
|
65
69
|
this.getDeviceLogSettings(accessory, device);
|
|
66
70
|
this.getDeviceRateSettings(accessory, device);
|
|
67
71
|
this.getDeviceRetry(device);
|
|
68
|
-
this.getDeviceConfigSettings(
|
|
72
|
+
this.getDeviceConfigSettings(device);
|
|
69
73
|
this.getDeviceContext(accessory, device);
|
|
70
74
|
this.getDeviceScanDuration(accessory, device);
|
|
71
|
-
this.
|
|
75
|
+
this.getMqttSettings(device);
|
|
72
76
|
|
|
73
77
|
// Set accessory information
|
|
74
78
|
accessory
|
|
75
79
|
.getService(this.hap.Service.AccessoryInformation)!
|
|
76
80
|
.setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
|
|
77
81
|
.setCharacteristic(this.hap.Characteristic.AppMatchingIdentifier, 'id1087374760')
|
|
78
|
-
.setCharacteristic(this.hap.Characteristic.Name, device.deviceName ?? accessory.displayName)
|
|
79
|
-
.setCharacteristic(this.hap.Characteristic.ConfiguredName, device.deviceName ?? accessory.displayName)
|
|
82
|
+
.setCharacteristic(this.hap.Characteristic.Name, device.configDeviceName ?? device.deviceName ?? accessory.displayName)
|
|
83
|
+
.setCharacteristic(this.hap.Characteristic.ConfiguredName, device.configDeviceName ?? device.deviceName ?? accessory.displayName)
|
|
80
84
|
.setCharacteristic(this.hap.Characteristic.Model, device.model ?? accessory.context.model)
|
|
81
85
|
.setCharacteristic(this.hap.Characteristic.ProductData, device.deviceId ?? accessory.context.deviceId)
|
|
82
86
|
.setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId);
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
async getDeviceLogSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
this.deviceLogging = accessory.context.logging = device.logging;
|
|
91
|
-
this.debugWarnLog(`Using Device Config Logging: ${this.deviceLogging}`);
|
|
92
|
-
} else if (this.config.logging) {
|
|
93
|
-
this.deviceLogging = accessory.context.logging = this.config.logging;
|
|
94
|
-
this.debugWarnLog(`Using Platform Config Logging: ${this.deviceLogging}`);
|
|
95
|
-
} else {
|
|
96
|
-
this.deviceLogging = accessory.context.logging = 'standard';
|
|
97
|
-
this.debugWarnLog(`Logging Not Set, Using: ${this.deviceLogging}`);
|
|
98
|
-
}
|
|
90
|
+
this.deviceLogging = this.platform.debugMode ? 'debugMode' : device.logging ?? this.config.logging ?? 'standard';
|
|
91
|
+
const logging = this.platform.debugMode ? 'Debug Mode' : device.logging ? 'Device Config' : this.config.logging ? 'Platform Config' : 'Default';
|
|
92
|
+
accessory.context.deviceLogging = this.deviceLogging;
|
|
93
|
+
await this.debugLog(`Using ${logging} Logging: ${this.deviceLogging}`);
|
|
99
94
|
}
|
|
100
95
|
|
|
101
96
|
async getDeviceRateSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
102
97
|
// refreshRate
|
|
103
|
-
|
|
104
|
-
this.deviceRefreshRate = device.refreshRate;
|
|
105
|
-
this.debugLog(`Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
106
|
-
} else if (this.config.options?.refreshRate) {
|
|
107
|
-
this.deviceRefreshRate = this.config.options.refreshRate;
|
|
108
|
-
this.debugLog(`Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
109
|
-
} else {
|
|
110
|
-
this.deviceRefreshRate = 5;
|
|
111
|
-
this.debugLog(`Using Default refreshRate: ${this.deviceRefreshRate}`);
|
|
112
|
-
}
|
|
98
|
+
this.deviceRefreshRate = device.refreshRate ?? this.config.options?.refreshRate ?? 5;
|
|
113
99
|
accessory.context.deviceRefreshRate = this.deviceRefreshRate;
|
|
100
|
+
const refreshRate = device.refreshRate ? 'Device Config' : this.config.options?.refreshRate ? 'Platform Config' : 'Default';
|
|
114
101
|
// updateRate
|
|
115
|
-
|
|
116
|
-
this.deviceUpdateRate = device.updateRate;
|
|
117
|
-
this.debugLog(`Using Device Config updateRate: ${this.deviceUpdateRate}`);
|
|
118
|
-
} else if (this.config.options?.updateRate) {
|
|
119
|
-
this.deviceUpdateRate = this.config.options.updateRate;
|
|
120
|
-
this.debugLog(`Using Platform Config updateRate: ${this.deviceUpdateRate}`);
|
|
121
|
-
} else {
|
|
122
|
-
this.deviceUpdateRate = 5;
|
|
123
|
-
this.debugLog(`Using Default updateRate: ${this.deviceUpdateRate}`);
|
|
124
|
-
}
|
|
102
|
+
this.deviceUpdateRate = device.updateRate ?? this.config.options?.updateRate ?? 5;
|
|
125
103
|
accessory.context.deviceUpdateRate = this.deviceUpdateRate;
|
|
104
|
+
const updateRate = device.updateRate ? 'Device Config' : this.config.options?.updateRate ? 'Platform Config' : 'Default';
|
|
126
105
|
// pushRate
|
|
127
|
-
|
|
128
|
-
this.devicePushRate = device.pushRate;
|
|
129
|
-
this.debugLog(`Using Device Config pushRate: ${this.deviceUpdateRate}`);
|
|
130
|
-
} else if (this.config.options?.pushRate) {
|
|
131
|
-
this.devicePushRate = this.config.options.pushRate;
|
|
132
|
-
this.debugLog(`Using Platform Config pushRate: ${this.deviceUpdateRate}`);
|
|
133
|
-
} else {
|
|
134
|
-
this.devicePushRate = 1;
|
|
135
|
-
this.debugLog(`Using Default pushRate: ${this.deviceUpdateRate}`);
|
|
136
|
-
}
|
|
106
|
+
this.devicePushRate = device.pushRate ?? this.config.options?.pushRate ?? 1;
|
|
137
107
|
accessory.context.devicePushRate = this.devicePushRate;
|
|
108
|
+
const pushRate = device.pushRate ? 'Device Config' : this.config.options?.pushRate ? 'Platform Config' : 'Default';
|
|
109
|
+
await this.debugLog(`Using ${refreshRate} refreshRate: ${this.deviceRefreshRate}, ${updateRate} updateRate: ${this.deviceUpdateRate},`
|
|
110
|
+
+ ` ${pushRate} pushRate: ${this.devicePushRate}`);
|
|
138
111
|
}
|
|
139
112
|
|
|
140
113
|
async getDeviceRetry(device: device & devicesConfig): Promise<void> {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
if (device.delayBetweenRetries) {
|
|
149
|
-
this.deviceDelayBetweenRetries = device.delayBetweenRetries * 1000;
|
|
150
|
-
this.debugLog(`Using Device Delay Between Retries: ${this.deviceDelayBetweenRetries}`);
|
|
151
|
-
} else {
|
|
152
|
-
this.deviceDelayBetweenRetries = 3000; // Delay between retries in milliseconds
|
|
153
|
-
this.debugLog(`Delay Between Retries Not Set, Using: ${this.deviceDelayBetweenRetries}`);
|
|
154
|
-
}
|
|
114
|
+
this.deviceMaxRetries = device.maxRetries ?? 5;
|
|
115
|
+
const maxRetries = device.maxRetries ? 'Device' : 'Default';
|
|
116
|
+
this.deviceDelayBetweenRetries = device.delayBetweenRetries ? (device.delayBetweenRetries * 1000) : 3000;
|
|
117
|
+
const delayBetweenRetries = device.delayBetweenRetries ? 'Device' : 'Default';
|
|
118
|
+
await this.debugLog(`Using ${maxRetries} Max Retries: ${this.deviceMaxRetries},`
|
|
119
|
+
+ ` ${delayBetweenRetries} Delay Between Retries: ${this.deviceDelayBetweenRetries}`);
|
|
155
120
|
}
|
|
156
121
|
|
|
157
122
|
async retryBLE({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
|
|
@@ -167,14 +132,12 @@ export abstract class deviceBase {
|
|
|
167
132
|
}
|
|
168
133
|
|
|
169
134
|
async maxRetryBLE(): Promise<number> {
|
|
170
|
-
|
|
171
|
-
return this.device.maxRetry;
|
|
172
|
-
} else {
|
|
173
|
-
return 5;
|
|
174
|
-
}
|
|
135
|
+
return this.device.maxRetry ? this.device.maxRetry : 5;
|
|
175
136
|
}
|
|
176
137
|
|
|
177
138
|
async getDeviceScanDuration(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
139
|
+
this.scanDuration = device.scanDuration ? (this.deviceUpdateRate > device.scanDuration) ? this.deviceUpdateRate : device.scanDuration
|
|
140
|
+
? (this.deviceUpdateRate > 1) ? this.deviceUpdateRate : 1 : this.deviceUpdateRate : 1;
|
|
178
141
|
if (device.scanDuration) {
|
|
179
142
|
if (this.deviceUpdateRate > device.scanDuration) {
|
|
180
143
|
this.scanDuration = this.deviceUpdateRate;
|
|
@@ -199,7 +162,7 @@ export abstract class deviceBase {
|
|
|
199
162
|
}
|
|
200
163
|
}
|
|
201
164
|
|
|
202
|
-
async getDeviceConfigSettings(
|
|
165
|
+
async getDeviceConfigSettings(device: device & devicesConfig): Promise<void> {
|
|
203
166
|
const deviceConfig = {};
|
|
204
167
|
if (device.logging !== 'standard') {
|
|
205
168
|
deviceConfig['logging'] = device.logging;
|
|
@@ -231,6 +194,12 @@ export abstract class deviceBase {
|
|
|
231
194
|
if (device.mqttURL !== '') {
|
|
232
195
|
deviceConfig['mqttURL'] = device.mqttURL;
|
|
233
196
|
}
|
|
197
|
+
if (device.mqttOptions) {
|
|
198
|
+
deviceConfig['mqttOptions'] = device.mqttOptions;
|
|
199
|
+
}
|
|
200
|
+
if (device.mqttPubOptions) {
|
|
201
|
+
deviceConfig['mqttPubOptions'] = device.mqttPubOptions;
|
|
202
|
+
}
|
|
234
203
|
if (device.maxRetries !== 0) {
|
|
235
204
|
deviceConfig['maxRetries'] = device.maxRetries;
|
|
236
205
|
}
|
|
@@ -319,21 +288,10 @@ export abstract class deviceBase {
|
|
|
319
288
|
const numberOfLevels = spaceBetweenLevels + 1;
|
|
320
289
|
this.debugLog(`LightLevel: ${lightLevel}, set_minLux: ${set_minLux}, set_maxLux: ${set_maxLux}, spaceBetweenLevels: ${spaceBetweenLevels},`
|
|
321
290
|
+ ` numberOfLevels: ${numberOfLevels}`);
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
this.debugLog(`LightLevel: ${lightLevel}, set_minLux: ${set_minLux}`);
|
|
327
|
-
break;
|
|
328
|
-
case numberOfLevels:
|
|
329
|
-
CurrentAmbientLightLevel = set_maxLux;
|
|
330
|
-
this.debugLog(`LightLevel: ${lightLevel}, set_maxLux: ${set_maxLux}`);
|
|
331
|
-
break;
|
|
332
|
-
default:
|
|
333
|
-
CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * (Number(lightLevel) - 1);
|
|
334
|
-
this.debugLog(`LightLevel: ${lightLevel}`);
|
|
335
|
-
}
|
|
336
|
-
this.debugLog(`CurrentAmbientLightLevel: ${CurrentAmbientLightLevel}`);
|
|
291
|
+
const CurrentAmbientLightLevel = lightLevel === 1 ? set_minLux : lightLevel = numberOfLevels
|
|
292
|
+
? set_maxLux : ((set_maxLux - set_minLux) / spaceBetweenLevels) * (Number(lightLevel) - 1);
|
|
293
|
+
await this.debugLog(`CurrentAmbientLightLevel: ${CurrentAmbientLightLevel}, LightLevel: ${lightLevel}, set_minLux: ${set_minLux},`
|
|
294
|
+
+ ` set_maxLux: ${set_maxLux}`);
|
|
337
295
|
return CurrentAmbientLightLevel;
|
|
338
296
|
}
|
|
339
297
|
|
|
@@ -342,41 +300,29 @@ export abstract class deviceBase {
|
|
|
342
300
|
* 'homebridge-switchbot/${this.device.deviceType}/xx:xx:xx:xx:xx:xx'
|
|
343
301
|
*/
|
|
344
302
|
async mqttPublish(message: string, topic?: string) {
|
|
345
|
-
const mac = this.device.deviceId
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const options = this.device.mqttPubOptions || {};
|
|
350
|
-
let mqttTopic: string;
|
|
351
|
-
let mqttMessageTopic: string;
|
|
352
|
-
if (topic) {
|
|
353
|
-
mqttTopic = `/${topic}`;
|
|
354
|
-
mqttMessageTopic = `${topic}/`;
|
|
355
|
-
} else {
|
|
356
|
-
mqttTopic = '';
|
|
357
|
-
mqttMessageTopic = '';
|
|
358
|
-
}
|
|
303
|
+
const mac = this.device.deviceId?.toLowerCase().match(/[\s\S]{1,2}/g)?.join(':');
|
|
304
|
+
const options = this.deviceMqttPubOptions ?? {};
|
|
305
|
+
const mqttTopic = topic ? `/${topic}` : '';
|
|
306
|
+
const mqttMessageTopic = topic ? `${topic}/` : '';
|
|
359
307
|
this.mqttClient?.publish(`homebridge-switchbot/${this.device.deviceType}/${mac}${mqttTopic}`, `${message}`, options);
|
|
360
308
|
this.debugLog(`MQTT message: ${mqttMessageTopic}${message} options:${JSON.stringify(options)}`);
|
|
361
309
|
}
|
|
362
310
|
|
|
363
311
|
/*
|
|
364
|
-
*
|
|
312
|
+
* MQTT Settings
|
|
365
313
|
*/
|
|
366
|
-
async
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
}
|
|
314
|
+
async getMqttSettings(device: device & devicesConfig): Promise<void> {
|
|
315
|
+
// mqttURL
|
|
316
|
+
this.deviceMqttURL = device.mqttURL ?? this.config.options?.mqttURL ?? '';
|
|
317
|
+
const mqttURL = device.mqttURL ? 'Device Config' : this.config.options?.mqttURL ? 'Platform Config' : 'Default';
|
|
318
|
+
// mqttOptions
|
|
319
|
+
this.deviceMqttOptions = device.mqttOptions ?? this.config.options?.mqttOptions ?? {};
|
|
320
|
+
const mqttOptions = device.mqttOptions ? 'Device Config' : this.config.options?.mqttOptions ? 'Platform Config' : 'Default';
|
|
321
|
+
// mqttPubOptions
|
|
322
|
+
this.deviceMqttPubOptions = device.mqttPubOptions ?? this.config.options?.mqttPubOptions ?? {};
|
|
323
|
+
const mqttPubOptions = device.mqttPubOptions ? 'Device Config' : this.config.options?.mqttPubOptions ? 'Platform Config' : 'Default';
|
|
324
|
+
await this.debugLog(`Using ${mqttURL} MQTT URL: ${this.deviceMqttURL}, ${mqttOptions} mqttOptions: ${JSON.stringify(this.deviceMqttOptions)},`
|
|
325
|
+
+ ` ${mqttPubOptions} mqttPubOptions: ${JSON.stringify(this.deviceMqttPubOptions)}`);
|
|
380
326
|
}
|
|
381
327
|
|
|
382
328
|
/*
|
|
@@ -715,32 +661,14 @@ export abstract class deviceBase {
|
|
|
715
661
|
device.bleModelName = SwitchBotBLEModelName.Unknown;
|
|
716
662
|
device.bleModelFriednlyName = SwitchBotBLEModelFriendlyName.Unknown;
|
|
717
663
|
}
|
|
718
|
-
this.debugLog(`Model: ${device.model}, BLE Model: ${device.bleModel}, BLE Model Name: ${device.bleModelName}, `
|
|
664
|
+
await this.debugLog(`Model: ${device.model}, BLE Model: ${device.bleModel}, BLE Model Name: ${device.bleModelName}, `
|
|
719
665
|
+ `BLE Model Friendly Name: ${device.bleModelFriednlyName}`);
|
|
720
666
|
accessory.context.model = device.model;
|
|
721
667
|
accessory.context.bleModel = device.bleModel;
|
|
722
668
|
accessory.context.bleModelName = device.bleModelName;
|
|
723
669
|
accessory.context.bleModelFriednlyName = device.bleModelFriednlyName;
|
|
724
670
|
|
|
725
|
-
|
|
726
|
-
let deviceFirmwareVersion: string;
|
|
727
|
-
if (device.firmware) {
|
|
728
|
-
deviceFirmwareVersion = device.firmware;
|
|
729
|
-
this.debugSuccessLog(`1 FirmwareRevision: ${device.firmware}`);
|
|
730
|
-
} else if (device.version) {
|
|
731
|
-
deviceFirmwareVersion = JSON.stringify(device.version);
|
|
732
|
-
this.debugSuccessLog(`2 FirmwareRevision: ${device.version}`);
|
|
733
|
-
} else if (accessory.context.deviceVersion) {
|
|
734
|
-
deviceFirmwareVersion = accessory.context.deviceVersion;
|
|
735
|
-
this.debugSuccessLog(`3 FirmwareRevision: ${accessory.context.deviceVersion}`);
|
|
736
|
-
} else {
|
|
737
|
-
deviceFirmwareVersion = this.platform.version ?? '0.0.0';
|
|
738
|
-
if (this.platform.version) {
|
|
739
|
-
this.debugSuccessLog(`4 FirmwareRevision: ${this.platform.version}`);
|
|
740
|
-
} else {
|
|
741
|
-
this.debugSuccessLog(`5 FirmwareRevision: ${deviceFirmwareVersion}`);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
671
|
+
const deviceFirmwareVersion = device.firmware ?? device.version ?? accessory.context.version ?? this.platform.version ?? '0.0.0';
|
|
744
672
|
const version = deviceFirmwareVersion.toString();
|
|
745
673
|
this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`);
|
|
746
674
|
let deviceVersion: string;
|
|
@@ -759,8 +687,8 @@ export abstract class deviceBase {
|
|
|
759
687
|
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
760
688
|
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
761
689
|
.updateValue(deviceVersion);
|
|
762
|
-
accessory.context.
|
|
763
|
-
this.debugSuccessLog(`
|
|
690
|
+
accessory.context.version = deviceVersion;
|
|
691
|
+
this.debugSuccessLog(`version: ${accessory.context.version}`);
|
|
764
692
|
}
|
|
765
693
|
|
|
766
694
|
async statusCode(statusCode: number): Promise<void> {
|