@switchbot/homebridge-switchbot 2.0.0-beta.3 → 2.0.0-beta.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/README.md +1 -2
  3. package/config.schema.json +102 -20
  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 +655 -649
  7. package/dist/device/bot.js.map +1 -1
  8. package/dist/device/colorbulb.d.ts +36 -19
  9. package/dist/device/colorbulb.d.ts.map +1 -1
  10. package/dist/device/colorbulb.js +483 -309
  11. package/dist/device/colorbulb.js.map +1 -1
  12. package/dist/device/contact.d.ts +18 -8
  13. package/dist/device/contact.d.ts.map +1 -1
  14. package/dist/device/contact.js +303 -237
  15. package/dist/device/contact.js.map +1 -1
  16. package/dist/device/curtain.d.ts +23 -16
  17. package/dist/device/curtain.d.ts.map +1 -1
  18. package/dist/device/curtain.js +541 -498
  19. package/dist/device/curtain.js.map +1 -1
  20. package/dist/device/humidifier.d.ts +24 -18
  21. package/dist/device/humidifier.d.ts.map +1 -1
  22. package/dist/device/humidifier.js +450 -369
  23. package/dist/device/humidifier.js.map +1 -1
  24. package/dist/device/lock.d.ts +27 -8
  25. package/dist/device/lock.d.ts.map +1 -1
  26. package/dist/device/lock.js +302 -148
  27. package/dist/device/lock.js.map +1 -1
  28. package/dist/device/meter.d.ts +22 -16
  29. package/dist/device/meter.d.ts.map +1 -1
  30. package/dist/device/meter.js +340 -262
  31. package/dist/device/meter.js.map +1 -1
  32. package/dist/device/meterplus.d.ts +24 -12
  33. package/dist/device/meterplus.d.ts.map +1 -1
  34. package/dist/device/meterplus.js +359 -213
  35. package/dist/device/meterplus.js.map +1 -1
  36. package/dist/device/motion.d.ts +18 -8
  37. package/dist/device/motion.d.ts.map +1 -1
  38. package/dist/device/motion.js +276 -216
  39. package/dist/device/motion.js.map +1 -1
  40. package/dist/device/plug.d.ts +27 -17
  41. package/dist/device/plug.d.ts.map +1 -1
  42. package/dist/device/plug.js +292 -251
  43. package/dist/device/plug.js.map +1 -1
  44. package/dist/device/striplight.d.ts +43 -19
  45. package/dist/device/striplight.d.ts.map +1 -1
  46. package/dist/device/striplight.js +503 -262
  47. package/dist/device/striplight.js.map +1 -1
  48. package/dist/irdevice/airconditioner.d.ts +9 -12
  49. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  50. package/dist/irdevice/airconditioner.js +275 -230
  51. package/dist/irdevice/airconditioner.js.map +1 -1
  52. package/dist/irdevice/airpurifier.d.ts +5 -3
  53. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  54. package/dist/irdevice/airpurifier.js +151 -104
  55. package/dist/irdevice/airpurifier.js.map +1 -1
  56. package/dist/irdevice/camera.d.ts +11 -8
  57. package/dist/irdevice/camera.d.ts.map +1 -1
  58. package/dist/irdevice/camera.js +130 -86
  59. package/dist/irdevice/camera.js.map +1 -1
  60. package/dist/irdevice/fan.d.ts +10 -7
  61. package/dist/irdevice/fan.d.ts.map +1 -1
  62. package/dist/irdevice/fan.js +157 -109
  63. package/dist/irdevice/fan.js.map +1 -1
  64. package/dist/irdevice/light.d.ts +11 -8
  65. package/dist/irdevice/light.d.ts.map +1 -1
  66. package/dist/irdevice/light.js +134 -103
  67. package/dist/irdevice/light.js.map +1 -1
  68. package/dist/irdevice/other.d.ts +11 -8
  69. package/dist/irdevice/other.d.ts.map +1 -1
  70. package/dist/irdevice/other.js +142 -98
  71. package/dist/irdevice/other.js.map +1 -1
  72. package/dist/irdevice/tv.d.ts +12 -9
  73. package/dist/irdevice/tv.d.ts.map +1 -1
  74. package/dist/irdevice/tv.js +140 -93
  75. package/dist/irdevice/tv.js.map +1 -1
  76. package/dist/irdevice/vacuumcleaner.d.ts +9 -10
  77. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  78. package/dist/irdevice/vacuumcleaner.js +129 -89
  79. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  80. package/dist/irdevice/waterheater.d.ts +8 -9
  81. package/dist/irdevice/waterheater.d.ts.map +1 -1
  82. package/dist/irdevice/waterheater.js +129 -89
  83. package/dist/irdevice/waterheater.js.map +1 -1
  84. package/dist/platform.d.ts +14 -12
  85. package/dist/platform.d.ts.map +1 -1
  86. package/dist/platform.js +479 -434
  87. package/dist/platform.js.map +1 -1
  88. package/dist/settings.d.ts +18 -11
  89. package/dist/settings.d.ts.map +1 -1
  90. package/dist/settings.js.map +1 -1
  91. package/package.json +12 -10
  92. package/src/device/bot.ts +654 -660
  93. package/src/device/colorbulb.ts +487 -344
  94. package/src/device/contact.ts +306 -241
  95. package/src/device/curtain.ts +546 -512
  96. package/src/device/humidifier.ts +453 -403
  97. package/src/device/lock.ts +311 -149
  98. package/src/device/meter.ts +351 -275
  99. package/src/device/meterplus.ts +369 -219
  100. package/src/device/motion.ts +282 -222
  101. package/src/device/plug.ts +296 -260
  102. package/src/device/striplight.ts +519 -289
  103. package/src/irdevice/airconditioner.ts +279 -241
  104. package/src/irdevice/airpurifier.ts +148 -103
  105. package/src/irdevice/camera.ts +128 -85
  106. package/src/irdevice/fan.ts +154 -106
  107. package/src/irdevice/light.ts +132 -103
  108. package/src/irdevice/other.ts +140 -97
  109. package/src/irdevice/tv.ts +139 -93
  110. package/src/irdevice/vacuumcleaner.ts +128 -89
  111. package/src/irdevice/waterheater.ts +127 -89
  112. package/src/platform.ts +469 -456
  113. package/src/settings.ts +18 -11
