UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

187 lines 7.46 kB
import { SwitchType } from "@zwave-js/cc"; import { MultilevelSwitchCCGet, MultilevelSwitchCCReport, MultilevelSwitchCCSet, MultilevelSwitchCCStartLevelChange, MultilevelSwitchCCStopLevelChange, MultilevelSwitchCCSupportedGet, MultilevelSwitchCCSupportedReport, } from "@zwave-js/cc/MultilevelSwitchCC"; import { CommandClasses, Duration, UNKNOWN_STATE, } from "@zwave-js/core"; import { setTimer } from "@zwave-js/shared"; import { getTransitionCurrentValue, getTransitionRemainingDuration, startTransition, stopTransition, } from "./MockTransition.js"; const defaultCapabilities = { defaultValue: 0, primarySwitchType: SwitchType["Down/Up"], travelTime: 0, }; const STATE_KEY_PREFIX = "MultilevelSwitch_"; const StateKeys = { currentValue: `${STATE_KEY_PREFIX}currentValue`, transition: `${STATE_KEY_PREFIX}transition`, }; /** Stops any running transition and snaps state. */ function stopCurrentTransition(self) { const existing = self.state.get(StateKeys.transition); if (existing) { const value = stopTransition(existing); self.state.set(StateKeys.currentValue, value); self.state.delete(StateKeys.transition); return { wasSupervised: existing.supervised }; } } /** * Stops any existing transition, then starts a new one. * Manages all state reads/writes. */ function beginTransition(controller, self, receivedCC, targetValue, travelTime, defaultValue, supervised) { stopCurrentTransition(self); const currentValue = (self.state.get(StateKeys.currentValue) ?? defaultValue ?? 0); const transition = startTransition({ currentValue, targetValue, duration: travelTime, supervised, onComplete: async () => { self.state.set(StateKeys.currentValue, targetValue); self.state.delete(StateKeys.transition); if (supervised) { await self.sendResponse(receivedCC, { action: "ok", }); return; } const cc = new MultilevelSwitchCCReport({ nodeId: controller.ownNodeId, currentValue: targetValue, targetValue, duration: new Duration(0, "seconds"), }); await self.sendResponse(receivedCC, { action: "sendCC", cc, }); }, onAbort: async () => { if (!supervised) return; await self.sendResponse(receivedCC, { action: "fail", }); }, }); if (transition) { self.state.set(StateKeys.transition, transition); return transition.durationMs; } else { self.state.set(StateKeys.currentValue, targetValue); return 0; } } const respondToMultilevelSwitchGet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof MultilevelSwitchCCGet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["Multilevel Switch"], receivedCC.endpointIndex), }; const transition = self.state.get(StateKeys.transition); let currentValue; let targetValue; let duration; if (transition) { currentValue = getTransitionCurrentValue(transition); targetValue = transition.targetValue; duration = getTransitionRemainingDuration(transition); } else { currentValue = (self.state.get(StateKeys.currentValue) ?? capabilities.defaultValue ?? UNKNOWN_STATE); targetValue = currentValue; duration = new Duration(0, "seconds"); } const cc = new MultilevelSwitchCCReport({ nodeId: controller.ownNodeId, currentValue, targetValue, duration, }); return { action: "sendCC", cc }; } }, }; const respondToMultilevelSwitchSet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof MultilevelSwitchCCSet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["Multilevel Switch"], receivedCC.endpointIndex), }; const durationMs = beginTransition(controller, self, receivedCC, receivedCC.targetValue, capabilities.travelTime, capabilities.defaultValue, receivedCC.isEncapsulatedWith(CommandClasses.Supervision)); return { action: "ok", durationMs, }; } }, }; const respondToMultilevelSwitchSupportedGet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof MultilevelSwitchCCSupportedGet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["Multilevel Switch"], receivedCC.endpointIndex), }; const cc = new MultilevelSwitchCCSupportedReport({ nodeId: controller.ownNodeId, switchType: capabilities.primarySwitchType, }); return { action: "sendCC", cc }; } }, }; const respondToMultilevelSwitchStartLevelChange = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof MultilevelSwitchCCStartLevelChange) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["Multilevel Switch"], receivedCC.endpointIndex), }; const targetValue = receivedCC.direction === "up" ? 99 : 0; const durationMs = beginTransition(controller, self, receivedCC, targetValue, capabilities.travelTime, capabilities.defaultValue, receivedCC.isEncapsulatedWith(CommandClasses.Supervision)); return { action: "ok", durationMs, }; } }, }; const respondToMultilevelSwitchStopLevelChange = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof MultilevelSwitchCCStopLevelChange) { const stoppedTransition = stopCurrentTransition(self); const currentValue = (self.state.get(StateKeys.currentValue) ?? 0); if (!stoppedTransition?.wasSupervised) { // Send a delayed report with the final state setTimer(async () => { const cc = new MultilevelSwitchCCReport({ nodeId: controller.ownNodeId, currentValue, targetValue: currentValue, duration: new Duration(0, "seconds"), }); await self.sendResponse(receivedCC, { action: "sendCC", cc, }); }, 100).unref(); } return { action: "ok" }; } }, }; export const MultilevelSwitchCCBehaviors = [ respondToMultilevelSwitchGet, respondToMultilevelSwitchSet, respondToMultilevelSwitchSupportedGet, respondToMultilevelSwitchStartLevelChange, respondToMultilevelSwitchStopLevelChange, ]; //# sourceMappingURL=MultilevelSwitch.js.map