1 Star 0 Fork 602

hjh2096 / iot

forked from iteaj / iotucy 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 11.14 KB
一键复制 编辑 原始数据 按行查看 历史
iteaj 提交于 2022-04-06 09:14 . update README.md.

iot网络中间件(v2.4.1)

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

主要特性

  • 支持服务端启动监听多个端口, 统一所有协议可使用的api接口
  • 包含一套代理客户端通信协议,支持调用:客户端 -> 服务端 -> 设备 -> 服务端 -> 客户端
  • 支持设备协议对象和其业务对象进行分离(支持默认业务处理器【spring单例注入】和自定义业务处理器)
  • 支持同步和异步调用设备, 支持应用程序代理客户端和设备服务端和设备三端之间的同步和异步调用
  • 服务端支持设备上线/下线/异常的事件通知, 支持自定义心跳事件, 客户端支持断线重连
  • 丰富的日志打印功能,包括设备上线,下线提示, 一个协议的生命周期(请求或者请求+响应)等
  • 支持请求时如果连接断线会自动重连(同步等待成功后发送)
  • 支持客户端发送请求时如果客户端不存在将自动创建客户端(同步等待成功后发送)

合作方式(qq: 97235681)

  1. 设备对接(不包括业务, 只负责设备协议部分,按设备协议数量收费)[800+]
  2. 物联网系统开发(包括设备和业务完整系统)[价格详谈]
  3. 为厂家提供专门的设备交互sdk(java)[价格详谈]

已/待开发的协议

  1. tcp(固定长度解码, 长度字段解码, 换行符解码,自定义分隔符解码,自定义字节到报文解码)[已完成/v2.0.0]
  2. mqtt协议客户端,支持连接标准mqtt broker服务器[已完成/v2.1.0]
  3. 提供modbus支持[已完成/v2.2.0]
    • 支持modbus tcp、rtu [已完成/v2.4.0]
    • 支持modbus tcp/rtu for dtu [已完成/v2.4.0]
    • 支持modbus tcp客户端 [已完成/v2.4.0]
    • 支持dtu心跳、设备注册、AT指令、以及自定义指令
  4. 新增plc(西门子、欧姆龙)支持(已完成/v2.4.0)
  5. taos数据库适配(已完成/v2.4.0)
    • 支持单条写入、批量写入

更新日志(最新 v2.4.1)

  1. 完成和测试通过modbus tcp客户端协议实现(2021/9/11)
  2. 完成和测试通过mqtt协议的客户端实现(2021/9/7)
  3. 完成西门子plc的开发和模拟调试(2021/12/17)
  4. 完成欧姆龙plc的开发和模拟调试(2021/12/28)
  5. 重新构建modbus tcp client以及新增modbus tcp for dtu功能【v2.4.0+】(2022/4/5)
  6. 重新构建modbus以及新增modbus rtu for dtu功能并新增DTU AT协议和自定义协议支持【v2.4.0+】(2022/4/5)

并发测试

  1. 测试包下载地址
  2. 使用方法:测试包是一个springboot应用,需要安装jdk环境,下载下来后在控制台输入运行命令:java -jar -Diot.num=5000 iot-test-2.3.0.jar。 其中iot.num参数用来指定要创建的连接数。此测试应用是用iot-test打包的源码请看iot-test模块
  3. 测试方式:首先会快速创建iot.num指定的连接数量, 然后会定时(3秒)从这些数量的连接中随机取出一台并且发送报文。其中包含有一个获取服务器实时配置数据的连接,用来实时报告测试服务器的运行状态。整个测试服务端会开启两个监听端口(15800, 15811)
  4. 测试环境的配置:2核8G centos8.0 带宽2M
  5. 服务启动前资源详情:可用内存:5634MB 启动后(客户端连接还没创建):5418MB

QQ群二维码

qq交流群

模拟工具

  1. QtSwissArmyKnife 支持udp、tcp、modbus、websocket、串口等调试
  2. IotClient 支持plc(西门子,欧姆龙,三菱),modbus,串口,mqtt,tcp, udp等模拟和调试

使用教程

首先创建一个springboot应用

// 注springboot 2.6以上的需要添加一下配置
spring.main.allow-circular-references=true

服务端教程

引入服务端jar包
//在maven文件里面引入服务端jar包
<dependency>
    <version>version</version>
    <groupId>com.iteaj</groupId>
    <artifactId>iot-server</artifactId>
</dependency>
创建报文解码组件
  1. 创建固定长度解码器组件(以固定长度解码器为例)
package com.iteaj.iot.test.server.fixed;

import com.iteaj.iot.AbstractProtocol;
import com.iteaj.iot.config.ConnectProperties;
import com.iteaj.iot.server.component.FixedLengthFrameDecoderComponent;
import com.iteaj.iot.server.protocol.HeartbeatProtocol;
import com.iteaj.iot.test.TestProtocolType;

/**
 * 固定长度解码器组件测试
 *  _注意:此组件必须交由spring容器管理_ 
 *  _注意:此处必须指定此组件使用的报文类型<FixedLengthServerMessage>_ 
 */
@Component
public class TestFixedLengthDecoderComponent extends FixedLengthFrameDecoderComponent<FixedLengthServerMessage> {

    // 构造函数指定要监听的端口 8080
    // 指定固定长度28
    public TestFixedLengthDecoderComponent() {
        super(new ConnectProperties(8080), 28);
    }

    @Override
    public String getDesc() {
        return "用于测试服务端固定长度字段解码器[FixedLengthFrameDecoder]";
    }

    /**
     * 通过报文头获取对应的协议
     */
    @Override
    public AbstractProtocol getProtocol(FixedLengthServerMessage message) {
        TestProtocolType protocolType = message.getHead().getType();
        // 心跳类型返回心跳协议
        if(protocolType == TestProtocolType.Heart) {
            return HeartProtocol.getInstance(message);
            
        // 对于客户端主动请求服务器的协议类型 - new一个协议对象    
        } else if(protocolType == TestProtocolType.CIReq) {
            return new FixedLengthClientRequestProtocol(message);
        } else {
            // 对于客户端响应服务器的协议类型 - 必须移除保存在服务端的协议
            return remove(message.getHead().getMessageId());
        }

    }

    @Override
    public String getName() {
        return "固定长度字段解码组件";
    }
}
  1. 创建固定长度解码报文类(一个组件对应一个报文)
package com.iteaj.iot.test.server.fixed;

import com.iteaj.iot.server.ServerMessage;
import com.iteaj.iot.test.MessageCreator;

/**
 * 固定长度报文 28
 *    8         8        4       8
 * 设备编号 + messageId + type + 递增值
 *  _注:服务端报文必须继承父类:ServerMessage _ 
 */
public class FixedLengthServerMessage extends ServerMessage {

    // 注意:此构造函数一定要存在
    public FixedLengthServerMessage(byte[] message) {
        super(message);
    }

    public FixedLengthServerMessage(MessageHead head) {
        super(head);
    }

    public FixedLengthServerMessage(MessageHead head, MessageBody body) {
        super(head, body);
    }

    // 解析出客户端请求报文的报文头
    @Override
    protected MessageHead doBuild(byte[] message) {
        return MessageCreator.buildFixedMessageHead(message);
    }
}
创建和设备交互的协议
// 交互协议包含两种
// 1. 客户端主动请求服务端(继承 ClientInitiativeProtocol) 比如:[设备获取服务器的当前时间(请求) -> 服务器响应当前时间给客户端(响应)]
package com.iteaj.iot.test.server.fixed;

import com.iteaj.iot.Message;
import com.iteaj.iot.ProtocolType;
import com.iteaj.iot.server.manager.DevicePipelineManager;
import com.iteaj.iot.server.protocol.ClientInitiativeProtocol;
import com.iteaj.iot.test.MessageCreator;
import com.iteaj.iot.test.TestProtocolType;

public class FixedLengthClientRequestProtocol extends ClientInitiativeProtocol<FixedLengthServerMessage> {

    public FixedLengthClientRequestProtocol(FixedLengthServerMessage requestMessage) {
        super(requestMessage);
    }

    // 构建要响应给客户端的报文
    @Override
    protected FixedLengthServerMessage doBuildResponseMessage() {
        Message.MessageHead head = requestMessage().getHead();
        String equipCode = head.getEquipCode();
        String messageId = head.getMessageId();
        DevicePipelineManager instance = DevicePipelineManager.getInstance();
        return MessageCreator.buildFixedLengthServerMessage(equipCode, messageId, instance.size(), head.getType());
    }
    // 解析出客户端请求的报文内容
    @Override
    protected void doBuildRequestMessage(FixedLengthServerMessage requestMessage) {

    }

    @Override
    public ProtocolType protocolType() {
        return TestProtocolType.CIReq;
    }
}
// 2. 服务端主动请求客户端(继承 ServerInitiativeProtocol)比如:[服务端下发开指令到客户端(请求) -> 客户端响应服务端操作是否成功的状态(响应)]
常用的解码组件

说明:以下是已经适配好的常用的解码器组件

  1. DelimiterBasedFrameDecoderComponent 自定义分隔符解码器组件
  2. FixedLengthFrameDecoderComponent 固定长度解码器组件
  3. LengthFieldBasedFrameDecoderComponent 长度字段解码器组件
  4. LineBasedFrameDecoderComponent 换行符解码器组件
  5. ByteToMessageDecoderComponent 自定义字节到报文解码器组件

客户端教程

引入客户端jar包
//在maven文件里面引入iot-client jar包
<dependency>
    <version>version</version>
    <groupId>com.iteaj</groupId>
    <artifactId>iot-client</artifactId>
</dependency>
使用mqtt客户端组件
//在maven文件里面引入iot-mqtt jar包
<dependency>
    <version>version</version>
    <groupId>com.iteaj</groupId>
    <artifactId>iot-mqtt</artifactId>
</dependency>
使用modbus客户端组件

2. 架构图

iot架构图

  1. 设备端和设备管理端同步和异步如线3、4所示
    • 平台主动向设备发起请求4->3:如果是同步调用则线程将等待设备返回在往下执行业务, 如果设备由于某些原因没有返回则将在指定的超时时间内解锁线程继续向下执行业务。如果是异步调用则在设备响应后会执行业务,并不会锁住当前调用的线程
    • 设备主动向平台发起请求3->4:如线3设备主动发起请求给平台, 平台将先解析设备请求的报文然后调用执行业务,执行完业务之后如线4平台将生成需要响应给设备的报文并推送给设备
  2. 应用管理端和设备管理端同步和异步(1、2所示)和1相同的流程
  3. 应用管理端和设备进行同步和异步调用如:1、2、3、4
    • 如果是同步:由应用客户端发起调用如线1所示,发起调用的线程将阻塞, 然后如线4所示设备管理端向设备发起异步调用,接着等待设备响应如线3,再然后设备管理端响应应用客户端如线2,最后将释放应用客户端的线程锁继续向下执行
    • 如果是异步:和同步的区别是应用客户端不加锁
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/hjh2096/iot.git
git@gitee.com:hjh2096/iot.git
hjh2096
iot
iot
main

搜索帮助

344bd9b3 5694891 D2dac590 5694891