@switchbot/homebridge-switchbot 2.0.0-beta.19 → 2.0.0-beta.20

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 (112) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/README.md +1 -2
  3. package/config.schema.json +51 -32
  4. package/dist/device/bot.d.ts +32 -29
  5. package/dist/device/bot.d.ts.map +1 -1
  6. package/dist/device/bot.js +549 -575
  7. package/dist/device/bot.js.map +1 -1
  8. package/dist/device/colorbulb.d.ts +33 -15
  9. package/dist/device/colorbulb.d.ts.map +1 -1
  10. package/dist/device/colorbulb.js +426 -341
  11. package/dist/device/colorbulb.js.map +1 -1
  12. package/dist/device/contact.d.ts +16 -9
  13. package/dist/device/contact.d.ts.map +1 -1
  14. package/dist/device/contact.js +246 -208
  15. package/dist/device/contact.js.map +1 -1
  16. package/dist/device/curtain.d.ts +21 -18
  17. package/dist/device/curtain.d.ts.map +1 -1
  18. package/dist/device/curtain.js +449 -449
  19. package/dist/device/curtain.js.map +1 -1
  20. package/dist/device/humidifier.d.ts +22 -20
  21. package/dist/device/humidifier.d.ts.map +1 -1
  22. package/dist/device/humidifier.js +346 -324
  23. package/dist/device/humidifier.js.map +1 -1
  24. package/dist/device/lock.d.ts +22 -10
  25. package/dist/device/lock.d.ts.map +1 -1
  26. package/dist/device/lock.js +257 -178
  27. package/dist/device/lock.js.map +1 -1
  28. package/dist/device/meter.d.ts +21 -14
  29. package/dist/device/meter.d.ts.map +1 -1
  30. package/dist/device/meter.js +287 -239
  31. package/dist/device/meter.js.map +1 -1
  32. package/dist/device/meterplus.d.ts +23 -10
  33. package/dist/device/meterplus.d.ts.map +1 -1
  34. package/dist/device/meterplus.js +308 -190
  35. package/dist/device/meterplus.js.map +1 -1
  36. package/dist/device/motion.d.ts +17 -10
  37. package/dist/device/motion.d.ts.map +1 -1
  38. package/dist/device/motion.js +225 -193
  39. package/dist/device/motion.js.map +1 -1
  40. package/dist/device/plug.d.ts +24 -17
  41. package/dist/device/plug.d.ts.map +1 -1
  42. package/dist/device/plug.js +270 -267
  43. package/dist/device/plug.js.map +1 -1
  44. package/dist/device/striplight.d.ts +36 -14
  45. package/dist/device/striplight.d.ts.map +1 -1
  46. package/dist/device/striplight.js +447 -299
  47. package/dist/device/striplight.js.map +1 -1
  48. package/dist/irdevice/airconditioner.d.ts +7 -14
  49. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  50. package/dist/irdevice/airconditioner.js +177 -169
  51. package/dist/irdevice/airconditioner.js.map +1 -1
  52. package/dist/irdevice/airpurifier.d.ts +3 -5
  53. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  54. package/dist/irdevice/airpurifier.js +72 -57
  55. package/dist/irdevice/airpurifier.js.map +1 -1
  56. package/dist/irdevice/camera.d.ts +3 -4
  57. package/dist/irdevice/camera.d.ts.map +1 -1
  58. package/dist/irdevice/camera.js +47 -33
  59. package/dist/irdevice/camera.js.map +1 -1
  60. package/dist/irdevice/fan.d.ts +3 -4
  61. package/dist/irdevice/fan.d.ts.map +1 -1
  62. package/dist/irdevice/fan.js +66 -48
  63. package/dist/irdevice/fan.js.map +1 -1
  64. package/dist/irdevice/light.d.ts +3 -4
  65. package/dist/irdevice/light.d.ts.map +1 -1
  66. package/dist/irdevice/light.js +48 -47
  67. package/dist/irdevice/light.js.map +1 -1
  68. package/dist/irdevice/other.d.ts +3 -4
  69. package/dist/irdevice/other.d.ts.map +1 -1
  70. package/dist/irdevice/other.js +47 -33
  71. package/dist/irdevice/other.js.map +1 -1
  72. package/dist/irdevice/tv.d.ts +10 -11
  73. package/dist/irdevice/tv.d.ts.map +1 -1
  74. package/dist/irdevice/tv.js +64 -48
  75. package/dist/irdevice/tv.js.map +1 -1
  76. package/dist/irdevice/vacuumcleaner.d.ts +7 -12
  77. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  78. package/dist/irdevice/vacuumcleaner.js +52 -41
  79. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  80. package/dist/irdevice/waterheater.d.ts +6 -11
  81. package/dist/irdevice/waterheater.d.ts.map +1 -1
  82. package/dist/irdevice/waterheater.js +52 -42
  83. package/dist/irdevice/waterheater.js.map +1 -1
  84. package/dist/platform.d.ts +0 -4
  85. package/dist/platform.d.ts.map +1 -1
  86. package/dist/platform.js +44 -66
  87. package/dist/platform.js.map +1 -1
  88. package/dist/settings.d.ts +3 -3
  89. package/dist/settings.d.ts.map +1 -1
  90. package/package.json +7 -6
  91. package/src/device/bot.ts +551 -589
  92. package/src/device/colorbulb.ts +441 -375
  93. package/src/device/contact.ts +249 -213
  94. package/src/device/curtain.ts +452 -461
  95. package/src/device/humidifier.ts +358 -365
  96. package/src/device/lock.ts +263 -179
  97. package/src/device/meter.ts +302 -253
  98. package/src/device/meterplus.ts +319 -194
  99. package/src/device/motion.ts +230 -199
  100. package/src/device/plug.ts +273 -274
  101. package/src/device/striplight.ts +460 -316
  102. package/src/irdevice/airconditioner.ts +181 -183
  103. package/src/irdevice/airpurifier.ts +70 -60
  104. package/src/irdevice/camera.ts +46 -36
  105. package/src/irdevice/fan.ts +64 -49
  106. package/src/irdevice/light.ts +47 -51
  107. package/src/irdevice/other.ts +46 -36
  108. package/src/irdevice/tv.ts +64 -51
  109. package/src/irdevice/vacuumcleaner.ts +52 -45
  110. package/src/irdevice/waterheater.ts +50 -45
  111. package/src/platform.ts +44 -68
  112. package/src/settings.ts +3 -3
