A state machine automatic generation tool

Follow + star official account , don't miss exciting content

0ea0dad360f93c47581f5e4d02d85f4c.gif

Material source | Internet

Writing a state machine for a practical software system is not an easy task, especially when the state machine itself is relatively complex. Many programmers who have experienced similar experiences often describe it as a "uncreative" process , because they need to devote a lot of time and energy to how to manage the various states in the state machine, rather than the operating logic of the program itself.

As a general software design pattern, there must be more or less commonality between the state machines of various software systems, so people began to try to develop some tools to automatically generate the framework code of the finite state machine, and in Linux Next, there is a very good choice──FSME (Finite State Machine Editor).

Visualized FSME

fd092d92a975c75d16dc0ae66ecfa915.jpeg

FSME is a Qt-based finite state machine tool that allows users to graphically model the state machine required in the program, and can also automatically generate state machine framework code implemented in C++ or Python.

Let's take the state machine of the city gate in the figure below as an example to introduce how to use FSME to automatically generate the state machine code required in the program.

State machine controlling the gate

94912b8d47b86a8d580153325a670bd6.jpeg

1 State machine modeling

First run the fsme command to start the state machine editor, then click the "New" button on the toolbar to create a new state machine. There are five basic elements used to build a state machine in FSME: event (Event), input (Input), output (Output), state (State) and transition (Transition), which can be found in the tree list on the left side of the interface Four of them.

  • state modeling

Select the "States" item in the tree list on the left side of the FSME interface, then press the Insert key on the keyboard to insert a new state, then enter the name of the state in the "Name" text box at the bottom right, and then enter the name of the state at the top right Click the position where the state should be placed in the drawing area of ​​the , and a new state is created. In the same way, all the states required by the state machine can be added, as shown in the figure below.

state modeling

b0e3eef123144fdd59fcbbc95d63fe28.jpeg

  • event modeling

Select the "Events" item in the tree list on the left side of the FSME interface, then press the Insert key on the keyboard to add a new event, then enter the name of the event in the "Name" text box at the bottom right, and then click " Apply" button, a new event is created. In the same way, all events required by the state machine can be added, as shown in the figure below.

f107f8c78a4bcb732359bd546b33fff3.jpeg

  • transformation modeling

State transition is the most important part of the whole modeling process, it is used to define how one state in the finite state machine switches to another state. For example, when the state machine used to control the city gate is in the Opened state, if a Close event occurs at this time, the current state of the state machine will switch to the Closed state. Such a complete process can be used in the state machine model as closeDoor A transform to describe.

To add such a conversion in FSME, you first need to select the "Opened" item under "States" in the tree list on the left side of the interface, then press the Insert key on the keyboard to add a new conversion, and then click the Enter the transition name "closeDoor" in the "Name" text box, enter "Close" in the "Condition" text box to indicate that the condition that triggers the transition is the generation of the event Close, and select the "Closed" item in the "Target" drop-down box to indicate After the transition occurs, the state machine will be switched to the Closed state, and finally click the "Apply" button to define a new state transition relationship, as shown in the figure below. All transitions required by the state machine can be added in the same way.

transformation modeling

094521d2e489b1cf5a0d33a1129b3c71.jpeg

2 Generate state machine frame

Using FSME can not only perform visual state machine modeling, but more importantly, it can also automatically generate a state machine framework implemented in C++ or Python based on the obtained model. First select the "Root" item in the tree list on the left of the FSME interface, then enter the name of the state machine "DoorFSM" in the "Name" text box in the lower right corner, and then select the state "Opened" from the "Initial State" drop-down list As the initialization state of the state machine, it is shown in Figure 6.

Set initial properties

a50ba2da1258d62a272803f3751ed13b.jpeg

After saving the state machine model as a door.fsm file, use the following command to generate a header file containing the state machine definition:

[xiaowp@linuxgam code]$ fsmc door.fsm -d -o DoorFSM.h

Further, it is also possible to generate framework code that includes a state machine implementation:

[xiaowp@linuxgam code]$ fsmc door.fsm -d -impl DoorFSM.h -o DoorFSM.cpp

If you want to verify the generated state machine, you only need to manually write a piece of code for testing:

/*
 * TestFSM.cpp
 * 测试生成的状态机框架
 */

#include "DoorFSM.h"

int main()
{
  DoorFSM door;
  door.A(DoorFSM::Close);
  door.A(DoorFSM::Lock);
  door.A(DoorFSM::Unlock);
  door.A(DoorFSM::Open);
}

The finite state machine is driven by events. In the state machine framework code generated by FSME, method A() can be used to send corresponding events to the state machine, thus providing the "power" required for the normal operation of the state machine. The state machine is responsible for maintaining an event queue inside it, and all arriving events will be put into the event queue for waiting, so as to ensure that they will be processed sequentially in the order of arrival. When processing each incoming event, the state machine will check whether the transition condition corresponding to the state has been satisfied according to its current state, and activate the corresponding state transition process if it is satisfied.

The generated state machine skeleton and test code can be compiled into an executable file using the following command:

[xiaowp@linuxgam code]$ g++ DoorFSM.cpp TestFSM.cpp -o fsm

Since the -d option was used when generating the state machine code with the fsmc command, the generated state machine frame will contain certain debugging information, including the activation event of each state transition in the state machine, the state before the transition, the experienced transitions, transitioned states, etc., as follows:

