Merge pull request 'NewBluetoothVersion' (#1) from NewBluetoothVersion into main

Reviewed-on: https://tea.app-dev.hu/GNSS/RoverAndBaseStation/pulls/1
This commit is contained in:
torok.istvan 2025-09-27 22:46:26 +02:00
commit 3aa4f38f8b
13 changed files with 1640 additions and 91 deletions

View File

@ -9,5 +9,6 @@
"outline.showNamespaces": false,
"outline.showProperties": false,
"outline.showTypeParameters": false,
"outline.showVariables": false
"outline.showVariables": false,
"C_Cpp.errorSquiggles": "disabled"
}

View File

@ -0,0 +1,88 @@
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
#include "BTAddress.h"
#include <string>
#include <sstream>
#include <iomanip>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#endif
/**
* @brief Create an address from the native ESP32 representation.
* @param [in] address The native representation.
*/
BTAddress::BTAddress(esp_bd_addr_t address) {
memcpy(m_address, address, ESP_BD_ADDR_LEN);
} // BTAddress
/**
* @brief Create an address from a hex string
*
* A hex string is of the format:
* ```
* 00:00:00:00:00:00
* ```
* which is 17 characters in length.
*
* @param [in] stringAddress The hex representation of the address.
*/
BTAddress::BTAddress(std::string stringAddress) {
if (stringAddress.length() != 17) return;
int data[6];
sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5]);
m_address[0] = (uint8_t) data[0];
m_address[1] = (uint8_t) data[1];
m_address[2] = (uint8_t) data[2];
m_address[3] = (uint8_t) data[3];
m_address[4] = (uint8_t) data[4];
m_address[5] = (uint8_t) data[5];
} // BTAddress
/**
* @brief Determine if this address equals another.
* @param [in] otherAddress The other address to compare against.
* @return True if the addresses are equal.
*/
bool BTAddress::equals(BTAddress otherAddress) {
return memcmp(otherAddress.getNative(), m_address, 6) == 0;
} // equals
/**
* @brief Return the native representation of the address.
* @return The native representation of the address.
*/
esp_bd_addr_t *BTAddress::getNative() {
return &m_address;
} // getNative
/**
* @brief Convert a BT address to a string.
*
* A string representation of an address is in the format:
*
* ```
* xx:xx:xx:xx:xx:xx
* ```
*
* @return The string representation of the address.
*/
std::string BTAddress::toString() {
auto size = 18;
char *res = (char*)malloc(size);
snprintf(res, size, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[0], m_address[1], m_address[2], m_address[3], m_address[4], m_address[5]);
std::string ret(res);
free(res);
return ret;
} // toString
#endif

View File

@ -0,0 +1,27 @@
#ifndef COMPONENTS_CPP_UTILS_BTADDRESS_H_
#define COMPONENTS_CPP_UTILS_BTADDRESS_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
#include <esp_gap_bt_api.h> // ESP32 BT
#include <string>
/**
* @brief A %BT device address.
*
* Every %BT device has a unique address which can be used to identify it and form connections.
*/
class BTAddress {
public:
BTAddress(esp_bd_addr_t address);
BTAddress(std::string stringAddress);
bool equals(BTAddress otherAddress);
esp_bd_addr_t* getNative();
std::string toString();
private:
esp_bd_addr_t m_address;
};
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BTADDRESS_H_ */

View File

@ -0,0 +1,58 @@
#ifndef __BTADVERTISEDDEVICE_H__
#define __BTADVERTISEDDEVICE_H__
#include "BTAddress.h"
class BTAdvertisedDevice {
public:
virtual ~BTAdvertisedDevice() = default;
virtual BTAddress getAddress();
virtual uint32_t getCOD();
virtual std::string getName();
virtual int8_t getRSSI();
virtual bool haveCOD();
virtual bool haveName();
virtual bool haveRSSI();
virtual std::string toString();
};
class BTAdvertisedDeviceSet : public virtual BTAdvertisedDevice {
public:
BTAdvertisedDeviceSet();
//~BTAdvertisedDeviceSet() = default;
BTAddress getAddress();
uint32_t getCOD();
std::string getName();
int8_t getRSSI();
bool haveCOD();
bool haveName();
bool haveRSSI();
std::string toString();
void setAddress(BTAddress address);
void setCOD(uint32_t cod);
void setName(std::string name);
void setRSSI(int8_t rssi);
bool m_haveCOD;
bool m_haveName;
bool m_haveRSSI;
BTAddress m_address = BTAddress((uint8_t*)"\0\0\0\0\0\0");
uint32_t m_cod;
std::string m_name;
int8_t m_rssi;
};
#endif

