Fix Bluetooth pairing, menu crashes, and improve UX
Major fixes and improvements to Bluetooth device management and menu navigation: **Bluetooth Device Pairing** - Fixed discovered devices not being saved as paired after connection - Only save devices to NVS when successfully connected (not just discovered) - Auto-pair discovered devices on successful A2DP connection - Update device list to show paired status immediately after connection **Critical Bug Fixes** - Fixed dangling pointer crash in NVS request/response mechanism - Was sending pointer to stack variable, now sends result value directly - Prevents crash when connecting to Bluetooth devices - Fixed use-after-free crash when clicking menu items after dynamic updates - Menu context now properly synchronized after adding/removing items - Prevents InstructionFetchError crashes in menu navigation - Fixed memory exhaustion by reducing MAX_BT_DEVICES from 20 to 8 - Prevents heap allocation failures when populating device list **Menu & UX Improvements** - "Clear Paired" button now properly disconnects active connections - "Clear Paired" button always visible when paired devices exist - GUI updates immediately after clearing paired devices - Paired devices marked with asterisk prefix (* Device Name) - Removed redundant "(paired)" suffix text - Long device names scroll smoothly when selected (3-second animation) - Refresh button preserved during menu updates to prevent crashes - Menu focus state properly maintained across all dynamic updates **Technical Details** - bt_add_discovered_device() no longer saves to NVS - Added currentFocusIndex() calls after all menu modifications - Improved clear_bt_device_list() to avoid deleting active buttons - Added bt_disconnect_current_device() for clean disconnections - Fixed NVS notification mechanism to avoid stack variable pointers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -22,12 +22,13 @@ void system_init(void)
|
||||
_systemState.zeroAngle = 0.0f;
|
||||
_systemState.primaryAxis = PRIMARY_AXIS;
|
||||
_systemState.pairedDeviceCount = 0;
|
||||
_systemState.isCharging = false;
|
||||
|
||||
_systemEvent = xEventGroupCreate();
|
||||
|
||||
_eventManager.count = 0;
|
||||
_eventManager.mutex = xSemaphoreCreateMutex();
|
||||
|
||||
|
||||
system_initNvsService();
|
||||
}
|
||||
|
||||
@@ -48,13 +49,29 @@ float system_getAngle(void)
|
||||
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
|
||||
|
||||
|
||||
angle = _systemState.imu.raw[_systemState.primaryAxis] - _systemState.zeroAngle;
|
||||
|
||||
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
|
||||
return angle;
|
||||
return angle;
|
||||
}
|
||||
|
||||
void system_setChargeStatus(bool charging)
|
||||
{
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
_systemState.isCharging = charging;
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
}
|
||||
|
||||
bool system_getChargeStatus(void)
|
||||
{
|
||||
bool charging;
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
charging = _systemState.isCharging;
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
return charging;
|
||||
}
|
||||
|
||||
void system_setZeroAngle(void)
|
||||
@@ -349,16 +366,16 @@ void system_processNvsRequests(void) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
request.result = ESP_ERR_INVALID_ARG;
|
||||
break;
|
||||
}
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
|
||||
request.response_ready = true;
|
||||
|
||||
// Send the result directly as the notification value (not a pointer)
|
||||
if (request.requestor) {
|
||||
xTaskNotify(request.requestor, (uint32_t)&request, eSetValueWithOverwrite);
|
||||
xTaskNotify(request.requestor, (uint32_t)request.result, eSetValueWithOverwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,8 +413,8 @@ esp_err_t system_savePairedDevice(const paired_device_t *device) {
|
||||
if (xQueueSend(_nvsRequestQueue, &request, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
uint32_t notification;
|
||||
if (xTaskNotifyWait(0, UINT32_MAX, ¬ification, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
nvs_request_t *response = (nvs_request_t*)notification;
|
||||
return response->result;
|
||||
// notification contains the result directly (not a pointer)
|
||||
return (esp_err_t)notification;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_TIMEOUT;
|
||||
@@ -425,8 +442,8 @@ esp_err_t system_removePairedDevice(esp_bd_addr_t bda) {
|
||||
if (xQueueSend(_nvsRequestQueue, &request, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
uint32_t notification;
|
||||
if (xTaskNotifyWait(0, UINT32_MAX, ¬ification, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
nvs_request_t *response = (nvs_request_t*)notification;
|
||||
return response->result;
|
||||
// notification contains the result directly (not a pointer)
|
||||
return (esp_err_t)notification;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_TIMEOUT;
|
||||
@@ -464,8 +481,8 @@ esp_err_t system_updateConnectionTimestamp(esp_bd_addr_t bda) {
|
||||
if (xQueueSend(_nvsRequestQueue, &request, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
uint32_t notification;
|
||||
if (xTaskNotifyWait(0, UINT32_MAX, ¬ification, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
nvs_request_t *response = (nvs_request_t*)notification;
|
||||
return response->result;
|
||||
// notification contains the result directly (not a pointer)
|
||||
return (esp_err_t)notification;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_TIMEOUT;
|
||||
@@ -473,10 +490,26 @@ esp_err_t system_updateConnectionTimestamp(esp_bd_addr_t bda) {
|
||||
|
||||
const paired_device_t* system_getPairedDevices(size_t *count) {
|
||||
if (!count) return NULL;
|
||||
|
||||
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
*count = _systemState.pairedDeviceCount;
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
|
||||
|
||||
return (const paired_device_t*)_systemState.pairedDevices;
|
||||
}
|
||||
|
||||
esp_err_t system_clearAllPairedDevices(void) {
|
||||
// Directly clear in-memory state and save to NVS
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
_systemState.pairedDeviceCount = 0;
|
||||
esp_err_t ret = nvs_save_devices_internal(_systemState.pairedDevices, 0);
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI("system", "Cleared all paired devices from NVS");
|
||||
} else {
|
||||
ESP_LOGE("system", "Failed to clear paired devices: %s", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user