Click or drag to resize
StaMaSimple State Machine Sample .NET Framework

The simple state machine sample demonstrates a minimal StaMa based state machine with two states and transtions between them. It runs in a Windows console application.

The sample doesn't have relevant real world functionality but can be used as a ready to use base for experiments with state machines.

Sample Simple State MachineNETFWK
Figure 1: Sample simple state machine console application
Demonstrates

The basic programming model for a StaMa based state machine.

How to implement a timeout transition based on a transition guard condition and the current time.

Example

The sample polls for keyboard input in a 100 msec loop in the main thread. The keyboard input is then forwarded through an event to the state machine.

If no keyboard input is available, the state machine checks the transition guard conditions, in particular the timeout.

Program.cs
using System;

namespace SampleSimpleStateMachineNETFWK
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine("Press E to trigger the transition from State1 to State2.");
            Console.WriteLine("Expect 2 seconds delay for timeout transition from State2 to State1.");
            Console.WriteLine("Press X or Space or ESC to exit.");

            SampleSimpleStateMachineNETFWK stateMachine = new SampleSimpleStateMachineNETFWK();

            bool exit = false;
            while (!exit)
            {
                DateTime startTime = DateTime.Now;
                if (Console.KeyAvailable)
                {
                    ConsoleKeyInfo key = Console.ReadKey(true);
                    switch (key.Key)
                    {
                        case ConsoleKey.E:
                            Console.WriteLine("{0} You pressed E!", DateTime.Now.ToString("HH:mm:ss.fff"));
                            stateMachine.KeyPressed(key.Key);
                            break;
                        case ConsoleKey.X:
                        case ConsoleKey.Spacebar:
                        case ConsoleKey.Escape:
                            Console.WriteLine("{0} Closing application.", DateTime.Now.ToString("HH:mm:ss.fff"));
                            stateMachine.Finish();
                            exit = true;
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    stateMachine.CheckTimeouts();
                }
                System.Threading.Thread.Sleep(100); // Throttle CPU load.
            }
        }
    }
}
SampleSimpleStateMachineNETFWK.cs
using System;
using StaMa;

namespace SampleSimpleStateMachineNETFWK
{
    class SampleSimpleStateMachineNETFWK
    {
        private StateMachine m_stateMachine;
        private DateTime m_state2Entered;


        public SampleSimpleStateMachineNETFWK()
        {
            StateMachineTemplate t = new StateMachineTemplate();

            //## Begin Structure
            // Generated from <file:S:\StaMa_State_Machine_Controller_Library\StaMaShapesMaster.vst> page "SampleSimpleStateMachineNETFWK"
            // at 07-22-2015 22:09:50 using StaMaShapes Version 2300
            t.Region("State1", false);
                t.State("State1", EnterState1, ExitState1);
                    t.Transition("Transition1to2", "State2", "Event1", null, null);
                t.EndState();
                t.State("State2", EnterState2, ExitState2);
                    t.Transition("Transition2to1", "State1", null, IsState2Timeout, null);
                t.EndState();
            t.EndRegion();
            //## End Structure

            m_stateMachine = t.CreateStateMachine();
            m_stateMachine.TraceStateChange = this.TraceStateChange;

            m_stateMachine.Startup();
        }


        public void Finish()
        {
            m_stateMachine.Finish();
        }


        public void KeyPressed(ConsoleKey key)
        {
            m_stateMachine.SendTriggerEvent("Event1");
        }


        public void CheckTimeouts()
        {
            m_stateMachine.SendTriggerEvent(null);
        }


        private void EnterState1(StateMachine stateMachine, object triggerEvent, EventArgs eventArgs)
        {
            Console.WriteLine("Called EnterState1");
        }


        private void ExitState1(StateMachine stateMachine, object triggerEvent, EventArgs eventArgs)
        {
            Console.WriteLine("Called ExitState1");
        }


        private void EnterState2(StateMachine stateMachine, object triggerEvent, EventArgs eventArgs)
        {
            Console.WriteLine("Called EnterState2");
            m_state2Entered = DateTime.Now;
        }


        private void ExitState2(StateMachine stateMachine, object triggerEvent, EventArgs eventArgs)
        {
            Console.WriteLine("Called ExitState2");
        }


        private bool IsState2Timeout(StateMachine stateMachine, object triggerEvent, EventArgs eventArgs)
        {
            return DateTime.Now - m_state2Entered > new TimeSpan(0, 0, 0, 2);
        }


        private void TraceStateChange(StateMachine stateMachine,
                                      StateConfiguration stateConfigurationFrom,
                                      StateConfiguration stateConfigurationTo,
                                      Transition transition)
        {
            Console.WriteLine("{0} ActiveState={1} entered through Transition={2}",
                              DateTime.Now.ToString("HH:mm:ss.fff"),
                              stateConfigurationTo.ToString(),
                              (transition != null) ? transition.Name : "Startup/Finish");
        }
    }
}