#include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "esp_log.h" #include "state_manager.h" #include "audio_driver.h" #include "wifi_connect.h" #include "socket_client.h" static const char *TAG = "state_manager"; // Centralized state container protected by a mutex static device_state_t s_device_state; static SemaphoreHandle_t s_state_mutex = NULL; void state_manager_init(void) { s_state_mutex = xSemaphoreCreateMutex(); // Set initial boot default states s_device_state.volume = 85; s_device_state.led_state = LED_STATE_OFF; s_device_state.led_brightness = 0.2f; s_device_state.wifi_connected = false; s_device_state.websocket_connected = false; s_device_state.haptic_intensity = 0; s_device_state.ambient_light = 0; s_device_state.touch_active = 0; ESP_LOGI(TAG, "State Manager initialized successfully."); } void state_get_current(device_state_t *out_state) { if (s_state_mutex == NULL) { return; } if (xSemaphoreTake(s_state_mutex, portMAX_DELAY) == pdTRUE) { memcpy(out_state, &s_device_state, sizeof(device_state_t)); xSemaphoreGive(s_state_mutex); } } void state_set_volume(uint8_t volume) { if (volume > 100) volume = 100; bool changed = false; if (s_state_mutex != NULL && xSemaphoreTake(s_state_mutex, portMAX_DELAY) == pdTRUE) { if (s_device_state.volume != volume) { s_device_state.volume = volume; changed = true; } xSemaphoreGive(s_state_mutex); } if (changed) { ESP_LOGI(TAG, "Volume state changed to %d. Updating DAC codec driver...", volume); Volume_Adjustment(volume); trigger_telemetry_broadcast(); } } void state_set_led(led_state_t state) { bool changed = false; if (s_state_mutex != NULL && xSemaphoreTake(s_state_mutex, portMAX_DELAY) == pdTRUE) { if (s_device_state.led_state != state) { s_device_state.led_state = state; changed = true; } xSemaphoreGive(s_state_mutex); } if (changed) { ESP_LOGI(TAG, "LED state changed to %d. Updating visual animation thread...", state); set_led_state(state); trigger_telemetry_broadcast(); } } void state_set_brightness(float brightness) { if (brightness < 0.0f) brightness = 0.0f; if (brightness > 1.0f) brightness = 1.0f; bool changed = false; if (s_state_mutex != NULL && xSemaphoreTake(s_state_mutex, portMAX_DELAY) == pdTRUE) { if (s_device_state.led_brightness != brightness) { s_device_state.led_brightness = brightness; changed = true; } xSemaphoreGive(s_state_mutex); } if (changed) { ESP_LOGI(TAG, "LED brightness state changed to %f", brightness); trigger_telemetry_broadcast(); } } void state_set_wifi_connected(bool connected) { bool changed = false; if (s_state_mutex != NULL && xSemaphoreTake(s_state_mutex, portMAX_DELAY) == pdTRUE) { if (s_device_state.wifi_connected != connected) { s_device_state.wifi_connected = connected; changed = true; } xSemaphoreGive(s_state_mutex); } if (changed) { ESP_LOGI(TAG, "Wi-Fi connection state changed to: %s", connected ? "CONNECTED" : "DISCONNECTED"); trigger_telemetry_broadcast(); } } void state_set_websocket_connected(bool connected) { bool changed = false; if (s_state_mutex != NULL && xSemaphoreTake(s_state_mutex, portMAX_DELAY) == pdTRUE) { if (s_device_state.websocket_connected != connected) { s_device_state.websocket_connected = connected; changed = true; } xSemaphoreGive(s_state_mutex); } if (changed) { ESP_LOGI(TAG, "WebSocket server state changed to: %s", connected ? "CONNECTED" : "DISCONNECTED"); trigger_telemetry_broadcast(); } } void state_set_haptic_intensity(uint8_t intensity) { if (intensity > 100) intensity = 100; bool changed = false; if (s_state_mutex != NULL && xSemaphoreTake(s_state_mutex, portMAX_DELAY) == pdTRUE) { if (s_device_state.haptic_intensity != intensity) { s_device_state.haptic_intensity = intensity; changed = true; } xSemaphoreGive(s_state_mutex); } if (changed) { ESP_LOGI(TAG, "Haptic intensity changed to %d", intensity); #ifdef MODEL_PROTO_1 extern void proto1_haptics_set_intensity(uint8_t intensity); proto1_haptics_set_intensity(intensity); #endif trigger_telemetry_broadcast(); } } void state_set_sensors(uint16_t ambient_light, uint8_t touch_active) { if (s_state_mutex != NULL && xSemaphoreTake(s_state_mutex, portMAX_DELAY) == pdTRUE) { s_device_state.ambient_light = ambient_light; s_device_state.touch_active = touch_active; xSemaphoreGive(s_state_mutex); } }