Skip to content

Instantly share code, notes, and snippets.

@jef-sure
Created June 19, 2021 16:51
Show Gist options
  • Save jef-sure/08b3e98627f61926bc6e58060f4c23b4 to your computer and use it in GitHub Desktop.
Save jef-sure/08b3e98627f61926bc6e58060f4c23b4 to your computer and use it in GitHub Desktop.
#include "esp_log.h"
#include "nvs_flash.h"
/* BLE */
#include "esp_nimble_hci.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "console/console.h"
#include "services/gap/ble_svc_gap.h"
static const char *tag = "NimBLE_BLE_CENT";
/* scan_event() calls scan(), so forward declaration is required */
static void scan(void);
static void ble_app_set_addr(void) {
ble_addr_t addr;
int rc;
/* generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(1, &addr);
assert(rc == 0);
/* set generated address */
rc = ble_hs_id_set_rnd(addr.val);
assert(rc == 0);
}
static void print_uuid(const ble_uuid_t *uuid) {
char buf[BLE_UUID_STR_LEN];
MODLOG_DFLT(DEBUG, "%s", ble_uuid_to_str(uuid, buf));
}
/* Utility function to log an array of bytes. */
static void print_bytes(const uint8_t *bytes, int len) {
int i;
for (i = 0; i < len; i++) {
MODLOG_DFLT(DEBUG, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
}
}
static char*
addr_str(const void *addr) {
static char buf[6 * 2 + 5 + 1];
const uint8_t *u8p;
u8p = addr;
sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
return buf;
}
static void print_adv_fields(const struct ble_hs_adv_fields *fields) {
char s[BLE_HS_ADV_MAX_SZ];
const uint8_t *u8p;
int i;
if (fields->flags != 0) {
MODLOG_DFLT(DEBUG, " flags=0x%02x\n", fields->flags);
}
if (fields->uuids16 != NULL) {
MODLOG_DFLT(INFO, " uuids16(%scomplete)=", fields->uuids16_is_complete ? "" : "in");
for (i = 0; i < fields->num_uuids16; i++) {
print_uuid(&fields->uuids16[i].u);
MODLOG_DFLT(INFO, " ");
}
MODLOG_DFLT(INFO, "\n");
}
if (fields->uuids32 != NULL) {
ESP_LOGI(tag, " uuids32(%scomplete)=", fields->uuids32_is_complete ? "" : "in");
for (i = 0; i < fields->num_uuids32; i++) {
print_uuid(&fields->uuids32[i].u);
MODLOG_DFLT(DEBUG, " ");
}
MODLOG_DFLT(DEBUG, "\n");
}
if (fields->uuids128 != NULL) {
ESP_LOGI(tag, " uuids128(%scomplete)=", fields->uuids128_is_complete ? "" : "in");
for (i = 0; i < fields->num_uuids128; i++) {
print_uuid(&fields->uuids128[i].u);
MODLOG_DFLT(DEBUG, " ");
}
MODLOG_DFLT(DEBUG, "\n");
}
if (fields->name != NULL) {
assert(fields->name_len < sizeof s - 1);
memcpy(s, fields->name, fields->name_len);
s[fields->name_len] = '\0';
ESP_LOGI(tag, " name(%scomplete)=%s\n", fields->name_is_complete ? "" : "in", s);
}
if (fields->tx_pwr_lvl_is_present) {
ESP_LOGI(tag, " tx_pwr_lvl=%d\n", fields->tx_pwr_lvl);
}
if (fields->slave_itvl_range != NULL) {
MODLOG_DFLT(DEBUG, " slave_itvl_range=");
print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
MODLOG_DFLT(DEBUG, "\n");
}
if (fields->svc_data_uuid16 != NULL) {
MODLOG_DFLT(DEBUG, " svc_data_uuid16=");
print_bytes(fields->svc_data_uuid16, fields->svc_data_uuid16_len);
MODLOG_DFLT(DEBUG, "\n");
}
if (fields->public_tgt_addr != NULL) {
MODLOG_DFLT(DEBUG, " public_tgt_addr=");
u8p = fields->public_tgt_addr;
for (i = 0; i < fields->num_public_tgt_addrs; i++) {
MODLOG_DFLT(DEBUG, "public_tgt_addr=%s ", addr_str(u8p));
u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
}
MODLOG_DFLT(DEBUG, "\n");
}
if (fields->appearance_is_present) {
ESP_LOGI(tag, " appearance=0x%04x\n", fields->appearance);
}
if (fields->adv_itvl_is_present) {
ESP_LOGI(tag, " adv_itvl=0x%04x\n", fields->adv_itvl);
}
if (fields->svc_data_uuid32 != NULL) {
MODLOG_DFLT(DEBUG, " svc_data_uuid32=");
print_bytes(fields->svc_data_uuid32, fields->svc_data_uuid32_len);
MODLOG_DFLT(DEBUG, "\n");
}
if (fields->svc_data_uuid128 != NULL) {
MODLOG_DFLT(DEBUG, " svc_data_uuid128=");
print_bytes(fields->svc_data_uuid128, fields->svc_data_uuid128_len);
MODLOG_DFLT(DEBUG, "\n");
}
if (fields->uri != NULL) {
MODLOG_DFLT(DEBUG, " uri=");
print_bytes(fields->uri, fields->uri_len);
MODLOG_DFLT(DEBUG, "\n");
}
if (fields->mfg_data != NULL) {
MODLOG_DFLT(DEBUG, " mfg_data=");
print_bytes(fields->mfg_data, fields->mfg_data_len);
MODLOG_DFLT(DEBUG, "\n");
}
}
static int scan_event(struct ble_gap_event *event, void *arg) {
struct ble_hs_adv_fields fields;
int rc;
switch (event->type) {
/* advertising report has been received during discovery procedure */
case BLE_GAP_EVENT_DISC:
MODLOG_DFLT(ERROR, "Advertising report received!\n");
rc = ble_hs_adv_parse_fields(&fields, event->disc.data, event->disc.length_data);
if (rc != 0) {
ESP_LOGI(tag, "adv_parse_fields failed: %d", rc);
}
print_adv_fields(&fields);
return 0;
/* discovery procedure has terminated */
case BLE_GAP_EVENT_DISC_COMPLETE:
ESP_LOGI(tag, "Discovery completed, terminaton code: %d\n", event->disc_complete.reason);
scan();
return 0;
default:
MODLOG_DFLT(ERROR, "Discovery event not handled\n");
return 0;
}
}
static void scan(void) {
/* set scan parameters */
struct ble_gap_disc_params scan_params;
scan_params.itvl = 500;
scan_params.window = 250;
scan_params.filter_policy = 0;
scan_params.limited = 0;
scan_params.passive = 1;
scan_params.filter_duplicates = 1;
/* performs discovery procedure; value of own_addr_type is hard-coded,
because NRPA is used */
ble_gap_disc(BLE_OWN_ADDR_RANDOM, 1000, &scan_params, scan_event, NULL);
}
static void on_sync(void) {
/* Generate a non-resolvable private address. */
ble_app_set_addr();
/* begin scanning */
scan();
}
static void on_reset(int reason) {
console_printf("Resetting state; reason=%d\n", reason);
}
void blecent_host_task(void *param) {
ESP_LOGI(tag, "BLE Host Task Started");
/* This function will return only when nimble_port_stop() is executed */
nimble_port_run();
nimble_port_freertos_deinit();
}
void app_main(void) {
int rc;
/* Initialize NVS — it is used to store PHY calibration data */
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_nimble_hci_and_controller_init());
nimble_port_init();
/* Configure the host. */
ble_hs_cfg.sync_cb = on_sync;
ble_hs_cfg.reset_cb = on_reset;
/* Set the default device name. */
rc = ble_svc_gap_device_name_set("nimble-blecent");
assert(rc == 0);
nimble_port_freertos_init(blecent_host_task);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment