目录
一、MQTT 协议简介
(一)协议基础
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种基于发布 / 订阅(publish/subscribe)模式的 “轻量级” 通讯协议,构建于 TCP/IP 协议之上,由 IBM 在 1999 年发布。它在物联网、小型设备、移动应用等诸多领域都有着较为广泛的应用。
在 MQTT 的体系架构里,主要包含三个重要部分:客户端、代理服务(Broker)和目标设备。客户端就好比是信息的 “收发员”,它既可以将消息发布到特定的主题上,比如一个温度传感器作为客户端,把采集到的温度数据发布到名为 “temperature” 的主题中;同时客户端也能订阅自己感兴趣的主题,去接收相应主题下的消息。代理服务则处于核心枢纽位置,负责接收客户端发布的消息,并精准地将这些消息转发给那些订阅了对应主题的客户端,例如多个显示终端订阅了 “temperature” 主题,代理服务就会把温度传感器发布的消息传递过去。而目标设备往往也是通过客户端角色来订阅主题,进而获取到所需的消息内容,实现信息的交互流通,以此构建起一套灵活且高效的通信机制。
(二)协议特点
MQTT 协议具备多方面显著的特点,使其在众多通信协议中脱颖而出。
首先是协议简单,它的设计简洁明了,没有过多复杂冗余的功能和规则,易于理解和实现。无论是专业的开发人员,还是刚接触相关领域的新手,都能够相对轻松地运用该协议进行开发工作。
开销小也是一大亮点,消息头部占用空间小,传输的数据量不大,尤其是在一些带宽资源有限的网络环境中,比如通过卫星链路通信的传感器网络,或者偶尔拨号的医疗设备所在的网络,MQTT 协议都能够凭借这一优势高效地传输信息,尽可能减少对带宽的占用,保证通信的顺畅进行。
可靠性高同样不容忽视,它支持三种不同的服务质量(Quality of Service, QoS)级别,分别是最多一次传递(QoS 0)、至少一次传递(QoS 1)和只有一次传递(QoS 2)。像在环境传感器数据传输场景中,若对数据丢失不太敏感,使用 QoS 0 级别即可;而对于一些计费系统等对消息准确性要求极高的情况,则可以采用 QoS 2 级别,严格确保消息仅传送到目的地一次,不会出现重复或丢失等影响结果准确性的问题,全方位满足不同应用场景对于消息传输可靠性的要求。
此外,MQTT 协议还具有很强的跨网络和物理设备通信的能力,它可以运行在不同的硬件平台以及操作系统之上,无论是常见的单片机、嵌入式设备,还是普通的计算机等,只要具备 TCP/IP 协议栈并实现了 MQTT 协议相关软件功能,就能参与到通信中来,并且能跨越有线网络、无线网络等不同类型的网络环境,实现设备之间的互联互通,为构建大规模的物联网应用提供了有力支撑。
二、单片机实现 MQTT 通信的准备
(一)硬件准备
在单片机实现 MQTT 通信的过程中,硬件的选择至关重要。例如 ATMEGA644PA 8 位单片机,它具备良好的性能和稳定性,能够满足许多基础应用场景下的数据处理需求。还有 ENC28J60,它是一款常用的网络接口芯片,可帮助单片机实现网络连接功能,从而为基于网络通信协议(如 MQTT)的数据传输搭建好硬件基础。像在一些小型的物联网项目里,将 ATMEGA644PA 单片机与 ENC28J60 结合使用,就能让传感器采集到的数据通过网络传输出去,进而实现远程的监测与控制等功能。
(二)软件准备
- 下载 MQTT C 语言包:
要实现单片机的 MQTT 通信,首先需要下载 MQTT C 语言包。大家可以通过 C/C++ MQTT Embedded clients 来获取,具体可访问https://www.eclipse.org/paho/clients/c/embedded/这个网址。除此之外,还有几种常见的下载途径。比如从 Eclipse Paho 官方网站(https://eclipse.dev/paho/)查找下载链接,不过官方网站可能更多是指向源代码仓库或提供构建指导;也可以直接从 GitHub 仓库下载 Paho MQTT C 库的源代码,操作方法是打开 Web 浏览器,访问 GitHub 网站(https://github.com/),在搜索栏中输入 “eclipse/paho.mqtt.c” 来查找 Paho MQTT C 库的官方仓库,进入仓库页面后,选择需要的版本,并点击对应的 “Code” 按钮,在弹出的菜单中,选择 “Download ZIP” 来下载该版本的源代码压缩包,或者选择 “Clone with HTTPS” 来获取仓库的 Git URL,以便使用 Git 命令克隆仓库;另外,如果使用的是支持包管理的集成开发环境(IDE)或构建系统,如 Keil MDK、IAR Embedded Workbench 或 CMake 等,还可以检查这些工具是否提供了对 Paho MQTT C 库的支持,通过工具直接搜索并安装该库,简化下载和集成的过程。但要注意在下载之前,需确保了解该库的版本兼容性、依赖关系和许可证条款等内容,特别是在嵌入式系统上使用时,要关注库的大小、内存占用和性能要求是否契合项目需求,在集成到项目中时,要按照库的文档和示例代码正确配置及使用其功能。
- 掌握 MQTT 基础知识:
对 MQTT 基础知识有清晰的了解也是必不可少的环节。大家可以通过一些专业的网站去学习相关内容,例如 MQTT 官方网站http://mqtt.org,上面有很全面的关于协议介绍等基础资料。还有像https://mcxiaoke.gitbooks.io/mqtt-cn/content/mqtt/01-Introduction.html这个网址,对 MQTT 的讲解也十分详细,有助于大家深入理解 MQTT 协议的方方面面,为后续在单片机上顺利实现 MQTT 通信筑牢知识根基。
三、单片机实现 MQTT 通信的步骤
(一)移植 MQTTPacket
要将 MQTTPacket 移植到项目里,首先需要进行相关文件的复制操作。把文件夹 MQTTPacket 复制到工程当中,然后再将 MQTTPacket\samples 里面的 transport.c、transport.h 也一并复制到工程里。这一步操作是后续实现单片机 MQTT 通信的基础,就像是搭建房子要先准备好合适的砖块一样,为整个通信功能的实现提供必要的代码素材。
(二)修改接口
在 transport.c 里存在四个重要的接口,分别是 transport_sendPacketBuffer (int sock, unsigned char* buf, int buflen)、transport_getdata (unsigned char* buf, int count)、transport_open (char* host, int port) 以及 transport_close (int sock)。从接口名称不难看出,这四个接口实现的是 TCP 数据的收发功能。
具体修改时,要依据已经实现的 TCP 接口来定。因为在单片机上经常使用的 TCP/IP 协议栈主要有 uip、LwIP 等,而且要知道 MQTT 是 tcp/ip 的应用层,传输层需要开发者自己去实现,这四个接口恰好分别对应 TCP 的连接、收、发和关闭操作,所以按照已有的 TCP 接口情况合理调整这四个接口,才能使其适配单片机的实际通信需求,保障数据能够准确无误地进行收发和连接控制。
(三)实现订阅 / 发布
以 pub0sub1.c 为例来说明相关参数的设置情况。
首先是连接参数部分,MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 这里的 data.clientID.cstring 就是客户 ID,它需要具有唯一性,比如设置为 “me2” 等符合规则的唯一标识;data.keepAliveInterval 代表保存存活时间,设置为 200s 的话,意味着每隔 200 秒会进行相应的保活操作;data.cleansession 的值决定了重新连接后是否清除之前的信息,当设置为 0 时表示不清除,设置为 1 则表示重连清除;如果服务器需要用户名密码进行验证,那么可以通过 data.username.cstring 和 data.password.cstring 来设置,例如都设置为 “admin”。
再来看 Qos 等级,它有三种不同的级别,0 表示最多一次传递,也就是消息发送出去后,接收者不会发送回应,发送者也不会重发消息,适用于对数据丢失不太敏感的场景,像一些简单环境数据的偶尔采集上报等情况;1 表示至少一次传递,意味着消息最少需要送达一次,但也有可能送达多次,在 QoS 1 的 PUBLISH 报文的可变报头中包含一个报文标识符,需要 PUBACK 报文确认,适合对数据有一定准确性要求,但偶尔重复接收也可接受的场景;2 表示只有一次传递,这是最高等级的服务质量,消息丢失和重复都是不可接受的,常用于对消息准确性要求极高的场合,比如计费系统等关键数据的传输。
通过合理配置这些参数,就能准确地实现消息的订阅和发布功能,确保单片机与服务器之间按照期望的规则进行通信交互。
(四)服务器实现
对于服务器实现这部分,我们通常采用 mosquitto 服务器。其实现方法如下:
首先要进行相应的安装配置等基础操作,mosquitto 是一款开源的 MQTT 消息代理(服务器)软件,能够实现 MQTT 协议版本 3.1 和 3.1.1,提供轻量级的、支持可发布 / 可订阅的消息推送模式,方便各类设备之间进行短消息通信。
在实际使用时,涉及到一些常用的指令。比如订阅指令 mosquitto_sub,格式为 mosquitto_sub -h xxx.xxx.xxx.xxx -u admin -P admin -t substopic,其中 - h 后面跟着的是服务器域名,-u 后面填写用户名(如果没有用户名要求可以省略),-P 后面填写密码(没有密码要求同样可以省略),-t 后面则是要订阅的 topic 名称;发布指令 mosquitto_pub,格式例如 mosquitto_pub -h xxx.xxx.xxx.xxx -u admin -P admin -t substopic -m hello,这里的 - m 后面跟着的就是要发布的具体内容。
通过运用这些指令,结合前面在单片机端的设置,基本就能实现单片机与服务器之间的联调通信,让整个 MQTT 通信链路顺畅运转起来。
四、单片机 MQTT 通信的应用场景
(一)物联网领域
在物联网领域,单片机 MQTT 通信有着极为广泛且重要的应用,特别是在智能家居、智能城市等场景中发挥着关键作用。
以智能家居为例,家中各类智能设备往往基于单片机进行控制和数据采集,像温湿度传感器、门窗传感器、智能灯具、智能插座等设备里的单片机,可通过 MQTT 通信协议与家庭网关或者云平台进行连接。比如,温湿度传感器的单片机采集到室内温湿度数据后,利用 MQTT 协议将数据发布到对应的 “home/temperature”“home/humidity” 等主题上,而智能空调、智能加湿器等设备的单片机则订阅这些主题,当接收到相关数据后,就能根据设定好的规则自动进行调节,像智能空调可依据温度数据来决定是否启动制冷或制热功能,以此实现家居环境的智能化调控。同时,用户也能通过手机端的智能家居 APP,借助 MQTT 协议向智能设备的单片机发布控制指令,如远程开关灯、调节窗帘开合程度等,实现对家居设备的远程控制与监测。
在智能城市方面,分布在城市各个角落的大量物联网设备,例如环境监测传感器、智能交通信号灯、智能路灯等,里面的单片机借助 MQTT 通信实现设备间的数据交互与协同工作。像环境监测传感器采集到的空气质量、噪音等数据,通过 MQTT 协议发布到相应主题,城市管理平台订阅这些主题后就能实时掌握环境状况,以便及时做出应对措施;智能交通信号灯中的单片机通过 MQTT 通信接收来自交通流量监测设备传来的数据,进而动态调整信号灯时长,优化交通流量,提升城市交通效率。总之,单片机 MQTT 通信保障了物联网场景下设备间高效、稳定的通信和控制,推动着物联网应用不断发展。
(二)科学研究
在科学研究过程中,实验数据的采集和传输是至关重要的环节,而单片机 MQTT 通信在其中扮演着解决关键问题的角色。
很多科研实验会涉及大量的数据产生,比如环境科学领域对野外生态环境长期监测实验,会有众多传感器采集温度、湿度、光照、土壤成分等各种数据;又或者在物理学的一些大型实验设备运行中,也会不断产生各类运行参数、检测数据等。这些数据量往往较大,并且在传输过程中,由于网络环境不稳定、带宽限制等因素,很容易出现丢包的情况。
而采用单片机结合 MQTT 通信,就能很好地应对这些问题。科研人员可以在传感器、数据采集终端等设备中嵌入带有 MQTT 通信功能的单片机,在数据采集后,通过 MQTT 协议进行传输。MQTT 协议支持不同的服务质量(QoS)级别,对于一些对数据准确性要求极高的实验数据传输场景,可以选择 QoS 2 级别,严格确保数据仅传送到目的地一次,不会出现重复或丢失等影响结果准确性的问题,保证了数据传输的稳定性和完整性。例如在一些天文观测项目中,望远镜采集到的遥远天体的观测数据通过单片机搭载的 MQTT 通信准确无误地传输回研究中心,为科研人员的分析研究提供可靠的数据支撑,助力科学研究顺利开展。
(三)金融行业
在金融行业,交易信息的实时监控和传输容不得丝毫差错,单片机 MQTT 通信在其中有着不可或缺的应用价值。
金融交易往往涉及海量的数据,像证券交易市场中,每一秒都有大量的股票买卖委托、成交等信息产生,并且这些交易信息量会随着市场活跃度不断变化,在传输过程中容易出现延迟等问题。而单片机结合 MQTT 通信,就能实现对交易信息快速且稳定的传输。
例如在银行的自助服务终端设备里,其内部的单片机可通过 MQTT 协议将客户的交易操作信息实时传输到银行的后台服务器,服务器端能及时进行数据处理、风险监控等操作,确保交易的安全性。再比如在金融机构的机房,对服务器、网络设备等运行状态数据的采集,通过嵌入了 MQTT 通信功能的单片机来实现传输,运维人员可以实时监控这些设备状态,及时发现潜在故障隐患,保障金融交易系统稳定运行。同时,MQTT 协议本身具备的可靠性以及可以跨越不同网络环境的能力,使得无论是在有线网络环境下的银行网点内部,还是通过无线网络连接的移动金融服务场景中,都能保证交易信息稳定、安全地传输,为金融行业的高效运转筑牢通信基础。
(四)医疗行业
在医疗行业,单片机 MQTT 通信对于患者生命体征采集和传输有着重要意义,关乎着医疗服务的质量和患者的健康安全。
医院病房中会配备众多医疗设备用于监测患者的各项生命体征,像心率监测仪、血压计、血氧仪等,这些设备内部的单片机可以借助 MQTT 协议将采集到的心率值、血压数据、血氧饱和度等生命体征数据传输到护士站的监控系统或者医院的医疗信息管理系统中。由于患者生命体征数据需要持续不断地采集和传输,数据量较大,而且医院内部网络环境复杂,存在信号干扰等情况,容易出现丢包问题。
而 MQTT 通信凭借其高可靠性,比如选择合适的 QoS 级别,能有效避免数据丢失,确保医护人员接收到的患者生命体征数据是完整、准确的。例如在重症监护病房(ICU),每一个患者身上连接的多种监测设备的单片机,通过 MQTT 通信实时将患者的关键生命数据发送到统一的监控平台,医护人员能随时掌握患者病情变化,一旦出现异常数据,能第一时间做出响应,采取相应的救治措施,保障患者生命安全,也为医疗决策提供了可靠的数据依据,极大地提升了医疗服务的效率和质量。
(五)能源行业
在能源行业,单片机 MQTT 通信在对能源设备监控和控制方面有着突出的优势,有力地支撑着能源行业的稳定运行和管理。
能源领域涵盖了诸如发电厂、变电站、风力发电场、太阳能电站等众多场景,存在着大量的能源设备,像发电机组、变压器、风机、光伏板等,这些设备分布广泛且所处的网络环境复杂多变。以风力发电场为例,分布在广阔区域内的众多风机,需要实时监控其运行状态,包括转速、叶片角度、发电功率等参数,风机内部的单片机利用 MQTT 通信协议,将这些数据发布到对应的主题上,运维管理中心订阅主题后就能实时掌握每一台风机的情况,当发现某个风机的数据出现异常时,可及时安排检修等维护工作,保障发电效率和设备安全。
同时,通过 MQTT 通信,还能实现对能源设备的远程控制。比如在智能电网中,变电站里的单片机可以接收来自调度中心通过 MQTT 协议发送的控制指令,对变压器的电压调节、开关刀闸等操作进行控制,优化电网的电能分配。而且 MQTT 协议的轻量级特点,使其能够很好地适应能源设备中单片机资源有限以及复杂网络环境的现状,确保能源设备之间稳定、高效的通信,助力能源行业智能化管理水平不断提升。
(六)物流行业
在物流行业,单片机 MQTT 通信对于货物实时监控和追踪起着关键作用,保障了物流运输过程的高效与透明。
随着物流行业的快速发展,货物运输规模日益庞大,货物的位置信息、状态信息等需要实时掌握。在运输车辆、物流仓库、智能快递柜等环节中,都有单片机结合 MQTT 通信的应用场景。例如在运输车辆上安装有定位设备、温湿度传感器等,这些设备里的单片机通过 MQTT 协议将车辆的实时位置、车厢内货物的温湿度情况等数据发布到相应主题,物流公司的监控平台订阅主题后,就能实时追踪货物位置,并且当温湿度超出适宜范围时及时采取措施,确保货物品质不受影响。
在智能快递柜方面,其内部的单片机利用 MQTT 通信可以将快递的存入、取出等状态信息传输给物流管理系统,方便快递员和用户实时了解快递状态。而且 MQTT 协议开销小、可靠性高的特点,保证了在复杂多变的物流网络环境下,货物的相关信息能够准确、实时地传输,为物流企业优化运输路线、提高配送效率、提升客户服务体验等提供了有力的通信保障。
五、单片机 MQTT 通信的优势
(一)低协议开销
MQTT 在协议开销方面有着独特的优势。它的每消息标题可以短至 2 个字节,而与之对比的 HTTP,为每个新请求消息重新建立 HTTP 连接会导致重大的开销。例如在一些需要频繁传输数据的物联网场景中,如果使用 HTTP 协议,每次传输都要经历繁琐的连接建立过程,产生大量额外的网络交互,增加了网络负担。但 MQTT 和 MQ 所使用的永久连接显著减少了这一开销,使得数据传输更加高效,尤其适用于那些对网络带宽要求较高、传输频率较频繁且希望尽量减少不必要开销的应用场景,像大量传感器节点向服务器传输环境监测数据等情况,MQTT 的低协议开销特点就能很好地发挥作用,让有限的带宽资源可以承载更多有效的数据传输。
(二)对不稳定网络的容忍
在应对不稳定网络方面,MQTT 表现出色。MQTT 和 MQ 能够从断开等故障中恢复,而且不需要额外编写进一步的代码来处理这类问题。然而,HTTP 却无法原生地实现此目的,一旦网络出现故障断开连接,往往需要客户端重试编码,而这个过程可能还会增加幂等性问题,使得数据传输的稳定性和准确性受到影响。比如在一些移动设备处于信号不佳环境下进行数据传输,或者是在偏远地区通过无线网络连接的物联网设备传输数据时,网络波动、临时中断是比较常见的情况,此时 MQTT 就能凭借自身对不稳定网络的良好容忍性,保障数据可以在网络恢复后继续正常传输,减少因网络问题导致的数据丢失或传输错误等情况发生。
(三)低功耗
MQTT 是专门针对低功耗目标而设计的,这是它的一大亮点。在很多物联网应用场景中,设备往往依靠电池供电,对功耗的要求比较严格。而 HTTP 的设计没有考虑低功耗这一因素,在使用过程中会相对增加功耗。例如那些部署在野外、不方便频繁更换电池的环境监测传感器设备,采用 MQTT 协议进行通信,就可以在满足数据传输需求的同时,最大程度地节省电量,延长设备的续航时间,确保设备能长时间稳定地运行,持续采集并传输数据,减少因电量耗尽导致的设备离线、数据中断等问题。
(四)数百万个连接的客户端
当涉及到处理大量并发连接的客户端时,MQTT 有着明显优势。在 HTTP 堆栈上,要维护数百万个并发连接,需要做大量的工作来提供支持,虽然理论上这种支持是可行的,但大多数商业产品都为处理这一数量级的永久连接进行了优化。比如 IBM 提供的 IBM MessageSight,这是一个单机架装载服务器,经过测试能处理多达 100 万个通过 MQTT 并发连接的设备。相反,MQ 并不是为大量并发客户端而设计的。像一些大型的物联网平台,需要接入海量的终端设备,如智能家居系统中众多的智能家电设备、智能城市里分布在各处的各类物联网感知设备等,MQTT 就能轻松应对这种大规模的客户端并发连接需求,保障系统稳定高效地运行,让各个设备之间可以顺畅地进行数据交互与通信。
(五)推送通知
推送通知对于及时向客户传递信息非常关键,而 MQTT 在这方面具备优势。企业有时候需要在没有第三方中介的情况下发送敏感的信息,从电池、系统负载和带宽角度讲,推送是最佳解决方案。HTTP 只允许使用一种称为 COMET 的方法,使用持久的 HTTP 请求来执行推送,从客户端和服务器的角度讲,此方法都很昂贵。但 MQ 和 MQTT 都支持推送,这是它们的一个基本特性。例如在一些即时通讯应用或者实时监控系统中,需要及时将新消息、告警信息等推送给客户端,MQTT 的推送机制就能快速且高效地完成这个任务,确保用户可以第一时间接收到重要通知,相较于 HTTP 的推送方式,更节省资源且及时性更强。
(六)客户端平台差异
HTTP 和 MQTT 客户端都已在大量平台上实现,不过 MQTT 的简单性有助于以极少的精力在额外的客户端上实现 MQTT。也就是说,在不同的操作系统、硬件平台等环境下,开发人员可以相对轻松地将 MQTT 协议集成到相应的客户端中,使其能够快速具备 MQTT 通信功能。比如在嵌入式设备、移动端设备、桌面端设备等多种类型的平台上,MQTT 都能比较便捷地进行部署和应用,降低了开发的难度和成本,提高了协议的通用性和适用性,让更多不同平台的设备可以利用 MQTT 进行高效通信。
(七)防火墙容错
在实际应用中,一些企业防火墙会将出站连接限制到一些已定义的端口,通常这些端口被限制为 HTTP(80 端口)、HTTPS(443 端口)等,HTTP 显然可以在这些情况下运行。而 MQTT 可封装在一个 WebSockets 连接中,显示为一个 HTTP 升级请求,从而允许在这些有端口限制的情况下运行,MQ 则不允许采用这种模式。