单片机与MQTT协议

MQTT 协议简述

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布 / 订阅(publish/subscribe)模式的 “轻量级” 通讯协议,该协议构建于 TCP/IP 协议上,由 IBM 在 1999 年发布。

它有着诸多显著特点,首先是轻量级,协议设计简洁,消息头部较小,传输的数据量不大,很适合在带宽有限的网络环境中进行传输,这使得它在资源受限的设备上也能很好地应用,比如嵌入式设备、小型化设备等。

可靠性方面,MQTT 协议支持三种不同的服务质量(Quality of Service, QoS)级别,分别是 “至多一次”“至少一次”“只有一次”。“至多一次” 时,消息发布完全依赖底层 TCP/IP 网络,会发生消息丢失或重复的情况,适用于像环境传感器数据这类丢失一次读记录无所谓的场景;“至少一次” 则确保消息能到达,但消息重复可能会发生;“只有一次” 可保证消息只被传递一次,常用于像计费系统这种对消息准确性要求严格的情况。

灵活性上,它支持多种客户端和服务器实现,能在不同的硬件平台以及操作系统上运行,并且还可以与其他协议(如 HTTP、TCP/IP 等)进行集成,方便在各种复杂的系统环境中部署使用。

在安全性方面,MQTT 协议支持基于 TLS/SSL 的加密通信,以此保护消息的安全性和隐私性,避免消息在传输过程中被窃取或篡改。

还有异步通信这一特点,它使用发布 / 订阅模式,允许消息进行异步传递,将发送者和接收者之间进行解耦,提高了系统的可伸缩性和灵活性,客户端可以通过订阅主题来接收实时的消息,从而支持实时事件驱动的应用场景。

此外,它还具备消息持久化的机制,就算遇到网络不稳定等情况,也能确保消息可靠地传递给接收者,并且还能对设备的在线 / 离线状态进行监测,实时感知设备的连接状态变化。

从整体架构来看,MQTT 协议中有几个关键的组成部分。发布者(Publisher)负责将消息发布到主题上,发布者一次只能向一个主题发送数据,且发布消息时无需关心订阅者是否在线;订阅者(Subscriber)通过订阅主题来接收消息,并且可一次订阅多个主题;代理(Broker)扮演着极为重要的角色,负责接收发布者的消息,并将消息转发至符合条件的订阅者,同时也要处理客户端发起的连接、断开连接、订阅、取消订阅等请求;主题(Topic)则是 MQTT 进行消息路由的基础,它类似 URL 路径,使用斜杠 / 进行分层,一个主题可以有多个订阅者,代理会将该主题下的消息转发给所有订阅者,一个主题也可以有多个发布者,代理将按照消息到达的顺序转发,而且 MQTT 还支持订阅者使用主题通配符一次订阅多个主题。

在应用场景方面,MQTT 协议在物联网领域应用极为广泛,像智能家居中各种智能设备(如智能灯光、智能家电、智能安防等)之间的通信和控制,智能交通系统里各个设备(如智能导航、智能停车、智能交通灯等)之间的通信和协作,还有智能制造中各类设备之间的通信和控制,以及物流和供应链、能源管理、智慧城市建设等众多场景下,MQTT 协议都发挥着重要作用,帮助实现设备间高效、稳定的消息传递与通信。 总之,MQTT 协议以其独特的优势,成为了物联网等相关领域中一种非常重要的消息传输协议。

单片机应用 MQTT 协议的准备工作

选择合适的 MQTT 库

在将单片机应用于 MQTT 协议时,选择一个合适的 MQTT 库至关重要,它能极大地影响开发的效率以及应用的性能。以下是一些不同单片机平台和开发环境下常用的 MQTT 库及其特点、适用场景介绍。

对于 Arduino 平台来说,PubSubClient 是一个备受青睐的选择。它具有良好的兼容性,能够轻松地在各种 Arduino 兼容设备(像 Arduino Uno、Arduino Mega、ESP8266 等)上实现 MQTT 功能。其优势在于使用较为简单,开发者可以通过简洁的 API 接口来完成连接、发布消息以及订阅主题等操作,方便初学者快速上手,适用于各类简单的物联网项目,比如在智能家居场景中控制智能灯泡、温湿度传感器等设备,或者实现一些基础的远程监控功能。