View File

@ -0,0 +1,71 @@
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
//#include <map>
#include "BTAdvertisedDevice.h"
//#include "BTScan.h"
BTAdvertisedDeviceSet::BTAdvertisedDeviceSet() {
m_cod = 0;
m_name = "";
m_rssi = 0;
m_haveCOD = false;
m_haveName = false;
m_haveRSSI = false;
} // BTAdvertisedDeviceSet
BTAddress BTAdvertisedDeviceSet::getAddress() { return m_address; }
uint32_t BTAdvertisedDeviceSet::getCOD() { return m_cod; }
std::string BTAdvertisedDeviceSet::getName() { return m_name; }
int8_t BTAdvertisedDeviceSet::getRSSI() { return m_rssi; }
bool BTAdvertisedDeviceSet::haveCOD() { return m_haveCOD; }
bool BTAdvertisedDeviceSet::haveName() { return m_haveName; }
bool BTAdvertisedDeviceSet::haveRSSI() { return m_haveRSSI; }
/**
* @brief Create a string representation of this device.
* @return A string representation of this device.
*/
std::string BTAdvertisedDeviceSet::toString() {
std::string res = "Name: " + getName() + ", Address: " + getAddress().toString();
if (haveCOD()) {
char val[6];
snprintf(val, sizeof(val), "%d", getCOD());
res += ", cod: ";
res += val;
}
if (haveRSSI()) {
char val[6];
snprintf(val, sizeof(val), "%d", (int8_t)getRSSI());
res += ", rssi: ";
res += val;
}
return res;
} // toString
void BTAdvertisedDeviceSet::setAddress(BTAddress address) {
m_address = address;
}
void BTAdvertisedDeviceSet::setCOD(uint32_t cod) {
m_cod = cod;
m_haveCOD = true;
}
void BTAdvertisedDeviceSet::setName(std::string name) {
m_name = name;
m_haveName = true;
}
void BTAdvertisedDeviceSet::setRSSI(int8_t rssi) {
m_rssi = rssi;
m_haveRSSI = true;
}
#endif /* CONFIG_BT_ENABLED */

View File

@ -0,0 +1,35 @@
#ifndef __BTSCAN_H__
#define __BTSCAN_H__
#include <map>
#include <string>
#include <Print.h>
#include "BTAddress.h"
#include "BTAdvertisedDevice.h"
class BTAdvertisedDevice;
class BTAdvertisedDeviceSet;
class BTScanResults {
public:
virtual ~BTScanResults() = default;
virtual void dump(Print *print = nullptr);
virtual int getCount();
virtual BTAdvertisedDevice* getDevice(uint32_t i);
};
class BTScanResultsSet : public BTScanResults {
public:
void dump(Print *print = nullptr);
int getCount();
BTAdvertisedDevice* getDevice(uint32_t i);
bool add(BTAdvertisedDeviceSet advertisedDevice, bool unique = true);
void clear();
std::map<std::string, BTAdvertisedDeviceSet> m_vectorAdvertisedDevices;
};
#endif

View File

