mirror of https://github.com/meshcore-dev/MeshCore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.0 KiB
118 lines
3.0 KiB
#include "SerialBLEInterface.h"
|
|
#include <Arduino.h>
|
|
|
|
#define BLE_HEALTH_CHECK_INTERVAL 10000
|
|
|
|
void SerialBLEInterface::onConnect(BLEServer* p) {
|
|
(void)p;
|
|
_isConnected = true;
|
|
send_queue_len = 0;
|
|
recv_queue_len = 0;
|
|
}
|
|
|
|
void SerialBLEInterface::onDisconnect(BLEServer* p) {
|
|
(void)p;
|
|
_isConnected = false;
|
|
send_queue_len = 0;
|
|
recv_queue_len = 0;
|
|
if (_isEnabled) {
|
|
BLE.startAdvertising();
|
|
}
|
|
}
|
|
|
|
void SerialBLEInterface::onWrite(BLECharacteristic* c) {
|
|
size_t len = c->valueLen();
|
|
const uint8_t* data = (const uint8_t*)c->valueData();
|
|
if (len > 0 && len <= MAX_FRAME_SIZE && recv_queue_len < FRAME_QUEUE_SIZE) {
|
|
recv_queue[recv_queue_len].len = len;
|
|
memcpy(recv_queue[recv_queue_len].buf, data, len);
|
|
recv_queue_len++;
|
|
}
|
|
}
|
|
|
|
void SerialBLEInterface::shiftSendQueueLeft() {
|
|
if (send_queue_len > 0) {
|
|
send_queue_len--;
|
|
for (uint8_t i = 0; i < send_queue_len; i++) send_queue[i] = send_queue[i + 1];
|
|
}
|
|
}
|
|
|
|
void SerialBLEInterface::shiftRecvQueueLeft() {
|
|
if (recv_queue_len > 0) {
|
|
recv_queue_len--;
|
|
for (uint8_t i = 0; i < recv_queue_len; i++) recv_queue[i] = recv_queue[i + 1];
|
|
}
|
|
}
|
|
|
|
void SerialBLEInterface::begin(const char* prefix, char* name, uint32_t pin_code) {
|
|
(void)pin_code;
|
|
|
|
char dev_name[48];
|
|
snprintf(dev_name, sizeof(dev_name), "%s%s", prefix, name);
|
|
|
|
BLE.begin(String(dev_name));
|
|
|
|
_server = BLE.server();
|
|
_server->setCallbacks(this);
|
|
|
|
_service = new BLEService(String(SERVICE_UUID));
|
|
_txChar = new BLECharacteristic(String(TX_UUID), BLERead | BLENotify);
|
|
_rxChar = new BLECharacteristic(String(RX_UUID), BLEWrite | BLEWriteWithoutResponse);
|
|
_rxChar->setCallbacks(this);
|
|
|
|
_service->addCharacteristic(_txChar);
|
|
_service->addCharacteristic(_rxChar);
|
|
_server->addService(_service);
|
|
|
|
enable();
|
|
}
|
|
|
|
void SerialBLEInterface::enable() {
|
|
if (_isEnabled) return;
|
|
_isEnabled = true;
|
|
_last_health_check = millis();
|
|
BLE.startAdvertising();
|
|
}
|
|
|
|
void SerialBLEInterface::disable() {
|
|
_isEnabled = false;
|
|
_isConnected = false;
|
|
BLE.stopAdvertising();
|
|
}
|
|
|
|
size_t SerialBLEInterface::writeFrame(const uint8_t src[], size_t len) {
|
|
if (!_isConnected || len == 0 || len > MAX_FRAME_SIZE) return 0;
|
|
if (send_queue_len >= FRAME_QUEUE_SIZE) return 0;
|
|
send_queue[send_queue_len].len = len;
|
|
memcpy(send_queue[send_queue_len].buf, src, len);
|
|
send_queue_len++;
|
|
return len;
|
|
}
|
|
|
|
size_t SerialBLEInterface::checkRecvFrame(uint8_t dest[]) {
|
|
// send queued frames
|
|
if (send_queue_len > 0 && _isConnected && millis() >= _last_write + BLE_WRITE_MIN_INTERVAL) {
|
|
_last_write = millis();
|
|
_txChar->setValue(send_queue[0].buf, send_queue[0].len);
|
|
shiftSendQueueLeft();
|
|
}
|
|
|
|
// return next received frame
|
|
if (recv_queue_len > 0) {
|
|
size_t len = recv_queue[0].len;
|
|
memcpy(dest, recv_queue[0].buf, len);
|
|
shiftRecvQueueLeft();
|
|
return len;
|
|
}
|
|
|
|
// advertising watchdog
|
|
if (_isEnabled && !_isConnected) {
|
|
unsigned long now = millis();
|
|
if (now - _last_health_check >= BLE_HEALTH_CHECK_INTERVAL) {
|
|
_last_health_check = now;
|
|
BLE.startAdvertising();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|