Split off the Bluetooth serial port code to prepare for BLE

pull/39/head
Pawel Jalocha 2021-05-07 20:30:32 +01:00
rodzic 0a985e4789
commit c6f4f5204d
11 zmienionych plików z 313 dodań i 282 usunięć

Wyświetl plik

@ -4,9 +4,7 @@
#define DEFAULT_PPSdelay 100
#define DEFAULT_FreqPlan 0
// #define WITH_HELTEC // HELTEC module: PCB LED on GPI025
// #define WITH_HELTEC_V2 // HELTEC module v2
// #define WITH_TTGO // TTGO module: PCB LED on GPIO2, GPIO25 free to use as DAC2 output
// #define WITH_TBEAM // T-Beam module
// #define WITH_TBEAM_V10 // T-Beam module
@ -15,20 +13,19 @@
// #define WITH_ILI9341 // 320x240 M5stack
// #define WITH_ST7789 // IPS 240x240 ST7789
// #define WITH_TFT_LCD // TFT LCD
// #define WITH_TFT_LCD // TFT LCD (incomplete)
// #define WITH_OLED // OLED display on the I2C: some TTGO modules are without OLED display
// #define WITH_OLED2 // 2nd OLED display, I2C address next higher
#define WITH_U8G2_OLED // I2C OLED through the U8g2 library
#define WITH_U8G2_SH1106 // correct controller for the bigger OLED
#define WITH_U8G2_FLIP // flip the OLED screen (rotate by 180deg)
#define WITH_U8G2_SH1106 // the bigger OLED controller
#define WITH_U8G2_FLIP // flip the OLED screen
#define WITH_RFM95 // RF chip selection: both HELTEC and TTGO use sx1276 which is same as RFM95
#define WITH_RFM95 // RF chip selection: FollowMe, HELTEC and TTGO use sx1276 which is same as RFM95 module
#define WITH_LORAWAN
// #define WITH_SLEEP // with software sleep mode controlled by the long-press on the button
// #define WITH_AXP // with AXP192 power controller (T-BEAM V1.0)
#define WITH_BQ // with BQ24295 power controller (FollowMe)
#define WITH_BQ // with BQ24295 power controller (new FollowMe)
// #define WITH_LED_RX
// #define WITH_LED_TX
@ -43,21 +40,15 @@
// #define WITH_MAVLINK
// #define WITH_GPS_UBX_PASS // to pass directly UBX packets to/from GPS
// #define WITH_GPS_NMEA_PASS // to pass directly NMEA to/from GPS
// #define WITH_GPS_NMEA_PASS // to pass directly NMEA to/from GPS
// #define WITH_BMP180 // BMP180 pressure sensor
// #define WITH_BMP280 // BMP280 pressure sensor
#define WITH_BME280 // BMP280 with humidity (but still works with BMP280)
#define WITH_BME280 // BMP280 with humidity (still works with BMP280)
// #define WITH_MS5607 // MS5607 pressure sensor
// #define WITH_MS5611 // MS5611 pressure sensor
// #define WITH_BMX055 // BMX055 magnetic and IMU sensor
// #define WITH_FANET
#define WITH_PFLAA // PFLAU and PFLAA for compatibility with XCsoar and LK8000
// #define WITH_POGNT
// #define WITH_GDL90
// #define WITH_PGAV5
#define WITH_PFLAA // $PFLAU and $PFLAA for compatibility with XCsoar and LK8000
// #define WITH_POGNT // $POGNT for traffic info
#define WITH_LOOKOUT
#define WITH_CONFIG // interpret the console input: $POGNS to change parameters
@ -68,21 +59,27 @@
// #define WITH_KNOB
// #define WITH_VARIO
#define WITH_LORAWAN // LoRaWAN TTN connectivity
// #define WITH_PAW // beta-code for PilotAware transmission
// #define WITH_FANET // beta-code for FANET transmissions, but breaks LoRaWAN, to be improved
#define WITH_AP // create WiFi Access Point for data, setup and log files
#define WITH_AP_BUTTON // activate Access Point only when button pressed at startup
#define WITH_HTTP // HTTP server, works with AP and Stratux
#define WITH_BT_SPP // (classic) Bluetooth serial port for smartphone/tablet link
// #define WITH_STRATUX // beta-code: connect to Stratux WiFi and send GPS and traffic info
// #define WITH_APRS // alpha-code: attempt to connect to the wifi router for uploading the log files to APRS
#define WITH_SD // use the SD card in SPI mode and FAT file system
#define WITH_SPIFFS_FAT
#define WITH_SPIFFS // use SPIFFS file system in Flash
#define WITH_SPIFFS_FAT // FAT system in internal flash
#define WITH_LOG // log own positions and other received to SPIFFS
#define WITH_SDLOG // log own position and other data to uSD card
#define WITH_LOG // log own positions and other received to SPIFFS and possibly to uSD
#define WITH_SDLOG //
// #define WITH_BT_SPP // Bluetooth serial port for smartphone/tablet link
// #define WITH_STRATUX // connect to Stratux as a client to send GPS and Pressure data
#define WITH_AP // WiFi AcessPoint and TCP decoder port
// #define WITH_APRS // attempt to connect to the wifi router and then APRS
// #define WITH_ENCRYPT // Encrypt (optionally) the position
#if defined(WITH_STRATUX) || defined(WITH_APRS) || defined(WITH_AP)
#define WITH_WIFI
#endif
// #define WITH_ENCRYPT // Encrypt (optionally) the position

