@switchbot/homebridge-switchbot 2.0.0-beta.8 → 2.0.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/CHANGELOG.md +10 -1
- package/README.md +3 -2
- package/config.schema.json +91 -19
- package/dist/device/bot.d.ts +34 -28
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +657 -648
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +137 -0
- package/dist/device/ceilinglight.d.ts.map +1 -0
- package/dist/device/ceilinglight.js +1127 -0
- package/dist/device/ceilinglight.js.map +1 -0
- package/dist/device/colorbulb.d.ts +36 -19
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +486 -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 +306 -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 +566 -502
- 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 +453 -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 +305 -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 +367 -267
- 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 +381 -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 +279 -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 +295 -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 +506 -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 +278 -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 +154 -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 +133 -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 +160 -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 +137 -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 +145 -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 +143 -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 +132 -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 +132 -89
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +13 -12
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +524 -418
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +19 -11
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/homebridge-ui/public/index.html +1 -0
- package/package.json +11 -9
- package/src/device/bot.ts +656 -659
- package/src/device/ceilinglight.ts +1208 -0
- package/src/device/colorbulb.ts +490 -344
- package/src/device/contact.ts +309 -241
- package/src/device/curtain.ts +571 -516
- package/src/device/humidifier.ts +456 -403
- package/src/device/lock.ts +314 -149
- package/src/device/meter.ts +378 -280
- package/src/device/meterplus.ts +391 -219
- package/src/device/motion.ts +285 -222
- package/src/device/plug.ts +299 -260
- package/src/device/striplight.ts +522 -289
- package/src/irdevice/airconditioner.ts +282 -241
- package/src/irdevice/airpurifier.ts +151 -103
- package/src/irdevice/camera.ts +131 -85
- package/src/irdevice/fan.ts +157 -106
- package/src/irdevice/light.ts +135 -103
- package/src/irdevice/other.ts +143 -97
- package/src/irdevice/tv.ts +142 -93
- package/src/irdevice/vacuumcleaner.ts +131 -89
- package/src/irdevice/waterheater.ts +130 -89
- package/src/platform.ts +522 -446
- package/src/settings.ts +20 -11
- package/.github/npm-version-script.js +0 -81
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,50 @@ 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`);
|
|
113
|
+
switch (this.lockState) {
|
|
114
|
+
case 'locked':
|
|
115
|
+
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.SECURED;
|
|
116
|
+
this.LockTargetState = this.platform.Characteristic.LockTargetState.SECURED;
|
|
117
|
+
break;
|
|
118
|
+
default:
|
|
119
|
+
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.UNSECURED;
|
|
120
|
+
this.LockTargetState = this.platform.Characteristic.LockTargetState.UNSECURED;
|
|
121
|
+
}
|
|
122
|
+
switch (this.doorState) {
|
|
123
|
+
case 'opened':
|
|
124
|
+
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
125
|
+
break;
|
|
126
|
+
default:
|
|
127
|
+
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
128
|
+
}
|
|
129
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
|
|
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`);
|
|
102
134
|
switch (this.lockState) {
|
|
103
135
|
case 'locked':
|
|
104
136
|
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.SECURED;
|
|
@@ -115,16 +147,31 @@ class Lock {
|
|
|
115
147
|
default:
|
|
116
148
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
|
|
117
149
|
}
|
|
118
|
-
this.debugLog(
|
|
150
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
|
|
119
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,308 @@ 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.BLEpushChanges();
|
|
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.external !== undefined) {
|
|
496
|
+
config['external'] = device.external;
|
|
497
|
+
}
|
|
498
|
+
if (device.logging !== undefined) {
|
|
499
|
+
config['logging'] = device.logging;
|
|
500
|
+
}
|
|
501
|
+
if (device.refreshRate !== undefined) {
|
|
502
|
+
config['refreshRate'] = device.refreshRate;
|
|
503
|
+
}
|
|
504
|
+
if (device.scanDuration !== undefined) {
|
|
505
|
+
config['scanDuration'] = device.scanDuration;
|
|
506
|
+
}
|
|
507
|
+
if (Object.entries(config).length !== 0) {
|
|
508
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${(0, super_stringify_1.default)(config)}`);
|
|
350
509
|
}
|
|
351
510
|
}
|
|
352
511
|
async logs(device) {
|
|
353
512
|
if (this.platform.debugMode) {
|
|
354
513
|
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
355
|
-
this.debugLog(
|
|
514
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
356
515
|
}
|
|
357
516
|
else if (device.logging) {
|
|
358
517
|
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
359
|
-
this.debugLog(
|
|
518
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
360
519
|
}
|
|
361
520
|
else if (this.platform.config.options?.logging) {
|
|
362
521
|
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
363
|
-
this.debugLog(
|
|
522
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
364
523
|
}
|
|
365
524
|
else {
|
|
366
525
|
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
367
|
-
this.debugLog(
|
|
526
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
368
527
|
}
|
|
369
528
|
}
|
|
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
529
|
/**
|
|
387
530
|
* Logging for Device
|
|
388
531
|
*/
|
|
@@ -396,11 +539,25 @@ class Lock {
|
|
|
396
539
|
this.platform.log.warn(String(...log));
|
|
397
540
|
}
|
|
398
541
|
}
|
|
542
|
+
debugWarnLog(...log) {
|
|
543
|
+
if (this.enablingDeviceLogging()) {
|
|
544
|
+
if (this.deviceLogging?.includes('debug')) {
|
|
545
|
+
this.platform.log.warn('[DEBUG]', String(...log));
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
399
549
|
errorLog(...log) {
|
|
400
550
|
if (this.enablingDeviceLogging()) {
|
|
401
551
|
this.platform.log.error(String(...log));
|
|
402
552
|
}
|
|
403
553
|
}
|
|
554
|
+
debugErrorLog(...log) {
|
|
555
|
+
if (this.enablingDeviceLogging()) {
|
|
556
|
+
if (this.deviceLogging?.includes('debug')) {
|
|
557
|
+
this.platform.log.error('[DEBUG]', String(...log));
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
404
561
|
debugLog(...log) {
|
|
405
562
|
if (this.enablingDeviceLogging()) {
|
|
406
563
|
if (this.deviceLogging === 'debug') {
|