物联网网络中间件的基本概念

这篇具有很好参考价值的文章主要介绍了物联网网络中间件的基本概念。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用java语言且基于netty, spring boot, redis等开源项目开发来的物联网网络中间件, 支持udp, tcp通讯等底层协议和http, mqtt, websocket(默认实现和自定义协议头实现), modbus(tcp,rtu),plc,dtu(支持心跳,设备注册功能以及AT协议和自定义协议支持),dtu for modbus tcp,dtu for modbus rtu组件适配 等上层协议. 主打工业物联网底层网络交互、设备管理、数据存储、大数据处理. (其中plc包括西门子S7系列,欧姆龙Fins,罗克韦尔CIP,三菱MC). 数据存储将使用taos数据库以及redis消息队列

主要特性
  • 支持服务端启动监听多个端口, 统一所有协议可使用的api接口
  • 包含一套代理客户端通信协议,支持调用:客户端 -> 服务端 -> 设备 -> 服务端 -> 客户端
  • 支持设备协议对象和其业务对象进行分离(支持默认业务处理器【spring单例注入】和自定义业务处理器)
  • 支持同步和异步调用设备, 支持应用程序代理客户端和设备服务端和设备三端之间的同步和异步调用
  • 服务端支持设备上线/下线/异常的事件通知, 支持自定义心跳事件, 客户端支持断线重连
  • 丰富的日志打印功能,包括设备上线,下线提示, 一个协议的生命周期(请求或者请求+响应)等
  • 支持请求时如果连接断线会自动重连(同步等待成功后发送)
  • 支持客户端发送请求时如果客户端不存在将自动创建客户端(同步等待成功后发送)
  • 支持作为mqtt网关,将从工业物联网采集的数据更加简单方便的发布到mqtt服务器
  • 支持常用的物联网协议比如:mqtt、plc、modbus、websocket
  • 支持通过dtu方式使用modbus协议操作plc
模拟工具
  1. QtSwissArmyKnife 支持udp、tcp、modbus、websocket、串口等调试
  2. IotClient 支持plc(西门子,欧姆龙,三菱),modbus,串口,mqtt,tcp, udp等模拟和调试

开发文档

1. 名词解释
  1. 报文对象(Message):报文是对在网络中进行传输的二进制数据的封装,也是二进制数据的载体,在一定程度上 报文 = 二进制数据
  2. 协议对象(Protocol):协议是报文的一个规范约束,比如报文内容是:0x04 AF CD EE 03,那怎么知道这一串表示的是什么呢,协议就是对这一串数据的声明, 比如第一个字节代表数据后面还有几个字节的长度, 第二个字节是电压,第三字节是电流,第四个字节是校验位
  3. 组件对象(FrameworkComponent):在服务端,组件用来管理一个端口所需要的各种接口;在客户端,组件用来管理连接同一个服务器的所有接口以及已经连接的所有客户端。比如服务端的设备管理器,报文需要用到的编解码器,同步异步处理都是由组件来管理
  4. 同步:在调用请求的时候,请求线程会加锁阻塞,直到接收到响应或者超时来解锁
  5. 异步:在调用请求的时候,请求线程在发送完报文后直接返回,不阻塞调用线程, 而是注册一个回调函数,等到对方响应或者超时的时候在做业务处理
  6. 编解码器:用来对网络上的二进制数据进行拆包和粘包的处理对象
  7. 协议工厂(ProtocolFactory):用来创建各个协议对象的地方(因为一个客户端可能包含多个功能(协议), 每个功能对应一个协议对象那就会有很多协议对象,协议工厂用来管理协议对象的创建)
  8. 协议处理器(ProtocolHandle): 用来对协议做业务处理的

