homebridge-zwave-usb 1.2.3 → 1.2.6

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.
@@ -14,7 +14,7 @@ class ControllerAccessory {
14
14
  this.platform = platform;
15
15
  this.controller = controller;
16
16
  const homeId = this.controller.homeId;
17
- const uuid = this.platform.api.hap.uuid.generate(`ZWaveController-${homeId}`);
17
+ const uuid = this.platform.api.hap.uuid.generate(`homebridge-zwave-usb-controller-${homeId}`);
18
18
  const existingAccessory = this.platform.accessories.find((accessory) => accessory.UUID === uuid);
19
19
  if (existingAccessory) {
20
20
  this.platformAccessory = existingAccessory;
@@ -25,6 +25,11 @@ class ControllerAccessory {
25
25
  this.platform.api.registerPlatformAccessories('homebridge-zwave-usb', 'ZWaveUSB', [this.platformAccessory]);
26
26
  this.platform.accessories.push(this.platformAccessory);
27
27
  }
28
+ // Set accessory information
29
+ this.platformAccessory.getService(this.platform.Service.AccessoryInformation)
30
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Aeotec / Z-Wave JS')
31
+ .setCharacteristic(this.platform.Characteristic.Model, 'Z-Wave USB Controller')
32
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, homeId?.toString() || 'Unknown');
28
33
  this.inclusionService =
29
34
  this.platformAccessory.getService('Inclusion Mode') ||
30
35
  this.platformAccessory.addService(this.platform.Service.Switch, 'Inclusion Mode', 'Inclusion');
@@ -24,6 +24,13 @@ class ZWaveAccessory {
24
24
  this.platform.api.registerPlatformAccessories('homebridge-zwave-usb', 'ZWaveUSB', [this.platformAccessory]);
25
25
  this.platform.accessories.push(this.platformAccessory);
26
26
  }
27
+ // Set accessory information
28
+ const manufacturer = this.node.deviceConfig?.manufacturer || 'Unknown';
29
+ const model = this.node.deviceConfig?.label || `Node ${this.node.nodeId}`;
30
+ this.platformAccessory.getService(this.platform.Service.AccessoryInformation)
31
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, manufacturer)
32
+ .setCharacteristic(this.platform.Characteristic.Model, model)
33
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, `Node ${this.node.nodeId}`);
27
34
  }
