ported minimal code over from barhead

This commit is contained in:
Morgan 'ARR\!' Allen 2024-12-01 21:57:17 -08:00
parent 54c7a2d2d6
commit d51d3633f2
2 changed files with 290 additions and 0 deletions

View file

@ -1,6 +1,9 @@
#ifndef __BAROS_H__
#define __BAROS_H__
#include <stdint.h>
#include "esp_event_base.h"
#define BAROS_BLE_SERVICE_PUMP_ENABLED (0x4200)
#define BAROS_BLE_SERVICE_PUMP_STATE (0x4300)
#define BAROS_BLE_SERVICE_PUMP_DURATION (0x4350)
@ -10,4 +13,25 @@
#define BAROS_CHAR_POUR (BAROS_BLE_SERVICE_BARBACK + 1) // 0x4401
#define BAROS_CHAR_BUTTON (BAROS_BLE_SERVICE_BARBACK + 2) // 0x4402
typedef enum {
BAROS_ROLE_BACK = 0,
BAROS_ROLE_HEAD,
BAROS_ROLE_ADMIN
} baros_role_t;
typedef struct {
const char *name;
baros_role_t role;
} baros_ble_cfg_t;
uint8_t baros_ble_init(baros_ble_cfg_t *cfg);
ESP_EVENT_DECLARE_BASE(EVENT_BAROS_BLE);
typedef enum {
BAROS_BLE_DISC,
BAROS_BLE_CONNECT,
} baros_ble_event_t;
#endif

266
src/baros_ble.c Normal file
View file

