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