@switchbot/homebridge-switchbot 2.0.0-beta.2 → 2.0.0-beta.21
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 +5 -5
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +227 -199
- 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 +216 -214
- package/src/settings.ts +15 -11
package/src/device/curtain.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { MqttClient } from 'mqtt';
|
|
|
5
5
|
import { IncomingMessage } from 'http';
|
|
6
6
|
import { interval, Subject } from 'rxjs';
|
|
7
7
|
import { connectAsync } from 'async-mqtt';
|
|
8
|
+
import superStringify from 'super-stringify';
|
|
8
9
|
import { SwitchBotPlatform } from '../platform';
|
|
9
10
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
10
11
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
@@ -35,10 +36,10 @@ export class Curtain {
|
|
|
35
36
|
// BLE Others
|
|
36
37
|
connected?: boolean;
|
|
37
38
|
switchbot!: switchbot;
|
|
38
|
-
SwitchToOpenAPI?: boolean;
|
|
39
39
|
serviceData!: serviceData;
|
|
40
40
|
spaceBetweenLevels!: number;
|
|
41
41
|
address!: ad['address'];
|
|
42
|
+
SwitchToOpenAPI?: boolean;
|
|
42
43
|
calibration: serviceData['calibration'];
|
|
43
44
|
battery: serviceData['battery'];
|
|
44
45
|
position: serviceData['position'];
|
|
@@ -48,6 +49,9 @@ export class Curtain {
|
|
|
48
49
|
setNewTarget!: boolean;
|
|
49
50
|
setNewTargetTimer!: NodeJS.Timeout;
|
|
50
51
|
|
|
52
|
+
//MQTT stuff
|
|
53
|
+
mqttClient: MqttClient | null = null;
|
|
54
|
+
|
|
51
55
|
// Config
|
|
52
56
|
set_minStep!: number;
|
|
53
57
|
updateRate!: number;
|
|
@@ -63,8 +67,9 @@ export class Curtain {
|
|
|
63
67
|
curtainUpdateInProgress!: boolean;
|
|
64
68
|
doCurtainUpdate!: Subject<void>;
|
|
65
69
|
|
|
66
|
-
//
|
|
67
|
-
|
|
70
|
+
// Connection
|
|
71
|
+
private readonly BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'Both');
|
|
72
|
+
private readonly OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'Both');
|
|
68
73
|
|
|
69
74
|
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
|
|
70
75
|
// default placeholders
|
|
@@ -73,9 +78,7 @@ export class Curtain {
|
|
|
73
78
|
this.scan(device);
|
|
74
79
|
this.config(device);
|
|
75
80
|
this.setupMqtt(device);
|
|
76
|
-
this.
|
|
77
|
-
this.TargetPosition = 0;
|
|
78
|
-
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
81
|
+
this.context();
|
|
79
82
|
|
|
80
83
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
81
84
|
this.doCurtainUpdate = new Subject();
|
|
@@ -137,33 +140,33 @@ export class Curtain {
|
|
|
137
140
|
|
|
138
141
|
// Light Sensor Service
|
|
139
142
|
if (device.curtain?.hide_lightsensor) {
|
|
140
|
-
this.debugLog(
|
|
143
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
|
|
141
144
|
this.lightSensorService = this.accessory.getService(this.platform.Service.LightSensor);
|
|
142
145
|
accessory.removeService(this.lightSensorService!);
|
|
143
146
|
} else if (!this.lightSensorService) {
|
|
144
|
-
this.debugLog(
|
|
147
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Light Sensor Service`);
|
|
145
148
|
(this.lightSensorService =
|
|
146
149
|
this.accessory.getService(this.platform.Service.LightSensor) || this.accessory.addService(this.platform.Service.LightSensor)),
|
|
147
150
|
`${accessory.displayName} Light Sensor`;
|
|
148
151
|
|
|
149
152
|
this.lightSensorService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Light Sensor`);
|
|
150
153
|
} else {
|
|
151
|
-
this.debugLog(
|
|
154
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Light Sensor Service Not Added`);
|
|
152
155
|
}
|
|
153
156
|
|
|
154
157
|
// Battery Service
|
|
155
|
-
if (!
|
|
156
|
-
this.debugLog(
|
|
158
|
+
if (!this.BLE) {
|
|
159
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Battery Service`);
|
|
157
160
|
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
158
161
|
accessory.removeService(this.batteryService!);
|
|
159
|
-
} else if (
|
|
160
|
-
this.debugLog(
|
|
162
|
+
} else if (this.BLE && !this.batteryService) {
|
|
163
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Battery Service`);
|
|
161
164
|
(this.batteryService = this.accessory.getService(this.platform.Service.Battery) || this.accessory.addService(this.platform.Service.Battery)),
|
|
162
165
|
`${accessory.displayName} Battery`;
|
|
163
166
|
|
|
164
167
|
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
165
168
|
} else {
|
|
166
|
-
this.debugLog(
|
|
169
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Battery Service Not Added`);
|
|
167
170
|
}
|
|
168
171
|
|
|
169
172
|
// Update Homekit
|
|
@@ -183,7 +186,7 @@ export class Curtain {
|
|
|
183
186
|
if (this.PositionState === this.platform.Characteristic.PositionState.STOPPED) {
|
|
184
187
|
return;
|
|
185
188
|
}
|
|
186
|
-
this.debugLog(
|
|
189
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Refresh Status When Moving, PositionState: ${this.PositionState}`);
|
|
187
190
|
await this.refreshStatus();
|
|
188
191
|
});
|
|
189
192
|
|
|
@@ -200,95 +203,65 @@ export class Curtain {
|
|
|
200
203
|
try {
|
|
201
204
|
await this.pushChanges();
|
|
202
205
|
} catch (e: any) {
|
|
203
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} failed pushChanges`);
|
|
204
|
-
if (this.deviceLogging.includes('debug')) {
|
|
205
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} failed pushChanges,` + ` Error Message: ${JSON.stringify(e.message)}`);
|
|
206
|
-
}
|
|
207
206
|
this.apiError(e);
|
|
207
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
|
|
208
|
+
+ ` Error Message: ${superStringify(e.message)}`);
|
|
208
209
|
}
|
|
209
210
|
this.curtainUpdateInProgress = false;
|
|
210
211
|
});
|
|
211
212
|
}
|
|
212
213
|
|
|
213
|
-
/*
|
|
214
|
-
* Publish MQTT message for topics of
|
|
215
|
-
* 'homebridge-switchbot/curtain/xx:xx:xx:xx:xx:xx'
|
|
216
|
-
*/
|
|
217
|
-
mqttPublish(topic: string, message: any) {
|
|
218
|
-
const mac = this.device.deviceId
|
|
219
|
-
?.toLowerCase()
|
|
220
|
-
.match(/[\s\S]{1,2}/g)
|
|
221
|
-
?.join(':');
|
|
222
|
-
const options = this.device.mqttPubOptions || {};
|
|
223
|
-
this.mqttClient?.publish(`homebridge-switchbot/curtain/${mac}/${topic}`, `${message}`, options);
|
|
224
|
-
this.debugLog(`Meter: ${this.accessory.displayName} MQTT message: ${topic}/${message} options:${JSON.stringify(options)}`);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/*
|
|
228
|
-
* Setup MQTT hadler if URL is specifed.
|
|
229
|
-
*/
|
|
230
|
-
async setupMqtt(device: device & devicesConfig): Promise<void> {
|
|
231
|
-
if (device.mqttURL) {
|
|
232
|
-
try {
|
|
233
|
-
this.mqttClient = await connectAsync(device.mqttURL, device.mqttOptions || {});
|
|
234
|
-
this.debugLog(`Meter: ${this.accessory.displayName} MQTT connection has been established successfully.`);
|
|
235
|
-
this.mqttClient.on('error', (e: Error) => {
|
|
236
|
-
this.errorLog(`Meter: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
|
|
237
|
-
});
|
|
238
|
-
} catch (e) {
|
|
239
|
-
this.mqttClient = null;
|
|
240
|
-
this.errorLog(`Meter: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
214
|
/**
|
|
246
215
|
* Parse the device status from the SwitchBot api
|
|
247
216
|
*/
|
|
248
217
|
async parseStatus(): Promise<void> {
|
|
249
|
-
if (this.
|
|
218
|
+
if (this.BLE && !this.SwitchToOpenAPI) {
|
|
219
|
+
await this.BLEparseStatus();
|
|
220
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
221
|
+
this.SwitchToOpenAPI = false;
|
|
250
222
|
await this.openAPIparseStatus();
|
|
251
223
|
} else {
|
|
252
|
-
|
|
224
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
225
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
253
226
|
}
|
|
254
227
|
}
|
|
255
228
|
|
|
256
229
|
async BLEparseStatus(): Promise<void> {
|
|
257
|
-
this.debugLog(
|
|
230
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
258
231
|
// CurrentPosition
|
|
259
232
|
this.CurrentPosition = 100 - Number(this.position);
|
|
260
233
|
await this.setMinMax();
|
|
261
|
-
this.debugLog(
|
|
234
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.CurrentPosition}`);
|
|
262
235
|
if (this.setNewTarget) {
|
|
263
|
-
this.infoLog(
|
|
236
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
|
|
264
237
|
}
|
|
265
238
|
|
|
266
239
|
if (this.setNewTarget) {
|
|
267
240
|
await this.setMinMax();
|
|
268
241
|
if (this.TargetPosition > this.CurrentPosition) {
|
|
269
|
-
this.debugLog(
|
|
242
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.CurrentPosition}`);
|
|
270
243
|
this.PositionState = this.platform.Characteristic.PositionState.INCREASING;
|
|
271
244
|
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
272
|
-
this.debugLog(
|
|
245
|
+
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} INCREASING PositionState: ${this.PositionState}`);
|
|
273
246
|
} else if (this.TargetPosition < this.CurrentPosition) {
|
|
274
|
-
this.debugLog(
|
|
247
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.CurrentPosition}`);
|
|
275
248
|
this.PositionState = this.platform.Characteristic.PositionState.DECREASING;
|
|
276
249
|
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
277
|
-
this.debugLog(
|
|
250
|
+
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} DECREASING PositionState: ${this.PositionState}`);
|
|
278
251
|
} else {
|
|
279
|
-
this.debugLog(
|
|
252
|
+
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} Standby, CurrentPosition: ${this.CurrentPosition}`);
|
|
280
253
|
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
281
254
|
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
282
|
-
this.debugLog(
|
|
255
|
+
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} STOPPED PositionState: ${this.PositionState}`);
|
|
283
256
|
}
|
|
284
257
|
} else {
|
|
285
|
-
this.debugLog(
|
|
258
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.CurrentPosition}`);
|
|
286
259
|
this.TargetPosition = this.CurrentPosition;
|
|
287
260
|
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
288
|
-
this.debugLog(
|
|
261
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
|
|
289
262
|
}
|
|
290
263
|
this.debugLog(
|
|
291
|
-
|
|
264
|
+
`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
|
|
292
265
|
` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`,
|
|
293
266
|
);
|
|
294
267
|
|
|
@@ -301,42 +274,42 @@ export class Curtain {
|
|
|
301
274
|
switch (this.lightLevel) {
|
|
302
275
|
case 1:
|
|
303
276
|
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
304
|
-
this.debugLog(
|
|
277
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
305
278
|
break;
|
|
306
279
|
case 2:
|
|
307
280
|
this.CurrentAmbientLightLevel = (this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels;
|
|
308
281
|
this.debugLog(
|
|
309
|
-
|
|
282
|
+
`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel},` +
|
|
310
283
|
` Calculation: ${(this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels}`,
|
|
311
284
|
);
|
|
312
285
|
break;
|
|
313
286
|
case 3:
|
|
314
287
|
this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 2;
|
|
315
|
-
this.debugLog(
|
|
288
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
316
289
|
break;
|
|
317
290
|
case 4:
|
|
318
291
|
this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 3;
|
|
319
|
-
this.debugLog(
|
|
292
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
320
293
|
break;
|
|
321
294
|
case 5:
|
|
322
295
|
this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 4;
|
|
323
|
-
this.debugLog(
|
|
296
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
324
297
|
break;
|
|
325
298
|
case 6:
|
|
326
299
|
this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 5;
|
|
327
|
-
this.debugLog(
|
|
300
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
328
301
|
break;
|
|
329
302
|
case 7:
|
|
330
303
|
this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 6;
|
|
331
|
-
this.debugLog(
|
|
304
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
332
305
|
break;
|
|
333
306
|
case 8:
|
|
334
307
|
this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 7;
|
|
335
|
-
this.debugLog(
|
|
308
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
336
309
|
break;
|
|
337
310
|
case 9:
|
|
338
311
|
this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 8;
|
|
339
|
-
this.debugLog(
|
|
312
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel}`);
|
|
340
313
|
break;
|
|
341
314
|
case 10:
|
|
342
315
|
default:
|
|
@@ -344,7 +317,8 @@ export class Curtain {
|
|
|
344
317
|
this.debugLog();
|
|
345
318
|
}
|
|
346
319
|
this.debugLog(
|
|
347
|
-
|
|
320
|
+
`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.lightLevel},`
|
|
321
|
+
+ ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`,
|
|
348
322
|
);
|
|
349
323
|
}
|
|
350
324
|
// Battery
|
|
@@ -354,89 +328,87 @@ export class Curtain {
|
|
|
354
328
|
} else {
|
|
355
329
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
356
330
|
}
|
|
357
|
-
this.debugLog(
|
|
331
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
|
|
332
|
+
+` StatusLowBattery: ${this.StatusLowBattery}`);
|
|
358
333
|
}
|
|
359
334
|
|
|
360
335
|
async openAPIparseStatus(): Promise<void> {
|
|
361
|
-
|
|
362
|
-
|
|
336
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
337
|
+
// CurrentPosition
|
|
338
|
+
this.CurrentPosition = 100 - Number(this.slidePosition);
|
|
339
|
+
await this.setMinMax();
|
|
340
|
+
this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
|
|
341
|
+
if (this.setNewTarget) {
|
|
342
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
|
|
363
343
|
}
|
|
364
|
-
if (this.platform.config.credentials?.token) {
|
|
365
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
366
|
-
// CurrentPosition
|
|
367
|
-
this.CurrentPosition = 100 - Number(this.slidePosition);
|
|
368
|
-
await this.setMinMax();
|
|
369
|
-
this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
|
|
370
|
-
if (this.setNewTarget) {
|
|
371
|
-
this.infoLog(`Curtain: ${this.accessory.displayName} Checking Status ...`);
|
|
372
|
-
}
|
|
373
344
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
} else {
|
|
387
|
-
this.debugLog(`Curtain: ${this.CurrentPosition} Standby, CurrentPosition: ${this.CurrentPosition}`);
|
|
388
|
-
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
389
|
-
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
390
|
-
this.debugLog(`Curtain: ${this.CurrentPosition} STOPPED PositionState: ${this.PositionState}`);
|
|
391
|
-
}
|
|
345
|
+
if (this.setNewTarget && this.moving) {
|
|
346
|
+
await this.setMinMax();
|
|
347
|
+
if (this.TargetPosition > this.CurrentPosition) {
|
|
348
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.CurrentPosition} `);
|
|
349
|
+
this.PositionState = this.platform.Characteristic.PositionState.INCREASING;
|
|
350
|
+
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
351
|
+
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} INCREASING PositionState: ${this.PositionState}`);
|
|
352
|
+
} else if (this.TargetPosition < this.CurrentPosition) {
|
|
353
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.CurrentPosition} `);
|
|
354
|
+
this.PositionState = this.platform.Characteristic.PositionState.DECREASING;
|
|
355
|
+
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
356
|
+
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} DECREASING PositionState: ${this.PositionState}`);
|
|
392
357
|
} else {
|
|
393
|
-
this.debugLog(
|
|
394
|
-
this.TargetPosition = this.CurrentPosition;
|
|
358
|
+
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} Standby, CurrentPosition: ${this.CurrentPosition}`);
|
|
395
359
|
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
396
|
-
this.
|
|
360
|
+
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
361
|
+
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} STOPPED PositionState: ${this.PositionState}`);
|
|
397
362
|
}
|
|
398
|
-
|
|
399
|
-
|
|
363
|
+
} else {
|
|
364
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.CurrentPosition}`);
|
|
365
|
+
this.TargetPosition = this.CurrentPosition;
|
|
366
|
+
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
367
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
|
|
368
|
+
}
|
|
369
|
+
this.debugLog(
|
|
370
|
+
`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
|
|
400
371
|
` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`,
|
|
401
|
-
|
|
372
|
+
);
|
|
402
373
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
374
|
+
if (!this.device.curtain?.hide_lightsensor) {
|
|
375
|
+
this.set_minLux = this.minLux();
|
|
376
|
+
this.set_maxLux = this.maxLux();
|
|
377
|
+
// Brightness
|
|
378
|
+
switch (this.brightness) {
|
|
379
|
+
case 'dim':
|
|
380
|
+
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
381
|
+
break;
|
|
382
|
+
case 'bright':
|
|
383
|
+
default:
|
|
384
|
+
this.CurrentAmbientLightLevel = this.set_maxLux;
|
|
416
385
|
}
|
|
386
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
417
387
|
}
|
|
418
388
|
}
|
|
419
389
|
|
|
420
390
|
async refreshStatus(): Promise<void> {
|
|
421
|
-
if (this.
|
|
391
|
+
if (this.BLE) {
|
|
422
392
|
await this.BLERefreshStatus();
|
|
423
|
-
} else {
|
|
393
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
424
394
|
await this.openAPIRefreshStatus();
|
|
395
|
+
} else {
|
|
396
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
397
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
425
398
|
}
|
|
426
399
|
}
|
|
427
400
|
|
|
428
401
|
async BLERefreshStatus(): Promise<void> {
|
|
429
|
-
this.debugLog(
|
|
402
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
|
|
430
403
|
const switchbot = await this.platform.connectBLE();
|
|
431
404
|
// Convert to BLE Address
|
|
432
405
|
this.device.bleMac = this.device
|
|
433
406
|
.deviceId!.match(/.{1,2}/g)!
|
|
434
407
|
.join(':')
|
|
435
408
|
.toLowerCase();
|
|
436
|
-
this.debugLog(
|
|
409
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
437
410
|
this.getCustomBLEAddress(switchbot);
|
|
438
411
|
// Start to monitor advertisement packets
|
|
439
|
-
this.errorLog(`Color Bulb: ${this.accessory.displayName} switchbot: ${JSON.stringify(switchbot)}`);
|
|
440
412
|
if (switchbot !== false) {
|
|
441
413
|
switchbot
|
|
442
414
|
.startScan({
|
|
@@ -450,26 +422,26 @@ export class Curtain {
|
|
|
450
422
|
if (this.deviceLogging.includes('debug')) {
|
|
451
423
|
this.infoLog(this.address);
|
|
452
424
|
this.infoLog(this.device.bleMac);
|
|
453
|
-
this.infoLog(
|
|
454
|
-
this.infoLog(
|
|
425
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
|
|
426
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
|
|
455
427
|
}
|
|
456
428
|
this.serviceData = ad.serviceData;
|
|
457
429
|
this.calibration = ad.serviceData.calibration;
|
|
458
430
|
this.battery = ad.serviceData.battery;
|
|
459
431
|
this.position = ad.serviceData.position;
|
|
460
432
|
this.lightLevel = ad.serviceData.lightLevel;
|
|
461
|
-
this.debugLog(
|
|
433
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${superStringify(ad.serviceData)}`);
|
|
462
434
|
this.debugLog(
|
|
463
|
-
|
|
435
|
+
`${this.device.deviceType}: ${this.accessory.displayName} calibration: ${ad.serviceData.calibration}, ` +
|
|
464
436
|
`position: ${ad.serviceData.position}, lightLevel: ${ad.serviceData.lightLevel}, battery: ${ad.serviceData.battery}`,
|
|
465
437
|
);
|
|
466
438
|
|
|
467
439
|
if (this.serviceData) {
|
|
468
440
|
this.connected = true;
|
|
469
|
-
this.debugLog(
|
|
441
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
470
442
|
} else {
|
|
471
443
|
this.connected = false;
|
|
472
|
-
this.debugLog(
|
|
444
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
473
445
|
}
|
|
474
446
|
};
|
|
475
447
|
// Wait 2 seconds
|
|
@@ -482,161 +454,101 @@ export class Curtain {
|
|
|
482
454
|
this.parseStatus();
|
|
483
455
|
this.updateHomeKitCharacteristics();
|
|
484
456
|
} else {
|
|
485
|
-
this.
|
|
486
|
-
if (this.platform.config.credentials?.token) {
|
|
487
|
-
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
488
|
-
this.SwitchToOpenAPI = true;
|
|
489
|
-
await this.openAPIRefreshStatus();
|
|
490
|
-
}
|
|
457
|
+
await this.BLEconnection(switchbot);
|
|
491
458
|
}
|
|
492
459
|
})
|
|
493
460
|
.catch(async (e: any) => {
|
|
494
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
|
|
495
|
-
if (this.deviceLogging.includes('debug')) {
|
|
496
|
-
this.errorLog(
|
|
497
|
-
`Curtain: ${this.accessory.displayName} failed refreshStatus with BLE Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
498
|
-
);
|
|
499
|
-
}
|
|
500
|
-
if (this.platform.config.credentials?.token) {
|
|
501
|
-
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
502
|
-
this.SwitchToOpenAPI = true;
|
|
503
|
-
await this.openAPIRefreshStatus();
|
|
504
|
-
}
|
|
505
461
|
this.apiError(e);
|
|
462
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
|
|
463
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
464
|
+
await this.BLEconnection(switchbot);
|
|
506
465
|
});
|
|
507
466
|
} else {
|
|
508
467
|
await this.BLEconnection(switchbot);
|
|
509
468
|
}
|
|
510
469
|
}
|
|
511
470
|
|
|
512
|
-
async getCustomBLEAddress(switchbot: any) {
|
|
513
|
-
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
514
|
-
(async () => {
|
|
515
|
-
// Start to monitor advertisement packets
|
|
516
|
-
await switchbot.startScan({
|
|
517
|
-
model: 'c',
|
|
518
|
-
});
|
|
519
|
-
// Set an event handler
|
|
520
|
-
switchbot.onadvertisement = (ad: any) => {
|
|
521
|
-
this.warnLog(`Curtain: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
|
|
522
|
-
};
|
|
523
|
-
await switchbot.wait(10000);
|
|
524
|
-
// Stop to monitor
|
|
525
|
-
switchbot.stopScan();
|
|
526
|
-
})();
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
async BLEconnection(switchbot: any): Promise<void> {
|
|
531
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
532
|
-
if (this.platform.config.credentials?.token) {
|
|
533
|
-
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
534
|
-
this.SwitchToOpenAPI = true;
|
|
535
|
-
await this.openAPIRefreshStatus();
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
471
|
async openAPIRefreshStatus(): Promise<void> {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} d: ${d}`);
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
res.on('end', () => {
|
|
571
|
-
try {
|
|
572
|
-
this.deviceStatus = JSON.parse(rawData);
|
|
573
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
574
|
-
this.slidePosition = this.deviceStatus.body.slidePosition;
|
|
575
|
-
this.moving = this.deviceStatus.body.moving;
|
|
576
|
-
this.brightness = this.deviceStatus.body.brightness;
|
|
577
|
-
this.parseStatus();
|
|
578
|
-
this.updateHomeKitCharacteristics();
|
|
579
|
-
} catch (e: any) {
|
|
580
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} error message: ${e.message}`);
|
|
581
|
-
}
|
|
582
|
-
});
|
|
472
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
473
|
+
try {
|
|
474
|
+
const t = Date.now();
|
|
475
|
+
const nonce = 'requestID';
|
|
476
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
477
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
478
|
+
const sign = signTerm.toString('base64');
|
|
479
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
480
|
+
const options = {
|
|
481
|
+
hostname: HostDomain,
|
|
482
|
+
port: 443,
|
|
483
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
484
|
+
method: 'GET',
|
|
485
|
+
headers: {
|
|
486
|
+
Authorization: this.platform.config.credentials?.token,
|
|
487
|
+
sign: sign,
|
|
488
|
+
nonce: nonce,
|
|
489
|
+
t: t,
|
|
490
|
+
'Content-Type': 'application/json',
|
|
491
|
+
},
|
|
492
|
+
};
|
|
493
|
+
const req = https.request(options, (res) => {
|
|
494
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
495
|
+
let rawData = '';
|
|
496
|
+
res.on('data', (d) => {
|
|
497
|
+
rawData += d;
|
|
498
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
583
499
|
});
|
|
584
|
-
|
|
585
|
-
|
|
500
|
+
res.on('end', () => {
|
|
501
|
+
try {
|
|
502
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
503
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
504
|
+
this.slidePosition = this.deviceStatus.body.slidePosition;
|
|
505
|
+
this.moving = this.deviceStatus.body.moving;
|
|
506
|
+
this.brightness = this.deviceStatus.body.brightness;
|
|
507
|
+
this.parseStatus();
|
|
508
|
+
this.updateHomeKitCharacteristics();
|
|
509
|
+
} catch (e: any) {
|
|
510
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
511
|
+
}
|
|
586
512
|
});
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
this.errorLog(
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
}
|
|
513
|
+
});
|
|
514
|
+
req.on('error', (e: any) => {
|
|
515
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
516
|
+
});
|
|
517
|
+
req.end();
|
|
518
|
+
} catch (e: any) {
|
|
519
|
+
this.apiError(e);
|
|
520
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
521
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
597
522
|
}
|
|
598
523
|
}
|
|
599
524
|
|
|
600
525
|
async pushChanges(): Promise<void> {
|
|
601
|
-
if (this.
|
|
602
|
-
await this.
|
|
603
|
-
} else {
|
|
526
|
+
if (this.BLE) {
|
|
527
|
+
await this.BLERefreshStatus();
|
|
528
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
604
529
|
await this.openAPIpushChanges();
|
|
530
|
+
} else {
|
|
531
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
532
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
605
533
|
}
|
|
606
534
|
interval(this.updateRate * 1000)
|
|
607
|
-
.pipe(take(
|
|
535
|
+
.pipe(take(1))
|
|
608
536
|
.subscribe(async () => {
|
|
609
537
|
await this.refreshStatus();
|
|
610
538
|
});
|
|
611
539
|
}
|
|
612
540
|
|
|
613
541
|
async BLEpushChanges(): Promise<void> {
|
|
542
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
614
543
|
if (this.TargetPosition !== this.CurrentPosition) {
|
|
615
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} BLE pushChanges`);
|
|
616
544
|
const switchbot = await this.platform.connectBLE();
|
|
617
545
|
// Convert to BLE Address
|
|
618
546
|
this.device.bleMac = this.device
|
|
619
547
|
.deviceId!.match(/.{1,2}/g)!
|
|
620
548
|
.join(':')
|
|
621
549
|
.toLowerCase();
|
|
622
|
-
this.debugLog(
|
|
623
|
-
|
|
624
|
-
if (this.device.curtain?.setOpenMode === '1') {
|
|
625
|
-
this.setPositionMode = 1;
|
|
626
|
-
this.Mode = 'Silent Mode';
|
|
627
|
-
} else {
|
|
628
|
-
this.setPositionMode = 0;
|
|
629
|
-
this.Mode = 'Performance Mode';
|
|
630
|
-
}
|
|
631
|
-
} else {
|
|
632
|
-
if (this.device.curtain?.setCloseMode === '1') {
|
|
633
|
-
this.setPositionMode = 1;
|
|
634
|
-
this.Mode = 'Silent Mode';
|
|
635
|
-
} else {
|
|
636
|
-
this.setPositionMode = 0;
|
|
637
|
-
this.Mode = 'Performance Mode';
|
|
638
|
-
}
|
|
639
|
-
}
|
|
550
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
551
|
+
this.SilentPerformance();
|
|
640
552
|
const adjustedMode = this.setPositionMode || null;
|
|
641
553
|
if (adjustedMode === null) {
|
|
642
554
|
this.Mode = 'Default Mode';
|
|
@@ -645,256 +557,286 @@ export class Curtain {
|
|
|
645
557
|
if (switchbot !== false) {
|
|
646
558
|
switchbot
|
|
647
559
|
.discover({ model: 'c', quick: true, id: this.device.bleMac })
|
|
648
|
-
.then((device_list) => {
|
|
560
|
+
.then((device_list: any) => {
|
|
649
561
|
this.infoLog(`${this.accessory.displayName} Target Position: ${this.TargetPosition}`);
|
|
650
562
|
return device_list[0].runToPos(100 - Number(this.TargetPosition), adjustedMode);
|
|
651
563
|
})
|
|
652
564
|
.then(() => {
|
|
653
|
-
this.debugLog(
|
|
565
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
654
566
|
})
|
|
655
567
|
.catch(async (e: any) => {
|
|
656
|
-
this.
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
if (this.platform.config.credentials?.token) {
|
|
663
|
-
this.warnLog(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
568
|
+
this.apiError(e);
|
|
569
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
570
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
571
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
572
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
664
573
|
await this.openAPIpushChanges();
|
|
665
574
|
}
|
|
666
|
-
this.apiError(e);
|
|
667
575
|
});
|
|
668
576
|
} else {
|
|
669
|
-
this.errorLog(
|
|
577
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
|
|
670
578
|
if (this.platform.config.credentials?.token) {
|
|
671
|
-
this.warnLog(
|
|
579
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
672
580
|
await this.openAPIpushChanges();
|
|
673
581
|
}
|
|
674
582
|
}
|
|
675
583
|
} else {
|
|
676
|
-
this.debugLog(
|
|
677
|
-
`Curtain: ${this.accessory.displayName} No BLE Changes, CurrentPosition & TargetPosition Are the Same.` +
|
|
584
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.` +
|
|
678
585
|
` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}`,
|
|
679
586
|
);
|
|
680
587
|
}
|
|
681
588
|
}
|
|
682
589
|
|
|
683
590
|
async openAPIpushChanges(): Promise<void> {
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
this.setPositionMode = this.device.curtain?.setOpenMode;
|
|
701
|
-
} else {
|
|
702
|
-
this.setPositionMode = this.device.curtain?.setCloseMode;
|
|
703
|
-
}
|
|
704
|
-
if (this.setPositionMode === '1') {
|
|
705
|
-
this.Mode = 'Silent Mode';
|
|
706
|
-
} else if (this.setPositionMode === '0') {
|
|
707
|
-
this.Mode = 'Performance Mode';
|
|
708
|
-
} else {
|
|
709
|
-
this.Mode = 'Default Mode';
|
|
710
|
-
}
|
|
711
|
-
this.debugLog(`${this.accessory.displayName} Mode: ${this.Mode}`);
|
|
712
|
-
const adjustedMode = this.setPositionMode || 'ff';
|
|
713
|
-
const body = JSON.stringify({
|
|
714
|
-
'command': 'setPosition',
|
|
715
|
-
'parameter': `0,${adjustedMode},${adjustedTargetPosition}`,
|
|
716
|
-
'commandType': 'command',
|
|
717
|
-
});
|
|
718
|
-
this.infoLog(`Curtain: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
719
|
-
const options = {
|
|
720
|
-
hostname: HostDomain,
|
|
721
|
-
port: 443,
|
|
722
|
-
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
723
|
-
method: 'POST',
|
|
724
|
-
headers: {
|
|
725
|
-
'Authorization': this.platform.config.credentials?.token,
|
|
726
|
-
'sign': sign,
|
|
727
|
-
'nonce': nonce,
|
|
728
|
-
't': t,
|
|
729
|
-
'Content-Type': 'application/json',
|
|
730
|
-
'Content-Length': body.length,
|
|
731
|
-
},
|
|
732
|
-
};
|
|
733
|
-
const req = https.request(options, res => {
|
|
734
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
735
|
-
this.statusCode({ res });
|
|
736
|
-
res.on('data', d => {
|
|
737
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} d: ${d}`);
|
|
738
|
-
});
|
|
739
|
-
});
|
|
740
|
-
req.on('error', (e: any) => {
|
|
741
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} error message: ${e.message}`);
|
|
742
|
-
});
|
|
743
|
-
req.write(body);
|
|
744
|
-
req.end();
|
|
745
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} openAPIpushChanges: ${JSON.stringify(req)}`);
|
|
591
|
+
try {
|
|
592
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI pushChanges`);
|
|
593
|
+
if (this.TargetPosition !== this.CurrentPosition) {
|
|
594
|
+
// Make Push On request to the API
|
|
595
|
+
const t = Date.now();
|
|
596
|
+
const nonce = 'requestID';
|
|
597
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
598
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
599
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
600
|
+
.digest();
|
|
601
|
+
const sign = signTerm.toString('base64');
|
|
602
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
603
|
+
this.debugLog(`Pushing ${this.TargetPosition}`);
|
|
604
|
+
const adjustedTargetPosition = 100 - Number(this.TargetPosition);
|
|
605
|
+
if (this.TargetPosition > 50) {
|
|
606
|
+
this.setPositionMode = this.device.curtain?.setOpenMode;
|
|
746
607
|
} else {
|
|
747
|
-
this.
|
|
748
|
-
`Curtain: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.` +
|
|
749
|
-
` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}`,
|
|
750
|
-
);
|
|
608
|
+
this.setPositionMode = this.device.curtain?.setCloseMode;
|
|
751
609
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
if (this.
|
|
755
|
-
this.
|
|
756
|
-
|
|
757
|
-
|
|
610
|
+
if (this.setPositionMode === '1') {
|
|
611
|
+
this.Mode = 'Silent Mode';
|
|
612
|
+
} else if (this.setPositionMode === '0') {
|
|
613
|
+
this.Mode = 'Performance Mode';
|
|
614
|
+
} else {
|
|
615
|
+
this.Mode = 'Default Mode';
|
|
758
616
|
}
|
|
759
|
-
this.
|
|
617
|
+
this.debugLog(`${this.accessory.displayName} Mode: ${this.Mode}`);
|
|
618
|
+
const adjustedMode = this.setPositionMode || 'ff';
|
|
619
|
+
const body = superStringify({
|
|
620
|
+
'command': 'setPosition',
|
|
621
|
+
'parameter': `0,${adjustedMode},${adjustedTargetPosition}`,
|
|
622
|
+
'commandType': 'command',
|
|
623
|
+
});
|
|
624
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
625
|
+
const options = {
|
|
626
|
+
hostname: HostDomain,
|
|
627
|
+
port: 443,
|
|
628
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
629
|
+
method: 'POST',
|
|
630
|
+
headers: {
|
|
631
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
632
|
+
'sign': sign,
|
|
633
|
+
'nonce': nonce,
|
|
634
|
+
't': t,
|
|
635
|
+
'Content-Type': 'application/json',
|
|
636
|
+
'Content-Length': body.length,
|
|
637
|
+
},
|
|
638
|
+
};
|
|
639
|
+
const req = https.request(options, res => {
|
|
640
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
|
|
641
|
+
this.statusCode({ res });
|
|
642
|
+
res.on('data', d => {
|
|
643
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
req.on('error', (e: any) => {
|
|
647
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
648
|
+
});
|
|
649
|
+
req.write(body);
|
|
650
|
+
req.end();
|
|
651
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges: ${superStringify(req)}`);
|
|
652
|
+
} else {
|
|
653
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.`
|
|
654
|
+
+` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}`,
|
|
655
|
+
);
|
|
760
656
|
}
|
|
657
|
+
} catch (e: any) {
|
|
658
|
+
this.apiError(e);
|
|
659
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushBrightnessChanges with ${this.device.connectionType}`
|
|
660
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`,
|
|
661
|
+
);
|
|
761
662
|
}
|
|
762
663
|
}
|
|
763
664
|
|
|
665
|
+
/**
|
|
666
|
+
* Handle requests to set the value of the "Target Position" characteristic
|
|
667
|
+
*/
|
|
668
|
+
async TargetPositionSet(value: CharacteristicValue): Promise<void> {
|
|
669
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
|
|
670
|
+
|
|
671
|
+
this.TargetPosition = value;
|
|
672
|
+
this.mqttPublish('TargetPosition', this.TargetPosition);
|
|
673
|
+
|
|
674
|
+
await this.setMinMax();
|
|
675
|
+
if (value > this.CurrentPosition) {
|
|
676
|
+
this.PositionState = this.platform.Characteristic.PositionState.INCREASING;
|
|
677
|
+
this.setNewTarget = true;
|
|
678
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value}, CurrentPosition: ${this.CurrentPosition}`);
|
|
679
|
+
} else if (value < this.CurrentPosition) {
|
|
680
|
+
this.PositionState = this.platform.Characteristic.PositionState.DECREASING;
|
|
681
|
+
this.setNewTarget = true;
|
|
682
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value}, CurrentPosition: ${this.CurrentPosition}`);
|
|
683
|
+
} else {
|
|
684
|
+
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
685
|
+
this.setNewTarget = false;
|
|
686
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value}, CurrentPosition: ${this.CurrentPosition}`);
|
|
687
|
+
}
|
|
688
|
+
this.windowCoveringService.setCharacteristic(this.platform.Characteristic.PositionState, this.PositionState);
|
|
689
|
+
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* If Curtain movement time is short, the moving flag from backend is always false.
|
|
693
|
+
* The minimum time depends on the network control latency.
|
|
694
|
+
*/
|
|
695
|
+
clearTimeout(this.setNewTargetTimer);
|
|
696
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.updateRate}`);
|
|
697
|
+
if (this.setNewTarget) {
|
|
698
|
+
this.setNewTargetTimer = setTimeout(() => {
|
|
699
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} setNewTarget ${this.setNewTarget} timeout`);
|
|
700
|
+
this.setNewTarget = false;
|
|
701
|
+
}, this.updateRate * 1000);
|
|
702
|
+
}
|
|
703
|
+
this.doCurtainUpdate.next();
|
|
704
|
+
}
|
|
705
|
+
|
|
764
706
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
765
707
|
await this.setMinMax();
|
|
766
708
|
if (this.CurrentPosition === undefined || Number.isNaN(this.CurrentPosition)) {
|
|
767
|
-
this.debugLog(
|
|
709
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
|
|
768
710
|
} else {
|
|
711
|
+
this.accessory.context.CurrentPosition = this.CurrentPosition;
|
|
769
712
|
this.windowCoveringService.updateCharacteristic(this.platform.Characteristic.CurrentPosition, Number(this.CurrentPosition));
|
|
770
|
-
this.debugLog(
|
|
713
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentPosition: ${this.CurrentPosition}`);
|
|
771
714
|
this.mqttPublish('CurrentPosition', this.CurrentPosition);
|
|
772
715
|
}
|
|
773
716
|
if (this.PositionState === undefined) {
|
|
774
|
-
this.debugLog(
|
|
717
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.PositionState}`);
|
|
775
718
|
} else {
|
|
719
|
+
this.accessory.context.PositionState = this.PositionState;
|
|
776
720
|
this.windowCoveringService.updateCharacteristic(this.platform.Characteristic.PositionState, Number(this.PositionState));
|
|
777
|
-
this.debugLog(
|
|
721
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic PositionState: ${this.PositionState}`);
|
|
778
722
|
this.mqttPublish('PositionState', this.PositionState);
|
|
779
723
|
}
|
|
780
724
|
if (this.TargetPosition === undefined || Number.isNaN(this.TargetPosition)) {
|
|
781
|
-
this.debugLog(
|
|
725
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.TargetPosition}`);
|
|
782
726
|
} else {
|
|
727
|
+
this.accessory.context.TargetPosition = this.TargetPosition;
|
|
783
728
|
this.windowCoveringService.updateCharacteristic(this.platform.Characteristic.TargetPosition, Number(this.TargetPosition));
|
|
784
|
-
this.debugLog(
|
|
729
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: ${this.TargetPosition}`);
|
|
785
730
|
this.mqttPublish('TargetPosition', this.TargetPosition);
|
|
786
731
|
}
|
|
787
732
|
if (!this.device.curtain?.hide_lightsensor) {
|
|
788
733
|
if (this.CurrentAmbientLightLevel === undefined || Number.isNaN(this.CurrentAmbientLightLevel)) {
|
|
789
|
-
this.debugLog(
|
|
734
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
790
735
|
} else {
|
|
736
|
+
this.accessory.context.CurrentAmbientLightLevel = this.CurrentAmbientLightLevel;
|
|
791
737
|
this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, this.CurrentAmbientLightLevel);
|
|
792
|
-
this.debugLog(
|
|
738
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
739
|
+
+ ` updateCharacteristic CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
793
740
|
this.mqttPublish('CurrentAmbientLightLevel', this.CurrentAmbientLightLevel);
|
|
794
741
|
}
|
|
795
742
|
}
|
|
796
|
-
if (this.
|
|
743
|
+
if (this.BLE) {
|
|
797
744
|
if (this.BatteryLevel === undefined) {
|
|
798
|
-
this.debugLog(
|
|
745
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
799
746
|
} else {
|
|
747
|
+
this.accessory.context.BatteryLevel = this.BatteryLevel;
|
|
800
748
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
|
|
801
|
-
this.debugLog(
|
|
749
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
802
750
|
this.mqttPublish('BatteryLevel', this.BatteryLevel);
|
|
803
751
|
}
|
|
804
752
|
if (this.StatusLowBattery === undefined) {
|
|
805
|
-
this.debugLog(
|
|
753
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
806
754
|
} else {
|
|
755
|
+
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
807
756
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
808
|
-
this.debugLog(
|
|
757
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
809
758
|
this.mqttPublish('StatusLowBattery', this.StatusLowBattery);
|
|
810
759
|
}
|
|
811
760
|
}
|
|
812
761
|
}
|
|
813
762
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
}
|
|
825
|
-
|
|
763
|
+
/*
|
|
764
|
+
* Publish MQTT message for topics of
|
|
765
|
+
* 'homebridge-switchbot/curtain/xx:xx:xx:xx:xx:xx'
|
|
766
|
+
*/
|
|
767
|
+
mqttPublish(topic: string, message: any) {
|
|
768
|
+
const mac = this.device.deviceId
|
|
769
|
+
?.toLowerCase()
|
|
770
|
+
.match(/[\s\S]{1,2}/g)
|
|
771
|
+
?.join(':');
|
|
772
|
+
const options = this.device.mqttPubOptions || {};
|
|
773
|
+
this.mqttClient?.publish(`homebridge-switchbot/curtain/${mac}/${topic}`, `${message}`, options);
|
|
774
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${topic}/${message} options:${superStringify(options)}`);
|
|
826
775
|
}
|
|
827
776
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
this.
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
this.
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
this.errorLog(`Curtain: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
844
|
-
break;
|
|
845
|
-
case 190:
|
|
846
|
-
this.errorLog(
|
|
847
|
-
`Curtain: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
848
|
-
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
849
|
-
);
|
|
850
|
-
break;
|
|
851
|
-
case 100:
|
|
852
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} Command successfully sent.`);
|
|
853
|
-
break;
|
|
854
|
-
default:
|
|
855
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} Unknown statusCode.`);
|
|
777
|
+
/*
|
|
778
|
+
* Setup MQTT hadler if URL is specifed.
|
|
779
|
+
*/
|
|
780
|
+
async setupMqtt(device: device & devicesConfig): Promise<void> {
|
|
781
|
+
if (device.mqttURL) {
|
|
782
|
+
try {
|
|
783
|
+
this.mqttClient = await connectAsync(device.mqttURL, device.mqttOptions || {});
|
|
784
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
|
|
785
|
+
this.mqttClient.on('error', (e: Error) => {
|
|
786
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
|
|
787
|
+
});
|
|
788
|
+
} catch (e) {
|
|
789
|
+
this.mqttClient = null;
|
|
790
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
|
|
791
|
+
}
|
|
856
792
|
}
|
|
857
793
|
}
|
|
858
794
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
795
|
+
async getCustomBLEAddress(switchbot: any) {
|
|
796
|
+
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
797
|
+
(async () => {
|
|
798
|
+
// Start to monitor advertisement packets
|
|
799
|
+
await switchbot.startScan({
|
|
800
|
+
model: 'c',
|
|
801
|
+
});
|
|
802
|
+
// Set an event handler
|
|
803
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
804
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
|
|
805
|
+
};
|
|
806
|
+
await switchbot.wait(10000);
|
|
807
|
+
// Stop to monitor
|
|
808
|
+
switchbot.stopScan();
|
|
809
|
+
})();
|
|
810
|
+
}
|
|
811
|
+
}
|
|
867
812
|
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
this.
|
|
872
|
-
this.
|
|
873
|
-
|
|
874
|
-
this.PositionState = this.platform.Characteristic.PositionState.DECREASING;
|
|
875
|
-
this.setNewTarget = true;
|
|
876
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} value: ${value}, CurrentPosition: ${this.CurrentPosition}`);
|
|
877
|
-
} else {
|
|
878
|
-
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
879
|
-
this.setNewTarget = false;
|
|
880
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} value: ${value}, CurrentPosition: ${this.CurrentPosition}`);
|
|
813
|
+
async BLEconnection(switchbot: any): Promise<void> {
|
|
814
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
815
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
816
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
817
|
+
this.SwitchToOpenAPI = true;
|
|
818
|
+
await this.openAPIRefreshStatus();
|
|
881
819
|
}
|
|
882
|
-
|
|
883
|
-
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.PositionState).updateValue(this.PositionState);
|
|
820
|
+
}
|
|
884
821
|
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
822
|
+
async SilentPerformance() {
|
|
823
|
+
if (this.TargetPosition > 50) {
|
|
824
|
+
if (this.device.curtain?.setOpenMode === '1') {
|
|
825
|
+
this.setPositionMode = 1;
|
|
826
|
+
this.Mode = 'Silent Mode';
|
|
827
|
+
} else {
|
|
828
|
+
this.setPositionMode = 0;
|
|
829
|
+
this.Mode = 'Performance Mode';
|
|
830
|
+
}
|
|
831
|
+
} else {
|
|
832
|
+
if (this.device.curtain?.setCloseMode === '1') {
|
|
833
|
+
this.setPositionMode = 1;
|
|
834
|
+
this.Mode = 'Silent Mode';
|
|
835
|
+
} else {
|
|
836
|
+
this.setPositionMode = 0;
|
|
837
|
+
this.Mode = 'Performance Mode';
|
|
838
|
+
}
|
|
896
839
|
}
|
|
897
|
-
this.doCurtainUpdate.next();
|
|
898
840
|
}
|
|
899
841
|
|
|
900
842
|
async setMinMax(): Promise<void> {
|
|
@@ -910,92 +852,120 @@ export class Curtain {
|
|
|
910
852
|
}
|
|
911
853
|
}
|
|
912
854
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
if (device.ble) {
|
|
919
|
-
config['ble'] = device.ble;
|
|
920
|
-
}
|
|
921
|
-
if (device.logging !== undefined) {
|
|
922
|
-
config['logging'] = device.logging;
|
|
923
|
-
}
|
|
924
|
-
if (device.refreshRate !== undefined) {
|
|
925
|
-
config['refreshRate'] = device.refreshRate;
|
|
926
|
-
}
|
|
927
|
-
if (device.scanDuration !== undefined) {
|
|
928
|
-
config['scanDuration'] = device.scanDuration;
|
|
929
|
-
}
|
|
930
|
-
if (Object.entries(config).length !== 0) {
|
|
931
|
-
this.infoLog(`Curtain: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
855
|
+
minStep(device: device & devicesConfig): number {
|
|
856
|
+
if (device.curtain?.set_minStep) {
|
|
857
|
+
this.set_minStep = device.curtain?.set_minStep;
|
|
858
|
+
} else {
|
|
859
|
+
this.set_minStep = 1;
|
|
932
860
|
}
|
|
861
|
+
return this.set_minStep;
|
|
933
862
|
}
|
|
934
863
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
this.
|
|
940
|
-
} else if (this.platform.config.options!.refreshRate) {
|
|
941
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
942
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
864
|
+
minLux(): number {
|
|
865
|
+
if (this.device.curtain?.set_minLux) {
|
|
866
|
+
this.set_minLux = this.device.curtain?.set_minLux;
|
|
867
|
+
} else {
|
|
868
|
+
this.set_minLux = 1;
|
|
943
869
|
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
870
|
+
return this.set_minLux;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
maxLux(): number {
|
|
874
|
+
if (this.device.curtain?.set_maxLux) {
|
|
875
|
+
this.set_maxLux = this.device.curtain?.set_maxLux;
|
|
948
876
|
} else {
|
|
949
|
-
this.
|
|
950
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} Using Default Curtain Refresh Rate.`);
|
|
877
|
+
this.set_maxLux = 6001;
|
|
951
878
|
}
|
|
879
|
+
return this.set_maxLux;
|
|
952
880
|
}
|
|
953
881
|
|
|
954
882
|
async scan(device: device & devicesConfig): Promise<void> {
|
|
955
883
|
if (device.scanDuration) {
|
|
956
884
|
if (this.updateRate > device.scanDuration) {
|
|
957
885
|
this.scanDuration = this.updateRate;
|
|
958
|
-
this.warnLog(
|
|
886
|
+
this.warnLog(`${this.device.deviceType}: `
|
|
887
|
+
+ `${this.accessory.displayName} scanDuration is less then updateRate, overriding scanDuration with updateRate`);
|
|
959
888
|
} else {
|
|
960
889
|
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
961
890
|
}
|
|
962
|
-
if (
|
|
963
|
-
this.debugLog(
|
|
891
|
+
if (this.BLE) {
|
|
892
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
964
893
|
}
|
|
965
894
|
} else {
|
|
966
895
|
if (this.updateRate > 1) {
|
|
967
896
|
this.scanDuration = this.updateRate;
|
|
968
|
-
this.warnLog(
|
|
897
|
+
this.warnLog(`${this.device.deviceType}: `
|
|
898
|
+
+ `${this.accessory.displayName} scanDuration is less then updateRate, overriding scanDuration with updateRate`);
|
|
969
899
|
} else {
|
|
970
900
|
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
971
901
|
}
|
|
972
|
-
if (this.
|
|
973
|
-
this.debugLog(
|
|
902
|
+
if (this.BLE) {
|
|
903
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
974
904
|
}
|
|
975
905
|
}
|
|
976
906
|
}
|
|
977
907
|
|
|
978
|
-
async
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
908
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
909
|
+
switch (res.statusCode) {
|
|
910
|
+
case 151:
|
|
911
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
912
|
+
break;
|
|
913
|
+
case 152:
|
|
914
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
|
|
915
|
+
break;
|
|
916
|
+
case 160:
|
|
917
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
|
|
918
|
+
break;
|
|
919
|
+
case 161:
|
|
920
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
|
|
921
|
+
this.offlineOff();
|
|
922
|
+
break;
|
|
923
|
+
case 171:
|
|
924
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
925
|
+
this.offlineOff();
|
|
926
|
+
break;
|
|
927
|
+
case 190:
|
|
928
|
+
this.errorLog(
|
|
929
|
+
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
930
|
+
` Or command: ${superStringify(res)} format is invalid`,
|
|
931
|
+
);
|
|
932
|
+
break;
|
|
933
|
+
case 100:
|
|
934
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
|
|
935
|
+
break;
|
|
936
|
+
default:
|
|
937
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
|
|
991
938
|
}
|
|
992
939
|
}
|
|
993
940
|
|
|
941
|
+
async offlineOff(): Promise<void> {
|
|
942
|
+
if (this.device.offline) {
|
|
943
|
+
this.CurrentPosition = 100;
|
|
944
|
+
this.windowCoveringService.getCharacteristic(this.platform.Characteristic.On).updateValue(this.CurrentPosition);
|
|
945
|
+
await this.updateHomeKitCharacteristics();
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
async apiError(e: any): Promise<void> {
|
|
950
|
+
this.windowCoveringService.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
|
|
951
|
+
this.windowCoveringService.updateCharacteristic(this.platform.Characteristic.PositionState, e);
|
|
952
|
+
this.windowCoveringService.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
|
|
953
|
+
if (!this.device.curtain?.hide_lightsensor) {
|
|
954
|
+
this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, e);
|
|
955
|
+
}
|
|
956
|
+
if (this.BLE) {
|
|
957
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
|
|
958
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
|
|
959
|
+
}
|
|
960
|
+
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
961
|
+
}
|
|
962
|
+
|
|
994
963
|
FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
|
|
995
964
|
let FirmwareRevision: string;
|
|
996
|
-
this.debugLog(
|
|
997
|
-
|
|
998
|
-
this.debugLog(
|
|
965
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
966
|
+
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
967
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
968
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
999
969
|
if (accessory.context.FirmwareRevision) {
|
|
1000
970
|
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
1001
971
|
} else if (device.firmware) {
|
|
@@ -1006,31 +976,81 @@ export class Curtain {
|
|
|
1006
976
|
return FirmwareRevision;
|
|
1007
977
|
}
|
|
1008
978
|
|
|
1009
|
-
|
|
1010
|
-
if (
|
|
1011
|
-
this.
|
|
979
|
+
async context() {
|
|
980
|
+
if (this.CurrentPosition === undefined) {
|
|
981
|
+
this.CurrentPosition = 0;
|
|
1012
982
|
} else {
|
|
1013
|
-
this.
|
|
983
|
+
this.CurrentPosition = this.accessory.context.CurrentPosition;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
if (this.TargetPosition === undefined) {
|
|
987
|
+
this.TargetPosition = 0;
|
|
988
|
+
} else {
|
|
989
|
+
this.TargetPosition = this.accessory.context.TargetPosition;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
if (this.PositionState === undefined) {
|
|
993
|
+
this.PositionState = this.platform.Characteristic.PositionState.STOPPED;
|
|
994
|
+
} else {
|
|
995
|
+
this.PositionState = this.accessory.context.PositionState;
|
|
1014
996
|
}
|
|
1015
|
-
return this.set_minStep;
|
|
1016
997
|
}
|
|
1017
998
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
999
|
+
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
1000
|
+
// refreshRate
|
|
1001
|
+
if (device.refreshRate) {
|
|
1002
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
1003
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1004
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
1005
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
1006
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1007
|
+
}
|
|
1008
|
+
// updateRate
|
|
1009
|
+
if (device?.curtain?.updateRate) {
|
|
1010
|
+
this.updateRate = device?.curtain?.updateRate;
|
|
1011
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Curtain refreshRate: ${this.deviceRefreshRate}`);
|
|
1021
1012
|
} else {
|
|
1022
|
-
this.
|
|
1013
|
+
this.updateRate = 7;
|
|
1014
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default Curtain Refresh Rate.`);
|
|
1023
1015
|
}
|
|
1024
|
-
return this.set_minLux;
|
|
1025
1016
|
}
|
|
1026
1017
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1018
|
+
async config(device: device & devicesConfig): Promise<void> {
|
|
1019
|
+
let config = {};
|
|
1020
|
+
if (device.curtain) {
|
|
1021
|
+
config = device.curtain;
|
|
1022
|
+
}
|
|
1023
|
+
if (device.connectionType !== undefined) {
|
|
1024
|
+
config['connectionType'] = device.connectionType;
|
|
1025
|
+
}
|
|
1026
|
+
if (device.logging !== undefined) {
|
|
1027
|
+
config['logging'] = device.logging;
|
|
1028
|
+
}
|
|
1029
|
+
if (device.refreshRate !== undefined) {
|
|
1030
|
+
config['refreshRate'] = device.refreshRate;
|
|
1031
|
+
}
|
|
1032
|
+
if (device.scanDuration !== undefined) {
|
|
1033
|
+
config['scanDuration'] = device.scanDuration;
|
|
1034
|
+
}
|
|
1035
|
+
if (Object.entries(config).length !== 0) {
|
|
1036
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
async logs(device: device & devicesConfig): Promise<void> {
|
|
1041
|
+
if (this.platform.debugMode) {
|
|
1042
|
+
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
1043
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
1044
|
+
} else if (device.logging) {
|
|
1045
|
+
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
1046
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
1047
|
+
} else if (this.platform.config.options?.logging) {
|
|
1048
|
+
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
1049
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
1030
1050
|
} else {
|
|
1031
|
-
this.
|
|
1051
|
+
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
1052
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
1032
1053
|
}
|
|
1033
|
-
return this.set_maxLux;
|
|
1034
1054
|
}
|
|
1035
1055
|
|
|
1036
1056
|
/**
|