imx6ull/linux应用编程学习(17)利用mqtt上传开发板数据,和控制开发板led(基于正点)

1.关于如何创建自己的服务器,可看上篇文章

imx6ull/linux应用编程学习(16)emqx ,mqtt创建连接mqtt.fx-CSDN博客

2.实现任务:(正点原子教程源码改)

(1)用户可通过手机或电脑远程控制开发板上的一颗 LED 灯;

(2) 开发板客户端每隔 30 秒向服务端发送 SoC 当前的温度值,用户通过手机或电脑可查看到该温度值

首先我们需要先准备好这些:

1.首先mqtt.fx连接上服务器

2.准备好客户端id、用户名、用户名密码。

3.代码:

目录结构为

首先创建cmake文件夹、build文件夹、CMakeLists.txt、mqttClient.c文件

CMakeLists.txt(已经加上注释)

#*******************************************************************************
#  Copyright © ALIENTEK Co., Ltd. 1998-2021. All rights reserved.
#
#  顶层CMakeLists.txt
#  All rights reserved. This program and the accompanying materials
#  are made available under the terms of the Eclipse Public License v2.0
#  and Eclipse Distribution License v1.0 which accompany this distribution.
#*******************************************************************************/# 指定最低的CMake版本要求
cmake_minimum_required(VERSION 2.8.12)# 定义项目名称和使用的语言
project(MQTTClient C)# 打印CMake的版本、系统名称和处理器信息
message(STATUS "CMake version: " ${CMAKE_VERSION})
message(STATUS "CMake system name: " ${CMAKE_SYSTEM_NAME})
message(STATUS "CMake system processor: " ${CMAKE_SYSTEM_PROCESSOR})# 设置可执行文件输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)# 定义可执行文件目标
add_executable(mqttClient mqttClient.c)# 指定MQTT客户端库头文件路径、库路径以及链接库
# ***大家需要根据MQTT的实际安装路径设置***# 设置MQTT头文件搜索路径,这是ubuntu上的路径
target_include_directories(mqttClient PRIVATE /home/book/linux/tool/mqtt/paho.mqtt.c/install/include)# 设置MQTT库文件搜索路径
target_link_directories(mqttClient PRIVATE /home/book/linux/tool/mqtt/paho.mqtt.c/install/lib)# 链接MQTT库文件
# 你可以选择使用以下一种方式链接库文件:
# 方式1: 使用库名称进行链接
# target_link_libraries(mqttClient PRIVATE paho-mqtt3c)  #MQTT链接库 libpaho-mqtt3c.so# 方式2: 使用库文件的完整路径进行链接,找到libpaho-mqtt3c.so文件,并且连接,意思为同步模式 MQTT 客户端库(不支持 SSL) 。
target_link_libraries(mqttClient /home/book/linux/tool/mqtt/paho.mqtt.c/install/lib/libpaho-mqtt3c.so)

在cmake文件夹中创建arm-linux-setup.cmake

arm-linux-setup.cmake

##################################
# 配置 ARM 交叉编译
##################################
set(CMAKE_SYSTEM_NAME Linux) # 设置目标系统名字
set(CMAKE_SYSTEM_PROCESSOR arm) # 设置目标处理器架构# 指定编译器的 sysroot 路径
set(TOOLCHAIN_DIR /home/book/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf)
set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc)# 指定交叉编译器
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-g++)# 为编译器添加编译选项
set(CMAKE_C_FLAGS "-march=armv7ve -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7")
set(CMAKE_CXX_FLAGS "-march=armv7ve -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7")# 设置查找路径模式
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

编译器路径和sysroot路径自己指定,关于如何查找sysroot路径:

arm-linux-gnueabihf-gcc --print-sysroot

可得,下面就是路径,

返回上级目录,创建mqttClient.c

