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

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