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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/CHANGELOG.md +4 -1
  3. package/config.schema.json +164 -22
  4. package/dist/device/blindtilt.d.ts +21 -96
  5. package/dist/device/blindtilt.d.ts.map +1 -1
  6. package/dist/device/blindtilt.js +457 -866
  7. package/dist/device/blindtilt.js.map +1 -1
  8. package/dist/device/bot.d.ts +27 -72
  9. package/dist/device/bot.d.ts.map +1 -1
  10. package/dist/device/bot.js +851 -913
  11. package/dist/device/bot.js.map +1 -1
  12. package/dist/device/ceilinglight.d.ts +15 -69
  13. package/dist/device/ceilinglight.d.ts.map +1 -1
  14. package/dist/device/ceilinglight.js +316 -742
  15. package/dist/device/ceilinglight.js.map +1 -1
  16. package/dist/device/colorbulb.d.ts +15 -76
  17. package/dist/device/colorbulb.d.ts.map +1 -1
  18. package/dist/device/colorbulb.js +380 -833
  19. package/dist/device/colorbulb.js.map +1 -1
  20. package/dist/device/contact.d.ts +14 -66
  21. package/dist/device/contact.d.ts.map +1 -1
  22. package/dist/device/contact.js +267 -602
  23. package/dist/device/contact.js.map +1 -1
  24. package/dist/device/curtain.d.ts +18 -89
  25. package/dist/device/curtain.d.ts.map +1 -1
  26. package/dist/device/curtain.js +469 -897
  27. package/dist/device/curtain.js.map +1 -1
  28. package/dist/device/device.d.ts +76 -0
  29. package/dist/device/device.d.ts.map +1 -0
  30. package/dist/device/device.js +846 -0
  31. package/dist/device/device.js.map +1 -0
  32. package/dist/device/fan.d.ts +63 -0
  33. package/dist/device/fan.d.ts.map +1 -0
  34. package/dist/device/fan.js +645 -0
  35. package/dist/device/fan.js.map +1 -0
  36. package/dist/device/hub.d.ts +19 -58
  37. package/dist/device/hub.d.ts.map +1 -1
  38. package/dist/device/hub.js +304 -640
  39. package/dist/device/hub.js.map +1 -1
  40. package/dist/device/humidifier.d.ts +11 -66
  41. package/dist/device/humidifier.d.ts.map +1 -1
  42. package/dist/device/humidifier.js +300 -710
  43. package/dist/device/humidifier.js.map +1 -1
  44. package/dist/device/iosensor.d.ts +12 -64
  45. package/dist/device/iosensor.d.ts.map +1 -1
  46. package/dist/device/iosensor.js +225 -643
  47. package/dist/device/iosensor.js.map +1 -1
  48. package/dist/device/lightstrip.d.ts +12 -70
  49. package/dist/device/lightstrip.d.ts.map +1 -1
  50. package/dist/device/lightstrip.js +371 -742
  51. package/dist/device/lightstrip.js.map +1 -1
  52. package/dist/device/lock.d.ts +17 -63
  53. package/dist/device/lock.d.ts.map +1 -1
  54. package/dist/device/lock.js +309 -642
  55. package/dist/device/lock.js.map +1 -1
  56. package/dist/device/meter.d.ts +15 -64
  57. package/dist/device/meter.d.ts.map +1 -1
  58. package/dist/device/meter.js +223 -638
  59. package/dist/device/meter.js.map +1 -1
  60. package/dist/device/meterplus.d.ts +15 -65
  61. package/dist/device/meterplus.d.ts.map +1 -1
  62. package/dist/device/meterplus.js +216 -644
  63. package/dist/device/meterplus.js.map +1 -1
  64. package/dist/device/motion.d.ts +12 -69
  65. package/dist/device/motion.d.ts.map +1 -1
  66. package/dist/device/motion.js +209 -588
  67. package/dist/device/motion.js.map +1 -1
  68. package/dist/device/plug.d.ts +10 -57
  69. package/dist/device/plug.d.ts.map +1 -1
  70. package/dist/device/plug.js +141 -532
  71. package/dist/device/plug.js.map +1 -1
  72. package/dist/device/robotvacuumcleaner.d.ts +13 -63
  73. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  74. package/dist/device/robotvacuumcleaner.js +252 -609
  75. package/dist/device/robotvacuumcleaner.js.map +1 -1
  76. package/dist/device/waterdetector.d.ts +11 -63
  77. package/dist/device/waterdetector.d.ts.map +1 -1
  78. package/dist/device/waterdetector.js +179 -521
  79. package/dist/device/waterdetector.js.map +1 -1
  80. package/dist/homebridge-ui/public/index.html +22 -16
  81. package/dist/homebridge-ui/server.js +1 -1
  82. package/dist/homebridge-ui/server.js.map +1 -1
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +2 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/irdevice/airconditioner.d.ts +10 -50
  88. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  89. package/dist/irdevice/airconditioner.js +337 -482
  90. package/dist/irdevice/airconditioner.js.map +1 -1
  91. package/dist/irdevice/airpurifier.d.ts +8 -39
  92. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  93. package/dist/irdevice/airpurifier.js +108 -333
  94. package/dist/irdevice/airpurifier.js.map +1 -1
  95. package/dist/irdevice/camera.d.ts +7 -36
  96. package/dist/irdevice/camera.d.ts.map +1 -1
  97. package/dist/irdevice/camera.js +47 -299
  98. package/dist/irdevice/camera.js.map +1 -1
  99. package/dist/irdevice/fan.d.ts +7 -43
  100. package/dist/irdevice/fan.d.ts.map +1 -1
  101. package/dist/irdevice/fan.js +95 -364
  102. package/dist/irdevice/fan.js.map +1 -1
  103. package/dist/irdevice/irdevice.d.ts +46 -0
  104. package/dist/irdevice/irdevice.d.ts.map +1 -0
  105. package/dist/irdevice/irdevice.js +393 -0
  106. package/dist/irdevice/irdevice.js.map +1 -0
  107. package/dist/irdevice/light.d.ts +12 -45
  108. package/dist/irdevice/light.d.ts.map +1 -1
  109. package/dist/irdevice/light.js +121 -376
  110. package/dist/irdevice/light.js.map +1 -1
  111. package/dist/irdevice/other.d.ts +19 -48
  112. package/dist/irdevice/other.d.ts.map +1 -1
  113. package/dist/irdevice/other.js +441 -584
  114. package/dist/irdevice/other.js.map +1 -1
  115. package/dist/irdevice/tv.d.ts +8 -40
  116. package/dist/irdevice/tv.d.ts.map +1 -1
  117. package/dist/irdevice/tv.js +94 -353
  118. package/dist/irdevice/tv.js.map +1 -1
  119. package/dist/irdevice/vacuumcleaner.d.ts +7 -36
  120. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  121. package/dist/irdevice/vacuumcleaner.js +48 -299
  122. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  123. package/dist/irdevice/waterheater.d.ts +7 -36
  124. package/dist/irdevice/waterheater.d.ts.map +1 -1
  125. package/dist/irdevice/waterheater.js +50 -305
  126. package/dist/irdevice/waterheater.js.map +1 -1
  127. package/dist/platform.d.ts +22 -8
  128. package/dist/platform.d.ts.map +1 -1
  129. package/dist/platform.js +342 -191
  130. package/dist/platform.js.map +1 -1
  131. package/dist/settings.d.ts +66 -18
  132. package/dist/settings.d.ts.map +1 -1
  133. package/dist/settings.js +16 -552
  134. package/dist/settings.js.map +1 -1
  135. package/dist/utils.d.ts +95 -0
  136. package/dist/utils.d.ts.map +1 -1
  137. package/dist/utils.js +657 -1
  138. package/dist/utils.js.map +1 -1
  139. package/eslint.config.js +96 -0
  140. package/package.json +20 -16
  141. package/src/custom.d.ts +2 -1
  142. package/src/device/blindtilt.ts +488 -937
  143. package/src/device/bot.ts +907 -1016
  144. package/src/device/ceilinglight.ts +330 -798
  145. package/src/device/colorbulb.ts +394 -904
  146. package/src/device/contact.ts +298 -637
  147. package/src/device/curtain.ts +496 -954
  148. package/src/device/device.ts +872 -0
  149. package/src/device/fan.ts +692 -0
  150. package/src/device/hub.ts +338 -671
  151. package/src/device/humidifier.ts +330 -777
  152. package/src/device/iosensor.ts +258 -671
  153. package/src/device/lightstrip.ts +394 -809
  154. package/src/device/lock.ts +345 -700
  155. package/src/device/meter.ts +256 -666
  156. package/src/device/meterplus.ts +248 -672
  157. package/src/device/motion.ts +234 -622
  158. package/src/device/plug.ts +152 -572
  159. package/src/device/robotvacuumcleaner.ts +273 -653
  160. package/src/device/waterdetector.ts +198 -549
  161. package/src/homebridge-ui/public/index.html +22 -16
  162. package/src/homebridge-ui/server.ts +1 -1
  163. package/src/index.ts +4 -3
  164. package/src/irdevice/airconditioner.ts +368 -540
  165. package/src/irdevice/airpurifier.ts +134 -369
  166. package/src/irdevice/camera.ts +60 -324
  167. package/src/irdevice/fan.ts +111 -392
  168. package/src/irdevice/irdevice.ts +406 -0
  169. package/src/irdevice/light.ts +159 -425
  170. package/src/irdevice/other.ts +509 -661
  171. package/src/irdevice/tv.ts +123 -388
  172. package/src/irdevice/vacuumcleaner.ts +61 -324
  173. package/src/irdevice/waterheater.ts +63 -333
  174. package/src/platform.ts +395 -259
  175. package/src/settings.ts +120 -610
  176. package/src/utils.ts +661 -1
  177. package/src/device/waterdetector.json +0 -11
