-modular industry micro,edge,cloud computing architecture
Arm 公司声称他们设计的处理器涵盖了从传感器到服务器(sensor to server)广泛的硬件设备。产品线从cortex-M 系列到cortex-A,从单核到多核,大小核,混搭核,种类繁多,令人眼花缭乱。不过到目前为主,除了cortex-M 面向各种嵌入式设备之外,cortex-A 系列的高性能处理器主要面向手机,平板,机顶盒,广告机,汽车面板这些消费类产品中。在工业领域使用高性能cortex-A 处理器并不多。
Cortex-A 处理器在工业领域进展缓慢的主要原因还是软件平台滞后,在手机,平板领域,google 的android 操作系统功不可没。 android OS为智能手机提供了用户交互界面,多媒体,手机底层驱动和App 虚拟机平台。android 一改linux 那样粗糙的用户界面和普通人难以适从的应用软件。为智能手机建立了一个生态系统。
高性能cortex-A 处理器要在工业领域广泛地应用,需要有一个类似android OS 那样的OS 来一统天下。事实上,现在也有许多人将android 采用在工业领域,当然目前还主要停留在看板,人机交互界面设备方面。
maxim labs 是一个研发iot 技术的公司,过去的两年中,我们开发了基于Arm 公司Mbed OS 的模块化物联网设备modular-2。
modular-2是一台基于cortex-M 系列微处理器为主的模块化微服务器它采用Arm 公司物联网操作系统Mbed OS , Mbed 的C++ 设备驱动API使程序员基本摆脱了硬件的细节,使应用软件更加模块化,更加清晰和高效率开发。
在modular-2 模块化微服务器成功地应用于多项物联网项目的基础上,maxim 公司于2019年开始开发modular-2 Edge 和modular-2 cloud 两个项目的研究与开发,构建涵盖从传感器到云端模块化工业服务器的体系结构。
目前,modular-2 技术包括了三项技术
modular-2 edge 是一个模块化边缘服务器,可以安装在各类工业现场,完成数据采集,控制,数据存储和分析。它基于linux OS,采用基于容器技术运行和维护各种工业App。并且规范了一个开放型工业边缘计算的系统架构(Open industry edge computing Architecture),其中包括网络协议,消息交换方式,App运行环境,UI界面。根据工业应用对计算能力的需要,modular-2 edge可以部署在低成本的Arm 处理器平台上,也可以部署在性能更强大的intel X86 计算机平台。使工业信息系统更加富有弹性。
modular-2 Edge 通过网络连接各种modular-2模块化微服务器,实现和PLC ,传感器,执行部件的连接。
尽管高性能Arm 处理器层出不穷,一日千里的飞速发展,但是相对于移动终端应用而言,高性能Arm 处理器在工业领域的应用并不快。工业领域依然以PLC,PC,windows这样传统的应用设备为主。其中一个非常主要的原因是以移动应用的技术没有迅速地转移到工业领域,特别是软件架构和软件开发方法进展缓慢。
工业应用对软件平台的要求与移动终端不同,它们有如下几个特点。
1 支持多种语言应用软件的开发
2 支持更多的通信协议
3 实时处理能力
4 本地数据存储
5 本地计算能力
6 远端管理能力
开发modular-2 技术的目的是探索将移动网络,云端服务技术转移到工业应用领域。让用户体验,HTML5 UI ,App化,容器化,敏捷开发,迅速迭代这些开放性技术和理念移植到工业领域。
具体地,modular-2 Edge 具有如下特点
1 容器化+微服务
容器化技术和微服务架构已经成为一种潮流。采用容器技术来构建工业边缘设备的App 运行环境比较合适。它可以实现App的远程部署,更新和维护,这都是工业边缘设备所必需的。同时,每个容器都为App 提供了一个合适的环境,松耦合,软件敏捷开发,适合多种技术和语言来开发工业App 程序。这是android 系统缺乏的。
从GE公司的predix,harting 公司的mosca,研化的网关产品以及最近arm 公司推出 mbed linux OS 看,他们不约而同地采纳了容器技术作为App 的管理平台。
2 基于web 的用户界面
工业边缘设备需要一个类似于手机,平板电脑那样统一的用户界面。虽然Arm cortex-A 处理器普遍带有GPU ,可以连接内置的LCD 显示屏,或者通过HDMI 连接更大的显示屏。但是许多场合下,在工业现场使用LCD 触控屏是不方便得。使用浏览器访问内置网页得方式更加合适。
每个App 的用户界面是不同的。为了实现统一的用户界面,在每一个App 中都内置了一个简单的web 服务器,提供个性化用户UI网页和配置网页。Base Service同样也提供一个内置的web 服务器,提供入口主页面,系统配置,容器管理页面。每个App 会在基础服务(Base Service)中注册,一旦注册后,App的图标会出现在主页面上。并且可以跳转到每个App的页面。
每一个App都是一个web服务器,这听起来有点疯狂,不过在App 中实现轻量级嵌入式web 服务器并不是特别复杂的事情。不同的语言App 采用不同的插件和程序库。
3 基于websocket 软件数据总线(mRPC)
在边缘设备上由一个基础服务和多个App与微服务构成。App是真正的工业应用程序,微服务为工业App 提供增值服务,比如提供influxDB 存储,云端访问,硬件接口访问,本地屏看板。
虽然App 的相互协同和消息交换并不多。但是工业应用App 和IO模块,微服务之间的消息交换和协同操作还是非常频繁的。需要一个在App和微服务之间统一的数据交换机制(所谓消息队列,软件数据总线)。
进入云OS 时代更有各种各有的消息系统。例如比较著名的有kafka,google的gRPC 也有IBM MQTT这样轻量级的消息系统。这种消息系统能够实现跨平台分布式消息交换。
然而,这些现成的消息系统大多数都是为云端服务器开发的,对于小型边缘设备而言,他们显得太庞大的。
在modular-2 Edge 中,我们设计了一个基于轻量级websocket上的RPC 消息机制mRPC。
mRPC 具有下面几个特点:
传统的函数调用是在同一的地址空间内实现的,函数的跳转是通过call 指令实现,参数通过堆栈传递。主程序和函数在编译时链接。
不同的App ,使用不同的地址空间,所以,哪怕是在一个设备中运行,他们之间的过程调用要通过RPC(远程过程调用)方式实现。
实现RPC 的方式有许多种,既可以基于内存共享的方式实现,也可以通过某种通信协议来实现。比如unix:sock,tcp/ip,http 等通信方式。为了支持分布式处理,mRPC 采取基于http web socket 的协议实现。websoket 是建立在http 协议之上的双向socket 通信。多种语言都支持websocket 通信协议,系统的兼容性更强。
工业领域的应用许多是流方式的,例如ADC 采集的数据,就是一个连续的流数据。如果是简单的调用/结果的RPC模式,对于流式数据就需要不断地调用,显然RPC的效率不高,mRPC 支持流RPC。实际上有两种流RPC 模式
-调用数据流
连续的RPC 调用,形成数据流。
-结果数据流
-一次RPC 调用,多个结果形成数据流
数据流RPC 支持广播方式。其它App 可以读取其它App 发起的数据流。
尽管处理json 会增加处理器的处理负担,但是数据的描述和解析更加清晰和灵活,有利于多种语开发App 的协同操作。所以mRPC 采用json 格式描述。
基础服务(Base Service)是modular-2 Edge 开发的一个重要的组成部分。它运行在linux 内核平台之上。为工业边缘设备提供了一个轻量级的App 运行环境。
类似智能手机的用户界面
在该界面下,用户可以安装,升级和删除App 软件,设置App 参数,观察App 的运行结果。
功能不断扩展的软件平台
软件开发者可以开发各种微服务应用软件,来扩展基础服务的性能。例如可以开发出时间序列数据库,dashboard看板,MQTT ,人工智能分析等各种微服务模块。工业App 使用mRPC 同一种的方式调用这些微服务。
IO接口硬件RPC化
工业领域的边缘设备涉及大量的IO接口,而Linux OS 是为桌面系统和服务器设计的,IO接口驱动并不丰富。modular-2 Edge 设备通过以太网和多个cortex-M 的IO模块相连接。并且通过基础服务将IO接口抽象成为mRPC 调用。工业App 不需要了解很多IO模块的细节就可以访问各种IO外围接口。
MbedOS是Arm 公司为iot开发的一个开源操作系统,面向cortex-M系列单片机。 它通过C++ API编程接口,开发应用程序比较快捷。cortex-M 处理器可以实现更智能和强大的IO接口,比如与PLC,传感器链接的modbus通信协议。
基础服务从微服务和io模块两个维度为工业App 提供了丰富的App 运行环境的功能扩展。
目前io模块的mRPC 还只是BaseService 内置的,未来将实现动态注册到BaseService 中去。
远程过程调用(Remote Procedure Call,缩写为 RPC)是一种通信协议,一个计算机上的程序远程调用另一台计算机上的过程。两个不同地址空间的App 也可以通过RPC 协议实现远程过程调用。
事实上,可以在各种协议上来实现远程RPC协议,例如TCP,UDP,HTTP,甚至串口。
RPC协议的重要内容是过程和结果的参数描述方式和串行化。可以是二进制编码,字符串格式,XML 或者json格式。显然二进制编码效率最高,但是程序可读性差,维护难度大。
mRPC 采用了websocket 来实现RPC 协议,采用json 描述RPC 过程和结果。
基本格式
最基本的mRPC格式由方法和结果组成。它们采用json 格式描述。
方法(method)
rpc_method={
"method": method_name ,
"mode":mode,
"path":path,
"params":{"value":value},
"id": id
}
其中:
methodName 过程的名称,字符串格式。
mode 调用模式,(详见 mode)
共有六种模式。
Normal 1
StartStream 2
StopStream 3
startReadStream 4
stopReadStream 5
MQTTStream 6 6
path RPC 调用的路径(详见path)
value RPC 的参数,使用二进制数组表示。
id 由一个整型数表示(0 ~5000),每发送一个RPC 调用,id 加一,到5000 翻转到0.
结果(result)
rpc_result={
“path”:path
“result”:{
“status”:status,
“value”:[values]
},
“id”id
}
path 为调用RPC 的路径。
status 为一个字符串。
-OK
-ERR
- 调用RPC 的名称
value 为RPC 的参数。
id 由一个整型数表示(0 ~5000),每发送一个RPC 调用,id 加一,到5000 翻转到0.
mRPC 的模式(mode)
普通模式(Normal)
普通模式类似普通的函数调用,一个方法调用对应一个result
流结果模式(stream result)
调用者一次RPC 调用后,被调用者发送流式结果给调用者,直到调用者发送stop stream RPC 为止。
读取流(stream read)
路径(path)
路径(path)指定RPC的所在位置,它由三部分组成:
主机地址/app地址/rpc地址
主机地址
标识被调用者的主机,本机为 000。这是为分布式处理做准备的。
每个BaseService 设备由一个唯一的主机地址,多个基于BaseService 的设备可以相互通信。
App地址
拥有该RPC 方法的App编号
每一个App拥有一个唯一的地址。
保留的地址
“000” –base 的地址
“000”~“008” 为IO模块地址
“009”~”255” 其它App 的地址
PRC地址
App 中不同RPC的地址。
基础服务提供的RPC 方法
一览表
-ping
-register.rpc
-register.app
-get.rpclist
-get.applist
_get.queue
- stream.write
- stream.read
-console.write
-console.read
描述
ping
App 需要向基础服务维持一个Ping 心跳信息,保持与基础服务的连接。
格式
ping={
method:”ping”,
}
注册App (register.app)
为了基础服务能够管理App,每个App 要在baseservice 中注册。
格式:
register_app={
method:”register.app”,
path:”000/000/003”,
mode:1
params:{
name:_appname,
port:_port
}
id:_id
}
注册RPC方法(register.rpc)
App 提供的RPC 需要向基础服务注册。以便另外的App 调用它时,jcfw可以实现转发。
格式
register_rpc={
method:”register.rpc”
path:”000/000/002”
mode:1
params:{
name:_method_name”
path: _path
}
id:_id
}
rpc 注册,调用和结果
读取所有注册App(get.applist)
运维RPC, 在运维网页中调用 。
格式
get_applist={
method:”get.applist”
mode:1,
path:”000/000/005”
params:{value:[0]}
id:_id
}
结果
result={
result:{
status:“get.applist
value:[{
}]
}}
读取所有注册RPC(get.rpclist)
运维RPC, 在运维网页中调用 。
格式
get_rpclist={
method:”get.rpclist”
mode:1,
path:”000/000/004”
params:{value:[0]}
id:_id
}
结果
result={
result:{
status:“get.rpclist”
value:[{
rpcname:_rpcname,
path:_path
index:_method_index
}]
}
id:_id
}
读取当前RPC队列(get.queue)
运维RPC, 在运维网页中调用 。
get_rpclist={
method:”get.queue”
mode:1,
path:”000/000/004”
params:{value:[0]}
id:_id
}
结果
result={
result:{
status:”get.queue”
value:[{
}]
}
id :_id
}
写数据流(stream.write)
将数据写入一个数据流,数据流用stream_path 标识。
stream_write={
method:”stream.write”
mode:1
path:000/000/007
params:{
content:_content;
path:stream_path;
}
id:_id
}
注意:
1 stream_path
如果写入的数据流由多个App 读取,stream_path 可以选取发送者所在的path ,也就是和命令中的path相同。
如果写入数据到同一的地方,可以写入目的地的path
如果系统中由多个数据流,多App 写入,多App 读取,可写入一个特定的stream_path
例如:000/255/000 或者 000/000/255 。
读数据流(stream.read)
读取一个数据流。该数据流可以是stream.write 产生的数据流,也可以是流式结果的PRC 产生的stream.
stream_read={
method=”stream.read”
path: 000/000/006,
params:{
path:stream_path
}
}
写控制台(console.write)
为了调试和运维的需要,App 回在本地tty上输出一些运维信息,但是当App装入docker以后,只有进入docker 内部,才能看见这些运维消息。显得十分不方便。写控制台将运维信息写入一个特殊的数据流,运维人员可以在网页上看到这些运维信息。写控制台是一个特殊的stream write RPC. .(stream path为000/000/008
console_write={
method:”console.write”
mode:1,
path:000/000/008
params:{
content:_content
}
id:_id
}
读控制台(console.read)
读取控制台数据流。
console.read={
method:”console.read”
mode:2
params:{value:[0]}
id:_id
}
结果:
result={
result:{
status:”console.read”,
content:_content
}
}
content 可以是一个字符串,也可以是一个json 字符串。
modular-2 Edge 中的App 由三部份组成:
-websocket 接口
App 通过websocket 与baseservice 通信,并且完成RPC的解析,完成相应的处理后反馈结果。向baseservice 发送json 格式的RPC调用。
-算法部分
执行RPC 请求的相关数据处理。
-内置web 服务器
每个App 都拥有一个轻量级的web 服务器。用户可以主界面跳转到某个App 的web 主页。内置web 网页完成两大功能
1 App 的用户操作界面
2 App 的配置网页
App的内置网页也可以与baseservice建立websocket通信,直接baseservice 服务,也可以通过Rest full API 和App 主程序交换信息。
App网页框架(app web framework)
App 网页风格和baseservice 的主页具有同样的风格,具有如下特点
-使用bootstrap 框架
-jquery
-256x256px png 格式App logo
-蓝色配色
基于网页的轻量级App
对于熟悉JavaScript的程序员而言,可以编写基于网页的App,在网页中直接可以通过websocket访问baseservice
modular-2 Edge使用alpine OS作为docker的基础镜像。该镜像很小,下载时间短。
alpine 镜像大约13M~20M,而ubuntu 的镜像大约是60M,debian OS 大约是200M。
baseservice alpine 20M,对应的ubuntu 100M,debian OS 130M 左右。
modular-2 微型服务器基于cortex-M系列处理器为主的微型服务器,用于连接各种工业控制器,传感器,和执行部件。cortex-M 系列处理器芯片支持众多常见的IO 外围电路。能与工业控制领域的数字IO,RS485,ADC/DAC转换电路,canbus 总线连接.并且随着高性能cortex-M4/M7的出现和性能提升,已具有一定的计算处理能力。
软件上,我们采用了Arm 公司的Mbed OS 作为程序平台,它使用C++作为开发语言,大大提升的软件开发效率。modular-2 的IO模块通过以太网接口与主处理器连接,提高了IO模块的扩展性和总线带宽。
modular-2 microserver 通过以太网与 modular-2 Edge 连接。同样采用的协议mRPC 协议。这样太棒了,modular-2 微型服务器看上去就像一个微处理器实现的App !
由于mbed OS 支持C++编程,我们也开发了实例模板程序,使用户可以方便地开发各种面向工业应用的微服务器。
实验系统目前实现了如下几个RPC 方法:
数字输出写数据digitalOut_Write
数字输出读数据digitalOut_Read
数字输出反转digitalOut_Flipflop
模拟输入analogIn
数字输入 终端interruptin
高速PWM 输出(pwm out)
事实上,cortex-M 处理器有比较强的计算能力,可以实现许多需要实时处理的计算和前端处理,用户可以根据需要,编写各种具有前端处理的的RPC方法,比如
工业PLC和传感器 的modbus 协议
modbus.read
modbus.write
汽车检测领域的canbus协议
canbus.read
canbus.write
其它工业应用协议
dmx512 灯光控制协议
具体的方法参见《modular-2 微服务器编程指南》
IO 模块RPC 实例
数字IO 输出digital.write
digital_write={
method::”digital.write”,
mode:1,
path:”000/001/001”
params:{
value:[0],
}
id:_id
}
说明:
1 path 访问IO模块的RPC 中,path的设置方式
000/board number/pin number
board number: IO板编号,从 1 到 15,最多可以连接15 个IO 模块。
pin number: 引脚的编号。IO模块中会有多个同一种类型的IO 外围电路 。采用pin 编号来区分。
2 params 中的value 是一个2 进制字节的数组。
启动模拟数字输入(analogIn.start)
analog_read={
method:“analog.start”
mode:2
path:“000/001/000“,
params:{
value:[1]
}
id:_id
}
结果
结果为一个流式result。
result:{
resule:{
status:”analog.read”
value:base64_string
}
id:_id
}
说明
返回的结果是一个 base 64 编码的二进制字节的字符串。具体的长度和格式与IO模块的analog ADC 有关。
例如返回值可以是16个24 位的浮点值。
base64 编码
Base64是一种能将任意Binary资料用64种字元组合成字串的方法,而这个Binary资料和字串资料彼此之间是可以互相转换的,十分方便。base64 用4个字节表示3 个二进制字节。所有经过base64 编码的二进制字节,会长30%左右。
16个24位浮点数长度位16*24=385个字节。经过base64 编码后,字符串长度为 (16*24)*3/4=512 字节。
大多数语言都支持base64 的编解码,例如浏览器中JavaScript使用windows.atob()。
工业边缘设备需要实现许多复杂的软件功能,比如本地数据库存储,与云端交换,本地交互面板,许多场合下,人们不得不采用工业PC/ windows 作为工业控制和数据采集的平台。而且实现一个哪怕就是简单的软件也需要经验丰富的C# 程序员。事实上,目前许多工业软件还在使用VB这样的传统语言开发。
容器+微服务的理念主张将功能复杂的单一程序拆解成为功能多个单一的微服务。在工业领域,常用的微服务包括:
-influxdb 时间序列数据库
-MQTT 代理
-本地看板
大多数边缘设备都配置了一个图形控制器,通过LCD接口和HDMI连接本地显示屏。工业App 共享一个本地看板(local dashboard) 在dashboard 上可以显示系统中主要的运行状态。本地看板使用electronJS 实现。
-人工智能
人工智能可以作为微服务加入。
-云端网关
modular-2 edge 可以通过一个云端网关(cloud agent)和各种云端相连接。例如微软公司 Azure OS,Amazon 的AWS,influxdb 的TICK,以及其它iot 云端。
多个基于baseservice 的边缘设备可以构建成为分布式系统。所有App可以调用其它App和微服务的RPC方法。
在下面的例子中,边缘baseservice 通过一个Cloud Agent App 与云端baseservice 连接。
modular-2 Edge 可以运行在任何linux OS 的计算机平台上,它们可以是Arm 处理器平台,也可以是intel x86 CPU 平台。modular-2 Edge对硬件的依赖程度非常低。既可以在低成本Arm cortex-A 平台上运行,也可以在高性能X86 平台上运行。能够覆盖工业应用的不同需求。
目前modular-2 edge已经实现了一个最小可运行系统,在RK3399 开发板和Intel i5 计算机上运行,linux OS 采用的是ubuntu OS。
我们针对各种工业领域的场景,对系统进行测试。
大致结果如下:
-
从模块化cortex-M 处理器为主的微服务器出发,向上发展 modular-2 edge和modular-2 cloud 两项技术。利用移动网络成熟的开发性技术,构建工业应用领域的软件体系架构,maxim 致力于工业领域软件体系结构的研究与开发。