当前位置: 首页 > news >正文

单片机与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_connectclient.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_connectclient.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 库是开源免费的,降低了开发过程中的软件成本;另一方面,单片机本身成本相对较低,二者结合能在满足物联网应用基本通信需求的同时,有效控制项目整体成本投入,尤其适合大规模、分布式的物联网项目部署,像智慧城市建设中众多设备间的通信组网等场景,都能凭借这一优势发挥重要作用。

相关文章:

单片机与MQTT协议

MQTT 协议简述 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布 / 订阅&#xff08;publish/subscribe&#xff09;模式的 “轻量级” 通讯协议&#xff0c;该协议构建于 TCP/IP 协议上&#xf…...

记录命令行操作树莓派Wifi的方式

打开WiFi rfkill unblock wlan 关闭WiFi rfkill block wlan 设置可连接的WiFi 方法一&#xff08;bullseye及以前版本才可用&#xff0c;bookworm版本&#xff09; sudo nano /etc/wpa_supplicant/wpa_supplicant.conf network{ssid"wifi_name"psk"wifi_pas…...

Docker 安装mysql ,redis,nacos

一、Mysql 一、Docker安装Mysql 1、启动Docker 启动&#xff1a;sudo systemctl start dockerservice docker start 停止&#xff1a;systemctl stop docker 重启&#xff1a;systemctl restart docker 2、查询mysql docker search mysql 3、安装mysql 3.1.默认拉取最新版…...