@@ -1,174 +1,155 @@
1
- import { request } from 'undici';
2
- import { sleep } from '../utils.js';
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * lock.ts: @switchbot/homebridge-switchbot.
4
+ */
5
+ import { deviceBase } from './device.js';
3
6
  import { interval, Subject } from 'rxjs';
4
- import { SwitchBotPlatform } from '../platform.js';
5
7
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { Service, PlatformAccessory, CharacteristicValue, API, Logging, HAP } from 'homebridge';
7
- import { device, devicesConfig, deviceStatus, Devices, serviceData, SwitchBotPlatformConfig } from '../settings.js';
8
-
9
- export class Lock {
10
- public readonly api: API;
11
- public readonly log: Logging;
12
- public readonly config!: SwitchBotPlatformConfig;
13
- protected readonly hap: HAP;
8
+
9
+ import type { SwitchBotPlatform } from '../platform.js';
10
+ import type { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
11
+ import type { device, devicesConfig, serviceData, deviceStatus } from '../settings.js';
12
+
13
+ export class Lock extends deviceBase {
14
14
  // Services
15
- lockService: Service;
16
- batteryService: Service;
17
- contactSensorService?: Service;
18
- latchButtonService?: Service;
19
-
20
- // Characteristic Values
21
- BatteryLevel!: CharacteristicValue;
22
- LockTargetState!: CharacteristicValue;
23
- LockCurrentState!: CharacteristicValue;
24
- FirmwareRevision!: CharacteristicValue;
25
- StatusLowBattery!: CharacteristicValue;
26
- ContactSensorState!: CharacteristicValue;
27
-
28
- // OpenAPI Status
29
- OpenAPI_BatteryLevel: deviceStatus['battery'];
30
- OpenAPI_FirmwareRevision: deviceStatus['version'];
31
- OpenAPI_LockCurrentState!: deviceStatus['lockState'];
32
- OpenAPI_ContactSensorState!: deviceStatus['doorState'];
33
-
34
- // BLE Status
35
- BLE_BatteryLevel: serviceData['battery'];
36
- BLE_LockCurrentState: serviceData['state'];
37
- BLE_Calibration: serviceData['calibration'];
38
- BLE_ContactSensorState: serviceData['door_open'];
39
-
40
- // BLE Others
41
- BLE_IsConnected?: boolean;
42
-
43
- // Config
44
- scanDuration!: number;
45
- deviceLogging!: string;
46
- deviceRefreshRate!: number;
15
+ private LockMechanism: {
16
+ Name: CharacteristicValue;
17
+ Service: Service;
18
+ LockTargetState: CharacteristicValue;
19
+ LockCurrentState: CharacteristicValue;
20
+ };
21
+
22
+ private Battery: {
23
+ Name: CharacteristicValue;
24
+ Service: Service;
25
+ BatteryLevel: CharacteristicValue;
26
+ StatusLowBattery: CharacteristicValue;
27
+ };
28
+
29
+ private ContactSensor?: {
30
+ Name: CharacteristicValue;
31
+ Service: Service;
32
+ ContactSensorState: CharacteristicValue;
33
+ };
34
+
35
+ private Switch?: {
36
+ Name: CharacteristicValue;
37
+ Service: Service;
38
+ On: CharacteristicValue;
39
+ };
47
40
 
48
41
  // Updates
49
42
  lockUpdateInProgress!: boolean;
50
43
  doLockUpdate!: Subject<void>;
51
44
 
52
- // Connection
53
- private readonly OpenAPI: boolean;
54
- private readonly BLE: boolean;
55
-
56
45
  constructor(
57
- private readonly platform: SwitchBotPlatform,
58
- private accessory: PlatformAccessory,
59
- public device: device & devicesConfig,
46
+ readonly platform: SwitchBotPlatform,
47
+ accessory: PlatformAccessory,
48
+ device: device & devicesConfig,
60
49
  ) {
61
- this.api = this.platform.api;
62
- this.log = this.platform.log;
63
- this.config = this.platform.config;
64
- this.hap = this.api.hap;
65
- // Connection
66
- this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
67
- this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
68
- // default placeholders
69
- this.deviceLogs(device);
70
- this.scan(device);
71
- this.refreshRate(device);
72
- this.deviceContext();
73
- this.deviceConfig(device);
74
-
50
+ super(platform, accessory, device);
75
51
  // this is subject we use to track when we need to POST changes to the SwitchBot API
76
52
  this.doLockUpdate = new Subject();
77
53
  this.lockUpdateInProgress = false;
78
54
 
79
- // Retrieve initial values and updateHomekit
80
- this.refreshStatus();
81
-
82
- // set accessory information
83
- accessory
84
- .getService(this.hap.Service.AccessoryInformation)!
85
- .setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
86
- .setCharacteristic(this.hap.Characteristic.Model, 'W1601700')
87
- .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId)
88
- .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.FirmwareRevision);
89
-
90
- // get the LockMechanism service if it exists, otherwise create a new LockMechanism service
91
- // you can create multiple services for each accessory
92
- const lockService = `${accessory.displayName} ${device.deviceType}`;
93
- (this.lockService = accessory.getService(this.hap.Service.LockMechanism)
94
- || accessory.addService(this.hap.Service.LockMechanism)), lockService;
95
-
96
- this.lockService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
97
- if (!this.lockService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
98
- this.lockService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
99
- }
100
-
101
- // each service must implement at-minimum the "required characteristics" for the given service type
102
- // see https://developers.homebridge.io/#/service/LockMechanism
103
-
104
-
105
- // create handlers for required characteristics
106
- this.lockService.getCharacteristic(this.hap.Characteristic.LockTargetState).onSet(this.LockTargetStateSet.bind(this));
107
-
108
-
109
- // Latch Button Service
110
- if (device.lock?.activate_latchbutton === false) { // remove the service when this variable is false
111
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Latch Button Service`);
112
- this.latchButtonService = accessory.getService(this.hap.Service.Switch);
113
- if (this.latchButtonService) {
114
- accessory.removeService(this.latchButtonService);
115
- this.latchButtonService = undefined; // Reset the service variable to undefined
116
- }
117
- } else
118
- if (!this.latchButtonService) {
119
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Adding Latch Button Service`);
120
- const latchServiceName = `${accessory.displayName} Latch`;
121
- this.latchButtonService = accessory.getService(this.hap.Service.Switch)
122
- || accessory.addService(this.hap.Service.Switch, latchServiceName, 'LatchButtonServiceIdentifier');
123
-
124
- this.latchButtonService.setCharacteristic(this.hap.Characteristic.Name, latchServiceName);
125
-
126
- if (!this.latchButtonService.testCharacteristic(this.hap.Characteristic.On)) {
127
- this.latchButtonService.addCharacteristic(this.hap.Characteristic.On);
128
- }
129
-
130
- this.latchButtonService.getCharacteristic(this.hap.Characteristic.On)
131
- .on('set', (value, callback) => {
132
- if (typeof value === 'boolean') {
133
- this.handleLatchCharacteristic(value, callback);
134
- } else {
135
- callback(new Error('Wrong characteristic value type'));
136
- }
137
- });
138
- } else {
139
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Latch Button Service already exists`);
140
- }
55
+ // Initialize LockMechanism Service
56
+ accessory.context.LockMechanism = accessory.context.LockMechanism ?? {};
57
+ this.LockMechanism = {
58
+ Name: accessory.context.LockMechanism.Name ?? accessory.displayName,
59
+ Service: accessory.getService(this.hap.Service.LockMechanism) ?? accessory.addService(this.hap.Service.LockMechanism) as Service,
60
+ LockTargetState: accessory.context.LockTargetState ?? this.hap.Characteristic.LockTargetState.SECURED,
61
+ LockCurrentState: accessory.context.LockCurrentState ?? this.hap.Characteristic.LockCurrentState.SECURED,
62
+ };
63
+ accessory.context.LockMechanism = this.LockMechanism as object;
64
+
65
+ // Initialize LockMechanism Characteristics
66
+ this.LockMechanism.Service
67
+ .setCharacteristic(this.hap.Characteristic.Name, this.LockMechanism.Name)
68
+ .getCharacteristic(this.hap.Characteristic.LockTargetState)
69
+ .onGet(() => {
70
+ return this.LockMechanism.LockTargetState;
71
+ })
72
+ .onSet(this.LockTargetStateSet.bind(this));
73
+
74
+ // Initialize Battery property
75
+ accessory.context.Battery = accessory.context.Battery ?? {};
76
+ this.Battery = {
77
+ Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
78
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
79
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
80
+ StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
81
+ };
82
+ accessory.context.Battery = this.Battery as object;
83
+
84
+ // Initialize Battery Characteristics
85
+ this.Battery.Service
86
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
87
+ .setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE)
88
+ .getCharacteristic(this.hap.Characteristic.BatteryLevel)
89
+ .onGet(() => {
90
+ return this.Battery.BatteryLevel;
91
+ });
141
92
 
93
+ this.Battery.Service
94
+ .getCharacteristic(this.hap.Characteristic.StatusLowBattery)
95
+ .onGet(() => {
96
+ return this.Battery.StatusLowBattery;
97
+ });
142
98
 
143
99
  // Contact Sensor Service
144
100
  if (device.lock?.hide_contactsensor) {
145
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Contact Sensor Service`);
146
- this.contactSensorService = this.accessory.getService(this.hap.Service.ContactSensor);
147
- accessory.removeService(this.contactSensorService!);
148
- } else if (!this.contactSensorService) {
149
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Contact Sensor Service`);
150
- const contactSensorService = `${accessory.displayName} Contact Sensor`;
151
- (this.contactSensorService = this.accessory.getService(this.hap.Service.ContactSensor)
152
- || this.accessory.addService(this.hap.Service.ContactSensor)), contactSensorService;
153
-
154
- this.contactSensorService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Contact Sensor`);
155
- if (!this.contactSensorService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
156
- this.contactSensorService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Contact Sensor`);
101
+ if (this.ContactSensor) {
102
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Contact Sensor Service`);
103
+ this.ContactSensor.Service = this.accessory.getService(this.hap.Service.ContactSensor) as Service;
104
+ accessory.removeService(this.ContactSensor.Service);
157
105
  }
