chzhm159 / IIoTDataGate

主要收集整理工业物联网环境中各种硬件的通信协议.
GNU General Public License v3.0
28 stars 3 forks source link

架构设计讨论 #1

Open chzhm159 opened 3 years ago

chzhm159 commented 3 years ago

达成目标

  1. 可以仅仅使用 协议封装 的模块,将对应模块嵌入到已有的项目中.自己掌管网络管理.
  2. 可以使用 协议封装+网络连接管理 的模块,嵌入到已有项目中, 通过提供的API完成业务需求
  3. 可以 协议封装+网络连接管理+访问接口的形式,以独立服务的形式,与现有系统整合.
  4. 协议可以方便扩展: 例如基恩士,欧姆龙,西门子,三菱等等PLC协议的扩展,以及串口,物联网协议的扩展.
  5. 连接管理的扩展: 例如 TCP,UDP,串口,各种物联网协议的扩展
  6. 访问接口的扩展: http,amqp,mqtt,stomp,关系型数据库,非关系型数据库,实时数据处理Flink等
  7. 配置文件化: 读/写配置,通过JSON配置文件实现,而不是通过代码,当然也可以使用代码.

    如何实现

    分为三个模块

  8. protocol 此模块仅处理协议封装.最基本的两个方法: 所以可以仅仅使用这一层嵌入到各自目前项目中.免去自己实现协议的工作量
    • public Byte[] getReadCommand(args){...}: 根据参数构造读取指令的数据包
    • public Byte[] getWriteCommand(args){...}: 根据参数构造写入指令的数据包
  9. core 基于Netty做网络管理,依赖 protocol 模块完成对设备的 读/写 功能. 可以直接使用这个模块直接与设备通讯免去协议实现+网络通信管理,只处理业务逻辑
  10. web 依赖 core模块,然后提供您 Restful 风格的操作接口,可以作为独立的服务运行,并支持数据推送免去协议实现,+网络通信+采集结果的处理,开箱即用,支持集群

    对于开发者

  11. 各种通信协议的支持
  12. 各种推送方式的支持,http,数据库,消息队列等
  13. core模块的特性支持,例如数据发生变化的时候才推送,用于大幅减少重复数据量,确保写入,写入失败重试,与plc强交互等
chzhm159 commented 3 years ago

关于数据存储的一些问题

一个比较接近实际情况的问题场景

笼统的来说以上场景带来如下问题:

  1. 数据量大,另外就是写多读少,比如监控设备状态,环境温度等等,这两个数据,如果1s的采集频率形成历史记录,就意味着每小时有7200条记录,如果多个设备,更多的信息点那数据更多.
  2. 包含常见的CRM的功能,此类功能通常关系型数据库最为适合.
  3. 需要数据统计
  4. 需要数据可视化

综合以上问题寻找方案

方案探索 首先不可能自己从头开发一套已经有大把现成的CRM系统.但是目前的CRM系统绝大多数基于关系型数据库.那么如何处理大量工业数据? 如何数据实时统计分析? 如何数据可视化? 需要一个整合方案.

  1. CRM系统基于目前市场上成熟产品
  2. 在CRM系统中衔接一种能够处理大量数据的存储系统
  3. 数据的实时计算,例如 Apache Flink , Apache Spark 等此类系统
  4. 数据可视化系统,最好是能与数据存储直接链接的,不需代码开发的最好,例如 Grafana

目前这块问题还没想好如何解决.也期望能遇到高人指点

chzhm159 commented 3 years ago

关于软件架构本身的一些思考

chzhm159 commented 3 years ago

数据处理思路

数据流向 应用场景
1. 采集程序--->Database 仅采集,直接录入数据库,且每秒写入数据量不是很大的情况
2. 采集程序--->MQ 从消息队列中消费数据,希望独立处理数据的场景
3. 采集程序--->[MQ]--->Flink--->Cassandra 通用一站式,解决方案

