Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: auto-fallback to no supervision for start/stopLevelChange #1178

Merged
merged 2 commits into from
Dec 2, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 67 additions & 24 deletions packages/zwave-js/src/lib/commandclass/MultilevelSwitchCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
CommandClass,
commandClass,
CommandClassDeserializationOptions,
CommandClassOptions,
expectedCCResponse,
gotDeserializationOptions,
implementedVersion,
Expand Down Expand Up @@ -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*/
function getSuperviseStartStopLevelChangeValueId(): ValueID {
return {
commandClass: CommandClasses["Multilevel Switch"],
property: "superviseStartStopLevelChange",
};
}

@API(CommandClasses["Multilevel Switch"])
export class MultilevelSwitchCCAPI extends CCAPI {
public supportsCommand(cmd: MultilevelSwitchCommand): Maybe<boolean> {
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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<void> {
const node = this.getNode()!;
const endpoint = this.getEndpoint()!;
Expand Down