feat: Code cleanup and initial implementation of improv

* feat: add improv

- add version to build flags
- add improv
- remove byte pointers from config calls

* ´fix: improve not initilizing in ADHOC mode

* feat: add wifihandler to observers

* refactor: move improv handler to top of loop

* refactor: minor refactor to callback

* refactor: minor refactor to callback

* refactor: trying to weed out the timeout issue

* refactor: trying to weed out the timeout issue

* refactor: total refactor to clean up code

-  clean up statemanagers
- fix observer
- fix bugs introducted by fixing the observer

BREAKING CHANGES

* refactor: minor logging refactor

* fix: add config save to delete method

* fix: improv provisioning error

* refactor: simplify library interface

- implement pass by reference for all objects
- implement get by reference for all objects
- remove passing state to classes
- migrate to range based for loops

BREAKING CHANGES

* fix: esp crash on wifi updates

- figure out why esp crashes sometimes when wifi config changes

* fix: add warning about clang-format to baseAPI.hpp

* refactor: update improv

* ci(ci-test): setup prerelease

- use ci to merge binaries for testing in etvr app

* fix: compile time error

* fix: compile time error

* fix folder names

* fix folder names

* fix: compile time error

* fix: compile time error

* feat: remove improv from main

- keep improv code, incase we fix issue later on
- comment out improv includes

* fix: remove pre-release from release cycle

* fix: resolve wifiState manager state in config

* fix: file name casing

* fix: file name casing

* feat: add custom string_view header

- it is the intention to implement string_view
- vastly reduce heap allocations and improve performance of strings

* refactor: move improv class to new branch

* fix: file name casing

* feat: add newer esp cam driver

* Cleanup after merge

---------

Co-authored-by: lorow <smykupyka@gmail.com>
This commit is contained in:
DaOfficialWizard 2023-04-02 16:44:38 +01:00 committed by GitHub
parent dfcb17e1d3
commit 17e3049be1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 2124 additions and 642 deletions

View File

@ -7,6 +7,7 @@ on:
branches:
- "master"
- "main"
- "feature/improv"
pull_request:
branches:
- "master"

View File

@ -19,6 +19,7 @@ lib_ldf_mode = deep+
;115200 is used for compatability - if you are on windows and want the code to flash faster use 921600
upload_speed = 921600
lib_deps =
esp32-camera
https://github.com/me-no-dev/ESPAsyncWebServer.git
https://github.com/me-no-dev/AsyncTCP.git
extra_scripts =
@ -29,7 +30,8 @@ build_flags =
-DADHOC_CHANNEL=${wifi.adhocchannel}
-DWIFI_CHANNEL=${wifi.channel}
-DDEBUG_ESP_PORT=Serial
'-DMDNS_HOSTNAME=${wifi.mdnsname}'
'-DVERSION=""' ; set the debug port
'-DMDNS_HOSTNAME=${wifi.mdnsname}' ; Set the OTA password
'-DWIFI_SSID=${wifi.ssid}'
'-DWIFI_PASSWORD=${wifi.password}'
'-DWIFI_AP_SSID=${wifi.ap_ssid}'

View File

@ -19,6 +19,7 @@ build_flags = -DENABLE_ADHOC=${wifi.enableadhoc}
'-DWIFI_AP_SSID=${wifi.ap_ssid}'
'-DWIFI_AP_PASSWORD=${wifi.ap_password}'
'-DWIFI_AP_CHANNEL=${wifi.adhocchannel}'
'-DVERSION=""'
-DOTA_SERVER_PORT=${ota.otaserverport}
'-DOTA_PASSWORD=${ota.otapassword}' ; Set the OTA password

View File

@ -7,3 +7,4 @@ StateManager<MDNSState_e> mdnsStateManager;
StateManager<CameraState_e> cameraStateManager;
StateManager<LEDStates_e> ledStateManager;
StateManager<StreamState_e> streamStateManager;
StateManager<ConfigState_e> configStateManager;

View File

