ESP32蓝牙BLE连接米家温湿度计

ESP32蓝牙BLE连接米家温湿度计

简介

最近在学习低功耗蓝牙BLE(Bluetooth Low Energy),刚好手里有个米家蓝牙温湿度计连接一下,在网上搜索了下相关资料,结合ESP32的BLE的历程完成数据获取以及对温湿度解析的工作。

需要准备的东西

  • 米家蓝牙温湿度计
  • BLE调试助手 or 谷雨蓝牙调试助手(小程序) or nRF Connect
  • ESP32开发环境

软件调试

  1. 首先我们使用谷雨蓝牙调试助手,小程序版本 搜索周边的蓝牙信号,找到名称为LWSD03MMC 的蓝牙
  2. 找到一个UUID为 EBE0CCB0打头 7DA3A6结尾 的服务
  3. 在该服务下找到UUID为EBE0CCC1打头 7DA3A6结尾的属性 权限是可读可通知
  4. 点击监听或者读取 将字符选择为16进制 等待监听一次数据

在这里插入图片描述

在这里插入图片描述

数据解析

我们收到的数据格式如下

440A357C0B

将其分开

0x44 0x0A 0x35 0x7C 0x0B

其中数据的格式是以大端模式存储的,即高位放低地址,高位放低地址 所以0x44 0x0a表示的温度信息就是 0x0a44

将其转换成10进制就是2628,对应的就是26.28℃,和表现的相差不大(更新时间的缘故),因此对于上面的数据 我们可以对他进行解析

0x0a44->温度数据->2628(DEC)->26.28℃
0x35->湿度数据->53(DEC)->53%
0x0B7C->电压数据->2940(DEC)->2.94V

在这里插入图片描述

代码实现

经过上述的讲解 我们已经可以简单的对数据进行解析,下面我们将要用ESP32的蓝牙gatt_client例程完成对蓝牙数据的解析,因为蓝牙温湿度计作为数据服务的提供者,所以是SERVER端,我们作为数据的接收者,所以是client的例程

修改查找的名称

在原本的例程中 上电会扫描周围的额蓝牙设备,直到扫描到指定名称的蓝牙设备才会停止,所以我们需要修改设备名称为LYWSD03MMC

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

修改需要连接的服务和属性

在代码中 是对BLE的属性做了过滤,这里我们填写上面调试得到的蓝牙UUID,注意这里是大端模式,所以上面的EB打头A6结尾就要变成A6打头EB结尾

在这里插入图片描述

添加解析数据的代码

我们在NOTIFY_EVT时间的处理中添加得到的notify信息,传入参数为收到的通知的值以及数据的长度

在这里插入图片描述

解析函数

解析函数如下所示,我们定义了一个数组,复制了传进来的数据,然后根据上面讲的大端模式,组成16位温度数据 8位湿度数据,16为电压数据 解析 让然后打印

//定义的存储数据的结构体
struct MI_SENSOR_DATA_t
{
    float temperature;
    uint8_t huminity;
    float batVoltage;
};

struct MI_SENSOR_DATA_t Mi_Sensor_data;


static void Deal_MISensor(uint8_t *rawdata,uint8_t rawdata_len)
{
    uint8_t rawdata_len_copy = rawdata_len;
    uint8_t rawdata_copy[rawdata_len_copy+2];

    uint16_t temp=0;

    memcpy(rawdata_copy, rawdata, rawdata_len_copy);
    ESP_LOGI(GATTC_My_TAG,"REC data len:%d ",rawdata_len_copy);
    esp_log_buffer_hex(GATTC_My_TAG, (unsigned char *)rawdata_copy, rawdata_len_copy);
    /*42 0a 3f 2a 0b*/
    /*0x0a42 ->温度 0x3f->湿度 0x0b2a 电量*/
    //获取温度
    temp = rawdata_copy[1];
    temp = (temp << 8)+rawdata_copy[0];
    Mi_Sensor_data.temperature=temp/100.0;
    //获取湿度
    temp &= 0x00;
    temp = rawdata_copy[2];
    Mi_Sensor_data.huminity = temp;

    //获取电池电量
    temp &= 0x00;
    temp = rawdata_copy[4];
    temp = (temp << 8)+rawdata_copy[3];
    Mi_Sensor_data.batVoltage = temp/1000.0;

    ESP_LOGI(GATTC_My_TAG,"温度:%.2f C 湿度:%d 电量:%.3f V \r\n",
            Mi_Sensor_data.temperature,
            Mi_Sensor_data.huminity,
            Mi_Sensor_data.batVoltage);
}

