/ RNode_Firmware_CE_G2 / BLESerial.cpp
BLESerial.cpp
  1  // Copyright (C) 2024, Mark Qvist
  2  
  3  // This program is free software: you can redistribute it and/or modify
  4  // it under the terms of the GNU General Public License as published by
  5  // the Free Software Foundation, either version 3 of the License, or
  6  // (at your option) any later version.
  7  
  8  // This program is distributed in the hope that it will be useful,
  9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
 10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 11  // GNU General Public License for more details.
 12  
 13  // You should have received a copy of the GNU General Public License
 14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 15  
 16  #include "Boards.h"
 17  
 18  #if PLATFORM != PLATFORM_NRF52
 19  #if HAS_BLE
 20  
 21  #include "BLESerial.h"
 22  
 23  uint32_t bt_passkey_callback();
 24  void bt_passkey_notify_callback(uint32_t passkey);
 25  bool bt_security_request_callback();
 26  void bt_authentication_complete_callback(esp_ble_auth_cmpl_t auth_result);
 27  bool bt_confirm_pin_callback(uint32_t pin);
 28  void bt_connect_callback(BLEServer *server);
 29  void bt_disconnect_callback(BLEServer *server);
 30  bool bt_client_authenticated();
 31  
 32  uint32_t BLESerial::onPassKeyRequest() { return bt_passkey_callback(); }
 33  void BLESerial::onPassKeyNotify(uint32_t passkey) { bt_passkey_notify_callback(passkey); }
 34  bool BLESerial::onSecurityRequest() { return bt_security_request_callback(); }
 35  void BLESerial::onAuthenticationComplete(esp_ble_auth_cmpl_t auth_result) { bt_authentication_complete_callback(auth_result); }
 36  void BLESerial::onConnect(BLEServer *server) { bt_connect_callback(server); }
 37  void BLESerial::onDisconnect(BLEServer *server) { bt_disconnect_callback(server); ble_server->startAdvertising(); }
 38  bool BLESerial::onConfirmPIN(uint32_t pin) { return bt_confirm_pin_callback(pin); };
 39  bool BLESerial::connected() { return ble_server->getConnectedCount() > 0; }
 40  
 41  int BLESerial::read() {
 42    int result = this->rx_buffer.pop();
 43    if (result == '\n') { this->numAvailableLines--; }
 44    return result;
 45  }
 46  
 47  size_t BLESerial::readBytes(uint8_t *buffer, size_t bufferSize) {
 48    int i = 0;
 49    while (i < bufferSize && available()) { buffer[i] = (uint8_t)this->rx_buffer.pop(); i++; }
 50    return i;
 51  }
 52  
 53  int BLESerial::peek() {
 54    if (this->rx_buffer.getLength() == 0) return -1;
 55    return this->rx_buffer.get(0);
 56  }
 57  
 58  int BLESerial::available() { return this->rx_buffer.getLength(); }
 59  
 60  size_t BLESerial::print(const char *str) {
 61    if (ble_server->getConnectedCount() <= 0) return 0;
 62    size_t written = 0; for (size_t i = 0; str[i] != '\0'; i++)  { written += this->write(str[i]); }
 63    flush();
 64  
 65    return written;
 66  }
 67  
 68  size_t BLESerial::write(const uint8_t *buffer, size_t bufferSize) {
 69    if (ble_server->getConnectedCount() <= 0) { return 0; } else {
 70      size_t written = 0; for (int i = 0; i < bufferSize; i++) { written += this->write(buffer[i]); }
 71      flush();
 72  
 73      return written;
 74    }
 75  }
 76  
 77  size_t BLESerial::write(uint8_t byte) {
 78    if (bt_client_authenticated()) {
 79      if (ble_server->getConnectedCount() <= 0) { return 0; } else {
 80        this->transmitBuffer[this->transmitBufferLength] = byte;
 81        this->transmitBufferLength++;
 82        if (this->transmitBufferLength == maxTransferSize) { flush(); }
 83        return 1;
 84      }
 85    } else {
 86      return 0;
 87    }
 88  }
 89  
 90  void BLESerial::flush() {
 91    if (this->transmitBufferLength > 0) {
 92      TxCharacteristic->setValue(this->transmitBuffer, this->transmitBufferLength);
 93      this->transmitBufferLength = 0;
 94      this->lastFlushTime = millis();
 95      TxCharacteristic->notify(true);
 96    }
 97  }
 98  
 99  void BLESerial::disconnect() {
100    if (ble_server->getConnectedCount() > 0) {
101      uint16_t conn_id = ble_server->getConnId();
102      // Serial.printf("Have connected: %d\n", conn_id);
103      ble_server->disconnect(conn_id);
104      // Serial.println("Disconnected");
105    } else {
106      // Serial.println("No connected");
107    }
108  }
109  
110  void BLESerial::begin(const char *name) {
111    ConnectedDeviceCount = 0;
112    BLEDevice::init(name);
113  
114    esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9); 
115    esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9);
116    esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN ,ESP_PWR_LVL_P9);
117  
118    ble_server = BLEDevice::createServer();
119    ble_server->setCallbacks(this);
120    // Use level 0 so esp_ble_set_encryption is not auto-called on connect (BLEDevice.cpp).
121    // ESP-IDF 5+ may define ESP_BLE_SEC_NONE; Arduino-ESP32 2.0.x does not — use (esp_ble_sec_act_t)0.
122    #if defined(ESP_BLE_SEC_NONE)
123      BLEDevice::setEncryptionLevel(ESP_BLE_SEC_NONE);
124    #else
125      BLEDevice::setEncryptionLevel((esp_ble_sec_act_t)0);
126    #endif
127    BLEDevice::setSecurityCallbacks(this);
128  
129    SetupSerialService();
130    this->startAdvertising();
131  }
132  
133  void BLESerial::startAdvertising() {
134    ble_adv = BLEDevice::getAdvertising();
135    ble_adv->addServiceUUID(BLE_SERIAL_SERVICE_UUID);
136    ble_adv->setMinPreferred(0x20);
137    ble_adv->setMaxPreferred(0x40);
138    ble_adv->setScanResponse(true);
139    ble_adv->start();
140  }
141  
142  void BLESerial::stopAdvertising() {
143    ble_adv = BLEDevice::getAdvertising();
144    ble_adv->stop();
145  }
146  
147  void BLESerial::end() { BLEDevice::deinit(); }
148  
149  void BLESerial::onWrite(BLECharacteristic *characteristic) {
150    if (characteristic->getUUID().toString() == BLE_RX_UUID) {
151      auto value = characteristic->getValue();
152      for (int i = 0; i < value.length(); i++) { rx_buffer.push(value[i]); }
153    }
154  }
155  
156  void BLESerial::SetupSerialService() {
157    SerialService = ble_server->createService(BLE_SERIAL_SERVICE_UUID);
158  
159    RxCharacteristic = SerialService->createCharacteristic(BLE_RX_UUID, BLECharacteristic::PROPERTY_WRITE);
160    RxCharacteristic->setAccessPermissions(ESP_GATT_PERM_WRITE_ENC_MITM);
161    RxCharacteristic->addDescriptor(new BLE2902());
162    RxCharacteristic->setWriteProperty(true);
163    RxCharacteristic->setCallbacks(this);
164  
165    TxCharacteristic = SerialService->createCharacteristic(BLE_TX_UUID, BLECharacteristic::PROPERTY_NOTIFY);
166    TxCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM);
167    TxCharacteristic->addDescriptor(new BLE2902());
168    TxCharacteristic->setNotifyProperty(true);
169    TxCharacteristic->setReadProperty(true);
170  
171    SerialService->start();
172  }
173  
174  BLESerial::BLESerial() { }
175  
176  #endif
177  #endif