@ -0,0 +1,88 @@
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
#include <esp_err.h>
#include "BTAdvertisedDevice.h"
#include "BTScan.h"
//#include "GeneralUtils.h"
#include "esp32-hal-log.h"
class BTAdvertisedDevice;
/**
* @brief Dump the scan results to the log.
*/
void BTScanResultsSet::dump(Print *print) {
int cnt = getCount();
if (print == nullptr) {
log_v(">> Dump scan results : %d", cnt);
for (int i=0; i < cnt; i++) {
BTAdvertisedDevice* dev = getDevice(i);
if (dev)
log_d("- %d: %s\n", i+1, dev->toString().c_str());
else
log_d("- %d is null\n", i+1);
}
log_v("-- dump finished --");
} else {
print->printf(">> Dump scan results: %d\n", cnt);
for (int i=0; i < cnt; i++) {
BTAdvertisedDevice* dev = getDevice(i);
if (dev)
print->printf("- %d: %s\n", i+1, dev->toString().c_str());
else
print->printf("- %d is null\n", i+1);
}
print->println("-- Dump finished --");
}
} // dump
/**
* @brief Return the count of devices found in the last scan.
* @return The number of devices found in the last scan.
*/
int BTScanResultsSet::getCount() {
return m_vectorAdvertisedDevices.size();
} // getCount
/**
* @brief Return the specified device at the given index.
* The index should be between 0 and getCount()-1.
* @param [in] i The index of the device.
* @return The device at the specified index.
*/
BTAdvertisedDevice* BTScanResultsSet::getDevice(uint32_t i) {
if (i < 0)
return nullptr;
uint32_t x = 0;
BTAdvertisedDeviceSet* pDev = &m_vectorAdvertisedDevices.begin()->second;
for (auto it = m_vectorAdvertisedDevices.begin(); it != m_vectorAdvertisedDevices.end(); it++) {
pDev = &it->second;
if (x==i) break;
x++;
}
return x==i ? pDev : nullptr;
}
void BTScanResultsSet::clear() {
//for(auto _dev : m_vectorAdvertisedDevices)
// delete _dev.second;
m_vectorAdvertisedDevices.clear();
}
bool BTScanResultsSet::add(BTAdvertisedDeviceSet advertisedDevice, bool unique) {
std::string key = advertisedDevice.getAddress().toString();
if (!unique || m_vectorAdvertisedDevices.count(key) == 0) {
m_vectorAdvertisedDevices.insert(std::pair<std::string, BTAdvertisedDeviceSet>(key, advertisedDevice));
return true;
} else
return false;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
#ifndef _BLUETOOTH_SERIAL_H_
#define _BLUETOOTH_SERIAL_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
#include "Arduino.h"
#include "Stream.h"
#include <esp_gap_bt_api.h>
#include <esp_spp_api.h>
#include <functional>
#include "BTScan.h"
typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb;
typedef std::function<void(uint32_t num_val)> ConfirmRequestCb;
typedef std::function<void(boolean success)> AuthCompleteCb;
typedef std::function<void(BTAdvertisedDevice* pAdvertisedDevice)> BTAdvertisedDeviceCb;
class BluetoothSerial: public Stream
{
public:
BluetoothSerial(void);
~BluetoothSerial(void);
bool begin(String localName=String(), bool isMaster=false, uint16_t rxQueueSize = 512 * 2, uint16_t txQueueSize = 512);
bool begin(unsigned long baud){//compatibility
return begin();
}
int available(void);
int peek(void);
bool hasClient(void);
int read(void);
size_t write(uint8_t c);
size_t write(const uint8_t *buffer, size_t size);
void flush();
void end(void);
void onData(BluetoothSerialDataCb cb);
esp_err_t register_callback(esp_spp_cb_t callback);
void onConfirmRequest(ConfirmRequestCb cb);
void onAuthComplete(AuthCompleteCb cb);
void confirmReply(boolean confirm);
void enableSSP();
bool setPin(const char *pin);
bool connect(String remoteName);
bool connect(uint8_t remoteAddress[]);
bool connect();
bool connected(int timeout=0);
bool isReady(bool checkMaster=false, int timeout=0);
bool disconnect();
bool unpairDevice(uint8_t remoteAddress[]);
BTScanResults* discover(int timeout=0x30*1280);
bool discoverAsync(BTAdvertisedDeviceCb cb, int timeout=0x30*1280);
void discoverAsyncStop();
void discoverClear();
BTScanResults* getScanResults();
const int INQ_TIME = 1280; // Inquire Time unit 1280 ms
const int MIN_INQ_TIME = (ESP_BT_GAP_MIN_INQ_LEN * INQ_TIME);
const int MAX_INQ_TIME = (ESP_BT_GAP_MAX_INQ_LEN * INQ_TIME);
operator bool() const;
private:
String local_name;
};
#endif
#endif

View File

@ -20,3 +20,6 @@ lib_deps =
greiman/SdFat@^2.2.0
jchristensen/JC_Button@^2.1.2
fbiego/ESP32Time@^2.0.0
avinabmalla/ESP32_BleSerial@1.0.4
build_flags=
-I BluetoothSerial

175
src/bluetoothSelect.h Normal file
View File

@ -0,0 +1,175 @@
#ifdef COMPILE_BT
#include "BluetoothSerial.h"
#include <BleSerial.h>
class BTSerialInterface
{
public:
virtual bool begin(String deviceName, bool isMaster, uint16_t rxQueueSize, uint16_t txQueueSize) = 0;
virtual void disconnect() = 0;
virtual void end() = 0;
virtual esp_err_t register_callback(esp_spp_cb_t callback) = 0;
virtual void setTimeout(unsigned long timeout) = 0;
virtual int available() = 0;
// virtual bool hasClient() = 0;
virtual size_t readBytes(uint8_t *buffer, size_t bufferSize) = 0;
virtual int read() = 0;
//virtual bool isCongested() = 0;
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
virtual size_t write(uint8_t value) = 0;
virtual void flush() = 0;
};
class BTClassicSerial : public virtual BTSerialInterface, public BluetoothSerial
{
// Everything is already implemented in BluetoothSerial since the code was
// originally written using that class
public:
bool begin(String deviceName, bool isMaster, uint16_t rxQueueSize, uint16_t txQueueSize)
{
return BluetoothSerial::begin(deviceName, isMaster, rxQueueSize, txQueueSize);
}
void disconnect()
{
BluetoothSerial::disconnect();
}
void end()
{
BluetoothSerial::end();
}
esp_err_t register_callback(esp_spp_cb_t callback)
{
return BluetoothSerial::register_callback(callback);
}
void setTimeout(unsigned long timeout)
{
BluetoothSerial::setTimeout(timeout);
}
int available()
{
return BluetoothSerial::available();
}
// bool hasClient()
// {
// return BluetoothSerial::hasClient();
// }
size_t readBytes(uint8_t *buffer, size_t bufferSize)
{
return BluetoothSerial::readBytes(buffer, bufferSize);
}
int read()
{
return BluetoothSerial::read();
}
size_t write(const uint8_t *buffer, size_t size)
{
return BluetoothSerial::write(buffer, size);
}
size_t write(uint8_t value)
{
return BluetoothSerial::write(value);
}
void flush()
{
BluetoothSerial::flush();
}
};
class BTLESerial : public virtual BTSerialInterface, public BleSerial
{
public:
// Missing from BleSerial
bool begin(String deviceName, bool isMaster, uint16_t rxQueueSize, uint16_t txQueueSize)
{
BleSerial::begin(deviceName.c_str());
return true;
}
void disconnect()
{
Server->disconnect(Server->getConnId());
}
void end()
{
BleSerial::end();
}
esp_err_t register_callback(esp_spp_cb_t callback)
{
connectionCallback = callback;
return ESP_OK;
}
void setTimeout(unsigned long timeout)
{
BleSerial::setTimeout(timeout);
}
int available()
{
return BleSerial::available();
}
size_t readBytes(uint8_t *buffer, size_t bufferSize)
{
return BleSerial::readBytes(buffer, bufferSize);
}
int read()
{
return BleSerial::read();
}
size_t write(const uint8_t *buffer, size_t size)
{
return BleSerial::write(buffer, size);
}
size_t write(uint8_t value)
{
return BleSerial::write(value);
}
void flush()
{
BleSerial::flush();
}
// override BLEServerCallbacks
void onConnect(BLEServer *pServer)
{
// bleConnected = true; Removed until PR is accepted
if(connectionCallback){
// connectionCallback(ESP_SPP_SRV_OPEN_EVT, nullptr);
}
}
void onDisconnect(BLEServer *pServer)
{
// bleConnected = false; Removed until PR is accepted
esp_spp_cb_param_t* param = NULL;
connectionCallback(ESP_SPP_CLOSE_EVT, nullptr);
Server->startAdvertising();
}
private:
esp_spp_cb_t connectionCallback;
};
#endif

View File

@ -292,7 +292,7 @@ bool zedUartPassed = false; //Goes true during testing if ESP can communicate wi
volatile int counter = 0;
long lastTime = 0;
#include <mybluetooth.h>
#include "bluetoothSelect.h"
// BluetoothSerial SerialBT;
BTSerialInterface *bluetoothSerial;
@ -965,11 +965,11 @@ void loop()
oled.setCursor(0,11);
oled.printf("%d bytes",fileSize);
if(bluetoothSerial->hasClient())
{
oled.setCursor(0,21);
oled.println("BT connected");
}
// if(bluetoothSerial->hasClient())
// {
// oled.setCursor(0,21);
// oled.println("BT connected");
// }
oled.display();
}
@ -1810,14 +1810,14 @@ void bluetoothStart()
// else if (settings.bluetoothRadioType == BLUETOOTH_RADIO_BLE)
// bluetoothSerial = new BTLESerial();
if (bluetoothSerial->begin(deviceName) == false)
{
Serial.println("An error occurred initializing Bluetooth");
// if (bluetoothSerial->begin(deviceName) == false)
// {
// Serial.println("An error occurred initializing Bluetooth");
if (productVariant == RTK_SURVEYOR)
digitalWrite(pin_bluetoothStatusLED, LOW);
return;
}
// if (productVariant == RTK_SURVEYOR)
// digitalWrite(pin_bluetoothStatusLED, LOW);
// return;
// }
//Set PIN to 1234 so we can connect to older BT devices, but not require a PIN for modern device pairing
//See issue: https://github.com/sparkfun/SparkFun_RTK_Firmware/issues/5
@ -1839,7 +1839,7 @@ void bluetoothStart()
esp_bt_gap_set_pin(pin_type, 4, pin_code);
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
bluetoothSerial->register_callback(bluetoothCallback); //Controls BT Status LED on Surveyor
// bluetoothSerial->register_callback(bluetoothCallback); //Controls BT Status LED on Surveyor
bluetoothSerial->setTimeout(250);
Serial.print("Bluetooth broadcasting as: ");

