golang的MQTT的连接操作

        最近在使用golang开发后端服务的时候,因为需要和物联网设备进行数据交互,由于需要终端主动上报数据,也需要平台主动下发指令,所以我们选择了mqtt进行通信。

1、MQTT通信逻辑

        MQTT采用的是订阅和发布的方式,数据是通过广播的方式,客户端A、B、C订阅了一个主题后,主题客户端发送数据的时候,A、B、C客户端都会收到广播出来的数据。那么当我们物联网设备需要向平台发送消息数据的时候,我们平台就订阅物联网设备发布的主题,然后设备发布消息后,平台收到订阅发布的消息,然后平台再对消息进行逻辑处理;当平台想给物联网设备发送消息的时候,物联网设备需要订阅平台发布的主题,然后平台发送广播消息,物联网设备就收到平台发送的消息。

        还有就是MQTT通信需要提前建立一个MQTT服务器,这个服务是MQTT消息的转发服务,他负责主题的管理,客户端端的管理等,我们项目使用的开源MQTT服务EMQX搭建的。

2、基于golang的代码实现

        基于golang实现的MQTT服务连接部分代码如下所示:

import ("fmt""crypto/tls""crypto/x509""io/ioutil"mqtt "github.com/eclipse/paho.mqtt.golang"
}type jellyMessgae struct {Message int         `json:"message"`Data    interface{} `json:"data"`
}type jellyCommand struct {Command int         `json:"command"`Data    interface{} `json:"data"`
}var g_client *mqtt.Clientfunc MQTTInit() {var broker = "192.168.10.138"var port = 8883opts := mqtt.NewClientOptions()opts.AddBroker(fmt.Sprintf("mqtts://%s:%d", broker, port))newclientid := "Mqttclientid-" + time.Now().Format("2006-01-02-15:04:05")opts.SetClientID(newclientid)opts.SetUsername("admin")opts.SetPassword("admin@123")opts.SetDefaultPublishHandler(messagePubHandler)opts.SetAutoReconnect(true)opts.OnConnect = connectHandleropts.OnConnectionLost = connectLostHandlertlsConfig := NewTlsConfig()opts.SetTLSConfig(tlsConfig)client := mqtt.NewClient(opts)g_client = &clientif token := (*g_client).Connect(); token.Wait() && token.Error() != nil {panic(token.Error())}
}func NewTlsConfig() *tls.Config {certpool := x509.NewCertPool()ca, err := ioutil.ReadFile("./config/ca.crt")if err != nil {fmt.Println(err.Error())}certpool.AppendCertsFromPEM(ca)return &tls.Config{RootCAs:            certpool,InsecureSkipVerify: true}
}// MQTT客户端连接Handle
var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) {fmt.Println("Connected MQTT Server!!!")//连接成功后,订阅主题,订阅后,EMQX才新建一个对应的主题token := client.Subscribe("message_topic", 1, nil)token.Wait()fmt.Println("Subscribed to topic: ", "message_topic")
}// MQTT最后一次链接Handle
var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {fmt.Printf("Connect lost: %v", err)//这里可以做自定义重连机制
}// MQTT客户端订阅消息处理回调Handle
var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {//处理agent传上来的消息var pmessage jellyMessgae json.Unmarshal(msg.Payload(), &pmessage)fmt.Println("Received message from topic: ", msg.Topic(), "message = ", pmessage.Message)//处理你接收到的数据// add your code //给终端发送MQTT消息var mesg jellyCommand //组装需要发送的数据//add your coderesByte, err := json.Marshal(mesg)if err != nil {fmt.Println("[MQTTCommand_AgentUpdate] json.Marshal error:", err)return}MQTTCommand_Publish("command_topic", resByte)}//平台发送命令到物联网设备的MQTT消息
func MQTTCommand_Publish(topic string, data interface{}) {fmt.Println("[MQTTCommand_Publish]: ", topic)token := (*g_client).Publish(topic, 0, false, data)token.Wait()
}

简单解析下上面的代码:

  • 代码不能直接运行,因为没有定义package包,需要将内容拷贝到你自己的测试代码里面去
  • 代码里面使用的是mqtts来连接的mqtt服务器,服务器使用mqtts才能进行连接,客户端需要配置一个ca证书,证书可以是自签证书也可以是CA机构颁发的证书,示例代码里面的证书使用的是ca.crt自签证书
  • 不管是发布消息还是接收消息,都需要使用一个唯一的客户端id去连接MQTT服务,然后再进行订阅、发布、接收等操作,示例代码中使用的是一个字符串加时间字符串来作为客户端ID
  • 代码里面订阅了一个叫message_topic的主题,平台订阅了这个主题后,物联网设备上报消息的时候,平台就可以收到消息,解析消息的代码也给出,具体怎么处理数据,大家自己修改代码
  • 平台通过同一个客户端ID去发送数据,主题为command_topic,发送的数据定义了一个结构体数据,用户自行组合数据进行数据的发送,物联网设备订阅了该主题的就会收到此数据
  • 为了简便展示,示例代码里面的逻辑是当平台收到主题为message_topic的消息后,马上就往主题为command_topic发送了数据。

3、小结

  • EMQX服务的主题不需要去创建和取消,当客户端发送消息,附带的主题时,服务会自动创建一个主题
  • 连接MQTT服务的客户端ID不能重复,否则会报错,无法连接到服务端
  • MQTT消息发送是广播形式,用户可以自己定义一些参数,标识数据是发给所有物联网终端还是发给单独的个别物联网终端
  • 代码示例中的broker是MQTT的服务端地址,port是对应的端口号,8883表示的mqtts的连接方式。

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

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

相关文章

前端大屏适配几种方案

一、方案一:remfont-size 动态设置HTML根字体大小和body字体大小,会使用到lib-flexible.js插件lib-flexible.js (function flexible(window, document) {var docEl document.documentElementvar dpr window.devicePixelRatio || 1// adjust body font…

Element-UI 自定义-下拉框选择年份

1.实现效果 场景表达&#xff1a; 默认展示当年的年份&#xff0c;默认展示前7年的年份 2.实现思路 创建一个新的Vue组件。 使用<select>元素和v-for指令来渲染年份下拉列表。 使用v-model来绑定选中的年份值。 3.实现代码展示 <template><div><el-…

智能革命:未来人工智能创业的天地

智能革命&#xff1a;未来人工智能创业的天地 一、引言 在这个数字化迅速变革的时代&#xff0c;人工智能(AI)已经从一个边缘科学发展成为推动未来经济和社会发展的关键动力。这一技术领域的飞速进步&#xff0c;不仅影响着科技行业的每一个角落&#xff0c;更是为创业者提供了…

创建一个flutter的左划重命名,右划隐藏的功能

首先定义一下参数&#xff0c;以及左划右划的方法 double deleteButtonPosition -120;double renameButtonPosition -120;void _onHorizontalDragUpdate(DragUpdateDetails details) {setState(() {if (details.delta.dx < 0) {// 左滑deleteButtonPosition 0; // 显示删…

【vs2019】window10环境变量设置

【vs2019】window10环境变量设置 【先赞后看养成习惯】求关注点赞收藏&#x1f60a; 安装VS2019时建议默认安装地址&#xff0c;最好不要改动&#xff0c;不然容易出问题 以下是安装完VS2019后环境变量的设置情况&#xff0c;C:\Program Files (x86)\Microsoft Visual Studi…

5.3 mybatis之autoMappingUnknownColumnBehavior作用

文章目录 1. NONE2. WARNING3. FAILING autoMappingUnknownColumnBehavior是< settings >配置下的属性&#xff0c;该属性是指定发现自动映射目标未知列&#xff08;或未知属性类型&#xff09;的行为。就是说当数据库中的字段找不到映射java对象的属性或者与java对象对应…

【C++成长记】C++入门 | 类和对象(上) |类的作用域、类的实例化、类的对象大小的计算、类成员函数的this指针

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;C❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、类的作用域 二、类的实例化 三、类对象模型 四、this指针 1、this指针的引出 2 this指针的特…

AI python

AI python 软件方面程序上的人工智能&#xff0c;和物理那种能跑机器人没关系

cocos creator 实现spine局部换装

1 使用3.7.4版本 2 js代码 3 c Native层修改源码

为什么你的LDO输出不稳定?

原文来自微信公众号&#xff1a;工程师看海&#xff0c;与我联系&#xff1a;chunhou0820 看海原创视频教程&#xff1a;《运放秘籍》 大家好&#xff0c;我是工程师看海。 前一阵朋友和我说当初用某型号LDO时&#xff0c;发现输出异常&#xff0c;仔细阅读datasheet后&#x…

Java可重复单列集合

Collection集合 Java Collection 是 java.util包中的一个接口&#xff0c;它用于将多个对象表示为单个单元。 Collection接口在Java中扮演着非常重要的角色&#xff0c;它提供了一种方式来存储和操作一组对象。以下是一些关于Java Collection的重要信息&#xff1a; 接口定义…

C++string类(个人笔记)

string类 1.认识string的接口以及熟练使用常用接口1.1string类对象的常见构造1.2string类对象的容量操作1.3string类对象的访问及遍历操作1.4string类对象的修改操作 2.vs 和g下string结构的说明3.string类运用的笔试题4.string类的模拟实现 1.认识string的接口以及熟练使用常用…

数据链路层(上):以太网、二层交换机和网络风暴

目录 数据链路层知识概览 数据链路层设备 1、二层交换机 2、拓展&#xff1a;二层交换机与三层交换机有啥区别&#xff1f; 3、广播风暴 4、交换机以太网接口的工作模式 数据链路层的功能 数据链路层--以太网 1、以太网是什么&#xff1f; 2、以太网地址 数据链路层知…

bugku-web-安慰奖

提示备份 开始扫后台 得到备份文件index.php.bak 得到php代码 <?phpheader("Content-Type: text/html;charsetutf-8"); error_reporting(0); echo "<!-- YmFja3Vwcw -->"; class ctf {protected $username hack;protected $cmd NULL;public f…

【python】 numpy 中常用随机数函数的使用和记忆(不易混淆)

文章目录 概述固定分布随机数&#xff08;只需指定形状的随机函数&#xff09;np.random.randomnp.random.randnp.random.randn 随机范围随机数&#xff08;需要指定范围和形状的随机函数&#xff09;np.random.randintnp.random.uniformnp.random.normalnp.random.poisson 代码…

数据分析案例(三):基于RFM分析的客户分群

实验2 基于RFM分析的客户分群 Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢…

PostgreSQL入门到实战-第二十九弹

PostgreSQL入门到实战 PostgreSQL中数据分组操作(四)官网地址PostgreSQL概述PostgreSQL中CUBE命令理论PostgreSQL中CUBE命令实战更新计划 PostgreSQL中数据分组操作(四) 如何使用PostgreSQL CUBE生成多个分组集 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不…

联为机器视觉的课程笔记

1.像素 2592x1944 相当于 500万像素 2.图像 本质是二位数组&#xff08;内存里面是一维数组&#xff09; 图像越大 分别率越大 3.特征对比相对大的 方便寻找大的 灰度图片进行处理 图像->区域->图像 函数 read_image() 从磁盘读取文件 get_image_size() 获取图片大小…

解析ShardingSphere:强大的分布式数据库中间件

在现代软件开发中&#xff0c;随着数据量的爆炸性增长和系统复杂度的持续上升&#xff0c;传统的单体数据库架构已经难以应对日益增长的性能与扩展性需求。针对这一挑战&#xff0c;ShardingSphere应运而生&#xff0c;它提供了一套全面的解决方案&#xff0c;帮助开发者构建更…

Offer必备算法25_01背包_四道力扣题详解(由易到难)

目录 ①牛客DP41 【模板】01背包 问题一解析 问题二解析 解析代码 滚动数组优化代码 ②力扣416. 分割等和子集 问题解析 解析代码 滚动数组优化代码 ③力扣494. 目标和 问题解析 解析代码 滚动数组优化代码 ④力扣1049. 最后一块石头的重量 II 问题解析 解析代…