@@ -24,26 +24,17 @@ class Meter {
24
24
  this.device = device;
25
25
  //MQTT stuff
26
26
  this.mqttClient = null;
27
+ // Connection
28
+ this.BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'Both');
29
+ this.OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'Both');
27
30
  // default placeholders
28
31
  this.logs(device);
29
- this.openAPI();
30
32
  this.scan(device);
31
- this.setupHistoryService(device);
32
33
  this.refreshRate(device);
33
34
  this.config(device);
35
+ this.context();
36
+ this.setupHistoryService(device);
34
37
  this.setupMqtt(device);
35
- if (this.CurrentRelativeHumidity === undefined) {
36
- this.CurrentRelativeHumidity = 0;
37
- }
38
- else {
39
- this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
40
- }
41
- if (this.CurrentTemperature === undefined) {
42
- this.CurrentTemperature = 0;
43
- }
44
- else {
45
- this.CurrentTemperature = this.accessory.context.CurrentTemperature;
46
- }
47
38
  // this is subject we use to track when we need to POST changes to the SwitchBot API
48
39
  this.doMeterUpdate = new rxjs_1.Subject();
49
40
  this.meterUpdateInProgress = false;
@@ -111,12 +102,12 @@ class Meter {
111
102
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Humidity Sensor Service Not Added`);
112
103
  }
113
104
  // Battery Service
114
- if (!device.ble) {
105
+ if (!this.BLE) {
115
106
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Battery Service`);
116
107
  this.batteryService = this.accessory.getService(this.platform.Service.Battery);
117
108
  accessory.removeService(this.batteryService);
118
109
  }