Adafruit MQTT 库也是为 Arduino 平台设计的优秀库之一。这个开源项目旨在为 Arduino 平台提供 MQTT 协议支持,它不仅简化了设备间的通信,还能与 Adafruit IO 实现无缝集成。其核心优势体现在广泛的硬件兼容性上,支持包括 Adafruit FONA、Arduino Yun、ESP8266 等在内的多种 Arduino 兼容设备。而且,它依赖于 Adafruit SleepyDog 等库,能够提供额外的功能,像看门狗定时器增强了系统的可靠性,适用于从家庭自动化到工业监控等多个领域,例如可以用于控制家中的智能灯光系统,也能在工业环境中监控机器的运行状态等。

如果是针对嵌入式系统,wolfMQTT 客户端库则是不错的选择。它是由 wolfSSL 团队开发的轻量级、高效的 MQTT 客户端实现,支持 MQTT v3.1.1 和 v5.0 规范,以及 MQTT-SN(传感器网络)规范。其特点非常突出,小巧的空间占用(大约 3.6kB)很适合资源有限的嵌入式物联网设备;可利用 wolfSSL 库进行安全连接,保障数据传输的安全性;有着良好的便携性,支持多种平台,易于在新平台上编译;并且 API 简单,使用 C89 编写,接口简洁明了,外部依赖也少,约 1200 行源代码。常用于 IoT 设备数据上报,像传感器定期向云端服务器报告状态或事件;也适用于监控系统实时通信以及智能家居、工业自动化等场景中的通信需求,比如在监控或报警系统中实现传感器数据的实时传输,或者作为客户端在智能家居、工业自动化场景里与控制器进行通信等。

另外,还有专门为传感器网络设计的 MQTT-SN 协议,其目标是为非 TCP/IP 协议栈的嵌入式设备(如 Zigbee、Bluetooth 等)提供应用层通信标准。例如在大规模分布式物联网中,EMQX 除了完整支持 MQTT 协议外,还可通过网关处理所有非 MQTT 协议的连接、认证和消息收发,并为其提供统一的用户层接口,方便在如智慧城市、智能家具、水电气表等具有短距离、带宽受限、低功耗等特点的应用场景中使用。

总之,在选择 MQTT 库时,需要综合考虑单片机的硬件资源、项目的具体应用场景以及对通信可靠性、安全性等方面的要求,这样才能挑选出最契合的库来助力项目开发。

配置相关参数

当在单片机代码中应用 MQTT 协议时,正确配置相关参数是实现与 MQTT 服务器顺利连接并通信的基础工作。以下是一些关键参数的设置讲解。

首先是服务器地址,这是明确要连接的 MQTT 服务器所在的网络位置,例如在测试时常用的 “tcp://test.mosquitto.org” 这样的公共测试服务器地址,如果是企业内部或者特定项目使用的私有服务器,就需要填入对应的 IP 地址或者域名,像在一些企业搭建的物联网平台中,服务器地址可能是 “mqtt.example.com” 等形式,务必确保地址准确无误,否则无法建立连接。

端口号也是必不可少的配置项,MQTT 协议默认使用的端口号一般是 1883,不过在有些应用场景下,如果采用了加密传输(基于 TLS/SSL),那可能会使用 8883 端口等其他指定端口,开发时需要根据服务器的实际设置来进行相应配置。

认证凭据方面,常见的有用户名和密码。很多 MQTT 服务器为了保证安全性,会要求客户端提供合法的用户名和密码进行身份验证,例如在连接阿里云的 MQTT 服务器时,需要在阿里云物联网平台创建设备后获取对应的设备认证信息,填入相应的用户名和密码字段,才能成功连接服务器进行后续通信。另外,对于一些支持 TLS/SSL 加密通信的情况,还需要配置相关的证书文件路径等参数,以此确保数据在传输过程中的安全性,避免消息被窃取或篡改,尤其是在涉及到敏感数据传输的物联网项目中,如远程医疗中医疗设备传输患者生理数据等场景,加密配置就显得格外重要。

除此之外,还有像客户端 ID,它用于在服务器端标识每个连接的客户端,需要保证其唯一性,一般可以根据项目实际情况自行设定一个具有辨识度的字符串作为客户端 ID。同时,根据具体的 MQTT 库以及应用需求,可能还需要配置如心跳时间间隔、会话保持相关的参数等,心跳时间间隔可以让服务器知晓客户端是否还处于在线状态,合理设置能避免因网络临时波动等原因误判客户端离线,而会话保持参数则关乎到客户端离线后重新上线时能否继续之前的通信状态等情况。

