diff --git a/api/lib/ZwaveClient.ts b/api/lib/ZwaveClient.ts index 55953aa8358..c84e132b79d 100644 --- a/api/lib/ZwaveClient.ts +++ b/api/lib/ZwaveClient.ts @@ -294,6 +294,20 @@ const observedCCProps: { }) }, }, + [CommandClasses['Node Naming and Location']]: { + name(node, value) { + this.setNodeName(node.id, value.value).catch((error) => { + logger.error(`Error while setting node name: ${error.message}`) + }) + }, + location(node, value) { + this.setNodeLocation(node.id, value.value).catch((error) => { + logger.error( + `Error while setting node location: ${error.message}`, + ) + }) + }, + }, } export type SensorTypeScale = { @@ -2462,7 +2476,9 @@ class ZwaveClient extends TypedEventEmitter { if (zwaveNode && node) { node.name = name - zwaveNode.name = name + if (zwaveNode.name !== name) { + zwaveNode.name = name + } } else { throw Error('Invalid Node ID') } @@ -2489,7 +2505,9 @@ class ZwaveClient extends TypedEventEmitter { if (node) { node.loc = loc - zwaveNode.location = loc + if (zwaveNode.location !== loc) { + zwaveNode.location = loc + } } else { throw Error('Invalid Node ID') } @@ -5350,7 +5368,7 @@ class ZwaveClient extends TypedEventEmitter { if (zwaveNode.ready) { const res = this._addValue(zwaveNode, args) - if (res.valueId) { + if (res?.valueId) { const node = this._nodes.get(zwaveNode.id) this.subscribeObservers(node, res.valueId) } @@ -6088,6 +6106,14 @@ class ZwaveClient extends TypedEventEmitter { if (!node) { logger.info(`ValueAdded: no such node: ${zwaveNode.id} error`) } else { + // ignore node name and location CC, we already show the inputs for it + if ( + zwaveValue.commandClass === + CommandClasses['Node Naming and Location'] + ) { + return null + } + const zwaveValueMeta = zwaveNode.getValueMetadata(zwaveValue) const valueId = this._parseValue( @@ -6200,42 +6226,63 @@ class ZwaveClient extends TypedEventEmitter { const valueId = node.values[vID] - if (valueId) { - // this is set when the updates comes from a write request - if (valueId.toUpdate) { - valueId.toUpdate = false + if (!valueId) { + // node name and location emit a value update but + // there could be no defined valueId as not all nodes + // support that CC but zwave-js does, also we ignore it + // on `_valueAdded`. Ref: (https://github.com/zwave-js/zwave-js-ui/issues/3591) + if ( + args.commandClass === + CommandClasses['Node Naming and Location'] + ) { + const prop = args.property + const observer = + observedCCProps[ + CommandClasses['Node Naming and Location'] + ]?.[prop] + + if (observer) { + observer.call(this, node, { + ...args, + value: args.newValue, + }) + } } - let newValue = args.newValue - if (Buffer.isBuffer(newValue)) { - // encode Buffers as HEX strings - newValue = utils.buffer2hex(newValue) - } + return + } - let prevValue = args.prevValue - if (Buffer.isBuffer(prevValue)) { - // encode Buffers as HEX strings - prevValue = utils.buffer2hex(prevValue) - } + // this is set when the updates comes from a write request + if (valueId.toUpdate) { + valueId.toUpdate = false + } - valueId.value = newValue - valueId.stateless = !!args.stateless + let newValue = args.newValue + if (Buffer.isBuffer(newValue)) { + // encode Buffers as HEX strings + newValue = utils.buffer2hex(newValue) + } - if (this.valuesObservers[valueId.id]) { - this.valuesObservers[valueId.id].call(this, node, valueId) - } + let prevValue = args.prevValue + if (Buffer.isBuffer(prevValue)) { + // encode Buffers as HEX strings + prevValue = utils.buffer2hex(prevValue) + } - // ensure duration is never undefined - if ( - valueId.type === 'duration' && - valueId.value === undefined - ) { - valueId.value = new Duration(undefined, 'seconds') - } + valueId.value = newValue + valueId.stateless = !!args.stateless - if (!skipUpdate) { - this.emitValueChanged(valueId, node, prevValue !== newValue) - } + if (this.valuesObservers[valueId.id]) { + this.valuesObservers[valueId.id].call(this, node, valueId) + } + + // ensure duration is never undefined + if (valueId.type === 'duration' && valueId.value === undefined) { + valueId.value = new Duration(undefined, 'seconds') + } + + if (!skipUpdate) { + this.emitValueChanged(valueId, node, prevValue !== newValue) } // if valueId is stateless, automatically reset the value after 1 sec