119
- else if (device.ble && !this.batteryService) {
110
+ else if (this.BLE && !this.batteryService) {
120
111
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Battery Service`);
121
112
  (this.batteryService = this.accessory.getService(this.platform.Service.Battery) || this.accessory.addService(this.platform.Service.Battery)),
122
113
  `${accessory.displayName} Battery`;
@@ -135,66 +126,24 @@ class Meter {
135
126
  await this.refreshStatus();
136
127
  });
137
128
  }
138
- /*
139
- * Publish MQTT message for topics of
140
- * 'homebridge-switchbot/meter/xx:xx:xx:xx:xx:xx'
141
- */
142
- mqttPublish(message) {
143
- const mac = this.device.deviceId
144
- ?.toLowerCase()
145
- .match(/[\s\S]{1,2}/g)
146
- ?.join(':');
147
- const options = this.device.mqttPubOptions || {};
148
- this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
149
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${(0, super_stringify_1.default)(options)}`);
150
- }
151
- /*
152
- * Setup MQTT hadler if URL is specifed.
153
- */
154
- async setupMqtt(device) {
155
- if (device.mqttURL) {
156
- try {
157
- this.mqttClient = await (0, async_mqtt_1.connectAsync)(device.mqttURL, device.mqttOptions || {});
158
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
159
- this.mqttClient.on('error', (e) => {
160
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
161
- });
162
- }
163
- catch (e) {
164
- this.mqttClient = null;
165
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
166
- }
167
- }
168
- }
169
- /*
170
- * Setup EVE history graph feature if enabled.
171
- */
172
- async setupHistoryService(device) {
173
- const mac = this.device
174
- .deviceId.match(/.{1,2}/g)
175
- .join(':')
176
- .toLowerCase();
177
- this.historyService = device.history
178
- ? new this.platform.fakegatoAPI('room', this.accessory, {
179
- log: this.platform.log,
180
- storage: 'fs',
181
- filename: `${(0, os_1.hostname)().split('.')[0]}_${mac}_persist.json`,
182
- })
183
- : null;
184
- }
185
129
  /**
186
130
  * Parse the device status from the SwitchBot api
187
131
  */
188
132
  async parseStatus() {
189
- if (this.SwitchToOpenAPI || !this.device.ble) {
133
+ if (this.BLE && !this.SwitchToOpenAPI) {
134
+ await this.BLEparseStatus();
135
+ }
136
+ else if (this.OpenAPI && this.platform.config.credentials?.token) {
137
+ this.SwitchToOpenAPI = false;
190
138
  await this.openAPIparseStatus();
191
139
  }
192
140
  else {
193
- await this.BLEparseStatus();
141
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
142
+ + ` ${this.device.connectionType}, parseStatus will not happen.`);
194
143
  }
195
144
  }
196
145
  async BLEparseStatus() {
197
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE parseStatus`);
146
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
198
147
  // Battery
199
148
  this.BatteryLevel = Number(this.battery);
200
149
  if (this.BatteryLevel < 15) {
@@ -203,8 +152,7 @@ class Meter {
203
152
  else {
204
153
  this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
205
154
  }
206
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
207
- + ` StatusLowBattery: ${this.StatusLowBattery}`);
155
+ this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
208
156
  // Humidity
209
157
  if (!this.device.meter?.hide_humidity) {
210
158
  this.CurrentRelativeHumidity = this.humidity;
@@ -218,36 +166,35 @@ class Meter {
218
166
  }
219
167
  }
220
168
  async openAPIparseStatus() {
221
- if (this.device.ble) {
222
- this.SwitchToOpenAPI = false;
169
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
170
+ // Current Relative Humidity
171
+ if (!this.device.meter?.hide_humidity) {
172
+ this.CurrentRelativeHumidity = this.Humidity;
173
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
223
174
  }
224
- if (this.platform.config.credentials?.token) {
225
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI parseStatus`);
226
- // Current Relative Humidity
227
- if (!this.device.meter?.hide_humidity) {
228
- this.CurrentRelativeHumidity = this.Humidity;
229
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
230
- }
231
- // Current Temperature
232
- if (!this.device.meter?.hide_temperature) {
233
- this.CurrentTemperature = this.Temperature;
234
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
235
- }
175
+ // Current Temperature
176
+ if (!this.device.meter?.hide_temperature) {
177
+ this.CurrentTemperature = this.Temperature;
178
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
236
179
  }
237
180
  }
238
181
  /**
239
182
  * Asks the SwitchBot API for the latest device information
240
183
  */
