@switchbot/homebridge-switchbot 3.5.0-beta.9 → 3.5.1-beta.0

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