[C#] 复数乘法的跨平台SIMD硬件加速向量算法(不仅支持X86的Sse、Avx、Avx512,还支持Arm的AdvSimd)

文章目录 一、简单算法二、向量算法2.1 算法思路2.1.1 复数乘法的数学定义2.1.2 复数的数据布局2.1.3 第1步&#xff1a;计算 (a*c) (-b*d)i2.1.4 第2步&#xff1a;计算 (a*d) (b*c)i2.1.5 第3步&#xff1a;计算结果合并 2.2 算法实现&#xff08;UseVectors&#xff09;2.…...

curl 放弃对 Hyper Rust HTTP 后端的支持

curl 放弃了对使用 Rust 编写 Hyper HTTP 后端的支持&#xff0c;因为用户和开发者对此功能的需求很少。 curl 创始人兼核心开发者 Daniel Stenberg 表示&#xff0c;尽管这项工作最初由 ISRG 赞助并且看起来很有希望&#xff0c;但 Hyper 支持多年来一直处于实验阶段&#xf…...

RK3506开发板:智能硬件领域的新选择,带来卓越性能与低功耗

在现代智能硬件开发中&#xff0c;选择一款性能稳定、功耗低的开发板是确保产品成功的关键。Rockchip最新推出的RK3506芯片&#xff0c;凭借其卓越的能效比、多功能扩展性和优秀的实时性能&#xff0c;已经成为智能家电、工业控制、手持终端等领域的热门选择。而基于RK3506的Ar…...

RBAC权限控制

1、Spring Security 是一个功能强大的Java安全框架&#xff0c;它提供了全面的安全认证和授权的支持。 2 SpringSecurity配置类&#xff08;源码逐行解析&#xff09; Spring Security的配置类是实现安全控制的核心部分 开启Spring Security各种功能&#xff0c;以确保Web应…...

Linux高并发服务器开发 第六天(rwx 对于目录和文件的区别 gcc编译器 动态库静态库)

目录 1.rwx 对于目录和文件的区别 2.gcc 编译器 2.1编译过程 2.2gcc 的其他参数 3.动态库和静态库 3.1函数库 1.rwx 对于目录和文件的区别 r 文件的内容可以被查看。支持cat、more、head...vim &#xff1b;目录的内容可以被查看。ls、tree …...

如何使用远程控制工具管理你的计算机系统

在现代工作环境中&#xff0c;远程控制技术越来越重要&#xff0c;尤其是对于系统管理员、技术支持人员以及需要远程工作的人来说。远程控制不仅仅是便捷&#xff0c;更是提高工作效率、快速解决问题的重要手段。今天&#xff0c;我们将讨论一些常见的远程控制工具&#xff0c;…...

在K8S中,CNI有什么作用?

在kubernetes中&#xff0c;Container Network Interface(CNI)起着至关重要的作用&#xff0c;主要解决了容器网络配置及通信的问题&#xff0c;确保了Pod间网络连通性及其外部世界的通信。CNI的具体作用包括但不限于以下几个方面。 1. 网络配置自动化&#xff1a; 当kuberne…...

C语言性能优化:从基础到高级的全面指南

引言 C 语言以其高效、灵活和功能强大而著称&#xff0c;被广泛应用于系统编程、嵌入式开发、游戏开发等领域。然而&#xff0c;要写出高性能的 C 语言代码&#xff0c;需要对 C 语言的特性和底层硬件有深入的了解。本文将详细介绍 C 语言性能优化的背后技术&#xff0c;并通过…...

JS中Symbol (符号)数据类型详解和应用场景

JavaScript中Symbol数据类型详解 Symbol是ES6引入的一种原始数据类型&#xff0c;表示唯一的标识符。它是通过Symbol()函数生成的&#xff0c;每次调用都会返回一个独一无二的值。Symbol值的主要用途是为对象的属性提供唯一标识&#xff0c;以避免属性名冲突。 特点 唯一性 每…...

Go gin框架(详细版)

目录 0. 为什么会有Go 1. 环境搭建 2. 单-请求&&返回-样例 3. RESTful API 3.1 首先什么是RESTful API 3.2 Gin框架支持RESTful API的开发 4. 返回前端代码 go.main index.html 5. 添加静态文件 main.go?改动的地方 index.html?改动的地方 style.css?改…...

Linux系统 —— 进程控制系列 - 进程的等待:wait 与 waitpid

目录 1. 进程的等待 1.1 为什么需要等待 2. 进程等待的方法 1. wait 2. waitpid 3. 获取子进程status 4. 阻塞与非阻塞等待 续接前文&#xff1a; Linux系统 —— 进程控制系列 - 进程的创建与终止 &#xff1a;fork与exit-CSDN博客https://blog.csdn.net/hedhjd/artic…...

blender中合并的模型,在threejs中显示多个mesh;blender多材质烘培成一个材质

描述&#xff1a;在blender中合并的模型导出为glb&#xff0c;在threejs中导入仍显示多个mesh&#xff0c;并不是统一的整体&#xff0c;导致需要整体高亮或者使用DragControls等不能统一控制。 原因&#xff1a;模型有多个材质&#xff0c;在blender中合并的时候&#xff0c;…...

探索多模态大语言模型(MLLMs)的推理能力

探索多模态大语言模型&#xff08;MLLMs&#xff09;的推理能力 Multimodal Large Language Models (MLLMs) flyfish 原文&#xff1a;Exploring the Reasoning Abilities of Multimodal Large Language Models (MLLMs): A Comprehensive Survey on Emerging Trends in Mult…...

[Wireshark] 使用Wireshark抓包https数据包并显示为明文、配置SSLKEYLOGFILE变量(附下载链接)

wireshark 下载链接&#xff1a;https://pan.quark.cn/s/eab7f1e963be 提取码&#xff1a;rRAg 链接失效&#xff08;可能会被官方和谐&#xff09;可评论或私信我重发 chrome与firefox在访问https网站的时候会将密钥写入这个环境变量SSLKEYLOGFILE中&#xff0c;在wireshark…...

单片机实物成品-007 汽车防盗系统(代码+硬件+论文)

汽车尾气监测系统&#xff08;温度震动传感器 红外热释电GPS三个指示灯蜂鸣器正常模式防盗模式wifi传输控制送APP源码 &#xff09; 把该系统划分为两个不同设计主体&#xff0c;一方面为硬件控制主体&#xff0c;通过C语言来编码实现&#xff0c;以STM32开发板为核心控制器&a…...

redis开发与运维-redis0401-补充-redis流水线与Jedis执行流水线

文章目录 【README】【1】redis流水线Pipeline【1.1】redis流水线概念【1.2】redis流水线性能测试【1.2.1】使用流水线与未使用流水线的性能对比【1.2.2】使用流水线与redis原生批量命令的性能对比【1.2.3】流水线缺点 【1.3】Jedis客户端执行流水线【1.3.1】Jedis客户端执行流…...

windows系统下使用cd命令切换到D盘的方法

windows系统下使用cd命令切换到D盘的方法 系统环境配置 win10系统原装C盘后期自己安装的硬盘D盘 python3.8安装在D盘中 问题说明 winR打开终端&#xff0c;使用 cd d:命令&#xff0c;无法将当前目录切换到D盘 解决方法 方法一&#xff1a;使用下面这条命令 cd /d d:运…...

word参考文献第二行缩进对齐

刚添加完参考文献的格式是这样&#xff1a; ”段落“—>缩进修改、取消孤行控制 就可以变成...

Springboot关于格式化记录

日期格式化 返回前端日期需要格式化 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.2</version> </dependency>JsonFormat(pattern "yyyy-MM-dd…...

1.business english--build rapport

build rapport with someone 建立融洽关系 Salespeople often try to build rapport with customers to boost sales. user a variety of appropriate questions. answer the question according to your experience. Do you know how to make a good connection with others…...

发明专利与实用新型专利申请过程及自助与代办方式对比

申请专利&#xff08;发明专利、实用新型专利、外观设计专利&#xff09;有两种方式&#xff1a;1、自己直接向国家知识产权局申请。2、通过专利代办处申请。以下是对这两种专利类型&#xff08;发明专利、实用新型专利&#xff09;申请过程及两种申请方式的详细介绍和对比,参考…...

设计模式-创建型-工厂方法模式

什么是工厂方法模式&#xff1f; 工厂方法模式&#xff08;Factory Method Pattern&#xff09;是 创建型设计模式之一&#xff0c;目的是通过定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪个类。简而言之&#xff0c;工厂方法模式通过延迟对象的创建过程到子类来…...

如何判断一个学术论文是否具有真正的科研价值?ChatGPT如何提供帮助?

目录 1.创新性与学术贡献的超级加分✔ 2.科研过程中的各个环节—从0到1✔ 3.创新性与理论深度的完美结合✔ 4.论证与写作的清晰性✔ 5.数据整理和文献回顾——效率与精准并存✔ 6.创新性要求辅助✔ 总结 宝子们&#xff0c;学术论文写作的旅程是不是感觉像是走进了迷雾森…...

Linux驱动开发--字符设备驱动开发

一、概述 字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节 流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的点灯、按键、 IIC、 SPI, LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。 Linux 应用程序对驱动程…...

Java 网络原理 ①-IO多路复用 || 自定义协议 || XML || JSON

这里是Themberfue 在学习完简单的网络编程后&#xff0c;我们将更加深入网络的学习——HTTP协议、TCP协议、UDP协议、IP协议........... IO多路复用 ✨在上一节基于 TCP 协议 编写应用层代码时&#xff0c;我们通过一个线程处理连接的申请&#xff0c;随后通过多线程或者线程…...

828华为云征文|使用sysbench对Flexus X实例对mysql进行性能测评

目录 一、Flexus X实例概述 1.1?Flexus X实例 1.2?在mysql方面的优势 二、在服务器上安装MySQL 2.1 在宝塔上安装docker 2.2 使用宝塔安装mysql 2.3 准备测试数据库和数据库表 三、安装sysbench并进行性能测试 3.1 使用yum命令sysbench 3.2?运行?sysbench 并进行…...

数据结构:堆

目录 1.堆的概念 2.堆的结构 3.堆的初始化 4.堆的销毁 5.堆的插入 6.堆的删除 7.判断堆是否为空 1.堆的概念 堆的性质&#xff1a; 堆中某个结点的值总是不大于或不小于其父结点的值&#xff1b; 堆总是一棵完全二叉树。 以下堆的结构默认大堆 &#xff1a; 2.堆的结…...

洪水灾害多智能体分布式模拟示例代码

1. 环境定义&#xff1a;支持灾害动态、地理数据和分布式架构 import numpy as np import random import matplotlib.pyplot as plt# 新疆主要城市及邻接关系 XINJIANG_CITIES {Urumqi: [Changji, Shihezi],Changji: [Urumqi, Shihezi, Turpan],Shihezi: [Urumqi, Changji, K…...

基于 Ragflow 搭建知识库-初步实践

基于 Ragflow 搭建知识库-初步实践 一、简介 Ragflow 是一个强大的工具&#xff0c;可用于构建知识库&#xff0c;实现高效的知识检索和查询功能。本文介绍如何利用 Ragflow 搭建知识库&#xff0c;包括环境准备、安装步骤、配置过程以及基本使用方法。 二、环境准备 硬件要…...

Selenium实践总结

1.使用显示等待而不是隐式等待 隐式等待可能会导致不可预测的测试行为&#xff0c;尤其是在动态 Web 应用程序中。显式等待&#xff0c;它允许您 等待特定条件发生后再继续测试&#xff0c;这种方法提供了更多的控制和可靠性。 WebDriverWait wait new WebDriverWait(drive…...

华为麦芒5(安卓6)termux记录 使用ddns-go,alist

下载0.119bate1 安卓5和6版本,不能换源,其他源似乎都用不了,如果root可以直接用面具模块 https://github.com/termux/termux-app/releases/download/v0.119.0-beta.1/termux-app_v0.119.0-beta.1apt-android-5-github-debug_arm64-v8a.apk 安装ssh(非必要) pkg install open…...

Springboot jar包加密加固并进行机器绑定

获取机器码&#xff0c;通过classfinal-fatjar-1.2.1.jar来获取机器码 命令&#xff1a;java -jar classfinal-fatjar-1.2.1.jar -C 对springboot打包的jar进行加密功能 java -jar classfinal-fatjar-1.2.1.jar -file lakers-ljxny-3.0.0.jar -packages com.lygmanager.laker…...

【Microi吾码】开源力量赋能低代码创新,重塑软件开发生态格局

我的个人主页 文章专栏&#xff1a;Microi吾码 一、引言 在当今数字化浪潮汹涌澎湃的时代&#xff0c;软件开发的需求呈现出爆发式增长。企业为了在激烈的市场竞争中脱颖而出&#xff0c;不断寻求创新的解决方案以加速数字化转型。传统的软件开发方式往往面临着开发周期长、技…...

系统思考—冰山模型

“卓越不是因机遇而生&#xff0c;而是智慧的选择与用心的承诺。”—— 亚里士多德 卓越&#xff0c;从来不是一次性行为&#xff0c;而是一种习惯。正如我们在日常辅导中常提醒自己&#xff1a;行为的背后&#xff0c;隐藏着选择的逻辑&#xff0c;而选择的根源&#xff0c;源…...

Java读取InfluxDB数据库的方法

本文介绍基于Java语言&#xff0c;读取InfluxDB数据库的方法&#xff0c;包括读取InfluxDB的所有数据库&#xff0c;以及指定数据库中的measurement、field、tag等。 首先&#xff0c;创建一个Java项目&#xff0c;用于撰写代码。如果大家是基于IDEA来创建项目&#xff0c;则可…...

【mybatis-plus问题集锦系列】在mybatisplus中无法autowired的原因排查及解决

mybatisplus简化了我们做数据操作&#xff0c;大大提升了我们的开发速度&#xff0c;但是今天在做测试的时候&#xff0c;突然报了这么个错误&#xff0c;排查好久才找到解决方案&#xff0c;特此记录下 问题复现 这里的测试方法报错&#xff0c;通过不了测试 org.springf…...

python中Windows系统使用 pywin32 来复制图像到剪贴板,并使用 Selenium 模拟 Ctrl+V 操作

步骤 1&#xff1a;安装必要的库 首先&#xff0c;安装 pywin32 和 selenium&#xff1a; pip install pywin32 selenium 如果使用的是 macOS&#xff0c;可以安装 pyobjc&#xff1a; pip install pyobjc 步骤 2&#xff1a;使用 pywin32 复制图像到剪贴板 在 Windows 系统中…...

uniapp——微信小程序,从客户端会话选择文件

微信小程序选择文件 文章目录 微信小程序选择文件效果图选择文件返回数据格式 API文档&#xff1a; chooseMessageFile 微信小程序读取文件&#xff0c;请查看 效果图 选择文件 /*** description 从客户端会话选择文件* returns {String} 文件路径*/ const chooseFile () &g…...

点亮核心板小灯 STM32U575

将核心板上的运行状态指示灯点亮 任务分析 灯如何点亮 如何看开发板原理图 开发板上的灯硬件组成 原理图 原理图&#xff08;Schematic Diagram&#xff09;&#xff0c;也称为电路图或电气图&#xff0c;是一种图形表示方法&#xff0c;用于展示电子系统或电路的工作原理和…...

“图书馆服务自动化”:基于SSM框架的图书借阅系统开发

3.1系统的需求分析 需求分析阶段是设计系统功能模块的总方向&#xff0c;可以这样来说&#xff0c;系统的整个的开发流程以及设计进度&#xff0c;基本上都是以需求分析为基本依据的[10]。需求分析阶段可以确定系统的基本功能设计&#xff0c;以及在最后的系统验收阶段&#xf…...

顶顶通呼叫中心中间件的三种呼叫方式(mod_cti基于FreeSWITCH)

顶顶通呼叫中心共有三种呼叫方式&#xff1a; 手拨呼叫点击呼叫自动外呼 联系我们 有意向了解呼叫中心中间件的用户&#xff0c;可以点击该链接添加工作人员&#xff1a;https://blog.csdn.net/H4_9Y/article/details/136148229 手拨呼叫 手拨呼叫属于常规的呼叫方式&…...

HCIA笔记9--NAT、ACL与链路聚合

1. ACL ACL: 访问控制列表, Access Control List。 通过定义规则来允许或拒绝流量的通过。 1.1 ACL分类 1.2 配置实例 如图所示&#xff0c;对R2的访问只允许192.168.1.0/24网段。 我们可以配置基本acl来限制 acl 2000 acl number 2000 rule 5 permit source 192.168.1.0 0…...

【笔记】在虚拟机中通过apache2给一个主机上配置多个web服务器

&#xff08;配置出来的web服务器又叫虚拟主机……&#xff09; 下载apache2 sudo apt update sudo apt install apache2 &#xff08;一&#xff09;ip相同 web端口不同的web服务器 进入 /var/www/html 创建站点一和站点二的目录文件&#xff08;目录文件名自定义哈&#x…...

“校园健康数据管理”:疫情管控系统的信息收集与分析

3.1可行性分析 通过对系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1 技术可行性 1.硬件可行性分析 校园疫情管控系统系统的硬件要求方面不存在特殊的要求&#xff0c…...

MySQL 中存储金额数据一般使用什么数据类型

在 MySQL 中存储金额数据时&#xff0c;应该谨慎选择数据类型&#xff0c;以确保数据的精度和安全性。以下是几种常用的数据类型及其适用性&#xff1a; DECIMAL 类型&#xff1a; 描述&#xff1a;DECIMAL 类型是专门为存储精确的小数而设计的。它可以指定小数点前后的数字位数…...

使用 .NET 6 或 .NET 8 上传大文件

如果您正在使用 .NET 6&#xff0c;并且它拒绝上传大文件&#xff0c;那么本文适合您。 我分享了一些处理大文件时需要牢记的建议&#xff0c;以及如何根据我们的需求配置我们的服务&#xff0c;并提供无限制的服务。 本文与 https://blog.csdn.net/hefeng_aspnet/arti…...

帝国cms电脑pc站url跳转到手机站url的方法

本文讲解一下帝国cms电脑网站跳转到手机动态网站和手机静态网站的方法,笔者以古诗词网 www.gushichi.com为例&#xff0c;为大家介绍操作步骤。方法一&#xff1a;帝国pc站跳转到手机静态站 1、假设我们有帝国cms 电脑网站www.XXX.com&#xff0c;手机网站m.XXX.com &#xf…...