Major Update

- migrate the rest of the toRepresentation methods out of header file
- optimize toRepresentation methods
- add query service to set up service name and hostname
This commit is contained in:
ZanzyTHEbar 2022-11-01 22:12:16 +00:00
parent 746a0a9f9b
commit 326ec8e4cd
12 changed files with 223 additions and 89 deletions

View File

@ -82,7 +82,9 @@ struct DeviceStates
MDNSState_Started,
MDNSState_Stopping,
MDNSState_Stopped,
MDNSState_Error
MDNSState_Error,
MDNSState_QueryStarted,
MDNSState_QueryComplete
};
enum CameraState_e

View File

@ -28,11 +28,15 @@ void ProjectConfig::initConfig()
! as it will create a blank network which breaks the WiFiManager
*/
this->config.device = {
_name,
"12345678",
3232,
};
this->config.mdns = {
"openiristracker",
"",
};
this->config.ap_network = {
"",
"",
@ -53,6 +57,7 @@ void ProjectConfig::save()
{
log_d("Saving project config");
deviceConfigSave();
mdnsConfigSave();
cameraConfigSave();
wifiConfigSave();
end(); // we call end() here to close the connection to the NVS partition, we only do this because we call ESP.restart() next.
@ -102,10 +107,15 @@ void ProjectConfig::wifiConfigSave()
void ProjectConfig::deviceConfigSave()
{
/* Device Config */
putString("deviceName", this->config.device.name.c_str());
putString("OTAPassword", this->config.device.OTAPassword.c_str());
putInt("OTAPort", this->config.device.OTAPort);
//! No need to save the JSON strings or bools, they are generated and used on the fly
}
void ProjectConfig::mdnsConfigSave()
{
/* Device Config */
putString("hostname", this->config.mdns.hostname.c_str());
putString("service", this->config.mdns.service.c_str());
}
void ProjectConfig::cameraConfigSave()
@ -134,11 +144,12 @@ void ProjectConfig::load()
}
/* Device Config */
this->config.device.name = getString("deviceName", "openiristracker").c_str();
this->config.device.OTAPassword = getString("OTAPassword", "12345678").c_str();
this->config.device.OTAPort = getInt("OTAPort", 3232);
//! No need to load the JSON strings or bools, they are generated and used on the fly
/* MDNS Config */
this->config.mdns.hostname = getString("hostname").c_str();
this->config.mdns.service = getString("service").c_str();
/* WiFi Config */
int networkCount = getInt("networkCount", 0);
std::string name = "name";
@ -195,10 +206,9 @@ void ProjectConfig::load()
//! DeviceConfig
//*
//**********************************************************************************************************************
void ProjectConfig::setDeviceConfig(const std::string &name, const std::string &OTAPassword, int *OTAPort, bool shouldNotify)
void ProjectConfig::setDeviceConfig(const std::string &OTAPassword, int *OTAPort, bool shouldNotify)
{
log_d("Updating device config");
this->config.device.name.assign(name);
this->config.device.OTAPassword.assign(OTAPassword);
this->config.device.OTAPort = *OTAPort;
@ -206,6 +216,16 @@ void ProjectConfig::setDeviceConfig(const std::string &name, const std::string &
this->notify(ObserverEvent::deviceConfigUpdated);
}
void ProjectConfig::setMDNSConfig(const std::string &hostname, const std::string &service, bool shouldNotify)
{
log_d("Updating MDNS config");
this->config.mdns.hostname.assign(hostname);
this->config.mdns.service.assign(service);
if (shouldNotify)
this->notify(ObserverEvent::mdnsConfigUpdated);
}
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");
@ -277,21 +297,55 @@ void ProjectConfig::setAPWifiConfig(const std::string &ssid, const std::string &
std::string ProjectConfig::DeviceConfig_t::toRepresentation()
{
std::string json = Helpers::format_string(
"device_config: {\"name\": \"%s\", \"OTAPassword\": \"%s\", \"OTAPort\": %u}",
this->name.c_str(),
"device_config: {\"OTAPassword\": \"%s\", \"OTAPort\": %u}",
this->OTAPassword.c_str(),
this->OTAPort);
return json;
}
std::string ProjectConfig::CameraConfig_t::toRepresentation()
{
std::string json = Helpers::format_string("camera_config: {\"vflip\": %d,\"framesize\": %d,\"href\": %d,\"quality\": %d,\"brightness\": %d}",
this->vflip,
this->framesize,
this->href,
this->quality,
this->brightness);
std::string json = Helpers::format_string(
"camera_config: {\"vflip\": %d,\"framesize\": %d,\"href\": %d,\"quality\": %d,\"brightness\": %d}",
this->vflip,
this->framesize,
this->href,
this->quality,
this->brightness);
return json;
}
}
std::string ProjectConfig::WiFiConfig_t::toRepresentation()
{
std::string json = Helpers::format_string(
"wifi_config: {\"name\": \"%s\", \"ssid\": \"%s\", \"password\": \"%s\", \"channel\": %u, \"adhoc\": %s}",
this->name.c_str(),
this->ssid.c_str(),
this->password.c_str(),
this->channel,
this->adhoc ? "true" : "false");
return json;
}
std::string ProjectConfig::AP_WiFiConfig_t::toRepresentation()
{
std::string json = Helpers::format_string(
"ap_wifi_config: {\"ssid\": \"%s\", \"password\": \"%s\", \"channel\": %u, \"adhoc\": %s}",
this->ssid.c_str(),
this->password.c_str(),
this->channel,
this->adhoc ? "true" : "false");
return json;
}
//**********************************************************************************************************************
//*
//! Get Methods
//*
//**********************************************************************************************************************
ProjectConfig::DeviceConfig_t *ProjectConfig::getDeviceConfig() { return &this->config.device; }
ProjectConfig::CameraConfig_t *ProjectConfig::getCameraConfig() { return &this->config.camera; }
std::vector<ProjectConfig::WiFiConfig_t> *ProjectConfig::getWifiConfigs() { return &this->config.networks; }
ProjectConfig::AP_WiFiConfig_t *ProjectConfig::getAPWifiConfig() { return &this->config.ap_network; }
ProjectConfig::MDNSConfig_t *ProjectConfig::getMDNSConfig() { return &this->config.mdns; }

View File

@ -19,15 +19,21 @@ public:
void wifiConfigSave();
void cameraConfigSave();
void deviceConfigSave();
void mdnsConfigSave();
bool reset();
void initConfig();
struct DeviceConfig_t
{
std::string name;
std::string OTAPassword;
int OTAPort;
std::string toRepresentation();
};
struct MDNSConfig_t
{
std::string hostname;
std::string service;
std::string toRepresentation();
};
@ -60,18 +66,7 @@ public:
uint8_t channel;
bool adhoc;
const char *toRepresentation()
{
char *p = (char *)"wifi_entry: {";
p += sprintf(p, "\"name\":%s,", this->name);
p += sprintf(p, "\"ssid\":%s,", this->ssid);
p += sprintf(p, "\"password\":%s,", this->password);
p += sprintf(p, "\"channel\":%u,", this->channel);
p += sprintf(p, "\"adhoc\":%u", this->adhoc);
p += sprintf(p, "},");
*p++ = 0;
return p;
}
std::string toRepresentation();
};
struct AP_WiFiConfig_t
@ -80,17 +75,7 @@ public:
std::string password;
uint8_t channel;
bool adhoc;
const char *toRepresentation()
{
char *p = (char *)"adhoc_network: {";
p += sprintf(p, "\"ssid\":%s,", this->ssid);
p += sprintf(p, "\"password\":%s,", this->password);
p += sprintf(p, "\"channel\":%u,", this->channel);
p += sprintf(p, "\"adhoc\":%d", this->adhoc);
p += sprintf(p, "},");
*p++ = 0;
return p;
}
std::string toRepresentation();
};
struct TrackerConfig_t
@ -99,14 +84,17 @@ public:
CameraConfig_t camera;
std::vector<WiFiConfig_t> networks;
AP_WiFiConfig_t ap_network;
MDNSConfig_t mdns;
};
DeviceConfig_t *getDeviceConfig() { return &this->config.device; }
CameraConfig_t *getCameraConfig() { return &this->config.camera; }
std::vector<WiFiConfig_t> *getWifiConfigs() { return &this->config.networks; }
AP_WiFiConfig_t *getAPWifiConfig() { return &this->config.ap_network; }
DeviceConfig_t *getDeviceConfig();
CameraConfig_t *getCameraConfig();
std::vector<WiFiConfig_t> *getWifiConfigs();
AP_WiFiConfig_t *getAPWifiConfig();
MDNSConfig_t *getMDNSConfig();
void setDeviceConfig(const std::string &name, const std::string &OTAPassword, int *OTAPort, bool shouldNotify);
void setDeviceConfig(const std::string &OTAPassword, int *OTAPort, bool shouldNotify);
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, bool shouldNotify);
void setWifiConfig(const std::string &networkName, const std::string &ssid, const std::string &password, uint8_t *channel, bool adhoc, bool shouldNotify);
void setAPWifiConfig(const std::string &ssid, const std::string &password, uint8_t *channel, bool adhoc, bool shouldNotify);

