State Machines
Components
Machines
A collection of States, Transitions and Actions. At the end of any given step each serial-sub-state within a machine will contain exactly one active state.
States
A state encapsulates a set of logic to be evaluated when active. States can be
hierarchical. A parent state is active if any of its child-states are active.
Each state has three phases of execution, entry, during, and exit. When a
State changes from inactive to active, its entry actions are evaluated. When a
State starts active and ends active (in a given step), its during actions are
evaluated. When a State changes from active to inactive, its exit actions are
evaluated.
Actions
Actions define processing within various scopes. Actions can be used to update the Machine local variables, set global variables, or make call-outs to external web services.
Transitions
The Transition defines a path between two states, the From-State and the To-State. Once a transition is executed, the From-State becomes inactive and the To-State becomes active. Transitions can include Actions which are evaluated once the transition is executed
Events
An alternate input-scheme which can be used instead-of or alongside local variables. Events can be useful if your approach includes combining several calculations ahead of evaluating the state-machine. The catch is that only a single Event can be handled by the state-machine for any given step.
Execution
State Machine Execution
Initialization
Once a Machine is created, it will sit in an uninitialized state, whereby no
state is active and no transitions have been evaluated. If the first call to
myMachine.step() happens before the machine is initialized, it will automatically
initialize the Machine. It’s best practice to explicitly initialize the Machine,
once construction is complete by calling myMachine.initialize().
During initialization, at each level in the hierarchy, the initial state is
determined during construction by explicitly specifying {initial: true} in the
desired state
if two states at the same level are specified as
initial, the last one specified wins
From the top of the hierarchy down, each initial-transition is identified and evaluated. The machine is fully initialized once every state has the appropriate number of active states as defined by it’s Decomposition (serial vs parallel).
Step
Once a Machine is initialized, it can be “stepped” through time. Each step represents a discrete point in time (in our specific case, the machine is “stepped” upon receipt of each IoT Message).
During the step, all Transitions from the active state hierarchy are evaluated
from the top, down. That is to say, given active state, B.B.B, all Transitions
out of the top state B are evaluated in priority order, executing the first
Transition who’s condition expression evaluates to true or who’s condition
doesn’t exists (i.e. an Unconditional Transition). If no Transitions at level
B are to be executed, all Transitions at the B.B level are evaluated in the
same manor until either a Transition is identified to evaluate, or no
Transitions are to be taken.
If a Transition is identified to evaluate, first the exit actions in the
lowest level From-State are evaluated, then the exit actions are evaluated up
the hierarchy until the lowest-common State between From-State and To-State.
Meaning in a transition from B.B.B to B.B.A, only the exit actions from
B.B.B are evaluated (since B.B is never exited during the transition).
Whereas if transitioning from B.B.B to A.B, the exit actions at B.B.B,
B.B, and B are evaluated.
If no Transitions are to be evaluated, the during actions of the current
active state are evaluated from the top, down.
Examples
Full Example
Illustrative (not functional) State Machine containing all possible features of the State Machine library.
Initialization:
- The initial transition into B is evaluated and the local variable,
time0is set tonow. - B is activated.
- B entry actions are evaluated, incrementing the machine variable,
bEntry - States B.A and B.B run in parallel (indicated by the dashed border). B.A and B.B are activated.
- So, the initial transitions into B.A.B and B.B.B are executed.
- Both B.A.B and B.B.B are activated.
Step 1:
- Both B.A.B and B.B.B are active.
- First there exists a transition at the top level,
somethingElse < 50. If this evaluates totrue, then all active children ofBare exited and deactivated from the bottom up. For this example let’s assumesomethingElse = 100, so this transition will not be executed. - Since the transition from B.B.B to B.B.A is unconditional, it is marked for evaluation.
- B.B.B exit actions are evaluated (local variable,
bbbExitis incremented) - B.B.B is deactivated
- If there were any actions defined on this transition, they’d be evaluated here.
- B.B.A is activated
- B.B.A entry actions are evaluated (local variable,
bbais nowtrue) - B during actions are evaluated (
bDuringis incremented)
Step 2:
- Both B.A.B and B.B.A are active.
- There are two transitions out of B.B.A (priority can be set on
transitions to handle this case). If
something < 10, then transition 1 would be marked for evaluation, otherwise, transition 2 is unconditional, so it will be marked for evaluation by default. For this example, let’s saysomething = 6, so transition 1 is marked for evaluation. - B.B.A is deactivated
- B.A.B is deactivated
- B.A is deactivated
- B.B is deactivated
- B.B exit actions are evaluated (
bbExitis incremented) - B is deactivated
- If there were any actions defined on this transition, they’d be evaluated here.
- A is activated
- A.A is activated
Advanced Topics
State-Decomposition
At any given level in the state-hierarchy, there are two possible modes of
execution: Serial (default) and Parallel. Serial decomposition defines that at
a given level, there is only ever a single active state at the end of any
give step. Contrary, Parallel decomposition defines that all states at a given
level are active. In the examples below, the Serial State Machine will only
ever have a single active state (e.g. 'A.B' or 'B.A.B'), whereas the
Parallel State Machine will have 3 active states at any given time (e.g.
['A.A', 'B.A.B', 'B.B.A'] etc.)
Serial State Machine
Parallel State Machine