Move REST API poll and led manager state display to tasks, beginng led manager refactor

This commit is contained in:
Lorow
2025-04-19 16:28:10 +02:00
parent b3354935fa
commit a580d0f097
7 changed files with 143 additions and 125 deletions
+79 -83
View File
@@ -2,50 +2,44 @@
const char *LED_MANAGER_TAG = "[LED_MANAGER]"; const char *LED_MANAGER_TAG = "[LED_MANAGER]";
LEDManager::ledStateMap_t LEDManager::ledStateMap = { // todo rethink the patterns
{LEDStates_e::_LedStateNone, {{0, 500}}}, ledStateMap_t LEDManager::ledStateMap = {
{LEDStates_e::_Improv_Error, {LEDStates_e::_LedStateNone, {{LED_OFF, 500}}},
{{1, 1000}, {0, 500}, {0, 1000}, {0, 500}, {1, 1000}}}, {LEDStates_e::_LedStateStreaming, {{LED_ON, 500}}},
{LEDStates_e::_Improv_Start, {LEDStates_e::_LedStateStoppedStreaming, {{LED_OFF, 500}}},
{{1, 500}, {0, 300}, {0, 300}, {0, 300}, {1, 500}}},
{LEDStates_e::_Improv_Stop,
{{1, 300}, {0, 500}, {0, 500}, {0, 500}, {1, 300}}},
{LEDStates_e::_Improv_Processing,
{{1, 200}, {0, 100}, {0, 500}, {0, 100}, {1, 200}}},
{LEDStates_e::_WebServerState_Error, {LEDStates_e::_WebServerState_Error,
{{1, 200}, {0, 100}, {0, 500}, {0, 100}, {1, 200}}}, {{LED_ON, 200}, {LED_OFF, 100}, {LED_ON, 200}, {LED_OFF, 100}, {LED_ON, 200}}},
{LEDStates_e::_WiFiState_Error, {LEDStates_e::_WiFiState_Error,
{{1, 200}, {0, 100}, {0, 500}, {0, 100}, {1, 200}}}, {{LED_ON, 200}, {LED_OFF, 100}, {LED_ON, 500}, {LED_OFF, 100}, {LED_ON, 200}}},
{LEDStates_e::_MDNSState_Error, {LEDStates_e::_MDNSState_Error,
{{1, 200}, {{LED_ON, 200},
{0, 100}, {0, 100},
{1, 200}, {LED_ON, 200},
{0, 100}, {0, 100},
{0, 500}, {LED_ON, 500},
{0, 100}, {0, 100},
{1, 200}, {LED_ON, 200},
{0, 100}, {0, 100},
{1, 200}}}, {LED_ON, 200}}},
// lmao no, rethink this
{LEDStates_e::_Camera_Error, {LEDStates_e::_Camera_Error,
{{1, 5000}}}, // this also works as a more general error - something went {{LED_ON, 5000}}}, // this also works as a more general error - something went
// critically wrong? We go here // critically wrong? We go here
{LEDStates_e::_WiFiState_Connecting, {{1, 100}, {0, 100}}}, {LEDStates_e::_WiFiState_Connecting, {{1, 100}, {0, 100}}},
{LEDStates_e::_WiFiState_Connected, {LEDStates_e::_WiFiState_Connected,
{{1, 100}, {{LED_ON, 100},
{0, 100}, {0, 100},
{1, 100}, {LED_ON, 100},
{0, 100}, {0, 100},
{1, 100}, {LED_ON, 100},
{0, 100}, {0, 100},
{1, 100}, {LED_ON, 100},
{0, 100}, {0, 100},
{1, 100}, {LED_ON, 100},
{0, 100}}}}; {0, 100}}}};
std::vector<LEDStates_e> LEDManager::keepAliveStates = { LEDManager::LEDManager(gpio_num_t pin, gpio_num_t illumninator_led_pin, QueueHandle_t ledStateQueue) : blink_led_pin(pin), illumninator_led_pin(illumninator_led_pin), ledStateQueue(ledStateQueue) {}
LEDStates_e::_WebServerState_Error, LEDStates_e::_Camera_Error};
LEDManager::LEDManager(gpio_num_t pin, gpio_num_t illumninator_led_pin) : blink_led_pin(pin), illumninator_led_pin(illumninator_led_pin), state(false) {}
void LEDManager::setup() void LEDManager::setup()
{ {
@@ -53,13 +47,7 @@ void LEDManager::setup()
gpio_reset_pin(blink_led_pin); gpio_reset_pin(blink_led_pin);
/* Set the GPIO as a push/pull output */ /* Set the GPIO as a push/pull output */
gpio_set_direction(blink_led_pin, GPIO_MODE_OUTPUT); gpio_set_direction(blink_led_pin, GPIO_MODE_OUTPUT);
// the defualt state is _LedStateNone so we're fine this->toggleLED(LED_OFF);
this->currentState = ledStateManager.getCurrentState();
this->currentPatternIndex = 0;
BlinkPatterns_t pattern =
this->ledStateMap[this->currentState][this->currentPatternIndex];
this->toggleLED(pattern.state);
this->nextStateChangeMillis = pattern.delayTime;
#ifdef CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL #ifdef CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL
ESP_LOGD(LED_MANAGER_TAG, "Setting up illuminator led."); ESP_LOGD(LED_MANAGER_TAG, "Setting up illuminator led.");
@@ -90,59 +78,55 @@ void LEDManager::setup()
ESP_LOGD(LED_MANAGER_TAG, "Done."); ESP_LOGD(LED_MANAGER_TAG, "Done.");
} }
/** // todo - rethink how it should work with a queue and vtaskdelay
* @brief Display the current state of the LED manager as a pattern of blinking
* LED
* @details This function must be called in the main loop
*/
void LEDManager::handleLED() void LEDManager::handleLED()
{ {
if (Helpers::getTimeInMillis() <= this->nextStateChangeMillis) // if (Helpers::getTimeInMillis() <= this->nextStateChangeMillis)
{ // {
return; // return;
} // }
// !TODO what if we want a looping state? Or a state that needs to stay // // !TODO what if we want a looping state? Or a state that needs to stay
// bright? Am overthinking this, aren't I? // // bright? Am overthinking this, aren't I? I was not.
// we've reached the timeout on that state, check if we can grab next one and // // we've reached the timeout on that state, check if we can grab next one and
// start displaying it, or if we need to keep displaying the current one // // start displaying it, or if we need to keep displaying the current one
if (this->currentPatternIndex > // if (this->currentPatternIndex >
this->ledStateMap[this->currentState].size() - 1) // this->ledStateMap[this->currentState].size() - 1)
{ // {
auto nextState = ledStateManager.getCurrentState(); // auto nextState = ledStateManager.getCurrentState();
// we want to keep displaying the same state only if its an keepAlive one, // // we want to keep displaying the same state only if its an keepAlive one,
// but we should change if the incoming one is also an errours state, maybe // // but we should change if the incoming one is also an errours state, maybe
// more serious one this time <- this may be a bad idea // // more serious one this time <- this may be a bad idea
if ((std::find(this->keepAliveStates.begin(), this->keepAliveStates.end(), // if ((std::find(this->keepAliveStates.begin(), this->keepAliveStates.end(),
this->currentState) != this->keepAliveStates.end() || // this->currentState) != this->keepAliveStates.end() ||
std::find(this->keepAliveStates.begin(), this->keepAliveStates.end(), // std::find(this->keepAliveStates.begin(), this->keepAliveStates.end(),
nextState) != this->keepAliveStates.end()) || // nextState) != this->keepAliveStates.end()) ||
(this->currentState != nextState && // (this->currentState != nextState &&
this->ledStateMap.find(nextState) != this->ledStateMap.end())) // this->ledStateMap.find(nextState) != this->ledStateMap.end()))
{ // {
ESP_LOGD(LED_MANAGER_TAG, "Updating the state and reseting"); // ESP_LOGD(LED_MANAGER_TAG, "Updating the state and reseting");
this->toggleLED(false); // this->toggleLED(false);
this->currentState = nextState; // this->currentState = nextState;
this->currentPatternIndex = 0; // this->currentPatternIndex = 0;
BlinkPatterns_t pattern = // BlinkPatterns_t pattern =
this->ledStateMap[this->currentState][this->currentPatternIndex]; // this->ledStateMap[this->currentState][this->currentPatternIndex];
this->nextStateChangeMillis = Helpers::getTimeInMillis() + pattern.delayTime; // this->nextStateChangeMillis = Helpers::getTimeInMillis() + pattern.delayTime;
return; // return;
} // }
// it wasn't a keepAlive state, nor did we have another one ready, // // it wasn't a keepAlive state, nor did we have another one ready,
// we're done for now // // we're done for now
this->toggleLED(false); // this->toggleLED(false);
return; // return;
} // }
// we can safely advance it and display the next stage // // we can safely advance it and display the next stage
BlinkPatterns_t pattern = // BlinkPatterns_t pattern =
this->ledStateMap[this->currentState][this->currentPatternIndex]; // this->ledStateMap[this->currentState][this->currentPatternIndex];
this->toggleLED(pattern.state); // this->toggleLED(pattern.state);
this->nextStateChangeMillis = Helpers::getTimeInMillis() + pattern.delayTime; // this->nextStateChangeMillis = Helpers::getTimeInMillis() + pattern.delayTime;
ESP_LOGD(LED_MANAGER_TAG, "before updating stage %d", this->currentPatternIndex); // ESP_LOGD(LED_MANAGER_TAG, "before updating stage %d", this->currentPatternIndex);
this->currentPatternIndex++; // this->currentPatternIndex++;
ESP_LOGD(LED_MANAGER_TAG, "updated stage %d", this->currentPatternIndex); // ESP_LOGD(LED_MANAGER_TAG, "updated stage %d", this->currentPatternIndex);
} }
/** /**
@@ -154,3 +138,15 @@ void LEDManager::toggleLED(bool state) const
{ {
gpio_set_level(blink_led_pin, state); gpio_set_level(blink_led_pin, state);
} }
void HandleLEDDisplayTask(void *pvParameter)
{
LEDManager *ledManager = (LEDManager *)pvParameter;
while (1)
{
printf("Hello from a task \n");
printf("The led manager is %d \n", bool(ledManager));
vTaskDelay(100);
}
}
+17 -13
View File
@@ -3,6 +3,8 @@
#define _LEDMANAGER_HPP_ #define _LEDMANAGER_HPP_
#include "driver/gpio.h" #include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#ifdef CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL #ifdef CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL
#include "driver/ledc.h" #include "driver/ledc.h"
@@ -16,10 +18,22 @@
#include <StateManager.hpp> #include <StateManager.hpp>
#include <Helpers.hpp> #include <Helpers.hpp>
// it kinda looks like different boards have these states swapped
#define LED_OFF 1
#define LED_ON 0
struct BlinkPatterns_t
{
int state;
int delayTime;
};
typedef std::unordered_map<LEDStates_e, std::vector<BlinkPatterns_t>> ledStateMap_t;
class LEDManager class LEDManager
{ {
public: public:
LEDManager(gpio_num_t blink_led_pin, gpio_num_t illumninator_led_pin); LEDManager(gpio_num_t blink_led_pin, gpio_num_t illumninator_led_pin, QueueHandle_t ledStateQueue);
void setup(); void setup();
void handleLED(); void handleLED();
@@ -27,23 +41,13 @@ public:
private: private:
gpio_num_t blink_led_pin; gpio_num_t blink_led_pin;
gpio_num_t illumninator_led_pin; gpio_num_t illumninator_led_pin;
QueueHandle_t ledStateQueue;
unsigned long nextStateChangeMillis = 0;
bool state = false;
struct BlinkPatterns_t
{
int state;
int delayTime;
};
typedef std::unordered_map<LEDStates_e, std::vector<BlinkPatterns_t>> ledStateMap_t;
static ledStateMap_t ledStateMap; static ledStateMap_t ledStateMap;
static std::vector<LEDStates_e> keepAliveStates;
LEDStates_e currentState; LEDStates_e currentState;
unsigned int currentPatternIndex = 0;
void toggleLED(bool state) const; void toggleLED(bool state) const;
}; };
void HandleLEDDisplayTask(void *pvParameter);
#endif #endif
+10
View File
@@ -71,6 +71,16 @@ void RestAPI::poll()
mg_mgr_poll(&mgr, 100); mg_mgr_poll(&mgr, 100);
} }
void HandleRestAPIPollTask(void *pvParameter)
{
RestAPI *rest_api_handler = static_cast<RestAPI *>(pvParameter);
while (1)
{
rest_api_handler->poll();
vTaskDelay(1000);
}
}
// COMMANDS // COMMANDS
// updates // updates
void RestAPI::handle_update_wifi(RequestContext *context) void RestAPI::handle_update_wifi(RequestContext *context)
+2
View File
@@ -63,4 +63,6 @@ namespace RestAPIHelpers
void event_handler(struct mg_connection *connection, int event, void *event_data); void event_handler(struct mg_connection *connection, int event, void *event_data);
}; };
void HandleRestAPIPollTask(void *pvParameter);
#endif #endif
@@ -1,7 +1,6 @@
#include "StateManager.hpp" #include "StateManager.hpp"
StateManager<WiFiState_e> wifiStateManager; StateManager<WiFiState_e> wifiStateManager;
StateManager<WebServerState_e> webServerStateManager;
StateManager<MDNSState_e> mdnsStateManager; StateManager<MDNSState_e> mdnsStateManager;
StateManager<CameraState_e> cameraStateManager; StateManager<CameraState_e> cameraStateManager;
StateManager<LEDStates_e> ledStateManager; StateManager<LEDStates_e> ledStateManager;
@@ -10,10 +10,8 @@ struct DeviceStates
enum LEDStates_e enum LEDStates_e
{ {
_LedStateNone, _LedStateNone,
_Improv_Start, _LedStateStreaming,
_Improv_Stop, _LedStateStoppedStreaming,
_Improv_Processing,
_Improv_Error,
_WebServerState_Error, _WebServerState_Error,
_WiFiState_Error, _WiFiState_Error,
_MDNSState_Error, _MDNSState_Error,
@@ -46,15 +44,6 @@ struct DeviceStates
WiFiState_Error WiFiState_Error
}; };
enum WebServerState_e
{
WebServerState_Stopped,
WebServerState_Starting,
WebServerState_Started,
WebServerState_Stopping,
WebServerState_Error
};
enum MDNSState_e enum MDNSState_e
{ {
MDNSState_Stopped, MDNSState_Stopped,
@@ -109,7 +98,6 @@ private:
}; };
typedef DeviceStates::WiFiState_e WiFiState_e; typedef DeviceStates::WiFiState_e WiFiState_e;
typedef DeviceStates::WebServerState_e WebServerState_e;
typedef DeviceStates::MDNSState_e MDNSState_e; typedef DeviceStates::MDNSState_e MDNSState_e;
typedef DeviceStates::CameraState_e CameraState_e; typedef DeviceStates::CameraState_e CameraState_e;
typedef DeviceStates::LEDStates_e LEDStates_e; typedef DeviceStates::LEDStates_e LEDStates_e;
@@ -117,7 +105,6 @@ typedef DeviceStates::StreamState_e StreamState_e;
typedef DeviceStates::ConfigState_e ConfigState_e; typedef DeviceStates::ConfigState_e ConfigState_e;
extern StateManager<WiFiState_e> wifiStateManager; extern StateManager<WiFiState_e> wifiStateManager;
extern StateManager<WebServerState_e> webServerStateManager;
extern StateManager<MDNSState_e> mdnsStateManager; extern StateManager<MDNSState_e> mdnsStateManager;
extern StateManager<CameraState_e> cameraStateManager; extern StateManager<CameraState_e> cameraStateManager;
extern StateManager<LEDStates_e> ledStateManager; extern StateManager<LEDStates_e> ledStateManager;
+32 -12
View File
@@ -2,6 +2,7 @@
#include <string> #include <string>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h" #include "esp_log.h"
#include "sdkconfig.h" #include "sdkconfig.h"
@@ -31,6 +32,8 @@
static const char *TAG = "[MAIN]"; static const char *TAG = "[MAIN]";
QueueHandle_t ledStateQueue = xQueueCreate(10, sizeof(DeviceStates::LEDStates_e));
std::shared_ptr<DependencyRegistry> dependencyRegistry = std::make_unique<DependencyRegistry>(); std::shared_ptr<DependencyRegistry> dependencyRegistry = std::make_unique<DependencyRegistry>();
std::shared_ptr<CommandManager> commandManager = std::make_shared<CommandManager>(dependencyRegistry); std::shared_ptr<CommandManager> commandManager = std::make_shared<CommandManager>(dependencyRegistry);
@@ -44,13 +47,13 @@ MDNSManager mdnsManager(deviceConfig);
std::shared_ptr<CameraManager> cameraHandler = std::make_shared<CameraManager>(deviceConfig); std::shared_ptr<CameraManager> cameraHandler = std::make_shared<CameraManager>(deviceConfig);
StreamServer streamServer(80); StreamServer streamServer(80);
RestAPI restAPI("http://0.0.0.0:81", commandManager); RestAPI *restAPI = new RestAPI("http://0.0.0.0:81", commandManager);
#ifdef CONFIG_WIRED_MODE #ifdef CONFIG_WIRED_MODE
UVCStreamManager uvcStream; UVCStreamManager uvcStream;
#endif #endif
LEDManager ledManager(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO); LEDManager *ledManager = new LEDManager(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO, ledStateQueue);
static void initNVSStorage() static void initNVSStorage()
{ {
@@ -73,7 +76,6 @@ extern "C" void app_main(void)
{ {
dependencyRegistry->registerService<ProjectConfig>(DependencyType::project_config, deviceConfig); dependencyRegistry->registerService<ProjectConfig>(DependencyType::project_config, deviceConfig);
dependencyRegistry->registerService<CameraManager>(DependencyType::camera_manager, cameraHandler); dependencyRegistry->registerService<CameraManager>(DependencyType::camera_manager, cameraHandler);
// uvc plan // uvc plan
// cleanup the logs - done // cleanup the logs - done
// prepare the camera to be initialized with UVC - done? // prepare the camera to be initialized with UVC - done?
@@ -105,6 +107,11 @@ extern "C" void app_main(void)
// here I can decouple the loading, initializing and saving logic from the config class and move // here I can decouple the loading, initializing and saving logic from the config class and move
// that into the separate modules, and have the config class only act as a container // that into the separate modules, and have the config class only act as a container
// rethink led manager - we need to move the state change sending into a queue and rethink the state lighting logic
// also, the entire led manager needs to be moved to a task
// with that, I couuld use vtaskdelayuntil to advance and display states
// and with that, I should rethink how state management works
// port serial manager // port serial manager
// implement OTA stuff, but prepare it for future use // implement OTA stuff, but prepare it for future use
// add endpoint to check firmware version // add endpoint to check firmware version
@@ -118,23 +125,36 @@ extern "C" void app_main(void)
Logo::printASCII(); Logo::printASCII();
initNVSStorage(); initNVSStorage();
esp_log_set_vprintf(&test_log); // esp_log_set_vprintf(&test_log);
ledManager.setup(); ledManager->setup();
xTaskCreate(
HandleLEDDisplayTask,
"HandleLEDDisplayTask",
1024 * 2,
ledManager,
3,
NULL // // it's fine for us not get a handle back, we don't need it
);
deviceConfig->load(); deviceConfig->load();
wifiManager.Begin(); wifiManager.Begin();
mdnsManager.start(); mdnsManager.start();
restAPI.begin(); restAPI->begin();
cameraHandler->setupCamera(); cameraHandler->setupCamera();
// make sure the server runs on a separate core // make sure the server runs on a separate core
streamServer.startStreamServer(); streamServer.startStreamServer();
xTaskCreate(
HandleRestAPIPollTask,
"HandleRestAPIPollTask",
1024 * 2,
restAPI,
1, // it's the rest API, we only serve commands over it so we don't really need a higher priority
NULL // // it's fine for us not get a handle back, we don't need iti
);
#ifdef CONFIG_WIRED_MODE #ifdef CONFIG_WIRED_MODE
uvcStream.setup(); uvcStream.setup();
#endif #endif
while (1)
{
ledManager.handleLED();
restAPI.poll();
vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
}
} }