Wyświetl plik

@ -17,14 +17,15 @@
// #define WITH_OLED // OLED display on the I2C: some TTGO modules are without OLED display
// #define WITH_OLED2 // 2nd OLED display, I2C address next higher
#define WITH_U8G2_OLED // I2C OLED through the U8g2 library
#define WITH_U8G2_FLIP
#define WITH_U8G2_SH1106 // the bigger OLED controller
#define WITH_U8G2_FLIP // flip the OLED screen
#define WITH_RFM95 // RF chip selection: both HELTEC and TTGO use sx1276 which is same as RFM95
#define WITH_RFM95 // RF chip selection: FollowMe, HELTEC and TTGO use sx1276 which is same as RFM95 module
// #define WITH_SLEEP // with software sleep mode controlled by the long-press on the button
// #define WITH_AXP // with AXP192 power controller (T-BEAM V1.0)
// #define WITH_BQ // with BQ24295 power controller (FollowMe)
// #define WITH_BQ // with BQ24295 power controller (new FollowMe)
// #define WITH_LED_RX
// #define WITH_LED_TX
@ -39,15 +40,15 @@
// #define WITH_MAVLINK
// #define WITH_GPS_UBX_PASS // to pass directly UBX packets to/from GPS
// #define WITH_GPS_NMEA_PASS // to pass directly NMEA to/from GPS
// #define WITH_GPS_NMEA_PASS // to pass directly NMEA to/from GPS
// #define WITH_BMP180 // BMP180 pressure sensor
// #define WITH_BMP280 // BMP280 pressure sensor
#define WITH_BME280 // BMP280 with humidity (but still works with BMP280)
#define WITH_BME280 // BMP280 with humidity (still works with BMP280)
// #define WITH_MS5607 // MS5607 pressure sensor
#define WITH_PFLAA // PFLAU and PFLAA for compatibility with XCsoar and LK8000
// #define WITH_POGNT
#define WITH_PFLAA // $PFLAU and $PFLAA for compatibility with XCsoar and LK8000
// #define WITH_POGNT // $POGNT for traffic info
#define WITH_LOOKOUT
#define WITH_CONFIG // interpret the console input: $POGNS to change parameters
@ -58,20 +59,23 @@
// #define WITH_KNOB
// #define WITH_VARIO
#define WITH_LORAWAN
#define WITH_LORAWAN // LoRaWAN TTN connectivity
// #define WITH_PAW // beta-code for PilotAware transmission
// #define WITH_FANET // beta-code for FANET transmissions, but breaks LoRaWAN, to be improved
#define WITH_AP // creat WiFi Access Point for data, setup and log files
// #define WITH_STRATUX // connect to Stratux WiFi as a client
// #define WITH_BT_SPP // Bluetooth serial port for smartphone/tablet link
// #define WITH_APRS // attempt to connect to the wifi router for uploading the log files to APRS
#define WITH_AP // create WiFi Access Point for data, setup and log files
#define WITH_AP_BUTTON // activate Access Point only when button pressed at startup
#define WITH_HTTP // HTTP server, works with AP and Stratux
#define WITH_BT_SPP // (classic) Bluetooth serial port for smartphone/tablet link
#define WITH_HTTP // HTTP server, works with AP dna should work with Stratux as well
// #define WITH_STRATUX // beta-code: connect to Stratux WiFi and send GPS and traffic info
// #define WITH_APRS // alpha-code: attempt to connect to the wifi router for uploading the log files to APRS
#define WITH_SD // use the SD card in SPI mode and FAT file system
#define WITH_SPIFFS_FAT
#define WITH_SPIFFS // use SPIFFS file system in Flash
#define WITH_LOG // log own positions and other received to SPIFFS and possibly to uSD
#define WITH_SDLOG
#define WITH_SDLOG //
// #define WITH_ENCRYPT // Encrypt (optionally) the position

