系统架构
我们推荐使用代码生成工具进行驱动的编写,并在生成的代码上进行微调。
FsuOS App的主要功能就是加载驱动,调度执行,加载告警规则,执行告警判断,动态配置执行,历史数据保存,调用B接口推送。
FsuOS 采用插件式驱动设计,本身只是一个调度框架,没有具体的业务数据功能,系统结构如下:
FsuOS App -> DI 驱动
-> AI 驱动 -- memcached/redis --- php helper/views
-> SP 驱动
-> Socket 驱动
-> PyDriver Python驱动
用户通过编写协议驱动,FsuOS 通过加载驱动,完成采集和告警,保存数据的功能。
协议驱动分为2种:
- C++编写的原生驱动,下面主要讲的是这种,开发者需要跟随C++驱动的编写方式,来理解驱动是如何工作的。
- Python编写的DriverPy,后面有个专门的章节讲这个。这个DriverPy也不是个新概念,本质上,我们采用了Python继承C++类的方式,使用Python代码做逻辑的判断,而使用C++原生驱动去执行操作,来,工作原理和C++原生协议驱动一致,但是由于python的可以直接在目标系统运行,不需要使用制定的编译器,因此少了为不同FSU分别编译驱动的部分,大大节省了维护成本。
用户编写驱动时,不考虑设备运行在哪个端口,只考虑业务数据的处理。
DI,AI和端口数据直接绑定处理,或者直接调用函数ReadDI,ReadAI处理,相对简单。
串口类型驱动场景相对复杂一些,主要是因为485接口的串口设备可以串联,其中涉及不同的通信协议,不同的地址,FsuOS支持各种协议和不同通讯参数的设备并联在一起采集,只要协议不冲突,就可以正常使用。
例如:
- 2个设备都是Modbus协议,一个是9600波特率,一个是2400波特率,支持。
- 2个设备,一个是电总协议,一个是modbus协议,支持。
- 2个都是modbus协议,但是都是地址1,不行,因为地址1是冲突的。
驱动包的组织:
- so驱动文件在对应的目录放
- public/DIPlugins
- public/AIPlugins
- public/SPPlugins
- public/SocketPlugins
- public/PyDrivers
- helper文件负责数据的解析
- view 文件负责解析后数据的显示
- ini/yaml负责B接口信号的映射
每个驱动都需要指定一个驱动文件名,如water2,m810g等,这个驱动文件名是FsuOS App真正使用的文件。
其中so驱动是由c++语言编写生成
php代码由php语言编写
PyDrivers下放置python编写的UniDriver文件。
问题:为什么so驱动不使用C语言编写? 我们注意到C语言具备非常强的向前和向后的兼容性,函数指针在解决动态加载上也够用,能保证程序的代码简单和最大的兼容性,但是FsuOS作为一个新系统,使用C语言开发的弊端同样明显:C语言过于原始,开发时需要格外谨慎,并且代码罗嗦,缺少string,stl,类,多态,智能指针,模板等令人舒服的特性。自c++11后,c++的使用和C#,Java等高级语言几乎一样,几乎没有风险,开发非常快速。
例: water2.zip
public/DIPlugins/water2.so
application/helpers/device/water2.php
application/views/portal/DevicePage/water2.php
application/helpers/ini/water2.ini
通常驱动的编写比较简单,用户只需要仿照例程的写法,就可以完成驱动的编写。如果需要更深刻地了解接口,就需要研究SMDDIDevice, SMDDAIDevice, SMDSPDevice, SMDSocketDevice的头文件,了解api接口。
FsuOS的驱动编写后,通过使用不同的编译器进行编译,就可以在对应的FSU上运行。
FsuOS的调度线程池的实时性,默认有3个调度线程池:
- 采集线程池 由于采集数据的实时性是首要保证的事情,因此此线程池内的动作只有异步读写设备数据,做少量解析,结束。速度最快。
- 告警线程池 采集完成后,要进行告警的判断,由于个别设备告警规则较多,可能为几十甚至上百条规则,并且可能叠加复杂的分权分域权限控制,因此时间会略长,独立使用一个线程池进行判断,这个线程池内任务的执行时间会略滞后于采集线程池。
- 存储/写文件线程池 如果打开了历史数据存储选项,定时器或者告警判断有异常时,会执行写历史数据操作,此时需要和慢速的NAND交互,在服务器端时,会和mongodb这种分布式数据库交互,速度非常慢。
通过设计3个线程池,保证了系统正常运行的时间要求。
服务器端采集
当前FsuOS上运行的驱动都是在FSU上运行的,这个方式的主要问题是:
- 受限于FSU的处理性能,不是所有FSU都具有较高的配置,一旦处理能力不足,优化过程会比较折腾
- 不太好维护,现在更新驱动代码都需要在FSU上操作,一旦数量一多,比如几百台,几千台,更新调试都很折腾。
虽然是可以写批量脚本进行统一覆盖,但是数量一大往往会出现一些莫名其妙的问题,比如只有几台FSU不正常,还要花很长时间定位和研究它们。
所以服务器端采集是一种相对方便维护的方式,服务器端采集的主要问题是:
- 无法支持离线数据,只能在线管理
- 性能优化难度大,毕竟那么多FSU的数据召测和告警都要在服务器测进行,但是优化做好后,性能更好
- 对网络有一定压力,数据传来传去,网络损耗大一点
优点:
- 方便维护,更新驱动只需要服务器一更新全网就更新了
- 数据一致性好
FsuOS解决方案在高级平台管理中也提供服务器端采集的方案,所有为FsuOS编写的驱动,使用服务器编译器编译后都可以在服务器端直接使用。