@switchbot/homebridge-switchbot 2.0.0-beta.3 → 2.0.0-beta.30
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 -1
- package/README.md +1 -2
- package/config.schema.json +102 -20
- package/dist/device/bot.d.ts +34 -28
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +655 -649
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +36 -19
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +483 -309
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +18 -8
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +303 -237
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +23 -16
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +541 -498
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +24 -18
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +450 -369
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +27 -8
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +302 -148
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +22 -16
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +340 -262
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +24 -12
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +359 -213
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +18 -8
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +276 -216
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +27 -17
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +292 -251
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +43 -19
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +503 -262
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +9 -12
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +275 -230
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +5 -3
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +151 -104
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +11 -8
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +130 -86
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +10 -7
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +157 -109
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +11 -8
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +134 -103
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +11 -8
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +142 -98
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +12 -9
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +140 -93
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +9 -10
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +129 -89
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +8 -9
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +129 -89
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +14 -12
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +479 -434
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +18 -11
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/package.json +12 -10
- package/src/device/bot.ts +654 -660
- package/src/device/colorbulb.ts +487 -344
- package/src/device/contact.ts +306 -241
- package/src/device/curtain.ts +546 -512
- package/src/device/humidifier.ts +453 -403
- package/src/device/lock.ts +311 -149
- package/src/device/meter.ts +351 -275
- package/src/device/meterplus.ts +369 -219
- package/src/device/motion.ts +282 -222
- package/src/device/plug.ts +296 -260
- package/src/device/striplight.ts +519 -289
- package/src/irdevice/airconditioner.ts +279 -241
- package/src/irdevice/airpurifier.ts +148 -103
- package/src/irdevice/camera.ts +128 -85
- package/src/irdevice/fan.ts +154 -106
- package/src/irdevice/light.ts +132 -103
- package/src/irdevice/other.ts +140 -97
- package/src/irdevice/tv.ts +139 -93
- package/src/irdevice/vacuumcleaner.ts +128 -89
- package/src/irdevice/waterheater.ts +127 -89
- package/src/platform.ts +469 -456
- package/src/settings.ts +18 -11
package/dist/device/lock.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.Lock = void 0;
|
|
|
7
7
|
const https_1 = __importDefault(require("https"));
|
|
8
8
|
const crypto_1 = __importDefault(require("crypto"));
|
|
9
9
|
const rxjs_1 = require("rxjs");
|
|
10
|
+
const super_stringify_1 = __importDefault(require("super-stringify"));
|
|
10
11
|
const operators_1 = require("rxjs/operators");
|
|
11
12
|
const settings_1 = require("../settings");
|
|
12
13
|
class Lock {
|
|
@@ -14,17 +15,15 @@ class Lock {
|
|
|
14
15
|
this.platform = platform;
|
|
15
16
|
this.accessory = accessory;
|
|
16
17
|
this.device = device;
|
|
18
|
+
// Connection
|
|
19
|
+
this.BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI');
|
|
20
|
+
this.OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI');
|
|
17
21
|
// default placeholders
|
|
18
22
|
this.logs(device);
|
|
19
23
|
this.scan(device);
|
|
20
24
|
this.refreshRate(device);
|
|
21
25
|
this.config(device);
|
|
22
|
-
|
|
23
|
-
this.LockTargetState = false;
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
this.LockTargetState = this.accessory.context.On;
|
|
27
|
-
}
|
|
26
|
+
this.conext();
|
|
28
27
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
29
28
|
this.doLockUpdate = new rxjs_1.Subject();
|
|
30
29
|
this.lockUpdateInProgress = false;
|
|
@@ -55,19 +54,19 @@ class Lock {
|
|
|
55
54
|
this.lockService.getCharacteristic(this.platform.Characteristic.LockTargetState).onSet(this.LockTargetStateSet.bind(this));
|
|
56
55
|
// Contact Sensor Service
|
|
57
56
|
if (device.lock?.hide_contactsensor) {
|
|
58
|
-
this.debugLog(
|
|
57
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Contact Sensor Service`);
|
|
59
58
|
this.contactSensorService = this.accessory.getService(this.platform.Service.ContactSensor);
|
|
60
59
|
accessory.removeService(this.contactSensorService);
|
|
61
60
|
}
|
|
62
61
|
else if (!this.contactSensorService) {
|
|
63
|
-
this.debugLog(
|
|
62
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Contact Sensor Service`);
|
|
64
63
|
(this.contactSensorService =
|
|
65
64
|
this.accessory.getService(this.platform.Service.ContactSensor) || this.accessory.addService(this.platform.Service.ContactSensor)),
|
|
66
65
|
`${accessory.displayName} Contact Sensor`;
|
|
67
66
|
this.contactSensorService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Contact Sensor`);
|
|
68
67
|
}
|
|
69
68
|
else {
|
|
70
|
-
this.debugLog(
|
|
69
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Contact Sensor Service Not Added`);
|
|
71
70
|
}
|
|
72
71
|
// Update Homekit
|
|
73
72
|
this.updateHomeKitCharacteristics();
|
|
@@ -88,17 +87,29 @@ class Lock {
|
|
|
88
87
|
await this.pushChanges();
|
|
89
88
|
}
|
|
90
89
|
catch (e) {
|
|
91
|
-
this.errorLog(`Lock: ${this.accessory.displayName} failed pushChanges`);
|
|
92
|
-
if (this.deviceLogging.includes('debug')) {
|
|
93
|
-
this.errorLog(`Lock: ${this.accessory.displayName} failed pushChanges,` + ` Error Message: ${JSON.stringify(e.message)}`);
|
|
94
|
-
}
|
|
95
90
|
this.apiError(e);
|
|
91
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
|
|
92
|
+
+ ` Error Message: ${(0, super_stringify_1.default)(e.message)}`);
|
|
96
93
|
}
|
|
97
94
|
this.lockUpdateInProgress = false;
|
|
98
95
|
});
|
|
99
96
|
}
|
|
100
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Parse the device status from the SwitchBot api
|
|
99
|
+
*/
|
|
101
100
|
async parseStatus() {
|
|
101
|
+
/*if (this.BLE) {
|
|
102
|
+
await this.BLEparseStatus();
|
|
103
|
+
} else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
104
|
+
await this.openAPIparseStatus();
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
108
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async BLEparseStatus() {
|
|
112
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
102
113
|
switch (this.lockState) {
|
|
103
114
|
case 'locked':
|
|
104
115
|
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.SECURED;
|
|
@@ -115,16 +126,52 @@ class Lock {
|
|
|
115
126
|
default:
|
|
116
127
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
117
128
|
}
|
|
118
|
-
this.debugLog(
|
|
129
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
|
|
119
130
|
}
|
|
131
|
+
//{"deviceId":"DBDC23B53139","deviceType":"Smart Lock","hubDeviceId":"E68B14109DA2","lockState":"locked","doorState":"opened","calibrate":true}
|
|
132
|
+
async openAPIparseStatus() {
|
|
133
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
134
|
+
switch (this.lockState) {
|
|
135
|
+
case 'locked':
|
|
136
|
+
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.SECURED;
|
|
137
|
+
this.LockTargetState = this.platform.Characteristic.LockTargetState.SECURED;
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.UNSECURED;
|
|
141
|
+
this.LockTargetState = this.platform.Characteristic.LockTargetState.UNSECURED;
|
|
142
|
+
}
|
|
143
|
+
switch (this.doorState) {
|
|
144
|
+
case 'opened':
|
|
145
|
+
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
149
|
+
}
|
|
150
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Asks the SwitchBot API for the latest device information
|
|
154
|
+
*/
|
|
120
155
|
async refreshStatus() {
|
|
156
|
+
/*if (this.BLE) {
|
|
157
|
+
await this.BLERefreshStatus();
|
|
158
|
+
} else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
159
|
+
await this.openAPIRefreshStatus();
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
163
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async openAPIRefreshStatus() {
|
|
167
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
121
168
|
try {
|
|
122
169
|
const t = Date.now();
|
|
123
170
|
const nonce = 'requestID';
|
|
124
171
|
const data = this.platform.config.credentials?.token + t + nonce;
|
|
125
172
|
const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
126
173
|
const sign = signTerm.toString('base64');
|
|
127
|
-
this.debugLog(
|
|
174
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
128
175
|
const options = {
|
|
129
176
|
hostname: settings_1.HostDomain,
|
|
130
177
|
port: 443,
|
|
@@ -139,37 +186,35 @@ class Lock {
|
|
|
139
186
|
},
|
|
140
187
|
};
|
|
141
188
|
const req = https_1.default.request(options, (res) => {
|
|
142
|
-
this.debugLog(
|
|
189
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
|
|
143
190
|
let rawData = '';
|
|
144
191
|
res.on('data', (d) => {
|
|
145
192
|
rawData += d;
|
|
146
|
-
this.debugLog(
|
|
193
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
147
194
|
});
|
|
148
195
|
res.on('end', () => {
|
|
149
196
|
try {
|
|
150
197
|
this.deviceStatus = JSON.parse(rawData);
|
|
151
|
-
this.debugLog(
|
|
198
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${(0, super_stringify_1.default)(this.deviceStatus)}`);
|
|
152
199
|
this.lockState = this.deviceStatus.body.lockState;
|
|
153
200
|
this.doorState = this.deviceStatus.body.doorState;
|
|
154
|
-
this.
|
|
201
|
+
this.openAPIparseStatus();
|
|
155
202
|
this.updateHomeKitCharacteristics();
|
|
156
203
|
}
|
|
157
204
|
catch (e) {
|
|
158
|
-
this.errorLog(
|
|
205
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
159
206
|
}
|
|
160
207
|
});
|
|
161
208
|
});
|
|
162
209
|
req.on('error', (e) => {
|
|
163
|
-
this.errorLog(
|
|
210
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
164
211
|
});
|
|
165
212
|
req.end();
|
|
166
213
|
}
|
|
167
214
|
catch (e) {
|
|
168
|
-
this.errorLog(`Lock: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
169
|
-
if (this.deviceLogging.includes('debug')) {
|
|
170
|
-
this.errorLog(`Lock: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`);
|
|
171
|
-
}
|
|
172
215
|
this.apiError(e);
|
|
216
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
217
|
+
+ ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
|
|
173
218
|
}
|
|
174
219
|
}
|
|
175
220
|
/**
|
|
@@ -179,210 +224,305 @@ class Lock {
|
|
|
179
224
|
* Lock - "command" "unlock" "default" = set to ???? state - LockCurrentState
|
|
180
225
|
*/
|
|
181
226
|
async pushChanges() {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
187
|
-
.update(Buffer.from(data, 'utf-8'))
|
|
188
|
-
.digest();
|
|
189
|
-
const sign = signTerm.toString('base64');
|
|
190
|
-
this.debugLog(`Lock: ${this.accessory.displayName} sign: ${sign}`);
|
|
191
|
-
let command = '';
|
|
192
|
-
if (this.LockTargetState) {
|
|
193
|
-
command = 'lock';
|
|
227
|
+
/*if (this.BLE) {
|
|
228
|
+
await this.BLERefreshStatus();
|
|
229
|
+
} else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
230
|
+
await this.openAPIpushChanges();
|
|
194
231
|
}
|
|
195
232
|
else {
|
|
196
|
-
|
|
233
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
234
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
197
235
|
}
|
|
198
|
-
const body = JSON.stringify({
|
|
199
|
-
'command': `${command}`,
|
|
200
|
-
'parameter': 'default',
|
|
201
|
-
'commandType': 'command',
|
|
202
|
-
});
|
|
203
|
-
this.infoLog(`Lock: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
204
|
-
const options = {
|
|
205
|
-
hostname: settings_1.HostDomain,
|
|
206
|
-
port: 443,
|
|
207
|
-
path: `${settings_1.DevicePath}/${this.device.deviceId}/commands`,
|
|
208
|
-
method: 'POST',
|
|
209
|
-
headers: {
|
|
210
|
-
'Authorization': this.platform.config.credentials?.token,
|
|
211
|
-
'sign': sign,
|
|
212
|
-
'nonce': nonce,
|
|
213
|
-
't': t,
|
|
214
|
-
'Content-Type': 'application/json',
|
|
215
|
-
'Content-Length': body.length,
|
|
216
|
-
},
|
|
217
|
-
};
|
|
218
|
-
const req = https_1.default.request(options, res => {
|
|
219
|
-
this.debugLog(`Lock: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
220
|
-
this.statusCode({ res });
|
|
221
|
-
res.on('data', d => {
|
|
222
|
-
this.debugLog(`Lock: ${this.accessory.displayName} d: ${d}`);
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
req.on('error', (e) => {
|
|
226
|
-
this.errorLog(`Lock: ${this.accessory.displayName} error message: ${e.message}`);
|
|
227
|
-
});
|
|
228
|
-
req.write(body);
|
|
229
|
-
req.end();
|
|
230
|
-
this.debugLog(`Lock: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
231
|
-
this.accessory.context.On = this.LockTargetState;
|
|
232
236
|
(0, rxjs_1.interval)(5000)
|
|
233
237
|
.pipe((0, operators_1.take)(1))
|
|
234
238
|
.subscribe(async () => {
|
|
235
239
|
await this.refreshStatus();
|
|
236
240
|
});
|
|
237
241
|
}
|
|
242
|
+
async BLEpushChanges() {
|
|
243
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
244
|
+
if (this.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
245
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges LockTargetState: ${this.LockTargetState}`
|
|
246
|
+
+ ` LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
247
|
+
const switchbot = await this.platform.connectBLE();
|
|
248
|
+
// Convert to BLE Address
|
|
249
|
+
this.device.bleMac = this.device
|
|
250
|
+
.deviceId.match(/.{1,2}/g)
|
|
251
|
+
.join(':')
|
|
252
|
+
.toLowerCase();
|
|
253
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
254
|
+
switchbot
|
|
255
|
+
.discover({
|
|
256
|
+
model: '',
|
|
257
|
+
id: this.device.bleMac,
|
|
258
|
+
})
|
|
259
|
+
.then(() => {
|
|
260
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
261
|
+
this.LockTargetState = this.platform.Characteristic.LockTargetState.SECURED;
|
|
262
|
+
})
|
|
263
|
+
.catch(async (e) => {
|
|
264
|
+
this.apiError(e);
|
|
265
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
266
|
+
+ ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
|
|
267
|
+
await this.BLEPushConnection();
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
|
|
272
|
+
+ `LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async openAPIpushChanges() {
|
|
276
|
+
try {
|
|
277
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
278
|
+
if (this.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
279
|
+
// Make Push On request to the API
|
|
280
|
+
const t = Date.now();
|
|
281
|
+
const nonce = 'requestID';
|
|
282
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
283
|
+
const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
284
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
285
|
+
.digest();
|
|
286
|
+
const sign = signTerm.toString('base64');
|
|
287
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
288
|
+
let command = '';
|
|
289
|
+
if (this.LockTargetState) {
|
|
290
|
+
command = 'lock';
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
command = 'unlock';
|
|
294
|
+
}
|
|
295
|
+
const body = (0, super_stringify_1.default)({
|
|
296
|
+
'command': `${command}`,
|
|
297
|
+
'parameter': 'default',
|
|
298
|
+
'commandType': 'command',
|
|
299
|
+
});
|
|
300
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
301
|
+
const options = {
|
|
302
|
+
hostname: settings_1.HostDomain,
|
|
303
|
+
port: 443,
|
|
304
|
+
path: `${settings_1.DevicePath}/${this.device.deviceId}/commands`,
|
|
305
|
+
method: 'POST',
|
|
306
|
+
headers: {
|
|
307
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
308
|
+
'sign': sign,
|
|
309
|
+
'nonce': nonce,
|
|
310
|
+
't': t,
|
|
311
|
+
'Content-Type': 'application/json',
|
|
312
|
+
'Content-Length': body.length,
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
const req = https_1.default.request(options, res => {
|
|
316
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
|
|
317
|
+
this.statusCode({ res });
|
|
318
|
+
res.on('data', d => {
|
|
319
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
req.on('error', (e) => {
|
|
323
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
324
|
+
});
|
|
325
|
+
req.write(body);
|
|
326
|
+
req.end();
|
|
327
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges: ${(0, super_stringify_1.default)(req)}`);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
|
|
331
|
+
+ `LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
catch (e) {
|
|
335
|
+
this.apiError(e);
|
|
336
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
337
|
+
+ ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Handle requests to set the value of the "On" characteristic
|
|
342
|
+
*/
|
|
343
|
+
async LockTargetStateSet(value) {
|
|
344
|
+
if (this.LockTargetState === this.accessory.context.LockTargetState) {
|
|
345
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set LockTargetState: ${value}`);
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
|
|
349
|
+
}
|
|
350
|
+
this.LockTargetState = value;
|
|
351
|
+
this.doLockUpdate.next();
|
|
352
|
+
}
|
|
238
353
|
async updateHomeKitCharacteristics() {
|
|
239
354
|
if (!this.device.lock?.hide_contactsensor) {
|
|
240
355
|
if (this.ContactSensorState === undefined) {
|
|
241
|
-
this.debugLog(
|
|
356
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
242
357
|
}
|
|
243
358
|
else {
|
|
359
|
+
this.accessory.context.ContactSensorState = this.ContactSensorState;
|
|
244
360
|
this.contactSensorService?.updateCharacteristic(this.platform.Characteristic.ContactSensorState, this.ContactSensorState);
|
|
245
|
-
this.debugLog(
|
|
361
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic ContactSensorState: ${this.ContactSensorState}`);
|
|
246
362
|
}
|
|
247
363
|
}
|
|
248
364
|
if (this.LockTargetState === undefined) {
|
|
249
|
-
this.debugLog(
|
|
365
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockTargetState: ${this.LockTargetState}`);
|
|
250
366
|
}
|
|
251
367
|
else {
|
|
368
|
+
this.accessory.context.LockTargetState = this.LockTargetState;
|
|
252
369
|
this.lockService.updateCharacteristic(this.platform.Characteristic.LockTargetState, this.LockTargetState);
|
|
253
|
-
this.debugLog(
|
|
370
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic LockTargetState: ${this.LockTargetState}`);
|
|
254
371
|
}
|
|
255
372
|
if (this.LockCurrentState === undefined) {
|
|
256
|
-
this.debugLog(
|
|
373
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockCurrentState: ${this.LockCurrentState}`);
|
|
257
374
|
}
|
|
258
375
|
else {
|
|
376
|
+
this.accessory.context.LockCurrentState = this.LockCurrentState;
|
|
259
377
|
this.lockService.updateCharacteristic(this.platform.Characteristic.LockCurrentState, this.LockCurrentState);
|
|
260
|
-
this.debugLog(
|
|
378
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic LockCurrentState: ${this.LockCurrentState}`);
|
|
261
379
|
}
|
|
262
380
|
}
|
|
263
|
-
async
|
|
264
|
-
if (
|
|
265
|
-
this.
|
|
381
|
+
async BLEPushConnection() {
|
|
382
|
+
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
383
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
|
|
384
|
+
await this.openAPIpushChanges();
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
async BLERefreshConnection(switchbot) {
|
|
388
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
389
|
+
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
390
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
|
|
391
|
+
await this.openAPIRefreshStatus();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
async scan(device) {
|
|
395
|
+
if (device.scanDuration) {
|
|
396
|
+
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
397
|
+
if (this.BLE) {
|
|
398
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
403
|
+
if (this.BLE) {
|
|
404
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
405
|
+
}
|
|
266
406
|
}
|
|
267
|
-
this.lockService.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
268
|
-
this.lockService.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
269
|
-
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
270
407
|
}
|
|
271
408
|
async statusCode({ res }) {
|
|
272
409
|
switch (res.statusCode) {
|
|
273
410
|
case 151:
|
|
274
|
-
this.errorLog(
|
|
411
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
275
412
|
break;
|
|
276
413
|
case 152:
|
|
277
|
-
this.errorLog(
|
|
414
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
|
|
278
415
|
break;
|
|
279
416
|
case 160:
|
|
280
|
-
this.errorLog(
|
|
417
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
|
|
281
418
|
break;
|
|
282
419
|
case 161:
|
|
283
|
-
this.errorLog(
|
|
420
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
|
|
421
|
+
this.offlineOff();
|
|
284
422
|
break;
|
|
285
423
|
case 171:
|
|
286
|
-
this.errorLog(
|
|
424
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
425
|
+
this.offlineOff();
|
|
287
426
|
break;
|
|
288
427
|
case 190:
|
|
289
|
-
this.errorLog(
|
|
290
|
-
` Or command: ${
|
|
428
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
429
|
+
` Or command: ${(0, super_stringify_1.default)(res)} format is invalid`);
|
|
291
430
|
break;
|
|
292
431
|
case 100:
|
|
293
|
-
this.debugLog(
|
|
432
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
|
|
294
433
|
break;
|
|
295
434
|
default:
|
|
296
|
-
this.debugLog(
|
|
435
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
|
|
297
436
|
}
|
|
298
437
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
this.doLockUpdate.next();
|
|
438
|
+
async offlineOff() {
|
|
439
|
+
if (this.device.offline) {
|
|
440
|
+
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.SECURED;
|
|
441
|
+
this.lockService.getCharacteristic(this.platform.Characteristic.LockCurrentState).updateValue(this.LockCurrentState);
|
|
442
|
+
await this.updateHomeKitCharacteristics();
|
|
443
|
+
}
|
|
306
444
|
}
|
|
307
|
-
async
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
config = device.lock;
|
|
445
|
+
async apiError(e) {
|
|
446
|
+
if (!this.device.lock?.hide_contactsensor) {
|
|
447
|
+
this.contactSensorService?.updateCharacteristic(this.platform.Characteristic.ContactSensorState, e);
|
|
311
448
|
}
|
|
312
|
-
|
|
313
|
-
|
|
449
|
+
this.lockService.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
450
|
+
this.lockService.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
451
|
+
}
|
|
452
|
+
FirmwareRevision(accessory, device) {
|
|
453
|
+
let FirmwareRevision;
|
|
454
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
455
|
+
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
456
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
457
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
458
|
+
if (accessory.context.FirmwareRevision) {
|
|
459
|
+
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
314
460
|
}
|
|
315
|
-
if (device.
|
|
316
|
-
|
|
461
|
+
else if (device.firmware) {
|
|
462
|
+
FirmwareRevision = device.firmware;
|
|
317
463
|
}
|
|
318
|
-
|
|
319
|
-
|
|
464
|
+
else {
|
|
465
|
+
FirmwareRevision = this.platform.version;
|
|
320
466
|
}
|
|
321
|
-
|
|
322
|
-
|
|
467
|
+
return FirmwareRevision;
|
|
468
|
+
}
|
|
469
|
+
conext() {
|
|
470
|
+
if (this.LockTargetState === undefined) {
|
|
471
|
+
this.LockTargetState = false;
|
|
323
472
|
}
|
|
324
|
-
|
|
325
|
-
this.
|
|
473
|
+
else {
|
|
474
|
+
this.LockTargetState = this.accessory.context.On;
|
|
326
475
|
}
|
|
327
476
|
}
|
|
328
477
|
async refreshRate(device) {
|
|
329
478
|
if (device.refreshRate) {
|
|
330
479
|
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
331
|
-
this.debugLog(
|
|
480
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
332
481
|
}
|
|
333
482
|
else if (this.platform.config.options.refreshRate) {
|
|
334
483
|
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options.refreshRate;
|
|
335
|
-
this.debugLog(
|
|
484
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
336
485
|
}
|
|
337
486
|
}
|
|
338
|
-
async
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
this.debugLog(`Lock: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
343
|
-
}
|
|
487
|
+
async config(device) {
|
|
488
|
+
let config = {};
|
|
489
|
+
if (device.lock) {
|
|
490
|
+
config = device.lock;
|
|
344
491
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
492
|
+
if (device.connectionType !== undefined) {
|
|
493
|
+
config['connectionType'] = device.connectionType;
|
|
494
|
+
}
|
|
495
|
+
if (device.logging !== undefined) {
|
|
496
|
+
config['logging'] = device.logging;
|
|
497
|
+
}
|
|
498
|
+
if (device.refreshRate !== undefined) {
|
|
499
|
+
config['refreshRate'] = device.refreshRate;
|
|
500
|
+
}
|
|
501
|
+
if (device.scanDuration !== undefined) {
|
|
502
|
+
config['scanDuration'] = device.scanDuration;
|
|
503
|
+
}
|
|
504
|
+
if (Object.entries(config).length !== 0) {
|
|
505
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${(0, super_stringify_1.default)(config)}`);
|
|
350
506
|
}
|
|
351
507
|
}
|
|
352
508
|
async logs(device) {
|
|
353
509
|
if (this.platform.debugMode) {
|
|
354
510
|
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
355
|
-
this.debugLog(
|
|
511
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
356
512
|
}
|
|
357
513
|
else if (device.logging) {
|
|
358
514
|
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
359
|
-
this.debugLog(
|
|
515
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
360
516
|
}
|
|
361
517
|
else if (this.platform.config.options?.logging) {
|
|
362
518
|
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
363
|
-
this.debugLog(
|
|
519
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
364
520
|
}
|
|
365
521
|
else {
|
|
366
522
|
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
367
|
-
this.debugLog(
|
|
523
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
368
524
|
}
|
|
369
525
|
}
|
|
370
|
-
FirmwareRevision(accessory, device) {
|
|
371
|
-
let FirmwareRevision;
|
|
372
|
-
this.debugLog(`Lock: ${this.accessory.displayName} accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
373
|
-
this.debugLog(`Lock: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
374
|
-
this.debugLog(`Lock: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
375
|
-
if (accessory.context.FirmwareRevision) {
|
|
376
|
-
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
377
|
-
}
|
|
378
|
-
else if (device.firmware) {
|
|
379
|
-
FirmwareRevision = device.firmware;
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
FirmwareRevision = this.platform.version;
|
|
383
|
-
}
|
|
384
|
-
return FirmwareRevision;
|
|
385
|
-
}
|
|
386
526
|
/**
|
|
387
527
|
* Logging for Device
|
|
388
528
|
*/
|
|
@@ -396,11 +536,25 @@ class Lock {
|
|
|
396
536
|
this.platform.log.warn(String(...log));
|
|
397
537
|
}
|
|
398
538
|
}
|
|
539
|
+
debugWarnLog(...log) {
|
|
540
|
+
if (this.enablingDeviceLogging()) {
|
|
541
|
+
if (this.deviceLogging?.includes('debug')) {
|
|
542
|
+
this.platform.log.warn('[DEBUG]', String(...log));
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
399
546
|
errorLog(...log) {
|
|
400
547
|
if (this.enablingDeviceLogging()) {
|
|
401
548
|
this.platform.log.error(String(...log));
|
|
402
549
|
}
|
|
403
550
|
}
|
|
551
|
+
debugErrorLog(...log) {
|
|
552
|
+
if (this.enablingDeviceLogging()) {
|
|
553
|
+
if (this.deviceLogging?.includes('debug')) {
|
|
554
|
+
this.platform.log.error('[DEBUG]', String(...log));
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
404
558
|
debugLog(...log) {
|
|
405
559
|
if (this.enablingDeviceLogging()) {
|
|
406
560
|
if (this.deviceLogging === 'debug') {
|