inventoresed
Version:
Z-Wave driver written entirely in JavaScript/TypeScript
124 lines (119 loc) • 3.37 kB
text/typescript
/* eslint-disable @typescript-eslint/require-await */
import { ConfigManager } from "@zwave-js/config";
import {
IZWaveNode,
MAX_SUPERVISION_SESSION_ID,
ValueDB,
ZWaveError,
ZWaveErrorCodes,
} from "@zwave-js/core";
import {
createThrowingMap,
createWrappingCounter,
type ThrowingMap,
} from "@zwave-js/shared";
import type { Overwrite } from "alcalzone-shared/types";
import type { ZWaveApplicationHost, ZWaveHost } from "./ZWaveHost";
export interface CreateTestingHostOptions {
homeId: ZWaveHost["homeId"];
ownNodeId: ZWaveHost["ownNodeId"];
getSafeCCVersionForNode: ZWaveHost["getSafeCCVersionForNode"];
}
export type TestingHost = Overwrite<
Omit<ZWaveApplicationHost, "__internalIsMockNode">,
{ nodes: ThrowingMap<number, IZWaveNode> }
>;
/** Creates a {@link ZWaveApplicationHost} that can be used for testing */
export function createTestingHost(
options: Partial<CreateTestingHostOptions> = {},
): TestingHost {
const valuesStorage = new Map();
const metadataStorage = new Map();
const valueDBCache = new Map<number, ValueDB>();
const ret: TestingHost = {
homeId: options.homeId ?? 0x7e570001,
ownNodeId: options.ownNodeId ?? 1,
isControllerNode: (nodeId) => nodeId === ret.ownNodeId,
securityManager: undefined,
securityManager2: undefined,
getDeviceConfig: undefined,
controllerLog: new Proxy({} as any, {
get() {
return () => {
/* intentionally empty */
};
},
}),
configManager: new ConfigManager(),
options: {
attempts: {
nodeInterview: 1,
// openSerialPort: 1,
sendData: 3,
controller: 3,
},
timeouts: {
refreshValue: 5000,
refreshValueAfterTransition: 1000,
},
},
nodes: createThrowingMap((nodeId) => {
throw new ZWaveError(
`Node ${nodeId} was not found!`,
ZWaveErrorCodes.Controller_NodeNotFound,
);
}),
getSafeCCVersionForNode: options.getSafeCCVersionForNode ?? (() => 100),
getNextCallbackId: createWrappingCounter(0xff),
getNextSupervisionSessionId: createWrappingCounter(
MAX_SUPERVISION_SESSION_ID,
),
getValueDB: (nodeId) => {
if (!valueDBCache.has(nodeId)) {
valueDBCache.set(
nodeId,
new ValueDB(
nodeId,
valuesStorage as any,
metadataStorage as any,
),
);
}
return valueDBCache.get(nodeId)!;
},
tryGetValueDB: (nodeId) => {
return ret.getValueDB(nodeId);
},
isCCSecure: (ccId, nodeId, endpointIndex = 0) => {
const node = ret.nodes.get(nodeId);
const endpoint = node?.getEndpoint(endpointIndex);
return (
node?.isSecure !== false &&
!!(endpoint ?? node)?.isCCSecure(ccId) &&
!!(ret.securityManager || ret.securityManager2)
);
},
getHighestSecurityClass: (nodeId) => {
const node = ret.nodes.getOrThrow(nodeId);
return node.getHighestSecurityClass();
},
hasSecurityClass: (nodeId, securityClass) => {
const node = ret.nodes.getOrThrow(nodeId);
return node.hasSecurityClass(securityClass);
},
setSecurityClass: (nodeId, securityClass, granted) => {
const node = ret.nodes.getOrThrow(nodeId);
node.setSecurityClass(securityClass, granted);
},
sendCommand: async (_command, _options) => {
return undefined as any;
},
waitForCommand: async (_predicate, _timeout) => {
return undefined as any;
},
schedulePoll: (_nodeId, _valueId, _options) => {
return false;
},
};
return ret;
}