上电演示

在这里插入图片描述

在这里插入图片描述

提示

运行了一会儿,10分钟左右,发现电压从2.929掉到了2.885 掉电还是挺快的 如果我们更新时间比较快的话是比较耗电的,这也就是说为什么手机端的数据一个小时更新一次的原因,因此我们可以不再noitify属性,而是主动去read属性 或者设备只在需要的时候去搜索 连接 notify然后断掉,具体到的玩法后续再开发
在这里插入图片描述
在这里插入图片描述

### ESP32蓝牙开发配置使用教程 #### 一、准备工作 为了实现ESP32作为低功耗蓝牙设备的功能,需先安装并设置好VSCode及其插件——Espressif IDF。该集成开发环境支持多种操作系统平台,在完成安装后还需下载对应的工具链以及SDK管理器来获取必要的库文件和支持包[^1]。 #### 二、创建项目与初始化BLE功能 通过命令行或者IDE界面新建一个基于ESP-IDF框架的应用程序工程;接着修改`main`目录下的源码文件以调用API接口开启Bluetooth模块,并注册回调处理函数用于监听状态变化事件(比如连接建立/断开)。对于具体操作而言,则涉及到如下几个方面: - 初始化LE控制器和主机堆栈; - 设置广告参数及载荷内容以便于被其他装置发现; - 构建服务定义和服务特性描述符结构体数组; - 注册GATT应用层协议栈事件处理器。 ```c #include "nvs_flash.h" #include "esp_bt.h" #include "esp_gap_ble_api.h" // ... 更多头文件省略 ... void app_main(void){ nvs_flash_init(); esp_bluedroid_enable(); // 启动bluetooth stack /* 广告数据 */ uint8_t adv_data[]={ 0x02,0x01,0x06, 0x0A,0x09,'E','S','P','-','B','L','E' }; /* 设定广播模式为不可连接的无定向广播 */ esp_ble_adv_params_t param={.adv_int_min=0x20,.adv_int_max=0x40}; esp_ble_gap_start_advertising(&param); } ``` 上述代码片段展示了如何启动蓝牙子系统并开始发送包含自定义名称在内的扫描响应报文。 #### 三、构建GATT Server端逻辑 按照官方文档指导编写相应的C/C++语言脚本,其中涉及到了特征值读写权限设定、通知机制启用等功能点的设计思路。这里给出一段简化版的服务声明语句供参考学习之用: ```c static const struct ble_gatt_svc_def gatt_svr_svcs[] = { [IDX_SVC_HDLS]={ .type=BLE_GATT_SVC_TYPE_PRIMARY, .uuid=&svc_uuid, .characteristics=(struct ble_gatts_chr_def[]){ { // Characteristic Declaration Handle .uuid=&chr_uuid, .access_cb=access_function_ptr, .val_handle_idx=IDX_CHAR_VAL, .flags=CHR_F_READ|CHR_F_WRITE|CHR_F_NOTIFY, }, 0,// End of characteristics list. } }, 0 // End of services list. }; /* 定义访问控制方法 */ int access_function(struct os_mbuf **om, void *arg) {/*...*/} ``` 以上示例说明了怎样向外界暴露可交互资源的同时也指定了针对这些属性的操作行为约束条件。 #### 四、实现业务流程联动效果 最后一步就是把之前准备好的硬件电路同软件算法结合起来达成预期目标啦~即每当检测到有客户端成功接入时就点亮板载指示灯,反之则关闭它。这部分可以通过GPIO引脚编程轻松搞定哦! ```c #define LED_PIN GPIO_NUM_2 extern void led_onoff(bool on); static void gap_event_handler(esp_gap_ble_cb_event_t event,void* param){ switch(event){ case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:{ printf("Advertising started.\r\n"); break; } case ESP_GAP_BLE_CONN_OPEN_EVT:{ led_onoff(true); printf("Connected\r\n"); break; } case ESP_GAP_BLE_CONN_CLOSE_EVT:{ led_onoff(false); printf("Disconnected\r\n"); break; } default:break; } } ``` 这段摘录体现了典型的事件驱动型应用程序架构特点之一:利用异步消息队列传递外部输入信号给内部状态机进行解析判断从而触发相应动作执行序列。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值