#include <main.h> #include "nvs.h" #include "nvs_flash.h" #include "esp_log.h" #include "esp_sleep.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_bt.h" #include "esp_bt_main.h" #include "esp_gap_ble_api.h" #include <string.h> #include <string> #include <unordered_set> #include <algorithm> #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG static const char* TAG = "main"; std::unordered_set<std::string> devices; uint8_t unique_pings = 0; uint16_t total_pings = 0; 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, // Set scan interval & window to 25ms (40 * 0.625) .scan_interval = 0x28, .scan_window = 0x28, .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; static void esp_gap_cb( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param ); void app_main(void) { // Initialize NVS. esp_err_t 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(); ret = esp_bt_controller_init(&bt_cfg); if (ret) { ESP_LOGE(TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret)); return; } ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); if (ret) { ESP_LOGE(TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret)); return; } ret = esp_bluedroid_init(); if (ret) { ESP_LOGE(TAG, "%s init bluetooth failed: %s\n", __func__, esp_err_to_name(ret)); return; } ret = esp_bluedroid_enable(); if (ret) { ESP_LOGE(TAG, "%s enable bluetooth failed: %s\n", __func__, esp_err_to_name(ret)); return; } //register the callback function to the gap module ret = esp_ble_gap_register_callback(esp_gap_cb); if (ret){ ESP_LOGE(TAG, "%s gap register failed, error code = %x\n", __func__, ret); return; } // Set wakeup interval of 4s esp_sleep_enable_timer_wakeup(4 * 1e6); while (true) { ret = esp_ble_gap_set_scan_params(&ble_scan_params); if (ret){ ESP_LOGE(TAG, "set scan params error, error code = %x", ret); } unique_pings = 0; total_pings = 0; devices.clear(); // Set scan duration to 30s, we can control it with the delay below esp_ble_gap_start_scanning(30); vTaskDelay(pdMS_TO_TICKS(2000)); ESP_ERROR_CHECK(esp_ble_gap_stop_scanning()); ESP_LOGI(TAG, "[%s]: Unique devices captured: %u", __func__, unique_pings); ESP_LOGI(TAG, "[%s]: Total pings captured: %u", __func__, total_pings); vTaskDelay(2); ESP_LOGI(TAG, "[%s]: Slep", __func__); esp_light_sleep_start(); ESP_LOGI(TAG, "[%s]: Wakey", __func__); } } static void esp_gap_cb( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param ) { uint8_t *adv_name = NULL; uint8_t adv_name_len = 0; switch (event) { case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: //scan start complete event to indicate scan start successfully or failed if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { ESP_LOGE(TAG, "scan start failed, error status = %x", param->scan_start_cmpl.status); break; } ESP_LOGI(TAG, "scan start success"); break; case ESP_GAP_BLE_SCAN_RESULT_EVT: { 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: { char mac[18]; auto addr = scan_result->scan_rst.bda; snprintf(mac, 18, "%.2x %.2x %.2x %.2x %.2x %.2x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); adv_name = esp_ble_resolve_adv_data( scan_result->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len ); if (adv_name_len > 0 && strncmp( (char*) adv_name, "INFOTECH", std::min(adv_name_len, (uint8_t) 8) ) == 0 ) { if (devices.find(mac) == devices.end()) { devices.insert(mac); unique_pings += 1; ESP_LOGI(TAG, "%s (%ddBm, %.*s)", mac, scan_result->scan_rst.rssi, adv_name_len, adv_name); } // Also count duplicates here total_pings += 1; ESP_LOGD(TAG, "%s", mac); } break; } case ESP_GAP_SEARCH_INQ_CMPL_EVT: break; default: break; } break; } case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){ ESP_LOGE(TAG, "scan stop failed, error status = %x", param->scan_stop_cmpl.status); break; } ESP_LOGI(TAG, "stop scan successfully"); break; case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){ ESP_LOGE(TAG, "adv stop failed, error status = %x", param->adv_stop_cmpl.status); break; } ESP_LOGI(TAG, "stop adv successfully"); break; default: break; } }