@switchbot/homebridge-switchbot 3.5.0-beta.4 → 3.5.0-beta.41

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 (168) hide show
  1. package/CHANGELOG.md +4 -1
  2. package/config.schema.json +120 -17
  3. package/dist/device/blindtilt.d.ts +21 -94
  4. package/dist/device/blindtilt.d.ts.map +1 -1
  5. package/dist/device/blindtilt.js +351 -757
  6. package/dist/device/blindtilt.js.map +1 -1
  7. package/dist/device/bot.d.ts +25 -71
  8. package/dist/device/bot.d.ts.map +1 -1
  9. package/dist/device/bot.js +587 -761
  10. package/dist/device/bot.js.map +1 -1
  11. package/dist/device/ceilinglight.d.ts +13 -67
  12. package/dist/device/ceilinglight.d.ts.map +1 -1
  13. package/dist/device/ceilinglight.js +213 -588
  14. package/dist/device/ceilinglight.js.map +1 -1
  15. package/dist/device/colorbulb.d.ts +13 -74
  16. package/dist/device/colorbulb.d.ts.map +1 -1
  17. package/dist/device/colorbulb.js +255 -634
  18. package/dist/device/colorbulb.js.map +1 -1
  19. package/dist/device/contact.d.ts +14 -65
  20. package/dist/device/contact.d.ts.map +1 -1
  21. package/dist/device/contact.js +208 -532
  22. package/dist/device/contact.js.map +1 -1
  23. package/dist/device/curtain.d.ts +17 -86
  24. package/dist/device/curtain.d.ts.map +1 -1
  25. package/dist/device/curtain.js +339 -787
  26. package/dist/device/curtain.js.map +1 -1
  27. package/dist/device/device.d.ts +59 -0
  28. package/dist/device/device.d.ts.map +1 -0
  29. package/dist/device/device.js +671 -0
  30. package/dist/device/device.js.map +1 -0
  31. package/dist/device/fan.d.ts +51 -0
  32. package/dist/device/fan.d.ts.map +1 -0
  33. package/dist/device/fan.js +504 -0
  34. package/dist/device/fan.js.map +1 -0
  35. package/dist/device/hub.d.ts +15 -59
  36. package/dist/device/hub.d.ts.map +1 -1
  37. package/dist/device/hub.js +246 -597
  38. package/dist/device/hub.js.map +1 -1
  39. package/dist/device/humidifier.d.ts +10 -65
  40. package/dist/device/humidifier.d.ts.map +1 -1
  41. package/dist/device/humidifier.js +211 -572
  42. package/dist/device/humidifier.js.map +1 -1
  43. package/dist/device/iosensor.d.ts +11 -64
  44. package/dist/device/iosensor.d.ts.map +1 -1
  45. package/dist/device/iosensor.js +178 -585
  46. package/dist/device/iosensor.js.map +1 -1
  47. package/dist/device/lightstrip.d.ts +10 -68
  48. package/dist/device/lightstrip.d.ts.map +1 -1
  49. package/dist/device/lightstrip.js +256 -569
  50. package/dist/device/lightstrip.js.map +1 -1
  51. package/dist/device/lock.d.ts +15 -62
  52. package/dist/device/lock.d.ts.map +1 -1
  53. package/dist/device/lock.js +214 -543
  54. package/dist/device/lock.js.map +1 -1
  55. package/dist/device/meter.d.ts +13 -63
  56. package/dist/device/meter.d.ts.map +1 -1
  57. package/dist/device/meter.js +174 -578
  58. package/dist/device/meter.js.map +1 -1
  59. package/dist/device/meterplus.d.ts +13 -64
  60. package/dist/device/meterplus.d.ts.map +1 -1
  61. package/dist/device/meterplus.js +163 -578
  62. package/dist/device/meterplus.js.map +1 -1
  63. package/dist/device/motion.d.ts +13 -69
  64. package/dist/device/motion.d.ts.map +1 -1
  65. package/dist/device/motion.js +141 -520
  66. package/dist/device/motion.js.map +1 -1
  67. package/dist/device/plug.d.ts +9 -57
  68. package/dist/device/plug.d.ts.map +1 -1
  69. package/dist/device/plug.js +86 -453
  70. package/dist/device/plug.js.map +1 -1
  71. package/dist/device/robotvacuumcleaner.d.ts +11 -62
  72. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  73. package/dist/device/robotvacuumcleaner.js +144 -452
  74. package/dist/device/robotvacuumcleaner.js.map +1 -1
  75. package/dist/device/waterdetector.d.ts +9 -70
  76. package/dist/device/waterdetector.d.ts.map +1 -1
  77. package/dist/device/waterdetector.js +125 -665
  78. package/dist/device/waterdetector.js.map +1 -1
  79. package/dist/homebridge-ui/public/index.html +2 -2
  80. package/dist/index.js +1 -1
  81. package/dist/irdevice/airconditioner.d.ts +8 -48
  82. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  83. package/dist/irdevice/airconditioner.js +309 -419
  84. package/dist/irdevice/airconditioner.js.map +1 -1
  85. package/dist/irdevice/airpurifier.d.ts +7 -38
  86. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  87. package/dist/irdevice/airpurifier.js +72 -304
  88. package/dist/irdevice/airpurifier.js.map +1 -1
  89. package/dist/irdevice/camera.d.ts +6 -35
  90. package/dist/irdevice/camera.d.ts.map +1 -1
  91. package/dist/irdevice/camera.js +34 -278
  92. package/dist/irdevice/camera.js.map +1 -1
  93. package/dist/irdevice/fan.d.ts +6 -39
  94. package/dist/irdevice/fan.d.ts.map +1 -1
  95. package/dist/irdevice/fan.js +67 -311
  96. package/dist/irdevice/fan.js.map +1 -1
  97. package/dist/irdevice/irdevice.d.ts +40 -0
  98. package/dist/irdevice/irdevice.d.ts.map +1 -0
  99. package/dist/irdevice/irdevice.js +512 -0
  100. package/dist/irdevice/irdevice.js.map +1 -0
  101. package/dist/irdevice/light.d.ts +6 -34
  102. package/dist/irdevice/light.d.ts.map +1 -1
  103. package/dist/irdevice/light.js +23 -272
  104. package/dist/irdevice/light.js.map +1 -1
  105. package/dist/irdevice/other.d.ts +18 -47
  106. package/dist/irdevice/other.d.ts.map +1 -1
  107. package/dist/irdevice/other.js +352 -546
  108. package/dist/irdevice/other.js.map +1 -1
  109. package/dist/irdevice/tv.d.ts +7 -39
  110. package/dist/irdevice/tv.d.ts.map +1 -1
  111. package/dist/irdevice/tv.js +82 -321
  112. package/dist/irdevice/tv.js.map +1 -1
  113. package/dist/irdevice/vacuumcleaner.d.ts +6 -35
  114. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  115. package/dist/irdevice/vacuumcleaner.js +41 -284
  116. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  117. package/dist/irdevice/waterheater.d.ts +6 -35
  118. package/dist/irdevice/waterheater.d.ts.map +1 -1
  119. package/dist/irdevice/waterheater.js +42 -287
  120. package/dist/irdevice/waterheater.js.map +1 -1
  121. package/dist/platform.d.ts +14 -1
  122. package/dist/platform.d.ts.map +1 -1
  123. package/dist/platform.js +343 -198
  124. package/dist/platform.js.map +1 -1
  125. package/dist/settings.d.ts +41 -11
  126. package/dist/settings.d.ts.map +1 -1
  127. package/dist/settings.js +0 -552
  128. package/dist/settings.js.map +1 -1
  129. package/dist/utils.d.ts +77 -0
  130. package/dist/utils.d.ts.map +1 -1
  131. package/dist/utils.js +638 -1
  132. package/dist/utils.js.map +1 -1
  133. package/package.json +16 -15
  134. package/src/custom.d.ts +2 -1
  135. package/src/device/blindtilt.ts +377 -783
  136. package/src/device/bot.ts +620 -845
  137. package/src/device/ceilinglight.ts +226 -608
  138. package/src/device/colorbulb.ts +268 -657
  139. package/src/device/contact.ts +233 -554
  140. package/src/device/curtain.ts +359 -811
  141. package/src/device/device.ts +699 -0
  142. package/src/device/fan.ts +553 -0
  143. package/src/device/hub.ts +273 -625
  144. package/src/device/humidifier.ts +241 -619
  145. package/src/device/iosensor.ts +204 -611
  146. package/src/device/lightstrip.ts +277 -597
  147. package/src/device/lock.ts +251 -583
  148. package/src/device/meter.ts +199 -601
  149. package/src/device/meterplus.ts +188 -603
  150. package/src/device/motion.ts +160 -542
  151. package/src/device/plug.ts +96 -481
  152. package/src/device/robotvacuumcleaner.ts +165 -478
  153. package/src/device/waterdetector.ts +142 -689
  154. package/src/homebridge-ui/public/index.html +2 -2
  155. package/src/index.ts +1 -1
  156. package/src/irdevice/airconditioner.ts +330 -446
  157. package/src/irdevice/airpurifier.ts +89 -321
  158. package/src/irdevice/camera.ts +42 -293
  159. package/src/irdevice/fan.ts +78 -327
  160. package/src/irdevice/irdevice.ts +528 -0
  161. package/src/irdevice/light.ts +32 -287
  162. package/src/irdevice/other.ts +396 -615
  163. package/src/irdevice/tv.ts +100 -339
  164. package/src/irdevice/vacuumcleaner.ts +49 -305
  165. package/src/irdevice/waterheater.ts +50 -310
  166. package/src/platform.ts +353 -206
  167. package/src/settings.ts +57 -566
  168. package/src/utils.ts +642 -1
