// ~/esp-idf/components/bt/bluedroid/api/include/esp_spp_api.h // esp_err_t esp_spp_write(uint32_t handle, int len, uint8_t *p_data); #include "hal.h" #include "format.h" #include "fifo.h" #ifdef WITH_BT_SPP // classic BT #include "esp_bt.h" #include "esp_bt_main.h" #include "esp_gap_bt_api.h" #include "esp_bt_device.h" #include "esp_spp_api.h" static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_CB; static const esp_spp_sec_t sec_mask = ESP_SPP_SEC_AUTHENTICATE; static const esp_spp_role_t role_slave = ESP_SPP_ROLE_SLAVE; static FIFO BT_SPP_TxFIFO; // buffer for console output to be sent over BT static FIFO BT_SPP_RxFIFO; // buffer for BT data to be send to the console static uint32_t BT_SPP_Conn = 0; // BT incoming connection handle static uint32_t BT_SPP_TxCong = 0; // congestion control // static TickType_t BT_SPP_LastTxPush=0; // [ms] // static esp_bd_addr_t BT_SPP_MAC; // BT incoming connection MAC - could be used for pilot id in the flight log // static uint32_t BT_SPP_Wait = 0; // bytes waiting to be written into BT_SPP // static const char *BT_SPP_Welcome = "ESP32 OGN-Tracker\n"; bool BT_SPP_isConnected(void) { return BT_SPP_Conn; } // is a client connected to BT_SPP ? static void setPilotID(esp_bd_addr_t MAC, size_t Len=6) // set PilotID in the parameters from the BT SPP client MAC (thus Pilot's smartphone) { char *ID = Parameters.PilotID; ID[0]='B'; ID[1]='T'; ID[2]='_'; ID+=3; for(int Idx=0; IdxMaxLen) Len=MaxLen; // limit the block size esp_err_t Ret=esp_spp_write(BT_SPP_Conn, Len, (uint8_t *)Data); // write the block to the BT if(Ret!=ESP_OK) return 0; // if an error then give up BT_SPP_TxFIFO.flushReadBlock(Len); // remove the transmitted block from the FIFO return Len; } // return number of transmitted bytes static void esp_spp_cb(esp_spp_cb_event_t Event, esp_spp_cb_param_t *Param) { switch(Event) { case ESP_SPP_INIT_EVT: // [0] esp_bt_dev_set_device_name(Parameters.BTname); // esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); // for older ESP-IDF esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); esp_spp_start_srv(sec_mask, role_slave, 0, "SPP_SERVER"); break; case ESP_SPP_DISCOVERY_COMP_EVT: // [8] break; case ESP_SPP_START_EVT: // [28] SPP server started succesfully break; case ESP_SPP_SRV_OPEN_EVT: // [34] server connection opens: new handle comes BT_SPP_TxFIFO.Clear(); // clear the TxFIFO BT_SPP_Conn = Param->srv_open.handle; // store handle for esp_spp_write() BT_SPP_TxCong = 0; // assume no congestion setPilotID(Param->srv_open.rem_bda, sizeof(esp_bd_addr_t)); // PilotID is now taken from the connected BT client // memcpy(BT_SPP_MAC, Param->srv_open.rem_bda, sizeof(esp_bd_addr_t)); // esp_spp_write(Param->srv_open.handle, BT_SPP_Wait, (uint8_t *)BT_SPP_Welcome); // write Welcome message to the BT_SPP #ifdef DEBUG_PRINT xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "BT_SPP: "); Format_MAC(CONS_UART_Write, Param->srv_open.rem_bda, sizeof(esp_bd_addr_t)); Format_String(CONS_UART_Write, " connected\n"); xSemaphoreGive(CONS_Mutex); #endif break; case ESP_SPP_OPEN_EVT: // [26] connection opens: what's the difference to ESP_SPP_SRV_OPEN_EVT ? // Param->open.handle, Param->open.rem_bda break; case ESP_SPP_CLOSE_EVT: // [27] connection closes for given handle BT_SPP_Conn=0; // clear the handle: signal the BT connection is off clrPilotID(); #ifdef DEBUG_PRINT xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "BT_SPP: \n"); // Format_MAC(CONS_UART_Write, BT_SPP_MAC); Format_String(CONS_UART_Write, " disconnected\n"); xSemaphoreGive(CONS_Mutex); #endif break; case ESP_SPP_DATA_IND_EVT: // [30] data is sent by the client BT_SPP_RxFIFO.Write(Param->data_ind.data, Param->data_ind.len); #ifdef DEBUG_PRINT xSemaphoreTake(CONS_Mutex, portMAX_DELAY); // Param->data_ind.handle, Param->data_ind.data, Param->data_ind.len Format_String(CONS_UART_Write, "BT_SPP: ["); Format_UnsDec(CONS_UART_Write, Param->data_ind.len); Format_String(CONS_UART_Write, "]\n"); xSemaphoreGive(CONS_Mutex); #endif break; case ESP_SPP_CONG_EVT: // [31] congestion on the outgoing data BT_SPP_TxCong = Param->cong.cong; break; case ESP_SPP_WRITE_EVT: // [33] (queued) data has been sent to the client BT_SPP_TxCong = Param->write.cong; break; default: #ifdef DEBUG_PRINT xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "BT_SPP: Event "); Format_UnsDec(CONS_UART_Write, (uint32_t)Event); Format_String(CONS_UART_Write, "\n"); xSemaphoreGive(CONS_Mutex); #endif break; } } static void esp_bt_gap_cb(esp_bt_gap_cb_event_t Event, esp_bt_gap_cb_param_t *Param) { switch(Event) // event numbers are in esp-idf/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h { case ESP_BT_GAP_AUTH_CMPL_EVT: xSemaphoreTake(CONS_Mutex, portMAX_DELAY); if (Param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { Format_String(CONS_UART_Write, "BT_GAP: "); Format_String(CONS_UART_Write, (const char *)Param->auth_cmpl.device_name); Format_String(CONS_UART_Write, " authenticated\n"); } else { Format_String(CONS_UART_Write, "BT_GAP: Authentication failure ("); Format_SignDec(CONS_UART_Write, Param->auth_cmpl.stat); Format_String(CONS_UART_Write, ")\n"); } // ESP_LOGI(SPP_TAG, "authentication success: %s", param->auth_cmpl.device_name); // esp_log_buffer_hex(SPP_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); // ESP_LOGE(SPP_TAG, "authentication failed, status:%d", param->auth_cmpl.stat); xSemaphoreGive(CONS_Mutex); break; case ESP_BT_GAP_PIN_REQ_EVT: /* ESP_LOGI(SPP_TAG, "ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit); if (param->pin_req.min_16_digit) { ESP_LOGI(SPP_TAG, "Input pin code: 0000 0000 0000 0000"); esp_bt_pin_code_t pin_code = {0}; esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code); } else { ESP_LOGI(SPP_TAG, "Input pin code: 1234"); esp_bt_pin_code_t pin_code; pin_code[0] = '1'; pin_code[1] = '2'; pin_code[2] = '3'; pin_code[3] = '4'; esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code); */ break; default: break; } xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "BT_GAP: Event "); Format_UnsDec(CONS_UART_Write, (uint32_t)Event); Format_String(CONS_UART_Write, "\n"); xSemaphoreGive(CONS_Mutex); } int BT_SPP_Read (uint8_t &Byte) // read a character from the BT serial port (buffer) { // if(!BT_SPP_Conn) return 0; return BT_SPP_RxFIFO.Read(Byte); } void BT_SPP_Write (char Byte) // send a character to the BT serial port { if(!BT_SPP_Conn) return; // if BT connection is active BT_SPP_TxFIFO.Write(Byte); // write the byte into the TxFIFO // TickType_t Behind = xTaskGetTickCount() - BT_SPP_LastTxPush; // [ms] // if(Behind>=20) BT_SPP_TxPush(); if( (BT_SPP_TxCong==0) && ( (Byte=='\n') || (BT_SPP_TxFIFO.Full()>=64) ) ) // if no congestion and EOL or 64B waiting already { BT_SPP_TxPush(); } // read a block from TxFIFO ad push it into the BT_SPP } int BT_SPP_Init(void) { esp_err_t Err=ESP_OK; if(Parameters.BTname[0]==0) return Err; esp_bt_controller_config_t BTconf = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); // the default mode is defined by the menuconfig settings BTconf.mode = ESP_BT_MODE_CLASSIC_BT; // Err = esp_bt_controller_mem_release(ESP_BT_MODE_BLE); Err = esp_bt_controller_init(&BTconf); if(Err!=ESP_OK) return Err; Err = esp_bt_controller_enable((esp_bt_mode_t)BTconf.mode); if(Err!=ESP_OK) return Err; // mode must be same as in BTconf // Err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT); if(Err!=ESP_OK) return Err; Err = esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); // this is supposed to release 30kB of RAM Err = esp_bluedroid_init(); if(Err!=ESP_OK) return Err; // init the BT stack Err = esp_bluedroid_enable(); if(Err!=ESP_OK) return Err; // enable the BT stack Err = esp_bt_gap_register_callback(esp_bt_gap_cb); if(Err!=ESP_OK) return Err; Err = esp_spp_register_callback(esp_spp_cb); if(Err!=ESP_OK) return Err; Err = esp_spp_init(esp_spp_mode); if(Err!=ESP_OK) return Err; // Set default parameters for Secure Simple Pairing esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_NONE; // _IO; esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); // Set default parameters for Legacy Pairing: fixed PIN esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_FIXED; esp_bt_pin_code_t pin_code = { '0', '1', '2', '3' }; esp_bt_gap_set_pin(pin_type, 4, pin_code); // set the UUID so this BT device is recognized as a serial port: thanks to Linar for this code esp_bt_cod_t cod; cod.minor = 0b000101; cod.major = 0b00001; cod.service = 0b00000001101; // 0b00000001101 = serial port, 0b00000010000 = generic esp_bt_gap_set_cod(cod, ESP_BT_INIT_COD); return Err; } #endif // WITH_BT_SPP #ifdef WITH_BLE_SPP // BLE BT #include "esp_bt.h" #include "esp_bt_defs.h" #include "esp_bt_main.h" #include "esp_gap_bt_api.h" #include "esp_bt_device.h" #include "esp_gap_ble_api.h" #include "esp_gatts_api.h" #include "esp_gatt_defs.h" #define ESP_SPP_APP_ID 0x56 #define SPP_SVC_INST_ID 0 // the instance id of the service #define SPP_DATA_MAX_LEN (512) #define SPP_CMD_MAX_LEN (20) #define SPP_STATUS_MAX_LEN (20) #define SPP_DATA_BUFF_MAX_LEN (1024) // SPP Service static const uint16_t spp_service_uuid = 0xABF0; // Characteristic UUID #define ESP_GATT_UUID_SPP_DATA_RECEIVE 0xABF1 #define ESP_GATT_UUID_SPP_DATA_NOTIFY 0xABF2 #define ESP_GATT_UUID_SPP_COMMAND_RECEIVE 0xABF3 #define ESP_GATT_UUID_SPP_COMMAND_NOTIFY 0xABF4 static esp_ble_adv_params_t spp_adv_params = { .adv_int_min = 0x20, .adv_int_max = 0x40, .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, }; enum { SPP_IDX_SVC, SPP_IDX_SPP_DATA_RECV_CHAR, SPP_IDX_SPP_DATA_RECV_VAL, SPP_IDX_SPP_DATA_NOTIFY_CHAR, SPP_IDX_SPP_DATA_NTY_VAL, SPP_IDX_SPP_DATA_NTF_CFG, SPP_IDX_SPP_COMMAND_CHAR, SPP_IDX_SPP_COMMAND_VAL, SPP_IDX_SPP_STATUS_CHAR, SPP_IDX_SPP_STATUS_VAL, SPP_IDX_SPP_STATUS_CFG, SPP_IDX_NB // the number of attribute to be added to the service database }; static uint16_t spp_handle_table[SPP_IDX_NB]; #define CHAR_DECLARATION_SIZE (sizeof(uint8_t)) static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE; static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE; static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY; static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE_NR|ESP_GATT_CHAR_PROP_BIT_READ; // SPP Service - data receive characteristic, read&write without response static const uint16_t spp_data_receive_uuid = ESP_GATT_UUID_SPP_DATA_RECEIVE; static const uint8_t spp_data_receive_val[20] = {0x00}; // SPP Service - data notify characteristic, notify&read static const uint16_t spp_data_notify_uuid = ESP_GATT_UUID_SPP_DATA_NOTIFY; static const uint8_t spp_data_notify_val[20] = {0x00}; static const uint8_t spp_data_notify_ccc[2] = {0x00, 0x00}; // SPP Service - command characteristic, read&write without response static const uint16_t spp_command_uuid = ESP_GATT_UUID_SPP_COMMAND_RECEIVE; static const uint8_t spp_command_val[10] = {0x00}; // SPP Service - status characteristic, notify&read static const uint16_t spp_status_uuid = ESP_GATT_UUID_SPP_COMMAND_NOTIFY; static const uint8_t spp_status_val[10] = {0x00}; static const uint8_t spp_status_ccc[2] = {0x00, 0x00}; // Full HRS Database Description - Used to add attributes into the database static const esp_gatts_attr_db_t spp_gatt_db[SPP_IDX_NB] = { // SPP - Service Declaration [SPP_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, sizeof(spp_service_uuid), sizeof(spp_service_uuid), (uint8_t *)&spp_service_uuid}}, // SPP - data receive characteristic Declaration [SPP_IDX_SPP_DATA_RECV_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}}, // SPP - data receive characteristic Value [SPP_IDX_SPP_DATA_RECV_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_data_receive_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, SPP_DATA_MAX_LEN,sizeof(spp_data_receive_val), (uint8_t *)spp_data_receive_val}}, // SPP - data notify characteristic Declaration [SPP_IDX_SPP_DATA_NOTIFY_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}}, // SPP - data notify characteristic Value [SPP_IDX_SPP_DATA_NTY_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_data_notify_uuid, ESP_GATT_PERM_READ, SPP_DATA_MAX_LEN, sizeof(spp_data_notify_val), (uint8_t *)spp_data_notify_val}}, // SPP - data notify characteristic - Client Characteristic Configuration Descriptor [SPP_IDX_SPP_DATA_NTF_CFG] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, sizeof(uint16_t),sizeof(spp_data_notify_ccc), (uint8_t *)spp_data_notify_ccc}}, // SPP - command characteristic Declaration [SPP_IDX_SPP_COMMAND_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}}, // SPP - command characteristic Value [SPP_IDX_SPP_COMMAND_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_command_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, SPP_CMD_MAX_LEN,sizeof(spp_command_val), (uint8_t *)spp_command_val}}, // SPP - status characteristic Declaration [SPP_IDX_SPP_STATUS_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}}, // SPP - status characteristic Value [SPP_IDX_SPP_STATUS_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_status_uuid, ESP_GATT_PERM_READ, SPP_STATUS_MAX_LEN,sizeof(spp_status_val), (uint8_t *)spp_status_val}}, // SPP - status characteristic - Client Characteristic Configuration Descriptor [SPP_IDX_SPP_STATUS_CFG] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, sizeof(uint16_t),sizeof(spp_status_ccc), (uint8_t *)spp_status_ccc}}, } ; static FIFO BT_SPP_TxFIFO; // buffer for console output to be sent over BT static FIFO BT_SPP_RxFIFO; // buffer for BT data to be send to the console // static uint32_t BT_SPP_Conn = 0; // BT incoming connection handle // static uint32_t BT_SPP_TxCong = 0; // congestion control static uint16_t spp_mtu_size = 23; static uint16_t spp_conn_id = 0xffff; static esp_gatt_if_t spp_gatts_if = 0xff; static bool is_connected = false; static esp_bd_addr_t spp_remote_bda = { 0x0, }; bool BT_SPP_isConnected(void) { return is_connected; } // is a client connected to BT_SPP ? static void setPilotID(esp_bd_addr_t MAC, size_t Len=6) // set PilotID in the parameters from the BT SPP client MAC (thus Pilot's smartphone) { char *ID = Parameters.PilotID; ID[0]='B'; ID[1]='T'; ID[2]='_'; ID+=3; for(int Idx=0; IdxMaxLen) Len=MaxLen; // limit the block size // esp_err_t Ret=esp_spp_write(BT_SPP_Conn, Len, (uint8_t *)Data); // write the block to the BT // if(Ret!=ESP_OK) return 0; // if an error then give up BT_SPP_TxFIFO.flushReadBlock(Len); // remove the transmitted block from the FIFO return Len; } // return number of transmitted bytes static uint8_t spp_adv_data_len = 23; static uint8_t spp_adv_data[25] = { 0x02, 0x01, 0x06, 0x03, 0x03, 0xF0, 0xAB, 0x0F, 0x09, 0x45, 0x53, 0x50, 0x5f, 0x53, 0x50, 0x50, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x00, 0x00 } ; // ESP_SPP_SERVER // static esp_ble_adv_data_t spp_adv_data = // { .include_name = true // }; static void esp_ble_gatts_cb(esp_gatts_cb_event_t Event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *Param) { // esp_ble_gatts_cb_param_t *p_data = (esp_ble_gatts_cb_param_t *)Param; switch(Event) // event numbers: esp-idf/components/bt/host/bluedroid/api/include/api/esp_gatts_api.h { case ESP_GATTS_REG_EVT: // #0 { // esp_ble_gap_set_device_name(Parameters.BTname); // esp_ble_gap_config_adv_data(&spp_adv_data); int NameLen = strlen(Parameters.BTname); if(NameLen>16) NameLen=16; memcpy(spp_adv_data+9, Parameters.BTname, NameLen); spp_adv_data[7]=NameLen+1; spp_adv_data_len=9+NameLen; esp_ble_gap_config_adv_data_raw(spp_adv_data, spp_adv_data_len); esp_ble_gatts_create_attr_tab(spp_gatt_db, gatts_if, SPP_IDX_NB, SPP_SVC_INST_ID); break; } case ESP_GATTS_CREAT_ATTR_TAB_EVT: // #22 if(Param->add_attr_tab.status != ESP_GATT_OK) break; if(Param->add_attr_tab.num_handle != SPP_IDX_NB) break; memcpy(spp_handle_table, Param->add_attr_tab.handles, sizeof(spp_handle_table)); esp_ble_gatts_start_service(spp_handle_table[SPP_IDX_SVC]); break; case ESP_GATTS_START_EVT: // #12 break; case ESP_GATTS_STOP_EVT: // break; case ESP_GATTS_UNREG_EVT: // #6 break; case ESP_GATTS_CONNECT_EVT: // #14 = GATT client connect spp_conn_id = Param->connect.conn_id; spp_gatts_if = gatts_if; is_connected = true; memcpy(&spp_remote_bda, &Param->connect.remote_bda, sizeof(esp_bd_addr_t)); break; case ESP_GATTS_DISCONNECT_EVT: // #15 = GATT client disconnect is_connected = false; esp_ble_gap_start_advertising(&spp_adv_params); break; case ESP_GATTS_MTU_EVT: // #4 = set MTU complete spp_mtu_size = Param->mtu.mtu; break; case ESP_GATTS_READ_EVT: // #1 = request read operation break; case ESP_GATTS_WRITE_EVT: // #2 = request write operation break; case ESP_GATTS_EXEC_WRITE_EVT: // #3 = request execute write opearation // if(Param->exec_write.exec_write_flag) { } break; default: break; } xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "BLE_GATTS: Event "); Format_UnsDec(CONS_UART_Write, (uint32_t)Event); Format_String(CONS_UART_Write, "."); Format_UnsDec(CONS_UART_Write, (uint32_t)gatts_if); Format_String(CONS_UART_Write, "\n"); xSemaphoreGive(CONS_Mutex); } static void esp_ble_gap_cb(esp_gap_ble_cb_event_t Event, esp_ble_gap_cb_param_t *Param) { switch(Event) // event numbers: esp-idf/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h { case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: esp_ble_gap_start_advertising(&spp_adv_params); break; case ESP_GAP_BLE_SEC_REQ_EVT: // #10 esp_ble_gap_security_rsp(Param->ble_security.ble_req.bd_addr, true); break; case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: // #20 break; case ESP_GAP_BLE_NC_REQ_EVT: // #16 = Numeric Comparison REQuest break; case ESP_GAP_BLE_AUTH_CMPL_EVT: // #8 = AUTHentication CoMPLete break; case ESP_GAP_BLE_KEY_EVT: // #9 = break; case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: // #6 = starting advertise complete break; default: break; } xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "BLE_GAP: Event "); Format_UnsDec(CONS_UART_Write, (uint32_t)Event); Format_String(CONS_UART_Write, "\n"); xSemaphoreGive(CONS_Mutex); } int BT_SPP_Read (uint8_t &Byte) // read a character from the BT serial port (buffer) { // if(!BT_SPP_Conn) return 0; return BT_SPP_RxFIFO.Read(Byte); } void BT_SPP_Write (char Byte) // send a character to the BT serial port { if(!is_connected) return; // if BT connection is active BT_SPP_TxFIFO.Write(Byte); // write the byte into the TxFIFO // if( (BT_SPP_TxCong==0) && ( (Byte=='\n') || (BT_SPP_TxFIFO.Full()>=64) ) ) // if no congestion and EOL or 64B waiting $ // { BT_SPP_TxPush(); } // read a block from TxFIFO ad push it into$ } int BT_SPP_Init(void) { esp_err_t Err=ESP_OK; if(Parameters.BTname[0]==0) return Err; esp_bt_controller_config_t BTconf = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); // the default mode is defined by the men$ BTconf.mode = ESP_BT_MODE_BLE; // Err = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); Err = esp_bt_controller_init(&BTconf); if(Err!=ESP_OK) return Err; Err = esp_bt_controller_enable((esp_bt_mode_t)BTconf.mode); if(Err!=ESP_OK) return Err; // mode must be same as in BTconf Err = esp_bluedroid_init(); if(Err!=ESP_OK) return Err; // init the BT stack Err = esp_bluedroid_enable(); if(Err!=ESP_OK) return Err; // enable the BT stack Err = esp_ble_gap_register_callback(esp_ble_gap_cb); if(Err!=ESP_OK) return Err; // GAP callback Err = esp_ble_gatts_register_callback(esp_ble_gatts_cb); if(Err!=ESP_OK) return Err; // GATTS callback Err = esp_ble_gatts_app_register(ESP_SPP_APP_ID); if(Err!=ESP_OK) return Err; esp_ble_io_cap_t IOcap = ESP_IO_CAP_NONE; // no input and no output capabilities esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &IOcap, sizeof(IOcap)); return Err; } #endif // WITH_BLE_SPP // ========================================================================================================