/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/****************************************************************************
*
* This file is for iBeacon demo. It supports both iBeacon sender and receiver
* which is distinguished by macros IBEACON_SENDER and IBEACON_RECEIVER,
*
* iBeacon is a trademark of Apple Inc. Before building devices which use iBeacon technology,
* visit https://developer.apple.com/ibeacon/ to obtain a license.
*
****************************************************************************/
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gattc_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_defs.h"
#include "esp_ibeacon_api.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
static const char* DEMO_TAG = "IBEACON_DEMO";
extern esp_ble_ibeacon_vendor_t vendor_config;
#if (IBEACON_MODE == IBEACON_RECEIVER)
// 在停止扫描请求发送后,蓝牙堆栈可能还会处理一些尚未完成的扫描结果。因此需要通过这个标志位来设置是否需要继续处理扫描完成事件
static bool is_scanning = false;
#endif
///Declare static functions
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
#if (IBEACON_MODE == IBEACON_RECEIVER)
static esp_ble_scan_params_t ble_scan_params = {
.scan_type = BLE_SCAN_TYPE_ACTIVE, // 主动扫描
.own_addr_type = BLE_ADDR_TYPE_PUBLIC, // 公共地址
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, // 允许扫描所有设备
.scan_interval = 0x50,
.scan_window = 0x30,
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
};
#elif (IBEACON_MODE == IBEACON_SENDER)
static esp_ble_adv_params_t ble_adv_params = {
.adv_int_min = 0x20, // 0x20*0.625ms=20ms,Range: 0x0020 to 0x4000 (20ms to 10240ms)
.adv_int_max = 0x40, // 0x40*0.625ms=40ms
.adv_type = ADV_TYPE_NONCONN_IND, // 不可连接广播
// .adv_type = ADV_TYPE_DIRECT_IND_HIGH, // 设置为高占空比定向广播
// .peer_addr = {0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6}, // 目标设备MAC地址
// .peer_addr_type = BLE_ADDR_TYPE_PUBLIC, // 目标设备的地址类型
.own_addr_type = BLE_ADDR_TYPE_PUBLIC, // 公共地址
.channel_map = ADV_CHNL_ALL, // 在 37,38,39 频道广播
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, // 允许任何设备扫描和连接
};
#endif
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
esp_err_t err;
ESP_LOGI(DEMO_TAG, "====> ESP_GAP_BLE_EVT %d <====", event);
switch (event) {
#if (IBEACON_MODE == IBEACON_SENDER)
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: { // 原始广播数据设置完成事件
if ((err = param->adv_data_raw_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(DEMO_TAG, "Set raw adv data failed: %s", esp_err_to_name(err));
return;
}
esp_ble_gap_start_advertising(&ble_adv_params);
break;
}
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: { // 广播启动完成事件
//adv start complete event to indicate adv start successfully or failed
if ((err = param->adv_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(DEMO_TAG, "Adv start failed: %s", esp_err_to_name(err));
}
break;
}
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: { // 广播停止完成事件
if ((err = param->adv_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS){
ESP_LOGE(DEMO_TAG, "Adv stop failed: %s", esp_err_to_name(err));
}
else {
ESP_LOGI(DEMO_TAG, "Stop adv successfully");
}
break;
}
#endif
#if (IBEACON_MODE == IBEACON_RECEIVER)
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: { // 扫描参数设置完成事件
//the unit of the duration is second, 0 means scan permanently
uint32_t duration = 0;
esp_ble_gap_start_scanning(duration);
break;
}
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: // 扫描启动完成事件
//scan start complete event to indicate scan start successfully or failed
if ((err = param->scan_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(DEMO_TAG, "Scan start failed: %s", esp_err_to_name(err));
} else {
is_scanning = true;
}
break;
case ESP_GAP_BLE_SCAN_RESULT_EVT: { // 扫描结果准备完毕事件
if (is_scanning == false) { // 如果没有在扫描,则不处理扫描结果
ESP_LOGW(DEMO_TAG, "Scan is not started yet");
break;
}
esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
switch (scan_result->scan_rst.search_evt) {
case ESP_GAP_SEARCH_INQ_RES_EVT: {
/* 搜索 BLE iBeacon 数据包 */
if (esp_ble_is_ibeacon_packet(scan_result->scan_rst.ble_adv, scan_result->scan_rst.adv_data_len)) {
esp_ble_ibeacon_t *ibeacon_data = (esp_ble_ibeacon_t*)(scan_result->scan_rst.ble_adv);
ESP_LOGI(DEMO_TAG, "----------iBeacon Found----------");
esp_log_buffer_hex("IBEACON_DEMO: Device address:", scan_result->scan_rst.bda, ESP_BD_ADDR_LEN );
esp_log_buffer_hex("