【ESP32】ESP32与MQTT通信:实现传感器数据监测与设备控制

ESP32与MQTT通信

    • 1 项目概览
    • 2 硬件组成
    • 3 MQTT协议解析
      • MQTT协议简介
      • MQTT核心概念
      • 本项目中的MQTT应用
    • 4 MQTT Broker选择
      • EMQX Broker
      • 其他常用MQTT Broker
    • 5 代码解析
      • 初始化与配置
      • MQTT消息处理
      • 发布传感器数据
    • 6 MQTT话题TOPIC设计
    • 7 EMQX的优势在IoT项目中的体现
    • 8 MQTT通信流程
    • 9 应用场景
    • 10 代码原文

1 项目概览

本项目实现了以下功能:

  • 通过ESP32读取光敏传感器的光照强度和倾斜传感器的状态
  • 使用MQTT协议将传感器数据发布到服务器
  • 接收服务器的控制命令,远程控制ESP32上的LED
    在这里插入图片描述

2 硬件组成

  • ESP32开发板:具备WiFi功能的微控制器
  • 光敏传感器:连接到ESP32的模拟引脚(GPIO34)
  • 倾斜传感器:连接到ESP32的数字引脚(GPIO5)
  • LED指示灯:使用ESP32的内置LED(GPIO2)

3 MQTT协议解析

MQTT协议简介

MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,专为资源受限设备和低带宽、高延迟网络设计。它具有以下特点:

  1. 轻量级:最小化网络带宽占用,适合IoT设备
  2. 发布/订阅模式:解耦消息发送者和接收者
  3. 可靠性:提供三种服务质量等级(QoS)
  4. 简单实现:易于集成到各种设备和平台

MQTT核心概念

  1. 发布者(Publisher):发送消息的客户端
  2. 订阅者(Subscriber):接收消息的客户端
  3. 代理(Broker):中心服务器,负责接收、过滤和分发消息
  4. 主题(Topic):消息的路由路径,采用层级结构
  5. 服务质量(QoS):消息传递的可靠性保证

本项目中的MQTT应用

在代码中,ESP32作为MQTT客户端既是发布者也是订阅者:

发布者角色

  • 将光敏传感器值发布到aovalue主题
  • 将倾斜传感器状态发布到dovalue主题

订阅者角色

  • 订阅switch主题接收LED控制命令

4 MQTT Broker选择

EMQX Broker

在本项目中,我们使用了安装在本地服务器(192.168.3.32)上的EMQX Broker。

特点

  • 开源、高性能的分布式MQTT消息服务器
  • 支持百万级并发连接
  • 完全支持MQTT 5.0和3.1.1协议
  • 提供丰富的插件系统和扩展能力
  • 内置WebSocket支持,便于Web应用集成
  • 提供详细的监控指标和可视化管理界面

安装方法

# Docker安装(推荐)
docker pull emqx/emqx:latest
docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx/emqx:latest# Debian/Ubuntu
curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash
sudo apt-get install emqx# CentOS/RHEL
curl -s https://assets.emqx.com/scripts/install-emqx-rpm.sh | sudo bash
sudo yum install emqx

基本配置
通过访问http://localhost:18083(默认用户名和密码:admin/public)进行管理界面配置。

其他常用MQTT Broker

Mosquitto/HiveMQ/AWS IoT Cor

5 代码解析

初始化与配置

const char* mqtt_server = "192.168.*.32";  // MQTT服务器IP地址// 定义引脚
const int ledPin = 2;        // LED引脚
const int lightSensorPin = 34; // 光敏传感器的模拟引脚
const int tiltSensorPin = 5;  // 倾斜传感器的数字引脚WiFiClient espClient;                // 创建WiFi客户端
PubSubClient client(espClient);      // 创建MQTT客户端

MQTT消息处理

void callback(char* topic, byte* payload, unsigned int length) {// 将接收到的消息转换为字符串String message;for (int i = 0; i < length; i++) {message += (char)payload[i];}// 判断主题是否为"switch"if (String(topic) == "switch") {// 根据消息内容控制LEDif (message == "ON") {digitalWrite(ledPin, HIGH);} else if (message == "OFF") {digitalWrite(ledPin, LOW);}}
}

发布传感器数据

// 每隔指定时间发布一次数据
if (now - lastMsg > publishInterval) {lastMsg = now;// 读取光敏传感器模拟值int lightValue = analogRead(lightSensorPin);// 读取倾斜传感器数字状态int tiltState = digitalRead(tiltSensorPin);// 发布光敏数据char lightStr[10];sprintf(lightStr, "%d", lightValue);client.publish("aovalue", lightStr);// 发布倾斜状态char tiltStr[2];sprintf(tiltStr, "%d", tiltState);client.publish("dovalue", tiltStr);
}

