大话 IOT 技术(3) -- MQTT篇

文章目录

    • 前言
    • 前情提要
    • MQTT介绍
    • 组成
    • 万恶的app
    • mqtt服务端
    • 伪代码实现
    • 开源的力量
    • 后话

当你迷茫的时候,请点击 物联网目录大纲 快速查看前面的技术文章,相信你总能找到前行的方向

前言

本篇将开始讲述IOT技术的一个重点,mqtt协议

我发现有一个物联网的准则,想分享给大家,名字我都想好了,就叫张氏定理

  1. 手机app端用http协议与服务端(eg.bypass)进行通信

  2. 设备端用mqtt协议与mqtt服务端进行通信

  3. 服务端(eg.bypass)还要能用mqtt协议与mqtt服务端进行通信

这样,手机到设备的通信链路就算是通了起来。

http协议大家早就司空见惯了,它就像是大货车,能装的东西种类很多,本身体积也是比较庞大的,适用于手机这种要实现丰富的功能的大款。

mqtt协议是本文的重点讲述的对象,它就像小车,轻便简捷,我们通常用json作为消息体进行传递mqtt信息。

下面我们就进入正文吧。

前情提要

上篇(大话 IOT 技术(2) – 配网篇)我们讲了配网的流程,不过与本文关系不大,所以,我们还是先回顾一下经典 IOT 整体架构图

MQTT介绍

本文我还是沿用我们大话系列的精神,用生动的故事形式,来介绍mqtt技术,所以朋友们不用担心太枯燥和无聊。

先引用官方的一段介绍作为开场白,详见 https://mqtt.org/mqtt-specification/:

MQTT is an OASIS standard. The specification is managed by the OASIS MQTT Technical Committee.

MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,它被设计为易于实现,支持所有消息方向的通信,并为远程通信环境提供必要的网络优化。

前面讲到过,mqtt协议和http协议很像,它们都是物联网中的基石。

一般所说xx协议直观理解都是以xx开头,比如,http协议以http/https 开头,例如,url 为 http://test.domain.com/aaa

同理,mqtt协议也是以 mqtt/mqtts开头,例如,mqtt://test.domain.com/bbb,协议具体怎么实现不是本文关注的(偏底层),有兴趣的朋友可以自行百度。

我们主要关注mqtt 应用层,主要里面的几个关键术语,mqtt客户端,mqtt服务端(又叫broker),连接,mqtt消息,主题(topic),发布,订阅

因为这些和我们工作息息相关,而且已经有开源库帮我们封装好了,我们只需要会调用就能实现 IOT 的所有功能。

组成

和众多C/S架构一样,由一个 mqtt服务端(server,又叫broker),还有一个或多个 mqtt客户端(client)组成。

mqtt服务端就像是妈妈,每个客户端就像是她的孩子,孩子们有心事不会跟其他兄弟姐妹们直接说,都会向妈妈倾诉,由妈妈代为转述

妈妈是他们的共同点,在第一篇文章中,我们也去找了手机与设备之间的共同点,只要有共同点,那就有通信的可能,这里也是一样的。

妈妈只是一个中间商,目的还是要实现各客户端之间的通信

