Washer is a sample demonstrating a use of a history state to recover a running state configuration with a simulated power off situation.
Anyone ever used a washing machine knows that if you can somehow pause the program it will continue from a same state when lid is closed. This kind of behaviour can be implemented in a state machine by using a history pseudo state.
States.
public enum States {
RUNNING, HISTORY, END,
WASHING, RINSING, DRYING,
POWEROFF
}
Events.
public enum Events {
RINSE, DRY, STOP,
RESTOREPOWER, CUTPOWER
}
Configuration - states.
@Override public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception { states .withStates() .initial(States.RUNNING) .state(States.POWEROFF) .end(States.END) .and() .withStates() .parent(States.RUNNING) .initial(States.WASHING) .state(States.RINSING) .state(States.DRYING) .history(States.HISTORY, History.SHALLOW); }
Configuration - transitions.
@Override public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception { transitions .withExternal() .source(States.WASHING).target(States.RINSING) .event(Events.RINSE) .and() .withExternal() .source(States.RINSING).target(States.DRYING) .event(Events.DRY) .and() .withExternal() .source(States.RUNNING).target(States.POWEROFF) .event(Events.CUTPOWER) .and() .withExternal() .source(States.POWEROFF).target(States.HISTORY) .event(Events.RESTOREPOWER) .and() .withExternal() .source(States.RUNNING).target(States.END) .event(Events.STOP); }
Let’s see an example how this state machine actually works.
sm>sm start Entry state RUNNING Entry state WASHING State machine started sm>sm event RINSE Exit state WASHING Entry state RINSING Event RINSE send sm>sm event DRY Exit state RINSING Entry state DRYING Event DRY send sm>sm event CUTPOWER Exit state DRYING Exit state RUNNING Entry state POWEROFF Event CUTPOWER send sm>sm event RESTOREPOWER Exit state POWEROFF Entry state RUNNING Entry state WASHING Entry state DRYING Event RESTOREPOWER send
What happened in above run: