2023-06-14 22:00:42 +02:00

236 lines
6.7 KiB
C

#include "nimble/ble.h"
#include "configuration.h"
#include "esp_err.h"
#include "host/ble_att.h"
#include "host/ble_gap.h"
#include "host/ble_gatt.h"
#include "host/ble_hs_adv.h"
#include "host/ble_hs_mbuf.h"
#include "host/ble_uuid.h"
#include "measure.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "os/os_mbuf.h"
#include "power_profiler.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "ble.h"
#include "gatt_svcs.h"
#include "BLE_UUID.h"
static struct ble_hs_adv_fields adv_fields = {
.tx_pwr_lvl_is_present = 1,
.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO,
.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP,
.name = (uint8_t*)&"Power Profiler"[0],
.name_len = 15,
.name_is_complete = 1,
};
static struct ble_gap_adv_params adv_params = {
.conn_mode = BLE_GAP_CONN_MODE_UND,
.disc_mode = BLE_GAP_DISC_MODE_GEN,
};
static uint16_t conn_handle;
static uint16_t cs_handle[INPUTS_NUM];
static uint16_t ev_handle[INPUTS_NUM];
static uint16_t settings_handle[SETTINGS_CHRS_NUM];
static uint8_t cs_notify_state[INPUTS_NUM];
static uint8_t ev_notify_state[INPUTS_NUM];
static struct ble_context ev_ctxt[INPUTS_NUM];
static struct ble_context cs_ctxt[INPUTS_NUM];
static struct ble_context settings_ctxt[SETTINGS_CHRS_NUM];
static struct ble_gatt_chr_def current_measure_char_template = {
.uuid = BLE_UUID16_DECLARE(ELECTRIC_CURRENT_CHAR),
.access_cb = gatt_char_access_cs,
.arg = &cs_ctxt,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.min_key_size = 0,
.val_handle = cs_handle,
.descriptors = (struct ble_gatt_dsc_def[]){
[0] = {
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_char_access_cs,
},
{ 0 },
},
};
static struct ble_gatt_chr_def voltage_measure_char_template = {
.uuid = BLE_UUID16_DECLARE(VOLTAGE_CHAR),
.access_cb = gatt_char_access_ev,
.arg = &ev_ctxt,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.min_key_size = 0,
.val_handle = ev_handle,
.descriptors = (struct ble_gatt_dsc_def[]){
[0] = {
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_char_access_ev,
},
{ 0 },
},
};
static struct ble_gatt_chr_def cs_char_array[INPUTS_NUM + 1];
static struct ble_gatt_chr_def rvs_char_array[INPUTS_NUM + 1];
static struct ble_gatt_svc_def gatt_svr_svcs[] = {
[CS_SVC_ID] = {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(METROLOGY_SERVICE),
.characteristics = cs_char_array,
},
[RVS_SVC_ID] = {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(METROLOGY_SERVICE),
.characteristics = rvs_char_array,
},
[SETTINGS_SVC_ID] = {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(CONFIGURATION_SERVICE),
.characteristics = (struct ble_gatt_chr_def[]){
[RFRSH_RATE_ID] = {
.uuid = BLE_UUID16_DECLARE(SAMPLING_RATE_CHAR),
.access_cb = gatt_char_access_sampling_rate,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
.min_key_size = 0,
.val_handle = settings_handle,
.arg = &settings_ctxt[RFRSH_RATE_ID],
.descriptors = (struct ble_gatt_dsc_def[]){
[0] = {
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_char_access_sampling_rate,
},
{ 0 },
}
},
{ 0 },
}
},
{ 0 },
};
static void ble_host_task(){
nimble_port_run();
nimble_port_freertos_deinit();
}
static int ble_gap_event(struct ble_gap_event *event, void* arg);
static void ble_advertise(void){
ESP_ERROR_CHECK(ble_gap_adv_set_fields(&adv_fields));
ESP_ERROR_CHECK(ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL));
}
static void gatt_svr_init(void){
ble_svc_gap_init();
ble_svc_gatt_init();
ESP_ERROR_CHECK(ble_gatts_count_cfg(gatt_svr_svcs));
ESP_ERROR_CHECK(ble_gatts_add_svcs(gatt_svr_svcs));
}
static void ble_on_sync(void){
ble_advertise();
}
static void ble_on_reset(int p){
}
static int ble_gap_event(struct ble_gap_event *event, void* arg){
switch(event->type){
case BLE_GAP_EVENT_CONNECT:
if(event->connect.status)
ble_advertise();
else
conn_handle = event->connect.conn_handle;
break;
case BLE_GAP_EVENT_SUBSCRIBE:
ESP_LOGI(TAG, "Subscribe %d", event->subscribe.attr_handle);
for(int i = 0; i < INPUTS_NUM; i++){
if(event->subscribe.attr_handle == cs_handle[i])
cs_notify_state[i] = event->subscribe.cur_notify;
if(event->subscribe.attr_handle == ev_handle[i])
ev_notify_state[i] = event->subscribe.cur_notify;
}
break;
}
return ESP_OK;
}
// Generate a characteristic for each inputs
static void generate_svc_defs(configuration* conf, measurements* meas){
for(int i = 0; i < INPUTS_NUM; i++){
ev_ctxt[i].conf = conf;
ev_ctxt[i].meas = meas;
cs_ctxt[i].conf = conf;
cs_ctxt[i].meas = meas;
memcpy(&cs_char_array[i], &current_measure_char_template, sizeof(current_measure_char_template));
memcpy(&rvs_char_array[i], &voltage_measure_char_template, sizeof(voltage_measure_char_template));
uint16_t ind = i;
cs_ctxt[i].handle = ind;
cs_char_array[i].arg = &cs_ctxt[i];
cs_char_array[i].val_handle = &cs_handle[i];
ev_ctxt[i].handle = ind;
rvs_char_array[i].arg = &ev_ctxt[i];
rvs_char_array[i].val_handle = &ev_handle[i];
}
memset(&cs_char_array[INPUTS_NUM], 0, sizeof(cs_char_array[INPUTS_NUM]));
memset(&rvs_char_array[INPUTS_NUM], 0, sizeof(rvs_char_array[INPUTS_NUM]));
for(int i = 0; i < SETTINGS_CHRS_NUM; i++){
settings_ctxt[i].conf = conf;
settings_ctxt[i].meas = meas;
}
}
void initBLE(configuration* conf, measurements* meas){
generate_svc_defs(conf, meas);
nimble_port_init();
ble_hs_cfg.sync_cb = ble_on_sync;
ble_hs_cfg.reset_cb = ble_on_reset;
gatt_svr_init();
ESP_ERROR_CHECK(ble_svc_gap_device_name_set("Power Profiler"));
nimble_port_freertos_init(ble_host_task);
}
void notify_update(measurements* meas){
for(int i = 0; i < INPUTS_NUM; i++){
if(cs_notify_state[i]){
ESP_LOGI(TAG, "notify current %d", i);
uint32_t data = meas->amperes[i];
struct os_mbuf* om = ble_hs_mbuf_from_flat(&data, sizeof(data));
ESP_ERROR_CHECK(ble_gattc_notify_custom(conn_handle, cs_handle[i], om));
}
if(ev_notify_state[i]){
ESP_LOGI(TAG, "notify voltage %d", i);
uint32_t data = meas->raw_volt[i];
struct os_mbuf* om = ble_hs_mbuf_from_flat(&data, sizeof(data));
ESP_ERROR_CHECK(ble_gattc_notify_custom(conn_handle, ev_handle[i], om));
}
}
}