homebridge-zwave-usb 2.0.2 → 2.0.4

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.
@@ -304,14 +304,20 @@ class ControllerAccessory {
304
304
  this.exclusionService.updateCharacteristic(this.platform.Characteristic.On, false);
305
305
  },
306
306
  'heal network progress': (progress) => {
307
- const done = Array.from(progress.values()).filter((v) => v !== 0).length;
307
+ const doneCount = Array.from(progress.values()).filter((v) => v !== 0).length;
308
308
  const total = progress.size;
309
- this.statusChar.updateValue(`Heal: ${done}/${total}`);
309
+ this.statusChar.updateValue(`Heal: ${doneCount}/${total}`);
310
+ // Safety: If we hit 100%, and the 'done' event hasn't fired yet, we'll wait for it.
311
+ // But if it stays at 100% and we are still 'active', the 'heal network done' handler will take care of it.
310
312
  },
311
313
  'heal network done': () => {
312
- this.platform.log.info('Controller event: Heal Network Done');
314
+ this.platform.log.info('Controller event: Heal Network Done. Resetting UI switch.');
313
315
  this.isHealActive = false;
314
- this.healService.updateCharacteristic(this.platform.Characteristic.On, false);
316
+ // Use a slight delay to ensure HomeKit UI catches the state change correctly
317
+ setTimeout(() => {
318
+ this.healService.updateCharacteristic(this.platform.Characteristic.On, false);
319
+ this.platform.log.debug('Heal Network switch set to OFF');
320
+ }, 500);
315
321
  },
316
322
  };
317
323
  for (const [event, handler] of Object.entries(this.handlers)) {
@@ -393,7 +399,6 @@ class ControllerAccessory {
393
399
  */
394
400
  this.platform.log.warn('Inclusion start request returned false (possibly already active). Keeping UI state ON.');
395
401
  }
396
- this.isInclusionActive = true;
397
402
  this.inclusionTimer = setTimeout(async () => {
398
403
  this.platform.log.info('Inclusion Mode timed out');
399
404
  await this.controller.stopInclusion();
@@ -444,7 +449,6 @@ class ControllerAccessory {
444
449
  if (!started) {
445
450
  this.platform.log.warn('Exclusion start request returned false (possibly already active). Keeping UI state ON.');
446
451
  }
447
- this.isExclusionActive = true;
448
452
  this.exclusionTimer = setTimeout(async () => {
449
453
  this.platform.log.info('Exclusion Mode timed out');
450
454
  await this.controller.stopExclusion();
@@ -490,7 +494,6 @@ class ControllerAccessory {
490
494
  if (!started) {
491
495
  this.platform.log.warn('Heal start request returned false (possibly already active). Keeping UI state ON.');
492
496
  }
493
- this.isHealActive = true;
494
497
  }
495
498
  else {
496
499
  this.platform.log.info('Requesting Heal Network OFF');
@@ -25,6 +25,7 @@ export declare class ZWaveController extends EventEmitter implements IZWaveContr
25
25
  private driver;
26
26
  readonly nodes: Map<number, ZWaveNode>;
27
27
  private pendingS2Pin;
28
+ private healSafetyTimer;
28
29
  private nodeListeners;
29
30
  private controllerListeners;
30
31
  constructor(log: Logger, serialPort: string, options?: ZWaveControllerOptions);
@@ -19,6 +19,7 @@ class ZWaveController extends events_1.EventEmitter {
19
19
  driver;
20
20
  nodes = new Map();
21
21
  pendingS2Pin;
22
+ healSafetyTimer;
22
23
  nodeListeners = new Map();
23
24
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
25
  controllerListeners = {};
@@ -75,9 +76,24 @@ class ZWaveController extends events_1.EventEmitter {
75
76
  this.log.info(`Heal Network Progress: ${done}/${total} nodes completed`);
76
77
  this.emit('status updated', `Heal: ${done}/${total}`);
77
78
  this.emit('heal network progress', progress);
79
+ // Safety: if we are at 100%, but no 'done' event arrives within 5s, auto-complete
80
+ if (done === total && total > 0) {
81
+ if (this.healSafetyTimer) {
82
+ clearTimeout(this.healSafetyTimer);
83
+ }
84
+ this.healSafetyTimer = setTimeout(() => {
85
+ this.log.info('Heal Network Safety Timeout: Triggering completion.');
86
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
87
+ (this.driver?.controller).emit('rebuild routes done', new Map());
88
+ }, 5000);
89
+ }
78
90
  },
79
91
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
80
92
  'rebuild routes done': (result) => {
93
+ if (this.healSafetyTimer) {
94
+ clearTimeout(this.healSafetyTimer);
95
+ this.healSafetyTimer = undefined;
96
+ }
81
97
  this.log.info('Heal Network Complete');
82
98
  this.emit('status updated', 'Heal Network Done');
83
99
  setTimeout(() => this.emit('status updated', 'Driver Ready'), 5000);
@@ -465,6 +481,10 @@ class ZWaveController extends events_1.EventEmitter {
465
481
  }
466
482
  async stop() {
467
483
  this.log.debug('Stopping Z-Wave controller and cleaning up listeners...');
484
+ if (this.healSafetyTimer) {
485
+ clearTimeout(this.healSafetyTimer);
486
+ this.healSafetyTimer = undefined;
487
+ }
468
488
  for (const [nodeId, node] of this.nodes) {
469
489
  const listeners = this.nodeListeners.get(nodeId);
470
490
  if (listeners) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-zwave-usb",
3
3
  "displayName": "Homebridge Z-Wave USB",
4
- "version": "2.0.2",
4
+ "version": "2.0.4",
5
5
  "description": "A Homebridge dynamic platform plugin for Z-Wave USB controllers using zwave-js.",
6
6
  "license": "Polyform-Noncommercial-1.0.0",
7
7
  "funding": {