@switchbot/homebridge-switchbot 3.6.1-beta.0 → 3.6.1-beta.10
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 +11 -0
- package/config.schema.json +11 -0
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +36 -18
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +1 -2
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +186 -396
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +3 -2
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +57 -32
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +3 -2
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +58 -30
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +36 -19
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +37 -18
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +9 -0
- package/dist/device/device.d.ts.map +1 -1
- package/dist/device/device.js +32 -5
- package/dist/device/device.js.map +1 -1
- package/dist/device/fan.d.ts.map +1 -1
- package/dist/device/fan.js +36 -19
- package/dist/device/fan.js.map +1 -1
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +38 -19
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +40 -21
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +38 -19
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +4 -3
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +58 -32
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +37 -18
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +38 -19
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +38 -19
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +36 -17
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +37 -18
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +36 -17
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +36 -17
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/irdevice/other.d.ts +1 -0
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +186 -228
- package/dist/irdevice/other.js.map +1 -1
- package/dist/platform.d.ts +4 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +41 -0
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +1 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/dist/types/bledevicestatus.d.ts +1 -0
- package/dist/types/bledevicestatus.d.ts.map +1 -1
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +16 -0
- package/dist/utils.js.map +1 -1
- package/package.json +8 -8
- package/src/device/blindtilt.ts +33 -18
- package/src/device/bot.ts +179 -406
- package/src/device/ceilinglight.ts +54 -34
- package/src/device/colorbulb.ts +56 -32
- package/src/device/contact.ts +33 -20
- package/src/device/curtain.ts +34 -18
- package/src/device/device.ts +38 -5
- package/src/device/fan.ts +33 -20
- package/src/device/hub.ts +35 -19
- package/src/device/humidifier.ts +37 -21
- package/src/device/iosensor.ts +35 -19
- package/src/device/lightstrip.ts +57 -34
- package/src/device/lock.ts +34 -18
- package/src/device/meter.ts +35 -19
- package/src/device/meterplus.ts +35 -19
- package/src/device/motion.ts +33 -17
- package/src/device/plug.ts +34 -18
- package/src/device/robotvacuumcleaner.ts +33 -17
- package/src/device/waterdetector.ts +33 -17
- package/src/irdevice/other.ts +214 -283
- package/src/platform.ts +39 -0
- package/src/settings.ts +1 -0
- package/src/types/bledevicestatus.ts +1 -0
- package/src/utils.ts +15 -0
|
@@ -42,8 +42,9 @@ export class CeilingLight extends deviceBase {
|
|
|
42
42
|
serviceData!: ceilingLightServiceData | ceilingLightProServiceData;
|
|
43
43
|
|
|
44
44
|
// Adaptive Lighting
|
|
45
|
+
adaptiveLighting!: boolean;
|
|
46
|
+
adaptiveLightingShift!: number;
|
|
45
47
|
AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
|
|
46
|
-
adaptiveLightingShift?: number;
|
|
47
48
|
|
|
48
49
|
// Updates
|
|
49
50
|
ceilingLightUpdateInProgress!: boolean;
|
|
@@ -59,7 +60,7 @@ export class CeilingLight extends deviceBase {
|
|
|
59
60
|
accessory.category = this.hap.Categories.LIGHTBULB;
|
|
60
61
|
|
|
61
62
|
// default placeholders
|
|
62
|
-
this.
|
|
63
|
+
this.getAdaptiveLightingSettings(accessory, device);
|
|
63
64
|
|
|
64
65
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
65
66
|
this.doCeilingLightUpdate = new Subject();
|
|
@@ -78,23 +79,24 @@ export class CeilingLight extends deviceBase {
|
|
|
78
79
|
};
|
|
79
80
|
accessory.context.LightBulb = this.LightBulb as object;
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
if (this.adaptiveLightingShift === -1 && accessory.context.adaptiveLighting) {
|
|
82
|
+
if (this.adaptiveLighting && this.adaptiveLightingShift === -1 && this.LightBulb) {
|
|
83
83
|
accessory.removeService(this.LightBulb.Service);
|
|
84
84
|
this.LightBulb.Service = accessory.addService(this.hap.Service.Lightbulb);
|
|
85
85
|
accessory.context.adaptiveLighting = false;
|
|
86
|
-
this.debugLog(`adaptiveLighting: ${
|
|
87
|
-
}
|
|
88
|
-
if (this.adaptiveLightingShift !== -1) {
|
|
86
|
+
this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
|
|
87
|
+
} else if (this.adaptiveLighting && this.adaptiveLightingShift >= 0 && this.LightBulb) {
|
|
89
88
|
this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.LightBulb.Service, {
|
|
89
|
+
controllerMode: this.hap.AdaptiveLightingControllerMode.AUTOMATIC,
|
|
90
90
|
customTemperatureAdjustment: this.adaptiveLightingShift,
|
|
91
91
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
this.debugLog(`adaptiveLighting: ${this.
|
|
95
|
-
|
|
92
|
+
accessory.configureController(this.AdaptiveLightingController);
|
|
93
|
+
accessory.context.adaptiveLighting = true;
|
|
94
|
+
this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}, adaptiveLightingShift: ${this.adaptiveLightingShift}`,
|
|
95
|
+
);
|
|
96
|
+
} else {
|
|
97
|
+
accessory.context.adaptiveLighting = false;
|
|
98
|
+
this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting}`);
|
|
96
99
|
}
|
|
97
|
-
this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
98
100
|
|
|
99
101
|
// Initialize LightBulb Characteristics
|
|
100
102
|
this.LightBulb.Service
|
|
@@ -166,9 +168,6 @@ export class CeilingLight extends deviceBase {
|
|
|
166
168
|
this.debugLog('Registering Webhook Event Handler');
|
|
167
169
|
this.registerWebhook();
|
|
168
170
|
|
|
169
|
-
//regisiter webhook event handler
|
|
170
|
-
this.registerWebhook();
|
|
171
|
-
|
|
172
171
|
// Start an update interval
|
|
173
172
|
interval(this.deviceRefreshRate * 1000)
|
|
174
173
|
.pipe(skipWhile(() => this.ceilingLightUpdateInProgress))
|
|
@@ -276,7 +275,7 @@ export class CeilingLight extends deviceBase {
|
|
|
276
275
|
async refreshStatus(): Promise<void> {
|
|
277
276
|
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
278
277
|
await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
279
|
-
} else if (this.BLE) {
|
|
278
|
+
} else if (this.BLE || this.config.options?.BLE) {
|
|
280
279
|
await this.BLERefreshStatus();
|
|
281
280
|
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
282
281
|
await this.openAPIRefreshStatus();
|
|
@@ -288,25 +287,41 @@ export class CeilingLight extends deviceBase {
|
|
|
288
287
|
|
|
289
288
|
async BLERefreshStatus(): Promise<void> {
|
|
290
289
|
await this.debugLog('BLERefreshStatus');
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
await this.
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
// Update HomeKit
|
|
300
|
-
if ((serviceData.model === SwitchBotBLEModel.CeilingLight || SwitchBotBLEModel.CeilingLightPro)
|
|
301
|
-
&& serviceData.modelName === SwitchBotBLEModelName.CeilingLight || SwitchBotBLEModelName.CeilingLightPro) {
|
|
302
|
-
this.serviceData = serviceData;
|
|
290
|
+
if (this.config.options?.BLE) {
|
|
291
|
+
await this.debugLog('is listening to Platform BLE.');
|
|
292
|
+
this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
|
|
293
|
+
await this.debugLog(`bleMac: ${this.device.bleMac}`);
|
|
294
|
+
this.platform.bleEventHandler[this.device.bleMac] = async (context: ceilingLightServiceData) => {
|
|
295
|
+
try {
|
|
296
|
+
await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
|
|
297
|
+
this.serviceData = context;
|
|
303
298
|
await this.BLEparseStatus();
|
|
304
299
|
await this.updateHomeKitCharacteristics();
|
|
305
|
-
}
|
|
306
|
-
await this.errorLog(`failed to
|
|
307
|
-
await this.BLERefreshConnection(switchbot);
|
|
300
|
+
} catch (e: any) {
|
|
301
|
+
await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
308
302
|
}
|
|
309
|
-
}
|
|
303
|
+
};
|
|
304
|
+
} else {
|
|
305
|
+
await this.debugLog('is using Device BLE Scanning.');
|
|
306
|
+
const switchbot = await this.switchbotBLE();
|
|
307
|
+
if (switchbot === undefined) {
|
|
308
|
+
await this.BLERefreshConnection(switchbot);
|
|
309
|
+
} else {
|
|
310
|
+
(async () => {
|
|
311
|
+
// Start to monitor advertisement packets
|
|
312
|
+
const serviceData = await this.monitorAdvertisementPackets(switchbot) as unknown as ceilingLightServiceData;
|
|
313
|
+
// Update HomeKit
|
|
314
|
+
if ((serviceData.model === SwitchBotBLEModel.CeilingLight || SwitchBotBLEModel.CeilingLightPro)
|
|
315
|
+
&& serviceData.modelName === SwitchBotBLEModelName.CeilingLight || SwitchBotBLEModelName.CeilingLightPro) {
|
|
316
|
+
this.serviceData = serviceData;
|
|
317
|
+
await this.BLEparseStatus();
|
|
318
|
+
await this.updateHomeKitCharacteristics();
|
|
319
|
+
} else {
|
|
320
|
+
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
|
|
321
|
+
await this.BLERefreshConnection(switchbot);
|
|
322
|
+
}
|
|
323
|
+
})();
|
|
324
|
+
}
|
|
310
325
|
}
|
|
311
326
|
}
|
|
312
327
|
|
|
@@ -687,13 +702,18 @@ export class CeilingLight extends deviceBase {
|
|
|
687
702
|
this.LightBulb.Saturation, 'Saturation');
|
|
688
703
|
}
|
|
689
704
|
|
|
690
|
-
async
|
|
705
|
+
async getAdaptiveLightingSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
706
|
+
// Adaptive Lighting
|
|
707
|
+
this.adaptiveLighting = accessory.context.adaptiveLighting ?? true;
|
|
708
|
+
await this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
|
|
709
|
+
// Adaptive Lighting Shift
|
|
691
710
|
if (device.ceilinglight?.adaptiveLightingShift) {
|
|
692
711
|
this.adaptiveLightingShift = device.ceilinglight.adaptiveLightingShift;
|
|
712
|
+
this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
693
713
|
} else {
|
|
694
714
|
this.adaptiveLightingShift = 0;
|
|
715
|
+
this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
695
716
|
}
|
|
696
|
-
await this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
697
717
|
}
|
|
698
718
|
|
|
699
719
|
async BLEPushConnection() {
|
package/src/device/colorbulb.ts
CHANGED
|
@@ -42,8 +42,9 @@ export class ColorBulb extends deviceBase {
|
|
|
42
42
|
serviceData!: colorBulbServiceData;
|
|
43
43
|
|
|
44
44
|
// Adaptive Lighting
|
|
45
|
+
adaptiveLighting!: boolean;
|
|
46
|
+
adaptiveLightingShift!: number;
|
|
45
47
|
AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
|
|
46
|
-
adaptiveLightingShift?: number;
|
|
47
48
|
|
|
48
49
|
// Updates
|
|
49
50
|
colorBulbUpdateInProgress!: boolean;
|
|
@@ -59,7 +60,7 @@ export class ColorBulb extends deviceBase {
|
|
|
59
60
|
accessory.category = this.hap.Categories.LIGHTBULB;
|
|
60
61
|
|
|
61
62
|
// default placeholders
|
|
62
|
-
this.
|
|
63
|
+
this.getAdaptiveLightingSettings(accessory, device);
|
|
63
64
|
|
|
64
65
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
65
66
|
this.doColorBulbUpdate = new Subject();
|
|
@@ -67,6 +68,10 @@ export class ColorBulb extends deviceBase {
|
|
|
67
68
|
|
|
68
69
|
// Initialize LightBulb property
|
|
69
70
|
accessory.context.LightBulb = accessory.context.LightBulb ?? {};
|
|
71
|
+
if (accessory.context.LightBulb.Name) {
|
|
72
|
+
accessory.context.LightBulb.Name = this.validateAndCleanString(accessory.context.LightBulb.Name,
|
|
73
|
+
'LightBulb Name', accessory.context.LightBulb.Name);
|
|
74
|
+
}
|
|
70
75
|
this.LightBulb = {
|
|
71
76
|
Name: accessory.context.LightBulb.Name ?? accessory.displayName,
|
|
72
77
|
Service: accessory.getService(this.hap.Service.Lightbulb) ?? accessory.addService(this.hap.Service.Lightbulb) as Service,
|
|
@@ -78,23 +83,24 @@ export class ColorBulb extends deviceBase {
|
|
|
78
83
|
};
|
|
79
84
|
accessory.context.LightBulb = this.LightBulb as object;
|
|
80
85
|
|
|
81
|
-
|
|
82
|
-
if (this.adaptiveLightingShift === -1 && accessory.context.adaptiveLighting) {
|
|
86
|
+
if (this.adaptiveLighting && this.adaptiveLightingShift === -1 && this.LightBulb) {
|
|
83
87
|
accessory.removeService(this.LightBulb.Service);
|
|
84
88
|
this.LightBulb.Service = accessory.addService(this.hap.Service.Lightbulb);
|
|
85
89
|
accessory.context.adaptiveLighting = false;
|
|
86
|
-
this.debugLog(`adaptiveLighting: ${
|
|
87
|
-
}
|
|
88
|
-
if (this.adaptiveLightingShift !== -1) {
|
|
90
|
+
this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
|
|
91
|
+
} else if (this.adaptiveLighting && this.adaptiveLightingShift >= 0 && this.LightBulb) {
|
|
89
92
|
this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.LightBulb.Service, {
|
|
93
|
+
controllerMode: this.hap.AdaptiveLightingControllerMode.AUTOMATIC,
|
|
90
94
|
customTemperatureAdjustment: this.adaptiveLightingShift,
|
|
91
95
|
});
|
|
92
96
|
accessory.configureController(this.AdaptiveLightingController);
|
|
93
97
|
accessory.context.adaptiveLighting = true;
|
|
94
|
-
this.debugLog(`adaptiveLighting: ${
|
|
95
|
-
|
|
98
|
+
this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}, adaptiveLightingShift: ${this.adaptiveLightingShift}`,
|
|
99
|
+
);
|
|
100
|
+
} else {
|
|
101
|
+
accessory.context.adaptiveLighting = false;
|
|
102
|
+
this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting}`);
|
|
96
103
|
}
|
|
97
|
-
this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
98
104
|
|
|
99
105
|
// Initialize LightBulb Characteristics
|
|
100
106
|
this.LightBulb.Service
|
|
@@ -162,9 +168,6 @@ export class ColorBulb extends deviceBase {
|
|
|
162
168
|
this.debugLog('Registering Webhook Event Handler');
|
|
163
169
|
this.registerWebhook();
|
|
164
170
|
|
|
165
|
-
//regisiter webhook event handler
|
|
166
|
-
this.registerWebhook();
|
|
167
|
-
|
|
168
171
|
// Start an update interval
|
|
169
172
|
interval(this.deviceRefreshRate * 1000)
|
|
170
173
|
.pipe(skipWhile(() => this.colorBulbUpdateInProgress))
|
|
@@ -297,7 +300,7 @@ export class ColorBulb extends deviceBase {
|
|
|
297
300
|
async refreshStatus(): Promise<void> {
|
|
298
301
|
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
299
302
|
await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
300
|
-
} else if (this.BLE) {
|
|
303
|
+
} else if (this.BLE || this.config.options?.BLE) {
|
|
301
304
|
await this.BLERefreshStatus();
|
|
302
305
|
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
303
306
|
await this.openAPIRefreshStatus();
|
|
@@ -309,25 +312,41 @@ export class ColorBulb extends deviceBase {
|
|
|
309
312
|
|
|
310
313
|
async BLERefreshStatus(): Promise<void> {
|
|
311
314
|
await this.debugLog('BLERefreshStatus');
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
await this.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const serviceData = await this.monitorAdvertisementPackets(switchbot) as colorBulbServiceData;
|
|
321
|
-
// Update HomeKit
|
|
322
|
-
if (serviceData.model === SwitchBotBLEModel.ColorBulb && serviceData.modelName === SwitchBotBLEModelName.ColorBulb) {
|
|
323
|
-
this.serviceData = serviceData;
|
|
315
|
+
if (this.config.options?.BLE) {
|
|
316
|
+
await this.debugLog('is listening to Platform BLE.');
|
|
317
|
+
this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
|
|
318
|
+
await this.debugLog(`bleMac: ${this.device.bleMac}`);
|
|
319
|
+
this.platform.bleEventHandler[this.device.bleMac] = async (context: colorBulbServiceData) => {
|
|
320
|
+
try {
|
|
321
|
+
await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
|
|
322
|
+
this.serviceData = context;
|
|
324
323
|
await this.BLEparseStatus();
|
|
325
324
|
await this.updateHomeKitCharacteristics();
|
|
326
|
-
}
|
|
327
|
-
await this.errorLog(`failed to
|
|
328
|
-
await this.BLERefreshConnection(switchbot);
|
|
325
|
+
} catch (e: any) {
|
|
326
|
+
await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
329
327
|
}
|
|
330
|
-
}
|
|
328
|
+
};
|
|
329
|
+
} else {
|
|
330
|
+
await this.debugLog('is using Device BLE Scanning.');
|
|
331
|
+
const switchbot = await this.switchbotBLE();
|
|
332
|
+
if (switchbot === undefined) {
|
|
333
|
+
await this.BLERefreshConnection(switchbot);
|
|
334
|
+
} else {
|
|
335
|
+
// Start to monitor advertisement packets
|
|
336
|
+
(async () => {
|
|
337
|
+
// Start to monitor advertisement packets
|
|
338
|
+
const serviceData = await this.monitorAdvertisementPackets(switchbot) as colorBulbServiceData;
|
|
339
|
+
// Update HomeKit
|
|
340
|
+
if (serviceData.model === SwitchBotBLEModel.ColorBulb && serviceData.modelName === SwitchBotBLEModelName.ColorBulb) {
|
|
341
|
+
this.serviceData = serviceData;
|
|
342
|
+
await this.BLEparseStatus();
|
|
343
|
+
await this.updateHomeKitCharacteristics();
|
|
344
|
+
} else {
|
|
345
|
+
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
|
|
346
|
+
await this.BLERefreshConnection(switchbot);
|
|
347
|
+
}
|
|
348
|
+
})();
|
|
349
|
+
}
|
|
331
350
|
}
|
|
332
351
|
}
|
|
333
352
|
|
|
@@ -820,13 +839,18 @@ export class ColorBulb extends deviceBase {
|
|
|
820
839
|
this.LightBulb.Saturation, 'Saturation');
|
|
821
840
|
}
|
|
822
841
|
|
|
823
|
-
async
|
|
842
|
+
async getAdaptiveLightingSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
843
|
+
// Adaptive Lighting
|
|
844
|
+
this.adaptiveLighting = accessory.context.adaptiveLighting ?? true;
|
|
845
|
+
await this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
|
|
846
|
+
// Adaptive Lighting Shift
|
|
824
847
|
if (device.colorbulb?.adaptiveLightingShift) {
|
|
825
848
|
this.adaptiveLightingShift = device.colorbulb.adaptiveLightingShift;
|
|
849
|
+
this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
826
850
|
} else {
|
|
827
851
|
this.adaptiveLightingShift = 0;
|
|
852
|
+
this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
828
853
|
}
|
|
829
|
-
await this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
830
854
|
}
|
|
831
855
|
|
|
832
856
|
async BLEPushConnection() {
|
package/src/device/contact.ts
CHANGED
|
@@ -176,9 +176,6 @@ export class Contact extends deviceBase {
|
|
|
176
176
|
this.debugLog('Registering Webhook Event Handler');
|
|
177
177
|
this.registerWebhook();
|
|
178
178
|
|
|
179
|
-
//regisiter webhook event handler
|
|
180
|
-
this.registerWebhook();
|
|
181
|
-
|
|
182
179
|
// Start an update interval
|
|
183
180
|
interval(this.deviceRefreshRate * 1000)
|
|
184
181
|
.pipe(skipWhile(() => this.contactUpdateInProgress))
|
|
@@ -287,7 +284,7 @@ export class Contact extends deviceBase {
|
|
|
287
284
|
async refreshStatus(): Promise<void> {
|
|
288
285
|
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
289
286
|
await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
290
|
-
} else if (this.BLE) {
|
|
287
|
+
} else if (this.BLE || this.config.options?.BLE) {
|
|
291
288
|
await this.BLERefreshStatus();
|
|
292
289
|
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
293
290
|
await this.openAPIRefreshStatus();
|
|
@@ -299,25 +296,41 @@ export class Contact extends deviceBase {
|
|
|
299
296
|
|
|
300
297
|
async BLERefreshStatus(): Promise<void> {
|
|
301
298
|
await this.debugLog('BLERefreshStatus');
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
await this.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const serviceData = await this.monitorAdvertisementPackets(switchbot) as contactSensorServiceData;
|
|
311
|
-
// Update HomeKit
|
|
312
|
-
if (serviceData.model === SwitchBotBLEModel.ContactSensor && serviceData.modelName === SwitchBotBLEModelName.ContactSensor) {
|
|
313
|
-
this.serviceData = serviceData;
|
|
299
|
+
if (this.config.options?.BLE) {
|
|
300
|
+
await this.debugLog('is listening to Platform BLE.');
|
|
301
|
+
this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
|
|
302
|
+
await this.debugLog(`bleMac: ${this.device.bleMac}`);
|
|
303
|
+
this.platform.bleEventHandler[this.device.bleMac] = async (context: contactSensorServiceData) => {
|
|
304
|
+
try {
|
|
305
|
+
await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
|
|
306
|
+
this.serviceData = context;
|
|
314
307
|
await this.BLEparseStatus();
|
|
315
308
|
await this.updateHomeKitCharacteristics();
|
|
316
|
-
}
|
|
317
|
-
await this.errorLog(`failed to
|
|
318
|
-
await this.BLERefreshConnection(switchbot);
|
|
309
|
+
} catch (e: any) {
|
|
310
|
+
await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
319
311
|
}
|
|
320
|
-
}
|
|
312
|
+
};
|
|
313
|
+
} else {
|
|
314
|
+
await this.debugLog('is using Device BLE Scanning.');
|
|
315
|
+
const switchbot = await this.switchbotBLE();
|
|
316
|
+
if (switchbot === undefined) {
|
|
317
|
+
await this.BLERefreshConnection(switchbot);
|
|
318
|
+
} else {
|
|
319
|
+
// Start to monitor advertisement packets
|
|
320
|
+
(async () => {
|
|
321
|
+
// Start to monitor advertisement packets
|
|
322
|
+
const serviceData = await this.monitorAdvertisementPackets(switchbot) as contactSensorServiceData;
|
|
323
|
+
// Update HomeKit
|
|
324
|
+
if (serviceData.model === SwitchBotBLEModel.ContactSensor && serviceData.modelName === SwitchBotBLEModelName.ContactSensor) {
|
|
325
|
+
this.serviceData = serviceData;
|
|
326
|
+
await this.BLEparseStatus();
|
|
327
|
+
await this.updateHomeKitCharacteristics();
|
|
328
|
+
} else {
|
|
329
|
+
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
|
|
330
|
+
await this.BLERefreshConnection(switchbot);
|
|
331
|
+
}
|
|
332
|
+
})();
|
|
333
|
+
}
|
|
321
334
|
}
|
|
322
335
|
}
|
|
323
336
|
|
package/src/device/curtain.ts
CHANGED
|
@@ -425,7 +425,7 @@ export class Curtain extends deviceBase {
|
|
|
425
425
|
async refreshStatus(): Promise<void> {
|
|
426
426
|
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
427
427
|
await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
428
|
-
} else if (this.BLE) {
|
|
428
|
+
} else if (this.BLE || this.config.options?.BLE) {
|
|
429
429
|
await this.BLERefreshStatus();
|
|
430
430
|
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
431
431
|
await this.openAPIRefreshStatus();
|
|
@@ -437,26 +437,42 @@ export class Curtain extends deviceBase {
|
|
|
437
437
|
|
|
438
438
|
async BLERefreshStatus(): Promise<void> {
|
|
439
439
|
await this.debugLog('BLERefreshStatus');
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
await this.
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const serviceData = await this.monitorAdvertisementPackets(switchbot) as curtainServiceData | curtain3ServiceData;
|
|
449
|
-
// Update HomeKit
|
|
450
|
-
if ((serviceData.model === SwitchBotBLEModel.Curtain || SwitchBotBLEModel.Curtain3)
|
|
451
|
-
&& (serviceData.modelName === SwitchBotBLEModelName.Curtain || SwitchBotBLEModelName.Curtain3)) {
|
|
452
|
-
this.serviceData = serviceData;
|
|
440
|
+
if (this.config.options?.BLE) {
|
|
441
|
+
await this.debugLog('is listening to Platform BLE.');
|
|
442
|
+
this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
|
|
443
|
+
await this.debugLog(`bleMac: ${this.device.bleMac}`);
|
|
444
|
+
this.platform.bleEventHandler[this.device.bleMac] = async (context: curtainServiceData | curtain3ServiceData) => {
|
|
445
|
+
try {
|
|
446
|
+
await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
|
|
447
|
+
this.serviceData = context;
|
|
453
448
|
await this.BLEparseStatus();
|
|
454
449
|
await this.updateHomeKitCharacteristics();
|
|
455
|
-
}
|
|
456
|
-
await this.errorLog(`failed to
|
|
457
|
-
await this.BLERefreshConnection(switchbot);
|
|
450
|
+
} catch (e: any) {
|
|
451
|
+
await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
458
452
|
}
|
|
459
|
-
}
|
|
453
|
+
};
|
|
454
|
+
} else {
|
|
455
|
+
await this.debugLog('is using Device BLE Scanning.');
|
|
456
|
+
const switchbot = await this.switchbotBLE();
|
|
457
|
+
if (switchbot === undefined) {
|
|
458
|
+
await this.BLERefreshConnection(switchbot);
|
|
459
|
+
} else {
|
|
460
|
+
// Start to monitor advertisement packets
|
|
461
|
+
(async () => {
|
|
462
|
+
// Start to monitor advertisement packets
|
|
463
|
+
const serviceData = await this.monitorAdvertisementPackets(switchbot) as curtainServiceData | curtain3ServiceData;
|
|
464
|
+
// Update HomeKit
|
|
465
|
+
if ((serviceData.model === SwitchBotBLEModel.Curtain || SwitchBotBLEModel.Curtain3)
|
|
466
|
+
&& (serviceData.modelName === SwitchBotBLEModelName.Curtain || SwitchBotBLEModelName.Curtain3)) {
|
|
467
|
+
this.serviceData = serviceData;
|
|
468
|
+
await this.BLEparseStatus();
|
|
469
|
+
await this.updateHomeKitCharacteristics();
|
|
470
|
+
} else {
|
|
471
|
+
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
|
|
472
|
+
await this.BLERefreshConnection(switchbot);
|
|
473
|
+
}
|
|
474
|
+
})();
|
|
475
|
+
}
|
|
460
476
|
}
|
|
461
477
|
}
|
|
462
478
|
|
package/src/device/device.ts
CHANGED
|
@@ -79,13 +79,20 @@ export abstract class deviceBase {
|
|
|
79
79
|
.getService(this.hap.Service.AccessoryInformation)!
|
|
80
80
|
.setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
|
|
81
81
|
.setCharacteristic(this.hap.Characteristic.AppMatchingIdentifier, 'id1087374760')
|
|
82
|
-
.setCharacteristic(this.hap.Characteristic.Name,
|
|
83
|
-
.setCharacteristic(this.hap.Characteristic.ConfiguredName,
|
|
82
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.validName(accessory, device))
|
|
83
|
+
.setCharacteristic(this.hap.Characteristic.ConfiguredName, this.validName(accessory, device))
|
|
84
84
|
.setCharacteristic(this.hap.Characteristic.Model, device.model ?? accessory.context.model)
|
|
85
85
|
.setCharacteristic(this.hap.Characteristic.ProductData, device.deviceId ?? accessory.context.deviceId)
|
|
86
86
|
.setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
public validName(accessory: PlatformAccessory, device: device & devicesConfig) {
|
|
90
|
+
const Name = device.configDeviceName ?? device.deviceName ?? accessory.displayName;
|
|
91
|
+
const NameOfName = device.configDeviceName ? 'configDeviceName' : device.deviceName ? 'deviceName' : 'displayName';
|
|
92
|
+
const validName = this.validateAndCleanString(Name, NameOfName, Name);
|
|
93
|
+
return validName;
|
|
94
|
+
}
|
|
95
|
+
|
|
89
96
|
async getDeviceLogSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
|
|
90
97
|
this.deviceLogging = this.platform.debugMode ? 'debugMode' : device.logging ?? this.config.logging ?? 'standard';
|
|
91
98
|
const logging = this.platform.debugMode ? 'Debug Mode' : device.logging ? 'Device Config' : this.config.logging ? 'Platform Config' : 'Default';
|
|
@@ -355,11 +362,11 @@ export abstract class deviceBase {
|
|
|
355
362
|
.deviceId!.match(/.{1,2}/g)!
|
|
356
363
|
.join(':')
|
|
357
364
|
.toLowerCase();
|
|
358
|
-
this.debugLog(`BLE Address: ${this.device.bleMac}`);
|
|
365
|
+
await this.debugLog(`BLE Address: ${this.device.bleMac}`);
|
|
359
366
|
}
|
|
360
367
|
|
|
361
368
|
async monitorAdvertisementPackets(switchbot: any) {
|
|
362
|
-
this.debugLog(`Scanning for ${this.device.bleModelName} devices...`);
|
|
369
|
+
await this.debugLog(`Scanning for ${this.device.bleModelName} devices...`);
|
|
363
370
|
await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
|
|
364
371
|
// Set an event handler
|
|
365
372
|
let serviceData = { model: this.device.bleModel, modelName: this.device.bleModelName } as ad['serviceData'];
|
|
@@ -374,7 +381,7 @@ export abstract class deviceBase {
|
|
|
374
381
|
this.debugLog(`serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
375
382
|
}
|
|
376
383
|
};
|
|
377
|
-
// Wait
|
|
384
|
+
// Wait
|
|
378
385
|
await switchbot.wait(this.scanDuration * 1000);
|
|
379
386
|
// Stop to monitor
|
|
380
387
|
await switchbot.stopScan();
|
|
@@ -765,6 +772,32 @@ export abstract class deviceBase {
|
|
|
765
772
|
}
|
|
766
773
|
}
|
|
767
774
|
|
|
775
|
+
/**
|
|
776
|
+
* Validate and clean a string value for a Name Characteristic.
|
|
777
|
+
* @param displayName
|
|
778
|
+
* @param name
|
|
779
|
+
* @param value
|
|
780
|
+
* @returns string value
|
|
781
|
+
*/
|
|
782
|
+
validateAndCleanString(displayName: string, name: string, value: string): string {
|
|
783
|
+
const validPattern = /^[a-zA-Z0-9][a-zA-Z0-9 ']*[a-zA-Z0-9]$/;
|
|
784
|
+
const invalidCharsPattern = /[^a-zA-Z0-9 ']/g;
|
|
785
|
+
|
|
786
|
+
if (!validPattern.test(value)) {
|
|
787
|
+
this.warnLog(`WARNING: The accessory '${displayName}' has an invalid '${name}' characteristic ('${value}'). Please use only alphanumeric,`
|
|
788
|
+
+ ' space, and apostrophe characters. Ensure it starts and ends with an alphabetic or numeric character, and avoid emojis. This may'
|
|
789
|
+
+ ' prevent the accessory from being added in the Home App or cause unresponsiveness.');
|
|
790
|
+
|
|
791
|
+
// Remove invalid characters
|
|
792
|
+
value = value.replace(invalidCharsPattern, '');
|
|
793
|
+
|
|
794
|
+
// Ensure it starts and ends with an alphanumeric character
|
|
795
|
+
value = value.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, '');
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
return value;
|
|
799
|
+
}
|
|
800
|
+
|
|
768
801
|
/**
|
|
769
802
|
* Logging for Device
|
|
770
803
|
*/
|
package/src/device/fan.ts
CHANGED
|
@@ -168,9 +168,6 @@ export class Fan extends deviceBase {
|
|
|
168
168
|
this.debugLog('Registering Webhook Event Handler');
|
|
169
169
|
this.registerWebhook();
|
|
170
170
|
|
|
171
|
-
//regisiter webhook event handler
|
|
172
|
-
this.registerWebhook();
|
|
173
|
-
|
|
174
171
|
// Start an update interval
|
|
175
172
|
interval(this.deviceRefreshRate * 1000)
|
|
176
173
|
.pipe(skipWhile(() => this.fanUpdateInProgress))
|
|
@@ -314,7 +311,7 @@ export class Fan extends deviceBase {
|
|
|
314
311
|
async refreshStatus(): Promise<void> {
|
|
315
312
|
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
316
313
|
await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
317
|
-
} else if (this.BLE) {
|
|
314
|
+
} else if (this.BLE || this.config.options?.BLE) {
|
|
318
315
|
await this.BLERefreshStatus();
|
|
319
316
|
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
320
317
|
await this.openAPIRefreshStatus();
|
|
@@ -326,25 +323,41 @@ export class Fan extends deviceBase {
|
|
|
326
323
|
|
|
327
324
|
async BLERefreshStatus(): Promise<void> {
|
|
328
325
|
await this.debugLog('BLERefreshStatus');
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
await this.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const serviceData = await this.monitorAdvertisementPackets(switchbot) as batteryCirculatorFanServiceData;
|
|
338
|
-
// Update HomeKit
|
|
339
|
-
if (serviceData.model === SwitchBotBLEModel.Unknown && SwitchBotBLEModelName.Unknown) {
|
|
340
|
-
this.serviceData = serviceData;
|
|
326
|
+
if (this.config.options?.BLE) {
|
|
327
|
+
await this.debugLog('is listening to Platform BLE.');
|
|
328
|
+
this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
|
|
329
|
+
await this.debugLog(`bleMac: ${this.device.bleMac}`);
|
|
330
|
+
this.platform.bleEventHandler[this.device.bleMac] = async (context: batteryCirculatorFanServiceData) => {
|
|
331
|
+
try {
|
|
332
|
+
await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
|
|
333
|
+
this.serviceData = context;
|
|
341
334
|
await this.BLEparseStatus();
|
|
342
335
|
await this.updateHomeKitCharacteristics();
|
|
343
|
-
}
|
|
344
|
-
await this.errorLog(`failed to
|
|
345
|
-
await this.BLERefreshConnection(switchbot);
|
|
336
|
+
} catch (e: any) {
|
|
337
|
+
await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
346
338
|
}
|
|
347
|
-
}
|
|
339
|
+
};
|
|
340
|
+
} else {
|
|
341
|
+
await this.debugLog('is using Device BLE Scanning.');
|
|
342
|
+
const switchbot = await this.switchbotBLE();
|
|
343
|
+
if (switchbot === undefined) {
|
|
344
|
+
await this.BLERefreshConnection(switchbot);
|
|
345
|
+
} else {
|
|
346
|
+
// Start to monitor advertisement packets
|
|
347
|
+
(async () => {
|
|
348
|
+
// Start to monitor advertisement packets
|
|
349
|
+
const serviceData = await this.monitorAdvertisementPackets(switchbot) as batteryCirculatorFanServiceData;
|
|
350
|
+
// Update HomeKit
|
|
351
|
+
if (serviceData.model === SwitchBotBLEModel.Unknown && SwitchBotBLEModelName.Unknown) {
|
|
352
|
+
this.serviceData = serviceData;
|
|
353
|
+
await this.BLEparseStatus();
|
|
354
|
+
await this.updateHomeKitCharacteristics();
|
|
355
|
+
} else {
|
|
356
|
+
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
|
|
357
|
+
await this.BLERefreshConnection(switchbot);
|
|
358
|
+
}
|
|
359
|
+
})();
|
|
360
|
+
}
|
|
348
361
|
}
|
|
349
362
|
}
|
|
350
363
|
|