UNPKG

inventoresed

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

158 lines (132 loc) 4.47 kB
import { MessageHeaders, MockSerialPort } from "@zwave-js/serial"; import type { 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"; import { isFunctionSupported_NoBridge } from "./fixtures"; describe("regression tests", () => { let driver: Driver; let serialport: MockSerialPort; process.env.LOGLEVEL = "debug"; beforeEach(async () => { ({ driver, serialport } = await createAndStartDriver()); driver["_controller"] = { ownNodeId: 1, isFunctionSupported: isFunctionSupported_NoBridge, nodes: new Map(), incrementStatistics: () => {}, removeAllListeners: () => {}, } as any; }); afterEach(async () => { await driver.destroy(); driver.removeAllListeners(); }); it("marking a node with a pending message as asleep does not mess up the remaining transactions", async () => { // Repro from #1107 // Node 10's awake timer elapses before its ping is rejected, // this causes mismatched responses for all following messages const node10 = new ZWaveNode(10, driver); const node17 = new ZWaveNode(17, driver); (driver.controller.nodes as ThrowingMap<number, ZWaveNode>).set( 10, node10, ); (driver.controller.nodes as ThrowingMap<number, ZWaveNode>).set( 17, node17, ); // Add event handlers for the nodes for (const node of driver.controller.nodes.values()) { driver["addNodeEventHandlers"](node); } node10["isListening"] = false; node10["isFrequentListening"] = false; node10.markAsAwake(); expect(node10.status).toBe(NodeStatus.Awake); // TODO: remove hack in packages/shared/src/wrappingCounter.ts when reworking this test to the new testing setup (driver.getNextCallbackId as any).value = 2; const ACK = Buffer.from([MessageHeaders.ACK]); const pingPromise10 = node10.ping(); await wait(1); node10.commandClasses.Basic.set(60); await wait(1); const pingPromise17 = node17.ping(); await wait(1); // » [Node 010] [REQ] [SendData] // │ transmit options: 0x25 // │ callback id: 3 // └─[NoOperationCC] expect(serialport.lastWrite).toEqual( Buffer.from("010800130a01002503c9", "hex"), ); await wait(10); serialport.receiveData(ACK); await wait(50); // « [RES] [SendData] // was sent: true serialport.receiveData(Buffer.from("0104011301e8", "hex")); // » [ACK] expect(serialport.lastWrite).toEqual(ACK); await wait(50); node10.markAsAsleep(); await wait(1); expect(node10.status).toBe(NodeStatus.Asleep); // The command queue should now abort the ongoing transaction // » [REQ] [SendDataAbort] expect(serialport.lastWrite).toEqual(Buffer.from("01030016ea", "hex")); await wait(10); serialport.receiveData(ACK); await wait(50); // Callback for previous message comes // « [REQ] [SendData] // callback id: 3 // transmit status: NoAck serialport.receiveData( Buffer.from( "011800130301019b007f7f7f7f7f010107000000000204000012", "hex", ), ); // await wait(1); expect(serialport.lastWrite).toEqual(ACK); // Abort was acknowledged, Ping for 10 should be failed await wait(50); await expect(pingPromise10).resolves.toBe(false); // Now the Ping for 17 should go out // » [Node 017] [REQ] [SendData] // │ transmit options: 0x25 // │ callback id: 4 // └─[NoOperationCC] expect(serialport.lastWrite).toEqual( Buffer.from("010800131101002504d5", "hex"), ); serialport.receiveData(ACK); await wait(50); // Ping 17 does not get resolved by the other callback await expect(Promise.race([pingPromise17, wait(50)])).resolves.toBe( undefined, ); // « [RES] [SendData] // was sent: true serialport.receiveData(Buffer.from("0104011301e8", "hex")); // » [ACK] expect(serialport.lastWrite).toEqual(ACK); await wait(50); // Callback for ping node 17 (failed) // « [REQ] [SendData] // callback id: 4 // transmit status: NoAck serialport.receiveData( Buffer.from( "011800130401019d007f7f7f7f7f010107000000000204000013", "hex", ), ); expect(serialport.lastWrite).toEqual(ACK); await expect(pingPromise17).resolves.toBeFalse(); driver.driverLog.sendQueue(driver["sendThread"].state.context.queue); }, 30000); });