本文讲解4.0版jxTMS中python服务的jxLocalStateMachine模块,整个系列的文章请查看:docker版jxTMS使用指南:4.0版升级内容
docker版本的使用,请参考:docker版jxTMS使用指南
jxLocalStateMachine提供了一个简单可靠的有限状态自动机。之所以叫做local,是因为jxTMS的python服务原本为了配合智能硬件工作,还提供了一个jxStateMachine的有限状态自动机【参考用jxTMS开发智能转运箱】。jxStateMachine是从智能硬件接收事件来驱动的,而jxLocalStateMachine则是本地手动触发事件来驱动的。
jxLocalStateMachine的几个概念:
状态,一个稳定的、可识别的阶段
初始状态,自动机启动后所处的第一个状态
跃迁,从一个状态切换到另一个状态
事件,外部对自动机的触发,事件可能导致自动机跃迁,也可能不跃迁,事件所起到的作用,首先取决于事件发生时状态机所处的状态。某状态时,如果指定接收到某事件时的处理,该事件就叫做此状态下的期望事件;某状态所有期望事件之外的事件,叫做该状态的非期望事件,也就是异常事件
响应,当跃迁发生时,自动机需要执行的动作,一般就是一个函数
跌落,某状态下出现非期望事件时跃迁到某个预设状态
有限状态自动机的工作机制是:
某状态时触发了某事件,如果该事件是此状态的期望事件,则跃迁到指定的状态【该状态可以是本状态】并执行响应动作
非期望事件发生时如果定义了跌落,则跃迁到跌落状态,并执行对应的异常处理
非期望事件发生时未定义跌落,则不做任何响应
jxLocalStateMachine提供的自动机包括三个部分:
状态跃迁图,定义自动机的状态、跃迁、事件、跌落等
响应函数,当响应时需要执行的处理函数
自动机实例,保存当前状态的、实际运行中的自动机。需要状态跟踪的对象一般都被定义为自动机实例,这会比较自然,如device中跟踪设备状态
引用:
from jx.jxLocalStateMachine import jxLocalStateMachine
状态机的定义需要先创建一个jxLocalStateMachine对象。其初始化函数为:
class jxLocalStateMachine:
def __init__(self,name, initState):
...
其中:
name:状态机的名字
initState:状态机的初始状态
如用于设备状态跟踪的自动机:
_devSM = jxLocalStateMachine('devSM','init')
状态机的对象函数有:
addTrans(self, state, event, toState, dual)
定义一个跃迁
参数:
state:当前状态
event:事件
toState:跃迁到的状态,也可以是当前状态
dual:响应函数,None则不执行
返回值:
无
示例:
#当前状态为idel时,发生了start事件,则跃迁到mi状态,并执行receiveStart函数
vrs20SM.addTrans('idel','start','mi',receiveStart)
说明:
某个状态下,所有用addSMTrans定义的事件,就是本状态的期望事件;期望事件之外的事件,就是非期望事件。如果没有给当前的状态定义跌落,那么所有的非期望事件都不做任何动作
addFall(self, state, elseState,elseDual)
定义一个跌落
参数:
state:当前状态
fallState:跌落到的状态
fallDual:响应函数,None则不执行
返回值:
无
示例:
#当前状态为init时,发生了非期望事件,则跃迁到idel状态并执行errorDual函数
vrs20SM.addFall('range','idel',errorDual)
说明:
本状态下出现了非期望的意外事件时的行为
如果一个状态,没有定义跌落,则出现非期望事件时不做任何动作,只是默默丢弃事件。
那么,如果给某状态用addTrans定义了出现某事件后跃迁回本状态,那和不用addFall定义该事件的跌落有什么区别呢?!两点:
1、addTrans如果定义了,则命中时,不管跃迁到哪个状态,都会执行响应函数
2、没用addTrans定义某事件跃迁回自己,如果定义了addFall,则会出现跌落
这样一来,在某状态时,【用addTrans定义了发生某事件后跃迁回本状态,但响应函数为None,虽然没有意义,但打开debug时可以跟踪状态机的运行情况】等价于【没有定义addFall,同时也没有用addTrans定义某事件的跃迁】。
状态机实例是定义好的自动机的具体应用,其在初始化时需要指定是哪个自动机的实例。
引用:
from jx.jxLocalStateMachine import SMInstance
目标对象继承自动机实例,并在初始化时声明其由哪个自动机衍生即可。如设备:
class device(SMInstance):
def __init__(self, name,...创建设备所需的参数):
super(device , self).__init__(_devSM,name=name)
...
这样一来,每台设备都可以跟踪自己的状态变化。
又如vrs20SM设备解析数据的自动机:
class vrs20(SMInstance):
def __init__(self, ...参数表):
super(vrs20 , self).__init__(vrs20SM)
...
则vrs20就可以绑定给一台设备来解析其接收到的消息。
状态机实例的对象函数:
happen(self,event,param=None)
触发一个事件
参数:
event:事件
param:事件参数
返回值:
无
示例:
#设备超时
self.happen('timeOut')
currentState(self)
获取当前状态
参数:
无
返回值:
当前状态
name(self)
获取自动机实例的名字,如果创建实例时给出了实例名,则实例的全名是:{自动机名}.{实例名},否则就只是:{自动机名}
参数:
无
返回值:
自动机实例的名字
debug(self, bv)
设置本自动机示例的运行跟踪,如果打开,则happen事件时会对自动机的运行过程进行全面跟踪,打印到日志中,包括没动作的情况
参数:
bv:是否跟踪,bool
返回值:
无
响应函数的示例:
def errorDual(SMInstanceObj, param):
...
SMInstanceObj就是调用的happen触发事件的自动机实例,param就是调用happen送入的参数
大家可以参考app目录中的policy_vrs20.py文件中vrs20SM的定义和使用。
参考资料:
jxTMS设计思想
jxTMS编程手册
下面的系列文章讲述了如何用jxTMS开发一个实用的业务功能:
如何用jxTMS开发一个功能
下面的系列文章讲述了jxTMS的一些基本开发能力:
jxTMS的HelloWorld