View File

@ -11,6 +11,7 @@ namespace ObserverEvent
deviceConfigUpdated = 2,
cameraConfigUpdated = 3,
networksConfigUpdated = 4,
mdnsConfigUpdated = 5,
};
}

View File

@ -1,7 +1,6 @@
#include "OTA.hpp"
OTA::OTA(ProjectConfig *_deviceConfig, const std::string &hostname) : _deviceConfig(_deviceConfig),
_hostname(std::move(hostname)) {}
OTA::OTA(ProjectConfig *_deviceConfig) : _deviceConfig(_deviceConfig) {}
OTA::~OTA() {}
@ -54,7 +53,8 @@ void OTA::SetupOTA()
log_i("Starting up basic OTA server");
log_i("OTA will be live for 30s, after which it will be disabled until restart");
ArduinoOTA.setHostname(_hostname.c_str());
auto mdnsConfig = _deviceConfig->getMDNSConfig();
ArduinoOTA.setHostname(mdnsConfig->hostname.c_str());
ArduinoOTA.begin();
_bootTimestamp = millis();
}

View File

@ -7,8 +7,7 @@
class OTA
{
public:
OTA(ProjectConfig *_deviceConfig,
const std::string &hostname);
OTA(ProjectConfig *_deviceConfig);
virtual ~OTA();
void SetupOTA();
void HandleOTAUpdate();
@ -17,6 +16,5 @@ private:
unsigned long _bootTimestamp = 0;
bool _isOtaEnabled = true;
ProjectConfig *_deviceConfig;
std::string _hostname;
};
#endif // OTA_HPP

