@switchbot/homebridge-switchbot 3.5.0-beta.23 → 3.5.0-beta.24

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