4. Define interface class between the state machine and its host
(also ok to use the host object itself):
structContext {bool powerOn;};
5. (Optional) Define type config:
usingConfig= hfsm2::Config::ContextT<Context>;
6. (Optional, recommended) Definehfsm2::Machine for convenience:
usingM= hfsm2::MachineT<Config>;
7. Declare state machine structure.
States need to be forward declared, e.g. with a magic macro:
#defineS(s) structsusingFSM= M::PeerRoot<S(Off), // initial top-level state M::Composite<S(On), // sub-machine region with a head state (On) and and 3 sub-statesS(Red), // initial sub-state of the regionS(Yellow),S(Green)>,S(Done)>;#undefS
8. (Optional) While HFSM2 transitions aren't event-based, events can be used to have FSM react to external stimuli:
structEvent {};
9. Define states and override required state methods:
structOff : FSM::State{voidentryGuard(FullControl& control) { // called before state activation, use to re-route transitionsif (control.context().powerOn) // access shared datacontrol.changeTo<On>(); // initiate a transition into 'On' region }};
structOn : FSM::State{voidenter(PlanControl& control) { // called on state activationauto plan =control.plan(); // access the plan for the regionplan.change<Red, Yellow>(); // sequence plan steps, executed when the previous state succeedsplan.change<Yellow, Green>();plan.change<Green, Yellow>();plan.change<Yellow, Red>(); }voidexit(PlanControl& /*control*/) {} // called on state deactivationvoidplanSucceeded(FullControl& control) { // called on the successful completion of all plan stepscontrol.changeTo<Done>(); }voidplanFailed(FullControl& /*control*/) {} // called if any of the plan steps fails};
structRed : FSM::State{voidupdate(FullControl& control) { // called on periodic state machine updatescontrol.succeed(); // notify successful completion of the plan step } // plan will advance to the 'Yellow' state};
structYellow : FSM::State{voidupdate(FullControl& control) {control.succeed(); // plan will advance to the 'Green' state on the first entry // and 'Red' state on the second one }};
structGreen : FSM::State{voidreact(constEvent&,FullControl& control) { // called on external eventscontrol.succeed(); // advance to the next plan step }};
structDone : FSM::State{};
10. Write the client code to use your new state machine: