ThingsBoard如何接受设备通过TCP发送的报文

news2024/9/25 17:21:28

1、概述

2、案例

2.1、阐述

2.2、导入依赖

2.3、构建Netty服务链接,接受的端口为8092

2.4、对数据进行相应的处理发送到ThingsBoard客户端

2.5、通过TCP链接工具

​2.6、查看遥测数据


1、概述

TCP(Transmission Control Protocol,传输控制协议)是互联网中的一种面向连接的、可靠的、基于字节流的传输层通信协议。它提供了点对点的通信,并且可靠地传递数据。TCPInternet 协议族中最为重要、应用最为广泛的一种协议。

2、案例

ThinsBoard原生代码中,只支持 Coap、Https、Lwm2m、Mqtt、Snmp五种协议的传输格式,并不支持TCP的报文协议,但是很多场景下设备的发送协议就是TCP协议或者是UDP协议的情况,如何把这类的设备接收到ThingsBoard平台中,目前共有三种实现方式:

第一种 :通过外部服务将报文转换成ThingsBoard原生代码支持的协议进行发送 

第二种:通过ThingsBoard GateWay进行进行数据的转换

第三种:修改ThingsBoatd源码,创建Transport来支持TCP协议的数据

三种转换的方式各有利弊,再次并不推荐说那种好或者那种不好,本次文章只对第一种情况进行讲解,在不修改源代码的情况下,将TCP接收到的数据,发送到ThingsBoard平台

2.1、阐述

设备通过TCP发送消息,其实就是需要建立对应的Socket链接,我们使用Netty来暴露对应的端口,让设备往对应的端口上发送数据,服务接受到数据后,对数据进行解析,解析完成后,推送到ThingsBoard平台

2.2、导入依赖
        <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.1.63.Final</version>
            </dependency>
            <dependency>
                <groupId>org.eclipse.paho</groupId>
                <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
                <version>1.2.5</version>
            </dependency>
2.3、构建Netty服务链接,接受的端口为8092
package com.example.tpson_tcp;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 * Netty服务端类,用于启动TCP服务器。
 */
@Service
public class NettyServer {

    /**
     * 在对象初始化后自动调用的方法,用于启动服务器。
     * 无参数和返回值。
     */
    @PostConstruct
    public void main() {
        // 创建EventLoopGroup用于处理网络事件
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            // 配置服务器启动参数
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class) // 指定使用的NIO通道类
                    .childHandler(new ChannelInitializer<SocketChannel>() { // 设置通道初始化处理器
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 在通道中添加处理链,用于解码、编码和处理设备数据
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                            ch.pipeline().addLast(new DeviceDataHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128) // 设置连接队列大小
                    .childOption(ChannelOption.SO_KEEPALIVE, true); // 启用TCP KeepAlive

            // 绑定端口并启动服务器
            ChannelFuture channelFuture = serverBootstrap.bind(8092).sync();
            // 等待服务器关闭
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            // 异常处理,抛出运行时异常
            throw new RuntimeException(e);
        } finally {
            // 关闭EventLoopGroup,释放资源
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}
2.4、对数据进行相应的处理发送到ThingsBoard客户端

mqtt的username是设备的ID,根据你们自己的设备ID进行修改

/**
 * 该类继承自SimpleChannelInboundHandler,用于处理设备数据。
 * 当设备数据到达时,会将数据发送到MQTT服务器。
 */
package com.example.tpson_tcp;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.eclipse.paho.client.mqttv3.IMqttClient;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;

public class DeviceDataHandler extends SimpleChannelInboundHandler<String> {

    private IMqttClient mqttClient; // MQTT客户端接口

    /**
     * 构造函数:初始化MQTT客户端并连接到服务器。
     */
    public DeviceDataHandler() {
        try {
            mqttClient = new MqttClient("tcp://127.0.0.1:1883", MqttClient.generateClientId());
            MqttConnectOptions options = new MqttConnectOptions();
            options.setCleanSession(true); // 设置会话清除标志
            options.setUserName("001001001"); // 设置用户名
            mqttClient.connect(options); // 连接到MQTT服务器
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 当通道中有可读数据时调用该方法。
     *
     * @param ctx 通道上下文
     * @param msg 接收到的消息
     * @throws Exception 抛出的异常
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("Received device data: " + msg);
        // 将接收到的设备数据发送到MQTT的主题
        MqttMessage message = new MqttMessage(msg.getBytes());
        System.out.println(message);
        mqttClient.publish("v1/devices/me/telemetry", message);
    }

    /**
     * 当捕获到异常时调用该方法。
     *
     * @param ctx 通道上下文
     * @param cause 异常原因
     * @throws Exception 抛出的异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close(); // 关闭通道
    }
}
2.5、通过TCP链接工具

链接到服务器:localhost,端口:8092上 

发送区发送数据:

{time:”2024年5月5日”}
 2.6、查看遥测数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1644537.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于 c++的模板库中的数组模板 is_array_v的测试

&#xff08;1&#xff09;该模板的源代码如下&#xff1a; template <class> // determine whether type argument is an array bool is_array_v false;template <class _Ty, size_t _Nx> bool is_array_v<_Ty[_Nx]> true;template <class _Ty>…

屏蔽罩材质和厚度对屏蔽效能的影响

​ 一&#xff0e;屏蔽效能的影响因素 屏蔽效能的影响因素主要有两个方面&#xff1a;屏蔽材料的特性和厚度&#xff1b;如下图所示&#xff0c;电磁波经过不同媒介时&#xff0c;会在分界面形成反射&#xff0c;穿过界面的电磁波一部分被反射回去&#xff0c;这部分能量损失…

nginx--反向代理

反向代理 指的是代理外网用户的请求到内部的指定web服务器器&#xff0c;并将数据返回给用户的一种方式&#xff0c;这是用的比较多的一种方式 模块和功能 ngx_http_proxy_module&#xff1a; 将客户端的请求以http协议转发至指定服务器进行处理。ngx_stream_proxy_module&…

自学错误合集--MessageSource国际化接口

java后端自学错误总结 一.MessageSource国际化接口总结 一.MessageSource国际化接口 今天第一次使用MessageSource接口,比较意外遇到了一些坑 messageSource是spring中的转换消息接口&#xff0c;提供了国际化信息的能力。MessageSource用于解析 消息&#xff0c;并支持消息的…

hadoop启动后没有namenode,datanode等解决方法

之前用的是虚拟机&#xff0c;在虚拟机上安装的hadoop&#xff0c;但是后来&#xff0c;电脑恢复出厂设置了&#xff0c;什么都重新开始。就在本地安装 Linux 子系统。 但是&#xff0c;有时候start-dfs.sh后&#xff0c;jps出现错误。 像这种拒绝连接 解决办法就是如下&…

智慧隧道建设中,如何提升隧道广播清晰度,解决隧道广播有效发布问题

近年来&#xff0c;我国高速公路智慧隧道建设步伐加快&#xff0c;全国各地高速公路运营单位纷纷加大投资力度&#xff0c;进行智慧隧道建设&#xff0c;提高隧道智能化水平。通过高清视频监控、AI视频识别、雷视融合、全域轨迹、激光雷达、火灾报警、气体检测、亮度检测、自动…

倪海厦(二)以果决其行,放空自己。

研究任何学问&#xff08;事物&#xff09;&#xff0c;批判去看&#xff0c;假设--验证--结果。以果决其行&#xff01;&#xff01;&#xff01;放空自己。学而后思&#xff0c;思学并进。 其实总结下来&#xff0c;也正如倪老师所说&#xff0c;以果决其行&#xff0c;我们…

STM32F1之FLASH闪存

目录 1. 简介 2. 闪存模块组织 3. FLASH基本结构 4. FLASH解锁 5. 使用指针访问存储器 6. 程序存储器全擦除 7. 程序存储器页擦除 8. 程序存储器编程 9. 选项字节 1. 简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&#xff0c;通过…

第 129 场 LeetCode 双周赛题解

A 构造相同颜色的正方形 枚举&#xff1a;枚举每个 3 3 3\times 3 33的矩阵&#xff0c;判断是否满足条件 class Solution {public:bool canMakeSquare(vector<vector<char>>& grid) {for (int i 0; i < 2; i)for (int j 0; j < 2; j) {int c1 0, c…

一款 NodeJS 版本管理工具 NVM (Windows)

一、简介 Node Version Manager&#xff08;NVM&#xff09;是一种用于管理多个 NodeJS 版本的工具。在日常工作中&#xff0c;我们可能同时在进行多个不同的项目开发&#xff0c;每个项目的需求不同&#xff0c;依赖与不同版本的NodeJS 运行环境。这种情况下&#xff0c;维护…

通过DataGrip将mysql表结构信息转存excel 复制select结果的insert插入语句

各位小伙伴们大家好&#xff0c;欢迎来到这个小扎扎的专栏 总结 | 提效 | 拓展&#xff0c;在这个系列专栏中记录了博主在学习期间总结的大块知识点&#xff0c;以及日常工作中遇到的各种技术点 ┗|&#xff40;O′|┛ &#x1f306; 内容速览 1 查询表结构信息&#xff0c;并…

巴菲特称AI与核武器一样可怕,并调侃AI诈骗可能成下一个增长产业|钛媒体AGI | 最新快讯

总的来看&#xff0c;巴菲特对于 AI 有所知晓&#xff0c;希望它能够是件好事&#xff0c;而且认为AI会颠覆和改变这个世界&#xff0c;但是他并不是很了解&#xff0c;也言下之意表示&#xff0c;他并不会在 AI 领域进行投资。 &#xff08;图片来源&#xff1a;由 AI 生成的巴…

C++中的内存管理(上)

一、C中的内存分布 我们先来看下下面的代码&#xff1a; int globalvar 1; static int staticGlobalvar 1; void test() {static int staticVar 1;int localvar 1;int num1[10] { 1, 3, 2, 4 };char char2[] "abcd";const char* pChar3 "abcd";in…

常见的零拷贝技术

传统IO 基于传统的IO方式&#xff0c;底层实际上通过调用read()和write()来实现。通过read()把数据从硬盘读取到内核缓冲区&#xff0c;再复制到用户缓冲区&#xff1b;然后再通过write()写入到socket缓冲区&#xff0c;最后写入网卡设备。整个过程发生了4次用户态和内核态的上…

【前端开发---Vue2】史上最详细的Vue入门教程(五) --- 细讲‘生命周期’

什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09;什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09;&#xff0c;本篇将详细讲解vue中的核心 --- 生命周期&#xff0c;并提供具体案例来让小伙伴们加深理解、彻底掌握…

# 从浅入深 学习 SpringCloud 微服务架构(九)

从浅入深 学习 SpringCloud 微服务架构&#xff08;九&#xff09; 一、微服务网关引入 1、在微服务架构中&#xff0c;不同的微服务一般会有不同的网络地址&#xff0c; 如果让客户端直接与各个微服务通讯&#xff0c;可能会有很多问题&#xff0c;如&#xff1a; 1&#…

AI适老化!10秒一张的AI姓氏头像,居然要卖9块9?中老年用户都说好!

看短视频的你&#xff0c;一定会刷到过这样的直播间&#xff1a; 现在大家明白了&#xff0c;这是一个做姓氏图像的直播间。我刚开始刷到的时候也觉得这种头像好看&#xff0c;高大上&#xff0c;也想做一个这样的图像&#xff0c;来当自己的微信头像。 做这样的图像需要排队刷…

Jenkins自动化搭建记录

每一份努力都是有一份期盼&#xff0c;每一份付出都是为了有更多的收获。 本文记录一次搭建Jenkins自动参数化打包APK的实现过程和碰到的问题&#xff0c;实现了在Windows和Mac系统下的自动化打包流程。 因为Jenkins的安装过程在网上的教程很多&#xff0c;这里就不在赘述。 …

手动实现简易版RPC(三)

手动实现简易版RPC(三) 往期内容 手动实现简易版RPC&#xff08;一&#xff09;&#xff1a;RPC简介及系统架构 手动实现简易版RPC&#xff08;二&#xff09;&#xff1a;简单RPC框架实现 前言 接上两篇博客我们实现了最简易RPC框架&#xff0c;接下来的几期重点在简易版…