ESP32 蓝牙网关实践:BLE 设备数据采集与 MQTT 云平台发布(附代码示例)

news2024/11/26 8:29:53

摘要: 本文详细介绍了如何使用 ESP32 构建强大的蓝牙网关,实现蓝牙设备与 Wi-Fi/互联网之间的无缝连接和数据桥接。文章涵盖了连接和桥接功能、数据处理和分析能力,并提供了详细的代码示例和 Mermaid 生成的图表,助您轻松构建自己的蓝牙网关解决方案。

一、 引言

随着物联网 (IoT) 的快速发展,蓝牙技术凭借其低功耗、低成本和易用性,在连接各种传感器、设备和智能家居产品方面发挥着至关重要的作用。然而,蓝牙设备通常通信范围有限,且无法直接连接互联网。ESP32 是一款功能强大的微控制器,集成了 Wi-Fi 和蓝牙功能,使其成为构建蓝牙网关的理想选择,可以将蓝牙设备连接到互联网,实现远程监控和控制。

二、 ESP32 蓝牙网关功能

ESP32 蓝牙网关可以实现以下关键功能:

1. 连接和桥接:

  • 蓝牙到 Wi-Fi/互联网桥接: ESP32 可以连接到蓝牙传感器、设备或信标,并将收集的数据通过 Wi-Fi 传输到云平台或本地服务器,实现远程监控和控制。
  • 蓝牙到蓝牙桥接: 扩展蓝牙设备的通信范围,例如连接位于不同房间或楼层的蓝牙设备。
  • 支持多种蓝牙协议: ESP32 支持多种蓝牙协议,包括 Bluetooth Classic (SPP, HID) 和 Bluetooth Low Energy (BLE),以连接各种类型的蓝牙设备。

2. 数据处理和分析:

  • 数据过滤和聚合: ESP32 可以对从蓝牙设备收集的数据进行预处理,例如过滤噪声数据或聚合多个传感器的数据,以减少网络负载并提高效率。
  • 本地数据存储: 使用 SD 卡或外部存储器,ESP32 可以存储从蓝牙设备收集的数据,以便在网络连接不可用时进行缓存或离线分析。
  • 边缘计算: ESP32 可以执行简单的计算任务,例如数据转换、阈值警报和趋势分析,从而减少数据传输量并提高响应速度。

三、 系统架构

下图展示了 ESP32 蓝牙网关的典型系统架构:

架构说明:

  • 多个蓝牙设备(例如传感器、智能灯泡、智能门锁)通过蓝牙连接到 ESP32 蓝牙网关。
  • ESP32 蓝牙网关通过 Wi-Fi 或以太网连接到互联网或本地服务器。
  • ESP32 网关可以将数据转发到云平台或本地服务器,也可以在本地处理数据并执行边缘计算任务。

四、 代码示例

以下是一个简单的 ESP32 蓝牙网关代码示例,演示了如何使用 BLE 连接到蓝牙传感器并通过 Wi-Fi 将数据发送到 MQTT broker:

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <WiFi.h>
#include <PubSubClient.h>

// 设置 Wi-Fi 和 MQTT broker 信息
const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";
const char* mqtt_server = "your_mqtt_broker_ip";
const int mqtt_port = 1883;

// 设置蓝牙服务和特征 UUID
static BLEUUID serviceUUID("your_service_uuid");
static BLEUUID characteristicUUID("your_characteristic_uuid");

// 创建 BLE 和 MQTT 客户端
BLEAdvertisedDevice* myDevice;
WiFiClient espClient;
PubSubClient client(espClient);

// 连接到 Wi-Fi
void setupWifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected!");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// 连接到 MQTT broker
void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client")) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

// 扫描蓝牙设备
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
    } 
  }
};

// 连接到蓝牙设备
bool connectToSensor() {
  BLEClient*  pClient  = BLEDevice::createClient();
  Serial.println(" - Created client");

  // 连接到 GATT 服务器
  Serial.println(" - Connecting to server...");
  if (!pClient->connect(myDevice)) {
    Serial.println(" - Failed to connect to server");
    return false;
  }
  Serial.println(" - Connected to server");

  // 获取服务
  BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
  if (pRemoteService == nullptr) {
    Serial.print(" - Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    return false;
  }
  Serial.println(" - Found our service");

  // 获取特征
  BLERemoteCharacteristic* pRemoteCharacteristic = pRemoteService->getCharacteristic(characteristicUUID);
  if (pRemoteCharacteristic == nullptr) {
    Serial.print(" - Failed to find our characteristic UUID: ");
    Serial.println(characteristicUUID.toString().c_str());
    return false;
  }
  Serial.println(" - Found our characteristic");

  // 读取特征值
  std::string value = pRemoteCharacteristic->readValue();
  Serial.print(" - The characteristic value was: ");
  Serial.println(value.c_str());

  // 发送数据到 MQTT broker
  if (client.connected()) {
    client.publish("sensor/data", value.c_str());
  }

  return true;
}

void setup() {
  Serial.begin(115200);
  setupWifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);

  // 初始化蓝牙
  BLEDevice::init("ESP32_Gateway");
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setInterval(2000);
  pBLEScan->start(60, false);
}

void loop() {
  if (!client.connected())
{
    reconnect();
  }
  client.loop();

  if (myDevice) {
    if (connectToSensor()) {
      Serial.println("Data sent to MQTT broker!");
    } else {
      Serial.println("Failed to connect to sensor!");
    }
    myDevice = nullptr;
    delay(5000); // 等待 5 秒后再次扫描
    BLEDevice::getScan()->start(60, false);
  }
}

代码说明:

  1. 设置 Wi-Fi 和 MQTT broker 信息: 替换 ssidpasswordmqtt_server 和 mqtt_port 为您的实际网络和 MQTT broker 信息。
  2. 设置蓝牙服务和特征 UUID: 替换 serviceUUID 和 characteristicUUID 为您要连接的蓝牙设备的服务和特征 UUID。
  3. 扫描蓝牙设备: 使用 BLEScan 类扫描附近的蓝牙设备,并查找与指定服务 UUID 匹配的设备。
  4. 连接到蓝牙设备: 使用 BLEClient 类连接到找到的蓝牙设备,并获取指定特征的值。
  5. 发送数据到 MQTT broker: 使用 PubSubClient 库将获取的蓝牙传感器数据发布到指定的 MQTT 主题。

五、 总结

本文介绍了如何使用 ESP32 构建蓝牙网关,实现蓝牙设备与 Wi-Fi/互联网之间的连接和数据桥接。通过结合 ESP32 强大的硬件功能和灵活的软件库,您可以轻松构建自定义的蓝牙网关解决方案,满足各种物联网应用的需求。

注意:

  • 本文提供的代码示例仅供参考,您需要根据实际需求进行修改和完善。
  • 在实际应用中,您可能需要考虑安全性、功耗优化和数据可靠性等方面的问题。

 

 

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

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

相关文章

仿写Spring IOC

文章目录 IOC思路手写代码思路一些杂七杂八&#xff08;可跳过&#xff09; IOC思路 手写代码思路 手写代码的思路: 自定义一个MyAnnotationConfigApplicationContext&#xff0c;构造器中传入要扫描的包。获取这个包下的所有类。遍历这些类&#xff0c;找出添加了Component注…

Ubuntu 安装CGAL

一、什么是CGAL CGAL&#xff08;Computational Geometry Algorithms Library&#xff09;是一个广泛使用的开源库&#xff0c;主要用于计算几何算法的实现。该库提供了一系列高效、可靠和易于使用的几何算法和数据结构&#xff0c;适用于各种应用领域。以下是 CGAL 的主要功能…

ubuntu下载Nginx

一、Nginx下载安装&#xff08;Ubuntu系统&#xff09; 1.nginx下载 sudo apt-get install nginx2.nginx启动 启动命令 sudo nginx重新编译(每次更改完nginx配置文件后运行&#xff09;&#xff1a; sudo nginx -s reload3.测试nginx是否启动成功 打开浏览器访问本机80端口…

09.QT控件:按钮类控件

1. QPushButton 在QT中使⽤ QPushButton 表⽰⼀个按钮。QPushButton 继承⾃ QAbstractButton&#xff0c;这个类是⼀个抽象类&#xff0c;是其他按钮的⽗类。 &#xff08;1&#xff09;QAbstractButton 中&#xff0c;和 QPushButton 相关性较⼤的属性&#xff1a; &#xf…

独立开发者系列(21)——HTTP协议的使用

作为网络访问的必备知识点&#xff0c;http协议&#xff0c;我们已经知道http协议属于tcp的一种&#xff0c;而且一般是用于网络通讯的&#xff0c;但是本身http协议本身包含的内容也很多&#xff0c;正是因为有这种协议&#xff0c;前后端和各种硬件接口/服务器接口/前端&…

OpenGL笔记七之顶点数据绘制命令和绘制模式

OpenGL笔记七之顶点数据绘制命令和绘制模式 —— 2024-07-07 杭州 下午 总结自bilibili赵新政老师的教程 文章目录 OpenGL笔记七之顶点数据绘制命令和绘制模式1.OpenGL版本号更改和编译更改2.GL_TRIANGLES模式绘制一个三角形、支持NFC坐标随窗口缩放2.1.三个点2.2.四个点从0号…

缓存-缓存的使用与基本详解

1.缓存使用 为了系统性能的提升&#xff0c;我们一般都会将部分数据放入缓存中&#xff0c;加速访问。而db承担数据落盘工作。 哪些数据适合放入缓存&#xff1f; 即时性、数据一致性要求不高的访问量大且更新频率不高的数据&#xff08;读多&#xff0c;写少&#xff09; …

【数据库】MySQL基本操作语句

