UNPKG

inventoresed

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

119 lines (113 loc) 2.31 kB
import { Interpreter, Machine, StateMachine } from "xstate"; import type { ZWaveNode } from "./Node"; import { NodeStatus } from "./_Types"; /* eslint-disable @typescript-eslint/ban-types */ export interface NodeStatusStateSchema { states: { unknown: {}; // non-sleeping nodes are either dead or alive dead: {}; alive: {}; // sleeping nodes are asleep or awake asleep: {}; awake: {}; }; } /* eslint-enable @typescript-eslint/ban-types */ const statusDict = { unknown: NodeStatus.Unknown, dead: NodeStatus.Dead, alive: NodeStatus.Alive, asleep: NodeStatus.Asleep, awake: NodeStatus.Awake, } as const; export function nodeStatusMachineStateToNodeStatus( state: keyof NodeStatusStateSchema["states"], ): NodeStatus { return statusDict[state] ?? NodeStatus.Unknown; } export type NodeStatusEvent = | { type: "DEAD" } | { type: "ALIVE" } | { type: "ASLEEP" } | { type: "AWAKE" }; export type NodeStatusMachine = StateMachine< any, NodeStatusStateSchema, NodeStatusEvent, any, any, any, any >; export type NodeStatusInterpreter = Interpreter< any, NodeStatusStateSchema, NodeStatusEvent >; export function createNodeStatusMachine(node: ZWaveNode): NodeStatusMachine { return Machine<any, NodeStatusStateSchema, NodeStatusEvent>( { id: "nodeStatus", initial: "unknown", states: { unknown: { on: { DEAD: { target: "dead", cond: "cannotSleep", }, ALIVE: { target: "alive", cond: "cannotSleep", }, ASLEEP: { target: "asleep", cond: "canSleep", }, AWAKE: { target: "awake", cond: "canSleep", }, }, }, dead: { on: { ALIVE: "alive", }, }, alive: { on: { DEAD: "dead", // GH#1054 we must have a way to send a node to sleep even if // it was previously detected as a non-sleeping device ASLEEP: { target: "asleep", cond: "canSleep", }, AWAKE: { target: "awake", cond: "canSleep", }, }, }, asleep: { on: { AWAKE: "awake", }, }, awake: { on: { ASLEEP: "asleep", }, }, }, }, { guards: { canSleep: () => !!node.canSleep, cannotSleep: () => !node.canSleep, }, }, ); }