add BLE bonding
Some checks failed
ESP-IDF Build / build (esp32, latest) (push) Failing after 46s
ESP-IDF Build / build (esp32, release-v5.4) (push) Failing after 46s
ESP-IDF Build / build (esp32, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32c3, latest) (push) Failing after 45s
ESP-IDF Build / build (esp32c3, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32c3, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32c5, latest) (push) Failing after 45s
ESP-IDF Build / build (esp32c5, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32c5, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32c6, latest) (push) Failing after 45s
ESP-IDF Build / build (esp32c6, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32c6, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32h2, latest) (push) Failing after 46s
ESP-IDF Build / build (esp32h2, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32h2, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32p4, latest) (push) Failing after 45s
ESP-IDF Build / build (esp32p4, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32p4, release-v5.5) (push) Failing after 52s
ESP-IDF Build / build (esp32s3, latest) (push) Failing after 56s
ESP-IDF Build / build (esp32s3, release-v5.4) (push) Failing after 46s
ESP-IDF Build / build (esp32s3, release-v5.5) (push) Failing after 45s
Some checks failed
ESP-IDF Build / build (esp32, latest) (push) Failing after 46s
ESP-IDF Build / build (esp32, release-v5.4) (push) Failing after 46s
ESP-IDF Build / build (esp32, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32c3, latest) (push) Failing after 45s
ESP-IDF Build / build (esp32c3, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32c3, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32c5, latest) (push) Failing after 45s
ESP-IDF Build / build (esp32c5, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32c5, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32c6, latest) (push) Failing after 45s
ESP-IDF Build / build (esp32c6, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32c6, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32h2, latest) (push) Failing after 46s
ESP-IDF Build / build (esp32h2, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32h2, release-v5.5) (push) Failing after 45s
ESP-IDF Build / build (esp32p4, latest) (push) Failing after 45s
ESP-IDF Build / build (esp32p4, release-v5.4) (push) Failing after 45s
ESP-IDF Build / build (esp32p4, release-v5.5) (push) Failing after 52s
ESP-IDF Build / build (esp32s3, latest) (push) Failing after 56s
ESP-IDF Build / build (esp32s3, release-v5.4) (push) Failing after 46s
ESP-IDF Build / build (esp32s3, release-v5.5) (push) Failing after 45s
Signed-off-by: Peter Siegmund <mars3142@users.noreply.github.com>
This commit is contained in:
@@ -14,7 +14,11 @@ esp_err_t wled_init(void)
|
|||||||
led_strip_config_t strip_config = {.strip_gpio_num = CONFIG_WLED_DIN_PIN,
|
led_strip_config_t strip_config = {.strip_gpio_num = CONFIG_WLED_DIN_PIN,
|
||||||
.max_leds = led_matrix.size,
|
.max_leds = led_matrix.size,
|
||||||
.led_model = LED_MODEL_WS2812,
|
.led_model = LED_MODEL_WS2812,
|
||||||
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB,
|
#if CONFIG_WLED_WITH_WHITE
|
||||||
|
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRBW,
|
||||||
|
#else
|
||||||
|
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_RGB,
|
||||||
|
#endif
|
||||||
.flags = {
|
.flags = {
|
||||||
.invert_out = false,
|
.invert_out = false,
|
||||||
}};
|
}};
|
||||||
|
@@ -7,26 +7,21 @@
|
|||||||
|
|
||||||
static const char *TAG = "outdoor";
|
static const char *TAG = "outdoor";
|
||||||
|
|
||||||
// Timer resolution (10 bit = 1024 steps)
|
#define LEDC_RESOLUTION LEDC_TIMER_10_BIT // Timer resolution (10 bit = 1024 steps)
|
||||||
#define LEDC_RESOLUTION LEDC_TIMER_10_BIT
|
|
||||||
#define MAX_DUTY 1023
|
#define MAX_DUTY 1023
|
||||||
|
|
||||||
// Constant brightness for the "normal state" (approx. 90%)
|
#define NORMAL_DUTY (MAX_DUTY * 0.9) // 90% brightness
|
||||||
#define NORMAL_DUTY (MAX_DUTY * 0.9)
|
|
||||||
|
|
||||||
// Parameters for flickering
|
#define FLICKER_CHANCE 2 // 2% chance of flickering per cycle
|
||||||
#define FLICKER_CHANCE 5 // 5% chance of flickering per cycle
|
|
||||||
#define FLICKER_COUNT 8 // Number of brightness changes during a flicker
|
#define FLICKER_COUNT 8 // Number of brightness changes during a flicker
|
||||||
|
|
||||||
TaskHandle_t outdoor_task_handle = NULL;
|
TaskHandle_t outdoor_task_handle = NULL;
|
||||||
|
|
||||||
void outdoor_task(void *pvParameters)
|
void outdoor_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Simulation of a defective light bulb started.");
|
|
||||||
|
|
||||||
int led_pin = *(int *)pvParameters;
|
int led_pin = *(int *)pvParameters;
|
||||||
|
|
||||||
// 1. LEDC timer configuration
|
|
||||||
ledc_timer_config_t ledc_timer = {.speed_mode = LEDC_LOW_SPEED_MODE,
|
ledc_timer_config_t ledc_timer = {.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||||
.timer_num = LEDC_TIMER_0,
|
.timer_num = LEDC_TIMER_0,
|
||||||
.duty_resolution = LEDC_RESOLUTION,
|
.duty_resolution = LEDC_RESOLUTION,
|
||||||
@@ -34,7 +29,6 @@ void outdoor_task(void *pvParameters)
|
|||||||
.clk_cfg = LEDC_AUTO_CLK};
|
.clk_cfg = LEDC_AUTO_CLK};
|
||||||
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
|
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
|
||||||
|
|
||||||
// 2. LEDC channel configuration
|
|
||||||
ledc_channel_config_t ledc_channel = {.speed_mode = LEDC_LOW_SPEED_MODE,
|
ledc_channel_config_t ledc_channel = {.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||||
.channel = LEDC_CHANNEL_0,
|
.channel = LEDC_CHANNEL_0,
|
||||||
.timer_sel = LEDC_TIMER_0,
|
.timer_sel = LEDC_TIMER_0,
|
||||||
@@ -44,40 +38,38 @@ void outdoor_task(void *pvParameters)
|
|||||||
.hpoint = 0};
|
.hpoint = 0};
|
||||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
|
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
|
||||||
|
|
||||||
// 3. Main loop with flicker logic
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
// First, set the LED to its normal brightness
|
|
||||||
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, NORMAL_DUTY);
|
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, NORMAL_DUTY);
|
||||||
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
|
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
|
||||||
|
|
||||||
// Random trigger for flickering
|
uint32_t random_val = esp_random() % 100;
|
||||||
uint32_t random_val = esp_random() % 100; // Random number between 0 and 99
|
|
||||||
|
|
||||||
if (random_val < FLICKER_CHANCE)
|
if (random_val < FLICKER_CHANCE)
|
||||||
{
|
{
|
||||||
// Start flicker sequence
|
|
||||||
for (int i = 0; i < FLICKER_COUNT; i++)
|
for (int i = 0; i < FLICKER_COUNT; i++)
|
||||||
{
|
{
|
||||||
// Set a random, lower brightness (e.g., 30-70% of normal brightness)
|
|
||||||
uint32_t flicker_duty = (NORMAL_DUTY * 0.3) + (esp_random() % (uint32_t)(NORMAL_DUTY * 0.4));
|
uint32_t flicker_duty = (NORMAL_DUTY * 0.3) + (esp_random() % (uint32_t)(NORMAL_DUTY * 0.4));
|
||||||
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, flicker_duty);
|
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, flicker_duty);
|
||||||
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
|
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
|
||||||
|
|
||||||
// Short, random delay for irregular flickering
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(20 + (esp_random() % 50)));
|
vTaskDelay(pdMS_TO_TICKS(20 + (esp_random() % 50)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A fixed delay in normal operation
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t outdoor_start(void)
|
esp_err_t outdoor_start(void)
|
||||||
{
|
{
|
||||||
static const int led_pin = 13;
|
ESP_LOGI(TAG, "Simulation of a defective light bulb started.");
|
||||||
xTaskCreate(outdoor_task, "outdoor_task", 2048, (void *)&led_pin, 5, &outdoor_task_handle);
|
|
||||||
|
static const int led_left_pin = CONFIG_LED_PIN_LEFT;
|
||||||
|
xTaskCreate(outdoor_task, "outdoor_task_left", 2048, (void *)&led_left_pin, 5, &outdoor_task_handle);
|
||||||
|
|
||||||
|
static const int led_right_pin = CONFIG_LED_PIN_RIGHT;
|
||||||
|
xTaskCreate(outdoor_task, "outdoor_task_right", 2048, (void *)&led_right_pin, 5, &outdoor_task_handle);
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
VALUE_TYPE_STRING,
|
VALUE_TYPE_STRING,
|
||||||
|
VALUE_TYPE_INT8,
|
||||||
VALUE_TYPE_INT32,
|
VALUE_TYPE_INT32,
|
||||||
} persistence_value_type_t;
|
} persistence_value_type_t;
|
||||||
|
|
||||||
|
@@ -10,6 +10,149 @@ static const char *TAG = "persistence";
|
|||||||
static nvs_handle_t persistence_handle;
|
static nvs_handle_t persistence_handle;
|
||||||
static SemaphoreHandle_t persistence_mutex;
|
static SemaphoreHandle_t persistence_mutex;
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "nvs.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
static const char *nvs_type_to_str(nvs_type_t type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case NVS_TYPE_U8:
|
||||||
|
return "U8";
|
||||||
|
case NVS_TYPE_I8:
|
||||||
|
return "I8";
|
||||||
|
case NVS_TYPE_U16:
|
||||||
|
return "U16";
|
||||||
|
case NVS_TYPE_I16:
|
||||||
|
return "I16";
|
||||||
|
case NVS_TYPE_U32:
|
||||||
|
return "U32";
|
||||||
|
case NVS_TYPE_I32:
|
||||||
|
return "I32";
|
||||||
|
case NVS_TYPE_U64:
|
||||||
|
return "U64";
|
||||||
|
case NVS_TYPE_I64:
|
||||||
|
return "I64";
|
||||||
|
case NVS_TYPE_STR:
|
||||||
|
return "STR";
|
||||||
|
case NVS_TYPE_BLOB:
|
||||||
|
return "BLOB";
|
||||||
|
case NVS_TYPE_ANY:
|
||||||
|
return "ANY";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_nvs_value(const char *namespace_name, const char *key, nvs_type_t type)
|
||||||
|
{
|
||||||
|
nvs_handle_t handle;
|
||||||
|
esp_err_t err = nvs_open(namespace_name, NVS_READONLY, &handle);
|
||||||
|
if (err != ESP_OK)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case NVS_TYPE_I8: {
|
||||||
|
int8_t value;
|
||||||
|
if (nvs_get_i8(handle, key, &value) == ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, " -> Value (I8): %d", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NVS_TYPE_I32: {
|
||||||
|
int32_t value;
|
||||||
|
if (nvs_get_i32(handle, key, &value) == ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, " -> Value (I32): %d", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NVS_TYPE_STR: {
|
||||||
|
size_t length = 0;
|
||||||
|
nvs_get_str(handle, key, NULL, &length);
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
char *value = malloc(length);
|
||||||
|
if (nvs_get_str(handle, key, value, &length) == ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, " -> Value (STR): %s", value);
|
||||||
|
}
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NVS_TYPE_BLOB: {
|
||||||
|
size_t length = 0;
|
||||||
|
nvs_get_blob(handle, key, NULL, &length);
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, " -> Value (BLOB): %d bytes", length);
|
||||||
|
|
||||||
|
// Optional: Erste Bytes als Hex anzeigen
|
||||||
|
uint8_t *blob = malloc(length);
|
||||||
|
if (nvs_get_blob(handle, key, blob, &length) == ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOG_BUFFER_HEX_LEVEL(TAG, blob, MIN(length, 32), ESP_LOG_INFO);
|
||||||
|
}
|
||||||
|
free(blob);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_close(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void list_all_nvs_entries(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "========== NVS ENTRIES ==========");
|
||||||
|
|
||||||
|
nvs_iterator_t it = NULL;
|
||||||
|
esp_err_t err;
|
||||||
|
|
||||||
|
// Iterator für alle Namespaces und Keys erstellen
|
||||||
|
err = nvs_entry_find(NVS_DEFAULT_PART_NAME, NULL, NVS_TYPE_ANY, &it);
|
||||||
|
|
||||||
|
while (err == ESP_OK)
|
||||||
|
{
|
||||||
|
nvs_entry_info_t info;
|
||||||
|
nvs_entry_info(it, &info);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Namespace: %-16s | Key: %-16s | Type: %s", info.namespace_name, info.key,
|
||||||
|
nvs_type_to_str(info.type));
|
||||||
|
|
||||||
|
// Optional: Wert anzeigen
|
||||||
|
display_nvs_value(info.namespace_name, info.key, info.type);
|
||||||
|
|
||||||
|
err = nvs_entry_next(&it);
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_release_iterator(it);
|
||||||
|
ESP_LOGI(TAG, "==================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_nvs_stats(void)
|
||||||
|
{
|
||||||
|
nvs_stats_t nvs_stats;
|
||||||
|
esp_err_t err = nvs_get_stats(NULL, &nvs_stats);
|
||||||
|
if (err == ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "NVS: Used entries = %d, Free entries = %d, Total entries = %d", nvs_stats.used_entries,
|
||||||
|
nvs_stats.free_entries, nvs_stats.total_entries);
|
||||||
|
|
||||||
|
size_t used_kb = (nvs_stats.used_entries * 32) / 1024; // Grobe Schätzung
|
||||||
|
size_t free_kb = (nvs_stats.free_entries * 32) / 1024;
|
||||||
|
ESP_LOGI(TAG, "NVS: ~%d KB used, ~%d KB free", used_kb, free_kb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void persistence_init(const char *namespace_name)
|
void persistence_init(const char *namespace_name)
|
||||||
{
|
{
|
||||||
esp_err_t ret = nvs_flash_init();
|
esp_err_t ret = nvs_flash_init();
|
||||||
@@ -20,6 +163,9 @@ void persistence_init(const char *namespace_name)
|
|||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(ret);
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
list_all_nvs_entries();
|
||||||
|
check_nvs_stats();
|
||||||
|
|
||||||
ESP_ERROR_CHECK(nvs_open(namespace_name, NVS_READWRITE, &persistence_handle));
|
ESP_ERROR_CHECK(nvs_open(namespace_name, NVS_READWRITE, &persistence_handle));
|
||||||
|
|
||||||
persistence_mutex = xSemaphoreCreateMutex();
|
persistence_mutex = xSemaphoreCreateMutex();
|
||||||
@@ -43,6 +189,10 @@ void persistence_save(persistence_value_type_t value_type, const char *key, cons
|
|||||||
err = nvs_set_str(persistence_handle, key, (char *)value);
|
err = nvs_set_str(persistence_handle, key, (char *)value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VALUE_TYPE_INT8:
|
||||||
|
err = nvs_set_i8(persistence_handle, key, *(int8_t *)value);
|
||||||
|
break;
|
||||||
|
|
||||||
case VALUE_TYPE_INT32:
|
case VALUE_TYPE_INT32:
|
||||||
err = nvs_set_i32(persistence_handle, key, *(int32_t *)value);
|
err = nvs_set_i32(persistence_handle, key, *(int32_t *)value);
|
||||||
break;
|
break;
|
||||||
@@ -80,6 +230,10 @@ void *persistence_load(persistence_value_type_t value_type, const char *key, voi
|
|||||||
err = nvs_get_str(persistence_handle, key, (char *)out, NULL);
|
err = nvs_get_str(persistence_handle, key, (char *)out, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VALUE_TYPE_INT8:
|
||||||
|
err = nvs_get_i8(persistence_handle, key, (int8_t *)out);
|
||||||
|
break;
|
||||||
|
|
||||||
case VALUE_TYPE_INT32:
|
case VALUE_TYPE_INT32:
|
||||||
err = nvs_get_i32(persistence_handle, key, (int32_t *)out);
|
err = nvs_get_i32(persistence_handle, key, (int32_t *)out);
|
||||||
break;
|
break;
|
||||||
|
@@ -1,3 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "host/ble_hs.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t conn_handle;
|
||||||
|
bool is_connected;
|
||||||
|
} ble_connection_t;
|
||||||
|
|
||||||
|
extern ble_connection_t g_connections[CONFIG_BT_NIMBLE_MAX_CONNECTIONS];
|
||||||
|
|
||||||
void remote_control_init(void);
|
void remote_control_init(void);
|
||||||
|
bool is_any_device_connected(void);
|
||||||
|
@@ -14,8 +14,7 @@ extern const ble_uuid128_t gatt_svr_chr_uart_rx_uuid;
|
|||||||
// TX Characteristic UUID: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E
|
// TX Characteristic UUID: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E
|
||||||
extern const ble_uuid128_t gatt_svr_chr_uart_tx_uuid;
|
extern const ble_uuid128_t gatt_svr_chr_uart_tx_uuid;
|
||||||
|
|
||||||
extern uint16_t conn_handle;
|
extern uint16_t tx_chr_val_handle; // This is still needed as it's set once by the stack
|
||||||
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);
|
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 send_ble_data(const char *data);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "persistence.h"
|
#include "persistence.h"
|
||||||
|
|
||||||
static uint8_t g_beacon_enabled = 0;
|
static uint8_t g_beacon_enabled = 0;
|
||||||
|
static int8_t g_led_value = 0;
|
||||||
|
|
||||||
/// Characteristic Callbacks
|
/// Characteristic Callbacks
|
||||||
int gatt_svr_chr_light_led_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt,
|
int gatt_svr_chr_light_led_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt,
|
||||||
@@ -14,13 +15,18 @@ int gatt_svr_chr_light_led_access(uint16_t conn_handle, uint16_t attr_handle, st
|
|||||||
os_mbuf_append(ctxt->om, data, strlen(data));
|
os_mbuf_append(ctxt->om, data, strlen(data));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR)
|
||||||
|
{
|
||||||
|
int8_t led_value = 0;
|
||||||
|
persistence_load(VALUE_TYPE_INT8, "LED_VALUE", &led_value);
|
||||||
|
}
|
||||||
return BLE_ATT_ERR_UNLIKELY;
|
return BLE_ATT_ERR_UNLIKELY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gatt_svr_chr_light_beacon_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt,
|
int gatt_svr_chr_light_beacon_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
persistence_load(VALUE_TYPE_INT32, "BEACON_ENABLED", &g_beacon_enabled);
|
|
||||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR)
|
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR)
|
||||||
{
|
{
|
||||||
return os_mbuf_append(ctxt->om, &g_beacon_enabled, sizeof(g_beacon_enabled)) == 0
|
return os_mbuf_append(ctxt->om, &g_beacon_enabled, sizeof(g_beacon_enabled)) == 0
|
||||||
@@ -29,6 +35,9 @@ int gatt_svr_chr_light_beacon_access(uint16_t conn_handle, uint16_t attr_handle,
|
|||||||
}
|
}
|
||||||
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR)
|
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR)
|
||||||
{
|
{
|
||||||
|
int8_t beacon_enabled = 0;
|
||||||
|
persistence_load(VALUE_TYPE_INT8, "BEACON_ENABLED", &beacon_enabled);
|
||||||
|
|
||||||
// it has to be 1 Byte (0 or 1)
|
// it has to be 1 Byte (0 or 1)
|
||||||
if (OS_MBUF_PKTLEN(ctxt->om) != 1)
|
if (OS_MBUF_PKTLEN(ctxt->om) != 1)
|
||||||
{
|
{
|
||||||
@@ -56,7 +65,7 @@ int gatt_svr_chr_light_beacon_access(uint16_t conn_handle, uint16_t attr_handle,
|
|||||||
{
|
{
|
||||||
beacon_stop();
|
beacon_stop();
|
||||||
}
|
}
|
||||||
persistence_save(VALUE_TYPE_INT32, "BEACON_ENABLED", &g_beacon_enabled);
|
persistence_save(VALUE_TYPE_INT8, "BEACON_ENABLED", &g_beacon_enabled);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return BLE_ATT_ERR_UNLIKELY;
|
return BLE_ATT_ERR_UNLIKELY;
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "esp_mac.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
@@ -21,6 +22,8 @@
|
|||||||
#include "services/gap/ble_svc_gap.h"
|
#include "services/gap/ble_svc_gap.h"
|
||||||
#include "services/gatt/ble_svc_gatt.h"
|
#include "services/gatt/ble_svc_gatt.h"
|
||||||
|
|
||||||
|
void ble_store_config_init(void);
|
||||||
|
|
||||||
static const char *TAG = "remote_control";
|
static const char *TAG = "remote_control";
|
||||||
|
|
||||||
static const ble_uuid16_t gatt_svr_svc_device_uuid = BLE_UUID16_INIT(0x180A);
|
static const ble_uuid16_t gatt_svr_svc_device_uuid = BLE_UUID16_INIT(0x180A);
|
||||||
@@ -29,6 +32,29 @@ static const ble_uuid16_t gatt_svr_svc_settings_uuid = BLE_UUID16_INIT(0xA999);
|
|||||||
|
|
||||||
uint8_t ble_addr_type;
|
uint8_t ble_addr_type;
|
||||||
|
|
||||||
|
ble_connection_t g_connections[CONFIG_BT_NIMBLE_MAX_CONNECTIONS];
|
||||||
|
|
||||||
|
static void init_connection_pool()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++)
|
||||||
|
{
|
||||||
|
g_connections[i].conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
g_connections[i].is_connected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_any_device_connected(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++)
|
||||||
|
{
|
||||||
|
if (g_connections[i].is_connected)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void ble_app_advertise(void);
|
static void ble_app_advertise(void);
|
||||||
|
|
||||||
// Descriptors for the Beacon Characteristic
|
// Descriptors for the Beacon Characteristic
|
||||||
@@ -121,14 +147,16 @@ static const struct ble_gatt_svc_def gatt_svcs[] = {
|
|||||||
{
|
{
|
||||||
// Beacon Characteristic
|
// Beacon Characteristic
|
||||||
.uuid = BLE_UUID16_DECLARE(0xBEA0),
|
.uuid = BLE_UUID16_DECLARE(0xBEA0),
|
||||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
|
.flags =
|
||||||
|
BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||||
.access_cb = gatt_svr_chr_light_beacon_access,
|
.access_cb = gatt_svr_chr_light_beacon_access,
|
||||||
.descriptors = beacon_char_desc,
|
.descriptors = beacon_char_desc,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// LED Characteristic
|
// LED Characteristic
|
||||||
.uuid = BLE_UUID16_DECLARE(0xF037),
|
.uuid = BLE_UUID16_DECLARE(0xF037),
|
||||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
|
.flags =
|
||||||
|
BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||||
.access_cb = gatt_svr_chr_light_led_access,
|
.access_cb = gatt_svr_chr_light_led_access,
|
||||||
.descriptors = led_char_desc,
|
.descriptors = led_char_desc,
|
||||||
},
|
},
|
||||||
@@ -165,22 +193,173 @@ static const struct ble_gatt_svc_def gatt_svcs[] = {
|
|||||||
},
|
},
|
||||||
{0}};
|
{0}};
|
||||||
|
|
||||||
|
inline static void format_addr(char *addr_str, uint8_t addr[])
|
||||||
|
{
|
||||||
|
sprintf(addr_str, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_conn_desc(struct ble_gap_conn_desc *desc)
|
||||||
|
{
|
||||||
|
/* Local variables */
|
||||||
|
char addr_str[18] = {0};
|
||||||
|
|
||||||
|
/* Connection handle */
|
||||||
|
ESP_LOGI(TAG, "connection handle: %d", desc->conn_handle);
|
||||||
|
|
||||||
|
/* Local ID address */
|
||||||
|
format_addr(addr_str, desc->our_id_addr.val);
|
||||||
|
ESP_LOGI(TAG, "device id address: type=%d, value=%s", desc->our_id_addr.type, addr_str);
|
||||||
|
|
||||||
|
/* Peer ID address */
|
||||||
|
format_addr(addr_str, desc->peer_id_addr.val);
|
||||||
|
ESP_LOGI(TAG, "peer id address: type=%d, value=%s", desc->peer_id_addr.type, addr_str);
|
||||||
|
|
||||||
|
/* Connection info */
|
||||||
|
ESP_LOGI(TAG,
|
||||||
|
"conn_itvl=%d, conn_latency=%d, supervision_timeout=%d, "
|
||||||
|
"encrypted=%d, authenticated=%d, bonded=%d\n",
|
||||||
|
desc->conn_itvl, desc->conn_latency, desc->supervision_timeout, desc->sec_state.encrypted,
|
||||||
|
desc->sec_state.authenticated, desc->sec_state.bonded);
|
||||||
|
}
|
||||||
|
|
||||||
// BLE event handling
|
// BLE event handling
|
||||||
static int ble_gap_event(struct ble_gap_event *event, void *arg)
|
static int ble_gap_event(struct ble_gap_event *event, void *arg)
|
||||||
{
|
{
|
||||||
|
esp_err_t rc;
|
||||||
|
struct ble_gap_conn_desc desc;
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case BLE_GAP_EVENT_CONNECT:
|
case BLE_GAP_EVENT_CONNECT:
|
||||||
ESP_LOGI(TAG, "Connection established; status=%d", event->connect.status);
|
/* A new connection was established or a connection attempt failed. */
|
||||||
conn_handle = event->connect.conn_handle;
|
ESP_LOGI(TAG, "connection %s; status=%d", event->connect.status == 0 ? "established" : "failed",
|
||||||
ESP_LOGI(TAG, "Connection handle: %d", conn_handle);
|
event->connect.status);
|
||||||
|
|
||||||
|
/* Connection succeeded */
|
||||||
|
if (event->connect.status == 0)
|
||||||
|
{
|
||||||
|
bool found_slot = false;
|
||||||
|
for (int i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++)
|
||||||
|
{
|
||||||
|
if (!g_connections[i].is_connected)
|
||||||
|
{
|
||||||
|
g_connections[i].conn_handle = event->connect.conn_handle;
|
||||||
|
g_connections[i].is_connected = true;
|
||||||
|
found_slot = true;
|
||||||
|
ESP_LOGI(TAG, "Connection stored in slot %d", i);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found_slot)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "No free connection slot available!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check connection handle */
|
||||||
|
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
print_conn_desc(&desc);
|
||||||
|
|
||||||
|
/* Try to update connection parameters */
|
||||||
|
struct ble_gap_upd_params params = {.itvl_min = desc.conn_itvl,
|
||||||
|
.itvl_max = desc.conn_itvl,
|
||||||
|
.latency = 3,
|
||||||
|
.supervision_timeout = desc.supervision_timeout};
|
||||||
|
rc = ble_gap_update_params(event->connect.conn_handle, ¶ms);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "failed to update connection parameters, error code: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Connection failed, restart advertising */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ble_app_advertise();
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
|
||||||
case BLE_GAP_EVENT_DISCONNECT:
|
case BLE_GAP_EVENT_DISCONNECT:
|
||||||
ESP_LOGI(TAG, "Disconnected; reason=%d", event->disconnect.reason);
|
ESP_LOGI(TAG, "Disconnected; reason=%d", event->disconnect.reason);
|
||||||
conn_handle = 0;
|
for (int i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++)
|
||||||
ble_app_advertise();
|
{
|
||||||
|
if (g_connections[i].conn_handle == event->disconnect.conn.conn_handle)
|
||||||
|
{
|
||||||
|
g_connections[i].is_connected = false;
|
||||||
|
g_connections[i].conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
ESP_LOGI(TAG, "Connection from slot %d removed", i);
|
||||||
|
ble_app_advertise(); // Restart advertising to allow new connections
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_PASSKEY_ACTION:
|
||||||
|
ESP_LOGI(TAG, "Passkey action required: %d", event->passkey.params.action);
|
||||||
|
struct ble_sm_io pkey = {0};
|
||||||
|
|
||||||
|
switch (event->passkey.params.action)
|
||||||
|
{
|
||||||
|
case BLE_SM_IOACT_DISP:
|
||||||
|
pkey.action = BLE_SM_IOACT_DISP;
|
||||||
|
pkey.passkey = CONFIG_BONDING_PASSPHRASE;
|
||||||
|
ESP_LOGI(TAG, "Displaying passkey: %06d", pkey.passkey);
|
||||||
|
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "failed to inject security manager io, error code: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unknown passkey action: %d", event->passkey.params.action);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_ENC_CHANGE:
|
||||||
|
ESP_LOGI(TAG, "Encryption change event; status=%d", event->enc_change.status);
|
||||||
|
|
||||||
|
if (event->enc_change.status != 0)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Encryption failed with status %d", event->enc_change.status);
|
||||||
|
|
||||||
|
rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
|
||||||
|
if (rc == 0)
|
||||||
|
{
|
||||||
|
char addr_str[18] = {0};
|
||||||
|
format_addr(addr_str, desc.peer_id_addr.val);
|
||||||
|
ESP_LOGI(TAG, "Deleting bond for peer: %s", addr_str);
|
||||||
|
|
||||||
|
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||||
|
|
||||||
|
ble_gap_terminate(event->enc_change.conn_handle, BLE_ERR_REM_USER_CONN_TERM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Encryption successfully established");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_REPEAT_PAIRING:
|
||||||
|
ESP_LOGI(TAG, "Repeat pairing requested");
|
||||||
|
|
||||||
|
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
||||||
|
if (rc == 0)
|
||||||
|
{
|
||||||
|
char addr_str[18] = {0};
|
||||||
|
format_addr(addr_str, desc.peer_id_addr.val);
|
||||||
|
ESP_LOGI(TAG, "Deleting old bond for specific peer: %s", addr_str);
|
||||||
|
|
||||||
|
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BLE_GAP_REPEAT_PAIRING_RETRY;
|
||||||
|
|
||||||
case BLE_GAP_EVENT_ADV_COMPLETE:
|
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||||
ESP_LOGI(TAG, "Advertising complete");
|
ESP_LOGI(TAG, "Advertising complete");
|
||||||
@@ -254,15 +433,29 @@ static void ble_app_advertise(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The application
|
static void on_stack_reset(int reason)
|
||||||
static void ble_app_on_sync(void)
|
|
||||||
{
|
{
|
||||||
|
/* On reset, print reset reason to console */
|
||||||
|
ESP_LOGI(TAG, "nimble stack reset, reset reason: %d", reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_stack_sync(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
uint8_t ble_addr[6] = {0};
|
uint8_t ble_addr[6] = {0};
|
||||||
int ret = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, ble_addr, NULL);
|
|
||||||
|
/* Figure out address to use while advertising (no privacy for now) */
|
||||||
|
ret = ble_hs_id_infer_auto(0, &ble_addr_type);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "error determining address type; rc=%d", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ble_hs_id_copy_addr(ble_addr_type, ble_addr, NULL);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Failed to get BLE MAC address (err: %d)", ret);
|
ESP_LOGE(TAG, "Failed to get BLE MAC address (err: %d)", ret);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char formatted_name[32];
|
char formatted_name[32];
|
||||||
@@ -270,26 +463,88 @@ static void ble_app_on_sync(void)
|
|||||||
ble_svc_gap_device_name_set(formatted_name);
|
ble_svc_gap_device_name_set(formatted_name);
|
||||||
|
|
||||||
// Start Advertising
|
// Start Advertising
|
||||||
ble_hs_id_infer_auto(0, &ble_addr_type); // Determines the best address type automatically
|
|
||||||
ble_app_advertise();
|
ble_app_advertise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static esp_err_t gatt_svc_init(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
ble_svc_gatt_init();
|
||||||
|
|
||||||
|
ret = ble_gatts_count_cfg(gatt_svcs);
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ble_gatts_add_svcs(gatt_svcs);
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t gap_init(void)
|
||||||
|
{
|
||||||
|
ble_svc_gap_init();
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// The infinite task
|
// The infinite task
|
||||||
static 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nimble_host_config_init(void)
|
||||||
|
{
|
||||||
|
// callbacks
|
||||||
|
ble_hs_cfg.reset_cb = on_stack_reset;
|
||||||
|
ble_hs_cfg.sync_cb = on_stack_sync;
|
||||||
|
|
||||||
|
ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_ONLY;
|
||||||
|
ble_hs_cfg.sm_bonding = 1;
|
||||||
|
ble_hs_cfg.sm_mitm = 1;
|
||||||
|
ble_hs_cfg.sm_our_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
|
||||||
|
ble_hs_cfg.sm_their_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
|
||||||
|
|
||||||
|
// Initialize BLE store configuration
|
||||||
|
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
||||||
|
|
||||||
|
ble_store_config_init();
|
||||||
|
}
|
||||||
|
|
||||||
void remote_control_init(void)
|
void remote_control_init(void)
|
||||||
{
|
{
|
||||||
nimble_port_init();
|
esp_err_t ret;
|
||||||
ble_svc_gap_init();
|
|
||||||
ble_svc_gatt_init();
|
|
||||||
ble_gatts_count_cfg(gatt_svcs);
|
|
||||||
ble_gatts_add_svcs(gatt_svcs);
|
|
||||||
|
|
||||||
// Callback for synchronization
|
ret = nimble_port_init();
|
||||||
ble_hs_cfg.sync_cb = ble_app_on_sync;
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize nimble stack (err: %s)", esp_err_to_name(ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_connection_pool();
|
||||||
|
|
||||||
|
ret = gap_init();
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize GAP service (err: %s)", esp_err_to_name(ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gatt_svc_init();
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize GATT server (err: %s)", esp_err_to_name(ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nimble_host_config_init();
|
||||||
|
|
||||||
nimble_port_freertos_init(host_task); // Start BLE host task
|
nimble_port_freertos_init(host_task); // Start BLE host task
|
||||||
|
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
#include "include/uart_service.h"
|
#include "include/uart_service.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "include/remote_control.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
static const char *TAG = "uart_service";
|
static const char *TAG = "uart_service";
|
||||||
|
|
||||||
@@ -14,7 +17,6 @@ const ble_uuid128_t gatt_svr_chr_uart_rx_uuid =
|
|||||||
const ble_uuid128_t gatt_svr_chr_uart_tx_uuid =
|
const ble_uuid128_t gatt_svr_chr_uart_tx_uuid =
|
||||||
BLE_UUID128_INIT(0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x03, 0x00, 0x40, 0x6E);
|
BLE_UUID128_INIT(0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x03, 0x00, 0x40, 0x6E);
|
||||||
|
|
||||||
uint16_t conn_handle;
|
|
||||||
uint16_t tx_chr_val_handle;
|
uint16_t tx_chr_val_handle;
|
||||||
|
|
||||||
// Callback function for GATT events (read/write on characteristics)
|
// Callback function for GATT events (read/write on characteristics)
|
||||||
@@ -51,19 +53,26 @@ int gatt_svr_chr_uart_access(uint16_t conn_handle, uint16_t attr_handle, struct
|
|||||||
// Function to send data via the TX characteristic
|
// Function to send data via the TX characteristic
|
||||||
void send_ble_data(const char *data)
|
void send_ble_data(const char *data)
|
||||||
{
|
{
|
||||||
if (conn_handle != 0)
|
ESP_LOGI(TAG, "Preparing to send data: %s", data);
|
||||||
{ // Only send when connected
|
|
||||||
struct os_mbuf *om = ble_hs_mbuf_from_flat(data, strlen(data));
|
struct os_mbuf *om;
|
||||||
|
|
||||||
|
for (int i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++)
|
||||||
|
{
|
||||||
|
if (g_connections[i].is_connected)
|
||||||
|
{
|
||||||
|
om = ble_hs_mbuf_from_flat(data, strlen(data));
|
||||||
if (om)
|
if (om)
|
||||||
{
|
{
|
||||||
int rc = ble_gatts_notify_custom(conn_handle, tx_chr_val_handle, om);
|
int rc = ble_gatts_notify_custom(g_connections[i].conn_handle, tx_chr_val_handle, om);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Sent data: %s", data);
|
ESP_LOGI(TAG, "Sent data to conn_handle %d: %s", g_connections[i].conn_handle, data);
|
||||||
}
|
}
|
||||||
else
|
else if (rc != BLE_HS_ENOTCONN) // Ignore "not connected" errors if a device just disconnected
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Error sending data: %d", rc);
|
ESP_LOGE(TAG, "Error sending data to conn_handle %d: %d", g_connections[i].conn_handle, rc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +85,7 @@ void uart_tx_task(void *param)
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||||
if (conn_handle != 0)
|
if (is_any_device_connected())
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Sending data over BLE UART TX");
|
ESP_LOGI(TAG, "Sending data over BLE UART TX");
|
||||||
sprintf(buffer, "Hello World #%d", count++);
|
sprintf(buffer, "Hello World #%d", count++);
|
||||||
|
@@ -15,4 +15,29 @@ menu "Warnemuende Lighthouse"
|
|||||||
int
|
int
|
||||||
default 1 if WLED_USE_DMA
|
default 1 if WLED_USE_DMA
|
||||||
default 0 if !WLED_USE_DMA
|
default 0 if !WLED_USE_DMA
|
||||||
|
|
||||||
|
config WLED_WITH_WHITE
|
||||||
|
bool "WLED with White Channel"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Use a WLED strip with a white channel (e.g. WS2812B RGBW).
|
||||||
|
|
||||||
|
config LED_PIN_LEFT
|
||||||
|
int "LED Left Pin"
|
||||||
|
default 11
|
||||||
|
help
|
||||||
|
The pin of the LED for the left side.
|
||||||
|
|
||||||
|
config LED_PIN_RIGHT
|
||||||
|
int "LED Right Pin"
|
||||||
|
default 12
|
||||||
|
help
|
||||||
|
The pin of the LED for the right side.
|
||||||
|
|
||||||
|
config BONDING_PASSPHRASE
|
||||||
|
int "Bonding Passphrase"
|
||||||
|
default 123456
|
||||||
|
help
|
||||||
|
The passphrase for the BLE bonding.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@@ -25,14 +25,6 @@ void app_main(void)
|
|||||||
printf("Failed to initialize beacon");
|
printf("Failed to initialize beacon");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/// start beacon service
|
|
||||||
uint8_t beacon_enabled = 1;
|
|
||||||
persistence_load(VALUE_TYPE_INT32, "BEACON_ENABLED", &beacon_enabled);
|
|
||||||
if (beacon_enabled && beacon_start() != ESP_OK)
|
|
||||||
{
|
|
||||||
printf("Failed to start beacon");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// start outdoor light service
|
/// start outdoor light service
|
||||||
if (outdoor_start() != ESP_OK)
|
if (outdoor_start() != ESP_OK)
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
# Name , Type , SubType , Offset , Size , Flags
|
# Name , Type , SubType , Offset , Size , Flags
|
||||||
nvs , data , nvs , 0x9000 , 20k ,
|
nvs , data , nvs , 0x9000 , 24k ,
|
||||||
otadata , data , ota , 0xe000 , 8k ,
|
phy_init , data , phy , , 4k ,
|
||||||
app0 , app , ota_0 , 0x10000 , 1792k ,
|
factory , app , factory , 0x10000 , 3584K ,
|
||||||
app1 , app , ota_1 , , 1792k ,
|
|
||||||
coredump , data , coredump , , 64k ,
|
coredump , data , coredump , , 64k ,
|
||||||
|
|
@@ -3,10 +3,10 @@ CONFIG_BT_ENABLED=y
|
|||||||
CONFIG_BT_NIMBLE_ENABLED=y
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
|
|
||||||
# NimBLE Options
|
# NimBLE Options
|
||||||
CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
|
CONFIG_BT_NIMBLE_SECURITY_ENABLE=y
|
||||||
CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="lighthouse"
|
|
||||||
CONFIG_BT_NIMBLE_NVS_PERSIST=y
|
CONFIG_BT_NIMBLE_NVS_PERSIST=y
|
||||||
CONFIG_BT_NIMBLE_SMP_ID_RESET=y
|
CONFIG_BT_NIMBLE_SMP_ID_RESET=y
|
||||||
|
CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS=y
|
||||||
|
|
||||||
# Flash Size
|
# Flash Size
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||||
|
Reference in New Issue
Block a user