@ -0,0 +1,266 @@
#include "freertos/FreeRTOS.h"
#include "esp_system.h"
#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 "services/gap/ble_svc_gap.h"
#include "services/bas/ble_svc_bas.h"
#include "esp_event_base.h"
#include "esp_event.h"
#include "baros.h"
#define TAG "BOS_BLE"
ESP_EVENT_DEFINE_BASE(EVENT_BAROS_BLE);
static uint8_t blehr_addr_type;
static uint16_t conn_handle;
static const char *device_name;
static const struct ble_gatt_svc_def service_defs[] = {
{ NULL }
};
static void ble_advertise(void);
static int ble_gap_event(struct ble_gap_event *event, void *arg) {
switch (event->type) {
case BLE_GAP_EVENT_DISC: {
struct ble_hs_adv_fields fields;
ESP_ERROR_CHECK(ble_hs_adv_parse_fields(&fields, event->disc.data, event->disc.length_data));
ESP_LOGV(TAG, "DISCOVERY: %d", event->disc.length_data);
uint8_t addr[6];
memcpy(&addr, (uint8_t*)&event->disc.addr + 1, 6);
ESP_LOGV(TAG, "addr: %02X:%02X:%02X:%02X:%02X:%02X", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
ESP_ERROR_CHECK(esp_event_post(EVENT_BAROS_BLE, BAROS_BLE_DISC, (void*)&event->disc, sizeof(struct ble_gap_disc_desc), 1000));
/*
uint8_t *buf = (uint8_t*)malloc(event->disc.length_data);
memcpy(buf, event->disc.data, event->disc.length_data);
printf("\ndata: ");
for(uint8_t i = 0; i < event->disc.length_data; i++) {
printf("0x%02X ", buf[i]);
}
printf("\n");
*/
if(fields.name != NULL) {
char *name = (char*)malloc(fields.name_len);
memcpy(name, (uint8_t*)fields.name, fields.name_len);
name[fields.name_len] = '\0';
ESP_LOGV(TAG, "Name: %s", name);
}
ESP_LOGV(TAG, "uuids: %d", fields.num_uuids16);
for (uint8_t i = 0; i < fields.num_uuids16; i++) {
ESP_LOGV(TAG, "uuid: 0x%04X", fields.uuids16[i].value);
if (ble_uuid_u16(&fields.uuids16[i].u) == BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME) {
ESP_LOGV(TAG, "device has name");
}
}
return 0;
}
case BLE_GAP_EVENT_CONNECT:
/* A new connection was established or a connection attempt failed */
conn_handle = event->connect.conn_handle;
ESP_LOGI(TAG, "connection %s; conn_handle: %d status=%d\n",
event->connect.status == 0 ? "established" : "failed",
conn_handle,
event->connect.status
);
// always keep advertising
ble_advertise();
break;
case BLE_GAP_EVENT_DISCONNECT:
ESP_LOGI(TAG, "disconnect; reason=%d\n", event->disconnect.reason);
/* Connection terminated; resume advertising */
ble_advertise();
break;
case BLE_GAP_EVENT_ADV_COMPLETE:
ESP_LOGI(TAG, "adv complete\n");
ble_advertise();
break;
case BLE_GAP_EVENT_SUBSCRIBE:
ESP_LOGI(TAG, "subscribe event; cur_notify=%d\n value handle; "
"val_handle=%d\n",
event->subscribe.cur_notify, event->subscribe.attr_handle);
break;
case BLE_GAP_EVENT_CONN_UPDATE:
ESP_LOGI(TAG, "BLE_GAP_EVENT_CONN_UPDATE, conn_handle: %d status: %d",
event->mtu.conn_handle,
event->enc_change.status
);
break;
case BLE_GAP_EVENT_ENC_CHANGE:
ESP_LOGI(TAG, "BLE_GAP_EVENT_ENC_CHANGE");
break;
case BLE_GAP_EVENT_MTU:
ESP_LOGI(TAG, "mtu update event; conn_handle=%d mtu=%d\n",
event->mtu.conn_handle,
event->mtu.value);
break;
case BLE_GAP_EVENT_NOTIFY_RX:
ESP_LOGI(TAG, "BLE_GAP_EVENT_NOTIFY_RX; conn_handle=%d mtu=%d attr_handle=%d\n",
event->mtu.conn_handle,
event->mtu.value,
event->notify_rx.attr_handle);
break;
case BLE_GAP_EVENT_NOTIFY_TX:
ESP_LOGI(TAG, "BLE_GAP_EVENT_NOTIFY_TX; conn_handle=%d mtu=%d\n",
event->mtu.conn_handle,
event->mtu.value);
break;
default:
ESP_LOGW(TAG, "unhandled ble_gap_event; conn_handle=%d type=%d\n",
event->mtu.conn_handle,
event->type
);
}
return 0;
}
static void ble_advertise(void) {
// check if already adverting
if(ble_gap_adv_active()) return;
struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields fields;
int rc;
memset(&fields, 0, sizeof(fields));
fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
fields.name = (uint8_t *)device_name;
fields.name_len = strlen(device_name);
fields.name_is_complete = 1;
rc = ble_gap_adv_set_fields(&fields);
if (rc != 0) {
ESP_LOGE(TAG, "error setting advertisement data; rc=%d\n", rc);
return;
}
/* Begin advertising */
memset(&adv_params, 0, sizeof(adv_params));
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
rc = ble_gap_adv_start(blehr_addr_type, NULL, BLE_HS_FOREVER,
&adv_params, ble_gap_event, NULL);
if (rc != 0) {
ESP_LOGE(TAG, "error enabling advertisement; rc=%d\n", rc);
return;
}
}
int ble_scan_start() {
uint8_t addr_type;
struct ble_gap_disc_params disc_params = {
.filter_duplicates = 1,
.passive = 1,
.itvl = 0,
.window = 0,
.filter_policy = 0,
.limited = 0,
};
ESP_ERROR_CHECK(ble_hs_id_infer_auto(0, &addr_type));
ble_gap_disc_cancel();
ESP_ERROR_CHECK(ble_gap_disc(addr_type, 3000, &disc_params, ble_gap_event, &addr_type));
return 0;
}
int ble_scan_stop() {
return ble_gap_disc_cancel();
}
void nimble_host_task(void *param) {
nimble_port_run();
}
static void on_sync() {
ESP_LOGI(TAG, "on_sync");
int err;
err = ble_hs_id_infer_auto(0, &blehr_addr_type);
ESP_ERROR_CHECK(err);
uint8_t addr_val[6] = {0};
err = ble_hs_id_copy_addr(blehr_addr_type, addr_val, NULL);
ESP_ERROR_CHECK(err);
ble_advertise();
}
static void on_reset(int reason) {
ESP_LOGE(TAG, "on_reset, reason: %d", reason);
}
uint8_t baros_ble_init(baros_ble_cfg_t *cfg) {
esp_err_t err;
device_name = cfg->name;
//ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
nimble_port_init();
ble_hs_cfg.sync_cb = on_sync;
ble_hs_cfg.reset_cb = on_reset;
// initialize services
err = ble_gatts_count_cfg(service_defs);
ESP_ERROR_CHECK(err);
err = ble_gatts_add_svcs(service_defs);
ESP_ERROR_CHECK(err);
ESP_LOGI(TAG, "Setting device name: %s", device_name);
err = ble_svc_gap_device_name_set(device_name);
ESP_ERROR_CHECK(err);
vTaskDelay(500 / portTICK_PERIOD_MS);
nimble_port_freertos_init(nimble_host_task);
return 0;
}