@@ -1,112 +1,85 @@
1
- import asyncmqtt from 'async-mqtt';
2
- import { CharacteristicValue, PlatformAccessory, Service, Units, API, Logging, HAP } from 'homebridge';
3
- import { MqttClient } from 'mqtt';
4
- import { hostname } from 'os';
5
- import { interval } from 'rxjs';
6
- import { request } from 'undici';
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * meter.ts: @switchbot/homebridge-switchbot.
4
+ */
5
+ import { deviceBase } from './device.js';
7
6
  import { SwitchBotPlatform } from '../platform.js';
8
- import { Devices, device, deviceStatus, devicesConfig, serviceData, temperature, SwitchBotPlatformConfig } from '../settings.js';
9
- import { sleep } from '../utils.js';
10
-
11
- export class Meter {
12
- public readonly api: API;
13
- public readonly log: Logging;
14
- public readonly config!: SwitchBotPlatformConfig;
15
- protected readonly hap: HAP;
7
+ import { convertUnits } from '../utils.js';
8
+ import { Subject, interval, skipWhile } from 'rxjs';
9
+ import { CharacteristicValue, PlatformAccessory, Service, Units } from 'homebridge';
10
+ import { device, devicesConfig, serviceData, deviceStatus, Devices } from '../settings.js';
11
+
12
+ export class Meter extends deviceBase {
16
13
  // Services
17
- batteryService: Service;
18
- humidityService?: Service;
19
- temperatureService?: Service;
20
-
21
- // Characteristic Values
22
- BatteryLevel!: CharacteristicValue;
23
- FirmwareRevision!: CharacteristicValue;
24
- StatusLowBattery!: CharacteristicValue;
25
- CurrentTemperature?: CharacteristicValue;
26
- CurrentRelativeHumidity?: CharacteristicValue;
27
-
28
- // OpenAPI Status
29
- OpenAPI_BatteryLevel: deviceStatus['battery'];
30
- OpenAPI_FirmwareRevision: deviceStatus['version'];
31
- OpenAPI_CurrentTemperature: deviceStatus['temperature'];
32
- OpenAPI_CurrentRelativeHumidity: deviceStatus['humidity'];
33
-
34
- // BLE Status
35
- BLE_Celsius!: temperature['c'];
36
- BLE_Fahrenheit!: temperature['f'];
37
- BLE_BatteryLevel!: serviceData['battery'];
38
- BLE_CurrentTemperature!: serviceData['temperature'];
39
- BLE_CurrentRelativeHumidity!: serviceData['humidity'];
40
-
41
- // BLE Others
42
- BLE_IsConnected?: boolean;
43
-
44
- //MQTT stuff
45
- mqttClient: MqttClient | null = null;
46
-
47
- // EVE history service handler
48
- historyService?: any;
49
-
50
- // Config
51
- scanDuration!: number;
52
- deviceLogging!: string;
53
- deviceRefreshRate!: number;
54
-
55
- // Connection
56
- private readonly OpenAPI: boolean;
57
- private readonly BLE: boolean;
14
+ private Battery!: {
15
+ Service: Service;
16
+ BatteryLevel: CharacteristicValue;
17
+ StatusLowBattery: CharacteristicValue;
18
+ };
19
+
20
+ private HumiditySensor?: {
21
+ Service: Service;
22
+ CurrentRelativeHumidity: CharacteristicValue;
23
+ };
24
+
25
+ private TemperatureSensor?: {
26
+ Service: Service;
27
+ CurrentTemperature: CharacteristicValue;
28
+ };
29
+
30
+ // Updates
31
+ meterUpdateInProgress!: boolean;
32
+ doMeterUpdate: Subject<void>;
58
33
 
59
34
  constructor(
60
- private readonly platform: SwitchBotPlatform,
61
- private accessory: PlatformAccessory,
62
- public device: device & devicesConfig,
35
+ readonly platform: SwitchBotPlatform,
36
+ accessory: PlatformAccessory,
37
+ device: device & devicesConfig,
63
38
  ) {
64
- this.api = this.platform.api;
65
- this.log = this.platform.log;
66
- this.config = this.platform.config;
67
- this.hap = this.api.hap;
68
- // Connection
69
- this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
70
- this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
71
- // default placeholders
72
- this.deviceLogs(device);
73
- this.scan(device);
74
- this.refreshRate(device);
75
- this.deviceContext();
76
- this.setupHistoryService(device);
77
- this.setupMqtt(device);
78
- this.deviceConfig(device);
79
-
80
- this.CurrentRelativeHumidity = accessory.context.CurrentRelativeHumidity;
81
- this.CurrentTemperature = accessory.context.CurrentTemperature;
39
+ super(platform, accessory, device);
40
+ // this is subject we use to track when we need to POST changes to the SwitchBot API
41
+ this.doMeterUpdate = new Subject();
42
+ this.meterUpdateInProgress = false;
43
+
44
+ // Initialize Temperature Sensor property
45
+ if (!device.meter?.hide_temperature) {
46
+ this.TemperatureSensor = {
47
+ Service: accessory.getService(this.hap.Service.TemperatureSensor)!,
48
+ CurrentTemperature: accessory.context.CurrentTemperature || 30,
49
+ };
50
+ }
51
+
52
+ // Initialize Humidity Sensor property
53
+ if (!device.meter?.hide_humidity) {
54
+ this.HumiditySensor = {
55
+ Service: accessory.getService(this.hap.Service.HumiditySensor)!,
56
+ CurrentRelativeHumidity: accessory.context.CurrentRelativeHumidity || 50,
57
+ };
58
+ }
59
+
60
+ // Initialize Battery property
61
+ this.Battery = {
62
+ Service: accessory.getService(this.hap.Service.Battery)!,
63
+ BatteryLevel: accessory.context.BatteryLevel || 100,
64
+ StatusLowBattery: accessory.context.StatusLowBattery || this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
65
+ };
82
66
 
83
67
  // Retrieve initial values and updateHomekit
84
68
  this.refreshStatus();
85
69
 
86
- // set accessory information
87
- accessory
88
- .getService(this.hap.Service.AccessoryInformation)!
89
- .setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
90
- .setCharacteristic(this.hap.Characteristic.Model, 'METERTH-S1')
91
- .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId)
92
- .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.FirmwareRevision);
93
-
94
70
  // Temperature Sensor Service
95
71
  if (device.meter?.hide_temperature) {
96
72
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Temperature Sensor Service`);
97
- this.temperatureService = this.accessory.getService(this.hap.Service.TemperatureSensor);
98
- accessory.removeService(this.temperatureService!);
99
- } else if (!this.temperatureService) {
73
+ this.TemperatureSensor!.Service = this.accessory.getService(this.hap.Service.TemperatureSensor) as Service;
74
+ accessory.removeService(this.TemperatureSensor!.Service);
75
+ } else if (!this.TemperatureSensor?.Service) {
100
76
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Temperature Sensor Service`);
101
- const temperatureService = `${accessory.displayName} Temperature Sensor`;
102
- (this.temperatureService = this.accessory.getService(this.hap.Service.TemperatureSensor)
103
- || this.accessory.addService(this.hap.Service.TemperatureSensor)), temperatureService;
77
+ const TemperatureSensorService = `${accessory.displayName} Temperature Sensor`;
78
+ (this.TemperatureSensor!.Service = this.accessory.getService(this.hap.Service.TemperatureSensor)
79
+ || this.accessory.addService(this.hap.Service.TemperatureSensor)), TemperatureSensorService;
104
80
 
105
- this.temperatureService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Temperature Sensor`);
106
- if (!this.temperatureService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
107
- this.temperatureService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Temperature Sensor`);
108
- }
109
- this.temperatureService
81
+ this.TemperatureSensor!.Service.setCharacteristic(this.hap.Characteristic.Name, TemperatureSensorService);
82
+ this.TemperatureSensor!.Service
110
83
  .getCharacteristic(this.hap.Characteristic.CurrentTemperature)
111
84
  .setProps({
112
85
  unit: Units['CELSIUS'],
@@ -116,7 +89,7 @@ export class Meter {
116
89
  minStep: 0.1,
117
90
  })
118
91
  .onGet(() => {
119
- return this.CurrentTemperature!;
92
+ return this.TemperatureSensor!.CurrentTemperature!;
120
93
  });
121
94
  } else {
122
95
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Temperature Sensor Service Not Added`);
@@ -125,67 +98,69 @@ export class Meter {
125
98
  // Humidity Sensor Service
126
99
  if (device.meter?.hide_humidity) {
127
100
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Humidity Sensor Service`);
128
- this.humidityService = this.accessory.getService(this.hap.Service.HumiditySensor);
129
- accessory.removeService(this.humidityService!);
130
- } else if (!this.humidityService) {
101
+ this.HumiditySensor!.Service = this.accessory.getService(this.hap.Service.HumiditySensor) as Service;
102
+ accessory.removeService(this.HumiditySensor!.Service);
103
+ } else if (!this.HumiditySensor?.Service) {
131
104
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Humidity Sensor Service`);
132
- const humidityService = `${accessory.displayName} Humidity Sensor`;
133
- (this.humidityService = this.accessory.getService(this.hap.Service.HumiditySensor)
134
- || this.accessory.addService(this.hap.Service.HumiditySensor)), humidityService;
105
+ const HumiditySensorService = `${accessory.displayName} Humidity Sensor`;
106
+ (this.HumiditySensor!.Service = this.accessory.getService(this.hap.Service.HumiditySensor)
107
+ || this.accessory.addService(this.hap.Service.HumiditySensor)), HumiditySensorService;
135
108
 
136
- this.humidityService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Humidity Sensor`);
137
- if (!this.humidityService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
138
- this.humidityService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Humidity Sensor`);
139
- }
140
- this.humidityService
109
+ this.HumiditySensor!.Service.setCharacteristic(this.hap.Characteristic.Name, HumiditySensorService);
110
+ this.HumiditySensor!.Service
141
111
  .getCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity)
142
112
  .setProps({
143
113
  minStep: 0.1,
144
114
  })
145
115
  .onGet(() => {
146
- return this.CurrentRelativeHumidity!;
116
+ return this.HumiditySensor!.CurrentRelativeHumidity!;
147
117
  });
148
118
  } else {
149
119
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Humidity Sensor Service Not Added`);
150
120
  }