重点说一下第 3 种: 首先 MQ 为非必须项,但是如果不适用MQ,则消息的持久化,可靠性,需要自己维护.故前期为了减少工作量,依然选择走MQ 采集到原始数据后,针对不同的场景,基本的处理思路:

  1. 如果需要先计算,再存储,则计算的工作,在Flink环节处理,可以利用其 Stateful 的特性,同时可以利用多个数据源,结合业务逻辑计算
  2. 结算存储进入 Cassandra,天然支持分布式,写入性能高,检索速度高,后续的数据可视化直接基于这里展开
yyt6801 commented 3 years ago

v2 路过,支持一下 同关注该领域,可惜技术栈为c/c++,不熟java... 那就提几条建议吧

  1. 首先支持 Modbus、 OPC DA、OPC UA、IEC101、104这几种常用协议之后再考虑其他;
  2. 既然是实时数据通讯,存储的话,必然有极大量的数据,考虑持久性的话,数据量这部分后续需好好考虑(数据库选型及压缩算法等)
chzhm159 commented 3 years ago

@yyt6801 多谢,真的非常感谢,找不到同伴,一个人摸索前进的感觉太难受了。

数据量部分我的规划是这样的:

  1. 在采集端减少数据量,例如设备状态,只有发生变化时才上抛;温湿度这种,在变化超过一个比例后再上抛会大幅度减少数据量
  2. 用时序数据库,天然支持物联网的应用场景,之前用过Influxdb,但是在此基础上做统计的话略显尴尬,多个指标关联查询的情况下比较麻烦,比如Influxdb2.0之前不支持jion操作。所以才有了目前用 Apache Flink先做数据计算(同时可以结合PostgreSQL),然后写入 Apache Cassandra的方案
chzhm159 commented 2 years ago

增加一层数据池的组件,方便程序的逻辑处理. 具体实现如下:

  1. 将采集和数据使用分离. 不直接通过onValue回调给 应用层,而是更新到数据池中即可. 比如数据池可以用Redis存储.
  2. 应用层,通过主动从数据池(Redis)中获取数据,完成逻辑控制,而数据池中如果有数据变动,会自动同步给设备.

这样会对程序控制逻辑上的改变.以具体案例说明:(工控领域常用的PLC与软件的握手流程) 软件需要监控 设备中 A变量=1 时,读取 B变量的数值,并且将B变量数值存入数据库,然后将 C变量设置为1,然后监控A变量,当A变量=0时,再将C变量设置为0.

实现方式: 一. 基于目前功能,针对 A变量, 设置一个回调函数,读取间隔100ms,然后在这个回调函数中,需要设置全局变量,来控制当A=0时,与当A=1时的逻辑处理.同时先读取B,在设置C=1,然后判断当A=0时,再设置C=0. 此时有个问题,就是 A只有一个回调函数,且每隔100ms就会被重入,而此时 会存在多种情况,比如 数据库写入失败,或者变量C写入失败.所以需要通过一些全局变量来指示当前状态,以便对各种异常做处理.

二. 使用定时器,轮询 A,C变量当前数值: 当A=0,C=0时不做任何处理 当A=1,C=0时,读取B,处理完后,将C=1 当A=1,C=1时,不做任何处理, 当A=0,C=1时,将C=0. 至此, 回到了 A=0,C=0.
逻辑更加清晰 A,B,C变量的读写,都是与数据池交互即可,完全屏蔽了通信层,而且可以同时操作多个变量 代价是实时性较低,A,C的监控周期都是100ms,那么第1次读取到A=0,写入C=0后,下一个周期再读取C时,可能C依然为0,或许网络波动,导致C还没写入设备.此时 A=0,C=1,不做处理,相当于浪费了100ms. 但是带来的好处就是,软件状态与设备状态是同步的,且逻辑清晰,异常情况好处理. 方法二是借鉴了电控中控制思路,同时Labview中与 OPC Server也同样是这么处理. 同时经过了用软件控制设备生产的实际应用考验后,决定的.

chzhm159 commented 1 year ago

几经波折,确定最终结构如下:

核心模块(Core)完成如下功能:

如需基于此库实现业务逻辑有2种方式: