@switchbot/homebridge-switchbot 2.0.0-beta.19 → 2.0.0-beta.20
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 +6 -1
- package/README.md +1 -2
- package/config.schema.json +51 -32
- package/dist/device/bot.d.ts +32 -29
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +549 -575
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +33 -15
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +426 -341
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +16 -9
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +246 -208
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +21 -18
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +449 -449
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +22 -20
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +346 -324
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +22 -10
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +257 -178
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +21 -14
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +287 -239
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +23 -10
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +308 -190
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +17 -10
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +225 -193
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +24 -17
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +270 -267
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +36 -14
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +447 -299
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +7 -14
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +177 -169
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +3 -5
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +72 -57
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +3 -4
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +47 -33
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +3 -4
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +66 -48
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +3 -4
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +48 -47
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +3 -4
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +47 -33
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +10 -11
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +64 -48
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -12
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +52 -41
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +6 -11
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +52 -42
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +0 -4
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +44 -66
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +3 -3
- package/dist/settings.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/device/bot.ts +551 -589
- package/src/device/colorbulb.ts +441 -375
- package/src/device/contact.ts +249 -213
- package/src/device/curtain.ts +452 -461
- package/src/device/humidifier.ts +358 -365
- package/src/device/lock.ts +263 -179
- package/src/device/meter.ts +302 -253
- package/src/device/meterplus.ts +319 -194
- package/src/device/motion.ts +230 -199
- package/src/device/plug.ts +273 -274
- package/src/device/striplight.ts +460 -316
- package/src/irdevice/airconditioner.ts +181 -183
- package/src/irdevice/airpurifier.ts +70 -60
- package/src/irdevice/camera.ts +46 -36
- package/src/irdevice/fan.ts +64 -49
- package/src/irdevice/light.ts +47 -51
- package/src/irdevice/other.ts +46 -36
- package/src/irdevice/tv.ts +64 -51
- package/src/irdevice/vacuumcleaner.ts +52 -45
- package/src/irdevice/waterheater.ts +50 -45
- package/src/platform.ts +44 -68
- package/src/settings.ts +3 -3
package/src/device/lock.ts
CHANGED
|
@@ -25,7 +25,6 @@ export class Lock {
|
|
|
25
25
|
deviceStatus!: any; //deviceStatusResponse;
|
|
26
26
|
|
|
27
27
|
// Config
|
|
28
|
-
OpenAPI?: boolean;
|
|
29
28
|
scanDuration!: number;
|
|
30
29
|
deviceLogging!: string;
|
|
31
30
|
deviceRefreshRate!: number;
|
|
@@ -34,18 +33,17 @@ export class Lock {
|
|
|
34
33
|
lockUpdateInProgress!: boolean;
|
|
35
34
|
doLockUpdate!: Subject<void>;
|
|
36
35
|
|
|
36
|
+
// Connection
|
|
37
|
+
private readonly BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'Both');
|
|
38
|
+
private readonly OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'Both');
|
|
39
|
+
|
|
37
40
|
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
|
|
38
41
|
// default placeholders
|
|
39
42
|
this.logs(device);
|
|
40
|
-
this.openAPI();
|
|
41
43
|
this.scan(device);
|
|
42
44
|
this.refreshRate(device);
|
|
43
45
|
this.config(device);
|
|
44
|
-
|
|
45
|
-
this.LockTargetState = false;
|
|
46
|
-
} else {
|
|
47
|
-
this.LockTargetState = this.accessory.context.On;
|
|
48
|
-
}
|
|
46
|
+
this.conext();
|
|
49
47
|
|
|
50
48
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
51
49
|
this.doLockUpdate = new Subject();
|
|
@@ -122,20 +120,33 @@ export class Lock {
|
|
|
122
120
|
try {
|
|
123
121
|
await this.pushChanges();
|
|
124
122
|
} catch (e: any) {
|
|
125
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges`);
|
|
126
|
-
if (this.deviceLogging.includes('debug')) {
|
|
127
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges,`
|
|
128
|
-
+ ` Error Message: ${superStringify(e.message)}`);
|
|
129
|
-
}
|
|
130
123
|
this.apiError(e);
|
|
124
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
|
|
125
|
+
+ ` Error Message: ${superStringify(e.message)}`);
|
|
131
126
|
}
|
|
132
127
|
this.lockUpdateInProgress = false;
|
|
133
128
|
});
|
|
134
129
|
}
|
|
135
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Parse the device status from the SwitchBot api
|
|
133
|
+
*/
|
|
134
|
+
async parseStatus(): Promise<void> {
|
|
135
|
+
/*if (this.BLE && !this.SwitchToOpenAPI) {
|
|
136
|
+
await this.BLEparseStatus();
|
|
137
|
+
} else*/ if (this.OpenAPI) {
|
|
138
|
+
//this.SwitchToOpenAPI = false;
|
|
139
|
+
await this.openAPIparseStatus();
|
|
140
|
+
} else {
|
|
141
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
142
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
136
146
|
//{"deviceId":"DBDC23B53139","deviceType":"Smart Lock","hubDeviceId":"E68B14109DA2","lockState":"locked","doorState":"opened","calibrate":true}
|
|
137
147
|
|
|
138
|
-
async
|
|
148
|
+
async openAPIparseStatus(): Promise<void> {
|
|
149
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
139
150
|
switch (this.lockState) {
|
|
140
151
|
case 'locked':
|
|
141
152
|
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.SECURED;
|
|
@@ -155,139 +166,215 @@ export class Lock {
|
|
|
155
166
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
|
|
156
167
|
}
|
|
157
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Asks the SwitchBot API for the latest device information
|
|
171
|
+
*/
|
|
158
172
|
async refreshStatus(): Promise<void> {
|
|
159
|
-
if (this.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const data = this.platform.config.credentials?.token + t + nonce;
|
|
164
|
-
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
165
|
-
const sign = signTerm.toString('base64');
|
|
166
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
167
|
-
const options = {
|
|
168
|
-
hostname: HostDomain,
|
|
169
|
-
port: 443,
|
|
170
|
-
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
171
|
-
method: 'GET',
|
|
172
|
-
headers: {
|
|
173
|
-
Authorization: this.platform.config.credentials?.token,
|
|
174
|
-
sign: sign,
|
|
175
|
-
nonce: nonce,
|
|
176
|
-
t: t,
|
|
177
|
-
'Content-Type': 'application/json',
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
const req = https.request(options, (res) => {
|
|
181
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
182
|
-
let rawData = '';
|
|
183
|
-
res.on('data', (d) => {
|
|
184
|
-
rawData += d;
|
|
185
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
186
|
-
});
|
|
187
|
-
res.on('end', () => {
|
|
188
|
-
try {
|
|
189
|
-
this.deviceStatus = JSON.parse(rawData);
|
|
190
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
191
|
-
this.lockState = this.deviceStatus.body.lockState;
|
|
192
|
-
this.doorState = this.deviceStatus.body.doorState;
|
|
193
|
-
this.parseStatus();
|
|
194
|
-
this.updateHomeKitCharacteristics();
|
|
195
|
-
} catch (e: any) {
|
|
196
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
req.on('error', (e: any) => {
|
|
201
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
202
|
-
});
|
|
203
|
-
req.end();
|
|
204
|
-
} catch (e: any) {
|
|
205
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
206
|
-
if (this.deviceLogging.includes('debug')) {
|
|
207
|
-
this.errorLog(
|
|
208
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
|
|
209
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
this.apiError(e);
|
|
213
|
-
}
|
|
173
|
+
/*if (this.BLE) {
|
|
174
|
+
await this.BLERefreshStatus();
|
|
175
|
+
} else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
176
|
+
await this.openAPIRefreshStatus();
|
|
214
177
|
} else {
|
|
215
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
178
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
179
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
216
180
|
}
|
|
217
181
|
}
|
|
218
182
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
* Lock - "command" "lock" "default" = set to ???? state
|
|
223
|
-
* Lock - "command" "unlock" "default" = set to ???? state - LockCurrentState
|
|
224
|
-
*/
|
|
225
|
-
async pushChanges(): Promise<void> {
|
|
226
|
-
if (this.OpenAPI) {
|
|
227
|
-
// Make Push On request to the API
|
|
183
|
+
async openAPIRefreshStatus(): Promise<void> {
|
|
184
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
185
|
+
try {
|
|
228
186
|
const t = Date.now();
|
|
229
187
|
const nonce = 'requestID';
|
|
230
188
|
const data = this.platform.config.credentials?.token + t + nonce;
|
|
231
|
-
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
232
|
-
.update(Buffer.from(data, 'utf-8'))
|
|
233
|
-
.digest();
|
|
189
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
234
190
|
const sign = signTerm.toString('base64');
|
|
235
191
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
236
|
-
let command = '';
|
|
237
|
-
if (this.LockTargetState) {
|
|
238
|
-
command = 'lock';
|
|
239
|
-
} else {
|
|
240
|
-
command = 'unlock';
|
|
241
|
-
}
|
|
242
|
-
const body = superStringify({
|
|
243
|
-
'command': `${command}`,
|
|
244
|
-
'parameter': 'default',
|
|
245
|
-
'commandType': 'command',
|
|
246
|
-
});
|
|
247
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
248
192
|
const options = {
|
|
249
193
|
hostname: HostDomain,
|
|
250
194
|
port: 443,
|
|
251
|
-
path: `${DevicePath}/${this.device.deviceId}/
|
|
252
|
-
method: '
|
|
195
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
196
|
+
method: 'GET',
|
|
253
197
|
headers: {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
198
|
+
Authorization: this.platform.config.credentials?.token,
|
|
199
|
+
sign: sign,
|
|
200
|
+
nonce: nonce,
|
|
201
|
+
t: t,
|
|
258
202
|
'Content-Type': 'application/json',
|
|
259
|
-
'Content-Length': body.length,
|
|
260
203
|
},
|
|
261
204
|
};
|
|
262
|
-
const req = https.request(options, res => {
|
|
263
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
264
|
-
|
|
265
|
-
res.on('data', d => {
|
|
205
|
+
const req = https.request(options, (res) => {
|
|
206
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
|
|
207
|
+
let rawData = '';
|
|
208
|
+
res.on('data', (d) => {
|
|
209
|
+
rawData += d;
|
|
266
210
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
267
211
|
});
|
|
212
|
+
res.on('end', () => {
|
|
213
|
+
try {
|
|
214
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
215
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
216
|
+
this.lockState = this.deviceStatus.body.lockState;
|
|
217
|
+
this.doorState = this.deviceStatus.body.doorState;
|
|
218
|
+
this.parseStatus();
|
|
219
|
+
this.updateHomeKitCharacteristics();
|
|
220
|
+
} catch (e: any) {
|
|
221
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
268
224
|
});
|
|
269
225
|
req.on('error', (e: any) => {
|
|
270
226
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
271
227
|
});
|
|
272
|
-
req.write(body);
|
|
273
228
|
req.end();
|
|
274
|
-
|
|
275
|
-
this.
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
229
|
+
} catch (e: any) {
|
|
230
|
+
this.apiError(e);
|
|
231
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
232
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Pushes the requested changes to the SwitchBot API
|
|
238
|
+
* deviceType commandType Command command parameter Description
|
|
239
|
+
* Lock - "command" "lock" "default" = set to ???? state
|
|
240
|
+
* Lock - "command" "unlock" "default" = set to ???? state - LockCurrentState
|
|
241
|
+
*/
|
|
242
|
+
async pushChanges(): Promise<void> {
|
|
243
|
+
/*if (this.BLE) {
|
|
244
|
+
await this.BLERefreshStatus();
|
|
245
|
+
} else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
246
|
+
await this.openAPIpushChanges();
|
|
247
|
+
} else {
|
|
248
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
249
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
250
|
+
}
|
|
251
|
+
interval(5000)
|
|
252
|
+
.pipe(take(1))
|
|
253
|
+
.subscribe(async () => {
|
|
254
|
+
await this.refreshStatus();
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async BLEpushChanges(): Promise<void> {
|
|
259
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
260
|
+
if (this.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
261
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges LockTargetState: ${this.LockTargetState}`
|
|
262
|
+
+ ` LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
263
|
+
const switchbot = await this.platform.connectBLE();
|
|
264
|
+
// Convert to BLE Address
|
|
265
|
+
this.device.bleMac = this.device
|
|
266
|
+
.deviceId!.match(/.{1,2}/g)!
|
|
267
|
+
.join(':')
|
|
268
|
+
.toLowerCase();
|
|
269
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
270
|
+
switchbot
|
|
271
|
+
.discover({
|
|
272
|
+
model: '',
|
|
273
|
+
id: this.device.bleMac,
|
|
274
|
+
})
|
|
275
|
+
.then(() => {
|
|
276
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
277
|
+
this.LockTargetState = this.platform.Characteristic.LockTargetState.SECURED;
|
|
278
|
+
})
|
|
279
|
+
.catch(async (e: any) => {
|
|
280
|
+
this.apiError(e);
|
|
281
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
282
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
283
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
284
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
285
|
+
await this.openAPIpushChanges();
|
|
286
|
+
}
|
|
280
287
|
});
|
|
281
288
|
} else {
|
|
282
|
-
this.
|
|
289
|
+
this.debugLog(
|
|
290
|
+
`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
|
|
291
|
+
+`LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async openAPIpushChanges(): Promise<void> {
|
|
297
|
+
try {
|
|
298
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
299
|
+
if (this.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
300
|
+
// Make Push On request to the API
|
|
301
|
+
const t = Date.now();
|
|
302
|
+
const nonce = 'requestID';
|
|
303
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
304
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
305
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
306
|
+
.digest();
|
|
307
|
+
const sign = signTerm.toString('base64');
|
|
308
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
309
|
+
let command = '';
|
|
310
|
+
if (this.LockTargetState) {
|
|
311
|
+
command = 'lock';
|
|
312
|
+
} else {
|
|
313
|
+
command = 'unlock';
|
|
314
|
+
}
|
|
315
|
+
const body = superStringify({
|
|
316
|
+
'command': `${command}`,
|
|
317
|
+
'parameter': 'default',
|
|
318
|
+
'commandType': 'command',
|
|
319
|
+
});
|
|
320
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
321
|
+
const options = {
|
|
322
|
+
hostname: HostDomain,
|
|
323
|
+
port: 443,
|
|
324
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
325
|
+
method: 'POST',
|
|
326
|
+
headers: {
|
|
327
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
328
|
+
'sign': sign,
|
|
329
|
+
'nonce': nonce,
|
|
330
|
+
't': t,
|
|
331
|
+
'Content-Type': 'application/json',
|
|
332
|
+
'Content-Length': body.length,
|
|
333
|
+
},
|
|
334
|
+
};
|
|
335
|
+
const req = https.request(options, res => {
|
|
336
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
|
|
337
|
+
this.statusCode({ res });
|
|
338
|
+
res.on('data', d => {
|
|
339
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
req.on('error', (e: any) => {
|
|
343
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
344
|
+
});
|
|
345
|
+
req.write(body);
|
|
346
|
+
req.end();
|
|
347
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges: ${superStringify(req)}`);
|
|
348
|
+
} else {
|
|
349
|
+
this.debugLog(
|
|
350
|
+
`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
|
|
351
|
+
+`LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
} catch (e: any) {
|
|
355
|
+
this.apiError(e);
|
|
356
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
357
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`,
|
|
358
|
+
);
|
|
283
359
|
}
|
|
284
360
|
}
|
|
285
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Handle requests to set the value of the "On" characteristic
|
|
364
|
+
*/
|
|
365
|
+
async LockTargetStateSet(value: CharacteristicValue): Promise<void> {
|
|
366
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
|
|
367
|
+
|
|
368
|
+
this.LockTargetState = value;
|
|
369
|
+
this.doLockUpdate.next();
|
|
370
|
+
}
|
|
371
|
+
|
|
286
372
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
287
373
|
if (!this.device.lock?.hide_contactsensor) {
|
|
288
374
|
if (this.ContactSensorState === undefined) {
|
|
289
375
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
290
376
|
} else {
|
|
377
|
+
this.accessory.context.ContactSensorState = this.ContactSensorState;
|
|
291
378
|
this.contactSensorService?.updateCharacteristic(this.platform.Characteristic.ContactSensorState, this.ContactSensorState);
|
|
292
379
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic ContactSensorState: ${this.ContactSensorState}`);
|
|
293
380
|
}
|
|
@@ -295,24 +382,31 @@ export class Lock {
|
|
|
295
382
|
if (this.LockTargetState === undefined) {
|
|
296
383
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockTargetState: ${this.LockTargetState}`);
|
|
297
384
|
} else {
|
|
385
|
+
this.accessory.context.LockTargetState = this.LockTargetState;
|
|
298
386
|
this.lockService.updateCharacteristic(this.platform.Characteristic.LockTargetState, this.LockTargetState);
|
|
299
387
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic LockTargetState: ${this.LockTargetState}`);
|
|
300
388
|
}
|
|
301
389
|
if (this.LockCurrentState === undefined) {
|
|
302
390
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockCurrentState: ${this.LockCurrentState}`);
|
|
303
391
|
} else {
|
|
392
|
+
this.accessory.context.LockCurrentState = this.LockCurrentState;
|
|
304
393
|
this.lockService.updateCharacteristic(this.platform.Characteristic.LockCurrentState, this.LockCurrentState);
|
|
305
394
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic LockCurrentState: ${this.LockCurrentState}`);
|
|
306
395
|
}
|
|
307
396
|
}
|
|
308
397
|
|
|
309
|
-
async
|
|
310
|
-
if (
|
|
311
|
-
this.
|
|
398
|
+
async scan(device: device & devicesConfig): Promise<void> {
|
|
399
|
+
if (device.scanDuration) {
|
|
400
|
+
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
401
|
+
if (this.BLE) {
|
|
402
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
406
|
+
if (this.BLE) {
|
|
407
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
408
|
+
}
|
|
312
409
|
}
|
|
313
|
-
this.lockService.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
314
|
-
this.lockService.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
315
|
-
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
316
410
|
}
|
|
317
411
|
|
|
318
412
|
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
@@ -328,9 +422,11 @@ export class Lock {
|
|
|
328
422
|
break;
|
|
329
423
|
case 161:
|
|
330
424
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
|
|
425
|
+
this.offlineOff();
|
|
331
426
|
break;
|
|
332
427
|
case 171:
|
|
333
428
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
429
|
+
this.offlineOff();
|
|
334
430
|
break;
|
|
335
431
|
case 190:
|
|
336
432
|
this.errorLog(
|
|
@@ -346,14 +442,54 @@ export class Lock {
|
|
|
346
442
|
}
|
|
347
443
|
}
|
|
348
444
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
445
|
+
async offlineOff(): Promise<void> {
|
|
446
|
+
if (this.device.offline) {
|
|
447
|
+
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.SECURED;
|
|
448
|
+
this.lockService.getCharacteristic(this.platform.Characteristic.LockCurrentState).updateValue(this.LockCurrentState);
|
|
449
|
+
await this.updateHomeKitCharacteristics();
|
|
450
|
+
}
|
|
451
|
+
}
|
|
354
452
|
|
|
355
|
-
|
|
356
|
-
this.
|
|
453
|
+
async apiError(e: any): Promise<void> {
|
|
454
|
+
if (!this.device.lock?.hide_contactsensor) {
|
|
455
|
+
this.contactSensorService?.updateCharacteristic(this.platform.Characteristic.ContactSensorState, e);
|
|
456
|
+
}
|
|
457
|
+
this.lockService.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
458
|
+
this.lockService.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
|
|
462
|
+
let FirmwareRevision: string;
|
|
463
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
464
|
+
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
465
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
466
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
467
|
+
if (accessory.context.FirmwareRevision) {
|
|
468
|
+
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
469
|
+
} else if (device.firmware) {
|
|
470
|
+
FirmwareRevision = device.firmware;
|
|
471
|
+
} else {
|
|
472
|
+
FirmwareRevision = this.platform.version;
|
|
473
|
+
}
|
|
474
|
+
return FirmwareRevision;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
private conext() {
|
|
478
|
+
if (this.LockTargetState === undefined) {
|
|
479
|
+
this.LockTargetState = false;
|
|
480
|
+
} else {
|
|
481
|
+
this.LockTargetState = this.accessory.context.On;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
486
|
+
if (device.refreshRate) {
|
|
487
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
488
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
489
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
490
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
491
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
492
|
+
}
|
|
357
493
|
}
|
|
358
494
|
|
|
359
495
|
async config(device: device & devicesConfig): Promise<void> {
|
|
@@ -361,11 +497,8 @@ export class Lock {
|
|
|
361
497
|
if (device.lock) {
|
|
362
498
|
config = device.lock;
|
|
363
499
|
}
|
|
364
|
-
if (device.
|
|
365
|
-
config['
|
|
366
|
-
}
|
|
367
|
-
if (device.openAPI !== undefined) {
|
|
368
|
-
config['openAPI'] = device.openAPI;
|
|
500
|
+
if (device.connectionType !== undefined) {
|
|
501
|
+
config['connectionType'] = device.connectionType;
|
|
369
502
|
}
|
|
370
503
|
if (device.logging !== undefined) {
|
|
371
504
|
config['logging'] = device.logging;
|
|
@@ -381,39 +514,6 @@ export class Lock {
|
|
|
381
514
|
}
|
|
382
515
|
}
|
|
383
516
|
|
|
384
|
-
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
385
|
-
if (device.refreshRate) {
|
|
386
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
387
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
388
|
-
} else if (this.platform.config.options!.refreshRate) {
|
|
389
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
390
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
async openAPI() {
|
|
395
|
-
if (!this.device.openAPI) {
|
|
396
|
-
this.OpenAPI = true;
|
|
397
|
-
} else {
|
|
398
|
-
this.OpenAPI = this.device.openAPI;
|
|
399
|
-
}
|
|
400
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI: ${this.OpenAPI}`);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
async scan(device: device & devicesConfig): Promise<void> {
|
|
404
|
-
if (device.scanDuration) {
|
|
405
|
-
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
406
|
-
if (device.ble) {
|
|
407
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
408
|
-
}
|
|
409
|
-
} else {
|
|
410
|
-
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
411
|
-
if (this.device.ble) {
|
|
412
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
517
|
async logs(device: device & devicesConfig): Promise<void> {
|
|
418
518
|
if (this.platform.debugMode) {
|
|
419
519
|
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
@@ -430,22 +530,6 @@ export class Lock {
|
|
|
430
530
|
}
|
|
431
531
|
}
|
|
432
532
|
|
|
433
|
-
FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
|
|
434
|
-
let FirmwareRevision: string;
|
|
435
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
436
|
-
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
437
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
438
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
439
|
-
if (accessory.context.FirmwareRevision) {
|
|
440
|
-
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
441
|
-
} else if (device.firmware) {
|
|
442
|
-
FirmwareRevision = device.firmware;
|
|
443
|
-
} else {
|
|
444
|
-
FirmwareRevision = this.platform.version;
|
|
445
|
-
}
|
|
446
|
-
return FirmwareRevision;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
533
|
/**
|
|
450
534
|
* Logging for Device
|
|
451
535
|
*/
|