@switchbot/homebridge-switchbot 0.2.0-alpha.2 → 1.0.1-beta.2
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/nodejs-beta.yml +1 -1
- package/.github/workflows/nodejs.yml +1 -1
- package/.github/workflows/{prerelease.js → prerelease-beta.js} +0 -0
- package/CHANGELOG.md +1 -1
- package/README.md +9 -5
- package/config.schema.json +370 -142
- package/dist/devices/bots.d.ts +18 -34
- package/dist/devices/bots.d.ts.map +1 -1
- package/dist/devices/bots.js +166 -171
- package/dist/devices/bots.js.map +1 -1
- package/dist/devices/{bulb.d.ts → colorbulb.d.ts} +12 -19
- package/dist/devices/colorbulb.d.ts.map +1 -0
- package/dist/devices/{bulb.js → colorbulb.js} +34 -32
- package/dist/devices/colorbulb.js.map +1 -0
- package/dist/devices/contact.d.ts +18 -16
- package/dist/devices/contact.d.ts.map +1 -1
- package/dist/devices/contact.js +101 -44
- package/dist/devices/contact.js.map +1 -1
- package/dist/devices/curtains.d.ts +17 -51
- package/dist/devices/curtains.d.ts.map +1 -1
- package/dist/devices/curtains.js +170 -248
- package/dist/devices/curtains.js.map +1 -1
- package/dist/devices/humidifiers.d.ts +13 -4
- package/dist/devices/humidifiers.d.ts.map +1 -1
- package/dist/devices/humidifiers.js +81 -8
- package/dist/devices/humidifiers.js.map +1 -1
- package/dist/devices/indoorcam.d.ts +6 -13
- package/dist/devices/indoorcam.d.ts.map +1 -1
- package/dist/devices/indoorcam.js.map +1 -1
- package/dist/devices/meters.d.ts +12 -15
- package/dist/devices/meters.d.ts.map +1 -1
- package/dist/devices/meters.js +38 -44
- package/dist/devices/meters.js.map +1 -1
- package/dist/devices/motion.d.ts +17 -15
- package/dist/devices/motion.d.ts.map +1 -1
- package/dist/devices/motion.js +87 -40
- package/dist/devices/motion.js.map +1 -1
- package/dist/devices/plugs.d.ts +6 -13
- package/dist/devices/plugs.d.ts.map +1 -1
- package/dist/devices/plugs.js.map +1 -1
- package/dist/irdevices/airconditioners.d.ts +10 -10
- package/dist/irdevices/airconditioners.d.ts.map +1 -1
- package/dist/irdevices/airconditioners.js +29 -9
- package/dist/irdevices/airconditioners.js.map +1 -1
- package/dist/irdevices/airpurifiers.d.ts +11 -11
- package/dist/irdevices/airpurifiers.d.ts.map +1 -1
- package/dist/irdevices/airpurifiers.js.map +1 -1
- package/dist/irdevices/cameras.d.ts +3 -3
- package/dist/irdevices/cameras.d.ts.map +1 -1
- package/dist/irdevices/cameras.js.map +1 -1
- package/dist/irdevices/fans.d.ts +6 -6
- package/dist/irdevices/fans.d.ts.map +1 -1
- package/dist/irdevices/fans.js +10 -10
- package/dist/irdevices/fans.js.map +1 -1
- package/dist/irdevices/lights.d.ts +3 -3
- package/dist/irdevices/lights.d.ts.map +1 -1
- package/dist/irdevices/lights.js.map +1 -1
- package/dist/irdevices/others.d.ts +3 -3
- package/dist/irdevices/others.d.ts.map +1 -1
- package/dist/irdevices/others.js.map +1 -1
- package/dist/irdevices/tvs.d.ts +3 -3
- package/dist/irdevices/tvs.d.ts.map +1 -1
- package/dist/irdevices/tvs.js +7 -5
- package/dist/irdevices/tvs.js.map +1 -1
- package/dist/irdevices/vacuumcleaners.d.ts +3 -3
- package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
- package/dist/irdevices/vacuumcleaners.js.map +1 -1
- package/dist/irdevices/waterheaters.d.ts +3 -3
- package/dist/irdevices/waterheaters.d.ts.map +1 -1
- package/dist/irdevices/waterheaters.js.map +1 -1
- package/dist/platform.d.ts +3 -2
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +136 -46
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +51 -8
- package/dist/settings.d.ts.map +1 -1
- package/package.json +65 -65
- package/src/devices/bots.ts +188 -193
- package/src/devices/{bulb.ts → colorbulb.ts} +46 -51
- package/src/devices/contact.ts +124 -68
- package/src/devices/curtains.ts +192 -300
- package/src/devices/humidifiers.ts +97 -14
- package/src/devices/indoorcam.ts +10 -20
- package/src/devices/meters.ts +57 -69
- package/src/devices/motion.ts +108 -62
- package/src/devices/plugs.ts +8 -19
- package/src/irdevices/airconditioners.ts +43 -20
- package/src/irdevices/airpurifiers.ts +15 -11
- package/src/irdevices/cameras.ts +5 -3
- package/src/irdevices/fans.ts +22 -16
- package/src/irdevices/lights.ts +5 -3
- package/src/irdevices/others.ts +5 -3
- package/src/irdevices/tvs.ts +13 -7
- package/src/irdevices/vacuumcleaners.ts +5 -3
- package/src/irdevices/waterheaters.ts +5 -3
- package/src/platform.ts +148 -49
- package/src/settings.ts +80 -8
- package/dist/devices/bulb.d.ts.map +0 -1
- package/dist/devices/bulb.js.map +0 -1
|
@@ -2,7 +2,8 @@ import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
|
2
2
|
import { SwitchBotPlatform } from '../platform';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { debounceTime, skipWhile, tap } from 'rxjs/operators';
|
|
5
|
-
import { DeviceURL, device, devicesConfig } from '../settings';
|
|
5
|
+
import { DeviceURL, device, devicesConfig, serviceData, ad, deviceStatusResponse } from '../settings';
|
|
6
|
+
import { AxiosResponse } from 'axios';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Platform Accessory
|
|
@@ -23,19 +24,31 @@ export class Humidifier {
|
|
|
23
24
|
Active!: CharacteristicValue;
|
|
24
25
|
WaterLevel!: CharacteristicValue;
|
|
25
26
|
|
|
26
|
-
//
|
|
27
|
-
deviceStatus!:
|
|
27
|
+
// OpenAPI
|
|
28
|
+
deviceStatus!: deviceStatusResponse;
|
|
29
|
+
|
|
30
|
+
// BLE Others
|
|
31
|
+
serviceData!: serviceData;
|
|
32
|
+
onState!: serviceData['onState'];
|
|
33
|
+
autoMode!: serviceData['autoMode'];
|
|
34
|
+
percentage!: serviceData['percentage'];
|
|
35
|
+
|
|
36
|
+
// Config
|
|
37
|
+
set_minStep?: number;
|
|
28
38
|
|
|
29
39
|
// Updates
|
|
30
40
|
humidifierUpdateInProgress!: boolean;
|
|
31
|
-
doHumidifierUpdate
|
|
32
|
-
set_minStep: number | undefined;
|
|
41
|
+
doHumidifierUpdate!: Subject<void>;
|
|
33
42
|
|
|
34
43
|
constructor(
|
|
35
44
|
private readonly platform: SwitchBotPlatform,
|
|
36
45
|
private accessory: PlatformAccessory,
|
|
37
46
|
public device: device & devicesConfig,
|
|
38
47
|
) {
|
|
48
|
+
// Humidifiers Config
|
|
49
|
+
this.platform.device(`[Humidifiers Config] ble: ${device.ble}, hide_temperature: ${device.humidifier?.hide_temperature},`
|
|
50
|
+
+ ` set_minStep: ${device.humidifier?.set_minStep}`);
|
|
51
|
+
|
|
39
52
|
// default placeholders
|
|
40
53
|
this.CurrentRelativeHumidity = 0;
|
|
41
54
|
this.TargetHumidifierDehumidifierState = this.platform.Characteristic.TargetHumidifierDehumidifierState.HUMIDIFIER;
|
|
@@ -180,7 +193,11 @@ export class Humidifier {
|
|
|
180
193
|
*/
|
|
181
194
|
parseStatus() {
|
|
182
195
|
// Current Relative Humidity
|
|
183
|
-
|
|
196
|
+
if (this.device.ble) {
|
|
197
|
+
this.CurrentRelativeHumidity = this.percentage!;
|
|
198
|
+
} else {
|
|
199
|
+
this.CurrentRelativeHumidity = this.deviceStatus.body.humidity!;
|
|
200
|
+
}
|
|
184
201
|
this.platform.debug(`Humidifier ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
|
|
185
202
|
this.platform.device(JSON.stringify(this.deviceStatus.body));
|
|
186
203
|
// Water Level
|
|
@@ -191,12 +208,16 @@ export class Humidifier {
|
|
|
191
208
|
}
|
|
192
209
|
this.platform.debug(`Humidifier ${this.accessory.displayName} WaterLevel: ${this.WaterLevel}`);
|
|
193
210
|
// Active
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
211
|
+
if (this.device.ble) {
|
|
212
|
+
this.Active = this.State();
|
|
213
|
+
} else {
|
|
214
|
+
switch (this.deviceStatus.body.power) {
|
|
215
|
+
case 'on':
|
|
216
|
+
this.Active = this.platform.Characteristic.Active.ACTIVE;
|
|
217
|
+
break;
|
|
218
|
+
default:
|
|
219
|
+
this.Active = this.platform.Characteristic.Active.INACTIVE;
|
|
220
|
+
}
|
|
200
221
|
}
|
|
201
222
|
this.platform.debug(`Humidifier ${this.accessory.displayName} Active: ${this.Active}`);
|
|
202
223
|
// Target Humidifier Dehumidifier State
|
|
@@ -226,15 +247,77 @@ export class Humidifier {
|
|
|
226
247
|
this.platform.debug(`Humidifier ${this.accessory.displayName} CurrentHumidifierDehumidifierState: ${this.CurrentHumidifierDehumidifierState}`);
|
|
227
248
|
// Current Temperature
|
|
228
249
|
if (!this.device.humidifier?.hide_temperature) {
|
|
229
|
-
this.CurrentTemperature = this.deviceStatus.body.temperature;
|
|
250
|
+
this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
|
|
230
251
|
this.platform.debug(`Humidifier ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
|
|
231
252
|
}
|
|
232
253
|
}
|
|
233
254
|
|
|
255
|
+
private State(): CharacteristicValue {
|
|
256
|
+
if (this.onState) {
|
|
257
|
+
return this.platform.Characteristic.Active.ACTIVE;
|
|
258
|
+
} else {
|
|
259
|
+
return this.platform.Characteristic.Active.INACTIVE;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
234
263
|
/**
|
|
235
264
|
* Asks the SwitchBot API for the latest device information
|
|
236
265
|
*/
|
|
237
266
|
async refreshStatus() {
|
|
267
|
+
if (this.device.ble) {
|
|
268
|
+
this.platform.device('BLE');
|
|
269
|
+
await this.BLERefreshStatus();
|
|
270
|
+
} else {
|
|
271
|
+
this.platform.device('OpenAPI');
|
|
272
|
+
await this.openAPIRefreshStatus();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private connectBLE() {
|
|
277
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
278
|
+
const Switchbot = require('node-switchbot');
|
|
279
|
+
const switchbot = new Switchbot();
|
|
280
|
+
const colon = this.device.deviceId!.match(/.{1,2}/g);
|
|
281
|
+
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
282
|
+
this.device.bleMac = bleMac.toLowerCase();
|
|
283
|
+
this.platform.device(this.device.bleMac!);
|
|
284
|
+
return switchbot;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private async BLERefreshStatus() {
|
|
288
|
+
this.platform.device('Bot BLE Device refreshStatus');
|
|
289
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
290
|
+
const switchbot = this.connectBLE();
|
|
291
|
+
// Start to monitor advertisement packets
|
|
292
|
+
switchbot.startScan({
|
|
293
|
+
model: 'e',
|
|
294
|
+
id: this.device.bleMac,
|
|
295
|
+
}).then(() => {
|
|
296
|
+
// Set an event hander
|
|
297
|
+
switchbot.onadvertisement = (ad: ad) => {
|
|
298
|
+
this.serviceData = ad.serviceData;
|
|
299
|
+
this.autoMode = ad.serviceData.autoMode;
|
|
300
|
+
this.onState = ad.serviceData.onState;
|
|
301
|
+
this.percentage = ad.serviceData.percentage;
|
|
302
|
+
this.platform.device(`${this.device.bleMac}: ${JSON.stringify(ad.serviceData)}`);
|
|
303
|
+
this.platform.device(`${this.accessory.displayName}, Model: ${ad.serviceData.model}, Model Name: ${ad.serviceData.modelName},`
|
|
304
|
+
+ `autoMode: ${ad.serviceData.autoMode}, onState: ${ad.serviceData.onState}, percentage: ${ad.serviceData.percentage}`);
|
|
305
|
+
};
|
|
306
|
+
// Wait 10 seconds
|
|
307
|
+
return switchbot.wait(10000);
|
|
308
|
+
}).then(() => {
|
|
309
|
+
// Stop to monitor
|
|
310
|
+
switchbot.stopScan();
|
|
311
|
+
this.parseStatus();
|
|
312
|
+
this.updateHomeKitCharacteristics();
|
|
313
|
+
}).catch(async (e: any) => {
|
|
314
|
+
this.platform.log.error(`BLE Connection Failed: ${e.message}`);
|
|
315
|
+
this.platform.log.warn('Using OpenAPI Connection');
|
|
316
|
+
await this.openAPIRefreshStatus();
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private async openAPIRefreshStatus() {
|
|
238
321
|
try {
|
|
239
322
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
240
323
|
if (this.deviceStatus.message === 'success') {
|
|
@@ -436,7 +519,7 @@ export class Humidifier {
|
|
|
436
519
|
}
|
|
437
520
|
}
|
|
438
521
|
|
|
439
|
-
private statusCode(push: {
|
|
522
|
+
private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
|
|
440
523
|
switch (push.data.statusCode) {
|
|
441
524
|
case 151:
|
|
442
525
|
this.platform.log.error('Command not supported by this device type.');
|
package/src/devices/indoorcam.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Service, PlatformAccessory, CharacteristicValue
|
|
1
|
+
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
2
2
|
import { SwitchBotPlatform } from '../platform';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { debounceTime, skipWhile, tap } from 'rxjs/operators';
|
|
5
|
-
import { DeviceURL, device, devicesConfig } from '../settings';
|
|
5
|
+
import { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse } from '../settings';
|
|
6
|
+
import { AxiosResponse } from 'axios';
|
|
6
7
|
|
|
7
8
|
export class IndoorCam {
|
|
8
9
|
// Services
|
|
@@ -12,26 +13,15 @@ export class IndoorCam {
|
|
|
12
13
|
On!: CharacteristicValue;
|
|
13
14
|
OutletInUse!: CharacteristicValue;
|
|
14
15
|
|
|
15
|
-
// Others
|
|
16
|
-
deviceStatus!:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
duration: any;
|
|
22
|
-
model: string;
|
|
23
|
-
quick: boolean;
|
|
24
|
-
id: MacAddress;
|
|
25
|
-
}
|
|
26
|
-
) => Promise<any>;
|
|
27
|
-
wait: (
|
|
28
|
-
arg0: number
|
|
29
|
-
) => any;
|
|
30
|
-
};
|
|
16
|
+
// OpenAPI Others
|
|
17
|
+
deviceStatus!: deviceStatusResponse;
|
|
18
|
+
|
|
19
|
+
// BLE Others
|
|
20
|
+
switchbot!: switchbot;
|
|
31
21
|
|
|
32
22
|
// Updates
|
|
33
23
|
cameraUpdateInProgress!: boolean;
|
|
34
|
-
doCameraUpdate
|
|
24
|
+
doCameraUpdate!: Subject<void>;
|
|
35
25
|
|
|
36
26
|
constructor(
|
|
37
27
|
private readonly platform: SwitchBotPlatform,
|
|
@@ -259,7 +249,7 @@ export class IndoorCam {
|
|
|
259
249
|
}
|
|
260
250
|
|
|
261
251
|
|
|
262
|
-
private statusCode(push: {
|
|
252
|
+
private statusCode(push: AxiosResponse<{ statusCode: number;}>) {
|
|
263
253
|
switch (push.data.statusCode) {
|
|
264
254
|
case 151:
|
|
265
255
|
this.platform.log.error('Command not supported by this device type.');
|
package/src/devices/meters.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Service, PlatformAccessory, Units, CharacteristicValue
|
|
1
|
+
import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
|
|
2
2
|
import { SwitchBotPlatform } from '../platform';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { skipWhile } from 'rxjs/operators';
|
|
5
|
-
import { DeviceURL, device, devicesConfig } from '../settings';
|
|
5
|
+
import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse } from '../settings';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Platform Accessory
|
|
@@ -24,34 +24,30 @@ export class Meter {
|
|
|
24
24
|
Active!: CharacteristicValue;
|
|
25
25
|
WaterLevel!: CharacteristicValue;
|
|
26
26
|
|
|
27
|
-
// Others
|
|
28
|
-
deviceStatus!:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
switchbot!:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
quick: boolean;
|
|
38
|
-
id: MacAddress;
|
|
39
|
-
}
|
|
40
|
-
) => Promise<any>;
|
|
41
|
-
wait: (
|
|
42
|
-
arg0: number
|
|
43
|
-
) => any;
|
|
44
|
-
};
|
|
27
|
+
// OpenAPI Others
|
|
28
|
+
deviceStatus!: deviceStatusResponse;
|
|
29
|
+
|
|
30
|
+
// BLE Others
|
|
31
|
+
switchbot!: switchbot;
|
|
32
|
+
serviceData!: serviceData;
|
|
33
|
+
battery!: serviceData['battery'];
|
|
34
|
+
humidity!: serviceData['humidity'];
|
|
35
|
+
fahrenheit!: serviceData['fahrenheit'];
|
|
36
|
+
temperature!: serviceData['temperature'];
|
|
45
37
|
|
|
46
38
|
// Updates
|
|
47
39
|
meterUpdateInProgress!: boolean;
|
|
48
|
-
doMeterUpdate
|
|
40
|
+
doMeterUpdate: Subject<void>;
|
|
49
41
|
|
|
50
42
|
constructor(
|
|
51
43
|
private readonly platform: SwitchBotPlatform,
|
|
52
44
|
private accessory: PlatformAccessory,
|
|
53
45
|
public device: device & devicesConfig,
|
|
54
46
|
) {
|
|
47
|
+
// Meter Config
|
|
48
|
+
this.platform.device(`[Meter Config] ble: ${device.ble}, unit: ${device.meter?.unit},`
|
|
49
|
+
+ ` hide_temperature: ${device.meter?.hide_temperature}, hide_humidity: ${device.meter?.hide_humidity}`);
|
|
50
|
+
|
|
55
51
|
// default placeholders
|
|
56
52
|
this.BatteryLevel = 0;
|
|
57
53
|
this.ChargingState = 2;
|
|
@@ -211,7 +207,7 @@ export class Meter {
|
|
|
211
207
|
// Current Relative Humidity
|
|
212
208
|
if (!this.device.meter?.hide_humidity) {
|
|
213
209
|
if (this.device.ble) {
|
|
214
|
-
this.CurrentRelativeHumidity = this.
|
|
210
|
+
this.CurrentRelativeHumidity = Number(this.humidity);
|
|
215
211
|
} else {
|
|
216
212
|
this.CurrentRelativeHumidity = this.deviceStatus.body.humidity!;
|
|
217
213
|
}
|
|
@@ -221,14 +217,14 @@ export class Meter {
|
|
|
221
217
|
// Current Temperature
|
|
222
218
|
if (!this.device.meter?.hide_temperature) {
|
|
223
219
|
if (this.device.ble) {
|
|
224
|
-
this.CurrentTemperature = this.
|
|
220
|
+
this.CurrentTemperature = Number(this.temperature);
|
|
225
221
|
} else {
|
|
226
222
|
if (this.device.meter?.unit === 1) {
|
|
227
223
|
this.CurrentTemperature = this.toFahrenheit(this.deviceStatus.body.temperature!);
|
|
228
224
|
} else if (this.device.meter?.unit === 0) {
|
|
229
225
|
this.CurrentTemperature = this.toCelsius(this.deviceStatus.body.temperature!);
|
|
230
226
|
} else {
|
|
231
|
-
this.CurrentTemperature = this.deviceStatus.body.temperature;
|
|
227
|
+
this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
|
|
232
228
|
}
|
|
233
229
|
}
|
|
234
230
|
this.platform.debug(`Meter ${this.accessory.displayName} - Temperature: ${this.CurrentTemperature}°c`);
|
|
@@ -248,8 +244,7 @@ export class Meter {
|
|
|
248
244
|
}
|
|
249
245
|
}
|
|
250
246
|
|
|
251
|
-
private
|
|
252
|
-
this.platform.debug('Meter BLE Device RefreshStatus');
|
|
247
|
+
private connectBLE() {
|
|
253
248
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
254
249
|
const Switchbot = require('node-switchbot');
|
|
255
250
|
const switchbot = new Switchbot();
|
|
@@ -257,49 +252,42 @@ export class Meter {
|
|
|
257
252
|
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
258
253
|
this.device.bleMac = bleMac.toLowerCase();
|
|
259
254
|
this.platform.device(this.device.bleMac!);
|
|
260
|
-
switchbot
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
this.platform.log.info('Stop scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
297
|
-
})
|
|
298
|
-
.catch(async (error: any) => {
|
|
299
|
-
this.platform.log.error(error);
|
|
300
|
-
await this.openAPIRefreshStatus();
|
|
301
|
-
});
|
|
302
|
-
}, this.platform.config.options!.refreshRate! * 60000);
|
|
255
|
+
return switchbot;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private async BLErefreshStatus() {
|
|
259
|
+
this.platform.debug('Meter BLE Device RefreshStatus');
|
|
260
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
261
|
+
const switchbot = this.connectBLE();
|
|
262
|
+
// Start to monitor advertisement packets
|
|
263
|
+
switchbot.startScan({
|
|
264
|
+
model: 'e',
|
|
265
|
+
id: this.device.bleMac,
|
|
266
|
+
}).then(() => {
|
|
267
|
+
// Set an event hander
|
|
268
|
+
switchbot.onadvertisement = (ad: ad) => {
|
|
269
|
+
this.serviceData = ad.serviceData;
|
|
270
|
+
this.temperature = ad.serviceData.temperature;
|
|
271
|
+
this.fahrenheit = ad.serviceData.fahrenheit;
|
|
272
|
+
this.humidity = ad.serviceData.humidity;
|
|
273
|
+
this.battery = ad.serviceData.battery;
|
|
274
|
+
this.platform.device(`${this.device.bleMac}: ${JSON.stringify(ad.serviceData)}`);
|
|
275
|
+
this.platform.device(`${this.accessory.displayName}, Model: ${ad.serviceData.model}, Model Name: ${ad.serviceData.modelName},`
|
|
276
|
+
+ `Temperature: ${ad.serviceData.temperature}, Fahrenheit: ${ad.serviceData.fahrenheit}, Humidity: ${ad.serviceData.humidity}`
|
|
277
|
+
+ `Battery: ${ad.serviceData.battery}`);
|
|
278
|
+
};
|
|
279
|
+
// Wait 10 seconds
|
|
280
|
+
return switchbot.wait(10000);
|
|
281
|
+
}).then(() => {
|
|
282
|
+
// Stop to monitor
|
|
283
|
+
switchbot.stopScan();
|
|
284
|
+
this.parseStatus();
|
|
285
|
+
this.updateHomeKitCharacteristics();
|
|
286
|
+
}).catch(async (e: any) => {
|
|
287
|
+
this.platform.log.error(`BLE Connection Failed: ${e.message}`);
|
|
288
|
+
this.platform.log.warn('Using OpenAPI Connection');
|
|
289
|
+
await this.openAPIRefreshStatus();
|
|
290
|
+
});
|
|
303
291
|
}
|
|
304
292
|
|
|
305
293
|
private async openAPIRefreshStatus() {
|
package/src/devices/motion.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Service, PlatformAccessory, CharacteristicValue
|
|
1
|
+
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
2
2
|
import { SwitchBotPlatform } from '../platform';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { skipWhile } from 'rxjs/operators';
|
|
5
|
-
import { DeviceURL, device, devicesConfig } from '../settings';
|
|
5
|
+
import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse } from '../settings';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Platform Accessory
|
|
@@ -12,31 +12,28 @@ import { DeviceURL, device, devicesConfig } from '../settings';
|
|
|
12
12
|
export class Motion {
|
|
13
13
|
// Services
|
|
14
14
|
private service: Service;
|
|
15
|
+
private lightSensorService?: Service;
|
|
16
|
+
private batteryService?: Service;
|
|
15
17
|
|
|
16
18
|
// Characteristic Values
|
|
17
19
|
MotionDetected!: CharacteristicValue;
|
|
20
|
+
BatteryLevel?: CharacteristicValue;
|
|
21
|
+
StatusLowBattery?: CharacteristicValue;
|
|
22
|
+
CurrentAmbientLightLevel?: CharacteristicValue;
|
|
18
23
|
|
|
19
|
-
// Others
|
|
20
|
-
deviceStatus!:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
quick: boolean;
|
|
29
|
-
id: MacAddress;
|
|
30
|
-
}
|
|
31
|
-
) => Promise<any>;
|
|
32
|
-
wait: (
|
|
33
|
-
arg0: number
|
|
34
|
-
) => any;
|
|
35
|
-
};
|
|
24
|
+
// OpenAPI Others
|
|
25
|
+
deviceStatus!: deviceStatusResponse;
|
|
26
|
+
|
|
27
|
+
// BLE Others
|
|
28
|
+
switchbot!: switchbot;
|
|
29
|
+
serviceData!: serviceData;
|
|
30
|
+
battery!: serviceData['battery'];
|
|
31
|
+
movement!: serviceData['movement'];
|
|
32
|
+
lightLevel!: serviceData['lightLevel'];
|
|
36
33
|
|
|
37
34
|
// Updates
|
|
38
35
|
motionUbpdateInProgress!: boolean;
|
|
39
|
-
doMotionUpdate
|
|
36
|
+
doMotionUpdate!: Subject<void>;
|
|
40
37
|
|
|
41
38
|
constructor(
|
|
42
39
|
private readonly platform: SwitchBotPlatform,
|
|
@@ -77,6 +74,21 @@ export class Motion {
|
|
|
77
74
|
accessory.getService(this.platform.Service.MotionSensor) ||
|
|
78
75
|
accessory.addService(this.platform.Service.MotionSensor)), `${accessory.displayName} Motion Sensor`;
|
|
79
76
|
|
|
77
|
+
if (device.ble) {
|
|
78
|
+
(this.lightSensorService =
|
|
79
|
+
accessory.getService(this.platform.Service.LightSensor) ||
|
|
80
|
+
accessory.addService(this.platform.Service.LightSensor)), `${accessory.displayName} Light Sensor`;
|
|
81
|
+
|
|
82
|
+
this.lightSensorService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Light Sensor`);
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
(this.batteryService =
|
|
86
|
+
accessory.getService(this.platform.Service.Battery) ||
|
|
87
|
+
accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
88
|
+
|
|
89
|
+
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
90
|
+
}
|
|
91
|
+
|
|
80
92
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
81
93
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
82
94
|
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.Motion, 'NAME', 'USER_DEFINED_SUBTYPE');
|
|
@@ -116,8 +128,24 @@ export class Motion {
|
|
|
116
128
|
}
|
|
117
129
|
|
|
118
130
|
private async BLEparseStatus() {
|
|
119
|
-
this.MotionDetected = Boolean(this.
|
|
131
|
+
this.MotionDetected = Boolean(this.movement);
|
|
120
132
|
this.platform.debug(`${this.accessory.displayName}, MotionDetected: ${this.MotionDetected}`);
|
|
133
|
+
// Light Level
|
|
134
|
+
switch (this.lightLevel) {
|
|
135
|
+
case 'dark':
|
|
136
|
+
case 0:
|
|
137
|
+
this.CurrentAmbientLightLevel = 0.0001;
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
this.CurrentAmbientLightLevel = 100000;
|
|
141
|
+
}
|
|
142
|
+
// Battery
|
|
143
|
+
this.BatteryLevel = Number(this.battery);
|
|
144
|
+
if (this.BatteryLevel < 10) {
|
|
145
|
+
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
146
|
+
} else {
|
|
147
|
+
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
148
|
+
}
|
|
121
149
|
}
|
|
122
150
|
|
|
123
151
|
private async openAPIparseStatus() {
|
|
@@ -131,15 +159,14 @@ export class Motion {
|
|
|
131
159
|
async refreshStatus() {
|
|
132
160
|
if (this.device.ble) {
|
|
133
161
|
this.platform.device('BLE');
|
|
134
|
-
await this.
|
|
162
|
+
await this.BLERefreshStatus();
|
|
135
163
|
} else {
|
|
136
164
|
this.platform.device('OpenAPI');
|
|
137
165
|
await this.openAPIRefreshStatus();
|
|
138
166
|
}
|
|
139
167
|
}
|
|
140
168
|
|
|
141
|
-
private
|
|
142
|
-
this.platform.debug('Motion BLE Device RefreshStatus');
|
|
169
|
+
private connectBLE() {
|
|
143
170
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
144
171
|
const Switchbot = require('node-switchbot');
|
|
145
172
|
const switchbot = new Switchbot();
|
|
@@ -147,46 +174,40 @@ export class Motion {
|
|
|
147
174
|
const bleMac = colon!.join(':'); //returns 1A:23:B4:56:78:9A;
|
|
148
175
|
this.device.bleMac = bleMac.toLowerCase();
|
|
149
176
|
this.platform.device(this.device.bleMac!);
|
|
150
|
-
switchbot
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
this.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return switchbot.wait(this.platform.config.options!.refreshRate! * 1000);
|
|
178
|
-
})
|
|
179
|
-
.then(() => {
|
|
180
|
-
switchbot.stopScan();
|
|
181
|
-
this.platform.log.info('Stop scan ' + this.device.deviceName + '(' + this.device.bleMac + ')');
|
|
182
|
-
})
|
|
183
|
-
.catch(async (error: any) => {
|
|
184
|
-
this.platform.log.error(error);
|
|
185
|
-
await this.openAPIRefreshStatus();
|
|
186
|
-
});
|
|
177
|
+
return switchbot;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private async BLERefreshStatus() {
|
|
181
|
+
this.platform.debug('Motion BLE Device RefreshStatus');
|
|
182
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
183
|
+
const switchbot = this.connectBLE();
|
|
184
|
+
// Start to monitor advertisement packets
|
|
185
|
+
switchbot.startScan({
|
|
186
|
+
model: 's',
|
|
187
|
+
id: this.device.bleMac,
|
|
188
|
+
}).then(() => {
|
|
189
|
+
// Set an event hander
|
|
190
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
191
|
+
this.serviceData = ad.serviceData;
|
|
192
|
+
this.platform.device(`${this.device.bleMac}: ${JSON.stringify(ad.serviceData)}`);
|
|
193
|
+
this.movement = ad.serviceData.movement;
|
|
194
|
+
this.battery = ad.serviceData.battery;
|
|
195
|
+
this.lightLevel = ad.serviceData.lightLevel;
|
|
196
|
+
this.platform.device(`${this.accessory.displayName}, Movement: ${ad.serviceData.movement}, Light Level: ${ad.serviceData.lightLevel},`
|
|
197
|
+
+ ` Battery: ${ad.serviceData.battery}`);
|
|
198
|
+
};
|
|
199
|
+
// Wait 10 seconds
|
|
200
|
+
return switchbot.wait(10000);
|
|
201
|
+
}).then(() => {
|
|
202
|
+
// Stop to monitor
|
|
203
|
+
switchbot.stopScan();
|
|
187
204
|
this.parseStatus();
|
|
188
205
|
this.updateHomeKitCharacteristics();
|
|
189
|
-
}
|
|
206
|
+
}).catch(async (e: any) => {
|
|
207
|
+
this.platform.log.error(`BLE Connection Failed: ${e.message}`);
|
|
208
|
+
this.platform.log.warn('Using OpenAPI Connection');
|
|
209
|
+
await this.openAPIRefreshStatus();
|
|
210
|
+
});
|
|
190
211
|
}
|
|
191
212
|
|
|
192
213
|
private async openAPIRefreshStatus() {
|
|
@@ -212,9 +233,34 @@ export class Motion {
|
|
|
212
233
|
this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.MotionDetected);
|
|
213
234
|
this.platform.device(`Motion ${this.accessory.displayName} updateCharacteristic MotionDetected: ${this.MotionDetected}`);
|
|
214
235
|
}
|
|
236
|
+
if (this.device.ble) {
|
|
237
|
+
if (this.BatteryLevel === undefined) {
|
|
238
|
+
this.platform.debug(`Motion ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
239
|
+
} else {
|
|
240
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
|
|
241
|
+
this.platform.device(`Motion ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
242
|
+
}
|
|
243
|
+
if (this.StatusLowBattery === undefined) {
|
|
244
|
+
this.platform.debug(`Motion ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
245
|
+
} else {
|
|
246
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
247
|
+
this.platform.device(`Motion ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
248
|
+
}
|
|
249
|
+
if (this.CurrentAmbientLightLevel === undefined) {
|
|
250
|
+
this.platform.debug(`Motion ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
251
|
+
} else {
|
|
252
|
+
this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, this.CurrentAmbientLightLevel);
|
|
253
|
+
this.platform.device(`Motion ${this.accessory.displayName} updateCharacteristic CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
215
256
|
}
|
|
216
257
|
|
|
217
258
|
public apiError(e: any) {
|
|
218
259
|
this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, e);
|
|
260
|
+
if (this.device.ble) {
|
|
261
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
|
|
262
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
|
|
263
|
+
this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, e);
|
|
264
|
+
}
|
|
219
265
|
}
|
|
220
266
|
}
|