@switchbot/homebridge-switchbot 2.0.0-beta.9 → 2.0.0

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