Skip to content

Commit

Permalink
feat(cc): implement sending Z-Wave+ CC reports, respond to Get (zwave…
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone authored May 10, 2022
1 parent d65a7b3 commit 6704313
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 38 deletions.
6 changes: 6 additions & 0 deletions docs/api/CCs/ZWavePlus.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@
```ts
async get(): Promise<Pick<ZWavePlusCCReport, "zwavePlusVersion" | "nodeType" | "roleType" | "installerIcon" | "userIcon"> | undefined>;
```

### `sendReport`

```ts
async sendReport(options: ZWavePlusCCReportOptions): Promise<void>;
```
104 changes: 67 additions & 37 deletions packages/zwave-js/src/lib/commandclass/ZWavePlusCC.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import type { Maybe, MessageOrCCLogEntry, ValueID } from "@zwave-js/core";
import { CommandClasses, validatePayload } from "@zwave-js/core";
import { getEnumMemberName, num2hex, pick } from "@zwave-js/shared";
import { validateArgs } from "@zwave-js/transformers";
import type { Driver } from "../driver/Driver";
import { MessagePriority } from "../message/Constants";
import { PhysicalCCAPI } from "./API";
import {
API,
CCCommand,
CCCommandOptions,
ccValue,
CommandClass,
commandClass,
CommandClassDeserializationOptions,
expectedCCResponse,
gotDeserializationOptions,
implementedVersion,
} from "./CommandClass";
import {
Expand Down Expand Up @@ -68,6 +71,7 @@ export class ZWavePlusCCAPI extends PhysicalCCAPI {
public supportsCommand(cmd: ZWavePlusCommand): Maybe<boolean> {
switch (cmd) {
case ZWavePlusCommand.Get:
case ZWavePlusCommand.Report:
return true; // This is mandatory
}
return super.supportsCommand(cmd);
Expand Down Expand Up @@ -95,6 +99,18 @@ export class ZWavePlusCCAPI extends PhysicalCCAPI {
]);
}
}

@validateArgs()
public async sendReport(options: ZWavePlusCCReportOptions): Promise<void> {
this.assertSupportsCommand(ZWavePlusCommand, ZWavePlusCommand.Report);

const cc = new ZWavePlusCCReport(this.driver, {
nodeId: this.endpoint.nodeId,
endpoint: this.endpoint.index,
...options,
});
await this.driver.sendCommand(cc, this.commandOptions);
}
}

