@switchbot/homebridge-switchbot 3.5.0-beta.9 → 3.5.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/.vscode/settings.json +4 -1
- package/CHANGELOG.md +4 -1
- package/config.schema.json +164 -22
- package/dist/device/blindtilt.d.ts +21 -96
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +457 -866
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +27 -72
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +851 -913
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +15 -69
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +316 -742
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +15 -76
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +380 -833
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +14 -66
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +267 -602
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +18 -89
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +469 -897
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +76 -0
- package/dist/device/device.d.ts.map +1 -0
- package/dist/device/device.js +846 -0
- package/dist/device/device.js.map +1 -0
- package/dist/device/fan.d.ts +63 -0
- package/dist/device/fan.d.ts.map +1 -0
- package/dist/device/fan.js +645 -0
- package/dist/device/fan.js.map +1 -0
- package/dist/device/hub.d.ts +19 -58
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +304 -640
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +11 -66
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +300 -710
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +12 -64
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +225 -643
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +12 -70
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +371 -742
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +17 -63
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +309 -642
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +15 -64
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +223 -638
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +15 -65
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +216 -644
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +12 -69
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +209 -588
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +10 -57
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +141 -532
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +13 -63
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +252 -609
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +11 -63
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +179 -521
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +22 -16
- package/dist/homebridge-ui/server.js +1 -1
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +10 -50
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +337 -482
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +8 -39
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +108 -333
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +7 -36
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +47 -299
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +7 -43
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +95 -364
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +46 -0
- package/dist/irdevice/irdevice.d.ts.map +1 -0
- package/dist/irdevice/irdevice.js +393 -0
- package/dist/irdevice/irdevice.js.map +1 -0
- package/dist/irdevice/light.d.ts +12 -45
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +121 -376
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +19 -48
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +441 -584
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +8 -40
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +94 -353
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -36
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +48 -299
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +7 -36
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +50 -305
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +22 -8
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +342 -191
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +66 -18
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +16 -552
- package/dist/settings.js.map +1 -1
- package/dist/utils.d.ts +95 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +657 -1
- package/dist/utils.js.map +1 -1
- package/eslint.config.js +96 -0
- package/package.json +20 -16
- package/src/custom.d.ts +2 -1
- package/src/device/blindtilt.ts +488 -937
- package/src/device/bot.ts +907 -1016
- package/src/device/ceilinglight.ts +330 -798
- package/src/device/colorbulb.ts +394 -904
- package/src/device/contact.ts +298 -637
- package/src/device/curtain.ts +496 -954
- package/src/device/device.ts +872 -0
- package/src/device/fan.ts +692 -0
- package/src/device/hub.ts +338 -671
- package/src/device/humidifier.ts +330 -777
- package/src/device/iosensor.ts +258 -671
- package/src/device/lightstrip.ts +394 -809
- package/src/device/lock.ts +345 -700
- package/src/device/meter.ts +256 -666
- package/src/device/meterplus.ts +248 -672
- package/src/device/motion.ts +234 -622
- package/src/device/plug.ts +152 -572
- package/src/device/robotvacuumcleaner.ts +273 -653
- package/src/device/waterdetector.ts +198 -549
- package/src/homebridge-ui/public/index.html +22 -16
- package/src/homebridge-ui/server.ts +1 -1
- package/src/index.ts +4 -3
- package/src/irdevice/airconditioner.ts +368 -540
- package/src/irdevice/airpurifier.ts +134 -369
- package/src/irdevice/camera.ts +60 -324
- package/src/irdevice/fan.ts +111 -392
- package/src/irdevice/irdevice.ts +406 -0
- package/src/irdevice/light.ts +159 -425
- package/src/irdevice/other.ts +509 -661
- package/src/irdevice/tv.ts +123 -388
- package/src/irdevice/vacuumcleaner.ts +61 -324
- package/src/irdevice/waterheater.ts +63 -333
- package/src/platform.ts +395 -259
- package/src/settings.ts +120 -610
- package/src/utils.ts +661 -1
- package/src/device/waterdetector.json +0 -11
package/src/device/lock.ts
CHANGED
|
@@ -1,174 +1,155 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* lock.ts: @switchbot/homebridge-switchbot.
|
|
4
|
+
*/
|
|
5
|
+
import { deviceBase } from './device.js';
|
|
3
6
|
import { interval, Subject } from 'rxjs';
|
|
4
|
-
import { SwitchBotPlatform } from '../platform.js';
|
|
5
7
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
public readonly config!: SwitchBotPlatformConfig;
|
|
13
|
-
protected readonly hap: HAP;
|
|
8
|
+
|
|
9
|
+
import type { SwitchBotPlatform } from '../platform.js';
|
|
10
|
+
import type { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
11
|
+
import type { device, devicesConfig, serviceData, deviceStatus } from '../settings.js';
|
|
12
|
+
|
|
13
|
+
export class Lock extends deviceBase {
|
|
14
14
|
// Services
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// BLE Others
|
|
41
|
-
BLE_IsConnected?: boolean;
|
|
42
|
-
|
|
43
|
-
// Config
|
|
44
|
-
scanDuration!: number;
|
|
45
|
-
deviceLogging!: string;
|
|
46
|
-
deviceRefreshRate!: number;
|
|
15
|
+
private LockMechanism: {
|
|
16
|
+
Name: CharacteristicValue;
|
|
17
|
+
Service: Service;
|
|
18
|
+
LockTargetState: CharacteristicValue;
|
|
19
|
+
LockCurrentState: CharacteristicValue;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
private Battery: {
|
|
23
|
+
Name: CharacteristicValue;
|
|
24
|
+
Service: Service;
|
|
25
|
+
BatteryLevel: CharacteristicValue;
|
|
26
|
+
StatusLowBattery: CharacteristicValue;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
private ContactSensor?: {
|
|
30
|
+
Name: CharacteristicValue;
|
|
31
|
+
Service: Service;
|
|
32
|
+
ContactSensorState: CharacteristicValue;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
private Switch?: {
|
|
36
|
+
Name: CharacteristicValue;
|
|
37
|
+
Service: Service;
|
|
38
|
+
On: CharacteristicValue;
|
|
39
|
+
};
|
|
47
40
|
|
|
48
41
|
// Updates
|
|
49
42
|
lockUpdateInProgress!: boolean;
|
|
50
43
|
doLockUpdate!: Subject<void>;
|
|
51
44
|
|
|
52
|
-
// Connection
|
|
53
|
-
private readonly OpenAPI: boolean;
|
|
54
|
-
private readonly BLE: boolean;
|
|
55
|
-
|
|
56
45
|
constructor(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
46
|
+
readonly platform: SwitchBotPlatform,
|
|
47
|
+
accessory: PlatformAccessory,
|
|
48
|
+
device: device & devicesConfig,
|
|
60
49
|
) {
|
|
61
|
-
|
|
62
|
-
this.log = this.platform.log;
|
|
63
|
-
this.config = this.platform.config;
|
|
64
|
-
this.hap = this.api.hap;
|
|
65
|
-
// Connection
|
|
66
|
-
this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
|
|
67
|
-
this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
|
|
68
|
-
// default placeholders
|
|
69
|
-
this.deviceLogs(device);
|
|
70
|
-
this.scan(device);
|
|
71
|
-
this.refreshRate(device);
|
|
72
|
-
this.deviceContext();
|
|
73
|
-
this.deviceConfig(device);
|
|
74
|
-
|
|
50
|
+
super(platform, accessory, device);
|
|
75
51
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
76
52
|
this.doLockUpdate = new Subject();
|
|
77
53
|
this.lockUpdateInProgress = false;
|
|
78
54
|
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.
|
|
85
|
-
.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
} else
|
|
118
|
-
if (!this.latchButtonService) {
|
|
119
|
-
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Adding Latch Button Service`);
|
|
120
|
-
const latchServiceName = `${accessory.displayName} Latch`;
|
|
121
|
-
this.latchButtonService = accessory.getService(this.hap.Service.Switch)
|
|
122
|
-
|| accessory.addService(this.hap.Service.Switch, latchServiceName, 'LatchButtonServiceIdentifier');
|
|
123
|
-
|
|
124
|
-
this.latchButtonService.setCharacteristic(this.hap.Characteristic.Name, latchServiceName);
|
|
125
|
-
|
|
126
|
-
if (!this.latchButtonService.testCharacteristic(this.hap.Characteristic.On)) {
|
|
127
|
-
this.latchButtonService.addCharacteristic(this.hap.Characteristic.On);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
this.latchButtonService.getCharacteristic(this.hap.Characteristic.On)
|
|
131
|
-
.on('set', (value, callback) => {
|
|
132
|
-
if (typeof value === 'boolean') {
|
|
133
|
-
this.handleLatchCharacteristic(value, callback);
|
|
134
|
-
} else {
|
|
135
|
-
callback(new Error('Wrong characteristic value type'));
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
} else {
|
|
139
|
-
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Latch Button Service already exists`);
|
|
140
|
-
}
|
|
55
|
+
// Initialize LockMechanism Service
|
|
56
|
+
accessory.context.LockMechanism = accessory.context.LockMechanism ?? {};
|
|
57
|
+
this.LockMechanism = {
|
|
58
|
+
Name: accessory.context.LockMechanism.Name ?? accessory.displayName,
|
|
59
|
+
Service: accessory.getService(this.hap.Service.LockMechanism) ?? accessory.addService(this.hap.Service.LockMechanism) as Service,
|
|
60
|
+
LockTargetState: accessory.context.LockTargetState ?? this.hap.Characteristic.LockTargetState.SECURED,
|
|
61
|
+
LockCurrentState: accessory.context.LockCurrentState ?? this.hap.Characteristic.LockCurrentState.SECURED,
|
|
62
|
+
};
|
|
63
|
+
accessory.context.LockMechanism = this.LockMechanism as object;
|
|
64
|
+
|
|
65
|
+
// Initialize LockMechanism Characteristics
|
|
66
|
+
this.LockMechanism.Service
|
|
67
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.LockMechanism.Name)
|
|
68
|
+
.getCharacteristic(this.hap.Characteristic.LockTargetState)
|
|
69
|
+
.onGet(() => {
|
|
70
|
+
return this.LockMechanism.LockTargetState;
|
|
71
|
+
})
|
|
72
|
+
.onSet(this.LockTargetStateSet.bind(this));
|
|
73
|
+
|
|
74
|
+
// Initialize Battery property
|
|
75
|
+
accessory.context.Battery = accessory.context.Battery ?? {};
|
|
76
|
+
this.Battery = {
|
|
77
|
+
Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
|
|
78
|
+
Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
|
|
79
|
+
BatteryLevel: accessory.context.BatteryLevel ?? 100,
|
|
80
|
+
StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
|
|
81
|
+
};
|
|
82
|
+
accessory.context.Battery = this.Battery as object;
|
|
83
|
+
|
|
84
|
+
// Initialize Battery Characteristics
|
|
85
|
+
this.Battery.Service
|
|
86
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
|
|
87
|
+
.setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE)
|
|
88
|
+
.getCharacteristic(this.hap.Characteristic.BatteryLevel)
|
|
89
|
+
.onGet(() => {
|
|
90
|
+
return this.Battery.BatteryLevel;
|
|
91
|
+
});
|
|
141
92
|
|
|
93
|
+
this.Battery.Service
|
|
94
|
+
.getCharacteristic(this.hap.Characteristic.StatusLowBattery)
|
|
95
|
+
.onGet(() => {
|
|
96
|
+
return this.Battery.StatusLowBattery;
|
|
97
|
+
});
|
|
142
98
|
|
|
143
99
|
// Contact Sensor Service
|
|
144
100
|
if (device.lock?.hide_contactsensor) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Contact Sensor Service`);
|
|
150
|
-
const contactSensorService = `${accessory.displayName} Contact Sensor`;
|
|
151
|
-
(this.contactSensorService = this.accessory.getService(this.hap.Service.ContactSensor)
|
|
152
|
-
|| this.accessory.addService(this.hap.Service.ContactSensor)), contactSensorService;
|
|
153
|
-
|
|
154
|
-
this.contactSensorService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Contact Sensor`);
|
|
155
|
-
if (!this.contactSensorService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
156
|
-
this.contactSensorService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Contact Sensor`);
|
|
101
|
+
if (this.ContactSensor) {
|
|
102
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Contact Sensor Service`);
|
|
103
|
+
this.ContactSensor.Service = this.accessory.getService(this.hap.Service.ContactSensor) as Service;
|
|
104
|
+
accessory.removeService(this.ContactSensor.Service);
|
|
157
105
|
}
|
|
158
106
|
} else {
|
|
159
|
-
|
|
107
|
+
accessory.context.ContactSensor = accessory.context.ContactSensor ?? {};
|
|
108
|
+
this.ContactSensor = {
|
|
109
|
+
Name: accessory.context.ContactSensor.Name ?? `${accessory.displayName} Contact Sensor`,
|
|
110
|
+
Service: accessory.getService(this.hap.Service.ContactSensor) ?? this.accessory.addService(this.hap.Service.ContactSensor) as Service,
|
|
111
|
+
ContactSensorState: accessory.context.ContactSensorState ?? this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED,
|
|
112
|
+
};
|
|
113
|
+
accessory.context.ContactSensor = this.ContactSensor as object;
|
|
114
|
+
|
|
115
|
+
// Initialize Contact Sensor Characteristics
|
|
116
|
+
this.ContactSensor.Service
|
|
117
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.ContactSensor.Name)
|
|
118
|
+
.setCharacteristic(this.hap.Characteristic.StatusActive, true)
|
|
119
|
+
.getCharacteristic(this.hap.Characteristic.ContactSensorState)
|
|
120
|
+
.onGet(() => {
|
|
121
|
+
return this.ContactSensor!.ContactSensorState;
|
|
122
|
+
});
|
|
160
123
|
}
|
|
161
124
|
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
125
|
+
// Initialize Latch Button Service
|
|
126
|
+
if (device.lock?.activate_latchbutton === false) {
|
|
127
|
+
if (this.Switch) {
|
|
128
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Latch Button Service`);
|
|
129
|
+
this.Switch.Service = accessory.getService(this.hap.Service.Switch) as Service;
|
|
130
|
+
accessory.removeService(this.Switch.Service);
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
accessory.context.Switch = accessory.context.Switch ?? {};
|
|
134
|
+
this.Switch = {
|
|
135
|
+
Name: accessory.context.Switch.Name ?? `${accessory.displayName} Latch`,
|
|
136
|
+
Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch) as Service,
|
|
137
|
+
On: accessory.context.On ?? false,
|
|
138
|
+
};
|
|
139
|
+
accessory.context.Switch = this.Switch as object;
|
|
140
|
+
|
|
141
|
+
// Initialize Latch Button Characteristics
|
|
142
|
+
this.Switch.Service
|
|
143
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Switch.Name)
|
|
144
|
+
.getCharacteristic(this.hap.Characteristic.On)
|
|
145
|
+
.onGet(() => {
|
|
146
|
+
return this.Switch!.On;
|
|
147
|
+
})
|
|
148
|
+
.onSet(this.OnSet.bind(this));
|
|
170
149
|
}
|
|
171
|
-
|
|
150
|
+
|
|
151
|
+
// Retrieve initial values and updateHomekit
|
|
152
|
+
this.refreshStatus();
|
|
172
153
|
|
|
173
154
|
// Update Homekit
|
|
174
155
|
this.updateHomeKitCharacteristics();
|
|
@@ -181,25 +162,7 @@ export class Lock {
|
|
|
181
162
|
});
|
|
182
163
|
|
|
183
164
|
//regisiter webhook event handler
|
|
184
|
-
|
|
185
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
|
|
186
|
-
this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
|
|
187
|
-
try {
|
|
188
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
|
|
189
|
-
const { lockState } = context;
|
|
190
|
-
const { LockCurrentState } = this;
|
|
191
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
|
|
192
|
-
'(lockState) = ' +
|
|
193
|
-
`Webhook:(${lockState}), ` +
|
|
194
|
-
`current:(${LockCurrentState})`);
|
|
195
|
-
this.LockCurrentState = lockState === 'LOCKED' ? 1 : 0;
|
|
196
|
-
this.updateHomeKitCharacteristics();
|
|
197
|
-
} catch (e: any) {
|
|
198
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
199
|
-
+ `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
}
|
|
165
|
+
this.registerWebhook(accessory, device);
|
|
203
166
|
|
|
204
167
|
// Watch for Lock change events
|
|
205
168
|
// We put in a debounce of 100ms so we don't make duplicate calls
|
|
@@ -208,150 +171,105 @@ export class Lock {
|
|
|
208
171
|
tap(() => {
|
|
209
172
|
this.lockUpdateInProgress = true;
|
|
210
173
|
}),
|
|
211
|
-
debounceTime(this.
|
|
174
|
+
debounceTime(this.devicePushRate * 1000),
|
|
212
175
|
)
|
|
213
176
|
.subscribe(async () => {
|
|
214
177
|
try {
|
|
215
178
|
await this.pushChanges();
|
|
216
179
|
} catch (e: any) {
|
|
217
180
|
this.apiError(e);
|
|
218
|
-
this.errorLog(
|
|
219
|
-
|
|
220
|
-
` Error Message: ${JSON.stringify(e.message)}`,
|
|
221
|
-
);
|
|
181
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
|
|
182
|
+
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
222
183
|
}
|
|
223
184
|
this.lockUpdateInProgress = false;
|
|
224
185
|
});
|
|
225
186
|
}
|
|
226
187
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
*/
|
|
230
|
-
async handleLatchCharacteristic(value: boolean, callback) {
|
|
231
|
-
this.debugLog(`handleLatchCharacteristic called with value: ${value}`);
|
|
232
|
-
|
|
233
|
-
if (value) {
|
|
234
|
-
this.debugLog('Attempting to open the latch');
|
|
235
|
-
|
|
236
|
-
this.openAPIpushChanges(value).then(() => {
|
|
237
|
-
this.debugLog('Latch opened successfully');
|
|
238
|
-
this.debugLog(`LatchButtonService is: ${this.latchButtonService ? 'available' : 'not available'}`);
|
|
239
|
-
|
|
240
|
-
// simulate button press to turn the switch back off
|
|
241
|
-
if (this.latchButtonService) {
|
|
242
|
-
const latchButtonService = this.latchButtonService;
|
|
243
|
-
// Simulate a button press by waiting a short period before turning the switch off
|
|
244
|
-
setTimeout(() => {
|
|
245
|
-
latchButtonService.getCharacteristic(this.hap.Characteristic.On).updateValue(false);
|
|
246
|
-
this.debugLog('Latch button switched off automatically.');
|
|
247
|
-
}, 500); // 500 ms delay
|
|
248
|
-
}
|
|
249
|
-
callback(null);
|
|
250
|
-
}).catch((error) => {
|
|
251
|
-
// Log the error if the operation failed
|
|
252
|
-
this.debugLog(`Error opening latch: ${error}`);
|
|
253
|
-
|
|
254
|
-
// Ensure we turn the switch back off even in case of an error
|
|
255
|
-
if (this.latchButtonService) {
|
|
256
|
-
this.latchButtonService.getCharacteristic(this.hap.Characteristic.On).updateValue(false);
|
|
257
|
-
this.debugLog('Latch button switched off after an error.');
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
callback(error);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
} else {
|
|
264
|
-
this.debugLog('Switch is off, nothing to do');
|
|
265
|
-
callback(null);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Parse the device status from the SwitchBot api
|
|
272
|
-
*/
|
|
273
|
-
async parseStatus(): Promise<void> {
|
|
274
|
-
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
275
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
276
|
-
/* } else if (this.BLE) {
|
|
277
|
-
await this.BLEparseStatus();*/
|
|
278
|
-
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
279
|
-
await this.openAPIparseStatus();
|
|
280
|
-
} else {
|
|
281
|
-
await this.offlineOff();
|
|
282
|
-
this.debugWarnLog(
|
|
283
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`,
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
async BLEparseStatus(): Promise<void> {
|
|
188
|
+
async BLEparseStatus(serviceData: serviceData): Promise<void> {
|
|
189
|
+
// BLE Status
|
|
289
190
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
290
|
-
switch (
|
|
191
|
+
switch (serviceData.status) {
|
|
291
192
|
case 'locked':
|
|
292
|
-
this.LockCurrentState = this.hap.Characteristic.LockCurrentState.SECURED;
|
|
293
|
-
this.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
|
|
193
|
+
this.LockMechanism.LockCurrentState = this.hap.Characteristic.LockCurrentState.SECURED;
|
|
194
|
+
this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
|
|
294
195
|
break;
|
|
295
196
|
default:
|
|
296
|
-
this.LockCurrentState = this.hap.Characteristic.LockCurrentState.UNSECURED;
|
|
297
|
-
this.LockTargetState = this.hap.Characteristic.LockTargetState.UNSECURED;
|
|
197
|
+
this.LockMechanism.LockCurrentState = this.hap.Characteristic.LockCurrentState.UNSECURED;
|
|
198
|
+
this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.UNSECURED;
|
|
298
199
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
200
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
201
|
+
+ ` LockTargetState: ${this.LockMechanism.LockTargetState}, LockCurrentState: ${this.LockMechanism.LockCurrentState}`);
|
|
202
|
+
|
|
203
|
+
// Contact Sensor
|
|
204
|
+
if (!this.device.lock?.hide_contactsensor) {
|
|
205
|
+
switch (serviceData.door_open) {
|
|
206
|
+
case 'opened':
|
|
207
|
+
this.ContactSensor!.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
208
|
+
break;
|
|
209
|
+
default:
|
|
210
|
+
this.ContactSensor!.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
211
|
+
}
|
|
212
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensor!.ContactSensorState}`);
|
|
213
|
+
|
|
305
214
|
}
|
|
306
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
|
|
307
215
|
// Battery
|
|
308
|
-
this.BatteryLevel = Number(
|
|
309
|
-
if (this.BatteryLevel < 10) {
|
|
310
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
216
|
+
this.Battery.BatteryLevel = Number(serviceData.battery);
|
|
217
|
+
if (this.Battery.BatteryLevel < 10) {
|
|
218
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
311
219
|
} else {
|
|
312
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
220
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
313
221
|
}
|
|
314
|
-
this.debugLog(
|
|
315
|
-
|
|
316
|
-
);
|
|
222
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
223
|
+
+ ` BatteryLevel: ${this.Battery.BatteryLevel}, StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
317
224
|
}
|
|
318
225
|
|
|
319
|
-
async openAPIparseStatus(): Promise<void> {
|
|
226
|
+
async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
|
|
320
227
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
321
|
-
switch (
|
|
228
|
+
switch (deviceStatus.body.lockState) {
|
|
322
229
|
case 'locked':
|
|
323
|
-
this.LockCurrentState = this.hap.Characteristic.LockCurrentState.SECURED;
|
|
324
|
-
this.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
|
|
230
|
+
this.LockMechanism.LockCurrentState = this.hap.Characteristic.LockCurrentState.SECURED;
|
|
231
|
+
this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
|
|
325
232
|
break;
|
|
326
233
|
default:
|
|
327
|
-
this.LockCurrentState = this.hap.Characteristic.LockCurrentState.UNSECURED;
|
|
328
|
-
this.LockTargetState = this.hap.Characteristic.LockTargetState.UNSECURED;
|
|
234
|
+
this.LockMechanism.LockCurrentState = this.hap.Characteristic.LockCurrentState.UNSECURED;
|
|
235
|
+
this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.UNSECURED;
|
|
329
236
|
}
|
|
330
|
-
switch (
|
|
237
|
+
switch (deviceStatus.body.doorState) {
|
|
331
238
|
case 'opened':
|
|
332
|
-
this.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
239
|
+
this.ContactSensor!.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
333
240
|
break;
|
|
334
241
|
default:
|
|
335
|
-
this.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
242
|
+
this.ContactSensor!.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
336
243
|
}
|
|
337
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
|
|
244
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockMechanism.LockTargetState}`);
|
|
338
245
|
|
|
339
246
|
// Battery
|
|
340
|
-
this.BatteryLevel = Number(
|
|
341
|
-
if (this.BatteryLevel < 10) {
|
|
342
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
247
|
+
this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
|
|
248
|
+
if (this.Battery.BatteryLevel < 10) {
|
|
249
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
343
250
|
} else {
|
|
344
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
251
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
345
252
|
}
|
|
346
|
-
if (Number.isNaN(this.BatteryLevel)) {
|
|
347
|
-
this.BatteryLevel = 100;
|
|
253
|
+
if (Number.isNaN(this.Battery.BatteryLevel)) {
|
|
254
|
+
this.Battery.BatteryLevel = 100;
|
|
348
255
|
}
|
|
349
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
|
|
350
|
-
+ ` StatusLowBattery: ${this.StatusLowBattery}`);
|
|
256
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
|
|
257
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
351
258
|
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
this.
|
|
259
|
+
// Firmware Version
|
|
260
|
+
const version = deviceStatus.body.version?.toString();
|
|
261
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
|
|
262
|
+
if (deviceStatus.body.version) {
|
|
263
|
+
const deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
|
|
264
|
+
this.accessory
|
|
265
|
+
.getService(this.hap.Service.AccessoryInformation)!
|
|
266
|
+
.setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
|
|
267
|
+
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
268
|
+
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
269
|
+
.updateValue(deviceVersion);
|
|
270
|
+
this.accessory.context.deviceVersion = deviceVersion;
|
|
271
|
+
this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
|
|
272
|
+
}
|
|
355
273
|
}
|
|
356
274
|
|
|
357
275
|
/**
|
|
@@ -366,134 +284,71 @@ export class Lock {
|
|
|
366
284
|
await this.openAPIRefreshStatus();
|
|
367
285
|
} else {
|
|
368
286
|
await this.offlineOff();
|
|
369
|
-
this.debugWarnLog(
|
|
370
|
-
|
|
371
|
-
` ${this.device.connectionType}, refreshStatus will not happen.`,
|
|
372
|
-
);
|
|
287
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
288
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
373
289
|
}
|
|
374
290
|
}
|
|
375
291
|
|
|
376
292
|
async BLERefreshStatus(): Promise<void> {
|
|
377
293
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
|
|
378
|
-
const switchbot = await this.
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
.
|
|
382
|
-
|
|
383
|
-
.toLowerCase();
|
|
384
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
385
|
-
this.getCustomBLEAddress(switchbot);
|
|
294
|
+
const switchbot = await this.switchbotBLE();
|
|
295
|
+
|
|
296
|
+
if (switchbot === undefined) {
|
|
297
|
+
await this.BLERefreshConnection(switchbot);
|
|
298
|
+
} else {
|
|
386
299
|
// Start to monitor advertisement packets
|
|
387
|
-
|
|
300
|
+
(async () => {
|
|
388
301
|
// Start to monitor advertisement packets
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
switchbot.onadvertisement = (ad: any) => {
|
|
395
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
|
|
396
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.serviceData.model}`);
|
|
397
|
-
if (this.device.bleMac === ad.address && ad.serviceData.model === 'o') {
|
|
398
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
399
|
-
this.BLE_BatteryLevel = ad.serviceData.battery;
|
|
400
|
-
this.BLE_Calibration = ad.serviceData.calibration;
|
|
401
|
-
this.BLE_LockCurrentState = ad.serviceData.status;
|
|
402
|
-
this.BLE_ContactSensorState = ad.serviceData.door_open;
|
|
302
|
+
const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
|
|
303
|
+
// Update HomeKit
|
|
304
|
+
if (serviceData.model !== '' && serviceData.modelName !== '') {
|
|
305
|
+
await this.BLEparseStatus(serviceData);
|
|
306
|
+
await this.updateHomeKitCharacteristics();
|
|
403
307
|
} else {
|
|
404
|
-
this.
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
// Wait 1 seconds
|
|
408
|
-
await switchbot.wait(this.scanDuration * 1000);
|
|
409
|
-
// Stop to monitor
|
|
410
|
-
await switchbot.stopScan();
|
|
411
|
-
// Update HomeKit
|
|
412
|
-
await this.BLEparseStatus();
|
|
413
|
-
await this.updateHomeKitCharacteristics();
|
|
414
|
-
})();
|
|
415
|
-
/*if (switchbot !== false) {
|
|
416
|
-
switchbot
|
|
417
|
-
.startScan({
|
|
418
|
-
model: 'o',
|
|
419
|
-
id: this.device.bleMac,
|
|
420
|
-
})
|
|
421
|
-
.then(async () => {
|
|
422
|
-
// Set an event handler
|
|
423
|
-
switchbot.onadvertisement = async (ad: ad) => {
|
|
424
|
-
this.debugLog(
|
|
425
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
|
|
426
|
-
` BLE Address Found: ${ad.address}`,
|
|
427
|
-
);
|
|
428
|
-
this.BLE_BatteryLevel = ad.serviceData.battery;
|
|
429
|
-
this.BLE_Calibration = ad.serviceData.calibration;
|
|
430
|
-
this.BLE_LockCurrentState = ad.serviceData.status;
|
|
431
|
-
this.BLE_ContactSensorState = ad.serviceData.door_open;
|
|
432
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
433
|
-
this.debugLog(
|
|
434
|
-
`${this.device.deviceType}: ${this.accessory.displayName} battery: ${ad.serviceData.battery}, ` +
|
|
435
|
-
`calibration: ${ad.serviceData.calibration}, status: ${ad.serviceData.status}, battery: ${ad.serviceData.battery}, ` +
|
|
436
|
-
`door_open: ${ad.serviceData.door_open}`,
|
|
437
|
-
);
|
|
438
|
-
|
|
439
|
-
if (ad.serviceData) {
|
|
440
|
-
this.BLE_IsConnected = true;
|
|
441
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
|
|
442
|
-
await this.stopScanning(switchbot);
|
|
443
|
-
} else {
|
|
444
|
-
this.BLE_IsConnected = false;
|
|
445
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
|
|
446
|
-
}
|
|
447
|
-
};
|
|
448
|
-
// Wait
|
|
449
|
-
return await sleep(this.scanDuration * 1000);
|
|
450
|
-
})
|
|
451
|
-
.then(async () => {
|
|
452
|
-
// Stop to monitor
|
|
453
|
-
await this.stopScanning(switchbot);
|
|
454
|
-
})
|
|
455
|
-
.catch(async (e: any) => {
|
|
456
|
-
this.apiError(e);
|
|
457
|
-
this.errorLog(
|
|
458
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
|
|
459
|
-
` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
460
|
-
);
|
|
308
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
|
|
461
309
|
await this.BLERefreshConnection(switchbot);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
}*/
|
|
310
|
+
}
|
|
311
|
+
})();
|
|
312
|
+
}
|
|
466
313
|
}
|
|
467
314
|
|
|
468
315
|
async openAPIRefreshStatus(): Promise<void> {
|
|
469
316
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
470
317
|
try {
|
|
471
|
-
const { body, statusCode } = await
|
|
472
|
-
headers: this.platform.generateHeaders(),
|
|
473
|
-
});
|
|
474
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
|
|
318
|
+
const { body, statusCode } = await this.deviceRefreshStatus();
|
|
475
319
|
const deviceStatus: any = await body.json();
|
|
476
|
-
this.
|
|
477
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
|
|
320
|
+
await this.refreshStatusCodes(statusCode, deviceStatus);;
|
|
478
321
|
if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
|
|
479
|
-
this.
|
|
480
|
-
|
|
481
|
-
this.
|
|
482
|
-
this.OpenAPI_ContactSensorState = deviceStatus.body.doorState;
|
|
483
|
-
this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
|
|
484
|
-
this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
|
|
485
|
-
this.openAPIparseStatus();
|
|
486
|
-
this.updateHomeKitCharacteristics();
|
|
322
|
+
await this.successfulRefreshStatus(statusCode, deviceStatus);
|
|
323
|
+
await this.openAPIparseStatus(deviceStatus);
|
|
324
|
+
await this.updateHomeKitCharacteristics();
|
|
487
325
|
} else {
|
|
488
|
-
this.
|
|
489
|
-
this.statusCode(deviceStatus.statusCode);
|
|
326
|
+
await this.statusCodes(statusCode, deviceStatus);
|
|
490
327
|
}
|
|
491
328
|
} catch (e: any) {
|
|
492
329
|
this.apiError(e);
|
|
493
|
-
this.errorLog(
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
330
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
331
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async registerWebhook(accessory: PlatformAccessory, device: device & devicesConfig) {
|
|
336
|
+
if (device.webhook) {
|
|
337
|
+
this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
|
|
338
|
+
this.platform.webhookEventHandler[device.deviceId] = async (context) => {
|
|
339
|
+
try {
|
|
340
|
+
this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
|
|
341
|
+
const { lockState } = context;
|
|
342
|
+
const { LockCurrentState } = this.LockMechanism;
|
|
343
|
+
this.debugLog(`${device.deviceType}: ${accessory.displayName} (lockState) = Webhook:(${lockState}), current:(${LockCurrentState})`);
|
|
344
|
+
this.LockMechanism.LockCurrentState = lockState === 'LOCKED' ? 1 : 0;
|
|
345
|
+
this.updateHomeKitCharacteristics();
|
|
346
|
+
} catch (e: any) {
|
|
347
|
+
this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
} else {
|
|
351
|
+
this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
|
|
497
352
|
}
|
|
498
353
|
}
|
|
499
354
|
|
|
@@ -506,15 +361,14 @@ export class Lock {
|
|
|
506
361
|
async pushChanges(): Promise<void> {
|
|
507
362
|
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
508
363
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
|
|
509
|
-
|
|
510
|
-
|
|
364
|
+
} else if (this.BLE) {
|
|
365
|
+
await this.BLEpushChanges();
|
|
511
366
|
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
512
367
|
await this.openAPIpushChanges();
|
|
513
368
|
} else {
|
|
514
369
|
await this.offlineOff();
|
|
515
|
-
this.debugWarnLog(
|
|
516
|
-
|
|
517
|
-
);
|
|
370
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
371
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
518
372
|
}
|
|
519
373
|
// Refresh the status from the API
|
|
520
374
|
interval(15000)
|
|
@@ -527,18 +381,12 @@ export class Lock {
|
|
|
527
381
|
|
|
528
382
|
async BLEpushChanges(): Promise<void> {
|
|
529
383
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
530
|
-
if (this.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
531
|
-
this.debugLog(
|
|
532
|
-
|
|
533
|
-
` LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
|
|
534
|
-
);
|
|
384
|
+
if (this.LockMechanism.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
385
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges LockTargetState: ${this.LockMechanism.LockTargetState}`
|
|
386
|
+
+ ` LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
535
387
|
const switchbot = await this.platform.connectBLE();
|
|
536
388
|
// Convert to BLE Address
|
|
537
|
-
|
|
538
|
-
.deviceId!.match(/.{1,2}/g)!
|
|
539
|
-
.join(':')
|
|
540
|
-
.toLowerCase();
|
|
541
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
389
|
+
await this.convertBLEAddress();
|
|
542
390
|
switchbot
|
|
543
391
|
.discover({
|
|
544
392
|
model: '',
|
|
@@ -546,35 +394,33 @@ export class Lock {
|
|
|
546
394
|
})
|
|
547
395
|
.then(() => {
|
|
548
396
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
549
|
-
this.
|
|
397
|
+
this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
398
|
+
+ `LockTargetState: ${this.LockMechanism.LockTargetState} sent over BLE, sent successfully`);
|
|
399
|
+
this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
|
|
550
400
|
})
|
|
551
401
|
.catch(async (e: any) => {
|
|
552
402
|
this.apiError(e);
|
|
553
|
-
this.errorLog(
|
|
554
|
-
|
|
555
|
-
` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
556
|
-
);
|
|
403
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
404
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
557
405
|
await this.BLEPushConnection();
|
|
558
406
|
});
|
|
559
407
|
} else {
|
|
560
|
-
this.debugLog(
|
|
561
|
-
|
|
562
|
-
`
|
|
563
|
-
`LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
|
|
564
|
-
);
|
|
408
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.`
|
|
409
|
+
+ `LockTargetState: ${this.LockMechanism.LockTargetState}, `
|
|
410
|
+
+ `LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
565
411
|
}
|
|
566
412
|
}
|
|
567
413
|
|
|
568
414
|
async openAPIpushChanges(LatchUnlock?): Promise<void> {
|
|
569
415
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
570
416
|
|
|
571
|
-
if ((this.LockTargetState !== this.accessory.context.LockTargetState) || LatchUnlock) {
|
|
417
|
+
if ((this.LockMechanism.LockTargetState !== this.accessory.context.LockTargetState) || LatchUnlock) {
|
|
572
418
|
// Determine the command based on the LockTargetState or the forceUnlock parameter
|
|
573
419
|
let command = '';
|
|
574
420
|
if (LatchUnlock) {
|
|
575
421
|
command = 'unlock';
|
|
576
422
|
} else {
|
|
577
|
-
command = this.LockTargetState ? 'lock' : 'unlock';
|
|
423
|
+
command = this.LockMechanism.LockTargetState ? 'lock' : 'unlock';
|
|
578
424
|
}
|
|
579
425
|
const bodyChange = JSON.stringify({
|
|
580
426
|
command: `${command}`,
|
|
@@ -583,36 +429,24 @@ export class Lock {
|
|
|
583
429
|
});
|
|
584
430
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
|
|
585
431
|
try {
|
|
586
|
-
const { body, statusCode } = await
|
|
587
|
-
body: bodyChange,
|
|
588
|
-
method: 'POST',
|
|
589
|
-
headers: this.platform.generateHeaders(),
|
|
590
|
-
});
|
|
591
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
|
|
432
|
+
const { body, statusCode } = await this.pushChangeRequest(bodyChange);
|
|
592
433
|
const deviceStatus: any = await body.json();
|
|
593
|
-
this.
|
|
594
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
|
|
595
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
|
|
434
|
+
await this.pushStatusCodes(statusCode, deviceStatus);
|
|
596
435
|
if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
|
|
597
|
-
this.
|
|
598
|
-
|
|
436
|
+
await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
|
|
437
|
+
await this.updateHomeKitCharacteristics();
|
|
599
438
|
} else {
|
|
600
|
-
this.statusCode(statusCode);
|
|
601
|
-
this.statusCode(deviceStatus.statusCode);
|
|
439
|
+
await this.statusCode(statusCode);
|
|
440
|
+
await this.statusCode(deviceStatus.statusCode);
|
|
602
441
|
}
|
|
603
442
|
} catch (e: any) {
|
|
604
443
|
this.apiError(e);
|
|
605
|
-
this.errorLog(
|
|
606
|
-
|
|
607
|
-
` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
608
|
-
);
|
|
444
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
445
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
609
446
|
}
|
|
610
447
|
} else {
|
|
611
|
-
this.debugLog(
|
|
612
|
-
`${this.
|
|
613
|
-
`LockTargetState: ${this.LockTargetState}, ` +
|
|
614
|
-
`LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
|
|
615
|
-
);
|
|
448
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges, LockTargetState: `
|
|
449
|
+
+ `${this.LockMechanism.LockTargetState}, LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
616
450
|
}
|
|
617
451
|
}
|
|
618
452
|
|
|
@@ -620,81 +454,97 @@ export class Lock {
|
|
|
620
454
|
* Handle requests to set the value of the "On" characteristic
|
|
621
455
|
*/
|
|
622
456
|
async LockTargetStateSet(value: CharacteristicValue): Promise<void> {
|
|
623
|
-
if (this.LockTargetState === this.accessory.context.LockTargetState) {
|
|
457
|
+
if (this.LockMechanism.LockTargetState === this.accessory.context.LockTargetState) {
|
|
624
458
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set LockTargetState: ${value}`);
|
|
625
459
|
} else {
|
|
626
460
|
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
|
|
627
461
|
}
|
|
628
462
|
|
|
629
|
-
this.LockTargetState = value;
|
|
463
|
+
this.LockMechanism.LockTargetState = value;
|
|
464
|
+
this.doLockUpdate.next();
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Handle requests to set the value of the "On" characteristic
|
|
469
|
+
*/
|
|
470
|
+
async OnSet(value: CharacteristicValue): Promise<void> {
|
|
471
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Latch Button Set On: ${value}`);
|
|
472
|
+
if (value) {
|
|
473
|
+
this.debugLog('Attempting to open the latch');
|
|
474
|
+
|
|
475
|
+
this.openAPIpushChanges(value).then(() => {
|
|
476
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Latch opened successfully`);
|
|
477
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
478
|
+
+ ` SwitchService is: ${this.Switch!.Service ? 'available' : 'not available'}`);
|
|
479
|
+
|
|
480
|
+
// simulate button press to turn the switch back off
|
|
481
|
+
if (this.Switch!.Service) {
|
|
482
|
+
const SwitchService = this.Switch!.Service;
|
|
483
|
+
// Simulate a button press by waiting a short period before turning the switch off
|
|
484
|
+
setTimeout(() => {
|
|
485
|
+
SwitchService.getCharacteristic(this.hap.Characteristic.On).updateValue(false);
|
|
486
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Latch button switched off automatically.`);
|
|
487
|
+
}, 500); // 500 ms delay
|
|
488
|
+
}
|
|
489
|
+
}).catch((e: any) => {
|
|
490
|
+
// Log the error if the operation failed
|
|
491
|
+
this.debugLog(`Error opening latch: ${e}`);
|
|
492
|
+
// Ensure we turn the switch back off even in case of an error
|
|
493
|
+
if (this.Switch!.Service) {
|
|
494
|
+
this.Switch!.Service.getCharacteristic(this.hap.Characteristic.On).updateValue(false);
|
|
495
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Latch button switched off after an error.`);
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
} else {
|
|
499
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch is off, nothing to do`);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
this.Switch!.On = value;
|
|
630
503
|
this.doLockUpdate.next();
|
|
631
504
|
}
|
|
632
505
|
|
|
633
506
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
634
507
|
if (!this.device.lock?.hide_contactsensor) {
|
|
635
|
-
if (this.ContactSensorState === undefined) {
|
|
636
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
508
|
+
if (this.ContactSensor!.ContactSensorState === undefined) {
|
|
509
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensor!.ContactSensorState}`);
|
|
637
510
|
} else {
|
|
638
|
-
this.accessory.context.ContactSensorState = this.ContactSensorState;
|
|
639
|
-
this.
|
|
640
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic
|
|
511
|
+
this.accessory.context.ContactSensorState = this.ContactSensor!.ContactSensorState;
|
|
512
|
+
this.ContactSensor!.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState, this.ContactSensor!.ContactSensorState);
|
|
513
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
514
|
+
+ ` ContactSensorState: ${this.ContactSensor!.ContactSensorState}`);
|
|
641
515
|
}
|
|
642
516
|
}
|
|
643
|
-
if (this.LockTargetState === undefined) {
|
|
644
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockTargetState: ${this.LockTargetState}`);
|
|
517
|
+
if (this.LockMechanism.LockTargetState === undefined) {
|
|
518
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockTargetState: ${this.LockMechanism.LockTargetState}`);
|
|
645
519
|
} else {
|
|
646
|
-
this.accessory.context.LockTargetState = this.LockTargetState;
|
|
647
|
-
this.
|
|
648
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic
|
|
520
|
+
this.accessory.context.LockTargetState = this.LockMechanism.LockTargetState;
|
|
521
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.LockMechanism.LockTargetState);
|
|
522
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
523
|
+
+ ` LockTargetState: ${this.LockMechanism.LockTargetState}`);
|
|
649
524
|
}
|
|
650
|
-
if (this.LockCurrentState === undefined) {
|
|
651
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockCurrentState: ${this.LockCurrentState}`);
|
|
525
|
+
if (this.LockMechanism.LockCurrentState === undefined) {
|
|
526
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockCurrentState: ${this.LockMechanism.LockCurrentState}`);
|
|
652
527
|
} else {
|
|
653
|
-
this.accessory.context.LockCurrentState = this.LockCurrentState;
|
|
654
|
-
this.
|
|
655
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic
|
|
528
|
+
this.accessory.context.LockCurrentState = this.LockMechanism.LockCurrentState;
|
|
529
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.LockMechanism.LockCurrentState);
|
|
530
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
531
|
+
+ ` LockCurrentState: ${this.LockMechanism.LockCurrentState}`);
|
|
656
532
|
}
|
|
657
|
-
if (this.BatteryLevel === undefined) {
|
|
658
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
533
|
+
if (this.Battery.BatteryLevel === undefined) {
|
|
534
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
659
535
|
} else {
|
|
660
|
-
this.accessory.context.BatteryLevel = this.BatteryLevel;
|
|
661
|
-
this.
|
|
662
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic
|
|
536
|
+
this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
|
|
537
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
|
|
538
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
539
|
+
+ ` BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
663
540
|
}
|
|
664
|
-
if (this.StatusLowBattery === undefined) {
|
|
665
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
666
|
-
} else {
|
|
667
|
-
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
668
|
-
this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
669
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
async stopScanning(switchbot: any) {
|
|
674
|
-
switchbot.stopScan();
|
|
675
|
-
if (this.BLE_IsConnected) {
|
|
676
|
-
await this.BLEparseStatus();
|
|
677
|
-
await this.updateHomeKitCharacteristics();
|
|
541
|
+
if (this.Battery.StatusLowBattery === undefined) {
|
|
542
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
678
543
|
} else {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
async getCustomBLEAddress(switchbot: any) {
|
|
684
|
-
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
685
|
-
(async () => {
|
|
686
|
-
// Start to monitor advertisement packets
|
|
687
|
-
await switchbot.startScan({
|
|
688
|
-
model: 'c',
|
|
689
|
-
});
|
|
690
|
-
// Set an event handler
|
|
691
|
-
switchbot.onadvertisement = (ad: any) => {
|
|
692
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
|
|
693
|
-
};
|
|
694
|
-
await sleep(10000);
|
|
695
|
-
// Stop to monitor
|
|
696
|
-
switchbot.stopScan();
|
|
697
|
-
})();
|
|
544
|
+
this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
|
|
545
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
|
|
546
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
547
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
698
548
|
}
|
|
699
549
|
}
|
|
700
550
|
|
|
@@ -714,227 +564,22 @@ export class Lock {
|
|
|
714
564
|
}
|
|
715
565
|
}
|
|
716
566
|
|
|
717
|
-
async scan(device: device & devicesConfig): Promise<void> {
|
|
718
|
-
if (device.scanDuration) {
|
|
719
|
-
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
720
|
-
if (this.BLE) {
|
|
721
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
722
|
-
}
|
|
723
|
-
} else {
|
|
724
|
-
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
725
|
-
if (this.BLE) {
|
|
726
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
async statusCode(statusCode: number): Promise<void> {
|
|
732
|
-
switch (statusCode) {
|
|
733
|
-
case 151:
|
|
734
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
|
|
735
|
-
break;
|
|
736
|
-
case 152:
|
|
737
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
|
|
738
|
-
break;
|
|
739
|
-
case 160:
|
|
740
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
|
|
741
|
-
break;
|
|
742
|
-
case 161:
|
|
743
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
|
|
744
|
-
this.offlineOff();
|
|
745
|
-
break;
|
|
746
|
-
case 171:
|
|
747
|
-
this.errorLog(
|
|
748
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
|
|
749
|
-
`Hub: ${this.device.hubDeviceId}`,
|
|
750
|
-
);
|
|
751
|
-
this.offlineOff();
|
|
752
|
-
break;
|
|
753
|
-
case 190:
|
|
754
|
-
this.errorLog(
|
|
755
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
756
|
-
` Or command format is invalid, statusCode: ${statusCode}`,
|
|
757
|
-
);
|
|
758
|
-
break;
|
|
759
|
-
case 100:
|
|
760
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
|
|
761
|
-
break;
|
|
762
|
-
case 200:
|
|
763
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
|
|
764
|
-
break;
|
|
765
|
-
case 400:
|
|
766
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
|
|
767
|
-
+ `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
|
|
768
|
-
break;
|
|
769
|
-
case 401:
|
|
770
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
|
|
771
|
-
+ `but the request has not been authenticated, statusCode: ${statusCode}`);
|
|
772
|
-
break;
|
|
773
|
-
case 403:
|
|
774
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
|
|
775
|
-
+ `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
|
|
776
|
-
break;
|
|
777
|
-
case 404:
|
|
778
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
|
|
779
|
-
+ `statusCode: ${statusCode}`);
|
|
780
|
-
break;
|
|
781
|
-
case 406:
|
|
782
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
|
|
783
|
-
+ `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
|
|
784
|
-
break;
|
|
785
|
-
case 415:
|
|
786
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
|
|
787
|
-
+ `header that is not supported by the server, statusCode: ${statusCode}`);
|
|
788
|
-
break;
|
|
789
|
-
case 422:
|
|
790
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
|
|
791
|
-
+ `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
|
|
792
|
-
break;
|
|
793
|
-
case 429:
|
|
794
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
|
|
795
|
-
+ `requests allowed for a given time window, statusCode: ${statusCode}`);
|
|
796
|
-
break;
|
|
797
|
-
case 500:
|
|
798
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
|
|
799
|
-
+ `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
|
|
800
|
-
break;
|
|
801
|
-
default:
|
|
802
|
-
this.infoLog(
|
|
803
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
|
|
804
|
-
`${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`,
|
|
805
|
-
);
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
|
|
809
567
|
async offlineOff(): Promise<void> {
|
|
810
568
|
if (this.device.offline) {
|
|
811
|
-
|
|
812
|
-
|
|
569
|
+
if (!this.device.lock?.hide_contactsensor) {
|
|
570
|
+
this.ContactSensor!.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState,
|
|
571
|
+
this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED);
|
|
572
|
+
}
|
|
573
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
|
|
574
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
|
|
813
575
|
}
|
|
814
576
|
}
|
|
815
577
|
|
|
816
578
|
async apiError(e: any): Promise<void> {
|
|
817
579
|
if (!this.device.lock?.hide_contactsensor) {
|
|
818
|
-
this.
|
|
819
|
-
}
|
|
820
|
-
this.lockService.updateCharacteristic(this.hap.Characteristic.LockTargetState, e);
|
|
821
|
-
this.lockService.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e);
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
async deviceContext() {
|
|
825
|
-
if (this.LockTargetState === undefined) {
|
|
826
|
-
this.LockTargetState = false;
|
|
827
|
-
} else {
|
|
828
|
-
this.LockTargetState = this.accessory.context.On;
|
|
829
|
-
}
|
|
830
|
-
if (this.FirmwareRevision === undefined) {
|
|
831
|
-
this.FirmwareRevision = this.platform.version;
|
|
832
|
-
this.accessory.context.FirmwareRevision = this.FirmwareRevision;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
837
|
-
if (device.refreshRate) {
|
|
838
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
839
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
840
|
-
} else if (this.platform.config.options!.refreshRate) {
|
|
841
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
842
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
async deviceConfig(device: device & devicesConfig): Promise<void> {
|
|
847
|
-
let config = {};
|
|
848
|
-
if (device.lock) {
|
|
849
|
-
config = device.lock;
|
|
850
|
-
}
|
|
851
|
-
if (device.connectionType !== undefined) {
|
|
852
|
-
config['connectionType'] = device.connectionType;
|
|
853
|
-
}
|
|
854
|
-
if (device.external !== undefined) {
|
|
855
|
-
config['external'] = device.external;
|
|
856
|
-
}
|
|
857
|
-
if (device.logging !== undefined) {
|
|
858
|
-
config['logging'] = device.logging;
|
|
859
|
-
}
|
|
860
|
-
if (device.refreshRate !== undefined) {
|
|
861
|
-
config['refreshRate'] = device.refreshRate;
|
|
862
|
-
}
|
|
863
|
-
if (device.scanDuration !== undefined) {
|
|
864
|
-
config['scanDuration'] = device.scanDuration;
|
|
865
|
-
}
|
|
866
|
-
if (device.webhook !== undefined) {
|
|
867
|
-
config['webhook'] = device.webhook;
|
|
868
|
-
}
|
|
869
|
-
if (Object.entries(config).length !== 0) {
|
|
870
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
async deviceLogs(device: device & devicesConfig): Promise<void> {
|
|
875
|
-
if (this.platform.debugMode) {
|
|
876
|
-
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
877
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
878
|
-
} else if (device.logging) {
|
|
879
|
-
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
880
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
881
|
-
} else if (this.platform.config.options?.logging) {
|
|
882
|
-
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
883
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
884
|
-
} else {
|
|
885
|
-
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
886
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
/**
|
|
891
|
-
* Logging for Device
|
|
892
|
-
*/
|
|
893
|
-
infoLog(...log: any[]): void {
|
|
894
|
-
if (this.enablingDeviceLogging()) {
|
|
895
|
-
this.platform.log.info(String(...log));
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
warnLog(...log: any[]): void {
|
|
900
|
-
if (this.enablingDeviceLogging()) {
|
|
901
|
-
this.platform.log.warn(String(...log));
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
debugWarnLog(...log: any[]): void {
|
|
906
|
-
if (this.enablingDeviceLogging()) {
|
|
907
|
-
if (this.deviceLogging?.includes('debug')) {
|
|
908
|
-
this.platform.log.warn('[DEBUG]', String(...log));
|
|
909
|
-
}
|
|
580
|
+
this.ContactSensor!.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState, e);
|
|
910
581
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
errorLog(...log: any[]): void {
|
|
914
|
-
if (this.enablingDeviceLogging()) {
|
|
915
|
-
this.platform.log.error(String(...log));
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
debugErrorLog(...log: any[]): void {
|
|
920
|
-
if (this.enablingDeviceLogging()) {
|
|
921
|
-
if (this.deviceLogging?.includes('debug')) {
|
|
922
|
-
this.platform.log.error('[DEBUG]', String(...log));
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
debugLog(...log: any[]): void {
|
|
928
|
-
if (this.enablingDeviceLogging()) {
|
|
929
|
-
if (this.deviceLogging === 'debug') {
|
|
930
|
-
this.platform.log.info('[DEBUG]', String(...log));
|
|
931
|
-
} else {
|
|
932
|
-
this.platform.log.debug(String(...log));
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
enablingDeviceLogging(): boolean {
|
|
938
|
-
return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
|
|
582
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, e);
|
|
583
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e);
|
|
939
584
|
}
|
|
940
585
|
}
|