feat: add wifi rssi endpoint

This commit is contained in:
ZanzyTHEbar 2023-02-27 15:26:45 +00:00
parent a7b61ff5ff
commit 8f2b6db65b
4 changed files with 407 additions and 459 deletions

View File

@ -1,76 +1,70 @@
#include "network_utilities.hpp" #include "network_utilities.hpp"
void Network_Utilities::SetupWifiScan() void Network_Utilities::SetupWifiScan() {
{ // Set WiFi to station mode and disconnect from an AP if it was previously
// Set WiFi to station mode and disconnect from an AP if it was previously connected // connected
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.disconnect(); // Disconnect from the access point if connected before WiFi.disconnect(); // Disconnect from the access point if connected before
my_delay(0.1); my_delay(0.1);
Serial.println("Setup done"); Serial.println("Setup done");
} }
bool Network_Utilities::LoopWifiScan() bool Network_Utilities::LoopWifiScan() {
{ // WiFi.scanNetworks will return the number of networks found
// WiFi.scanNetworks will return the number of networks found log_i("[INFO]: Beginning WiFi Scanner");
log_i("[INFO]: Beginning WiFi Scanner"); int networks = WiFi.scanNetworks(true, true);
int networks = WiFi.scanNetworks(true, true); log_i("[INFO]: scan done");
log_i("[INFO]: scan done"); log_i("%d networks found", networks);
log_i("%d networks found", networks); for (int i = networks; i--;) {
for (int i = networks; i--;) // Print SSID and RSSI for each network found
{ //! TODO: Add method here to interface with the API and forward the scanned
// Print SSID and RSSI for each network found //! networks to the API
//! TODO: Add method here to interface with the API and forward the scanned networks to the API log_i("%d: %s (%d) %s\n", i - 1, WiFi.SSID(i), WiFi.RSSI(i),
log_i("%d: %s (%d) %s\n", i - 1, WiFi.SSID(i), WiFi.RSSI(i), (WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*"); (WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
my_delay(0.02); // delay 20ms my_delay(0.02); // delay 20ms
} }
return (networks > 0); return (networks > 0);
} }
// Take measurements of the Wi-Fi strength and return the average result. // Take measurements of the Wi-Fi strength and return the average result.
int Network_Utilities::getStrength(int points) // TODO: add to JSON doc int Network_Utilities::getStrength(int points) {
{ int32_t rssi = 0, averageRSSI = 0;
int32_t rssi = 0, averageRSSI = 0; for (int i = 0; i < points; i++) {
for (int i = 0; i < points; i++) rssi += WiFi.RSSI();
{ my_delay(0.02);
rssi += WiFi.RSSI(); }
my_delay(0.02); averageRSSI = rssi / points;
} return averageRSSI;
averageRSSI = rssi / points;
return averageRSSI;
} }
void Network_Utilities::my_delay(volatile long delay_time) void Network_Utilities::my_delay(volatile long delay_time) {
{ delay_time = delay_time * 1e6L;
delay_time = delay_time * 1e6L; for (volatile long count = delay_time; count > 0; count--)
for (volatile long count = delay_time; count > 0; count--) ;
;
} }
std::string shaEncoder(const std::string &data) std::string shaEncoder(const std::string& data) {
{ const char* data_c = data.c_str();
const char *data_c = data.c_str(); int size = 64;
int size = 64; uint8_t hash[size];
uint8_t hash[size]; mbedtls_md_context_t ctx;
mbedtls_md_context_t ctx; mbedtls_md_type_t md_type = MBEDTLS_MD_SHA512;
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA512;
const size_t len = strlen(data_c); const size_t len = strlen(data_c);
mbedtls_md_init(&ctx); mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0); mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
mbedtls_md_starts(&ctx); mbedtls_md_starts(&ctx);
mbedtls_md_update(&ctx, (const unsigned char *)data_c, len); mbedtls_md_update(&ctx, (const unsigned char*)data_c, len);
mbedtls_md_finish(&ctx, hash); mbedtls_md_finish(&ctx, hash);
mbedtls_md_free(&ctx); mbedtls_md_free(&ctx);
std::string hash_string = ""; std::string hash_string = "";
for (uint16_t i = 0; i < size; i++) for (uint16_t i = 0; i < size; i++) {
{ std::string hex = String(hash[i], HEX).c_str();
std::string hex = String(hash[i], HEX).c_str(); if (hex.length() < 2) {
if (hex.length() < 2) hex = "0" + hex;
{
hex = "0" + hex;
}
hash_string += hex;
} }
return hash_string; hash_string += hex;
} }
return hash_string;
}

