co2-firmware/components/BTlib/BTlib_nimble.c
2022-12-20 17:24:27 +01:00

627 lines
19 KiB
C

#include "battery.h"
#include "host/ble_att.h"
#include "host/ble_gap.h"
#include "host/ble_gatt.h"
#include "host/ble_uuid.h"
#include "nimble/hci_common.h"
#include "os/os_mbuf.h"
#include "sdkconfig.h"
#include <stdint.h>
#ifdef CONFIG_BT_NIMBLE_ENABLED
#include "BTlib_nimble.h"
#include "nimble/ble.h"
#include "esp_nimble_hci.h"
#include "nimble/nimble_port.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "nimble/nimble_port_freertos.h"
static configuration_data_t* main_app_conf;
static uint8_t ble_addr_type;
static uint16_t conn_handle;
static uint16_t es_handle[ES_CHAR_NB];
static uint16_t batt_handle[BATT_CHAR_NB];
static uint16_t pow_handle[POWER_CHAR_NB];
static uint16_t magfield_handle[MAGFIELD_CHAR_NB];
static uint8_t notify_state[ES_CHAR_NB];
static int ble_gap_event(struct ble_gap_event *event, void* arg);
static int gatt_svr_chr_access_co2(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_temp(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_hum(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_batt_level(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_power_voltage(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_power_pin(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_power_pout(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_power_format(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_magfield_x(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_magfield_y(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_magfield_z(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_chr_access_magfield_format(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg);
static int gatt_svr_init(void);
ES_char_descr_t CO2_char_descr = {
.flags = 0, // RFU
.sampling_function = ES_SAMPLING_FUNC_INSTANT,
.measurement_period = {30,0,0},
.update_interval = {30,0,0},
.application = ES_APP_AIR,
.measurement_uncertainty = 10,
};
ES_char_descr_t temp_char_descr = {
.flags = 0, // RFU
.sampling_function = ES_SAMPLING_FUNC_INSTANT,
.measurement_period = {30,0,0},
.update_interval = {30,0,0},
.application = ES_APP_AIR,
.measurement_uncertainty = 5,
};
ES_char_descr_t hum_char_descr = {
.flags = 0, // RFU
.sampling_function = ES_SAMPLING_FUNC_INSTANT,
.measurement_period = {30,0,0},
.update_interval = {30,0,0},
.application = ES_APP_AIR,
.measurement_uncertainty = 30,
};
char_pres_format_t CO2_char_pres_format = {
.format = FORMAT_INT16,
.exponent = 0,
.unit = PPM_UNIT_UUID,
.namespc = 1,
.descr = NSP_DESC_MAIN,
};
char_pres_format_t batt_level_char_pres_format = {
.format = FORMAT_UINT8,
.exponent = 0,
.unit = PERCENT_UNIT_UUID,
.namespc = 1,
.descr = NSP_DESC_MAIN,
};
char_pres_format_t voltage_char_pres_format = {
.format = FORMAT_UINT16,
.exponent = -3,
.unit = VOLTAGE_UNIT_UUID,
.namespc = 1,
.descr = NSP_DESC_MAIN,
};
char_pres_format_t power_char_pres_format = {
.format = FORMAT_INT16,
.exponent = -3,
.unit = POWER_UNIT_UUID,
.namespc = 1,
.descr = NSP_DESC_MAIN,
};
char_pres_format_t magfield_char_pres_format = {
.format = FORMAT_INT32,
.exponent = -12,
.unit = TESLA_UNIT_UUID,
.namespc = 1,
.descr = NSP_DESC_INSIDE,
};
struct ble_hs_adv_fields adv_fields = {
.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP,
.tx_pwr_lvl_is_present = 1,
.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO,
.name = (uint8_t*)DEFAULT_NAME,
.name_len = DEFAULT_NAME_LEN,
.name_is_complete = 1,
.appearance = CO2_SENSOR_APPEARANCE,
.appearance_is_present = 1,
};
struct ble_gap_adv_params adv_params = {
.conn_mode = BLE_GAP_CONN_MODE_UND,
.disc_mode = BLE_GAP_DISC_MODE_GEN,
.itvl_min = 1000,
.itvl_max = 2000,
//.itvl_max = 0x4000,
};
struct ble_gap_upd_params conn_params = {
.itvl_min = 100, //Minimum value for connection interval in 1.25ms units min=6 (7.5ms) max=3200 (4s)
.itvl_max = 1000, //3200,
.latency = 0,
.supervision_timeout = 3200, //Supervision timeout in 10ms units min=10 max=3200
.min_ce_len = 0, //Minimum length of connection event in 0.625ms units
.max_ce_len = 10,
};
static struct ble_gatt_svc_def gatt_svr_svcs[] = {
[ES_SVC_IDX] = {
// Environmental sensing service
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(ENVIRONMENTAL_SENSING_UUID),
.characteristics = (struct ble_gatt_chr_def[]){
// CO2
[ES_CHAR_CO2] = {
.uuid = BLE_UUID16_DECLARE(CHAR_CO2_UUID),
.access_cb = gatt_svr_chr_access_co2,
.val_handle = &es_handle[ES_CHAR_CO2],
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(ES_MEASUREMENT_UUID),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_co2,
},
{
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_co2,
},
{ 0 },
},
},
// TEMP
[ES_CHAR_TEMP] = {
.uuid = BLE_UUID16_DECLARE(CHAR_TEMP_UUID),
.access_cb = gatt_svr_chr_access_temp,
.val_handle = &es_handle[ES_CHAR_TEMP],
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(ES_MEASUREMENT_UUID),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_temp,
},
{ 0 },
},
},
// HUMIDITY
[ES_CHAR_HUM] = {
.uuid = BLE_UUID16_DECLARE(CHAR_HUM_UUID),
.access_cb = gatt_svr_chr_access_hum,
.val_handle = &es_handle[ES_CHAR_HUM],
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(ES_MEASUREMENT_UUID),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_hum,
},
{ 0 },
},
},
{ 0 },
},
},
[BATT_SVC_IDX] = {
// Battery service
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(BATT_SVC_UUID),
.characteristics = (struct ble_gatt_chr_def[]){
[BATT_CHAR_LEVEL] = {
.uuid = BLE_UUID16_DECLARE(BATT_LEVEL_UUID),
.access_cb = gatt_svr_chr_access_batt_level,
.val_handle = &batt_handle[BATT_CHAR_LEVEL],
.flags = BLE_GATT_CHR_F_READ,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_batt_level,
},
{ 0 },
},
},
{ 0 },
},
},
[POWER_SVC_IDX] = {
// power status service
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID32_DECLARE(POWER_SVC_UUID),
.characteristics = (struct ble_gatt_chr_def[]){
[POWER_CHAR_VOLTAGE] = {
.uuid = BLE_UUID16_DECLARE(BATT_VOLTAGE_UUID),
.access_cb = gatt_svr_chr_access_power_voltage,
.val_handle = &pow_handle[POWER_CHAR_VOLTAGE],
.flags = BLE_GATT_CHR_F_READ,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_power_voltage,
},
{ 0 },
},
},
[POWER_CHAR_PIN] = {
.uuid = BLE_UUID16_DECLARE(ALIM_POWER_IN_UUID),
.access_cb = gatt_svr_chr_access_power_pin,
.val_handle = &pow_handle[POWER_CHAR_PIN],
.flags = BLE_GATT_CHR_F_READ,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_power_format,
},
{ 0 },
},
},
[POWER_CHAR_POUT] = {
.uuid = BLE_UUID16_DECLARE(ALIM_POWER_OUT_UUID),
.access_cb = gatt_svr_chr_access_power_pout,
.val_handle = &pow_handle[POWER_CHAR_POUT],
.flags = BLE_GATT_CHR_F_READ,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_power_format,
},
{ 0 },
},
},
{ 0 },
},
},
[MAGFIELD_SVC_UUID] = {
// magnetic field measure (debug?)
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID32_DECLARE(MAGFIELD_SVC_UUID),
.characteristics = (struct ble_gatt_chr_def[]){
[MAGFIELD_CHAR_X] = {
.uuid = BLE_UUID16_DECLARE(MAGFIELD_X_UUID),
.access_cb = gatt_svr_chr_access_magfield_x,
.val_handle = &magfield_handle[MAGFIELD_CHAR_X],
.flags = BLE_GATT_CHR_F_READ,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_magfield_format,
},
{ 0 }
},
},
[MAGFIELD_CHAR_Y] = {
.uuid = BLE_UUID16_DECLARE(MAGFIELD_Y_UUID),
.access_cb = gatt_svr_chr_access_magfield_y,
.val_handle = &magfield_handle[MAGFIELD_CHAR_Y],
.flags = BLE_GATT_CHR_F_READ,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_magfield_format,
},
{ 0 }
},
},
[MAGFIELD_CHAR_Z] = {
.uuid = BLE_UUID16_DECLARE(MAGFIELD_Z_UUID),
.access_cb = gatt_svr_chr_access_magfield_z,
.val_handle = &magfield_handle[MAGFIELD_CHAR_Z],
.flags = BLE_GATT_CHR_F_READ,
.descriptors = (struct ble_gatt_dsc_def[]){
{
.uuid = BLE_UUID16_DECLARE(CHAR_PRES_FORMAT),
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svr_chr_access_magfield_format,
},
{ 0 }
},
},
{ 0 },
},
},
{ 0 },
};
static int gatt_svr_chr_access_co2(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg){
int rc = 0;
ESP_LOGI(NIMBLE_LOG_TAG, "co2 access evt");
switch(ctxt->op){
case BLE_GATT_ACCESS_OP_READ_CHR:
rc = os_mbuf_append(ctxt->om, &main_app_conf->measure->co2, sizeof(main_app_conf->measure->co2));
break;
case BLE_GATT_ACCESS_OP_READ_DSC:{
uint16_t uuid = ble_uuid_u16(ctxt->dsc->uuid);
switch(uuid){
case ES_MEASUREMENT_UUID:
rc = os_mbuf_append(ctxt->om, &CO2_char_descr, 11); // hardcoded size 'cause struct gets padded to 12bytes
break;
case CHAR_PRES_FORMAT:
rc = os_mbuf_append(ctxt->om, &CO2_char_pres_format, 7);
}
}
break;
}
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static int gatt_svr_chr_access_temp(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg){
int rc = 0;
ESP_LOGI(NIMBLE_LOG_TAG, "temp access evt");
switch(ctxt->op){
case BLE_GATT_ACCESS_OP_READ_CHR:
{
int16_t raw_temp = main_app_conf->measure->temperature;
int16_t temp = raw_temp/10;
rc = os_mbuf_append(ctxt->om, &temp, sizeof(temp));
}
break;
case BLE_GATT_ACCESS_OP_READ_DSC:
rc = os_mbuf_append(ctxt->om, &temp_char_descr, 11); // hardcoded size 'cause struct gets padded to 12bytes
break;
}
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static int gatt_svr_chr_access_hum(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg){
int rc = 0;
ESP_LOGI(NIMBLE_LOG_TAG, "hum access evt");
switch(ctxt->op){
case BLE_GATT_ACCESS_OP_READ_CHR:
{
int32_t raw_hum = main_app_conf->measure->humidity;
int16_t hum = raw_hum/10;
rc = os_mbuf_append(ctxt->om, &hum, sizeof(hum));
}
break;
case BLE_GATT_ACCESS_OP_READ_DSC:
rc = os_mbuf_append(ctxt->om, &hum_char_descr, 11); // hardcoded size 'cause struct gets padded to 12bytes
break;
}
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static int gatt_svr_chr_access_batt_level(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg){
int rc = 0;
ESP_LOGI(NIMBLE_LOG_TAG, "batt_level access event");
switch(ctxt->op){
case BLE_GATT_ACCESS_OP_READ_CHR:
{
update_battery_level(main_app_conf->battery_conf);
uint8_t battery_level = main_app_conf->battery_conf->data->battery_percent;
rc = os_mbuf_append(ctxt->om, &battery_level, sizeof(battery_level));
}
break;
case BLE_GATT_ACCESS_OP_READ_DSC:
{
uint16_t uuid = ble_uuid_u16(ctxt->dsc->uuid);
switch(uuid){
case CHAR_PRES_FORMAT:
rc = os_mbuf_append(ctxt->om, &batt_level_char_pres_format, 7);
break;
}
}
break;
}
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static int gatt_svr_chr_access_power_voltage(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg){
int rc = 0;
ESP_LOGI(NIMBLE_LOG_TAG, "batt voltage access event");
switch(ctxt->op){
case BLE_GATT_ACCESS_OP_READ_CHR:
{
update_battery_level(main_app_conf->battery_conf);
uint16_t battery_voltage = main_app_conf->battery_conf->data->battery_mv;
rc = os_mbuf_append(ctxt->om, &battery_voltage, sizeof(battery_voltage));
}
break;
case BLE_GATT_ACCESS_OP_READ_DSC:
{
uint16_t uuid = ble_uuid_u16(ctxt->dsc->uuid);
switch(uuid){
case CHAR_PRES_FORMAT:
rc = os_mbuf_append(ctxt->om, &voltage_char_pres_format, 7);
break;
}
}
break;
}
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static int gatt_svr_chr_access_power_pin(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg){
int rc = 0;
ESP_LOGI(NIMBLE_LOG_TAG, "batt power access event");
switch(ctxt->op){
case BLE_GATT_ACCESS_OP_READ_CHR:
{
update_power_inout_readings(main_app_conf->power_conf->data);
uint16_t powerin = main_app_conf->power_conf->data->pin;
rc = os_mbuf_append(ctxt->om, &powerin, sizeof(powerin));
}
break;
case BLE_GATT_ACCESS_OP_READ_DSC:
{
uint16_t uuid = ble_uuid_u16(ctxt->dsc->uuid);
switch(uuid){
case CHAR_PRES_FORMAT:
rc = os_mbuf_append(ctxt->om, &voltage_char_pres_format, 7);
break;
}
}
break;
}
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static int gatt_svr_chr_access_power_pout(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg){
int rc = 0;
ESP_LOGI(NIMBLE_LOG_TAG, "batt power access event");
switch(ctxt->op){
case BLE_GATT_ACCESS_OP_READ_CHR:
{
update_power_inout_readings(main_app_conf->power_conf->data);
uint16_t powerout = main_app_conf->power_conf->data->pout;
rc = os_mbuf_append(ctxt->om, &powerout, sizeof(powerout));
}
break;
case BLE_GATT_ACCESS_OP_READ_DSC:
{
uint16_t uuid = ble_uuid_u16(ctxt->dsc->uuid);
switch(uuid){
case CHAR_PRES_FORMAT:
rc = os_mbuf_append(ctxt->om, &voltage_char_pres_format, 7);
break;
}
}
break;
}
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static int gatt_svr_chr_access_power_format(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg){
int rc = 0;
if(ctxt->op != BLE_GATT_ACCESS_OP_READ_DSC){
ESP_LOGE(NIMBLE_LOG_TAG, "wrong callback called");
}
ESP_LOGI(NIMBLE_LOG_TAG, "batt voltage pres access event");
uint16_t uuid = ble_uuid_u16(ctxt->dsc->uuid);
switch(uuid){
case CHAR_PRES_FORMAT:
rc = os_mbuf_append(ctxt->om, &power_char_pres_format, 7);
break;
}
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static void ble_advertise(void){
main_app_conf->sensor->enabled = false;
ESP_ERROR_CHECK(ble_gap_adv_set_fields(&adv_fields));
ESP_ERROR_CHECK(ble_gap_adv_start(ble_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL));
}
static int ble_gap_event(struct ble_gap_event *event, void* arg){
switch(event->type){
case BLE_GAP_EVENT_CONNECT:
ESP_LOGI(NIMBLE_LOG_TAG, "connect event");
if(event->connect.status)
ble_advertise();
else {
conn_handle = event->connect.conn_handle;
ESP_ERROR_CHECK(ble_gap_update_params(event->connect.conn_handle, &conn_params));
main_app_conf->sensor->enabled = true;
}
break;
case BLE_GAP_EVENT_DISCONNECT:
ESP_LOGI(NIMBLE_LOG_TAG, "disconnect event");
ble_advertise();
break;
case BLE_GAP_EVENT_ADV_COMPLETE:
ESP_LOGI(NIMBLE_LOG_TAG, "adv complete");
ble_advertise();
break;
case BLE_GAP_EVENT_SUBSCRIBE:
ESP_LOGI(NIMBLE_LOG_TAG, "subscribe event notify : %d", event->subscribe.attr_handle);
for(int i=0; i<ES_CHAR_NB; i++)
if(event->subscribe.attr_handle == es_handle[i]){
ESP_LOGI(NIMBLE_LOG_TAG, "enabling notifs for %d", i);
notify_state[i] = event->subscribe.cur_notify;
}
break;
case BLE_GAP_EVENT_MTU:
ESP_LOGI(NIMBLE_LOG_TAG, "MTU event");
break;
}
return ESP_OK;
}
static int gatt_svr_init(void){
ble_svc_gap_init();
ble_svc_gatt_init();
int res;
res = ble_gatts_count_cfg(gatt_svr_svcs);
if(res)
return res;
res = ble_gatts_add_svcs(gatt_svr_svcs);
return res;
}
static void ble_on_sync(void){
//TODO
ESP_LOGI(NIMBLE_LOG_TAG, "on sync event");
ble_advertise();
}
static void ble_on_reset(int reason){
ESP_LOGI(NIMBLE_LOG_TAG, "on reset event %d", reason);
}
static void ble_host_task(void* param){
nimble_port_run();
// return on stop
nimble_port_freertos_deinit();
}
void initBle(configuration_data_t* main_conf){
main_app_conf = main_conf;
ESP_LOGI("MAIN", "%s\n", main_conf->hostname);
adv_fields.name = (uint8_t*)&main_conf->hostname;
adv_fields.name_len = strlen(main_conf->hostname);
//ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
nimble_port_init();
ble_hs_cfg.sync_cb = ble_on_sync;
ble_hs_cfg.reset_cb = ble_on_reset;
ESP_ERROR_CHECK(gatt_svr_init());
ESP_ERROR_CHECK(ble_svc_gap_device_name_set(main_conf->hostname));
nimble_port_freertos_init(ble_host_task);
}
void ble_sensor_notify(){
if(notify_state[ES_CHAR_CO2]){
ESP_LOGI(NIMBLE_LOG_TAG, "notify co2");
uint16_t co2 = main_app_conf->measure->co2;
struct os_mbuf* om = ble_hs_mbuf_from_flat(&co2, sizeof(co2));
ESP_ERROR_CHECK(ble_gattc_notify_custom(conn_handle, es_handle[ES_CHAR_CO2], om));
}
if(notify_state[ES_CHAR_TEMP]){
ESP_LOGI(NIMBLE_LOG_TAG, "notify temp");
int16_t temp = main_app_conf->measure->temperature / 10;
struct os_mbuf* om = ble_hs_mbuf_from_flat(&temp, sizeof(temp));
ESP_ERROR_CHECK(ble_gattc_notify_custom(conn_handle, es_handle[ES_CHAR_TEMP], om));
}
if(notify_state[ES_CHAR_HUM]){
ESP_LOGI(NIMBLE_LOG_TAG, "notify hum");
int16_t hum = main_app_conf->measure->humidity / 10;
struct os_mbuf* om = ble_hs_mbuf_from_flat(&hum, sizeof(hum));
ESP_ERROR_CHECK(ble_gattc_notify_custom(conn_handle, es_handle[ES_CHAR_HUM], om));
}
}
#endif