View File

@ -1,76 +0,0 @@
#include "BluetoothSerial.h"
class BTSerialInterface
{
public:
virtual bool begin(String deviceName) = 0;
virtual void disconnect() = 0;
virtual void end() = 0;
virtual esp_err_t register_callback(esp_spp_cb_t * callback) = 0;
virtual void setTimeout(unsigned long timeout) = 0;
virtual int available() = 0;
virtual bool hasClient() = 0;
virtual size_t readBytes(uint8_t *buffer, size_t bufferSize) = 0;
//virtual bool isCongested() = 0;
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
virtual void flush() = 0;
};
class BTClassicSerial : public virtual BTSerialInterface, public BluetoothSerial
{
// Everything is already implemented in BluetoothSerial since the code was
// originally written using that class
public:
bool begin(String deviceName)
{
return BluetoothSerial::begin(deviceName);
}
void disconnect()
{
BluetoothSerial::disconnect();
}
void end()
{
BluetoothSerial::end();
}
esp_err_t register_callback(esp_spp_cb_t * callback)
{
return BluetoothSerial::register_callback(callback);
}
void setTimeout(unsigned long timeout)
{
BluetoothSerial::setTimeout(timeout);
}
int available()
{
return BluetoothSerial::available();
}
bool hasClient()
{
return BluetoothSerial::hasClient();
}
size_t readBytes(uint8_t *buffer, size_t bufferSize)
{
return BluetoothSerial::readBytes(buffer, bufferSize);
}
size_t write(const uint8_t *buffer, size_t size)
{
return BluetoothSerial::write(buffer, size);
}
void flush()
{
BluetoothSerial::flush();
}
};