From 7faf53d9bae62a1b5cd4842b6bcf36999945d752 Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Sun, 18 May 2025 17:01:40 +0200 Subject: [PATCH] testing BLE Signed-off-by: Peter Siegmund --- components/remote_control/CMakeLists.txt | 7 +- components/remote_control/remote_control.c | 145 +++++++++++++++++++-- main/main.c | 2 +- 3 files changed, 144 insertions(+), 10 deletions(-) diff --git a/components/remote_control/CMakeLists.txt b/components/remote_control/CMakeLists.txt index ad8a575..05de17e 100644 --- a/components/remote_control/CMakeLists.txt +++ b/components/remote_control/CMakeLists.txt @@ -1,2 +1,7 @@ idf_component_register(SRCS "remote_control.c" - INCLUDE_DIRS "include") + INCLUDE_DIRS "include" + REQUIRES + bt + esp_timer + nvs_flash +) diff --git a/components/remote_control/remote_control.c b/components/remote_control/remote_control.c index 469b3bd..604bf4d 100644 --- a/components/remote_control/remote_control.c +++ b/components/remote_control/remote_control.c @@ -1,18 +1,147 @@ -#include "remote_control.h" - -#include "esp_log.h" +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp_log.h" +#include "nvs_flash.h" + +// NimBLE-Header +#include "esp_nimble_hci.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "services/gap/ble_svc_gap.h" + +// Tag für Logging +static const char *TAG = "remote_control"; + +#define DEVICE_NAME "Miniature Town" + +uint8_t ble_addr_type; + +/** + * Konfiguriert und startet das BLE-Advertising. + */ +static void ble_app_advertise(void) +{ + struct ble_gap_adv_params adv_params; + struct ble_hs_adv_fields fields; + int rc; + + // Fülle die Advertising-Felder + memset(&fields, 0, sizeof(fields)); + + // Flags: + // - BLE_HS_ADV_F_DISC_GEN: General discoverable mode + // - BLE_HS_ADV_F_BREDR_UNSUP: BR/EDR (Classic Bluetooth) nicht unterstützt + fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; + + // Device Name + // Stelle sicher, dass der Name + Overhead in das Advertising-Paket passt. + // Bei Bedarf muss der Name gekürzt werden oder in Scan Response platziert werden. + fields.name = (uint8_t *)DEVICE_NAME; + fields.name_len = strlen(DEVICE_NAME); + fields.name_is_complete = 1; // Der Name ist vollständig im Advertising-Paket + + // Setze die Advertising-Daten + rc = ble_gap_adv_set_fields(&fields); + if (rc != 0) + { + ESP_LOGE(TAG, "Fehler beim Setzen der Advertising-Daten; rc=%d", rc); + return; + } + + // Konfiguriere die Advertising-Parameter + memset(&adv_params, 0, sizeof(adv_params)); + adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; // Undirected connectable + adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; // General discoverable + + // Starte das Advertising + // Parameter: + // - own_addr_type: Typ der eigenen Adresse (wird von ble_hs_id_infer_auto gesetzt) + // - peer_addr: NULL für undirected advertising + // - duration_ms: BLE_HS_FOREVER für kontinuierliches Advertising + // - adv_params: Die oben konfigurierten Parameter + // - cb: Callback-Funktion bei GAP-Events (z.B. Verbindung, Trennung) + // - cb_arg: Argument für die Callback-Funktion + rc = ble_gap_adv_start(ble_addr_type, NULL, BLE_HS_FOREVER, &adv_params, NULL, NULL); + if (rc != 0) + { + ESP_LOGE(TAG, "Fehler beim Starten des Advertising; rc=%d", rc); + return; + } + ESP_LOGI(TAG, "Advertising gestartet. Gerät sollte sichtbar sein als '%s'", DEVICE_NAME); +} + +/** + * Callback-Funktion, die aufgerufen wird, wenn der BLE-Host-Stack synchronisiert (bereit) ist. + */ +static void ble_app_on_sync(void) +{ + int rc; + + // Setze eine zufällige statische Adresse oder eine öffentliche Adresse + // Hier verwenden wir eine zufällige statische Adresse als Beispiel + rc = ble_hs_id_infer_auto(0, &ble_addr_type); + if (rc != 0) + { + ESP_LOGE(TAG, "Fehler beim Bestimmen der Adresse; rc=%d", rc); + return; + } + + // Die Adresse wurde gesetzt, starte Advertising + ble_app_advertise(); +} + +/** + * Host-Task für NimBLE. + */ +void ble_host_task(void *param) +{ + ESP_LOGI(TAG, "BLE Host Task gestartet"); + // Dieser Aufruf blockiert, bis nimble_port_stop() aufgerufen wird + nimble_port_run(); + + nimble_port_freertos_deinit(); +} void ble_init(void *args) { - ESP_LOGI(pcTaskGetName(NULL), "Calling ble_init()"); + int rc; - while (1) + // Initialisiere NVS (Non-Volatile Storage) + // Dies ist für BLE erforderlich, um Controller-Konfigurationen zu speichern + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - vTaskDelay(pdMS_TO_TICKS(100)); + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); } + ESP_ERROR_CHECK(ret); - ESP_LOGI(pcTaskGetName(NULL), "Exiting ble_init()"); - vTaskDelete(NULL); + // Initialisiere den NimBLE-Port (FreeRTOS spezifisch) + nimble_port_init(); + + // Konfiguriere den BLE-Host-Stack: + // - Setze den Callback für "on_sync" (wenn der Stack bereit ist) + // - Setze den Callback für "on_reset" (wenn der Controller zurückgesetzt wird) + ble_hs_cfg.sync_cb = ble_app_on_sync; + ble_hs_cfg.reset_cb = NULL; // Hier nicht explizit benötigt für einfaches Advertising + + // Optional: Setze den Gerätenamen direkt im GAP Service. + // Dies ist eine andere Stelle als das Advertising-Paket, aber gute Praxis. + rc = ble_svc_gap_device_name_set(DEVICE_NAME); + assert(rc == 0); + + // Initialisiere das NimBLE HCI Layer + // ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init()); // Für ESP32, ESP32-C3, ESP32-S3 (kombinierter Host & Controller) + // Für ESP32-C2, ESP32-C6, ESP32-H2, die VHCI verwenden, wird eine andere Initialisierung benötigt. + // Aber für typische ESP32 ist dies korrekt. + + // Starte den NimBLE Host Task in einem eigenen Thread. + // Die Priorität und Stack-Größe können angepasst werden. + // NIMBLE_STACK_SIZE ist in nimble_port_freertos.h definiert + nimble_port_freertos_init(ble_host_task); + + ESP_LOGI(TAG, "BLE App Main abgeschlossen. BLE Host Task läuft."); } diff --git a/main/main.c b/main/main.c index ba81b39..6b2b636 100644 --- a/main/main.c +++ b/main/main.c @@ -7,5 +7,5 @@ void app_main(void) { xTaskCreatePinnedToCore(led_matrix_init, "led_matrix", configMINIMAL_STACK_SIZE * 2, NULL, 5, NULL, 1); - xTaskCreatePinnedToCore(ble_init, "remote_control", configMINIMAL_STACK_SIZE * 2, NULL, 5, NULL, 1); + ble_init(NULL); }