@switchbot/homebridge-switchbot 0.1.2-beta.0 → 0.1.2-beta.4
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/.github/workflows/issue-validate.yml +1 -1
- package/dist/devices/bots.d.ts +1 -0
- package/dist/devices/bots.d.ts.map +1 -1
- package/dist/devices/bots.js +70 -22
- package/dist/devices/bots.js.map +1 -1
- package/dist/devices/bulb.d.ts +10 -1
- package/dist/devices/bulb.d.ts.map +1 -1
- package/dist/devices/bulb.js +12 -1
- package/dist/devices/bulb.js.map +1 -1
- package/dist/devices/contact.d.ts +13 -3
- package/dist/devices/contact.d.ts.map +1 -1
- package/dist/devices/contact.js +77 -2
- package/dist/devices/contact.js.map +1 -1
- package/dist/devices/curtains.d.ts +19 -8
- package/dist/devices/curtains.d.ts.map +1 -1
- package/dist/devices/curtains.js +96 -19
- package/dist/devices/curtains.js.map +1 -1
- package/dist/devices/humidifiers.d.ts.map +1 -1
- package/dist/devices/humidifiers.js +2 -2
- package/dist/devices/humidifiers.js.map +1 -1
- package/dist/devices/meters.d.ts +13 -4
- package/dist/devices/meters.d.ts.map +1 -1
- package/dist/devices/meters.js +28 -9
- package/dist/devices/meters.js.map +1 -1
- package/dist/devices/motion.d.ts +11 -3
- package/dist/devices/motion.d.ts.map +1 -1
- package/dist/devices/motion.js +67 -1
- package/dist/devices/motion.js.map +1 -1
- package/dist/devices/plugs.d.ts +11 -1
- package/dist/devices/plugs.d.ts.map +1 -1
- package/dist/devices/plugs.js +67 -1
- package/dist/devices/plugs.js.map +1 -1
- package/dist/irdevices/airconditioners.js +2 -2
- package/dist/irdevices/airconditioners.js.map +1 -1
- package/dist/irdevices/airpurifiers.js +2 -2
- package/dist/irdevices/airpurifiers.js.map +1 -1
- package/dist/irdevices/cameras.js +1 -1
- package/dist/irdevices/cameras.js.map +1 -1
- package/dist/irdevices/fans.js +1 -1
- package/dist/irdevices/fans.js.map +1 -1
- package/dist/irdevices/lights.js +3 -3
- package/dist/irdevices/lights.js.map +1 -1
- package/dist/irdevices/others.js +1 -1
- package/dist/irdevices/others.js.map +1 -1
- package/dist/irdevices/tvs.d.ts.map +1 -1
- package/dist/irdevices/tvs.js +2 -3
- package/dist/irdevices/tvs.js.map +1 -1
- package/dist/irdevices/vacuumcleaners.js +1 -1
- package/dist/irdevices/vacuumcleaners.js.map +1 -1
- package/package.json +1 -1
- package/src/devices/bots.ts +85 -35
- package/src/devices/bulb.ts +32 -2
- package/src/devices/contact.ts +101 -9
- package/src/devices/curtains.ts +135 -35
- package/src/devices/humidifiers.ts +7 -2
- package/src/devices/meters.ts +50 -14
- package/src/devices/motion.ts +90 -7
- package/src/devices/plugs.ts +89 -4
- package/src/irdevices/airconditioners.ts +2 -2
- package/src/irdevices/airpurifiers.ts +2 -2
- package/src/irdevices/cameras.ts +1 -1
- package/src/irdevices/fans.ts +1 -1
- package/src/irdevices/lights.ts +3 -3
- package/src/irdevices/others.ts +1 -1
- package/src/irdevices/tvs.ts +2 -4
- package/src/irdevices/vacuumcleaners.ts +1 -1
package/src/devices/curtains.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
2
|
-
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
2
|
+
import { Service, PlatformAccessory, CharacteristicValue, MacAddress } from 'homebridge';
|
|
3
3
|
import { SwitchBotPlatform } from '../platform';
|
|
4
4
|
import { interval, Subject } from 'rxjs';
|
|
5
5
|
import { debounceTime, skipWhile, tap } from 'rxjs/operators';
|
|
@@ -7,31 +7,51 @@ import { DeviceURL, device, deviceStatusResponse } from '../settings';
|
|
|
7
7
|
import { AxiosResponse } from 'axios';
|
|
8
8
|
|
|
9
9
|
export class Curtain {
|
|
10
|
+
// Services
|
|
10
11
|
private service: Service;
|
|
12
|
+
private lightSensorService: Service;
|
|
11
13
|
|
|
14
|
+
// Characteristic Values
|
|
12
15
|
CurrentPosition!: CharacteristicValue;
|
|
13
16
|
PositionState!: CharacteristicValue;
|
|
14
17
|
TargetPosition!: CharacteristicValue;
|
|
15
|
-
|
|
16
|
-
setNewTarget!: boolean;
|
|
17
|
-
setNewTargetTimer!: NodeJS.Timeout;
|
|
18
|
+
CurrentAmbientLightLevel!: CharacteristicValue;
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
switchbot;
|
|
20
|
+
// Others
|
|
21
|
+
deviceStatus!: deviceStatusResponse;
|
|
22
22
|
moveTimer!: NodeJS.Timeout;
|
|
23
|
+
ScanIntervalId!: NodeJS.Timeout;
|
|
24
|
+
setNewTargetTimer!: NodeJS.Timeout;
|
|
25
|
+
AutoDisableFastScanTimeoutId!: NodeJS.Timeout;
|
|
26
|
+
setNewTarget!: boolean;
|
|
23
27
|
moveTime!: number;
|
|
24
28
|
ScanDuration: any;
|
|
25
29
|
ReverseDir: any;
|
|
26
30
|
FastScanEnabled!: boolean;
|
|
27
|
-
ScanIntervalId!: NodeJS.Timeout;
|
|
28
31
|
FastScanInterval!: number;
|
|
29
32
|
SlowScanInterval!: number;
|
|
30
33
|
OpenCloseThreshold: any;
|
|
31
34
|
PreviousPosition: any;
|
|
32
35
|
Position: any;
|
|
33
|
-
AutoDisableFastScanTimeoutId;
|
|
34
36
|
FastScanDuration: number | undefined;
|
|
37
|
+
switchbot!: {
|
|
38
|
+
discover: (
|
|
39
|
+
arg0:
|
|
40
|
+
{
|
|
41
|
+
duration: any;
|
|
42
|
+
model: string;
|
|
43
|
+
quick: boolean;
|
|
44
|
+
id: MacAddress;
|
|
45
|
+
}
|
|
46
|
+
) => Promise<any>;
|
|
47
|
+
wait: (
|
|
48
|
+
arg0: number
|
|
49
|
+
) => any;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Updates
|
|
53
|
+
curtainUpdateInProgress!: boolean;
|
|
54
|
+
doCurtainUpdate;
|
|
35
55
|
|
|
36
56
|
constructor(
|
|
37
57
|
private readonly platform: SwitchBotPlatform,
|
|
@@ -75,7 +95,7 @@ export class Curtain {
|
|
|
75
95
|
// you can create multiple services for each accessory
|
|
76
96
|
(this.service =
|
|
77
97
|
accessory.getService(this.platform.Service.WindowCovering) ||
|
|
78
|
-
accessory.addService(this.platform.Service.WindowCovering)),
|
|
98
|
+
accessory.addService(this.platform.Service.WindowCovering)), `${device.deviceName} ${device.deviceType}`;
|
|
79
99
|
|
|
80
100
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
81
101
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
@@ -111,6 +131,21 @@ export class Curtain {
|
|
|
111
131
|
})
|
|
112
132
|
.onSet(this.TargetPositionSet.bind(this));
|
|
113
133
|
|
|
134
|
+
//set up brightness level from the builtin sensor as light sensor accessory
|
|
135
|
+
(this.lightSensorService =
|
|
136
|
+
accessory.getService(this.platform.Service.LightSensor) ||
|
|
137
|
+
accessory.addService(this.platform.Service.LightSensor)), 'Builtin Lightsensor of %s %s', device.deviceName, device.deviceType;
|
|
138
|
+
this.lightSensorService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
139
|
+
// handle on / off events using the On characteristic
|
|
140
|
+
this.lightSensorService.getCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel).onGet(() => {
|
|
141
|
+
if (this.CurrentAmbientLightLevel === 'bright') {
|
|
142
|
+
return 100000;
|
|
143
|
+
} else {
|
|
144
|
+
return 0.0001;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
|
|
114
149
|
// Update Homekit
|
|
115
150
|
this.updateHomeKitCharacteristics();
|
|
116
151
|
|
|
@@ -187,35 +222,94 @@ export class Curtain {
|
|
|
187
222
|
}
|
|
188
223
|
}
|
|
189
224
|
}
|
|
225
|
+
// Brightness
|
|
226
|
+
switch (this.deviceStatus.body.brightness) {
|
|
227
|
+
case 'dim':
|
|
228
|
+
this.CurrentAmbientLightLevel = 0.0001;
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
this.CurrentAmbientLightLevel = 100000;
|
|
232
|
+
}
|
|
190
233
|
this.platform.debug(
|
|
191
|
-
`Curtain ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}
|
|
192
|
-
TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState}
|
|
234
|
+
`Curtain ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}
|
|
235
|
+
, TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState}
|
|
236
|
+
, CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
193
237
|
}
|
|
194
238
|
|
|
195
239
|
async refreshStatus() {
|
|
196
240
|
if (this.platform.config.options?.ble?.includes(this.device.deviceId!)) {
|
|
197
|
-
this.platform.log.warn('BLE DEVICE-1');
|
|
241
|
+
this.platform.log.warn('BLE DEVICE-REFRESH-1');
|
|
242
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
243
|
+
const Switchbot = require('node-switchbot');
|
|
244
|
+
const switchbot = new Switchbot();
|
|
245
|
+
const colon = this.device.deviceId!.match(/.{1,2}/g);
|
|
246
|
+
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
247
|
+
this.device.bleMac = bleMac.toLowerCase();
|
|
248
|
+
if (this.platform.config.options.debug) {
|
|
249
|
+
this.platform.log.warn(this.device.bleMac!);
|
|
250
|
+
}
|
|
251
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
252
|
+
this.platform.log.info(JSON.stringify(ad, null, ' '));
|
|
253
|
+
this.platform.log.warn('ad:', JSON.stringify(ad));
|
|
254
|
+
};
|
|
255
|
+
switchbot
|
|
256
|
+
.startScan({
|
|
257
|
+
id: this.device.bleMac,
|
|
258
|
+
})
|
|
259
|
+
.then(() => {
|
|
260
|
+
return switchbot.wait(this.platform.config.options!.refreshRate! * 1000);
|
|
261
|
+
})
|
|
262
|
+
.then(() => {
|
|
263
|
+
switchbot.stopScan();
|
|
264
|
+
})
|
|
265
|
+
.catch(async (error: any) => {
|
|
266
|
+
this.platform.log.error(error);
|
|
267
|
+
await this.openAPIRefreshStatus();
|
|
268
|
+
});
|
|
269
|
+
setInterval(() => {
|
|
270
|
+
this.platform.log.info('Start scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
271
|
+
switchbot
|
|
272
|
+
.startScan({
|
|
273
|
+
mode: 'T',
|
|
274
|
+
id: bleMac,
|
|
275
|
+
})
|
|
276
|
+
.then(() => {
|
|
277
|
+
return switchbot.wait(this.platform.config.options!.refreshRate! * 1000);
|
|
278
|
+
})
|
|
279
|
+
.then(() => {
|
|
280
|
+
switchbot.stopScan();
|
|
281
|
+
this.platform.log.info('Stop scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
282
|
+
})
|
|
283
|
+
.catch(async (error: any) => {
|
|
284
|
+
this.platform.log.error(error);
|
|
285
|
+
await this.openAPIRefreshStatus();
|
|
286
|
+
});
|
|
287
|
+
}, this.platform.config.options!.refreshRate! * 60000);
|
|
198
288
|
} else {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
this.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
this.platform.debug(`Curtain ${this.accessory.displayName} - ${JSON.stringify(e)}`),
|
|
216
|
-
);
|
|
217
|
-
this.apiError(e);
|
|
289
|
+
await this.openAPIRefreshStatus();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private async openAPIRefreshStatus() {
|
|
294
|
+
try {
|
|
295
|
+
this.platform.debug('Curtain - Reading', `${DeviceURL}/${this.device.deviceId}/status`);
|
|
296
|
+
const deviceStatus: deviceStatusResponse = (
|
|
297
|
+
await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)
|
|
298
|
+
).data;
|
|
299
|
+
if (deviceStatus.message === 'success') {
|
|
300
|
+
this.deviceStatus = deviceStatus;
|
|
301
|
+
this.platform.debug(`Curtain ${this.accessory.displayName} refreshStatus - ${JSON.stringify(this.deviceStatus)}`);
|
|
302
|
+
this.setMinMax();
|
|
303
|
+
this.parseStatus();
|
|
304
|
+
this.updateHomeKitCharacteristics();
|
|
218
305
|
}
|
|
306
|
+
} catch (e: any) {
|
|
307
|
+
this.platform.log.error(
|
|
308
|
+
`Curtain - Failed to refresh status of ${this.device.deviceName}`,
|
|
309
|
+
JSON.stringify(e.message),
|
|
310
|
+
this.platform.debug(`Curtain ${this.accessory.displayName} - ${JSON.stringify(e)}`),
|
|
311
|
+
);
|
|
312
|
+
this.apiError(e);
|
|
219
313
|
}
|
|
220
314
|
}
|
|
221
315
|
|
|
@@ -258,7 +352,9 @@ export class Curtain {
|
|
|
258
352
|
CurrentPosition: this.CurrentPosition,
|
|
259
353
|
PositionState: this.PositionState,
|
|
260
354
|
TargetPosition: this.TargetPosition,
|
|
261
|
-
|
|
355
|
+
CurrentAmbientLightLevel: this.CurrentAmbientLightLevel,
|
|
356
|
+
})}`,
|
|
357
|
+
);
|
|
262
358
|
this.setMinMax();
|
|
263
359
|
if (this.CurrentPosition !== undefined) {
|
|
264
360
|
this.service.updateCharacteristic(this.platform.Characteristic.CurrentPosition, this.CurrentPosition);
|
|
@@ -269,12 +365,16 @@ export class Curtain {
|
|
|
269
365
|
if (this.TargetPosition !== undefined) {
|
|
270
366
|
this.service.updateCharacteristic(this.platform.Characteristic.TargetPosition, this.TargetPosition);
|
|
271
367
|
}
|
|
368
|
+
if (this.CurrentAmbientLightLevel !== undefined) {
|
|
369
|
+
this.lightSensorService.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, this.CurrentAmbientLightLevel);
|
|
370
|
+
}
|
|
272
371
|
}
|
|
273
372
|
|
|
274
373
|
public apiError(e: any) {
|
|
275
374
|
this.service.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
276
375
|
this.service.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
277
376
|
this.service.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
377
|
+
this.service.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, e);
|
|
278
378
|
}
|
|
279
379
|
|
|
280
380
|
|
|
@@ -406,7 +506,7 @@ export class Curtain {
|
|
|
406
506
|
* Ask the device to start moving to the given position (which must be a device value and not an HomeKit value).
|
|
407
507
|
* Returns a Promise that's resolved as soon as the command was sent to the device.
|
|
408
508
|
*/
|
|
409
|
-
public runToPosition(pos: number): Promise<void> {
|
|
509
|
+
public async runToPosition(pos: number): Promise<void> {
|
|
410
510
|
const SwitchBot = require('node-switchbot');
|
|
411
511
|
const switchbot = new SwitchBot();
|
|
412
512
|
|
|
@@ -533,4 +633,4 @@ export class Curtain {
|
|
|
533
633
|
}
|
|
534
634
|
}
|
|
535
635
|
}
|
|
536
|
-
}
|
|
636
|
+
}
|
|
@@ -11,9 +11,11 @@ import { AxiosResponse } from 'axios';
|
|
|
11
11
|
* Each accessory may expose multiple services of different service types.
|
|
12
12
|
*/
|
|
13
13
|
export class Humidifier {
|
|
14
|
+
// Services
|
|
14
15
|
private service: Service;
|
|
15
16
|
temperatureservice?: Service;
|
|
16
17
|
|
|
18
|
+
// Characteristic Values
|
|
17
19
|
CurrentRelativeHumidity!: CharacteristicValue;
|
|
18
20
|
CurrentTemperature!: CharacteristicValue;
|
|
19
21
|
TargetHumidifierDehumidifierState!: CharacteristicValue;
|
|
@@ -21,8 +23,11 @@ export class Humidifier {
|
|
|
21
23
|
RelativeHumidityHumidifierThreshold!: CharacteristicValue;
|
|
22
24
|
Active!: CharacteristicValue;
|
|
23
25
|
WaterLevel!: CharacteristicValue;
|
|
26
|
+
|
|
27
|
+
// Others
|
|
24
28
|
deviceStatus!: deviceStatusResponse;
|
|
25
29
|
|
|
30
|
+
// Updates
|
|
26
31
|
humidifierUpdateInProgress!: boolean;
|
|
27
32
|
doHumidifierUpdate;
|
|
28
33
|
|
|
@@ -58,7 +63,7 @@ export class Humidifier {
|
|
|
58
63
|
// you can create multiple services for each accessory
|
|
59
64
|
(this.service =
|
|
60
65
|
accessory.getService(this.platform.Service.HumidifierDehumidifier) ||
|
|
61
|
-
accessory.addService(this.platform.Service.HumidifierDehumidifier)),
|
|
66
|
+
accessory.addService(this.platform.Service.HumidifierDehumidifier)), `${device.deviceName} ${device.deviceType}`;
|
|
62
67
|
|
|
63
68
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
64
69
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
@@ -113,7 +118,7 @@ export class Humidifier {
|
|
|
113
118
|
}
|
|
114
119
|
(this.temperatureservice =
|
|
115
120
|
this.accessory.getService(this.platform.Service.TemperatureSensor) ||
|
|
116
|
-
this.accessory.addService(this.platform.Service.TemperatureSensor)),
|
|
121
|
+
this.accessory.addService(this.platform.Service.TemperatureSensor)), `${device.deviceName} ${device.deviceType} TemperatureSensor`;
|
|
117
122
|
|
|
118
123
|
this.temperatureservice
|
|
119
124
|
.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
|
package/src/devices/meters.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
|
|
1
|
+
import { Service, PlatformAccessory, Units, CharacteristicValue, MacAddress } from 'homebridge';
|
|
2
2
|
import { SwitchBotPlatform } from '../platform';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { skipWhile } from 'rxjs/operators';
|
|
@@ -10,10 +10,12 @@ import { DeviceURL, device, deviceStatusResponse } from '../settings';
|
|
|
10
10
|
* Each accessory may expose multiple services of different service types.
|
|
11
11
|
*/
|
|
12
12
|
export class Meter {
|
|
13
|
+
// Services
|
|
13
14
|
private service: Service;
|
|
14
15
|
temperatureservice?: Service;
|
|
15
16
|
humidityservice?: Service;
|
|
16
17
|
|
|
18
|
+
// Characteristic Values
|
|
17
19
|
CurrentRelativeHumidity!: CharacteristicValue;
|
|
18
20
|
CurrentTemperature!: CharacteristicValue;
|
|
19
21
|
BatteryLevel!: CharacteristicValue;
|
|
@@ -21,13 +23,29 @@ export class Meter {
|
|
|
21
23
|
StatusLowBattery!: CharacteristicValue;
|
|
22
24
|
Active!: CharacteristicValue;
|
|
23
25
|
WaterLevel!: CharacteristicValue;
|
|
26
|
+
|
|
27
|
+
// Others
|
|
24
28
|
deviceStatus!: deviceStatusResponse;
|
|
25
|
-
|
|
29
|
+
BLEtemperature!: number;
|
|
30
|
+
BLEHumidity!: number;
|
|
31
|
+
switchbot!: {
|
|
32
|
+
discover: (
|
|
33
|
+
arg0:
|
|
34
|
+
{
|
|
35
|
+
duration: any;
|
|
36
|
+
model: string;
|
|
37
|
+
quick: boolean;
|
|
38
|
+
id: MacAddress;
|
|
39
|
+
}
|
|
40
|
+
) => Promise<any>;
|
|
41
|
+
wait: (
|
|
42
|
+
arg0: number
|
|
43
|
+
) => any;
|
|
44
|
+
};
|
|
26
45
|
|
|
46
|
+
// Updates
|
|
27
47
|
meterUpdateInProgress!: boolean;
|
|
28
48
|
doMeterUpdate;
|
|
29
|
-
BLEtemperature: any;
|
|
30
|
-
BLEHumidity: any;
|
|
31
49
|
|
|
32
50
|
constructor(
|
|
33
51
|
private readonly platform: SwitchBotPlatform,
|
|
@@ -40,6 +58,17 @@ export class Meter {
|
|
|
40
58
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
41
59
|
this.CurrentRelativeHumidity = 0;
|
|
42
60
|
this.CurrentTemperature = 0;
|
|
61
|
+
if (this.platform.config.options?.ble?.includes(this.device.deviceId!)) {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
63
|
+
const SwitchBot = require('node-switchbot');
|
|
64
|
+
this.switchbot = new SwitchBot();
|
|
65
|
+
const colon = device.deviceId!.match(/.{1,2}/g);
|
|
66
|
+
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
67
|
+
this.device.bleMac = bleMac.toLowerCase();
|
|
68
|
+
if (this.platform.config.options.debug) {
|
|
69
|
+
this.platform.log.warn(this.device.bleMac.toLowerCase());
|
|
70
|
+
}
|
|
71
|
+
}
|
|
43
72
|
|
|
44
73
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
45
74
|
this.doMeterUpdate = new Subject();
|
|
@@ -59,7 +88,7 @@ export class Meter {
|
|
|
59
88
|
// you can create multiple services for each accessory
|
|
60
89
|
(this.service =
|
|
61
90
|
accessory.getService(this.platform.Service.Battery) ||
|
|
62
|
-
accessory.addService(this.platform.Service.Battery)),
|
|
91
|
+
accessory.addService(this.platform.Service.Battery)), `${device.deviceName} ${device.deviceType}`;
|
|
63
92
|
|
|
64
93
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
65
94
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
@@ -88,7 +117,7 @@ export class Meter {
|
|
|
88
117
|
}
|
|
89
118
|
(this.temperatureservice =
|
|
90
119
|
this.accessory.getService(this.platform.Service.TemperatureSensor) ||
|
|
91
|
-
this.accessory.addService(this.platform.Service.TemperatureSensor)),
|
|
120
|
+
this.accessory.addService(this.platform.Service.TemperatureSensor)), `${device.deviceName} ${device.deviceType} TemperatureSensor`;
|
|
92
121
|
|
|
93
122
|
this.temperatureservice
|
|
94
123
|
.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
|
|
@@ -119,7 +148,7 @@ export class Meter {
|
|
|
119
148
|
} else if (!this.humidityservice) {
|
|
120
149
|
(this.humidityservice =
|
|
121
150
|
this.accessory.getService(this.platform.Service.HumiditySensor) ||
|
|
122
|
-
this.accessory.addService(this.platform.Service.HumiditySensor)),
|
|
151
|
+
this.accessory.addService(this.platform.Service.HumiditySensor)), `${device.deviceName} ${device.deviceType} HumiditySensor`;
|
|
123
152
|
|
|
124
153
|
this.humidityservice
|
|
125
154
|
.getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity)
|
|
@@ -194,6 +223,7 @@ export class Meter {
|
|
|
194
223
|
*/
|
|
195
224
|
async refreshStatus() {
|
|
196
225
|
if (this.platform.config.options?.ble?.includes(this.device.deviceId!)) {
|
|
226
|
+
this.platform.log.warn('BLE DEVICE-REFRESH');
|
|
197
227
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
198
228
|
const Switchbot = require('node-switchbot');
|
|
199
229
|
const switchbot = new Switchbot();
|
|
@@ -221,14 +251,15 @@ export class Meter {
|
|
|
221
251
|
.then(() => {
|
|
222
252
|
switchbot.stopScan();
|
|
223
253
|
})
|
|
224
|
-
.catch((error: any) => {
|
|
254
|
+
.catch(async (error: any) => {
|
|
225
255
|
this.platform.log.error(error);
|
|
256
|
+
await this.openAPIRefreshStatus();
|
|
226
257
|
});
|
|
227
258
|
setInterval(() => {
|
|
228
|
-
|
|
259
|
+
this.platform.log.info('Start scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
229
260
|
switchbot
|
|
230
261
|
.startScan({
|
|
231
|
-
|
|
262
|
+
mode: 'T',
|
|
232
263
|
id: bleMac,
|
|
233
264
|
})
|
|
234
265
|
.then(() => {
|
|
@@ -236,20 +267,26 @@ export class Meter {
|
|
|
236
267
|
})
|
|
237
268
|
.then(() => {
|
|
238
269
|
switchbot.stopScan();
|
|
239
|
-
this.platform.log.info('Stop scan ' + this.device.deviceName + '(' + bleMac + ')');
|
|
270
|
+
this.platform.log.info('Stop scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
240
271
|
})
|
|
241
|
-
.catch((error: any) => {
|
|
272
|
+
.catch(async (error: any) => {
|
|
242
273
|
this.platform.log.error(error);
|
|
274
|
+
await this.openAPIRefreshStatus();
|
|
243
275
|
});
|
|
244
276
|
}, this.platform.config.options!.refreshRate! * 60000);
|
|
277
|
+
} else {
|
|
278
|
+
await this.openAPIRefreshStatus();
|
|
245
279
|
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private async openAPIRefreshStatus() {
|
|
246
283
|
try {
|
|
247
284
|
const deviceStatus: deviceStatusResponse = (
|
|
248
285
|
await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)
|
|
249
286
|
).data;
|
|
250
287
|
if (deviceStatus.message === 'success') {
|
|
251
288
|
this.deviceStatus = deviceStatus;
|
|
252
|
-
this.platform.debug(`Meter ${this.accessory.displayName}
|
|
289
|
+
this.platform.debug(`Meter ${this.accessory.displayName} openAPIRefreshStatus - ${JSON.stringify(this.deviceStatus)}`);
|
|
253
290
|
this.parseStatus();
|
|
254
291
|
this.updateHomeKitCharacteristics();
|
|
255
292
|
}
|
|
@@ -262,7 +299,6 @@ export class Meter {
|
|
|
262
299
|
);
|
|
263
300
|
this.apiError(e);
|
|
264
301
|
}
|
|
265
|
-
|
|
266
302
|
}
|
|
267
303
|
|
|
268
304
|
/**
|
package/src/devices/motion.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
1
|
+
import { Service, PlatformAccessory, CharacteristicValue, MacAddress } from 'homebridge';
|
|
2
2
|
import { SwitchBotPlatform } from '../platform';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { skipWhile } from 'rxjs/operators';
|
|
@@ -10,13 +10,30 @@ import { DeviceURL, device, deviceStatusResponse } from '../settings';
|
|
|
10
10
|
* Each accessory may expose multiple services of different service types.
|
|
11
11
|
*/
|
|
12
12
|
export class Motion {
|
|
13
|
+
// Services
|
|
13
14
|
private service: Service;
|
|
14
|
-
temperatureservice?: Service;
|
|
15
|
-
humidityservice?: Service;
|
|
16
15
|
|
|
16
|
+
// Characteristic Values
|
|
17
17
|
MotionDetected!: CharacteristicValue;
|
|
18
|
-
deviceStatus!: deviceStatusResponse;
|
|
19
18
|
|
|
19
|
+
// Others
|
|
20
|
+
deviceStatus!: deviceStatusResponse;
|
|
21
|
+
switchbot!: {
|
|
22
|
+
discover: (
|
|
23
|
+
arg0:
|
|
24
|
+
{
|
|
25
|
+
duration: any;
|
|
26
|
+
model: string;
|
|
27
|
+
quick: boolean;
|
|
28
|
+
id: MacAddress;
|
|
29
|
+
}
|
|
30
|
+
) => Promise<any>;
|
|
31
|
+
wait: (
|
|
32
|
+
arg0: number
|
|
33
|
+
) => any;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Updates
|
|
20
37
|
motionUbpdateInProgress!: boolean;
|
|
21
38
|
doMotionUpdate;
|
|
22
39
|
|
|
@@ -28,6 +45,19 @@ export class Motion {
|
|
|
28
45
|
// default placeholders
|
|
29
46
|
this.MotionDetected = false;
|
|
30
47
|
|
|
48
|
+
// BLE Connection
|
|
49
|
+
if (this.platform.config.options?.ble?.includes(this.device.deviceId!)) {
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
51
|
+
const SwitchBot = require('node-switchbot');
|
|
52
|
+
this.switchbot = new SwitchBot();
|
|
53
|
+
const colon = device.deviceId!.match(/.{1,2}/g);
|
|
54
|
+
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
55
|
+
this.device.bleMac = bleMac.toLowerCase();
|
|
56
|
+
if (this.platform.config.options.debug) {
|
|
57
|
+
this.platform.log.warn(this.device.bleMac.toLowerCase());
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
31
61
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
32
62
|
this.doMotionUpdate = new Subject();
|
|
33
63
|
this.motionUbpdateInProgress = false;
|
|
@@ -46,7 +76,7 @@ export class Motion {
|
|
|
46
76
|
// you can create multiple services for each accessory
|
|
47
77
|
(this.service =
|
|
48
78
|
accessory.getService(this.platform.Service.MotionSensor) ||
|
|
49
|
-
accessory.addService(this.platform.Service.MotionSensor)),
|
|
79
|
+
accessory.addService(this.platform.Service.MotionSensor)), `${device.deviceName} ${device.deviceType}`;
|
|
50
80
|
|
|
51
81
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
52
82
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
@@ -89,6 +119,60 @@ export class Motion {
|
|
|
89
119
|
* Asks the SwitchBot API for the latest device information
|
|
90
120
|
*/
|
|
91
121
|
async refreshStatus() {
|
|
122
|
+
if (this.platform.config.options?.ble?.includes(this.device.deviceId!)) {
|
|
123
|
+
this.platform.log.warn('BLE DEVICE-REFRESH');
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
125
|
+
const Switchbot = require('node-switchbot');
|
|
126
|
+
const switchbot = new Switchbot();
|
|
127
|
+
const colon = this.device.deviceId!.match(/.{1,2}/g);
|
|
128
|
+
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
129
|
+
this.device.bleMac = bleMac.toLowerCase();
|
|
130
|
+
if (this.platform.config.options.debug) {
|
|
131
|
+
this.platform.log.warn(this.device.bleMac!);
|
|
132
|
+
}
|
|
133
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
134
|
+
this.platform.log.info(JSON.stringify(ad, null, ' '));
|
|
135
|
+
this.platform.log.warn('ad:', JSON.stringify(ad));
|
|
136
|
+
};
|
|
137
|
+
switchbot
|
|
138
|
+
.startScan({
|
|
139
|
+
id: this.device.bleMac,
|
|
140
|
+
})
|
|
141
|
+
.then(() => {
|
|
142
|
+
return switchbot.wait(this.platform.config.options!.refreshRate! * 1000);
|
|
143
|
+
})
|
|
144
|
+
.then(() => {
|
|
145
|
+
switchbot.stopScan();
|
|
146
|
+
})
|
|
147
|
+
.catch(async (error: any) => {
|
|
148
|
+
this.platform.log.error(error);
|
|
149
|
+
await this.openAPIRefreshStatus();
|
|
150
|
+
});
|
|
151
|
+
setInterval(() => {
|
|
152
|
+
this.platform.log.info('Start scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
153
|
+
switchbot
|
|
154
|
+
.startScan({
|
|
155
|
+
mode: 'M',
|
|
156
|
+
id: bleMac,
|
|
157
|
+
})
|
|
158
|
+
.then(() => {
|
|
159
|
+
return switchbot.wait(this.platform.config.options!.refreshRate! * 1000);
|
|
160
|
+
})
|
|
161
|
+
.then(() => {
|
|
162
|
+
switchbot.stopScan();
|
|
163
|
+
this.platform.log.info('Stop scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
164
|
+
})
|
|
165
|
+
.catch(async (error: any) => {
|
|
166
|
+
this.platform.log.error(error);
|
|
167
|
+
await this.openAPIRefreshStatus();
|
|
168
|
+
});
|
|
169
|
+
}, this.platform.config.options!.refreshRate! * 60000);
|
|
170
|
+
} else {
|
|
171
|
+
await this.openAPIRefreshStatus();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private async openAPIRefreshStatus() {
|
|
92
176
|
try {
|
|
93
177
|
const deviceStatus: deviceStatusResponse = (
|
|
94
178
|
await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)
|
|
@@ -105,8 +189,7 @@ export class Motion {
|
|
|
105
189
|
'Motion - Failed to update status of',
|
|
106
190
|
this.device.deviceName,
|
|
107
191
|
JSON.stringify(e.message),
|
|
108
|
-
this.platform.debug(`Motion ${this.accessory.displayName} - ${JSON.stringify(e)}`)
|
|
109
|
-
);
|
|
192
|
+
this.platform.debug(`Motion ${this.accessory.displayName} - ${JSON.stringify(e)}`));
|
|
110
193
|
this.apiError(e);
|
|
111
194
|
}
|
|
112
195
|
}
|