系统架构

我们推荐使用代码生成工具进行驱动的编写,并在生成的代码上进行微调。

FsuOS App的主要功能就是加载驱动,调度执行,加载告警规则,执行告警判断,动态配置执行,历史数据保存,调用B接口推送。

FsuOS 采用插件式驱动设计,本身只是一个调度框架,没有具体的业务数据功能,系统结构如下:

FsuOS App -> DI 驱动
          -> AI 驱动      -- memcached/redis ---  php helper/views
          -> SP 驱动
          -> Socket 驱动
          -> PyDriver Python驱动

用户通过编写协议驱动,FsuOS 通过加载驱动,完成采集和告警,保存数据的功能。 协议驱动分为2种:

  1. C++编写的原生驱动,下面主要讲的是这种,开发者需要跟随C++驱动的编写方式,来理解驱动是如何工作的。
  2. Python编写的DriverPy,后面有个专门的章节讲这个。这个DriverPy也不是个新概念,本质上,我们采用了Python继承C++类的方式,使用Python代码做逻辑的判断,而使用C++原生驱动去执行操作,来,工作原理和C++原生协议驱动一致,但是由于python的可以直接在目标系统运行,不需要使用制定的编译器,因此少了为不同FSU分别编译驱动的部分,大大节省了维护成本。

用户编写驱动时,不考虑设备运行在哪个端口,只考虑业务数据的处理。

DI,AI和端口数据直接绑定处理,或者直接调用函数ReadDI,ReadAI处理,相对简单。
串口类型驱动场景相对复杂一些,主要是因为485接口的串口设备可以串联,其中涉及不同的通信协议,不同的地址,FsuOS支持各种协议和不同通讯参数的设备并联在一起采集,只要协议不冲突,就可以正常使用。
例如:

  1. 2个设备都是Modbus协议,一个是9600波特率,一个是2400波特率,支持。
  2. 2个设备,一个是电总协议,一个是modbus协议,支持。
  3. 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上运行的,这个方式的主要问题是:

  1. 受限于FSU的处理性能,不是所有FSU都具有较高的配置,一旦处理能力不足,优化过程会比较折腾
  2. 不太好维护,现在更新驱动代码都需要在FSU上操作,一旦数量一多,比如几百台,几千台,更新调试都很折腾。 虽然是可以写批量脚本进行统一覆盖,但是数量一大往往会出现一些莫名其妙的问题,比如只有几台FSU不正常,还要花很长时间定位和研究它们。

所以服务器端采集是一种相对方便维护的方式,服务器端采集的主要问题是:

  1. 无法支持离线数据,只能在线管理
  2. 性能优化难度大,毕竟那么多FSU的数据召测和告警都要在服务器测进行,但是优化做好后,性能更好
  3. 对网络有一定压力,数据传来传去,网络损耗大一点
    优点:
  4. 方便维护,更新驱动只需要服务器一更新全网就更新了
  5. 数据一致性好

FsuOS解决方案在高级平台管理中也提供服务器端采集的方案,所有为FsuOS编写的驱动,使用服务器编译器编译后都可以在服务器端直接使用。