@switchbot/homebridge-switchbot 1.6.4-beta.5 → 1.7.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 +23 -2
- package/config.schema.json +125 -33
- package/dist/devices/bots.d.ts +21 -9
- package/dist/devices/bots.d.ts.map +1 -1
- package/dist/devices/bots.js +352 -48
- package/dist/devices/bots.js.map +1 -1
- package/dist/devices/colorbulb.d.ts +6 -1
- package/dist/devices/colorbulb.d.ts.map +1 -1
- package/dist/devices/colorbulb.js +18 -11
- package/dist/devices/colorbulb.js.map +1 -1
- package/dist/devices/contact.d.ts +10 -2
- package/dist/devices/contact.d.ts.map +1 -1
- package/dist/devices/contact.js +92 -51
- package/dist/devices/contact.js.map +1 -1
- package/dist/devices/curtains.d.ts +10 -3
- package/dist/devices/curtains.d.ts.map +1 -1
- package/dist/devices/curtains.js +52 -34
- 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 +28 -35
- 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 +14 -0
- 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 +355 -52
- package/src/devices/colorbulb.ts +24 -14
- package/src/devices/contact.ts +99 -55
- package/src/devices/curtains.ts +60 -36
- package/src/devices/humidifiers.ts +36 -36
- 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 +15 -0
package/src/devices/colorbulb.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { interval, Subject } from 'rxjs';
|
|
|
3
3
|
import { SwitchBotPlatform } from '../platform';
|
|
4
4
|
import { debounceTime, skipWhile, tap } from 'rxjs/operators';
|
|
5
5
|
import { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
|
|
6
|
-
import { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse, payload, hs2rgb, rgb2hs, m2hs } from '../settings';
|
|
6
|
+
import { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse, payload, hs2rgb, rgb2hs, m2hs, deviceStatus } from '../settings';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Platform Accessory
|
|
@@ -27,6 +27,10 @@ export class ColorBulb {
|
|
|
27
27
|
ColorTemperatureCached!: CharacteristicValue;
|
|
28
28
|
|
|
29
29
|
// OpenAPI Others
|
|
30
|
+
power: deviceStatus['power'];
|
|
31
|
+
color: deviceStatus['color'];
|
|
32
|
+
brightness: deviceStatus['brightness'];
|
|
33
|
+
colorTemperature: deviceStatus['colorTemperature'];
|
|
30
34
|
deviceStatus!: deviceStatusResponse;
|
|
31
35
|
|
|
32
36
|
// BLE Others
|
|
@@ -57,6 +61,7 @@ export class ColorBulb {
|
|
|
57
61
|
this.logs();
|
|
58
62
|
this.refreshRate();
|
|
59
63
|
this.adaptiveLighting();
|
|
64
|
+
this.config(device);
|
|
60
65
|
if (this.On === undefined) {
|
|
61
66
|
this.On = false;
|
|
62
67
|
} else {
|
|
@@ -68,11 +73,6 @@ export class ColorBulb {
|
|
|
68
73
|
this.ColorTemperature = 140;
|
|
69
74
|
this.minKelvin = 2000;
|
|
70
75
|
this.maxKelvin = 9000;
|
|
71
|
-
|
|
72
|
-
// ColorBulb Config
|
|
73
|
-
this.debugLog(`Color Bulb: ${this.accessory.displayName} Config: (ble: ${device.ble}, set_minStep: ${device.colorbulb?.set_minStep},`
|
|
74
|
-
+ ` adaptiveLighting: ${device.colorbulb?.adaptiveLightingShift})`);
|
|
75
|
-
|
|
76
76
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
77
77
|
this.doColorBulbUpdate = new Subject();
|
|
78
78
|
this.colorBulbUpdateInProgress = false;
|
|
@@ -214,6 +214,12 @@ export class ColorBulb {
|
|
|
214
214
|
});
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
config(device: device & devicesConfig) {
|
|
218
|
+
if (device.colorbulb !== undefined) {
|
|
219
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} Config: ${JSON.stringify(device.colorbulb)}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
217
223
|
refreshRate() {
|
|
218
224
|
if (this.device.refreshRate) {
|
|
219
225
|
this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
|
|
@@ -267,7 +273,7 @@ export class ColorBulb {
|
|
|
267
273
|
}
|
|
268
274
|
|
|
269
275
|
parseStatus() {
|
|
270
|
-
switch (this.
|
|
276
|
+
switch (this.power) {
|
|
271
277
|
case 'on':
|
|
272
278
|
this.On = true;
|
|
273
279
|
break;
|
|
@@ -277,13 +283,13 @@ export class ColorBulb {
|
|
|
277
283
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} On: ${this.On}`);
|
|
278
284
|
|
|
279
285
|
// Brightness
|
|
280
|
-
this.Brightness = Number(this.
|
|
286
|
+
this.Brightness = Number(this.brightness);
|
|
281
287
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} Brightness: ${this.Brightness}`);
|
|
282
288
|
|
|
283
289
|
// Color, Hue & Brightness
|
|
284
|
-
if (this.
|
|
285
|
-
this.debugLog(`Color Bulb: ${this.accessory.displayName} color: ${JSON.stringify(this.
|
|
286
|
-
const [red, green, blue] = this.
|
|
290
|
+
if (this.color) {
|
|
291
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} color: ${JSON.stringify(this.color)}`);
|
|
292
|
+
const [red, green, blue] = this.color!.split(':');
|
|
287
293
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} red: ${JSON.stringify(red)}`);
|
|
288
294
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} green: ${JSON.stringify(green)}`);
|
|
289
295
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} blue: ${JSON.stringify(blue)}`);
|
|
@@ -301,9 +307,9 @@ export class ColorBulb {
|
|
|
301
307
|
}
|
|
302
308
|
|
|
303
309
|
// ColorTemperature
|
|
304
|
-
if (!Number.isNaN(this.
|
|
305
|
-
this.debugLog(`Color Bulb: ${this.accessory.displayName} OpenAPI ColorTemperature: ${this.
|
|
306
|
-
const mired = Math.round(1000000 / this.
|
|
310
|
+
if (!Number.isNaN(this.colorTemperature)) {
|
|
311
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} OpenAPI ColorTemperature: ${this.colorTemperature}`);
|
|
312
|
+
const mired = Math.round(1000000 / this.colorTemperature!);
|
|
307
313
|
|
|
308
314
|
this.ColorTemperature = Number(mired);
|
|
309
315
|
|
|
@@ -316,6 +322,10 @@ export class ColorBulb {
|
|
|
316
322
|
try {
|
|
317
323
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
318
324
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
325
|
+
this.power = this.deviceStatus.body.power;
|
|
326
|
+
this.color = this.deviceStatus.body.color;
|
|
327
|
+
this.brightness = this.deviceStatus.body.brightness;
|
|
328
|
+
this.colorTemperature = this.deviceStatus.body.colorTemperature;
|
|
319
329
|
this.parseStatus();
|
|
320
330
|
this.updateHomeKitCharacteristics();
|
|
321
331
|
} catch (e: any) {
|
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'];
|
|
@@ -36,6 +40,8 @@ export class Contact {
|
|
|
36
40
|
lightLevel!: serviceData['lightLevel'];
|
|
37
41
|
|
|
38
42
|
// Config
|
|
43
|
+
set_minLux!: number;
|
|
44
|
+
set_maxLux!: number;
|
|
39
45
|
scanDuration!: number;
|
|
40
46
|
deviceLogging!: string;
|
|
41
47
|
deviceRefreshRate!: number;
|
|
@@ -53,13 +59,9 @@ export class Contact {
|
|
|
53
59
|
this.logs();
|
|
54
60
|
this.scan();
|
|
55
61
|
this.refreshRate();
|
|
62
|
+
this.config(device);
|
|
56
63
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
57
64
|
|
|
58
|
-
// Contact Config
|
|
59
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline},`
|
|
60
|
-
+ ` hide_lightsensor: ${device.contact?.hide_lightsensor}, hide_motionsensor: ${device.contact?.hide_motionsensor})`);
|
|
61
|
-
|
|
62
|
-
|
|
63
65
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
64
66
|
this.doContactUpdate = new Subject();
|
|
65
67
|
this.contactUbpdateInProgress = false;
|
|
@@ -89,7 +91,7 @@ export class Contact {
|
|
|
89
91
|
this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
90
92
|
|
|
91
93
|
// each service must implement at-minimum the "required characteristics" for the given service type
|
|
92
|
-
// see https://developers.homebridge.io/#/service/
|
|
94
|
+
// see https://developers.homebridge.io/#/service/ContactSensor
|
|
93
95
|
|
|
94
96
|
// Motion Sensor Service
|
|
95
97
|
if (device.contact?.hide_motionsensor) {
|
|
@@ -125,12 +127,21 @@ export class Contact {
|
|
|
125
127
|
this.debugLog(`Contact Sensor: ${accessory.displayName} Light Sensor Service Not Added`);
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
|
|
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`);
|
|
129
137
|
(this.batteryService =
|
|
130
|
-
accessory.getService(this.platform.Service.Battery) ||
|
|
131
|
-
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`;
|
|
132
140
|
|
|
133
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`);
|
|
134
145
|
}
|
|
135
146
|
|
|
136
147
|
// Retrieve initial values and updateHomekit
|
|
@@ -144,6 +155,12 @@ export class Contact {
|
|
|
144
155
|
});
|
|
145
156
|
}
|
|
146
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
|
+
|
|
147
164
|
refreshRate() {
|
|
148
165
|
if (this.device.refreshRate) {
|
|
149
166
|
this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
|
|
@@ -191,23 +208,37 @@ export class Contact {
|
|
|
191
208
|
}
|
|
192
209
|
}
|
|
193
210
|
|
|
211
|
+
private minLux(): number {
|
|
212
|
+
if (this.device.contact?.set_minLux) {
|
|
213
|
+
this.set_minLux = this.device.contact!.set_minLux!;
|
|
214
|
+
} else {
|
|
215
|
+
this.set_minLux = 1;
|
|
216
|
+
}
|
|
217
|
+
return this.set_minLux;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private maxLux(): number {
|
|
221
|
+
if (this.device.contact?.set_maxLux) {
|
|
222
|
+
this.set_maxLux = this.device.contact!.set_maxLux!;
|
|
223
|
+
} else {
|
|
224
|
+
this.set_maxLux = 6001;
|
|
225
|
+
}
|
|
226
|
+
return this.set_maxLux;
|
|
227
|
+
}
|
|
228
|
+
|
|
194
229
|
/**
|
|
195
230
|
* Parse the device status from the SwitchBot api
|
|
196
231
|
*/
|
|
197
232
|
async parseStatus() {
|
|
198
|
-
if (this.device.ble) {
|
|
199
|
-
await this.BLEparseStatus();
|
|
200
|
-
} else {
|
|
233
|
+
if (this.SwitchToOpenAPI || !this.device.ble) {
|
|
201
234
|
await this.openAPIparseStatus();
|
|
235
|
+
} else {
|
|
236
|
+
await this.BLEparseStatus();
|
|
202
237
|
}
|
|
203
238
|
}
|
|
204
239
|
|
|
205
240
|
private async BLEparseStatus() {
|
|
206
241
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE parseStatus`);
|
|
207
|
-
if (this.device.contact?.hide_motionsensor) {
|
|
208
|
-
// Movement
|
|
209
|
-
this.MotionDetected = Boolean(this.movement);
|
|
210
|
-
}
|
|
211
242
|
// Door State
|
|
212
243
|
switch (this.doorState) {
|
|
213
244
|
case 'open':
|
|
@@ -221,44 +252,74 @@ export class Contact {
|
|
|
221
252
|
default:
|
|
222
253
|
this.errorLog(`Contact Sensor: ${this.accessory.displayName} timeout no closed, doorstate: ${this.doorState}`);
|
|
223
254
|
}
|
|
224
|
-
|
|
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}`);
|
|
259
|
+
}
|
|
260
|
+
// Light Level
|
|
261
|
+
if (!this.device.contact?.hide_lightsensor) {
|
|
262
|
+
this.set_minLux = this.minLux();
|
|
263
|
+
this.set_maxLux = this.maxLux();
|
|
225
264
|
switch (this.lightLevel) {
|
|
226
265
|
case 'dark':
|
|
227
266
|
case 0:
|
|
228
|
-
this.CurrentAmbientLightLevel =
|
|
267
|
+
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
229
268
|
break;
|
|
230
269
|
default:
|
|
231
|
-
this.CurrentAmbientLightLevel =
|
|
270
|
+
this.CurrentAmbientLightLevel = this.set_maxLux;
|
|
232
271
|
}
|
|
272
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} LightLevel: ${this.lightLevel},`
|
|
273
|
+
+ ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
233
274
|
}
|
|
234
275
|
// Battery
|
|
276
|
+
if (this.battery === undefined) {
|
|
277
|
+
this.battery === 100;
|
|
278
|
+
}
|
|
235
279
|
this.BatteryLevel = Number(this.battery);
|
|
236
280
|
if (this.BatteryLevel < 10) {
|
|
237
281
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
238
282
|
} else {
|
|
239
283
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
240
284
|
}
|
|
241
|
-
|
|
242
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}, MotionDetected: `
|
|
243
|
-
+ `${this.MotionDetected}, CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}, BatteryLevel: ${this.BatteryLevel}`);
|
|
285
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
|
|
244
286
|
}
|
|
245
287
|
|
|
246
288
|
private async openAPIparseStatus() {
|
|
289
|
+
if (this.device.ble) {
|
|
290
|
+
this.SwitchToOpenAPI = false;
|
|
291
|
+
}
|
|
247
292
|
if (this.platform.config.credentials?.openToken) {
|
|
248
293
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
249
|
-
|
|
294
|
+
// Contact State
|
|
295
|
+
if (this.openState === 'open') {
|
|
250
296
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
251
297
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
252
|
-
} else if (this.
|
|
298
|
+
} else if (this.openState === 'close') {
|
|
253
299
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
254
300
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
255
301
|
} else {
|
|
256
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} openState: ${this.
|
|
302
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} openState: ${this.openState}`);
|
|
257
303
|
}
|
|
258
|
-
|
|
259
|
-
|
|
304
|
+
// Motion State
|
|
305
|
+
if (!this.device.contact?.hide_motionsensor) {
|
|
306
|
+
this.MotionDetected = this.moveDetected!;
|
|
307
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
308
|
+
}
|
|
309
|
+
// Light Level
|
|
310
|
+
if (!this.device.contact?.hide_lightsensor) {
|
|
311
|
+
this.set_minLux = this.minLux();
|
|
312
|
+
this.set_maxLux = this.maxLux();
|
|
313
|
+
switch (this.brightness) {
|
|
314
|
+
case 'dim':
|
|
315
|
+
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
316
|
+
break;
|
|
317
|
+
case 'bright':
|
|
318
|
+
default:
|
|
319
|
+
this.CurrentAmbientLightLevel = this.set_maxLux;
|
|
320
|
+
}
|
|
321
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
260
322
|
}
|
|
261
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
262
323
|
}
|
|
263
324
|
}
|
|
264
325
|
|
|
@@ -273,34 +334,12 @@ export class Contact {
|
|
|
273
334
|
}
|
|
274
335
|
}
|
|
275
336
|
|
|
276
|
-
public async connectBLE() {
|
|
277
|
-
let switchbot: any;
|
|
278
|
-
try {
|
|
279
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
280
|
-
const Switchbot = require('node-switchbot');
|
|
281
|
-
switchbot = new Switchbot();
|
|
282
|
-
// Convert to BLE Address
|
|
283
|
-
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
284
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
285
|
-
} catch (e: any) {
|
|
286
|
-
switchbot = false;
|
|
287
|
-
this.errorLog(`Contact Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot}`);
|
|
288
|
-
if (this.deviceLogging === 'debug') {
|
|
289
|
-
this.errorLog(`Contact Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
|
|
290
|
-
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
291
|
-
}
|
|
292
|
-
if (this.platform.debugMode) {
|
|
293
|
-
this.errorLog(`Contact Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
|
|
294
|
-
+ ` Error: ${JSON.stringify(e)}`);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return switchbot;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
337
|
private async BLERefreshStatus() {
|
|
301
338
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE refreshStatus`);
|
|
302
|
-
|
|
303
|
-
|
|
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}`);
|
|
304
343
|
// Start to monitor advertisement packets
|
|
305
344
|
if (switchbot !== false) {
|
|
306
345
|
switchbot.startScan({
|
|
@@ -353,6 +392,7 @@ export class Contact {
|
|
|
353
392
|
}
|
|
354
393
|
if (this.platform.config.credentials?.openToken) {
|
|
355
394
|
this.warnLog(`Contact Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
395
|
+
this.SwitchToOpenAPI = true;
|
|
356
396
|
await this.openAPIRefreshStatus();
|
|
357
397
|
}
|
|
358
398
|
this.apiError(e);
|
|
@@ -366,6 +406,7 @@ export class Contact {
|
|
|
366
406
|
this.errorLog(`Contact Sensor: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
367
407
|
if (this.platform.config.credentials?.openToken) {
|
|
368
408
|
this.warnLog(`Contact Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
409
|
+
this.SwitchToOpenAPI = true;
|
|
369
410
|
await this.openAPIRefreshStatus();
|
|
370
411
|
}
|
|
371
412
|
}
|
|
@@ -376,6 +417,9 @@ export class Contact {
|
|
|
376
417
|
try {
|
|
377
418
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
378
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;
|
|
379
423
|
this.parseStatus();
|
|
380
424
|
this.updateHomeKitCharacteristics();
|
|
381
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'];
|
|
@@ -44,7 +49,6 @@ export class Curtain {
|
|
|
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,6 +64,7 @@ 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;
|
|
@@ -142,6 +147,23 @@ export class Curtain {
|
|
|
142
147
|
this.debugLog(`Curtain: ${accessory.displayName} Light Sensor Service Not Added`);
|
|
143
148
|
}
|
|
144
149
|
|
|
150
|
+
// Battery Service
|
|
151
|
+
if (!device.ble) {
|
|
152
|
+
this.debugLog(`Curtain: ${accessory.displayName} Removing Battery Service`);
|
|
153
|
+
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
154
|
+
accessory.removeService(this.batteryService!);
|
|
155
|
+
} else if (device.ble && !this.batteryService) {
|
|
156
|
+
this.debugLog(`Curtain: ${accessory.displayName} Add Battery Service`);
|
|
157
|
+
(this.batteryService =
|
|
158
|
+
this.accessory.getService(this.platform.Service.Battery) ||
|
|
159
|
+
this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
160
|
+
|
|
161
|
+
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
162
|
+
|
|
163
|
+
} else {
|
|
164
|
+
this.debugLog(`Curtain: ${accessory.displayName} Battery Service Not Added`);
|
|
165
|
+
}
|
|
166
|
+
|
|
145
167
|
|
|
146
168
|
// Update Homekit
|
|
147
169
|
this.updateHomeKitCharacteristics();
|
|
@@ -193,6 +215,12 @@ export class Curtain {
|
|
|
193
215
|
});
|
|
194
216
|
}
|
|
195
217
|
|
|
218
|
+
config(device: device & devicesConfig) {
|
|
219
|
+
if (device.curtain !== undefined || device.ble !== undefined) {
|
|
220
|
+
this.warnLog(`Curtain: ${this.accessory.displayName} Config: ${JSON.stringify(device.curtain)}, BLE: ${device.ble}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
196
224
|
refreshRate() {
|
|
197
225
|
// refreshRate
|
|
198
226
|
if (this.device.refreshRate) {
|
|
@@ -253,30 +281,6 @@ export class Curtain {
|
|
|
253
281
|
}
|
|
254
282
|
}
|
|
255
283
|
|
|
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
284
|
private minStep(): number {
|
|
281
285
|
if (this.device.curtain?.set_minStep) {
|
|
282
286
|
this.set_minStep = this.device.curtain?.set_minStep;
|
|
@@ -304,16 +308,20 @@ export class Curtain {
|
|
|
304
308
|
return this.set_maxLux;
|
|
305
309
|
}
|
|
306
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Parse the device status from the SwitchBot api
|
|
313
|
+
*/
|
|
307
314
|
async parseStatus() {
|
|
308
|
-
if (this.device.ble) {
|
|
309
|
-
await this.BLEparseStatus();
|
|
310
|
-
} else {
|
|
315
|
+
if (this.SwitchToOpenAPI || !this.device.ble) {
|
|
311
316
|
await this.openAPIparseStatus();
|
|
317
|
+
} else {
|
|
318
|
+
await this.BLEparseStatus();
|
|
312
319
|
}
|
|
313
320
|
}
|
|
314
321
|
|
|
315
322
|
private async BLEparseStatus() {
|
|
316
323
|
this.debugLog(`Curtain: ${this.accessory.displayName} BLE parseStatus`);
|
|
324
|
+
// CurrentPosition
|
|
317
325
|
this.setMinMax();
|
|
318
326
|
this.CurrentPosition = 100 - Number(this.position);
|
|
319
327
|
this.debugLog(`Curtain: ${this.accessory.displayName} CurrentPosition ${this.CurrentPosition}`);
|
|
@@ -339,6 +347,7 @@ export class Curtain {
|
|
|
339
347
|
// If Curtain calibration distance is short, there will be an error between the current percentage and the target percentage.
|
|
340
348
|
this.TargetPosition = this.CurrentPosition;
|
|
341
349
|
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
350
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} Stopped`);
|
|
342
351
|
}
|
|
343
352
|
}
|
|
344
353
|
this.debugLog(`Curtain: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},`
|
|
@@ -407,17 +416,20 @@ export class Curtain {
|
|
|
407
416
|
}
|
|
408
417
|
|
|
409
418
|
private async openAPIparseStatus() {
|
|
419
|
+
if (this.device.ble) {
|
|
420
|
+
this.SwitchToOpenAPI = false;
|
|
421
|
+
}
|
|
410
422
|
if (this.platform.config.credentials?.openToken) {
|
|
411
423
|
this.debugLog(`Curtain: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
412
424
|
// CurrentPosition
|
|
413
425
|
this.setMinMax();
|
|
414
|
-
this.CurrentPosition = 100 - this.
|
|
426
|
+
this.CurrentPosition = 100 - Number(this.slidePosition);
|
|
415
427
|
this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
|
|
416
428
|
if (this.setNewTarget) {
|
|
417
|
-
this.infoLog(`
|
|
429
|
+
this.infoLog(`Curtain: ${this.accessory.displayName} Checking Status ...`);
|
|
418
430
|
}
|
|
419
431
|
|
|
420
|
-
if (this.
|
|
432
|
+
if (this.setNewTarget && this.moving) {
|
|
421
433
|
this.setMinMax();
|
|
422
434
|
if (this.TargetPosition > this.CurrentPosition) {
|
|
423
435
|
this.debugLog(`Curtain: ${this.accessory.displayName} Closing, CurrentPosition: ${this.CurrentPosition} `);
|
|
@@ -435,6 +447,7 @@ export class Curtain {
|
|
|
435
447
|
/*If Curtain calibration distance is short, there will be an error between the current percentage and the target percentage.*/
|
|
436
448
|
this.TargetPosition = this.CurrentPosition;
|
|
437
449
|
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
450
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} Stopped`);
|
|
438
451
|
}
|
|
439
452
|
}
|
|
440
453
|
this.debugLog(`Curtain: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},`
|
|
@@ -444,7 +457,7 @@ export class Curtain {
|
|
|
444
457
|
this.set_minLux = this.minLux();
|
|
445
458
|
this.set_maxLux = this.maxLux();
|
|
446
459
|
// Brightness
|
|
447
|
-
switch (this.
|
|
460
|
+
switch (this.brightness) {
|
|
448
461
|
case 'dim':
|
|
449
462
|
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
450
463
|
break;
|
|
@@ -467,8 +480,10 @@ export class Curtain {
|
|
|
467
480
|
|
|
468
481
|
private async BLERefreshStatus() {
|
|
469
482
|
this.debugLog(`Curtain: ${this.accessory.displayName} BLE refreshStatus`);
|
|
470
|
-
|
|
471
|
-
|
|
483
|
+
const switchbot = await this.platform.connectBLE();
|
|
484
|
+
// Convert to BLE Address
|
|
485
|
+
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
486
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
472
487
|
// Start to monitor advertisement packets
|
|
473
488
|
if (switchbot !== false) {
|
|
474
489
|
switchbot.startScan({
|
|
@@ -506,6 +521,7 @@ export class Curtain {
|
|
|
506
521
|
this.errorLog(`Curtain: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
|
|
507
522
|
if (this.platform.config.credentials?.openToken) {
|
|
508
523
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
524
|
+
this.SwitchToOpenAPI = true;
|
|
509
525
|
await this.openAPIRefreshStatus();
|
|
510
526
|
}
|
|
511
527
|
}
|
|
@@ -521,6 +537,7 @@ export class Curtain {
|
|
|
521
537
|
}
|
|
522
538
|
if (this.platform.config.credentials?.openToken) {
|
|
523
539
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
540
|
+
this.SwitchToOpenAPI = true;
|
|
524
541
|
await this.openAPIRefreshStatus();
|
|
525
542
|
}
|
|
526
543
|
this.apiError(e);
|
|
@@ -534,6 +551,7 @@ export class Curtain {
|
|
|
534
551
|
this.errorLog(`Curtain: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
535
552
|
if (this.platform.config.credentials?.openToken) {
|
|
536
553
|
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
554
|
+
this.SwitchToOpenAPI = true;
|
|
537
555
|
await this.openAPIRefreshStatus();
|
|
538
556
|
}
|
|
539
557
|
}
|
|
@@ -544,6 +562,9 @@ export class Curtain {
|
|
|
544
562
|
try {
|
|
545
563
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
546
564
|
this.debugLog(`Curtain: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
565
|
+
this.slidePosition = this.deviceStatus.body.slidePosition;
|
|
566
|
+
this.moving = this.deviceStatus.body.moving;
|
|
567
|
+
this.brightness = this.deviceStatus.body.brightness;
|
|
547
568
|
this.parseStatus();
|
|
548
569
|
this.updateHomeKitCharacteristics();
|
|
549
570
|
} catch (e: any) {
|
|
@@ -578,7 +599,10 @@ export class Curtain {
|
|
|
578
599
|
private async BLEpushChanges() {
|
|
579
600
|
if (this.TargetPosition !== this.CurrentPosition) {
|
|
580
601
|
this.debugLog(`Curtain: ${this.accessory.displayName} BLE pushChanges`);
|
|
581
|
-
const switchbot = await this.connectBLE();
|
|
602
|
+
const switchbot = await this.platform.connectBLE();
|
|
603
|
+
// Convert to BLE Address
|
|
604
|
+
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
605
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
582
606
|
if (switchbot !== false) {
|
|
583
607
|
switchbot.discover({ model: 'c', quick: true, id: this.device.bleMac }).then((device_list) => {
|
|
584
608
|
this.infoLog(`${this.accessory.displayName} Target Position: ${this.TargetPosition}`);
|