View File

@ -1,374 +1,334 @@
#include "baseAPI.hpp" #include "baseAPI.hpp"
//! These have to be called before the constructor of the class because they are static //! These have to be called before the constructor of the class because they are
//! C++ 11 does not have inline variables, sadly. So we have to do this. //! static C++ 11 does not have inline variables, sadly. So we have to do this.
// const char *BaseAPI::MIMETYPE_HTML{"text/html"}; // const char *BaseAPI::MIMETYPE_HTML{"text/html"};
// const char *BaseAPI::MIMETYPE_CSS{"text/css"}; // const char *BaseAPI::MIMETYPE_CSS{"text/css"};
// const char *BaseAPI::MIMETYPE_JS{"application/javascript"}; // const char *BaseAPI::MIMETYPE_JS{"application/javascript"};
// const char *BaseAPI::MIMETYPE_PNG{"image/png"}; // const char *BaseAPI::MIMETYPE_PNG{"image/png"};
// const char *BaseAPI::MIMETYPE_JPG{"image/jpeg"}; // const char *BaseAPI::MIMETYPE_JPG{"image/jpeg"};
// const char *BaseAPI::MIMETYPE_ICO{"image/x-icon"}; // const char *BaseAPI::MIMETYPE_ICO{"image/x-icon"};
const char *BaseAPI::MIMETYPE_JSON{"application/json"}; const char* BaseAPI::MIMETYPE_JSON{"application/json"};
BaseAPI::BaseAPI(int CONTROL_PORT, BaseAPI::BaseAPI(int CONTROL_PORT,
ProjectConfig *projectConfig, ProjectConfig* projectConfig,
CameraHandler *camera, CameraHandler* camera,
StateManager<WiFiState_e> *WiFiStateManager, StateManager<WiFiState_e>* WiFiStateManager,
const std::string &api_url) : server(CONTROL_PORT), const std::string& api_url)
projectConfig(projectConfig), : server(CONTROL_PORT),
camera(camera), projectConfig(projectConfig),
wiFiStateManager(wiFiStateManager), camera(camera),
api_url(api_url) {} wiFiStateManager(wiFiStateManager),
api_url(api_url) {}
BaseAPI::~BaseAPI() {} BaseAPI::~BaseAPI() {}
void BaseAPI::begin() void BaseAPI::begin() {
{ //! i have changed this to use lambdas instead of std::bind to avoid the
//! i have changed this to use lambdas instead of std::bind to avoid the overhead. Lambdas are always more preferable. //! overhead. Lambdas are always more preferable.
server.on("/", 0b00000001, [&](AsyncWebServerRequest *request) server.on("/", 0b00000001,
{ request->send(200); }); [&](AsyncWebServerRequest* request) { request->send(200); });
// preflight cors check // preflight cors check
server.on("/", 0b01000000, [&](AsyncWebServerRequest *request) server.on("/", 0b01000000, [&](AsyncWebServerRequest* request) {
{ AsyncWebServerResponse* response = request->beginResponse(204);
AsyncWebServerResponse* response = request->beginResponse(204); response->addHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
response->addHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS"); response->addHeader("Access-Control-Allow-Headers",
response->addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization"); "Accept, Content-Type, Authorization");
response->addHeader("Access-Control-Allow-Credentials", "true"); response->addHeader("Access-Control-Allow-Credentials", "true");
request->send(response); }); request->send(response);
});
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
// std::bind(&BaseAPI::notFound, &std::placeholders::_1); // std::bind(&BaseAPI::notFound, &std::placeholders::_1);
server.onNotFound([&](AsyncWebServerRequest *request) server.onNotFound([&](AsyncWebServerRequest* request) { notFound(request); });
{ notFound(request); });
} }
void BaseAPI::notFound(AsyncWebServerRequest *request) const void BaseAPI::notFound(AsyncWebServerRequest* request) const {
{ if (_networkMethodsMap.find(request->method()) != _networkMethodsMap.end()) {
if (_networkMethodsMap.find(request->method()) != _networkMethodsMap.end()) log_i("%s: http://%s%s/\n",
{ _networkMethodsMap.at(request->method()).c_str(),
log_i("%s: http://%s%s/\n", _networkMethodsMap.at(request->method()).c_str(), request->host().c_str(), request->url().c_str()); request->host().c_str(), request->url().c_str());
char buffer[100]; char buffer[100];
snprintf(buffer, sizeof(buffer), "Request %s Not found: %s", _networkMethodsMap.at(request->method()).c_str(), request->url().c_str()); snprintf(buffer, sizeof(buffer), "Request %s Not found: %s",
request->send(404, "text/plain", buffer); _networkMethodsMap.at(request->method()).c_str(),
} request->url().c_str());
else request->send(404, "text/plain", buffer);
{ } else {
request->send(404, "text/plain", "Request Not found using unknown method"); request->send(404, "text/plain", "Request Not found using unknown method");
} }
} }
//********************************************************************************************* //*********************************************************************************************
//! Command Functions //! Command Functions
//********************************************************************************************* //*********************************************************************************************
void BaseAPI::setWiFi(AsyncWebServerRequest *request) void BaseAPI::setWiFi(AsyncWebServerRequest* request) {
{ switch (_networkMethodsMap_enum[request->method()]) {
switch (_networkMethodsMap_enum[request->method()]) case POST: {
{ int params = request->params();
case POST: std::string networkName;
{ std::string ssid;
int params = request->params(); std::string password;
std::string networkName; uint8_t channel = 0;
std::string ssid; uint8_t power = 0;
std::string password; uint8_t adhoc = 0;
uint8_t channel = 0;
uint8_t power = 0;
uint8_t adhoc = 0;
log_d("Number of Params: %d", params); log_d("Number of Params: %d", params);
for (int i = 0; i < params; i++) for (int i = 0; i < params; i++) {
{ AsyncWebParameter* param = request->getParam(i);
AsyncWebParameter *param = request->getParam(i); if (param->name() == "networkName") {
if (param->name() == "networkName") networkName = param->value().c_str();
{ } else if (param->name() == "ssid") {
networkName = param->value().c_str(); ssid = param->value().c_str();
} } else if (param->name() == "password") {
else if (param->name() == "ssid") password = param->value().c_str();
{ } else if (param->name() == "channel") {
ssid = param->value().c_str(); channel = (uint8_t)atoi(param->value().c_str());
} } else if (param->name() == "power") {
else if (param->name() == "password") power = (uint8_t)atoi(param->value().c_str());
{ } else if (param->name() == "adhoc") {
password = param->value().c_str(); adhoc = (uint8_t)atoi(param->value().c_str());
} }
else if (param->name() == "channel")
{
channel = (uint8_t)atoi(param->value().c_str());
}
else if (param->name() == "power")
{
power = (uint8_t)atoi(param->value().c_str());
}
else if (param->name() == "adhoc")
{
adhoc = (uint8_t)atoi(param->value().c_str());
}
log_i("%s[%s]: %s\n", _networkMethodsMap[request->method()].c_str(), param->name().c_str(), param->value().c_str()); log_i("%s[%s]: %s\n", _networkMethodsMap[request->method()].c_str(),
} param->name().c_str(), param->value().c_str());
// note: We're passing empty params by design, this is done to reset specific fields }
projectConfig->setWifiConfig(networkName, ssid, password, &channel, &power, adhoc, true); // note: We're passing empty params by design, this is done to reset
// specific fields
projectConfig->setWifiConfig(networkName, ssid, password, &channel,
&power, adhoc, true);
/* if (WiFiStateManager->getCurrentState() == WiFiState_e::WiFiState_ADHOC) /* if (WiFiStateManager->getCurrentState() ==
{ WiFiState_e::WiFiState_ADHOC)
projectConfig->setAPWifiConfig(ssid, password, &channel, adhoc, true); {
} projectConfig->setAPWifiConfig(ssid, password, &channel, adhoc,
else true);
{ }
else
{
} */ } */
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Done. Wifi Creds have been set.\"}"); request->send(200, MIMETYPE_JSON,
break; "{\"msg\":\"Done. Wifi Creds have been set.\"}");
} break;
default: }
{ default: {
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}"); request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
request->redirect("/"); request->redirect("/");
break; break;
} }
} }
} }
void BaseAPI::getJsonConfig(AsyncWebServerRequest *request) void BaseAPI::getJsonConfig(AsyncWebServerRequest* request) {
{ // returns the current stored config in case it get's deleted on the PC.
// returns the current stored config in case it get's deleted on the PC. switch (_networkMethodsMap_enum[request->method()]) {
switch (_networkMethodsMap_enum[request->method()]) case GET: {
{ std::string wifiConfigSerialized = "\"wifi_config\": [";
case GET: auto networksConfigs = projectConfig->getWifiConfigs();
{ for (auto networkIterator = networksConfigs->begin();
std::string wifiConfigSerialized = "\"wifi_config\": ["; networkIterator != networksConfigs->end(); networkIterator++) {
auto networksConfigs = projectConfig->getWifiConfigs(); wifiConfigSerialized +=
for (auto networkIterator = networksConfigs->begin(); networkIterator != networksConfigs->end(); networkIterator++) networkIterator->toRepresentation() +
{ (std::next(networkIterator) != networksConfigs->end() ? "," : "");
wifiConfigSerialized += networkIterator->toRepresentation() + (std::next(networkIterator) != networksConfigs->end() ? "," : ""); }
} wifiConfigSerialized += "]";
wifiConfigSerialized += "]";
std::string json = Helpers::format_string( std::string json = Helpers::format_string(
"{%s, %s, %s, %s, %s}", "{%s, %s, %s, %s, %s}",
projectConfig->getDeviceConfig()->toRepresentation().c_str(), projectConfig->getDeviceConfig()->toRepresentation().c_str(),
projectConfig->getCameraConfig()->toRepresentation().c_str(), projectConfig->getCameraConfig()->toRepresentation().c_str(),
wifiConfigSerialized.c_str(), wifiConfigSerialized.c_str(),
projectConfig->getMDNSConfig()->toRepresentation().c_str(), projectConfig->getMDNSConfig()->toRepresentation().c_str(),
projectConfig->getAPWifiConfig()->toRepresentation().c_str()); projectConfig->getAPWifiConfig()->toRepresentation().c_str());
request->send(200, MIMETYPE_JSON, json.c_str()); request->send(200, MIMETYPE_JSON, json.c_str());
break; break;
} }
default: default: {
{ request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}"); break;
break; }
} }
}
} }
void BaseAPI::setDeviceConfig(AsyncWebServerRequest *request) void BaseAPI::setDeviceConfig(AsyncWebServerRequest* request) {
{ switch (_networkMethodsMap_enum[request->method()]) {
switch (_networkMethodsMap_enum[request->method()]) case GET: {
{ request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
case GET: break;
{ }
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}"); case POST: {
break; int params = request->params();
}
case POST:
{
int params = request->params();
std::string hostname; std::string hostname;
std::string service; std::string service;
std::string ota_password; std::string ota_password;
std::string firmware_name; std::string firmware_name;
int ota_port; int ota_port;
for (int i = 0; i < params; i++) for (int i = 0; i < params; i++) {
{ AsyncWebParameter* param = request->getParam(i);
AsyncWebParameter *param = request->getParam(i); if (param->name() == "hostname") {
if (param->name() == "hostname") hostname.assign(param->value().c_str());
{ } else if (param->name() == "service") {
hostname.assign(param->value().c_str()); service.assign(param->value().c_str());
} } else if (param->name() == "ota_port") {
else if (param->name() == "service") ota_port = atoi(param->value().c_str());
{ } else if (param->name() == "ota_password") {
service.assign(param->value().c_str()); ota_password.assign(param->value().c_str());
} } else if (param->name() == "firmware_name") {
else if (param->name() == "ota_port") firmware_name.assign(param->value().c_str());
{ }
ota_port = atoi(param->value().c_str()); }
} // note: We're passing empty params by design, this is done to reset
else if (param->name() == "ota_password") // specific fields
{ projectConfig->setDeviceConfig(ota_password, ota_port, firmware_name,
ota_password.assign(param->value().c_str()); true);
} projectConfig->setMDNSConfig(hostname, service, true);
else if (param->name() == "firmware_name") request->send(200, MIMETYPE_JSON,
{ "{\"msg\":\"Done. Device Config has been set.\"}");
firmware_name.assign(param->value().c_str()); }
} }
}
// note: We're passing empty params by design, this is done to reset specific fields
projectConfig->setDeviceConfig(ota_password, ota_port, firmware_name, true);
projectConfig->setMDNSConfig(hostname, service, true);
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Done. Device Config has been set.\"}");
}
}
} }
void BaseAPI::setWiFiTXPower(AsyncWebServerRequest *request) void BaseAPI::setWiFiTXPower(AsyncWebServerRequest* request) {
{ switch (_networkMethodsMap_enum[request->method()]) {
switch (_networkMethodsMap_enum[request->method()]) case GET: {
{ int params = request->params();
case GET:
{
int params = request->params();
uint8_t txPower = 0; uint8_t txPower = 0;
for (int i = 0; i < params; i++) for (int i = 0; i < params; i++) {
{ AsyncWebParameter* param = request->getParam(i);
AsyncWebParameter *param = request->getParam(i); if (param->name() == "txPower") {
if (param->name() == "txPower") txPower = atoi(param->value().c_str());
{ }
txPower = atoi(param->value().c_str()); }
} projectConfig->setWiFiTxPower(&txPower, true);
} projectConfig->wifiTxPowerConfigSave();
projectConfig->setWiFiTxPower(&txPower, true); request->send(200, MIMETYPE_JSON,
projectConfig->wifiTxPowerConfigSave(); "{\"msg\":\"Done. TX Power has been set.\"}");
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Done. TX Power has been set.\"}"); break;
break; }
} case POST: {
case POST: int params = request->params();
{
int params = request->params();
uint8_t txPower = 0; uint8_t txPower = 0;
for (int i = 0; i < params; i++) for (int i = 0; i < params; i++) {
{ AsyncWebParameter* param = request->getParam(i);
AsyncWebParameter *param = request->getParam(i); if (param->name() == "txPower") {
if (param->name() == "txPower") txPower = atoi(param->value().c_str());
{ }
txPower = atoi(param->value().c_str()); }
} projectConfig->setWiFiTxPower(&txPower, true);
} projectConfig->wifiTxPowerConfigSave();
projectConfig->setWiFiTxPower(&txPower, true); request->send(200, MIMETYPE_JSON,
projectConfig->wifiTxPowerConfigSave(); "{\"msg\":\"Done. TX Power has been set.\"}");
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Done. TX Power has been set.\"}"); }
} }
}
} }
void BaseAPI::rebootDevice(AsyncWebServerRequest *request) void BaseAPI::rebootDevice(AsyncWebServerRequest* request) {
{ switch (_networkMethodsMap_enum[request->method()]) {
switch (_networkMethodsMap_enum[request->method()]) case GET: {
{ request->send(200, MIMETYPE_JSON, "{\"msg\":\"Rebooting Device\"}");
case GET: OpenIrisTasks::ScheduleRestart(2000);
{ }
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Rebooting Device\"}"); default: {
OpenIrisTasks::ScheduleRestart(2000); request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
} break;
default: }
{ }
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
break;
}
}
} }
void BaseAPI::factoryReset(AsyncWebServerRequest *request) void BaseAPI::factoryReset(AsyncWebServerRequest* request) {
{ switch (_networkMethodsMap_enum[request->method()]) {
switch (_networkMethodsMap_enum[request->method()]) case GET: {
{ log_d("Factory Reset");
case GET: projectConfig->reset();
{ request->send(200, MIMETYPE_JSON, "{\"msg\":\"Factory Reset\"}");
log_d("Factory Reset"); }
projectConfig->reset(); default: {
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Factory Reset\"}"); request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
} break;
default: }
{ }
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
break;
}
}
} }
//********************************************************************************************* //*********************************************************************************************
//! Camera Command Functions //! Camera Command Functions
//********************************************************************************************* //*********************************************************************************************
void BaseAPI::setCamera(AsyncWebServerRequest *request) void BaseAPI::setCamera(AsyncWebServerRequest* request) {
{ switch (_networkMethodsMap_enum[request->method()]) {
switch (_networkMethodsMap_enum[request->method()]) case GET: {
{ // create temporary variables to store the values
case GET: uint8_t temp_camera_framesize = 0;
{ uint8_t temp_camera_vflip = 0;
// create temporary variables to store the values uint8_t temp_camera_hflip = 0;
uint8_t temp_camera_framesize = 0; uint8_t temp_camera_quality = 0;
uint8_t temp_camera_vflip = 0; uint8_t temp_camera_brightness = 0;
uint8_t temp_camera_hflip = 0;
uint8_t temp_camera_quality = 0;
uint8_t temp_camera_brightness = 0;
int params = request->params(); int params = request->params();
//! Using the else if statements to ensure that the values do not need to be set in a specific order //! Using the else if statements to ensure that the values do not need to
//! This means the order of the URL params does not matter //! be set in a specific order This means the order of the URL params does
for (int i = 0; i < params; i++) //! not matter
{ for (int i = 0; i < params; i++) {
AsyncWebParameter *param = request->getParam(i); AsyncWebParameter* param = request->getParam(i);
if (param->name() == "framesize") if (param->name() == "framesize") {
{ temp_camera_framesize = (uint8_t)param->value().toInt();
temp_camera_framesize = (uint8_t)param->value().toInt(); } else if (param->name() == "vflip") {
} temp_camera_vflip = (uint8_t)param->value().toInt();
else if (param->name() == "vflip") } else if (param->name() == "hflip") {
{ temp_camera_hflip = (uint8_t)param->value().toInt();
temp_camera_vflip = (uint8_t)param->value().toInt(); } else if (param->name() == "quality") {
} temp_camera_quality = (uint8_t)param->value().toInt();
else if (param->name() == "hflip") } else if (param->name() == "brightness") {
{ temp_camera_brightness = (uint8_t)param->value().toInt();
temp_camera_hflip = (uint8_t)param->value().toInt(); }
} }
else if (param->name() == "quality") // note: We're passing empty params by design, this is done to reset
{ // specific fields
temp_camera_quality = (uint8_t)param->value().toInt(); projectConfig->setCameraConfig(&temp_camera_vflip, &temp_camera_framesize,
} &temp_camera_hflip, &temp_camera_quality,
else if (param->name() == "brightness") &temp_camera_brightness, true);
{
temp_camera_brightness = (uint8_t)param->value().toInt();
}
}
// 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);
request->send(200, MIMETYPE_JSON, "{\"msg\":\"Done. Camera Settings have been set.\"}"); request->send(200, MIMETYPE_JSON,
break; "{\"msg\":\"Done. Camera Settings have been set.\"}");
} break;
default: }
{ default: {
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}"); request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Request\"}");
request->redirect("/"); request->redirect("/");
break; break;
} }
} }
} }
void BaseAPI::restartCamera(AsyncWebServerRequest *request) void BaseAPI::restartCamera(AsyncWebServerRequest* request) {
{ bool mode = (bool)atoi(request->arg("mode").c_str());
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.\"}"); request->send(200, MIMETYPE_JSON,
"{\"msg\":\"Done. Camera had been restarted.\"}");
} }
void BaseAPI::ping(AsyncWebServerRequest *request) void BaseAPI::ping(AsyncWebServerRequest* request) {
{ request->send(200, MIMETYPE_JSON, "{\"msg\": \"ok\" }");
request->send(200, MIMETYPE_JSON, "{\"msg\": \"ok\" }");
} }
void BaseAPI::save(AsyncWebServerRequest *request) void BaseAPI::save(AsyncWebServerRequest* request) {
{ projectConfig->save();
projectConfig->save(); request->send(200, MIMETYPE_JSON, "{\"msg\": \"ok\" }");
request->send(200, MIMETYPE_JSON, "{\"msg\": \"ok\" }"); }
void BaseAPI::rssi(AsyncWebServerRequest* request) {
int rssi = Network_Utilities::getStrength(
request->getParam("points")->value().toInt());
char _rssiBuffer[20];
snprintf(_rssiBuffer, sizeof(_rssiBuffer), "{\"rssi\": %d }", rssi);
request->send(200, MIMETYPE_JSON, _rssiBuffer);
} }

