SCXML有限状态自动机

简介: 状态机简介 状态存储关于过去的信息,就是说:它反映从系统开始到现在时刻的输入变化。转移指示状态变更,并且用必须满足来确使转移发生的条件来描述它。动作是在给定时刻要进行的活动的描述。有多种类型的动作: 进入动作(entry action):在进入状态时进行退出动作:在退出状态时进行输入动作:依赖于当前状态和输入条件进行转移动作:在进行特定转移时进行     FSM(

状态机简介

状态存储关于过去的信息,就是说:它反映从系统开始到现在时刻的输入变化。转移指示状态变更,并且用必须满足来确使转移发生的条件来描述它。动作是在给定时刻要进行的活动的描述。有多种类型的动作:

进入动作( entry action):在进入状态时进行
退出动作:在退出状态时进行
输入动作:依赖于当前状态和输入条件进行
转移动作:在进行特定转移时进行

    FSM(有限状态机)可以使用上面图 1 那样的状态图(或状态转移图)来表示。此外可以使用多种类型的状态转移表。下面展示最常见的表示:当前状态(B)和条件(Y)的组合指示出下一个状态(C)。完整的动作信息可以只使用脚注来增加。包括完整动作信息的 FSM 定义可以使用状态表


  • SCXML Parser
  • 核心 API,用于 SCXML 文档的解析模块,该 SCXML 文档中的各个元素解析组装成对应的 Java 对象实现。
  • DataModel
  • 核心 API,用于实现 SCXML 状态机中的数据模型定义,将 SCXML 文档中的 datamodel 元素对应的子元素封装成 Java 对象,供状态机引挚在后续操作中使用。
  • Context and Evaluators
  • 核心 API,用于实现对 SCXML 状态机中上下文环境的保存和更改,以及对 SCXML 文档中表达式语言(例如 <log expr=”${data.value}” />)的解析操作。
  • Executor
  • 引挚执行器的实例化模块,核心 API,通过此模块完成一个完整引挚执行器的组装和实例化,并提供引挚启动,停止服务器基础功能模块。
  • Triggering Event
  • 核心 API,SCXML 引挚中事件的定义实现和执行模块。此模块完成一个外部事件的封装,事件池的组织以及具体的事件作用流程控制。
  • Custom Actions
  • 高级 API,SCXML 状态机引挚的自定义事件支持。除了 SCXML 标准自带的 <var >、<assign> 和 <log> 等标准事件外,程序人员可以进行自定义事件的开发工作,例如系统平台的构件添加、构件删除操作等,需要程序人员的扩展开发工作。以下代码为 Custom Actions 的使用范例。

应用场景:
    

应用案例说明:
计时器的例子:
stopwatch state chart diagram


创建Maven工程:

<dependencies>
<dependency>
<groupId>commons-scxml</groupId>
<artifactId>commons-scxml</artifactId>
<version>0.9</version>
</dependency>

<dependency>
<groupId>commons-jexl</groupId>
<artifactId>commons-jexl</artifactId>
<version>1.1</version>
</dependency>

<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.6.0</version>
</dependency>

</dependencies>
创建状态机模型文件:stopwatch.xml
<scxml xmlns="http://www.w3.org/2005/07/scxml"
version="1.0"
initialstate="reset">
<state id="reset">
<transition event="watch.start" target="running"/>
</state>
<state id="running">
<transition event="watch.split" target="paused"/>
<transition event="watch.stop" target="stopped"/>
</state>
<state id="paused">
<transition event="watch.unsplit" target="running"/>
<transition event="watch.stop" target="stopped"/>
</state>
<state id="stopped">
<transition event="watch.reset" target="reset"/>
</state>
</scxml>
创建状态机:StopWatch.java
import org.apache.commons.scxml.SCXMLListener;
import org.apache.commons.scxml.env.AbstractStateMachine;
import org.apache.commons.scxml.model.ModelException;
import org.apache.commons.scxml.model.State;
import org.apache.commons.scxml.model.Transition;
import org.apache.commons.scxml.model.TransitionTarget;

import java.util.Timer;
import java.util.TimerTask;

public class StopWatch extends AbstractStateMachine {
/**
* The events for the stop watch.
*/
public static final String EVENT_START = "watch.start",
EVENT_STOP = "watch.stop", EVENT_SPLIT = "watch.split",
EVENT_UNSPLIT = "watch.unsplit", EVENT_RESET = "watch.reset";

/**
* The fragments of the elapsed time.
*/
private int hr, min, sec, fract;

/**
* The fragments of the display time.
*/
private int dhr, dmin, dsec, dfract;

/**
* The stopwatch "split" (display freeze).
*/
private boolean split;

/**
* The Timer to keep time.
*/
private Timer timer;

/**
* The display decorations.
*/
private static final String DELIM = ":", DOT = ".", EMPTY = "", ZERO = "0";

public StopWatch() throws ModelException {

super(StopWatch.class.getClassLoader().getResource("stopwatch.xml"));
getEngine().addListener(getEngine().getStateMachine(), new EntryListener());
System.out.println(StopWatch.class.getClassLoader().getResource("stopwatch.xml"));
}

public void reset() {

hr = min = sec = fract = dhr = dmin = dsec = dfract = 0;
split = false;
}

public void running() {

split = false;
if (timer == null) {
timer = new Timer(true);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
increment();
}
}, 100, 100);
}
}