151
121
 
152
122
  // Battery Service
153
- const batteryService = `${accessory.displayName} Battery`;
154
- (this.batteryService = this.accessory.getService(this.hap.Service.Battery)
155
- || accessory.addService(this.hap.Service.Battery)), batteryService;
123
+ const BatteryService = `${accessory.displayName} Battery`;
124
+ (this.Battery.Service = this.accessory.getService(this.hap.Service.Battery)
125
+ || accessory.addService(this.hap.Service.Battery)), BatteryService;
156
126
 
157
- this.batteryService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Battery`);
158
- if (!this.batteryService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
159
- this.batteryService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Battery`);
160
- }
161
- this.batteryService.setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
127
+ this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, BatteryService);
128
+ this.Battery.Service.setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
162
129
 
163
130
  // Retrieve initial values and update Homekit
164
131
  this.updateHomeKitCharacteristics();
165
132
 
166
133
  // Start an update interval
167
134
  interval(this.deviceRefreshRate * 1000)
135
+ .pipe(skipWhile(() => this.meterUpdateInProgress))
168
136
  .subscribe(async () => {
169
137
  await this.refreshStatus();
170
138
  });
171
139
 
172
140
  //regisiter webhook event handler
173
- if (this.device.webhook) {
174
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
141
+ if (device.webhook) {
142
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
175
143
  this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
176
144
  try {
177
145
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
178
- if (context.scale === 'CELSIUS') {
179
- const { temperature, humidity } = context;
180
- const { CurrentTemperature, CurrentRelativeHumidity } = this;
181
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
182
- '(temperature, humidity) = ' +
183
- `Webhook:(${temperature}, ${humidity}), ` +
184
- `current:(${CurrentTemperature}, ${CurrentRelativeHumidity})`);
185
- this.CurrentRelativeHumidity = humidity;
186
- this.CurrentTemperature = temperature;
187
- this.updateHomeKitCharacteristics();
146
+ const { temperature, humidity } = context;
147
+ const { CurrentTemperature } = this.TemperatureSensor || { CurrentTemperature: undefined };
148
+ const { CurrentRelativeHumidity } = this.HumiditySensor || { CurrentRelativeHumidity: undefined };
149
+ if (context.scale !== 'CELCIUS' && device.meter?.convertUnitTo === undefined) {
150
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook scale: `
151
+ + `${context.scale}, instead of CELCIUS. Use the *convertUnitsTo* config under Meter settings, if displaying incorrectly in HomeKit.`);
152
+ }
153
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
154
+ '(scale, temperature, humidity) = '
155
+ + `Webhook:(${context.scale}, ${convertUnits(temperature, context.scale, device.meter?.convertUnitTo)}, ${humidity}), `
156
+ + `current:(${CurrentTemperature}, ${CurrentRelativeHumidity})`);
157
+ if (this.device.meter?.hide_humidity) {
158
+ this.HumiditySensor!.CurrentRelativeHumidity = humidity;
159
+ }
160
+ if (this.device.meter?.hide_temperature) {
161
+ this.TemperatureSensor!.CurrentTemperature = convertUnits(temperature, context.scale, device.meter?.convertUnitTo);
188
162
  }
163
+ this.updateHomeKitCharacteristics();
189
164
  } catch (e: any) {
190
165
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
191
166
  + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
@@ -194,90 +169,70 @@ export class Meter {
194
169
  }
195
170
  }
196
171
 
197
- /**
198
- * Parse the device status from the SwitchBot api
199
- */
200
- async parseStatus(): Promise<void> {
201
- if (!this.device.enableCloudService && this.OpenAPI) {
202
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
203
- } else if (this.BLE) {
204
- await this.BLEparseStatus();
205
- } else if (this.OpenAPI && this.platform.config.credentials?.token) {
206
- await this.openAPIparseStatus();
207
- } else {
208
- await this.offlineOff();
209
- this.debugWarnLog(
210
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`,
211
- );
212
- }
213
- }
214
-
215
- async BLEparseStatus(): Promise<void> {
172
+ async BLEparseStatus(serviceData: serviceData): Promise<void> {
216
173
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
217
174
 
218
175
  // BatteryLevel
219
- this.BatteryLevel = Number(this.BLE_BatteryLevel);
220
- if (this.BatteryLevel < 15) {
221
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
176
+ this.Battery.BatteryLevel = Number(serviceData.battery);
177
+ if (this.Battery.BatteryLevel < 15) {
178
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
222
179
  } else {
223
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
180
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
224
181
  }
225
- this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
182
+ this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}, StatusLowBattery: ${this.Battery.StatusLowBattery}`);
226
183
 
227
184
  // CurrentRelativeHumidity
228
185
  if (!this.device.meter?.hide_humidity) {
229
- this.CurrentRelativeHumidity = this.BLE_CurrentRelativeHumidity!;
230
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
186
+ this.HumiditySensor!.CurrentRelativeHumidity = serviceData.humidity!;
187
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.HumiditySensor!.CurrentRelativeHumidity}%`);
231
188
  }
232
189
 
233
190
  // CurrentTemperature
234
191
  if (!this.device.meter?.hide_temperature) {
235
- this.BLE_Celsius < 0 ? 0 : this.BLE_Celsius > 100 ? 100 : this.BLE_Celsius;
236
- this.CurrentTemperature = this.BLE_Celsius;
237
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
192
+ serviceData.temperature!.c < 0 ? 0 : serviceData.temperature!.c > 100 ? 100 : serviceData.temperature!.c;
193
+ this.TemperatureSensor!.CurrentTemperature = serviceData.temperature!.c;
194
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.TemperatureSensor!.CurrentTemperature}°c`);
238
195
  }
239
196
  }
240
197
 
241
- async openAPIparseStatus(): Promise<void> {
198
+ async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
242
199
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
243
200
 
244
- // BatteryLevel
245
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
246
- if (this.BatteryLevel < 15) {
247
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
201
+ // Battery
202
+ this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
203
+ if (this.Battery.BatteryLevel < 10) {
204
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
248
205
  } else {
249
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
206
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
207
+ }
208
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
209
+ this.Battery.BatteryLevel = 100;
250
210
  }
251
- this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
211
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
212
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
252
213
 
253
214
  // CurrentRelativeHumidity
254
215
  if (!this.device.meter?.hide_humidity) {
255
- this.CurrentRelativeHumidity = this.OpenAPI_CurrentRelativeHumidity!;
256
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
216
+ this.HumiditySensor!.CurrentRelativeHumidity = deviceStatus.body.humidity!;
217
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.HumiditySensor!.CurrentRelativeHumidity}%`);
257
218
  }
