@switchbot/homebridge-switchbot 2.0.0-beta.2 → 2.0.0-beta.21

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