6 MQTT话题TOPIC设计

本项目使用了三个TOPIC:

  1. aovalue:模拟输出值(Analog Output Value)

    • 用于发布光敏传感器的模拟值
    • 数值范围:0-4095
  2. dovalue:数字输出值(Digital Output Value)

    • 用于发布倾斜传感器的状态
    • 数值:0或1
  3. switch:控制指令

    • 用于接收LED控制命令
    • 有效值:“ON"或"OFF”

这种主题设计简单明确,适合小型项目。在大型项目中,EMQX支持更复杂的主题结构和通配符订阅,如:

device/{deviceID}/{sensorType}/value
device/{deviceID}/control/{action}

7 EMQX的优势在IoT项目中的体现

  1. 高性能:EMQX可处理大量并发连接,适合规模化IoT部署
  2. 规则引擎:内置数据处理、转发和持久化能力
  3. 认证与授权:提供多种认证方式,增强安全性
  4. 丰富的监控:详细的实时监控指标,便于系统管理
  5. 集群能力:支持水平扩展,满足业务增长需求
  6. 多协议支持:除MQTT外,还支持CoAP、LwM2M等IoT协议
  7. 数据集成:可轻松集成Kafka、数据库等后端系统

8 MQTT通信流程

  1. 连接阶段

    • ESP32连接到WiFi网络
    • 连接到EMQX Broker
    • 订阅"switch"主题
  2. 发布阶段

    • 定期读取传感器数据
    • 将数据发布到相应主题
  3. 订阅处理

    • 接收"switch"主题的消息
    • 根据消息内容控制LED状态
  4. 断线重连

    • 监测MQTT连接状态
    • 断线时自动重连并恢复订阅

9 应用场景

这个简单项目的基础技术可扩展到多种应用场景:

  1. 环境监测:监测光照变化,可用于智能农业
  2. 安全监控:检测设备是否被移动或倾斜
  3. 家居自动化:基于环境变化自动控制设备
  4. 数据收集:将传感器数据集中存储分析

10 代码原文

