Sample State Machine
This is a sample state machine.
Definition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | var elevator = new PassiveStateMachine<States, Events>( "Elevator" ); elevator.DefineHierarchyOn(States.Healthy) .WithHistoryType(HistoryType.Deep) .WithInitialSubState(States.OnFloor) .WithSubState(States.Moving); elevator.DefineHierarchyOn(States.Moving) .WithHistoryType(HistoryType.Shallow) .WithInitialSubState(States.MovingUp) .WithSubState(States.MovingDown); elevator.DefineHierarchyOn(States.OnFloor) .WithHistoryType(HistoryType.None) .WithInitialSubState(States.DoorClosed) .WithSubState(States.DoorOpen); elevator.In(States.Healthy) .On(Events.ErrorOccured).Goto(States.Error); elevator.In(States.Error) .On(Events.Reset).Goto(States.Healthy) .On(Events.ErrorOccured); elevator.In(States.OnFloor) .ExecuteOnEntry( this .AnnounceFloor) .ExecuteOnExit(Beep) .ExecuteOnExit(Beep) // just beep a second time .On(Events.CloseDoor).Goto(States.DoorClosed) .On(Events.OpenDoor).Goto(States.DoorOpen) .On(Events.GoUp) .If(CheckOverload).Goto(States.MovingUp) .Otherwise().Execute( this .AnnounceOverload, Beep) .On(Events.GoDown) .If(CheckOverload).Goto(States.MovingDown) .Otherwise().Execute( this .AnnounceOverload); elevator.In(States.Moving) .On(Events.Stop).Goto(States.OnFloor); elevator.Initialize(States.OnFloor); |
The above state machine uses these actions and guards:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private void AnnounceFloor() { /* announce floor number */ } private void AnnounceOverload() { /* announce overload */ } private void Beep() { /* beep */ } private bool CheckOverload() { return whetherElevatorHasOverload; } |
Run the State Machine
This is a small sample to show how to interact with the state machine:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // queue some events to be performed when state machine is started. elevator.Fire(Events.ErrorOccured); elevator.Fire(Events.Reset); elevator.Start(); // these events are performed immediately elevator.Fire(Events.OpenDoor); elevator.Fire(Events.CloseDoor); elevator.Fire(Events.GoUp); elevator.Fire(Events.Stop); elevator.Fire(Events.OpenDoor); elevator.Stop(); |
Log
If you add the log4net log extensions available in the Appccelerate.SourceTemplate package:
1 | elevator.AddExtension( new Appccelerate.Log4Net.StateMachineLogExtension<States, Events>( "Elevator" )); |
to the above code then these are the log messages (if all are enabled - see log4net documentation on how to configure log messages). Note how the state exits and enters are logged, especially for hierarchical transitions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | Logger Level Message Elevator INFO State machine Elevator initializes to state OnFloor. Elevator INFO State machine Elevator switched from state to state DoorClosed. Elevator DEBUG State machine Elevator performed -> Enter Healthy -> Enter OnFloor -> Enter DoorClosed. Elevator INFO Fire event ErrorOccured on state machine Elevator with current state DoorClosed and event arguments . Elevator INFO State machine Elevator switched from state DoorClosed to state Error. Elevator DEBUG State machine Elevator performed -> Exit DoorClosed -> Exit OnFloor -> Exit Healthy -> Enter Error. Elevator INFO Fire event Reset on state machine Elevator with current state Error and event arguments . Elevator INFO State machine Elevator switched from state Error to state DoorClosed. Elevator DEBUG State machine Elevator performed -> Exit Error -> Enter Healthy -> Enter OnFloor -> Enter DoorClosed. Elevator INFO Fire event OpenDoor on state machine Elevator with current state DoorClosed and event arguments . Elevator INFO State machine Elevator switched from state DoorClosed to state DoorOpen. Elevator DEBUG State machine Elevator performed -> Exit DoorClosed -> Enter DoorOpen. Elevator INFO Fire event CloseDoor on state machine Elevator with current state DoorOpen and event arguments . Elevator INFO State machine Elevator switched from state DoorOpen to state DoorClosed. Elevator DEBUG State machine Elevator performed -> Exit DoorOpen -> Enter DoorClosed. Elevator INFO Fire event GoUp on state machine Elevator with current state DoorClosed and event arguments . Elevator INFO State machine Elevator switched from state DoorClosed to state MovingUp. Elevator DEBUG State machine Elevator performed -> Exit DoorClosed -> Exit OnFloor -> Enter Moving -> Enter MovingUp. Elevator INFO Fire event Stop on state machine Elevator with current state MovingUp and event arguments . Elevator INFO State machine Elevator switched from state MovingUp to state DoorClosed. Elevator DEBUG State machine Elevator performed -> Exit MovingUp -> Exit Moving -> Enter OnFloor -> Enter DoorClosed. Elevator INFO Fire event OpenDoor on state machine Elevator with current state DoorClosed and event arguments . Elevator INFO State machine Elevator switched from state DoorClosed to state DoorOpen. Elevator DEBUG State machine Elevator performed -> Exit DoorClosed -> Enter DoorOpen. |
You can write your own extension for different logging.
Reports
yEd Report

csv Report
Source | Entry | Exit | Children |
OnFloor | AnnounceFloor | Beep, Beep | DoorClosed, DoorOpen |
Moving | MovingUp, MovingDown | ||
Healthy | OnFloor, Moving | ||
MovingUp | |||
MovingDown | |||
DoorClosed | |||
DoorOpen | |||
Error |
Source | Event | Guard | Target | Actions |
OnFloor | CloseDoor | DoorClosed | ||
OnFloor | OpenDoor | DoorOpen | ||
OnFloor | GoUp | CheckOverload | MovingUp | |
OnFloor | GoUp | internal transition | AnnounceOverload, Beep | |
OnFloor | GoDown | CheckOverload | MovingDown | |
OnFloor | GoDown | internal transition | AnnounceOverload | |
Moving | Stop | OnFloor | ||
Healthy | ErrorOccured | Error | ||
Error | Reset | Healthy | ||
Error | ErrorOccured | internal transition |
Textual Report
Elevator: initial state = OnFloor Healthy: initial state = OnFloor history type = Deep entry action: exit action: ErrorOccured -> Error actions: guard: OnFloor: initial state = DoorClosed history type = None entry action: AnnounceFloor exit action: Beep, Beep CloseDoor -> DoorClosed actions: guard: OpenDoor -> DoorOpen actions: guard: GoUp -> MovingUp actions: guard: CheckOverload GoUp -> internal actions: AnnounceOverload, Beep guard: GoDown -> MovingDown actions: guard: CheckOverload GoDown -> internal actions: AnnounceOverload guard: DoorClosed: initial state = None history type = None entry action: exit action: DoorOpen: initial state = None history type = None entry action: exit action: Moving: initial state = MovingUp history type = Shallow entry action: exit action: Stop -> OnFloor actions: guard: MovingUp: initial state = None history type = None entry action: exit action: MovingDown: initial state = None history type = None entry action: exit action: Error: initial state = None history type = None entry action: exit action: Reset -> Healthy actions: guard: ErrorOccured -> internal actions: guard: