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: don't create values for unsupported Door Lock CC features #5555

Merged
merged 1 commit into from
Mar 10, 2023
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ coverage/

# npm package files
zwave-js-*.tgz
zwave-js.tgz
.monopack/

# ZWave cache
*/cache
Expand Down
18 changes: 9 additions & 9 deletions packages/cc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4590,11 +4590,11 @@ export const DoorLockCCValues: Readonly<{
};
readonly options: {
readonly internal: false;
readonly minVersion: 1;
readonly secret: false;
readonly stateful: true;
readonly secret: false;
readonly minVersion: 1;
readonly supportsEndpoints: true;
readonly autoCreate: true;
readonly autoCreate: (applHost: ZWaveApplicationHost_2, endpoint: IZWaveEndpoint_2) => boolean;
};
};
doorSupported: {
Expand Down Expand Up @@ -4641,11 +4641,11 @@ export const DoorLockCCValues: Readonly<{
};
readonly options: {
readonly internal: false;
readonly minVersion: 1;
readonly secret: false;
readonly stateful: true;
readonly secret: false;
readonly minVersion: 1;
readonly supportsEndpoints: true;
readonly autoCreate: true;
readonly autoCreate: (applHost: ZWaveApplicationHost_2, endpoint: IZWaveEndpoint_2) => boolean;
};
};
boltSupported: {
Expand Down Expand Up @@ -4692,11 +4692,11 @@ export const DoorLockCCValues: Readonly<{
};
readonly options: {
readonly internal: false;
readonly minVersion: 1;
readonly secret: false;
readonly stateful: true;
readonly secret: false;
readonly minVersion: 1;
readonly supportsEndpoints: true;
readonly autoCreate: true;
readonly autoCreate: (applHost: ZWaveApplicationHost_2, endpoint: IZWaveEndpoint_2) => boolean;
};
};
latchSupported: {
Expand Down
94 changes: 67 additions & 27 deletions packages/cc/src/cc/DoorLockCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
CommandClasses,
Duration,
enumValuesToMetadataStates,
IZWaveEndpoint,
Maybe,
MessageOrCCLogEntry,
MessagePriority,
Expand Down Expand Up @@ -169,25 +170,76 @@ export const DoorLockCCValues = Object.freeze({
),

...V.staticProperty("latchSupported", undefined, { internal: true }),
...V.staticProperty("latchStatus", {
...ValueMetadata.ReadOnly,
label: "Current status of the latch",
} as const),
...V.staticProperty(
"latchStatus",
{
...ValueMetadata.ReadOnly,
label: "Current status of the latch",
} as const,
{
autoCreate: shouldAutoCreateLatchStatusValue,
} as const,
),

...V.staticProperty("boltSupported", undefined, { internal: true }),
...V.staticProperty("boltStatus", {
...ValueMetadata.ReadOnly,
label: "Current status of the bolt",
} as const),
...V.staticProperty(
"boltStatus",
{
...ValueMetadata.ReadOnly,
label: "Current status of the bolt",
} as const,
{
autoCreate: shouldAutoCreateBoltStatusValue,
} as const,
),

...V.staticProperty("doorSupported", undefined, { internal: true }),
...V.staticProperty("doorStatus", {
...ValueMetadata.ReadOnly,
label: "Current status of the door",
} as const),
...V.staticProperty(
"doorStatus",
{
...ValueMetadata.ReadOnly,
label: "Current status of the door",
} as const,
{
autoCreate: shouldAutoCreateDoorStatusValue,
} as const,
),
}),
});

function shouldAutoCreateLatchStatusValue(
applHost: ZWaveApplicationHost,
endpoint: IZWaveEndpoint,
): boolean {
const valueDB = applHost.tryGetValueDB(endpoint.nodeId);
if (!valueDB) return false;
return !!valueDB.getValue(
DoorLockCCValues.latchSupported.endpoint(endpoint.index),
);
}

function shouldAutoCreateBoltStatusValue(
applHost: ZWaveApplicationHost,
endpoint: IZWaveEndpoint,
): boolean {
const valueDB = applHost.tryGetValueDB(endpoint.nodeId);
if (!valueDB) return false;
return !!valueDB.getValue(
DoorLockCCValues.boltSupported.endpoint(endpoint.index),
);
}

function shouldAutoCreateDoorStatusValue(
applHost: ZWaveApplicationHost,
endpoint: IZWaveEndpoint,
): boolean {
const valueDB = applHost.tryGetValueDB(endpoint.nodeId);
if (!valueDB) return false;
return !!valueDB.getValue(
DoorLockCCValues.doorSupported.endpoint(endpoint.index),
);
}

const configurationSetParameters = [
"operationType",
"outsideHandlesCanOpenDoorConfiguration",
Expand Down Expand Up @@ -536,35 +588,23 @@ supports block to block: ${resp.blockToBlockSupported}`;
if (!hadCriticalTimeout) {
// Save support information for the status values
const doorStatusValue = DoorLockCCValues.doorStatus;
this.setMetadata(
applHost,
doorStatusValue,
doorSupported ? doorStatusValue.meta : undefined,
);
if (doorSupported) this.setMetadata(applHost, doorStatusValue);
this.setValue(
applHost,
DoorLockCCValues.doorSupported,
doorSupported,
);

const latchStatusValue = DoorLockCCValues.latchStatus;
this.setMetadata(
applHost,
latchStatusValue,
latchSupported ? latchStatusValue.meta : undefined,
);
if (latchSupported) this.setMetadata(applHost, latchStatusValue);
this.setValue(
applHost,
DoorLockCCValues.latchSupported,
latchSupported,
);

const boltStatusValue = DoorLockCCValues.boltStatus;
this.setMetadata(
applHost,
boltStatusValue,
boltSupported ? boltStatusValue.meta : undefined,
);
if (boltSupported) this.setMetadata(applHost, boltStatusValue);
this.setValue(
applHost,
DoorLockCCValues.boltSupported,
Expand Down
26 changes: 15 additions & 11 deletions packages/cc/src/lib/CommandClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,17 @@ export class CommandClass implements ICommandClass {
);
}

private shouldAutoCreateValue(
applHost: ZWaveApplicationHost,
value: StaticCCValue,
): boolean {
return (
value.options.autoCreate === true ||
(typeof value.options.autoCreate === "function" &&
value.options.autoCreate(applHost, this.getEndpoint(applHost)!))
);
}

/** Returns a list of all value names that are defined for this CommandClass */
public getDefinedValueIDs(applHost: ZWaveApplicationHost): ValueID[] {
// In order to compare value ids, we need them to be strings
Expand Down Expand Up @@ -769,16 +780,7 @@ export class CommandClass implements ICommandClass {
if (value.options.internal) continue;

// And determine if this value should be automatically "created"
if (
value.options.autoCreate === false ||
(typeof value.options.autoCreate === "function" &&
!value.options.autoCreate(
applHost,
this.getEndpoint(applHost)!,
))
) {
continue;
}
if (!this.shouldAutoCreateValue(applHost, value)) continue;

existingValueIds.push(value.endpoint(this.endpointIndex));
}
Expand Down Expand Up @@ -858,7 +860,9 @@ export class CommandClass implements ICommandClass {
// ... but only if the value is included in the report we are persisting
(sourceValue != undefined ||
// ... or if we know which CC version the node supports
this._knownVersion >= value.options.minVersion);
// and the value may be automatically created
(this._knownVersion >= value.options.minVersion &&
this.shouldAutoCreateValue(applHost, value)));

if (createMetadata && !valueDB.hasMetadata(valueId)) {
valueDB.setMetadata(valueId, value.meta);
Expand Down