目录 一、SQL语句 1.1 SQL分类 1.2 SQL语言规范 1.3 数据库对象与命名 1.3.1 数据库的组件(对象)&#xff1a; 1.3.2 命名规则&#xff1a; 1.4 SQL语句分类 二、基本命令 2.1 查看帮助信息 2.2 查看支持的字符集 2.3 查看默认使用的字符集 2.4 修改默认字符集 2.5…

SwiftData 模型对象的多个实例在 SwiftUI 中不能及时同步的解决

概览 我们已经知道,用 CoreData 在背后默默支持的 SwiftUI 视图在使用 @FetchRequest 来查询托管对象集合时,若查询结果中的托管对象在别处被改变将不会在 FetchedResults 中得到及时的刷新。 那么这一“囧境”在 SwiftData 里是否也会“卷土重来”呢?空说无益,就让我们在…

将 KNX 接入 Home Assistant 之四 功能测试

一&#xff1a;测试标准的KNX网关功能 测试软件识别是否正常 可以看到再ETS6和ETS5上都能正常识别 测试数据收发 可以正常发送数据 测试配置设备参数&#xff08;下载配置&#xff09; 可以看出&#xff0c;在ETS5上是可以正常下载参数的 但是 ETS6下载是失败的&#xff…

KDP数据分析实战:从0到1完成数据实时采集处理到可视化

智领云自主研发的开源轻量级Kubernetes数据平台&#xff0c;即Kubernetes Data Platform (简称KDP)&#xff0c;能够为用户提供在Kubernetes上的一站式云原生数据集成与开发平台。在最新的v1.1.0版本中&#xff0c;用户可借助 KDP 平台上开箱即用的 Airflow、AirByte、Flink、K…

JCR一区 | Matlab实现GAF-PCNN-MATT、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断

JJCR一区 | Matlab实现GAF-PCNN-MATT、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断 目录 JJCR一区 | Matlab实现GAF-PCNN-MATT、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断分类效果格拉姆矩阵图GAF-PCNN-MATTGASF-CNNGADF-CNN 基本介绍程序设计参考资料 分…

make工具

1、什么是make&#xff1f; make是个命令&#xff0c;是个可执行程序&#xff0c;是个工具&#xff0c;用来解析Makefile文件的命令&#xff0c;这个命令存放在/usr/bin/目录下 -rwxr-xr-x 1 root root 250K 2月 15 2022 make -rwxr-xr-x 1 root root 4.8K 2月 15 2022 ma…

图片高效管理神器,随机高度切割,一键生成灰色图片,个性化处理随心所欲

在数字化时代&#xff0c;图片已成为我们生活和工作中不可或缺的一部分。然而&#xff0c;面对海量的图片资源&#xff0c;如何高效管理、快速处理&#xff0c;成为了许多人头疼的问题。今天&#xff0c;我们为您带来了一款全新的图片高效管理神器_——首助编辑高手&#xff0c…

【全面介绍下如何使用Zoom视频会议软件!】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

Halcon 背景网格产品刮伤缺陷检测

* 关闭窗口 dev_close_window ()*关闭程序计数器,图形变量更新,窗口图形更新 dev_update_off ()*设置图像路径 Path : lcd/mura_defects_blur_*读取一张图像 read_image (Image, Path 01)*获取图像大小 get_image_size (Image, Width, Height)*创建一个新窗体 dev_open_window…

昇思25天学习打卡营第13天 | LLM原理和实践:文本解码原理--以MindNLP为例

1. 文本解码原理--以MindNLP为例 1.1 自回归语言模型 根据前文预测下一个单词 一个文本序列的概率分布可以分解为每个词基于其上文的条件概率的乘积 W 0 W_0 W0​:初始上下文单词序列 t t t: 时间步 当生成EOS标签时&#xff0c;停止生成。 MindNLP/huggingface Transfor…

NewStarCTF2023-Misc

目录 week1 CyberChefs Secret 机密图片 流量&#xff01;鲨鱼&#xff01; 压缩包们 空白格 隐秘的眼睛 week2 新建Word文档 永不消逝的电波 1-序章 base! WebShell的利用 Jvav week3 阳光开朗大男孩 大怨种 2-分析 键盘侠 滴滴滴 week4 通大残 Nmap 依…

Unity AssetsBundle 详解

文章目录 1.AssetBundle 概念2.AssetBundle 优势3.AssetBundle 特性4.AssetBundle 使用流程4.1 分组4.2 打包4.3 加载包4.4 加载资源4.5 卸载资源 5.AssetBundleManifest6.AssetBundle的内存占用7.AB包资源加密 1.AssetBundle 概念 AssetBundle又称AB包&#xff0c;是Unity提供…

Python视觉轨迹几何惯性单元超维计算结构算法

&#x1f3af;要点 &#x1f3af;视觉轨迹几何惯性单元超维计算结构算法 | &#x1f3af;超维计算结构视觉场景理解 | &#x1f3af;超维计算结构算法解瑞文矩阵 | &#x1f3af;超维矢量计算递归神经算法 &#x1f36a;语言内容分比 &#x1f347;Python蒙特卡罗惯性导航 蒙…