258
219
 
259
220
  // CurrentTemperature
260
221
  if (!this.device.meter?.hide_temperature) {
261
- this.CurrentTemperature = this.OpenAPI_CurrentTemperature!;
262
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
222
+ this.TemperatureSensor!.CurrentTemperature = deviceStatus.body.temperature!;
223
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.TemperatureSensor!.CurrentTemperature}°c`);
263
224
  }
264
225
 
265
- // Battery
266
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
267
- if (this.BatteryLevel < 10) {
268
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
269
- } else {
270
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
226
+ // Firmware Version
227
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${deviceStatus.body.version}`);
228
+ if (deviceStatus.body.version) {
229
+ this.accessory.context.version = deviceStatus.body.version;
230
+ this.accessory
231
+ .getService(this.hap.Service.AccessoryInformation)!
232
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.accessory.context.version)
233
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
234
+ .updateValue(this.accessory.context.version);
271
235
  }
272
- if (Number.isNaN(this.BatteryLevel)) {
273
- this.BatteryLevel = 100;
274
- }
275
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
276
- + ` StatusLowBattery: ${this.StatusLowBattery}`);
277
-
278
- // FirmwareRevision
279
- this.FirmwareRevision = this.OpenAPI_FirmwareRevision!;
280
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
281
236
  }
282
237
 
283
238
  /**
@@ -311,108 +266,44 @@ export class Meter {
311
266
  this.getCustomBLEAddress(switchbot);
312
267
  // Start to monitor advertisement packets
313
268
  (async () => {
314
- await switchbot.startScan({
315
- model: 'T',
316
- id: this.device.bleMac,
317
- });
269
+ // Start to monitor advertisement packets
270
+ await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
318
271
  // Set an event handler
319
272
  switchbot.onadvertisement = (ad: any) => {
320
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
321
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.serviceData.model}`);
322
- if (this.device.bleMac === ad.address && ad.serviceData.model === 'T') {
273
+ if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
274
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
275
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
323
276
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
324
- this.BLE_CurrentRelativeHumidity = ad.serviceData.humidity < 0 ? 0 : ad.serviceData.humidity > 100 ? 100 : ad.serviceData.humidity;
325
- this.BLE_CurrentTemperature = ad.serviceData.temperature;
326
- this.BLE_Celsius = ad.serviceData.temperature!.c;
327
- this.BLE_Fahrenheit = ad.serviceData.temperature!.f;
328
- this.BLE_BatteryLevel = ad.serviceData.battery;
329
277
  } else {
330
278
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
331
279
  }
332
280
  };
333
- // Wait 1 seconds
281
+ // Wait 10 seconds
334
282
  await switchbot.wait(this.scanDuration * 1000);
335
283
  // Stop to monitor
336
284
  await switchbot.stopScan();
337
285
  // Update HomeKit
338
- await this.BLEparseStatus();
286
+ await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
339
287
  await this.updateHomeKitCharacteristics();
340
288
  })();
341
- /*if (switchbot !== false) {
342
- switchbot
343
- .startScan({
344
- model: 'T',
345
- id: this.device.bleMac,
346
- })
347
- .then(async () => {
348
- // Set an event handler
349
- switchbot.onadvertisement = async (ad: ad) => {
350
- this.debugLog(
351
- `${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
352
- ` BLE Address Found: ${ad.address}`,
353
- );
354
- if (ad.serviceData.humidity! > 0) {
355
- // reject unreliable data
356
- this.BLE_CurrentRelativeHumidity = ad.serviceData.humidity;
357
- }
358
- this.BLE_CurrentTemperature = ad.serviceData.temperature;
359
- this.BLE_Celsius = ad.serviceData.temperature!.c;
360
- this.BLE_Fahrenheit = ad.serviceData.temperature!.f;
361
- this.BLE_BatteryLevel = ad.serviceData.battery;
362
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
363
- this.debugLog(
364
- `${this.device.deviceType}: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
365
- `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
366
- `battery: ${ad.serviceData.battery}`,
367
- );
368
-
369
- if (ad.serviceData) {
370
- this.BLE_IsConnected = true;
371
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
372
- await this.stopScanning(switchbot);
373
- } else {
374
- this.BLE_IsConnected = false;
375
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
376
- }
377
- };
378
- // Wait
379
- return await sleep(this.scanDuration * 1000);
380
- })
381
- .then(async () => {
382
- // Stop to monitor
383
- await this.stopScanning(switchbot);
384
- })
385
- .catch(async (e: any) => {
386
- this.apiError(e);
387
- this.errorLog(
388
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
389
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
390
- );
391
- await this.BLERefreshConnection(switchbot);
392
- });
393
- } else {
289
+ if (switchbot === undefined) {
394
290
  await this.BLERefreshConnection(switchbot);
395
- }*/
291
+ }
396
292
  }
397
293
 
398
294
  async openAPIRefreshStatus(): Promise<void> {
399
295
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
400
296
  try {
401
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
402
- headers: this.platform.generateHeaders(),
403
- });
297
+ const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
298
+ `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
404
299
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
405
300
  const deviceStatus: any = await body.json();
406
301
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
407
302
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
408
303
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
409
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
304
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
410
305
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
411
- this.OpenAPI_CurrentRelativeHumidity = deviceStatus.body.humidity!;
412
- this.OpenAPI_CurrentTemperature = deviceStatus.body.temperature!;
413
- this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
414
- this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
415
- this.openAPIparseStatus();
306
+ this.openAPIparseStatus(deviceStatus);
416
307
  this.updateHomeKitCharacteristics();
417
308
  } else {
418
309
  this.statusCode(statusCode);
@@ -436,64 +327,72 @@ export class Meter {
436
327
 
437
328
  // CurrentRelativeHumidity
438
329
  if (!this.device.meter?.hide_humidity) {
439
- if (this.CurrentRelativeHumidity === undefined) {
440
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
330
+ if (this.HumiditySensor!.CurrentRelativeHumidity === undefined) {
331
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
332
+ + ` CurrentRelativeHumidity: ${this.HumiditySensor!.CurrentRelativeHumidity}`);
441
333
  } else {
334
+ this.accessory.context.CurrentRelativeHumidity = this.HumiditySensor!.CurrentRelativeHumidity;
335
+ this.HumiditySensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity,
336
+ this.HumiditySensor!.CurrentRelativeHumidity);
337
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
338
+ + ` updateCharacteristic CurrentRelativeHumidity: ${this.HumiditySensor!.CurrentRelativeHumidity}`);
442
339
  if (this.device.mqttURL) {
443
- mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
340
+ mqttmessage.push(`"humidity": ${this.HumiditySensor!.CurrentRelativeHumidity}`);
444
341
  }
445
342
  if (this.device.history) {
446
- entry['humidity'] = this.CurrentRelativeHumidity;
343
+ entry['humidity'] = this.HumiditySensor!.CurrentRelativeHumidity;
447
344
  }
448
- this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidity;
449
- this.humidityService?.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
450
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} `
451
- + `updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
452
345
  }
453
346
  }
347
+
454
348
  // CurrentTemperature
455
349
  if (!this.device.meter?.hide_temperature) {
456
- if (this.CurrentTemperature === undefined) {
457
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
350
+ if (this.TemperatureSensor!.CurrentTemperature === undefined) {
351
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentTemperature: ${this.TemperatureSensor!.CurrentTemperature}`);
458
352
  } else {
353
+ this.accessory.context.CurrentTemperature = this.TemperatureSensor!.CurrentTemperature;
354
+ this.TemperatureSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.TemperatureSensor!.CurrentTemperature);
355
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
356
+ + ` CurrentTemperature: ${this.TemperatureSensor!.CurrentTemperature}`);
459
357
  if (this.device.mqttURL) {
460
- mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
358
+ mqttmessage.push(`"temperature": ${this.TemperatureSensor!.CurrentTemperature}`);
461
359
  }
462
360
  if (this.device.history) {
463
- entry['temp'] = this.CurrentTemperature;
361
+ entry['temp'] = this.TemperatureSensor!.CurrentTemperature;
464
362
  }
465
- this.accessory.context.CurrentTemperature = this.CurrentTemperature;
466
- this.temperatureService?.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.CurrentTemperature);
467
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
468
363
  }
469
364
  }
365
+
470
366
  // BatteryLevel