241
184
  async refreshStatus() {
242
- if (this.device.ble) {
243
- this.BLErefreshStatus();
185
+ if (this.BLE) {
186
+ await this.BLERefreshStatus();
187
+ }
188
+ else if (this.OpenAPI && this.platform.config.credentials?.token) {
189
+ await this.openAPIRefreshStatus();
244
190
  }
245
191
  else {
246
- this.openAPIRefreshStatus();
192
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
193
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
247
194
  }
248
195
  }
249
- async BLErefreshStatus() {
250
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE RefreshStatus`);
196
+ async BLERefreshStatus() {
197
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
251
198
  const switchbot = await this.platform.connectBLE();
252
199
  // Convert to BLE Address
253
200
  this.device.bleMac = this.device
@@ -275,11 +222,11 @@ class Meter {
275
222
  }
276
223
  if (ad.serviceData.humidity > 0) {
277
224
  // reject unreliable data
278
- this.serviceData = ad.serviceData;
279
- this.temperature = ad.serviceData.temperature.c;
280
225
  this.humidity = ad.serviceData.humidity;
281
- this.battery = ad.serviceData.battery;
282
226
  }
227
+ this.serviceData = ad.serviceData;
228
+ this.temperature = ad.serviceData.temperature.c;
229
+ this.battery = ad.serviceData.battery;
283
230
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${(0, super_stringify_1.default)(ad.serviceData)}`);
284
231
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
285
232
  `temperature: ${(0, super_stringify_1.default)(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
@@ -308,108 +255,68 @@ class Meter {
308
255
  }
309
256
  })
310
257
  .catch(async (e) => {
311
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
312
- if (this.deviceLogging.includes('debug')) {
313
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
314
- + ` Error Message: ${(0, super_stringify_1.default)(e.message)}`);
315
- }
316
- if (this.platform.config.credentials?.token) {
317
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
318
- this.SwitchToOpenAPI = true;
319
- this.openAPIRefreshStatus();
320
- }
321
258
  this.apiError(e);
259
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
260
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
261
+ await this.BLEconnection(switchbot);
322
262
  });
323
263
  }
324
264
  else {
325
265
  await this.BLEconnection(switchbot);
326
266
  }
327
267
  }
328
- async getCustomBLEAddress(switchbot) {
329
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
330
- (async () => {
331
- // Start to monitor advertisement packets
332
- await switchbot.startScan({
333
- model: 'T',
334
- });
335
- // Set an event handler
336
- switchbot.onadvertisement = (ad) => {
337
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${(0, super_stringify_1.default)(ad, null, ' ')}`);
338
- };
339
- await switchbot.wait(10000);
340
- // Stop to monitor
341
- switchbot.stopScan();
342
- })();
343
- }
344
- }
345
- async BLEconnection(switchbot) {
346
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
347
- if (this.platform.config.credentials?.token) {
348
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
349
- this.SwitchToOpenAPI = true;
350
- await this.openAPIRefreshStatus();
351
- }
352
- }
353
268
  async openAPIRefreshStatus() {
354
- if (this.platform.config.credentials?.token && this.OpenAPI) {
355
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI RefreshStatus`);
356
- try {
357
- const t = Date.now();
358
- const nonce = 'requestID';
359
- const data = this.platform.config.credentials?.token + t + nonce;
360
- const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
361
- const sign = signTerm.toString('base64');
362
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
363
- const options = {
364
- hostname: settings_1.HostDomain,
365
- port: 443,
366
- path: `${settings_1.DevicePath}/${this.device.deviceId}/status`,
367
- method: 'GET',
368
- headers: {
369
- Authorization: this.platform.config.credentials?.token,
370
- sign: sign,
371
- nonce: nonce,
372
- t: t,
373
- 'Content-Type': 'application/json',
374
- },
375
- };
376
- const req = https_1.default.request(options, (res) => {
377
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
378
- let rawData = '';
379
- res.on('data', (d) => {
380
- rawData += d;
381
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
382
- });
383
- res.on('end', () => {
384
- try {
385
- this.deviceStatus = JSON.parse(rawData);
386
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${(0, super_stringify_1.default)(this.deviceStatus)}`);
387
- this.Humidity = this.deviceStatus.body.humidity;
388
- this.Temperature = this.deviceStatus.body.temperature;
389
- this.parseStatus();
390
- this.updateHomeKitCharacteristics();
391
- }
392
- catch (e) {
393
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
394
- }
395
- });
269
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
270
+ try {
271
+ const t = Date.now();
272
+ const nonce = 'requestID';
273
+ const data = this.platform.config.credentials?.token + t + nonce;
274
+ const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
275
+ const sign = signTerm.toString('base64');
276
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
277
+ const options = {
278
+ hostname: settings_1.HostDomain,
279
+ port: 443,
280
+ path: `${settings_1.DevicePath}/${this.device.deviceId}/status`,
281
+ method: 'GET',
282
+ headers: {
283
+ Authorization: this.platform.config.credentials?.token,
284
+ sign: sign,
285
+ nonce: nonce,
286
+ t: t,
287
+ 'Content-Type': 'application/json',
288
+ },
289
+ };
290
+ const req = https_1.default.request(options, (res) => {
291
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
292
+ let rawData = '';
293
+ res.on('data', (d) => {
294
+ rawData += d;
295
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
396
296
  });
397
- req.on('error', (e) => {
398
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
297
+ res.on('end', () => {
298
+ try {
299
+ this.deviceStatus = JSON.parse(rawData);
300
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${(0, super_stringify_1.default)(this.deviceStatus)}`);
301
+ this.Humidity = this.deviceStatus.body.humidity;
302
+ this.Temperature = this.deviceStatus.body.temperature;
303
+ this.parseStatus();
304
+ this.updateHomeKitCharacteristics();
305
+ }
306
+ catch (e) {
307
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
308
+ }
399
309
  });
400
- req.end();
401
- }
402
- catch (e) {
403
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
404
- if (this.deviceLogging.includes('debug')) {
405
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
406
- + ` Error Message: ${(0, super_stringify_1.default)(e.message)}`);
407
- }
408
- this.apiError(e);
409
- }
310
+ });
311
+ req.on('error', (e) => {
312
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
313
+ });
314
+ req.end();
410
315
  }
411
- else {
412
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI is disabled, commands will not be sent.`);
316
+ catch (e) {
317
+ this.apiError(e);
318
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
319
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
413
320
  }
414
321
  }
415
322
  /**
@@ -423,6 +330,7 @@ class Meter {
423
330
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
424
331
  }
425
332
  else {
333
+ this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidity;
426
334
  this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
427
335
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
428
336
  + ` CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
@@ -435,28 +343,31 @@ class Meter {
435
343
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
436
344
  }
437
345
  else {
438
- this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature);
439
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
440
346
  mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
441
347
  entry['temp'] = this.CurrentTemperature;
348
+ this.accessory.context.CurrentTemperature = this.CurrentTemperature;
349
+ this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature);
350
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
442
351
  }
443
352
  }
444
- if (this.device.ble) {
353
+ if (this.BLE) {
445
354
  if (this.BatteryLevel === undefined) {
446
355
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
447
356
  }
448
357
  else {
358
+ mqttmessage.push(`"battery": ${this.BatteryLevel}`);
359
+ this.accessory.context.BatteryLevel = this.BatteryLevel;
449
360
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
450
361
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
451
- mqttmessage.push(`"battery": ${this.BatteryLevel}`);
452
362
  }
453
363
  if (this.StatusLowBattery === undefined) {
454
364
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
455
365
  }
456
366
  else {
367
+ mqttmessage.push(`"lowBattery": ${this.StatusLowBattery}`);
368
+ this.accessory.context.StatusLowBattery = this.StatusLowBattery;
457
369
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
458
370
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
459
- mqttmessage.push(`"lowBattery": ${this.StatusLowBattery}`);
460
371
  }
461
372
  }
462
373
  this.mqttPublish(`{${mqttmessage.join(',')}}`);
@@ -465,6 +376,141 @@ class Meter {
465
376
  this.historyService?.addEntry(entry);
466
377
  }
467
378
  }
379
+ /*
380
+ * Publish MQTT message for topics of
381
+ * 'homebridge-switchbot/meter/xx:xx:xx:xx:xx:xx'
382
+ */
383
+ mqttPublish(message) {
384
+ const mac = this.device.deviceId
385
+ ?.toLowerCase()
386
+ .match(/[\s\S]{1,2}/g)
387
+ ?.join(':');
388
+ const options = this.device.mqttPubOptions || {};
389
+ this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
390
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${(0, super_stringify_1.default)(options)}`);
391
+ }
392
+ /*
393
+ * Setup MQTT hadler if URL is specifed.
394
+ */
395
+ async setupMqtt(device) {
396
+ if (device.mqttURL) {
397
+ try {
398
+ this.mqttClient = await (0, async_mqtt_1.connectAsync)(device.mqttURL, device.mqttOptions || {});
399
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
400
+ this.mqttClient.on('error', (e) => {
401
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
402
+ });
403
+ }
404
+ catch (e) {
405
+ this.mqttClient = null;
406
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
407
+ }
408
+ }
409
+ }
410
+ /*
411
+ * Setup EVE history graph feature if enabled.
412
+ */
413
+ async setupHistoryService(device) {
414
+ const mac = this.device
415
+ .deviceId.match(/.{1,2}/g)
416
+ .join(':')
417
+ .toLowerCase();
418
+ this.historyService = device.history
419
+ ? new this.platform.fakegatoAPI('room', this.accessory, {
420
+ log: this.platform.log,
421
+ storage: 'fs',
422
+ filename: `${(0, os_1.hostname)().split('.')[0]}_${mac}_persist.json`,
423
+ })
424
+ : null;
425
+ }
426
+ async getCustomBLEAddress(switchbot) {
427
+ if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
428
+ (async () => {
429
+ // Start to monitor advertisement packets
430
+ await switchbot.startScan({
431
+ model: 'T',
432
+ });
433
+ // Set an event handler
434
+ switchbot.onadvertisement = (ad) => {
435
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${(0, super_stringify_1.default)(ad, null, ' ')}`);
436
+ };
437
+ await switchbot.wait(10000);
438
+ // Stop to monitor
439
+ switchbot.stopScan();
440
+ })();
441
+ }
442
+ }
443
+ async BLEconnection(switchbot) {
444
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
445
+ if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
446
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
447
+ this.SwitchToOpenAPI = true;
448
+ await this.openAPIRefreshStatus();
449
+ }
450
+ }
451
+ async scan(device) {
452
+ if (device.scanDuration) {
453
+ this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
454
+ if (this.BLE) {
455
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
456
+ }
457
+ }
458
+ else {
459
+ this.scanDuration = this.accessory.context.scanDuration = 1;
460
+ if (this.BLE) {
461
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
462
+ }
463
+ }
464
+ }
465
+ async statusCode({ res }) {
466
+ switch (res.statusCode) {
467
+ case 151:
468
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
469
+ break;
470
+ case 152:
471
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
472
+ break;
473
+ case 160:
474
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
475
+ break;
476
+ case 161:
477
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
478
+ this.offlineOff();
479
+ break;
480
+ case 171:
481
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
482
+ this.offlineOff();
483
+ break;
484
+ case 190:
485
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
486
+ ` Or command: ${(0, super_stringify_1.default)(res)} format is invalid`);
487
+ break;
488
+ case 100:
489
+ if (this.platform.debugMode) {
490
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
491
+ }
492
+ break;
493
+ default:
494
+ if (this.platform.debugMode) {
495
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
496
+ }
497
+ }
498
+ }
499
+ async offlineOff() {
500
+ if (this.device.offline) {
501
+ if (!this.device.meter?.hide_humidity) {
502
+ this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.accessory.context.CurrentRelativeHumidity);
503
+ }
504
+ if (!this.device.meter?.hide_temperature) {
505
+ this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.accessory.context.CurrentTemperature);
506
+ }
507
+ if (this.BLE) {
508
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.accessory.context.BatteryLevel);
509
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.accessory.context.StatusLowBattery);
510
+ }
511
+ await this.updateHomeKitCharacteristics();
512
+ }
513
+ }
468
514
  async apiError(e) {
469
515
  if (!this.device.meter?.hide_humidity) {
470
516
  this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
@@ -472,34 +518,55 @@ class Meter {
472
518
  if (!this.device.meter?.hide_temperature) {
473
519
  this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
474
520
  }
475
- if (this.device.ble) {
521
+ if (this.BLE) {
476
522
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
477
523
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
478
524
  }
479
- //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
480
525
  }
481
- async config(device) {
482
- let config = {};
483
- if (device.meter) {
484
- config = device.meter;
526
+ FirmwareRevision(accessory, device) {
527
+ let FirmwareRevision;
528
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
529
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
530
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
531
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
532
+ if (accessory.context.FirmwareRevision) {
533
+ FirmwareRevision = accessory.context.FirmwareRevision;
485
534
  }
486
- if (device.ble !== undefined) {
487
- config['ble'] = device.ble;
535
+ else if (device.firmware) {
536
+ FirmwareRevision = device.firmware;
488
537
  }
489
- if (device.openAPI !== undefined) {
490
- config['openAPI'] = device.openAPI;
538
+ else {
539
+ FirmwareRevision = this.platform.version;
491
540
  }
492
- if (device.logging !== undefined) {
493
- config['logging'] = device.logging;
541
+ return FirmwareRevision;
542
+ }
543
+ async context() {
544
+ if (this.CurrentRelativeHumidity === undefined) {
545
+ this.CurrentRelativeHumidity = 0;
494
546
  }
495
- if (device.refreshRate !== undefined) {
496
- config['refreshRate'] = device.refreshRate;
547
+ else {
548
+ this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
497
549
  }
498
- if (device.scanDuration !== undefined) {
499
- config['scanDuration'] = device.scanDuration;
550
+ if (this.CurrentTemperature === undefined) {
551
+ this.CurrentTemperature = 0;
500
552
  }
501
- if (Object.entries(config).length !== 0) {
502
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${(0, super_stringify_1.default)(config)}`);
553
+ else {
554
+ this.CurrentTemperature = this.accessory.context.CurrentTemperature;
555
+ }
556
+ if (this.BLE) {
557
+ if (this.BatteryLevel === undefined) {
558
+ this.BatteryLevel = 100;
559
+ }
560
+ else {
561
+ this.BatteryLevel = this.accessory.context.BatteryLevel;
562
+ }
563
+ if (this.StatusLowBattery === undefined) {
564
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
565
+ this.accessory.context.StatusLowBattery = this.StatusLowBattery;
566
+ }
567
+ else {
568
+ this.StatusLowBattery = this.accessory.context.StatusLowBattery;
569
+ }
503
570
  }
504
571
  }
505
572
  async refreshRate(device) {
@@ -512,27 +579,25 @@ class Meter {
512
579
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
513
580
  }
514
581
  }
515
- async openAPI() {
516
- if (!this.device.openAPI) {
517
- this.OpenAPI = true;
582
+ async config(device) {
583
+ let config = {};
584
+ if (device.meter) {
585
+ config = device.meter;
518
586
  }
519
- else {
520
- this.OpenAPI = this.device.openAPI;
587
+ if (device.connectionType !== undefined) {
588
+ config['connectionType'] = device.connectionType;
521
589
  }
522
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI: ${this.OpenAPI}`);
523
- }
524
- async scan(device) {
525
- if (device.scanDuration) {
526
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
527
- if (device.ble) {
528
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
529
- }
590
+ if (device.logging !== undefined) {
591
+ config['logging'] = device.logging;
530
592
  }
531
- else {
532
- this.scanDuration = this.accessory.context.scanDuration = 1;
533
- if (this.device.ble) {
534
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
535
- }
593
+ if (device.refreshRate !== undefined) {
594
+ config['refreshRate'] = device.refreshRate;
595
+ }
596
+ if (device.scanDuration !== undefined) {
597
+ config['scanDuration'] = device.scanDuration;
598
+ }
599
+ if (Object.entries(config).length !== 0) {
600
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${(0, super_stringify_1.default)(config)}`);
536
601
  }
537
602
  }
538
603
  async logs(device) {
@@ -553,23 +618,6 @@ class Meter {
553
618
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
554
619
  }
555
620
  }
556
- FirmwareRevision(accessory, device) {
557
- let FirmwareRevision;
558
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
559
- + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
560
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
561
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
562
- if (accessory.context.FirmwareRevision) {
563
- FirmwareRevision = accessory.context.FirmwareRevision;
564
- }
565
- else if (device.firmware) {
566
- FirmwareRevision = device.firmware;
567
- }
568
- else {
569
- FirmwareRevision = this.platform.version;
570
- }
571
- return FirmwareRevision;
572
- }
573
621
  /**
574
622
  * Logging for Device
575
623
  */