158
106
  } else {
159
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Contact Sensor Service Not Added`);
107
+ accessory.context.ContactSensor = accessory.context.ContactSensor ?? {};
108
+ this.ContactSensor = {
109
+ Name: accessory.context.ContactSensor.Name ?? `${accessory.displayName} Contact Sensor`,
110
+ Service: accessory.getService(this.hap.Service.ContactSensor) ?? this.accessory.addService(this.hap.Service.ContactSensor) as Service,
111
+ ContactSensorState: accessory.context.ContactSensorState ?? this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED,
112
+ };
113
+ accessory.context.ContactSensor = this.ContactSensor as object;
114
+
115
+ // Initialize Contact Sensor Characteristics
116
+ this.ContactSensor.Service
117
+ .setCharacteristic(this.hap.Characteristic.Name, this.ContactSensor.Name)
118
+ .setCharacteristic(this.hap.Characteristic.StatusActive, true)
119
+ .getCharacteristic(this.hap.Characteristic.ContactSensorState)
120
+ .onGet(() => {
121
+ return this.ContactSensor!.ContactSensorState;
122
+ });
160
123
  }
161
124
 
162
- // Battery Service
163
- const batteryService = `${accessory.displayName} Battery`;
164
- (this.batteryService = this.accessory.getService(this.hap.Service.Battery)
165
- || accessory.addService(this.hap.Service.Battery)), batteryService;
166
-
167
- this.batteryService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Battery`);
168
- if (!this.batteryService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
169
- this.batteryService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Battery`);
125
+ // Initialize Latch Button Service
126
+ if (device.lock?.activate_latchbutton === false) {
127
+ if (this.Switch) {
128
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Latch Button Service`);
129
+ this.Switch.Service = accessory.getService(this.hap.Service.Switch) as Service;
130
+ accessory.removeService(this.Switch.Service);
131
+ }
132
+ } else {
133
+ accessory.context.Switch = accessory.context.Switch ?? {};
134
+ this.Switch = {
135
+ Name: accessory.context.Switch.Name ?? `${accessory.displayName} Latch`,
136
+ Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch) as Service,
137
+ On: accessory.context.On ?? false,
138
+ };
139
+ accessory.context.Switch = this.Switch as object;
140
+
141
+ // Initialize Latch Button Characteristics
142
+ this.Switch.Service
143
+ .setCharacteristic(this.hap.Characteristic.Name, this.Switch.Name)
144
+ .getCharacteristic(this.hap.Characteristic.On)
145
+ .onGet(() => {
146
+ return this.Switch!.On;
147
+ })
148
+ .onSet(this.OnSet.bind(this));
170
149
  }
