From 19e2766aa684e72a48c1c2501dd5bb88bc2a07f9 Mon Sep 17 00:00:00 2001 From: Dominic Griesel Date: Tue, 1 Dec 2020 17:31:30 +0100 Subject: [PATCH 1/2] fix: auto-fallback to no supervision for start/stopLevelChange --- .../lib/commandclass/MultilevelSwitchCC.ts | 91 ++++++++++++++----- 1 file changed, 67 insertions(+), 24 deletions(-) diff --git a/packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts b/packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts index 045e6988f6c0..362820539cb8 100644 --- a/packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts +++ b/packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts @@ -31,6 +31,7 @@ import { CommandClass, commandClass, CommandClassDeserializationOptions, + CommandClassOptions, expectedCCResponse, gotDeserializationOptions, implementedVersion, @@ -98,6 +99,14 @@ function getCurrentValueValueID(endpoint: number): ValueID { }; } +/** Returns the ValueID used to remember whether a node supports supervision on the start/stop level change commands*/ +export function getSuperviseStartStopLevelChangeValueId(): ValueID { + return { + commandClass: CommandClasses["Multilevel Switch"], + property: "superviseStartStopLevelChange", + }; +} + @API(CommandClasses["Multilevel Switch"]) export class MultilevelSwitchCCAPI extends CCAPI { public supportsCommand(cmd: MultilevelSwitchCommand): Maybe { @@ -195,20 +204,33 @@ export class MultilevelSwitchCCAPI extends CCAPI { ...options, }); - // Try to supervise the command execution - const supervisionResult = await this.driver.trySendCommandSupervised( - cc, - ); + const superviseValueId = getSuperviseStartStopLevelChangeValueId(); + const node = this.endpoint.getNodeUnsafe()!; + // Assume supervision is supported until we know it is not + let mayUseSupervision = node.getValue(superviseValueId) !== false; - if ( - supervisionResult && - (supervisionResult.status === SupervisionStatus.Fail || - supervisionResult.status === SupervisionStatus.NoSupport) - ) { - throw new ZWaveError( - "startLevelChange failed", - ZWaveErrorCodes.SupervisionCC_CommandFailed, + if (mayUseSupervision) { + // Try to supervise the command execution + const supervisionResult = await this.driver.trySendCommandSupervised( + cc, ); + + if (supervisionResult?.status === SupervisionStatus.Fail) { + throw new ZWaveError( + "startLevelChange failed", + ZWaveErrorCodes.SupervisionCC_CommandFailed, + ); + } else if ( + supervisionResult?.status === SupervisionStatus.NoSupport + ) { + // Remember that we shouldn't use supervision for that + node.valueDB.setValue(superviseValueId, false); + mayUseSupervision = false; + } + } + // In order to support a fallback to no supervision, we must not use else-if here + if (!mayUseSupervision) { + await this.driver.sendCommand(cc); } } @@ -223,20 +245,33 @@ export class MultilevelSwitchCCAPI extends CCAPI { endpoint: this.endpoint.index, }); - // Try to supervise the command execution - const supervisionResult = await this.driver.trySendCommandSupervised( - cc, - ); + const superviseValueId = getSuperviseStartStopLevelChangeValueId(); + const node = this.endpoint.getNodeUnsafe()!; + // Assume supervision is supported until we know it is not + let mayUseSupervision = node.getValue(superviseValueId) !== false; - if ( - supervisionResult && - (supervisionResult.status === SupervisionStatus.Fail || - supervisionResult.status === SupervisionStatus.NoSupport) - ) { - throw new ZWaveError( - "stopLevelChange failed", - ZWaveErrorCodes.SupervisionCC_CommandFailed, + if (mayUseSupervision) { + // Try to supervise the command execution + const supervisionResult = await this.driver.trySendCommandSupervised( + cc, ); + + if (supervisionResult?.status === SupervisionStatus.Fail) { + throw new ZWaveError( + "stopLevelChange failed", + ZWaveErrorCodes.SupervisionCC_CommandFailed, + ); + } else if ( + supervisionResult?.status === SupervisionStatus.NoSupport + ) { + // Remember that we shouldn't use supervision for that + node.valueDB.setValue(superviseValueId, false); + mayUseSupervision = false; + } + } + // In order to support a fallback to no supervision, we must not use else-if here + if (!mayUseSupervision) { + await this.driver.sendCommand(cc); } } @@ -318,6 +353,14 @@ export class MultilevelSwitchCCAPI extends CCAPI { export class MultilevelSwitchCC extends CommandClass { declare ccCommand: MultilevelSwitchCommand; + public constructor(driver: Driver, options: CommandClassOptions) { + super(driver, options); + this.registerValue( + getSuperviseStartStopLevelChangeValueId().property, + true, + ); + } + public async interview(complete: boolean = true): Promise { const node = this.getNode()!; const endpoint = this.getEndpoint()!; From 40d0c355d3d14f1abd7c5a57814a1d5d403f1489 Mon Sep 17 00:00:00 2001 From: Dominic Griesel Date: Tue, 1 Dec 2020 17:56:12 +0100 Subject: [PATCH 2/2] refactor: don't export --- packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts b/packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts index 362820539cb8..37dce081b15b 100644 --- a/packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts +++ b/packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts @@ -100,7 +100,7 @@ function getCurrentValueValueID(endpoint: number): ValueID { } /** Returns the ValueID used to remember whether a node supports supervision on the start/stop level change commands*/ -export function getSuperviseStartStopLevelChangeValueId(): ValueID { +function getSuperviseStartStopLevelChangeValueId(): ValueID { return { commandClass: CommandClasses["Multilevel Switch"], property: "superviseStartStopLevelChange",