mirror of
https://github.com/EyeTrackVR/OpenIris.git
synced 2025-09-26 23:29:14 +08:00
Compare commits
2 Commits
b2a8936bee
...
176a85a403
Author | SHA1 | Date | |
---|---|---|---|
![]() |
176a85a403 | ||
![]() |
fe09dd0c62 |
@ -1,5 +1,4 @@
|
||||
#include "CommandManager.hpp"
|
||||
#include "data/DeviceMode/DeviceMode.hpp"
|
||||
#include "tasks/tasks.hpp"
|
||||
|
||||
|
||||
@ -59,15 +58,9 @@ void CommandManager::handleCommand(JsonVariant command) {
|
||||
0, // power, should this be zero?
|
||||
false, false);
|
||||
|
||||
DeviceModeManager* deviceModeManager = DeviceModeManager::getInstance();
|
||||
if (deviceModeManager) {
|
||||
deviceModeManager->setHasWiFiCredentials(true);
|
||||
|
||||
deviceModeManager->setMode(DeviceMode::WIFI_MODE);
|
||||
log_i("[CommandManager] Switching to WiFi mode after receiving credentials");
|
||||
|
||||
OpenIrisTasks::ScheduleRestart(2000);
|
||||
}
|
||||
this->deviceConfig->setHasWiFiCredentials(true, false);
|
||||
this->deviceConfig->setDeviceMode(DeviceMode::WIFI_MODE, true);
|
||||
log_i("[CommandManager] Switching to WiFi mode after receiving credentials");
|
||||
|
||||
break;
|
||||
}
|
||||
@ -97,30 +90,25 @@ void CommandManager::handleCommand(JsonVariant command) {
|
||||
|
||||
int modeValue = command["data"]["mode"];
|
||||
DeviceMode newMode = static_cast<DeviceMode>(modeValue);
|
||||
DeviceMode currentMode;
|
||||
DeviceMode currentMode = this->deviceConfig->getDeviceModeConfig().mode;
|
||||
|
||||
DeviceModeManager* deviceModeManager = DeviceModeManager::getInstance();
|
||||
if (deviceModeManager) {
|
||||
currentMode = deviceModeManager->getMode();
|
||||
|
||||
// If switching to USB mode from WiFi or AP mode, disconnect WiFi immediately
|
||||
if (newMode == DeviceMode::USB_MODE &&
|
||||
(currentMode == DeviceMode::WIFI_MODE || currentMode == DeviceMode::AP_MODE)) {
|
||||
log_i("[CommandManager] Immediately switching to USB mode");
|
||||
WiFi.disconnect(true);
|
||||
}
|
||||
|
||||
deviceModeManager->setMode(newMode);
|
||||
log_i("[CommandManager] Switching to mode: %d", modeValue);
|
||||
|
||||
// Only schedule a restart if not switching to USB mode during WiFi/AP initialization
|
||||
if (!(newMode == DeviceMode::USB_MODE &&
|
||||
(currentMode == DeviceMode::WIFI_MODE || currentMode == DeviceMode::AP_MODE) &&
|
||||
wifiStateManager.getCurrentState() == WiFiState_e::WiFiState_Connecting)) {
|
||||
OpenIrisTasks::ScheduleRestart(2000);
|
||||
}
|
||||
// If switching to USB mode from WiFi or AP mode, disconnect WiFi immediately
|
||||
if (newMode == DeviceMode::USB_MODE &&
|
||||
(currentMode == DeviceMode::WIFI_MODE || currentMode == DeviceMode::AP_MODE)) {
|
||||
log_i("[CommandManager] Immediately switching to USB mode");
|
||||
WiFi.disconnect(true);
|
||||
}
|
||||
|
||||
this->deviceConfig->setDeviceMode(newMode, true);
|
||||
log_i("[CommandManager] Switching to mode: %d", modeValue);
|
||||
|
||||
// Removed automatic restart to allow explicit control via RESTART_DEVICE command
|
||||
// if (!(newMode == DeviceMode::USB_MODE &&
|
||||
// (currentMode == DeviceMode::WIFI_MODE || currentMode == DeviceMode::AP_MODE) &&
|
||||
// wifiStateManager.getCurrentState() == WiFiState_e::WiFiState_Connecting)) {
|
||||
// OpenIrisTasks::ScheduleRestart(2000);
|
||||
// }
|
||||
|
||||
break;
|
||||
}
|
||||
case CommandType::WIPE_WIFI_CREDS: {
|
||||
@ -130,18 +118,18 @@ void CommandManager::handleCommand(JsonVariant command) {
|
||||
this->deviceConfig->deleteWifiConfig(network.name, false);
|
||||
}
|
||||
|
||||
DeviceModeManager* deviceModeManager = DeviceModeManager::getInstance();
|
||||
if (deviceModeManager) {
|
||||
deviceModeManager->setHasWiFiCredentials(false);
|
||||
|
||||
deviceModeManager->setMode(DeviceMode::USB_MODE);
|
||||
log_i("[CommandManager] Switching to USB mode after wiping credentials");
|
||||
|
||||
OpenIrisTasks::ScheduleRestart(2000);
|
||||
}
|
||||
this->deviceConfig->setHasWiFiCredentials(false, false);
|
||||
this->deviceConfig->setDeviceMode(DeviceMode::USB_MODE, true);
|
||||
log_i("[CommandManager] Switching to USB mode after wiping credentials");
|
||||
// Removed automatic restart to allow processing of all commands in payload
|
||||
|
||||
break;
|
||||
}
|
||||
case CommandType::RESTART_DEVICE: {
|
||||
log_i("[CommandManager] Explicit restart requested");
|
||||
OpenIrisTasks::ScheduleRestart(2000);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ enum CommandType {
|
||||
SET_MDNS,
|
||||
SWITCH_MODE,
|
||||
WIPE_WIFI_CREDS,
|
||||
RESTART_DEVICE,
|
||||
};
|
||||
|
||||
struct CommandsPayload {
|
||||
@ -26,6 +27,7 @@ class CommandManager {
|
||||
{"set_mdns", CommandType::SET_MDNS},
|
||||
{"switch_mode", CommandType::SWITCH_MODE},
|
||||
{"wipe_wifi_creds", CommandType::WIPE_WIFI_CREDS},
|
||||
{"restart_device", CommandType::RESTART_DEVICE},
|
||||
};
|
||||
|
||||
ProjectConfig* deviceConfig;
|
||||
@ -37,6 +39,7 @@ class CommandManager {
|
||||
public:
|
||||
CommandManager(ProjectConfig* deviceConfig);
|
||||
void handleCommands(CommandsPayload commandsPayload);
|
||||
ProjectConfig* getDeviceConfig() { return deviceConfig; }
|
||||
};
|
||||
|
||||
#endif
|
@ -1,62 +0,0 @@
|
||||
#include "DeviceMode.hpp"
|
||||
|
||||
DeviceModeManager* DeviceModeManager::instance = nullptr;
|
||||
|
||||
DeviceModeManager::DeviceModeManager() : currentMode(DeviceMode::USB_MODE) {}
|
||||
|
||||
DeviceModeManager::~DeviceModeManager() {
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
void DeviceModeManager::init() {
|
||||
preferences.begin(PREF_NAMESPACE, false);
|
||||
|
||||
// Load the saved mode or use default (USB_MODE)
|
||||
int savedMode = preferences.getInt(MODE_KEY, static_cast<int>(DeviceMode::AUTO_MODE));
|
||||
currentMode = static_cast<DeviceMode>(savedMode);
|
||||
|
||||
// If in AUTO_MODE, determine the appropriate mode based on saved credentials
|
||||
if (currentMode == DeviceMode::AUTO_MODE) {
|
||||
currentMode = determineMode();
|
||||
}
|
||||
|
||||
log_i("[DeviceModeManager] Initialized with mode: %d", static_cast<int>(currentMode));
|
||||
}
|
||||
|
||||
DeviceMode DeviceModeManager::getMode() {
|
||||
return currentMode;
|
||||
}
|
||||
|
||||
void DeviceModeManager::setMode(DeviceMode mode) {
|
||||
currentMode = mode;
|
||||
preferences.putInt(MODE_KEY, static_cast<int>(mode));
|
||||
log_i("[DeviceModeManager] Mode set to: %d", static_cast<int>(mode));
|
||||
}
|
||||
|
||||
bool DeviceModeManager::hasWiFiCredentials() {
|
||||
return preferences.getBool(HAS_WIFI_CREDS_KEY, false);
|
||||
}
|
||||
|
||||
void DeviceModeManager::setHasWiFiCredentials(bool hasCredentials) {
|
||||
preferences.putBool(HAS_WIFI_CREDS_KEY, hasCredentials);
|
||||
log_i("[DeviceModeManager] WiFi credentials status set to: %d", hasCredentials);
|
||||
}
|
||||
|
||||
DeviceMode DeviceModeManager::determineMode() {
|
||||
// If WiFi credentials are saved, use WiFi mode, otherwise use AP mode
|
||||
return hasWiFiCredentials() ? DeviceMode::WIFI_MODE : DeviceMode::AP_MODE;
|
||||
}
|
||||
|
||||
DeviceModeManager* DeviceModeManager::getInstance() {
|
||||
if (instance == nullptr) {
|
||||
createInstance();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
void DeviceModeManager::createInstance() {
|
||||
if (instance == nullptr) {
|
||||
instance = new DeviceModeManager();
|
||||
instance->init();
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef DEVICE_MODE_HPP
|
||||
#define DEVICE_MODE_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Preferences.h>
|
||||
#include <string>
|
||||
|
||||
// Enum to represent the device operating mode
|
||||
enum class DeviceMode {
|
||||
USB_MODE, // Device operates in USB mode only
|
||||
WIFI_MODE, // Device operates in WiFi mode only
|
||||
AP_MODE, // Device operates in AP mode with serial commands enabled
|
||||
AUTO_MODE // Device automatically selects mode based on saved credentials
|
||||
};
|
||||
|
||||
class DeviceModeManager {
|
||||
private:
|
||||
static DeviceModeManager* instance;
|
||||
Preferences preferences;
|
||||
DeviceMode currentMode;
|
||||
const char* PREF_NAMESPACE = "device_mode";
|
||||
const char* MODE_KEY = "mode";
|
||||
const char* HAS_WIFI_CREDS_KEY = "has_wifi_creds";
|
||||
|
||||
public:
|
||||
DeviceModeManager();
|
||||
~DeviceModeManager();
|
||||
|
||||
static DeviceModeManager* getInstance();
|
||||
|
||||
static void createInstance();
|
||||
|
||||
void init();
|
||||
|
||||
DeviceMode getMode();
|
||||
|
||||
void setMode(DeviceMode mode);
|
||||
|
||||
bool hasWiFiCredentials();
|
||||
|
||||
void setHasWiFiCredentials(bool hasCredentials);
|
||||
|
||||
DeviceMode determineMode();
|
||||
};
|
||||
|
||||
#endif // DEVICE_MODE_HPP
|
@ -28,7 +28,8 @@ struct DeviceStates {
|
||||
networksConfigUpdated,
|
||||
apConfigUpdated,
|
||||
wifiTxPowerUpdated,
|
||||
cameraConfigUpdated
|
||||
cameraConfigUpdated,
|
||||
deviceModeUpdated
|
||||
};
|
||||
|
||||
enum WiFiState_e {
|
||||
|
@ -58,6 +58,12 @@ void ProjectConfig::initConfig() {
|
||||
.quality = 7,
|
||||
.brightness = 2,
|
||||
};
|
||||
|
||||
// Initialize device mode with default values
|
||||
this->config.deviceMode = {
|
||||
.mode = DeviceMode::AUTO_MODE,
|
||||
.hasWiFiCredentials = false,
|
||||
};
|
||||
}
|
||||
|
||||
void ProjectConfig::save() {
|
||||
@ -67,11 +73,13 @@ void ProjectConfig::save() {
|
||||
cameraConfigSave();
|
||||
wifiConfigSave();
|
||||
wifiTxPowerConfigSave();
|
||||
end(); // we call end() here to close the connection to the NVS partition, we
|
||||
// only do this because we call ESP.restart() next.
|
||||
OpenIrisTasks::ScheduleRestart(2000);
|
||||
deviceModeConfigSave();
|
||||
end(); // we call end() here to close the connection to the NVS partition
|
||||
// Removed automatic restart to allow explicit control via RESTART_DEVICE command
|
||||
// OpenIrisTasks::ScheduleRestart(2000);
|
||||
}
|
||||
|
||||
|
||||
void ProjectConfig::wifiConfigSave() {
|
||||
log_d("Saving wifi config");
|
||||
|
||||
@ -126,6 +134,15 @@ void ProjectConfig::wifiTxPowerConfigSave() {
|
||||
putInt("txpower", this->config.txpower.power);
|
||||
}
|
||||
|
||||
void ProjectConfig::deviceModeConfigSave() {
|
||||
/* Device Mode Config */
|
||||
putInt(MODE_KEY, static_cast<int>(this->config.deviceMode.mode));
|
||||
putBool(HAS_WIFI_CREDS_KEY, this->config.deviceMode.hasWiFiCredentials);
|
||||
log_i("[ProjectConfig] Device mode config saved: mode=%d, hasWiFiCredentials=%d",
|
||||
static_cast<int>(this->config.deviceMode.mode),
|
||||
this->config.deviceMode.hasWiFiCredentials);
|
||||
}
|
||||
|
||||
void ProjectConfig::cameraConfigSave() {
|
||||
/* Camera Config */
|
||||
putInt("vflip", this->config.camera.vflip);
|
||||
@ -204,6 +221,18 @@ void ProjectConfig::load() {
|
||||
this->config.camera.framesize = getInt("framesize", (uint8_t)CAM_RESOLUTION);
|
||||
this->config.camera.quality = getInt("quality", 7);
|
||||
this->config.camera.brightness = getInt("brightness", 2);
|
||||
|
||||
int savedMode = getInt(MODE_KEY, static_cast<int>(DeviceMode::AUTO_MODE));
|
||||
this->config.deviceMode.mode = static_cast<DeviceMode>(savedMode);
|
||||
this->config.deviceMode.hasWiFiCredentials = getBool(HAS_WIFI_CREDS_KEY, false);
|
||||
|
||||
if (this->config.deviceMode.mode == DeviceMode::AUTO_MODE) {
|
||||
this->config.deviceMode.mode = determineMode();
|
||||
}
|
||||
|
||||
log_i("[ProjectConfig] Loaded device mode: %d, hasWiFiCredentials: %d",
|
||||
static_cast<int>(this->config.deviceMode.mode),
|
||||
this->config.deviceMode.hasWiFiCredentials);
|
||||
|
||||
this->_already_loaded = true;
|
||||
this->notifyAll(ConfigState_e::configLoaded);
|
||||
@ -419,6 +448,14 @@ std::string ProjectConfig::WiFiTxPower_t::toRepresentation() {
|
||||
return json;
|
||||
}
|
||||
|
||||
std::string ProjectConfig::DeviceModeConfig_t::toRepresentation() {
|
||||
std::string json = Helpers::format_string(
|
||||
"\"device_mode\": {\"mode\": %d, \"hasWiFiCredentials\": %s}",
|
||||
static_cast<int>(this->mode),
|
||||
this->hasWiFiCredentials ? "true" : "false");
|
||||
return json;
|
||||
}
|
||||
|
||||
//**********************************************************************************************************************
|
||||
//*
|
||||
//! Get Methods
|
||||
@ -443,3 +480,32 @@ ProjectConfig::MDNSConfig_t& ProjectConfig::getMDNSConfig() {
|
||||
ProjectConfig::WiFiTxPower_t& ProjectConfig::getWiFiTxPowerConfig() {
|
||||
return this->config.txpower;
|
||||
}
|
||||
|
||||
ProjectConfig::DeviceModeConfig_t& ProjectConfig::getDeviceModeConfig() {
|
||||
return this->config.deviceMode;
|
||||
}
|
||||
|
||||
void ProjectConfig::setDeviceMode(DeviceMode mode, bool shouldNotify) {
|
||||
this->config.deviceMode.mode = mode;
|
||||
putInt(MODE_KEY, static_cast<int>(mode));
|
||||
log_i("[ProjectConfig] Mode set to: %d", static_cast<int>(mode));
|
||||
|
||||
if (shouldNotify) {
|
||||
this->notifyAll(ConfigState_e::deviceModeUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectConfig::setHasWiFiCredentials(bool hasCredentials, bool shouldNotify) {
|
||||
this->config.deviceMode.hasWiFiCredentials = hasCredentials;
|
||||
putBool(HAS_WIFI_CREDS_KEY, hasCredentials);
|
||||
log_i("[ProjectConfig] WiFi credentials status set to: %d", hasCredentials);
|
||||
|
||||
if (shouldNotify) {
|
||||
this->notifyAll(ConfigState_e::deviceModeUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
DeviceMode ProjectConfig::determineMode() {
|
||||
// If WiFi credentials are saved, use WiFi mode, otherwise use AP mode
|
||||
return this->config.deviceMode.hasWiFiCredentials ? DeviceMode::WIFI_MODE : DeviceMode::AP_MODE;
|
||||
}
|
||||
|
@ -13,6 +13,14 @@
|
||||
#include "data/utilities/network_utilities.hpp"
|
||||
#include "tasks/tasks.hpp"
|
||||
|
||||
// Enum to represent the device operating mode
|
||||
enum class DeviceMode {
|
||||
USB_MODE, // Device operates in USB mode only
|
||||
WIFI_MODE, // Device operates in WiFi mode only
|
||||
AP_MODE, // Device operates in AP mode with serial commands enabled
|
||||
AUTO_MODE // Device automatically selects mode based on saved credentials
|
||||
};
|
||||
|
||||
class ProjectConfig : public Preferences, public ISubject<ConfigState_e> {
|
||||
public:
|
||||
ProjectConfig(const std::string& name = std::string(),
|
||||
@ -88,6 +96,12 @@ class ProjectConfig : public Preferences, public ISubject<ConfigState_e> {
|
||||
std::string toRepresentation();
|
||||
};
|
||||
|
||||
struct DeviceModeConfig_t {
|
||||
DeviceMode mode;
|
||||
bool hasWiFiCredentials;
|
||||
std::string toRepresentation();
|
||||
};
|
||||
|
||||
struct TrackerConfig_t {
|
||||
DeviceConfig_t device;
|
||||
CameraConfig_t camera;
|
||||
@ -95,6 +109,7 @@ class ProjectConfig : public Preferences, public ISubject<ConfigState_e> {
|
||||
AP_WiFiConfig_t ap_network;
|
||||
MDNSConfig_t mdns;
|
||||
WiFiTxPower_t txpower;
|
||||
DeviceModeConfig_t deviceMode;
|
||||
};
|
||||
|
||||
DeviceConfig_t& getDeviceConfig();
|
||||
@ -103,6 +118,7 @@ class ProjectConfig : public Preferences, public ISubject<ConfigState_e> {
|
||||
AP_WiFiConfig_t& getAPWifiConfig();
|
||||
MDNSConfig_t& getMDNSConfig();
|
||||
WiFiTxPower_t& getWiFiTxPowerConfig();
|
||||
DeviceModeConfig_t& getDeviceModeConfig();
|
||||
|
||||
void setDeviceConfig(const std::string& OTALogin,
|
||||
const std::string& OTAPassword,
|
||||
@ -132,12 +148,24 @@ class ProjectConfig : public Preferences, public ISubject<ConfigState_e> {
|
||||
void setWiFiTxPower(uint8_t power, bool shouldNotify);
|
||||
|
||||
void deleteWifiConfig(const std::string& networkName, bool shouldNotify);
|
||||
|
||||
void setDeviceMode(DeviceMode mode, bool shouldNotify);
|
||||
|
||||
void setHasWiFiCredentials(bool hasCredentials, bool shouldNotify);
|
||||
|
||||
DeviceMode determineMode();
|
||||
|
||||
void deviceModeConfigSave();
|
||||
|
||||
private:
|
||||
TrackerConfig_t config;
|
||||
std::string _name;
|
||||
std::string _mdnsName;
|
||||
bool _already_loaded;
|
||||
|
||||
// Device mode related constants
|
||||
const char* MODE_KEY = "mode";
|
||||
const char* HAS_WIFI_CREDS_KEY = "has_wifi_creds";
|
||||
};
|
||||
|
||||
#endif // PROJECT_CONFIG_HPP
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "SerialManager.hpp"
|
||||
#include "data/DeviceMode/DeviceMode.hpp"
|
||||
|
||||
SerialManager::SerialManager(CommandManager* commandManager)
|
||||
: commandManager(commandManager) {}
|
||||
@ -20,7 +19,8 @@ void SerialManager::sendQuery(QueryAction action,
|
||||
}
|
||||
|
||||
void SerialManager::checkUSBMode() {
|
||||
DeviceMode currentMode = DeviceModeManager::getInstance()->getMode();
|
||||
// Get device mode from ProjectConfig via CommandManager
|
||||
DeviceMode currentMode = this->commandManager->getDeviceConfig()->getDeviceModeConfig().mode;
|
||||
if (currentMode == DeviceMode::USB_MODE) {
|
||||
log_i("[SerialManager] USB mode active - auto-streaming enabled");
|
||||
|
||||
@ -99,8 +99,7 @@ void SerialManager::run() {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we're in USB mode and automatically send frames
|
||||
DeviceMode currentMode = DeviceModeManager::getInstance()->getMode();
|
||||
DeviceMode currentMode = this->commandManager->getDeviceConfig()->getDeviceModeConfig().mode;
|
||||
if (currentMode == DeviceMode::USB_MODE) {
|
||||
this->send_frame();
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ void BaseAPI::begin() {
|
||||
|
||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
|
||||
|
||||
// The restart_device endpoint has been removed in favor of using rebootDevice through POST
|
||||
|
||||
// std::bind(&BaseAPI::notFound, &std::placeholders::_1);
|
||||
server.onNotFound([&](AsyncWebServerRequest* request) { notFound(request); });
|
||||
}
|
||||
@ -214,7 +216,15 @@ void BaseAPI::rebootDevice(AsyncWebServerRequest* request) {
|
||||
switch (_networkMethodsMap_enum[request->method()]) {
|
||||
case GET: {
|
||||
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Rebooting Device\"}");
|
||||
|
||||
OpenIrisTasks::ScheduleRestart(2000);
|
||||
break;
|
||||
}
|
||||
case POST: {
|
||||
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Rebooting Device\"}");
|
||||
|
||||
OpenIrisTasks::ScheduleRestart(2000);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
|
||||
@ -381,7 +391,7 @@ void BaseAPI::beginOTA() {
|
||||
esp_camera_deinit(); // deinitialize the camera driver
|
||||
digitalWrite(PWDN_GPIO_NUM, HIGH); // turn power off to camera module
|
||||
|
||||
AsyncWebServerResponse* response = request->beginResponse_P(
|
||||
AsyncWebServerResponse* response = request->beginResponse(
|
||||
200, "text/html", ELEGANT_HTML, ELEGANT_HTML_SIZE);
|
||||
response->addHeader("Content-Encoding", "gzip");
|
||||
request->send(response);
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <WiFi.h>
|
||||
#include "data/StateManager/StateManager.hpp"
|
||||
#include "data/utilities/helpers.hpp"
|
||||
#include "data/DeviceMode/DeviceMode.hpp"
|
||||
|
||||
WiFiHandler::WiFiHandler(ProjectConfig& configManager,
|
||||
const std::string& ssid,
|
||||
@ -93,7 +92,6 @@ void WiFiHandler::begin() {
|
||||
void WiFiHandler::adhoc(const std::string& ssid,
|
||||
uint8_t channel,
|
||||
const std::string& password) {
|
||||
|
||||
wifiStateManager.setState(WiFiState_e::WiFiState_ADHOC);
|
||||
|
||||
log_i("\n[INFO]: Configuring access point...\n");
|
||||
@ -173,8 +171,7 @@ bool WiFiHandler::iniSTA(const std::string& ssid,
|
||||
log_d("Progress: %d \n\r", progress);
|
||||
|
||||
// Check if mode has been changed to USB mode during connection attempt
|
||||
DeviceModeManager* deviceModeManager = DeviceModeManager::getInstance();
|
||||
if (deviceModeManager && deviceModeManager->getMode() == DeviceMode::USB_MODE) {
|
||||
if (configManager.getDeviceModeConfig().mode == DeviceMode::USB_MODE) {
|
||||
log_i("[WiFiHandler] Mode changed to USB during connection, aborting WiFi setup");
|
||||
WiFi.disconnect(true);
|
||||
wifiStateManager.setState(WiFiState_e::WiFiState_Disconnected);
|
||||
@ -182,7 +179,7 @@ bool WiFiHandler::iniSTA(const std::string& ssid,
|
||||
}
|
||||
|
||||
if (Serial.available()) {
|
||||
yield();
|
||||
yield(); // Allow other processes to run
|
||||
}
|
||||
|
||||
if ((currentMillis - startingMillis) >= connectionTimeout) {
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <openiris.hpp>
|
||||
#include "data/DeviceMode/DeviceMode.hpp"
|
||||
/**
|
||||
* @brief ProjectConfig object
|
||||
* @brief This is the main configuration object for the project
|
||||
@ -40,8 +39,7 @@ StreamServer streamServer;
|
||||
|
||||
void etvr_eye_tracker_web_init() {
|
||||
// Check if mode has been changed to USB mode before starting network initialization
|
||||
DeviceModeManager* deviceModeManager = DeviceModeManager::getInstance();
|
||||
if (deviceModeManager && deviceModeManager->getMode() == DeviceMode::USB_MODE) {
|
||||
if (deviceConfig.getDeviceModeConfig().mode == DeviceMode::USB_MODE) {
|
||||
log_i("[SETUP]: Mode changed to USB before network initialization, aborting");
|
||||
WiFi.disconnect(true);
|
||||
return;
|
||||
@ -51,7 +49,7 @@ void etvr_eye_tracker_web_init() {
|
||||
deviceConfig.attach(mdnsHandler);
|
||||
|
||||
// Check mode again before starting WiFi
|
||||
if (deviceModeManager && deviceModeManager->getMode() == DeviceMode::USB_MODE) {
|
||||
if (deviceConfig.getDeviceModeConfig().mode == DeviceMode::USB_MODE) {
|
||||
log_i("[SETUP]: Mode changed to USB before WiFi initialization, aborting");
|
||||
WiFi.disconnect(true);
|
||||
return;
|
||||
@ -61,7 +59,7 @@ void etvr_eye_tracker_web_init() {
|
||||
wifiHandler.begin();
|
||||
|
||||
// Check mode again before starting MDNS
|
||||
if (deviceModeManager && deviceModeManager->getMode() == DeviceMode::USB_MODE) {
|
||||
if (deviceConfig.getDeviceModeConfig().mode == DeviceMode::USB_MODE) {
|
||||
log_i("[SETUP]: Mode changed to USB before MDNS initialization, aborting");
|
||||
WiFi.disconnect(true);
|
||||
return;
|
||||
@ -111,8 +109,7 @@ void setup() {
|
||||
Logo::printASCII();
|
||||
ledManager.begin();
|
||||
|
||||
DeviceModeManager::createInstance();
|
||||
DeviceModeManager* deviceModeManager = DeviceModeManager::getInstance();
|
||||
// Device mode is now managed by ProjectConfig
|
||||
|
||||
#ifdef CONFIG_CAMERA_MODULE_SWROOM_BABBLE_S3 // Set IR emitter strength to 100%.
|
||||
const int ledPin = 1; // Replace this with a command endpoint eventually.
|
||||
@ -132,7 +129,7 @@ void setup() {
|
||||
|
||||
serialManager.init();
|
||||
|
||||
DeviceMode currentMode = deviceModeManager->getMode();
|
||||
DeviceMode currentMode = deviceConfig.getDeviceModeConfig().mode;
|
||||
|
||||
if (currentMode == DeviceMode::WIFI_MODE) {
|
||||
// Initialize WiFi mode
|
||||
|
@ -14,6 +14,7 @@ class OpenIrisModeTester:
|
||||
self.serial_conn = None
|
||||
self.device_ip = None
|
||||
self.device_port = None
|
||||
self.last_boot_time = None
|
||||
|
||||
def connect_serial(self):
|
||||
try:
|
||||
@ -101,61 +102,267 @@ class OpenIrisModeTester:
|
||||
except Exception as e:
|
||||
print(f"Error testing WiFi API: {e}")
|
||||
return False
|
||||
|
||||
def restart_device_serial(self):
|
||||
"""Send reboot command via serial connection"""
|
||||
command = {"commands": [{"command": "restart_device"}]}
|
||||
print("Sending reboot command via serial...")
|
||||
response = self.send_command(command)
|
||||
print(f"Response: {response}")
|
||||
self.last_boot_time = time.time()
|
||||
|
||||
# Close the serial connection after sending reboot command
|
||||
# This helps prevent permission issues when reconnecting
|
||||
if self.serial_conn and self.serial_conn.is_open:
|
||||
try:
|
||||
self.serial_conn.close()
|
||||
print("Serial connection closed after reboot command")
|
||||
except Exception as e:
|
||||
print(f"Error closing serial connection: {e}")
|
||||
|
||||
return response
|
||||
|
||||
def restart_device_wifi(self):
|
||||
"""Send reboot command via WiFi API"""
|
||||
if not self.device_ip:
|
||||
print("Device IP not available. Cannot restart via WiFi.")
|
||||
return False
|
||||
|
||||
try:
|
||||
# First verify the device is responsive via WiFi
|
||||
ping_url = f"http://{self.device_ip}:81/control/builtin/command/ping"
|
||||
print(f"Testing device responsiveness with: {ping_url}")
|
||||
ping_response = requests.get(ping_url, timeout=5)
|
||||
if ping_response.status_code != 200:
|
||||
print(f"Device not responsive via WiFi before restart attempt: {ping_response.status_code}")
|
||||
return False
|
||||
|
||||
# Use rebootDevice endpoint with POST method
|
||||
url = f"http://{self.device_ip}:81/update/rebootDevice"
|
||||
print(f"Sending reboot command to: {url}")
|
||||
|
||||
# Use POST method as recommended
|
||||
try:
|
||||
response = requests.post(url, timeout=5)
|
||||
if response.status_code == 200:
|
||||
print("Reboot command via WiFi (POST) sent successfully!")
|
||||
self.last_boot_time = time.time()
|
||||
return True
|
||||
else:
|
||||
print(f"Reboot command via WiFi (POST) failed with status code: {response.status_code}")
|
||||
return False
|
||||
except requests.exceptions.ConnectionError:
|
||||
print("Connection error during POST: Device may have already started restarting")
|
||||
self.last_boot_time = time.time()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error sending POST reboot command: {e}")
|
||||
return False
|
||||
except requests.exceptions.ConnectionError:
|
||||
print("Connection error: Device may have already started restarting")
|
||||
self.last_boot_time = time.time()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error sending reboot command via WiFi: {e}")
|
||||
return False
|
||||
|
||||
def verify_restart(self, wait_time=60, retry_count=3):
|
||||
"""Verify that the device has rebooted by checking uptime"""
|
||||
if not self.last_boot_time:
|
||||
print("No reboot command was previously sent")
|
||||
return False
|
||||
|
||||
# Calculate elapsed time since reboot command
|
||||
elapsed = time.time() - self.last_boot_time
|
||||
if elapsed < wait_time:
|
||||
# Wait remaining time if needed
|
||||
remaining = wait_time - elapsed
|
||||
print(f"Waiting {remaining:.1f} more seconds for device to reboot...")
|
||||
time.sleep(remaining)
|
||||
else:
|
||||
print(f"Already waited {elapsed:.1f} seconds since reboot command")
|
||||
|
||||
# Close the serial connection before attempting to reconnect
|
||||
if self.serial_conn and self.serial_conn.is_open:
|
||||
try:
|
||||
self.serial_conn.close()
|
||||
time.sleep(1) # Give the OS time to release the port
|
||||
except Exception as e:
|
||||
print(f"Error closing serial connection: {e}")
|
||||
|
||||
# Try to reconnect serial with retries
|
||||
for attempt in range(retry_count):
|
||||
try:
|
||||
if self.connect_serial():
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"Error during reconnection attempt {attempt+1}: {e}")
|
||||
|
||||
if attempt < retry_count - 1:
|
||||
print(f"Reconnection attempt {attempt+1} failed, retrying in 2 seconds...")
|
||||
time.sleep(2)
|
||||
else:
|
||||
print(f"Failed to reconnect to device after {retry_count} attempts")
|
||||
return False
|
||||
|
||||
# Send ping command to check if device is responsive
|
||||
for attempt in range(retry_count):
|
||||
ping_command = {"commands": [{"command": "ping"}]}
|
||||
response = self.send_command(ping_command)
|
||||
|
||||
if response and "pong" in response.lower():
|
||||
print(f"Device responded after restart (attempt {attempt+1})")
|
||||
return True
|
||||
elif attempt < retry_count - 1:
|
||||
print(f"Ping attempt {attempt+1} failed, retrying in 2 seconds...")
|
||||
time.sleep(2)
|
||||
|
||||
print(f"Device did not respond properly after {retry_count} ping attempts")
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
if self.serial_conn and self.serial_conn.is_open:
|
||||
self.serial_conn.close()
|
||||
|
||||
|
||||
def run_test(port, ssid, password):
|
||||
def run_test(port, ssid, password, wait_time=15, retry_count=3, skip_wifi_test=False):
|
||||
tester = OpenIrisModeTester(port)
|
||||
test_results = {
|
||||
"serial_connection": False,
|
||||
"wifi_credentials": False,
|
||||
"device_discovery": False,
|
||||
"wifi_api": False,
|
||||
"serial_restart": False,
|
||||
"wifi_restart": False,
|
||||
"usb_mode": False
|
||||
}
|
||||
|
||||
try:
|
||||
print("\n=== Step 1: Testing Serial Connection ===")
|
||||
if not tester.connect_serial():
|
||||
return
|
||||
print("❌ Serial connection failed. Aborting test.")
|
||||
return test_results
|
||||
test_results["serial_connection"] = True
|
||||
print("✅ Serial connection successful")
|
||||
|
||||
print("\n=== Step 1: Setting WiFi credentials ===")
|
||||
tester.set_wifi_credentials(ssid, password)
|
||||
print("Device will restart. Waiting 10 seconds...")
|
||||
time.sleep(10)
|
||||
print("\n=== Step 2: Setting WiFi credentials ===")
|
||||
response = tester.set_wifi_credentials(ssid, password)
|
||||
if response and "error" not in response.lower():
|
||||
test_results["wifi_credentials"] = True
|
||||
print("✅ WiFi credentials set successfully")
|
||||
|
||||
# Explicitly send reboot command after setting WiFi credentials
|
||||
print("Sending reboot command after setting WiFi credentials...")
|
||||
tester.restart_device_serial()
|
||||
|
||||
# Wait specifically 30 seconds for the device to restart
|
||||
print("Waiting 30 seconds for device to restart...")
|
||||
time.sleep(30)
|
||||
else:
|
||||
print("❌ Failed to set WiFi credentials")
|
||||
|
||||
# Verify device reboots after setting WiFi credentials
|
||||
if not tester.verify_restart(wait_time=wait_time, retry_count=retry_count):
|
||||
print("❌ Device did not reboot properly after setting WiFi credentials")
|
||||
else:
|
||||
print("✅ Device rebooted successfully after setting WiFi credentials")
|
||||
|
||||
tester.connect_serial()
|
||||
print("\n=== Step 3: Discovering device on network ===")
|
||||
if tester.discover_device():
|
||||
test_results["device_discovery"] = True
|
||||
print("✅ Device discovered on network")
|
||||
|
||||
print("\n=== Step 4: Testing WiFi API ===")
|
||||
if tester.test_wifi_api():
|
||||
test_results["wifi_api"] = True
|
||||
print("✅ WiFi API test successful")
|
||||
|
||||
print("\n=== Step 5: Testing reboot via WiFi ===")
|
||||
if tester.restart_device_wifi():
|
||||
# Wait for device to reboot
|
||||
if tester.verify_restart(wait_time=wait_time, retry_count=retry_count):
|
||||
test_results["wifi_restart"] = True
|
||||
print("✅ Device rebooted successfully via WiFi")
|
||||
else:
|
||||
print("❌ Device did not reboot properly via WiFi")
|
||||
else:
|
||||
print("❌ Failed to send reboot command via WiFi")
|
||||
else:
|
||||
print("❌ WiFi API test failed")
|
||||
else:
|
||||
print("❌ Failed to discover device on network")
|
||||
|
||||
# Reconnect serial if needed
|
||||
if not tester.serial_conn or not tester.serial_conn.is_open:
|
||||
tester.connect_serial()
|
||||
tester.flush_serial_logs()
|
||||
|
||||
print("\n=== Step 2: Discovering device on network ===")
|
||||
if tester.discover_device():
|
||||
print("\n=== Step 3: Testing WiFi API ===")
|
||||
tester.test_wifi_api()
|
||||
print("\n=== Step 6: Testing reboot via Serial ===")
|
||||
tester.restart_device_serial()
|
||||
if tester.verify_restart(wait_time=wait_time, retry_count=retry_count):
|
||||
test_results["serial_restart"] = True
|
||||
print("✅ Device rebooted successfully via Serial")
|
||||
else:
|
||||
print("❌ Device did not reboot properly via Serial")
|
||||
|
||||
tester.flush_serial_logs()
|
||||
print("\n=== Step 7: Wiping WiFi credentials ===")
|
||||
tester.wipe_wifi_credentials()
|
||||
if not tester.verify_restart(wait_time=wait_time, retry_count=retry_count):
|
||||
print("❌ Device did not reboot properly after wiping WiFi credentials")
|
||||
else:
|
||||
print("✅ Device rebooted successfully after wiping WiFi credentials")
|
||||
|
||||
print("\n=== Step 4: Wiping WiFi credentials ===")
|
||||
tester.wipe_wifi_credentials()
|
||||
print("Device will restart in USB mode. Waiting 10 seconds...")
|
||||
time.sleep(10)
|
||||
print("\n=== Step 8: Verifying USB mode ===")
|
||||
ping_command = {"commands": [{"command": "ping"}]}
|
||||
response = tester.send_command(ping_command)
|
||||
if response and "pong" in response.lower():
|
||||
test_results["usb_mode"] = True
|
||||
print("✅ Device is in USB mode")
|
||||
else:
|
||||
print("❌ Failed to verify USB mode")
|
||||
|
||||
tester.connect_serial()
|
||||
tester.flush_serial_logs()
|
||||
tester.flush_serial_logs()
|
||||
|
||||
# Print summary
|
||||
print("\n=== Test Summary ===")
|
||||
for test, result in test_results.items():
|
||||
status = "✅ PASS" if result else "❌ FAIL"
|
||||
print(f"{test.replace('_', ' ').title()}: {status}")
|
||||
|
||||
print("\n=== Step 5: Verifying USB mode ===")
|
||||
ping_command = {"commands": [{"command": "ping"}]}
|
||||
print("Device is most likely booting, waiting 10 seconds...")
|
||||
time.sleep(10)
|
||||
|
||||
response = tester.send_command(ping_command)
|
||||
print(f"Response: {response}")
|
||||
|
||||
tester.flush_serial_logs()
|
||||
return test_results
|
||||
|
||||
finally:
|
||||
tester.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Test OpenIris mode switching functionality")
|
||||
parser = argparse.ArgumentParser(description="Test OpenIris mode switching and reboot functionality")
|
||||
parser.add_argument("--port", required=True, help="Serial port (e.g., COM3 or /dev/ttyUSB0)")
|
||||
parser.add_argument("--ssid", required=True, help="WiFi SSID")
|
||||
parser.add_argument("--password", required=True, help="WiFi password")
|
||||
parser.add_argument("--wait-time", type=int, default=60, help="Wait time in seconds for device reboot (default: 15)")
|
||||
parser.add_argument("--retry-count", type=int, default=3, help="Number of retry attempts for reconnection (default: 3)")
|
||||
parser.add_argument("--skip-wifi-test", action="store_true", help="Skip WiFi-related tests")
|
||||
|
||||
args = parser.parse_args()
|
||||
run_test(args.port, args.ssid, args.password)
|
||||
|
||||
# Configure test parameters
|
||||
test_config = {
|
||||
"port": args.port,
|
||||
"ssid": args.ssid,
|
||||
"password": args.password,
|
||||
"wait_time": args.wait_time,
|
||||
"retry_count": args.retry_count,
|
||||
"skip_wifi_test": args.skip_wifi_test
|
||||
}
|
||||
|
||||
# Run the test and get results
|
||||
results = run_test(**test_config)
|
||||
|
||||
# Exit with appropriate status code
|
||||
if all(results.values()):
|
||||
print("\n✅ All tests passed successfully!")
|
||||
exit(0)
|
||||
else:
|
||||
print("\n❌ Some tests failed. See details above.")
|
||||
exit(1)
|
Loading…
Reference in New Issue
Block a user