mirror of
https://github.com/MrUnknownDE/OpenIris-ESPIDF.git
synced 2026-04-19 06:23:44 +02:00
upload mutimodal
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <CommandManager.hpp>
|
||||
#include <SerialManager.hpp>
|
||||
#include <RestAPI.hpp>
|
||||
#include <main_globals.hpp>
|
||||
|
||||
#ifdef CONFIG_WIRED_MODE
|
||||
#include <UVCStream.hpp>
|
||||
@@ -29,8 +30,10 @@
|
||||
#define CONFIG_LED_C_PIN_GPIO (gpio_num_t) CONFIG_LED_C_PIN
|
||||
|
||||
esp_timer_handle_t timerHandle;
|
||||
esp_timer_handle_t startupTimerHandle;
|
||||
QueueHandle_t eventQueue = xQueueCreate(10, sizeof(SystemEvent));
|
||||
QueueHandle_t ledStateQueue = xQueueCreate(10, sizeof(uint32_t));
|
||||
bool startupCommandReceived = false;
|
||||
|
||||
auto *stateManager = new StateManager(eventQueue, ledStateQueue);
|
||||
auto dependencyRegistry = std::make_shared<DependencyRegistry>();
|
||||
@@ -39,8 +42,8 @@ auto commandManager = std::make_shared<CommandManager>(dependencyRegistry);
|
||||
WebSocketLogger webSocketLogger;
|
||||
Preferences preferences;
|
||||
|
||||
std::shared_ptr<ProjectConfig> deviceConfig = std::make_shared<ProjectConfig>(&preferences);
|
||||
WiFiManager wifiManager(deviceConfig, eventQueue, stateManager);
|
||||
auto deviceConfig = std::make_shared<ProjectConfig>(&preferences);
|
||||
auto wifiManager = std::make_shared<WiFiManager>(deviceConfig, eventQueue, stateManager);
|
||||
MDNSManager mdnsManager(deviceConfig, eventQueue);
|
||||
|
||||
std::shared_ptr<CameraManager> cameraHandler = std::make_shared<CameraManager>(deviceConfig, eventQueue);
|
||||
@@ -53,7 +56,7 @@ UVCStreamManager uvcStream;
|
||||
#endif
|
||||
|
||||
auto *ledManager = new LEDManager(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO, ledStateQueue);
|
||||
auto *serialManager = new SerialManager(commandManager, &timerHandle);
|
||||
auto *serialManager = new SerialManager(commandManager, &timerHandle, deviceConfig);
|
||||
|
||||
static void initNVSStorage() {
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
@@ -73,58 +76,151 @@ void disable_serial_manager_task(TaskHandle_t serialManagerHandle) {
|
||||
vTaskDelete(serialManagerHandle);
|
||||
}
|
||||
|
||||
// the idea here is pretty simple.
|
||||
// After setting everything up, we start a 30s timer with this as a callback
|
||||
// if we get anything on the serial, we stop the timer and reset it after the commands are done
|
||||
// this is done to ensure the user has enough time to configure the board if need be
|
||||
void start_video_streaming(void *arg) {
|
||||
// if we're in auto-mode, we can decide which streaming helper to start based on the
|
||||
// presence of Wi-Fi credentials
|
||||
ESP_LOGI("[MAIN]", "Setup window expired, starting streaming services, quitting serial manager.");
|
||||
switch (deviceConfig->getDeviceMode().mode) {
|
||||
case StreamingMode::AUTO:
|
||||
if (!deviceConfig->getWifiConfigs().empty() || strcmp(CONFIG_WIFI_SSID, "") != 0) {
|
||||
// todo make sure the server runs on a separate core
|
||||
ESP_LOGI("[MAIN]", "WiFi setup detected, starting WiFi streaming.");
|
||||
streamServer.startStreamServer();
|
||||
} else {
|
||||
ESP_LOGI("[MAIN]", "UVC setup detected, starting UVC streaming.");
|
||||
uvcStream.setup();
|
||||
// New setup flow:
|
||||
// 1. Device starts in setup mode (AP + Serial active)
|
||||
// 2. User configures WiFi via serial commands
|
||||
// 3. Device attempts WiFi connection while maintaining setup interfaces
|
||||
// 4. Device reports connection status via serial
|
||||
// 5. User explicitly starts streaming after verifying connectivity
|
||||
void start_video_streaming(void *arg)
|
||||
{
|
||||
// Get the stored device mode
|
||||
StreamingMode deviceMode = deviceConfig->getDeviceMode();
|
||||
|
||||
// Check if WiFi is actually connected, not just configured
|
||||
bool hasWifiCredentials = !deviceConfig->getWifiConfigs().empty() || strcmp(CONFIG_WIFI_SSID, "") != 0;
|
||||
bool wifiConnected = (wifiManager->GetCurrentWiFiState() == WiFiState_e::WiFiState_Connected);
|
||||
|
||||
if (deviceMode == StreamingMode::UVC) {
|
||||
#ifdef CONFIG_WIRED_MODE
|
||||
ESP_LOGI("[MAIN]", "Starting UVC streaming mode.");
|
||||
// Initialize UVC if not already done
|
||||
static bool uvcInitialized = false;
|
||||
if (!uvcInitialized) {
|
||||
ESP_LOGI("[MAIN]", "Initializing UVC hardware...");
|
||||
esp_err_t ret = uvcStream.setup();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE("[MAIN]", "Failed to initialize UVC: %s", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case StreamingMode::UVC:
|
||||
ESP_LOGI("[MAIN]", "Device set to UVC Mode, starting UVC streaming.");
|
||||
uvcStream.setup();
|
||||
break;
|
||||
case StreamingMode::WIFI:
|
||||
ESP_LOGI("[MAIN]", "Device set to Wi-Fi mode, starting WiFi streaming.");
|
||||
streamServer.startStreamServer();
|
||||
break;
|
||||
uvcInitialized = true;
|
||||
}
|
||||
uvcStream.start();
|
||||
#else
|
||||
ESP_LOGE("[MAIN]", "UVC mode selected but CONFIG_WIRED_MODE not enabled in build!");
|
||||
ESP_LOGI("[MAIN]", "Falling back to WiFi mode if credentials available");
|
||||
deviceMode = StreamingMode::WIFI;
|
||||
#endif
|
||||
}
|
||||
|
||||
const auto serialTaskHandle = static_cast<TaskHandle_t>(arg);
|
||||
disable_serial_manager_task(serialTaskHandle);
|
||||
if ((deviceMode == StreamingMode::WIFI || deviceMode == StreamingMode::AUTO) && hasWifiCredentials && wifiConnected) {
|
||||
ESP_LOGI("[MAIN]", "Starting WiFi streaming mode.");
|
||||
streamServer.startStreamServer();
|
||||
} else {
|
||||
if (hasWifiCredentials && !wifiConnected) {
|
||||
ESP_LOGE("[MAIN]", "WiFi credentials configured but not connected. Try connecting first.");
|
||||
} else {
|
||||
ESP_LOGE("[MAIN]", "No streaming mode available. Please configure WiFi.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI("[MAIN]", "Streaming started successfully.");
|
||||
|
||||
// Optionally disable serial manager after explicit streaming start
|
||||
if (arg != nullptr) {
|
||||
ESP_LOGI("[MAIN]", "Disabling setup interfaces after streaming start.");
|
||||
const auto serialTaskHandle = static_cast<TaskHandle_t>(arg);
|
||||
disable_serial_manager_task(serialTaskHandle);
|
||||
}
|
||||
}
|
||||
|
||||
esp_timer_handle_t createStartVideoStreamingTimer(void *pvParameter) {
|
||||
esp_timer_handle_t handle;
|
||||
const esp_timer_create_args_t args = {
|
||||
.callback = &start_video_streaming,
|
||||
.arg = pvParameter,
|
||||
.name = "startVideoStreaming"
|
||||
};
|
||||
// Manual streaming activation - no timer needed
|
||||
void activate_streaming(TaskHandle_t serialTaskHandle = nullptr)
|
||||
{
|
||||
start_video_streaming(serialTaskHandle);
|
||||
}
|
||||
|
||||
if (const auto result = esp_timer_create(&args, &handle); result != ESP_OK) {
|
||||
ESP_LOGE("[MAIN]", "Failed to create timer: %s", esp_err_to_name(result));
|
||||
// Callback for automatic startup after delay
|
||||
void startup_timer_callback(void* arg)
|
||||
{
|
||||
ESP_LOGI("[MAIN]", "Startup timer fired, startupCommandReceived=%s, startupPaused=%s",
|
||||
startupCommandReceived ? "true" : "false",
|
||||
startupPaused ? "true" : "false");
|
||||
|
||||
if (!startupCommandReceived && !startupPaused) {
|
||||
ESP_LOGI("[MAIN]", "No command received during startup delay, proceeding with automatic mode startup");
|
||||
|
||||
// Get the stored device mode
|
||||
StreamingMode deviceMode = deviceConfig->getDeviceMode();
|
||||
ESP_LOGI("[MAIN]", "Stored device mode: %d", (int)deviceMode);
|
||||
|
||||
// Get the serial manager handle to disable it after streaming starts
|
||||
TaskHandle_t* serialHandle = getSerialManagerHandle();
|
||||
TaskHandle_t serialTaskHandle = (serialHandle && *serialHandle) ? *serialHandle : nullptr;
|
||||
|
||||
if (deviceMode == StreamingMode::WIFI || deviceMode == StreamingMode::AUTO) {
|
||||
// For WiFi mode, check if we have credentials and are connected
|
||||
bool hasWifiCredentials = !deviceConfig->getWifiConfigs().empty() || strcmp(CONFIG_WIFI_SSID, "") != 0;
|
||||
bool wifiConnected = (wifiManager->GetCurrentWiFiState() == WiFiState_e::WiFiState_Connected);
|
||||
|
||||
ESP_LOGI("[MAIN]", "WiFi check - hasCredentials: %s, connected: %s",
|
||||
hasWifiCredentials ? "true" : "false",
|
||||
wifiConnected ? "true" : "false");
|
||||
|
||||
if (hasWifiCredentials && wifiConnected) {
|
||||
ESP_LOGI("[MAIN]", "Starting WiFi streaming automatically");
|
||||
activate_streaming(serialTaskHandle);
|
||||
} else if (hasWifiCredentials && !wifiConnected) {
|
||||
ESP_LOGI("[MAIN]", "WiFi credentials exist but not connected, waiting...");
|
||||
// Could retry connection here
|
||||
} else {
|
||||
ESP_LOGI("[MAIN]", "No WiFi credentials, staying in setup mode");
|
||||
}
|
||||
}
|
||||
else if (deviceMode == StreamingMode::UVC) {
|
||||
#ifdef CONFIG_WIRED_MODE
|
||||
ESP_LOGI("[MAIN]", "Starting UVC streaming automatically");
|
||||
activate_streaming(serialTaskHandle);
|
||||
#else
|
||||
ESP_LOGE("[MAIN]", "UVC mode selected but CONFIG_WIRED_MODE not enabled in build!");
|
||||
ESP_LOGI("[MAIN]", "Device will stay in setup mode. Enable CONFIG_WIRED_MODE and rebuild.");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ESP_LOGI("[MAIN]", "Unknown device mode: %d", (int)deviceMode);
|
||||
}
|
||||
} else {
|
||||
if (startupPaused) {
|
||||
ESP_LOGI("[MAIN]", "Startup paused, staying in heartbeat mode");
|
||||
} else {
|
||||
ESP_LOGI("[MAIN]", "Command received during startup, staying in heartbeat mode");
|
||||
}
|
||||
}
|
||||
|
||||
return handle;
|
||||
// Delete the timer after it fires
|
||||
esp_timer_delete(startupTimerHandle);
|
||||
startupTimerHandle = nullptr;
|
||||
}
|
||||
|
||||
// Function to notify that a command was received during startup
|
||||
void notify_startup_command_received()
|
||||
{
|
||||
startupCommandReceived = true;
|
||||
|
||||
// Cancel the startup timer if it's still running
|
||||
if (startupTimerHandle != nullptr) {
|
||||
esp_timer_stop(startupTimerHandle);
|
||||
esp_timer_delete(startupTimerHandle);
|
||||
startupTimerHandle = nullptr;
|
||||
ESP_LOGI("[MAIN]", "Startup timer cancelled, staying in heartbeat mode");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void app_main(void) {
|
||||
TaskHandle_t *serialManagerHandle = nullptr;
|
||||
dependencyRegistry->registerService<ProjectConfig>(DependencyType::project_config, deviceConfig);
|
||||
dependencyRegistry->registerService<CameraManager>(DependencyType::camera_manager, cameraHandler);
|
||||
dependencyRegistry->registerService<WiFiManager>(DependencyType::wifi_manager, wifiManager);
|
||||
// uvc plan
|
||||
// cleanup the logs - done
|
||||
// prepare the camera to be initialized with UVC - done?
|
||||
@@ -197,19 +293,23 @@ extern "C" void app_main(void) {
|
||||
deviceConfig->load();
|
||||
serialManager->setup();
|
||||
|
||||
static TaskHandle_t serialManagerHandle = nullptr;
|
||||
xTaskCreate(
|
||||
HandleSerialManagerTask,
|
||||
"HandleSerialManagerTask",
|
||||
1024 * 6,
|
||||
serialManager,
|
||||
1, // we only rely on the serial manager during provisioning, we can run it slower
|
||||
serialManagerHandle);
|
||||
&serialManagerHandle);
|
||||
|
||||
wifiManager.Begin();
|
||||
wifiManager->Begin();
|
||||
mdnsManager.start();
|
||||
restAPI->begin();
|
||||
cameraHandler->setupCamera();
|
||||
|
||||
// Don't initialize UVC here - wait for the timer to decide
|
||||
// UVC will be initialized when streaming actually starts
|
||||
|
||||
xTaskCreate(
|
||||
HandleRestAPIPollTask,
|
||||
"HandleRestAPIPollTask",
|
||||
@@ -218,8 +318,44 @@ extern "C" void app_main(void) {
|
||||
1, // it's the rest API, we only serve commands over it so we don't really need a higher priority
|
||||
nullptr);
|
||||
|
||||
timerHandle = createStartVideoStreamingTimer(serialManagerHandle);
|
||||
if (timerHandle != nullptr) {
|
||||
esp_timer_start_once(timerHandle, 30000000); // 30s
|
||||
// New flow: Device starts with a 20-second delay before automatic mode startup
|
||||
ESP_LOGI("[MAIN]", "=====================================");
|
||||
ESP_LOGI("[MAIN]", "STARTUP: 20-SECOND DELAY MODE ACTIVE");
|
||||
ESP_LOGI("[MAIN]", "=====================================");
|
||||
ESP_LOGI("[MAIN]", "Device will wait 20 seconds for commands...");
|
||||
|
||||
// Get the stored device mode
|
||||
StreamingMode deviceMode = deviceConfig->getDeviceMode();
|
||||
ESP_LOGI("[MAIN]", "Stored device mode: %s (value: %d)",
|
||||
deviceMode == StreamingMode::UVC ? "UVC" :
|
||||
deviceMode == StreamingMode::WIFI ? "WiFi" :
|
||||
"Auto", (int)deviceMode);
|
||||
|
||||
// If WiFi credentials exist, attempt connection but stay in setup mode
|
||||
if (!deviceConfig->getWifiConfigs().empty()) {
|
||||
ESP_LOGI("[MAIN]", "WiFi credentials found, attempting connection in background");
|
||||
// WiFi connection happens in wifiManager->Begin() above
|
||||
}
|
||||
|
||||
// Reset startup state
|
||||
startupCommandReceived = false;
|
||||
|
||||
// Create a one-shot timer for 20 seconds
|
||||
const esp_timer_create_args_t startup_timer_args = {
|
||||
.callback = &startup_timer_callback,
|
||||
.arg = nullptr,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "startup_timer",
|
||||
.skip_unhandled_events = false
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_timer_create(&startup_timer_args, &startupTimerHandle));
|
||||
ESP_ERROR_CHECK(esp_timer_start_once(startupTimerHandle, 20000000)); // 20 seconds in microseconds
|
||||
|
||||
ESP_LOGI("[MAIN]", "Started 20-second startup timer");
|
||||
ESP_LOGI("[MAIN]", "Send any command within 20 seconds to enter heartbeat mode");
|
||||
|
||||
// Set global handles for component access
|
||||
setStreamingTimerHandle(&timerHandle);
|
||||
setSerialManagerHandle(&serialManagerHandle);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user