立立电气

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 8111|回复: 0

labVIEW中JKI状态机+AMC框架

[复制链接]

68

主题

68

帖子

290

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
290
发表于 2022-4-21 22:48:22 | 显示全部楼层 |阅读模式

labVIEW中JKI状态机+AMC框架

首先重要事情复习三遍,labVIEW是一门语言,labVIEW是一门语言,labVIEW是一门语言。本人是labVIEW编程爱好者,近日编程感想甚多,又遇风和日丽,写篇文章,烦请各路大神来掐(手动狗头)。接触labVIEW三载有余,从一个小白白,到如今的小白,从来都是逛知乎,今儿也写篇文章,话不多说。来人啊,鲜美无比,给云长送去...

JKI状态机
JKI状态机,一直在用,怎么说呢,入口即化。在陈树学的两本书中和各种文章视频,都有提到JKI状态机。
JKI,其和核心就是队列消息状态机+用户界面处理器模式,也就是事件驱动队列消息状态机。JKI状态机没有采用枚举来描述状态,而是采用规定格式的字符串。
首先,由于采用字符串来描述状态,因而只要按照规定格式编辑字符串,就可以构成一个消息队列。同时字符串也可以携带附加的数据消息,因此也可以构成消息+数据队列状态机。
其次,采用字符串来描述状态,因此可以在外部任何文本编辑器编辑消息。在VI内部读取消消息文件,这样就做到了外部控制JKI状态机,而VI本身不需要任何改变。其他类型的状态机是很难从外部控制其内部状态转换的。
安装下载不用多说VIPM,需要安装包的小伙伴也可以直接私信我。下面我们从内部看一下JKI状态机。
  • 状态分类:因为复杂项目必然存在大量的状态,所以最好把状态按照其用途进行分类,这样从状态的命名就可以看出其所属类别和用途。JKI状态使用“:”对命令进行分组。比如UI:Initialize,UI表示该命令针对UI界面操作,Initialize表示是对UI进行初始化。
  • 状态参数:JKI的命令都可以携带参数,命令和参数之间用>>分隔。比如UI: Cursor Set >> Busy,Busy表示参数,在UI: Cursor Set分支中把鼠标设置忙碌。
  • 单一状态:上述的两个状态都是单一状态,用一行字符串表示,注意单一状态不需要输入换行符,添加状态函数自动加入换行, JKI也有自带的创建“状态+参数”函数--Build State String with Arguments。
  • 状态序列:JKI允许同时加入多个状态,构成状态序列。这里要注意的一点是,连接两个或多个状态的时候,不要使用“连接字符串”函数,因为这样会导致JKI内部找不到你的状态,但也可以添加换行符,这样比较麻烦,还是用JKI自带的函数,不易出错。

JKI状态机的优势具体体现以下几点特性,高效性、可读性、可维护性、健壮性、简单性。具体如下;他其中的事件结构只负责产生事件发生的状态,而处理这些状态由条件结构来执行,每个条件分支都代表程序中的一个方法,这样使得程序健壮性更强,且程序框图界面清晰、整洁,更易于管理和修改这其中的分支或方法。也提高了程序的可读性,借用某大神的一句话,代码,大多数时间是用来读的,修改的,偶尔拿出来执行一下。呃,这波,我在第五层...の皮
可维护性,如果一组代码可以被作者之外的其他开发人员理解,并且源代码易于修改和扩展以改变或增加新的功能,那么这个labVIEW应用程序就是可维护的。JKI状态机的可维护性,怎么说呢,我个人认为,我们把每个状态看成是你要编写对象的方法,把他本身的参数看成是属性的话,在外部,我们需要用哪些他的功能方法就发送给他去执行,执行过程中可设置他的参数,这样不就实现了低耦合,而低耦合高内聚,才能实现扩展性更强,可维护性更好。藕断丝连怎能担此重任,书接上回,孔明潸然泪下看着马谡,斩...咳咳。
JKI的流程,简单写了一下,如果有看不懂的小伙伴们也可程序高亮一下。

下面就拿我写的例子来演示一下,
把每个要执行的事件写成一个分支,清晰明了,具体内容的话,太麻烦,需要的小伙伴私信吧,这是一个数据分析的程序,通用性还是很强的。