@commandClass(CommandClasses["Z-Wave Plus Info"])
Expand Down Expand Up @@ -141,68 +157,82 @@ user icon: ${num2hex(zwavePlusResponse.userIcon)}`;
}
}

export interface ZWavePlusCCReportOptions {
zwavePlusVersion: number;
nodeType: ZWavePlusNodeType;
roleType: ZWavePlusRoleType;
installerIcon: number;
userIcon: number;
}

@CCCommand(ZWavePlusCommand.Report)
export class ZWavePlusCCReport extends ZWavePlusCC {
public constructor(
driver: Driver,
options: CommandClassDeserializationOptions,
options:
| CommandClassDeserializationOptions
| (CCCommandOptions & ZWavePlusCCReportOptions),
) {
super(driver, options);

validatePayload(this.payload.length >= 7);
this._zwavePlusVersion = this.payload[0];
this._roleType = this.payload[1];
this._nodeType = this.payload[2];
this._installerIcon = this.payload.readUInt16BE(3);
this._userIcon = this.payload.readUInt16BE(5);
this.persistValues();
if (gotDeserializationOptions(options)) {
validatePayload(this.payload.length >= 7);
this.zwavePlusVersion = this.payload[0];
this.roleType = this.payload[1];
this.nodeType = this.payload[2];
this.installerIcon = this.payload.readUInt16BE(3);
this.userIcon = this.payload.readUInt16BE(5);
this.persistValues();
} else {
this.zwavePlusVersion = options.zwavePlusVersion;
this.roleType = options.roleType;
this.nodeType = options.nodeType;
this.installerIcon = options.installerIcon;
this.userIcon = options.userIcon;
}
}

private _zwavePlusVersion: number;
@ccValue({ internal: true })
public get zwavePlusVersion(): number {
return this._zwavePlusVersion;
}

private _nodeType: ZWavePlusNodeType;
public zwavePlusVersion: number;
@ccValue({ internal: true })
public get nodeType(): ZWavePlusNodeType {
return this._nodeType;
}

private _roleType: ZWavePlusRoleType;
public nodeType: ZWavePlusNodeType;
@ccValue({ internal: true })
public get roleType(): ZWavePlusRoleType {
return this._roleType;
}

private _installerIcon: number;
public roleType: ZWavePlusRoleType;
@ccValue({ internal: true })
public get installerIcon(): number {
return this._installerIcon;
}

private _userIcon: number;
public installerIcon: number;
@ccValue({ internal: true })
public get userIcon(): number {
return this._userIcon;
public userIcon: number;

public serialize(): Buffer {
this.payload = Buffer.from([
this.zwavePlusVersion,
this.roleType,
this.nodeType,
// placeholder for icons
0,
0,
0,
0,
]);
this.payload.writeUInt16BE(this.installerIcon, 3);
this.payload.writeUInt16BE(this.userIcon, 5);
return super.serialize();
}

public toLogEntry(): MessageOrCCLogEntry {
return {
...super.toLogEntry(),
message: {
version: this._zwavePlusVersion,
version: this.zwavePlusVersion,
"node type": getEnumMemberName(
ZWavePlusNodeType,
this._nodeType,
this.nodeType,
),
"role type": getEnumMemberName(
ZWavePlusRoleType,
this._roleType,
this.roleType,
),
"icon (mgmt.)": num2hex(this._installerIcon),
"icon (user)": num2hex(this._userIcon),
"icon (mgmt.)": num2hex(this.installerIcon),
"icon (user)": num2hex(this.userIcon),
},
};
}
Expand Down
18 changes: 17 additions & 1 deletion packages/zwave-js/src/lib/node/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ import {
getNodeTypeValueId,
getRoleTypeValueId,
getZWavePlusVersionValueId,
ZWavePlusCCGet,
} from "../commandclass/ZWavePlusCC";
import {
CentralSceneKeys,
Expand Down Expand Up @@ -2367,6 +2368,8 @@ protocol version: ${this.protocolVersion}`;
return this.handleEntryControlNotification(command);
} else if (command instanceof PowerlevelCCTestNodeReport) {
return this.handlePowerlevelTestNodeReport(command);
} else if (command instanceof ZWavePlusCCGet) {
return this.handleZWavePlusGet(command);
}

// Ignore all commands that don't need to be handled
Expand Down Expand Up @@ -2972,6 +2975,19 @@ protocol version: ${this.protocolVersion}`;
}
}

private async handleZWavePlusGet(_command: ZWavePlusCCGet): Promise<void> {
// treat this as a sign that the node is awake
this.markAsAwake();

await this.commandClasses["Z-Wave Plus Info"].sendReport({
zwavePlusVersion: 2,
roleType: ZWavePlusRoleType.CentralStaticController,
nodeType: ZWavePlusNodeType.Node,
installerIcon: 0x0500, // Generic Gateway
userIcon: 0x0500, // Generic Gateway
});
}

/**
* Allows automatically resetting notification values to idle if the node does not do it itself
*/
Expand Down Expand Up @@ -3235,7 +3251,7 @@ protocol version: ${this.protocolVersion}`;
command.minute !== minutes
) {
const endpoint = command.getEndpoint();
if (!endpoint || !endpoint.commandClasses.Clock.isSupported()) {
if (!endpoint /*|| !endpoint.commandClasses.Clock.isSupported()*/) {
// Make sure the endpoint supports the CC (GH#1704)
return;
}
Expand Down

0 comments on commit 6704313

Please sign in to comment.