diff --git a/firmware/components/light/CMakeLists.txt b/firmware/components/light/CMakeLists.txt index a25ae4c..26a9dd4 100644 --- a/firmware/components/light/CMakeLists.txt +++ b/firmware/components/light/CMakeLists.txt @@ -7,4 +7,5 @@ idf_component_register(SRCS esp_driver_gpio esp_driver_gptimer esp_driver_ledc + persistence ) diff --git a/firmware/components/light/beacon.c b/firmware/components/light/beacon.c index c1f966a..e01d02d 100644 --- a/firmware/components/light/beacon.c +++ b/firmware/components/light/beacon.c @@ -6,6 +6,7 @@ #include "freertos/task.h" #include "led_strip.h" #include "light.h" +#include "persistence.h" #include "sdkconfig.h" #include "semaphore.h" @@ -84,6 +85,8 @@ esp_err_t beacon_start(void) { ESP_LOGI(TAG, "GPTimer started."); } + + ESP_LOGD(TAG, "Beacon started."); return ret; } @@ -110,6 +113,7 @@ esp_err_t beacon_stop(void) { ESP_LOGE(TAG, "Failed to enable gptimer: %s", esp_err_to_name(ret)); } + return ret; } diff --git a/firmware/components/remote_control/CMakeLists.txt b/firmware/components/remote_control/CMakeLists.txt index 7e28cfb..eae86b9 100644 --- a/firmware/components/remote_control/CMakeLists.txt +++ b/firmware/components/remote_control/CMakeLists.txt @@ -1,4 +1,5 @@ idf_component_register(SRCS + "char_desc.c" "device_service.c" "light_service.c" "remote_control.c" @@ -8,4 +9,5 @@ idf_component_register(SRCS bt esp_app_format light + persistence ) diff --git a/firmware/components/remote_control/char_desc.c b/firmware/components/remote_control/char_desc.c new file mode 100644 index 0000000..09151b3 --- /dev/null +++ b/firmware/components/remote_control/char_desc.c @@ -0,0 +1,31 @@ +#include "char_desc.h" + +int gatt_svr_desc_presentation_bool_access(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 gatt_svr_desc_valid_range_bool_access(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/device_service.c b/firmware/components/remote_control/device_service.c index 45630ab..fb7f0dc 100644 --- a/firmware/components/remote_control/device_service.c +++ b/firmware/components/remote_control/device_service.c @@ -3,7 +3,8 @@ #include #include -int device_name_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int gatt_svr_chr_device_name_access(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 +22,8 @@ int device_name_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_a return 0; } -int device_firmware_revision_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg) +int gatt_svr_chr_device_firmware_access(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 +41,16 @@ int device_firmware_revision_cb(uint16_t conn_handle, uint16_t attr_handle, stru return 0; } -int device_hardware_revision_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, - void *arg) +int gatt_svr_chr_device_hardware_access(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_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int gatt_svr_chr_device_manufacturer_access(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/char_desc.h b/firmware/components/remote_control/include/char_desc.h new file mode 100644 index 0000000..a972189 --- /dev/null +++ b/firmware/components/remote_control/include/char_desc.h @@ -0,0 +1,9 @@ +#pragma once + +#include "host/ble_gatt.h" +#include + +int gatt_svr_desc_presentation_bool_access(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg); +int gatt_svr_desc_valid_range_bool_access(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg); diff --git a/firmware/components/remote_control/include/device_service.h b/firmware/components/remote_control/include/device_service.h index 178b41a..1f65a48 100644 --- a/firmware/components/remote_control/include/device_service.h +++ b/firmware/components/remote_control/include/device_service.h @@ -4,15 +4,17 @@ #include // 0x2A00 - Device Name -int device_name_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +int gatt_svr_chr_device_name_access(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); +int gatt_svr_chr_device_firmware_access(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); +int gatt_svr_chr_device_hardware_access(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); +int gatt_svr_chr_device_manufacturer_access(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 c245be1..fd7baa3 100644 --- a/firmware/components/remote_control/include/light_service.h +++ b/firmware/components/remote_control/include/light_service.h @@ -4,15 +4,17 @@ #include // 0xA000 - Light Service -int led_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +int gatt_svr_chr_light_led_access(uint16_t conn_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); +int gatt_svr_chr_light_beacon_access(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); +int gatt_svr_desc_led_user_desc_access(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); +int gatt_svr_desc_beacon_user_desc_access(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg); diff --git a/firmware/components/remote_control/include/uart_service.h b/firmware/components/remote_control/include/uart_service.h index c8ba92f..6f30150 100644 --- a/firmware/components/remote_control/include/uart_service.h +++ b/firmware/components/remote_control/include/uart_service.h @@ -19,3 +19,4 @@ extern uint16_t tx_chr_val_handle; int gatt_svr_chr_uart_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); void send_ble_data(const char *data); +void uart_tx_task(void *param); diff --git a/firmware/components/remote_control/light_service.c b/firmware/components/remote_control/light_service.c index f559198..9156760 100644 --- a/firmware/components/remote_control/light_service.c +++ b/firmware/components/remote_control/light_service.c @@ -1,12 +1,12 @@ #include "include/light_service.h" #include "beacon.h" +#include "persistence.h" -static const char *TAG = "light_service"; - -static uint8_t g_led_enabled = 1; // 0=false, 1=true +static uint8_t g_beacon_enabled = 0; /// Characteristic Callbacks -int led_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int gatt_svr_chr_light_led_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg) { if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { @@ -17,11 +17,15 @@ int led_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ct return BLE_ATT_ERR_UNLIKELY; } -int beacon_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int gatt_svr_chr_light_beacon_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, + void *arg) { + persistence_load(VALUE_TYPE_INT32, "BEACON_ENABLED", &g_beacon_enabled); if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { - return os_mbuf_append(ctxt->om, &g_led_enabled, sizeof(g_led_enabled)) == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + return os_mbuf_append(ctxt->om, &g_beacon_enabled, sizeof(g_beacon_enabled)) == 0 + ? 0 + : BLE_ATT_ERR_INSUFFICIENT_RES; } if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { @@ -37,14 +41,14 @@ int beacon_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access return BLE_ATT_ERR_UNLIKELY; // or BLE_ATT_ERR_INVALID_ATTR_VALUE } - if (val == g_led_enabled) // value is already set + if (val == g_beacon_enabled) // value is already set { return 0; } - g_led_enabled = val; + g_beacon_enabled = val; - if (g_led_enabled) + if (g_beacon_enabled) { beacon_start(); } @@ -52,13 +56,15 @@ int beacon_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access { beacon_stop(); } + persistence_save(VALUE_TYPE_INT32, "BEACON_ENABLED", &g_beacon_enabled); return 0; } return BLE_ATT_ERR_UNLIKELY; } // 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) +int gatt_svr_desc_led_user_desc_access(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) { @@ -68,7 +74,8 @@ int led_char_user_desc_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble return BLE_ATT_ERR_READ_NOT_PERMITTED; } -int beacon_char_user_desc_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +int gatt_svr_desc_beacon_user_desc_access(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) { @@ -77,31 +84,3 @@ int beacon_char_user_desc_cb(uint16_t conn_handle, uint16_t attr_handle, struct } 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 e13d059..a277952 100644 --- a/firmware/components/remote_control/remote_control.c +++ b/firmware/components/remote_control/remote_control.c @@ -11,6 +11,7 @@ #include "host/ble_hs.h" #include "host/ble_sm.h" #include "host/ble_uuid.h" +#include "include/char_desc.h" #include "include/device_service.h" #include "include/light_service.h" #include "include/uart_service.h" @@ -30,41 +31,48 @@ uint8_t ble_addr_type; static void ble_app_advertise(void); -// Descriptors for the characteristics -static struct ble_gatt_dsc_def led_char_desc[] = { +// Descriptors for the Beacon Characteristic +static struct ble_gatt_dsc_def beacon_char_desc[] = { { + // User Description Descriptor .uuid = BLE_UUID16_DECLARE(0x2901), .att_flags = BLE_ATT_F_READ, - .access_cb = led_char_user_desc_cb, + .access_cb = gatt_svr_desc_beacon_user_desc_access, }, { + // Presentation Format Descriptor .uuid = BLE_UUID16_DECLARE(0x2904), .att_flags = BLE_ATT_F_READ, - .access_cb = bool_char_presentation_cb, + .access_cb = gatt_svr_desc_presentation_bool_access, }, { + // Valid Range Descriptor .uuid = BLE_UUID16_DECLARE(0x2906), .att_flags = BLE_ATT_F_READ, - .access_cb = bool_char_valid_range_cb, + .access_cb = gatt_svr_desc_valid_range_bool_access, }, {0}, }; -static struct ble_gatt_dsc_def beacon_char_desc[] = { +// Descriptors for the LED Characteristic +static struct ble_gatt_dsc_def led_char_desc[] = { { + // User Description Descriptor .uuid = BLE_UUID16_DECLARE(0x2901), .att_flags = BLE_ATT_F_READ, - .access_cb = beacon_char_user_desc_cb, + .access_cb = gatt_svr_desc_led_user_desc_access, }, { + // Presentation Format Descriptor .uuid = BLE_UUID16_DECLARE(0x2904), .att_flags = BLE_ATT_F_READ, - .access_cb = bool_char_presentation_cb, + .access_cb = gatt_svr_desc_presentation_bool_access, }, { + // Valid Range Descriptor .uuid = BLE_UUID16_DECLARE(0x2906), .att_flags = BLE_ATT_F_READ, - .access_cb = bool_char_valid_range_cb, + .access_cb = gatt_svr_desc_valid_range_bool_access, }, {0}, }; @@ -72,54 +80,63 @@ static struct ble_gatt_dsc_def beacon_char_desc[] = { // Array of pointers to service definitions static const struct ble_gatt_svc_def gatt_svcs[] = { { + // Device Information Service .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &gatt_svr_svc_device_uuid.u, .characteristics = (struct ble_gatt_chr_def[]){ { + // Manufacturer String .uuid = BLE_UUID16_DECLARE(0x2A29), .flags = BLE_GATT_CHR_F_READ, - .access_cb = device_manufacturer_cb, + .access_cb = gatt_svr_chr_device_manufacturer_access, }, { + // Hardware Revision String .uuid = BLE_UUID16_DECLARE(0x2A27), .flags = BLE_GATT_CHR_F_READ, - .access_cb = device_hardware_revision_cb, + .access_cb = gatt_svr_chr_device_hardware_access, }, { + // Firmware Revision String .uuid = BLE_UUID16_DECLARE(0x2A26), .flags = BLE_GATT_CHR_F_READ, - .access_cb = device_firmware_revision_cb, + .access_cb = gatt_svr_chr_device_firmware_access, }, { + // Device Name .uuid = BLE_UUID16_DECLARE(0x2A00), .flags = BLE_GATT_CHR_F_READ, - .access_cb = device_name_cb, + .access_cb = gatt_svr_chr_device_name_access, }, {0}, }, }, { + // Light Service .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &gatt_svr_svc_light_uuid.u, .characteristics = (struct ble_gatt_chr_def[]){ { + // Beacon Characteristic .uuid = BLE_UUID16_DECLARE(0xBEA0), .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, - .access_cb = beacon_cb, + .access_cb = gatt_svr_chr_light_beacon_access, .descriptors = beacon_char_desc, }, { + // LED Characteristic .uuid = BLE_UUID16_DECLARE(0xF037), .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, - .access_cb = led_cb, + .access_cb = gatt_svr_chr_light_led_access, .descriptors = led_char_desc, }, {0}, }, }, { + // UART Service .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &gatt_svr_svc_uart_uuid.u, .characteristics = @@ -140,6 +157,7 @@ static const struct ble_gatt_svc_def gatt_svcs[] = { {0}, }, }, + // Settings Service (empty for now) { .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &gatt_svr_svc_settings_uuid.u, @@ -256,22 +274,6 @@ static void ble_app_on_sync(void) ble_app_advertise(); } -static void uart_tx_task(void *param) -{ - char buffer[50]; - int count = 0; - while (1) - { - vTaskDelay(pdMS_TO_TICKS(2000)); - if (conn_handle != 0) - { - ESP_LOGI(TAG, "Sending data over BLE UART TX"); - sprintf(buffer, "Hello World #%d", count++); - send_ble_data(buffer); - } - } -} - // The infinite task static void host_task(void *param) { diff --git a/firmware/components/remote_control/uart_service.c b/firmware/components/remote_control/uart_service.c index 5d4c8d0..5f6e9f8 100644 --- a/firmware/components/remote_control/uart_service.c +++ b/firmware/components/remote_control/uart_service.c @@ -68,3 +68,19 @@ void send_ble_data(const char *data) } } } + +void uart_tx_task(void *param) +{ + char buffer[50]; + int count = 0; + while (1) + { + vTaskDelay(pdMS_TO_TICKS(2000)); + if (conn_handle != 0) + { + ESP_LOGI(TAG, "Sending data over BLE UART TX"); + sprintf(buffer, "Hello World #%d", count++); + send_ble_data(buffer); + } + } +} \ No newline at end of file