Wyświetl plik

@ -4,9 +4,7 @@
#define DEFAULT_PPSdelay 100
#define DEFAULT_FreqPlan 0
// #define WITH_HELTEC // HELTEC module: PCB LED on GPI025
// #define WITH_HELTEC_V2 // HELTEC module v2
// #define WITH_TTGO // TTGO module: PCB LED on GPIO2, GPIO25 free to use as DAC2 output
// #define WITH_TBEAM // T-Beam module
#define WITH_TBEAM_V10 // T-Beam module
@ -15,11 +13,10 @@
// #define WITH_ILI9341 // 320x240 M5stack
// #define WITH_ST7789 // IPS 240x240 ST7789
// #define WITH_TFT_LCD // TFT LCD
// #define WITH_TFT_LCD // TFT LCD (incomplete)
// #define WITH_OLED // OLED display on the I2C: some TTGO modules are without OLED display
// #define WITH_OLED2 // 2nd OLED display, I2C address next higher
// #define WITH_U8G2_OLED // I2C OLED through the U8g2 library
// #define WITH_U8G2_SH1106
#define WITH_RFM95 // RF chip selection: both HELTEC and TTGO use sx1276 which is same as RFM95
@ -45,9 +42,8 @@
// #define WITH_BMP180 // BMP180 pressure sensor
// #define WITH_BMP280 // BMP280 pressure sensor
// #define WITH_BME280 // BMP280 with humidity (but still works with BMP280)
#define WITH_BME280 // BMP280 with humidity (but still works with BMP280)
// #define WITH_MS5607 // MS5607 pressure sensor
// #define WITH_MS5611 // MS5611 pressure sensor
#define WITH_PFLAA // PFLAU and PFLAA for compatibility with XCsoar and LK8000
// #define WITH_POGNT
@ -55,21 +51,30 @@
#define WITH_CONFIG // interpret the console input: $POGNS to change parameters
// #define WITH_BEEPER // with digital buzzer
#define WITH_BEEPER // with digital buzzer
// #define WITH_SOUND // with analog sound produced by DAC on pin 25
// #define WITH_KNOB
// #define WITH_VARIO
#define WITH_LORAWAN
#define WITH_AP // WiFi Access Point: can work together with BT_SPP
#define WITH_AP_BUTTON // only starts when button pressed at sartup
#define WITH_BT_SPP // Bluetooth serial port for smartphone/tablet link: can work together with WiFi Access point
// #define WITH_STRATUX // beta-code: connect to Stratux WiFi and serve as GPS and OGN transmitter/receiver
// #define WITH_APRS // alpha-code: attempt to connect to the wifi router for uploading the log files to APRS
#define WITH_HTTP // HTTP server, works with AP dna should work with Stratux as well
// #define WITH_SD // use the SD card in SPI mode and FAT file system
#define WITH_SPIFFS_FAT
#define WITH_SPIFFS // use SPIFFS file system in Flash
#define WITH_LOG // log own positions and other received to SPIFFS and possibly to uSD
// #define WITH_STRATUX
#define WITH_BT_SPP // Bluetooth serial port for smartphone/tablet link
// #define WITH_WIFI // attempt to connect to the wifi router for uploading the log files
// #define WITH_SPIFFS_LOG // log transmitted and received packets to SPIFFS
// #define WITH_ENCRYPT // Encrypt (optionally) the position
#if defined(WITH_STRATUX) || defined(WITH_APRS) || defined(WITH_AP)
#define WITH_WIFI
#endif

Wyświetl plik

@ -59,10 +59,11 @@
#define WITH_LORAWAN
#define WITH_AP
// #define WITH_STRATUX
// #define WITH_BT_SPP // Bluetooth serial port for smartphone/tablet link
// #define WITH_APRS // attempt to connect to the wifi router for uploading the log files to APRS
#define WITH_AP // WiFi Access Point: can work together with BT_SPP
#define WITH_AP_BUTTON // only starts when button pressed at sartup
#define WITH_BT_SPP // Bluetooth serial port for smartphone/tablet link: can work together with WiFi Access point
// #define WITH_STRATUX // beta-code: connect to Stratux WiFi and serve as GPS and OGN transmitter/receiver
// #define WITH_APRS // alpha-code: attempt to connect to the wifi router for uploading the log files to APRS
#define WITH_HTTP // HTTP server, works with AP dna should work with Stratux as well

220
main/bt.cpp 100644
Wyświetl plik

