@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
@@ -1,11 +1,16 @@
1
1
  import https from 'https';
2
2
  import crypto from 'crypto';
3
3
  import { Context } from 'vm';
4
+ import { hostname } from 'os';
5
+ import { MqttClient } from 'mqtt';
6
+ import { connectAsync } from 'async-mqtt';
4
7
  import { interval, Subject } from 'rxjs';
5
8
  import { skipWhile } from 'rxjs/operators';
9
+ import superStringify from 'super-stringify';
6
10
  import { SwitchBotPlatform } from '../platform';
7
11
  import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
8
12
  import { device, devicesConfig, serviceData, ad, switchbot, temperature, deviceStatus, HostDomain, DevicePath } from '../settings';
13
+ import { IncomingMessage } from 'http';
9
14
 
10
15
  /**
11
16
  * Platform Accessory
@@ -20,14 +25,10 @@ export class MeterPlus {
20
25
 
21
26
  // Characteristic Values
22
27
  CurrentRelativeHumidity!: CharacteristicValue;
23
- CurrentRelativeHumidityCached!: CharacteristicValue;
24
28
  CurrentTemperature?: CharacteristicValue;
25
- CurrentTemperatureCached?: CharacteristicValue;
26
29
  BatteryLevel?: CharacteristicValue;
27
30
  ChargingState?: CharacteristicValue;
28
31
  StatusLowBattery?: CharacteristicValue;
29
- Active!: CharacteristicValue;
30
- WaterLevel!: CharacteristicValue;
31
32
 
32
33
  // OpenAPI Others
33
34
  Temperature: deviceStatus['temperature'];
@@ -37,13 +38,18 @@ export class MeterPlus {
37
38
  // BLE Others
38
39
  connected?: boolean;
39
40
  switchbot!: switchbot;
40
- SwitchToOpenAPI?: boolean;
41
41
  serviceData!: serviceData;
42
42
  address!: ad['address'];
43
43
  temperature!: temperature['c'];
44
44
  battery!: serviceData['battery'];
45
45
  humidity!: serviceData['humidity'];
46
46
 
47
+ //MQTT stuff
48
+ mqttClient: MqttClient | null = null;
49
+
50
+ // EVE history service handler
51
+ historyService?: any;
52
+
47
53
  // Config
48
54
  scanDuration!: number;
49
55
  deviceLogging!: string;
@@ -53,22 +59,19 @@ export class MeterPlus {
53
59
  meterUpdateInProgress!: boolean;
54
60
  doMeterUpdate: Subject<void>;
55
61
 
62
+ // Connection
63
+ private readonly BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI');
64
+ private readonly OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI');
65
+
56
66
  constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
57
67
  // default placeholders
58
68
  this.logs(device);
59
69
  this.scan(device);
60
70
  this.refreshRate(device);
61
71
  this.config(device);
62
- if (this.CurrentRelativeHumidity === undefined) {
63
- this.CurrentRelativeHumidity = 0;
64
- } else {
65
- this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
66
- }
67
- if (this.CurrentTemperature === undefined) {
68
- this.CurrentTemperature = 0;
69
- } else {
70
- this.CurrentTemperature = this.accessory.context.CurrentTemperature;
71
- }
72
+ this.context();
73
+ this.setupHistoryService(device);
74
+ this.setupMqtt(device);
72
75
 
73
76
  // this is subject we use to track when we need to POST changes to the SwitchBot API
74
77
  this.doMeterUpdate = new Subject();
@@ -89,11 +92,11 @@ export class MeterPlus {
89
92
 
90
93
  // Temperature Sensor Service
91
94
  if (device.meter?.hide_temperature) {
92
- this.debugLog(`Meter Plus: ${accessory.displayName} Removing Temperature Sensor Service`);
95
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Temperature Sensor Service`);
93
96
  this.temperatureservice = this.accessory.getService(this.platform.Service.TemperatureSensor);
94
97
  accessory.removeService(this.temperatureservice!);
95
98
  } else if (!this.temperatureservice) {
96
- this.debugLog(`Meter Plus: ${accessory.displayName} Add Temperature Sensor Service`);
99
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Temperature Sensor Service`);
97
100
  (this.temperatureservice =
98
101
  this.accessory.getService(this.platform.Service.TemperatureSensor) || this.accessory.addService(this.platform.Service.TemperatureSensor)),
99
102
  `${accessory.displayName} Temperature Sensor`;
@@ -113,16 +116,16 @@ export class MeterPlus {
113
116
  return this.CurrentTemperature!;
114
117
  });
115
118
  } else {
116
- this.debugLog(`Meter Plus: ${accessory.displayName} Temperature Sensor Service Not Added`);
119
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Temperature Sensor Service Not Added`);
117
120
  }
118
121
 
119
122
  // Humidity Sensor Service
120
123
  if (device.meter?.hide_humidity) {
121
- this.debugLog(`Meter Plus: ${accessory.displayName} Removing Humidity Sensor Service`);
124
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Humidity Sensor Service`);
122
125
  this.humidityservice = this.accessory.getService(this.platform.Service.HumiditySensor);
123
126
  accessory.removeService(this.humidityservice!);
124
127
  } else if (!this.humidityservice) {
125
- this.debugLog(`Meter Plus: ${accessory.displayName} Add Humidity Sensor Service`);
128
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Humidity Sensor Service`);
126
129
  (this.humidityservice =
127
130
  this.accessory.getService(this.platform.Service.HumiditySensor) || this.accessory.addService(this.platform.Service.HumiditySensor)),
128
131
  `${accessory.displayName} Humidity Sensor`;
@@ -138,16 +141,16 @@ export class MeterPlus {
138
141
  return this.CurrentRelativeHumidity;
139
142
  });
140
143
  } else {
141
- this.debugLog(`Meter Plus: ${accessory.displayName} Humidity Sensor Service Not Added`);
144
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Humidity Sensor Service Not Added`);
142
145
  }
143
146
 
144
147
  // Battery Service
145
- if (!device.ble) {
146
- this.debugLog(`Meter Plus: ${accessory.displayName} Removing Battery Service`);
148
+ if (!this.BLE) {
149
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Battery Service`);
147
150
  this.batteryService = this.accessory.getService(this.platform.Service.Battery);
148
151
  accessory.removeService(this.batteryService!);
149
- } else if (device.ble && !this.batteryService) {
150
- this.debugLog(`Meter Plus: ${accessory.displayName} Add Battery Service`);
152
+ } else if (this.BLE && !this.batteryService) {
153
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Battery Service`);
151
154
  (this.batteryService = this.accessory.getService(this.platform.Service.Battery) || this.accessory.addService(this.platform.Service.Battery)),
152
155
  `${accessory.displayName} Battery`;
153
156
 
@@ -155,7 +158,7 @@ export class MeterPlus {
155
158
 
156
159
  this.batteryService.setCharacteristic(this.platform.Characteristic.ChargingState, this.platform.Characteristic.ChargingState.NOT_CHARGEABLE);
157
160
  } else {
158
- this.debugLog(`Meter Plus: ${accessory.displayName} Battery Service Not Added`);
161
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Battery Service Not Added`);
159
162
  }
160
163
 
161
164
  // Retrieve initial values and updateHomekit
@@ -173,15 +176,18 @@ export class MeterPlus {
173
176
  * Parse the device status from the SwitchBot api
174
177
  */