下面将由一个例子来展开说明iot框架的使用 例子:比如服务端接受到客户端报文如下:0x01 11 12 13 05 06 EE FF 八个字节, 如果客户端发送完此报文之后没有连续发送, 服务端接受到的数据就是一包完整的报文, 我们可以很容易的读取缓存区的内容然后进行处理; 那如果第一包发送完之后服务端还在忙其他的时没有及时读取缓冲区内容这时候又接收到了客户端的第二个报文,这时候数据缓冲区的数据如下:0x01 11 12 13 05 06 EE FF 02 21 22 23 25 26 AA BB CC DD,这时候程序读取的缓冲区是两包完整的报文,这时候程序怎么将两包报文拆开处理呢?这时候就需要编解码器上场了! 如何处理上面报文粘包和拆包的情况呢?netty提供了一下几种常用的解码器

2. 编解码器
  1. FixedLengthFrameDecoder: 固定长度解码器是最简单的一种方式,每个包的长度是固定的,比如每个包都是8个字节,那么程序就可以以8字节为单位进行拆包
  2. LineBasedFrameDecoder:换行符解码器是让每个报文都用换行符结尾,这时候程序可以循环读取每个字节判断,如果这个字节是换行符就说明已经读完了一包报文
  3. DelimiterBasedFrameDecoder:如果我们的数据里面刚好包含换行符这时候读取就会出错,这时候可以用自定义分隔符来拆分报文
  4. LengthFieldBasedFrameDecoder:不管是换行符解码还是自定义分隔符解码,都需要循环判断每个字节,如果在一包完整的报文很长的情况下性能会非常差,这时候有个非常好用且性能极高的解码器,长度字段解码,就是在报文里面加入一个长度字段用来标识整个报文的长度
  5. ByteToMessageDecoder:如果还有更好的解码方式可以使用自定义报文解码
  6. SimpleChannelInboundHandler:简单的解码器

在设备对接的时候厂家一般会提供协议文档,然后就需要我们来选择合适的解码器,当我们确认好了解码器之后就可以开始编码了,下面先开始服务端的对接教程

3. 服务端教程

编写服务端网络程序时需要监听某个端口来给客户端连接, 当我们选择某个解码器之后就可以选择对应的服务端解码器组件来开启某个端口,iot框架适配了netty提供的几个常用的解码器

创建解码器组件
  1. FixedLengthFrameDecoderServerComponent 使用固定长度解码器的服务端组件
  2. LineBasedFrameDecoderServerComponent 使用换行符解码器的服务端组件
  3. DelimiterBasedFrameDecoderServerComponent 使用自定义分隔符解码器的服务端组件
  4. LengthFieldBasedFrameDecoderServerComponent 使用长度字段解码器的服务端组件
  5. ByteToMessageDecoderServerComponent 使用自定义解码器的服务端组件
  6. DatagramPacketDecoderServerComponent udp协议的服务端组件
  7. SimpleChannelDecoderComponent 简单自定义解码器对应的组件

以下是使用LengthFieldBasedFrameDecoderServerComponent示例

// 首先:必须先创建一个组件对象来继承LengthFieldBasedFrameDecoderServerComponent // 以iot-test模块的断路器服务端模拟为例 public class BreakerServerComponent extends LengthFieldBasedFrameDecoderServerComponent<BreakerServerMessage> { public BreakerServerComponent(ConnectProperties connectProperties) { super(connectProperties, ByteOrder.LITTLE_ENDIAN, 256, 0 , 4, 0, 0, true); } xxx 实现省略 } // 注:要求传入ConnectProperties对象作为构造参数, 此对象可以指定ip和端口

我们看到上面的组件需要一个泛型参数BreakerServerMessage, 此参数就是报文对象,上面我们说过报文对象是一个二进制数据载体,用于在iot框架各个对象中进行使用,下面我们来看看报文对象除了作为数据载体还有哪些扩展功能

创建报文对象

