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