171
- this.batteryService.setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
150
+
151
+ // Retrieve initial values and updateHomekit
152
+ this.refreshStatus();
172
153
 
173
154
  // Update Homekit
174
155
  this.updateHomeKitCharacteristics();
@@ -181,25 +162,7 @@ export class Lock {
181
162
  });
182
163
 
183
164
  //regisiter webhook event handler
184
- if (this.device.webhook) {
185
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
186
- this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
187
- try {
188
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
189
- const { lockState } = context;
190
- const { LockCurrentState } = this;
191
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
192
- '(lockState) = ' +
193
- `Webhook:(${lockState}), ` +
194
- `current:(${LockCurrentState})`);
195
- this.LockCurrentState = lockState === 'LOCKED' ? 1 : 0;
196
- this.updateHomeKitCharacteristics();
197
- } catch (e: any) {
198
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
199
- + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
200
- }
201
- };
202
- }
165
+ this.registerWebhook(accessory, device);
203
166
 
204
167
  // Watch for Lock change events
205
168
  // We put in a debounce of 100ms so we don't make duplicate calls
@@ -208,150 +171,105 @@ export class Lock {
208
171
  tap(() => {
209
172
  this.lockUpdateInProgress = true;
210
173
  }),
211
- debounceTime(this.platform.config.options!.pushRate! * 1000),
174
+ debounceTime(this.devicePushRate * 1000),
212
175
  )
