From e26dd83f5d915943711efa5219095a105f658c39 Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Wed, 27 Aug 2025 21:09:20 +0200 Subject: [PATCH] more characteristics and descriptors Signed-off-by: Peter Siegmund --- firmware/components/light/beacon.c | 51 ++++-- .../components/remote_control/CMakeLists.txt | 1 + .../remote_control/device_service.c | 12 +- .../remote_control/include/device_service.h | 20 +-- .../remote_control/include/light_service.h | 20 ++- .../components/remote_control/light_service.c | 166 +++++++++--------- .../remote_control/remote_control.c | 89 ++++++---- 7 files changed, 195 insertions(+), 164 deletions(-) diff --git a/firmware/components/light/beacon.c b/firmware/components/light/beacon.c index 25e2924..c1f966a 100644 --- a/firmware/components/light/beacon.c +++ b/firmware/components/light/beacon.c @@ -28,24 +28,27 @@ static bool IRAM_ATTR beacon_timer_callback(gptimer_handle_t timer, const gptime return true; } +static void led_refresh(uint32_t brightness) +{ + LedMatrix_t led_matrix = get_led_matrix(); + + for (uint32_t i = 0; i < led_matrix.size; i++) + { + led_strip_set_pixel(led_matrix.led_strip, i, 0, brightness, 0); + } + led_strip_refresh(led_matrix.led_strip); +} + static void beacon_timer_event_task(void *arg) { while (true) { if (xSemaphoreTake(timer_semaphore, portMAX_DELAY)) { - LedMatrix_t led_matrix = get_led_matrix(); static bool level = false; level = !level; - if (led_matrix.led_strip) - { - for (uint32_t i = 0; i < led_matrix.size; i++) - { - led_strip_set_pixel(led_matrix.led_strip, i, 0, (level) ? value : 0, 0); - } - led_strip_refresh(led_matrix.led_strip); - } + led_refresh(level ? value : 0); ESP_LOGD(TAG, "Timer Event, LED now %s", level ? "ON" : "OFF"); } } @@ -58,7 +61,21 @@ esp_err_t beacon_start(void) ESP_LOGE(TAG, "GPTimer not initialized"); return ESP_ERR_INVALID_STATE; } - esp_err_t ret = gptimer_start(gptimer); + esp_err_t ret = gptimer_enable(gptimer); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "Failed to enable gptimer: %s", esp_err_to_name(ret)); + return beacon_stop(); + } + + ret = gptimer_set_raw_count(gptimer, 0); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "Failed to set gptimer raw count: %s", esp_err_to_name(ret)); + return beacon_stop(); + } + + ret = gptimer_start(gptimer); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to start gptimer: %s", esp_err_to_name(ret)); @@ -72,6 +89,7 @@ esp_err_t beacon_start(void) esp_err_t beacon_stop(void) { + led_refresh(0); if (gptimer == NULL) { ESP_LOGE(TAG, "GPTimer not initialized"); @@ -86,6 +104,12 @@ esp_err_t beacon_stop(void) { ESP_LOGI(TAG, "GPTimer stopped."); } + + ret = gptimer_disable(gptimer); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "Failed to enable gptimer: %s", esp_err_to_name(ret)); + } return ret; } @@ -115,13 +139,6 @@ esp_err_t beacon_init(void) goto cleanupTimer; } - ret = gptimer_enable(gptimer); - if (ret != ESP_OK) - { - ESP_LOGE(TAG, "Failed to enable gptimer: %s", esp_err_to_name(ret)); - goto cleanupTimer; - } - gptimer_alarm_config_t alarm_config = { .alarm_count = 2000000, .reload_count = 0, diff --git a/firmware/components/remote_control/CMakeLists.txt b/firmware/components/remote_control/CMakeLists.txt index 69633b1..8cfd239 100644 --- a/firmware/components/remote_control/CMakeLists.txt +++ b/firmware/components/remote_control/CMakeLists.txt @@ -6,4 +6,5 @@ idf_component_register(SRCS PRIV_REQUIRES bt esp_app_format + light ) diff --git a/firmware/components/remote_control/device_service.c b/firmware/components/remote_control/device_service.c index 9d60189..45630ab 100644 --- a/firmware/components/remote_control/device_service.c +++ b/firmware/components/remote_control/device_service.c @@ -3,7 +3,7 @@ #include #include -int device_name_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int device_name_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { char firmware_revision_str[33]; const esp_app_desc_t *app_desc = esp_app_get_description(); @@ -21,8 +21,8 @@ int device_name_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt return 0; } -int device_firmware_revision_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg) +int device_firmware_revision_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg) { char firmware_revision_str[33]; const esp_app_desc_t *app_desc = esp_app_get_description(); @@ -40,15 +40,15 @@ int device_firmware_revision_read(uint16_t conn_handle, uint16_t attr_handle, st return 0; } -int device_hardware_revision_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg) +int device_hardware_revision_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg) { char *hardware_revision = "rev1"; os_mbuf_append(ctxt->om, hardware_revision, strlen(hardware_revision)); return 0; } -int device_manufacturer_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int device_manufacturer_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { char *manufacturer = "mars3142"; os_mbuf_append(ctxt->om, manufacturer, strlen(manufacturer)); diff --git a/firmware/components/remote_control/include/device_service.h b/firmware/components/remote_control/include/device_service.h index 7c8c994..178b41a 100644 --- a/firmware/components/remote_control/include/device_service.h +++ b/firmware/components/remote_control/include/device_service.h @@ -3,16 +3,16 @@ #include "host/ble_hs.h" #include -// 0x2A00 Device Name -int device_name_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +// 0x2A00 - Device Name +int device_name_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); -// 0x2A26 Firmware Revision String -int device_firmware_revision_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg); +// 0x2A26 - Firmware Revision String +int device_firmware_revision_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg); -// 0x2A27 Hardware Revision String -int device_hardware_revision_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg); +// 0x2A27 - Hardware Revision String +int device_hardware_revision_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg); -// 0x2A29 Manufacturer Name String -int device_manufacturer_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +// 0x2A29 - Manufacturer Name String +int device_manufacturer_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); diff --git a/firmware/components/remote_control/include/light_service.h b/firmware/components/remote_control/include/light_service.h index f03c3f6..c245be1 100644 --- a/firmware/components/remote_control/include/light_service.h +++ b/firmware/components/remote_control/include/light_service.h @@ -3,12 +3,16 @@ #include "host/ble_hs.h" #include -/// LED Service Characteristic Callbacks -int led_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); -int led_capabilities_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +// 0xA000 - Light Service +int led_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); -/// LED Service Characteristic User Description -int led_char_a000_user_desc(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); -int led_char_dead_user_desc(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); -int led_char_dead_presentation(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); -int led_char_dead_valid_range(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +// 0xBEA0 - Beacon Control +int beacon_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); + +/// Outdoor Light Descriptors +int led_char_user_desc_cb(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); + +/// Beacon Characteristic Descriptors +int beacon_char_user_desc_cb(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +int bool_char_presentation_cb(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +int bool_char_valid_range_cb(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); diff --git a/firmware/components/remote_control/light_service.c b/firmware/components/remote_control/light_service.c index 8efa46e..f559198 100644 --- a/firmware/components/remote_control/light_service.c +++ b/firmware/components/remote_control/light_service.c @@ -1,111 +1,107 @@ #include "include/light_service.h" +#include "beacon.h" static const char *TAG = "light_service"; -/// Capabilities of Device -int led_capabilities_read(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +static uint8_t g_led_enabled = 1; // 0=false, 1=true + +/// Characteristic Callbacks +int led_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { - char *data = "To be implemented later"; - os_mbuf_append(ctxt->om, data, strlen(data)); - return 0; + if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) + { + char *data = "To be implemented later"; + os_mbuf_append(ctxt->om, data, strlen(data)); + return 0; + } + return BLE_ATT_ERR_UNLIKELY; } -// Write data to ESP32 defined as server -int led_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int beacon_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { - const char *received_payload = (const char *)ctxt->om->om_data; - uint16_t payload_len = ctxt->om->om_len; - - // Define command strings - const char CMD_LIGHT_ON[] = "LIGHT ON"; - const char CMD_LIGHT_OFF[] = "LIGHT OFF"; - const char CMD_FAN_ON[] = "FAN ON"; - const char CMD_FAN_OFF[] = "FAN OFF"; - - if (payload_len == (sizeof(CMD_LIGHT_ON) - 1) && strncmp(received_payload, CMD_LIGHT_ON, payload_len) == 0) + if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { - ESP_LOGI(TAG, "LIGHT ON"); - // for (int i = 0; i < led_matrix_get_size(); i++) + return os_mbuf_append(ctxt->om, &g_led_enabled, sizeof(g_led_enabled)) == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) + { + // it has to be 1 Byte (0 or 1) + if (OS_MBUF_PKTLEN(ctxt->om) != 1) { - // led_matrix_set_pixel(i, 10, 10, 0); + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - } - else if (payload_len == (sizeof(CMD_LIGHT_OFF) - 1) && strncmp(received_payload, CMD_LIGHT_OFF, payload_len) == 0) - { - ESP_LOGI(TAG, "LIGHT OFF"); - // for (int i = 0; i < led_matrix_get_size(); i++) + uint8_t val; + os_mbuf_copydata(ctxt->om, 0, 1, &val); + if (val > 1) { - // led_matrix_set_pixel(i, 0, 0, 0); + return BLE_ATT_ERR_UNLIKELY; // or BLE_ATT_ERR_INVALID_ATTR_VALUE } - } - else if (payload_len == (sizeof(CMD_FAN_ON) - 1) && strncmp(received_payload, CMD_FAN_ON, payload_len) == 0) - { - ESP_LOGI(TAG, "FAN ON"); - // TODO: Implement action for FAN ON - } - else if (payload_len == (sizeof(CMD_FAN_OFF) - 1) && strncmp(received_payload, CMD_FAN_OFF, payload_len) == 0) - { - ESP_LOGI(TAG, "FAN OFF"); - // TODO: Implement action for FAN OFF - } - else - { - char temp_buffer[payload_len + 1]; - memcpy(temp_buffer, received_payload, payload_len); - temp_buffer[payload_len] = '\0'; - ESP_LOGI(TAG, "Unknown command from client: %s", temp_buffer); - } + if (val == g_led_enabled) // value is already set + { + return 0; + } - return 0; + g_led_enabled = val; + + if (g_led_enabled) + { + beacon_start(); + } + else + { + beacon_stop(); + } + return 0; + } + return BLE_ATT_ERR_UNLIKELY; } -int led_char_a000_user_desc(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +// Characteristic User Descriptions +int led_char_user_desc_cb(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 led_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)); - return 0; -} - -int led_char_dead_presentation(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - if (ctxt->op != BLE_GATT_ACCESS_OP_READ_DSC) + if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) { - return BLE_ATT_ERR_READ_NOT_PERMITTED; + const char *desc = "Aussenbeleuchtung"; + return os_mbuf_append(ctxt->om, desc, strlen(desc)) == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } - - // GATT Presentation Format (0x2904), 7 Bytes: - // [format, exponent, unit(2), namespace, description(2)] - // format 0x04 = uint8, exponent 0, unit 0x2700 (unitless), namespace 1 (Bluetooth SIG Assigned Numbers), - // description 0 - const uint8_t fmt[7] = { - 0x04, // format = uint8 - 0x00, // exponent - 0x00, 0x27, // unit = org.bluetooth.unit.unitless (0x2700) - 0x01, // namespace = 1 (SIG) - 0x00, 0x00 // description - }; - return os_mbuf_append(ctxt->om, fmt, sizeof(fmt)) == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + return BLE_ATT_ERR_READ_NOT_PERMITTED; } -int led_char_dead_valid_range(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int beacon_char_user_desc_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { - if (ctxt->op != BLE_GATT_ACCESS_OP_READ_DSC) + if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) { - return BLE_ATT_ERR_READ_NOT_PERMITTED; + const char *desc = "Leuchtfeuer"; + return os_mbuf_append(ctxt->om, desc, strlen(desc)) == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } - - // Valid Range Descriptor (0x2906) Payload: - // - Für numerische Werte: [min .. max] im "nativen" Datentyp der Characteristic. - // Hier: uint8, also 1 Byte min + 1 Byte max. - const uint8_t range[2] = {0x00, 0x01}; // min=0, max=1 - - return os_mbuf_append(ctxt->om, range, sizeof(range)) == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + return BLE_ATT_ERR_READ_NOT_PERMITTED; +} + +int bool_char_presentation_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) + { + // 7-Byte Format: [format, exponent, unit(2), namespace, description(2)] + uint8_t fmt[7] = { + 0x01, // format = boolean + 0x00, // exponent + 0x00, 0x00, // unit = none + 0x01, // namespace = Bluetooth SIG + 0x00, 0x00 // description + }; + return os_mbuf_append(ctxt->om, fmt, sizeof(fmt)) == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + return BLE_ATT_ERR_READ_NOT_PERMITTED; +} + +int bool_char_valid_range_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) + { + // for bool optional. but here as 1-Byte-Min/Max (0..1) + uint8_t range[2] = {0x00, 0x01}; // min=0, max=1 + return os_mbuf_append(ctxt->om, range, sizeof(range)) == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + return BLE_ATT_ERR_READ_NOT_PERMITTED; } diff --git a/firmware/components/remote_control/remote_control.c b/firmware/components/remote_control/remote_control.c index 12306da..d032d62 100644 --- a/firmware/components/remote_control/remote_control.c +++ b/firmware/components/remote_control/remote_control.c @@ -19,11 +19,9 @@ static const char *TAG = "remote_control"; -// 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 device_service_uuid = BLE_UUID16_INIT(0x180A); static const ble_uuid16_t light_service_uuid = BLE_UUID16_INIT(0xA000); +static const ble_uuid16_t settings_service_uuid = BLE_UUID16_INIT(0xA999); uint8_t ble_addr_type; @@ -32,32 +30,42 @@ static uint16_t g_capa_char_val_handle; 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 = led_char_a000_user_desc, - }, - {0}}; +// Descriptors for the characteristics +static struct ble_gatt_dsc_def led_char_desc[] = {{ + .uuid = BLE_UUID16_DECLARE(0x2901), + .att_flags = BLE_ATT_F_READ, + .access_cb = led_char_user_desc_cb, + }, + { + .uuid = BLE_UUID16_DECLARE(0x2904), + .att_flags = BLE_ATT_F_READ, + .access_cb = bool_char_presentation_cb, + }, + { + .uuid = BLE_UUID16_DECLARE(0x2906), + .att_flags = BLE_ATT_F_READ, + .access_cb = bool_char_valid_range_cb, + }, + {0}}; -static struct ble_gatt_dsc_def char_0xDEAD_descs[] = { - { - .uuid = BLE_UUID16_DECLARE(0x2901), - .att_flags = BLE_ATT_F_WRITE, - .access_cb = led_char_dead_user_desc, - }, - { - .uuid = BLE_UUID16_DECLARE(0x2904), // Presentation Format (optional, empfehlenswert) - .att_flags = BLE_ATT_F_READ, - .access_cb = led_char_dead_presentation, - }, - { - .uuid = BLE_UUID16_DECLARE(0x2906), // Valid Range - .att_flags = BLE_ATT_F_READ, - .access_cb = led_char_dead_valid_range, - }, - {0}}; +static struct ble_gatt_dsc_def beacon_char_desc[] = {{ + .uuid = BLE_UUID16_DECLARE(0x2901), + .att_flags = BLE_ATT_F_READ, + .access_cb = beacon_char_user_desc_cb, + }, + { + .uuid = BLE_UUID16_DECLARE(0x2904), + .att_flags = BLE_ATT_F_READ, + .access_cb = bool_char_presentation_cb, + }, + { + .uuid = BLE_UUID16_DECLARE(0x2906), + .att_flags = BLE_ATT_F_READ, + .access_cb = bool_char_valid_range_cb, + }, + {0}}; -// Array of pointers to other service definitions +// Array of pointers to service definitions static const struct ble_gatt_svc_def gatt_svcs[] = { { .type = BLE_GATT_SVC_TYPE_PRIMARY, @@ -65,22 +73,22 @@ static const struct ble_gatt_svc_def gatt_svcs[] = { .characteristics = (struct ble_gatt_chr_def[]){{ .uuid = BLE_UUID16_DECLARE(0x2A29), .flags = BLE_GATT_CHR_F_READ, - .access_cb = device_manufacturer_read, + .access_cb = device_manufacturer_cb, }, { .uuid = BLE_UUID16_DECLARE(0x2A27), .flags = BLE_GATT_CHR_F_READ, - .access_cb = device_hardware_revision_read, + .access_cb = device_hardware_revision_cb, }, { .uuid = BLE_UUID16_DECLARE(0x2A26), .flags = BLE_GATT_CHR_F_READ, - .access_cb = device_firmware_revision_read, + .access_cb = device_firmware_revision_cb, }, { .uuid = BLE_UUID16_DECLARE(0x2A00), .flags = BLE_GATT_CHR_F_READ, - .access_cb = device_name_read, + .access_cb = device_name_cb, }, {0}}, }, @@ -88,19 +96,24 @@ static const struct ble_gatt_svc_def gatt_svcs[] = { .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &light_service_uuid.u, .characteristics = (struct ble_gatt_chr_def[]){{ - .uuid = BLE_UUID16_DECLARE(0xA000), + .uuid = BLE_UUID16_DECLARE(0xBEA0), .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, - .access_cb = led_capabilities_read, - .descriptors = char_0xA000_descs, + .access_cb = beacon_cb, + .descriptors = beacon_char_desc, }, { - .uuid = BLE_UUID16_DECLARE(0xDEAD), + .uuid = BLE_UUID16_DECLARE(0xF037), .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, - .access_cb = led_write, - .descriptors = char_0xDEAD_descs, + .access_cb = led_cb, + .descriptors = led_char_desc, }, {0}}, }, + { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &settings_service_uuid.u, + .characteristics = (struct ble_gatt_chr_def[]){{0}}, + }, {0}}; // BLE event handling @@ -170,7 +183,7 @@ static void ble_app_advertise(void) struct ble_hs_adv_fields fields; memset(&fields, 0, sizeof(fields)); uint8_t mfg_data[] = {0xDE, 0xC0, 0x05, 0x10, 0x20, 0x25}; - static const ble_uuid16_t services[] = {device_service_uuid, light_service_uuid}; + static const ble_uuid16_t services[] = {device_service_uuid, light_service_uuid, settings_service_uuid}; fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; fields.uuids16 = services;