@switchbot/homebridge-switchbot 2.0.0-beta.2 → 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 +8 -1
- package/README.md +1 -2
- package/config.schema.json +75 -20
- package/dist/device/bot.d.ts +32 -28
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +646 -648
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +34 -19
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +429 -304
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +16 -7
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +288 -230
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +21 -16
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +519 -489
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +22 -18
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +415 -360
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +22 -8
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +253 -147
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +21 -16
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +325 -255
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +23 -12
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +346 -208
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +17 -8
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +261 -209
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +24 -16
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +267 -242
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +51 -16
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +527 -185
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +7 -12
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +261 -230
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +3 -3
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +137 -104
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +9 -8
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +116 -86
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +8 -7
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +143 -109
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +9 -8
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +120 -103
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +9 -8
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +128 -98
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +10 -9
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +126 -93
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -10
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +115 -89
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +6 -9
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +115 -89
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +3 -5
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +203 -200
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +15 -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 +641 -657
- package/src/device/colorbulb.ts +440 -339
- package/src/device/contact.ts +289 -233
- package/src/device/curtain.ts +523 -503
- package/src/device/humidifier.ts +421 -396
- package/src/device/lock.ts +257 -147
- package/src/device/meter.ts +335 -268
- package/src/device/meterplus.ts +354 -213
- package/src/device/motion.ts +264 -213
- package/src/device/plug.ts +270 -251
- package/src/device/striplight.ts +552 -207
- package/src/irdevice/airconditioner.ts +263 -241
- package/src/irdevice/airpurifier.ts +132 -103
- package/src/irdevice/camera.ts +112 -85
- package/src/irdevice/fan.ts +138 -106
- package/src/irdevice/light.ts +116 -103
- package/src/irdevice/other.ts +124 -97
- package/src/irdevice/tv.ts +123 -93
- package/src/irdevice/vacuumcleaner.ts +112 -89
- package/src/irdevice/waterheater.ts +111 -89
- package/src/platform.ts +195 -216
- package/src/settings.ts +15 -11
package/src/device/bot.ts
CHANGED
|
@@ -3,6 +3,7 @@ import crypto from 'crypto';
|
|
|
3
3
|
import { Context } from 'vm';
|
|
4
4
|
import { IncomingMessage } from 'http';
|
|
5
5
|
import { interval, Subject } from 'rxjs';
|
|
6
|
+
import superStringify from 'super-stringify';
|
|
6
7
|
import { SwitchBotPlatform } from '../platform';
|
|
7
8
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
8
9
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
@@ -29,7 +30,6 @@ export class Bot {
|
|
|
29
30
|
|
|
30
31
|
// Characteristic Values
|
|
31
32
|
On!: CharacteristicValue;
|
|
32
|
-
OnCached!: CharacteristicValue;
|
|
33
33
|
BatteryLevel!: CharacteristicValue;
|
|
34
34
|
StatusLowBattery!: CharacteristicValue;
|
|
35
35
|
|
|
@@ -40,9 +40,9 @@ export class Bot {
|
|
|
40
40
|
// BLE Others
|
|
41
41
|
connected?: boolean;
|
|
42
42
|
switchbot!: switchbot;
|
|
43
|
-
SwitchToOpenAPI?: boolean;
|
|
44
43
|
serviceData!: serviceData;
|
|
45
44
|
address!: ad['address'];
|
|
45
|
+
SwitchToOpenAPI?: boolean;
|
|
46
46
|
mode!: serviceData['mode'];
|
|
47
47
|
state!: serviceData['state'];
|
|
48
48
|
battery!: serviceData['battery'];
|
|
@@ -61,6 +61,10 @@ export class Bot {
|
|
|
61
61
|
botUpdateInProgress!: boolean;
|
|
62
62
|
doBotUpdate!: Subject<void>;
|
|
63
63
|
|
|
64
|
+
// Connection
|
|
65
|
+
private readonly BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'Both');
|
|
66
|
+
private readonly OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'Both');
|
|
67
|
+
|
|
64
68
|
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
|
|
65
69
|
// default placeholders
|
|
66
70
|
this.logs(device);
|
|
@@ -69,20 +73,8 @@ export class Bot {
|
|
|
69
73
|
this.PressOrSwitch(device);
|
|
70
74
|
this.allowPushChanges(device);
|
|
71
75
|
this.config(device);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.accessory.context.On = this.On;
|
|
75
|
-
} else {
|
|
76
|
-
this.On = this.accessory.context.On;
|
|
77
|
-
}
|
|
78
|
-
if (device.bot?.doublePress) {
|
|
79
|
-
this.doublePress = device.bot?.doublePress;
|
|
80
|
-
this.accessory.context.doublePress = this.doublePress;
|
|
81
|
-
} else {
|
|
82
|
-
this.doublePress = 1;
|
|
83
|
-
}
|
|
84
|
-
this.BatteryLevel = 100;
|
|
85
|
-
this.StatusLowBattery = 0;
|
|
76
|
+
this.context();
|
|
77
|
+
this.DoublePress(device);
|
|
86
78
|
|
|
87
79
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
88
80
|
this.doBotUpdate = new Subject();
|
|
@@ -117,10 +109,10 @@ export class Bot {
|
|
|
117
109
|
// Add switchService
|
|
118
110
|
(this.switchService = accessory.getService(this.platform.Service.Switch) || accessory.addService(this.platform.Service.Switch)),
|
|
119
111
|
`${accessory.displayName} Switch`;
|
|
120
|
-
this.infoLog(
|
|
112
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Switch`);
|
|
121
113
|
|
|
122
114
|
this.switchService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
123
|
-
this.switchService.getCharacteristic(this.platform.Characteristic.On).onSet(this.
|
|
115
|
+
this.switchService.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
124
116
|
} else if (device.bot?.deviceType === 'garagedoor') {
|
|
125
117
|
this.removeFanService(accessory);
|
|
126
118
|
this.removeLockService(accessory);
|
|
@@ -136,10 +128,10 @@ export class Bot {
|
|
|
136
128
|
(this.garageDoorService =
|
|
137
129
|
accessory.getService(this.platform.Service.GarageDoorOpener) || accessory.addService(this.platform.Service.GarageDoorOpener)),
|
|
138
130
|
`${accessory.displayName} Garage Door Opener`;
|
|
139
|
-
this.infoLog(
|
|
131
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Garage Door Opener`);
|
|
140
132
|
|
|
141
133
|
this.garageDoorService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
142
|
-
this.garageDoorService.getCharacteristic(this.platform.Characteristic.TargetDoorState).onSet(this.
|
|
134
|
+
this.garageDoorService.getCharacteristic(this.platform.Characteristic.TargetDoorState).onSet(this.OnSet.bind(this));
|
|
143
135
|
this.garageDoorService.setCharacteristic(this.platform.Characteristic.ObstructionDetected, false);
|
|
144
136
|
} else if (device.bot?.deviceType === 'door') {
|
|
145
137
|
this.removeFanService(accessory);
|
|
@@ -155,7 +147,7 @@ export class Bot {
|
|
|
155
147
|
// Add switchService
|
|
156
148
|
(this.doorService = accessory.getService(this.platform.Service.Door) || accessory.addService(this.platform.Service.Door)),
|
|
157
149
|
`${accessory.displayName} Door`;
|
|
158
|
-
this.infoLog(
|
|
150
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Door`);
|
|
159
151
|
|
|
160
152
|
this.doorService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
161
153
|
this.doorService
|
|
@@ -166,7 +158,7 @@ export class Bot {
|
|
|
166
158
|
maxValue: 100,
|
|
167
159
|
minStep: 100,
|
|
168
160
|
})
|
|
169
|
-
.onSet(this.
|
|
161
|
+
.onSet(this.OnSet.bind(this));
|
|
170
162
|
this.doorService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
171
163
|
} else if (device.bot?.deviceType === 'window') {
|
|
172
164
|
this.removeFanService(accessory);
|
|
@@ -182,7 +174,7 @@ export class Bot {
|
|
|
182
174
|
// Add switchService
|
|
183
175
|
(this.windowService = accessory.getService(this.platform.Service.Window) || accessory.addService(this.platform.Service.Window)),
|
|
184
176
|
`${accessory.displayName} Window`;
|
|
185
|
-
this.infoLog(
|
|
177
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Window`);
|
|
186
178
|
|
|
187
179
|
this.windowService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
188
180
|
this.windowService
|
|
@@ -193,7 +185,7 @@ export class Bot {
|
|
|
193
185
|
maxValue: 100,
|
|
194
186
|
minStep: 100,
|
|
195
187
|
})
|
|
196
|
-
.onSet(this.
|
|
188
|
+
.onSet(this.OnSet.bind(this));
|
|
197
189
|
this.windowService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
198
190
|
} else if (device.bot?.deviceType === 'windowcovering') {
|
|
199
191
|
this.removeFanService(accessory);
|
|
@@ -210,7 +202,7 @@ export class Bot {
|
|
|
210
202
|
(this.windowCoveringService =
|
|
211
203
|
accessory.getService(this.platform.Service.WindowCovering) || accessory.addService(this.platform.Service.WindowCovering)),
|
|
212
204
|
`${accessory.displayName} Window Covering`;
|
|
213
|
-
this.infoLog(
|
|
205
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Window Covering`);
|
|
214
206
|
|
|
215
207
|
this.windowCoveringService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
216
208
|
this.windowCoveringService
|
|
@@ -221,7 +213,7 @@ export class Bot {
|
|
|
221
213
|
maxValue: 100,
|
|
222
214
|
minStep: 100,
|
|
223
215
|
})
|
|
224
|
-
.onSet(this.
|
|
216
|
+
.onSet(this.OnSet.bind(this));
|
|
225
217
|
this.windowCoveringService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
226
218
|
} else if (device.bot?.deviceType === 'lock') {
|
|
227
219
|
this.removeFanService(accessory);
|
|
@@ -237,10 +229,10 @@ export class Bot {
|
|
|
237
229
|
// Add switchService
|
|
238
230
|
(this.lockService = accessory.getService(this.platform.Service.LockMechanism) || accessory.addService(this.platform.Service.LockMechanism)),
|
|
239
231
|
`${accessory.displayName} Lock`;
|
|
240
|
-
this.infoLog(
|
|
232
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Lock`);
|
|
241
233
|
|
|
242
234
|
this.lockService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
243
|
-
this.lockService.getCharacteristic(this.platform.Characteristic.LockTargetState).onSet(this.
|
|
235
|
+
this.lockService.getCharacteristic(this.platform.Characteristic.LockTargetState).onSet(this.OnSet.bind(this));
|
|
244
236
|
} else if (device.bot?.deviceType === 'faucet') {
|
|
245
237
|
this.removeFanService(accessory);
|
|
246
238
|
this.removeLockService(accessory);
|
|
@@ -255,10 +247,10 @@ export class Bot {
|
|
|
255
247
|
// Add switchService
|
|
256
248
|
(this.faucetService = accessory.getService(this.platform.Service.Faucet) || accessory.addService(this.platform.Service.Faucet)),
|
|
257
249
|
`${accessory.displayName} Faucet`;
|
|
258
|
-
this.infoLog(
|
|
250
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Faucet`);
|
|
259
251
|
|
|
260
252
|
this.faucetService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
261
|
-
this.faucetService.getCharacteristic(this.platform.Characteristic.Active).onSet(this.
|
|
253
|
+
this.faucetService.getCharacteristic(this.platform.Characteristic.Active).onSet(this.OnSet.bind(this));
|
|
262
254
|
} else if (device.bot?.deviceType === 'fan') {
|
|
263
255
|
this.removeLockService(accessory);
|
|
264
256
|
this.removeDoorService(accessory);
|
|
@@ -273,10 +265,10 @@ export class Bot {
|
|
|
273
265
|
// Add switchService
|
|
274
266
|
(this.fanService = accessory.getService(this.platform.Service.Fan) || accessory.addService(this.platform.Service.Fan)),
|
|
275
267
|
`${accessory.displayName} Fan`;
|
|
276
|
-
this.infoLog(
|
|
268
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Fan`);
|
|
277
269
|
|
|
278
270
|
this.fanService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
279
|
-
this.fanService.getCharacteristic(this.platform.Characteristic.On).onSet(this.
|
|
271
|
+
this.fanService.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
280
272
|
} else if (device.bot?.deviceType === 'stateful') {
|
|
281
273
|
this.removeFanService(accessory);
|
|
282
274
|
this.removeLockService(accessory);
|
|
@@ -293,12 +285,12 @@ export class Bot {
|
|
|
293
285
|
accessory.getService(this.platform.Service.StatefulProgrammableSwitch) ||
|
|
294
286
|
accessory.addService(this.platform.Service.StatefulProgrammableSwitch)),
|
|
295
287
|
`${accessory.displayName} Stateful Programmable Switch`;
|
|
296
|
-
this.infoLog(
|
|
288
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Stateful Programmable Switch`);
|
|
297
289
|
|
|
298
290
|
this.statefulProgrammableSwitchService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
299
291
|
this.statefulProgrammableSwitchService
|
|
300
292
|
.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState)
|
|
301
|
-
.onSet(this.
|
|
293
|
+
.onSet(this.OnSet.bind(this));
|
|
302
294
|
} else {
|
|
303
295
|
this.removeFanService(accessory);
|
|
304
296
|
this.removeLockService(accessory);
|
|
@@ -313,25 +305,25 @@ export class Bot {
|
|
|
313
305
|
// Add outletService
|
|
314
306
|
(this.outletService = accessory.getService(this.platform.Service.Outlet) || accessory.addService(this.platform.Service.Outlet)),
|
|
315
307
|
`${accessory.displayName} Outlet`;
|
|
316
|
-
this.infoLog(
|
|
308
|
+
this.infoLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Outlet`);
|
|
317
309
|
|
|
318
310
|
this.outletService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
319
|
-
this.outletService.getCharacteristic(this.platform.Characteristic.On).onSet(this.
|
|
311
|
+
this.outletService.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
320
312
|
}
|
|
321
313
|
|
|
322
314
|
// Battery Service
|
|
323
|
-
if (!
|
|
324
|
-
this.debugLog(
|
|
315
|
+
if (!this.BLE) {
|
|
316
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Battery Service`);
|
|
325
317
|
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
326
318
|
accessory.removeService(this.batteryService!);
|
|
327
|
-
} else if (
|
|
328
|
-
this.debugLog(
|
|
319
|
+
} else if (this.BLE && !this.batteryService) {
|
|
320
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Battery Service`);
|
|
329
321
|
(this.batteryService = this.accessory.getService(this.platform.Service.Battery) || this.accessory.addService(this.platform.Service.Battery)),
|
|
330
322
|
`${accessory.displayName} Battery`;
|
|
331
323
|
|
|
332
324
|
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
333
325
|
} else {
|
|
334
|
-
this.debugLog(
|
|
326
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Battery Service Not Added`);
|
|
335
327
|
}
|
|
336
328
|
|
|
337
329
|
// Retrieve initial values and updateHomekit
|
|
@@ -345,29 +337,25 @@ export class Bot {
|
|
|
345
337
|
});
|
|
346
338
|
|
|
347
339
|
// Watch for Bot change events
|
|
348
|
-
// We put in a debounce of
|
|
340
|
+
// We put in a debounce of 1000ms so we don't make duplicate calls
|
|
349
341
|
this.doBotUpdate
|
|
350
342
|
.pipe(
|
|
351
343
|
tap(() => {
|
|
352
344
|
this.botUpdateInProgress = true;
|
|
353
345
|
}),
|
|
354
|
-
debounceTime(
|
|
346
|
+
debounceTime(this.platform.config.options!.pushRate! * 1000),
|
|
355
347
|
)
|
|
356
348
|
.subscribe(async () => {
|
|
357
349
|
try {
|
|
358
|
-
interval(
|
|
350
|
+
interval(15000)
|
|
359
351
|
.pipe(take(this.doublePress!))
|
|
360
352
|
.subscribe(async () => {
|
|
361
353
|
await this.pushChanges();
|
|
362
354
|
});
|
|
363
355
|
} catch (e: any) {
|
|
364
|
-
this.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
}
|
|
368
|
-
if (this.platform.debugMode) {
|
|
369
|
-
this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges,` + ` Error: ${JSON.stringify(e)}`);
|
|
370
|
-
}
|
|
356
|
+
this.apiError(e);
|
|
357
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
|
|
358
|
+
+ ` Error Message: ${superStringify(e.message)}`);
|
|
371
359
|
}
|
|
372
360
|
this.botUpdateInProgress = false;
|
|
373
361
|
});
|
|
@@ -377,28 +365,30 @@ export class Bot {
|
|
|
377
365
|
* Parse the device status from the SwitchBot api
|
|
378
366
|
*/
|
|
379
367
|
async parseStatus(): Promise<void> {
|
|
380
|
-
if (this.
|
|
368
|
+
if (this.BLE && !this.SwitchToOpenAPI) {
|
|
369
|
+
await this.BLEparseStatus();
|
|
370
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
371
|
+
this.SwitchToOpenAPI = false;
|
|
381
372
|
await this.openAPIparseStatus();
|
|
382
373
|
} else {
|
|
383
|
-
|
|
374
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
375
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
384
376
|
}
|
|
385
377
|
}
|
|
386
378
|
|
|
387
379
|
async BLEparseStatus(): Promise<void> {
|
|
388
|
-
this.debugLog(
|
|
380
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
389
381
|
// BLEmode (true if Switch Mode) | (false if Press Mode)
|
|
390
382
|
if (this.mode) {
|
|
391
|
-
this.
|
|
392
|
-
this.accessory.context.On = this.OnCached;
|
|
383
|
+
this.accessory.context.On = this.On;
|
|
393
384
|
if (this.On === undefined) {
|
|
394
385
|
this.On = Boolean(this.state);
|
|
395
386
|
}
|
|
396
|
-
this.debugLog(
|
|
387
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, mode: ${this.mode}, On: ${this.On}`);
|
|
397
388
|
} else {
|
|
398
389
|
this.On = false;
|
|
399
|
-
this.
|
|
400
|
-
this.accessory.
|
|
401
|
-
this.debugLog(`Bot: ${this.accessory.displayName} Press Mode, mode: ${this.mode}, On: ${this.On}`);
|
|
390
|
+
this.accessory.context.On = this.On;
|
|
391
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode, mode: ${this.mode}, On: ${this.On}`);
|
|
402
392
|
}
|
|
403
393
|
|
|
404
394
|
this.BatteryLevel = Number(this.battery);
|
|
@@ -410,207 +400,155 @@ export class Bot {
|
|
|
410
400
|
if (Number.isNaN(this.BatteryLevel)) {
|
|
411
401
|
this.BatteryLevel = 100;
|
|
412
402
|
}
|
|
413
|
-
this.debugLog(
|
|
403
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
414
404
|
}
|
|
415
405
|
|
|
416
406
|
async openAPIparseStatus(): Promise<void> {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
407
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
408
|
+
if (this.botMode === 'press') {
|
|
409
|
+
this.On = false;
|
|
410
|
+
this.accessory.context.On = this.On;
|
|
411
|
+
} else {
|
|
412
|
+
this.accessory.context.On = this.On;
|
|
413
|
+
if (this.On === undefined) {
|
|
423
414
|
this.On = false;
|
|
424
|
-
this.OnCached = this.On;
|
|
425
|
-
this.accessory.context.On = this.OnCached;
|
|
426
|
-
} else {
|
|
427
|
-
/*if (this.power === 'on') {
|
|
428
|
-
this.On = true;
|
|
429
|
-
this.OnCached = this.On;
|
|
430
|
-
this.accessory.context.On = this.OnCached;
|
|
431
|
-
} else {
|
|
432
|
-
this.On = false;
|
|
433
|
-
this.OnCached = this.On;
|
|
434
|
-
this.accessory.context.On = this.OnCached;
|
|
435
|
-
}*/
|
|
436
|
-
this.OnCached = this.On;
|
|
437
|
-
this.accessory.context.On = this.OnCached;
|
|
438
|
-
if (this.On === undefined) {
|
|
439
|
-
this.On = false;
|
|
440
|
-
}
|
|
441
415
|
}
|
|
442
|
-
this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
|
|
443
416
|
}
|
|
417
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
444
418
|
}
|
|
445
419
|
|
|
446
420
|
/**
|
|
447
421
|
* Asks the SwitchBot API for the latest device information
|
|
448
422
|
*/
|
|
449
423
|
async refreshStatus(): Promise<void> {
|
|
450
|
-
if (this.
|
|
424
|
+
if (this.BLE) {
|
|
451
425
|
await this.BLERefreshStatus();
|
|
452
|
-
} else {
|
|
426
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
453
427
|
await this.openAPIRefreshStatus();
|
|
428
|
+
} else {
|
|
429
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
430
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
454
431
|
}
|
|
455
432
|
}
|
|
456
433
|
|
|
457
434
|
async BLERefreshStatus(): Promise<void> {
|
|
458
|
-
this.debugLog(
|
|
435
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
|
|
459
436
|
const switchbot = await this.platform.connectBLE();
|
|
460
437
|
// Convert to BLE Address
|
|
461
438
|
this.device.bleMac = this.device
|
|
462
439
|
.deviceId!.match(/.{1,2}/g)!
|
|
463
440
|
.join(':')
|
|
464
441
|
.toLowerCase();
|
|
465
|
-
this.debugLog(
|
|
442
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
466
443
|
this.getCustomBLEAddress(switchbot);
|
|
467
444
|
// Start to monitor advertisement packets
|
|
468
|
-
if (switchbot
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
})
|
|
476
|
-
.then(() => {
|
|
445
|
+
if (switchbot !== false) {
|
|
446
|
+
switchbot
|
|
447
|
+
.startScan({
|
|
448
|
+
model: 'H',
|
|
449
|
+
id: this.device.bleMac,
|
|
450
|
+
})
|
|
451
|
+
.then(() => {
|
|
477
452
|
// Set an event hander
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
453
|
+
switchbot.onadvertisement = (ad: ad) => {
|
|
454
|
+
this.address = ad.address;
|
|
455
|
+
if (this.deviceLogging.includes('debug')) {
|
|
456
|
+
this.infoLog(this.address);
|
|
457
|
+
this.infoLog(this.device.bleMac);
|
|
458
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
|
|
459
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
|
|
460
|
+
}
|
|
461
|
+
this.serviceData = ad.serviceData;
|
|
462
|
+
this.mode = ad.serviceData.mode;
|
|
463
|
+
this.state = ad.serviceData.state;
|
|
464
|
+
this.battery = ad.serviceData.battery;
|
|
465
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${superStringify(ad.serviceData)}`);
|
|
466
|
+
this.debugLog(
|
|
467
|
+
`${this.device.deviceType}: ${this.accessory.displayName}, model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName},` +
|
|
493
468
|
` mode: ${ad.serviceData.mode}, state: ${ad.serviceData.state}, battery: ${ad.serviceData.battery}`,
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
if (this.serviceData) {
|
|
472
|
+
this.connected = true;
|
|
473
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
474
|
+
} else {
|
|
475
|
+
this.connected = false;
|
|
476
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
// Wait 2 seconds
|
|
480
|
+
return switchbot.wait(this.scanDuration * 1000);
|
|
481
|
+
})
|
|
482
|
+
.then(async () => {
|
|
508
483
|
// Stop to monitor
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if (this.platform.config.credentials?.token) {
|
|
516
|
-
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
517
|
-
this.SwitchToOpenAPI = true;
|
|
518
|
-
await this.openAPIRefreshStatus();
|
|
484
|
+
switchbot.stopScan();
|
|
485
|
+
if (this.connected) {
|
|
486
|
+
this.parseStatus();
|
|
487
|
+
this.updateHomeKitCharacteristics();
|
|
488
|
+
} else {
|
|
489
|
+
await this.BLEconnection(switchbot);
|
|
519
490
|
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
this.
|
|
526
|
-
`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
527
|
-
);
|
|
528
|
-
}
|
|
529
|
-
if (this.platform.config.credentials?.token) {
|
|
530
|
-
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
531
|
-
this.SwitchToOpenAPI = true;
|
|
532
|
-
await this.openAPIRefreshStatus();
|
|
533
|
-
}
|
|
534
|
-
this.apiError(e);
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
async getCustomBLEAddress(switchbot: any) {
|
|
539
|
-
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
540
|
-
(async () => {
|
|
541
|
-
// Start to monitor advertisement packets
|
|
542
|
-
await switchbot.startScan({
|
|
543
|
-
model: 'H',
|
|
491
|
+
})
|
|
492
|
+
.catch(async (e: any) => {
|
|
493
|
+
this.apiError(e);
|
|
494
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
|
|
495
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
496
|
+
await this.BLEconnection(switchbot);
|
|
544
497
|
});
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
this.warnLog(`Bot: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
|
|
548
|
-
};
|
|
549
|
-
await switchbot.wait(10000);
|
|
550
|
-
// Stop to monitor
|
|
551
|
-
switchbot.stopScan();
|
|
552
|
-
})();
|
|
498
|
+
} else {
|
|
499
|
+
await this.BLEconnection(switchbot);
|
|
553
500
|
}
|
|
554
501
|
}
|
|
555
502
|
|
|
556
503
|
async openAPIRefreshStatus(): Promise<void> {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
this.debugLog(`d: ${d}`);
|
|
585
|
-
});
|
|
586
|
-
res.on('end', () => {
|
|
587
|
-
try {
|
|
588
|
-
this.deviceStatus = JSON.parse(rawData);
|
|
589
|
-
this.debugLog(`Bot: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
590
|
-
this.power = this.deviceStatus.body.power;
|
|
591
|
-
this.parseStatus();
|
|
592
|
-
this.updateHomeKitCharacteristics();
|
|
593
|
-
} catch (e: any) {
|
|
594
|
-
this.errorLog(`Bot: ${this.accessory.displayName} error message: ${e.message}`);
|
|
595
|
-
}
|
|
596
|
-
});
|
|
504
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
505
|
+
try {
|
|
506
|
+
const t = Date.now();
|
|
507
|
+
const nonce = 'requestID';
|
|
508
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
509
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
510
|
+
const sign = signTerm.toString('base64');
|
|
511
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
512
|
+
const options = {
|
|
513
|
+
hostname: HostDomain,
|
|
514
|
+
port: 443,
|
|
515
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
516
|
+
method: 'GET',
|
|
517
|
+
headers: {
|
|
518
|
+
Authorization: this.platform.config.credentials?.token,
|
|
519
|
+
sign: sign,
|
|
520
|
+
nonce: nonce,
|
|
521
|
+
t: t,
|
|
522
|
+
'Content-Type': 'application/json',
|
|
523
|
+
},
|
|
524
|
+
};
|
|
525
|
+
const req = https.request(options, (res) => {
|
|
526
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
|
|
527
|
+
let rawData = '';
|
|
528
|
+
res.on('data', (d) => {
|
|
529
|
+
rawData += d;
|
|
530
|
+
this.debugLog(`d: ${d}`);
|
|
597
531
|
});
|
|
598
|
-
|
|
599
|
-
|
|
532
|
+
res.on('end', () => {
|
|
533
|
+
try {
|
|
534
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
535
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
536
|
+
this.power = this.deviceStatus.body.power;
|
|
537
|
+
this.parseStatus();
|
|
538
|
+
this.updateHomeKitCharacteristics();
|
|
539
|
+
} catch (e: any) {
|
|
540
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
541
|
+
}
|
|
600
542
|
});
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
this.errorLog(
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
this.errorLog(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` + ` Error: ${JSON.stringify(e)}`);
|
|
611
|
-
}
|
|
612
|
-
this.apiError(e);
|
|
613
|
-
}
|
|
543
|
+
});
|
|
544
|
+
req.on('error', (e: any) => {
|
|
545
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
546
|
+
});
|
|
547
|
+
req.end();
|
|
548
|
+
} catch (e: any) {
|
|
549
|
+
this.apiError(e);
|
|
550
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
551
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
614
552
|
}
|
|
615
553
|
}
|
|
616
554
|
|
|
@@ -622,10 +560,13 @@ export class Bot {
|
|
|
622
560
|
* Bot - "command" "press" "default" = trigger press
|
|
623
561
|
*/
|
|
624
562
|
async pushChanges(): Promise<void> {
|
|
625
|
-
if (this.
|
|
626
|
-
await this.
|
|
627
|
-
} else {
|
|
563
|
+
if (this.BLE) {
|
|
564
|
+
await this.BLERefreshStatus();
|
|
565
|
+
} else if (this.OpenAPI) {
|
|
628
566
|
await this.openAPIpushChanges();
|
|
567
|
+
} else {
|
|
568
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
569
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
629
570
|
}
|
|
630
571
|
interval(5000)
|
|
631
572
|
.pipe(take(1))
|
|
@@ -635,184 +576,198 @@ export class Bot {
|
|
|
635
576
|
}
|
|
636
577
|
|
|
637
578
|
async BLEpushChanges(): Promise<void> {
|
|
638
|
-
this.debugLog(
|
|
639
|
-
if (this.On !== this.
|
|
640
|
-
this.debugLog(
|
|
579
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
580
|
+
if (this.On !== this.accessory.context.On || this.allowPush) {
|
|
581
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
|
|
641
582
|
const switchbot = await this.platform.connectBLE();
|
|
642
583
|
// Convert to BLE Address
|
|
643
584
|
this.device.bleMac = this.device
|
|
644
585
|
.deviceId!.match(/.{1,2}/g)!
|
|
645
586
|
.join(':')
|
|
646
587
|
.toLowerCase();
|
|
647
|
-
this.debugLog(
|
|
588
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
648
589
|
//if (switchbot !== false) {
|
|
649
590
|
if (this.botMode === 'press') {
|
|
650
|
-
this.debugLog(
|
|
591
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
651
592
|
switchbot
|
|
652
593
|
.discover({ model: 'H', quick: true, id: this.device.bleMac })
|
|
653
594
|
.then((device_list: { press: (arg0: { id: string | undefined }) => any }[]) => {
|
|
654
|
-
this.infoLog(
|
|
595
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
655
596
|
return device_list[0].press({ id: this.device.bleMac });
|
|
656
597
|
})
|
|
657
598
|
.then(() => {
|
|
658
|
-
this.debugLog(
|
|
659
|
-
this.On =
|
|
660
|
-
this.OnCached = this.On;
|
|
661
|
-
this.accessory.context.On = this.OnCached;
|
|
599
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
600
|
+
this.accessory.context.On = this.On;
|
|
662
601
|
setTimeout(() => {
|
|
663
602
|
if (this.device.bot?.deviceType === 'switch') {
|
|
664
603
|
this.switchService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
665
604
|
} else {
|
|
666
605
|
this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
667
606
|
}
|
|
668
|
-
this.debugLog(
|
|
607
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}, Switch Timeout`);
|
|
669
608
|
}, 500);
|
|
670
609
|
})
|
|
671
610
|
.catch(async (e: any) => {
|
|
672
|
-
this.
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
);
|
|
677
|
-
}
|
|
678
|
-
if (this.platform.debugMode) {
|
|
679
|
-
this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,` + ` Error: ${JSON.stringify(e)}`);
|
|
680
|
-
}
|
|
681
|
-
if (this.platform.config.credentials?.token) {
|
|
682
|
-
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
611
|
+
this.apiError(e);
|
|
612
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
613
|
+
+ ` Connection & botMode: ${this.botMode}, Error Message: ${superStringify(e.message)}`);
|
|
614
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
615
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
683
616
|
await this.openAPIpushChanges();
|
|
684
617
|
}
|
|
685
|
-
this.apiError(e);
|
|
686
618
|
});
|
|
687
619
|
} else if (this.botMode === 'switch') {
|
|
688
|
-
this.debugLog(
|
|
620
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode: ${this.botMode}`);
|
|
689
621
|
switchbot
|
|
690
622
|
.discover({ model: 'H', quick: true, id: this.device.bleMac })
|
|
691
623
|
.then((device_list: any) => {
|
|
692
|
-
this.infoLog(
|
|
624
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
693
625
|
return this.turnOnOff(device_list);
|
|
694
626
|
})
|
|
695
627
|
.then(() => {
|
|
696
|
-
this.debugLog(
|
|
697
|
-
this.
|
|
698
|
-
this.accessory.context.On = this.OnCached;
|
|
628
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
629
|
+
this.accessory.context.On = this.On;
|
|
699
630
|
})
|
|
700
631
|
.catch(async (e: any) => {
|
|
701
|
-
this.
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
);
|
|
706
|
-
}
|
|
707
|
-
if (this.platform.debugMode) {
|
|
708
|
-
this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,` + ` Error: ${JSON.stringify(e)}`);
|
|
709
|
-
}
|
|
710
|
-
if (this.platform.config.credentials?.token) {
|
|
711
|
-
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
632
|
+
this.apiError(e);
|
|
633
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
634
|
+
+ ` Connection & botMode: ${this.botMode}, Error Message: ${superStringify(e.message)}`);
|
|
635
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
636
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
712
637
|
await this.openAPIpushChanges();
|
|
713
638
|
}
|
|
714
|
-
this.apiError(e);
|
|
715
639
|
});
|
|
716
640
|
} else {
|
|
717
|
-
|
|
641
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
718
642
|
}
|
|
643
|
+
} else {
|
|
644
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, `
|
|
645
|
+
+`OnCached: ${this.accessory.context.On}`);
|
|
719
646
|
}
|
|
720
|
-
this.OnCached = this.On;
|
|
721
|
-
this.accessory.context.On = this.OnCached;
|
|
722
647
|
}
|
|
723
648
|
|
|
724
|
-
async
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
649
|
+
async openAPIpushChanges(): Promise<void> {
|
|
650
|
+
try {
|
|
651
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
652
|
+
if (this.On !== this.accessory.context.On || this.allowPush) {
|
|
653
|
+
// Make Push On request to the API
|
|
654
|
+
const t = Date.now();
|
|
655
|
+
const nonce = 'requestID';
|
|
656
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
657
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
658
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
659
|
+
.digest();
|
|
660
|
+
const sign = signTerm.toString('base64');
|
|
661
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
662
|
+
let command = '';
|
|
663
|
+
if (this.botMode === 'switch' && this.On) {
|
|
664
|
+
command = 'turnOn';
|
|
665
|
+
this.On = true;
|
|
666
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
|
|
667
|
+
} else if (this.botMode === 'switch' && !this.On) {
|
|
668
|
+
command = 'turnOff';
|
|
669
|
+
this.On = false;
|
|
670
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
|
|
671
|
+
} else if (this.botMode === 'press') {
|
|
672
|
+
command = 'press';
|
|
673
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode`);
|
|
674
|
+
this.On = false;
|
|
730
675
|
} else {
|
|
731
|
-
|
|
676
|
+
throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
|
|
732
677
|
}
|
|
733
|
-
|
|
734
|
-
|
|
678
|
+
const body = superStringify({
|
|
679
|
+
'command': `${command}`,
|
|
680
|
+
'parameter': 'default',
|
|
681
|
+
'commandType': 'command',
|
|
682
|
+
});
|
|
683
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
684
|
+
const options = {
|
|
685
|
+
hostname: HostDomain,
|
|
686
|
+
port: 443,
|
|
687
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
688
|
+
method: 'POST',
|
|
689
|
+
headers: {
|
|
690
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
691
|
+
'sign': sign,
|
|
692
|
+
'nonce': nonce,
|
|
693
|
+
't': t,
|
|
694
|
+
'Content-Type': 'application/json',
|
|
695
|
+
'Content-Length': body.length,
|
|
696
|
+
},
|
|
697
|
+
};
|
|
698
|
+
const req = https.request(options, res => {
|
|
699
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
|
|
700
|
+
this.statusCode({ res });
|
|
701
|
+
res.on('data', d => {
|
|
702
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
req.on('error', (e: any) => {
|
|
706
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
707
|
+
});
|
|
708
|
+
req.write(body);
|
|
709
|
+
req.end();
|
|
710
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges: ${superStringify(req)}`);
|
|
711
|
+
} else {
|
|
712
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `On: ${this.On}, `
|
|
713
|
+
+`OnCached: ${this.accessory.context.On}`);
|
|
714
|
+
}
|
|
715
|
+
} catch (e: any) {
|
|
716
|
+
this.apiError(e);
|
|
717
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
718
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`,
|
|
719
|
+
);
|
|
720
|
+
}
|
|
735
721
|
}
|
|
736
722
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
'Authorization': this.platform.config.credentials?.token,
|
|
780
|
-
'sign': sign,
|
|
781
|
-
'nonce': nonce,
|
|
782
|
-
't': t,
|
|
783
|
-
'Content-Type': 'application/json',
|
|
784
|
-
'Content-Length': body.length,
|
|
785
|
-
},
|
|
786
|
-
};
|
|
787
|
-
const req = https.request(options, res => {
|
|
788
|
-
this.debugLog(`Bot: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
789
|
-
this.statusCode({ res });
|
|
790
|
-
res.on('data', d => {
|
|
791
|
-
this.debugLog(`Bot: ${this.accessory.displayName} d: ${d}`);
|
|
792
|
-
});
|
|
793
|
-
});
|
|
794
|
-
req.on('error', (e: any) => {
|
|
795
|
-
this.errorLog(`Bot: ${this.accessory.displayName} error message: ${e.message}`);
|
|
796
|
-
});
|
|
797
|
-
req.write(body);
|
|
798
|
-
req.end();
|
|
799
|
-
this.debugLog(`Bot: ${this.accessory.displayName} openAPIpushChanges: ${JSON.stringify(req)}`);
|
|
800
|
-
this.OnCached = this.On;
|
|
801
|
-
this.accessory.context.On = this.OnCached;
|
|
802
|
-
}
|
|
803
|
-
} catch (e: any) {
|
|
804
|
-
this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
805
|
-
if (this.deviceLogging.includes('debug')) {
|
|
806
|
-
this.errorLog(
|
|
807
|
-
`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
808
|
-
);
|
|
809
|
-
}
|
|
810
|
-
if (this.platform.debugMode) {
|
|
811
|
-
this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,` + ` Error: ${JSON.stringify(e)}`);
|
|
812
|
-
}
|
|
813
|
-
this.apiError(e);
|
|
723
|
+
/**
|
|
724
|
+
* Handle requests to set the "On" characteristic
|
|
725
|
+
*/
|
|
726
|
+
async OnSet(value: CharacteristicValue): Promise<void> {
|
|
727
|
+
if (this.device.bot?.deviceType === 'garagedoor') {
|
|
728
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetDoorState: ${value}`);
|
|
729
|
+
if (value === this.platform.Characteristic.TargetDoorState.CLOSED) {
|
|
730
|
+
this.On = false;
|
|
731
|
+
} else {
|
|
732
|
+
this.On = true;
|
|
733
|
+
}
|
|
734
|
+
} else if (
|
|
735
|
+
this.device.bot?.deviceType === 'door' ||
|
|
736
|
+
this.device.bot?.deviceType === 'window' ||
|
|
737
|
+
this.device.bot?.deviceType === 'windowcovering'
|
|
738
|
+
) {
|
|
739
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
|
|
740
|
+
if (value === 0) {
|
|
741
|
+
this.On = false;
|
|
742
|
+
} else {
|
|
743
|
+
this.On = true;
|
|
744
|
+
}
|
|
745
|
+
} else if (this.device.bot?.deviceType === 'lock') {
|
|
746
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
|
|
747
|
+
if (value === this.platform.Characteristic.LockTargetState.SECURED) {
|
|
748
|
+
this.On = false;
|
|
749
|
+
} else {
|
|
750
|
+
this.On = true;
|
|
751
|
+
}
|
|
752
|
+
} else if (this.device.bot?.deviceType === 'faucet') {
|
|
753
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Active: ${value}`);
|
|
754
|
+
if (value === this.platform.Characteristic.Active.INACTIVE) {
|
|
755
|
+
this.On = false;
|
|
756
|
+
} else {
|
|
757
|
+
this.On = true;
|
|
758
|
+
}
|
|
759
|
+
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
760
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ProgrammableSwitchOutputState: ${value}`);
|
|
761
|
+
if (value === 0) {
|
|
762
|
+
this.On = false;
|
|
763
|
+
} else {
|
|
764
|
+
this.On = true;
|
|
814
765
|
}
|
|
766
|
+
} else {
|
|
767
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
|
|
768
|
+
this.On = value;
|
|
815
769
|
}
|
|
770
|
+
this.doBotUpdate.next();
|
|
816
771
|
}
|
|
817
772
|
|
|
818
773
|
/**
|
|
@@ -821,7 +776,7 @@ export class Bot {
|
|
|
821
776
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
822
777
|
if (this.device.bot?.deviceType === 'garagedoor') {
|
|
823
778
|
if (this.On === undefined) {
|
|
824
|
-
this.debugLog(
|
|
779
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
825
780
|
} else {
|
|
826
781
|
if (this.On) {
|
|
827
782
|
this.garageDoorService?.updateCharacteristic(
|
|
@@ -832,7 +787,8 @@ export class Bot {
|
|
|
832
787
|
this.platform.Characteristic.CurrentDoorState,
|
|
833
788
|
this.platform.Characteristic.CurrentDoorState.OPEN,
|
|
834
789
|
);
|
|
835
|
-
this.debugLog(
|
|
790
|
+
this.debugLog(`${this.device.deviceType}: `
|
|
791
|
+
+ `${this.accessory.displayName} updateCharacteristic TargetDoorState: Open, CurrentDoorState: Open`);
|
|
836
792
|
} else {
|
|
837
793
|
this.garageDoorService?.updateCharacteristic(
|
|
838
794
|
this.platform.Characteristic.TargetDoorState,
|
|
@@ -842,47 +798,48 @@ export class Bot {
|
|
|
842
798
|
this.platform.Characteristic.CurrentDoorState,
|
|
843
799
|
this.platform.Characteristic.CurrentDoorState.CLOSED,
|
|
844
800
|
);
|
|
845
|
-
this.debugLog(
|
|
801
|
+
this.debugLog(`${this.device.deviceType}: `
|
|
802
|
+
+`${this.accessory.displayName} updateCharacteristic TargetDoorState: Open, CurrentDoorState: Open`);
|
|
846
803
|
}
|
|
847
804
|
}
|
|
848
|
-
this.debugLog(
|
|
805
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Garage Door On: ${this.On}`);
|
|
849
806
|
} else if (this.device.bot?.deviceType === 'door') {
|
|
850
807
|
if (this.On === undefined) {
|
|
851
|
-
this.debugLog(
|
|
808
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
852
809
|
} else {
|
|
853
810
|
if (this.On) {
|
|
854
811
|
this.doorService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 100);
|
|
855
812
|
this.doorService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 100);
|
|
856
813
|
this.doorService?.updateCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
857
|
-
this.debugLog(
|
|
814
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
|
|
858
815
|
} else {
|
|
859
816
|
this.doorService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 0);
|
|
860
817
|
this.doorService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 0);
|
|
861
818
|
this.doorService?.updateCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
862
|
-
this.debugLog(
|
|
819
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
|
|
863
820
|
}
|
|
864
821
|
}
|
|
865
|
-
this.debugLog(
|
|
822
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Door On: ${this.On}`);
|
|
866
823
|
} else if (this.device.bot?.deviceType === 'window') {
|
|
867
824
|
if (this.On === undefined) {
|
|
868
|
-
this.debugLog(
|
|
825
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
869
826
|
} else {
|
|
870
827
|
if (this.On) {
|
|
871
828
|
this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 100);
|
|
872
829
|
this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 100);
|
|
873
830
|
this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
874
|
-
this.debugLog(
|
|
831
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
|
|
875
832
|
} else {
|
|
876
833
|
this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 0);
|
|
877
834
|
this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 0);
|
|
878
835
|
this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
|
|
879
|
-
this.debugLog(
|
|
836
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
|
|
880
837
|
}
|
|
881
838
|
}
|
|
882
|
-
this.debugLog(
|
|
839
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Window On: ${this.On}`);
|
|
883
840
|
} else if (this.device.bot?.deviceType === 'windowcovering') {
|
|
884
841
|
if (this.On === undefined) {
|
|
885
|
-
this.debugLog(
|
|
842
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
886
843
|
} else {
|
|
887
844
|
if (this.On) {
|
|
888
845
|
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 100);
|
|
@@ -891,7 +848,7 @@ export class Bot {
|
|
|
891
848
|
this.platform.Characteristic.PositionState,
|
|
892
849
|
this.platform.Characteristic.PositionState.STOPPED,
|
|
893
850
|
);
|
|
894
|
-
this.debugLog(
|
|
851
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
|
|
895
852
|
} else {
|
|
896
853
|
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 0);
|
|
897
854
|
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 0);
|
|
@@ -899,13 +856,13 @@ export class Bot {
|
|
|
899
856
|
this.platform.Characteristic.PositionState,
|
|
900
857
|
this.platform.Characteristic.PositionState.STOPPED,
|
|
901
858
|
);
|
|
902
|
-
this.debugLog(
|
|
859
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
|
|
903
860
|
}
|
|
904
861
|
}
|
|
905
|
-
this.debugLog(
|
|
862
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Window Covering On: ${this.On}`);
|
|
906
863
|
} else if (this.device.bot?.deviceType === 'lock') {
|
|
907
864
|
if (this.On === undefined) {
|
|
908
|
-
this.debugLog(
|
|
865
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
909
866
|
} else {
|
|
910
867
|
if (this.On) {
|
|
911
868
|
this.lockService?.updateCharacteristic(
|
|
@@ -916,46 +873,48 @@ export class Bot {
|
|
|
916
873
|
this.platform.Characteristic.LockCurrentState,
|
|
917
874
|
this.platform.Characteristic.LockCurrentState.UNSECURED,
|
|
918
875
|
);
|
|
919
|
-
this.debugLog(
|
|
876
|
+
this.debugLog(`${this.device.deviceType}: `
|
|
877
|
+
+ `${this.accessory.displayName} updateCharacteristic LockTargetState: UNSECURED, LockCurrentState: UNSECURED`);
|
|
920
878
|
} else {
|
|
921
879
|
this.lockService?.updateCharacteristic(this.platform.Characteristic.LockTargetState, this.platform.Characteristic.LockTargetState.SECURED);
|
|
922
880
|
this.lockService?.updateCharacteristic(
|
|
923
881
|
this.platform.Characteristic.LockCurrentState,
|
|
924
882
|
this.platform.Characteristic.LockCurrentState.SECURED,
|
|
925
883
|
);
|
|
926
|
-
this.debugLog(
|
|
884
|
+
this.debugLog(`${this.device.deviceType}: `
|
|
885
|
+
+ `${this.accessory.displayName} updateCharacteristic LockTargetState: SECURED, LockCurrentState: SECURED`);
|
|
927
886
|
}
|
|
928
887
|
}
|
|
929
|
-
this.debugLog(
|
|
888
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Lock On: ${this.On}`);
|
|
930
889
|
} else if (this.device.bot?.deviceType === 'faucet') {
|
|
931
890
|
if (this.On === undefined) {
|
|
932
|
-
this.debugLog(
|
|
891
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
933
892
|
} else {
|
|
934
893
|
if (this.On) {
|
|
935
894
|
this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active, this.platform.Characteristic.Active.ACTIVE);
|
|
936
|
-
this.debugLog(
|
|
895
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.On}`);
|
|
937
896
|
} else {
|
|
938
897
|
this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active, this.platform.Characteristic.Active.INACTIVE);
|
|
939
|
-
this.debugLog(
|
|
898
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.On}`);
|
|
940
899
|
}
|
|
941
900
|
}
|
|
942
|
-
this.debugLog(
|
|
901
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Faucet On: ${this.On}`);
|
|
943
902
|
} else if (this.device.bot?.deviceType === 'fan') {
|
|
944
903
|
if (this.On === undefined) {
|
|
945
|
-
this.debugLog(
|
|
904
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
946
905
|
} else {
|
|
947
906
|
if (this.On) {
|
|
948
907
|
this.fanService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
|
|
949
|
-
this.debugLog(
|
|
908
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
950
909
|
} else {
|
|
951
910
|
this.fanService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
|
|
952
|
-
this.debugLog(
|
|
911
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
953
912
|
}
|
|
954
913
|
}
|
|
955
|
-
this.debugLog(
|
|
914
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Fan On: ${this.On}`);
|
|
956
915
|
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
957
916
|
if (this.On === undefined) {
|
|
958
|
-
this.debugLog(
|
|
917
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
959
918
|
} else {
|
|
960
919
|
if (this.On) {
|
|
961
920
|
this.statefulProgrammableSwitchService?.updateCharacteristic(
|
|
@@ -963,179 +922,190 @@ export class Bot {
|
|
|
963
922
|
this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
|
|
964
923
|
);
|
|
965
924
|
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, 1);
|
|
966
|
-
this.debugLog(
|
|
925
|
+
this.debugLog(`${this.device.deviceType}: `
|
|
926
|
+
+ `${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1`);
|
|
967
927
|
} else {
|
|
968
928
|
this.statefulProgrammableSwitchService?.updateCharacteristic(
|
|
969
929
|
this.platform.Characteristic.ProgrammableSwitchEvent,
|
|
970
930
|
this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
|
|
971
931
|
);
|
|
972
932
|
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, 0);
|
|
973
|
-
this.debugLog(
|
|
933
|
+
this.debugLog(`${this.device.deviceType}: `
|
|
934
|
+
+ `${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0`);
|
|
974
935
|
}
|
|
975
936
|
}
|
|
976
|
-
this.debugLog(
|
|
937
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatefulProgrammableSwitch On: ${this.On}`);
|
|
977
938
|
} else if (this.device.bot?.deviceType === 'switch') {
|
|
978
939
|
if (this.On === undefined) {
|
|
979
|
-
this.debugLog(
|
|
940
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
980
941
|
} else {
|
|
981
942
|
this.switchService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
|
|
982
|
-
this.debugLog(
|
|
943
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
983
944
|
}
|
|
984
945
|
} else {
|
|
985
946
|
if (this.On === undefined) {
|
|
986
|
-
this.debugLog(
|
|
947
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
987
948
|
} else {
|
|
988
949
|
this.outletService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
|
|
989
|
-
this.debugLog(
|
|
950
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
990
951
|
}
|
|
991
952
|
}
|
|
992
|
-
|
|
953
|
+
this.accessory.context.On = this.On;
|
|
954
|
+
if (this.BLE) {
|
|
993
955
|
if (this.BatteryLevel === undefined) {
|
|
994
|
-
this.debugLog(
|
|
956
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
995
957
|
} else {
|
|
958
|
+
this.accessory.context.BatteryLevel = this.BatteryLevel;
|
|
996
959
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
|
|
997
|
-
this.debugLog(
|
|
960
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
998
961
|
}
|
|
999
962
|
if (this.StatusLowBattery === undefined) {
|
|
1000
|
-
this.debugLog(
|
|
963
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
1001
964
|
} else {
|
|
965
|
+
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
1002
966
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
1003
|
-
this.debugLog(
|
|
967
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
1004
968
|
}
|
|
1005
969
|
}
|
|
1006
970
|
}
|
|
1007
971
|
|
|
1008
|
-
async
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
this.
|
|
1013
|
-
} else if (this.device.bot?.deviceType === 'door') {
|
|
1014
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1015
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1016
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1017
|
-
} else if (this.device.bot?.deviceType === 'window') {
|
|
1018
|
-
this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1019
|
-
this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1020
|
-
this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1021
|
-
} else if (this.device.bot?.deviceType === 'windowcovering') {
|
|
1022
|
-
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1023
|
-
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1024
|
-
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1025
|
-
} else if (this.device.bot?.deviceType === 'lock') {
|
|
1026
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
1027
|
-
this.doorService?.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
1028
|
-
} else if (this.device.bot?.deviceType === 'faucet') {
|
|
1029
|
-
this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active, e);
|
|
1030
|
-
} else if (this.device.bot?.deviceType === 'fan') {
|
|
1031
|
-
this.fanService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1032
|
-
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
1033
|
-
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent, e);
|
|
1034
|
-
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, e);
|
|
1035
|
-
} else if (this.device.bot?.deviceType === 'switch') {
|
|
1036
|
-
this.switchService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1037
|
-
} else {
|
|
1038
|
-
this.outletService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
972
|
+
async removeOutletService(accessory: PlatformAccessory): Promise<void> {
|
|
973
|
+
// If outletService still pressent, then remove first
|
|
974
|
+
this.outletService = this.accessory.getService(this.platform.Service.Outlet);
|
|
975
|
+
if (this.outletService) {
|
|
976
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Outlet Service`);
|
|
1039
977
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
978
|
+
accessory.removeService(this.outletService!);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
async removeGarageDoorService(accessory: PlatformAccessory): Promise<void> {
|
|
982
|
+
// If garageDoorService still pressent, then remove first
|
|
983
|
+
this.garageDoorService = this.accessory.getService(this.platform.Service.GarageDoorOpener);
|
|
984
|
+
if (this.garageDoorService) {
|
|
985
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Garage Door Service`);
|
|
1043
986
|
}
|
|
1044
|
-
|
|
987
|
+
accessory.removeService(this.garageDoorService!);
|
|
1045
988
|
}
|
|
1046
989
|
|
|
1047
|
-
async
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
case 152:
|
|
1053
|
-
this.errorLog(`Bot: ${this.accessory.displayName} Device not found.`);
|
|
1054
|
-
break;
|
|
1055
|
-
case 160:
|
|
1056
|
-
this.errorLog(`Bot: ${this.accessory.displayName} Command is not supported.`);
|
|
1057
|
-
break;
|
|
1058
|
-
case 161:
|
|
1059
|
-
this.errorLog(`Bot: ${this.accessory.displayName} Device is offline.`);
|
|
1060
|
-
this.offlineOff();
|
|
1061
|
-
break;
|
|
1062
|
-
case 171:
|
|
1063
|
-
this.errorLog(`Bot: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
1064
|
-
this.offlineOff();
|
|
1065
|
-
break;
|
|
1066
|
-
case 190:
|
|
1067
|
-
this.errorLog(
|
|
1068
|
-
`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
1069
|
-
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
1070
|
-
);
|
|
1071
|
-
break;
|
|
1072
|
-
case 100:
|
|
1073
|
-
this.debugLog(`Bot: ${this.accessory.displayName} Command successfully sent.`);
|
|
1074
|
-
break;
|
|
1075
|
-
default:
|
|
1076
|
-
this.debugLog(`Bot: ${this.accessory.displayName} Unknown statusCode.`);
|
|
990
|
+
async removeDoorService(accessory: PlatformAccessory): Promise<void> {
|
|
991
|
+
// If doorService still pressent, then remove first
|
|
992
|
+
this.doorService = this.accessory.getService(this.platform.Service.Door);
|
|
993
|
+
if (this.doorService) {
|
|
994
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Door Service`);
|
|
1077
995
|
}
|
|
996
|
+
accessory.removeService(this.doorService!);
|
|
1078
997
|
}
|
|
1079
998
|
|
|
1080
|
-
async
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
} else {
|
|
1086
|
-
this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
1087
|
-
}
|
|
999
|
+
async removeLockService(accessory: PlatformAccessory): Promise<void> {
|
|
1000
|
+
// If lockService still pressent, then remove first
|
|
1001
|
+
this.lockService = this.accessory.getService(this.platform.Service.LockMechanism);
|
|
1002
|
+
if (this.lockService) {
|
|
1003
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Lock Service`);
|
|
1088
1004
|
}
|
|
1005
|
+
accessory.removeService(this.lockService!);
|
|
1089
1006
|
}
|
|
1090
1007
|
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
this.device.
|
|
1105
|
-
|
|
1106
|
-
)
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1008
|
+
async removeFaucetService(accessory: PlatformAccessory): Promise<void> {
|
|
1009
|
+
// If faucetService still pressent, then remove first
|
|
1010
|
+
this.faucetService = this.accessory.getService(this.platform.Service.Faucet);
|
|
1011
|
+
if (this.faucetService) {
|
|
1012
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Faucet Service`);
|
|
1013
|
+
}
|
|
1014
|
+
accessory.removeService(this.faucetService!);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
async removeFanService(accessory: PlatformAccessory): Promise<void> {
|
|
1018
|
+
// If fanService still pressent, then remove first
|
|
1019
|
+
this.fanService = this.accessory.getService(this.platform.Service.Fan);
|
|
1020
|
+
if (this.fanService) {
|
|
1021
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Fan Service`);
|
|
1022
|
+
}
|
|
1023
|
+
accessory.removeService(this.fanService!);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
async removeWindowService(accessory: PlatformAccessory): Promise<void> {
|
|
1027
|
+
// If windowService still pressent, then remove first
|
|
1028
|
+
this.windowService = this.accessory.getService(this.platform.Service.Window);
|
|
1029
|
+
if (this.windowService) {
|
|
1030
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Service`);
|
|
1031
|
+
}
|
|
1032
|
+
accessory.removeService(this.windowService!);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
async removeWindowCoveringService(accessory: PlatformAccessory): Promise<void> {
|
|
1036
|
+
// If windowCoveringService still pressent, then remove first
|
|
1037
|
+
this.windowCoveringService = this.accessory.getService(this.platform.Service.WindowCovering);
|
|
1038
|
+
if (this.windowCoveringService) {
|
|
1039
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Covering Service`);
|
|
1040
|
+
}
|
|
1041
|
+
accessory.removeService(this.windowCoveringService!);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
async removeStatefulProgrammableSwitchService(accessory: PlatformAccessory): Promise<void> {
|
|
1045
|
+
// If statefulProgrammableSwitchService still pressent, then remove first
|
|
1046
|
+
this.statefulProgrammableSwitchService = this.accessory.getService(this.platform.Service.StatefulProgrammableSwitch);
|
|
1047
|
+
if (this.statefulProgrammableSwitchService) {
|
|
1048
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
|
|
1049
|
+
}
|
|
1050
|
+
accessory.removeService(this.statefulProgrammableSwitchService!);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
async removeSwitchService(accessory: PlatformAccessory): Promise<void> {
|
|
1054
|
+
// If switchService still pressent, then remove first
|
|
1055
|
+
this.switchService = this.accessory.getService(this.platform.Service.Switch);
|
|
1056
|
+
if (this.switchService) {
|
|
1057
|
+
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Switch Service`);
|
|
1058
|
+
}
|
|
1059
|
+
accessory.removeService(this.switchService!);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
private DoublePress(device: device & devicesConfig) {
|
|
1063
|
+
if (device.bot?.doublePress) {
|
|
1064
|
+
this.doublePress = device.bot?.doublePress;
|
|
1065
|
+
this.accessory.context.doublePress = this.doublePress;
|
|
1134
1066
|
} else {
|
|
1135
|
-
this.
|
|
1136
|
-
this.On = value;
|
|
1067
|
+
this.doublePress = 1;
|
|
1137
1068
|
}
|
|
1138
|
-
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
async getCustomBLEAddress(switchbot: any) {
|
|
1072
|
+
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
1073
|
+
(async () => {
|
|
1074
|
+
// Start to monitor advertisement packets
|
|
1075
|
+
await switchbot.startScan({
|
|
1076
|
+
model: 'H',
|
|
1077
|
+
});
|
|
1078
|
+
// Set an event handler
|
|
1079
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
1080
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
|
|
1081
|
+
};
|
|
1082
|
+
await switchbot.wait(10000);
|
|
1083
|
+
// Stop to monitor
|
|
1084
|
+
switchbot.stopScan();
|
|
1085
|
+
})();
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
async BLEconnection(switchbot: any): Promise<void> {
|
|
1090
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
1091
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
1092
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
1093
|
+
this.SwitchToOpenAPI = true;
|
|
1094
|
+
await this.openAPIRefreshStatus();
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
async turnOnOff(device_list: any): Promise<any> {
|
|
1099
|
+
return await this.retry({
|
|
1100
|
+
max: await this.maxRetry(),
|
|
1101
|
+
fn: () => {
|
|
1102
|
+
if (this.On) {
|
|
1103
|
+
return device_list[0].turnOn({ id: this.device.bleMac });
|
|
1104
|
+
} else {
|
|
1105
|
+
return device_list[0].turnOff({ id: this.device.bleMac });
|
|
1106
|
+
}
|
|
1107
|
+
},
|
|
1108
|
+
});
|
|
1139
1109
|
}
|
|
1140
1110
|
|
|
1141
1111
|
async retry({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
|
|
@@ -1160,76 +1130,134 @@ export class Bot {
|
|
|
1160
1130
|
return maxRetry;
|
|
1161
1131
|
}
|
|
1162
1132
|
|
|
1163
|
-
async
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
if (device.
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
if (device.
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
}
|
|
1177
|
-
if (device.scanDuration !== undefined) {
|
|
1178
|
-
config['scanDuration'] = device.scanDuration;
|
|
1179
|
-
}
|
|
1180
|
-
if (device.offline !== undefined) {
|
|
1181
|
-
config['offline'] = device.offline;
|
|
1182
|
-
}
|
|
1183
|
-
if (Object.entries(config).length !== 0) {
|
|
1184
|
-
this.infoLog(`Bot: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
1133
|
+
async PressOrSwitch(device: device & devicesConfig): Promise<void> {
|
|
1134
|
+
if (!device.bot?.mode) {
|
|
1135
|
+
this.botMode = 'switch';
|
|
1136
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} does not have bot mode set in the Plugin's SwitchBot Device Settings,`);
|
|
1137
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} is defaulting to "${this.botMode}" mode, you may experience issues.`);
|
|
1138
|
+
} else if (device.bot?.mode === 'switch') {
|
|
1139
|
+
this.botMode = 'switch';
|
|
1140
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1141
|
+
} else if (device.bot?.mode === 'press') {
|
|
1142
|
+
this.botMode = 'press';
|
|
1143
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1144
|
+
} else {
|
|
1145
|
+
throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
1185
1146
|
}
|
|
1186
1147
|
}
|
|
1187
1148
|
|
|
1188
|
-
async
|
|
1189
|
-
if (device.
|
|
1190
|
-
this.
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
1194
|
-
this.debugLog(`Bot: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1149
|
+
async allowPushChanges(device: device & devicesConfig): Promise<void> {
|
|
1150
|
+
if (device.bot?.allowPush) {
|
|
1151
|
+
this.allowPush = true;
|
|
1152
|
+
} else {
|
|
1153
|
+
this.allowPush = false;
|
|
1195
1154
|
}
|
|
1155
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Allowing Push Changes: ${this.allowPush}`);
|
|
1196
1156
|
}
|
|
1197
1157
|
|
|
1198
1158
|
async scan(device: device & devicesConfig): Promise<void> {
|
|
1199
1159
|
if (device.scanDuration) {
|
|
1200
1160
|
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
1201
|
-
if (
|
|
1202
|
-
this.debugLog(
|
|
1161
|
+
if (this.BLE) {
|
|
1162
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
1203
1163
|
}
|
|
1204
1164
|
} else {
|
|
1205
1165
|
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
1206
|
-
if (this.
|
|
1207
|
-
this.debugLog(
|
|
1166
|
+
if (this.BLE) {
|
|
1167
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
1208
1168
|
}
|
|
1209
1169
|
}
|
|
1210
1170
|
}
|
|
1211
1171
|
|
|
1212
|
-
async
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1172
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
1173
|
+
switch (res.statusCode) {
|
|
1174
|
+
case 151:
|
|
1175
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
1176
|
+
break;
|
|
1177
|
+
case 152:
|
|
1178
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
|
|
1179
|
+
break;
|
|
1180
|
+
case 160:
|
|
1181
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
|
|
1182
|
+
break;
|
|
1183
|
+
case 161:
|
|
1184
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
|
|
1185
|
+
this.offlineOff();
|
|
1186
|
+
break;
|
|
1187
|
+
case 171:
|
|
1188
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
1189
|
+
this.offlineOff();
|
|
1190
|
+
break;
|
|
1191
|
+
case 190:
|
|
1192
|
+
this.errorLog(
|
|
1193
|
+
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
1194
|
+
` Or command: ${superStringify(res)} format is invalid`,
|
|
1195
|
+
);
|
|
1196
|
+
break;
|
|
1197
|
+
case 100:
|
|
1198
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
|
|
1199
|
+
break;
|
|
1200
|
+
default:
|
|
1201
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
async offlineOff(): Promise<void> {
|
|
1206
|
+
if (this.device.offline) {
|
|
1207
|
+
this.On = false;
|
|
1208
|
+
if (this.device.bot?.deviceType === 'switch') {
|
|
1209
|
+
this.switchService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
1210
|
+
} else {
|
|
1211
|
+
this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
1212
|
+
}
|
|
1213
|
+
await this.updateHomeKitCharacteristics();
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
async apiError(e: any): Promise<void> {
|
|
1218
|
+
if (this.device.bot?.deviceType === 'garagedoor') {
|
|
1219
|
+
this.garageDoorService?.updateCharacteristic(this.platform.Characteristic.TargetDoorState, e);
|
|
1220
|
+
this.garageDoorService?.updateCharacteristic(this.platform.Characteristic.CurrentDoorState, e);
|
|
1221
|
+
this.garageDoorService?.updateCharacteristic(this.platform.Characteristic.ObstructionDetected, e);
|
|
1222
|
+
} else if (this.device.bot?.deviceType === 'door') {
|
|
1223
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1224
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1225
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1226
|
+
} else if (this.device.bot?.deviceType === 'window') {
|
|
1227
|
+
this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1228
|
+
this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1229
|
+
this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1230
|
+
} else if (this.device.bot?.deviceType === 'windowcovering') {
|
|
1231
|
+
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
1232
|
+
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
1233
|
+
this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
1234
|
+
} else if (this.device.bot?.deviceType === 'lock') {
|
|
1235
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
1236
|
+
this.doorService?.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
1237
|
+
} else if (this.device.bot?.deviceType === 'faucet') {
|
|
1238
|
+
this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active, e);
|
|
1239
|
+
} else if (this.device.bot?.deviceType === 'fan') {
|
|
1240
|
+
this.fanService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1241
|
+
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
1242
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent, e);
|
|
1243
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, e);
|
|
1244
|
+
} else if (this.device.bot?.deviceType === 'switch') {
|
|
1245
|
+
this.switchService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1222
1246
|
} else {
|
|
1223
|
-
this.
|
|
1224
|
-
|
|
1247
|
+
this.outletService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1248
|
+
}
|
|
1249
|
+
if (this.BLE) {
|
|
1250
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
|
|
1251
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
|
|
1225
1252
|
}
|
|
1226
1253
|
}
|
|
1227
1254
|
|
|
1228
1255
|
FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
|
|
1229
1256
|
let FirmwareRevision: string;
|
|
1230
|
-
this.debugLog(
|
|
1231
|
-
|
|
1232
|
-
this.debugLog(
|
|
1257
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
1258
|
+
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
1259
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
1260
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
1233
1261
|
if (accessory.context.FirmwareRevision) {
|
|
1234
1262
|
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
1235
1263
|
} else if (device.firmware) {
|
|
@@ -1240,119 +1268,75 @@ export class Bot {
|
|
|
1240
1268
|
return FirmwareRevision;
|
|
1241
1269
|
}
|
|
1242
1270
|
|
|
1243
|
-
|
|
1244
|
-
if (
|
|
1245
|
-
this.
|
|
1246
|
-
this.
|
|
1247
|
-
this.warnLog(`Bot: ${this.accessory.displayName} is defaulting to "${this.botMode}" mode, you may experience issues.`);
|
|
1248
|
-
} else if (device.bot?.mode === 'switch') {
|
|
1249
|
-
this.botMode = 'switch';
|
|
1250
|
-
this.debugLog(`Bot: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1251
|
-
} else if (device.bot?.mode === 'press') {
|
|
1252
|
-
this.botMode = 'press';
|
|
1253
|
-
this.debugLog(`Bot: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1271
|
+
private context() {
|
|
1272
|
+
if (this.On === undefined) {
|
|
1273
|
+
this.On = false;
|
|
1274
|
+
this.accessory.context.On = this.On;
|
|
1254
1275
|
} else {
|
|
1255
|
-
|
|
1276
|
+
this.On = this.accessory.context.On;
|
|
1256
1277
|
}
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
async allowPushChanges(device: device & devicesConfig): Promise<void> {
|
|
1260
|
-
if (device.bot?.allowPush) {
|
|
1261
|
-
this.allowPush = true;
|
|
1278
|
+
if (this.BatteryLevel === undefined) {
|
|
1279
|
+
this.BatteryLevel = 100;
|
|
1262
1280
|
} else {
|
|
1263
|
-
this.
|
|
1281
|
+
this.BatteryLevel = this.accessory.context.BatteryLevel;
|
|
1264
1282
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
this.outletService = this.accessory.getService(this.platform.Service.Outlet);
|
|
1271
|
-
if (this.outletService) {
|
|
1272
|
-
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Outlet Service`);
|
|
1283
|
+
if (this.StatusLowBattery === undefined) {
|
|
1284
|
+
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
1285
|
+
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
1286
|
+
} else {
|
|
1287
|
+
this.StatusLowBattery = this.accessory.context.StatusLowBattery;
|
|
1273
1288
|
}
|
|
1274
|
-
accessory.removeService(this.outletService!);
|
|
1275
1289
|
}
|
|
1276
1290
|
|
|
1277
|
-
async
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1291
|
+
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
1292
|
+
if (device.refreshRate) {
|
|
1293
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
1294
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1295
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
1296
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
1297
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1282
1298
|
}
|
|
1283
|
-
accessory.removeService(this.garageDoorService!);
|
|
1284
1299
|
}
|
|
1285
1300
|
|
|
1286
|
-
async
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Door Service`);
|
|
1301
|
+
async config(device: device & devicesConfig): Promise<void> {
|
|
1302
|
+
let config = {};
|
|
1303
|
+
if (device.bot) {
|
|
1304
|
+
config = device.bot;
|
|
1291
1305
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
async removeLockService(accessory: PlatformAccessory): Promise<void> {
|
|
1296
|
-
// If lockService still pressent, then remove first
|
|
1297
|
-
this.lockService = this.accessory.getService(this.platform.Service.LockMechanism);
|
|
1298
|
-
if (this.lockService) {
|
|
1299
|
-
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Lock Service`);
|
|
1306
|
+
if (device.connectionType !== undefined) {
|
|
1307
|
+
config['connectionType'] = device.connectionType;
|
|
1300
1308
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
async removeFaucetService(accessory: PlatformAccessory): Promise<void> {
|
|
1305
|
-
// If faucetService still pressent, then remove first
|
|
1306
|
-
this.faucetService = this.accessory.getService(this.platform.Service.Faucet);
|
|
1307
|
-
if (this.faucetService) {
|
|
1308
|
-
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Faucet Service`);
|
|
1309
|
+
if (device.logging !== undefined) {
|
|
1310
|
+
config['logging'] = device.logging;
|
|
1309
1311
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
async removeFanService(accessory: PlatformAccessory): Promise<void> {
|
|
1314
|
-
// If fanService still pressent, then remove first
|
|
1315
|
-
this.fanService = this.accessory.getService(this.platform.Service.Fan);
|
|
1316
|
-
if (this.fanService) {
|
|
1317
|
-
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Fan Service`);
|
|
1312
|
+
if (device.refreshRate !== undefined) {
|
|
1313
|
+
config['refreshRate'] = device.refreshRate;
|
|
1318
1314
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
async removeWindowService(accessory: PlatformAccessory): Promise<void> {
|
|
1323
|
-
// If windowService still pressent, then remove first
|
|
1324
|
-
this.windowService = this.accessory.getService(this.platform.Service.Window);
|
|
1325
|
-
if (this.windowService) {
|
|
1326
|
-
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Window Service`);
|
|
1315
|
+
if (device.scanDuration !== undefined) {
|
|
1316
|
+
config['scanDuration'] = device.scanDuration;
|
|
1327
1317
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
async removeWindowCoveringService(accessory: PlatformAccessory): Promise<void> {
|
|
1332
|
-
// If windowCoveringService still pressent, then remove first
|
|
1333
|
-
this.windowCoveringService = this.accessory.getService(this.platform.Service.WindowCovering);
|
|
1334
|
-
if (this.windowCoveringService) {
|
|
1335
|
-
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Window Covering Service`);
|
|
1318
|
+
if (device.offline !== undefined) {
|
|
1319
|
+
config['offline'] = device.offline;
|
|
1336
1320
|
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
async removeStatefulProgrammableSwitchService(accessory: PlatformAccessory): Promise<void> {
|
|
1341
|
-
// If statefulProgrammableSwitchService still pressent, then remove first
|
|
1342
|
-
this.statefulProgrammableSwitchService = this.accessory.getService(this.platform.Service.StatefulProgrammableSwitch);
|
|
1343
|
-
if (this.statefulProgrammableSwitchService) {
|
|
1344
|
-
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
|
|
1321
|
+
if (Object.entries(config).length !== 0) {
|
|
1322
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
|
|
1345
1323
|
}
|
|
1346
|
-
accessory.removeService(this.statefulProgrammableSwitchService!);
|
|
1347
1324
|
}
|
|
1348
1325
|
|
|
1349
|
-
async
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1326
|
+
async logs(device: device & devicesConfig): Promise<void> {
|
|
1327
|
+
if (this.platform.debugMode) {
|
|
1328
|
+
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
1329
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
1330
|
+
} else if (device.logging) {
|
|
1331
|
+
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
1332
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
1333
|
+
} else if (this.platform.config.options?.logging) {
|
|
1334
|
+
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
1335
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
1336
|
+
} else {
|
|
1337
|
+
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
1338
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
1354
1339
|
}
|
|
1355
|
-
accessory.removeService(this.switchService!);
|
|
1356
1340
|
}
|
|
1357
1341
|
|
|
1358
1342
|
/**
|