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