From 87c4ec642ed44fd589b4d1874dd0691c1955f8fd Mon Sep 17 00:00:00 2001 From: simonmicro Date: Sun, 19 May 2024 19:08:55 +0200 Subject: [PATCH] Added BLE server task Signed-off-by: simonmicro --- include/services/OswServiceTaskBLECompanion.h | 6 +- include/services/OswServiceTaskBLEServer.h | 38 ++++++++ include/services/OswServiceTasks.h | 4 + platformio.ini | 1 + src/osw_config.cpp | 5 + src/services/OswServiceTaskBLECompanion.cpp | 2 + src/services/OswServiceTaskBLEServer.cpp | 97 +++++++++++++++++++ src/services/OswServiceTasks.cpp | 7 ++ 8 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 include/services/OswServiceTaskBLEServer.h create mode 100644 src/services/OswServiceTaskBLEServer.cpp diff --git a/include/services/OswServiceTaskBLECompanion.h b/include/services/OswServiceTaskBLECompanion.h index bb68d05ad..79b62c367 100644 --- a/include/services/OswServiceTaskBLECompanion.h +++ b/include/services/OswServiceTaskBLECompanion.h @@ -1,6 +1,6 @@ -#ifndef OSW_SERVICE_COMPANION_H -#define OSW_SERVICE_COMPANION_H +#pragma once +#if SERVICE_BLE_COMPANION == 1 #ifndef OSW_EMULATOR #include #include @@ -43,4 +43,4 @@ class OswServiceTaskBLECompanion : public OswServiceTask { }; #endif -#endif \ No newline at end of file +#endif diff --git a/include/services/OswServiceTaskBLEServer.h b/include/services/OswServiceTaskBLEServer.h new file mode 100644 index 000000000..686e65d40 --- /dev/null +++ b/include/services/OswServiceTaskBLEServer.h @@ -0,0 +1,38 @@ +#pragma once +#ifdef OSW_FEATURE_BLE_SERVER +#include "osw_service.h" + +#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL +#include + +class OswServiceTaskBLEServer : public OswServiceTask, NimBLEServerCallbacks { + public: + OswServiceTaskBLEServer() {}; + virtual void setup() override; + virtual void loop() override; + virtual void stop() override; + ~OswServiceTaskBLEServer() {}; + + void updateName(); + private: + class BatteryCharacteristicCallbacks: public NimBLECharacteristicCallbacks { + void onRead(NimBLECharacteristic* pCharacteristic); + uint8_t byte = 0; // will be read from + }; + + // ↓ NimBLEServerCallbacks + void onConnect(BLEServer* pServer); + void onDisconnect(BLEServer* pServer); + uint32_t onPassKeyRequest(); + bool onConfirmPIN(uint32_t pass_key); + + // ↓ managed by NimBLE + NimBLEServer* server = nullptr; + BLEService* serviceBat = nullptr; + NimBLECharacteristic* characteristicBat = nullptr; + + // ↓ our own stuff + char name[8]; // BLE advertising only support up to 8 bytes + BatteryCharacteristicCallbacks battery; +}; +#endif diff --git a/include/services/OswServiceTasks.h b/include/services/OswServiceTasks.h index d880bfaa2..9557e94a5 100644 --- a/include/services/OswServiceTasks.h +++ b/include/services/OswServiceTasks.h @@ -1,6 +1,7 @@ #include "osw_service.h" class OswServiceTaskBLECompanion; +class OswServiceTaskBLEServer; class OswServiceTaskExample; class OswServiceTaskMemMonitor; class OswServiceTaskNotifier; @@ -20,6 +21,9 @@ extern OswServiceTaskWebserver webserver; #if OSW_SERVICE_NOTIFIER == 1 extern OswServiceTaskNotifier notifier; #endif +#ifdef OSW_FEATURE_BLE_SERVER +extern OswServiceTaskBLEServer bleServer; +#endif extern OswServiceTaskMemMonitor memory; } diff --git a/platformio.ini b/platformio.ini index 7ff9a6281..e3b6256f1 100755 --- a/platformio.ini +++ b/platformio.ini @@ -28,6 +28,7 @@ lib_deps = bblanchon/ArduinoJson@^6.21.2 finitespace/BME280@^3.0.0 ; TODO Use the more popular Adafruit BME280 Library instead (also true for others?)? mprograms/QMC5883LCompass@^1.1.1 + h2zero/NimBLE-Arduino@^1.4.1 upload_speed = 460800 monitor_speed = 115200 ; Define additional build stage scripts - used to "compile" the html or define additional information diff --git a/src/osw_config.cpp b/src/osw_config.cpp index 4219ec2be..c90d9971d 100644 --- a/src/osw_config.cpp +++ b/src/osw_config.cpp @@ -13,6 +13,8 @@ #include // For timezone reloading #include // For color reloading #include "apps/watchfaces/OswAppWatchfaceDigital.h" +#include +#include std::unique_ptr OswConfig::instance = nullptr; @@ -160,4 +162,7 @@ void OswConfig::notifyChange() { // OswUI::getInstance()->resetTextColors(); // nope - this is done by the ui itself OswHal::getInstance()->updateTimezoneOffsets(); OswAppWatchfaceDigital::refreshDateFormatCache(); +#ifdef OSW_FEATURE_BLE_SERVER + OswServiceAllTasks::bleServer.updateName(); +#endif } \ No newline at end of file diff --git a/src/services/OswServiceTaskBLECompanion.cpp b/src/services/OswServiceTaskBLECompanion.cpp index 07490d263..461736ef5 100644 --- a/src/services/OswServiceTaskBLECompanion.cpp +++ b/src/services/OswServiceTaskBLECompanion.cpp @@ -1,3 +1,4 @@ +#if SERVICE_BLE_COMPANION == 1 #ifndef OSW_EMULATOR #include "./services/OswServiceTaskBLECompanion.h" #include "osw_hal.h" @@ -94,4 +95,5 @@ void OswServiceTaskBLECompanion::loop() { void OswServiceTaskBLECompanion::stop() { OswServiceTask::stop(); } +#endif #endif \ No newline at end of file diff --git a/src/services/OswServiceTaskBLEServer.cpp b/src/services/OswServiceTaskBLEServer.cpp new file mode 100644 index 000000000..df0358da7 --- /dev/null +++ b/src/services/OswServiceTaskBLEServer.cpp @@ -0,0 +1,97 @@ +#ifdef OSW_FEATURE_BLE_SERVER +#include "./services/OswServiceTaskBLEServer.h" +#include "osw_hal.h" + +#define BATTERY_SERVICE_UUID "0000180F-0000-1000-8000-00805f9b34fb" +#define BATTERY_LEVEL_CHARACTERISTIC_UUID "00002A19-0000-1000-8000-00805f9b34fb" + +void OswServiceTaskBLEServer::setup() { + OswServiceTask::setup(); + this->updateName(); + + NimBLEDevice::setSecurityAuth(true, false, false); // support bonding, but no mitm-protection or secure pairing + NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_YESNO); // we can display yes/no with a given key to the user + + // Create the BLE Server + server = NimBLEDevice::getServer(); + if(server == nullptr) { + OSW_LOG_D("No server found, creating a new one."); + server = NimBLEDevice::createServer(); + } + server->setCallbacks(this); // make sure, we are the servers authority + + { + // Create the BLE Service + serviceBat = server->createService(BATTERY_SERVICE_UUID); + + // Create a BLE Characteristic + characteristicBat = serviceBat->createCharacteristic( + BATTERY_LEVEL_CHARACTERISTIC_UUID, + NIMBLE_PROPERTY::READ + ); + characteristicBat->setCallbacks(&battery); + + // Start the service + serviceBat->start(); + } + + // Start advertising + { + BLEAdvertising* pAdvertising = BLEDevice::getAdvertising(); + pAdvertising->addServiceUUID(BATTERY_SERVICE_UUID); + pAdvertising->setScanResponse(false); + /** Note, this could be left out as that is the default value */ + pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter + BLEDevice::startAdvertising(); + } +} + +void OswServiceTaskBLEServer::loop() { + +} + +void OswServiceTaskBLEServer::stop() { + OswServiceTask::stop(); + + BLEDevice::stopAdvertising(); + serviceBat->removeCharacteristic(characteristicBat, true); + server->removeService(serviceBat, true); +} + +void OswServiceTaskBLEServer::updateName() { + memset(this->name, 0, 8); // clear the name buffer + strncpy(this->name, OswConfigAllKeys::hostname.get().c_str(), 8); + NimBLEDevice::init(this->name); +} + +void OswServiceTaskBLEServer::onConnect(BLEServer* pServer) { + OSW_LOG_D("A client has connected!"); +} + +void OswServiceTaskBLEServer::onDisconnect(BLEServer* pServer) { + OSW_LOG_D("A client has disconnected!"); +} + +uint32_t OswServiceTaskBLEServer::onPassKeyRequest() { + // TODO connecting client asked for a pin to confirm + OSW_LOG_I("Server PassKeyRequest: ", 123456); + return 123456; +} + +bool OswServiceTaskBLEServer::onConfirmPIN(uint32_t pass_key) { + // TODO user must confirm if this is the correct key sent by the other device + OSW_LOG_I("The passkey YES/NO number: ", pass_key); + return true; +} + + +void OswServiceTaskBLEServer::BatteryCharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic) { + // get the current battery level into the inner byte buffer + if(OswHal::getInstance()->isCharging()) { + byte = 255; // invalid value + } else { + this->byte = OswHal::getInstance()->getBatteryPercent(); + } + pCharacteristic->setValue(&this->byte, 1); +} +#endif diff --git a/src/services/OswServiceTasks.cpp b/src/services/OswServiceTasks.cpp index 45aa19ff6..5467b9094 100644 --- a/src/services/OswServiceTasks.cpp +++ b/src/services/OswServiceTasks.cpp @@ -1,6 +1,7 @@ #include "services/OswServiceTasks.h" #include "services/OswServiceTaskBLECompanion.h" +#include "services/OswServiceTaskBLEServer.h" #include "services/OswServiceTaskExample.h" #include "services/OswServiceTaskGPS.h" #include "services/OswServiceTaskMemMonitor.h" @@ -24,6 +25,9 @@ OswServiceTaskGPS gps; OswServiceTaskWiFi wifi; OswServiceTaskWebserver webserver; #endif +#ifdef OSW_FEATURE_BLE_SERVER +OswServiceTaskBLEServer bleServer; +#endif #if OSW_SERVICE_NOTIFIER == 1 OswServiceTaskNotifier notifier; #endif @@ -44,6 +48,9 @@ OswServiceTask* oswServiceTasks[] = { #ifdef OSW_FEATURE_WIFI & OswServiceAllTasks::wifi, &OswServiceAllTasks::webserver, #endif +#ifdef OSW_FEATURE_BLE_SERVER + & OswServiceAllTasks::bleServer, +#endif #if OSW_SERVICE_NOTIFIER == 1 & OswServiceAllTasks::notifier, #endif