mqttClient.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "MQTTClient.h" //包含 MQTT 客户端库头文件
/* ########################宏定义##################### */
#define BROKER_ADDRESS "tcp://iot.ranye-iot.net:1883" //然也物联平台社区版 MQTT 服务器地址
/* 客户端 id、用户名、密码 *
* 当您成功申请到然也物联平台的社区版 MQTT 服务后
* 然也物联工作人员会给你发送 8 组用于连接社区版 MQTT 服务器
* 的客户端连接认证信息:也就是客户端 id、用户名和密码
* 注意一共有 8 组,您选择其中一组覆盖下面的示例值
* 后续我们使用 MQTT.fx 或 MQTTool 的时候 也需要使用一组连接认证信息
* 去连接社区版 MQTT 服务器!
* 由于这是属于个人隐私 笔者不可能将自己的信息写到下面 */
#define CLIENTID "您的客户端 ID" //客户端 id
#define USERNAME "您的用户名" //用户名
#define PASSWORD "您的密码" //密码
/* 然也物联社区版 MQTT 服务为每个申请成功的用户
* 提供了个人专属主题级别,在官方发给您的微信信息中
* 提到了
* 以下 dt_mqtt/ 便是笔者的个人主题级别
* dt_mqtt 其实就是笔者申请社区版 MQTT 服务时注册的用户名
* 大家也是一样,所以你们需要替换下面的 dt_mqtt 前缀
* 换成你们的个人专属主题级别(也就是您申请时的用户名)
*/
#define WILL_TOPIC "ymj/will" //遗嘱主题
#define LED_TOPIC "ymj/led" //LED 主题
#define TEMP_TOPIC "ymj/temperature" //温度主题
/* ################################################# */
static int msgarrvd(void *context, char *topicName, int topicLen,
MQTTClient_message *message)
{
if (!strcmp(topicName, LED_TOPIC)) { //校验消息的主题
if (!strcmp("2", message->payload)) //如果接收到的消息是"2"则设置 LED 为呼吸灯模式
system("echo heartbeat > /sys/class/leds/sys-led/trigger");
if (!strcmp("1", message->payload)) { //如果是"1"则 LED 常量
system("echo none > /sys/class/leds/sys-led/trigger");
system("echo 1 > /sys/class/leds/sys-led/brightness");
}
else if (!strcmp("0", message->payload)) {//如果是"0"则 LED 熄灭
system("echo none > /sys/class/leds/sys-led/trigger");
system("echo 0 > /sys/class/leds/sys-led/brightness");
}
// 接收到其它数据 不做处理
}
/* 释放占用的内存空间 */MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
/* 退出 */
return 1;
}
static void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
int main(int argc, char *argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
int rc;
/* 创建 mqtt 客户端对象 */
if (MQTTCLIENT_SUCCESS !=
(rc = MQTTClient_create(&client, BROKER_ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL))) {
printf("Failed to create client, return code %d\n", rc);
rc = EXIT_FAILURE;
goto exit;
}
/* 设置回调 */
if (MQTTCLIENT_SUCCESS !=
(rc = MQTTClient_setCallbacks(client, NULL, connlost,
msgarrvd, NULL))) {
printf("Failed to set callbacks, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
/* 连接 MQTT 服务器 */
will_opts.topicName = WILL_TOPIC; //遗嘱主题
will_opts.message = "Unexpected disconnection"; //遗嘱消息
will_opts.retained = 1; //保留消息will_opts.qos = 0; //QoS0
conn_opts.will = &will_opts;
conn_opts.keepAliveInterval = 30; //心跳包间隔时间
conn_opts.cleansession = 0; //cleanSession 标志
conn_opts.username = USERNAME; //用户名
conn_opts.password = PASSWORD; //密码
if (MQTTCLIENT_SUCCESS !=
(rc = MQTTClient_connect(client, &conn_opts))) {
printf("Failed to connect, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
printf("MQTT 服务器连接成功!\n");
/* 发布上线消息 */
pubmsg.payload = "Online"; //消息的内容
pubmsg.payloadlen = 6; //内容的长度
pubmsg.qos = 0; //QoS 等级
pubmsg.retained = 1; //保留消息
if (MQTTCLIENT_SUCCESS !=
(rc = MQTTClient_publishMessage(client, WILL_TOPIC, &pubmsg, NULL))) {
printf("Failed to publish message, return code %d\n", rc);
rc = EXIT_FAILURE;
goto disconnect_exit;
}
/* 订阅主题 dt_mqtt/led */
if (MQTTCLIENT_SUCCESS !=
(rc = MQTTClient_subscribe(client, LED_TOPIC, 0))) {
printf("Failed to subscribe, return code %d\n", rc);
rc = EXIT_FAILURE;
goto disconnect_exit;
}
/* 向服务端发布芯片温度信息 */
for ( ; ; ) {
MQTTClient_message tempmsg = MQTTClient_message_initializer;
char temp_str[10] = {0};
int fd;
/* 读取温度值 */
fd = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);
read(fd, temp_str, sizeof(temp_str));//读取 temp 属性文件即可获取温度
close(fd);
/* 发布温度信息 */
tempmsg.payload = temp_str; //消息的内容
tempmsg.payloadlen = strlen(temp_str); //内容的长度
tempmsg.qos = 0; //QoS 等级
tempmsg.retained = 1; //保留消息
if (MQTTCLIENT_SUCCESS !=
(rc = MQTTClient_publishMessage(client, TEMP_TOPIC, &tempmsg, NULL))) {
printf("Failed to publish message, return code %d\n", rc);
rc = EXIT_FAILURE;
goto unsubscribe_exit;
}
sleep(30); //每隔 30 秒 更新一次数据
}
unsubscribe_exit:
if (MQTTCLIENT_SUCCESS !=
(rc = MQTTClient_unsubscribe(client, LED_TOPIC))) {
printf("Failed to unsubscribe, return code %d\n", rc);
rc = EXIT_FAILURE;
}
disconnect_exit:
if (MQTTCLIENT_SUCCESS !=
(rc = MQTTClient_disconnect(client, 10000))) {
printf("Failed to disconnect, return code %d\n", rc);
rc = EXIT_FAILURE;
}
destroy_exit:
MQTTClient_destroy(&client);
exit:
return rc;
}

(1)消息到达回调函数

static int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)

处理接收到的消息,根据不同的消息内容控制 LED 状态。

(2)连接丢失回调函数

static void connlost(void *context, char *cause)

当连接丢失时打印原因。

(3)变量声明和初始化

  • MQTTClient client:MQTT 客户端对象。
  • MQTTClient_connectOptions conn_opts:MQTT 连接选项结构体,用于设置连接参数。
  • MQTTClient_willOptions will_opts:MQTT 遗嘱选项结构体,用于设置遗嘱消息。
  • MQTTClient_message pubmsg:MQ

(4)#define BROKER_ADDRESS "tcp://iot.ranye-iot.net:1883" 

这个是你的服务器地址,需要改,格式“tcp://xxxxxxx:端口”

(5)注意,这里开发板和电脑/手机是不同的客户端,所以程序里面的是开发板的客户端,所以器客户端还有用户名,需要和mqtt.fx上的不一样,之后再emqx上面认证授权

进入build文件夹,cmake ../

然后make。

可见在bin中有生成文件

将mqttClient,利用scp传至开发板。

4. 测试(端口1883)

mqtt.fx 连接服务器

订阅主题,主题可以根据自己的名字改变,在emqx更新主题

注意,开发板必须要可以联网,可以用ping baidu.com来测试

执行./mqttClient发现报错

意思是没有连接开发板环境

首先找到自己的mqtt库文件路径,然后执行

export LD_LIBRARY_PATH=/home/root/tool/mqtt/install/lib:$LD_LIBRARY_PATH

在执行

./mqttClient

或者是直接执行

LD_LIBRARY_PATH=/home/root/tool/mqtt/install/lib:$LD_LIBRARY_PATH ./mqttClient

如果你的端口是1883,那么就没有问题啦,执行成功!就直接可以了

但是如果你还有服务器的端口是8883,则看还要开启SSL服务,需要mqtt库包含支持ssl的文件

libpaho-mqtt3a.so: 异步模式 MQTT 客户端库(不支持 SSL) 。

 libpaho-mqtt3as.so: 异步模式 MQTT 客户端库(支持 SSL) 。

 libpaho-mqtt3c.so: 同步模式 MQTT 客户端库(不支持 SSL) 。

 libpaho-mqtt3cs.so: 支持 SSL 的同步模式客户端库(支持 SSL) 。

我的mqtt库比较老,不支持ssl,没有,所以进行更新

5.更新mqtt

首先确认你是否安装了openssl

以下语句测试:

ls /home/book/linux/tool/mqtt/openssl-1.0.0s/include/openssl/pem.h
ls /home/book/linux/tool/mqtt/openssl-1.0.0s/include/openssl/ssl.h

如果没有,

安装openssl

sudo apt update
sudo apt install libssl-dev

我的openssl头文件目录:

/home/book/linux/tool/mqtt/openssl-1.0.0s/include/openssl

如果有,则下一步:

安装Paho MQTT C 库

sudo apt update
sudo apt install cmake build-essential libssl-dev

下载源码

git clone https://github.com/eclipse/paho.mqtt.c.git
cd paho.mqtt.c

cmake

cmake -DPAHO_WITH_SSL=ON -DOPENSSL_ROOT_DIR=/home/book/linux/tool/mqtt/openssl-1.0.0s -DOPENSSL_INCLUDE_DIR=/home/book/linux/tool/mqtt/openssl-1.0.0s/include ..

make

可以看到已经有了。为了不破坏原来路径,我将这个与原来的老mqtt库替换。

cd ~/linux/tool/mqtt/mqtt_new/paho.mqtt.c

创建install文件夹,再install文件夹创建lib和linclude文件夹

进入文件目录:/home/book/linux/tool/mqtt/mqtt_new/paho.mqtt.c

cp -r src/* install/include

进入/home/book/linux/tool/mqtt/mqtt_new/paho.mqtt.c/build

执行

cp -r src/* ../install/lib

回到/home/book/linux/tool/mqtt

cp -r mqtt_new/paho.mqtt.c paho.mqtt.c

移植成功!然后利用scp更新开发板的环境

 scp -r book@192.168.137.12:/home/book/linux/tool/mqtt/paho.mqtt.c/install /home/root/tool/mqtt

移植成功

6.测试(端口8883)

端口8883,我们需要改一些链接 

打开CMakeLists.txt文件,将最后一行的链接libpaho-mqtt3c.so改为libpaho-mqtt3cs.so支持ssl

然后打开cmake文件夹,打开arm-linux-setup.cmake

arm-linux-setup.cmake

##################################
# 配置 ARM 交叉编译
##################################
set(CMAKE_SYSTEM_NAME Linux) # 设置目标系统名字
set(CMAKE_SYSTEM_PROCESSOR arm) # 设置目标处理器架构# 指定编译器的 sysroot 路径
set(TOOLCHAIN_DIR /home/book/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf)
set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc)# 指定交叉编译器
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-g++)# 为编译器添加编译选项
set(CMAKE_C_FLAGS "-march=armv7ve -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7")
set(CMAKE_CXX_FLAGS "-march=armv7ve -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7")# 设置查找路径模式
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)# 添加 OpenSSL 的路径
set(OPENSSL_ROOT_DIR /home/book/linux/tool/mqtt/openssl-1.0.0s)
set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT_DIR}/include/openssl)
set(OPENSSL_CRYPTO_LIBRARY ${OPENSSL_ROOT_DIR}/libcrypto.so)
set(OPENSSL_SSL_LIBRARY ${OPENSSL_ROOT_DIR}/libssl.so)

加入openssl链接,因为8883端口需要ssl支持,所以需要加入链接。

然后重点来了!!!!!!!!!!!!

对比1883端口,8883端口需要ssl支持,所以,开发板需要CA证书文件!!!!!!!!!!!

将下载的ca证书传到开发板,记住目录,记得加到程序中,然后进行了修改:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h> // 包含open和close函数的定义
#include <unistd.h> // 包含unistd.h以使用read函数
#include "MQTTClient.h" // 包含MQTT客户端库的定义// 定义MQTT服务器的地址和连接信息
#define BROKER_ADDRESS "ssl://d9d31e0e.ala.cn-hangzhou.emqxsl.cn:8883"
#define CLIENTID "d0800680277b44359129dd68ef11675b"
#define USERNAME "ymj3"
#define PASSWORD "123456"
#define WILL_TOPIC "ymj/will1"
#define LED_TOPIC "ymj/led1"
#define TEMP_TOPIC "ymj/temperature1"
#define CA_PATH "/home/root/mqtt_test/emqxsl-ca.crt"// 回调函数:连接丢失时调用
void connlost(void *context, char *cause) {printf("\nConnection lost\n");printf("cause: %s\n", cause);
}// 回调函数:接收到消息时调用
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message) {printf("Message arrived\n");printf("topic: %s\n", topicName);printf("message: %.*s\n", message->payloadlen, (char*)message->payload);// 检查是否是LED_TOPICif (strcmp(topicName, LED_TOPIC) == 0) {if (strncmp(message->payload, "ON", message->payloadlen) == 0) {// 打开LEDprintf("Turning LED ON\n");system("echo 1 > /sys/class/leds/sys-led/brightness");} else if (strncmp(message->payload, "OFF", message->payloadlen) == 0) {// 关闭LEDprintf("Turning LED OFF\n");system("echo 0 > /sys/class/leds/sys-led/brightness");}}// 释放消息内存MQTTClient_freeMessage(&message);MQTTClient_free(topicName);return 1;
}int main(int argc, char* argv[]) {MQTTClient client; // 定义MQTT客户端对象MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; // 初始化MQTT连接选项MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer; // 初始化遗嘱选项MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer; // 初始化SSL选项int rc; // 用于存储返回代码// 创建MQTT客户端MQTTClient_create(&client, BROKER_ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);// 设置回调函数MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, NULL);// 设置遗嘱选项will_opts.topicName = WILL_TOPIC;will_opts.message = "Unexpected disconnection";will_opts.retained = 1;will_opts.qos = 0;conn_opts.will = &will_opts;conn_opts.keepAliveInterval = 30;conn_opts.cleansession = 1;conn_opts.username = USERNAME;conn_opts.password = PASSWORD;// 配置SSL选项ssl_opts.trustStore = CA_PATH;conn_opts.ssl = &ssl_opts;// 增加调试信息printf("Attempting to connect to %s with client ID %s\n", BROKER_ADDRESS, CLIENTID);printf("Using username: %s and password: %s\n", USERNAME, PASSWORD);printf("Using CA file: %s\n", CA_PATH);// 连接到MQTT服务器if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {printf("Failed to connect, return code %d\n", rc);exit(EXIT_FAILURE);}printf("Connected to broker\n");// 订阅LED_TOPIC主题if ((rc = MQTTClient_subscribe(client, LED_TOPIC, 0)) != MQTTCLIENT_SUCCESS) {printf("Failed to subscribe, return code %d\n", rc);goto disconnect_exit;}// 发布上线消息MQTTClient_message pubmsg = MQTTClient_message_initializer;pubmsg.payload = "Online";pubmsg.payloadlen = strlen(pubmsg.payload);pubmsg.qos = 0;pubmsg.retained = 1;MQTTClient_deliveryToken token;if ((rc = MQTTClient_publishMessage(client, WILL_TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS) {printf("Failed to publish message, return code %d\n", rc);goto unsubscribe_exit;}printf("Waiting for publication of %s\n", (char*) pubmsg.payload);rc = MQTTClient_waitForCompletion(client, token, 10000L);printf("Message with delivery token %d delivered\n", token);// 向服务端发布芯片温度信息while (1) {MQTTClient_message tempmsg = MQTTClient_message_initializer;char temp_str[10] = {0};int fd;// 读取温度值fd = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);if (fd < 0) {perror("Failed to open temp file");continue;}read(fd, temp_str, sizeof(temp_str));close(fd);// 发布温度信息tempmsg.payload = temp_str;tempmsg.payloadlen = strlen(temp_str);tempmsg.qos = 0;tempmsg.retained = 1;if ((rc = MQTTClient_publishMessage(client, TEMP_TOPIC, &tempmsg, &token)) != MQTTCLIENT_SUCCESS) {printf("Failed to publish message, return code %d\n", rc);goto unsubscribe_exit;}printf("Published temperature: %s\n", temp_str);sleep(30); // 每隔30秒更新一次数据}unsubscribe_exit:if ((rc = MQTTClient_unsubscribe(client, LED_TOPIC)) != MQTTCLIENT_SUCCESS) {printf("Failed to unsubscribe, return code %d\n", rc);}
disconnect_exit:if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS) {printf("Failed to disconnect, return code %d\n", rc);}MQTTClient_destroy(&client);return rc;
}

  • 包含必要的头文件

    • stdio.hstdlib.hstring.h:标准输入输出和字符串处理函数。
    • fcntl.h:文件控制选项,包含 O_RDONLY 的定义。
    • unistd.h:POSIX 操作系统 API,包含 read 函数的定义。
    • MQTTClient.h:MQTT 客户端库的定义。
  • 定义宏

    • BROKER_ADDRESSCLIENTIDUSERNAMEPASSWORD:MQTT 服务器的连接信息。
    • WILL_TOPICLED_TOPICTEMP_TOPIC:MQTT 主题。
    • CA_PATH:CA 证书的路径。
  • 回调函数 connlost:当连接丢失时打印原因。

  • 回调函数 msgarrvd:当接收到消息时处理消息内容。如果消息主题是 LED_TOPIC,则根据消息内容控制 LED 的开关状态。

执行

/usr/local/bin/cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/arm-linux-setup.cmake -DCMAKE_BUILD_TYPE=Release ..

make

将文件传到开发板

实现功能:

  • 连接到 MQTT 服务器:通过 SSL/TLS 安全连接到指定的 MQTT 服务器。
  • 设置回调函数:设置回调函数来处理连接丢失和消息到达的情况。
  • 订阅主题:订阅 ymj/led1 主题以接收控制 LED 灯状态的消息,NO为开,OFF为关。
  • 发布上线消息:在连接到 MQTT 服务器后,发布一条上线消息到 ymj/will1 主题。
  • 定期发布温度信息:每隔30秒读取一次温度信息并发布到 ymj/temperature1 主题。
  • 控制 LED 灯:根据收到的消息内容,通过 ymj/led1 主题控制 LED 灯的状态(开/关)

注意开发板的用户名和id要和mqtt.fx不一样,然后都要到emqx进行认证和授权

演示

NO:

OFF

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

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

相关文章

小白的OS Copilot 产品测评

背景 通过群友介绍才知OS Copilot 。不想错过任何优秀的AI产品。随着互联网的发展和时代的进步&#xff0c;要紧跟时代&#xff0c;了解市面上的优秀的AI科技产品。 OS Copilot 产品体验评测 1&#xff09;您的角色是什么&#xff1f;开发、运维、学生&#xff1f;如果使用O…

类和对象——【const成员】【static成员】【友元】【内部类】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件iostream的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

css文字自适应宽度动态出现省略号...

前言 在列表排行榜中通常会出现的一个需求&#xff1a;从左到右依次是名次、头像、昵称、徽标、分数。徽标可能会有多个或者没有徽标&#xff0c;徽标长度是动态的&#xff0c;昵称如果过长要随着有无徽标进行动态截断出现省略号。如下图布局所示&#xff08;花里胡哨的底色是…

若依vue集成electron实现打包exe应用程序

一、修改package.json文件,加入相关依赖和配置 {"name": "ruoyi","version": "3.8.6","description": "若依管理系统","author": "若依","license":

分层图最短路,CF 1725M - Moving Both Hands

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1725M - Moving Both Hands 二、解题报告 1、思路分析 题意看似很简单&#xff0c;就是问我们两个人分别处于1, p两个点上&#xff0c;二者同时出发&#xff0c;相遇时二者所用路径之和的最小值 不难想到求…

Git协作

文章目录 Git协作冲突冲突的发生情况解决冲突如何处理冲突 1 分支1.1 什么是Git分支1.2 创建分支 2 切换分支2.1 指向分支2.2 暂存分支切换分支与未提交更改的处理使用 Stash 临时保存更改Stash 的工作原理&#xff1a;场景设定使用 Git Stash 3 远程分支3.1 快进合并快进合并的…

Qt/QML学习-定位器

QML学习 定位器例程视频讲解代码 main.qml import QtQuick 2.15 import QtQuick.Window 2.15Window {width: 640height: 480visible: truetitle: qsTr("positioner")Rectangle {id: rectColumnwidth: parent.width / 2height: parent.height / 2border.width: 1Col…

Qt基础控件总结—多页面切换(QStackWidget类、QTabBar类和QTabWidget类)

QStackedWidget 类 QStackedWidget 类是在 QStackedLayout 之上构造的一个便利的部件,其使用方法与步骤和 QStackedLayout 是一样的。QStackedWidget 类的成员函数与 QStackedLayout 类也基本上是一致的,使用该类就和使用 QStackedLayout 一样。 使用该类可以参考QStackedL…

iPhone数据恢复篇:在 iPhone 上恢复找回短信的 5 种方法

方法 1&#xff1a;检查最近删除的文件夹 iOS 允许您在 30 天内恢复已删除的短信。您需要先从“设置”菜单启用“过滤器”。让我们来实际检查一下。 步骤 1&#xff1a;打开“设置” > “信息”。 步骤 2&#xff1a;选择“未知和垃圾邮件”&#xff0c;然后切换到“过滤…

如何将若依vue升级到springboot3.x?

为了确保项目符合要求,Spring Boot 3.x 要求Java版本为17或更高。 1、修改根目录下的pom.xml文件 <!-- java.version版本8更换为17 --> <java.version>17</java.version><!-- 新增节点 --> <mybatis-spring-boot.version>3.0.3<

SpringMVC(3)——SpringMVC注解实战

前言 SpringMVC&#xff08;2&#xff09;——controller方法参数与html表单对应&#xff08;请求参数的绑定&#xff09; 上篇博客我们提到了controller方法的参数与html表单之间的对应关系 但是这种对应关系有很多缺点&#xff1a; 传递参数只能放在request的body当中&am…

极狐Gitlab使用(2)

目录 1. Gitlab命令行修改管理员密码 2. Gitlab服务管理 3. 公司的开发代码提交处理流程 4. Gitlab 备份与恢复 数据备份 测试数据恢复 5. 邮箱配置 1. Gitlab命令行修改管理员密码 [roottty01 ~]# gitlab-rails console -e production # 启动GitLab的Rails控制…

windows USB 设备驱动开发-USB电源管理(一)

符合通用串行总线 (USB) 规范的 USB 设备的电源管理功能具有一组丰富而复杂的电源管理功能。 请务必了解这些功能如何与 Windows 驱动程序模型 (WDM) 交互&#xff0c;特别是 Microsoft Windows 如何调整标准 USB 功能以支持系统唤醒体系结构。 基于内核模式驱动程序框架的 US…

2024年06月CCF-GESP编程能力等级认证Python编程四级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 一、单选题(每题 2 分,共 30 分) 第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级,那他可以选择的认证语言有几种?( ) A. 1 B. 2 C…

React文档内网搭建

React文档内网搭建流程 官网地址 官网中文地址 通过官网我们可以找到React的github存储库 ReactGitHub 在介绍中可以找到对应的文档存储库 React文档存储库 此存储库是英文文档地址,我们通过中文文档地址以及该存储库作者目录下找到中文存储库 React文档中文存储库 下载…

13个Python自动化实战脚本

1、批量文件重命名神器在工作中&#xff0c;我们常常需要对大量文件进行批量重命名&#xff0c;Python帮你轻松搞定&#xff01; 2、自动发送邮件通知告别手动发送&#xff0c;用Python编写定时发送邮件的自动化脚本。 3、定时任务自动化执行使用Python调度库&#xff0c;实现定…

高盛开源的量化金融 Python 库

GS Quant GS Quant是用于量化金融的Python工具包&#xff0c;建立在世界上最强大的风险转移平台之一之上。旨在加速量化交易策略和风险管理解决方案的开发&#xff0c;凭借25年的全球市场经验精心打造。 它由高盛的定量开发人员&#xff08;定量&#xff09;创建和维护&#…

云开发技术的壁纸小程序源码,无需服务期无需域名

1、本款小程序为云开发版本&#xff0c;不需要服务器域名 2、文件内有图文搭建教程&#xff0c;小白也不用担心不会搭建。 3、本程序反应速度极快&#xff0c;拥有用户投稿、积分系统帮助各位老板更多盈利。 4、独家动态壁纸在线下载&#xff0c;给用户更多的选择 5、最新版套图…

Open3D 点云配准精度评价指标-RMSE

目录 一、概述 1.1RMSE的计算方法 1.2RMSE的评价标准 二、代码实现 三、实现效果 3.1原始点云 3.2计算数据 一、概述 均方根误差(RMSE, Root Mean Squared Error)是衡量两个点云之间平均误差的一个常用指标。它通过计算匹配点对之间距离的平方和的平方根,来…

有必要找第三方软件测评公司吗?如何选择靠谱软件测评机构?

软件测试是确保软件质量的重要环节&#xff0c;而在进行软件测试时&#xff0c;是否有必要找第三方软件测评公司呢?第三方软件测评公司是指独立于软件开发公司和用户之间的中立机构&#xff0c;专门从事软件测试和测评工作。与自身开发团队或内部测试团队相比&#xff0c;选择…