@switchbot/homebridge-switchbot 3.5.0-beta.7 → 3.5.0-beta.70

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