#include <WiFi.h>           // ESP32的WiFi库
#include <PubSubClient.h>   // MQTT客户端库const char* ssid = "601B";            // WIFI名称
const char* password = "12345678";    // WIFI密码
const char* mqtt_server = "192.168.3.32";  // MQTT服务器IP地址// 定义引脚
const int ledPin = 2;        // LED引脚,ESP32内置LED通常在引脚2
const int lightSensorPin = 34; // 光敏传感器的模拟输入引脚,根据实际连接调整
const int tiltSensorPin = 5;  // 倾斜传感器的数字输入引脚,根据实际连接调整// 设置上次发布的时间
unsigned long lastMsg = 0;
const int publishInterval = 1000;  // 发布频率(毫秒)WiFiClient espClient;                // 创建WiFi客户端对象
PubSubClient client(espClient);      // 创建MQTT客户端对象// 函数用于连接WiFi网络
void setup_wifi() {delay(10);Serial.println();Serial.print("WIFI连接到: ");Serial.println(ssid);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}randomSeed(micros());Serial.println("");Serial.println("WIFI连接成功");Serial.println("IP地址: ");Serial.println(WiFi.localIP());
}// 回调函数,当接收到订阅主题的消息时调用
void callback(char* topic, byte* payload, unsigned int length) {Serial.print("收到消息 [");Serial.print(topic);Serial.print("] ");// 将接收到的消息转换为字符串String message;for (int i = 0; i < length; i++) {message += (char)payload[i];}Serial.println(message);// 判断主题是否为"switch"if (String(topic) == "switch") {// 如果消息内容为"ON",打开LEDif (message == "ON") {digitalWrite(ledPin, HIGH);Serial.println("LED 已打开");} // 如果消息内容为"OFF",关闭LEDelse if (message == "OFF") {digitalWrite(ledPin, LOW);Serial.println("LED 已关闭");}}
}// 函数用于连接或重新连接到MQTT服务器
void reconnect() {while (!client.connected()) {Serial.println("正在尝试MQTT连接...");// 创建随机客户端IDString clientId = "ESP32Client-";clientId += String(random(0xffff), HEX);// 尝试连接if (client.connect(clientId.c_str())) {Serial.println("已连接到MQTT服务器");// 成功连接后,订阅"switch"主题以控制LEDclient.subscribe("switch");Serial.println("已订阅主题: switch");} else {Serial.print("连接失败, 错误码=");Serial.print(client.state());Serial.println(",5秒后重试");delay(5000);}}
}void setup() { // 初始化串口通信Serial.begin(115200);// 设置引脚模式pinMode(ledPin, OUTPUT);pinMode(tiltSensorPin, INPUT);// 初始状态:LED关闭digitalWrite(ledPin, LOW);// 连接WiFisetup_wifi();// 设置MQTT服务器和回调函数client.setServer(mqtt_server, 1883);client.setCallback(callback);
}void loop() {// 如果与MQTT服务器断开连接,重新连接if (!client.connected()) {reconnect();}// 处理MQTT消息client.loop();// 当前时间unsigned long now = millis();// 每隔指定时间发布一次数据if (now - lastMsg > publishInterval) {lastMsg = now;// 读取光敏传感器数值(模拟值)int lightValue = analogRead(lightSensorPin);// 读取倾斜传感器状态(数字值)int tiltState = digitalRead(tiltSensorPin);// 将光敏传感器数值转换为字符串并发布char lightStr[10];sprintf(lightStr, "%d", lightValue);client.publish("aovalue", lightStr);Serial.print("发布光敏数据: ");Serial.println(lightValue);// 将倾斜传感器状态转换为字符串并发布char tiltStr[2];sprintf(tiltStr, "%d", tiltState);client.publish("dovalue", tiltStr);Serial.print("发布倾斜状态: ");Serial.println(tiltState);}
}

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

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

相关文章

[特殊字符]《Curve DAO 系统学习目录》

本教程旨在系统学习 Curve DAO 项目的整体架构、核心机制、合约设计、治理逻辑与代币经济等内容&#xff0c;帮助开发者全面理解其设计理念及运作方式。 目录总览&#xff1a; 1. Curve 项目概览 • 1.1 Curve 是什么&#xff1f;主要解决什么问题&#xff1f; • 1.2 与其他…

每天一篇目标检测文献(六)——Part One

今天看的是《Object Detection with Deep Learning: A Review》 目录 一、摘要 1.1 原文 1.2 翻译 二、介绍 2.1 信息区域选择 2.2 特征提取 2.3 分类 三、深度学习的简要回顾 3.1 历史、诞生、衰落和繁荣 3.2 CNN架构和优势 一、摘要 1.1 原文 Due to object dete…

Arthas线上问题诊断器

Arthas是Alibaba开源的java诊断工具 解决问题 这个类从哪个jar 包加载的&#xff1f;为什么会报各种相关的Exception&#xff1f; 遇到问题无法在线上debug&#xff0c;不能直通过加载日志再重新发布 有什么办法可以监控到JVM的实时运行状态&#xff1f; …

[Lc5_dfs+floodfill] 简介 | 图像渲染 | 岛屿数量

目录 0.floodfill算法简介 1.图像渲染 题解 2.岛屿数量 题解 之前我们在 bfs 中有介绍过[Lc15_bfsfloodfill] 图像渲染 | 岛屿数量 | 岛屿的最大面积 | 被围绕的区域&#xff0c;现在我们来看看 dfs 又是如何解决的呢 0.floodfill算法简介 floodfill算法又叫洪水灌溉或者…

JVM类加载器详解

文章目录 1.类与类加载器2.类加载器加载规则3.JVM 中内置的三个重要类加载器为什么 获取到 ClassLoader 为null就是 BootstrapClassLoader 加载的呢&#xff1f; 4.自定义类加载器什么时候需要自定义类加载器代码示例 5.双亲委派模式类与类加载器双亲委派模型双亲委派模型的执行…

Chapters 15 16:What Is Architecture?Independence_《clean architecture》notes

What Is Architecture?&Independence **Chapter 15: What Is Architecture?****Key Concepts**:**Code Example: Layered Architecture**: **Chapter 16: Independence****Key Concepts**:**Code Example: Dependency Inversion & Interfaces**: **Combined Example:…

【SPP】RFCOMM 层在SPP中互操作性要求深度解析

蓝牙串口协议&#xff08;SPP&#xff09;通过 RFCOMM 协议实现 RS232 串口仿真&#xff0c;其互操作性是设备互联的关键。本文基于蓝牙核心规范&#xff0c;深度解析 RFCOMM 层的能力矩阵、信号处理、流控机制及实战开发&#xff0c;结合状态机、流程图和代码示例&#xff0c;…

阻塞式IO与非阻塞IO的区别

阻塞式IO与非阻塞IO的区别 1. 阻塞式IO (Blocking I/O) 定义 当程序发起一个I/O操作&#xff08;如读取文件、网络数据&#xff09;时&#xff0c;进程会被挂起&#xff08;阻塞&#xff09;&#xff0c;直到操作完成或超时才会继续执行后续代码。在此期间&#xff0c;程序无法…

Gossip协议:分布式系统中的“八卦”传播艺术

目录 一、 什么是Gossip协议&#xff1f;二、 Gossip协议的应用 &#x1f4a1;三、 Gossip协议消息传播模式详解 &#x1f4da;四、 Gossip协议的优缺点五、 总结&#xff1a; &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢博主的讲解方式&…

【C++初阶】----模板初阶

1.泛型函数 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础。 2.函数模板 2.1函数模板的概念 函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型…

git-- github的使用--账户和本地连接

以下指令在git 执行bash 流程&#xff1a;先看有没有密钥&#xff1b; 没有的话&#xff0c;在电脑生成密钥对&#xff0c;公钥复制到github&#xff1b; 要想使用https&#xff0c;配置令牌&#xff0c;注意令牌有期限问题&#xff0c;连接不了有可能是期限问题 一个电脑对…

OTN(Optical Transport Network)详解

OTN&#xff08;光传送网&#xff09;是一种基于**波分复用&#xff08;WDM&#xff09;**的大容量光传输技术&#xff0c;结合了SDH的运维管理优势和WDM的高带宽特性&#xff0c;广泛应用于骨干网、城域核心层及数据中心互联&#xff08;DCI&#xff09;。 1. OTN 的基本概念 …

Python 中列表(List)、元组(Tuple)、集合(Set)和字典(Dict)四大数据结构的完整对比

以下是 Python 中列表&#xff08;List&#xff09;、元组&#xff08;Tuple&#xff09;、集合&#xff08;Set&#xff09;和字典&#xff08;Dict&#xff09;四大数据结构的完整对比分析&#xff0c;结合了核心特性、操作方式和应用场景的深度总结&#xff1a; 一、核心特性…

Angular由一个bug说起之十五:自定义基于Overlay的Tooltip

背景 工具提示&#xff08;tooltip&#xff09;是一个常见的 UI 组件&#xff0c;用于在用户与页面元素交互时提供额外的信息。由于angular/material/tooltip的matTooltip只能显示纯文本&#xff0c;所以我们可以通过自定义Directive来实现一个灵活且功能丰富的tooltip Overlay…

软件工程面试题(十五)

1、servlet 创建过程以及ruquest,response,session的生命周期? Servlet的创建过程: 第一步 public class AAA extends HttpServlet{ 实现对应的doxxx方法 } 第二步: 在web.xml中配置 <servlet> <servlet-name></servlet-name> <servlet-c…

搭建QNX Software Center的Docker环境

背景 本人使用 Ubuntu Server 22.04 服务器&#xff0c;所以没有图形界面&#xff0c;而 QNX Software Center 需要图形界面。为了保证服务器环境的整理&#xff0c;计划使用Docker部署QNX Software Center 一瓶安装图形界面。本方既是实现方案的记录。 资源 Dockerfile&…

C#/.NET/.NET Core技术前沿周刊 | 第 31 期(2025年3.17-3.23)

前言 C#/.NET/.NET Core技术前沿周刊&#xff0c;你的每周技术指南针&#xff01;记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿&#xff0c;助力技术成长与视野拓宽。 欢迎投稿、推荐…

粘包问题解决方案

粘包问题详解&#xff1a;TCP协议中的常见问题及Go语言解决方案 一、什么是粘包问题&#xff1f; 粘包问题是指在TCP通信中&#xff0c;发送方发送的多个独立消息在接收方被合并成一个消息接收的现象。换句话说&#xff0c;发送方发送的多条消息在接收方被“粘”在一起&#…

vue:突然发现onok无法使用

const that this;this.$confirm({title: "修改商品提示",content: "如果当前商品存在于商品活动库&#xff0c;则在商品活动库的状态会下架",onOk: function () {that.submitForm();}}); 突然发现 this.$confirm无法进入onok 最终发现是主题冲突&#x…

redis hashtable 的sizemask理解

在 Redis 的哈希表实现中&#xff0c;index hash & dict->ht[0].sizemask 是计算键值对应存储位置的核心操作。这个操作看起来简单&#xff0c;但背后涉及哈希表的内存布局和性能优化策略。我们通过以下步骤逐步解析其原理&#xff1a; 一、哈希表的设计目标 快速定位…