@switchbot/homebridge-switchbot 1.15.0 → 1.15.1-beta.0
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/config.schema.json +1 -1
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +3 -3
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +15 -1
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +140 -13
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +8 -5
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +6 -2
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +2 -1
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +2 -1
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +25 -14
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +2 -1
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +2 -1
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +7 -7
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +1 -1
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +7 -11
- package/dist/device/striplight.js.map +1 -1
- package/package.json +79 -79
- package/src/device/bot.ts +3 -3
- package/src/device/colorbulb.ts +169 -18
- package/src/device/contact.ts +9 -6
- package/src/device/curtain.ts +6 -2
- package/src/device/humidifier.ts +2 -1
- package/src/device/lock.ts +4 -3
- package/src/device/meter.ts +42 -32
- package/src/device/meterplus.ts +2 -1
- package/src/device/motion.ts +2 -1
- package/src/device/plug.ts +9 -9
- package/src/device/striplight.ts +8 -14
package/src/device/colorbulb.ts
CHANGED
|
@@ -3,7 +3,20 @@ 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 {
|
|
6
|
+
import {
|
|
7
|
+
DeviceURL,
|
|
8
|
+
device,
|
|
9
|
+
devicesConfig,
|
|
10
|
+
switchbot,
|
|
11
|
+
deviceStatusResponse,
|
|
12
|
+
payload,
|
|
13
|
+
hs2rgb,
|
|
14
|
+
rgb2hs,
|
|
15
|
+
m2hs,
|
|
16
|
+
deviceStatus,
|
|
17
|
+
serviceData,
|
|
18
|
+
ad,
|
|
19
|
+
} from '../settings';
|
|
7
20
|
import { Context } from 'vm';
|
|
8
21
|
|
|
9
22
|
/**
|
|
@@ -35,10 +48,18 @@ export class ColorBulb {
|
|
|
35
48
|
deviceStatus!: deviceStatusResponse;
|
|
36
49
|
|
|
37
50
|
// BLE Others
|
|
51
|
+
connected?: boolean;
|
|
38
52
|
switchbot!: switchbot;
|
|
53
|
+
address!: ad['address'];
|
|
54
|
+
SwitchToOpenAPI?: boolean;
|
|
55
|
+
serviceData!: serviceData;
|
|
56
|
+
state: serviceData['state'];
|
|
57
|
+
delay: serviceData['delay'];
|
|
58
|
+
wifiRssi: serviceData['wifiRssi'];
|
|
39
59
|
|
|
40
60
|
// Config
|
|
41
61
|
set_minStep?: number;
|
|
62
|
+
scanDuration!: number;
|
|
42
63
|
deviceLogging!: string;
|
|
43
64
|
deviceRefreshRate!: number;
|
|
44
65
|
adaptiveLightingShift?: number;
|
|
@@ -86,7 +107,8 @@ export class ColorBulb {
|
|
|
86
107
|
.setCharacteristic(this.platform.Characteristic.Model, 'W1401400')
|
|
87
108
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!)
|
|
88
109
|
.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
|
|
89
|
-
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
110
|
+
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
111
|
+
.updateValue(this.FirmwareRevision(accessory, device));
|
|
90
112
|
|
|
91
113
|
// get the Lightbulb service if it exists, otherwise create a new Lightbulb service
|
|
92
114
|
// you can create multiple services for each accessory
|
|
@@ -212,6 +234,27 @@ export class ColorBulb {
|
|
|
212
234
|
}
|
|
213
235
|
|
|
214
236
|
async parseStatus(): Promise<void> {
|
|
237
|
+
if (this.SwitchToOpenAPI || !this.device.ble) {
|
|
238
|
+
await this.openAPIparseStatus();
|
|
239
|
+
} else {
|
|
240
|
+
await this.BLEparseStatus();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async BLEparseStatus(): Promise<void> {
|
|
245
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} BLE parseStatus`);
|
|
246
|
+
// State
|
|
247
|
+
switch (this.state) {
|
|
248
|
+
case 'on':
|
|
249
|
+
this.On = true;
|
|
250
|
+
break;
|
|
251
|
+
default:
|
|
252
|
+
this.On = false;
|
|
253
|
+
}
|
|
254
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} On: ${this.On}`);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async openAPIparseStatus() {
|
|
215
258
|
switch (this.power) {
|
|
216
259
|
case 'on':
|
|
217
260
|
this.On = true;
|
|
@@ -234,9 +277,7 @@ export class ColorBulb {
|
|
|
234
277
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} blue: ${JSON.stringify(blue)}`);
|
|
235
278
|
|
|
236
279
|
const [hue, saturation] = rgb2hs(Number(red), Number(green), Number(blue));
|
|
237
|
-
this.debugLog(
|
|
238
|
-
`Color Bulb: ${this.accessory.displayName} hs: ${JSON.stringify(rgb2hs(Number(red), Number(green), Number(blue)))}`,
|
|
239
|
-
);
|
|
280
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} hs: ${JSON.stringify(rgb2hs(Number(red), Number(green), Number(blue)))}`);
|
|
240
281
|
|
|
241
282
|
// Hue
|
|
242
283
|
this.Hue = hue;
|
|
@@ -257,10 +298,126 @@ export class ColorBulb {
|
|
|
257
298
|
this.ColorTemperature = Math.max(Math.min(this.ColorTemperature, 500), 140);
|
|
258
299
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
|
|
259
300
|
}
|
|
260
|
-
|
|
261
301
|
}
|
|
262
302
|
|
|
263
303
|
async refreshStatus(): Promise<void> {
|
|
304
|
+
if (this.device.ble) {
|
|
305
|
+
await this.BLERefreshStatus();
|
|
306
|
+
} else {
|
|
307
|
+
await this.openAPIRefreshStatus();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
async BLERefreshStatus(): Promise<void> {
|
|
312
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} BLE refreshStatus`);
|
|
313
|
+
const switchbot = await this.platform.connectBLE();
|
|
314
|
+
// Convert to BLE Address
|
|
315
|
+
this.device.bleMac = this.device
|
|
316
|
+
.deviceId!.match(/.{1,2}/g)!
|
|
317
|
+
.join(':')
|
|
318
|
+
.toLowerCase();
|
|
319
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
320
|
+
this.getCustomBLEAddress(switchbot);
|
|
321
|
+
// Start to monitor advertisement packets
|
|
322
|
+
if (switchbot !== false) {
|
|
323
|
+
switchbot
|
|
324
|
+
.startScan({
|
|
325
|
+
model: 'u',
|
|
326
|
+
id: this.device.bleMac,
|
|
327
|
+
})
|
|
328
|
+
.then(() => {
|
|
329
|
+
// Set an event hander
|
|
330
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
331
|
+
this.address = ad.address;
|
|
332
|
+
if (this.deviceLogging.includes('debug')) {
|
|
333
|
+
this.infoLog(this.address);
|
|
334
|
+
this.infoLog(this.device.bleMac);
|
|
335
|
+
this.infoLog(`Color Bulb: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
|
|
336
|
+
this.infoLog(`Color Bulb: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
|
|
337
|
+
}
|
|
338
|
+
this.serviceData = ad.serviceData;
|
|
339
|
+
this.state = ad.serviceData.state;
|
|
340
|
+
this.delay = ad.serviceData.delay;
|
|
341
|
+
//this.timer = ad.serviceData.timer;
|
|
342
|
+
//this.syncUtcTime = ad.serviceData.syncUtcTime;
|
|
343
|
+
this.wifiRssi = ad.serviceData.wifiRssi;
|
|
344
|
+
//this.overload = ad.serviceData.overload;
|
|
345
|
+
//this.currentPower = ad.serviceData.currentPower;
|
|
346
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
347
|
+
this.debugLog(
|
|
348
|
+
`Color Bulb: ${this.accessory.displayName} state: ${ad.serviceData.state}, ` +
|
|
349
|
+
`delay: ${ad.serviceData.delay}, timer: ${ad.serviceData.timer}, syncUtcTime: ${ad.serviceData.syncUtcTime} ` +
|
|
350
|
+
`wifiRssi: ${ad.serviceData.wifiRssi}, overload: ${ad.serviceData.overload}, currentPower: ${ad.serviceData.currentPower}`,
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
if (this.serviceData) {
|
|
354
|
+
this.connected = true;
|
|
355
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
356
|
+
} else {
|
|
357
|
+
this.connected = false;
|
|
358
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
// Wait 2 seconds
|
|
362
|
+
return switchbot.wait(this.scanDuration * 1000);
|
|
363
|
+
})
|
|
364
|
+
.then(async () => {
|
|
365
|
+
// Stop to monitor
|
|
366
|
+
switchbot.stopScan();
|
|
367
|
+
if (this.connected) {
|
|
368
|
+
this.parseStatus();
|
|
369
|
+
this.updateHomeKitCharacteristics();
|
|
370
|
+
} else {
|
|
371
|
+
await this.BLEconnection(switchbot);
|
|
372
|
+
}
|
|
373
|
+
})
|
|
374
|
+
.catch(async (e: any) => {
|
|
375
|
+
this.errorLog(`Color Bulb: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
|
|
376
|
+
if (this.deviceLogging.includes('debug')) {
|
|
377
|
+
this.errorLog(
|
|
378
|
+
`Color Bulb: ${this.accessory.displayName} failed refreshStatus with BLE Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
if (this.platform.config.credentials?.openToken) {
|
|
382
|
+
this.warnLog(`Color Bulb: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
383
|
+
this.SwitchToOpenAPI = true;
|
|
384
|
+
await this.openAPIRefreshStatus();
|
|
385
|
+
}
|
|
386
|
+
this.apiError(e);
|
|
387
|
+
});
|
|
388
|
+
} else {
|
|
389
|
+
await this.BLEconnection(switchbot);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
async getCustomBLEAddress(switchbot: any) {
|
|
394
|
+
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
395
|
+
(async () => {
|
|
396
|
+
// Start to monitor advertisement packets
|
|
397
|
+
await switchbot.startScan({
|
|
398
|
+
model: 'u',
|
|
399
|
+
});
|
|
400
|
+
// Set an event handler
|
|
401
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
402
|
+
this.warnLog(JSON.stringify(ad, null, ' '));
|
|
403
|
+
};
|
|
404
|
+
await switchbot.wait(10000);
|
|
405
|
+
// Stop to monitor
|
|
406
|
+
switchbot.stopScan();
|
|
407
|
+
})();
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
async BLEconnection(switchbot: any): Promise<void> {
|
|
412
|
+
this.errorLog(`Color Bulb: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
413
|
+
if (this.platform.config.credentials?.openToken) {
|
|
414
|
+
this.warnLog(`Color Bulb: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
415
|
+
this.SwitchToOpenAPI = true;
|
|
416
|
+
await this.openAPIRefreshStatus();
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
private async openAPIRefreshStatus() {
|
|
264
421
|
try {
|
|
265
422
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
266
423
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
@@ -275,8 +432,7 @@ export class ColorBulb {
|
|
|
275
432
|
this.errorLog(`Color Bulb: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
276
433
|
if (this.deviceLogging.includes('debug')) {
|
|
277
434
|
this.errorLog(
|
|
278
|
-
`Color Bulb: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` +
|
|
279
|
-
` Error Message: ${JSON.stringify(e.message)}`,
|
|
435
|
+
`Color Bulb: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
280
436
|
);
|
|
281
437
|
}
|
|
282
438
|
this.apiError(e);
|
|
@@ -339,8 +495,7 @@ export class ColorBulb {
|
|
|
339
495
|
this.errorLog(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
340
496
|
if (this.deviceLogging.includes('debug')) {
|
|
341
497
|
this.errorLog(
|
|
342
|
-
`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` +
|
|
343
|
-
` Error Message: ${JSON.stringify(e.message)}`,
|
|
498
|
+
`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
344
499
|
);
|
|
345
500
|
}
|
|
346
501
|
this.apiError(e);
|
|
@@ -383,8 +538,7 @@ export class ColorBulb {
|
|
|
383
538
|
this.errorLog(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
384
539
|
if (this.deviceLogging.includes('debug')) {
|
|
385
540
|
this.errorLog(
|
|
386
|
-
`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` +
|
|
387
|
-
` Error Message: ${JSON.stringify(e.message)}`,
|
|
541
|
+
`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
388
542
|
);
|
|
389
543
|
}
|
|
390
544
|
this.apiError(e);
|
|
@@ -423,8 +577,7 @@ export class ColorBulb {
|
|
|
423
577
|
this.errorLog(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
424
578
|
if (this.deviceLogging.includes('debug')) {
|
|
425
579
|
this.errorLog(
|
|
426
|
-
`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` +
|
|
427
|
-
` Error Message: ${JSON.stringify(e.message)}`,
|
|
580
|
+
`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
428
581
|
);
|
|
429
582
|
}
|
|
430
583
|
this.apiError(e);
|
|
@@ -452,16 +605,14 @@ export class ColorBulb {
|
|
|
452
605
|
this.BrightnessCached = this.Brightness;
|
|
453
606
|
} else {
|
|
454
607
|
this.debugLog(
|
|
455
|
-
`Color Bulb: ${this.accessory.displayName} No Changes.` +
|
|
456
|
-
`Brightness: ${this.Brightness}, BrightnessCached: ${this.BrightnessCached}`,
|
|
608
|
+
`Color Bulb: ${this.accessory.displayName} No Changes.` + `Brightness: ${this.Brightness}, BrightnessCached: ${this.BrightnessCached}`,
|
|
457
609
|
);
|
|
458
610
|
}
|
|
459
611
|
} catch (e: any) {
|
|
460
612
|
this.errorLog(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
461
613
|
if (this.deviceLogging.includes('debug')) {
|
|
462
614
|
this.errorLog(
|
|
463
|
-
`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` +
|
|
464
|
-
` Error Message: ${JSON.stringify(e.message)}`,
|
|
615
|
+
`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
465
616
|
);
|
|
466
617
|
}
|
|
467
618
|
this.apiError(e);
|
package/src/device/contact.ts
CHANGED
|
@@ -74,7 +74,8 @@ export class Contact {
|
|
|
74
74
|
.setCharacteristic(this.platform.Characteristic.Model, 'W1201500')
|
|
75
75
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!)
|
|
76
76
|
.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
|
|
77
|
-
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
77
|
+
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
78
|
+
.updateValue(this.FirmwareRevision(accessory, device));
|
|
78
79
|
|
|
79
80
|
// get the Contact service if it exists, otherwise create a new Contact service
|
|
80
81
|
// you can create multiple services for each accessory
|
|
@@ -265,10 +266,12 @@ export class Contact {
|
|
|
265
266
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE refreshStatus`);
|
|
266
267
|
const switchbot = await this.platform.connectBLE();
|
|
267
268
|
// Convert to BLE Address
|
|
268
|
-
this.device.bleMac =
|
|
269
|
-
.
|
|
270
|
-
.
|
|
271
|
-
|
|
269
|
+
this.device.bleMac =
|
|
270
|
+
this.device.customBLEaddress ||
|
|
271
|
+
this.device
|
|
272
|
+
.deviceId!.match(/.{1,2}/g)!
|
|
273
|
+
.join(':')
|
|
274
|
+
.toLowerCase();
|
|
272
275
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
273
276
|
this.getCustomBLEAddress(switchbot);
|
|
274
277
|
// Start to monitor advertisement packets
|
|
@@ -296,7 +299,7 @@ export class Contact {
|
|
|
296
299
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
297
300
|
this.debugLog(
|
|
298
301
|
`Contact Sensor: ${this.accessory.displayName} movement: ${ad.serviceData.movement}, doorState: ` +
|
|
299
|
-
|
|
302
|
+
`${ad.serviceData.doorState}, lightLevel: ${ad.serviceData.lightLevel}, battery: ${ad.serviceData.battery}`,
|
|
300
303
|
);
|
|
301
304
|
|
|
302
305
|
if (this.serviceData) {
|
package/src/device/curtain.ts
CHANGED
|
@@ -90,7 +90,8 @@ export class Curtain {
|
|
|
90
90
|
.setCharacteristic(this.platform.Characteristic.Model, 'W0701600')
|
|
91
91
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId)
|
|
92
92
|
.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
|
|
93
|
-
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
93
|
+
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
94
|
+
.updateValue(this.FirmwareRevision(accessory, device));
|
|
94
95
|
|
|
95
96
|
// get the WindowCovering service if it exists, otherwise create a new WindowCovering service
|
|
96
97
|
// you can create multiple services for each accessory
|
|
@@ -212,7 +213,10 @@ export class Curtain {
|
|
|
212
213
|
* 'homebridge-switchbot/curtain/xx:xx:xx:xx:xx:xx'
|
|
213
214
|
*/
|
|
214
215
|
mqttPublish(topic: string, message: any) {
|
|
215
|
-
const mac = this.device.deviceId
|
|
216
|
+
const mac = this.device.deviceId
|
|
217
|
+
?.toLowerCase()
|
|
218
|
+
.match(/[\s\S]{1,2}/g)
|
|
219
|
+
?.join(':');
|
|
216
220
|
const options = this.device.mqttPubOptions || {};
|
|
217
221
|
this.mqttClient?.publish(`homebridge-switchbot/curtain/${mac}/${topic}`, `${message}`, options);
|
|
218
222
|
this.debugLog(`Meter: ${this.accessory.displayName} MQTT message: ${topic}/${message} options:${JSON.stringify(options)}`);
|
package/src/device/humidifier.ts
CHANGED
|
@@ -80,7 +80,8 @@ export class Humidifier {
|
|
|
80
80
|
.setCharacteristic(this.platform.Characteristic.Model, 'W0801800')
|
|
81
81
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!)
|
|
82
82
|
.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
|
|
83
|
-
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
83
|
+
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
84
|
+
.updateValue(this.FirmwareRevision(accessory, device));
|
|
84
85
|
|
|
85
86
|
// get the service if it exists, otherwise create a new service
|
|
86
87
|
// you can create multiple services for each accessory
|
package/src/device/lock.ts
CHANGED
|
@@ -56,7 +56,8 @@ export class Lock {
|
|
|
56
56
|
.setCharacteristic(this.platform.Characteristic.Model, 'W1601700')
|
|
57
57
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!)
|
|
58
58
|
.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
|
|
59
|
-
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
59
|
+
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
60
|
+
.updateValue(this.FirmwareRevision(accessory, device));
|
|
60
61
|
|
|
61
62
|
// get the LockMechanism service if it exists, otherwise create a new LockMechanism service
|
|
62
63
|
// you can create multiple services for each accessory
|
|
@@ -187,7 +188,7 @@ export class Lock {
|
|
|
187
188
|
|
|
188
189
|
this.infoLog(
|
|
189
190
|
`Lock: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
190
|
-
|
|
191
|
+
` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
|
|
191
192
|
);
|
|
192
193
|
|
|
193
194
|
// Make the API request
|
|
@@ -254,7 +255,7 @@ export class Lock {
|
|
|
254
255
|
case 190:
|
|
255
256
|
this.errorLog(
|
|
256
257
|
`Lock: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
257
|
-
|
|
258
|
+
` Or command: ${JSON.stringify(push.data)} format is invalid`,
|
|
258
259
|
);
|
|
259
260
|
break;
|
|
260
261
|
case 100:
|
package/src/device/meter.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceSta
|
|
|
6
6
|
import { Context } from 'vm';
|
|
7
7
|
import { MqttClient } from 'mqtt';
|
|
8
8
|
import { connectAsync } from 'async-mqtt';
|
|
9
|
-
import { hostname } from
|
|
9
|
+
import { hostname } from 'os';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Platform Accessory
|
|
@@ -56,7 +56,7 @@ export class Meter {
|
|
|
56
56
|
|
|
57
57
|
//MQTT stuff
|
|
58
58
|
mqttClient: MqttClient | null = null;
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
// EVE history service handler
|
|
61
61
|
historyService: any;
|
|
62
62
|
|
|
@@ -93,7 +93,8 @@ export class Meter {
|
|
|
93
93
|
.setCharacteristic(this.platform.Characteristic.Model, 'METERTH-S1')
|
|
94
94
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!)
|
|
95
95
|
.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
|
|
96
|
-
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
96
|
+
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
97
|
+
.updateValue(this.FirmwareRevision(accessory, device));
|
|
97
98
|
|
|
98
99
|
// Temperature Sensor Service
|
|
99
100
|
if (device.meter?.hide_temperature) {
|
|
@@ -182,7 +183,10 @@ export class Meter {
|
|
|
182
183
|
* 'homebridge-switchbot/meter/xx:xx:xx:xx:xx:xx'
|
|
183
184
|
*/
|
|
184
185
|
mqttPublish(message: any) {
|
|
185
|
-
const mac = this.device.deviceId
|
|
186
|
+
const mac = this.device.deviceId
|
|
187
|
+
?.toLowerCase()
|
|
188
|
+
.match(/[\s\S]{1,2}/g)
|
|
189
|
+
?.join(':');
|
|
186
190
|
const options = this.device.mqttPubOptions || {};
|
|
187
191
|
this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
|
|
188
192
|
this.debugLog(`Meter: ${this.accessory.displayName} MQTT message: ${message} options:${JSON.stringify(options)}`);
|
|
@@ -194,14 +198,14 @@ export class Meter {
|
|
|
194
198
|
async setupMqtt(device: device & devicesConfig): Promise<void> {
|
|
195
199
|
if (device.mqttURL) {
|
|
196
200
|
try {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
201
|
+
this.mqttClient = await connectAsync(device.mqttURL, device.mqttOptions || {});
|
|
202
|
+
this.debugLog(`Meter: ${this.accessory.displayName} MQTT connection has been established successfully.`);
|
|
203
|
+
this.mqttClient.on('error', (e: Error) => {
|
|
204
|
+
this.errorLog(`Meter: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
|
|
205
|
+
});
|
|
202
206
|
} catch (e) {
|
|
203
|
-
|
|
204
|
-
|
|
207
|
+
this.mqttClient = null;
|
|
208
|
+
this.errorLog(`Meter: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
|
|
205
209
|
}
|
|
206
210
|
}
|
|
207
211
|
}
|
|
@@ -210,15 +214,19 @@ export class Meter {
|
|
|
210
214
|
* Setup EVE history graph feature if enabled.
|
|
211
215
|
*/
|
|
212
216
|
async setupHistoryService(device: device & devicesConfig): Promise<void> {
|
|
213
|
-
const mac = this.device
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
const mac = this.device
|
|
218
|
+
.deviceId!.match(/.{1,2}/g)!
|
|
219
|
+
.join(':')
|
|
220
|
+
.toLowerCase();
|
|
221
|
+
this.historyService = device.history
|
|
222
|
+
? new this.platform.fakegatoAPI('room', this.accessory, {
|
|
223
|
+
log: this.platform.log,
|
|
224
|
+
storage: 'fs',
|
|
225
|
+
filename: `${hostname().split('.')[0]}_${mac}_persist.json`,
|
|
226
|
+
})
|
|
227
|
+
: null;
|
|
220
228
|
}
|
|
221
|
-
|
|
229
|
+
|
|
222
230
|
/**
|
|
223
231
|
* Parse the device status from the SwitchBot api
|
|
224
232
|
*/
|
|
@@ -240,7 +248,7 @@ export class Meter {
|
|
|
240
248
|
} else {
|
|
241
249
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
242
250
|
}
|
|
243
|
-
|
|
251
|
+
this.debugLog(`Meter: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
|
|
244
252
|
|
|
245
253
|
// Humidity
|
|
246
254
|
if (!this.device.meter?.hide_humidity) {
|
|
@@ -314,12 +322,13 @@ export class Meter {
|
|
|
314
322
|
this.infoLog(`Meter: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
|
|
315
323
|
this.infoLog(`Meter: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
|
|
316
324
|
}
|
|
317
|
-
|
|
325
|
+
if (ad.serviceData.humidity! > 0) {
|
|
326
|
+
// reject unreliable data
|
|
318
327
|
this.serviceData = ad.serviceData;
|
|
319
328
|
this.temperature = ad.serviceData.temperature!.c;
|
|
320
329
|
this.humidity = ad.serviceData.humidity;
|
|
321
330
|
this.battery = ad.serviceData.battery;
|
|
322
|
-
|
|
331
|
+
}
|
|
323
332
|
this.debugLog(`Meter: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
324
333
|
this.debugLog(
|
|
325
334
|
`Meter: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
|
|
@@ -420,16 +429,16 @@ export class Meter {
|
|
|
420
429
|
* Updates the status for each of the HomeKit Characteristics
|
|
421
430
|
*/
|
|
422
431
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
423
|
-
|
|
424
|
-
|
|
432
|
+
const mqttmessage: string[] = [];
|
|
433
|
+
const entry = { time: Math.round(new Date().valueOf() / 1000) };
|
|
425
434
|
if (!this.device.meter?.hide_humidity) {
|
|
426
435
|
if (this.CurrentRelativeHumidity === undefined) {
|
|
427
436
|
this.debugLog(`Meter: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
|
|
428
437
|
} else {
|
|
429
438
|
this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
|
|
430
439
|
this.debugLog(`Meter: ${this.accessory.displayName} updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
|
|
431
|
-
|
|
432
|
-
|
|
440
|
+
mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
|
|
441
|
+
entry['humidity'] = this.CurrentRelativeHumidity;
|
|
433
442
|
}
|
|
434
443
|
}
|
|
435
444
|
if (!this.device.meter?.hide_temperature) {
|
|
@@ -438,8 +447,8 @@ export class Meter {
|
|
|
438
447
|
} else {
|
|
439
448
|
this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature);
|
|
440
449
|
this.debugLog(`Meter: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
|
|
441
|
-
|
|
442
|
-
|
|
450
|
+
mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
|
|
451
|
+
entry['temp'] = this.CurrentTemperature;
|
|
443
452
|
}
|
|
444
453
|
}
|
|
445
454
|
if (this.device.ble) {
|
|
@@ -448,18 +457,19 @@ export class Meter {
|
|
|
448
457
|
} else {
|
|
449
458
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
|
|
450
459
|
this.debugLog(`Meter: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
451
|
-
|
|
460
|
+
mqttmessage.push(`"battery": ${this.BatteryLevel}`);
|
|
452
461
|
}
|
|
453
462
|
if (this.StatusLowBattery === undefined) {
|
|
454
463
|
this.debugLog(`Meter: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
455
464
|
} else {
|
|
456
465
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
457
466
|
this.debugLog(`Meter: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
458
|
-
|
|
467
|
+
mqttmessage.push(`"lowBattery": ${this.StatusLowBattery}`);
|
|
459
468
|
}
|
|
460
469
|
}
|
|
461
|
-
this.mqttPublish(`{${mqttmessage.join(',')}}`)
|
|
462
|
-
if (this.CurrentRelativeHumidity > 0) {
|
|
470
|
+
this.mqttPublish(`{${mqttmessage.join(',')}}`);
|
|
471
|
+
if (this.CurrentRelativeHumidity > 0) {
|
|
472
|
+
// reject unreliable data
|
|
463
473
|
this.historyService?.addEntry(entry);
|
|
464
474
|
}
|
|
465
475
|
}
|
package/src/device/meterplus.ts
CHANGED
|
@@ -82,7 +82,8 @@ export class MeterPlus {
|
|
|
82
82
|
.setCharacteristic(this.platform.Characteristic.Model, this.model(device))
|
|
83
83
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!)
|
|
84
84
|
.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
|
|
85
|
-
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
85
|
+
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
86
|
+
.updateValue(this.FirmwareRevision(accessory, device));
|
|
86
87
|
|
|
87
88
|
// Temperature Sensor Service
|
|
88
89
|
if (device.meter?.hide_temperature) {
|
package/src/device/motion.ts
CHANGED
|
@@ -70,7 +70,8 @@ export class Motion {
|
|
|
70
70
|
.setCharacteristic(this.platform.Characteristic.Model, 'W1101500')
|
|
71
71
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!)
|
|
72
72
|
.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
|
|
73
|
-
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
73
|
+
.getCharacteristic(this.platform.Characteristic.FirmwareRevision)
|
|
74
|
+
.updateValue(this.FirmwareRevision(accessory, device));
|
|
74
75
|
|
|
75
76
|
// get the Battery service if it exists, otherwise create a new Motion service
|
|
76
77
|
// you can create multiple services for each accessory
|
package/src/device/plug.ts
CHANGED
|
@@ -21,9 +21,16 @@ export class Plug {
|
|
|
21
21
|
// BLE Others
|
|
22
22
|
connected?: boolean;
|
|
23
23
|
switchbot!: switchbot;
|
|
24
|
+
address!: ad['address'];
|
|
24
25
|
SwitchToOpenAPI?: boolean;
|
|
25
26
|
serviceData!: serviceData;
|
|
26
|
-
|
|
27
|
+
state: serviceData['state'];
|
|
28
|
+
delay: serviceData['delay'];
|
|
29
|
+
timer: serviceData['timer'];
|
|
30
|
+
wifiRssi: serviceData['wifiRssi'];
|
|
31
|
+
overload: serviceData['overload'];
|
|
32
|
+
syncUtcTime: serviceData['syncUtcTime'];
|
|
33
|
+
currentPower: serviceData['currentPower'];
|
|
27
34
|
|
|
28
35
|
// Config
|
|
29
36
|
scanDuration!: number;
|
|
@@ -33,13 +40,6 @@ export class Plug {
|
|
|
33
40
|
// Updates
|
|
34
41
|
plugUpdateInProgress!: boolean;
|
|
35
42
|
doPlugUpdate!: Subject<void>;
|
|
36
|
-
state: serviceData['state'];
|
|
37
|
-
delay: serviceData['delay'];
|
|
38
|
-
timer: serviceData['timer'];
|
|
39
|
-
syncUtcTime: serviceData['syncUtcTime'];
|
|
40
|
-
wifiRssi: serviceData['wifiRssi'];
|
|
41
|
-
overload: serviceData['overload'];
|
|
42
|
-
currentPower: serviceData['currentPower'];
|
|
43
43
|
|
|
44
44
|
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
|
|
45
45
|
// default placeholders
|
|
@@ -271,7 +271,7 @@ export class Plug {
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
async BLEconnection(switchbot: any): Promise<void> {
|
|
274
|
-
this.errorLog(`Plug: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-
|
|
274
|
+
this.errorLog(`Plug: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
275
275
|
if (this.platform.config.credentials?.openToken) {
|
|
276
276
|
this.warnLog(`Plug: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
277
277
|
this.SwitchToOpenAPI = true;
|