@switchbot/homebridge-switchbot 3.5.0-beta.6 → 3.5.0-beta.61

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