471
- if (this.BatteryLevel === undefined) {
472
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
367
+ if (this.Battery.BatteryLevel === undefined) {
368
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
473
369
  } else {
370
+ this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
371
+ this.Battery!.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
372
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
474
373
  if (this.device.mqttURL) {
475
- mqttmessage.push(`"battery": ${this.BatteryLevel}`);
374
+ mqttmessage.push(`"battery": ${this.Battery.BatteryLevel}`);
476
375
  }
477
- this.accessory.context.BatteryLevel = this.BatteryLevel;
478
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.BatteryLevel);
479
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
480
376
  }
481
- if (this.StatusLowBattery === undefined) {
482
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
377
+ if (this.Battery.StatusLowBattery === undefined) {
378
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
483
379
  } else {
380
+ this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
381
+ this.Battery!.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
382
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
383
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
484
384
  if (this.device.mqttURL) {
485
- mqttmessage.push(`"lowBattery": ${this.StatusLowBattery}`);
385
+ mqttmessage.push(`"lowBattery": ${this.Battery.StatusLowBattery}`);
486
386
  }
487
- this.accessory.context.StatusLowBattery = this.StatusLowBattery;
488
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery);
489
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
490
387
  }
491
388
 
492
- // MQTT
389
+ // MQTT Publish
493
390
  if (this.device.mqttURL) {
494
391
  this.mqttPublish(`{${mqttmessage.join(',')}}`);
495
392
  }
496
- if (Number(this.CurrentRelativeHumidity) > 0) {
393
+
394
+ // History Service
395
+ if (!this.device.meter?.hide_humidity && (Number(this.HumiditySensor!.CurrentRelativeHumidity) > 0)) {
497
396
  // reject unreliable data
498
397
  if (this.device.history) {
499
398
  this.historyService?.addEntry(entry);
@@ -501,84 +400,6 @@ export class Meter {
501
400
  }
502
401
  }
503
402
 
504
- /*
505
- * Publish MQTT message for topics of
506
- * 'homebridge-switchbot/meter/xx:xx:xx:xx:xx:xx'
507
- */
508
- mqttPublish(message: any) {
509
- const mac = this.device.deviceId
510
- ?.toLowerCase()
511
- .match(/[\s\S]{1,2}/g)
512
- ?.join(':');
513
- const options = this.device.mqttPubOptions || {};
514
- this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
515
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${JSON.stringify(options)}`);
516
- }
517
-
518
- /*
519
- * Setup MQTT hadler if URL is specified.
520
- */
521
- async setupMqtt(device: device & devicesConfig): Promise<void> {
522
- if (device.mqttURL) {
523
- try {
524
- const { connectAsync } = asyncmqtt;
525
- this.mqttClient = await connectAsync(device.mqttURL, device.mqttOptions || {});
526
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
527
- this.mqttClient.on('error', (e: Error) => {
528
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
529
- });
530
- } catch (e) {
531
- this.mqttClient = null;
532
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
533
- }
534
- }
535
- }
536
-
537
- /*
538
- * Setup EVE history graph feature if enabled.
539
- */
540
- async setupHistoryService(device: device & devicesConfig): Promise<void> {
541
- const mac = this.device
542
- .deviceId!.match(/.{1,2}/g)!
543
- .join(':')
544
- .toLowerCase();
545
- this.historyService = device.history
546
- ? new this.platform.fakegatoAPI('room', this.accessory, {
547
- log: this.platform.log,
548
- storage: 'fs',
549
- filename: `${hostname().split('.')[0]}_${mac}_persist.json`,
550
- })
551
- : null;
552
- }
553
-
554
- async stopScanning(switchbot: any) {
555
- switchbot.stopScan();
556
- if (this.BLE_IsConnected) {
557
- await this.BLEparseStatus();
558
- await this.updateHomeKitCharacteristics();
559
- } else {
560
- await this.BLERefreshConnection(switchbot);
561
- }
562
- }
563
-
564
- async getCustomBLEAddress(switchbot: any) {
565
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
566
- (async () => {
567
- // Start to monitor advertisement packets
568
- await switchbot.startScan({
569
- model: 'T',
570
- });
571
- // Set an event handler
572
- switchbot.onadvertisement = (ad: any) => {
573
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
574
- };
575
- await sleep(10000);
576
- // Stop to monitor
577
- switchbot.stopScan();
578
- })();
579
- }
580
- }
581
-
582
403
  async BLERefreshConnection(switchbot: any): Promise<void> {
583
404
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
584
405
  + ` ${JSON.stringify(switchbot)}`);
@@ -588,249 +409,26 @@ export class Meter {
588
409
  }
589
410
  }
590
411
 
591
- async scan(device: device & devicesConfig): Promise<void> {
592
- if (device.scanDuration) {
593
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
594
- if (this.BLE) {
595
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
596
- }
597
- } else {
598
- this.scanDuration = this.accessory.context.scanDuration = 1;
599
- if (this.BLE) {
600
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
601
- }
602
- }
603
- }
604
-
605
- async statusCode(statusCode: number): Promise<void> {
606
- switch (statusCode) {
607
- case 151:
608
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
609
- break;
610
- case 152:
611
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
612
- break;
613
- case 160:
614
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
615
- break;
616
- case 161:
617
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
618
- this.offlineOff();
619
- break;
620
- case 171:
621
- this.errorLog(
622
- `${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
623
- `Hub: ${this.device.hubDeviceId}`,
624
- );
625
- this.offlineOff();
626
- break;
627
- case 190:
628
- this.errorLog(
629
- `${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
630
- ` Or command format is invalid, statusCode: ${statusCode}`,
631
- );
632
- break;
633
- case 100:
634
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
635
- break;
636
- case 200:
637
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
638
- break;
639
- case 400:
640
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
641
- + `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
642
- break;
643
- case 401:
644
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
645
- + `but the request has not been authenticated, statusCode: ${statusCode}`);
646
- break;
647
- case 403:
648
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
649
- + `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
650
- break;
651
- case 404:
652
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
653
- + `statusCode: ${statusCode}`);
654
- break;
655
- case 406:
656
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
657
- + `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
658
- break;
659
- case 415:
660
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
661
- + `header that is not supported by the server, statusCode: ${statusCode}`);
662
- break;
663
- case 422:
664
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
665
- + `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
666
- break;
667
- case 429:
668
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
669
- + `requests allowed for a given time window, statusCode: ${statusCode}`);
670
- break;
671
- case 500:
672
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
673
- + `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
674
- break;
675
- default:
676
- this.infoLog(
677
- `${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
678
- `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`,
679
- );
680
- }
681
- }
682
-
683
412
  async offlineOff(): Promise<void> {
684
413
  if (this.device.offline) {
685
- await this.deviceContext();
686
- await this.updateHomeKitCharacteristics();
414
+ if (!this.device.meter?.hide_humidity) {
415
+ this.HumiditySensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, 50);
416
+ }
417
+ if (!this.device.meter?.hide_temperature) {
418
+ this.TemperatureSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, 30);
419
+ }
420
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, 100);
687
421
  }
688
422
  }
689
423
 
690
424
  async apiError(e: any): Promise<void> {
691
425
  if (!this.device.meter?.hide_humidity) {
692
- this.humidityService?.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, e);
426
+ this.HumiditySensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, e);
693
427
  }
694
428
  if (!this.device.meter?.hide_temperature) {
695
- this.temperatureService?.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, e);
696
- }
697
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
698
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
699
- }
700
-
701
- async deviceContext() {
702
- if (this.CurrentRelativeHumidity === undefined) {
703
- this.CurrentRelativeHumidity = 0;
704
- } else {
705
- this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
706
- }
707
- if (this.CurrentTemperature === undefined) {
708
- this.CurrentTemperature = 0;
709
- } else {
710
- this.CurrentTemperature = this.accessory.context.CurrentTemperature;
711
- }
712
- if (this.BatteryLevel === undefined) {
713
- this.BatteryLevel = 100;
714
- } else {
715
- this.BatteryLevel = this.accessory.context.BatteryLevel;
716
- }
717
- if (this.StatusLowBattery === undefined) {
718
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
719
- this.accessory.context.StatusLowBattery = this.StatusLowBattery;
720
- } else {
721
- this.StatusLowBattery = this.accessory.context.StatusLowBattery;
722
- }
723
- if (this.FirmwareRevision === undefined) {
724
- this.FirmwareRevision = this.platform.version;
725
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
726
- }
727
- }
728
-
729
- async refreshRate(device: device & devicesConfig): Promise<void> {
730
- if (device.refreshRate) {
731
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
732
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
733
- } else if (this.platform.config.options!.refreshRate) {
734
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
735
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
736
- }
737
- }
738
-
739
- async deviceConfig(device: device & devicesConfig): Promise<void> {
740
- let config = {};
741
- if (device.meter) {
742
- config = device.meter;
743
- }
744
- if (device.connectionType !== undefined) {
745
- config['connectionType'] = device.connectionType;
746
- }
747
- if (device.external !== undefined) {
748
- config['external'] = device.external;
749
- }
750
- if (device.mqttURL !== undefined) {
751
- config['mqttURL'] = device.mqttURL;
752
- }
753
- if (device.logging !== undefined) {
754
- config['logging'] = device.logging;
755
- }
756
- if (device.refreshRate !== undefined) {
757
- config['refreshRate'] = device.refreshRate;
429
+ this.TemperatureSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, e);
758
430
  }
759
- if (device.scanDuration !== undefined) {
760
- config['scanDuration'] = device.scanDuration;
761
- }
762
- if (device.webhook !== undefined) {
763
- config['webhook'] = device.webhook;
764
- }
765
- if (Object.entries(config).length !== 0) {
766
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
767
- }
768
- }
769
-
770
- async deviceLogs(device: device & devicesConfig): Promise<void> {
771
- if (this.platform.debugMode) {
772
- this.deviceLogging = this.accessory.context.logging = 'debugMode';
773
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
774
- } else if (device.logging) {
775
- this.deviceLogging = this.accessory.context.logging = device.logging;
776
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
777
- } else if (this.platform.config.options?.logging) {
778
- this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
779
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
780
- } else {
781
- this.deviceLogging = this.accessory.context.logging = 'standard';
782
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
783
- }
784
- }
785
-
786
- /**
787
- * Logging for Device
788
- */
789
- infoLog(...log: any[]): void {
790
- if (this.enablingDeviceLogging()) {
791
- this.platform.log.info(String(...log));
792
- }
793
- }
794
-
795
- warnLog(...log: any[]): void {
796
- if (this.enablingDeviceLogging()) {
797
- this.platform.log.warn(String(...log));
798
- }
799
- }
800
-
801
- debugWarnLog(...log: any[]): void {
802
- if (this.enablingDeviceLogging()) {
803
- if (this.deviceLogging?.includes('debug')) {
804
- this.platform.log.warn('[DEBUG]', String(...log));
805
- }
806
- }
807
- }
808
-
809
- errorLog(...log: any[]): void {
810
- if (this.enablingDeviceLogging()) {
811
- this.platform.log.error(String(...log));
812
- }
813
- }
814
-
815
- debugErrorLog(...log: any[]): void {
816
- if (this.enablingDeviceLogging()) {
817
- if (this.deviceLogging?.includes('debug')) {
818
- this.platform.log.error('[DEBUG]', String(...log));
819
- }
820
- }
821
- }
822
-
823
- debugLog(...log: any[]): void {
824
- if (this.enablingDeviceLogging()) {
825
- if (this.deviceLogging === 'debug') {
826
- this.platform.log.info('[DEBUG]', String(...log));
827
- } else {
828
- this.platform.log.debug(String(...log));
829
- }
830
- }
831
- }
832
-
833
- enablingDeviceLogging(): boolean {
834
- return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
431
+ this.Battery!.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
432
+ this.Battery!.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
835
433
  }
836
434
  }