Skip to content

Commit

Permalink
feat(test): implement communication between mock controller and mock …
Browse files Browse the repository at this point in the history
…nodes (#4697)
  • Loading branch information
AlCalzone committed Jul 19, 2022
1 parent b908f6c commit 1e4cb5e
Show file tree
Hide file tree
Showing 32 changed files with 1,180 additions and 242 deletions.
4 changes: 3 additions & 1 deletion .vscode/launch.json
Expand Up @@ -39,7 +39,9 @@
"./maintenance/esbuild-register.js",
"${workspaceFolder}/test/mock.ts"
],
"env": {},
"env": {
"NO_CACHE": "true"
},
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**"],
"sourceMaps": true,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -91,7 +91,7 @@
"scripts": {
"foreach": "yarn workspaces foreach -pvi --exclude @zwave-js/repo",
"clean": "rm -rf packages/*/{build,*.tsbuildinfo}",
"prebuild": "yarn workspace @zwave-js/maintenance run build",
"prebuild": "yarn workspace @zwave-js/maintenance run build && yarn workspace @zwave-js/cc run prebuild",
"build": "yarn prebuild && yarn workspace zwave-js run build",
"watch": "yarn prebuild && yarn workspace zwave-js run watch",
"test:reset": "jest --clear-cache",
Expand Down
5 changes: 3 additions & 2 deletions packages/cc/package.json
Expand Up @@ -49,9 +49,10 @@
},
"scripts": {
"b": "yarn ts maintenance/_build.ts",
"build": "yarn b prebuild && tsc -b tsconfig.build.json --verbose",
"prebuild": "yarn b prebuild",
"build": "yarn run prebuild && tsc -b tsconfig.build.json --verbose",
"clean": "tsc -b tsconfig.build.json --clean",
"watch": "yarn b prebuild && tsc -b tsconfig.build.json --watch --pretty",
"watch": "yarn run prebuild && tsc -b tsconfig.build.json --watch --pretty",
"lint_zwave": "yarn b lint",
"ts": "node -r esbuild-register"
},
Expand Down
1 change: 1 addition & 0 deletions packages/cc/src/cc/CRC16CC.ts
Expand Up @@ -102,6 +102,7 @@ export class CRC16CCCommandEncapsulation extends CRC16CC {
data: ccBuffer,
fromEncapsulation: true,
encapCC: this,
origin: options.origin,
});
} else {
this.encapsulated = options.encapsulated;
Expand Down
2 changes: 2 additions & 0 deletions packages/cc/src/cc/MultiChannelCC.ts
Expand Up @@ -1137,6 +1137,7 @@ export class MultiChannelCCCommandEncapsulation extends MultiChannelCC {
data: this.payload.slice(2),
fromEncapsulation: true,
encapCC: this,
origin: options.origin,
});
} else {
this.encapsulated = options.encapsulated;
Expand Down Expand Up @@ -1315,6 +1316,7 @@ export class MultiChannelCCV1CommandEncapsulation extends MultiChannelCC {
data: this.payload.slice(isV2withV1Header ? 2 : 1),
fromEncapsulation: true,
encapCC: this,
origin: options.origin,
});
} else {
this.encapsulated = options.encapsulated;
Expand Down
1 change: 1 addition & 0 deletions packages/cc/src/cc/MultiCommandCC.ts
Expand Up @@ -105,6 +105,7 @@ export class MultiCommandCCCommandEncapsulation extends MultiCommandCC {
),
fromEncapsulation: true,
encapCC: this,
origin: options.origin,
}),
);
offset += 1 + cmdLength;
Expand Down
1 change: 1 addition & 0 deletions packages/cc/src/cc/SupervisionCC.ts
Expand Up @@ -278,6 +278,7 @@ export class SupervisionCCGet extends SupervisionCC {
data: this.payload.slice(2),
fromEncapsulation: true,
encapCC: this,
origin: options.origin,
});
} else {
this.sessionId = getNextSessionId();
Expand Down
38 changes: 38 additions & 0 deletions packages/cc/src/cc/index.ts
Expand Up @@ -517,3 +517,41 @@ export {
WakeUpCCWakeUpNotification,
} from "./WakeUpCC";
export { ZWavePlusCC, ZWavePlusCCGet, ZWavePlusCCReport } from "./ZWavePlusCC";
export {
ZWaveProtocolCC,
ZWaveProtocolCCAcceptLost,
ZWaveProtocolCCAssignIDs,
ZWaveProtocolCCAssignReturnRoute,
ZWaveProtocolCCAssignReturnRoutePriority,
ZWaveProtocolCCAssignSUCReturnRoute,
ZWaveProtocolCCAssignSUCReturnRoutePriority,
ZWaveProtocolCCAutomaticControllerUpdateStart,
ZWaveProtocolCCCommandComplete,
ZWaveProtocolCCExcludeRequest,
ZWaveProtocolCCFindNodesInRange,
ZWaveProtocolCCGetNodesInRange,
ZWaveProtocolCCLost,
ZWaveProtocolCCNewNodeRegistered,
ZWaveProtocolCCNewRangeRegistered,
ZWaveProtocolCCNodeInformationFrame,
ZWaveProtocolCCNodesExist,
ZWaveProtocolCCNodesExistReply,
ZWaveProtocolCCNOPPower,
ZWaveProtocolCCRangeInfo,
ZWaveProtocolCCRequestNodeInformationFrame,
ZWaveProtocolCCReservedIDs,
ZWaveProtocolCCReserveNodeIDs,
ZWaveProtocolCCSetNWIMode,
ZWaveProtocolCCSetSUC,
ZWaveProtocolCCSetSUCAck,
ZWaveProtocolCCSmartStartIncludedNodeInformation,
ZWaveProtocolCCSmartStartInclusionRequest,
ZWaveProtocolCCSmartStartPrime,
ZWaveProtocolCCStaticRouteRequest,
ZWaveProtocolCCSUCNodeID,
ZWaveProtocolCCTransferEnd,
ZWaveProtocolCCTransferNewPrimaryControllerComplete,
ZWaveProtocolCCTransferNodeInformation,
ZWaveProtocolCCTransferPresentation,
ZWaveProtocolCCTransferRangeInformation,
} from "./ZWaveProtocolCC";
13 changes: 11 additions & 2 deletions packages/cc/src/lib/CommandClass.ts
Expand Up @@ -21,6 +21,7 @@ import {
ZWaveErrorCodes,
} from "@zwave-js/core";
import type { ZWaveApplicationHost, ZWaveHost } from "@zwave-js/host";
import { MessageOrigin } from "@zwave-js/serial";
import {
buffer2hex,
getEnumMemberName,
Expand All @@ -40,7 +41,10 @@ import {
isCommandClassContainer,
} from "./ICommandClassContainer";

export type CommandClassDeserializationOptions = { data: Buffer } & (
export type CommandClassDeserializationOptions = {
data: Buffer;
origin?: MessageOrigin;
} & (
| {
fromEncapsulation?: false;
nodeId: number;
Expand All @@ -67,6 +71,7 @@ interface CommandClassCreationOptions extends CCCommandOptions {
ccId?: number; // Used to overwrite the declared CC ID
ccCommand?: number; // undefined = NoOp
payload?: Buffer;
origin?: undefined;
}

function gotCCCommandOptions(options: any): options is CCCommandOptions {
Expand Down Expand Up @@ -144,7 +149,11 @@ export class CommandClass implements ICommandClass {

if (this instanceof InvalidCC) return;

if (this.isSinglecast() && this.nodeId !== NODE_ID_BROADCAST) {
if (
options.origin !== MessageOrigin.Host &&
this.isSinglecast() &&
this.nodeId !== NODE_ID_BROADCAST
) {
// For singlecast CCs, set the CC version as high as possible
this.version = this.host.getSafeCCVersionForNode(
this.ccId,
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/capabilities/NodeInfo.test.ts
Expand Up @@ -37,7 +37,7 @@ describe("lib/node/NodeInfo", () => {
describe("parseNodeUpdatePayload()", () => {
const payload = Buffer.from([
5, // NodeID
2, // CC list length
5, // remaining length
0x03, // Slave
0x01, // Remote Controller
0x02, // Portable Scene Controller
Expand All @@ -52,7 +52,7 @@ describe("lib/node/NodeInfo", () => {
});

it("should extract the correct BasicDeviceClass", () => {
expect(nup.basic).toBe(3);
expect(nup.basicDeviceClass).toBe(3);
});

it("should extract the correct GenericDeviceClass", () => {
Expand All @@ -73,7 +73,7 @@ describe("lib/node/NodeInfo", () => {
it("correctly parses extended CCs", () => {
const payload = Buffer.from([
5, // NodeID
6, // CC list length
9, // remaining length
0x03,
0x01,
0x02, // Portable Scene Controller
Expand Down
28 changes: 21 additions & 7 deletions packages/core/src/capabilities/NodeInfo.ts
Expand Up @@ -21,20 +21,34 @@ export function parseApplicationNodeInformation(

export interface NodeUpdatePayload extends ApplicationNodeInformation {
nodeId: number;
basic: number;
basicDeviceClass: number;
}

export function parseNodeUpdatePayload(nif: Buffer): NodeUpdatePayload {
const numCCs = nif[1];
// The application node info starts at 3, and contains 2+N bytes
validatePayload(nif.length >= 3 + 2 + numCCs);
const nodeId = nif[0];
const remainingLength = nif[1];
validatePayload(nif.length >= 2 + remainingLength);
return {
nodeId: nif[0],
basic: nif[2],
...parseApplicationNodeInformation(nif.slice(3, 3 + 2 + numCCs)),
nodeId,
basicDeviceClass: nif[2],
...parseApplicationNodeInformation(nif.slice(3, 2 + remainingLength)),
};
}

export function encodeNodeUpdatePayload(nif: NodeUpdatePayload): Buffer {
const ccList = encodeCCList(nif.supportedCCs, []);
return Buffer.concat([
Buffer.from([
nif.nodeId,
3 + ccList.length,
nif.basicDeviceClass,
nif.genericDeviceClass,
nif.specificDeviceClass,
]),
ccList,
]);
}

export function isExtendedCCId(ccId: CommandClasses): boolean {
return ccId >= 0xf1;
}
Expand Down
15 changes: 13 additions & 2 deletions packages/serial/src/message/Message.ts
Expand Up @@ -22,8 +22,15 @@ type Constructable<T extends Message> = new (
options?: MessageOptions,
) => T;

/** Where a serialized message originates from, to distinguish how certain messages need to be deserialized */
export enum MessageOrigin {
Controller,
Host,
}

export interface MessageDeserializationOptions {
data: Buffer;
origin?: MessageOrigin;
}

/**
Expand Down Expand Up @@ -227,9 +234,13 @@ export class Message {
}

/** Creates an instance of the message that is serialized in the given buffer */
public static from(host: ZWaveHost, data: Buffer): Message {
public static from(
host: ZWaveHost,
data: Buffer,
origin?: MessageOrigin,
): Message {
const Constructor = Message.getConstructor(data);
const ret = new Constructor(host, { data });
const ret = new Constructor(host, { data, origin });
return ret;
}

Expand Down

0 comments on commit 1e4cb5e

Please sign in to comment.