diff --git a/components/remote_control/CMakeLists.txt b/components/remote_control/CMakeLists.txt index ee82fd8..ae34fa6 100644 --- a/components/remote_control/CMakeLists.txt +++ b/components/remote_control/CMakeLists.txt @@ -1,6 +1,11 @@ -idf_component_register(SRCS "led_service.c" "device_service.c" "remote_control.c" +idf_component_register(SRCS + "capability_service.c" + "device_service.c" + "led_service.c" + "remote_control.c" INCLUDE_DIRS "include" PRIV_REQUIRES bt + esp_app_format led_matrix ) diff --git a/components/remote_control/capability_service.c b/components/remote_control/capability_service.c new file mode 100644 index 0000000..9105713 --- /dev/null +++ b/components/remote_control/capability_service.c @@ -0,0 +1,18 @@ +#include "capability_service.h" + +static const char *capa_json = "{" + "}"; + +int capa_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + char *content = "JSON"; + os_mbuf_append(ctxt->om, content, strlen(content)); + return 0; +} + +int capa_char_1979_user_desc(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + const char *desc = "Capabilities of the device"; + os_mbuf_append(ctxt->om, desc, strlen(desc)); + return 0; +} diff --git a/components/remote_control/device_service.c b/components/remote_control/device_service.c index 654634c..bf0af6d 100644 --- a/components/remote_control/device_service.c +++ b/components/remote_control/device_service.c @@ -1,9 +1,23 @@ #include "include/device_service.h" +#include "esp_app_desc.h" +#include +#include int ds_model_number_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { - char *model_number = "Miniature Town v1"; - os_mbuf_append(ctxt->om, model_number, strlen(model_number)); + char model_number_str[65]; + const esp_app_desc_t *app_desc = esp_app_get_description(); + + if (app_desc->project_name[0] != '\0' && app_desc->version[0] != '\0') + { + snprintf(model_number_str, sizeof(model_number_str), "%s v%s", app_desc->project_name, app_desc->version); + } + else + { + snprintf(model_number_str, sizeof(model_number_str), "undefined"); + } + + os_mbuf_append(ctxt->om, model_number_str, strlen(model_number_str)); return 0; } diff --git a/components/remote_control/include/capability_service.h b/components/remote_control/include/capability_service.h new file mode 100644 index 0000000..cab8e63 --- /dev/null +++ b/components/remote_control/include/capability_service.h @@ -0,0 +1,10 @@ +#pragma once + +#include "host/ble_hs.h" +#include + +/// Service Characteristics Callback +int capa_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); + +/// Service Characteristics User Description +int capa_char_1979_user_desc(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); diff --git a/components/remote_control/include/led_service.h b/components/remote_control/include/led_service.h index 13212eb..5875481 100644 --- a/components/remote_control/include/led_service.h +++ b/components/remote_control/include/led_service.h @@ -8,7 +8,5 @@ int ls_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ int ls_capabilities_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); /// LED Service Characteristic User Description -int ls_char_a000_user_desc_read(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg); -int ls_char_dead_user_desc_read(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg); +int ls_char_a000_user_desc(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +int ls_char_dead_user_desc(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); diff --git a/components/remote_control/led_service.c b/components/remote_control/led_service.c index 6a30e80..fbf261d 100644 --- a/components/remote_control/led_service.c +++ b/components/remote_control/led_service.c @@ -62,16 +62,14 @@ int ls_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ return 0; } -int ls_char_a000_user_desc_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg) +int ls_char_a000_user_desc(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { const char *desc = "Capabilities of Device"; os_mbuf_append(ctxt->om, desc, strlen(desc)); return 0; } -int ls_char_dead_user_desc_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg) +int ls_char_dead_user_desc(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { const char *desc = "Readable Data from Server"; os_mbuf_append(ctxt->om, desc, strlen(desc)); diff --git a/components/remote_control/remote_control.c b/components/remote_control/remote_control.c index aa677dc..c6919fd 100644 --- a/components/remote_control/remote_control.c +++ b/components/remote_control/remote_control.c @@ -1,6 +1,7 @@ #include #include +#include "capability_service.h" #include "esp_event.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" @@ -21,27 +22,35 @@ static const char *TAG = "remote_control"; static const ble_uuid16_t device_service_uuid = BLE_UUID16_INIT(0x180A); -static const ble_uuid128_t led_service_uuid128 = +static const ble_uuid128_t capability_service_uuid = BLE_UUID128_INIT(0x91, 0xB6, 0xCA, 0x95, 0xB2, 0xC6, 0x7B, 0x90, 0x31, 0x45, 0x77, 0xE6, 0x67, 0x10, 0x68, 0xB9); +static const ble_uuid16_t led_service_uuid = BLE_UUID16_INIT(0x1007); uint8_t ble_addr_type; -void ble_app_advertise(void); +static void ble_app_advertise(void); static struct ble_gatt_dsc_def char_0xA000_descs[] = {{ .uuid = BLE_UUID16_DECLARE(0x2901), .att_flags = BLE_ATT_F_READ, - .access_cb = ls_char_a000_user_desc_read, + .access_cb = ls_char_a000_user_desc, }, {0}}; static struct ble_gatt_dsc_def char_0xDEAD_descs[] = {{ .uuid = BLE_UUID16_DECLARE(0x2901), .att_flags = BLE_ATT_F_WRITE, - .access_cb = ls_char_dead_user_desc_read, + .access_cb = ls_char_dead_user_desc, }, {0}}; +static struct ble_gatt_dsc_def char_0x1979_desc[] = {{ + .uuid = BLE_UUID16_DECLARE(0x2901), + .att_flags = BLE_ATT_F_READ, + .access_cb = capa_char_1979_user_desc, + }, + {0}}; + // Array of pointers to other service definitions static const struct ble_gatt_svc_def gatt_svcs[] = { { @@ -55,7 +64,18 @@ static const struct ble_gatt_svc_def gatt_svcs[] = { }, { .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = &led_service_uuid128.u, + .uuid = &capability_service_uuid.u, + .characteristics = (struct ble_gatt_chr_def[]){{ + .uuid = BLE_UUID16_DECLARE(0x1979), + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + .access_cb = capa_read, + .descriptors = char_0x1979_desc, + }, + {0}}, + }, + { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &led_service_uuid.u, .characteristics = (struct ble_gatt_chr_def[]){{ .uuid = BLE_UUID16_DECLARE(0xA000), .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, @@ -105,23 +125,24 @@ static int ble_gap_event(struct ble_gap_event *event, void *arg) } // Define the BLE connection -void ble_app_advertise(void) +static void ble_app_advertise(void) { - // GAP - device name definition - struct ble_hs_adv_fields fields; - struct ble_hs_adv_fields scan_rsp_fields; - const char *device_name; int ret; - memset(&fields, 0, sizeof(fields)); - // GAP - advertising definition + struct ble_hs_adv_fields fields; + memset(&fields, 0, sizeof(fields)); fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; - fields.uuids128 = (ble_uuid128_t[]){led_service_uuid128}; + fields.uuids128 = (ble_uuid128_t[]){capability_service_uuid}; fields.num_uuids128 = 1; fields.uuids128_is_complete = 1; - ble_gap_adv_set_fields(&fields); + ret = ble_gap_adv_set_fields(&fields); + if (ret != 0) + { + ESP_LOGE(TAG, "Failed to set advertising data (err: %d)", ret); + return; + } // GAP - device connectivity definition struct ble_gap_adv_params adv_params; @@ -136,9 +157,11 @@ void ble_app_advertise(void) } // --- Configure Scan Response Data (SCAN_RSP) --- + struct ble_hs_adv_fields scan_rsp_fields; memset(&scan_rsp_fields, 0, sizeof(scan_rsp_fields)); // Get the device name + const char *device_name; device_name = ble_svc_gap_device_name(); scan_rsp_fields.name = (uint8_t *)device_name; scan_rsp_fields.name_len = strlen(device_name); @@ -157,30 +180,41 @@ void ble_app_advertise(void) } // The application -void ble_app_on_sync(void) +static void ble_app_on_sync(void) { + uint8_t ble_addr[6] = {0}; + int ret = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, ble_addr, NULL); + if (ret != 0) + { + ESP_LOGE(TAG, "Failed to get BLE MAC address (err: %d)", ret); + return; + } + + char formatted_name[32]; + snprintf(formatted_name, sizeof(formatted_name), "Miniature Town %02X%02X", ble_addr[4], ble_addr[5]); + ble_svc_gap_device_name_set(formatted_name); + + // Start Advertising ble_hs_id_infer_auto(0, &ble_addr_type); // Determines the best address type automatically - ble_app_advertise(); // Define the BLE connection + ble_app_advertise(); } // The infinite task -void host_task(void *param) +static void host_task(void *param) { - nimble_port_run(); // This function will return only when nimble_port_stop() - // is executed + nimble_port_run(); // This function will return only when nimble_port_stop() is executed } void ble_init(void) { nimble_port_init(); - ble_svc_gap_device_name_set("Miniature Town"); ble_svc_gap_init(); ble_svc_gatt_init(); ble_gatts_count_cfg(gatt_svcs); ble_gatts_add_svcs(gatt_svcs); + + // Callback für Synchronisation ble_hs_cfg.sync_cb = ble_app_on_sync; - nimble_port_freertos_init(host_task); // Run the host task - - xTaskCreatePinnedToCore(led_matrix_init, "led_matrix", configMINIMAL_STACK_SIZE * 2, NULL, 5, NULL, 1); + nimble_port_freertos_init(host_task); // Start BLE-Host-Task } diff --git a/main/main.c b/main/main.c index 5715c09..f5b9bd1 100644 --- a/main/main.c +++ b/main/main.c @@ -1,3 +1,5 @@ +#include "freertos/FreeRTOS.h" +#include "led_matrix.h" #include "persistence.h" #include "remote_control.h" @@ -5,4 +7,5 @@ void app_main(void) { persistence_init("miniature_town"); ble_init(); + xTaskCreatePinnedToCore(led_matrix_init, "led_matrix", configMINIMAL_STACK_SIZE * 2, NULL, 5, NULL, 1); }