213
176
  .subscribe(async () => {
214
177
  try {
215
178
  await this.pushChanges();
216
179
  } catch (e: any) {
217
180
  this.apiError(e);
218
- this.errorLog(
219
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,` +
220
- ` Error Message: ${JSON.stringify(e.message)}`,
221
- );
181
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
182
+ + ` Error Message: ${JSON.stringify(e.message)}`);
222
183
  }
223
184
  this.lockUpdateInProgress = false;
224
185
  });
225
186
  }
226
187
 
227
- /**
228
- * Method for handling the LatchCharacteristic
229
- */
230
- async handleLatchCharacteristic(value: boolean, callback) {
231
- this.debugLog(`handleLatchCharacteristic called with value: ${value}`);
232
-
233
- if (value) {
234
- this.debugLog('Attempting to open the latch');
235
-
236
- this.openAPIpushChanges(value).then(() => {
237
- this.debugLog('Latch opened successfully');
238
- this.debugLog(`LatchButtonService is: ${this.latchButtonService ? 'available' : 'not available'}`);
239
-
240
- // simulate button press to turn the switch back off
241
- if (this.latchButtonService) {
242
- const latchButtonService = this.latchButtonService;
243
- // Simulate a button press by waiting a short period before turning the switch off
244
- setTimeout(() => {
245
- latchButtonService.getCharacteristic(this.hap.Characteristic.On).updateValue(false);
246
- this.debugLog('Latch button switched off automatically.');
247
- }, 500); // 500 ms delay
248
- }
249
- callback(null);
250
- }).catch((error) => {
251
- // Log the error if the operation failed
252
- this.debugLog(`Error opening latch: ${error}`);
253
-
254
- // Ensure we turn the switch back off even in case of an error
255
- if (this.latchButtonService) {
256
- this.latchButtonService.getCharacteristic(this.hap.Characteristic.On).updateValue(false);
257
- this.debugLog('Latch button switched off after an error.');
258
- }
259
-
260
- callback(error);
261
- });
262
-
263
- } else {
264
- this.debugLog('Switch is off, nothing to do');
265
- callback(null);
266
- }
267
- }
268
-
269
-
270
- /**
271
- * Parse the device status from the SwitchBot api
272
- */
273
- async parseStatus(): Promise<void> {
274
- if (!this.device.enableCloudService && this.OpenAPI) {
275
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
276
- /* } else if (this.BLE) {
277
- await this.BLEparseStatus();*/
278
- } else if (this.OpenAPI && this.platform.config.credentials?.token) {
279
- await this.openAPIparseStatus();
280
- } else {
281
- await this.offlineOff();
282
- this.debugWarnLog(
283
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`,
284
- );
285
- }
286
- }
287
-
288
- async BLEparseStatus(): Promise<void> {
188
+ async BLEparseStatus(serviceData: serviceData): Promise<void> {
189
+ // BLE Status
289
190
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
290
- switch (this.BLE_LockCurrentState) {
191
+ switch (serviceData.status) {
291
192
  case 'locked':
292
- this.LockCurrentState = this.hap.Characteristic.LockCurrentState.SECURED;
293
- this.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
193
+ this.LockMechanism.LockCurrentState = this.hap.Characteristic.LockCurrentState.SECURED;
194
+ this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
294
195
  break;
295
196
  default:
296
- this.LockCurrentState = this.hap.Characteristic.LockCurrentState.UNSECURED;
297
- this.LockTargetState = this.hap.Characteristic.LockTargetState.UNSECURED;
197
+ this.LockMechanism.LockCurrentState = this.hap.Characteristic.LockCurrentState.UNSECURED;
198
+ this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.UNSECURED;
298
199
  }
299
- switch (this.BLE_ContactSensorState) {
300
- case 'opened':
301
- this.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
302
- break;
303
- default:
304
- this.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
200
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
201
+ + ` LockTargetState: ${this.LockMechanism.LockTargetState}, LockCurrentState: ${this.LockMechanism.LockCurrentState}`);
202
+
203
+ // Contact Sensor
204
+ if (!this.device.lock?.hide_contactsensor) {
205
+ switch (serviceData.door_open) {
206
+ case 'opened':
207
+ this.ContactSensor!.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
208
+ break;
209
+ default:
210
+ this.ContactSensor!.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
211
+ }
212
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensor!.ContactSensorState}`);
213
+
305
214
  }
306
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
307
215
  // Battery
308
- this.BatteryLevel = Number(this.BLE_BatteryLevel);
309
- if (this.BatteryLevel < 10) {
310
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
216
+ this.Battery.BatteryLevel = Number(serviceData.battery);
217
+ if (this.Battery.BatteryLevel < 10) {
218
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
311
219
  } else {
312
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
220
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
313
221
  }
314
- this.debugLog(
315
- `${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},` + ` StatusLowBattery: ${this.StatusLowBattery}`,
316
- );
222
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
223
+ + ` BatteryLevel: ${this.Battery.BatteryLevel}, StatusLowBattery: ${this.Battery.StatusLowBattery}`);
317
224
  }
318
225
 
319
- async openAPIparseStatus(): Promise<void> {
226
+ async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
320
227
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
321
- switch (this.OpenAPI_LockCurrentState) {
228
+ switch (deviceStatus.body.lockState) {
322
229
  case 'locked':
323
- this.LockCurrentState = this.hap.Characteristic.LockCurrentState.SECURED;
324
- this.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
230
+ this.LockMechanism.LockCurrentState = this.hap.Characteristic.LockCurrentState.SECURED;
231
+ this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
325
232
  break;
326
233
  default:
327
- this.LockCurrentState = this.hap.Characteristic.LockCurrentState.UNSECURED;
328
- this.LockTargetState = this.hap.Characteristic.LockTargetState.UNSECURED;
234
+ this.LockMechanism.LockCurrentState = this.hap.Characteristic.LockCurrentState.UNSECURED;
235
+ this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.UNSECURED;
329
236
  }
330
- switch (this.OpenAPI_ContactSensorState) {
237
+ switch (deviceStatus.body.doorState) {
331
238
  case 'opened':
332
- this.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
239
+ this.ContactSensor!.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
333
240
  break;
334
241
  default:
335
- this.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
242
+ this.ContactSensor!.ContactSensorState = this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED;
336
243
  }
337
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockTargetState}`);
244
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockMechanism.LockTargetState}`);
338
245
 
339
246
  // Battery
340
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
341
- if (this.BatteryLevel < 10) {
342
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
247
+ this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
248
+ if (this.Battery.BatteryLevel < 10) {
249
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
343
250
  } else {
344
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
251
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
345
252
  }
346
- if (Number.isNaN(this.BatteryLevel)) {
347
- this.BatteryLevel = 100;
253
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
254
+ this.Battery.BatteryLevel = 100;
348
255
  }
349
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
350
- + ` StatusLowBattery: ${this.StatusLowBattery}`);
256
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
257
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
351
258
 
352
- // FirmwareRevision
353
- this.FirmwareRevision = this.OpenAPI_FirmwareRevision!;
354
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
259
+ // Firmware Version
260
+ const version = deviceStatus.body.version?.toString();
261
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
262
+ if (deviceStatus.body.version) {
263
+ const deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
264
+ this.accessory
265
+ .getService(this.hap.Service.AccessoryInformation)!
266
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
267
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
268
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
269
+ .updateValue(deviceVersion);
270
+ this.accessory.context.deviceVersion = deviceVersion;
271
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
272
+ }
355
273
  }
356
274
 
357
275
  /**
@@ -366,134 +284,71 @@ export class Lock {
366
284
  await this.openAPIRefreshStatus();
367
285
  } else {
368
286
  await this.offlineOff();
369
- this.debugWarnLog(
370
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` +
371
- ` ${this.device.connectionType}, refreshStatus will not happen.`,
372
- );
287
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
288
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
373
289
  }
374
290
  }
375
291
 
376
292
  async BLERefreshStatus(): Promise<void> {
377
293
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
378
- const switchbot = await this.platform.connectBLE();
379
- // Convert to BLE Address
380
- this.device.bleMac = this.device
381
- .deviceId!.match(/.{1,2}/g)!
382
- .join(':')
383
- .toLowerCase();
384
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
385
- this.getCustomBLEAddress(switchbot);
294
+ const switchbot = await this.switchbotBLE();
295
+
296
+ if (switchbot === undefined) {
297
+ await this.BLERefreshConnection(switchbot);
298
+ } else {
386
299
  // Start to monitor advertisement packets
387
- (async () => {
300
+ (async () => {
388
301
  // Start to monitor advertisement packets
389
- await switchbot.startScan({
390
- model: 'o',
391
- id: this.device.bleMac,
392
- });
393
- // Set an event handler
394
- switchbot.onadvertisement = (ad: any) => {
395
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
396
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.serviceData.model}`);
397
- if (this.device.bleMac === ad.address && ad.serviceData.model === 'o') {
398
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
399
- this.BLE_BatteryLevel = ad.serviceData.battery;
400
- this.BLE_Calibration = ad.serviceData.calibration;
401
- this.BLE_LockCurrentState = ad.serviceData.status;
402
- this.BLE_ContactSensorState = ad.serviceData.door_open;
302
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
303
+ // Update HomeKit
304
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
305
+ await this.BLEparseStatus(serviceData);
306
+ await this.updateHomeKitCharacteristics();
403
307
  } else {
404
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
405
- }
406
- };
407
- // Wait 1 seconds
408
- await switchbot.wait(this.scanDuration * 1000);
409
- // Stop to monitor
410
- await switchbot.stopScan();
411
- // Update HomeKit
412
- await this.BLEparseStatus();
413
- await this.updateHomeKitCharacteristics();
414
- })();
415
- /*if (switchbot !== false) {
416
- switchbot
417
- .startScan({
418
- model: 'o',
419
- id: this.device.bleMac,
420
- })
421
- .then(async () => {
422
- // Set an event handler
423
- switchbot.onadvertisement = async (ad: ad) => {
424
- this.debugLog(
425
- `${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
426
- ` BLE Address Found: ${ad.address}`,
427
- );
428
- this.BLE_BatteryLevel = ad.serviceData.battery;
429
- this.BLE_Calibration = ad.serviceData.calibration;
430
- this.BLE_LockCurrentState = ad.serviceData.status;
431
- this.BLE_ContactSensorState = ad.serviceData.door_open;
432
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
433
- this.debugLog(
434
- `${this.device.deviceType}: ${this.accessory.displayName} battery: ${ad.serviceData.battery}, ` +
435
- `calibration: ${ad.serviceData.calibration}, status: ${ad.serviceData.status}, battery: ${ad.serviceData.battery}, ` +
436
- `door_open: ${ad.serviceData.door_open}`,
437
- );
438
-
439
- if (ad.serviceData) {
440
- this.BLE_IsConnected = true;
441
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
442
- await this.stopScanning(switchbot);
443
- } else {
444
- this.BLE_IsConnected = false;
445
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
446
- }
447
- };
448
- // Wait
449
- return await sleep(this.scanDuration * 1000);
450
- })
451
- .then(async () => {
452
- // Stop to monitor
453
- await this.stopScanning(switchbot);
454
- })
455
- .catch(async (e: any) => {
456
- this.apiError(e);
457
- this.errorLog(
458
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
459
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
460
- );
308
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
461
309
  await this.BLERefreshConnection(switchbot);
462
- });
463
- } else {
464
- await this.BLERefreshConnection(switchbot);
465
- }*/
310
+ }
311
+ })();
312
+ }
466
313
  }