[xiaowp@linuxgam code]$ ./fsm
DoorFSM:event:'Close'
DoorFSM:state:'Opened'
DoorFSM:transition:'closeDoor'
DoorFSM:new state:'Closed'
DoorFSM:event:'Lock'
DoorFSM:state:'Closed'
DoorFSM:transition:'lockDoor'
DoorFSM:new state:'Locked'
DoorFSM:event:'Unlock'
DoorFSM:state:'Locked'
DoorFSM:transition:'unlockDoor'
DoorFSM:new state:'Unlocked'
DoorFSM:event:'Open'
DoorFSM:state:'Unlocked'
DoorFSM:transition:'openDoor'
DoorFSM:new state:'Opened'

3 Custom state machine

The current state machine has been able to respond to various events from the outside, and properly adjust its current state, that is to say, the function of the state machine engine has been realized, and the next thing to do is to adjust the state machine according to the specific needs of the application. Customize to add to the state machine those processing logics related to the software system itself. In FSME, the operations related to specific applications are called Output. They are actually some virtual functions that need to be given specific implementation by the user. The automatically generated state machine engine is responsible for calling them when entering or exiting a certain state.

Still taking the state machine that controls the city gate as an example, suppose we want to add some processing logic when entering each state. First select the "Outputs" item in the tree list on the left side of the FSME interface, then press the Insert key on the keyboard to add a new output, then enter the corresponding name in the "Name" text box at the bottom right, and then click " Apply" button, a new output is created, as shown in the figure. All the outputs needed by the state machine can be added in the same way.

add output

ce0f8fa7286cc4b2ba29ec9263ed974f.jpeg

When all the outputs are defined, it is then possible to bind the corresponding outputs for each state in the state machine. First select the corresponding state in the "States" item on the left side of the FSME interface, then select the output corresponding to the state from the "Available" list box in the lower right corner, and then click the "<" button to add it to the "In" list, as shown in the figure. In the same way, corresponding outputs can be set for all states in the state machine. The same state can have multiple outputs. The output in the In list will be called when entering the state, and the output in the Out list will be It is called when exiting this state, and the order of output calls is consistent with its order in the In or Out list.

The picture shows the state setting output

11dfae2bfd2d0af6e3da5c339c51179f.jpeg

Due to the modification of the state machine model, we need to generate the framework code of the state machine again, but this time there is no need to add the -d parameter:

[xiaowp@linuxgam code]$ fsmc door.fsm -o DoorFSM.h
[xiaowp@linuxgam code]$ fsmc door.fsm -d -impl DoorFSM.h -o DoorFSM.cpp

We have added four outputs of enterOpend, enterClosed, enterLocked and enterUnlocked to the new state machine model, so the generated class DoorFSM will contain the following pure virtual functions:

virtual void enterOpened() = 0;
virtual void enterLocked() = 0;
virtual void enterUnlocked() = 0;
virtual void enterClosed() = 0;

Obviously, the state machine framework generated at this time can no longer be directly compiled, we must derive a subclass from the class DoorFSM, and provide the specific implementation of these pure virtual functions:

/*
 * DoorFSMLogic.h
 * 状态机控制逻辑的头文件
 */
#include "DoorFSM.h"

class DoorFSMLogic : public DoorFSM
{
 
 protected:
  virtual void enterOpened();
  virtual void enterLocked();
  virtual void enterUnlocked();
  virtual void enterClosed();
};

As mentioned above, these functions actually represent the processing logic of the application system. As an example, we simply output some prompt information:

/*
 * DoorFSMLogic.cpp
 * 状态机控制逻辑的实现文件
 */
#include "DoorFSMLogic.h"
#include <iostream>

void DoorFSMLogic::enterOpened()
{
    std::cout << "Enter Opened state." << std::endl;
}

void DoorFSMLogic::enterClosed()
{
    std::cout << "Enter Closed state." << std::endl;
}

void DoorFSMLogic::enterLocked()
{
    std::cout << "Enter Locked state." << std::endl;
}

void DoorFSMLogic::enterUnlocked()
{
    std::cout << "Enter Unlocked state." << std::endl;
}

Similarly, in order to verify the generated state machine, we also need to manually write a piece of test code:

/*
 * TestFSM.cpp
 * 测试状态机逻辑
 */
#include "DoorFSMLogic.h"

int main()
{
  DoorFSMLogic door;
  door.A(DoorFSM::Close);
  door.A(DoorFSM::Lock);
  door.A(DoorFSM::Unlock);
  door.A(DoorFSM::Open);
}

The generated state machine skeleton and test code can be compiled into an executable file using the following command:

[xiaowp@linuxgam code]$ g++ DoorFSM.cpp DoorFSMLogic.cpp TestLogic.cpp -o logic

The running results are as follows:

[xiaowp@linuxgam code]$ ./logic
Enter Closed state.
Enter Locked state.
Enter Unlocked state.
Enter Opened state.

This article involves code downloads: http://www.uml.org.cn/umlcode/code.zip

Disclaimer: The material of this article comes from the Internet, and the copyright belongs to the original author. If it involves copyright issues, please contact me to delete.

------------ END ------------

79e5d600640655b39cc97205c1c1228b.gif

●Column "Embedded Tools "

●Column "Embedded Development"

●Column "Keil Tutorial"

●Selected tutorials in the embedded column

Pay attention to the official account and reply " Jiagroup " to join the technical exchange group according to the rules, and reply " 1024 " to view more content.

6d729b2999c7283dff860c844a744406.jpeg

e354460fded1ffd8880bc55436782879.png

Click " Read the original text " to view more sharing.

Guess you like

Origin blog.csdn.net/ybhuangfugui/article/details/132033245