@@ -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,209 @@ 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
+ mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
381
+ entry['humidity'] = this.CurrentRelativeHumidity;
415
382
  }
416
383
  }
417
384
  if (!this.device.meter?.hide_temperature) {
418
385
  if (this.CurrentTemperature === undefined) {
419
- this.debugLog(`Meter Plus: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
386
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
420
387
  } else {
388
+ mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
389
+ entry['temp'] = this.CurrentTemperature;
390
+ this.accessory.context.CurrentTemperature = this.CurrentTemperature;
421
391
  this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature);
422
- this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
392
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
423
393
  }
424
394
  }
425
- if (this.device.ble) {
395
+ if (this.BLE) {
426
396
  if (this.BatteryLevel === undefined) {
427
- this.debugLog(`Meter Plus: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
397
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
428
398
  } else {
399
+ mqttmessage.push(`"battery": ${this.BatteryLevel}`);
400
+ this.accessory.context.BatteryLevel = this.BatteryLevel;
429
401
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
430
- this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
402
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
431
403
  }
432
404
  if (this.StatusLowBattery === undefined) {
433
- this.debugLog(`Meter Plus: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
405
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
434
406
  } else {
407
+ mqttmessage.push(`"lowBattery": ${this.StatusLowBattery}`);
408
+ this.accessory.context.StatusLowBattery = this.StatusLowBattery;
435
409
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
436
- this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
410
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
411
+ }
412
+ }
413
+ this.mqttPublish(`{${mqttmessage.join(',')}}`);
414
+ if (this.CurrentRelativeHumidity > 0) {
415
+ // reject unreliable data
416
+ this.historyService?.addEntry(entry);
417
+ }
418
+ }
419
+
420
+ /*
421
+ * Publish MQTT message for topics of
422
+ * 'homebridge-switchbot/meter/xx:xx:xx:xx:xx:xx'
423
+ */
424
+ mqttPublish(message: any) {
425
+ const mac = this.device.deviceId
426
+ ?.toLowerCase()
427
+ .match(/[\s\S]{1,2}/g)
428
+ ?.join(':');
429
+ const options = this.device.mqttPubOptions || {};
430
+ this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
431
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${superStringify(options)}`);
432
+ }
433
+
434
+ /*
435
+ * Setup MQTT hadler if URL is specifed.
436
+ */
437
+ async setupMqtt(device: device & devicesConfig): Promise<void> {
438
+ if (device.mqttURL) {
439
+ try {
440
+ this.mqttClient = await connectAsync(device.mqttURL, device.mqttOptions || {});
441
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
442
+ this.mqttClient.on('error', (e: Error) => {
443
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
444
+ });
445
+ } catch (e) {
446
+ this.mqttClient = null;
447
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
437
448
  }
438
449
  }
439
450
  }
440
451
 
452
+ /*
453
+ * Setup EVE history graph feature if enabled.
454
+ */
455
+ async setupHistoryService(device: device & devicesConfig): Promise<void> {
456
+ const mac = this.device
457
+ .deviceId!.match(/.{1,2}/g)!
458
+ .join(':')
459
+ .toLowerCase();
460
+ this.historyService = device.history
461
+ ? new this.platform.fakegatoAPI('room', this.accessory, {
462
+ log: this.platform.log,
463
+ storage: 'fs',
464
+ filename: `${hostname().split('.')[0]}_${mac}_persist.json`,
465
+ })
466
+ : null;
467
+ }
468
+
469
+ async getCustomBLEAddress(switchbot: any) {
470
+ if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
471
+ (async () => {
472
+ // Start to monitor advertisement packets
473
+ await switchbot.startScan({
474
+ model: 'i',
475
+ });
476
+ // Set an event handler
477
+ switchbot.onadvertisement = (ad: any) => {
478
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
479
+ };
480
+ await switchbot.wait(10000);
481
+ // Stop to monitor
482
+ switchbot.stopScan();
483
+ })();
484
+ }
485
+ }
486
+
487
+ async BLERefreshConnection(switchbot: any): Promise<void> {
488
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
489
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
490
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
491
+ await this.openAPIRefreshStatus();
492
+ }
493
+ }
494
+
495
+ model(device: device & devicesConfig): CharacteristicValue {
496
+ let model: string;
497
+ if (device.deviceType === 'Meter Plus (JP)') {
498
+ model = 'W2201500';
499
+ } else {
500
+ model = 'W2301500';
501
+ }
502
+ return model;
503
+ }
504
+
505
+ async scan(device: device & devicesConfig): Promise<void> {
506
+ if (device.scanDuration) {
507
+ this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
508
+ if (this.BLE) {
509
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
510
+ }
511
+ } else {
512
+ this.scanDuration = this.accessory.context.scanDuration = 1;
513
+ if (this.BLE) {
514
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
515
+ }
516
+ }
517
+ }
518
+
519
+ async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
520
+ switch (res.statusCode) {
521
+ case 151:
522
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
523
+ break;
524
+ case 152:
525
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
526
+ break;
527
+ case 160:
528
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
529
+ break;
530
+ case 161:
531
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
532
+ this.offlineOff();
533
+ break;
534
+ case 171:
535
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
536
+ this.offlineOff();
537
+ break;
538
+ case 190:
539
+ this.errorLog(
540
+ `${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
541
+ ` Or command: ${superStringify(res)} format is invalid`,
542
+ );
543
+ break;
544
+ case 100:
545
+ if (this.platform.debugMode) {
546
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
547
+ }
548
+ break;
549
+ default:
550
+ if (this.platform.debugMode) {
551
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
552
+ }
553
+ }
554
+ }
555
+
556
+ async offlineOff(): Promise<void> {
557
+ if (this.device.offline) {
558
+ if (!this.device.meter?.hide_humidity) {
559
+ this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity,
560
+ this.accessory.context.CurrentRelativeHumidity);
561
+ }
562
+ if (!this.device.meter?.hide_temperature) {
563
+ this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.accessory.context.CurrentTemperature);
564
+ }
565
+ if (this.BLE) {
566
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.accessory.context.BatteryLevel);
567
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.accessory.context.StatusLowBattery);
568
+ }
569
+ await this.updateHomeKitCharacteristics();
570
+ }
571
+ }
572
+
441
573
  async apiError(e: any): Promise<void> {
442
574
  if (!this.device.meter?.hide_humidity) {
443
575
  this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
@@ -445,21 +577,62 @@ export class MeterPlus {
445
577
  if (!this.device.meter?.hide_temperature) {
446
578
  this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
447
579
  }
448
- if (this.device.ble) {
580
+ if (this.BLE) {
449
581
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
450
582
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
451
583
  }
452
- //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
453
584
  }
454
585
 
455
- model(device: device & devicesConfig): CharacteristicValue {
456
- let model: string;
457
- if (device.deviceType === 'Meter Plus (JP)') {
458
- model = 'W2201500';
586
+ FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
587
+ let FirmwareRevision: string;
588
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
589
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
590
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
591
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
592
+ if (accessory.context.FirmwareRevision) {
593
+ FirmwareRevision = accessory.context.FirmwareRevision;
594
+ } else if (device.firmware) {
595
+ FirmwareRevision = device.firmware;
459
596
  } else {
460
- model = 'W2301500';
597
+ FirmwareRevision = this.platform.version;
598
+ }
599
+ return FirmwareRevision;
600
+ }
601
+
602
+ private context() {
603
+ if (this.CurrentRelativeHumidity === undefined) {
604
+ this.CurrentRelativeHumidity = 0;
605
+ } else {
606
+ this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
607
+ }
608
+ if (this.CurrentTemperature === undefined) {
609
+ this.CurrentTemperature = 0;
610
+ } else {
611
+ this.CurrentTemperature = this.accessory.context.CurrentTemperature;
612
+ }
613
+ if (this.BLE) {
614
+ if (this.BatteryLevel === undefined) {
615
+ this.BatteryLevel = 100;
616
+ } else {
617
+ this.BatteryLevel = this.accessory.context.BatteryLevel;
618
+ }
619
+ if (this.StatusLowBattery === undefined) {
620
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
621
+ this.accessory.context.StatusLowBattery = this.StatusLowBattery;
622
+ } else {
623
+ this.StatusLowBattery = this.accessory.context.StatusLowBattery;
624
+ }
625
+ }
626
+ }
627
+
628
+ async refreshRate(device: device & devicesConfig): Promise<void> {
629
+ if (device.refreshRate) {
630
+ this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
631
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
632
+ } else if (this.platform.config.options!.refreshRate) {
633
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
634
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
461
635
  }
462
- return model;
463
636
  }
464
637
 
465
638
  async config(device: device & devicesConfig): Promise<void> {
@@ -467,8 +640,8 @@ export class MeterPlus {
467
640
  if (device.meter) {
468
641
  config = device.meter;
469
642
  }
470
- if (device.ble !== undefined) {
471
- config['ble'] = device.ble;
643
+ if (device.connectionType !== undefined) {
644
+ config['connectionType'] = device.connectionType;
472
645
  }
473
646
  if (device.logging !== undefined) {
474
647
  config['logging'] = device.logging;
@@ -480,63 +653,24 @@ export class MeterPlus {
480
653
  config['scanDuration'] = device.scanDuration;
481
654
  }
482
655
  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
- }
656
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
508
657
  }
509
658
  }
510
659
 
511
660
  async logs(device: device & devicesConfig): Promise<void> {
512
661
  if (this.platform.debugMode) {
513
662
  this.deviceLogging = this.accessory.context.logging = 'debugMode';
514
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
663
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
515
664
  } else if (device.logging) {
516
665
  this.deviceLogging = this.accessory.context.logging = device.logging;
517
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
666
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
518
667
  } else if (this.platform.config.options?.logging) {
519
668
  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}`);
669
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
521
670
  } else {
522
671
  this.deviceLogging = this.accessory.context.logging = 'standard';
523
- this.debugLog(`Meter Plus: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
524
- }
525
- }
526
-
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;
672
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
538
673
  }
539
- return FirmwareRevision;
540
674
  }
541
675
 
542
676
  /**
@@ -554,12 +688,28 @@ export class MeterPlus {
554
688
  }
555
689
  }
556
690
 
691
+ debugWarnLog(...log: any[]): void {
692
+ if (this.enablingDeviceLogging()) {
693
+ if (this.deviceLogging?.includes('debug')) {
694
+ this.platform.log.warn('[DEBUG]', String(...log));
695
+ }
696
+ }
697
+ }
698
+
557
699
  errorLog(...log: any[]): void {
558
700
  if (this.enablingDeviceLogging()) {
559
701
  this.platform.log.error(String(...log));
560
702
  }
561
703
  }
562
704
 
705
+ debugErrorLog(...log: any[]): void {
706
+ if (this.enablingDeviceLogging()) {
707
+ if (this.deviceLogging?.includes('debug')) {
708
+ this.platform.log.error('[DEBUG]', String(...log));
709
+ }
710
+ }
711
+ }
712
+
563
713
  debugLog(...log: any[]): void {
564
714
  if (this.enablingDeviceLogging()) {
565
715
  if (this.deviceLogging === 'debug') {