总之,这些参数的准确配置是单片机能够顺利运用 MQTT 协议与服务器进行通信的关键所在,需要开发者仔细核对并按照实际情况进行合理设置。

单片机与 MQTT 协议的通信流程

连接服务器

在单片机与 MQTT 协议的通信中,连接服务器是首要步骤。以常用的一些 MQTT 库为例,来看看具体是如何操作的。

比如在 Arduino 平台中使用 PubSubClient 库时,首先要引入该库到你的项目中。然后在代码里,需要利用库提供的函数来配置服务器相关信息,像服务器地址、端口号、客户端 ID 等参数。示例代码如下:

 
#include <PubSubClient.h>

// 假设你的MQTT服务器地址,这里以测试服务器为例,实际应用中替换成真实地址

const char* mqtt_server = "tcp://test.mosquitto.org";

// 客户端ID,需保证唯一性,可自行按规则设定

const char* clientId = "myUniqueClientId";

WiFiClient espClient;

PubSubClient client(espClient);

void setup() {

// 初始化串口等其他必要的设置(此处省略部分常规初始化代码)

// 设置MQTT服务器相关信息

client.setServer(mqtt_server, 1883);

client.setClientId(clientId);

// 尝试连接服务器

if (client.connect()) {

Serial.println("Connected to MQTT server");

} else {

Serial.println("Connection failed");

}

}

void loop() {

// 后续的循环里可以进行如保持连接、消息处理等操作,这里暂不展开

client.loop();

}

上述代码先是定义了服务器地址和客户端 ID,接着通过setServer和setClientId函数配置好参数,最后使用connect函数尝试与服务器建立连接。

如果是在嵌入式系统中采用 wolfMQTT 客户端库,代码层面的实现稍有不同。以下是一个简单示意(省略部分头文件包含等基础操作):

 
#include "wolfmqtt/mqtt_client.h"

// 定义服务器地址、端口等参数

#define SERVER_ADDRESS "tcp://yourserver.com"

#define SERVER_PORT 1883

#define CLIENT_ID "myEmbeddedClient"

int main() {

// 初始化MQTT客户端结构体

MqttClient client;

// 配置客户端相关参数,比如设置服务器地址、端口、客户端ID等

MqttClient_Init(&client, SERVER_ADDRESS, SERVER_PORT, CLIENT_ID);

// 尝试连接服务器

int result = MqttClient_Connect(&client);

if (result == 0) {

printf("Connected to MQTT server successfully.\n");

} else {

printf("Connection failed with error code: %d\n", result);

}

// 后续可进行如订阅、发布消息等操作

return 0;

}

这里通过MqttClient_Init函数初始化客户端并配置参数,再调用MqttClient_Connect函数来建立与服务器的连接。

总之,不同的库虽然函数名称和使用方式略有差异,但基本思路都是先配置好服务器相关的关键参数,然后调用对应的连接函数来建立单片机与 MQTT 服务器的连接,为后续的订阅、发布消息等操作打好基础。

订阅与发布主题

在 MQTT 协议里,主题(Topic)是消息发布和订阅的关键概念。它类似于一种消息的分类标签,用于标识消息的类别和内容,其结构设计是分层次的,各层级之间用斜杠(/)分隔,例如 “home/livingroom/temperature” 就可以表示家中客厅的温度数据这样的消息类别。

在单片机代码中进行主题的订阅与发布操作时,不同的 MQTT 库同样有着对应的函数来实现相应功能。

仍以 Arduino 平台常用的 PubSubClient 库为例,订阅主题可以使用subscribe函数。比如要订阅一个名为 “sensorData” 的主题,代码如下:

 
#include <PubSubClient.h>

// 服务器地址等相关参数定义(同前面连接服务器示例部分,此处省略重复代码)

void setup() {

// 初始化及连接服务器相关操作(省略部分代码)

if (client.connect()) {

Serial.println("Connected to MQTT server");

// 订阅主题,QoS级别这里设置为0(至多一次传递,可按需调整)

if (client.subscribe("sensorData", 0)) {

Serial.println("Subscribed to topic: sensorData");

} else {

Serial.println("Subscribe failed");

}

}

}