// 创建服务端报文对象必须继承ServerMessage类 public class BreakerServerMessage extends ServerMessage { public BreakerServerMessage(byte[] message) { super(message); } //省略其他构造函数 @Override protected MessageHead doBuild(byte[] message) { this.messageBody = MessageCreator.buildBreakerBody(message); return MessageCreator.buildBreakerHeader(message); } }

  1. 首先报文对象的构造函数BreakerServerMessage#BreakerServerMessage(byte[])必须存在
  2. 报文对象是连接组件和协议的桥梁,所以需要为每个服务端组件创建一个与之对应的报文对象
  3. 需要在BreakerServerMessage#doBuild(byte[])方法里初步解析出对应的equipCode、messageId、protocolType几个参数,这也是对客户端请求数据的初步解析

当我们创建了组件和报文类之后就可以启动应用了, 这时候日志里面会打印出组件配置的端口已经开启监听了。到了这里已经开了一个好头了算是成功了一半了,接下来就是创建协议对象了,从厂家那里拿到的协议文档至少包含一个协议, 一般我们建议为文档里面的每个协议创建一个对应的协议对象(Protocol)

创建协议对象

协议对象就是用来将接收到的二进制数据解析成和协议文档里对应的字段的;出于框架架构的需要我们将协议分成两种类型 如下:

  1. ClientInitiativeProtocol 声明此协议是客户端主动发起的协议 比如断路器主动上报当前的电流、电压、或报警
  2. ServerInitiativeProtocol 声明此协议是服务端主动发起的协议 比如服务端下发断开断路器的指令

首先我们先看一下ClientInitiativeProtocol方法声明, 还是以断路器为例

// 用来接收断路器主动上报的电压电流等数据 public class DataAcceptProtocol extends ClientInitiativeProtocol<BreakerServerMessage> { private double v; // 电压 private double i; // 电流 private double power1; // 有功功率 private double power2; // 无功功率 private double py; // 功率因素 public DataAcceptProtocol(BreakerServerMessage requestMessage) { super(requestMessage); } @Override protected void doBuildRequestMessage(BreakerServerMessage requestMessage) { byte[] message = requestMessage.getBody().getMessage(); this.v = ByteUtil.bytesToInt(message, 0) / 100.0; this.i = ByteUtil.bytesToInt(message, 4) / 100.0; this.power1 = ByteUtil.bytesToInt(message, 8) / 100.0; this.power2 = ByteUtil.bytesToInt(message, 12) / 100.0; this.py = ByteUtil.bytesToShort(message, 16) / 100.0; } // 响应断路器的请求 @Override protected BreakerServerMessage doBuildResponseMessage() { Message.MessageHead head = requestMessage().getHead(); return new BreakerServerMessage(MessageCreator.buildBreakerHeader(head .getEquipCode(), head.getMessageId(), 4, head.getType()), MessageCreator.buildBreakerBody(StatusCode.Success)); } // 省略其他 }

平台已经可以接收设备主动上报的数据了,那平台要怎么主动给设备发送数据呢?ServerInitiativeProtocol协议就是用来声明一个协议是平台主动发给客户端的,下面以平台下发给断路器切换开关为例

/** * 切换断路器的开闭状态 */ public class SwitchStatusProtocol extends ServerInitiativeProtocol<BreakerServerMessage> { private String deviceSn; public SwitchStatusProtocol(String deviceSn) { this.deviceSn = deviceSn; } /** * 构建要发送给断路器的报文 */ @Override protected BreakerServerMessage doBuildRequestMessage() throws IOException { DefaultMessageHead messageHead = MessageCreator.buildBreakerHeader(Long.valueOf(this.deviceSn), 0, protocolType()); return new BreakerServerMessage(messageHead); } /** * 处理断路器对此处请求的响应 */ @Override protected void doBuildResponseMessage(BreakerServerMessage message) { /*设备响应是否切换成功的处理*/ } @Override public BreakerProtocolType protocolType() { return BreakerProtocolType.SwitchStatus; } } // 然后在业务代码里面调用请求方法:new SwitchStatusProtocol(deviceSn).request(); 这样就可以向指定的设备发起请求了文章来源地址https://www.toymoban.com/news/detail-562657.html

