Added ESP32 BLE serial driver
This commit is contained in:
		
							
								
								
									
										122
									
								
								BLESerial.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								BLESerial.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										111
									
								
								BLESerial.h
									
									
									
									
									
										Normal 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;
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user