当有其他客户端向 “sensorData” 主题发布消息时,单片机就能接收到了。

而发布消息到主题,则可以使用publish函数。假设要发布一个温度传感器采集到的温度值 “25” 到 “sensorData” 主题,代码可以这样写:

 
#include <PubSubClient.h>

// 相关参数定义及初始化、连接服务器操作(省略)

void loop() {

client.loop();

// 假设这里获取到的温度值为25,实际应用中需从传感器获取真实数据

int temperature = 25;

char msg[10];

sprintf(msg, "%d", temperature);

// 发布消息到主题,同样QoS级别可按需调整

if (client.publish("sensorData", msg)) {

Serial.println("Message published");

} else {

Serial.println("Publish failed");

}

delay(1000); // 可根据实际情况设置发布消息的时间间隔

}

在其他库中,例如使用 Python 的paho-mqtt库(适用于一些能运行 Python 的单片机环境或者用于测试与单片机通信的上位机代码等情况),订阅主题和发布消息的示例如下:

 
import paho.mqtt.client as mqtt

# 当连接成功时调用的回调函数

def on_connect(client, userdata, flags, rc):

print("Connected with result code " + str(rc))

client.subscribe("testTopic") # 订阅主题

# 当接收到消息时调用的回调函数

def on_message(client, userdata, msg):

print(f"Message received: {msg.payload.decode()}")

client = mqtt.Client()

client.on_connect = on_connect

client.on_message = on_message

# 连接到MQTT服务器,替换成真实的服务器地址和端口

client.connect("broker.hivemq.com", 1883, 60)

# 发布消息示例

client.publish("testTopic", "Hello from Python client")

client.loop_forever()

通过上述不同语言、不同库针对主题订阅与发布的操作示例可以看出,开发者需要依据具体的应用场景、所选用的库,合理地调用相应函数来完成主题相关操作,以此实现单片机与其他设备之间基于 MQTT 协议的消息交互。

消息处理机制

当有新消息到达单片机所连接的 MQTT 服务器,并匹配到已订阅的主题时,MQTT 库会调用预先定义的回调函数来处理消息。

以常用的一些库为例,像在 Arduino 平台结合 PubSubClient 库时,一般会这样定义和使用回调函数来处理消息:

 
#include <PubSubClient.h>

// 服务器等相关参数定义(省略重复代码)

// 回调函数,用于处理接收到的消息

void callback(char* topic, byte* payload, unsigned int length) {

Serial.print("Message arrived [");

Serial.print(topic);

Serial.print("] ");

for (int i = 0; i < length; i++) {

Serial.print((char)payload[i]);

}

Serial.println();

// 在这里可以根据消息内容执行相应操作,比如解析消息判断是什么类型的数据(温度、湿度等)

if (strcmp(topic, "temperatureData") == 0) {

// 假设消息内容是温度数值的字符串形式,将其解析并进行后续处理,此处简单示例

char tempStr[length + 1];

strncpy(tempStr, (char*)payload, length);

tempStr[length] = '\0';

int temperature = atoi(tempStr);

Serial.print("Received temperature: ");

Serial.println(temperature);

// 可以根据温度值做进一步的操作,比如控制相关设备等(此处省略具体控制代码)

}

}

void setup() {

// 初始化及连接服务器等操作(省略部分代码)

client.setCallback(callback); // 设置回调函数

}

void loop() {

client.loop(); // 持续监听消息,触发回调函数处理

}

在上述代码中,定义了callback函数作为消息到达的回调处理函数,当有匹配订阅主题的消息到来时,会传入消息的主题、内容以及内容长度等参数。在函数内部,先是将消息内容打印出来方便查看,然后针对特定主题(如 “temperatureData”)的消息进行解析,把接收到的温度数值字符串转换为整型数值,后续就可以根据这个温度值来执行诸如控制其他设备等相应的操作了。

在 Python 的paho-mqtt库中,消息处理的回调函数定义如下:


import paho.mqtt.client as mqtt

# 当接收到消息时调用的回调函数

def on_message(client, userdata, msg):

print(f"Message received: {msg.payload.decode()}")

# 同样可以在这里进行消息解析及对应操作

if msg.topic == "sensor_status":

status = msg.payload.decode()

if status == "on":

print("The sensor is turned on.")

# 可以添加更多针对传感器开启状态的操作代码