467
314
 
468
315
  async openAPIRefreshStatus(): Promise<void> {
469
316
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
470
317
  try {
471
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
472
- headers: this.platform.generateHeaders(),
473
- });
474
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
318
+ const { body, statusCode } = await this.deviceRefreshStatus();
475
319
  const deviceStatus: any = await body.json();
476
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
477
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
320
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
478
321
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
479
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
480
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
481
- this.OpenAPI_LockCurrentState = deviceStatus.body.lockState;
482
- this.OpenAPI_ContactSensorState = deviceStatus.body.doorState;
483
- this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
484
- this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
485
- this.openAPIparseStatus();
486
- this.updateHomeKitCharacteristics();
322
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
323
+ await this.openAPIparseStatus(deviceStatus);
324
+ await this.updateHomeKitCharacteristics();
487
325
  } else {
488
- this.statusCode(statusCode);
489
- this.statusCode(deviceStatus.statusCode);
326
+ await this.statusCodes(statusCode, deviceStatus);
490
327
  }
491
328
  } catch (e: any) {
492
329
  this.apiError(e);
493
- this.errorLog(
494
- `${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}` +
495
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
496
- );
330
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
331
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
332
+ }
333
+ }
334
+
335
+ async registerWebhook(accessory: PlatformAccessory, device: device & devicesConfig) {
336
+ if (device.webhook) {
337
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
338
+ this.platform.webhookEventHandler[device.deviceId] = async (context) => {
339
+ try {
340
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
341
+ const { lockState } = context;
342
+ const { LockCurrentState } = this.LockMechanism;
343
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} (lockState) = Webhook:(${lockState}), current:(${LockCurrentState})`);
344
+ this.LockMechanism.LockCurrentState = lockState === 'LOCKED' ? 1 : 0;
345
+ this.updateHomeKitCharacteristics();
346
+ } catch (e: any) {
347
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
348
+ }
349
+ };
350
+ } else {
351
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
497
352
  }
498
353
  }
499
354
 
@@ -506,15 +361,14 @@ export class Lock {
506
361
  async pushChanges(): Promise<void> {
507
362
  if (!this.device.enableCloudService && this.OpenAPI) {
508
363
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
509
- /*} else if (this.BLE) {
510
- await this.BLEpushChanges();*/
364
+ } else if (this.BLE) {
365
+ await this.BLEpushChanges();
511
366
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
512
367
  await this.openAPIpushChanges();
513
368
  } else {
514
369
  await this.offlineOff();
515
- this.debugWarnLog(
516
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, pushChanges will not happen.`,
517
- );
370
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
371
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
518
372
  }
519
373
  // Refresh the status from the API
520
374
  interval(15000)
@@ -527,18 +381,12 @@ export class Lock {
527
381
 
528
382
  async BLEpushChanges(): Promise<void> {
529
383
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
530
- if (this.LockTargetState !== this.accessory.context.LockTargetState) {
531
- this.debugLog(
532
- `${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges LockTargetState: ${this.LockTargetState}` +
533
- ` LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
534
- );
384
+ if (this.LockMechanism.LockTargetState !== this.accessory.context.LockTargetState) {
385
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges LockTargetState: ${this.LockMechanism.LockTargetState}`
386
+ + ` LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
535
387
  const switchbot = await this.platform.connectBLE();
536
388
  // Convert to BLE Address
537
- this.device.bleMac = this.device
538
- .deviceId!.match(/.{1,2}/g)!
539
- .join(':')
540
- .toLowerCase();
541
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
389
+ await this.convertBLEAddress();
542
390
  switchbot
543
391
  .discover({
544
392
  model: '',
@@ -546,35 +394,33 @@ export class Lock {
546
394
  })
547
395
  .then(() => {
548
396
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
549
- this.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
397
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
398
+ + `LockTargetState: ${this.LockMechanism.LockTargetState} sent over BLE, sent successfully`);
399
+ this.LockMechanism.LockTargetState = this.hap.Characteristic.LockTargetState.SECURED;
550
400
  })
551
401
  .catch(async (e: any) => {
552
402
  this.apiError(e);
553
- this.errorLog(
554
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
555
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
556
- );
403
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
404
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
557
405
  await this.BLEPushConnection();
558
406
  });
559
407
  } else {
560
- this.debugLog(
561
- `${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` +
562
- `LockTargetState: ${this.LockTargetState}, ` +
563
- `LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
564
- );
408
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.`
409
+ + `LockTargetState: ${this.LockMechanism.LockTargetState}, `
410
+ + `LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
565
411
  }
566
412
  }
567
413
 
568
414
  async openAPIpushChanges(LatchUnlock?): Promise<void> {
569
415
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
570
416
 
571
- if ((this.LockTargetState !== this.accessory.context.LockTargetState) || LatchUnlock) {
417
+ if ((this.LockMechanism.LockTargetState !== this.accessory.context.LockTargetState) || LatchUnlock) {
572
418
  // Determine the command based on the LockTargetState or the forceUnlock parameter
573
419
  let command = '';
574
420
  if (LatchUnlock) {
575
421
  command = 'unlock';
576
422
  } else {
577
- command = this.LockTargetState ? 'lock' : 'unlock';
423
+ command = this.LockMechanism.LockTargetState ? 'lock' : 'unlock';
578
424
  }
579
425
  const bodyChange = JSON.stringify({
580
426
  command: `${command}`,
@@ -583,36 +429,24 @@ export class Lock {
583
429
  });
584
430
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
585
431
  try {
586
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
587
- body: bodyChange,
588
- method: 'POST',
589
- headers: this.platform.generateHeaders(),
590
- });
591
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
432
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
592
433
  const deviceStatus: any = await body.json();
593
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
594
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
595
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
434
+ await this.pushStatusCodes(statusCode, deviceStatus);
596
435
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
597
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
598
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
436
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
437
+ await this.updateHomeKitCharacteristics();
599
438
  } else {
600
- this.statusCode(statusCode);
601
- this.statusCode(deviceStatus.statusCode);
439
+ await this.statusCode(statusCode);
440
+ await this.statusCode(deviceStatus.statusCode);
602
441
  }
603
442
  } catch (e: any) {
604
443
  this.apiError(e);
605
- this.errorLog(
606
- `${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}` +
607
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
608
- );
444
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
445
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
609
446
  }
610
447
  } else {
611
- this.debugLog(
612
- `${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` +
613
- `LockTargetState: ${this.LockTargetState}, ` +
614
- `LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
615
- );
448
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges, LockTargetState: `
449
+ + `${this.LockMechanism.LockTargetState}, LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
616
450
  }
617
451
  }
618
452
 
@@ -620,81 +454,97 @@ export class Lock {
620
454
  * Handle requests to set the value of the "On" characteristic
621
455
  */
622
456
  async LockTargetStateSet(value: CharacteristicValue): Promise<void> {
623
- if (this.LockTargetState === this.accessory.context.LockTargetState) {
457
+ if (this.LockMechanism.LockTargetState === this.accessory.context.LockTargetState) {
624
458
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set LockTargetState: ${value}`);
625
459
  } else {
626
460
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
627
461
  }
628
462
 
629
- this.LockTargetState = value;
463
+ this.LockMechanism.LockTargetState = value;
464
+ this.doLockUpdate.next();
465
+ }
466
+
467
+ /**
468
+ * Handle requests to set the value of the "On" characteristic
469
+ */
470
+ async OnSet(value: CharacteristicValue): Promise<void> {
471
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Latch Button Set On: ${value}`);
472
+ if (value) {
473
+ this.debugLog('Attempting to open the latch');
474
+
475
+ this.openAPIpushChanges(value).then(() => {
476
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Latch opened successfully`);
477
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
478
+ + ` SwitchService is: ${this.Switch!.Service ? 'available' : 'not available'}`);
479
+
480
+ // simulate button press to turn the switch back off
481
+ if (this.Switch!.Service) {
482
+ const SwitchService = this.Switch!.Service;
483
+ // Simulate a button press by waiting a short period before turning the switch off
484
+ setTimeout(() => {
485
+ SwitchService.getCharacteristic(this.hap.Characteristic.On).updateValue(false);
486
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Latch button switched off automatically.`);
487
+ }, 500); // 500 ms delay
488
+ }
489
+ }).catch((e: any) => {
490
+ // Log the error if the operation failed
491
+ this.debugLog(`Error opening latch: ${e}`);
492
+ // Ensure we turn the switch back off even in case of an error
493
+ if (this.Switch!.Service) {
494
+ this.Switch!.Service.getCharacteristic(this.hap.Characteristic.On).updateValue(false);
495
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Latch button switched off after an error.`);
496
+ }
497
+ });
498
+ } else {
499
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch is off, nothing to do`);
500
+ }
501
+
502
+ this.Switch!.On = value;
630
503
  this.doLockUpdate.next();
631
504
  }
632
505
 
633
506
  async updateHomeKitCharacteristics(): Promise<void> {
634
507
  if (!this.device.lock?.hide_contactsensor) {
635
- if (this.ContactSensorState === undefined) {
636
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
508
+ if (this.ContactSensor!.ContactSensorState === undefined) {
509
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensor!.ContactSensorState}`);
637
510
  } else {
638
- this.accessory.context.ContactSensorState = this.ContactSensorState;
639
- this.contactSensorService?.updateCharacteristic(this.hap.Characteristic.ContactSensorState, this.ContactSensorState);
640
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic ContactSensorState: ${this.ContactSensorState}`);
511
+ this.accessory.context.ContactSensorState = this.ContactSensor!.ContactSensorState;
512
+ this.ContactSensor!.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState, this.ContactSensor!.ContactSensorState);
513
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
514
+ + ` ContactSensorState: ${this.ContactSensor!.ContactSensorState}`);
641
515
  }
642
516
  }
643
- if (this.LockTargetState === undefined) {
644
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockTargetState: ${this.LockTargetState}`);
517
+ if (this.LockMechanism.LockTargetState === undefined) {
518
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockTargetState: ${this.LockMechanism.LockTargetState}`);
645
519
  } else {
646
- this.accessory.context.LockTargetState = this.LockTargetState;
647
- this.lockService.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.LockTargetState);
648
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic LockTargetState: ${this.LockTargetState}`);
520
+ this.accessory.context.LockTargetState = this.LockMechanism.LockTargetState;
521
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.LockMechanism.LockTargetState);
522
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
523
+ + ` LockTargetState: ${this.LockMechanism.LockTargetState}`);
649
524
  }