到了这里,关于物联网网络中间件的基本概念的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【缓存中间件】Redis哈希槽的概念

    分布式数据库首先要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整体数据的一个子集。。 需要重点关注的是数据分区规则。常见的分区规则有哈希分区和顺序分区两种,哈希分区离散度好、数据分布业务无关、无法顺

    2024年02月13日
    浏览(44)
  • .Net Core核心概念——依赖注入和中间件

    1. 为什么要用依赖注入(DI) 什么是依赖注入,为什么要使用呢?简单通俗说就是一个类需要另一个类来协助工作,就产生了依赖,所以需要的依赖项就要【注入】过来一起来协同完成工作。 软件设计原则中有一个依赖倒置原则(DIP)讲的是要依赖于抽象,不要依赖于具体,高层

    2024年02月08日
    浏览(52)
  • Ubuntu配置基本环境以及docker安装基本中间件

    提示:ip地址请改为自己的本地ip 为了安全性,建议都给一些中间件设置密码(本文也会教大家如何设置密码) 此处如果安装失败,apt要换源。 docker版本为24.0.2 首先,更新软件包索引,并且安装必要的依赖软件,来添加一个新的 HTTPS 软件源: 使用下面的 curl 导入源仓库的

    2024年02月01日
    浏览(56)
  • MQ(消息中间件)概述及 RabbitMQ 的基本介绍

    消息队列中间件是分布式系统中重要的组件,主要解决 应用解耦,异步消息,流量削锋等 问题,实现高性能,高可用,可伸缩和最终一致性架构。流量削锋 : 削减峰值压力(秒杀,抢购) MQ(Message Queue,消息队列)是典型的生产者、消费者模型。生产者不断向消息队列中

    2024年02月12日
    浏览(47)
  • 数据库访问中间件--springdata-jpa的基本使用

    回顾 示例 JPQL 片段 And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2 Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2 Is,Equals findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1 Between findByStartDateBetween … where x.startDate between ?1 and ?2 LessThan findByAgeLessT

    2024年02月14日
    浏览(45)
  • 网络安全基础知识&中间件简单介绍

    apache-httpd tomcat iis lighttp nginx:不是用来web服务器,而是用来做反向代理(tps10w,优化tqs2020w) fastdf:FastDFS 是一个开源的高性能分布式文件系统(DFS)。 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合以

    2023年04月16日
    浏览(49)
  • 系统平台同一网络下不同设备及进程的话题通讯--DDS数据分发服务中间件

    提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理

    2024年02月08日
    浏览(87)
  • 虹科教程 | Linux网络命名空间与虹科PROFINET协议栈的GOAL中间件结合使用

    PROFINET是由PI推出的开放式工业以太网标准,它使用TCP/IP等IT标准,并由IEC 61158和IEC 61784 标准化,具有实时功能,并能够无缝集成到现场总线系统中。凭借其技术的开放性、灵活性和性能优势,PROFINET可应用于过程/工厂自动化、运动控制等领域。通过PROFINET,可实现确定性响应

    2024年02月13日
    浏览(48)
  • 【中间件】消息中间件之Kafka

    一、概念介绍 Apache Kafka是一个分布式流处理平台,用于构建实时数据管道和流应用。它可以处理网站、应用或其他来源产生的大量数据流,并能实时地将这些数据流传输到另一个系统或应用中进行处理。 核心概念: Topic(主题) :消息的分类,用于区分不同的业务消息。

    2024年01月20日
    浏览(66)
  • scrapy---爬虫中间件和下载中间件

            -进来request对象         -加代理         -加cookie         -加请求头     -出去response对象         -修改响应对象,最后进入到爬虫的parser中就是修改后的response 1.加代理   2.加cookie,修改请求头,随机生成UserAgent         2.1加cookie        2.2 修改请求头

    2024年02月16日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包