elif status == "off":

print("The sensor is turned off.")

# 对应传感器关闭状态的操作代码(省略)

client = mqtt.Client()

client.on_connect = on_connect

client.on_message = on_message

# 连接等其他操作(省略)

client.loop_forever()

这里的on_message回调函数会在接收到消息时被触发,先是打印出消息内容,然后针对特定主题(如 “sensor_status”)的消息进行判断解析,根据消息里表示的传感器状态来执行相应的逻辑操作。

总的来说,消息处理机制就是依靠预先定义好的回调函数,在有新消息到达时自动触发,开发者在回调函数里完成解析消息、根据消息内容判断类型以及执行相应操作等流程,从而实现单片机基于 MQTT 协议对不同消息做出合理的响应和处理,达到与其他设备间有效的信息交互目的。

单片机结合 MQTT 协议的应用场景实例

常见物联网平台应用

在当今的物联网领域中,有不少常见且功能强大的物联网平台,例如腾讯云、阿里云、百度云等,它们与单片机结合 MQTT 协议后,能够实现诸多实用的功能。

以阿里云物联网平台为例,当单片机借助 MQTT 协议与之通信时,一方面,阿里云物联网平台可以对单片机数字量输出、保持寄存器进行设置操作。这意味着我们可以远程控制单片机连接的各类设备,比如在智能家居场景中,对连接到单片机上的智能灯光进行开关、亮度调节等设置,或者控制智能插座的通断电情况;在工业环境里,可以远程操控与单片机相连的电机启动、停止以及转速调节等。另一方面,单片机能够实时上报数字量输入、数字量输出、输入寄存器和保持寄存器的状态。像环境监测场景中,单片机连接的温湿度传感器、空气质量传感器等采集到的数据,可通过 MQTT 协议实时传递给阿里云平台,方便用户随时了解环境状况。

腾讯云物联网平台同样有着出色的表现。通过 MQTT 协议连接后,腾讯云平台也能实现对单片机相关参数的设置操作,并且支持单片机实时反馈如设备运行状态、传感器采集的数据等各类状态信息。例如在智能农业项目中,单片机连接的土壤湿度传感器、光照传感器等获取的数据可以上报给腾讯云平台,而平台端也能对单片机控制的灌溉设备、遮阳设备等进行远程操作,实现智能化的农业生产管理。

百度云物联网平台也是如此,借助 MQTT 协议与单片机通信,既可以让平台对单片机进行相应控制操作,又能接收单片机实时上报的各类状态数据,应用在如智能交通、智能安防等多个领域,方便实现设备间的协同工作以及远程监控与管理等功能。

总之,这些常见的物联网平台与单片机及 MQTT 协议配合,为物联网应用的开发和实施提供了强大且便捷的基础,助力实现各种智能化的业务场景。

特定功能实现案例

在单片机中,我们可以使用开源的 EMQX 客户端库来实现如保留消息和遗嘱消息功能,以下为具体的实现过程介绍。

首先,需要在 EMQX 服务器上创建一个 MQTT 客户端,并获取其账号密码、主题等信息。这一步是后续操作的基础,就好比我们要进入一个特定场所,需要先拿到对应的 “门票”(账号密码)以及明确要去的 “区域”(主题)一样。在 EMQX 服务器的相关管理界面或者配置文件中,按照要求填写好客户端的各项信息,创建并记录下生成的账号密码以及确定好要使用的主题名称等内容。

接下来,在单片机上进行相应代码的编写,实现 MQTT 客户端的初始化、连接和订阅等操作。以下是一个使用 ESP32 开发板和 EMQX 客户端库实现相关功能的示例代码解读:

 
#include <WiFi.h>

#include <PubSubClient.h>

// WiFi网络设置

const char* ssid = "your_SSID";

const char* password = "your_PASSWORD";

// MQTT服务器设置

const char* mqtt_server = "your_MQTT_SERVER";

const int mqtt_port = 1883;

const char* mqtt_username = "your_MQTT_USERNAME";

const char* mqtt_password = "your_MQTT_PASSWORD";

// 这里首先定义了WiFi网络的名称(SSID)和密码,以及MQTT服务器的地址、端口号、用户名和密码等关键信息