28
35
  addFeature(feature) {
29
36
  this.features.push(feature);
@@ -1,6 +1,7 @@
1
1
  import { BaseFeature } from './ZWaveFeature';
2
2
  export declare class MultilevelSwitchFeature extends BaseFeature {
3
3
  private service;
4
+ private lastKnownBrightness;
4
5
  init(): void;
5
6
  update(): void;
6
7
  private handleGetOn;
@@ -4,6 +4,7 @@ exports.MultilevelSwitchFeature = void 0;
4
4
  const ZWaveFeature_1 = require("./ZWaveFeature");
5
5
  class MultilevelSwitchFeature extends ZWaveFeature_1.BaseFeature {
6
6
  service;
7
+ lastKnownBrightness = 0;
7
8
  init() {
8
9
  const subType = this.endpoint.index.toString();
9
10
  this.service = this.getService(this.platform.Service.Lightbulb, undefined, subType);
@@ -25,13 +26,15 @@ class MultilevelSwitchFeature extends ZWaveFeature_1.BaseFeature {
25
26
  if (typeof value === 'number') {
26
27
  const isOn = value > 0;
27
28
  this.service.updateCharacteristic(this.platform.Characteristic.On, isOn);
28
- if (isOn && value <= 99) {
29
- // Brightness in Z-Wave is 0-99, in HomeKit 0-100
29
+ if (value <= 99) {
30
+ this.lastKnownBrightness = value;
30
31
  this.service.updateCharacteristic(this.platform.Characteristic.Brightness, value);
31
32
  }
32
- else if (isOn && value === 255) {
33
+ else if (value === 255 && isOn) {
33
34
  // 255 = restore previous level
34
- // We don't necessarily know the previous level, so we leave it as is or default to 100
35
+ // Use our tracked brightness, default to 100 if unknown
36
+ const brightness = this.lastKnownBrightness > 0 ? this.lastKnownBrightness : 100;
37
+ this.service.updateCharacteristic(this.platform.Characteristic.Brightness, brightness);
35
38
  }
36
39
  }
37
40
  }
@@ -68,18 +68,31 @@ class ZWaveUsbPlatform {
68
68
  for (const acc of this.zwaveAccessories.values()) {
69
69
  managedUuids.add(acc.platformAccessory.UUID);
70
70
  }
71
- const orphaned = this.accessories.filter(acc => !managedUuids.has(acc.UUID));
71
+ this.log.debug(`Reconciliation: ${managedUuids.size} managed accessories, ${this.accessories.length} in cache.`);
72
+ const orphaned = this.accessories.filter(acc => {
73
+ const isOrphaned = !managedUuids.has(acc.UUID);
74
+ if (isOrphaned) {
75
+ this.log.info(`Found orphaned accessory in cache: ${acc.displayName} (${acc.UUID})`);
76
+ }
77
+ return isOrphaned;
78
+ });
72
79
  if (orphaned.length > 0) {
73
80
  this.log.info(`Removing ${orphaned.length} orphaned accessories from cache...`);
74
- this.api.unregisterPlatformAccessories('homebridge-zwave-usb', 'ZWaveUSB', orphaned);
75
- for (const orphan of orphaned) {
76
- const index = this.accessories.indexOf(orphan);
77
- if (index !== -1) {
78
- this.accessories.splice(index, 1);
81
+ try {
82
+ this.api.unregisterPlatformAccessories('homebridge-zwave-usb', 'ZWaveUSB', orphaned);
83
+ for (const orphan of orphaned) {
84
+ const index = this.accessories.indexOf(orphan);
85
+ if (index !== -1) {
86
+ this.accessories.splice(index, 1);
87
+ }
79
88
  }
89
+ this.log.info('Successfully removed orphaned accessories.');
90
+ }
91
+ catch (err) {
92
+ this.log.error('Failed to unregister orphaned accessories:', err);
80
93
  }
81
94
  }
82
- }, 5000);
95
+ }, 10000);
83
96
  }
84
97
  catch (err) {
85
98
  this.log.error('Failed to connect to Z-Wave controller:', err);
@@ -90,6 +103,10 @@ class ZWaveUsbPlatform {
90
103
  }
91
104
  handleNodeReady(node) {
92
105
  this.log.info(`Node ${node.nodeId} ready`);
106
+ if (!node.ready) {
107
+ this.log.warn(`Node ${node.nodeId} reported ready but node.ready is false, skipping...`);
108
+ return;
109
+ }
93
110
  const homeId = this.zwaveController?.homeId;
94
111
  if (!homeId) {
95
112
  this.log.error(`Cannot create accessory for Node ${node.nodeId} - Home ID not available`);
@@ -32,27 +32,11 @@ class ZWaveController extends events_1.EventEmitter {
32
32
  securityKeys.S2_AccessControl = Buffer.from(this.options.securityKeys.S2_AccessControl, 'hex');
33
33
  }
34
34
  }
35
- // Redirect Z-Wave JS logs to Homebridge
36
- const customLogTransport = {
37
- log: (info, next) => {
38
- const message = info.message || info;
39
- const label = info.label ? `[${info.label}] ` : '';
40
- const output = `${label}${message}`;
41
- if (this.options.debug || info.level === 'error' || info.level === 'warn') {
42
- this.log.info(`[Z-Wave JS] ${output}`);
43
- }
44
- else {
45
- this.log.debug(`[Z-Wave JS] ${output}`);
46
- }
47
- if (next) {
48
- next();
49
- }
50
- }
51
- };
35
+ // Z-Wave JS logging configuration - use default console logging to avoid winston compatibility issues
36
+ // Custom logging can be added in future if needed
52
37
  const logConfig = {
53
38
  enabled: true,
54
39
  level: this.options.debug ? 'debug' : 'info',
55
- transports: [customLogTransport] // eslint-disable-line @typescript-eslint/no-explicit-any
56
40
  };
57
41
  const storagePath = this.options.storagePath || process.cwd();
58
42
  this.driver = new zwave_js_1.Driver(this.serialPort, {
@@ -190,6 +174,12 @@ class ZWaveController extends events_1.EventEmitter {
190
174
  if (listeners) {
191
175
  node.off('ready', listeners.ready);
192
176
  node.off('value updated', listeners.value);
177
+ if (listeners.interviewStageCompleted) {
178
+ node.off('interview stage completed', listeners.interviewStageCompleted);
179
+ }
180
+ if (listeners.interviewFailed) {
181
+ node.off('interview failed', listeners.interviewFailed);
182
+ }
193
183
  }
194
184
  }
195
185
  this.nodeListeners.clear();
@@ -17,6 +17,7 @@ export interface IZWaveNode {
17
17
  name?: string;
18
18
  deviceConfig?: {
19
19
  label?: string;
20
+ manufacturer?: string;
20
21
  };
21
22
  ready: boolean;
22
23
  interviewStage: unknown;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-zwave-usb",
3
3
  "displayName": "Z-Wave USB",
4
- "version": "1.2.3",
4
+ "version": "1.2.6",
5
5
  "description": "A Homebridge dynamic platform plugin for Z-Wave USB controllers using zwave-js.",
6
6
  "repository": {
7
7
  "type": "git",