UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

90 lines 4.49 kB
import { SupervisionCCReport, } from "@zwave-js/cc"; import { ZWaveError, ZWaveErrorCodes, mergeSupervisionResults, } from "@zwave-js/core"; /** Creates a wrapper that looks like an instance of a specific CC API, but can handle multiple instances of that API */ export function createMultiCCAPIWrapper(apiInstances) { if (apiInstances.length === 0) { throw new ZWaveError("At least one CC API instance must be provided", ZWaveErrorCodes.Argument_Invalid); } else if (apiInstances.some((a) => a.ccId !== apiInstances[0].ccId)) { throw new ZWaveError("All CC API instances must be for the same CC", ZWaveErrorCodes.Argument_Invalid); } const withOptions = (options) => createMultiCCAPIWrapper( // Create a new wrapper where each instance has the options applied apiInstances.map((a) => a.withOptions(options))); const withTXReport = () => createMultiCCAPIWrapper(apiInstances.map((a) => a.withTXReport())); // Delegate some properties to the first instance const version = apiInstances[0].version; const ccId = apiInstances[0].ccId; const isSupported = () => apiInstances[0].isSupported(); const isSetValueOptimistic = (valueId) => apiInstances[0].isSetValueOptimistic(valueId); const supportsCommand = (cmd) => apiInstances[0].supportsCommand(cmd); // Since all instances are the same, either all of them or none have a set value implementation const setValue = apiInstances[0] .setValue ? async (...args) => { const tasks = apiInstances.map((a) => a.setValue.call(a, ...args)); const results = await Promise.all(tasks); return mergeSupervisionResults(results); } : undefined; // This wrapper is by definition for multiple nodes, so we cannot return one const getNode = () => undefined; const tryGetNode = () => undefined; return new Proxy({}, { get(target, prop) { // Avoid ultra-weird error messages during testing if (process.env.NODE_ENV === "test" && typeof prop === "string" && (prop === "$$typeof" || prop === "constructor" || prop.includes("@@__IMMUTABLE"))) { return undefined; } switch (prop) { case "ccId": return ccId; case "version": return version; case "isSupported": return isSupported; case "getNode": return getNode; case "tryGetNode": return tryGetNode; case "isSetValueOptimistic": return isSetValueOptimistic; case "supportsCommand": return supportsCommand; case "withOptions": return withOptions; case "withTXReport": return withTXReport; case "pollValue": // We don't do multicast polls return undefined; case "setValue": return setValue; default: // Assume everything else is a CC-specific method. // Call all of them and merge the results return async (...args) => { const tasks = apiInstances.map((a) => // This may throw when a non-existing method is accessed, but that is desired here a[prop].call(a, ...args)); // This call won't go through the sendSupervisedCommand method, so supervision results are not automatically unwrapped const responses = await Promise.all(tasks); const results = responses.map((r) => { if (r instanceof SupervisionCCReport) { return r.toSupervisionResult(); } return undefined; }); // The call site may use a GET-type method, which does not make sense in a multicast context // The following will return `undefined` in that case return mergeSupervisionResults(results); }; } }, }); } //# sourceMappingURL=MultiCCAPIWrapper.js.map