View File

@ -130,34 +130,47 @@ void BaseAPI::getJsonConfig(AsyncWebServerRequest *request)
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
}
void BaseAPI::setDeviceConfig(AsyncWebServerRequest *request){
switch (_networkMethodsMap_enum[request->method()]){
case GET:
void BaseAPI::setDeviceConfig(AsyncWebServerRequest *request)
{
switch (_networkMethodsMap_enum[request->method()])
{
case GET:
{
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
break;
}
case POST:
{
int params = request->params();
std::string hostname;
std::string service;
std::string ota_password;
int ota_port;
for (int i = 0; i < params; i++)
{
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
break;
}
case POST: {
int params = request->params();
std::string device_name;
std::string ota_password;
int ota_port;
for (int i = 0; i < params; i++){
AsyncWebParameter *param = request->getParam(i);
if (param->name() == "device_name"){
device_name = param->value().c_str();
}
if (param->name() == "ota_port"){
ota_port = atoi(param->value().c_str());
}
if (param->name() == "ota_password"){
ota_password = param->value().c_str();
}
AsyncWebParameter *param = request->getParam(i);
if (param->name() == "hostname")
{
hostname = param->value().c_str();
}
if (param->name() == "service")
{
service = param->value().c_str();
}
if (param->name() == "ota_port")
{
ota_port = atoi(param->value().c_str());
}
if (param->name() == "ota_password")
{
ota_password = param->value().c_str();
}
projectConfig->setDeviceConfig(device_name, ota_password, &ota_port, true);
}
projectConfig->setDeviceConfig(ota_password, &ota_port, true);
projectConfig->setMDNSConfig(hostname, service, true);
}
}
}

View File

@ -6,15 +6,14 @@ MDNSHandler::MDNSHandler(StateManager<MDNSState_e> *stateManager,
void MDNSHandler::startMDNS()
{
ProjectConfig::DeviceConfig_t *deviceConfig = configManager->getDeviceConfig();
// deviceConfig->name.c_str()
if (MDNS.begin("openiristracker")) // lowercase only - as this will be the url
ProjectConfig::MDNSConfig_t *mdnsConfig = configManager->getMDNSConfig();
if (MDNS.begin(mdnsConfig->hostname.c_str())) // lowercase only - as this will be the url
{
stateManager->setState(MDNSState_e::MDNSState_Starting);
MDNS.addService(deviceConfig->name.c_str(), "tcp", 80);
MDNS.addService(mdnsConfig->hostname.c_str(), "tcp", 80);
char port[20];
//! Add service needs leading _ on ESP32 implementation for some reason (according to the docs)
MDNS.addServiceTxt(("_" + deviceConfig->name).c_str(), "_tcp", "_stream_port", (const char *)Helpers::itoa(80, port, 10)); //! convert int to const char* using a very efficient implemenation of itoa
MDNS.addServiceTxt(("_" + mdnsConfig->hostname).c_str(), "_tcp", "_stream_port", (const char *)Helpers::itoa(80, port, 10)); //! convert int to const char* using a very efficient implemenation of itoa
log_i("MDNS initialized!");
stateManager->setState(MDNSState_e::MDNSState_Started);
}
@ -29,7 +28,7 @@ void MDNSHandler::update(ObserverEvent::Event event)
{
switch (event)
{
case ObserverEvent::Event::deviceConfigUpdated:
case ObserverEvent::Event::mdnsConfigUpdated:
MDNS.end();
startMDNS();
break;

View File

@ -0,0 +1,65 @@
#include "queryMDNS.hpp"
QueryMDNSService::QueryMDNSService(StateManager<MDNSState_e> *stateManager,
ProjectConfig *configManager) : stateManager(stateManager),
configManager(configManager) {}
QueryMDNSService::~QueryMDNSService()
{
// Finalize the MDNS library
mdns_free();
}
void QueryMDNSService::queryMDNS()
{
stateManager->setState(MDNSState_e::MDNSState_QueryComplete);
ProjectConfig::MDNSConfig_t *mdnsConfig = configManager->getMDNSConfig();
// check if we have a valid MDNS config
if (mdnsConfig->hostname.empty() && mdnsConfig->service.empty())
{
// Initialize the MDNS library
std::string hostname;
std::string service;
// Initialize the MDNS library
if (mdns_init() != ESP_OK)
{
log_e("Error initializing MDNS Query");
return;
}
int services_found = MDNS.queryService("openiristracker", "tcp");
if (services_found == 0)
{
log_e("No services found!");
log_e("Setting a default hostname of 'openiristracker'");
hostname.assign("openiristracker");
log_i("Hostname: %s", hostname.c_str());
service.assign("openiristracker");
}
else
{
log_i("Services found: %d", services_found);
for (int i = 0; i < services_found; i++)
{
log_i("------------------------");
log_i("Service #%d", i);
log_i(" - Hostname: %s", MDNS.hostname(i).c_str());
log_i(" - IP: %s", MDNS.IP(i).toString().c_str());
log_i(" - Port: %d", MDNS.port(i));
log_i("------------------------");
}
// append one greater than the number of services found to the hostname
// this will allow for multiple trackers to be found
hostname.assign(MDNS.hostname(services_found).c_str());
hostname.append(std::to_string(services_found));
service.assign(MDNS.hostname(services_found).c_str());
service.append(std::to_string(services_found));
}
mdns_free(); // Free the MDNS library
stateManager->setState(MDNSState_e::MDNSState_QueryComplete);
return;
}
stateManager->setState(MDNSState_e::MDNSState_QueryComplete);
return;
}

View File

@ -1,13 +1,14 @@
#pragma once
#ifndef QUERYMDNSSERVICE_HPP
#define QUERYMDNSSERVICE_HPP
#include <Arduino.h>
#include <ESPmDNS.h>
#include "data/StateManager/StateManager.hpp"
#include "data/utilities/Observer.hpp"
#include "data/utilities/helpers.hpp"
#include "data/config/project_config.hpp"
class QueryMDNSService : public IObserver
class QueryMDNSService
{
private:
StateManager<MDNSState_e> *stateManager;
@ -16,8 +17,8 @@ private:
public:
QueryMDNSService(StateManager<MDNSState_e> *stateManager,
ProjectConfig *configManager);
virtual ~QueryMDNSService();
void queryMDNS();
void update(ObserverEvent::Event event);
};
#endif // QUERYMDNSSERVICE_HPP

View File

@ -1,10 +1,12 @@
#include <Arduino.h>
#include <network/WifiHandler/WifiHandler.hpp>
#include <network/mDNS/MDNSManager.hpp>
#include <network/mDNS/queryMDNS.hpp>
#include <io/camera/cameraHandler.hpp>
#include <io/LEDManager/LEDManager.hpp>
#include <network/stream/streamServer.hpp>
#include <network/api/webserverHandler.hpp>
//! TODO: Setup OTA enabled state to be controllable by API if enabled at compile time
#if ENABLE_OTA
#include <network/OTA/OTA.hpp>
@ -20,13 +22,14 @@ int CONTROL_SERVER_PORT = 81;
ProjectConfig deviceConfig;
#if ENABLE_OTA
OTA ota(&deviceConfig, "openiristracker");
OTA ota(&deviceConfig);
#endif // ENABLE_OTA
LEDManager ledManager(33);
CameraHandler cameraHandler(&deviceConfig, &ledStateManager);
// SerialManager serialManager(&deviceConfig);
WiFiHandler wifiHandler(&deviceConfig, &wifiStateManager, WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL);
APIServer apiServer(CONTROL_SERVER_PORT, &deviceConfig, &cameraHandler, &wifiStateManager, "/control");
QueryMDNSService mdnsQuery(&mdnsStateManager, &deviceConfig);
MDNSHandler mdnsHandler(&mdnsStateManager, &deviceConfig);
StreamServer streamServer(STREAM_SERVER_PORT);
@ -76,7 +79,17 @@ void setup()
log_d("[SETUP]: Starting Stream Server");
apiServer.begin();
log_d("[SETUP]: Starting API Server");
mdnsHandler.startMDNS();
mdnsQuery.queryMDNS(); // Query MDNS for hostname
switch (mdnsStateManager.getCurrentState())
{
case MDNSState_e::MDNSState_QueryComplete:
{
log_d("[SETUP]: MDNS Query Complete");
mdnsHandler.startMDNS();
break;
}
}
break;
}
case WiFiState_e::WiFiState_Connecting:

View File

@ -1 +1 @@
288
300