Tips:
抛砖引玉,本文记录ESP32学习过程中遇到的收获。如有不对的地方,欢迎指正。
目录
esp_ble_gap_set_security_param
1.前言
上次写了关于BLE用作服务端的文章,这次准备介绍一下用作HID设备的方法,经过博主对代码的研究发现,其实HID只是在服务端基础上只创建一个电池服务,多创建了一个HID的应用程序,然后就是添加了安全加密方面的东西,可以配对对端设备。详细内容下文介绍。
这次使用的是ESP32S3-DevKitC-1开发板,见下图:
2.实现功能
1.使用ESP32的BLE作为HID设备,向外广播,接受其他设备配对连接。
2.配置GPIO按键中断,用于控制手机音乐的播放暂停。
3.代码思路
1.以IDF的例程代码:BLE_HIDD_DEMO为基础开发,修改发送的操作指令。
2.配置GPIO中断模式,注册并编写中断服务函数。
4.HID设备简介
HID(Human Interface Device,人机接口设备)是一种设备类别,专门用于与用户进行交互,通常是输入设备。HID设备能够使用户通过物理操作(例如按键、触摸或移动)向计算机或其他电子设备传输信息。HID设备的设计使其能够通过标准的接口协议与计算机进行通信,通常不需要安装特定的驱动程序。
常见的HID设备包括:
键盘:用于输入文字和命令。
鼠标:用于移动光标并执行点击操作。
触摸板和触摸屏:用于通过触摸输入信息。
游戏控制器:例如游戏手柄、方向盘等。
扫描仪:例如条形码扫描器。
手写板:用于数字化手写输入。
HID的特点:
标准化协议:HID设备通常使用USB接口或蓝牙等无线方式与计算机或其他设备连接,使用HID协议进行通信。这意味着,设备可以即插即用(即无需额外驱动程序)。
设备灵活性:HID协议并不限制设备类型,任何符合HID标准的设备都可以作为HID设备。设备可以包含多种输入方式,如按键、触摸、传感器等。
简单易用:由于HID协议的标准化,用户使用这些设备时通常不需要额外配置,插入设备后,操作系统会自动识别并启用。
HID协议广泛应用于各种计算机和嵌入式系统中,特别是在用户交互和人机界面设计上。ESP32由于其拥有BLE可实现无线通信的功能,故也能作为一种HID设备。ESP32可以通过蓝牙协议模拟或充当一个HID设备,向其他设备(如智能手机、电脑、平板等)发送输入信号。简单来说,就是ESP32能够通过蓝牙与其他设备进行人机交互,模拟键盘、鼠标、游戏手柄等设备的功能。为了实现蓝牙HID设备功能,ESP32需要通过蓝牙协议栈(通常是ESP32的官方库或SDK提供的蓝牙HID功能)来模拟HID设备的行为。程序员可以通过特定的库(例如ESP-IDF中的hid_device库)来开发此类应用。
5.代码讲解
5.1 头文件、全局变量
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_hidd_prf_api.h"
#include "esp_bt_defs.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "driver/gpio.h"
#include "hid_dev.h"
#define HID_DEMO_TAG "HID_DEMO"
static uint16_t hid_conn_id = 0; // GATT连接ID
static bool sec_conn = false; // HID连接状态
//static bool send_volum_up = false; // 音量加发送状态
#define BUTTON_GPIO GPIO_NUM_9 // 按键GPIO
#define CHAR_DECLARATION_SIZE (sizeof(uint8_t)) // 特征声明大小
static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);//HID事件回调函数声明
#define HIDD_DEVICE_NAME "ESP32_HID" // HID设备名称
static uint8_t hidd_service_uuid128[] = {
/* LSB <--------------------------------------------------------------------------------> MSB */
//first uuid, 16bit, [12],[13] is the value服务UUID
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x12, 0x18, 0x00, 0x00,
};
static esp_ble_adv_data_t hidd_adv_data = { // HID广播数据
.set_scan_rsp = false, //是否是扫描响应数据:否
.include_name = true, //是否包含设备名称:是
.include_txpower = true, //是否包含发射功率:是
.min_interval = 0x0006, //广播最小连接间隔, Time = min_interval * 1.25 msec= 7.5ms
.max_interval = 0x0010, //广播最大连接间隔, Time = max_interval * 1.25 msec= 15 ms
.appearance = 0x03c0, //设备外观:键盘
.manufacturer_len = 0, // 制造商数据的长度(单位为字节)
.p_manufacturer_data = NULL, // 制造商数据
.service_data_len = 0, // 服务数据的长度(单位为字节)
.p_service_data = NULL, // 服务数据
.service_uuid_len = sizeof(hidd_service_uuid128), // 服务UUID长度
.p_service_uuid = hidd_service_uuid128, // 服务UUID
.flag = 0x6, //广播标志:可连接可扫描
};
static esp_ble_adv_params_t hidd_adv_params = { // HID广播参数
.adv_int_min = 0x20, //广播最小间隔, Time = min_interval * 0.625 msec= 20ms
.adv_int_max = 0x30, //广播最大间隔, Time = max_interval * 0.625 msec= 30ms
.adv_type = ADV_TYPE_IND, //广播类型:指示广播
.own_addr_type = BLE_ADDR_TYPE_PUBLIC, //广播地址类型:公共地址
//.peer_addr = //使用其他地址类型可能会需要设置这两个成员
//.peer_addr_type =
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
这部分主要是包含需要用到的头文件,定义一些蓝牙协议栈需要用到的全局变量,比如设备名称、UUID等,esp_ble_adv_data_t类型定义的是蓝牙广播数据的内容,它是用来向其他设备广播自身属性的数据,在其它设备扫描可连接蓝牙时看到的ESP32蓝牙的信息就是由这个类型定义的。esp_ble_adv_params_t类型定义的是广播参数,他决定了ESP32蓝牙的广播方式。
5.2 HID设备事件回调函数
static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
{
// 根据事件类型进行不同的处理
switch(event) {
case ESP_HIDD_EVENT_REG_FINISH: {
// 如果初始化完成
if (param->init_finish.state == ESP_HIDD_INIT_OK) {
//esp_bd_addr_t rand_addr = {0x04,0x11,0x11,0x11,0x11,0x05};
// 设置设备名称
esp_ble_gap_set_device_name(HIDD_DEVICE_NAME);
// 配置广播数据
esp_ble_gap_config_adv_data(&hidd_adv_data);
}
break;
}
case ESP_BAT_EVENT_REG: {
// TODO: 处理电池事件
break;
}
case ESP_HIDD_EVENT_DEINIT_FINISH:
// TODO: 处理HIDD事件
break;
case ESP_HIDD_EVENT_BLE_CONNECT: {
// TODO: 处理BLE连接事件
ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_CONNECT");
// 获取连接ID
hid_conn_id = param->connect.conn_id;
break;
}
case ESP_HIDD_EVENT_BLE_DISCONNECT: {
// TODO: 处理BLE断开连接事件
sec_conn = false;
ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_DISCONNECT");
// 开始广播
esp_ble_gap_start_advertising(&hidd_adv_params);
break;
}
case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT: {
// TODO: 处理BLE供应商报告写入事件
ESP_LOGI(HID_DEMO_TAG, "%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__);
// 打印数据
ESP_LOG_BUFFER_HEX(HID_DEMO_TAG, param->vendor_write.data, param->vendor_write.length);
break;
}
case ESP_HIDD_EVENT_BLE_LED_REPORT_WRITE_EVT: {
// TODO: 处理BLE LED报告写入事件
ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_LED_REPORT_WRITE_EVT");
// 打印数据
ESP_LOG_BUFFER_HEX(HID_DEMO_TAG, param->led_write.data, param->led_write.length);
break;
}
default:
break;
}
return;
}
这个函数是为了处理HID设备发生事件时,需要作出的动作。在这个函数中可以看到:在HID设备注册完成时的事件中,设置设备的名称,配置广播数据。在BLE断开连接的状态事件中开启广播,因为无设备连接时需要对外广播提供连接。其他事件只是做打印这些简单处理。该函数在主函数中注册回调。
5.3 GAP蓝牙事件回调函数
// 静态函数,处理蓝牙事件
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
// 根据事件类型进行不同的处理
switch (event) {
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
// 广播数据设置完成,开始广播
esp_ble_gap_start_advertising(&hidd_adv_params);
break;
case ESP_GAP_BLE_SEC_REQ_EVT:
// 安全请求事件,打印请求地址
for(int i = 0; i < ESP_BD_ADDR_LEN; i++) {
ESP_LOGD(HID_DEMO_TAG, "%x:",param->ble_security.ble_req.bd_addr[i]);
}
// 发送安全响应
esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
break;
case ESP_GAP_BLE_AUTH_CMPL_EVT:
// 认证完成事件,设置安全连接标志
sec_conn = true;
esp_bd_addr_t bd_addr;
// 复制地址
memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr, sizeof(esp_bd_addr_t));
// 打印远程地址
ESP_LOGI(HID_DEMO_TAG, "remote BD_ADDR: %08x%04x",\
(bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
(bd_addr[4] << 8) + bd_addr[5]);
// 打印地址类型
ESP_LOGI(HID_DEMO_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type);
// 打印认证状态
ESP_LOGI(HID_DEMO_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail");
// 如果认证失败,打印失败原因
if(!param->ble_security.auth_cmpl.success) {
ESP_LOGE(HID_DEMO_TAG, "fail reason = 0x%x",param->ble_security.auth_cmpl.fail_reason);
}
break;
default:
break;
}
}
GAP(Generic Access Profile,通用访问配置文件)事件回调函数主要处理与蓝牙设备发现、连接、断开连接和其他设备管理相关的事件。这里列举的事件有限,当广播数据配置完成时发生事件,在这个事件中开启广播,需要向其他设备告知自己的存在以及自身的属性和能力。在遇到安全请求事件时,发送安全响应。通常安全请求由对端设备发起,ESP32来响应,一般在需要配对的时候会发生此事件。当认证完成时也会产生一个事件,我们的处理是取出对端设备地址打印出来,一同打印的还有认证状态,若是失败了也会打印失败原因。该函数在主函数中注册回调。
5.4 按键初始化及中断处理
// 初始化按键
void KEY_Init(gpio_num_t pin)
{
// 定义按键的GPIO配置
gpio_set_direction(pin, GPIO_MODE_INPUT);
gpio_set_intr_type(pin, GPIO_INTR_POSEDGE); // 上升沿触发中断
}
// 读取按键状态
void IRAM_ATTR KEY_read()
{
static bool botton_init = false; // 定义一个静态变量,用于记录按键的状态
if(gpio_get_level(GPIO_NUM_45) == 1){ // 如果按键引脚的电平为高电平
if(botton_init == false){ // 如果按键状态为未按下
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_PLAY, true); // 发送播放命令按下
vTaskDelay(3 / portTICK_PERIOD_MS); // 延时3ms
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_PLAY, false); // 发送播放命令松开
botton_init = true; // 更新按键状态为按下
}
else if(botton_init == true){ // 如果按键状态为按下
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_PAUSE, true); // 发送暂停命令按下
vTaskDelay(3 / portTICK_PERIOD_MS); // 延时3ms
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_PAUSE, false); // 发送暂停命令松开
botton_init = false; // 更新按键状态为未按下
}
}
}
对IO的配置其中一个就是选择哪种中断触发方式,具体有:上升沿触发、下降沿触发、上升下降沿触发、输入电平高触发、输入电平低触发。作为中断IO使用我们需要配置为输入模式,然后选择要使用的IO的端口号,最后配置为上升沿触发中断。
在中断服务函数中,我们定义一个静态布尔变量表示按键状态,由于硬件有做消抖处理,所以我们没有做软件消抖,无非就是检测到按下之后多等待一会检测是否真的按下,然后做进一步处理。实现的按键功能就是按一下播放再按一下暂停。读者可以自行理解代码,且代码中有注释,在此不多解释了。esp_hidd_send_consumer_value函数最后一个参数介绍一下:他是一个布尔值,表示按键是否被按下,如果为真,则把命令填充到buffer中,如果为假,则不处理,默认为处初始化的0。意思就是:这个布尔值决定按键是否按下,完整的流程是需要按下后松开,所以需要两个esp_hidd_send_consumer_value函数,仅仅最后一个参数不同,表示按下松开。下面贴一下这个函数的内部处理流程:
void esp_hidd_send_consumer_value(uint16_t conn_id, uint8_t key_cmd, bool key_pressed)
{
uint8_t buffer[HID_CC_IN_RPT_LEN] = {0, 0};
if (key_pressed) {
ESP_LOGD(HID_LE_PRF_TAG, "hid_consumer_build_report");
hid_consumer_build_report(buffer, key_cmd);
}
ESP_LOGD(HID_LE_PRF_TAG, "buffer[0] = %x, buffer[1] = %x", buffer[0], buffer[1]);
hid_dev_send_report(hidd_le_env.gatt_if, conn_id,
HID_RPT_ID_CC_IN, HID_REPORT_TYPE_INPUT, HID_CC_IN_RPT_LEN, buffer);
return;
}
还有一点要注意!!中断服务函数里面禁用printf!!否则程序会崩溃。这里ESP_LOGD函数在中断中也没有作用!
5.5 主函数
void app_main(void)
{
KEY_Init(GPIO_NUM_45);// 初始化按键,IO45
gpio_install_isr_service(0);// 安装GPIO中断服务
gpio_isr_handler_add(GPIO_NUM_45,KEY_read,NULL);// 添加GPIO中断处理函数
esp_err_t ret;
// Initialize NVS.
ret = nvs_flash_init();// 初始化NVS
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {// 如果NVS没有足够的空间,则擦除NVS
ESP_ERROR_CHECK(nvs_flash_erase());// 如果NVS没有足够的空间,则擦除NVS
ret = nvs_flash_init();// 重新初始化NVS
}
ESP_ERROR_CHECK( ret );
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));// 释放经典蓝牙内存
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);// 初始化蓝牙控制器
if (ret) {
ESP_LOGE(HID_DEMO_TAG, "%s initialize controller failed", __func__);
return;
}
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);// 启用蓝牙控制器
if (ret) {
ESP_LOGE(HID_DEMO_TAG, "%s enable controller failed", __func__);
return;
}
esp_bluedroid_config_t bluedroid_cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT();// 初始化蓝牙配置
ret = esp_bluedroid_init_with_cfg(&bluedroid_cfg);// 初始化蓝牙
if (ret) {
ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed", __func__);
return;
}
ret = esp_bluedroid_enable();// 启用蓝牙
if (ret) {
ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed", __func__);
return;
}
if((ret = esp_hidd_profile_init()) != ESP_OK) {// 初始化HID
ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed", __func__);
}
//注册回调函数到GAP模块
esp_ble_gap_register_callback(gap_event_handler);// 注册GAP回调函数
esp_hidd_register_callbacks(hidd_event_callback);// 注册HID回调函数
/* set the security iocap & auth_req & key size & init key response key parameters to the stack*/
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND; //设置认证后与对端设备绑定
esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; //设置IO能力为 No output No input
uint8_t key_size = 16; //密钥大小应为7~16 bytes
uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;//设置初始密钥为加密密钥和身份密钥
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;//设置响应密钥为加密密钥和身份密钥
esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));//设置认证模式
esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));//设置IO能力
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));//设置密钥大小
/* If your BLE device act as a Slave, the init_key means you hope which types of key of the master should distribute to you,
and the response key means which key you can distribute to the Master;
If your BLE device act as a master, the response key means you hope which types of key of the slave should distribute to you,
and the init key means which key you can distribute to the slave. */
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));//设置初始密钥
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));//设置响应密钥
}
主函数中首先初始化了IO中断,然后就是NVS初始化,这个是每个例程都有的。接着是初始化蓝牙步骤。
esp_hidd_register_callbacks
这个函数可以深究一下,有点特殊。他将HID事件回调函数当成参数传入,首先一个功能就是注册HID回调函数,如果进去它的定义中查看,可以发现它内部执行了服务注册的函数,见下图:
hidd_register_cb函数中就是执行了esp_ble_gatts_register_callback函数用于在GATTS模块中注册应用程序回调函数。见下图:
gatts_event_handler 函数主要用于将新添加的服务配置文件赋予gatt_if,并为配置文件中的GATT服务器gatts_cb注册回调函数:esp_hidd_prf_cb_hdl,在这个函数中的注册应用程序ID事件里调用了hidd_le_create_service函数,见下图:
配置文件表中分配 esp_hidd_prf_cb_hdl函数为回调函数。
在已注册的gatts_event_handler函数中,当GATTS服务器注册事件到来时执行了esp_hidd_prf_cb_hdl函数并将相关参数传入。
在这个函数(hidd_le_create_service)中调用了GATTS模块的API:esp_ble_gatts_create_attr_tab函数注册了服务程序。见下图:
第一个参数bas_att_db便是服务列表,创建了电池服务。
由此可见,当ESP32的BLE用于HID设备时,虽然使用的是HID协议,但是其本质上在HID协议内部也会创建一个GATTS服务器应用程序, 随后再创建另外一个HID应用程序。当然,如果你不希望有这个电池服务也可以选择不创建。
esp_ble_gap_set_security_param
这个函数用来设置GAP安全参数值,覆盖掉默认值。它是 BLE 配对和加密过程中的一个关键函数,能够控制蓝牙设备在不同安全等级下的行为。通过配置此函数,你可以指定设备的配对模式、加密级别、IO能力(如是否要求用户输入配对码)等安全参数。
函数原型
esp_err_t esp_ble_gap_set_security_param(esp_ble_sm_param_t param, void *value, uint16_t len);
参数解析:
--param:该参数指定了要设置的安全参数的类型,类型为esp_ble_sm_param_t,它是一个枚举类型,表示不同的安全参数。
--value:指定对应的安全参数值。根据param的不同,value的的类型和内容会有所不同。
--len:value的长度,即传入的参数值的字节数。
esp_ble_sm_param_t是一个枚举类型,定义了可以设置的不同安全参数。不同的参数类型会影响 BLE 设备的安全行为,如加密强度、认证方式、输入输出能力等。下面是常见的参数类型及其详细说明。
1.ESP_BLE_SM_AUTHEN_REQ_MODE
类型:uint8_t
描述:设置设备配对时的认证要求。控制配对过程中是否启用 MITM 保护、设备是否需要绑定等。
值的选项:
ESP_LE_AUTH_NO_BOND:不绑定
ESP_LE_AUTH_BOND:与对端设备绑定
ESP_LE_AUTH_REQ_MITM:防止中间人攻击
ESP_LE_AUTH_REQ_BOND_MITM:启用绑定并防止中间人攻击
ESP_LE_AUTH_REQ_SC_ONLY:启用安全连接
ESP_LE_AUTH_REQ_SC_BOND:启用安全连接绑定
ESP_LE_AUTH_REQ_SC_MITM:启用安全连接并防止中间人攻击
ESP_LE_AUTH_REQ_SC_MITM_BOND:启用安全连接、防止中间人攻击、并且启用设备绑定。
2.ESP_BLE_SM_IOCAP_MODE
类型:uint8_t
描述:设置设备的输入输出能力,决定设备配对时如何与用户交互(是否显示配对码、是否需要输入 PIN 码等)。
值的选项:
ESP_IO_CAP_OUT:表示设备仅具有输出能力,即设备能够显示配对信息,但不具有输入能力,它意味着设备能显示配对码或认证信息,但无法进行键盘输入或其他形式的用户交互。
ESP_IO_CAP_IO:表示设备同时支持输入和输出能力。设备既可以显示配对信息(如配对码),也可以接收用户输入(如键盘输入或 PIN 码输入)。
ESP_IO_CAP_IN:表示设备只有输入能力,即设备不能显示任何信息(如配对码),但可以接收用户输入。例如,用户可以通过设备的按钮或键盘输入配对密码。
ESP_IO_CAP_NONE:表示设备既没有输入能力,也没有输出能力。设备无法与用户进行任何交互,无法显示配对信息或接收用户输入。
ESP_IO_CAP_KBDISP:表示设备同时具有键盘输入能力和显示输出能力。设备可以显示配对信息(如配对码),同时也能接收用户输入(如通过键盘输入 PIN 码)。
3.ESP_BLE_SM_MAX_KEY_SIZE
类型:uint8_t
描述:设置配对时的最大加密密钥长度。通常情况下,配对过程中使用的加密密钥长度会在最小和最大值之间自动协商。
值的范围:通常为16字节
4.ESP_BLE_SM_SET_INIT_KEY
类型:uint8_t
描述:启动器密钥分发/生成
值的选项:
ESP_BLE_ENC_KEY_MASK:加密密钥
ESP_BLE_ID_KEY_MASK:身份密钥
ESP_BLE_CSR_KEY_MASK:CSR密钥
ESP_BLE_LINK_KEY_MASK:链接密钥
5.ESP_BLE_SM_SET_RSP_KEY
类型:uint8_t
描述:启动器密钥分发/生成
值的选项:同上
6.成果展示
设置安全参数的作用就在这里,手机会提示配对选项,点击配对即可。
在电池服务中,我将电量的值设为了100,手机上同样可以看到设备电量显示。
按下板子上的按键,即可控制手机音乐的播放和暂停。
7.总结
以上就是关于BLE用作HID设备的内容,使用它可以让ESP32模拟HID设备的行为,通过蓝牙对其他设备实现控制或数据传输的功能。
本文对BLE本身没有过多的展开介绍,如果想了解可以移步至我的主页查看上一期文章。大家如果觉得有用,还请多多点赞收藏关注,你的支持就是对我最大的肯定。谢谢大家!
如有疑问欢迎留言交流。以上观点为个人理解,只想抛砖引玉,如有不对的地方欢迎指正,不喜轻喷。
2024.11.19-14:54