Skip to content

Commit

Permalink
feat(cc): implement Z-Wave Protocol CC, fix CC snippets (#4691)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone committed Jul 20, 2022
1 parent eecded7 commit 6f23e34
Show file tree
Hide file tree
Showing 10 changed files with 1,474 additions and 134 deletions.
111 changes: 55 additions & 56 deletions .vscode/typescript.code-snippets
Expand Up @@ -5,23 +5,21 @@
"body": [
"import {",
"\tMessageOrCCLogEntry,",
"\tMessagePriority,",
"\tZWaveError,",
"\tZWaveErrorCodes,",
"} from \"@zwave-js/core\";",
"import type { ZWaveHost } from \"@zwave-js/host\";",
"import type { ZWaveApplicationHost, ZWaveHost } from \"@zwave-js/host\";",
"import {",
"\tFunctionType,",
"\tMessagePriority,",
"\tMessageType,",
"} from \"../../message/Constants\";",
"import {",
"\tgotDeserializationOptions,",
"\tMessage,",
"\tMessageBaseOptions,",
"\tMessageDeserializationOptions,",
"\tMessageType,",
"\tmessageTypes,",
"\tpriority,",
"} from \"../../message/Message\";",
"} from \"@zwave-js/serial\";",
"",
"export interface ${1}RequestOptions extends MessageBaseOptions {",
"\t${0:someProperty: number;}",
Expand Down Expand Up @@ -71,25 +69,23 @@
"body": [
"import {",
"\tMessageOrCCLogEntry,",
"\tMessagePriority,",
"\tZWaveError,",
"\tZWaveErrorCodes,",
"} from \"@zwave-js/core\";",
"import type { ZWaveHost } from \"@zwave-js/host\";",
"import {",
"\tFunctionType,",
"\tMessagePriority,",
"\tMessageType,",
"} from \"../../message/Constants\";",
"import type { ZWaveApplicationHost, ZWaveHost } from \"@zwave-js/host\";",
"import {",
"\texpectedResponse,",
"\tFunctionType,",
"\tgotDeserializationOptions,",
"\tMessage,",
"\tMessageBaseOptions,",
"\tMessageDeserializationOptions,",
"\tMessageType,",
"\tmessageTypes,",
"\tpriority,",
"} from \"../../message/Message\";",
"import type { SuccessIndicator } from \"../../message/SuccessIndicator\";",
"\tSuccessIndicator,",
"} from \"@zwave-js/serial\";",
"",
"export interface ${1}RequestOptions extends MessageBaseOptions {",
"\t${0:someProperty: number;}",
Expand Down Expand Up @@ -161,27 +157,25 @@
"body": [
"import {",
"\tMessageOrCCLogEntry,",
"\tMessagePriority,",
"\tZWaveError,",
"\tZWaveErrorCodes,",
"} from \"@zwave-js/core\";",
"import type { ZWaveHost } from \"@zwave-js/host\";",
"import {",
"\tFunctionType,",
"\tMessagePriority,",
"\tMessageType,",
"} from \"../../message/Constants\";",
"import type { ZWaveApplicationHost, ZWaveHost } from \"@zwave-js/host\";",
"import {",
"\texpectedCallback,",
"\texpectedResponse,",
"\tFunctionType,",
"\tgotDeserializationOptions,",
"\tMessage,",
"\tMessageBaseOptions,",
"\tMessageDeserializationOptions,",
"\tMessageOptions,",
"\tMessageType,",
"\tmessageTypes,",
"\tpriority,",
"} from \"../../message/Message\";",
"import type { SuccessIndicator } from \"../../message/SuccessIndicator\";",
"\tSuccessIndicator,",
"} from \"@zwave-js/serial\";",
"",
"@messageTypes(MessageType.Request, FunctionType.${1:Dummy})",
"@priority(MessagePriority.${2:Normal})",
Expand Down Expand Up @@ -290,16 +284,14 @@
"body": [
"import {",
"\tMessageOrCCLogEntry,",
"\tMessagePriority,",
"\tZWaveError,",
"\tZWaveErrorCodes,",
"} from \"@zwave-js/core\";",
"import type { ZWaveHost } from \"@zwave-js/host\";",
"import type { ZWaveApplicationHost, ZWaveHost } from \"@zwave-js/host\";",
"import {",
"\tFunctionType,",
"\tMessagePriority,",
"\tMessageType,",
"} from \"../../message/Constants\";",
"import {",
"\texpectedCallback,",
"\tgotDeserializationOptions,",
"\tMessage,",
Expand All @@ -308,8 +300,8 @@
"\tMessageOptions,",
"\tmessageTypes,",
"\tpriority,",
"} from \"../../message/Message\";",
"import type { SuccessIndicator } from \"../../message/SuccessIndicator\";",
"\tSuccessIndicator,",
"} from \"@zwave-js/serial\";",
"",
"@messageTypes(MessageType.Request, FunctionType.${1:Dummy})",
"@priority(MessagePriority.${2:Normal})",
Expand Down Expand Up @@ -439,19 +431,25 @@
"body": [
"import {",
"\tCCCommand,",
"\tCCCommandOptions,",
"\tCommandClass,",
"\tcommandClass,",
"\texpectedCCResponse,",
"\timplementedVersion,",
"\tCommandClassDeserializationOptions,",
"\tgotDeserializationOptions,",
"} from \"./CommandClass\";",
"import { CommandClasses } from \"@zwave-js/core\";",
"import type { Driver } from \"../driver/Driver\";",
"\ttype CCCommandOptions,",
"\ttype CommandClassDeserializationOptions,",
"} from \"../lib/CommandClass\";",
"import {",
"\tCommandClasses,",
"\tMessageOrCCLogEntry,",
"\tMessagePriority,",
"\tZWaveError,",
"\tZWaveErrorCodes,",
"} from \"@zwave-js/core\";",
"import type { ZWaveApplicationHost, ZWaveHost } from \"@zwave-js/host\";",
"import { CCAPI } from \"../lib/API\";",
"",
"// TODO: Move this enumeration into the _Types.ts file",
"// TODO: Move this enumeration into the src/lib/_Types.ts file",
"// All additional type definitions (except CC constructor options) must be defined there too",
"export enum ${1:${TM_FILENAME_BASE/(.*)CC$/$1/}}Command {",
"\t${3:// Get = 0x01}",
Expand Down Expand Up @@ -528,14 +526,7 @@
"prefix": "zwccemptycmd",
"body": [
"@CCCommand(${1:${TM_FILENAME_BASE/(.*)CC$/$1/}}Command.${2:Get})",
"export class ${1}CC${2} extends ${1}CC {",
"\tpublic constructor(",
"\t\thost: ZWaveHost,",
"\t\toptions: CommandClassDeserializationOptions | CCCommandOptions,",
"\t) {",
"\t\tsuper(host, options);",
"\t}",
"}"
"export class ${1}CC${2} extends ${1}CC {}"
],
"description": "Specific implementation of CC command that is sent and expects no parameters"
},
Expand Down Expand Up @@ -621,35 +612,39 @@
"scope": "typescript",
"prefix": "zwccinterview",
"body": [
"public async interview(driver: Driver): Promise<void> {",
"\tconst node = this.getNode()!;",
"\tconst endpoint = this.getEndpoint()!;",
"\tconst api = endpoint.commandClasses.${1:${TM_FILENAME_BASE/(.*)CC$/$1/}}.withOptions({",
"public async interview(applHost: ZWaveApplicationHost): Promise<void> {",
"\tconst node = this.getNode(applHost)!;",
"\tconst endpoint = this.getEndpoint(applHost)!;",
"\tconst api = CCAPI.create(",
"\t\tCommandClasses.${1:${TM_FILENAME_BASE/(.*)CC$/$1/}},",
"\t\tapplHost,",
"\t\tendpoint",
"\t).withOptions({",
"\t\tpriority: MessagePriority.NodeQuery,",
"\t});",
"\tconst valueDB = this.getValueDB(driver);",
"\tconst valueDB = this.getValueDB(applHost);",
"",
"\tdriver.controllerLog.logNode(node.id, {",
"\tapplHost.controllerLog.logNode(node.id, {",
"\t\tendpoint: this.endpointIndex,",
"\t\tmessage: `Interviewing ${this.ccName}...`,",
"\t\tdirection: \"none\",",
"\t});",
"",
"\tdriver.controllerLog.logNode(node.id, {",
"\tapplHost.controllerLog.logNode(node.id, {",
"\t\tendpoint: this.endpointIndex,",
"\t\tmessage: \"doing something...\",",
"\t\tdirection: \"outbound\",",
"\t});",
"\t${0:// TODO: Implementation}",
"\tconst logMessage = `received response for something...`;",
"\tdriver.controllerLog.logNode(node.id, {",
"\tapplHost.controllerLog.logNode(node.id, {",
"\t\tendpoint: this.endpointIndex,",
"\t\tmessage: logMessage,",
"\t\tdirection: \"inbound\",",
"\t});",
"",
"\t// Remember that the interview is complete",
"\tthis.setInterviewComplete(driver, true);",
"\tthis.setInterviewComplete(applHost, true);",
"}"
]
},
Expand All @@ -669,13 +664,17 @@
"scope": "typescript",
"prefix": "zwccrefval",
"body": [
"public async refreshValues(driver: Driver): Promise<void> {",
"\tconst node = this.getNode()!;",
"\tconst endpoint = this.getEndpoint()!;",
"\tconst api = endpoint.commandClasses[\"${1:${TM_FILENAME_BASE/(.*)CC$/$1/}}\"].withOptions({",
"public async refreshValues(applHost: ZWaveApplicationHost): Promise<void> {",
"\tconst node = this.getNode(applHost)!;",
"\tconst endpoint = this.getEndpoint(applHost)!;",
"\tconst api = CCAPI.create(",
"\t\tCommandClasses.${1:${TM_FILENAME_BASE/(.*)CC$/$1/}},",
"\t\tapplHost,",
"\t\tendpoint",
"\t).withOptions({",
"\t\tpriority: MessagePriority.NodeQuery,",
"\t});",
"\tconst valueDB = this.getValueDB(driver);",
"\tconst valueDB = this.getValueDB(applHost);",
"",
"\t${0:// TODO: Implementation}",
"}"
Expand Down
18 changes: 11 additions & 7 deletions packages/cc/src/cc/MultiChannelCC.ts
@@ -1,5 +1,6 @@
import type { GenericDeviceClass, SpecificDeviceClass } from "@zwave-js/config";
import {
ApplicationNodeInformation,
CommandClasses,
encodeBitMask,
getCCName,
Expand All @@ -8,8 +9,8 @@ import {
MessageOrCCLogEntry,
MessagePriority,
MessageRecord,
parseApplicationNodeInformation,
parseBitMask,
parseNodeInformationFrame,
validatePayload,
ValueID,
ZWaveError,
Expand Down Expand Up @@ -719,23 +720,26 @@ export class MultiChannelCCEndPointReport extends MultiChannelCC {
export class MultiChannelCCEndPointGet extends MultiChannelCC {}

@CCCommand(MultiChannelCommand.CapabilityReport)
export class MultiChannelCCCapabilityReport extends MultiChannelCC {
export class MultiChannelCCCapabilityReport
extends MultiChannelCC
implements ApplicationNodeInformation
{
public constructor(
host: ZWaveHost,
options: CommandClassDeserializationOptions,
) {
super(host, options);

// Only validate the bytes we expect to see here
// parseNodeInformationFrame does its own validation
// parseApplicationNodeInformation does its own validation
validatePayload(this.payload.length >= 1);
this.endpointIndex = this.payload[0] & 0b01111111;
const NIF = parseNodeInformationFrame(this.payload.slice(1));
this.isDynamic = !!(this.payload[0] & 0b10000000);
this.genericDeviceClass = NIF.generic;
this.specificDeviceClass = NIF.specific;

const NIF = parseApplicationNodeInformation(this.payload.slice(1));
this.genericDeviceClass = NIF.genericDeviceClass;
this.specificDeviceClass = NIF.specificDeviceClass;
this.supportedCCs = NIF.supportedCCs;
// TODO: does this include controlledCCs aswell?

// Removal reports have very specific information
this.wasRemoved =
Expand Down

0 comments on commit 6f23e34

Please sign in to comment.