inventoresed
Version:
Z-Wave driver written entirely in JavaScript/TypeScript
134 lines (113 loc) • 3.5 kB
text/typescript
import { FunctionType, MessageHeaders, MockSerialPort } from "@zwave-js/serial";
import { getEnumMemberName, ThrowingMap } from "@zwave-js/shared";
import { wait } from "alcalzone-shared/async";
import type { Driver } from "../../driver/Driver";
import { ZWaveNode } from "../../node/Node";
import { NodeStatus } from "../../node/_Types";
import { createAndStartDriver } from "../utils";
// Test mock for isFunctionSupported to control which commands are getting used
function isFunctionSupported(fn: FunctionType): boolean {
switch (fn) {
case FunctionType.SendDataBridge:
case FunctionType.SendDataMulticastBridge:
return false;
}
return true;
}
describe("When a ping succeeds, the node should be marked awake/alive", () => {
let driver: Driver;
let serialport: MockSerialPort;
process.env.LOGLEVEL = "debug";
beforeEach(async () => {
({ driver, serialport } = await createAndStartDriver());
driver["_controller"] = {
ownNodeId: 1,
isFunctionSupported,
nodes: new Map(),
incrementStatistics: () => {},
removeAllListeners: () => {},
} as any;
});
afterEach(async () => {
await driver.destroy();
driver.removeAllListeners();
});
for (const initialStatus of [
NodeStatus.Unknown,
NodeStatus.Asleep,
NodeStatus.Dead,
]) {
for (const canSleep of [true, false]) {
// Exclude tests that make no sense
if (
(initialStatus === NodeStatus.Asleep && !canSleep) ||
(canSleep && initialStatus === NodeStatus.Dead)
) {
continue;
}
const expectedStatus = canSleep
? NodeStatus.Awake
: NodeStatus.Alive;
it(`Can sleep: ${canSleep}, initial status: ${getEnumMemberName(
NodeStatus,
initialStatus,
)}`, async () => {
// https://github.com/zwave-js/node-zwave-js/issues/1364#issuecomment-760006591
const node4 = new ZWaveNode(4, driver);
(driver.controller.nodes as ThrowingMap<number, ZWaveNode>).set(
node4.id,
node4,
);
// Add event handlers for the nodes
for (const node of driver.controller.nodes.values()) {
driver["addNodeEventHandlers"](node);
}
if (canSleep) {
node4["isListening"] = false;
node4["isFrequentListening"] = false;
} else {
node4["isListening"] = true;
node4["isFrequentListening"] = false;
}
if (initialStatus === NodeStatus.Asleep) {
node4.markAsAsleep();
} else if (initialStatus === NodeStatus.Dead) {
node4.markAsDead();
}
expect(node4.status).toBe(initialStatus);
const ACK = Buffer.from([MessageHeaders.ACK]);
const pingPromise = node4.ping();
await wait(1);
// » [Node 004] [REQ] [SendData]
// │ transmit options: 0x25
// │ callback id: 1
// └─[NoOperationCC]
expect(serialport.lastWrite).toEqual(
Buffer.from("010800130401002501c5", "hex"),
);
await wait(10);
serialport.receiveData(ACK);
await wait(10);
// « [RES] [SendData]
// was sent: true
serialport.receiveData(Buffer.from("0104011301e8", "hex"));
// » [ACK]
expect(serialport.lastWrite).toEqual(ACK);
await wait(10);
// « [REQ] [SendData]
// callback id: 1
// transmit status: OK
serialport.receiveData(
Buffer.from(
"011800130100000100bd7f7f7f7f010103000000000201000049",
"hex",
),
);
expect(serialport.lastWrite).toEqual(ACK);
await wait(10);
await pingPromise;
expect(node4.status).toBe(expectedStatus);
}, 5000);
}
}
});