从零开始学ESP32:(三)ESP32的蓝牙GATT服务测试
从零开始学ESP32:个人笔记记录:
芯片型号: ESP32
网络环境支持:LWIP
IDF.PY-SDK: ESP-IDF v4.3
芯片功能: 支持STA/AP网络共存模式:
参考工程:esp-idf/examples/bluetooth/bluedroid/ble/gatt_server
蓝牙初始化:主要测试接口,要注意的是我将ESP32的代码重新编排了
TEST_DEVICE_NAME 蓝牙设备名称
#define TEST_DEVICE_NAME "ESP_GATTS_DEMO" /***************************************************************************** 函数名称:BLE_bleDeviceMain* 输入值: * 输出值:* 返回值:* 其他:* 说明: 蓝牙设备处理 * * */
void BLE_bleDeviceMain(void)
{esp_err_t ret = 0;esp_err_t local_mtu_ret = 0;ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}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();for( int i = 0; i < 9 ; i++){switch ( i ){case 0: ret = esp_bt_controller_init(&bt_cfg); break;case 1: ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); break;case 2: ret = esp_bluedroid_init(); break;case 3: ret = esp_bluedroid_enable(); break;case 4: ret = esp_ble_gatts_register_callback(gatts_event_handler); break;case 5: ret = esp_ble_gap_register_callback(gap_event_handler); break;case 6: ret = esp_ble_gatts_app_register(PROFILE_A_APP_ID); break;#ifdef POR_FILE_Bcase 7: ret = esp_ble_gatts_app_register(PROFILE_B_APP_ID); break;#endif case 8: local_mtu_ret = esp_ble_gatt_set_local_mtu(500); break;default: break;}if( ret || local_mtu_ret ){DEV_PRINTF("number = %d errot local_mtu_ret = %x %s\n", i , local_mtu_ret , esp_err_to_name(ret) );DEV_PRINTF("BEL DEVICE INIT FAILED ");return ; }}return;
}
讲解这个代码: 里面ESP32默认开启的是两条服务配置,
也就是PORFILE_A和 PORFILE_B 服务。
在注册进去的时候,例程里面提供了两个事件回调函数结构:
下面分别介绍gatts_profile_a_event_handler 和 gatts_profile_b_event_handler回调函数:
由于ESP32蓝牙这块的代码写实在是有点难以言喻,按照事件重新编排,但是其实本质上是没有变化的
gatts_profile_a_event_handler 回调函数的讲解
学习主要是学习几个事件:
ESP_GATTS_REG_EVT 在注册时候回出现注册回调
ESP_GATTS_READ_EVT
ESP_GATTS_WRITE_EVT 作为服务端的写事件,居然是接收手机APP发送过来的数据
ESP_GATTS_CONNECT_EVT 当前用户连接进来就会回调产生事件
ESP_GATTS_DISCONNECT_EVT 断开事件
static void gatts_profile_a_event_handler( esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param )
{switch ( event ){case ESP_GATTS_REG_EVT: gatt_a_registerEventHandler( event , gatts_if , param ); break; // 注册case ESP_GATTS_READ_EVT: gatt_a_readPackEventHandler( event , gatts_if , param ); break; //读case ESP_GATTS_WRITE_EVT: gatt_a_writePackEventHandler(event , gatts_if , param ); break; //写case ESP_GATTS_EXEC_WRITE_EVT: gatt_a_execPackWriteHandler( event , gatts_if , param ); break;case ESP_GATTS_MTU_EVT: DEV_PRINTF("ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu); break;case ESP_GATTS_CREATE_EVT: gatt_a_createPackEventHandler(event , gatts_if , param); break;case ESP_GATTS_ADD_CHAR_EVT: gatt_a_addCharPackEventHandler(event , gatts_if , param); break;case ESP_GATTS_ADD_CHAR_DESCR_EVT: gatt_a_addCharDescrEventHandler(event, gatts_if , param); break;case ESP_GATTS_CONNECT_EVT: gatt_a_connectEventHandler( event , gatts_if , param ); break; //连接事件case ESP_GATTS_DISCONNECT_EVT: gatt_a_disconnectEventHandler( event, gatts_if, param ); break; //断开连接case ESP_GATTS_CONF_EVT: gatt_a_configEventHandler( event , gatts_if , param ); break; case ESP_GATTS_START_EVT: DEV_PRINTF("SERVICE_START_EVT, status %d, service_handle %d\n",param->start.status, param->start.service_handle); break;case ESP_GATTS_UNREG_EVT: break;case ESP_GATTS_ADD_INCL_SRVC_EVT: break;case ESP_GATTS_DELETE_EVT: break;case ESP_GATTS_STOP_EVT: break;case ESP_GATTS_OPEN_EVT: break;case ESP_GATTS_CANCEL_OPEN_EVT: break;case ESP_GATTS_CLOSE_EVT: break;case ESP_GATTS_LISTEN_EVT: break;case ESP_GATTS_CONGEST_EVT: break;default: DEV_PRINTF("none event "); break;}return ;
}*******主要可以看看 事件的回调和产生************/***************************************************************************** 函数名称* * * GATT B 系列事件 ESP_GATTS_WRITE_EVT* */
void gatt_b_writePackEventHandler( esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param )
{char buff[100] = { 0 }; // DEV_PRINTF ("GATT_WRITE_EVT, conn_id %d, trans_id %d, handle %d\n", param->write.conn_id, param->write.trans_id, param->write.handle);if (!param->write.is_prep){memcpy( buff ,param->write.value, param->write.len );buff[ param->write.len ] = '\0'; /******** param->write.value 就是我们接收到APP 的信息 **************/DEV_PRINTF("value = %s len %d, value :", buff , param->write.len ); if (gl_profile_tab[PROFILE_B_APP_ID].descr_handle == param->write.handle && param->write.len == 2) {uint16_t descr_value= param->write.value[1]<<8 | param->write.value[0];if (descr_value == 0x0001){if (b_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){DEV_PRINTF("notify enable");uint8_t notify_data[15];for (int i = 0; i < sizeof(notify_data); ++i){notify_data[i] = i%0xff;}//the size of notify_data[] need less than MTU sizeesp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_B_APP_ID].char_handle,sizeof(notify_data), notify_data, false);}}else if (descr_value == 0x0002){if (b_property & ESP_GATT_CHAR_PROP_BIT_INDICATE){DEV_PRINTF("indicate enable");uint8_t indicate_data[15];for (int i = 0; i < sizeof(indicate_data); ++i){indicate_data[i] = i%0xff;}esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_B_APP_ID].char_handle,sizeof(indicate_data), indicate_data, true);}}else if (descr_value == 0x0000){DEV_PRINTF("notify/indicate disable ");}else{DEV_PRINTF("unknown value");}}}example_write_event_env(gatts_if, &b_prepare_write_env, param);
}
有关APP得测试:
IOS : NRF CONNECT
ANDROID : NRF CONNECT
下面是测试图片:
进行一次连接和断开操作,发现都存在事件回调
下面是收到APP的数据
IOS系统的NRF CONECT 软件操作:
ANDROID系统的NRF CONECT 软件操作:
关注微信公众号 一起学习 ( 技术Code城 )
从零开始学ESP32:(三)ESP32的蓝牙GATT服务测试相关推荐
- 从零开始学架构三 高性能
从零开始学架构三 高性能 读写分离 读写分离的基本实现是: 数据库服务器搭建主从集群,一主一从.一主多从都可以. 数据库主机负责读写操作,从机只负责读操作. 数据库主机通过复制将数据同步到从机,每台数 ...
- python从0开始学编程课件_小白从零开始学编程(三)--python基本概念
前言 从2020年3月份开始,计划写一系列文档--<小白从零开始学编程>,记录自己从0开始学习的一些东西. 第一个系列:python,计划从安装.环境搭建.基本语法.到利用Django和F ...
- 从零开始学JavaScript三(变量)
一.变量 ECMAscript变量是松散型变量,所谓松散型变量,就是变量名称可以保存任何类型的数据,每个变量仅仅是一个用于保存值的占位符. 定义变量时要使用var操作符 如: var message; ...
- 从零开始学python网络爬虫-从零开始学Python 三(网络爬虫)
本章由网络爬虫的编写来学习python.首先写几行代码抓取百度首页,提提精神,代码如下: importurllib.request file=urllib.request.urlopen(" ...
- 从零开始学安全(三)●黑客常用的windows端口
端口可选1-65536 1-1024 预保留端口 留给windows系统服务的 下面是常见的端口对应的服务 1 TCP Port Service Multiplexer 传输控制协议端口服务多路开关选 ...
- 从零开始学java-(三)for ZCL:java基本数据类型
上一篇文章最后我们留了几个问题,下面来解答,并解释一下为什么! 1,修改HelloWrold.java文件编译之后,出现什么?怎么看出现的东西? 如果你做了修改,根据每个人修改的不同,javac编译的 ...
- php图片木马抓鸡,从零开始学安全(三十八)●cobaltstrike生成木马抓肉鸡
链接:https://pan.baidu.com/s/1qstCSM9nO95tFGBsnYFYZw 提取码:w6ih 上面是工具 需要java jdk 在1.8.5 以上 实验环境windows ...
- (七)深入理解蓝牙BLE之“蓝牙GATT服务”
目录 前言: 学习总结: uuid的定义: GATT Declarations: GATT Service: GATT Characteristic and Object Type:
- ESP32学习笔记(30)——BLE GATT服务端自定义服务和特征
一.简介 1.1 低功耗蓝牙(BLE)协议栈 链路层(LL) 控制设备的射频状态,有五个设备状态:待机.广播.扫描.初始化和连接. 广播 为广播数据包,而 扫描 则是监听广播. GAP通信中角色,中心 ...
最新文章
- uva 315 (poj 1144 求割点)
- PHP的静态变量介绍
- PGA Usage Larger than PGA_AGGREGATE_TARGET setting?
- Thrown KeeperErrorCode = Unimplemented for /services exception
- 概率图模型中的变量消除顺序
- OpenReports中文支持方案
- JDBC预处理对象prepareStatement
- Python 全局变量
- win7 mysql添加到服务_MySQL服务添加到Windows系统服务中
- 有关《8zsb》的一些介绍
- IIS 部署WCF时遇到这么个错:
- Java 输入一个整数,计算它各位上数字的和。(注意:是任意位的整数)
- 专访世纪互联:公共云才是真正云计算
- 2018ICPC焦作D(几何)---Keiichi Tsuchiya the Drift King
- a标签如何链接php文件路径,HTML的a标签href属性指定相对路径与绝对路径的用法讲解...
- 计算机教室使用与管理制度,《计算机教室使用与管理制度》
- linux skb_buf大小,linux网络 skb_buff
- js获取当前时间24小时制
- K8S 配置域名访问 Ingress【Traefik】
- matlab索引奇数,将列表分为偶数索引部分和奇数索引部分
热门文章
- flyme os 插桩红米2 教程
- C#使用微软TTS语音引擎实现文字转语音示例
- 10111001的曼彻斯特编码_曼彻斯特编码
- 浅谈Matchvs联网对战服务的几点优势
- Steemit 会颠覆 Quora/知乎 甚至 Facebook 吗?
- 在电脑桌面单击 计算机,解决方案:计算机鼠标可以移动,不能在桌面图标上单击。怎么了?...
- android.process修复,如何修复“ Android Widget”的“ process is bad”错误?
- Apriltag跟踪和定位
- 计算机视觉行为分析,计算机视觉技术在人体行为分析中的研究与应用
- Python 中的自动点击器——2 种简单易行的方法