View File

@ -51,6 +51,7 @@ protected:
void rebootDevice(AsyncWebServerRequest *request); void rebootDevice(AsyncWebServerRequest *request);
void ping(AsyncWebServerRequest *request); void ping(AsyncWebServerRequest *request);
void save(AsyncWebServerRequest *request); void save(AsyncWebServerRequest *request);
void rssi(AsyncWebServerRequest *request);
/* Camera Handlers */ /* Camera Handlers */
void setCamera(AsyncWebServerRequest *request); void setCamera(AsyncWebServerRequest *request);

View File

@ -5,56 +5,57 @@
//********************************************************************************************* //*********************************************************************************************
APIServer::APIServer(int CONTROL_PORT, APIServer::APIServer(int CONTROL_PORT,
ProjectConfig *projectConfig, ProjectConfig* projectConfig,
CameraHandler *camera, CameraHandler* camera,
StateManager<WiFiState_e> *wiFiStateManager, StateManager<WiFiState_e>* wiFiStateManager,
const std::string &api_url) : BaseAPI(CONTROL_PORT, const std::string& api_url)
projectConfig, : BaseAPI(CONTROL_PORT, projectConfig, camera, wiFiStateManager, api_url) {}
camera,
wiFiStateManager,
api_url) {}
APIServer::~APIServer() {} APIServer::~APIServer() {}
void APIServer::begin() void APIServer::begin() {
{ log_d("Initializing REST API Server");
log_d("Initializing REST API Server"); this->setupServer();
this->setupServer(); BaseAPI::begin();
BaseAPI::begin();
char buffer[1000]; char buffer[1000];
snprintf(buffer, sizeof(buffer), "^\\%s\\/([a-zA-Z0-9]+)\\/command\\/([a-zA-Z0-9]+)$", this->api_url.c_str()); snprintf(buffer, sizeof(buffer),
log_d("API URL: %s", buffer); "^\\%s\\/([a-zA-Z0-9]+)\\/command\\/([a-zA-Z0-9]+)$",
server.on(buffer, 0b01111111, [&](AsyncWebServerRequest *request) this->api_url.c_str());
{ handleRequest(request); }); log_d("API URL: %s", buffer);
server.begin(); server.on(buffer, 0b01111111,
[&](AsyncWebServerRequest* request) { handleRequest(request); });
server.begin();
} }
void APIServer::setupServer() void APIServer::setupServer() {
{ routes.emplace("wifi", &APIServer::setWiFi);
routes.emplace("wifi", &APIServer::setWiFi); routes.emplace("resetConfig", &APIServer::factoryReset);
routes.emplace("resetConfig", &APIServer::factoryReset); routes.emplace("setDevice", &APIServer::setDeviceConfig);
routes.emplace("setDevice", &APIServer::setDeviceConfig); routes.emplace("rebootDevice", &APIServer::rebootDevice);
routes.emplace("rebootDevice", &APIServer::rebootDevice); routes.emplace("getStoredConfig", &APIServer::getJsonConfig);
routes.emplace("getStoredConfig", &APIServer::getJsonConfig); routes.emplace("setTxPower", &APIServer::setWiFiTXPower);
routes.emplace("setTxPower", &APIServer::setWiFiTXPower); // Camera Routes
// Camera Routes routes.emplace("setCamera", &APIServer::setCamera);
routes.emplace("setCamera", &APIServer::setCamera); routes.emplace("restartCamera", &APIServer::restartCamera);
routes.emplace("restartCamera", &APIServer::restartCamera); routes.emplace("ping", &APIServer::ping);
routes.emplace("ping", &APIServer::ping); routes.emplace("save", &APIServer::save);
routes.emplace("save", &APIServer::save); routes.emplace("wifiStrength", &APIServer::rssi);
//! reserve enough memory for all routes - must be called after adding routes and before adding routes to route_map //! reserve enough memory for all routes - must be called after adding routes
indexes.reserve(routes.size()); // this is done to avoid reallocation of memory and copying of data //! and before adding routes to route_map
addRouteMap("builtin", routes, indexes); // add new route map to the route_map indexes.reserve(routes.size()); // this is done to avoid reallocation of
// memory and copying of data
addRouteMap("builtin", routes,
indexes); // add new route map to the route_map
} }
void APIServer::findParam(AsyncWebServerRequest *request, const char *param, std::string &value) void APIServer::findParam(AsyncWebServerRequest* request,
{ const char* param,
if (request->hasParam(param)) std::string& value) {
{ if (request->hasParam(param)) {
value = request->getParam(param)->value().c_str(); value = request->getParam(param)->value().c_str();
} }
} }
/** /**
@ -62,56 +63,48 @@ void APIServer::findParam(AsyncWebServerRequest *request, const char *param, std
* *
* @param index * @param index
* @param funct * @param funct
* @param indexes \c std::vector<std::string> a list of the routes of the command handlers * @param indexes \c std::vector<std::string> a list of the routes of the
* command handlers
* *
* @return void * @return void
* *
*/ */
void APIServer::addRouteMap(const std::string &index, route_t route, std::vector<std::string> &indexes) void APIServer::addRouteMap(const std::string& index,
{ route_t route,
route_map.emplace(index, route); std::vector<std::string>& indexes) {
route_map.emplace(index, route);
for (const auto &key : route) for (const auto& key : route) {
{ indexes.emplace_back(key.first); // add the route to the list of routes -
indexes.emplace_back(key.first); // add the route to the list of routes - use emplace_back to avoid copying // use emplace_back to avoid copying
} }
} }
void APIServer::handleRequest(AsyncWebServerRequest *request) void APIServer::handleRequest(AsyncWebServerRequest* request) {
{ try {
try // Get the route
{ log_i("Request URL: %s", request->url().c_str());
// Get the route log_i("Request: %s", request->pathArg(0).c_str());
log_i("Request URL: %s", request->url().c_str()); log_i("Request: %s", request->pathArg(1).c_str());
log_i("Request: %s", request->pathArg(0).c_str());
log_i("Request: %s", request->pathArg(1).c_str());
auto it_map = route_map.find(request->pathArg(0).c_str()); auto it_map = route_map.find(request->pathArg(0).c_str());
auto it_method = it_map->second.find(request->pathArg(1).c_str()); auto it_method = it_map->second.find(request->pathArg(1).c_str());
if (it_map != route_map.end()) if (it_map != route_map.end()) {
{ if (it_method != it_map->second.end()) {
if (it_method != it_map->second.end()) log_d("We are trying to execute the function");
{ (*this.*(it_method->second))(request);
log_d("We are trying to execute the function"); } else {
(*this.*(it_method->second))(request); log_e("Invalid Command");
} request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Command\"}");
else return;
{ }
log_e("Invalid Command"); } else {
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Command\"}"); log_e("Invalid Map Index");
return; request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Map Index\"}");
} return;
} }
else } catch (...) {
{ log_e("Error handling request");
log_e("Invalid Map Index"); }
request->send(400, MIMETYPE_JSON, "{\"msg\":\"Invalid Map Index\"}");
return;
}
}
catch (...)
{
log_e("Error handling request");
}
} }