diff --git a/FollowMe.cfg b/FollowMe.cfg index 7eb37fb..82ebb17 100644 --- a/FollowMe.cfg +++ b/FollowMe.cfg @@ -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 - diff --git a/FollowMe_old.cfg b/FollowMe_old.cfg index a0a68d5..dc81898 100644 --- a/FollowMe_old.cfg +++ b/FollowMe_old.cfg @@ -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 diff --git a/T-Beam_v10.cfg b/T-Beam_v10.cfg index e17aec1..f4e0f95 100644 --- a/T-Beam_v10.cfg +++ b/T-Beam_v10.cfg @@ -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 + diff --git a/T-Beam_v10_LCD.cfg b/T-Beam_v10_LCD.cfg index 1e574e6..9ee2590 100644 --- a/T-Beam_v10_LCD.cfg +++ b/T-Beam_v10_LCD.cfg @@ -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 diff --git a/main/bt.cpp b/main/bt.cpp new file mode 100644 index 0000000..64e112b --- /dev/null +++ b/main/bt.cpp @@ -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 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 + 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 + +// ======================================================================================================== diff --git a/main/bt.h b/main/bt.h new file mode 100644 index 0000000..bfad1fe --- /dev/null +++ b/main/bt.h @@ -0,0 +1,11 @@ +#ifndef __BT_H__ +#define __BT_H__ + +#include + +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__ diff --git a/main/disp_oled.cpp b/main/disp_oled.cpp index 8dc21f5..fbfd83c 100644 --- a/main/disp_oled.cpp +++ b/main/disp_oled.cpp @@ -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" diff --git a/main/hal.cpp b/main/hal.cpp index 20f872a..987d32d 100644 --- a/main/hal.cpp +++ b/main/hal.cpp @@ -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 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 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; 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); -} - -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; diff --git a/main/hal.h b/main/hal.h index dc730b0..348dc8a 100644 --- a/main/hal.h +++ b/main/hal.h @@ -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"); diff --git a/main/main.cpp b/main/main.cpp index 85b89fb..52904eb 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -28,6 +28,10 @@ #include "stratux.h" #endif +#ifdef WITH_BT_SPP +#include "bt.h" +#endif + #ifdef WITH_AP #include "ap.h" #endif diff --git a/main/parameters.h b/main/parameters.h index 3fae42f..e5a00ed 100644 --- a/main/parameters.h +++ b/main/parameters.h @@ -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];