175
178
  async parseStatus(): Promise<void> {
176
- if (this.SwitchToOpenAPI || !this.device.ble) {
179
+ if (this.BLE) {
180
+ await this.BLEparseStatus();
181
+ } else if (this.OpenAPI && this.platform.config.credentials?.token) {
177
182
  await this.openAPIparseStatus();
178
183
  } else {
179
- await this.BLEparseStatus();
184
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
185
+ + ` ${this.device.connectionType}, parseStatus will not happen.`);
180
186
  }
181
187
  }
182
188
 
183
189
  async BLEparseStatus(): Promise<void> {
184
- this.debugLog(`Meter Plus: ${this.accessory.displayName} BLE parseStatus`);
190
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
185
191
 
186
192
  // Battery
187
193
  this.BatteryLevel = Number(this.battery);
@@ -195,34 +201,29 @@ export class MeterPlus {
195
201
  // Humidity
196
202
  if (!this.device.meter?.hide_humidity) {
197
203
  this.CurrentRelativeHumidity = this.humidity!;
198
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
204
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
199
205
  }
200
206
 
201
207
  // Current Temperature
202
208
  if (!this.device.meter?.hide_temperature) {
203
209
  this.temperature < 0 ? 0 : this.temperature > 100 ? 100 : this.temperature;
204
210
  this.CurrentTemperature = this.temperature;
205
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
211
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
206
212
  }
207
213
  }
208
214
 
209
215
  async openAPIparseStatus(): Promise<void> {
210
- if (this.device.ble) {
211
- this.SwitchToOpenAPI = false;
216
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
217
+ // Current Relative Humidity
218
+ if (!this.device.meter?.hide_humidity) {
219
+ this.CurrentRelativeHumidity = this.Humidity!;
220
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
212
221
  }
213
- if (this.platform.config.credentials?.token) {
214
- this.debugLog(`Meter Plus: ${this.accessory.displayName} OpenAPI parseStatus`);
215
- // Current Relative Humidity
216
- if (!this.device.meter?.hide_humidity) {
217
- this.CurrentRelativeHumidity = this.Humidity!;
218
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
219
- }
220
222
 
221
- // Current Temperature
222
- if (!this.device.meter?.hide_temperature) {
223
- this.CurrentTemperature = this.Temperature!;
224
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
225
- }
223
+ // Current Temperature
224
+ if (!this.device.meter?.hide_temperature) {
225
+ this.CurrentTemperature = this.Temperature!;
226
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
226
227
  }
227
228
  }
228
229
 
@@ -230,22 +231,25 @@ export class MeterPlus {
230
231
  * Asks the SwitchBot API for the latest device information
231
232
  */
232
233
  async refreshStatus(): Promise<void> {
233
- if (this.device.ble) {
234
- this.BLErefreshStatus();
234
+ if (this.BLE) {
235
+ await this.BLERefreshStatus();
236
+ } else if (this.OpenAPI && this.platform.config.credentials?.token) {
237
+ await this.openAPIRefreshStatus();
235
238
  } else {
236
- this.openAPIRefreshStatus();
239
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
240
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
237
241
  }
238
242
  }
239
243
 
240
- async BLErefreshStatus(): Promise<void> {
241
- this.debugLog(`Meter Plus: ${this.accessory.displayName} BLE RefreshStatus`);
244
+ async BLERefreshStatus(): Promise<void> {
245
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
242
246
  const switchbot = await this.platform.connectBLE();
243
247
  // Convert to BLE Address
244
248
  this.device.bleMac = this.device
245
249
  .deviceId!.match(/.{1,2}/g)!
246
250
  .join(':')
247
251
  .toLowerCase();
248
- this.debugLog(`Meter Plus: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
252
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
249
253
  this.getCustomBLEAddress(switchbot);
250
254
  // Start to monitor advertisement packets
251
255
  if (switchbot !== false) {
@@ -258,29 +262,28 @@ export class MeterPlus {
258
262
  // Set an event hander
259
263
  switchbot.onadvertisement = (ad: ad) => {
260
264
  this.address = ad.address;
261
- if (this.deviceLogging.includes('debug')) {
262
- this.infoLog(this.address);
263
- this.infoLog(this.device.bleMac);
264
- this.infoLog(`Meter Plus: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
265
- this.infoLog(`Meter Plus: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
265
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},`
266
+ + ` BLE Address Found: ${this.address}`);
267
+ if (ad.serviceData.humidity! > 0) {
268
+ // reject unreliable data
269
+ this.humidity = ad.serviceData.humidity;
266
270
  }
267
271
  this.serviceData = ad.serviceData;
268
272
  this.temperature = ad.serviceData.temperature!.c;
269
- this.humidity = ad.serviceData.humidity;
270
273
  this.battery = ad.serviceData.battery;
271
- this.debugLog(`Meter Plus: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
274
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${superStringify(ad.serviceData)}`);
272
275
  this.debugLog(
273
- `Meter Plus: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
274
- `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
276
+ `${this.device.deviceType}: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
277
+ `temperature: ${superStringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
275
278
  `battery: ${ad.serviceData.battery}`,
276
279
  );
277
280
 
278
281
  if (this.serviceData) {
279
282
  this.connected = true;
280
- this.debugLog(`Meter Plus: ${this.accessory.displayName} connected: ${this.connected}`);
283
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
281
284
  } else {
282
285
  this.connected = false;
283
- this.debugLog(`Meter Plus: ${this.accessory.displayName} connected: ${this.connected}`);
286
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
284
287
  }
285
288
  };
286
289
  // Wait 10 seconds
@@ -293,112 +296,70 @@ export class MeterPlus {
293
296
  this.parseStatus();
294
297
  this.updateHomeKitCharacteristics();
295
298
  } else {
296
- await this.BLEconnection(switchbot);
299
+ await this.BLERefreshConnection(switchbot);
297
300
  }
298
301
  })
299
302
  .catch(async (e: any) => {
300
- this.errorLog(`Meter Plus: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
301
- if (this.deviceLogging.includes('debug')) {
302
- this.errorLog(
303
- `Meter Plus: ${this.accessory.displayName} failed refreshStatus with BLE Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
304
- );
305
- }
306
- if (this.platform.config.credentials?.token) {
307
- this.warnLog(`Meter Plus: ${this.accessory.displayName} Using OpenAPI Connection`);
308
- this.SwitchToOpenAPI = true;
309
- this.openAPIRefreshStatus();
310
- }
311
303
  this.apiError(e);
304
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
305
+ + ` Connection, Error Message: ${superStringify(e.message)}`);
306
+ await this.BLERefreshConnection(switchbot);
312
307
  });
313
308
  } else {
314
- await this.BLEconnection(switchbot);
315
- }
316
- }
317
-
318
- async getCustomBLEAddress(switchbot: any) {
319
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
320
- (async () => {
321
- // Start to monitor advertisement packets
322
- await switchbot.startScan({
323
- model: 'i',
324
- });
325
- // Set an event handler
326
- switchbot.onadvertisement = (ad: any) => {
327
- this.warnLog(`Meter Plus: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
328
- };
329
- await switchbot.wait(10000);
330
- // Stop to monitor
331
- switchbot.stopScan();
332
- })();
333
- }
334
- }
335
-
336
- async BLEconnection(switchbot: any): Promise<void> {
337
- this.errorLog(`Meter Plus: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
338
- if (this.platform.config.credentials?.token) {
339
- this.warnLog(`Meter Plus: ${this.accessory.displayName} Using OpenAPI Connection`);
340
- this.SwitchToOpenAPI = true;
341
- await this.openAPIRefreshStatus();
309
+ await this.BLERefreshConnection(switchbot);
342
310
  }
343
311
  }
344
312
 
345
313
  async openAPIRefreshStatus(): Promise<void> {
346
- if (this.platform.config.credentials?.token) {
347
- this.debugLog(`Meter Plus: ${this.accessory.displayName} OpenAPI RefreshStatus`);
348
- try {
349
- const t = Date.now();
350
- const nonce = 'requestID';
351
- const data = this.platform.config.credentials?.token + t + nonce;
352
- const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
353
- const sign = signTerm.toString('base64');
354
- this.debugLog(`Meter Plus: ${this.accessory.displayName} sign: ${sign}`);
355
- const options = {
356
- hostname: HostDomain,
357
- port: 443,
358
- path: `${DevicePath}/${this.device.deviceId}/status`,
359
- method: 'GET',
360
- headers: {
361
- Authorization: this.platform.config.credentials?.token,
362
- sign: sign,
363
- nonce: nonce,
364
- t: t,
365
- 'Content-Type': 'application/json',
366
- },
367
- };
368
- const req = https.request(options, (res) => {
369
- this.debugLog(`Meter Plus: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
370
- let rawData = '';
371
- res.on('data', (d) => {
372
- rawData += d;
373
- this.debugLog(`Meter Plus: ${this.accessory.displayName} d: ${d}`);
374
- });
375
- res.on('end', () => {
376
- try {
377
- this.deviceStatus = JSON.parse(rawData);
378
- this.debugLog(`Meter Plus: ${this.accessory.displayName} openAPIRefreshStatus: ${JSON.stringify(this.deviceStatus)}`);
379
- this.Humidity = this.deviceStatus.body.humidity!;
380
- this.Temperature = this.deviceStatus.body.temperature!;
381
- this.parseStatus();
382
- this.updateHomeKitCharacteristics();
383
- } catch (e: any) {
384
- this.errorLog(`Meter Plus: ${this.accessory.displayName} error message: ${e.message}`);
385
- }
386
- });
314
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
315
+ try {
316
+ const t = Date.now();
317
+ const nonce = 'requestID';
318
+ const data = this.platform.config.credentials?.token + t + nonce;
319
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
320
+ const sign = signTerm.toString('base64');
321
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
322
+ const options = {
323
+ hostname: HostDomain,
324
+ port: 443,
325
+ path: `${DevicePath}/${this.device.deviceId}/status`,
326
+ method: 'GET',
327
+ headers: {
328
+ Authorization: this.platform.config.credentials?.token,
329
+ sign: sign,
330
+ nonce: nonce,
331
+ t: t,
332
+ 'Content-Type': 'application/json',
333
+ },
334
+ };
335
+ const req = https.request(options, (res) => {
336
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
337
+ let rawData = '';
338
+ res.on('data', (d) => {
339
+ rawData += d;
340
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
387
341
  });
388
- req.on('error', (e: any) => {
389
- this.errorLog(`Meter Plus: ${this.accessory.displayName} error message: ${e.message}`);
342
+ res.on('end', () => {
343
+ try {
344
+ this.deviceStatus = JSON.parse(rawData);
345
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
346
+ this.Humidity = this.deviceStatus.body.humidity!;
347
+ this.Temperature = this.deviceStatus.body.temperature!;
348
+ this.parseStatus();
349
+ this.updateHomeKitCharacteristics();
350
+ } catch (e: any) {
351
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
352
+ }
390
353
  });
391
- req.end();
392
- } catch (e: any) {
393
- this.errorLog(`Meter Plus: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
394
- if (this.deviceLogging.includes('debug')) {
395
- this.errorLog(
396
- `Meter Plus: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` +
397
- ` Error Message: ${JSON.stringify(e.message)}`,
398
- );
399
- }
400
- this.apiError(e);
401
- }
354
+ });
355
+ req.on('error', (e: any) => {
356
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
357
+ });
358
+ req.end();
359
+ } catch (e: any) {
360
+ this.apiError(e);
361
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
362
+ + ` Connection, Error Message: ${superStringify(e.message)}`);
402
363
  }
403
364
  }
404
365
 
@@ -406,38 +367,225 @@ export class MeterPlus {
406
367
  * Updates the status for each of the HomeKit Characteristics
407
368
  */
408
369
  async updateHomeKitCharacteristics(): Promise<void> {
370
+ const mqttmessage: string[] = [];
371
+ const entry = { time: Math.round(new Date().valueOf() / 1000) };
409
372
  if (!this.device.meter?.hide_humidity) {
410
373
  if (this.CurrentRelativeHumidity === undefined) {
411
- this.debugLog(`Meter Plus: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
374
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
412
375
  } else {
376
+ this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidity;
413
377
  this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
414
- this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
378
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
379
+ + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
380
+ if (this.device.mqttURL) {
381
+ mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
382
+ }
383
+ if (this.device.history) {
384
+ entry['humidity'] = this.CurrentRelativeHumidity;
385
+ }
415
386
  }
416
387
  }
417
388
  if (!this.device.meter?.hide_temperature) {
418
389
  if (this.CurrentTemperature === undefined) {
419
- this.debugLog(`Meter Plus: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
390
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
420
391
  } else {
392
+ if (this.device.mqttURL) {
393
+ mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
394
+ }
395
+ if (this.device.history){
396
+ entry['temp'] = this.CurrentTemperature;
397
+ }
398
+ this.accessory.context.CurrentTemperature = this.CurrentTemperature;
421
399
  this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature);
422
- this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
400
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
423
401
  }
424
402
  }
425
- if (this.device.ble) {
403
+ if (this.BLE) {
426
404
  if (this.BatteryLevel === undefined) {
427
- this.debugLog(`Meter Plus: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
405
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
428
406
  } else {
407
+ if (this.device.mqttURL) {
408
+ mqttmessage.push(`"battery": ${this.BatteryLevel}`);
409
+ }
410
+ this.accessory.context.BatteryLevel = this.BatteryLevel;
429
411
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
430
- this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
412
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
431
413
  }
432
414
  if (this.StatusLowBattery === undefined) {
433
- this.debugLog(`Meter Plus: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
415
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
434
416
  } else {
417
+ if (this.device.mqttURL) {
418
+ mqttmessage.push(`"lowBattery": ${this.StatusLowBattery}`);
419
+ }
420
+ this.accessory.context.StatusLowBattery = this.StatusLowBattery;
435
421
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
436
- this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
422
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
423
+ }
424
+ }
425
+ if (this.device.mqttURL) {
426
+ this.mqttPublish(`{${mqttmessage.join(',')}}`);
427
+ }
428
+ if (this.CurrentRelativeHumidity > 0) {
429
+ // reject unreliable data
430
+ if (this.device.history) {
431
+ this.historyService?.addEntry(entry);
432
+ }
433
+ }
434
+ }
435
+
436
+ /*
437
+ * Publish MQTT message for topics of
438
+ * 'homebridge-switchbot/meter/xx:xx:xx:xx:xx:xx'
439
+ */
440
+ mqttPublish(message: any) {
441
+ const mac = this.device.deviceId
442
+ ?.toLowerCase()
443
+ .match(/[\s\S]{1,2}/g)
444
+ ?.join(':');
445
+ const options = this.device.mqttPubOptions || {};
446
+ this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
447
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${superStringify(options)}`);
448
+ }
449
+
450
+ /*
451
+ * Setup MQTT hadler if URL is specifed.
452
+ */
453
+ async setupMqtt(device: device & devicesConfig): Promise<void> {
454
+ if (device.mqttURL) {
455
+ try {
456
+ this.mqttClient = await connectAsync(device.mqttURL, device.mqttOptions || {});
457
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
458
+ this.mqttClient.on('error', (e: Error) => {
459
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
460
+ });
461
+ } catch (e) {
462
+ this.mqttClient = null;
463
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
437
464
  }
438
465
  }
439
466
  }
440
467
 
468
+ /*
469
+ * Setup EVE history graph feature if enabled.
470
+ */
471
+ async setupHistoryService(device: device & devicesConfig): Promise<void> {
472
+ const mac = this.device
473
+ .deviceId!.match(/.{1,2}/g)!
474
+ .join(':')
475
+ .toLowerCase();
476
+ this.historyService = device.history
477
+ ? new this.platform.fakegatoAPI('room', this.accessory, {
478
+ log: this.platform.log,
479
+ storage: 'fs',
480
+ filename: `${hostname().split('.')[0]}_${mac}_persist.json`,
481
+ })
482
+ : null;
483
+ }
484
+
485
+ async getCustomBLEAddress(switchbot: any) {
486
+ if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
487
+ (async () => {
488
+ // Start to monitor advertisement packets
489
+ await switchbot.startScan({
490
+ model: 'i',
491
+ });
492
+ // Set an event handler
493
+ switchbot.onadvertisement = (ad: any) => {
494
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
495
+ };
496
+ await switchbot.wait(10000);
497
+ // Stop to monitor
498
+ switchbot.stopScan();
499
+ })();
500
+ }
501
+ }
502
+
503
+ async BLERefreshConnection(switchbot: any): Promise<void> {
504
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
505
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
506
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
507
+ await this.openAPIRefreshStatus();
508
+ }
509
+ }
510
+
511
+ model(device: device & devicesConfig): CharacteristicValue {
512
+ let model: string;
513
+ if (device.deviceType === 'Meter Plus (JP)') {
514
+ model = 'W2201500';
515
+ } else {
516
+ model = 'W2301500';
517
+ }
518
+ return model;
519
+ }
520
+
521
+ async scan(device: device & devicesConfig): Promise<void> {
522
+ if (device.scanDuration) {
523
+ this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
524
+ if (this.BLE) {
525
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
526
+ }
527
+ } else {
528
+ this.scanDuration = this.accessory.context.scanDuration = 1;
529
+ if (this.BLE) {
530
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
531
+ }
532
+ }
533
+ }
534
+
535
+ async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
536
+ switch (res.statusCode) {
537
+ case 151:
538
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
539
+ break;
540
+ case 152:
541
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
542
+ break;
543
+ case 160:
544
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
545
+ break;
546
+ case 161:
547
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
548
+ this.offlineOff();
549
+ break;
550
+ case 171:
551
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
552
+ this.offlineOff();
553
+ break;
554
+ case 190:
555
+ this.errorLog(
556
+ `${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
557
+ ` Or command: ${superStringify(res)} format is invalid`,
558
+ );
559
+ break;
560
+ case 100:
561
+ if (this.platform.debugMode) {
562
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
563
+ }
564
+ break;
565
+ default:
566
+ if (this.platform.debugMode) {
567
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
568
+ }
569
+ }
570
+ }
571
+
572
+ async offlineOff(): Promise<void> {
573
+ if (this.device.offline) {
574
+ if (!this.device.meter?.hide_humidity) {
575
+ this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity,
576
+ this.accessory.context.CurrentRelativeHumidity);
577
+ }
578
+ if (!this.device.meter?.hide_temperature) {
579
+ this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.accessory.context.CurrentTemperature);
580
+ }
581
+ if (this.BLE) {
582
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.accessory.context.BatteryLevel);
583
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.accessory.context.StatusLowBattery);
584
+ }
585
+ await this.updateHomeKitCharacteristics();
586
+ }
587
+ }
588
+
441
589
  async apiError(e: any): Promise<void> {
442
590
  if (!this.device.meter?.hide_humidity) {
443
591
  this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
@@ -445,21 +593,62 @@ export class MeterPlus {
445
593
  if (!this.device.meter?.hide_temperature) {
446
594
  this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
447
595
  }
448
- if (this.device.ble) {
596
+ if (this.BLE) {
449
597
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
450
598
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
451
599
  }
452
- //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
453
600
  }
454
601
 
455
- model(device: device & devicesConfig): CharacteristicValue {
456
- let model: string;
457
- if (device.deviceType === 'Meter Plus (JP)') {
458
- model = 'W2201500';
602
+ FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
603
+ let FirmwareRevision: string;
604
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
605
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
606
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
607
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
608
+ if (accessory.context.FirmwareRevision) {
609
+ FirmwareRevision = accessory.context.FirmwareRevision;
610
+ } else if (device.firmware) {
611
+ FirmwareRevision = device.firmware;
459
612
  } else {
460
- model = 'W2301500';
613
+ FirmwareRevision = this.platform.version;
614
+ }
615
+ return FirmwareRevision;
616
+ }
617
+
618
+ private context() {
619
+ if (this.CurrentRelativeHumidity === undefined) {
620
+ this.CurrentRelativeHumidity = 0;
621
+ } else {
622
+ this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
623
+ }
624
+ if (this.CurrentTemperature === undefined) {
625
+ this.CurrentTemperature = 0;
626
+ } else {
627
+ this.CurrentTemperature = this.accessory.context.CurrentTemperature;
628
+ }
629
+ if (this.BLE) {
630
+ if (this.BatteryLevel === undefined) {
631
+ this.BatteryLevel = 100;
632
+ } else {
633
+ this.BatteryLevel = this.accessory.context.BatteryLevel;
634
+ }
635
+ if (this.StatusLowBattery === undefined) {
636
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
637
+ this.accessory.context.StatusLowBattery = this.StatusLowBattery;
638
+ } else {
639
+ this.StatusLowBattery = this.accessory.context.StatusLowBattery;
640
+ }
641
+ }
642
+ }
643
+
644
+ async refreshRate(device: device & devicesConfig): Promise<void> {
645
+ if (device.refreshRate) {
646
+ this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
647
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
648
+ } else if (this.platform.config.options!.refreshRate) {
649
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
650
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
461
651
  }
462
- return model;
463
652
  }
464
653
 
465
654
  async config(device: device & devicesConfig): Promise<void> {
@@ -467,8 +656,14 @@ export class MeterPlus {
467
656
  if (device.meter) {
468
657
  config = device.meter;
469
658
  }
470
- if (device.ble !== undefined) {
471
- config['ble'] = device.ble;
659
+ if (device.connectionType !== undefined) {
660
+ config['connectionType'] = device.connectionType;
661
+ }
662
+ if (device.external !== undefined) {
663
+ config['external'] = device.external;
664
+ }
665
+ if (device.mqttURL !== undefined) {
666
+ config['mqttURL'] = device.mqttURL;
472
667
  }
473
668
  if (device.logging !== undefined) {
474
669
  config['logging'] = device.logging;
@@ -480,65 +675,26 @@ export class MeterPlus {
480
675
  config['scanDuration'] = device.scanDuration;
481
676
  }
482
677
  if (Object.entries(config).length !== 0) {
483
- this.infoLog(`Meter Plus: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
484
- }
485
- }
486
-
487
- async refreshRate(device: device & devicesConfig): Promise<void> {
488
- if (device.refreshRate) {
489
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
490
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
491
- } else if (this.platform.config.options!.refreshRate) {
492
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
493
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
494
- }
495
- }
496
-
497
- async scan(device: device & devicesConfig): Promise<void> {
498
- if (device.scanDuration) {
499
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
500
- if (device.ble) {
501
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
502
- }
503
- } else {
504
- this.scanDuration = this.accessory.context.scanDuration = 1;
505
- if (this.device.ble) {
506
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
507
- }
678
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
508
679
  }
509
680
  }
510
681
 
511
682
  async logs(device: device & devicesConfig): Promise<void> {
512
683
  if (this.platform.debugMode) {
513
684
  this.deviceLogging = this.accessory.context.logging = 'debugMode';
514
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
685
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
515
686
  } else if (device.logging) {
516
687
  this.deviceLogging = this.accessory.context.logging = device.logging;
517
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
688
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
518
689
  } else if (this.platform.config.options?.logging) {
519
690
  this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
520
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
691
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
521
692
  } else {
522
693
  this.deviceLogging = this.accessory.context.logging = 'standard';
523
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
694
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
524
695
  }
525
696
  }
526
697
 
527
- FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
528
- let FirmwareRevision: string;
529
- this.debugLog(`Meter Plus: ${this.accessory.displayName} accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
530
- this.debugLog(`Meter Plus: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
531
- this.debugLog(`Meter Plus: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
532
- if (accessory.context.FirmwareRevision) {
533
- FirmwareRevision = accessory.context.FirmwareRevision;
534
- } else if (device.firmware) {
535
- FirmwareRevision = device.firmware;
536
- } else {
537
- FirmwareRevision = this.platform.version;
538
- }
539
- return FirmwareRevision;
540
- }
541
-
542
698
  /**
543
699
  * Logging for Device
544
700
  */
@@ -554,12 +710,28 @@ export class MeterPlus {
554
710
  }
555
711
  }
556
712
 
713
+ debugWarnLog(...log: any[]): void {
714
+ if (this.enablingDeviceLogging()) {
715
+ if (this.deviceLogging?.includes('debug')) {
716
+ this.platform.log.warn('[DEBUG]', String(...log));
717
+ }
718
+ }
719
+ }
720
+
557
721
  errorLog(...log: any[]): void {
558
722
  if (this.enablingDeviceLogging()) {
559
723
  this.platform.log.error(String(...log));
560
724
  }
561
725
  }
562
726
 
727
+ debugErrorLog(...log: any[]): void {
728
+ if (this.enablingDeviceLogging()) {
729
+ if (this.deviceLogging?.includes('debug')) {
730
+ this.platform.log.error('[DEBUG]', String(...log));
731
+ }
732
+ }
733
+ }
734
+
563
735
  debugLog(...log: any[]): void {
564
736
  if (this.enablingDeviceLogging()) {
565
737
  if (this.deviceLogging === 'debug') {