AMC框架
以上简单介绍了一下JKI状态机,但是JKI状态机是个单线程啊,单线程,单线,单。目前一般大型程序大多数都是多线程,需要在多个VI之前传递数据,数据交互,怎么办。不急,JKI 公司又推出了JKI SMO架构,这个架构可以说完全可以应付各种,但奈何本人学艺不精,无法参透其源代,故而放弃,好了,今天就到这吧。主公,你变了,变的不像从前....那么为了多线程之间实现数据交互,AMC啊,AMC可以做到啊。书接前文,子龙啊,那你就随玄德去吧...
异步消息通信(AMC)的目的是为各种本地和分布式LabVIEW应用程序提供易于使用的可扩展消息传递体系结构。它允许您在应用程序的一个进程内、一个LabVIEW目标上的不同进程之间或通过以太网连接的不同LabVIEW目标上的进程之间发送消息。此设计模式类似于通常称为排队状态机的其他VI体系结构实现。由于设计模式可以用于传统状态机和面向状态的任务之外的许多目的,因此选择此设计模式的名称来代表设计模式的实现。
AMC VIs的一个稍微高级的用例是在同一LabVIEW目标上从一个进程向另一个进程发送消息。消息仍然通过LabVIEW队列发送,因为在两个进程中都可以引用相同的队列。在这种情况下,每个接收方进程将实例化一个命名的消息队列,任何其他进程都可以使用消息队列名称向接收方进程发送消息。每个发送方队列使用接收方进程提供的队列名称引用接收方进程和队列。
对于两个或多个进程之间的双向消息通信,每个接收方进程将创建自己的接收方队列,任何其他进程都可以将其消息发送到每个接收方的一个公共队列。这意味着每个进程只需要一个消息队列,而不是在每对通信进程之间建立单独的连接。
以上就是AMC架构的简单介绍。大家也可查看范例,简单点说,AMC架构其中就是队列函数封装的,传引用,传数据。
那么我们将JKI和AMC结合用,我靠,三国周郎赤壁啊。那有的小伙伴要问了,为何不使用用户事件结构,因为用户事件没有缓冲区啊,你品,你细品,举个例子,当A.vi向B.vi发送数据,A.vi发送完了,但是B.vi没有运行啊,当B.vi运行的时候,接不到刚才数据,怎么办。反正我是不晓得了,也欢迎各位大神来帮我答疑解惑。但是队列可以啊,有缓冲区,可以存储啊,正所谓铜雀春深锁二乔啊。

JKI+AMC
  • 下面我将用写的例子,具体说明一下,是如何使用JKI+AMC的;下图是我的主界面vi程序框图,上面循环为JKI状态机,下面循环为队列状态机,两个循环数据交互使用用户事件结构。

  • 在上图中的橙色方框内是初始化队列,程序运行首先将项目中需要用的子vi都创建一个AMC队列,用AMC函数中的“Create Message Queue.vi”创建。如下图

因为我的程序需要,所以我创建了这些。
  • 接下来我们需要编写子vi的程序,看下如何使用JKI状态机进行数据交换,先上图

上图为“试验设置.vi”中的程序,也就是子vi。首先在本vi初始化的时候,获取“试验设置”队列的引用,使用AMC函数中"Get Queue From Registry.vi",将引用连入移位寄存器。(“Queue: Register”分支手动添加)
  • 接下改写超时结构中的程序,下图

在上图中,把超时设置成100ms,因为这样才能接收到来自其他线程的实时数据,此超时结构只负责接收其他vi发送到“试验设置队列”的数据。使用AMC函数的“Read Next Message.vi"函数接收消息数据。
这里要提到的一点是AMC传递的消息,由AMC库中的类型定义(TypeDef)定义。通过添加其他元素或更改现有元素,可以根据应用程序的需要自定义TypeDef。AMC库中包含的消息定义包含消息名称(字符串)、值(字符串)、属性(键控字符串数组)和一些附加参数等。也可把复杂类型的消息转化成XML格式字符串,发送出去。下图为AMC消息簇。
  • 前面我们说完了,创建队列,接收消息。接下来,我们看下如何发送消息。

上图为发送消息队列,其中"队列发送数据.vi",其中的意思是向"Main.vi"中,也就是Main队列中发送名字为"试验重设标识"的字符串,发送的值为状态Arguments中的数据
上图为队列发送数据的程序框图,其中都是用到的AMC函数,再次就不一一叙述,很简单。
  • 最后在编写其他子vi的程序,跟上述所说的vi模式一样,这样可以在多个vi之间进行数据交互了。


其实这种JKI+AMC的结构说不上特别优秀,因为在超时分支中设置成100ms,也就是说子vi打开之后在没有数据的时候也是一直在循环的,浪费资源。但是这种结构能解决我们大部分项目的需要。
本人还有一种想法,就是JKI SMO 中的方法。用JKI 状态机+用户事件,其实这种方式是可行的,但在项目运行中,需要把所有子VI都挂起,需要哪个前面板,就打开哪个,这种方式也在不断尝试中。
上文所述,如有不对之处,烦请各位大神指正,吾乃细听分说。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|立立电气

GMT+8, 2024-12-3 05:09 , Processed in 0.062318 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表