@ -0,0 +1,220 @@
// ~/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);
// #ifdef WITH_BT_SPP
#include "hal.h"
#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"
#include "format.h"
#include "fifo.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<char, 1024> BT_SPP_TxFIFO; // buffer for console output to be sent over BT
static FIFO<uint8_t, 256> 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; Idx<Len; Idx++)
{ Format_Hex(ID, MAC[Idx]); ID+=2; }
ID[0]=0; }
static void clrPilotID(void) // clear the Pilot_ID when BT SPP gets disconnected
{ Parameters.PilotID[0]=0; }
static size_t BT_SPP_TxPush(size_t MaxLen=128) // transmit part of the TxFIFO to the BT link
{ // BT_SPP_LastTxPush = xTaskGetTickCount(); // [ms] remember last time the TxPush was done
char *Data; size_t Len=BT_SPP_TxFIFO.getReadBlock(Data); // see how much data is there in the queue for transmission
if(Len==0) return 0; // if block is empty then give up
if(Len>MaxLen) 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
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_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
// ========================================================================================================

11
main/bt.h 100644
Wyświetl plik

@ -0,0 +1,11 @@
#ifndef __BT_H__
#define __BT_H__
#include <stdint.h>
int BT_SPP_Init(void);
bool BT_SPP_isConnected(void);
int BT_SPP_Read (uint8_t &Byte);
void BT_SPP_Write (char Byte);
#endif // __BT_H__

Wyświetl plik

@ -23,6 +23,10 @@
#include "wifi.h"
#endif
#ifdef WITH_BT_SPP
#include "bt.h"
#endif
#include "gps.h"
// #include "ubx.h"
// #include "timesync.h"

Wyświetl plik

@ -16,6 +16,10 @@
#include "esp_system.h"
#include "esp_freertos_hooks.h"
#ifdef WITH_BT_SPP
#include "bt.h"
#endif
#ifdef WITH_LORAWAN
#include "lorawan.h"
#endif
@ -40,15 +44,6 @@
#include "sdmmc_cmd.h"
#endif
#ifdef WITH_BT_SPP
#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"
#include "fifo.h"
#endif
#ifdef WITH_AP
#include "ap.h"
#endif
@ -642,215 +637,6 @@ bool Button_isPressed(void) { return !gpio_get_level(PIN_BUTTON); }
// ========================================================================================================
// ~/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);
#ifdef WITH_BT_SPP
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<char, 1024> BT_SPP_TxFIFO; // buffer for console output to be sent over BT
static FIFO<uint8_t, 256> 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 conencted 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; Idx<Len; Idx++)
{ Format_Hex(ID, MAC[Idx]); ID+=2; }
ID[0]=0; }
static void clrPilotID(void) // clear the Pilot_ID when BT SPP gets disconnected
{ Parameters.PilotID[0]=0; }
static size_t BT_SPP_TxPush(size_t MaxLen=128) // transmit part of the TxFIFO to the BT link
{ // BT_SPP_LastTxPush = xTaskGetTickCount(); // [ms] remember last time the TxPush was done
char *Data; size_t Len=BT_SPP_TxFIFO.getReadBlock(Data); // see how much data is there in the queue for transmission
if(Len==0) return 0; // if block is empty then give up
if(Len>MaxLen) 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);
}
static 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); }
static 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
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_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
// ========================================================================================================
// Console UART
SemaphoreHandle_t CONS_Mutex;

Wyświetl plik

@ -11,6 +11,10 @@
#include "fifo.h"
#ifdef WITH_BT_SPP
#include "bt.h"
#endif
// ============================================================================================================
#define WITH_ESP32
@ -186,11 +190,6 @@ void IO_Configuration(void); // Configure I/O
int NVS_Init(void); // initialize non-volatile-storage in the Flash
#ifdef WITH_BT_SPP
int BT_SPP_Init(void);
bool BT_SPP_isConnected(void);
#endif
#ifdef WITH_SPIFFS
int SPIFFS_Register(const char *Path="/spiffs", const char *Label="intlog", size_t MaxOpenFiles=5);
int SPIFFS_Info(size_t &Total, size_t &Used, const char *Label="intlog");

Wyświetl plik

@ -28,6 +28,10 @@
#include "stratux.h"
#endif
#ifdef WITH_BT_SPP
#include "bt.h"
#endif
#ifdef WITH_AP
#include "ap.h"
#endif

Wyświetl plik

@ -124,7 +124,7 @@ class FlashParameters
// char Copilot[16]
// char Category[16]
uint32_t PageMask;
uint32_t PageMask; // enable/disable individual pages on the LCD or OLED screen
#ifdef WITH_BT_SPP
char BTname[16];