UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

142 lines 4.75 kB
import { InterviewStage } from "@zwave-js/core"; import { cacheKeys } from "../../driver/NetworkCache.js"; import { createNodeReadyMachine, } from "../NodeReadyMachine.js"; import { createNodeStatusMachine, nodeStatusMachineStateToNodeStatus, } from "../NodeStatusMachine.js"; import { NodeStatus } from "../_Types.js"; import { NodeEventsMixin } from "./10_Events.js"; export class NodeStatusMixin extends NodeEventsMixin { constructor(nodeId, driver, index, deviceClass, supportedCCs) { super(nodeId, driver, index, deviceClass, supportedCCs); // Create the state machines this.statusMachine = createNodeStatusMachine(this); this.readyMachine = createNodeReadyMachine(); } statusMachine; _status = NodeStatus.Unknown; /** * Which status the node is believed to be in */ get status() { return this._status; } restartStatusMachine() { this.statusMachine.restart(); this.onStatusChange(NodeStatus.Unknown); } updateStatusMachine(input) { const newState = this.statusMachine.next(input)?.newState; if (newState) { this.statusMachine.transition(newState); this.onStatusChange(nodeStatusMachineStateToNodeStatus(newState.value)); } } onStatusChange(newStatus) { // Ignore duplicate events if (newStatus === this._status) return; const oldStatus = this._status; this._status = newStatus; if (this._status === NodeStatus.Asleep) { this._emit("sleep", this, oldStatus); } else if (this._status === NodeStatus.Awake) { this._emit("wake up", this, oldStatus); } else if (this._status === NodeStatus.Dead) { this._emit("dead", this, oldStatus); } else if (this._status === NodeStatus.Alive) { this._emit("alive", this, oldStatus); } // To be marked ready, a node must be known to be not dead. // This means that listening nodes must have communicated with us and // sleeping nodes are assumed to be ready this.updateReadyMachine({ value: this._status !== NodeStatus.Unknown && this._status !== NodeStatus.Dead ? "NOT_DEAD" : "MAYBE_DEAD", }); } /** * @internal * Marks this node as dead (if applicable) */ markAsDead() { this.updateStatusMachine({ value: "DEAD" }); } /** * @internal * Marks this node as alive (if applicable) */ markAsAlive() { this.updateStatusMachine({ value: "ALIVE" }); } /** * @internal * Marks this node as asleep (if applicable) */ markAsAsleep() { this.updateStatusMachine({ value: "ASLEEP" }); } /** * @internal * Marks this node as awake (if applicable) */ markAsAwake() { this.updateStatusMachine({ value: "AWAKE" }); } // The node is only ready when the interview has been completed // to a certain degree readyMachine; _ready = false; restartReadyMachine() { this.readyMachine.restart(); this.onReadyChange(false); } updateReadyMachine(input) { const newState = this.readyMachine.next(input)?.newState; if (newState) { this.readyMachine.transition(newState); this.onReadyChange(newState.value === "ready"); } } onReadyChange(ready) { // Ignore duplicate events if (ready === this._ready) return; this._ready = ready; if (ready) this._emit("ready", this); } /** * Whether the node is ready to be used */ get ready() { return this._ready; } set ready(ready) { this._ready = ready; } get interviewStage() { return (this.driver.cacheGet(cacheKeys.node(this.id).interviewStage) ?? InterviewStage.None); } set interviewStage(value) { this.driver.cacheSet(cacheKeys.node(this.id).interviewStage, value); // Mark the node as bootstrapped once the interview is complete if (value === InterviewStage.Complete) { this.bootstrapped = true; } } get bootstrapped() { return (this.driver.cacheGet(cacheKeys.node(this.id).bootstrapped) // When the cache entry is missing, we assume the node is bootstrapped // only if the interview is complete ?? this.interviewStage === InterviewStage.Complete); } set bootstrapped(value) { this.driver.cacheSet(cacheKeys.node(this.id).bootstrapped, value); } } //# sourceMappingURL=20_Status.js.map