void setup() {

// 初始化串口等其他必要的设置(此处省略部分常规初始化代码)

// 连接WiFi网络

WiFi.begin(ssid, password);

while (WiFi.status()!= WL_CONNECTED) {

delay(1000);

Serial.println("Connecting to WiFi...");

}

Serial.println("Connected to WiFi");

// 创建MQTT客户端实例,并设置服务器相关信息

PubSubClient client(WiFiClient());

client.setServer(mqtt_server, mqtt_port);

client.setCallback(callback);

// 尝试连接MQTT服务器

while (!client.connect("ESP32Client", mqtt_username, mqtt_password)) {

Serial.println("Failed to connect to MQTT server. Retrying...");

delay(5000);

}

Serial.println("Connected to MQTT server");

// 订阅主题,这里假设要订阅的主题名为 "testTopic"

if (client.subscribe("testTopic")) {

Serial.println("Subscribed to topic: testTopic");

} else {

Serial.println("Subscribe failed");

}

}

// 这部分是setup函数,先是进行了WiFi网络的连接,确保单片机能够正常联网。然后创建了MQTT客户端实例,配置好服务器信息后尝试连接服务器,连接成功后再订阅相应的主题。

void loop() {

if (client.connected()) {

client.loop();

} else {

reconnect();

}

}

// loop函数里,先判断客户端是否处于连接状态,如果连接着就持续监听消息(通过client.loop()),若断开连接则调用reconnect函数尝试重新连接。

// 回调函数,用于处理接收到的消息

void callback(char* topic, byte* payload, unsigned int length) {

Serial.print("Message arrived [");

Serial.print(topic);

Serial.print("] ");

for (int i = 0; i < length; i++) {

Serial.print((char)payload[i]);

}

Serial.println();

// 在这里可以根据消息内容执行相应操作,比如解析消息判断是什么类型的数据(温度、湿度等)

}

在上述代码中,setup函数完成了初始化、连接 WiFi、创建并配置 MQTT 客户端以及订阅主题等基础且关键的操作,loop函数保障了客户端在连接状态下能持续处理消息以及在断开连接时尝试重新连接,而callback函数则负责对接收到的消息进行相应处理,比如可以根据具体消息内容进行进一步的业务逻辑操作,像判断是控制指令还是传感器数据等,并执行对应的动作,如控制相关设备状态改变或者记录传感器数值等。

通过这样一套流程,就能够在单片机中利用 EMQX 客户端库实现如保留消息和遗嘱消息等特定功能,开发者可以根据实际项目需求在此基础上进行拓展和优化,以满足多样化的物联网应用场景要求。

单片机与 MQTT 协议结合的优势总结

在物联网应用中,单片机与 MQTT 协议的结合展现出了诸多显著优势。

其一,MQTT 协议是轻量级的,协议设计简洁,消息头部较小,传输数据量不大,很适合在带宽有限的网络环境中传输,这恰好与单片机常应用于资源受限设备的特点相契合。比如在一些偏远地区的环境监测项目里,使用单片机连接各类传感器(像温湿度传感器、空气质量传感器等),借助 MQTT 协议就能轻松地将采集到的数据通过低带宽网络回传至服务器端,实现对环境状况的远程监控。

其二,MQTT 协议能适应不稳定网络环境。在实际应用场景中,网络波动是常见情况,像在移动的车载物联网设备或者一些信号覆盖不佳的工业场所中,单片机结合 MQTT 协议,凭借其消息持久化机制以及对不同服务质量(QoS)级别的支持,就算遇到网络临时中断、信号弱等不稳定因素,也能确保消息可靠地传递给接收者,最大程度减少数据丢失的风险,保障物联网设备间通信的连贯性。

再者,它可以跨越各种网络和物理设备进行通信。无论是基于 TCP/IP 网络的有线连接,还是像 Zigbee、Bluetooth 等短距离无线通信的嵌入式设备所构建的网络环境,MQTT 协议都能作为统一的消息传输桥梁,让不同网络协议、不同类型的单片机设备(如 Arduino、STM32 等不同平台的单片机)之间实现互联互通。例如在智能家居场景中,通过单片机控制的智能灯光、智能家电、智能安防设备等可能采用多种不同的通信方式和网络协议,但利用 MQTT 协议就能打破这些差异,实现各设备间高效、稳定的通信与协同工作。

