Added ESP32 BLE serial driver

This commit is contained in:
Mark Qvist 2024-09-29 21:59:11 +02:00
parent fe9538de7e
commit 339003039a
2 changed files with 233 additions and 0 deletions

122
BLESerial.cpp Normal file
View File

@ -0,0 +1,122 @@
#include "BLESerial.h"
uint32_t bt_passkey_callback();
void bt_passkey_notify_callback(uint32_t passkey);
bool bt_security_request_callback();
void bt_authentication_complete_callback(esp_ble_auth_cmpl_t auth_result);
bool bt_confirm_pin_callback(uint32_t pin);
void bt_connect_callback(uint16_t conn_handle);
void bt_disconnect_callback(uint16_t conn_handle, uint8_t reason);
uint32_t BLESerial::onPassKeyRequest() { return bt_passkey_callback(); }
void BLESerial::onPassKeyNotify(uint32_t passkey) { bt_passkey_notify_callback(passkey); }
bool BLESerial::onSecurityRequest() { return bt_security_request_callback(); }
void BLESerial::onAuthenticationComplete(esp_ble_auth_cmpl_t auth_result) { bt_authentication_complete_callback(auth_result); }
void BLESerial::onConnect(BLEServer *server) { bt_connect_callback(0); }
void BLESerial::onDisconnect(BLEServer *server) { bt_disconnect_callback(0, 0); ble_server->startAdvertising(); }
bool BLESerial::onConfirmPIN(uint32_t pin) { return false; };
bool BLESerial::connected() { return ble_server->getConnectedCount() > 0; }
int BLESerial::read() {
int result = this->rx_buffer.pop();
if (result == '\n') { this->numAvailableLines--; }
return result;
}
size_t BLESerial::readBytes(uint8_t *buffer, size_t bufferSize) {
int i = 0;
while (i < bufferSize && available()) { buffer[i] = (uint8_t)this->rx_buffer.pop(); i++; }
return i;
}
int BLESerial::peek() {
if (this->rx_buffer.getLength() == 0) return -1;
return this->rx_buffer.get(0);
}
int BLESerial::available() { return this->rx_buffer.getLength(); }
size_t BLESerial::print(const char *str) {
if (ble_server->getConnectedCount() <= 0) return 0;
size_t written = 0; for (size_t i = 0; str[i] != '\0'; i++) { written += this->write(str[i]); }
flush();
return written;
}
size_t BLESerial::write(const uint8_t *buffer, size_t bufferSize) {
if (ble_server->getConnectedCount() <= 0) { return 0; } else {
size_t written = 0; for (int i = 0; i < bufferSize; i++) { written += this->write(buffer[i]); }
flush();
return written;
}
}
size_t BLESerial::write(uint8_t byte) {
if (ble_server->getConnectedCount() <= 0) { return 0; } else {
this->transmitBuffer[this->transmitBufferLength] = byte;
this->transmitBufferLength++;
if (this->transmitBufferLength == maxTransferSize) { flush(); }
return 1;
}
}
void BLESerial::flush() {
if (this->transmitBufferLength > 0) {
TxCharacteristic->setValue(this->transmitBuffer, this->transmitBufferLength);
this->transmitBufferLength = 0;
this->lastFlushTime = millis();
TxCharacteristic->notify(true);
}
}
void BLESerial::begin(const char *name) {
ConnectedDeviceCount = 0;
BLEDevice::init(name);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN ,ESP_PWR_LVL_P9);
ble_server = BLEDevice::createServer();
ble_server->setCallbacks(this);
BLEDevice::setSecurityCallbacks(this);
SetupSerialService();
ble_adv = BLEDevice::getAdvertising();
ble_adv->addServiceUUID(BLE_SERIAL_SERVICE_UUID);
ble_adv->setMinPreferred(0x20);
ble_adv->setMaxPreferred(0x40);
ble_adv->setScanResponse(true);
ble_adv->start();
}
void BLESerial::end() { BLEDevice::deinit(); }
void BLESerial::onWrite(BLECharacteristic *characteristic) {
if (characteristic->getUUID().toString() == BLE_RX_UUID) {
auto value = characteristic->getValue();
for (int i = 0; i < value.length(); i++) { rx_buffer.push(value[i]); }
}
}
void BLESerial::SetupSerialService() {
SerialService = ble_server->createService(BLE_SERIAL_SERVICE_UUID);
RxCharacteristic = SerialService->createCharacteristic(BLE_RX_UUID, BLECharacteristic::PROPERTY_WRITE);
RxCharacteristic->setAccessPermissions(ESP_GATT_PERM_WRITE_ENC_MITM);
RxCharacteristic->addDescriptor(new BLE2902());
RxCharacteristic->setWriteProperty(true);
RxCharacteristic->setCallbacks(this);
TxCharacteristic = SerialService->createCharacteristic(BLE_TX_UUID, BLECharacteristic::PROPERTY_NOTIFY);
TxCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM);
TxCharacteristic->addDescriptor(new BLE2902());
TxCharacteristic->setReadProperty(true);
SerialService->start();
}
BLESerial::BLESerial() { }

111
BLESerial.h Normal file
View File

@ -0,0 +1,111 @@
#pragma once
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
template <size_t n>
class BLEFIFO {
private:
uint8_t buffer[n];
int head = 0;
int tail = 0;
public:
void push(uint8_t value) {
buffer[head] = value;
head = (head + 1) % n;
if (head == tail) { tail = (tail + 1) % n; }
}
int pop() {
if (head == tail) {
return -1;
} else {
uint8_t value = buffer[tail];
tail = (tail + 1) % n;
return value;
}
}
void clear() { head = 0; tail = 0; }
int get(size_t index) {
if (index >= this->getLength()) {
return -1;
} else {
return buffer[(tail + index) % n];
}
}
size_t getLength() {
if (head >= tail) {
return head - tail;
} else {
return n - tail + head;
}
}
};
#define RX_BUFFER_SIZE 6144
#define BLE_BUFFER_SIZE 512 // Must fit in max GATT attribute length
#define MIN_MTU 50
class BLESerial : public BLECharacteristicCallbacks, public BLEServerCallbacks, public BLESecurityCallbacks, public Stream {
public:
BLESerial();
void begin(const char *name);
void end();
void onWrite(BLECharacteristic *characteristic);
int available();
int peek();
int read();
size_t readBytes(uint8_t *buffer, size_t bufferSize);
size_t write(uint8_t byte);
size_t write(const uint8_t *buffer, size_t bufferSize);
size_t print(const char *value);
void flush();
void onConnect(BLEServer *server);
void onDisconnect(BLEServer *server);
uint32_t onPassKeyRequest();
void onPassKeyNotify(uint32_t passkey);
bool onSecurityRequest();
void onAuthenticationComplete(esp_ble_auth_cmpl_t);
bool onConfirmPIN(uint32_t pin);
bool connected();
BLEServer *ble_server;
BLEAdvertising *ble_adv;
BLEService *SerialService;
BLECharacteristic *TxCharacteristic;
BLECharacteristic *RxCharacteristic;
size_t transmitBufferLength;
unsigned long long lastFlushTime;
private:
BLESerial(BLESerial const &other) = delete;
void operator=(BLESerial const &other) = delete;
BLEFIFO<RX_BUFFER_SIZE> rx_buffer;
size_t numAvailableLines;
uint8_t transmitBuffer[BLE_BUFFER_SIZE];
int ConnectedDeviceCount;
void SetupSerialService();
uint16_t peerMTU;
uint16_t maxTransferSize = BLE_BUFFER_SIZE;
bool checkMTU();
const char *BLE_SERIAL_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
const char *BLE_RX_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";
const char *BLE_TX_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
bool started = false;
};