public void paused() {

split = true;
}

public void stopped() {

timer.cancel();
timer = null;
}

public String getDisplay() {

String padhr = dhr > 9 ? EMPTY : ZERO;
String padmin = dmin > 9 ? EMPTY : ZERO;
String padsec = dsec > 9 ? EMPTY : ZERO;
return new StringBuffer().append(padhr).append(dhr).append(DELIM).
append(padmin).append(dmin).append(DELIM).append(padsec).
append(dsec).append(DOT).append(dfract).toString();
}

public String getCurrentState() {

return ((State)getEngine().getCurrentStatus().getStates().iterator().next()).getId();
}

private void increment() {
if (fract < 9) {
fract++;
} else {
fract = 0;
if (sec < 59) {
sec++;
} else {
sec = 0;
if (min < 59) {
min++;
} else {
min = 0;
if (hr < 99) {
hr++;
} else {
hr = 0; //wrap
}
}
}
}
if (!split) {
dhr = hr;
dmin = min;
dsec = sec;
dfract = fract;
}
}

/**
* A SCXMLListener that is only concerned about &quot;onentry&quot;
* notifications.
*/
protected class EntryListener implements SCXMLListener {
public void onEntry(final TransitionTarget entered) {
System.out.println("Current State:"+entered.getId());
}
public void onTransition(final TransitionTarget from,
final TransitionTarget to, final Transition transition) {
// nothing to do
}
public void onExit(final TransitionTarget exited) {
// nothing to do
}

}
}

测试代码:
public static void main(String[] args) throws ModelException {

StopWatch stopWatch = new StopWatch();
Scanner input=new Scanner(System.in);
System.out.println("event: watch.start watch.stop watch.reset watch.split watch.unsplit");
while(true){
String event=input.nextLine();
if(event.trim()!=null&&!event.trim().equals("")){
if(event.equals("exit")) break;
else{
stopWatch.fireEvent(event);
System.out.println(stopWatch.getCurrentState());
System.out.print(stopWatch.getDisplay());
}
}
}

}
每一个状态下会调用对应状态的方法来处理具体的业务处理逻辑。这样就可以实现一个简单的处理机。

Q&A:
关于序列化:2.0版本中可以通过将SCXML中attach的SCInstance实例的序列化来完成,恢复后通过deattach来恢复。

状态恢复:可以通过引入一个新的状态reset状态


reference:
http://www.w3.org/TR/scxml/




目录
相关文章
|
6月前
|
编解码 并行计算 数据可视化
【数学建模】元胞自动机
【数学建模】元胞自动机
68 0
|
9月前
|
机器学习/深度学习 传感器 算法
【元胞自动机】基于元胞自动机模拟森林救火问题附matlab代码
【元胞自动机】基于元胞自动机模拟森林救火问题附matlab代码
|
9月前
|
机器学习/深度学习 传感器 并行计算
【元胞自动机】基于元胞自动机实现传染病传播模拟附matlab代码
【元胞自动机】基于元胞自动机实现传染病传播模拟附matlab代码
|
9月前
|
自然语言处理 算法
【无人机路径规划】基于IRM和RRTstar进行无人机路径规划(Matlab代码实现)
【无人机路径规划】基于IRM和RRTstar进行无人机路径规划(Matlab代码实现)
104 0
|
10月前
|
机器学习/深度学习 传感器 算法
【元胞自动机】基于元胞自动机模拟气体交换碰撞附matlab代码
【元胞自动机】基于元胞自动机模拟气体交换碰撞附matlab代码
|
10月前
|
机器学习/深度学习 传感器 算法
【元胞自动机】基于元胞自动机模拟风速影响的森林火灾模型含Matlab代码
【元胞自动机】基于元胞自动机模拟风速影响的森林火灾模型含Matlab代码
|
11月前
|
机器学习/深度学习 存储 传感器
【元胞自动机】基于元胞自动机模拟交通路况(含超车)附matlab代码
【元胞自动机】基于元胞自动机模拟交通路况(含超车)附matlab代码
|
机器学习/深度学习 传感器 算法
【交通流】基于元胞自动机模拟收费站交通流附matlab代码
【交通流】基于元胞自动机模拟收费站交通流附matlab代码
|
12月前
|
机器学习/深度学习 传感器 算法
【交通流】基于元胞自动机模拟货车客车换道模型附matlab代码
【交通流】基于元胞自动机模拟货车客车换道模型附matlab代码
|
机器学习/深度学习 传感器 算法
【元胞自动机】基于元胞自动机模拟地区未来的城市增长附Matlab代码
【元胞自动机】基于元胞自动机模拟地区未来的城市增长附Matlab代码