比如:

  1. bypass服务 发送 mqtt消息mqtt服务端,消息是想查询设备1的状态(bypass —> mqtt 服务端)

  2. 设备1mqtt服务端获取消息(订阅消息),将自己的状态参数也写成一个 mqtt消息,发给 mqtt服务端(mqtt 服务端--->设备1设备1 ---> mqtt 服务端

  3. bypass服务mqtt服务端获取到了设备1的消息(订阅消息),再进行业务处理,更新在手机端显示(mqtt 服务端 ---> bypass

这样,就完成了 bypass服务 与 设备1 之间的通信

同理,bypass服务 与 设备2 之间的通信也是类似。

那么问题又来了,你怎么保证 bypass服务发送的 mqtt消息 一定能被 设备1 收到呢?设备2 会不会偷看消息

真是个 good question,这也就是 mqtt服务端 的职责所在。

万恶的app

首先,我们来讲个题外话

相信大家手机中肯定装了很多种app,很多万恶的app在你安装后就会流氓地要你关注订阅一些感兴趣的频道,比如,科技,财经,军事,娱乐…

而它的万恶是我都感兴趣,却不让我勾选了,最多只能选几个,这真的让人火大,那我一个也不选吧,还不行,你看这整的我只想说一句粗口:……

好吧,我忍了!

于是我手机上多了一个万恶的app,大概长这样

有没有同款的朋友们,请扣1哈

每个关注订阅的频道,都会有消息的通知,就像上面那样,用消息数量显示,我知道体育频道没有消息,我就不会点进去看,我最喜欢的娱乐频道消息满天飞,我就会点击进去浏览各种八卦……

虽然万恶,但其思想与本文要讲的 mqtt服务很像,所以我才忍你很久了,曾子曰:“我的忍耐是有限度的……"

上面不经意还是引入了一个mqtt专业术语:订阅(subscribe),我们再加一个,主题(topic)

订阅想必大家很好理解,毕竟烂大街的订阅加关注,一键三连……

主题就是上面的兴趣频道

mqtt 中的订阅主题,就等同于所说的关注订阅某个频道,然后巴巴地等着新消息查看。比如汪苏泷的演唱会要来深圳了,什么时候开始抢票,他好帅啊……

这个万恶的app其实就是充当了服务端的身份,管理这些主题,消息动态,而我就是那个可怜巴巴没有抢到票的弱小客户端,悲伤不禁逆流成河……

我们丰富一下流程吧

服务端是那个万恶的app后端服务,客户端有某科技博主和我。

发布消息过程:某科技博主写了一篇文章,标注了科技的标签,提交后,服务端后台会处理,会在科技频道新增一篇科技的文章,并返回成功的响应。

订阅消息过程:我点击了娱乐消息想要查看,服务端接收到了我的请求,从数据库中查询出标签为娱乐的消息并返回。

mqtt服务端

类似上面的万恶app,mqtt服务端也是类似,我们来转变一下上图:

服务端变成了mqtt 服务端,客户端有bypass服务和设备

发布消息过程bypass 发布了一个主题为topic1 的消息,mqtt服务端处理发布消息,在topic1新增一条消息,并返回成功的响应。

订阅消息过程:设备订阅主题为topic4 的消息,mqtt服务端处理订阅请求,从主题topic4中获取其消息并发回给设备,并且客户端的 on_message方法处理消息。

一般地,主题topic可以设置为含有设备的cid的字符串,更简单可以用cid 作为主题,既能保证主题唯一,又能方便设备订阅,这样每个设备都只需要订阅与自己 cid 相关的主题。

那么,bypass 可以发送消息到 cid的主题,设备订阅自己cid 的主题,得到消息后设备再自行处理。

伪代码实现

上面我们主要关注发布和订阅的处理,因为这也是mqtt设计的核心,其他的我们可以暂时忽略,如果让我们自己来设计实现,那我们会怎么做呢?

我认为主要是服务端和客户端设计实现,首先对它们进行梳理一下

mqtt 服务端

  1. 对客户端连接的验证(do_connect),主要校验账号密码或者证书公私钥是否正确
  2. 管理 topic 对应的消息,用队列保存/读取,先入先出
  3. 处理客户端的发布请求(do_publish
  4. 处理客户端的订阅请求(do_subscribe

mqtt 客户端

  1. 连接服务端(connect),连接结果处理(on_connect
  2. 发布消息(publish
  3. 订阅消息(subscribe),对消息处理(on_message

在客户端有 on_connecton_message 是扩展方法,是留给用户去实现自定义业务逻辑。

那我们很自然地可以定义 mqtt 的两个类

下面是我自己实现的mqtt完整的代码,仅仅代表思路的验证,不可用于实际生产哦

import queueclass MqttBroker:def __init__(self) -> None:self.topic_queue_map = {}@staticmethoddef do_connect(**args):print("broker: do_connect 处理客户端连接请求")# 做一些账密或证书公私钥的验证,这里简化一下,直接返回truereturn Truedef do_publish(self, msg: dict):print("broker: do_publish 处理客户端发布请求")topic=msg.get('topic','')q:queue.Queue=self.topic_queue_map.get(topic,queue.Queue())q.put(msg)self.topic_queue_map[topic]=qreturn Truedef do_subscribe(self, topic: str):print("broker: do_subscribe 处理客户端订阅请求")q:queue.Queue=self.topic_queue_map.get(topic,queue.Queue())return qclass MqttClient:def __init__(self) -> None:self.conn: MqttBroker = Nonedef connect(self, user_name: str, password: str):print("client: 发起 mqtt connect 请求...")res=MqttBroker.do_connect(user_name=user_name, password=password)if res:self.conn = MqttBroker()self.on_connect(res=res)def publish(self, msg: dict):print(f"client: publish 发布消息{msg}")res=self.conn.do_publish(msg=msg)print("client: publish success !") if res else print("client: publish failed")def subscribe(self, topic):print(f"client: subscribe 订阅 topic为{topic}的消息")q:queue.Queue=self.conn.do_subscribe(topic=topic)while not q.empty():self.on_message(q.get())def on_connect(self, res):r= '成功' if res else '失败'print(f"client: on_connect ,连接{r}!")def on_message(self, msg):print(f"client: on_message ,自定义处理消息: {msg}")if __name__ == '__main__':client = MqttClient()# 模拟连接print("模拟连接:")client.connect('user', 'password')# 模拟发布print("\n\n\n模拟发布:")for i in range(3):msg = {'topic': '1001', 'msg': {'playload': f'msg{i}: hello mqtt! '}}client.publish(msg=msg)# 模拟订阅print("\n\n\n模拟订阅:")client.subscribe(topic="1001")

执行结果:

模拟连接:
client: 发起 mqtt connect 请求...
broker: do_connect 处理客户端连接请求
client: on_connect ,连接成功!模拟发布:
client: publish 发布消息{'topic': '1001', 'msg': {'playload': 'msg0: hello mqtt! '}}
broker: do_publish 处理客户端发布请求
client: publish success !
client: publish 发布消息{'topic': '1001', 'msg': {'playload': 'msg1: hello mqtt! '}}
broker: do_publish 处理客户端发布请求
client: publish success !
client: publish 发布消息{'topic': '1001', 'msg': {'playload': 'msg2: hello mqtt! '}}
broker: do_publish 处理客户端发布请求
client: publish success !模拟订阅:
client: subscribe 订阅 topic为1001的消息
broker: do_subscribe 处理客户端订阅请求
client: on_message ,自定义处理消息: {'topic': '1001', 'msg': {'playload': 'msg0: hello mqtt! '}}
client: on_message ,自定义处理消息: {'topic': '1001', 'msg': {'playload': 'msg1: hello mqtt! '}}
client: on_message ,自定义处理消息: {'topic': '1001', 'msg': {'playload': 'msg2: hello mqtt! '}}

开源的力量

幸运的是,开源社区早就已经开发出 mqtt 服务端和客户端的程序,不需要自己从头开始去实现。

mqtt broker 参考开源的 EMQX,https://www.emqx.com

mqtt client 参考 paho-mqtt 客户端库使用,十分优雅:

https://docs.emqx.com/zh/cloud/latest/connect_to_deployments/python_sdk.html

后话

我们通过一篇有趣的故事,推理出 mqtt 协议中服务端和客户端的功能和伪代码实现

其实我们生产上用的都是开源的库和工具,根本不需要自我去重新实现,有利有弊。这样我们往往不会继续深究其原理,也对其为什么这样设计感到迷茫。

自己从头设计和简单地实现一遍主体,更有助于理解 mqtt 和被开源工具封装的思路设计,让我们在学习过程中更有成就感。

此文可谓是大话IOT系列迄今为止最重要也是最干货的一篇文章了,我希望能给大家带来一些技术的帮助收获。

相信认真看完这几篇文章的朋友们,是不是有点跃跃欲试了?感觉物联网似乎不过如此啊?我们自己也能实现不是吗?

当然可以啦,事在人为嘛,不过过程就会比较艰辛和漫长,但我相信,只要掌握了物联网的核心,我们自己完全可以实现一个智能家居系统出来。

作为一个普通人员,我自己还是没有那么大的野心的,要精通的事情就太多了,前端,后端,UI,测试,嵌入式……不然一个公司那么多人的工作靠你一个就能完成了?简直是天方夜谭。

我所能做的,只不过是在我认知的范围里面力所能及的,比如大话系列技术的总结,关于工作过程中的代码及心得体会,技术往往都是在一次又一次的总结中成长,等有一天你会发现,你原来这么牛了!所以,多拥抱你手中的笔吧,这才是技术的源泉

后期我还会再写一下测试中用到的模拟设备的代码实现,硬核来袭,敬请期待吧!

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

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

相关文章

大语言模型生成的“超龄劳动者权益保障制度系统化完善建议(修订版)”

大纲 │ ├── 一、基于征求意见稿现状的评估 │ ├── 制度意义:25条暂行规定首次明确权益范围,提供法律依据 │ └── 关键缺陷 │ ├── 法律定位不明确 │ ├── 社保衔接不足 │ └── 实施机制不完善 │ ├── 二、法…

【UnityAS】Unity Android Studio 联合开发快速入门:环境配置、AAR 集成与双向调用教程

这是一篇2021年的存档,使用Unity2020版本。 至今,Unity与AS很多通讯方式也是基于此衍生。 作为Unity与AS联合开发的受益者,难得掏出自己的饭碗,诸君共享! Unity & Android Studio 联合开发快速入门 ——Unity与AS…

前后端联合实现多个文件上传

1、前端 Vue3CommonApplyBasicInfoForm.vue<script setup lang"ts" name"CommonApplyBasicInfoForm"> ...... // 文件输入实例对象 const fileInputRef ref<HTMLInputElement | null>(null); // 选择文件列表 const selectedFiles ref<Fi…

软考高级--系统架构设计师--综合知识真题解析

系列文章目录 文章目录系列文章目录一、2019年真题二、2020年真题三、2021年真题四、2022年真题总结一、2019年真题 二、2020年真题 三、2021年真题 四、2022年真题 总结

“帕萨特B5钳盘式制动器结构设计三维PROE模型7张CAD图纸PDF图“

摘 要本文首先对汽车制动器原理和对各种各样的制动器进行分析,详细地阐述了各类制动器的结构,工作原理和优缺点。再根据轿车的车型和结构选择了适合的方案。根据市场上同系列车型的车大多数是滑钳盘式制动器,而且滑动钳式盘式制动器结构简单,性能居中,设计规范,所以我选择滑动…

SQL注入6----(其他注入手法)

一.前言 本章节来介绍一下其他的注入手法&#xff0c;也就是非常规注入手法&#xff0c;来和大家介绍一下 二.加密注入 前端提交的有些数据是加密之后&#xff0c;到了后台在解密&#xff0c;然后再进行数据库查询等相关操作的&#xff0c;那么既然如 此我们也应该将注入语句…

visual studio2022 配置 PCL 1.13.1

PCL库下载 下载链接&#xff1a; https://github.com/PointCloudLibrary/pcl/releases 下载这两个。 PCL库安装 运行.exe文件进行安装。 环境变量勾第二个&#xff08;其实无所谓&#xff0c;反正还要添加别的环境变量&#xff0c;这里没选之后加也一样&#xff09;。 安装…

金融学-货币理论

前言 前面学习了什么是货币供给&#xff0c;货币供给的决定以及联邦储备体系在货币供给中所起的作用。现在我们要开始探讨经济中货币供给在决定价格水平与全部商品和劳务(总供给)中的作用。关于货币对经济影响的研究&#xff0c;称为货币理论(monetarythe-ory) 货币数量论 古典…

Visio绘图——给多边形增加连接线

每次在画项目框图和各类爪图的时候&#xff0c;连接线是最烦人的&#xff0c;虽然选择的是折线&#xff0c;单往往事与愿违。 下面就记录一下&#xff0c;如何查找各类连接线。 1、先展开左侧菜单栏&#xff0c;点击如下所示的“&#xff1e;”2、在展开的界面&#xff0c;再次…

【开题答辩全过程】以 付费自习室系统小程序为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

开疆智能Profinet转EtherCAT网关连接TR-Electronic传感器配置案例

本案例是通过开疆智能研发的Profinet转EtherCAT网关将传感器数据传送到PLC&#xff0c;由于两边设备采用协议不同&#xff0c;故而使用网关进行转换。网关配置&#xff1a;打开网关配置软件“EtherCAT Manager”并新建项目。根据不通网关型号也可选择ModbusTCP&#xff0c;Ethe…

VSCode中使用Markdown

文章目录1. 背景2. 安装插件3. 基础写作与预览4. 生成PDF文档5. 插入代码6. 插入图片7. 小结1. 背景 编程技术人员&#xff0c;很多人写作习惯用Markdown格式吧。 首先Markdown很简单&#xff0c;第二它的层次结构特别清晰&#xff0c;再然后它对嵌入图片、代码的支持很优秀。…

2024全栈技术栈选型指南

前后端技术栈选择现代前后端技术栈选择需兼顾市场需求与个人兴趣。前端领域React、Vue、Angular形成三足鼎立&#xff0c;React在大型项目占比达58%&#xff0c;Vue在小中型企业更受欢迎。TypeScript采用率年增长25%&#xff0c;已成为工程化标配。后端技术呈现多元化趋势&…

Spring Boot 项目文件上传安全与优化:OSS、MinIO、Nginx 分片上传实战

在实际的 Web 项目中&#xff0c;文件上传是一个常见需求&#xff1a;用户上传头像、企业后台上传资料、视频平台上传大文件等等。然而&#xff0c;文件上传也是最容易引发安全风险的功能之一&#xff0c;比如恶意脚本上传、木马文件伪装、存储空间消耗攻击。同时&#xff0c;当…

智能安防:以AI重塑安全新边界

传统安防依赖人力监控与简单报警&#xff0c;效率低下且易遗漏风险。随着人工智能、物联网及大数据技术的融合&#xff0c;智能安防正重新定义安全管理的范式&#xff0c;从被动响应转向主动预警&#xff0c;成为智慧城市与数字化生活的重要基石。智能安防的核心是人工智能视觉…

【AI】【强化学习】强化学习算法总结、资料汇总、个人理解

前言&#xff1a;自己学习西湖大学赵老师的课、youtube系列的课程相关比较重要的内容&#xff0c;后续不断再进行完善。 YouTube Serrano.academy rlhf讲的很好 合集最后一个没看 强化学习第四章 police没一步需要无穷&#xff0c;值迭代只需要一步 收敛不一样 值迭代:原因在于…

一键掌控三线资源:极简 Shell 脚本实现 CPU·磁盘·内存可视化巡检

目录 前言 数值型 for 循环 语法格式 示例&#xff1a;打印 1 到 5 示例&#xff1a;打印5次Hello World 示例&#xff1a;计算 1 到 100 的累加和 遍历型 for 循环 语法格式 示例&#xff1a;遍历字符串列表 示例&#xff1a;遍历数组 示例&#xff1a;遍历文件列表…

数据结构:创建堆(或者叫“堆化”,Heapify)

目录 最直观的思路 更优化的思路&#xff08;自底向上的构建&#xff09; 第一步&#xff1a;重新审视问题 第二步&#xff1a;找到规律&#xff0c;形成策略 用一个实例来推演 第三步&#xff1a;编写代码 总结与分析 我们来深入探讨“创建堆”&#xff08;或者叫“堆化…

基于 GPT-OSS 的成人自考口语评测 API 开发全记录

1️⃣ 需求与指标 在项目启动前&#xff0c;我们设定了核心指标&#xff1a; 字错率&#xff08;WER&#xff09;< 5%响应延迟 < 800 ms高可用、可扩展 这些指标将贯穿整个开发和测试流程。 2️⃣ 数据准备 准备训练数据是关键步骤&#xff0c;我们使用了 1k 条自考口…

Linux初始——基础指令篇

Linux常用指令pwdlscdtouchmkdirrmmancpmvcatmorelesswhichwhereisaliasgrepfilezip/unzip 指令rzsztarpwd 在xshell中输入pwd并回车&#xff0c;将输出当前用户所存在的目录位置 可看到当前用户是在/home/hhw这个目录下 ls 在xshell中输入ls会显示当前目录所包含的文件 其中…