zwave-js
Version:
Z-Wave driver written entirely in JavaScript/TypeScript
142 lines • 4.75 kB
JavaScript
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