最后,从成本角度来看,这种结合为物联网设备间通信提供了便捷高效且低成本的解决方案。一方面,很多 MQTT 库是开源免费的,降低了开发过程中的软件成本;另一方面,单片机本身成本相对较低,二者结合能在满足物联网应用基本通信需求的同时,有效控制项目整体成本投入,尤其适合大规模、分布式的物联网项目部署,像智慧城市建设中众多设备间的通信组网等场景,都能凭借这一优势发挥重要作用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣矩阵-算法模版总结

lc-73.矩阵置零-(时隔14天)-12.27 思路&#xff1a;(23min22s) 1.直接遍历遇0将行列设0肯定不行&#xff0c;会影响后续判断&#xff0c;题目又要求原地算法&#xff0c;那么进一步考虑是否可以将元素为0&#xff0c;其行列需要设为0的位置给存储下来&#xff0c;最后再遍历根据…

C++的第一个程序

前言 在学习c之前&#xff0c;你一定还记得c语言的第一个程序 当时刚刚开始进行语言学习 因此告诉到&#xff0c;仅仅需要记住就可以 #include <stdio.h>int main(){printf("Hello World");return 0; }而对于c中的第一个程序&#xff0c;似乎有所变化 C的…

使用jvisualvm远程连接Linux服务器上java进程

使用jvisualvm连接远程服务器有两种方式&#xff1a;JMX和jstatd&#xff0c;两种方式都不能完美支持所有功能&#xff0c;例如JMX不支持VisualGC&#xff0c;jstatd不支持CPU监控&#xff0c;实际使用可同时配置上并按需选用。 一、jstatd连接 1、在Linux中配置远程授权 要监…

麒麟操作系统服务架构保姆级教程(六)部署PHP环境

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 本来小屁打算直接写LNMP架构的&#xff08;LB负载均衡NginxmysqlPHP&#xff09;&#xff0c;但是发现之前用过的包是红帽的吗&#xff0c;在麒麟上没法直接部署PHP&#xff0c;所以小屁用两天的时间…

SpringCloudAlibaba升级手册-nacos问题记录

目录 一、前言 二、升级过程 1.问题 2.原因 3.出处 4.理论解决 5.测试环境问题 6.Spring Cloud Alibaba版本对比 7. Spring Cloud Alibaba适配组件版本对比 8.降低Spring Cloud版本 9.SpringCloud与SpringBoot兼容对比表 10.naocs-client版本对比 三、最终解决 一…

[SAP ABAP] 程序备份

备份当前程序到本地的方式如下&#xff1a; 1.复制粘贴 Ctrl A 、Ctrl V 2.【实用程序】|【更多实用程序】|【上载/下载】|【下载】 ​ 3.快捷键&#xff0c;支持多种格式导出(.abap .html .pdf 等) 在事务码SE38(ABAP编辑器)屏幕右下角&#xff0c;点击【Options选项】图…

距离25年PMP第一次考试还有70多天,如何短期通过考试?

距离205年3月考试时间具体还有78天&#xff0c;除去过年放假的时间还有2个月多一点吧&#xff0c;可以说复习时间并不是很充裕&#xff0c;那么在2个月甚至不足两个月的时间里我们该如何应对呢&#xff1f;如何短期内上岸&#xff1f; 接下来给大家分享一下我的复习方法&#…

【AIGC-ChatGPT副业提示词指令 - 动图】魔法咖啡馆:一个融合创意与治愈的互动体验设计

引言 在当今快节奏的生活中&#xff0c;咖啡早已不仅仅是提神醒脑的饮品&#xff0c;更成为了一种情感寄托和生活态度的表达。本文将介绍一个独特的"魔法咖啡馆"互动体验设计&#xff0c;通过将咖啡与情感、魔法元素相结合&#xff0c;创造出一个充满想象力和治愈感…

通过远程控制软件实现企业高效协作

在这个信息技术迅猛发展的时代&#xff0c;远程办公已经成为一种趋势&#xff0c;而远程控制软件则是连接分散团队的重要工具。技术的革新不仅推动了远程控制软件的广泛应用&#xff0c;也为现代办公带来了高效的协作体验。本文将探讨远程控制软件的发展&#xff0c;并以RayLin…

解决 vue3 中 echarts图表在el-dialog中显示问题

原因&#xff1a; 第一次点开不显示图表&#xff0c;第二次点开虽然显示图表&#xff0c;但是图表挤在一起&#xff0c;页面检查发现宽高只有100px,但是明明已经设置样式宽高100% 这可能是由于 el-dialog 还没有完全渲染完成&#xff0c;而你的 echarts 组件已经开始尝试渲染图…

