@switchbot/homebridge-switchbot 1.7.1-beta.0 → 1.7.1-beta.12
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 +12 -2
- package/config.schema.json +80 -36
- package/dist/devices/bots.d.ts +7 -5
- package/dist/devices/bots.d.ts.map +1 -1
- package/dist/devices/bots.js +72 -69
- package/dist/devices/bots.js.map +1 -1
- package/dist/devices/colorbulb.d.ts +9 -4
- package/dist/devices/colorbulb.d.ts.map +1 -1
- package/dist/devices/colorbulb.js +46 -36
- package/dist/devices/colorbulb.js.map +1 -1
- package/dist/devices/contact.d.ts +6 -3
- package/dist/devices/contact.d.ts.map +1 -1
- package/dist/devices/contact.js +59 -108
- package/dist/devices/contact.js.map +1 -1
- package/dist/devices/curtains.d.ts +11 -4
- package/dist/devices/curtains.d.ts.map +1 -1
- package/dist/devices/curtains.js +67 -44
- package/dist/devices/curtains.js.map +1 -1
- package/dist/devices/humidifiers.d.ts +8 -2
- package/dist/devices/humidifiers.d.ts.map +1 -1
- package/dist/devices/humidifiers.js +39 -36
- package/dist/devices/humidifiers.js.map +1 -1
- package/dist/devices/meters.d.ts +14 -12
- package/dist/devices/meters.d.ts.map +1 -1
- package/dist/devices/meters.js +63 -103
- package/dist/devices/meters.js.map +1 -1
- package/dist/devices/motion.d.ts +10 -3
- package/dist/devices/motion.d.ts.map +1 -1
- package/dist/devices/motion.js +114 -68
- package/dist/devices/motion.js.map +1 -1
- package/dist/devices/plugs.d.ts +3 -1
- package/dist/devices/plugs.d.ts.map +1 -1
- package/dist/devices/plugs.js +8 -1
- package/dist/devices/plugs.js.map +1 -1
- package/dist/irdevices/airconditioners.d.ts +1 -0
- package/dist/irdevices/airconditioners.d.ts.map +1 -1
- package/dist/irdevices/airconditioners.js +6 -0
- package/dist/irdevices/airconditioners.js.map +1 -1
- package/dist/irdevices/airpurifiers.d.ts +1 -0
- package/dist/irdevices/airpurifiers.d.ts.map +1 -1
- package/dist/irdevices/airpurifiers.js +6 -0
- package/dist/irdevices/airpurifiers.js.map +1 -1
- package/dist/irdevices/cameras.d.ts +1 -0
- package/dist/irdevices/cameras.d.ts.map +1 -1
- package/dist/irdevices/cameras.js +6 -0
- package/dist/irdevices/cameras.js.map +1 -1
- package/dist/irdevices/fans.d.ts +1 -0
- package/dist/irdevices/fans.d.ts.map +1 -1
- package/dist/irdevices/fans.js +6 -0
- package/dist/irdevices/fans.js.map +1 -1
- package/dist/irdevices/lights.d.ts +1 -0
- package/dist/irdevices/lights.d.ts.map +1 -1
- package/dist/irdevices/lights.js +6 -0
- package/dist/irdevices/lights.js.map +1 -1
- package/dist/irdevices/others.d.ts +1 -0
- package/dist/irdevices/others.d.ts.map +1 -1
- package/dist/irdevices/others.js +6 -0
- package/dist/irdevices/others.js.map +1 -1
- package/dist/irdevices/tvs.d.ts +1 -0
- package/dist/irdevices/tvs.d.ts.map +1 -1
- package/dist/irdevices/tvs.js +6 -0
- package/dist/irdevices/tvs.js.map +1 -1
- package/dist/irdevices/vacuumcleaners.d.ts +1 -0
- package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
- package/dist/irdevices/vacuumcleaners.js +6 -0
- package/dist/irdevices/vacuumcleaners.js.map +1 -1
- package/dist/irdevices/waterheaters.d.ts +1 -0
- package/dist/irdevices/waterheaters.d.ts.map +1 -1
- package/dist/irdevices/waterheaters.js +6 -0
- package/dist/irdevices/waterheaters.js.map +1 -1
- package/dist/platform.d.ts +2 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +14 -1
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +13 -1
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/package.json +5 -5
- package/src/devices/bots.ts +74 -72
- package/src/devices/colorbulb.ts +52 -39
- package/src/devices/contact.ts +61 -113
- package/src/devices/curtains.ts +76 -48
- package/src/devices/humidifiers.ts +47 -37
- package/src/devices/meters.ts +79 -113
- package/src/devices/motion.ts +125 -74
- package/src/devices/plugs.ts +11 -2
- package/src/irdevices/airconditioners.ts +7 -0
- package/src/irdevices/airpurifiers.ts +7 -0
- package/src/irdevices/cameras.ts +7 -0
- package/src/irdevices/fans.ts +7 -0
- package/src/irdevices/lights.ts +7 -0
- package/src/irdevices/others.ts +7 -0
- package/src/irdevices/tvs.ts +7 -0
- package/src/irdevices/vacuumcleaners.ts +7 -0
- package/src/irdevices/waterheaters.ts +7 -0
- package/src/platform.ts +14 -1
- package/src/settings.ts +14 -1
package/src/devices/contact.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { interval, Subject } from 'rxjs';
|
|
|
2
2
|
import { skipWhile } from 'rxjs/operators';
|
|
3
3
|
import { SwitchBotPlatform } from '../platform';
|
|
4
4
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
5
|
-
import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse } from '../settings';
|
|
5
|
+
import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, deviceStatus } from '../settings';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Platform Accessory
|
|
@@ -24,11 +24,15 @@ export class Contact {
|
|
|
24
24
|
StatusLowBattery!: CharacteristicValue;
|
|
25
25
|
|
|
26
26
|
// OpenAPI others
|
|
27
|
+
openState: deviceStatus['openState'];
|
|
28
|
+
moveDetected: deviceStatus['moveDetected'];
|
|
29
|
+
brightness: deviceStatus['brightness'];
|
|
27
30
|
deviceStatus!: deviceStatusResponse;
|
|
28
31
|
|
|
29
32
|
// BLE Others
|
|
30
33
|
connected?: boolean;
|
|
31
34
|
switchbot!: switchbot;
|
|
35
|
+
SwitchToOpenAPI!: boolean;
|
|
32
36
|
serviceData!: serviceData;
|
|
33
37
|
battery!: serviceData['battery'];
|
|
34
38
|
movement!: serviceData['movement'];
|
|
@@ -38,7 +42,6 @@ export class Contact {
|
|
|
38
42
|
// Config
|
|
39
43
|
set_minLux!: number;
|
|
40
44
|
set_maxLux!: number;
|
|
41
|
-
spaceBetweenLevels!: number;
|
|
42
45
|
scanDuration!: number;
|
|
43
46
|
deviceLogging!: string;
|
|
44
47
|
deviceRefreshRate!: number;
|
|
@@ -56,13 +59,9 @@ export class Contact {
|
|
|
56
59
|
this.logs();
|
|
57
60
|
this.scan();
|
|
58
61
|
this.refreshRate();
|
|
62
|
+
this.config(device);
|
|
59
63
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
60
64
|
|
|
61
|
-
// Contact Config
|
|
62
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline},`
|
|
63
|
-
+ ` hide_lightsensor: ${device.contact?.hide_lightsensor}, hide_motionsensor: ${device.contact?.hide_motionsensor})`);
|
|
64
|
-
|
|
65
|
-
|
|
66
65
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
67
66
|
this.doContactUpdate = new Subject();
|
|
68
67
|
this.contactUbpdateInProgress = false;
|
|
@@ -92,7 +91,7 @@ export class Contact {
|
|
|
92
91
|
this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
93
92
|
|
|
94
93
|
// each service must implement at-minimum the "required characteristics" for the given service type
|
|
95
|
-
// see https://developers.homebridge.io/#/service/
|
|
94
|
+
// see https://developers.homebridge.io/#/service/ContactSensor
|
|
96
95
|
|
|
97
96
|
// Motion Sensor Service
|
|
98
97
|
if (device.contact?.hide_motionsensor) {
|
|
@@ -128,12 +127,21 @@ export class Contact {
|
|
|
128
127
|
this.debugLog(`Contact Sensor: ${accessory.displayName} Light Sensor Service Not Added`);
|
|
129
128
|
}
|
|
130
129
|
|
|
131
|
-
|
|
130
|
+
// Battery Service
|
|
131
|
+
if (!device.ble) {
|
|
132
|
+
this.debugLog(`Contact Sensor: ${accessory.displayName} Removing Battery Service`);
|
|
133
|
+
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
134
|
+
accessory.removeService(this.batteryService!);
|
|
135
|
+
} else if (device.ble && !this.batteryService) {
|
|
136
|
+
this.debugLog(`Contact Sensor: ${accessory.displayName} Add Battery Service`);
|
|
132
137
|
(this.batteryService =
|
|
133
|
-
accessory.getService(this.platform.Service.Battery) ||
|
|
134
|
-
accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
138
|
+
this.accessory.getService(this.platform.Service.Battery) ||
|
|
139
|
+
this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
135
140
|
|
|
136
141
|
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
142
|
+
|
|
143
|
+
} else {
|
|
144
|
+
this.debugLog(`Contact Sensor: ${accessory.displayName} Battery Service Not Added`);
|
|
137
145
|
}
|
|
138
146
|
|
|
139
147
|
// Retrieve initial values and updateHomekit
|
|
@@ -147,6 +155,12 @@ export class Contact {
|
|
|
147
155
|
});
|
|
148
156
|
}
|
|
149
157
|
|
|
158
|
+
config(device: device & devicesConfig) {
|
|
159
|
+
if (device.contact !== undefined) {
|
|
160
|
+
this.warnLog(`Contact Sensor: ${this.accessory.displayName} Config: ${JSON.stringify(device.contact)}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
150
164
|
refreshRate() {
|
|
151
165
|
if (this.device.refreshRate) {
|
|
152
166
|
this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
|
|
@@ -195,7 +209,7 @@ export class Contact {
|
|
|
195
209
|
}
|
|
196
210
|
|
|
197
211
|
private minLux(): number {
|
|
198
|
-
if (this.device.
|
|
212
|
+
if (this.device.contact?.set_minLux) {
|
|
199
213
|
this.set_minLux = this.device.contact!.set_minLux!;
|
|
200
214
|
} else {
|
|
201
215
|
this.set_minLux = 1;
|
|
@@ -204,7 +218,7 @@ export class Contact {
|
|
|
204
218
|
}
|
|
205
219
|
|
|
206
220
|
private maxLux(): number {
|
|
207
|
-
if (this.device.
|
|
221
|
+
if (this.device.contact?.set_maxLux) {
|
|
208
222
|
this.set_maxLux = this.device.contact!.set_maxLux!;
|
|
209
223
|
} else {
|
|
210
224
|
this.set_maxLux = 6001;
|
|
@@ -216,19 +230,15 @@ export class Contact {
|
|
|
216
230
|
* Parse the device status from the SwitchBot api
|
|
217
231
|
*/
|
|
218
232
|
async parseStatus() {
|
|
219
|
-
if (this.device.ble) {
|
|
220
|
-
await this.BLEparseStatus();
|
|
221
|
-
} else {
|
|
233
|
+
if (this.SwitchToOpenAPI || !this.device.ble) {
|
|
222
234
|
await this.openAPIparseStatus();
|
|
235
|
+
} else {
|
|
236
|
+
await this.BLEparseStatus();
|
|
223
237
|
}
|
|
224
238
|
}
|
|
225
239
|
|
|
226
240
|
private async BLEparseStatus() {
|
|
227
241
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE parseStatus`);
|
|
228
|
-
if (!this.device.contact?.hide_motionsensor) {
|
|
229
|
-
// Movement
|
|
230
|
-
this.MotionDetected = Boolean(this.movement);
|
|
231
|
-
}
|
|
232
242
|
// Door State
|
|
233
243
|
switch (this.doorState) {
|
|
234
244
|
case 'open':
|
|
@@ -242,110 +252,65 @@ export class Contact {
|
|
|
242
252
|
default:
|
|
243
253
|
this.errorLog(`Contact Sensor: ${this.accessory.displayName} timeout no closed, doorstate: ${this.doorState}`);
|
|
244
254
|
}
|
|
245
|
-
//
|
|
246
|
-
if (!this.device.contact?.
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
case 0:
|
|
250
|
-
this.CurrentAmbientLightLevel = 0.0001;
|
|
251
|
-
break;
|
|
252
|
-
default:
|
|
253
|
-
this.CurrentAmbientLightLevel = 100000;
|
|
254
|
-
}
|
|
255
|
+
// Movement
|
|
256
|
+
if (!this.device.contact?.hide_motionsensor) {
|
|
257
|
+
this.MotionDetected = Boolean(this.movement);
|
|
258
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
255
259
|
}
|
|
256
|
-
|
|
257
|
-
/*
|
|
258
260
|
// Light Level
|
|
259
261
|
if (!this.device.contact?.hide_lightsensor) {
|
|
260
262
|
this.set_minLux = this.minLux();
|
|
261
263
|
this.set_maxLux = this.maxLux();
|
|
262
|
-
this.spaceBetweenLevels = 9;
|
|
263
|
-
|
|
264
|
-
//
|
|
265
264
|
switch (this.lightLevel) {
|
|
266
|
-
case
|
|
265
|
+
case 'dark':
|
|
266
|
+
case 0:
|
|
267
267
|
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
268
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
269
|
-
break;
|
|
270
|
-
case 2:
|
|
271
|
-
this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels);
|
|
272
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel},`
|
|
273
|
-
+ ` Calculation: ${((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels)}`);
|
|
274
|
-
break;
|
|
275
|
-
case 3:
|
|
276
|
-
this.CurrentAmbientLightLevel = (((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 2);
|
|
277
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
278
|
-
break;
|
|
279
|
-
case 4:
|
|
280
|
-
this.CurrentAmbientLightLevel = (((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 3);
|
|
281
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
282
|
-
break;
|
|
283
|
-
case 5:
|
|
284
|
-
this.CurrentAmbientLightLevel = (((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 4);
|
|
285
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
286
|
-
break;
|
|
287
|
-
case 6:
|
|
288
|
-
this.CurrentAmbientLightLevel = (((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 5);
|
|
289
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
290
268
|
break;
|
|
291
|
-
case 7:
|
|
292
|
-
this.CurrentAmbientLightLevel = (((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 6);
|
|
293
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
294
|
-
break;
|
|
295
|
-
case 8:
|
|
296
|
-
this.CurrentAmbientLightLevel = (((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 7);
|
|
297
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
298
|
-
break;
|
|
299
|
-
case 9:
|
|
300
|
-
this.CurrentAmbientLightLevel = (((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 8);
|
|
301
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
302
|
-
break;
|
|
303
|
-
case 10:
|
|
304
269
|
default:
|
|
305
270
|
this.CurrentAmbientLightLevel = this.set_maxLux;
|
|
306
|
-
this.debugLog();
|
|
307
271
|
}
|
|
308
|
-
this.debugLog(`
|
|
272
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} LightLevel: ${this.lightLevel},`
|
|
309
273
|
+ ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
274
|
+
}
|
|
313
275
|
// Battery
|
|
276
|
+
if (this.battery === undefined) {
|
|
277
|
+
this.battery === 100;
|
|
278
|
+
}
|
|
314
279
|
this.BatteryLevel = Number(this.battery);
|
|
315
280
|
if (this.BatteryLevel < 10) {
|
|
316
281
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
317
282
|
} else {
|
|
318
283
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
319
284
|
}
|
|
320
|
-
|
|
321
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}, MotionDetected: `
|
|
322
|
-
+ `${this.MotionDetected}, CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}, BatteryLevel: ${this.BatteryLevel}`);
|
|
285
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
|
|
323
286
|
}
|
|
324
287
|
|
|
325
288
|
private async openAPIparseStatus() {
|
|
289
|
+
if (this.device.ble) {
|
|
290
|
+
this.SwitchToOpenAPI = false;
|
|
291
|
+
}
|
|
326
292
|
if (this.platform.config.credentials?.openToken) {
|
|
327
|
-
// Contact State
|
|
328
293
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
329
|
-
|
|
294
|
+
// Contact State
|
|
295
|
+
if (this.openState === 'open') {
|
|
330
296
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
331
297
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
332
|
-
} else if (this.
|
|
298
|
+
} else if (this.openState === 'close') {
|
|
333
299
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
334
300
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
335
301
|
} else {
|
|
336
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} openState: ${this.
|
|
302
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} openState: ${this.openState}`);
|
|
337
303
|
}
|
|
338
304
|
// Motion State
|
|
339
305
|
if (!this.device.contact?.hide_motionsensor) {
|
|
340
|
-
this.MotionDetected =
|
|
306
|
+
this.MotionDetected = this.moveDetected!;
|
|
307
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
341
308
|
}
|
|
342
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
343
309
|
// Light Level
|
|
344
310
|
if (!this.device.contact?.hide_lightsensor) {
|
|
345
311
|
this.set_minLux = this.minLux();
|
|
346
312
|
this.set_maxLux = this.maxLux();
|
|
347
|
-
|
|
348
|
-
switch (this.deviceStatus.body.brightness) {
|
|
313
|
+
switch (this.brightness) {
|
|
349
314
|
case 'dim':
|
|
350
315
|
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
351
316
|
break;
|
|
@@ -369,34 +334,12 @@ export class Contact {
|
|
|
369
334
|
}
|
|
370
335
|
}
|
|
371
336
|
|
|
372
|
-
public async connectBLE() {
|
|
373
|
-
let switchbot: any;
|
|
374
|
-
try {
|
|
375
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
376
|
-
const Switchbot = require('node-switchbot');
|
|
377
|
-
switchbot = new Switchbot();
|
|
378
|
-
// Convert to BLE Address
|
|
379
|
-
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
380
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
381
|
-
} catch (e: any) {
|
|
382
|
-
switchbot = false;
|
|
383
|
-
this.errorLog(`Contact Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot}`);
|
|
384
|
-
if (this.deviceLogging === 'debug') {
|
|
385
|
-
this.errorLog(`Contact Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
|
|
386
|
-
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
387
|
-
}
|
|
388
|
-
if (this.platform.debugMode) {
|
|
389
|
-
this.errorLog(`Contact Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
|
|
390
|
-
+ ` Error: ${JSON.stringify(e)}`);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return switchbot;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
337
|
private async BLERefreshStatus() {
|
|
397
338
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE refreshStatus`);
|
|
398
|
-
|
|
399
|
-
|
|
339
|
+
const switchbot = await this.platform.connectBLE();
|
|
340
|
+
// Convert to BLE Address
|
|
341
|
+
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
342
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
400
343
|
// Start to monitor advertisement packets
|
|
401
344
|
if (switchbot !== false) {
|
|
402
345
|
switchbot.startScan({
|
|
@@ -449,6 +392,7 @@ export class Contact {
|
|
|
449
392
|
}
|
|
450
393
|
if (this.platform.config.credentials?.openToken) {
|
|
451
394
|
this.warnLog(`Contact Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
395
|
+
this.SwitchToOpenAPI = true;
|
|
452
396
|
await this.openAPIRefreshStatus();
|
|
453
397
|
}
|
|
454
398
|
this.apiError(e);
|
|
@@ -462,6 +406,7 @@ export class Contact {
|
|
|
462
406
|
this.errorLog(`Contact Sensor: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
463
407
|
if (this.platform.config.credentials?.openToken) {
|
|
464
408
|
this.warnLog(`Contact Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
409
|
+
this.SwitchToOpenAPI = true;
|
|
465
410
|
await this.openAPIRefreshStatus();
|
|
466
411
|
}
|
|
467
412
|
}
|
|
@@ -472,6 +417,9 @@ export class Contact {
|
|
|
472
417
|
try {
|
|
473
418
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
474
419
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
420
|
+
this.openState = this.deviceStatus.body.openState;
|
|
421
|
+
this.moveDetected = this.deviceStatus.body.moveDetected;
|
|
422
|
+
this.brightness = this.deviceStatus.body.brightness;
|
|
475
423
|
this.parseStatus();
|
|
476
424
|
this.updateHomeKitCharacteristics();
|
|
477
425
|
} catch (e: any) {
|
package/src/devices/curtains.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { interval, Subject } from 'rxjs';
|
|
|
4
4
|
import { SwitchBotPlatform } from '../platform';
|
|
5
5
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
6
6
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
7
|
-
import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, payload } from '../settings';
|
|
7
|
+
import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, payload, deviceStatus } from '../settings';
|
|
8
8
|
|
|
9
9
|
export class Curtain {
|
|
10
10
|
// Services
|
|
@@ -22,11 +22,16 @@ export class Curtain {
|
|
|
22
22
|
|
|
23
23
|
// OpenAPI Others
|
|
24
24
|
deviceStatus!: deviceStatusResponse;
|
|
25
|
+
slidePosition: deviceStatus['slidePosition'];
|
|
26
|
+
moving: deviceStatus['moving'];
|
|
27
|
+
brightness: deviceStatus['brightness'];
|
|
25
28
|
|
|
26
29
|
// BLE Others
|
|
27
30
|
connected?: boolean;
|
|
28
31
|
switchbot!: switchbot;
|
|
32
|
+
SwitchToOpenAPI?: boolean;
|
|
29
33
|
serviceData!: serviceData;
|
|
34
|
+
spaceBetweenLevels!: number;
|
|
30
35
|
calibration: serviceData['calibration'];
|
|
31
36
|
battery: serviceData['battery'];
|
|
32
37
|
position: serviceData['position'];
|
|
@@ -38,13 +43,12 @@ export class Curtain {
|
|
|
38
43
|
|
|
39
44
|
// Config
|
|
40
45
|
set_minStep!: number;
|
|
41
|
-
|
|
46
|
+
updateRate!: number;
|
|
42
47
|
set_minLux!: number;
|
|
43
48
|
set_maxLux!: number;
|
|
44
49
|
scanDuration!: number;
|
|
45
50
|
deviceLogging!: string;
|
|
46
51
|
deviceRefreshRate!: number;
|
|
47
|
-
spaceBetweenLevels!: number;
|
|
48
52
|
|
|
49
53
|
// Updates
|
|
50
54
|
curtainUpdateInProgress!: boolean;
|
|
@@ -60,16 +64,11 @@ export class Curtain {
|
|
|
60
64
|
this.scan();
|
|
61
65
|
this.setMinMax();
|
|
62
66
|
this.refreshRate();
|
|
67
|
+
this.config(device);
|
|
63
68
|
this.CurrentPosition = 0;
|
|
64
69
|
this.TargetPosition = 0;
|
|
65
70
|
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
66
71
|
|
|
67
|
-
// Curtain Config
|
|
68
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} Config: (ble: ${device.ble}, disable_group: ${device.curtain?.disable_group},`
|
|
69
|
-
+ ` hide_lightsensor: ${device.curtain?.hide_lightsensor}, set_minLux: ${device.curtain?.set_minLux}, set_maxLux: `
|
|
70
|
-
+ `${device.curtain?.set_maxLux}, refreshRate: ${device.curtain?.refreshRate}, set_max: ${device.curtain?.set_max}, set_min: `
|
|
71
|
-
+ `${device.curtain?.set_min}, set_minStep: ${device.curtain?.set_minStep})`);
|
|
72
|
-
|
|
73
72
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
74
73
|
this.doCurtainUpdate = new Subject();
|
|
75
74
|
this.curtainUpdateInProgress = false;
|
|
@@ -142,6 +141,23 @@ export class Curtain {
|
|
|
142
141
|
this.debugLog(`Curtain: ${accessory.displayName} Light Sensor Service Not Added`);
|
|
143
142
|
}
|
|
144
143
|
|
|
144
|
+
// Battery Service
|
|
145
|
+
if (!device.ble) {
|
|
146
|
+
this.debugLog(`Curtain: ${accessory.displayName} Removing Battery Service`);
|
|
147
|
+
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
148
|
+
accessory.removeService(this.batteryService!);
|
|
149
|
+
} else if (device.ble && !this.batteryService) {
|
|
150
|
+
this.debugLog(`Curtain: ${accessory.displayName} Add Battery Service`);
|
|
151
|
+
(this.batteryService =
|
|
152
|
+
this.accessory.getService(this.platform.Service.Battery) ||
|
|
153
|
+
this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
154
|
+
|
|
155
|
+
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
156
|
+
|
|
157
|
+
} else {
|
|
158
|
+
this.debugLog(`Curtain: ${accessory.displayName} Battery Service Not Added`);
|
|
159
|
+
}
|
|
160
|
+
|
|
145
161
|
|
|
146
162
|
// Update Homekit
|
|
147
163
|
this.updateHomeKitCharacteristics();
|
|
@@ -154,7 +170,7 @@ export class Curtain {
|
|
|
154
170
|
});
|
|
155
171
|
|
|
156
172
|
// update slide progress
|
|
157
|
-
interval(this.
|
|
173
|
+
interval(this.updateRate * 1000)
|
|
158
174
|
.pipe(skipWhile(() => this.curtainUpdateInProgress))
|
|
159
175
|
.subscribe(() => {
|
|
160
176
|
if (this.PositionState === this.platform.Characteristic.PositionState.STOPPED) {
|
|
@@ -193,6 +209,22 @@ export class Curtain {
|
|
|
193
209
|
});
|
|
194
210
|
}
|
|
195
211
|
|
|
212
|
+
config(device: device & devicesConfig) {
|
|
213
|
+
const config: any = device.curtain;
|
|
214
|
+
if (device.curtain !== undefined) {
|
|
215
|
+
if (device.ble !== undefined) {
|
|
216
|
+
config['ble'] = device.ble;
|
|
217
|
+
}
|
|
218
|
+
if (device.logging !== undefined) {
|
|
219
|
+
config['logging'] = device.logging;
|
|
220
|
+
}
|
|
221
|
+
if (device.refreshRate !== undefined) {
|
|
222
|
+
config['refreshRate'] = device.refreshRate;
|
|
223
|
+
}
|
|
224
|
+
this.warnLog(`Curtain: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
196
228
|
refreshRate() {
|
|
197
229
|
// refreshRate
|
|
198
230
|
if (this.device.refreshRate) {
|
|
@@ -206,14 +238,14 @@ export class Curtain {
|
|
|
206
238
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
207
239
|
}
|
|
208
240
|
}
|
|
209
|
-
//
|
|
210
|
-
if (this.device?.curtain?.
|
|
211
|
-
this.
|
|
241
|
+
// updateRate
|
|
242
|
+
if (this.device?.curtain?.updateRate) {
|
|
243
|
+
this.updateRate = this.device?.curtain?.updateRate;
|
|
212
244
|
if (this.platform.debugMode || (this.deviceLogging === 'debug')) {
|
|
213
245
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using Device Config Curtain refreshRate: ${this.deviceRefreshRate}`);
|
|
214
246
|
}
|
|
215
247
|
} else {
|
|
216
|
-
this.
|
|
248
|
+
this.updateRate = 5;
|
|
217
249
|
if (this.platform.debugMode || (this.deviceLogging === 'debug')) {
|
|
218
250
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using Default Curtain Refresh Rate.`);
|
|
219
251
|
}
|
|
@@ -253,30 +285,6 @@ export class Curtain {
|
|
|
253
285
|
}
|
|
254
286
|
}
|
|
255
287
|
|
|
256
|
-
public async connectBLE() {
|
|
257
|
-
let switchbot: any;
|
|
258
|
-
try {
|
|
259
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
260
|
-
const Switchbot = require('node-switchbot');
|
|
261
|
-
switchbot = new Switchbot();
|
|
262
|
-
// Convert to BLE Address
|
|
263
|
-
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
264
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
265
|
-
} catch (e: any) {
|
|
266
|
-
switchbot = false;
|
|
267
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot}`);
|
|
268
|
-
if (this.deviceLogging === 'debug') {
|
|
269
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
|
|
270
|
-
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
271
|
-
}
|
|
272
|
-
if (this.platform.debugMode) {
|
|
273
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
|
|
274
|
-
+ ` Error: ${JSON.stringify(e)}`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return switchbot;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
288
|
private minStep(): number {
|
|
281
289
|
if (this.device.curtain?.set_minStep) {
|
|
282
290
|
this.set_minStep = this.device.curtain?.set_minStep;
|
|
@@ -304,16 +312,20 @@ export class Curtain {
|
|
|
304
312
|
return this.set_maxLux;
|
|
305
313
|
}
|
|
306
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Parse the device status from the SwitchBot api
|
|
317
|
+
*/
|
|
307
318
|
async parseStatus() {
|
|
308
|
-
if (this.device.ble) {
|
|
309
|
-
await this.BLEparseStatus();
|
|
310
|
-
} else {
|
|
319
|
+
if (this.SwitchToOpenAPI || !this.device.ble) {
|
|
311
320
|
await this.openAPIparseStatus();
|
|
321
|
+
} else {
|
|
322
|
+
await this.BLEparseStatus();
|
|
312
323
|
}
|
|
313
324
|
}
|
|
314
325
|
|
|
315
326
|
private async BLEparseStatus() {
|
|
316
327
|
this.debugLog(`Curtain: ${this.accessory.displayName} BLE parseStatus`);
|
|
328
|
+
// CurrentPosition
|
|
317
329
|
this.setMinMax();
|
|
318
330
|
this.CurrentPosition = 100 - Number(this.position);
|
|
319
331
|
this.debugLog(`Curtain: ${this.accessory.displayName} CurrentPosition ${this.CurrentPosition}`);
|
|
@@ -339,6 +351,7 @@ export class Curtain {
|
|
|
339
351
|
// If Curtain calibration distance is short, there will be an error between the current percentage and the target percentage.
|
|
340
352
|
this.TargetPosition = this.CurrentPosition;
|
|
341
353
|
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
354
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} Stopped`);
|
|
342
355
|
}
|
|
343
356
|
}
|
|
344
357
|
this.debugLog(`Curtain: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},`
|
|
@@ -407,17 +420,20 @@ export class Curtain {
|
|
|
407
420
|
}
|
|
408
421
|
|
|
409
422
|
private async openAPIparseStatus() {
|
|
423
|
+
if (this.device.ble) {
|
|
424
|
+
this.SwitchToOpenAPI = false;
|
|
425
|
+
}
|
|
410
426
|
if (this.platform.config.credentials?.openToken) {
|
|
411
427
|
this.debugLog(`Curtain: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
412
428
|
// CurrentPosition
|
|
413
429
|
this.setMinMax();
|
|
414
|
-
this.CurrentPosition = 100 - this.
|
|
430
|
+
this.CurrentPosition = 100 - Number(this.slidePosition);
|
|
415
431
|
this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
|
|
416
432
|
if (this.setNewTarget) {
|
|
417
|
-
this.infoLog(`
|
|
433
|
+
this.infoLog(`Curtain: ${this.accessory.displayName} Checking Status ...`);
|
|
418
434
|
}
|
|
419
435
|
|
|
420
|
-
if (this.
|
|
436
|
+
if (this.setNewTarget && this.moving) {
|
|
421
437
|
this.setMinMax();
|
|
422
438
|
if (this.TargetPosition > this.CurrentPosition) {
|
|
423
439
|
this.debugLog(`Curtain: ${this.accessory.displayName} Closing, CurrentPosition: ${this.CurrentPosition} `);
|
|
@@ -435,6 +451,7 @@ export class Curtain {
|
|
|
435
451
|
/*If Curtain calibration distance is short, there will be an error between the current percentage and the target percentage.*/
|
|
436
452
|
this.TargetPosition = this.CurrentPosition;
|
|
437
453
|
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
454
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} Stopped`);
|
|
438
455
|
}
|
|
439
456
|
}
|
|
440
457
|
this.debugLog(`Curtain: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},`
|
|
@@ -444,7 +461,7 @@ export class Curtain {
|
|
|
444
461
|
this.set_minLux = this.minLux();
|
|
445
462
|
this.set_maxLux = this.maxLux();
|
|
446
463
|
// Brightness
|
|
447
|
-
switch (this.
|
|
464
|
+
switch (this.brightness) {
|
|
448
465
|
case 'dim':
|
|
449
466
|
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
450
467
|
break;
|
|
@@ -467,8 +484,10 @@ export class Curtain {
|
|
|
467
484
|
|
|
468
485
|
private async BLERefreshStatus() {
|
|
469
486
|
this.debugLog(`Curtain: ${this.accessory.displayName} BLE refreshStatus`);
|
|
470
|
-
|
|
471
|
-
|
|
487
|
+
const switchbot = await this.platform.connectBLE();
|
|
488
|
+
// Convert to BLE Address
|
|
489
|
+
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
490
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
472
491
|
// Start to monitor advertisement packets
|
|
473
492
|
if (switchbot !== false) {
|
|
474
493
|
switchbot.startScan({
|
|
@@ -506,6 +525,7 @@ export class Curtain {
|
|
|
506
525
|
this.errorLog(`Curtain: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
|
|
507
526
|
if (this.platform.config.credentials?.openToken) {
|
|
508
527
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
528
|
+
this.SwitchToOpenAPI = true;
|
|
509
529
|
await this.openAPIRefreshStatus();
|
|
510
530
|
}
|
|
511
531
|
}
|
|
@@ -521,6 +541,7 @@ export class Curtain {
|
|
|
521
541
|
}
|
|
522
542
|
if (this.platform.config.credentials?.openToken) {
|
|
523
543
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
544
|
+
this.SwitchToOpenAPI = true;
|
|
524
545
|
await this.openAPIRefreshStatus();
|
|
525
546
|
}
|
|
526
547
|
this.apiError(e);
|
|
@@ -534,6 +555,7 @@ export class Curtain {
|
|
|
534
555
|
this.errorLog(`Curtain: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
535
556
|
if (this.platform.config.credentials?.openToken) {
|
|
536
557
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
558
|
+
this.SwitchToOpenAPI = true;
|
|
537
559
|
await this.openAPIRefreshStatus();
|
|
538
560
|
}
|
|
539
561
|
}
|
|
@@ -544,6 +566,9 @@ export class Curtain {
|
|
|
544
566
|
try {
|
|
545
567
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
546
568
|
this.debugLog(`Curtain: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
569
|
+
this.slidePosition = this.deviceStatus.body.slidePosition;
|
|
570
|
+
this.moving = this.deviceStatus.body.moving;
|
|
571
|
+
this.brightness = this.deviceStatus.body.brightness;
|
|
547
572
|
this.parseStatus();
|
|
548
573
|
this.updateHomeKitCharacteristics();
|
|
549
574
|
} catch (e: any) {
|
|
@@ -578,7 +603,10 @@ export class Curtain {
|
|
|
578
603
|
private async BLEpushChanges() {
|
|
579
604
|
if (this.TargetPosition !== this.CurrentPosition) {
|
|
580
605
|
this.debugLog(`Curtain: ${this.accessory.displayName} BLE pushChanges`);
|
|
581
|
-
const switchbot = await this.connectBLE();
|
|
606
|
+
const switchbot = await this.platform.connectBLE();
|
|
607
|
+
// Convert to BLE Address
|
|
608
|
+
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
609
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
582
610
|
if (switchbot !== false) {
|
|
583
611
|
switchbot.discover({ model: 'c', quick: true, id: this.device.bleMac }).then((device_list) => {
|
|
584
612
|
this.infoLog(`${this.accessory.displayName} Target Position: ${this.TargetPosition}`);
|