homebridge-ttlock-accesscode 2.0.0-beta.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"deviceManager.js","sourceRoot":"","sources":["../../src/devices/deviceManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deviceManager.js","sourceRoot":"","sources":["../../src/devices/deviceManager.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import type { Characteristic, CharacteristicValue, WithUUID } from 'homebridge';
2
- import type HomeKitDevice from './baseDevice.js';
3
2
  import type TTLockAccessCodePlatform from '../platform.js';
4
3
  export type TTLockDevice = Lock;
5
4
  export interface SysInfo {
@@ -31,14 +30,17 @@ export interface Passcode {
31
30
  }
32
31
  export interface DescriptorContext {
33
32
  platform: TTLockAccessCodePlatform;
34
- device: HomeKitDevice;
33
+ device: SysInfo;
34
+ alias: string;
35
35
  }
36
36
  export interface CharacteristicDescriptor {
37
37
  type: WithUUID<new () => Characteristic>;
38
38
  name?: string;
39
39
  writable?: boolean;
40
40
  syncGroup?: string;
41
- getInitial(context?: DescriptorContext): CharacteristicValue;
42
- getCurrent(context?: DescriptorContext): CharacteristicValue;
41
+ debouncePolls?: number;
42
+ syncHomeKitValueAfterSet?: boolean;
43
+ getInitial(context: DescriptorContext): CharacteristicValue;
44
+ getCurrent(context: DescriptorContext): CharacteristicValue;
43
45
  applySet?(value: CharacteristicValue, context: DescriptorContext): Promise<void | string>;
44
46
  }
@@ -11,6 +11,21 @@ export default class HomeKitDeviceLock extends HomeKitDevice {
11
11
  protected getServiceTypes(): WithUUID<typeof Service>[];
12
12
  protected buildDescriptors(service: Service): CharacteristicDescriptor[];
13
13
  private getAccessCodeSupportedConfiguration;
14
+ private getAccessCodeService;
15
+ private setLockBusy;
16
+ private ensurePasscodesLoaded;
17
+ private refreshPasscodes;
18
+ private getPasscodeIdentifier;
19
+ private encodePasscodeIdentifier;
20
+ private findPasscodeByIdentifier;
21
+ private buildPasscodeResponseRecord;
22
+ private parseOperationType;
23
+ private parseIdentifierRequest;
24
+ private parsePasscodeRequest;
25
+ private buildListResponse;
26
+ private buildReadResponse;
27
+ private buildAddResponse;
28
+ private buildDeleteResponse;
14
29
  private setAccessCodeControlPoint;
15
30
  private getConfigurationState;
16
31
  protected updateAllServicesAndCharacteristics(forceUpdate: boolean): Promise<void>;
@@ -2,6 +2,8 @@ import pkg from 'ber-tlv';
2
2
  import HomeKitDevice from './baseDevice.js';
3
3
  import { buildAccessCodeDescriptors, buildBatteryDescriptors, buildLockDescriptors, } from './descriptorHelpers.js';
4
4
  const { TlvFactory } = pkg;
5
+ class AccessCodeProtocolError extends Error {
6
+ }
5
7
  export default class HomeKitDeviceLock extends HomeKitDevice {
6
8
  ttlockDevice;
7
9
  hasPasscode;
@@ -26,7 +28,7 @@ export default class HomeKitDeviceLock extends HomeKitDevice {
26
28
  const C = this.platform.Characteristic;
27
29
  if (service.UUID === this.platform.Service.LockMechanism.UUID) {
28
30
  return buildLockDescriptors(C, async (value, context) => {
29
- await this.deviceManager.controlDevice(context.device.id, 'state', value);
31
+ await this.deviceManager.controlDevice(context.device.device_id, 'state', value);
30
32
  });
31
33
  }
32
34
  if (service.UUID === this.platform.Service.Battery.UUID) {
@@ -34,7 +36,7 @@ export default class HomeKitDeviceLock extends HomeKitDevice {
34
36
  }
35
37
  if (service.UUID === this.platform.Service.AccessCode.UUID) {
36
38
  return buildAccessCodeDescriptors(C, () => this.getAccessCodeSupportedConfiguration(), async (value, context) => {
37
- return await this.setAccessCodeControlPoint(context.device.ttlockDevice.sys_info, value);
39
+ return await this.setAccessCodeControlPoint(context.device, value);
38
40
  }, () => this.getConfigurationState());
39
41
  }
40
42
  return [];
@@ -53,129 +55,177 @@ export default class HomeKitDeviceLock extends HomeKitDevice {
53
55
  }
54
56
  return Buffer.concat(tlvBuffer).toString('base64') ?? 'AQEBAgEGAwEJBAEK';
55
57
  }
58
+ getAccessCodeService() {
59
+ return this.homebridgeAccessory.getService(this.platform.Service.AccessCode) ?? undefined;
60
+ }
61
+ setLockBusy(busy) {
62
+ this.lockBusy = busy;
63
+ const accessCodeService = this.getAccessCodeService();
64
+ if (accessCodeService) {
65
+ accessCodeService
66
+ .getCharacteristic(this.platform.Characteristic.ConfigurationState)
67
+ .updateValue(this.getConfigurationState());
68
+ }
69
+ }
70
+ async ensurePasscodesLoaded(device) {
71
+ if (Array.isArray(device.passcodes)) {
72
+ return device.passcodes;
73
+ }
74
+ device.passcodes = await this.deviceManager.managePasscodes(device.device_id, 'get');
75
+ return device.passcodes;
76
+ }
77
+ async refreshPasscodes(device) {
78
+ device.passcodes = await this.deviceManager.managePasscodes(device.device_id, 'get');
79
+ return device.passcodes;
80
+ }
81
+ getPasscodeIdentifier(passcode) {
82
+ return BigInt(passcode.index);
83
+ }
84
+ encodePasscodeIdentifier(identifier) {
85
+ let hex = identifier.toString(16);
86
+ if (hex.length % 2 !== 0) {
87
+ hex = `0${hex}`;
88
+ }
89
+ return hex;
90
+ }
91
+ findPasscodeByIdentifier(passcodes, identifier) {
92
+ return passcodes.find(passcode => this.getPasscodeIdentifier(passcode) === identifier);
93
+ }
94
+ buildPasscodeResponseRecord(passcode) {
95
+ const identifierValue = this.encodePasscodeIdentifier(this.getPasscodeIdentifier(passcode));
96
+ const identifier = TlvFactory.serialize(TlvFactory.primitiveTlv('01', identifierValue)).toString('hex');
97
+ const accessCode = TlvFactory.serialize(TlvFactory.primitiveTlv('02', Buffer.from(passcode.passcode).toString('hex'))).toString('hex');
98
+ const flags = TlvFactory.serialize(TlvFactory.primitiveTlv('03', '00')).toString('hex');
99
+ const status = TlvFactory.serialize(TlvFactory.primitiveTlv('04', '00')).toString('hex');
100
+ return TlvFactory.serialize(TlvFactory.primitiveTlv('03', identifier + accessCode + flags + status)).toString('hex');
101
+ }
102
+ parseOperationType(decodedTlv) {
103
+ if (decodedTlv.length === 0) {
104
+ throw new AccessCodeProtocolError('Empty AccessCodeControlPoint request');
105
+ }
106
+ return Number(decodedTlv[0].value.toString('hex'));
107
+ }
108
+ parseIdentifierRequest(element, requestType) {
109
+ const request = TlvFactory.parse(element.value);
110
+ if (request.length === 0) {
111
+ throw new AccessCodeProtocolError(`${requestType} request is missing its passcode index`);
112
+ }
113
+ const identifier = request[0].value.toString('hex');
114
+ if (!identifier) {
115
+ throw new AccessCodeProtocolError(`${requestType} request contained an empty passcode index`);
116
+ }
117
+ return BigInt(`0x${identifier}`);
118
+ }
119
+ parsePasscodeRequest(element) {
120
+ const request = TlvFactory.parse(element.value);
121
+ if (request.length === 0) {
122
+ throw new AccessCodeProtocolError('Add request is missing the passcode payload');
123
+ }
124
+ return request[0].value.toString();
125
+ }
126
+ async buildListResponse(device) {
127
+ const passcodes = await this.ensurePasscodesLoaded(device);
128
+ const records = passcodes.map(passcode => {
129
+ this.log.debug(`Passcode ${passcode.passcode} found on ${this.name}`);
130
+ return this.buildPasscodeResponseRecord(passcode);
131
+ });
132
+ return `010101${records.join('0000')}`;
133
+ }
134
+ async buildReadResponse(device, decodedTlv) {
135
+ const passcodes = await this.ensurePasscodesLoaded(device);
136
+ const records = decodedTlv.slice(1).map((element) => {
137
+ const passcodeIdentifier = this.parseIdentifierRequest(element, 'Read');
138
+ const passcode = this.findPasscodeByIdentifier(passcodes, passcodeIdentifier);
139
+ if (!passcode) {
140
+ throw new AccessCodeProtocolError(`Passcode identifier ${passcodeIdentifier.toString()} was not found for read`);
141
+ }
142
+ this.log.debug(`Reading passcode ${passcode.passcode} on ${this.name}`);
143
+ return this.buildPasscodeResponseRecord(passcode);
144
+ });
145
+ return `010102${records.join('0000')}`;
146
+ }
147
+ async buildAddResponse(device, decodedTlv) {
148
+ const records = [];
149
+ for (const element of decodedTlv.slice(1)) {
150
+ const newPassCode = this.parsePasscodeRequest(element);
151
+ const cachedPasscodes = await this.ensurePasscodesLoaded(device);
152
+ let passcode = cachedPasscodes.find(existing => existing.passcode === newPassCode);
153
+ if (!passcode) {
154
+ this.log.info(`Adding new passcode ${newPassCode} to ${this.name}`);
155
+ const newPasscode = await this.deviceManager
156
+ .managePasscodes(device.device_id, 'add', newPassCode);
157
+ const refreshedPasscodes = await this.refreshPasscodes(device);
158
+ passcode = refreshedPasscodes.find(existing => existing.passcode_id === newPasscode.keyboardPwdId.toString()
159
+ || existing.passcode === newPassCode);
160
+ }
161
+ else {
162
+ this.log.debug(`Passcode ${newPassCode} already exists on ${this.name}`);
163
+ }
164
+ if (!passcode) {
165
+ throw new AccessCodeProtocolError(`Passcode ${newPassCode} was not available after add`);
166
+ }
167
+ records.push(this.buildPasscodeResponseRecord(passcode));
168
+ }
169
+ return `010103${records.join('0000')}`;
170
+ }
171
+ async buildDeleteResponse(device, decodedTlv) {
172
+ if (decodedTlv.length < 2) {
173
+ throw new AccessCodeProtocolError('Delete request is missing the target passcode index');
174
+ }
175
+ const passcodes = await this.ensurePasscodesLoaded(device);
176
+ const deletePasscodeIdentifier = this.parseIdentifierRequest(decodedTlv[1], 'Delete');
177
+ const passcode = this.findPasscodeByIdentifier(passcodes, deletePasscodeIdentifier);
178
+ if (!passcode) {
179
+ throw new AccessCodeProtocolError(`Passcode identifier ${deletePasscodeIdentifier.toString()} was not found for delete`);
180
+ }
181
+ this.log.info(`Deleting passcode ${passcode.passcode} on ${this.name}`);
182
+ await this.deviceManager.managePasscodes(device.device_id, 'delete', passcode.passcode_id);
183
+ await this.refreshPasscodes(device);
184
+ return `010105${this.buildPasscodeResponseRecord(passcode)}`;
185
+ }
56
186
  async setAccessCodeControlPoint(device, value) {
187
+ this.setLockBusy(true);
57
188
  try {
58
- this.lockBusy = true;
59
- this.isUpdating = true;
60
189
  const decodedTlv = TlvFactory.parse(Buffer.from(String(value), 'base64').toString('hex'));
61
190
  this.log.debug(`Decoded TLV for AccessCodeControlPoint on ${this.name}:`, decodedTlv);
62
- let responseTlv = '';
63
- let response = '';
64
191
  let requestType = '';
65
- let identifier = '', accessCode = '', flags = '', status = '';
66
- switch (Number(decodedTlv[0].value.toString('hex'))) {
192
+ let responseTlv = '';
193
+ switch (this.parseOperationType(decodedTlv)) {
67
194
  case 1: {
68
195
  requestType = 'List';
69
- responseTlv = '010101';
70
- device.passcodes.forEach((pc, index) => {
71
- identifier = TlvFactory.serialize(TlvFactory.primitiveTlv('01', String(pc.index).padStart(2, '0'))).toString('hex');
72
- accessCode = TlvFactory.serialize(TlvFactory.primitiveTlv('02', Buffer.from(pc.passcode).toString('hex'))).toString('hex');
73
- flags = TlvFactory.serialize(TlvFactory.primitiveTlv('03', '00')).toString('hex');
74
- status = TlvFactory.serialize(TlvFactory.primitiveTlv('04', '00')).toString('hex');
75
- this.log.debug(`Passcode ${pc.passcode} found on ${this.name}`);
76
- responseTlv += TlvFactory.serialize(TlvFactory.primitiveTlv('03', identifier + accessCode + flags + status)).toString('hex') + (index !== (device.passcodes.length - 1) ? '0000' : '');
77
- });
78
- response = Buffer.from(responseTlv, 'hex').toString('base64');
196
+ responseTlv = await this.buildListResponse(device);
79
197
  break;
80
198
  }
81
199
  case 2: {
82
200
  requestType = 'Read';
83
- responseTlv = '010102';
84
- if (device.passcodes.length > 0) {
85
- for (let index = 1; index < decodedTlv.length; ++index) {
86
- const element = decodedTlv[index];
87
- const readReq = TlvFactory.parse(element.value);
88
- if (readReq.length > 0) {
89
- const passcodeIndexHex = readReq[0].value.toString('hex');
90
- const passcodeIndex = parseInt(passcodeIndexHex, 16);
91
- const pc = device.passcodes[passcodeIndex];
92
- if (pc) {
93
- this.log.debug(`Reading passcode ${pc.passcode} on ${this.name}`);
94
- identifier = TlvFactory.serialize(TlvFactory.primitiveTlv('01', String(pc.index).padStart(2, '0'))).toString('hex');
95
- accessCode = TlvFactory.serialize(TlvFactory.primitiveTlv('02', Buffer.from(pc.passcode).toString('hex'))).toString('hex');
96
- flags = TlvFactory.serialize(TlvFactory.primitiveTlv('03', '00')).toString('hex');
97
- status = TlvFactory.serialize(TlvFactory.primitiveTlv('04', '00')).toString('hex');
98
- }
99
- }
100
- responseTlv += TlvFactory.serialize(TlvFactory.primitiveTlv('03', identifier + accessCode + flags + status)).toString('hex') + (index !== (decodedTlv.length - 1) ? '0000' : '');
101
- }
102
- }
103
- response = Buffer.from(responseTlv, 'hex').toString('base64');
201
+ responseTlv = await this.buildReadResponse(device, decodedTlv);
104
202
  break;
105
203
  }
106
204
  case 3: {
107
205
  requestType = 'Add';
108
- responseTlv = '010103';
109
- for (let index = 1; index < decodedTlv.length; index++) {
110
- const addReq = TlvFactory.parse(decodedTlv[index].value);
111
- if (addReq.length > 0) {
112
- const newPassCodeHex = addReq[0];
113
- const newPassCode = newPassCodeHex.value.toString();
114
- let pc = device.passcodes.find(p => p.passcode === newPassCode);
115
- if (!pc) {
116
- this.log.info(`Adding new passcode ${newPassCode} to ${this.name}`);
117
- try {
118
- const newPc = await this.deviceManager
119
- .managePasscodes(device.device_id, 'add', newPassCode);
120
- device.passcodes = await this.deviceManager.managePasscodes(device.device_id, 'get');
121
- pc = device.passcodes.find((p) => p.passcode_id === newPc.keyboardPwdId.toString() ||
122
- p.passcode === newPassCode);
123
- }
124
- catch (err) {
125
- this.log.error(`Failed to add passcode ${newPassCode} to ${this.name}`, err);
126
- }
127
- }
128
- else {
129
- this.log.debug(`Passcode ${newPassCode} already exists on ${this.name}`);
130
- }
131
- if (pc) {
132
- identifier = TlvFactory.serialize(TlvFactory.primitiveTlv('01', String(pc.index).padStart(2, '0'))).toString('hex');
133
- accessCode = TlvFactory.serialize(TlvFactory.primitiveTlv('02', Buffer.from(pc.passcode).toString('hex'))).toString('hex');
134
- flags = TlvFactory.serialize(TlvFactory.primitiveTlv('03', '00')).toString('hex');
135
- status = TlvFactory.serialize(TlvFactory.primitiveTlv('04', '00')).toString('hex');
136
- responseTlv += TlvFactory.serialize(TlvFactory.primitiveTlv('03', identifier + accessCode + flags + status)).toString('hex') + (index !== (decodedTlv.length - 1) ? '0000' : '');
137
- }
138
- }
139
- }
140
- response = Buffer.from(responseTlv, 'hex').toString('base64');
206
+ responseTlv = await this.buildAddResponse(device, decodedTlv);
141
207
  break;
142
208
  }
143
209
  case 5: {
144
210
  requestType = 'Delete';
145
- responseTlv = '010105';
146
- const deleteReq = TlvFactory.parse(decodedTlv[1].value);
147
- if (deleteReq.length > 0) {
148
- const deletePassCodeIndexHex = deleteReq[0].value.toString('hex');
149
- const deletePassCodeIndex = parseInt(deletePassCodeIndexHex, 16);
150
- const pc = device.passcodes[deletePassCodeIndex];
151
- if (pc) {
152
- this.log.info(`Deleting passcode ${pc.passcode} on ${this.name}`);
153
- await this.deviceManager.managePasscodes(device.device_id, 'delete', pc.passcode_id);
154
- device.passcodes = await this.deviceManager.managePasscodes(device.device_id, 'get');
155
- identifier = TlvFactory.serialize(TlvFactory.primitiveTlv('01', String(pc.index).padStart(2, '0'))).toString('hex');
156
- accessCode = TlvFactory.serialize(TlvFactory.primitiveTlv('02', Buffer.from(pc.passcode).toString('hex'))).toString('hex');
157
- flags = TlvFactory.serialize(TlvFactory.primitiveTlv('03', '00')).toString('hex');
158
- status = TlvFactory.serialize(TlvFactory.primitiveTlv('04', '00')).toString('hex');
159
- responseTlv += TlvFactory.serialize(TlvFactory.primitiveTlv('03', identifier + accessCode + flags + status)).toString('hex');
160
- }
161
- }
162
- response = Buffer.from(responseTlv, 'hex').toString('base64');
211
+ responseTlv = await this.buildDeleteResponse(device, decodedTlv);
163
212
  break;
164
213
  }
214
+ default:
215
+ throw new AccessCodeProtocolError(`Unsupported AccessCodeControlPoint operation: ${this.parseOperationType(decodedTlv)}`);
165
216
  }
166
217
  this.log.info(`Access Code Control ${requestType} Request completed for ${this.name}`);
167
- return response;
218
+ return Buffer.from(responseTlv, 'hex').toString('base64');
168
219
  }
169
220
  catch (error) {
170
- this.log.error('Error processing AccessCodeControlPoint', error);
171
- this.ttlockDevice.offline = true;
172
- await this.stopPolling();
173
- return '';
221
+ if (error instanceof AccessCodeProtocolError) {
222
+ this.log.warn(`Invalid AccessCodeControlPoint request on ${this.name}: ${error.message}`);
223
+ return '';
224
+ }
225
+ throw error;
174
226
  }
175
227
  finally {
176
- this.lockBusy = false;
177
- this.isUpdating = false;
178
- this.updateEmitter.emit('updateComplete');
228
+ this.setLockBusy(false);
179
229
  }
180
230
  }
181
231
  getConfigurationState() {
@@ -1 +1 @@
1
- {"version":3,"file":"homekitLock.js","sourceRoot":"","sources":["../../src/devices/homekitLock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"homekitLock.js","sourceRoot":"","sources":["../../src/devices/homekitLock.ts"],"names":[],"mappings":"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"}
@@ -27,13 +27,16 @@ export default class TTLockAccessCodePlatform implements DynamicPlatformPlugin {
27
27
  taskQueue: TaskQueue;
28
28
  private readonly homekitDevicesById;
29
29
  private deviceDiscoveredHandler?;
30
+ private discoveryInterval?;
30
31
  private platformInitialization;
32
+ private usageTierChangedHandler?;
31
33
  constructor(log: Logging, config: PlatformConfig, api: API);
32
34
  private setupDeviceEventEmitter;
33
35
  initializePlatform(): Promise<void>;
34
36
  private logInitializationDetails;
35
37
  private verifyEnvironment;
36
38
  private didFinishLaunching;
39
+ private startTTLockApiWithRetry;
37
40
  private setupPeriodicDiscovery;
38
41
  private discoverDevices;
39
42
  private periodicDeviceDiscovery;
package/dist/platform.js CHANGED
@@ -26,7 +26,9 @@ export default class TTLockAccessCodePlatform {
26
26
  taskQueue;
27
27
  homekitDevicesById = new Map();
28
28
  deviceDiscoveredHandler;
29
+ discoveryInterval;
29
30
  platformInitialization;
31
+ usageTierChangedHandler;
30
32
  constructor(log, config, api) {
31
33
  this.log = log;
32
34
  this.api = api;
@@ -53,9 +55,16 @@ export default class TTLockAccessCodePlatform {
53
55
  if (!this.isShuttingDown) {
54
56
  this.isShuttingDown = true;
55
57
  }
58
+ if (this.discoveryInterval) {
59
+ clearInterval(this.discoveryInterval);
60
+ this.log.debug('Cleared periodic device discovery interval');
61
+ }
62
+ if (this.deviceDiscoveredHandler) {
63
+ deviceEventEmitter.off('deviceDiscovered', this.deviceDiscoveredHandler);
64
+ }
56
65
  this.log.debug('Stopping all polling tasks');
57
66
  for (const device of this.homekitDevicesById.values()) {
58
- await device.stopPolling();
67
+ await device.stopPolling(true);
59
68
  }
60
69
  this.log.debug('Waiting for tasks to complete');
61
70
  try {
@@ -64,7 +73,7 @@ export default class TTLockAccessCodePlatform {
64
73
  catch (error) {
65
74
  this.log.error('Error while waiting for task queue to empty during shutdown:', error);
66
75
  }
67
- this.stopTTLockApi();
76
+ await this.stopTTLockApi();
68
77
  });
69
78
  }
70
79
  setupDeviceEventEmitter(mode, discoveredDeviceIds) {
@@ -125,7 +134,11 @@ export default class TTLockAccessCodePlatform {
125
134
  async didFinishLaunching() {
126
135
  this.log.debug('Finished launching');
127
136
  try {
128
- await this.startTTLockApi();
137
+ const apiStarted = await this.startTTLockApiWithRetry();
138
+ if (!apiStarted) {
139
+ this.log.warn('TTLock API did not start before shutdown; skipping device manager startup');
140
+ return;
141
+ }
129
142
  this.log.debug('Initializing DeviceManager');
130
143
  this.deviceManager = new DeviceManager(this);
131
144
  this.log.debug('DeviceManager initialized');
@@ -138,6 +151,25 @@ export default class TTLockAccessCodePlatform {
138
151
  this.log.error('An error occurred during startup:', error);
139
152
  }
140
153
  }
154
+ async startTTLockApiWithRetry() {
155
+ let attempt = 0;
156
+ while (!this.isShuttingDown) {
157
+ try {
158
+ await this.startTTLockApi();
159
+ if (attempt > 0) {
160
+ this.log.info('TTLock API startup recovered after retries');
161
+ }
162
+ return true;
163
+ }
164
+ catch (error) {
165
+ attempt++;
166
+ const delayMs = Math.min(5 * 60 * 1000, Math.pow(2, Math.min(attempt, 8)) * 1000);
167
+ this.log.error(`TTLock API startup attempt ${attempt} failed; retrying in ${Math.floor(delayMs / 1000)}s:`, error);
168
+ await new Promise(resolve => setTimeout(resolve, delayMs));
169
+ }
170
+ }
171
+ return false;
172
+ }
141
173
  setupPeriodicDiscovery(discoveredDeviceIds) {
142
174
  this.log.debug('Setting up periodic device discovery');
143
175
  this.setupDeviceEventEmitter('periodicDiscovery', discoveredDeviceIds);
@@ -145,7 +177,7 @@ export default class TTLockAccessCodePlatform {
145
177
  await this.periodicDeviceDiscovery(discoveredDeviceIds);
146
178
  };
147
179
  const deferredDiscoveryTask = deferAndCombine(discoveryTask, this.config.advancedOptions.waitTimeUpdate);
148
- setInterval(() => {
180
+ this.discoveryInterval = setInterval(() => {
149
181
  try {
150
182
  this.taskQueue.addTask(deferredDiscoveryTask);
151
183
  }
@@ -190,6 +222,7 @@ export default class TTLockAccessCodePlatform {
190
222
  return;
191
223
  }
192
224
  this.periodicDeviceDiscovering = true;
225
+ let discoverySucceeded = false;
193
226
  discoveredDeviceIds.clear();
194
227
  this.log.debug('Cleared discoveredDeviceIds set before discovery.');
195
228
  try {
@@ -209,13 +242,19 @@ export default class TTLockAccessCodePlatform {
209
242
  this.log.debug('Error reserving budget for periodic discovery', error);
210
243
  }
211
244
  await this.deviceManager.discoverDevices();
245
+ discoverySucceeded = true;
212
246
  }
213
247
  }
214
248
  catch (error) {
215
249
  this.log.error('Error during periodic device discovery:', error);
216
250
  }
217
251
  finally {
218
- this.handleOfflineDevices(discoveredDeviceIds);
252
+ if (discoverySucceeded) {
253
+ this.handleOfflineDevices(discoveredDeviceIds);
254
+ }
255
+ else {
256
+ this.log.warn('Skipping offline accessory reconciliation because periodic discovery did not complete successfully');
257
+ }
219
258
  this.periodicDeviceDiscovering = false;
220
259
  this.periodicDeviceDiscoveryEmitter.emit('periodicDeviceDiscoveryComplete');
221
260
  this.log.debug('Finished periodic device discovery');
@@ -283,15 +322,18 @@ export default class TTLockAccessCodePlatform {
283
322
  const existingDevice = this.homekitDevicesById.get(device.sys_info.device_id);
284
323
  if (existingDevice) {
285
324
  if (!existingDevice.isUpdating) {
286
- if (existingDevice.ttlockDevice.offline && !device.offline) {
325
+ const comingOnline = existingDevice.ttlockDevice.offline && !device.offline;
326
+ existingDevice.ttlockDevice.sys_info = device.sys_info;
327
+ existingDevice.ttlockDevice.feature_info = device.feature_info;
328
+ existingDevice.ttlockDevice.last_seen = device.last_seen;
329
+ existingDevice.ttlockDevice.offline = device.offline;
330
+ if (comingOnline) {
287
331
  this.log.debug(`Device [${device.sys_info.device_id}] was offline and is now online. Updating and starting polling.`);
288
- existingDevice.ttlockDevice = device;
289
- existingDevice.updateAfterPeriodicDiscovery();
332
+ existingDevice.updateAfterPeriodicDiscovery(true);
290
333
  existingDevice.startPolling();
291
334
  }
292
335
  else {
293
336
  this.log.debug(`Updating existing HomeKit device [${device.sys_info.device_id}].`);
294
- existingDevice.ttlockDevice = device;
295
337
  existingDevice.updateAfterPeriodicDiscovery();
296
338
  }
297
339
  }
@@ -308,8 +350,12 @@ export default class TTLockAccessCodePlatform {
308
350
  await this.foundDevice(device);
309
351
  }
310
352
  updateAccessoryStatus(accessory, lastSeen, offline) {
353
+ const offlineStatusChanged = accessory.context.offline !== offline;
311
354
  accessory.context.lastSeen = lastSeen;
312
355
  accessory.context.offline = offline;
356
+ if (offlineStatusChanged) {
357
+ this.api.updatePlatformAccessories([accessory]);
358
+ }
313
359
  }
314
360
  async startTTLockApi() {
315
361
  this.log.debug('Starting TTLock API');
@@ -318,12 +364,21 @@ export default class TTLockAccessCodePlatform {
318
364
  this.log.debug('TTLock API process started successfully');
319
365
  }
320
366
  catch (error) {
367
+ await this.stopTTLockApi();
321
368
  this.log.error(`Error starting TTLock API process: ${error instanceof Error ? error.message : 'Unknown error'}`);
322
369
  throw error;
323
370
  }
324
371
  }
325
- stopTTLockApi() {
372
+ async stopTTLockApi() {
326
373
  this.log.debug('Stopping TTLock API');
374
+ if (this.usageTracker) {
375
+ if (this.usageTierChangedHandler) {
376
+ this.usageTracker.off('tierChanged', this.usageTierChangedHandler);
377
+ this.usageTierChangedHandler = undefined;
378
+ }
379
+ await this.usageTracker.stop();
380
+ this.usageTracker = undefined;
381
+ }
327
382
  if (this.ttLockApi) {
328
383
  this.log.debug('TTLock API process found, attempting to kill the process');
329
384
  this.ttLockApi = undefined;
@@ -340,14 +395,16 @@ export default class TTLockAccessCodePlatform {
340
395
  this.usageTracker = new UsageTracker(this.api, this.log, this.config.totalApiCallsPerMonth);
341
396
  await this.usageTracker.init();
342
397
  this.log.debug('UsageTracker initialized');
343
- this.usageTracker.on('tierChanged', () => {
398
+ this.usageTierChangedHandler = () => {
344
399
  this.log.info('API usage tier changed — recalculating polling intervals...');
345
400
  void this.reschedulePolling();
346
- });
401
+ };
402
+ this.usageTracker.on('tierChanged', this.usageTierChangedHandler);
347
403
  }
348
404
  catch (err) {
349
405
  this.log.error('Failed to initialize usage tracker', err);
350
406
  this.usageTracker = undefined;
407
+ this.usageTierChangedHandler = undefined;
351
408
  }
352
409
  this.log.debug('Initializing TTLockApi...');
353
410
  this.ttLockApi = new TTLockApi(this.log, this.config.clientId, this.config.clientSecret, this.usageTracker);
@@ -426,12 +483,12 @@ export default class TTLockAccessCodePlatform {
426
483
  if (!this.configuredAccessories.has(accessory.UUID)) {
427
484
  this.log.debug(`Platform Accessory ${accessory.displayName} is not in configuredAccessories, adding it.`);
428
485
  this.configuredAccessories.set(accessory.UUID, accessory);
486
+ this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
487
+ this.log.debug(`Platform Accessory ${accessory.displayName} registered with Homebridge.`);
429
488
  }
430
489
  else {
431
490
  this.log.debug(`Platform Accessory ${accessory.displayName} is already in configuredAccessories.`);
432
491
  }
433
- this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
434
- this.log.debug(`Platform Accessory ${accessory.displayName} registered with Homebridge.`);
435
492
  }
436
493
  configureAccessory(accessory) {
437
494
  this.log.debug(`Configuring Platform Accessory: [${accessory.displayName}] UUID: ${accessory.UUID}`);