Thanks a lot Roland. Good stuff for the docs 
I tried the B approach but could not see the three parallel state machines. Can you show code that reads states and sends signals to each orthogonal state?
Thanks a lot Roland. Good stuff for the docs 
I tried the B approach but could not see the three parallel state machines. Can you show code that reads states and sends signals to each orthogonal state?
The below Windows console application creates the state machine from my last reply and sends the Init, Part3Initialized, Part1Initialized and Part2Initialized events to the state machine.
Trace output for state changes, entry and exit of states is written to the console.
Please note that the transition to the āSystemInitializedā state is automatically triggered with the last event for the sub-parts (āPart2Initializedā) due to ārun to completionā processing.
Please find the corresponding state machine diagram attached.
using System;
using StaMa;
namespace ForkAndJoin
{
class Program
{
//## Begin StateAndTransitionNames71
// Generated from <file:...\ForkAndJoin.vsd>
// at 08-03-2014 20:03:35 using StaMaShapes Version 2
private static readonly string Uninitialized = "Uninitialized";
private static readonly string Transi43 = "Transi43";
private static readonly string Init = "Init";
private static readonly string SystemInitializing = "SystemInitializing";
private static readonly string Transi57 = "Transi57";
private static readonly string Initialized1 = "Initialized1";
private static readonly string Initializing1 = "Initializing1";
private static readonly string Transi48 = "Transi48";
private static readonly string Part1Initialized = "Part1Initialized";
private static readonly string Initialized2 = "Initialized2";
private static readonly string Initializing2 = "Initializing2";
private static readonly string Transi50 = "Transi50";
private static readonly string Part2Initialized = "Part2Initialized";
private static readonly string Initialized3 = "Initialized3";
private static readonly string Initializing3 = "Initializing3";
private static readonly string Transi52 = "Transi52";
private static readonly string Part3Initialized = "Part3Initialized";
private static readonly string SystemInitialized = "SystemInitialized";
//## End StateAndTransitionNames71
static void Main(string[] args)
{
StateMachineTemplate t = new StateMachineTemplate();
//## Begin StateMachineTemplate66
// Generated from <file:...\ForkAndJoin\ForkAndJoin.vsd>
// at 08-03-2014 20:03:35 using StaMaShapes Version 2
t.Region(Uninitialized, false);
t.State(Uninitialized, (stm, ev, arg) => Console.WriteLine("Enter Unintialized"), (stm, ev, arg) => Console.WriteLine("Exit Uninitialized"));
t.Transition(Transi43, Uninitialized, new string[] {Initializing1, Initializing2, Initializing3}, Init, null, null);
t.EndState();
t.State(SystemInitializing, (stm, ev, arg) => Console.WriteLine("Enter SystemInitializing"), (stm, ev, arg) => Console.WriteLine("Exit SystemInitializing"));
t.Transition(Transi57, new string[] {Initialized1, Initialized2, Initialized3}, SystemInitialized, null, null, null);
t.Region(Initializing1, false);
t.State(Initialized1, (stm, ev, arg) => Console.WriteLine("Enter Initialized1"), (stm, ev, arg) => Console.WriteLine("Exit Initialized1"));
t.EndState();
t.State(Initializing1, (stm, ev, arg) => Console.WriteLine("Enter Initializing1"), (stm, ev, arg) => Console.WriteLine("Exit Initializing1"));
t.Transition(Transi48, Initializing1, Initialized1, Part1Initialized, null, null);
t.EndState();
t.EndRegion();
t.Region(Initializing2, false);
t.State(Initialized2, (stm, ev, arg) => Console.WriteLine("Enter Initialized2"), (stm, ev, arg) => Console.WriteLine("Exit Initialized2"));
t.EndState();
t.State(Initializing2, (stm, ev, arg) => Console.WriteLine("Enter Initializing2"), (stm, ev, arg) => Console.WriteLine("Exit Initializing2"));
t.Transition(Transi50, Initializing2, Initialized2, Part2Initialized, null, null);
t.EndState();
t.EndRegion();
t.Region(Initializing3, false);
t.State(Initialized3, (stm, ev, arg) => Console.WriteLine("Enter Initialized3"), (stm, ev, arg) => Console.WriteLine("Exit Initialized3"));
t.EndState();
t.State(Initializing3, (stm, ev, arg) => Console.WriteLine("Enter Initializing3"), (stm, ev, arg) => Console.WriteLine("Exit Initializing3"));
t.Transition(Transi52, Initializing3, Initialized3, Part3Initialized, null, null);
t.EndState();
t.EndRegion();
t.EndState();
t.State(SystemInitialized, (stm, ev, arg) => Console.WriteLine("Enter SystemInitialized"), (stm, ev, arg) => Console.WriteLine("Exit SystemInitialized"));
t.EndState();
t.EndRegion();
//## End StateMachineTemplate66
StateMachine stateMachine = t.CreateStateMachine();
stateMachine.TraceStateChange = delegate(StateMachine stm, StateConfiguration from, StateConfiguration to, Transition transi)
{
Console.WriteLine(String.Format("StateChange From={0} To={1} Transition={2}", from.ToString(), to.ToString(), (transi != null) ? transi.Name : "Startup/Finish"));
};
stateMachine.Startup();
stateMachine.SendTriggerEvent(Init);
stateMachine.SendTriggerEvent(Part3Initialized);
stateMachine.SendTriggerEvent(Part1Initialized);
stateMachine.SendTriggerEvent(Part2Initialized);
stateMachine.Finish();
// The above sequence of events creates the following output:
// StateChange From=* To=Uninitialized Transition=Startup/Finish
// Enter Unintialized
// StateChange From=Uninitialized To=SystemInitializing(Initializing1,Initializing2,Initializing3) Transition=Transi43
// Exit Uninitialized
// Enter SystemInitializing
// Enter Initializing1
// Enter Initializing2
// Enter Initializing3
// StateChange From=SystemInitializing(Initializing1,Initializing2,Initializing3) To=SystemInitializing(Initializing1,Initializing2,Initialized3) Transition=Transi52
// Exit Initializing3
// Enter Initialized3
// StateChange From=SystemInitializing(Initializing1,Initializing2,Initialized3) To=SystemInitializing(Initialized1,Initializing2,Initialized3) Transition=Transi48
// Exit Initializing1
// Enter Initialized1
// StateChange From=SystemInitializing(Initialized1,Initializing2,Initialized3) To=SystemInitializing(Initialized1,Initialized2,Initialized3) Transition=Transi50
// Exit Initializing2
// Enter Initialized2
// StateChange From=SystemInitializing(Initialized1,Initialized2,Initialized3) To=SystemInitialized Transition=Transi57
// Exit Initialized3
// Exit Initialized2
// Exit Initialized1
// Exit SystemInitializing
// Enter SystemInitialized
// StateChange From=SystemInitialized To=* Transition=Startup/Finish
// Exit SystemInitialized
}
}
}
@ Roland - thanks again for carefully crafted response. Thanks
Its all good, makes me want to experiment. What I dont see is how I check the current state of the middle orthogonal state.
There is three simultaneous states in progress, and they can be any state. And what if the two orthogonal states receive the same signal, will only one get it, or both?
Iām hoping youāll let me participate in this thread in the hopes of becoming user #2. I use state machines as a mater of course for almost all my projects. However, Iām having trouble mapping my understanding and usage to your implementation.
In my current application, I have a state machine implemented in my usual crude way as an switch/case block inside a while loop. Each case is a distinct state.
Each state has a state entry block for stuff that happens once at the beginning of the state, a main body that handles what ever the state needs to do and looks for the the state exit conditions each pass through the while loop, and a state exit block that does the cleanup when transitioning to a new state.
I also have queue for all the event handlers in my program to dump data structures into. Anything in the queue gets taken care of each pass through the while loop. For example, all my serial port event handlers dump their messages (as a data structure) onto the queue when a complete message arrives along with a time stamp and an error code.
This might be a tough question but can I ask how that maps to your state machine implementation?
@ Gene - thanks Gene and welcome.
I guess your approach is ānormalā and you would benefit a lot from seperation of concerns. Put your io into threads and model your states with stama. You will find the benefits in your speed to deliver and reduced āweird behaviourā.
My app is moderately straight forward to explain. It is a profiling float for oceanographic research. Basically a bunch of RS232 instruments stuck on a pressure housing that profiles vertically up and down in the ocean sometimes stopping at a particular depth and sometime anchoring on the bottom. Several times a day the float comes to the surface and telemeters all its data over Iridiumā¦
Hereās what Iām thinking for how I might use StaMa. Make the whole app an event driven state machine. Iāve only got a few events like: 1) a character comes in on a serial port. 2) Iāve reached a certain depth and need to do something like sample an instrument or enter the āparkā state 3) One of several timers goes off that says to do something like sample a specific instrument, adjust my buoyancy control engine, stop descending or a couple of other time driven things.
So hereās a specific example to see if stama is appropriate. Iām descending through the water column and the state machine (SM) is in the idle state. The depth sensor spits up one character of its depth message on its serial port. Arrival of the character transitions the SM into the state that calls the method that handles the depth sensor data. If the character that came in is the last character in the depth message, update the current depth value Then back to the idle state. Nothing happens until another character comes in or a timer goes off. Letās say itās my buoyancy control timer. That transitions the SM into the buoyancy control method where I do a PID loop on the latest depth and adjust the buoyancy engine. Then back to the idle state and so on for every event that might happen.
What I havenāt been able to figure out is how to get these kind of events to trigger a state transition in stama.
Hello Niels,
Checking for a state can be done through the StateMachine.IsInState method.
The IsInState method requires a so-called StateConfiguration which in turn can be created through the StateMachineTemplate.CreateStateConfiguration method.
Checking if the stateMachine in the previous example is in state āInitializing2ā could be acconplished like this:
StateConfiguration stateCfgInitializing2 = t.CreateStateConfiguration(Initializing2);
bool isInInitializing2 = stateMachine.IsInState(stateCfgInitializing2);
The StateConfiguration class generalizes the specification of a state for the case of hierarchy and orthogonality where a single state name isnāt sufficient to uniquely specify the StateMachine current state.
Passing in the single state name creates a āpartiallyā defined StateConfiguration that leaves the first and third orthogonal state unspecified.
StateConfiguration instances are constructed separately through the StateMachineTemplate because they are a little more time consuming to build and involve consistency checks.
Once created, the comparison with the StateMachine current state should be quite fast.
Events are propagated to each orthogonal region. All transitions that are active (i.e. the trigger type matches and the guard returns true) are collected and will be executed one after each other according to the defined order.
Active higher level transitions take precendence over nested transitions.
Roland.
Hello Gene,
welcome. Your project sounds exciting.
Iām not sure if I understood everything correctly.
Your software reads single bytes from RS232 through the same state machine that controls higher level functions like ascending/descending?
Control of the continuous diving depth is controlled through a state machine with discrete states?
At first sight this sounds unexpected for me, but maybe it is due to lack of understanding and knowledge.
I would expect some separation/layering of lower level component controllers which would act asynchronously and a higher level main operations controller. The higher level operations controller is a clear candidate for a state machine, the lower level component controllers could be implemented through any suitable approach, where applicable also with a state machine.
So I agree with Nielsā reply #24.
Iām not sure if this thread will become messy, if we start discussing the system design of Your application. Maybe this is worth itās own thread?
Questions regarding StaMa as a library and tool are welcome here.
But this is Nielsā thread.
Roland.
Thanks for your reply. I am working on implementing your replies. Have some 4.3 challenges to solve before testing commences. But these are examples of things that would be impossible without you or documentation.
But I MISS the documentation 
Thanks again
@ Roland - Are you planning to port to 4.3 soon?
You have many ā#if !MF_FRAMEWORK_VERSION_V4_2ā which probably should be changed to ā#if !MF_FRAMEWORK_VERSION_V4_3ā and that should be itā¦?
Niels,
locally I āportedā to NETMF 4.3 with the following results:
In next release the StaMaNETMF.csproj defines a generic version independent symbol MF_FRAMEWORK. Clients may switch to whatever framework version they use and recompile the assembly.
You donāt have to wait, You could do that today if needed:
Gene,
from my perspective I see now 2 basic kinds of state machine applications:
In case Your application is an open loop controller You would have to do the following to integrate StaMa:
The below Windows console application shows how this would actually work.
The application cycles with 100ms and reads input and writes text.
The state machine has 2 states. It switches from StateA to StateB when the B key is pressed and falls back to StateA when the do-activity counter in StateB reaches 20.
using System;
using System.Runtime.InteropServices;
using StaMa;
namespace ControlLoop
{
static class Program
{
[STAThread]
static void Main()
{
Console.WriteLine(@ "Hello");
bool aPressed = false;
bool bPressed = false;
bool rShiftKeyPressed = false;
int counter = 0;
// Initialize the (here simple) state machine structure
StateMachineTemplate t = new StateMachineTemplate();
t.Region("StateA", false);
t.State("StateA", null, null);
t.Transition("T1", "StateA", "StateB", null, (stm, ev, args) => bPressed, null);
t.EndState();
t.State("StateB", null, (stm, ev, args) => counter = 0);
// t.StateDoActivity((stm) => counter += 1); Proposal how to configure do-activities
t.Transition("T2", "StateB", "StateA", null, (stm, ev, args) => counter == 20, null);
t.EndState();
t.EndRegion();
// Define do-activities to be executed while the state machine is in the state
DoActions doActions = new DoActions(delegate(string stateName)
{
switch (stateName)
{
default:
break;
case "StateB":
counter += 1;
break;
}
});
// Init state machine instance
StateMachine stateMachine = t.CreateStateMachine();
stateMachine.Startup();
bool runLoop = true;
while (runLoop)
{
// Get some input
aPressed = GetKeyPressed(ConsoleKey.A);
bPressed = GetKeyPressed(ConsoleKey.B);
rShiftKeyPressed = GetKeyPressed((ConsoleKey)0xa1);
// Throw away unneccessary characters
while (Console.KeyAvailable)
{
Console.ReadKey(true);
}
// Execute the state machine
stateMachine.SendTriggerEvent(null);
StateConfiguration currentState = stateMachine.ActiveStateConfiguration;
// Execute the do-activities of the active states
currentState.PassThrough(doActions);
// Write info about current state
Console.Write(String.Format("{0} \r", currentState.ToString()));
// Throttle speed
System.Threading.Thread.Sleep(100);
}
}
private class DoActions : IStateConfigurationVisitor
{
private Action<string> myDoActions;
public DoActions(Action<string> doActions)
{
myDoActions = doActions;
}
void IStateConfigurationVisitor.BeginSubStates()
{
}
void IStateConfigurationVisitor.EndSubStates()
{
}
void IStateConfigurationVisitor.NextSubState()
{
}
void IStateConfigurationVisitor.State(string stateName)
{
myDoActions(stateName);
}
void IStateConfigurationVisitor.StateAny()
{
throw new NotImplementedException();
}
}
[DllImport("User32.dll")]
private static extern ushort GetAsyncKeyState(int vKey);
private static bool GetKeyPressed(ConsoleKey key)
{
return (GetAsyncKeyState((int)key) & 0xF000) != 0;
}
}
}
The switch/case doesnāt look nice. But this is a sample to demonstrate that programmable logic controller like execution can be supported in StaMa.
Does this help?
Roland.
This is a lot of help. Iām at the tail end of getting my current switch/case statement state machine with asynchronous queue for IO fully tested. When things calm down a little bit Iām planning on taking a good look at your StaMa.
Thanks for the help.
Cheers - Gene
@ Roland Schneider - This is exceptionally cool stuff, I did not even imagine how cool this is.
Thanks
@ Roland Schneider
Hi Roland.
Weāre starting a new project using your amazing StaMa library.
Since weād like to add some small changes (e.g. Transition parameter on TransitionActivity and TransitionGuard delegates, in order to promote usage of generic code), do you accept pull requests or similar in order to (validate and) merge 3rd party contributions?
Also, as you surely know, Visio running on x64 doesnāt allow use of Scripting COM component, so itās very hard to get your VBA code running. Did you ever try any alternative code generation technique?
We would be also interested in scenarios, best practices and patterns concerning usage of StaMa framework in automation āspaceā,so it would be great if you could provide some reference sample related to, for example, coordination among async and partially inter-dependent automas.
Thanks!
Hello www.innovactive.it (?),
thank You very much for Your interest in StaMa.
Of course You are welcome to make proposals for improvement.
Obviously the fork button is missing in the StaMa Codeplex source code page, other pages have it.
Do You know how I can enable it? Iād gladly turn that functionality on, if possible.
[Update 2014-12-10] Fork of TFS based projects is not supported, see http://codeplex.codeplex.com/discussions/355769. Would require to convert to Git or Mercurial.
Regarding parameters for transitions and guards: There is already an overload StateMachine.SendTriggerEvent(Object,EventArgs) which forwards an additional EventArgs parameter to the StateMachineGuardCallback or StateMachineActivityCallback.
Could You use this?
A long time ago I tried out making StaMa more typesafe with generic parameters, but it ended that nearly all methods or classes throughout StaMa required this generic parameter. So I discarded this change, as it makes so much of the source code lengthy.
Further NETMF doesnāt support generics (or?), therefore introducing generics would require to deliver separate code for NETMF and .NET Framework for Windows.
But generally Iām open towards generics in case a majority wants it.
Visio is a controversial tool.
Definitely it would be nice to have a freeware tool for drawing and generating code.
Could You use the 32bit version of Visio? From my point of view there is no advantage in running MS Office applications as 64bit.
Unfortunately I cannot provide more complex samples or specific samples for a technical domain.
Iām currently preparing a developers guide that explains the library in more detail, however the documentation doesnāt contain more complex samples.
Eventually Niels has something that helps You.
Roland.
@ Roland Schneider - The version I saw of the developer guide, where state of the art documentation, and deserves a release! 
I dont have problems with Visio on 32bit, and its the same licenseā¦
Looking forward to more updates from youā¦
StaMa State Machine Controller Library 2.2 is released and targets NETMF 4.3 / VS2012
The documentation for the library and Visio shapes is included in the package as a .chm file and available through http://StaMa.org/ .
Please have a look into it and report at StaMa home if something is unclear or needs improvement.
@ Gene: StaMa now allows to specify do-actions at the state definition.
Do-actions are executed within the StateMachine.SendTriggerEvent method.
Periodically calling SendTriggerEvent in a loop with e.g. 100ms should allow to execute an open or closed loop control algorithm within the do-actions, like described above.
Do-actions have to be enabled explicitly at the StateMachineTemplate constructor.
Thanks Niels for contributing the stama.org domain.
Roland.
Now there is no excuse for getting started with state machines and increase the quality of your projects. 
This might be of interest to you: http://www.visual-paradigm.com/support/documents/vpuserguide/94/2579/6714_creatingstat.html