@nanomatic/fsm
Implementation of the Finite State Machine.
📝 Table of Contents
🏁 Getting Started
Installing
npm i @nanomatic/fsm
Using
Example code below:
import { State, StateMachine } from '@nanomatic/fsm';
/*
Three states. Steps:
1. All devices turned off.
2. Lamp turned on after three seconds (simulated user operation).
3. Motor turned on after another three seconds.
4. Go to the step 1 after ten seconds from beginig.
FSM will be paused after 4 seconds from the start.
Another 4 seconds to resume.
*/
// Time in s
const hundredMiliseconds = .1;
const threeSeconds = 3;
const fourSeconds = 4;
const eightSeconds = 8;
const fiveteenSeconds = 15;
// Types
interface Data {
lamp: boolean;
motor: boolean;
start: boolean;
}
// Variables
let showLogs = true;
const data: Data = {
lamp: false,
motor: false,
start: false
};
// Helper function
const allSwitchOff = () => {
data.lamp = false;
data.motor = false;
showLogs = false;
};
// States
const allOff = new State;
const lampOn = new State(() => data.lamp = true);
const motorOn = new State({ entry: () => data.motor = true, exit: allSwitchOff });
console.log(`Total number of states: ${State.states}`);
// State machine
// const fsm = new StateMachine(allOff); // Step 1 (immediately)
const fsm = new StateMachine<Data>(allOff); // Step 1 (immediately)
// Transitions
allOff.addTransition(lampOn, ({ start }: Data) => start); // Step 2 (after three seconds)
lampOn.addTransition(motorOn); // Step 3 (automatic flow after another three seconds)
lampOn.time = threeSeconds; // When time is equal to zero then transition fire imiditly
// lampOn.time = () => threeSeconds;
fsm.addCommonState(allOff, [], ({ start }: Data) => !start); // Step 4 (after ten seconds from beginig)
// Program cycle (100 ms)
setInterval(() => fsm.step(data), hundredMiliseconds);
// Only for data simulation
setTimeout(() => data.start = true, threeSeconds * 1000); // Step 2 (after three seconds)
setTimeout(() => data.start = false, fiveteenSeconds * 1000); // Step 4 (after ten seconds from beginig)
const programInterval = setInterval(() => {
// tslint:disable-next-line: no-console
console.log(`Lamp: ${data.lamp}\tMotor: ${data.motor}\tStart: ${data.start}\tRemaining time: ${fsm.state.timer.remainingTime.toFixed(3)}s`);
if (!showLogs)
clearInterval(programInterval);
}, hundredMiliseconds * 1000);
setTimeout(() => fsm.pause(), fourSeconds * 1000); // Pause after 4 seconds
setTimeout(() => fsm.resume(), eightSeconds * 1000); // Resume after next 4 seconds
⛏️ Built With
- ts-node-dev - TypeScript Node Dev
- tsc-watch - The nodemon for TypeScript
- TSLint - TypeScript linter
- NodeJs - Test Environment
📦 Dependencies
- @nanomatic/timer - Implementation of the reuseable timer
✍️ Authors
- @NANOmatic - Idea & Initial work
🎉 Acknowledgments
- Special thanks for Sebastian for working together and giving ideas
😉