MySQL如何只取根据某列连续重复行的第一条记录

前言 MySQL如何只取根据某列连续重复行的第一条记录&#xff0c;条件&#xff1a;某列、连续、验重 建表准备 DROP TABLE IF EXISTS test; CREATE TABLE test (id bigint NOT NULL,time datetime NULL DEFAULT NULL,price int NULL DEFAULT NULL,PRIMARY KEY (id) USING BT…

图文教程:使用PowerDesigner导出数据库表结构为Word/Html文档

1、第一种情况-无数据库表&#xff0c;但有数据模型 1.1 使用PowerDesigner已完成数据建模 您已经使用PowerDesigner完成数据库建模&#xff0c;如下图&#xff1a; 1.2 Report配置和导出 1、点击&#xff1a;Report->Reports&#xff0c;如下图&#xff1a; 2、点击&…

AI三驾马车——数据、算法与算力的一体化融合体验

一、概述 随着AI大模型、云计算和大数据技术的快速发展&#xff0c;智能算力市场需求持续增长。今年7月由国家信息中心发布的《智能算力产业发展白皮书》指出&#xff0c;随着AI大模型等关键技术取得突破&#xff0c;算力需求正从通用计算转向智能计算。智能计算是指面向人工智…

Vue 3 与 Tauri 集成开发跨端APP

1、安装RUST 下载地址&#xff1a;Install Rust - Rust Programming Language 安装&#xff1a; 安装完成后&#xff0c;在命令行里运行: rustup 2、安装 Node.js 与 npm 或 pnpm &#xff0c;如果已经安装&#xff0c;可以忽略 # 使用 nvm 安装 Node.js 最新版本 nvm install…

指针详解之 多层嵌套的关系

1 例子之指向3个字符串的指针数组&#xff0c;易混淆&#xff01; 1.1过程详解&#xff1a; char *str[3]{ "Hello,thisisasample!", "Hi,goodmorning.", "Helloworld" }; char s[80]&#xff1b; strcpy(s,str[0]); //也可写成strcpy(s,*st…

Keras2.0 ImageDataGenerator 适配

最近在学习keras,总遇到使用 ImageDataGenerator当作训练参数&#xff0c;使用 fit_generator(), 而 Keras 2.0 已经放弃了&#xff0c;导致执行不下去了 经过N多天的摸索&#xff0c;终于是成功了 # 训练集数据生成 datagen ImageDataGenerator(rotation_range40,rescale…

循环神经网络(RNN)入门指南:从原理到实践

目录 1. 循环神经网络的基本概念 2. 简单循环网络及其应用 3. 参数学习与优化 4. 基于门控的循环神经网络 4.1 长短期记忆网络&#xff08;LSTM&#xff09; 4.1.1 LSTM的核心组件&#xff1a; 4.2 门控循环单元&#xff08;GRU&#xff09; 5 实际应用中的优化技巧 5…

低代码开源项目Joget的研究——Joget8社区版安装部署

大纲 环境准备安装必要软件配置Java配置JAVA_HOME配置Java软链安装三方库 获取源码配置MySql数据库创建用户创建数据库导入初始数据 配置数据库连接配置sessionFactory&#xff08;非必须&#xff0c;如果后续保存再配置&#xff09;编译下载tomcat启动下载aspectjweaver移动jw…

赋能开发者 | 麒麟信安受邀参加2024开放原子开发者大会,以技术为引领,以人才创发展

12月20至21日&#xff0c;以“一切为了开发者”为主题的“2024开放原子开发者大会暨首届开源技术学术大会”在湖北武汉举办。本届大会由开放原子开源基金会、中国通信学会联合主办&#xff0c;旨在贯彻落实国家软件发展战略&#xff0c;加速培育壮大我国开源生态。工业和信息化…

HTML5实现好看的喜庆圣诞节网站源码

HTML5实现好看的喜庆圣诞节网站源码 前言一、设计来源1.1 主界面1.2 圣诞介绍界面1.3 圣诞象征界面1.4 圣诞活动界面1.5 圣诞热度界面1.6 圣诞纪念界面1.7 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好看的喜庆圣诞节网站源码&#xff0c;圣…