650
- if (this.LockCurrentState === undefined) {
651
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockCurrentState: ${this.LockCurrentState}`);
525
+ if (this.LockMechanism.LockCurrentState === undefined) {
526
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LockCurrentState: ${this.LockMechanism.LockCurrentState}`);
652
527
  } else {
653
- this.accessory.context.LockCurrentState = this.LockCurrentState;
654
- this.lockService.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.LockCurrentState);
655
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic LockCurrentState: ${this.LockCurrentState}`);
528
+ this.accessory.context.LockCurrentState = this.LockMechanism.LockCurrentState;
529
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.LockMechanism.LockCurrentState);
530
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
531
+ + ` LockCurrentState: ${this.LockMechanism.LockCurrentState}`);
656
532
  }
657
- if (this.BatteryLevel === undefined) {
658
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
533
+ if (this.Battery.BatteryLevel === undefined) {
534
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
659
535
  } else {
660
- this.accessory.context.BatteryLevel = this.BatteryLevel;
661
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.BatteryLevel);
662
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
536
+ this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
537
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
538
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
539
+ + ` BatteryLevel: ${this.Battery.BatteryLevel}`);
663
540
  }
664
- if (this.StatusLowBattery === undefined) {
665
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
666
- } else {
667
- this.accessory.context.StatusLowBattery = this.StatusLowBattery;
668
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery);
669
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
670
- }
671
- }
672
-
673
- async stopScanning(switchbot: any) {
674
- switchbot.stopScan();
675
- if (this.BLE_IsConnected) {
676
- await this.BLEparseStatus();
677
- await this.updateHomeKitCharacteristics();
541
+ if (this.Battery.StatusLowBattery === undefined) {
542
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
678
543
  } else {
679
- await this.BLERefreshConnection(switchbot);
680
- }
681
- }
682
-
683
- async getCustomBLEAddress(switchbot: any) {
684
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
685
- (async () => {
686
- // Start to monitor advertisement packets
687
- await switchbot.startScan({
688
- model: 'c',
689
- });
690
- // Set an event handler
691
- switchbot.onadvertisement = (ad: any) => {
692
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
693
- };
694
- await sleep(10000);
695
- // Stop to monitor
696
- switchbot.stopScan();
697
- })();
544
+ this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
545
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
546
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
547
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
698
548
  }
699
549
  }
700
550
 
@@ -714,227 +564,22 @@ export class Lock {
714
564
  }
715
565
  }
716
566
 
717
- async scan(device: device & devicesConfig): Promise<void> {
718
- if (device.scanDuration) {
719
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
720
- if (this.BLE) {
721
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
722
- }
723
- } else {
724
- this.scanDuration = this.accessory.context.scanDuration = 1;
725
- if (this.BLE) {
726
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
727
- }
728
- }
729
- }
730
-
731
- async statusCode(statusCode: number): Promise<void> {
732
- switch (statusCode) {
733
- case 151:
734
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
735
- break;
736
- case 152:
737
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
738
- break;
739
- case 160:
740
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
741
- break;
742
- case 161:
743
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
744
- this.offlineOff();
745
- break;
746
- case 171:
747
- this.errorLog(
748
- `${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
749
- `Hub: ${this.device.hubDeviceId}`,
750
- );
751
- this.offlineOff();
752
- break;
753
- case 190:
754
- this.errorLog(
755
- `${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
756
- ` Or command format is invalid, statusCode: ${statusCode}`,
757
- );
758
- break;
759
- case 100:
760
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
761
- break;
762
- case 200:
763
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
764
- break;
765
- case 400:
766
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
767
- + `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
768
- break;
769
- case 401:
770
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
771
- + `but the request has not been authenticated, statusCode: ${statusCode}`);
772
- break;
773
- case 403:
774
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
775
- + `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
776
- break;
777
- case 404:
778
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
779
- + `statusCode: ${statusCode}`);
780
- break;
781
- case 406:
782
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
783
- + `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
784
- break;
785
- case 415:
786
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
787
- + `header that is not supported by the server, statusCode: ${statusCode}`);
788
- break;
789
- case 422:
790
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
791
- + `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
792
- break;
793
- case 429:
794
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
795
- + `requests allowed for a given time window, statusCode: ${statusCode}`);
796
- break;
797
- case 500:
798
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
799
- + `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
800
- break;
801
- default:
802
- this.infoLog(
803
- `${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
804
- `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`,
805
- );
806
- }
807
- }
808
-
809
567
  async offlineOff(): Promise<void> {
810
568
  if (this.device.offline) {
811
- await this.deviceContext();
812
- await this.updateHomeKitCharacteristics();
569
+ if (!this.device.lock?.hide_contactsensor) {
570
+ this.ContactSensor!.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState,
571
+ this.hap.Characteristic.ContactSensorState.CONTACT_DETECTED);
572
+ }
573
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
574
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
813
575
  }
814
576
  }
815
577
 
816
578
  async apiError(e: any): Promise<void> {
817
579
  if (!this.device.lock?.hide_contactsensor) {
818
- this.contactSensorService?.updateCharacteristic(this.hap.Characteristic.ContactSensorState, e);
819
- }
820
- this.lockService.updateCharacteristic(this.hap.Characteristic.LockTargetState, e);
821
- this.lockService.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e);
822
- }
823
-
824
- async deviceContext() {
825
- if (this.LockTargetState === undefined) {
826
- this.LockTargetState = false;
827
- } else {
828
- this.LockTargetState = this.accessory.context.On;
829
- }
830
- if (this.FirmwareRevision === undefined) {
831
- this.FirmwareRevision = this.platform.version;
832
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
833
- }
834
- }
835
-
836
- async refreshRate(device: device & devicesConfig): Promise<void> {
837
- if (device.refreshRate) {
838
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
839
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
840
- } else if (this.platform.config.options!.refreshRate) {
841
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
842
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
843
- }
844
- }
845
-
846
- async deviceConfig(device: device & devicesConfig): Promise<void> {
847
- let config = {};
848
- if (device.lock) {
849
- config = device.lock;
850
- }
851
- if (device.connectionType !== undefined) {
852
- config['connectionType'] = device.connectionType;
853
- }
854
- if (device.external !== undefined) {
855
- config['external'] = device.external;
856
- }
857
- if (device.logging !== undefined) {
858
- config['logging'] = device.logging;
859
- }
860
- if (device.refreshRate !== undefined) {
861
- config['refreshRate'] = device.refreshRate;
862
- }
863
- if (device.scanDuration !== undefined) {
864
- config['scanDuration'] = device.scanDuration;
865
- }
866
- if (device.webhook !== undefined) {
867
- config['webhook'] = device.webhook;
868
- }
869
- if (Object.entries(config).length !== 0) {
870
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
871
- }
872
- }
873
-
874
- async deviceLogs(device: device & devicesConfig): Promise<void> {
875
- if (this.platform.debugMode) {
876
- this.deviceLogging = this.accessory.context.logging = 'debugMode';
877
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
878
- } else if (device.logging) {
879
- this.deviceLogging = this.accessory.context.logging = device.logging;
880
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
881
- } else if (this.platform.config.options?.logging) {
882
- this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
883
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
884
- } else {
885
- this.deviceLogging = this.accessory.context.logging = 'standard';
886
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
887
- }
888
- }
889
-
890
- /**
891
- * Logging for Device
892
- */
893
- infoLog(...log: any[]): void {
894
- if (this.enablingDeviceLogging()) {
895
- this.platform.log.info(String(...log));
896
- }
897
- }
898
-
899
- warnLog(...log: any[]): void {
900
- if (this.enablingDeviceLogging()) {
901
- this.platform.log.warn(String(...log));
902
- }
903
- }
904
-
905
- debugWarnLog(...log: any[]): void {
906
- if (this.enablingDeviceLogging()) {
907
- if (this.deviceLogging?.includes('debug')) {
908
- this.platform.log.warn('[DEBUG]', String(...log));
909
- }
580
+ this.ContactSensor!.Service.updateCharacteristic(this.hap.Characteristic.ContactSensorState, e);
910
581
  }
911
- }
912
-
913
- errorLog(...log: any[]): void {
914
- if (this.enablingDeviceLogging()) {
915
- this.platform.log.error(String(...log));
916
- }
917
- }
918
-
919
- debugErrorLog(...log: any[]): void {
920
- if (this.enablingDeviceLogging()) {
921
- if (this.deviceLogging?.includes('debug')) {
922
- this.platform.log.error('[DEBUG]', String(...log));
923
- }
924
- }
925
- }
926
-
927
- debugLog(...log: any[]): void {
928
- if (this.enablingDeviceLogging()) {
929
- if (this.deviceLogging === 'debug') {
930
- this.platform.log.info('[DEBUG]', String(...log));
931
- } else {
932
- this.platform.log.debug(String(...log));
933
- }
934
- }
935
- }
936
-
937
- enablingDeviceLogging(): boolean {
938
- return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
582
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, e);
583
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e);
939
584
  }
940
585
  }