@switchbot/homebridge-switchbot 3.7.1-beta.2 → 3.7.1-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +14 -0
- package/assets/security-privacy-bluetooth.png +0 -0
- package/config.schema.json +74 -2
- package/dist/device/blindtilt.d.ts +21 -9
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +167 -96
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot-old.d.ts +132 -0
- package/dist/device/bot-old.d.ts.map +1 -0
- package/dist/device/bot-old.js +1482 -0
- package/dist/device/bot-old.js.map +1 -0
- package/dist/device/bot.d.ts +10 -9
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +186 -187
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +14 -13
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +87 -97
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +13 -12
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +92 -105
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +6 -5
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +71 -68
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +17 -5
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +184 -118
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +18 -18
- package/dist/device/device.d.ts.map +1 -1
- package/dist/device/device.js +33 -36
- package/dist/device/device.js.map +1 -1
- package/dist/device/fan.d.ts +9 -8
- package/dist/device/fan.d.ts.map +1 -1
- package/dist/device/fan.js +94 -101
- package/dist/device/fan.js.map +1 -1
- package/dist/device/hub.d.ts +6 -5
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +69 -65
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +6 -5
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +89 -104
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +6 -5
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +72 -66
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +7 -6
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +85 -99
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +10 -9
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +89 -79
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +6 -5
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +72 -65
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +6 -5
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +72 -64
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +6 -5
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +65 -58
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +13 -12
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +68 -52
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +12 -11
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +93 -82
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +6 -5
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +73 -63
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/homebridge-ui/server.js +2 -2
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +8 -8
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +61 -105
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +10 -10
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +22 -42
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +9 -9
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +15 -25
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +8 -8
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +21 -40
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +11 -11
- package/dist/irdevice/irdevice.d.ts.map +1 -1
- package/dist/irdevice/irdevice.js +14 -22
- package/dist/irdevice/irdevice.js.map +1 -1
- package/dist/irdevice/light.d.ts +9 -9
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +24 -47
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +9 -9
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +40 -83
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +9 -9
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +29 -54
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +5 -5
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +11 -21
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +5 -5
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +11 -22
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +24 -23
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +509 -723
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +5 -2
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/dist/types/bledevicestatus.d.ts +9 -9
- package/dist/types/bledevicestatus.d.ts.map +1 -1
- package/dist/types/devicelist.d.ts +6 -6
- package/dist/types/devicelist.d.ts.map +1 -1
- package/dist/types/deviceresponse.d.ts +4 -4
- package/dist/types/deviceresponse.d.ts.map +1 -1
- package/dist/types/devicestatus.d.ts +2 -2
- package/dist/types/devicestatus.d.ts.map +1 -1
- package/dist/types/devicewebhookstatus.d.ts +5 -5
- package/dist/types/devicewebhookstatus.d.ts.map +1 -1
- package/dist/types/irdevicelist.d.ts +4 -4
- package/dist/types/irdevicelist.d.ts.map +1 -1
- package/dist/types/pushbody.d.ts +2 -2
- package/dist/types/pushbody.d.ts.map +1 -1
- package/dist/utils.d.ts +4 -4
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +9 -13
- package/dist/utils.js.map +1 -1
- package/eslint.config.js +48 -93
- package/package.json +64 -57
- package/src/device/blindtilt.ts +537 -456
- package/src/device/bot-old.ts +1540 -0
- package/src/device/bot.ts +732 -725
- package/src/device/ceilinglight.ts +359 -368
- package/src/device/colorbulb.ts +441 -453
- package/src/device/contact.ts +229 -226
- package/src/device/curtain.ts +526 -444
- package/src/device/device.ts +206 -208
- package/src/device/fan.ts +336 -345
- package/src/device/hub.ts +213 -214
- package/src/device/humidifier.ts +326 -347
- package/src/device/iosensor.ts +211 -209
- package/src/device/lightstrip.ts +391 -404
- package/src/device/lock.ts +292 -282
- package/src/device/meter.ts +212 -210
- package/src/device/meterplus.ts +212 -209
- package/src/device/motion.ts +198 -190
- package/src/device/plug.ts +203 -182
- package/src/device/robotvacuumcleaner.ts +280 -269
- package/src/device/waterdetector.ts +198 -189
- package/src/homebridge-ui/server.ts +16 -15
- package/src/index.ts +5 -6
- package/src/irdevice/airconditioner.ts +277 -326
- package/src/irdevice/airpurifier.ts +124 -143
- package/src/irdevice/camera.ts +58 -64
- package/src/irdevice/fan.ts +106 -123
- package/src/irdevice/irdevice.ts +116 -119
- package/src/irdevice/light.ts +119 -143
- package/src/irdevice/other.ts +417 -461
- package/src/irdevice/tv.ts +155 -177
- package/src/irdevice/vacuumcleaner.ts +54 -60
- package/src/irdevice/waterheater.ts +56 -63
- package/src/platform.ts +1491 -1681
- package/src/settings.ts +172 -169
- package/src/types/bledevicestatus.ts +252 -256
- package/src/types/devicelist.ts +79 -79
- package/src/types/deviceresponse.ts +12 -13
- package/src/types/devicestatus.ts +124 -124
- package/src/types/devicewebhookstatus.ts +126 -131
- package/src/types/irdevicelist.ts +10 -10
- package/src/types/pushbody.ts +5 -5
- package/src/utils.ts +64 -65
- package/tsconfig.json +10 -9
package/src/device/lock.ts
CHANGED
|
@@ -2,293 +2,307 @@
|
|
|
2
2
|
*
|
|
3
3
|
* lock.ts: @switchbot/homebridge-switchbot.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
import type {
|
|
10
|
-
import type { device } from '../types/devicelist.js'
|
|
11
|
-
import type {
|
|
12
|
-
import type {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
|
|
6
|
+
|
|
7
|
+
import type { SwitchBotPlatform } from '../platform.js'
|
|
8
|
+
import type { devicesConfig } from '../settings.js'
|
|
9
|
+
import type { lockProServiceData, lockServiceData } from '../types/bledevicestatus.js'
|
|
10
|
+
import type { device } from '../types/devicelist.js'
|
|
11
|
+
import type { lockProStatus, lockStatus } from '../types/devicestatus.js'
|
|
12
|
+
import type { lockProWebhookContext, lockWebhookContext } from '../types/devicewebhookstatus.js'
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* For Testing Locally:
|
|
16
|
+
* import { SwitchBotBLEModel, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
|
|
17
|
+
*/
|
|
18
|
+
import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot'
|
|
19
|
+
import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs'
|
|
20
|
+
|
|
21
|
+
import { deviceBase } from './device.js'
|
|
16
22
|
|
|
17
23
|
export class Lock extends deviceBase {
|
|
18
24
|
// Services
|
|
19
25
|
private LockMechanism: {
|
|
20
|
-
Name: CharacteristicValue
|
|
21
|
-
Service: Service
|
|
22
|
-
LockTargetState: CharacteristicValue
|
|
23
|
-
LockCurrentState: CharacteristicValue
|
|
24
|
-
}
|
|
26
|
+
Name: CharacteristicValue
|
|
27
|
+
Service: Service
|
|
28
|
+
LockTargetState: CharacteristicValue
|
|
29
|
+
LockCurrentState: CharacteristicValue
|
|
30
|
+
}
|
|
25
31
|
|
|
26
32
|
private Battery: {
|
|
27
|
-
Name: CharacteristicValue
|
|
28
|
-
Service: Service
|
|
29
|
-
BatteryLevel: CharacteristicValue
|
|
30
|
-
StatusLowBattery: CharacteristicValue
|
|
31
|
-
}
|
|
33
|
+
Name: CharacteristicValue
|
|
34
|
+
Service: Service
|
|
35
|
+
BatteryLevel: CharacteristicValue
|
|
36
|
+
StatusLowBattery: CharacteristicValue
|
|
37
|
+
}
|
|
32
38
|
|
|
33
39
|
private ContactSensor?: {
|
|
34
|
-
Name: CharacteristicValue
|
|
35
|
-
Service: Service
|
|
36
|
-
ContactSensorState: CharacteristicValue
|
|
37
|
-
}
|
|
40
|
+
Name: CharacteristicValue
|
|
41
|
+
Service: Service
|
|
42
|
+
ContactSensorState: CharacteristicValue
|
|
43
|
+
}
|
|
38
44
|
|
|
39
45
|
private Switch?: {
|
|
40
|
-
Name: CharacteristicValue
|
|
41
|
-
Service: Service
|
|
42
|
-
On: CharacteristicValue
|
|
43
|
-
}
|
|
46
|
+
Name: CharacteristicValue
|
|
47
|
+
Service: Service
|
|
48
|
+
On: CharacteristicValue
|
|
49
|
+
}
|
|
44
50
|
|
|
45
51
|
// OpenAPI
|
|
46
|
-
deviceStatus!: lockStatus | lockProStatus
|
|
52
|
+
deviceStatus!: lockStatus | lockProStatus
|
|
47
53
|
|
|
48
|
-
//Webhook
|
|
49
|
-
webhookContext!: lockWebhookContext | lockProWebhookContext
|
|
54
|
+
// Webhook
|
|
55
|
+
webhookContext!: lockWebhookContext | lockProWebhookContext
|
|
50
56
|
|
|
51
57
|
// BLE
|
|
52
|
-
serviceData!: lockServiceData | lockProServiceData
|
|
58
|
+
serviceData!: lockServiceData | lockProServiceData
|
|
53
59
|
|
|
54
60
|
// Updates
|
|
55
|
-
lockUpdateInProgress!: boolean
|
|
56
|
-
doLockUpdate!: Subject<void
|
|
61
|
+
lockUpdateInProgress!: boolean
|
|
62
|
+
doLockUpdate!: Subject<void>
|
|
57
63
|
|
|
58
64
|
constructor(
|
|
59
65
|
readonly platform: SwitchBotPlatform,
|
|
60
66
|
accessory: PlatformAccessory,
|
|
61
67
|
device: device & devicesConfig,
|
|
62
68
|
) {
|
|
63
|
-
super(platform, accessory, device)
|
|
69
|
+
super(platform, accessory, device)
|
|
64
70
|
// Set category
|
|
65
|
-
accessory.category = this.hap.Categories.DOOR_LOCK
|
|
71
|
+
accessory.category = this.hap.Categories.DOOR_LOCK
|
|
66
72
|
|
|
67
73
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
68
|
-
this.doLockUpdate = new Subject()
|
|
69
|
-
this.lockUpdateInProgress = false
|
|
74
|
+
this.doLockUpdate = new Subject()
|
|
75
|
+
this.lockUpdateInProgress = false
|
|
70
76
|
|
|
71
77
|
// Initialize LockMechanism Service
|
|
72
|
-
accessory.context.LockMechanism = accessory.context.LockMechanism ?? {}
|
|
78
|
+
accessory.context.LockMechanism = accessory.context.LockMechanism ?? {}
|
|
73
79
|
this.LockMechanism = {
|
|
74
80
|
Name: accessory.displayName,
|
|
75
81
|
Service: accessory.getService(this.hap.Service.LockMechanism) ?? accessory.addService(this.hap.Service.LockMechanism) as Service,
|
|
76
82
|
LockTargetState: accessory.context.LockTargetState ?? this.hap.Characteristic.LockTargetState.SECURED,
|
|
77
83
|
LockCurrentState: accessory.context.LockCurrentState ?? this.hap.Characteristic.LockCurrentState.SECURED,
|
|
78
|
-
}
|
|
79
|
-
accessory.context.LockMechanism = this.LockMechanism as object
|
|
84
|
+
}
|
|
85
|
+
accessory.context.LockMechanism = this.LockMechanism as object
|
|
80
86
|
|
|
81
87
|
// Initialize LockMechanism Characteristics
|
|
82
|
-
this.LockMechanism.Service
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
.onGet(() => {
|
|
86
|
-
return this.LockMechanism.LockTargetState;
|
|
87
|
-
})
|
|
88
|
-
.onSet(this.LockTargetStateSet.bind(this));
|
|
88
|
+
this.LockMechanism.Service.setCharacteristic(this.hap.Characteristic.Name, this.LockMechanism.Name).getCharacteristic(this.hap.Characteristic.LockTargetState).onGet(() => {
|
|
89
|
+
return this.LockMechanism.LockTargetState
|
|
90
|
+
}).onSet(this.LockTargetStateSet.bind(this))
|
|
89
91
|
|
|
90
92
|
// Initialize Battery property
|
|
91
|
-
accessory.context.Battery = accessory.context.Battery ?? {}
|
|
93
|
+
accessory.context.Battery = accessory.context.Battery ?? {}
|
|
92
94
|
this.Battery = {
|
|
93
95
|
Name: `${accessory.displayName} Battery`,
|
|
94
96
|
Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
|
|
95
97
|
BatteryLevel: accessory.context.BatteryLevel ?? 100,
|
|
96
98
|
StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
|
|
97
|
-
}
|
|
98
|
-
accessory.context.Battery = this.Battery as object
|
|
99
|
+
}
|
|
100
|
+
accessory.context.Battery = this.Battery as object
|
|
99
101
|
|
|
100
102
|
// Initialize Battery Characteristics
|
|
101
|
-
this.Battery.Service
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.Battery.Service
|
|
110
|
-
.getCharacteristic(this.hap.Characteristic.StatusLowBattery)
|
|
111
|
-
.onGet(() => {
|
|
112
|
-
return this.Battery.StatusLowBattery;
|
|
113
|
-
});
|
|
103
|
+
this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name).setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE).getCharacteristic(this.hap.Characteristic.BatteryLevel).onGet(() => {
|
|
104
|
+
return this.Battery.BatteryLevel
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
this.Battery.Service.getCharacteristic(this.hap.Characteristic.StatusLowBattery).onGet(() => {
|
|
108
|
+
return this.Battery.StatusLowBattery
|
|
109
|
+
})
|
|
114
110
|
|
|
115
111
|
// Contact Sensor Service
|
|
116
112
|
if (device.lock?.hide_contactsensor) {
|
|
117
113
|
if (this.ContactSensor) {
|
|
118
|
-
this.debugLog('Removing Contact Sensor Service')
|
|
119
|
-
this.ContactSensor.Service = this.accessory.getService(this.hap.Service.ContactSensor) as Service
|
|
120
|
-
accessory.removeService(this.ContactSensor.Service)
|
|
114
|
+
this.debugLog('Removing Contact Sensor Service')
|
|
115
|
+
this.ContactSensor.Service = this.accessory.getService(this.hap.Service.ContactSensor) as Service
|
|
116
|
+
accessory.removeService(this.ContactSensor.Service)
|
|
121
117
|
}
|
|
122
118
|
} else {
|
|
123
|
-
accessory.context.ContactSensor = accessory.context.ContactSensor ?? {}
|
|
119
|
+
accessory.context.ContactSensor = accessory.context.ContactSensor ?? {}
|
|
124
120
|
this.ContactSensor = {
|
|
125
121
|
Name: `${accessory.displayName} Contact Sensor`,
|
|
126
122
|
Service: accessory.getService(this.hap.Service.ContactSensor) ?? this.accessory.addService(this.hap.Service.ContactSensor) as Service,
|
|
127
123
|
ContactSensorState: accessory.context.ContactSensorState ?? this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED,
|
|
128
|
-
}
|
|
129
|
-
accessory.context.ContactSensor = this.ContactSensor as object
|
|
124
|
+
}
|
|
125
|
+
accessory.context.ContactSensor = this.ContactSensor as object
|
|
130
126
|
|
|
131
127
|
// Initialize Contact Sensor Characteristics
|
|
132
|
-
this.ContactSensor.Service
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
.getCharacteristic(this.hap.Characteristic.ContactSensorState)
|
|
136
|
-
.onGet(() => {
|
|
137
|
-
return this.ContactSensor!.ContactSensorState;
|
|
138
|
-
});
|
|
128
|
+
this.ContactSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.ContactSensor.Name).setCharacteristic(this.hap.Characteristic.StatusActive, true).getCharacteristic(this.hap.Characteristic.ContactSensorState).onGet(() => {
|
|
129
|
+
return this.ContactSensor!.ContactSensorState
|
|
130
|
+
})
|
|
139
131
|
}
|
|
140
132
|
|
|
141
133
|
// Initialize Latch Button Service
|
|
142
134
|
if (device.lock?.activate_latchbutton === false) {
|
|
143
135
|
if (this.Switch) {
|
|
144
|
-
this.debugLog('Removing Latch Button Service')
|
|
145
|
-
this.Switch.Service = accessory.getService(this.hap.Service.Switch) as Service
|
|
146
|
-
accessory.removeService(this.Switch.Service)
|
|
136
|
+
this.debugLog('Removing Latch Button Service')
|
|
137
|
+
this.Switch.Service = accessory.getService(this.hap.Service.Switch) as Service
|
|
138
|
+
accessory.removeService(this.Switch.Service)
|
|
147
139
|
}
|
|
148
140
|
} else {
|
|
149
|
-
accessory.context.Switch = accessory.context.Switch ?? {}
|
|
141
|
+
accessory.context.Switch = accessory.context.Switch ?? {}
|
|
150
142
|
this.Switch = {
|
|
151
143
|
Name: `${accessory.displayName} Latch`,
|
|
152
144
|
Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch) as Service,
|
|
153
145
|
On: accessory.context.On ?? false,
|
|
154
|
-
}
|
|
155
|
-
accessory.context.Switch = this.Switch as object
|
|
146
|
+
}
|
|
147
|
+
accessory.context.Switch = this.Switch as object
|
|
156
148
|
|
|
157
149
|
// Initialize Latch Button Characteristics
|
|
158
|
-
this.Switch.Service
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
.onGet(() => {
|
|
162
|
-
return this.Switch!.On;
|
|
163
|
-
})
|
|
164
|
-
.onSet(this.OnSet.bind(this));
|
|
150
|
+
this.Switch.Service.setCharacteristic(this.hap.Characteristic.Name, this.Switch.Name).getCharacteristic(this.hap.Characteristic.On).onGet(() => {
|
|
151
|
+
return this.Switch!.On
|
|
152
|
+
}).onSet(this.OnSet.bind(this))
|
|
165
153
|
}
|
|
166
154
|
|
|
167
155
|
// Retrieve initial values and updateHomekit
|
|
168
|
-
|
|
169
|
-
|
|
156
|
+
try {
|
|
157
|
+
this.debugLog('Retrieve initial values and update Homekit')
|
|
158
|
+
this.refreshStatus()
|
|
159
|
+
} catch (e: any) {
|
|
160
|
+
this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e}`)
|
|
161
|
+
}
|
|
170
162
|
|
|
171
|
-
//regisiter webhook event handler
|
|
172
|
-
|
|
173
|
-
|
|
163
|
+
// regisiter webhook event handler if enabled
|
|
164
|
+
try {
|
|
165
|
+
this.debugLog('Registering Webhook Event Handler')
|
|
166
|
+
this.registerWebhook()
|
|
167
|
+
} catch (e: any) {
|
|
168
|
+
this.errorLog(`failed to registerWebhook, Error: ${e}`)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// regisiter platform BLE event handler if enabled
|
|
172
|
+
try {
|
|
173
|
+
this.debugLog('Registering Platform BLE Event Handler')
|
|
174
|
+
this.registerPlatformBLE()
|
|
175
|
+
} catch (e: any) {
|
|
176
|
+
this.errorLog(`failed to registerPlatformBLE, Error: ${e}`)
|
|
177
|
+
}
|
|
174
178
|
|
|
175
179
|
// Start an update interval
|
|
176
180
|
interval(this.deviceRefreshRate * 1000)
|
|
177
181
|
.pipe(skipWhile(() => this.lockUpdateInProgress))
|
|
178
182
|
.subscribe(async () => {
|
|
179
|
-
await this.refreshStatus()
|
|
180
|
-
})
|
|
183
|
+
await this.refreshStatus()
|
|
184
|
+
})
|
|
181
185
|
|
|
182
186
|
// Watch for Lock change events
|
|
183
187
|
// We put in a debounce of 100ms so we don't make duplicate calls
|
|
184
188
|
this.doLockUpdate
|
|
185
189
|
.pipe(
|
|
186
190
|
tap(() => {
|
|
187
|
-
this.lockUpdateInProgress = true
|
|
191
|
+
this.lockUpdateInProgress = true
|
|
188
192
|
}),
|
|
189
193
|
debounceTime(this.devicePushRate * 1000),
|
|
190
194
|
)
|
|
191
195
|
.subscribe(async () => {
|
|
192
196
|
try {
|
|
193
|
-
await this.pushChanges()
|
|
197
|
+
await this.pushChanges()
|
|
194
198
|
} catch (e: any) {
|
|
195
|
-
await this.apiError(e)
|
|
196
|
-
await this.errorLog(`failed pushChanges with ${device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
199
|
+
await this.apiError(e)
|
|
200
|
+
await this.errorLog(`failed pushChanges with ${device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
197
201
|
}
|
|
198
|
-
this.lockUpdateInProgress = false
|
|
199
|
-
})
|
|
202
|
+
this.lockUpdateInProgress = false
|
|
203
|
+
})
|
|
200
204
|
}
|
|
201
205
|
|
|
202
206
|
async BLEparseStatus(): Promise<void> {
|
|
203
|
-
await this.debugLog('BLEparseStatus')
|
|
204
|
-
await this.debugLog(`(lockState) = BLE:(${this.serviceData.status}), current:(${this.LockMechanism.LockCurrentState})`)
|
|
207
|
+
await this.debugLog('BLEparseStatus')
|
|
208
|
+
await this.debugLog(`(lockState) = BLE:(${this.serviceData.status}), current:(${this.LockMechanism.LockCurrentState})`)
|
|
205
209
|
|
|
206
210
|
// LockCurrentState
|
|
207
211
|
this.LockMechanism.LockCurrentState = this.serviceData.status === 'locked'
|
|
208
|
-
? this.hap.Characteristic.LockCurrentState.SECURED
|
|
209
|
-
|
|
212
|
+
? this.hap.Characteristic.LockCurrentState.SECURED
|
|
213
|
+
: this.hap.Characteristic.LockCurrentState.UNSECURED
|
|
214
|
+
await this.debugLog(`LockCurrentState: ${this.LockMechanism.LockCurrentState}`)
|
|
210
215
|
|
|
211
216
|
// LockTargetState
|
|
212
217
|
this.LockMechanism.LockTargetState = this.serviceData.status === 'locked'
|
|
213
|
-
? this.hap.Characteristic.LockTargetState.SECURED
|
|
214
|
-
|
|
218
|
+
? this.hap.Characteristic.LockTargetState.SECURED
|
|
219
|
+
: this.hap.Characteristic.LockTargetState.UNSECURED
|
|
220
|
+
await this.debugLog(`LockTargetState: ${this.LockMechanism.LockTargetState}`)
|
|
215
221
|
|
|
216
222
|
// Contact Sensor
|
|
217
223
|
if (!this.device.lock?.hide_contactsensor && this.ContactSensor?.Service) {
|
|
218
224
|
this.ContactSensor.ContactSensorState = this.serviceData.door_open === 'opened'
|
|
219
|
-
? this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
|
|
220
|
-
|
|
225
|
+
? this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
|
|
226
|
+
: this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED
|
|
227
|
+
await this.debugLog(`ContactSensorState: ${this.ContactSensor.ContactSensorState}`)
|
|
221
228
|
}
|
|
222
229
|
|
|
223
230
|
// BatteryLevel
|
|
224
|
-
this.Battery.BatteryLevel = this.serviceData.battery
|
|
225
|
-
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
|
|
231
|
+
this.Battery.BatteryLevel = this.serviceData.battery
|
|
232
|
+
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
|
|
226
233
|
|
|
227
234
|
// StatusLowBattery
|
|
228
235
|
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
229
|
-
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
|
|
230
|
-
|
|
236
|
+
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
|
|
237
|
+
: this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
|
|
238
|
+
await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
|
|
231
239
|
}
|
|
232
240
|
|
|
233
241
|
async openAPIparseStatus(): Promise<void> {
|
|
234
|
-
await this.debugLog('openAPIparseStatus')
|
|
235
|
-
await this.debugLog(`(lockState) = OpenAPI:(${this.deviceStatus.lockState}), current:(${this.LockMechanism.LockCurrentState})`)
|
|
242
|
+
await this.debugLog('openAPIparseStatus')
|
|
243
|
+
await this.debugLog(`(lockState) = OpenAPI:(${this.deviceStatus.lockState}), current:(${this.LockMechanism.LockCurrentState})`)
|
|
236
244
|
|
|
237
245
|
// LockCurrentState
|
|
238
246
|
this.LockMechanism.LockCurrentState = this.deviceStatus.lockState === 'locked'
|
|
239
|
-
? this.hap.Characteristic.LockCurrentState.SECURED
|
|
240
|
-
|
|
247
|
+
? this.hap.Characteristic.LockCurrentState.SECURED
|
|
248
|
+
: this.hap.Characteristic.LockCurrentState.UNSECURED
|
|
249
|
+
await this.debugLog(`LockCurrentState: ${this.LockMechanism.LockCurrentState}`)
|
|
241
250
|
|
|
242
251
|
// LockTargetState
|
|
243
252
|
this.LockMechanism.LockTargetState = this.deviceStatus.lockState === 'locked'
|
|
244
|
-
? this.hap.Characteristic.LockTargetState.SECURED
|
|
245
|
-
|
|
253
|
+
? this.hap.Characteristic.LockTargetState.SECURED
|
|
254
|
+
: this.hap.Characteristic.LockTargetState.UNSECURED
|
|
255
|
+
await this.debugLog(`LockTargetState: ${this.LockMechanism.LockTargetState}`)
|
|
246
256
|
|
|
247
257
|
// ContactSensorState
|
|
248
258
|
if (!this.device.lock?.hide_contactsensor && this.ContactSensor?.Service) {
|
|
249
259
|
this.ContactSensor.ContactSensorState = this.deviceStatus.doorState === 'opened'
|
|
250
|
-
? this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
|
|
251
|
-
|
|
260
|
+
? this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
|
|
261
|
+
: this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED
|
|
262
|
+
await this.debugLog(`ContactSensorState: ${this.ContactSensor.ContactSensorState}`)
|
|
252
263
|
}
|
|
253
264
|
|
|
254
265
|
// BatteryLevel
|
|
255
|
-
this.Battery.BatteryLevel = this.deviceStatus.battery
|
|
256
|
-
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
|
|
266
|
+
this.Battery.BatteryLevel = this.deviceStatus.battery
|
|
267
|
+
await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
|
|
257
268
|
|
|
258
269
|
// StatusLowBattery
|
|
259
270
|
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
260
|
-
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
|
|
261
|
-
|
|
271
|
+
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
|
|
272
|
+
: this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
|
|
273
|
+
await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
|
|
262
274
|
|
|
263
275
|
// Firmware Version
|
|
264
276
|
if (this.deviceStatus.version) {
|
|
265
|
-
const version = this.deviceStatus.version.toString()
|
|
266
|
-
await this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`)
|
|
267
|
-
const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0'
|
|
277
|
+
const version = this.deviceStatus.version.toString()
|
|
278
|
+
await this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`)
|
|
279
|
+
const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0'
|
|
268
280
|
this.accessory
|
|
269
281
|
.getService(this.hap.Service.AccessoryInformation)!
|
|
270
282
|
.setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
|
|
271
283
|
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
272
284
|
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
273
|
-
.updateValue(deviceVersion)
|
|
274
|
-
this.accessory.context.version = deviceVersion
|
|
275
|
-
await this.debugSuccessLog(`version: ${this.accessory.context.version}`)
|
|
285
|
+
.updateValue(deviceVersion)
|
|
286
|
+
this.accessory.context.version = deviceVersion
|
|
287
|
+
await this.debugSuccessLog(`version: ${this.accessory.context.version}`)
|
|
276
288
|
}
|
|
277
289
|
}
|
|
278
290
|
|
|
279
291
|
async parseStatusWebhook(): Promise<void> {
|
|
280
|
-
await this.debugLog('parseStatusWebhook')
|
|
281
|
-
await this.debugLog(`(lockState) = Webhook:(${this.webhookContext.lockState}), current:(${this.LockMechanism.LockCurrentState})`)
|
|
292
|
+
await this.debugLog('parseStatusWebhook')
|
|
293
|
+
await this.debugLog(`(lockState) = Webhook:(${this.webhookContext.lockState}), current:(${this.LockMechanism.LockCurrentState})`)
|
|
282
294
|
|
|
283
295
|
// LockCurrentState
|
|
284
296
|
this.LockMechanism.LockCurrentState = this.webhookContext.lockState === 'LOCKED'
|
|
285
|
-
? this.hap.Characteristic.LockCurrentState.SECURED
|
|
286
|
-
|
|
297
|
+
? this.hap.Characteristic.LockCurrentState.SECURED
|
|
298
|
+
: this.hap.Characteristic.LockCurrentState.UNSECURED
|
|
299
|
+
await this.debugLog(`LockCurrentState: ${this.LockMechanism.LockCurrentState}`)
|
|
287
300
|
|
|
288
301
|
// LockTargetState
|
|
289
302
|
this.LockMechanism.LockTargetState = this.webhookContext.lockState === 'LOCKED'
|
|
290
|
-
? this.hap.Characteristic.LockTargetState.SECURED
|
|
291
|
-
|
|
303
|
+
? this.hap.Characteristic.LockTargetState.SECURED
|
|
304
|
+
: this.hap.Characteristic.LockTargetState.UNSECURED
|
|
305
|
+
await this.debugLog(`LockTargetState: ${this.LockMechanism.LockTargetState}`)
|
|
292
306
|
}
|
|
293
307
|
|
|
294
308
|
/**
|
|
@@ -296,128 +310,132 @@ export class Lock extends deviceBase {
|
|
|
296
310
|
*/
|
|
297
311
|
async refreshStatus(): Promise<void> {
|
|
298
312
|
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
299
|
-
await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`)
|
|
300
|
-
} else if (this.BLE
|
|
301
|
-
await this.BLERefreshStatus()
|
|
313
|
+
await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`)
|
|
314
|
+
} else if (this.BLE) {
|
|
315
|
+
await this.BLERefreshStatus()
|
|
302
316
|
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
303
|
-
await this.openAPIRefreshStatus()
|
|
317
|
+
await this.openAPIRefreshStatus()
|
|
304
318
|
} else {
|
|
305
|
-
await this.offlineOff()
|
|
306
|
-
await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`)
|
|
319
|
+
await this.offlineOff()
|
|
320
|
+
await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`)
|
|
307
321
|
}
|
|
308
322
|
}
|
|
309
323
|
|
|
310
324
|
async BLERefreshStatus(): Promise<void> {
|
|
311
|
-
await this.debugLog('BLERefreshStatus')
|
|
325
|
+
await this.debugLog('BLERefreshStatus')
|
|
326
|
+
const switchbot = await this.switchbotBLE()
|
|
327
|
+
if (switchbot === undefined) {
|
|
328
|
+
await this.BLERefreshConnection(switchbot)
|
|
329
|
+
} else {
|
|
330
|
+
// Start to monitor advertisement packets
|
|
331
|
+
(async () => {
|
|
332
|
+
// Start to monitor advertisement packets
|
|
333
|
+
const serviceData = await this.monitorAdvertisementPackets(switchbot) as lockServiceData | lockProServiceData
|
|
334
|
+
// Update HomeKit
|
|
335
|
+
if ((serviceData.model === SwitchBotBLEModel.Lock || SwitchBotBLEModel.LockPro)
|
|
336
|
+
&& (serviceData.modelName === SwitchBotBLEModelName.Lock || SwitchBotBLEModelName.LockPro)) {
|
|
337
|
+
this.serviceData = serviceData
|
|
338
|
+
await this.BLEparseStatus()
|
|
339
|
+
await this.updateHomeKitCharacteristics()
|
|
340
|
+
} else {
|
|
341
|
+
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`)
|
|
342
|
+
await this.BLERefreshConnection(switchbot)
|
|
343
|
+
}
|
|
344
|
+
})()
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async registerPlatformBLE(): Promise<void> {
|
|
349
|
+
await this.debugLog('registerPlatformBLE')
|
|
312
350
|
if (this.config.options?.BLE) {
|
|
313
|
-
await this.debugLog('is listening to Platform BLE.')
|
|
314
|
-
this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase()
|
|
315
|
-
await this.debugLog(`bleMac: ${this.device.bleMac}`)
|
|
351
|
+
await this.debugLog('is listening to Platform BLE.')
|
|
352
|
+
this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase()
|
|
353
|
+
await this.debugLog(`bleMac: ${this.device.bleMac}`)
|
|
316
354
|
this.platform.bleEventHandler[this.device.bleMac] = async (context: lockServiceData | lockProServiceData) => {
|
|
317
355
|
try {
|
|
318
|
-
await this.debugLog(`received BLE: ${JSON.stringify(context)}`)
|
|
319
|
-
this.serviceData = context
|
|
320
|
-
await this.BLEparseStatus()
|
|
321
|
-
await this.updateHomeKitCharacteristics()
|
|
356
|
+
await this.debugLog(`received BLE: ${JSON.stringify(context)}`)
|
|
357
|
+
this.serviceData = context
|
|
358
|
+
await this.BLEparseStatus()
|
|
359
|
+
await this.updateHomeKitCharacteristics()
|
|
322
360
|
} catch (e: any) {
|
|
323
|
-
await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`)
|
|
361
|
+
await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`)
|
|
324
362
|
}
|
|
325
|
-
};
|
|
326
|
-
} else {
|
|
327
|
-
await this.debugLog('is using Device BLE Scanning.');
|
|
328
|
-
const switchbot = await this.switchbotBLE();
|
|
329
|
-
if (switchbot === undefined) {
|
|
330
|
-
await this.BLERefreshConnection(switchbot);
|
|
331
|
-
} else {
|
|
332
|
-
// Start to monitor advertisement packets
|
|
333
|
-
(async () => {
|
|
334
|
-
// Start to monitor advertisement packets
|
|
335
|
-
const serviceData = await this.monitorAdvertisementPackets(switchbot) as lockServiceData | lockProServiceData;
|
|
336
|
-
// Update HomeKit
|
|
337
|
-
if ((serviceData.model === SwitchBotBLEModel.Lock || SwitchBotBLEModel.LockPro)
|
|
338
|
-
&& (serviceData.modelName === SwitchBotBLEModelName.Lock || SwitchBotBLEModelName.LockPro)) {
|
|
339
|
-
this.serviceData = serviceData;
|
|
340
|
-
await this.BLEparseStatus();
|
|
341
|
-
await this.updateHomeKitCharacteristics();
|
|
342
|
-
} else {
|
|
343
|
-
await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
|
|
344
|
-
await this.BLERefreshConnection(switchbot);
|
|
345
|
-
}
|
|
346
|
-
})();
|
|
347
363
|
}
|
|
364
|
+
} else {
|
|
365
|
+
await this.debugLog('is not listening to Platform BLE')
|
|
348
366
|
}
|
|
349
367
|
}
|
|
350
368
|
|
|
351
369
|
async openAPIRefreshStatus(): Promise<void> {
|
|
352
|
-
await this.debugLog('openAPIRefreshStatus')
|
|
370
|
+
await this.debugLog('openAPIRefreshStatus')
|
|
353
371
|
try {
|
|
354
|
-
const { body, statusCode } = await this.deviceRefreshStatus()
|
|
355
|
-
const deviceStatus: any = await body.json()
|
|
356
|
-
await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
372
|
+
const { body, statusCode } = await this.deviceRefreshStatus()
|
|
373
|
+
const deviceStatus: any = await body.json()
|
|
374
|
+
await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
357
375
|
if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
|
|
358
|
-
await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
359
|
-
this.deviceStatus = deviceStatus.body
|
|
360
|
-
await this.openAPIparseStatus()
|
|
361
|
-
await this.updateHomeKitCharacteristics()
|
|
376
|
+
await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
377
|
+
this.deviceStatus = deviceStatus.body
|
|
378
|
+
await this.openAPIparseStatus()
|
|
379
|
+
await this.updateHomeKitCharacteristics()
|
|
362
380
|
} else {
|
|
363
|
-
await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
364
|
-
await this.debugWarnLog(statusCode, deviceStatus)
|
|
381
|
+
await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
382
|
+
await this.debugWarnLog(statusCode, deviceStatus)
|
|
365
383
|
}
|
|
366
384
|
} catch (e: any) {
|
|
367
|
-
await this.apiError(e)
|
|
368
|
-
await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
385
|
+
await this.apiError(e)
|
|
386
|
+
await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
369
387
|
}
|
|
370
388
|
}
|
|
371
389
|
|
|
372
390
|
async registerWebhook() {
|
|
373
391
|
if (this.device.webhook) {
|
|
374
|
-
await this.debugLog('is listening webhook.')
|
|
392
|
+
await this.debugLog('is listening webhook.')
|
|
375
393
|
this.platform.webhookEventHandler[this.device.deviceId] = async (context: lockWebhookContext | lockProWebhookContext) => {
|
|
376
394
|
try {
|
|
377
|
-
await this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
|
|
378
|
-
this.webhookContext = context
|
|
379
|
-
await this.parseStatusWebhook()
|
|
380
|
-
await this.updateHomeKitCharacteristics()
|
|
395
|
+
await this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
|
|
396
|
+
this.webhookContext = context
|
|
397
|
+
await this.parseStatusWebhook()
|
|
398
|
+
await this.updateHomeKitCharacteristics()
|
|
381
399
|
} catch (e: any) {
|
|
382
|
-
await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`)
|
|
400
|
+
await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`)
|
|
383
401
|
}
|
|
384
|
-
}
|
|
402
|
+
}
|
|
385
403
|
} else {
|
|
386
|
-
await this.debugLog('is not listening webhook.')
|
|
404
|
+
await this.debugLog('is not listening webhook.')
|
|
387
405
|
}
|
|
388
406
|
}
|
|
389
407
|
|
|
390
408
|
/**
|
|
391
409
|
* Pushes the requested changes to the SwitchBot API
|
|
392
|
-
* deviceType
|
|
393
|
-
* Lock - "command" "lock" "default"
|
|
394
|
-
* Lock - "command" "unlock" "default"
|
|
410
|
+
* deviceType commandType Command command parameter Description
|
|
411
|
+
* Lock - "command" "lock" "default" = set to ???? state
|
|
412
|
+
* Lock - "command" "unlock" "default" = set to ???? state - LockCurrentState
|
|
395
413
|
*/
|
|
396
414
|
async pushChanges(): Promise<void> {
|
|
397
415
|
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
398
|
-
await this.errorLog(`pushChanges enableCloudService: ${this.device.enableCloudService}`)
|
|
416
|
+
await this.errorLog(`pushChanges enableCloudService: ${this.device.enableCloudService}`)
|
|
399
417
|
} else if (this.BLE) {
|
|
400
|
-
await this.BLEpushChanges()
|
|
418
|
+
await this.BLEpushChanges()
|
|
401
419
|
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
402
|
-
await this.openAPIpushChanges()
|
|
420
|
+
await this.openAPIpushChanges()
|
|
403
421
|
} else {
|
|
404
|
-
await this.offlineOff()
|
|
405
|
-
await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, pushChanges will not happen.`)
|
|
422
|
+
await this.offlineOff()
|
|
423
|
+
await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, pushChanges will not happen.`)
|
|
406
424
|
}
|
|
407
425
|
// Refresh the status from the API
|
|
408
426
|
interval(15000)
|
|
409
427
|
.pipe(skipWhile(() => this.lockUpdateInProgress))
|
|
410
428
|
.pipe(take(1))
|
|
411
429
|
.subscribe(async () => {
|
|
412
|
-
await this.refreshStatus()
|
|
413
|
-
})
|
|
430
|
+
await this.refreshStatus()
|
|
431
|
+
})
|
|
414
432
|
}
|
|
415
433
|
|
|
416
434
|
async BLEpushChanges(): Promise<void> {
|
|
417
|
-
await this.debugLog('BLEpushChanges')
|
|
435
|
+
await this.debugLog('BLEpushChanges')
|
|
418
436
|
if (this.LockMechanism.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
419
|
-
const switchbot = await this.platform.connectBLE(this.accessory, this.device)
|
|
420
|
-
await this.convertBLEAddress()
|
|
437
|
+
const switchbot = await this.platform.connectBLE(this.accessory, this.device)
|
|
438
|
+
await this.convertBLEAddress()
|
|
421
439
|
if (switchbot !== false) {
|
|
422
440
|
switchbot
|
|
423
441
|
.discover({ model: this.device.bleModel, id: this.device.bleMac })
|
|
@@ -426,61 +444,59 @@ export class Lock extends deviceBase {
|
|
|
426
444
|
max: await this.maxRetryBLE(),
|
|
427
445
|
fn: async () => {
|
|
428
446
|
if (this.LockMechanism.LockTargetState === this.hap.Characteristic.LockTargetState.SECURED) {
|
|
429
|
-
return await device_list[0].lock({ id: this.device.bleMac })
|
|
447
|
+
return await device_list[0].lock({ id: this.device.bleMac })
|
|
430
448
|
} else {
|
|
431
|
-
return await device_list[0].unlock({ id: this.device.bleMac })
|
|
449
|
+
return await device_list[0].unlock({ id: this.device.bleMac })
|
|
432
450
|
}
|
|
433
451
|
},
|
|
434
|
-
})
|
|
452
|
+
})
|
|
435
453
|
})
|
|
436
454
|
.then(async () => {
|
|
437
|
-
await this.successLog(`LockTargetState: ${this.LockMechanism.LockTargetState} sent over SwitchBot BLE, sent successfully`)
|
|
438
|
-
await this.updateHomeKitCharacteristics()
|
|
455
|
+
await this.successLog(`LockTargetState: ${this.LockMechanism.LockTargetState} sent over SwitchBot BLE, sent successfully`)
|
|
456
|
+
await this.updateHomeKitCharacteristics()
|
|
439
457
|
})
|
|
440
458
|
.catch(async (e: any) => {
|
|
441
|
-
await this.apiError(e)
|
|
442
|
-
await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
443
|
-
await this.BLEPushConnection()
|
|
444
|
-
})
|
|
459
|
+
await this.apiError(e)
|
|
460
|
+
await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
461
|
+
await this.BLEPushConnection()
|
|
462
|
+
})
|
|
445
463
|
} else {
|
|
446
|
-
await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
|
|
447
|
-
await this.BLEPushConnection()
|
|
464
|
+
await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
|
|
465
|
+
await this.BLEPushConnection()
|
|
448
466
|
}
|
|
449
467
|
} else {
|
|
450
|
-
await this.debugLog(`No changes (BLEpushChanges), LockTargetState: ${this.LockMechanism.LockTargetState}
|
|
451
|
-
+ ` LockCurrentState: ${this.LockMechanism.LockCurrentState}`);
|
|
468
|
+
await this.debugLog(`No changes (BLEpushChanges), LockTargetState: ${this.LockMechanism.LockTargetState}, LockCurrentState: ${this.LockMechanism.LockCurrentState}`)
|
|
452
469
|
}
|
|
453
470
|
}
|
|
454
471
|
|
|
455
472
|
async openAPIpushChanges(LatchUnlock?: boolean): Promise<void> {
|
|
456
|
-
await this.debugLog('openAPIpushChanges')
|
|
473
|
+
await this.debugLog('openAPIpushChanges')
|
|
457
474
|
if ((this.LockMechanism.LockTargetState !== this.accessory.context.LockTargetState) || LatchUnlock) {
|
|
458
475
|
// Determine the command based on the LockTargetState or the forceUnlock parameter
|
|
459
|
-
const command = LatchUnlock ? 'unlock' : this.LockMechanism.LockTargetState ? 'lock' : 'unlock'
|
|
476
|
+
const command = LatchUnlock ? 'unlock' : this.LockMechanism.LockTargetState ? 'lock' : 'unlock'
|
|
460
477
|
const bodyChange = JSON.stringify({
|
|
461
478
|
command: `${command}`,
|
|
462
479
|
parameter: 'default',
|
|
463
480
|
commandType: 'command',
|
|
464
|
-
})
|
|
465
|
-
await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`)
|
|
481
|
+
})
|
|
482
|
+
await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`)
|
|
466
483
|
try {
|
|
467
|
-
const { body, statusCode } = await this.pushChangeRequest(bodyChange)
|
|
468
|
-
const deviceStatus: any = await body.json()
|
|
469
|
-
await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
484
|
+
const { body, statusCode } = await this.pushChangeRequest(bodyChange)
|
|
485
|
+
const deviceStatus: any = await body.json()
|
|
486
|
+
await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
470
487
|
if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
|
|
471
|
-
await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
472
|
-
await this.updateHomeKitCharacteristics()
|
|
488
|
+
await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
489
|
+
await this.updateHomeKitCharacteristics()
|
|
473
490
|
} else {
|
|
474
|
-
await this.statusCode(statusCode)
|
|
475
|
-
await this.statusCode(deviceStatus.statusCode)
|
|
491
|
+
await this.statusCode(statusCode)
|
|
492
|
+
await this.statusCode(deviceStatus.statusCode)
|
|
476
493
|
}
|
|
477
494
|
} catch (e: any) {
|
|
478
|
-
await this.apiError(e)
|
|
479
|
-
await this.errorLog(`failed openAPIpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
495
|
+
await this.apiError(e)
|
|
496
|
+
await this.errorLog(`failed openAPIpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
480
497
|
}
|
|
481
498
|
} else {
|
|
482
|
-
await this.debugLog(`No changes (openAPIpushChanges), LockCurrentState: ${this.LockMechanism.LockCurrentState}
|
|
483
|
-
+ ` TargetPosition: ${this.LockMechanism.LockTargetState}`);
|
|
499
|
+
await this.debugLog(`No changes (openAPIpushChanges), LockCurrentState: ${this.LockMechanism.LockCurrentState}, TargetPosition: ${this.LockMechanism.LockTargetState}`)
|
|
484
500
|
}
|
|
485
501
|
}
|
|
486
502
|
|
|
@@ -489,106 +505,100 @@ export class Lock extends deviceBase {
|
|
|
489
505
|
*/
|
|
490
506
|
async LockTargetStateSet(value: CharacteristicValue): Promise<void> {
|
|
491
507
|
if (this.LockMechanism.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
492
|
-
await this.infoLog(`Set LockTargetState: ${value}`)
|
|
508
|
+
await this.infoLog(`Set LockTargetState: ${value}`)
|
|
493
509
|
} else {
|
|
494
|
-
await this.debugLog(`No Changes, LockTargetState: ${value}`)
|
|
510
|
+
await this.debugLog(`No Changes, LockTargetState: ${value}`)
|
|
495
511
|
}
|
|
496
512
|
|
|
497
|
-
this.LockMechanism.LockTargetState = value
|
|
498
|
-
this.doLockUpdate.next()
|
|
513
|
+
this.LockMechanism.LockTargetState = value
|
|
514
|
+
this.doLockUpdate.next()
|
|
499
515
|
}
|
|
500
516
|
|
|
501
517
|
/**
|
|
502
518
|
* Handle requests to set the value of the "On" characteristic
|
|
503
519
|
*/
|
|
504
520
|
async OnSet(value: CharacteristicValue): Promise<void> {
|
|
505
|
-
await this.debugLog(`Latch Button Set On: ${value}`)
|
|
521
|
+
await this.debugLog(`Latch Button Set On: ${value}`)
|
|
506
522
|
if (value) {
|
|
507
|
-
await this.debugLog('Attempting to open the latch')
|
|
523
|
+
await this.debugLog('Attempting to open the latch')
|
|
508
524
|
|
|
509
525
|
this.openAPIpushChanges(value as boolean).then(async () => {
|
|
510
|
-
await this.debugLog('Latch opened successfully')
|
|
511
|
-
await this.debugLog(`SwitchService is: ${this.Switch?.Service ? 'available' : 'not available'}`)
|
|
526
|
+
await this.debugLog('Latch opened successfully')
|
|
527
|
+
await this.debugLog(`SwitchService is: ${this.Switch?.Service ? 'available' : 'not available'}`)
|
|
512
528
|
|
|
513
529
|
// simulate button press to turn the switch back off
|
|
514
530
|
if (this.Switch?.Service) {
|
|
515
|
-
const SwitchService = this.Switch.Service
|
|
531
|
+
const SwitchService = this.Switch.Service
|
|
516
532
|
// Simulate a button press by waiting a short period before turning the switch off
|
|
517
|
-
setTimeout(async() => {
|
|
518
|
-
SwitchService.getCharacteristic(this.hap.Characteristic.On).updateValue(false)
|
|
519
|
-
await this.debugLog('Latch button switched off automatically.')
|
|
520
|
-
}, 500)
|
|
533
|
+
setTimeout(async () => {
|
|
534
|
+
SwitchService.getCharacteristic(this.hap.Characteristic.On).updateValue(false)
|
|
535
|
+
await this.debugLog('Latch button switched off automatically.')
|
|
536
|
+
}, 500) // 500 ms delay
|
|
521
537
|
}
|
|
522
538
|
}).catch(async (e: any) => {
|
|
523
539
|
// Log the error if the operation failed
|
|
524
|
-
await this.debugLog(`Error opening latch: ${e}`)
|
|
540
|
+
await this.debugLog(`Error opening latch: ${e}`)
|
|
525
541
|
// Ensure we turn the switch back off even in case of an error
|
|
526
542
|
if (this.Switch?.Service) {
|
|
527
|
-
this.Switch.Service.getCharacteristic(this.hap.Characteristic.On).updateValue(false)
|
|
528
|
-
await this.debugLog('Latch button switched off after an error.')
|
|
543
|
+
this.Switch.Service.getCharacteristic(this.hap.Characteristic.On).updateValue(false)
|
|
544
|
+
await this.debugLog('Latch button switched off after an error.')
|
|
529
545
|
}
|
|
530
|
-
})
|
|
546
|
+
})
|
|
531
547
|
} else {
|
|
532
|
-
await this.debugLog('Switch is off, nothing to do')
|
|
548
|
+
await this.debugLog('Switch is off, nothing to do')
|
|
533
549
|
}
|
|
534
550
|
|
|
535
|
-
this.Switch!.On = value
|
|
536
|
-
this.doLockUpdate.next()
|
|
551
|
+
this.Switch!.On = value
|
|
552
|
+
this.doLockUpdate.next()
|
|
537
553
|
}
|
|
538
554
|
|
|
539
555
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
540
556
|
// LockCurrentState
|
|
541
|
-
await this.updateCharacteristic(this.LockMechanism.Service, this.hap.Characteristic.LockTargetState,
|
|
542
|
-
this.LockMechanism.LockTargetState, 'LockTargetState');
|
|
557
|
+
await this.updateCharacteristic(this.LockMechanism.Service, this.hap.Characteristic.LockTargetState, this.LockMechanism.LockTargetState, 'LockTargetState')
|
|
543
558
|
// LockCurrentState
|
|
544
|
-
await this.updateCharacteristic(this.LockMechanism.Service, this.hap.Characteristic.LockCurrentState,
|
|
545
|
-
this.LockMechanism.LockCurrentState, 'LockCurrentState');
|
|
559
|
+
await this.updateCharacteristic(this.LockMechanism.Service, this.hap.Characteristic.LockCurrentState, this.LockMechanism.LockCurrentState, 'LockCurrentState')
|
|
546
560
|
// ContactSensorState
|
|
547
561
|
if (!this.device.lock?.hide_contactsensor && this.ContactSensor?.Service) {
|
|
548
|
-
await this.updateCharacteristic(this.ContactSensor.Service, this.hap.Characteristic.ContactSensorState,
|
|
549
|
-
this.ContactSensor.ContactSensorState, 'ContactSensorState');
|
|
562
|
+
await this.updateCharacteristic(this.ContactSensor.Service, this.hap.Characteristic.ContactSensorState, this.ContactSensor.ContactSensorState, 'ContactSensorState')
|
|
550
563
|
}
|
|
551
564
|
// BatteryLevel
|
|
552
|
-
await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel,
|
|
553
|
-
this.Battery.BatteryLevel, 'BatteryLevel');
|
|
565
|
+
await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel, 'BatteryLevel')
|
|
554
566
|
// StatusLowBattery
|
|
555
|
-
await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery,
|
|
556
|
-
this.Battery.StatusLowBattery, 'StatusLowBattery');
|
|
567
|
+
await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery, 'StatusLowBattery')
|
|
557
568
|
}
|
|
558
569
|
|
|
559
570
|
async BLEPushConnection() {
|
|
560
571
|
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
561
|
-
await this.warnLog('Using OpenAPI Connection to Push Changes')
|
|
562
|
-
await this.openAPIpushChanges()
|
|
572
|
+
await this.warnLog('Using OpenAPI Connection to Push Changes')
|
|
573
|
+
await this.openAPIpushChanges()
|
|
563
574
|
}
|
|
564
575
|
}
|
|
565
576
|
|
|
566
577
|
async BLERefreshConnection(switchbot: any): Promise<void> {
|
|
567
|
-
await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
|
|
578
|
+
await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
|
|
568
579
|
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
569
|
-
await this.warnLog('Using OpenAPI Connection to Refresh Status')
|
|
570
|
-
await this.openAPIRefreshStatus()
|
|
580
|
+
await this.warnLog('Using OpenAPI Connection to Refresh Status')
|
|
581
|
+
await this.openAPIRefreshStatus()
|
|
571
582
|
}
|
|
572
583
|
}
|
|
573
584
|
|
|
574
585
|
async offlineOff(): Promise<void> {
|
|
575
586
|
if (this.device.offline) {
|
|
576
|
-
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED)
|
|
577
|
-
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED)
|
|
587
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED)
|
|
588
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED)
|
|
578
589
|
if (!this.device.lock?.hide_contactsensor && this.ContactSensor?.Service) {
|
|
579
|
-
this.ContactSensor.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState,
|
|
580
|
-
this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED);
|
|
590
|
+
this.ContactSensor.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState, this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED)
|
|
581
591
|
}
|
|
582
592
|
}
|
|
583
593
|
}
|
|
584
594
|
|
|
585
595
|
async apiError(e: any): Promise<void> {
|
|
586
|
-
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, e)
|
|
587
|
-
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e)
|
|
596
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, e)
|
|
597
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e)
|
|
588
598
|
if (!this.device.lock?.hide_contactsensor && this.ContactSensor?.Service) {
|
|
589
|
-
this.ContactSensor.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState, e)
|
|
599
|
+
this.ContactSensor.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState, e)
|
|
590
600
|
}
|
|
591
|
-
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e)
|
|
592
|
-
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e)
|
|
601
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e)
|
|
602
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e)
|
|
593
603
|
}
|
|
594
604
|
}
|