@ -6,74 +6,68 @@
* StateManager
* All Project States are managed here
*/
struct DeviceStates
{
enum State_e
{
Starting,
Started,
Stopping,
Stopped,
Error
};
struct DeviceStates {
enum LEDStates_e {
_LedStateNone,
_Improv_Start,
_Improv_Stop,
_Improv_Processing,
_Improv_Error,
_WebServerState_Error,
_WiFiState_Error,
_MDNSState_Error,
_Camera_Error,
_WiFiState_Connecting,
_WiFiState_Connected
};
enum LEDStates_e
{
_LedStateNone,
_SerialManager_Error,
_WebServerState_Error,
_WiFiState_Error,
_MDNSState_Error,
_Camera_Error,
_WiFiState_Connecting,
_WiFiState_Connected
};
enum ConfigState_e {
configLoaded,
deviceConfigUpdated,
mdnsConfigUpdated,
networksConfigUpdated,
apConfigUpdated,
wifiTxPowerUpdated,
cameraConfigUpdated
};
enum WiFiState_e
{
WiFiState_None,
WiFiState_Idle,
WiFiState_Disconnected,
WiFiState_Connecting,
WiFiState_Connected,
WiFiState_ADHOC,
WiFiState_Error
};
enum WiFiState_e {
WiFiState_None,
WiFiState_Idle,
WiFiState_Disconnected,
WiFiState_Connecting,
WiFiState_Connected,
WiFiState_ADHOC,
WiFiState_Error
};
enum WebServerState_e
{
WebServerState_Stopped,
WebServerState_Starting,
WebServerState_Started,
WebServerState_Stopping,
WebServerState_Error
};
enum WebServerState_e {
WebServerState_Stopped,
WebServerState_Starting,
WebServerState_Started,
WebServerState_Stopping,
WebServerState_Error
};
enum MDNSState_e
{
MDNSState_Stopped,
MDNSState_Starting,
MDNSState_Started,
MDNSState_Stopping,
MDNSState_Error,
MDNSState_QueryStarted,
MDNSState_QueryComplete
};
enum MDNSState_e {
MDNSState_Stopped,
MDNSState_Starting,
MDNSState_Started,
MDNSState_Stopping,
MDNSState_Error,
MDNSState_QueryStarted,
MDNSState_QueryComplete
};
enum CameraState_e
{
Camera_Disconnected,
Camera_Success,
Camera_Connected,
Camera_Error
};
enum CameraState_e {
Camera_Disconnected,
Camera_Success,
Camera_Connected,
Camera_Error
};
enum StreamState_e
{
Stream_OFF,
Stream_ON,
Stream_Error
};
enum StreamState_e { Stream_OFF, Stream_ON, Stream_Error };
enum State_e { Starting, Started, Stopping, Stopped, Error };
};
/*
@ -81,34 +75,25 @@ struct DeviceStates
* All Project Events are managed here
*/
template <class T>
class StateManager
{
public:
StateManager() {
this->_current_state = static_cast<T>(0);
}
class StateManager {
public:
StateManager() { this->_current_state = static_cast<T>(0); }
virtual ~StateManager() {}
virtual ~StateManager() {}
/*
* @brief Sets the state of the stateManager
* @param T state - the state to be set
*/
void setState(T state)
{
_current_state = state;
}
/*
* @brief Sets the state of the stateManager
* @param T state - the state to be set
*/
void setState(T state) { _current_state = state; }
/*
* @brief Returns the current state of the stateManager
*/
T getCurrentState()
{
return _current_state;
}
/*
* @brief Returns the current state of the stateManager
*/
T getCurrentState() { return _current_state; }
private:
T _current_state;
private:
T _current_state;
};
typedef DeviceStates::State_e State_e;
@ -118,6 +103,7 @@ typedef DeviceStates::MDNSState_e MDNSState_e;
typedef DeviceStates::CameraState_e CameraState_e;
typedef DeviceStates::LEDStates_e LEDStates_e;
typedef DeviceStates::StreamState_e StreamState_e;
typedef DeviceStates::ConfigState_e ConfigState_e;
extern StateManager<State_e> stateManager;
extern StateManager<WiFiState_e> wifiStateManager;
@ -126,5 +112,6 @@ extern StateManager<MDNSState_e> mdnsStateManager;
extern StateManager<CameraState_e> cameraStateManager;
extern StateManager<LEDStates_e> ledStateManager;
extern StateManager<StreamState_e> streamStateManager;
extern StateManager<ConfigState_e> configStateManager;
#endif // STATEMANAGER_HPP
#endif // STATEMANAGER_HPP

View File

@ -21,8 +21,8 @@ void ProjectConfig::initConfig() {
bool success = begin(_name.c_str());
log_i("Config name: %s", _name.c_str());
log_i("Config loaded: %s", success ? "true" : "false");
log_i("[Project Config]: Config name: %s", _name.c_str());
log_i("[Project Config]: Config loaded: %s", success ? "true" : "false");
/*
* If the config is not loaded,
@ -41,7 +41,7 @@ void ProjectConfig::initConfig() {
"openiristracker",
};
log_i("MDNS name: %s", _mdnsName.c_str());
log_i("[Project Config]: MDNS name: %s", _mdnsName.c_str());
this->config.ap_network = {
"",
@ -104,7 +104,7 @@ void ProjectConfig::wifiConfigSave() {
putString("apPass", this->config.ap_network.password.c_str());
putUInt("apChannel", this->config.ap_network.channel);
log_i("Project config saved and system is rebooting");
log_i("[Project Config]: Wifi configs saved");
}
void ProjectConfig::deviceConfigSave() {
@ -201,7 +201,7 @@ void ProjectConfig::load() {
this->config.camera.brightness = getInt("brightness", 2);
this->_already_loaded = true;
this->notify(ObserverEvent::configLoaded);
this->notifyAll(ConfigState_e::configLoaded);
}
//**********************************************************************************************************************
@ -219,7 +219,7 @@ void ProjectConfig::setDeviceConfig(const std::string& OTALogin,
this->config.device.OTAPort = OTAPort;
if (shouldNotify)
this->notify(ObserverEvent::deviceConfigUpdated);
this->notifyAll(ConfigState_e::deviceConfigUpdated);
}
void ProjectConfig::setMDNSConfig(const std::string& hostname,
@ -230,64 +230,58 @@ void ProjectConfig::setMDNSConfig(const std::string& hostname,
this->config.mdns.service.assign(service);
if (shouldNotify)
this->notify(ObserverEvent::mdnsConfigUpdated);
this->notifyAll(ConfigState_e::mdnsConfigUpdated);
}
void ProjectConfig::setCameraConfig(uint8_t* vflip,
uint8_t* framesize,
uint8_t* href,
uint8_t* quality,
uint8_t* brightness,
void ProjectConfig::setCameraConfig(uint8_t vflip,
uint8_t framesize,
uint8_t href,
uint8_t quality,
uint8_t brightness,
bool shouldNotify) {
log_d("Updating camera config");
this->config.camera.vflip = *vflip;
this->config.camera.href = *href;
this->config.camera.framesize = *framesize;
this->config.camera.quality = *quality;
this->config.camera.brightness = *brightness;
this->config.camera.vflip = vflip;
this->config.camera.href = href;
this->config.camera.framesize = framesize;
this->config.camera.quality = quality;
this->config.camera.brightness = brightness;
log_d("Updating Camera config");
if (shouldNotify)
this->notify(ObserverEvent::cameraConfigUpdated);
this->notifyAll(ConfigState_e::cameraConfigUpdated);
}
void ProjectConfig::setWifiConfig(const std::string& networkName,
const std::string& ssid,
const std::string& password,
uint8_t* channel,
uint8_t* power,
uint8_t channel,
uint8_t power,
bool adhoc,
bool shouldNotify) {
// we store the ADHOC flag as false because the networks we store in the
// config are the ones we want the esp to connect to, rather than host as AP,
// and here we're just updating them
size_t size = this->config.networks.size();
// we're allowing to store up to three additional networks
if (size == 0) {
Serial.println("No networks, We're adding a new network");
this->config.networks.emplace_back(networkName, ssid, password, *channel,
*power, false);
if (shouldNotify)
this->notify(ObserverEvent::networksConfigUpdated);
return;
}
for (auto it = this->config.networks.begin();
it != this->config.networks.end();) {
if (it->name == networkName) {
log_i("Found network %s, updating it ...", it->name.c_str());
log_i("[Project Config]: Found network %s, updating it ...",
it->name.c_str());
it->name = networkName;
it->ssid = ssid;
it->password = password;
it->channel = *channel;
it->power = *power;
it->channel = channel;
it->power = power;
it->adhoc = false;
if (shouldNotify)
this->notify(ObserverEvent::networksConfigUpdated);
if (shouldNotify) {
wifiStateManager.setState(WiFiState_e::WiFiState_Disconnected);
WiFi.disconnect();
this->wifiConfigSave();
this->notifyAll(ConfigState_e::networksConfigUpdated);
}
return;
} else {
@ -295,17 +289,28 @@ void ProjectConfig::setWifiConfig(const std::string& networkName,
}
}
if (size < 3) {
if (size < 3 && size > 0) {
Serial.println("We're adding a new network");
// we don't have that network yet, we can add it as we still have some
// space we're using emplace_back as push_back will create a copy of it,
// we want to avoid that
this->config.networks.emplace_back(networkName, ssid, password, *channel,
*power, false);
this->config.networks.emplace_back(networkName, ssid, password, channel,
power, false);
}
if (shouldNotify)
this->notify(ObserverEvent::networksConfigUpdated);
// we're allowing to store up to three additional networks
if (size == 0) {
Serial.println("No networks, We're adding a new network");
this->config.networks.emplace_back(networkName, ssid, password, channel,
power, false);
}
if (shouldNotify) {
wifiStateManager.setState(WiFiState_e::WiFiState_None);
WiFi.disconnect();
this->wifiConfigSave();
this->notifyAll(ConfigState_e::networksConfigUpdated);
}
}
void ProjectConfig::deleteWifiConfig(const std::string& networkName,
@ -318,40 +323,47 @@ void ProjectConfig::deleteWifiConfig(const std::string& networkName,
for (auto it = this->config.networks.begin();
it != this->config.networks.end();) {
if (it->name == networkName) {
log_i("Found network %s", it->name.c_str());
log_i("[Project Config]: Found network %s", it->name.c_str());
it = this->config.networks.erase(it);
log_i("Deleted network %s", networkName.c_str());
log_i("[Project Config]: Deleted network %s", networkName.c_str());
} else {
++it;
}
}
if (shouldNotify)
this->notify(ObserverEvent::networksConfigUpdated);
if (shouldNotify) {
this->wifiConfigSave();
this->notifyAll(ConfigState_e::networksConfigUpdated);
}
}
void ProjectConfig::setWiFiTxPower(uint8_t* power, bool shouldNotify) {
this->config.txpower.power = *power;
void ProjectConfig::setWiFiTxPower(uint8_t power, bool shouldNotify) {
this->config.txpower.power = power;
log_d("Updating wifi tx power");
if (shouldNotify)
this->notify(ObserverEvent::wifiTxPowerUpdated);
this->notifyAll(ConfigState_e::wifiTxPowerUpdated);
}
void ProjectConfig::setAPWifiConfig(const std::string& ssid,
const std::string& password,
uint8_t* channel,
uint8_t channel,
bool adhoc,
bool shouldNotify) {
this->config.ap_network.ssid.assign(ssid);
this->config.ap_network.password.assign(password);
this->config.ap_network.channel = *channel;
this->config.ap_network.channel = channel;
this->config.ap_network.adhoc = adhoc;
log_d("Updating access point config");
if (shouldNotify)
this->notify(ObserverEvent::networksConfigUpdated);
if (shouldNotify) {
wifiStateManager.setState(WiFiState_e::WiFiState_None);
WiFi.disconnect();
this->wifiConfigSave();
this->notifyAll(ConfigState_e::networksConfigUpdated);
}
}
std::string ProjectConfig::DeviceConfig_t::toRepresentation() {
@ -409,21 +421,21 @@ std::string ProjectConfig::WiFiTxPower_t::toRepresentation() {
//*
//**********************************************************************************************************************
ProjectConfig::DeviceConfig_t* ProjectConfig::getDeviceConfig() {
return &this->config.device;
ProjectConfig::DeviceConfig_t& ProjectConfig::getDeviceConfig() {
return this->config.device;
}
ProjectConfig::CameraConfig_t* ProjectConfig::getCameraConfig() {
return &this->config.camera;
ProjectConfig::CameraConfig_t& ProjectConfig::getCameraConfig() {
return this->config.camera;
}
std::vector<ProjectConfig::WiFiConfig_t>* ProjectConfig::getWifiConfigs() {
return &this->config.networks;
std::vector<ProjectConfig::WiFiConfig_t>& ProjectConfig::getWifiConfigs() {
return this->config.networks;
}
ProjectConfig::AP_WiFiConfig_t* ProjectConfig::getAPWifiConfig() {
return &this->config.ap_network;
ProjectConfig::AP_WiFiConfig_t& ProjectConfig::getAPWifiConfig() {
return this->config.ap_network;
}
ProjectConfig::MDNSConfig_t* ProjectConfig::getMDNSConfig() {
return &this->config.mdns;
ProjectConfig::MDNSConfig_t& ProjectConfig::getMDNSConfig() {
return this->config.mdns;
}
ProjectConfig::WiFiTxPower_t* ProjectConfig::getWiFiTxPowerConfig() {
return &this->config.txpower;
ProjectConfig::WiFiTxPower_t& ProjectConfig::getWiFiTxPowerConfig() {
return this->config.txpower;
}

View File

@ -7,11 +7,13 @@
#include <string>
#include <vector>
#include "data/StateManager/StateManager.hpp"
#include "data/utilities/Observer.hpp"
#include "data/utilities/helpers.hpp"
#include "data/utilities/network_utilities.hpp"
#include "tasks/tasks.hpp"
class ProjectConfig : public Preferences, public ISubject {
class ProjectConfig : public Preferences, public ISubject<ConfigState_e> {
public:
ProjectConfig(const std::string& name = std::string(),
const std::string& mdnsName = std::string());
@ -95,12 +97,12 @@ class ProjectConfig : public Preferences, public ISubject {
WiFiTxPower_t txpower;
};
DeviceConfig_t* getDeviceConfig();
CameraConfig_t* getCameraConfig();
std::vector<WiFiConfig_t>* getWifiConfigs();
AP_WiFiConfig_t* getAPWifiConfig();
MDNSConfig_t* getMDNSConfig();
WiFiTxPower_t* getWiFiTxPowerConfig();
DeviceConfig_t& getDeviceConfig();
CameraConfig_t& getCameraConfig();
std::vector<WiFiConfig_t>& getWifiConfigs();
AP_WiFiConfig_t& getAPWifiConfig();
MDNSConfig_t& getMDNSConfig();
WiFiTxPower_t& getWiFiTxPowerConfig();
void setDeviceConfig(const std::string& OTALogin,
const std::string& OTAPassword,
@ -109,25 +111,25 @@ class ProjectConfig : public Preferences, public ISubject {
void setMDNSConfig(const std::string& hostname,
const std::string& service,
bool shouldNotify);
void setCameraConfig(uint8_t* vflip,
uint8_t* framesize,
uint8_t* href,
uint8_t* quality,
uint8_t* brightness,
void setCameraConfig(uint8_t vflip,
uint8_t framesize,
uint8_t href,
uint8_t quality,
uint8_t brightness,
bool shouldNotify);
void setWifiConfig(const std::string& networkName,
const std::string& ssid,
const std::string& password,
uint8_t* channel,
uint8_t* power,
uint8_t channel,
uint8_t power,
bool adhoc,
bool shouldNotify);
void setAPWifiConfig(const std::string& ssid,
const std::string& password,
uint8_t* channel,
uint8_t channel,
bool adhoc,
bool shouldNotify);
void setWiFiTxPower(uint8_t* power, bool shouldNotify);
void setWiFiTxPower(uint8_t power, bool shouldNotify);
void deleteWifiConfig(const std::string& networkName, bool shouldNotify);

View File

@ -1,50 +1,60 @@
#pragma once
#ifndef OBSERVER_HPP
#define OBSERVER_HPP
#include <set>
#include <memory>
#include <string>
#include <unordered_map>
namespace ObserverEvent
{
enum Event
{
configLoaded = 1,
deviceConfigUpdated = 2,
cameraConfigUpdated = 3,
networksConfigUpdated = 4,
mdnsConfigUpdated = 5,
wifiTxPowerUpdated = 6,
};
}
class IObserver
{
public:
virtual void update(ObserverEvent::Event event) = 0;
template <typename EnumT>
class IObserver {
public:
virtual void update(EnumT event) = 0;
virtual std::string getName() = 0;
};
class ISubject
{
private:
std::set<IObserver *> observers;
template <typename EnumT>
class ISubject {
private:
typedef IObserver<EnumT>& Observer_t;
typedef std::unordered_map<std::string, Observer_t> Observers_t;
public:
void attach(IObserver *observer)
{
this->observers.insert(observer);
Observers_t observers;
public:
void attach(Observer_t observer) {
this->observers.emplace(observer.getName(), observer);
}
void detach(IObserver *observer)
{
this->observers.erase(observer);
void detach(Observer_t observer) {
// Note: delete pointer
delete (*this->observers.find(observer.getName())).second;
this->observers.erase(observer.getName());
}
void notify(ObserverEvent::Event event)
{
for (auto observer : this->observers)
{
observer->update(event);
void detachAll() {
// Note: delete pointers
for (auto observer = observers.begin(); observer != observers.end();
++observer) {
delete (*observer).second;
}
// Note: clear map
this->observers.clear();
}
void notifyAll(EnumT event) {
for (auto observer = observers.begin(); observer != observers.end();
++observer) {
(*observer).second.update(event);
}
}
};
#endif // !OBSERVER_HPP
void notify(EnumT event, const std::string& observerName) {
auto it_map = observers.find(observerName);
if (it_map != observers.end()) {
(*it_map).second->update(event);
return;
}
log_e("Invalid Map Index");
return;
}
};
#endif // OBSERVER_HPP

View File

@ -5,7 +5,7 @@ void Network_Utilities::setupWifiScan()
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect(); // Disconnect from the access point if connected before
my_delay(0.1L);
my_delay(0.1);
Serial.println("Setup done");
}

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,13 @@
LEDManager::ledStateMap_t LEDManager::ledStateMap = {
{LEDStates_e::_LedStateNone, {{0, 500}}},
{LEDStates_e::_SerialManager_Error,
{LEDStates_e::_Improv_Error,
{{1, 1000}, {0, 500}, {0, 1000}, {0, 500}, {1, 1000}}},
{LEDStates_e::_Improv_Start,
{{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,
{{1, 200}, {0, 100}, {0, 500}, {0, 100}, {1, 200}}},
@ -46,15 +52,14 @@ LEDManager::ledStateMap_t LEDManager::ledStateMap = {
std::vector<LEDStates_e> LEDManager::keepAliveStates = {
LEDStates_e::_WebServerState_Error, LEDStates_e::_Camera_Error};
LEDManager::LEDManager(byte pin, StateManager<LEDStates_e>* stateManager)
: _ledPin(pin), _stateManager(stateManager), _ledState(false) {}
LEDManager::LEDManager(byte pin) : _ledPin(pin), _ledState(false) {}
LEDManager::~LEDManager() {}
void LEDManager::begin() {
pinMode(_ledPin, OUTPUT);
// the defualt state is _LedStateNone so we're fine
this->currentState = this->_stateManager->getCurrentState();
this->currentState = ledStateManager.getCurrentState();
this->currentPatternIndex = 0;
BlinkPatterns_t pattern =
this->ledStateMap[this->currentState][this->currentPatternIndex];
@ -81,7 +86,7 @@ void LEDManager::handleLED() {
// start displaying it, or if we need to keep displaying the current one
if (this->currentPatternIndex >
this->ledStateMap[this->currentState].size() - 1) {
auto nextState = this->_stateManager->getCurrentState();
auto nextState = ledStateManager.getCurrentState();
// 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
// more serious one this time <- this may be a bad idea
@ -98,14 +103,14 @@ void LEDManager::handleLED() {
BlinkPatterns_t pattern =
this->ledStateMap[this->currentState][this->currentPatternIndex];
this->nextStateChangeMillis = millis() + pattern.delayTime;
return;
return;
}
// it wasn't a keepAlive state, nor did we have another one ready,
// we're done for now
this->toggleLED(false);
return;
}
// we can safely adnace it and display the next stage
// we can safely advance it and display the next stage
BlinkPatterns_t pattern =
this->ledStateMap[this->currentState][this->currentPatternIndex];
this->toggleLED(pattern.state);

View File

@ -8,7 +8,7 @@
class LEDManager
{
public:
LEDManager(byte pin, StateManager<LEDStates_e> *stateManager);
LEDManager(byte pin);
virtual ~LEDManager();
void begin();
@ -17,7 +17,6 @@ public:
private:
byte _ledPin;
StateManager<LEDStates_e> *_stateManager;
unsigned long nextStateChangeMillis = 0;
bool _ledState;
@ -34,4 +33,4 @@ private:
unsigned int currentPatternIndex = 0;
};
#endif // LEDMANAGER_HPP
#endif // LEDMANAGER_HPP

View File

@ -1,212 +1,221 @@
#include "cameraHandler.hpp"
CameraHandler::CameraHandler(ProjectConfig *configManager,
StateManager<LEDStates_e> *stateManager) : configManager(configManager),
stateManager(stateManager) {}
CameraHandler::CameraHandler(ProjectConfig& configManager)
: configManager(configManager) {}
void CameraHandler::setupCameraPinout()
{
// Workaround for espM5SStack not having a defined camera
void CameraHandler::setupCameraPinout() {
// Workaround for espM5SStack not having a defined camera
#ifdef CAMERA_MODULE_NAME
log_i("Camera module is %s", CAMERA_MODULE_NAME);
log_i("Camera module is %s", CAMERA_MODULE_NAME);
#else
log_i("Camera module is undefined");
log_i("Camera module is undefined");
#endif
#if CONFIG_CAMERA_MODULE_ESP_EYE
/* IO13, IO14 is designed for JTAG by default,
* to use it as generalized input,
* firstly declair it as pullup input
**/
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
log_i("ESP_EYE");
/* IO13, IO14 is designed for JTAG by default,
* to use it as generalized input,
* firstly declair it as pullup input
**/
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
log_i("ESP_EYE");
#elif CONFIG_CAMERA_MODULE_CAM_BOARD
/* IO13, IO14 is designed for JTAG by default,
* to use it as generalized input,
* firstly declair it as pullup input
**/
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
log_i("CAM_BOARD");
/* IO13, IO14 is designed for JTAG by default,
* to use it as generalized input,
* firstly declair it as pullup input
**/
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
log_i("CAM_BOARD");
#endif
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.grab_mode = CAMERA_GRAB_LATEST;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 16500000; // 10000000 stable,
// 16500000 optimal,
// 20000000 max fps
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.grab_mode = CAMERA_GRAB_LATEST;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 16500000; // 10000000 stable,
// 16500000 optimal,
// 20000000 max fps
}
void CameraHandler::setupBasicResolution()
{
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_240X240;
void CameraHandler::setupBasicResolution() {
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_240X240;
if (!psramFound())
{
log_e("Did not find psram, setting lower image quality");
config.fb_location = CAMERA_FB_IN_DRAM;
config.jpeg_quality = 9;
config.fb_count = 2;
return;
}
if (!psramFound()) {
log_e("Did not find psram, setting lower image quality");
config.fb_location = CAMERA_FB_IN_DRAM;
config.jpeg_quality = 9;
config.fb_count = 2;
return;
}
log_d("Found psram, setting the higher image quality");
config.jpeg_quality = 7; // 0-63 lower number = higher quality, more latency and less fps 7 for most fps, 5 for best quality
config.fb_count = 3;
log_d("Found psram, setting the higher image quality");
config.jpeg_quality = 7; // 0-63 lower number = higher quality, more latency
// and less fps 7 for most fps, 5 for best quality
config.fb_count = 3;
}
void CameraHandler::setupCameraSensor()
{
camera_sensor = esp_camera_sensor_get();
// fixes corrupted jpegs, https://github.com/espressif/esp32-camera/issues/203
// documentation https://www.uctronics.com/download/cam_module/OV2640DS.pdf
camera_sensor->set_reg(camera_sensor, 0xff, 0xff, 0x00); // banksel, here we're directly writing to the registers. 0xFF==0x00 is the first bank, there's also 0xFF==0x01
camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock
camera_sensor->set_brightness(camera_sensor, 2); // -2 to 2
camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2
camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2
void CameraHandler::setupCameraSensor() {
camera_sensor = esp_camera_sensor_get();
// fixes corrupted jpegs, https://github.com/espressif/esp32-camera/issues/203
// documentation https://www.uctronics.com/download/cam_module/OV2640DS.pdf
camera_sensor->set_reg(
camera_sensor, 0xff, 0xff,
0x00); // banksel, here we're directly writing to the registers.
// 0xFF==0x00 is the first bank, there's also 0xFF==0x01
camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock
camera_sensor->set_brightness(camera_sensor, 2); // -2 to 2
camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2
camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2
// white balance control
camera_sensor->set_whitebal(camera_sensor, 1); // 0 = disable , 1 = enable
camera_sensor->set_awb_gain(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_wb_mode(camera_sensor, 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
// controls the exposure
camera_sensor->set_exposure_ctrl(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_aec2(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_ae_level(camera_sensor, 0); // -2 to 2
camera_sensor->set_aec_value(camera_sensor, 300); // 0 to 1200
// white balance control
camera_sensor->set_whitebal(camera_sensor, 1); // 0 = disable , 1 = enable
camera_sensor->set_awb_gain(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_wb_mode(camera_sensor,
0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 -
// Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
// controls the gain
camera_sensor->set_gain_ctrl(camera_sensor, 0); // 0 = disable , 1 = enable
// automatic gain control gain, controls by how much the resulting image should be amplified
camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30
camera_sensor->set_gainceiling(camera_sensor, (gainceiling_t)6); // 0 to 6
// controls the exposure
camera_sensor->set_exposure_ctrl(camera_sensor,
0); // 0 = disable , 1 = enable
camera_sensor->set_aec2(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_ae_level(camera_sensor, 0); // -2 to 2
camera_sensor->set_aec_value(camera_sensor, 300); // 0 to 1200
// black and white pixel correction, averages the white and black spots
camera_sensor->set_bpc(camera_sensor, 1); // 0 = disable , 1 = enable
camera_sensor->set_wpc(camera_sensor, 1); // 0 = disable , 1 = enable
// digital clamp white balance
camera_sensor->set_dcw(camera_sensor, 0); // 0 = disable , 1 = enable
// controls the gain
camera_sensor->set_gain_ctrl(camera_sensor, 0); // 0 = disable , 1 = enable
//gamma correction
camera_sensor->set_raw_gma(camera_sensor, 1); // 0 = disable , 1 = enable (makes much lighter and noisy)
camera_sensor->set_lenc(camera_sensor, 0); // 0 = disable , 1 = enable // 0 = disable , 1 = enable
camera_sensor->set_colorbar(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_special_effect(camera_sensor, 2); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
// automatic gain control gain, controls by how much the resulting image
// should be amplified
camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30
camera_sensor->set_gainceiling(camera_sensor, (gainceiling_t)6); // 0 to 6
// black and white pixel correction, averages the white and black spots
camera_sensor->set_bpc(camera_sensor, 1); // 0 = disable , 1 = enable
camera_sensor->set_wpc(camera_sensor, 1); // 0 = disable , 1 = enable
// digital clamp white balance
camera_sensor->set_dcw(camera_sensor, 0); // 0 = disable , 1 = enable
// gamma correction
camera_sensor->set_raw_gma(
camera_sensor,
1); // 0 = disable , 1 = enable (makes much lighter and noisy)
camera_sensor->set_lenc(camera_sensor, 0); // 0 = disable , 1 = enable // 0 =
// disable , 1 = enable
camera_sensor->set_colorbar(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_special_effect(
camera_sensor,
2); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint,
// 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
}
bool CameraHandler::setupCamera()
{
this->setupCameraPinout();
this->setupBasicResolution();
esp_err_t hasCameraBeenInitialized = esp_camera_init(&config);
bool CameraHandler::setupCamera() {
this->setupCameraPinout();
this->setupBasicResolution();
esp_err_t hasCameraBeenInitialized = esp_camera_init(&config);
if (hasCameraBeenInitialized != ESP_OK)
{
log_e("Camera initialization failed with error: 0x%x \r\n", hasCameraBeenInitialized);
log_e("Camera most likely not seated properly in the socket. Please fix the camera and reboot the device.\r\n");
stateManager->setState(LEDStates_e::_Camera_Error);
return false;
}
if (hasCameraBeenInitialized != ESP_OK) {
log_e("Camera initialization failed with error: 0x%x \r\n",
hasCameraBeenInitialized);
log_e(
"Camera most likely not seated properly in the socket. Please fix the "
"camera and reboot the device.\r\n");
ledStateManager.setState(LEDStates_e::_Camera_Error);
return false;
}
this->setupCameraSensor();
return true;
this->setupCameraSensor();
return true;
}
void CameraHandler::loadConfigData()
{
ProjectConfig::CameraConfig_t *cameraConfig = configManager->getCameraConfig();
this->setHFlip(cameraConfig->href);
this->setVFlip(cameraConfig->vflip);
this->setCameraResolution((framesize_t)cameraConfig->framesize);
camera_sensor->set_quality(camera_sensor, cameraConfig->quality);
camera_sensor->set_agc_gain(camera_sensor, cameraConfig->brightness);
void CameraHandler::loadConfigData() {
ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig();
this->setHFlip(cameraConfig.href);
this->setVFlip(cameraConfig.vflip);
this->setCameraResolution((framesize_t)cameraConfig.framesize);
camera_sensor->set_quality(camera_sensor, cameraConfig.quality);
camera_sensor->set_agc_gain(camera_sensor, cameraConfig.brightness);
}
void CameraHandler::update(ObserverEvent::Event event)
{
switch (event)
{
case ObserverEvent::Event::configLoaded:
this->setupCamera();
this->loadConfigData();
break;
case ObserverEvent::Event::cameraConfigUpdated:
this->loadConfigData();
break;
default:
break;
}
int CameraHandler::setCameraResolution(framesize_t frameSize) {
if (camera_sensor->pixformat == PIXFORMAT_JPEG) {
try {
return camera_sensor->set_framesize(camera_sensor, frameSize);
} catch (...) {
// they sent us a malformed or unsupported frameSize - rather than crash -
// tell them about it
return -1;
}
}
return -1;
}
int CameraHandler::setCameraResolution(framesize_t frameSize)
{
if (camera_sensor->pixformat == PIXFORMAT_JPEG)
{
try
{
return camera_sensor->set_framesize(camera_sensor, frameSize);
}
catch (...)
{
// they sent us a malformed or unsupported frameSize - rather than crash - tell them about it
return -1;
}
}
return -1;
int CameraHandler::setVFlip(int direction) {
return camera_sensor->set_vflip(camera_sensor, direction);
}
int CameraHandler::setVFlip(int direction)
{
return camera_sensor->set_vflip(camera_sensor, direction);
int CameraHandler::setHFlip(int direction) {
return camera_sensor->set_hmirror(camera_sensor, direction);
}
int CameraHandler::setHFlip(int direction)
{
return camera_sensor->set_hmirror(camera_sensor, direction);
int CameraHandler::setVieWindow(int offsetX,
int offsetY,
int outputX,
int outputY) {
return 0;
}
//! either hardware(1) or software(0)
void CameraHandler::resetCamera(bool type)
{
if (type)
{
// power cycle the camera module (handy if camera stops responding)
digitalWrite(PWDN_GPIO_NUM, HIGH); // turn power off to camera module
Network_Utilities::my_delay(0.3); // a for loop with a delay of 300ms
digitalWrite(PWDN_GPIO_NUM, LOW);
Network_Utilities::my_delay(0.3);
setupCamera();
}
else
{
// reset via software (handy if you wish to change resolution or image type etc. - see test procedure)
esp_camera_deinit();
Network_Utilities::my_delay(0.05);
setupCamera();
}
void CameraHandler::resetCamera(bool type) {
if (type) {
// power cycle the camera module (handy if camera stops responding)
digitalWrite(PWDN_GPIO_NUM, HIGH); // turn power off to camera module
Network_Utilities::my_delay(0.3); // a for loop with a delay of 300ms
digitalWrite(PWDN_GPIO_NUM, LOW);
Network_Utilities::my_delay(0.3);
setupCamera();
} else {
// reset via software (handy if you wish to change resolution or image type
// etc. - see test procedure)
esp_camera_deinit();
Network_Utilities::my_delay(0.05);
setupCamera();
}
}
void CameraHandler::update(ConfigState_e event) {
switch (event) {
case ConfigState_e::configLoaded:
this->setupCamera();
this->loadConfigData();
break;
case ConfigState_e::cameraConfigUpdated:
this->loadConfigData();
break;
default:
break;
}
}
std::string CameraHandler::getName() {
return "CameraHandler";
}

View File

@ -6,27 +6,26 @@
#include "data/config/project_config.hpp"
#include "data/StateManager/StateManager.hpp"
class CameraHandler : public IObserver
{
private:
sensor_t *camera_sensor;
camera_config_t config;
ProjectConfig *configManager;
StateManager<LEDStates_e> *stateManager;
class CameraHandler : public IObserver<ConfigState_e> {
private:
sensor_t* camera_sensor;
camera_config_t config;
ProjectConfig& configManager;
public:
CameraHandler(ProjectConfig *configManager, StateManager<LEDStates_e> *stateManager);
int setCameraResolution(framesize_t frameSize);
int setVFlip(int direction);
int setHFlip(int direction);
int setVieWindow(int offsetX, int offsetY, int outputX, int outputY);
void update(ObserverEvent::Event event);
void resetCamera(bool type = 0);
public:
CameraHandler(ProjectConfig& configManager);
int setCameraResolution(framesize_t frameSize);
int setVFlip(int direction);
int setHFlip(int direction);
int setVieWindow(int offsetX, int offsetY, int outputX, int outputY);
void update(ConfigState_e event);
std::string getName();
void resetCamera(bool type = 0);
private:
void loadConfigData();
bool setupCamera();
void setupCameraPinout();
void setupBasicResolution();
void setupCameraSensor();
private:
void loadConfigData();
bool setupCamera();
void setupCameraPinout();
void setupBasicResolution();
void setupCameraSensor();
};

View File

@ -1,40 +0,0 @@
#pragma once
#ifndef WIFIHANDLER_HPP
#define WIFIHANDLER_HPP
#include <memory>
#include <string>
#include <vector>
#include <WiFi.h>
#include "data/StateManager/StateManager.hpp"
#include "data/config/project_config.hpp"
#include "data/utilities/helpers.hpp"
class WiFiHandler
{
public:
WiFiHandler(ProjectConfig *configManager,
StateManager<WiFiState_e> *stateManager,
StateManager<LEDStates_e> *ledStateManger,
const std::string &ssid,
const std::string &password,
uint8_t channel);
virtual ~WiFiHandler();
void setupWifi();
ProjectConfig *configManager;
StateManager<WiFiState_e> *stateManager;
StateManager<LEDStates_e> *ledStateManager;
bool _enable_adhoc;
private:
void setUpADHOC();
void adhoc(const std::string &ssid, uint8_t channel, const std::string &password = std::string());
bool iniSTA(const std::string &ssid, const std::string &password, uint8_t channel, wifi_power_t power);
std::string ssid;
std::string password;
uint8_t channel;
uint8_t power;
};
#endif // WIFIHANDLER_HPP

View File

@ -1,14 +1,13 @@
#include "WifiHandler.hpp"
#include "wifihandler.hpp"
#include <WiFi.h>
#include "data/StateManager/StateManager.hpp"
#include "data/utilities/helpers.hpp"
WiFiHandler::WiFiHandler(ProjectConfig* configManager,
StateManager<WiFiState_e>* stateManager,
StateManager<LEDStates_e>* ledStateManger,
WiFiHandler::WiFiHandler(ProjectConfig& configManager,
const std::string& ssid,
const std::string& password,
uint8_t channel)
: configManager(configManager),
stateManager(stateManager),
ledStateManager(ledStateManager),
ssid(ssid),
password(password),
channel(channel),
@ -17,41 +16,38 @@ WiFiHandler::WiFiHandler(ProjectConfig* configManager,
WiFiHandler::~WiFiHandler() {}
void WiFiHandler::setupWifi() {
void WiFiHandler::begin() {
if (this->_enable_adhoc ||
stateManager->getCurrentState() == WiFiState_e::WiFiState_ADHOC) {
wifiStateManager.getCurrentState() == WiFiState_e::WiFiState_ADHOC) {
this->setUpADHOC();
return;
}
ProjectConfig::WiFiTxPower_t* txpower = configManager->getWiFiTxPowerConfig();
auto txpower = configManager.getWiFiTxPowerConfig();
WiFi.mode(WIFI_STA);
WiFi.setSleep(WIFI_PS_NONE);
log_i("Initializing connection to wifi \n\r");
stateManager->setState(WiFiState_e::WiFiState_Connecting);
wifiStateManager.setState(WiFiState_e::WiFiState_Connecting);
std::vector<ProjectConfig::WiFiConfig_t>* networks =
configManager->getWifiConfigs();
auto networks = configManager.getWifiConfigs();
if (networks->empty()) {
if (networks.empty()) {
log_i("No networks found in config, trying the default one \n\r");
if (this->iniSTA(this->ssid, this->password, this->channel,
(wifi_power_t)txpower->power)) {
return;
} else {
log_i(
"Could not connect to the hardcoded network, setting up ADHOC "
"network \n\r");
this->setUpADHOC();
(wifi_power_t)txpower.power)) {
return;
}
log_i(
"Could not connect to the hardcoded network, setting up ADHOC "
"network \n\r");
this->setUpADHOC();
return;
}
for (auto networkIterator = networks->begin();
networkIterator != networks->end(); ++networkIterator) {
if (this->iniSTA(networkIterator->ssid, networkIterator->password,
networkIterator->channel,
(wifi_power_t)networkIterator->power)) {
for (auto& network : networks) {
log_i("Trying to connect to network: %s \n\r", network.ssid.c_str());
if (this->iniSTA(network.ssid, network.password, network.channel,
(wifi_power_t)txpower.power)) {
return;
}
}
@ -62,20 +58,21 @@ void WiFiHandler::setupWifi() {
"to hardcoded network: %s \n\r",
this->ssid.c_str());
if (this->iniSTA(this->ssid, this->password, this->channel,
(wifi_power_t)txpower->power)) {
(wifi_power_t)txpower.power)) {
log_i("Successfully connected to the hardcoded network. \n\r");
} else {
log_i(
"Could not connect to the hardcoded network, setting up adhoc. "
"\n\r");
this->setUpADHOC();
return;
}
log_i(
"Could not connect to the hardcoded network, setting up adhoc. "
"\n\r");
this->setUpADHOC();
}
void WiFiHandler::adhoc(const std::string& ssid,
uint8_t channel,
const std::string& password) {
stateManager->setState(WiFiState_e::WiFiState_ADHOC);
wifiStateManager.setState(WiFiState_e::WiFiState_ADHOC);
log_i("\n[INFO]: Configuring access point...\n");
WiFi.mode(WIFI_AP);
@ -84,16 +81,16 @@ void WiFiHandler::adhoc(const std::string& ssid,
IPAddress IP = WiFi.softAPIP();
Serial.printf("[INFO]: AP IP address: %s.\r\n", IP.toString().c_str());
// You can remove the password parameter if you want the AP to be open.
ProjectConfig::WiFiTxPower_t* txpower = configManager->getWiFiTxPowerConfig();
ProjectConfig::WiFiTxPower_t txpower = configManager.getWiFiTxPowerConfig();
WiFi.softAP(ssid.c_str(), password.c_str(),
channel); // AP mode with password
WiFi.setTxPower((wifi_power_t)txpower->power);
WiFi.setTxPower((wifi_power_t)txpower.power);
}
void WiFiHandler::setUpADHOC() {
log_i("\n[INFO]: Setting Up Access Point...\n");
size_t ssidLen = configManager->getAPWifiConfig()->ssid.length();
size_t passwordLen = configManager->getAPWifiConfig()->password.length();
size_t ssidLen = configManager.getAPWifiConfig().ssid.length();
size_t passwordLen = configManager.getAPWifiConfig().password.length();
if (ssidLen <= 0) {
log_i("\n[INFO]: Configuring access point with default values\n");
this->adhoc(WIFI_AP_SSID, WIFI_AP_CHANNEL, WIFI_AP_PASSWORD);
@ -102,21 +99,20 @@ void WiFiHandler::setUpADHOC() {
if (passwordLen <= 0) {
log_i("\n[INFO]: Configuring access point without a password\n");
this->adhoc(configManager->getAPWifiConfig()->ssid,
configManager->getAPWifiConfig()->channel);
this->adhoc(configManager.getAPWifiConfig().ssid,
configManager.getAPWifiConfig().channel);
return;
}
this->adhoc(configManager->getAPWifiConfig()->ssid,
configManager->getAPWifiConfig()->channel,
configManager->getAPWifiConfig()->password);
this->adhoc(configManager.getAPWifiConfig().ssid,
configManager.getAPWifiConfig().channel,
configManager.getAPWifiConfig().password);
log_i("\n[INFO]: Configuring access point...\n");
log_d("\n[DEBUG]: ssid: %s\n",
configManager->getAPWifiConfig()->ssid.c_str());
log_d("\n[DEBUG]: ssid: %s\n", configManager.getAPWifiConfig().ssid.c_str());
log_d("\n[DEBUG]: password: %s\n",
configManager->getAPWifiConfig()->password.c_str());
log_d("\n[DEBUG]: channel: %d\n", configManager->getAPWifiConfig()->channel);
configManager.getAPWifiConfig().password.c_str());
log_d("\n[DEBUG]: channel: %d\n", configManager.getAPWifiConfig().channel);
}
bool WiFiHandler::iniSTA(const std::string& ssid,
@ -128,13 +124,13 @@ bool WiFiHandler::iniSTA(const std::string& ssid,
int connectionTimeout = 30000; // 30 seconds
int progress = 0;
stateManager->setState(WiFiState_e::WiFiState_Connecting);
wifiStateManager.setState(WiFiState_e::WiFiState_Connecting);
log_i("Trying to connect to: %s \n\r", ssid.c_str());
auto mdnsConfig = configManager->getMDNSConfig();
auto mdnsConfig = configManager.getMDNSConfig();
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE,
INADDR_NONE); // need to call before setting hostname
WiFi.setHostname(mdnsConfig->hostname.c_str());
WiFi.setHostname(mdnsConfig.hostname.c_str());
WiFi.begin(ssid.c_str(), password.c_str(), channel);
while (WiFi.status() != WL_CONNECTED) {
progress++;
@ -142,14 +138,28 @@ bool WiFiHandler::iniSTA(const std::string& ssid,
Helpers::update_progress_bar(progress, 100);
delay(301);
if ((currentMillis - startingMillis) >= connectionTimeout) {
stateManager->setState(WiFiState_e::WiFiState_Error);
wifiStateManager.setState(WiFiState_e::WiFiState_Error);
log_e("Connection to: %s TIMEOUT \n\r", ssid.c_str());
return false;
}
}
stateManager->setState(WiFiState_e::WiFiState_Connected);
wifiStateManager.setState(WiFiState_e::WiFiState_Connected);
log_i("Successfully connected to %s \n\r", ssid.c_str());
log_i("Setting TX power to: %d \n\r", (uint8_t)power);
WiFi.setTxPower(power);
return true;
}
void WiFiHandler::update(ConfigState_e event) {
switch (event) {
case ConfigState_e::networksConfigUpdated:
this->begin();
break;
default:
break;
}
}
std::string WiFiHandler::getName() {
return "WiFiHandler";
}

View File

@ -0,0 +1,39 @@
#pragma once
#ifndef WIFIHANDLER_HPP
#define WIFIHANDLER_HPP
#include <string>
#include "data/config/project_config.hpp"
#include "data/utilities/Observer.hpp"
class WiFiHandler : public IObserver<ConfigState_e> {
public:
WiFiHandler(ProjectConfig& configManager,
const std::string& ssid,
const std::string& password,
uint8_t channel);
virtual ~WiFiHandler();
void begin();
void update(ConfigState_e event) override;
std::string getName() override;
bool _enable_adhoc;
private:
void setUpADHOC();
void adhoc(const std::string& ssid,
uint8_t channel,
const std::string& password = std::string());
bool iniSTA(const std::string& ssid,
const std::string& password,
uint8_t channel,
wifi_power_t power);
ProjectConfig& configManager;
std::string ssid;
std::string password;
uint8_t channel;
uint8_t power;
};
#endif // WIFIHANDLER_HPP

View File

@ -10,17 +10,19 @@
// const char *BaseAPI::MIMETYPE_ICO{"image/x-icon"};
const char* BaseAPI::MIMETYPE_JSON{"application/json"};
BaseAPI::BaseAPI(ProjectConfig* projectConfig,
CameraHandler* camera,
StateManager<WiFiState_e>* WiFiStateManager,
BaseAPI::BaseAPI(ProjectConfig& projectConfig,
#ifndef SIM_ENABLED
CameraHandler& camera,
#endif // SIM_ENABLED
const std::string& api_url,
int port)
: projectConfig(projectConfig),
const int CONTROL_PORT)
: server(CONTROL_PORT),
projectConfig(projectConfig),
#ifndef SIM_ENABLED
camera(camera),
wiFiStateManager(wiFiStateManager),
server(port),
api_url(api_url),
_authRequired(false) {}
#endif // SIM_ENABLED
api_url(api_url) {
}
BaseAPI::~BaseAPI() {}
@ -97,13 +99,13 @@ void BaseAPI::setWiFi(AsyncWebServerRequest* request) {
}
// note: We're passing empty params by design, this is done to reset
// specific fields
projectConfig->setWifiConfig(networkName, ssid, password, &channel,
&power, adhoc, true);
projectConfig.setWifiConfig(networkName, ssid, password, channel, power,
adhoc, true);
/* if (WiFiStateManager->getCurrentState() ==
WiFiState_e::WiFiState_ADHOC)
{
projectConfig->setAPWifiConfig(ssid, password, &channel, adhoc,
projectConfig.setAPWifiConfig(ssid, password, &channel, adhoc,
true);
}
else
@ -116,7 +118,7 @@ void BaseAPI::setWiFi(AsyncWebServerRequest* request) {
break;
}
case DELETE: {
projectConfig->deleteWifiConfig(request->arg("networkName").c_str(),
projectConfig.deleteWifiConfig(request->arg("networkName").c_str(),
true);
request->send(200, MIMETYPE_JSON,
"{\"msg\":\"Done. Wifi Creds have been deleted.\"}");
@ -135,22 +137,22 @@ void BaseAPI::getJsonConfig(AsyncWebServerRequest* request) {
switch (_networkMethodsMap_enum[request->method()]) {
case GET: {
std::string wifiConfigSerialized = "\"wifi_config\": [";
auto networksConfigs = projectConfig->getWifiConfigs();
for (auto networkIterator = networksConfigs->begin();
networkIterator != networksConfigs->end(); networkIterator++) {
wifiConfigSerialized +=
networkIterator->toRepresentation() +
(std::next(networkIterator) != networksConfigs->end() ? "," : "");
auto networksConfigs = projectConfig.getWifiConfigs();
for (auto& networkConfig : networksConfigs) {
wifiConfigSerialized += networkConfig.toRepresentation();
if (&networkConfig != &networksConfigs.back())
wifiConfigSerialized += ",";
}
wifiConfigSerialized += "]";
std::string json = Helpers::format_string(
"{%s, %s, %s, %s, %s}",
projectConfig->getDeviceConfig()->toRepresentation().c_str(),
projectConfig->getCameraConfig()->toRepresentation().c_str(),
projectConfig.getDeviceConfig().toRepresentation().c_str(),
projectConfig.getCameraConfig().toRepresentation().c_str(),
wifiConfigSerialized.c_str(),
projectConfig->getMDNSConfig()->toRepresentation().c_str(),
projectConfig->getAPWifiConfig()->toRepresentation().c_str());
projectConfig.getMDNSConfig().toRepresentation().c_str(),
projectConfig.getAPWifiConfig().toRepresentation().c_str());
request->send(200, MIMETYPE_JSON, json.c_str());
break;
}
@ -198,8 +200,8 @@ void BaseAPI::setDeviceConfig(AsyncWebServerRequest* request) {
}
// note: We're passing empty params by design, this is done to reset
// specific fields
projectConfig->setDeviceConfig(ota_login, ota_password, ota_port, true);
projectConfig->setMDNSConfig(hostname, service, true);
projectConfig.setDeviceConfig(ota_login, ota_password, ota_port, true);
projectConfig.setMDNSConfig(hostname, service, true);
request->send(200, MIMETYPE_JSON,
"{\"msg\":\"Done. Device Config has been set.\"}");
}
@ -219,8 +221,8 @@ void BaseAPI::setWiFiTXPower(AsyncWebServerRequest* request) {
txPower = atoi(param->value().c_str());
}
}
projectConfig->setWiFiTxPower(&txPower, true);
projectConfig->wifiTxPowerConfigSave();
projectConfig.setWiFiTxPower(txPower, true);
projectConfig.wifiTxPowerConfigSave();
request->send(200, MIMETYPE_JSON,
"{\"msg\":\"Done. TX Power has been set.\"}");
break;
@ -236,8 +238,8 @@ void BaseAPI::setWiFiTXPower(AsyncWebServerRequest* request) {
txPower = atoi(param->value().c_str());
}
}
projectConfig->setWiFiTxPower(&txPower, true);
projectConfig->wifiTxPowerConfigSave();
projectConfig.setWiFiTxPower(txPower, true);
projectConfig.wifiTxPowerConfigSave();
request->send(200, MIMETYPE_JSON,
"{\"msg\":\"Done. TX Power has been set.\"}");
}
@ -261,7 +263,7 @@ void BaseAPI::factoryReset(AsyncWebServerRequest* request) {
switch (_networkMethodsMap_enum[request->method()]) {
case GET: {
log_d("Factory Reset");
projectConfig->reset();
projectConfig.reset();
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Factory Reset\"}");
}
default: {
@ -274,7 +276,7 @@ void BaseAPI::factoryReset(AsyncWebServerRequest* request) {
//*********************************************************************************************
//! Camera Command Functions
//*********************************************************************************************
#ifndef SIM_ENABLED
void BaseAPI::setCamera(AsyncWebServerRequest* request) {
switch (_networkMethodsMap_enum[request->method()]) {
case GET: {
@ -305,9 +307,9 @@ void BaseAPI::setCamera(AsyncWebServerRequest* request) {
}
// note: We're passing empty params by design, this is done to reset
// specific fields
projectConfig->setCameraConfig(&temp_camera_vflip, &temp_camera_framesize,
&temp_camera_hflip, &temp_camera_quality,
&temp_camera_brightness, true);
projectConfig.setCameraConfig(temp_camera_vflip, temp_camera_framesize,
temp_camera_hflip, temp_camera_quality,
temp_camera_brightness, true);
request->send(200, MIMETYPE_JSON,
"{\"msg\":\"Done. Camera Settings have been set.\"}");
@ -323,11 +325,12 @@ void BaseAPI::setCamera(AsyncWebServerRequest* request) {
void BaseAPI::restartCamera(AsyncWebServerRequest* request) {
bool mode = (bool)atoi(request->arg("mode").c_str());
camera->resetCamera(mode);
camera.resetCamera(mode);
request->send(200, MIMETYPE_JSON,
"{\"msg\":\"Done. Camera had been restarted.\"}");
}
#endif // SIM_ENABLED
//*********************************************************************************************
//! General Command Functions
@ -338,7 +341,7 @@ void BaseAPI::ping(AsyncWebServerRequest* request) {
}
void BaseAPI::save(AsyncWebServerRequest* request) {
projectConfig->save();
projectConfig.save();
request->send(200, MIMETYPE_JSON, "{\"msg\": \"ok\" }");
}
@ -372,10 +375,10 @@ void BaseAPI::checkAuthentication(AsyncWebServerRequest* request,
void BaseAPI::beginOTA() {
// NOTE: Code adapted from: https://github.com/ayushsharma82/AsyncElegantOTA/
auto device_config = projectConfig->getDeviceConfig();
auto mdns_config = projectConfig->getMDNSConfig();
auto device_config = projectConfig.getDeviceConfig();
auto mdns_config = projectConfig.getMDNSConfig();
if (device_config->OTAPassword.empty()) {
if (device_config.OTAPassword.empty()) {
log_e(
"Password is empty, you need to provide a password in order to setup "
"the OTA server");
@ -386,13 +389,13 @@ void BaseAPI::beginOTA() {
log_i(
"[OTA Server]: Navigate to http://%s.local:81/update to update the "
"firmware",
mdns_config->hostname.c_str());
mdns_config.hostname.c_str());
log_d("[OTA Server]: Username: %s, Password: %s",
device_config->OTALogin.c_str(), device_config->OTAPassword.c_str());
device_config.OTALogin.c_str(), device_config.OTAPassword.c_str());
log_d("[DEBUG] Free Heap: %d", ESP.getFreeHeap());
const char* login = device_config->OTALogin.c_str();
const char* password = device_config->OTAPassword.c_str();
const char* login = device_config.OTALogin.c_str();
const char* password = device_config.OTAPassword.c_str();
log_d("[DEBUG] Free Heap: %d", ESP.getFreeHeap());
// Note: HTTP_GET

View File

@ -1,6 +1,9 @@
#ifndef BASEAPI_HPP
#define BASEAPI_HPP
//! Warning do not format this file with clang-format or it will break the code
#include <unordered_map>
#include <string>
#include <unordered_map>
@ -97,32 +100,33 @@ class BaseAPI {
typedef std::unordered_map<std::string, WebRequestMethodComposite>
networkMethodsMap_t;
ProjectConfig* projectConfig;
/// @brief Local instance of the AsyncWebServer - so that we dont need to use
/// new and delete
CameraHandler* camera;
StateManager<WiFiState_e>* wiFiStateManager;
AsyncWebServer server;
public:
BaseAPI(ProjectConfig* projectConfig,
CameraHandler* camera,
StateManager<WiFiState_e>* wiFiStateManager,
const std::string& api_url,
ProjectConfig &projectConfig;
/// @brief Local instance of the AsyncWebServer - so that we dont need to use new and delete
AsyncWebServer server;
#ifndef SIM_ENABLED
int port = 81
CameraHandler &camera;
#endif // SIM_ENABLED
public :
BaseAPI(ProjectConfig& projectConfig,
#ifndef SIM_ENABLED
CameraHandler& camera,
#endif // SIM_ENABLED
const std::string& api_url,
#ifndef SIM_ENABLED
int port = 81
#else
int port = 80
int port = 80
#endif
);
virtual ~BaseAPI();
virtual void begin();
void checkAuthentication(AsyncWebServerRequest* request,
const char* login,
const char* password);
void beginOTA();
void notFound(AsyncWebServerRequest* request) const;
virtual ~BaseAPI();
virtual void begin();
void checkAuthentication(AsyncWebServerRequest* request,
const char* login,
const char* password);
void beginOTA();
void notFound(AsyncWebServerRequest* request) const;
};
#endif // BASEAPI_HPP

View File

@ -4,11 +4,17 @@
//! API Server
//*********************************************************************************************
APIServer::APIServer(ProjectConfig* projectConfig,
CameraHandler* camera,
StateManager<WiFiState_e>* wiFiStateManager,
APIServer::APIServer(ProjectConfig& projectConfig,
#ifndef SIM_ENABLED
CameraHandler& camera,
#endif // SIM_ENABLED
const std::string& api_url)
: BaseAPI(projectConfig, camera, wiFiStateManager, api_url) {}
: BaseAPI(projectConfig,
#ifndef SIM_ENABLED
camera,
#endif // SIM_ENABLED
api_url) {
}
APIServer::~APIServer() {}
@ -22,16 +28,13 @@ void APIServer::setup() {
"^\\%s\\/([a-zA-Z0-9]+)\\/command\\/([a-zA-Z0-9]+)$",
this->api_url.c_str());
log_d("API URL: %s", buffer);
this->server.on(buffer, 0b01111111, [&](AsyncWebServerRequest* request) {
handleRequest(request);
server.on(buffer, 0b01111111, [&](AsyncWebServerRequest* request) {
handleRequest(request);
});
// Note: Start OTA after all routes have been added
#ifndef SIM_ENABLED
//this->_authRequired = true;
//this->_authRequired = true;
#endif // SIM_ENABLED
this->beginOTA();
beginOTA();
server.begin();
}
@ -43,8 +46,10 @@ void APIServer::setupServer() {
routes.emplace("getStoredConfig", &APIServer::getJsonConfig);
routes.emplace("setTxPower", &APIServer::setWiFiTXPower);
// Camera Routes
#ifndef SIM_ENABLED
routes.emplace("setCamera", &APIServer::setCamera);
routes.emplace("restartCamera", &APIServer::restartCamera);
#endif // SIM_ENABLED
routes.emplace("ping", &APIServer::ping);
routes.emplace("save", &APIServer::save);
routes.emplace("wifiStrength", &APIServer::rssi);
@ -57,14 +62,6 @@ void APIServer::setupServer() {
indexes); // add new route map to the route_map
}
void APIServer::findParam(AsyncWebServerRequest* request,
const char* param,
std::string& value) {
if (request->hasParam(param)) {
value = request->getParam(param)->value().c_str();
}
}
/**
* @brief Add a command handler to the API
*

View File

@ -6,17 +6,15 @@
class APIServer : public BaseAPI {
public:
APIServer(ProjectConfig* projectConfig,
CameraHandler* camera,
StateManager<WiFiState_e>* wiFiStateManager,
APIServer(ProjectConfig& projectConfig,
#ifndef SIM_ENABLED
CameraHandler& camera,
#endif // SIM_ENABLED
const std::string& api_url);
virtual ~APIServer();
void setup();
void setupServer();
void findParam(AsyncWebServerRequest* request,
const char* param,
std::string& value);
void addRouteMap(const std::string& index,
route_t route,
std::vector<std::string>& indexes);

View File

@ -1,35 +1,37 @@
#include "MDNSManager.hpp"
MDNSHandler::MDNSHandler(StateManager<MDNSState_e>* stateManager,
ProjectConfig* configManager)
: stateManager(stateManager), configManager(configManager) {}
MDNSHandler::MDNSHandler(ProjectConfig& configManager)
: configManager(configManager) {}
bool MDNSHandler::startMDNS() {
const std::string service = "_openiristracker";
ProjectConfig::MDNSConfig_t* mdnsConfig = configManager->getMDNSConfig();
if (!MDNS.begin(mdnsConfig->hostname
auto mdnsConfig = configManager.getMDNSConfig();
if (!MDNS.begin(mdnsConfig.hostname
.c_str())) // lowercase only - as this will be the url
{
stateManager->setState(MDNSState_e::MDNSState_Error);
mdnsStateManager.setState(MDNSState_e::MDNSState_Error);
log_e("Error initializing MDNS");
return false;
}
stateManager->setState(MDNSState_e::MDNSState_Starting);
mdnsStateManager.setState(MDNSState_e::MDNSState_Starting);
MDNS.addService(service.c_str(), "_tcp", 80);
char port[20];
//! Add service needs leading _ on ESP32 implementation for some reason
//! (according to the docs)
MDNS.addServiceTxt(service.c_str(), "_tcp", "stream_port",
"80");
MDNS.addServiceTxt(service.c_str(), "_tcp", "stream_port", "80");
log_i("MDNS initialized!");
stateManager->setState(MDNSState_e::MDNSState_Started);
mdnsStateManager.setState(MDNSState_e::MDNSState_Started);
return true;
}
void MDNSHandler::update(ObserverEvent::Event event) {
std::string MDNSHandler::getName() {
return "MDNSHandler";
}
void MDNSHandler::update(ConfigState_e event) {
switch (event) {
case ObserverEvent::Event::mdnsConfigUpdated:
case ConfigState_e::mdnsConfigUpdated:
MDNS.end();
startMDNS();
break;

View File

@ -2,21 +2,19 @@
#define MDNSHANDLER_HPP
#include <ESPmDNS.h>
#include "data/StateManager/StateManager.hpp"
#include "data/config/project_config.hpp"
#include "data/utilities/Observer.hpp"
#include "data/utilities/helpers.hpp"
#include "data/config/project_config.hpp"
class MDNSHandler : public IObserver
{
private:
StateManager<MDNSState_e> *stateManager;
ProjectConfig *configManager;
class MDNSHandler : public IObserver<ConfigState_e> {
private:
ProjectConfig& configManager;
public:
MDNSHandler(StateManager<MDNSState_e> *stateManager,
ProjectConfig *configManager);
bool startMDNS();
void update(ObserverEvent::Event event);
public:
MDNSHandler(ProjectConfig& configManager);
bool startMDNS();
void update(ConfigState_e event) override;
std::string getName() override;
};
#endif // MDNSHANDLER_HPP
#endif // MDNSHANDLER_HPP

View File

@ -74,9 +74,7 @@ esp_err_t StreamHelpers::stream(httpd_req_t *req)
return res;
}
StreamServer::StreamServer(int STREAM_PORT,
StateManager<WiFiState_e> *stateManager) : STREAM_SERVER_PORT(STREAM_PORT),
stateManager(stateManager) {}
StreamServer::StreamServer(const int STREAM_PORT) : STREAM_SERVER_PORT(STREAM_PORT) {}
int StreamServer::startStreamServer()
{
@ -102,7 +100,7 @@ int StreamServer::startStreamServer()
{
httpd_register_uri_handler(camera_stream, &stream_page);
Serial.println("Stream server initialized");
switch (stateManager->getCurrentState())
switch (wifiStateManager.getCurrentState())
{
case WiFiState_e::WiFiState_ADHOC:
Serial.printf("\n\rThe stream is under: http://%s:%i\n\r", WiFi.softAPIP().toString().c_str(), this->STREAM_SERVER_PORT);

View File

@ -23,11 +23,9 @@ class StreamServer
private:
httpd_handle_t camera_stream = nullptr;
int STREAM_SERVER_PORT;
StateManager<WiFiState_e> *stateManager;
public:
StreamServer(int STREAM_PORT,
StateManager<WiFiState_e> *stateManager);
StreamServer(const int STREAM_PORT = 80);
int startStreamServer();
};

View File

@ -0,0 +1,165 @@
#include "wifihandler.hpp"
#include <WiFi.h>
#include "data/StateManager/StateManager.hpp"
#include "data/utilities/helpers.hpp"
WiFiHandler::WiFiHandler(ProjectConfig& configManager,
const std::string& ssid,
const std::string& password,
uint8_t channel)
: configManager(configManager),
ssid(ssid),
password(password),
channel(channel),
power(0),
_enable_adhoc(false) {}
WiFiHandler::~WiFiHandler() {}
void WiFiHandler::begin() {
if (this->_enable_adhoc ||
wifiStateManager.getCurrentState() == WiFiState_e::WiFiState_ADHOC) {
this->setUpADHOC();
return;
}
auto txpower = configManager.getWiFiTxPowerConfig();
WiFi.mode(WIFI_STA);
WiFi.setSleep(WIFI_PS_NONE);
log_i("Initializing connection to wifi \n\r");
wifiStateManager.setState(WiFiState_e::WiFiState_Connecting);
auto networks = configManager.getWifiConfigs();
if (networks.empty()) {
log_i("No networks found in config, trying the default one \n\r");
if (this->iniSTA(this->ssid, this->password, this->channel,
(wifi_power_t)txpower.power)) {
return;
}
log_i(
"Could not connect to the hardcoded network, setting up ADHOC "
"network \n\r");
this->setUpADHOC();
return;
}
for (auto& network : networks) {
log_i("Trying to connect to network: %s \n\r", network.ssid.c_str());
if (this->iniSTA(network.ssid, network.password, network.channel,
(wifi_power_t)txpower.power)) {
return;
}
}
// at this point, we've tried every network, let's just setup adhoc
log_i(
"We've gone through every network, each timed out. Trying to connect "
"to hardcoded network: %s \n\r",
this->ssid.c_str());
if (this->iniSTA(this->ssid, this->password, this->channel,
(wifi_power_t)txpower.power)) {
log_i("Successfully connected to the hardcoded network. \n\r");
return;
}
log_i(
"Could not connect to the hardcoded network, setting up adhoc. "
"\n\r");
this->setUpADHOC();
}
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");
WiFi.mode(WIFI_AP);
WiFi.setSleep(WIFI_PS_NONE);
Serial.printf("\r\nStarting AP. \r\n");
IPAddress IP = WiFi.softAPIP();
Serial.printf("[INFO]: AP IP address: %s.\r\n", IP.toString().c_str());
// You can remove the password parameter if you want the AP to be open.
ProjectConfig::WiFiTxPower_t txpower = configManager.getWiFiTxPowerConfig();
WiFi.softAP(ssid.c_str(), password.c_str(),
channel); // AP mode with password
WiFi.setTxPower((wifi_power_t)txpower.power);
}
void WiFiHandler::setUpADHOC() {
log_i("\n[INFO]: Setting Up Access Point...\n");
size_t ssidLen = configManager.getAPWifiConfig().ssid.length();
size_t passwordLen = configManager.getAPWifiConfig().password.length();
if (ssidLen <= 0) {
log_i("\n[INFO]: Configuring access point with default values\n");
this->adhoc(WIFI_AP_SSID, WIFI_AP_CHANNEL, WIFI_AP_PASSWORD);
return;
}
if (passwordLen <= 0) {
log_i("\n[INFO]: Configuring access point without a password\n");
this->adhoc(configManager.getAPWifiConfig().ssid,
configManager.getAPWifiConfig().channel);
return;
}
this->adhoc(configManager.getAPWifiConfig().ssid,
configManager.getAPWifiConfig().channel,
configManager.getAPWifiConfig().password);
log_i("\n[INFO]: Configuring access point...\n");
log_d("\n[DEBUG]: ssid: %s\n", configManager.getAPWifiConfig().ssid.c_str());
log_d("\n[DEBUG]: password: %s\n",
configManager.getAPWifiConfig().password.c_str());
log_d("\n[DEBUG]: channel: %d\n", configManager.getAPWifiConfig().channel);
}
bool WiFiHandler::iniSTA(const std::string& ssid,
const std::string& password,
uint8_t channel,
wifi_power_t power) {
unsigned long currentMillis = millis();
unsigned long startingMillis = currentMillis;
int connectionTimeout = 30000; // 30 seconds
int progress = 0;
wifiStateManager.setState(WiFiState_e::WiFiState_Connecting);
log_i("Trying to connect to: %s \n\r", ssid.c_str());
auto mdnsConfig = configManager.getMDNSConfig();
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE,
INADDR_NONE); // need to call before setting hostname
WiFi.setHostname(mdnsConfig.hostname.c_str());
WiFi.begin(ssid.c_str(), password.c_str(), channel);
while (WiFi.status() != WL_CONNECTED) {
progress++;
currentMillis = millis();
Helpers::update_progress_bar(progress, 100);
delay(301);
if ((currentMillis - startingMillis) >= connectionTimeout) {
wifiStateManager.setState(WiFiState_e::WiFiState_Error);
log_e("Connection to: %s TIMEOUT \n\r", ssid.c_str());
return false;
}
}
wifiStateManager.setState(WiFiState_e::WiFiState_Connected);
log_i("Successfully connected to %s \n\r", ssid.c_str());
log_i("Setting TX power to: %d \n\r", (uint8_t)power);
WiFi.setTxPower(power);
return true;
}
void WiFiHandler::update(ConfigState_e event) {
switch (event) {
case ConfigState_e::networksConfigUpdated:
this->begin();
break;
default:
break;
}
}
std::string WiFiHandler::getName() {
return "WiFiHandler";
}

View File

@ -0,0 +1,39 @@
#pragma once
#ifndef WIFIHANDLER_HPP
#define WIFIHANDLER_HPP
#include <string>
#include "data/config/project_config.hpp"
#include "data/utilities/Observer.hpp"
class WiFiHandler : public IObserver<ConfigState_e> {
public:
WiFiHandler(ProjectConfig& configManager,
const std::string& ssid,
const std::string& password,
uint8_t channel);
virtual ~WiFiHandler();
void begin();
void update(ConfigState_e event) override;
std::string getName() override;
bool _enable_adhoc;
private:
void setUpADHOC();
void adhoc(const std::string& ssid,
uint8_t channel,
const std::string& password = std::string());
bool iniSTA(const std::string& ssid,
const std::string& password,
uint8_t channel,
wifi_power_t power);
ProjectConfig& configManager;
std::string ssid;
std::string password;
uint8_t channel;
uint8_t power;
};
#endif // WIFIHANDLER_HPP

View File

@ -1,15 +1,14 @@
#include <Arduino.h>
#include <io/LEDManager/LEDManager.hpp>
#include <io/camera/cameraHandler.hpp>
#include <network/WifiHandler/WifiHandler.hpp>
#include <network/api/webserverHandler.hpp>
#include <network/mDNS/MDNSManager.hpp>
#include <network/stream/streamServer.hpp>
#include <network/wifihandler/wifihandler.hpp>
#include <data/config/project_config.hpp>
#include <logo/logo.hpp>
int STREAM_SERVER_PORT = 80;
/**
* @brief ProjectConfig object
* @brief This is the main configuration object for the project
@ -18,30 +17,25 @@ int STREAM_SERVER_PORT = 80;
*/
ProjectConfig deviceConfig("openiris", MDNS_HOSTNAME);
LEDManager ledManager(33, &ledStateManager);
LEDManager ledManager(33);
#ifndef SIM_ENABLED
CameraHandler cameraHandler(&deviceConfig, &ledStateManager);
CameraHandler cameraHandler(deviceConfig);
#endif // SIM_ENABLED
WiFiHandler wifiHandler(&deviceConfig,
&wifiStateManager,
&ledStateManager,
WIFI_SSID,
WIFI_PASSWORD,
WIFI_CHANNEL);
WiFiHandler wifiHandler(deviceConfig, WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL);
// ImprovHandler improvHandler(deviceConfig);
#ifndef SIM_ENABLED
APIServer apiServer(&deviceConfig,
&cameraHandler,
&wifiStateManager,
"/control");
APIServer apiServer(deviceConfig, cameraHandler, "/control");
#else
APIServer apiServer(&deviceConfig, NULL, &wifiStateManager, "/control");
APIServer apiServer(deviceConfig, wifiStateManager, "/control");
#endif // SIM_ENABLED
MDNSHandler mdnsHandler(&mdnsStateManager, &deviceConfig);
MDNSHandler mdnsHandler(deviceConfig);
#ifndef SIM_ENABLED
StreamServer streamServer(STREAM_SERVER_PORT, &wifiStateManager);
StreamServer streamServer;
#endif // SIM_ENABLED
void setup() {
@ -51,13 +45,14 @@ void setup() {
Serial.flush();
ledManager.begin();
#ifndef SIM_ENABLED
deviceConfig.attach(&cameraHandler);
deviceConfig.attach(cameraHandler);
#endif // SIM_ENABLED
deviceConfig.attach(&mdnsHandler);
deviceConfig.attach(mdnsHandler);
deviceConfig.attach(wifiHandler);
deviceConfig.initConfig();
deviceConfig.load();
wifiHandler._enable_adhoc = ENABLE_ADHOC;
wifiHandler.setupWifi();
wifiHandler.begin();
mdnsHandler.startMDNS();
switch (wifiStateManager.getCurrentState()) {

View File

@ -144,6 +144,9 @@ def customName(project, version, commit, branch):
"echo %s > %s" % (env["PROGNAME"], env.subst("./tools/firmware_name.txt"))
)
# replace the VERSION macro with the version from Git
env.Replace(VERSION="%s" % (s(defines.get("PIO_SRC_TAG"))))
try:
flags = env["BUILD_FLAGS"]

View File

@ -1,7 +1,7 @@
[wokwi]
version = 1
elf = ".pio/build/esp32AIThinker_sim/OpenIris-v1.10.6-esp32AIThinker_sim-44d44d5-feautre-elegant-ota.elf"
firmware = ".pio/build/esp32AIThinker_sim/OpenIris-v1.10.6-esp32AIThinker_sim-44d44d5-feautre-elegant-ota.bin"
elf = ".pio/build/esp32AIThinker_sim/OpenIris-v1.10.6-esp32AIThinker_sim-c0391d0-feature-improv.elf"
firmware = ".pio/build/esp32AIThinker_sim/OpenIris-v1.10.6-esp32AIThinker_sim-c0391d0-feature-improv.bin"
[[net.forward]]
from = "localhost:8180"
to = "target:80"