diff --git a/components/CommandManager/CMakeLists.txt b/components/CommandManager/CMakeLists.txt index 9c32fd5..b97a3e6 100644 --- a/components/CommandManager/CMakeLists.txt +++ b/components/CommandManager/CMakeLists.txt @@ -1,4 +1,8 @@ -idf_component_register(SRCS "CommandManager/CommandManager.cpp" - INCLUDE_DIRS "CommandManager" +idf_component_register( + SRCS + "CommandManager/CommandManager.cpp" + "CommandManager/Commands.cpp" + INCLUDE_DIRS + "CommandManager" REQUIRES ProjectConfig cJSON ) \ No newline at end of file diff --git a/components/CommandManager/CommandManager/CommandManager.cpp b/components/CommandManager/CommandManager/CommandManager.cpp index caa0c07..5a50273 100644 --- a/components/CommandManager/CommandManager/CommandManager.cpp +++ b/components/CommandManager/CommandManager/CommandManager.cpp @@ -36,9 +36,9 @@ std::unique_ptr CommandManager::createCommand(CommandType type) } } -CommandResult CommandManager::executeFromJson(std::string *json) +CommandResult CommandManager::executeFromJson(std::string_view json) { - cJSON *parsedJson = cJSON_Parse(json->c_str()); + cJSON *parsedJson = cJSON_Parse(json.data()); if (parsedJson == nullptr) return CommandResult::getErrorResult("Invalid JSON"); @@ -67,7 +67,7 @@ CommandResult CommandManager::executeFromJson(std::string *json) return CommandResult::getErrorResult("Commands missing"); } -CommandResult CommandManager::executeFromType(CommandType type, std::string *json) +CommandResult CommandManager::executeFromType(CommandType type, std::string_view json) { auto command = createCommand(type); @@ -76,5 +76,5 @@ CommandResult CommandManager::executeFromType(CommandType type, std::string *jso return CommandResult::getErrorResult("Unknown command"); } - return command->execute(*json); + return command->execute(json); } \ No newline at end of file diff --git a/components/CommandManager/CommandManager/CommandManager.hpp b/components/CommandManager/CommandManager/CommandManager.hpp index 023b6e5..217270d 100644 --- a/components/CommandManager/CommandManager/CommandManager.hpp +++ b/components/CommandManager/CommandManager/CommandManager.hpp @@ -16,6 +16,7 @@ enum CommandType None, PING, SET_WIFI, + UPDATE_DEVICE, UPDATE_WIFI, DELETE_NETWORK, UPDATE_AP_WIFI, @@ -36,8 +37,8 @@ public: CommandManager(std::shared_ptr projectConfig) : projectConfig(projectConfig) {}; std::unique_ptr createCommand(CommandType type); - CommandResult executeFromJson(std::string *json); - CommandResult executeFromType(CommandType type, std::string *json); + CommandResult executeFromJson(std::string_view json); + CommandResult executeFromType(CommandType type, std::string_view json); }; #endif \ No newline at end of file diff --git a/components/CommandManager/CommandManager/CommandResult.hpp b/components/CommandManager/CommandManager/CommandResult.hpp index 8074985..df44aa0 100644 --- a/components/CommandManager/CommandManager/CommandResult.hpp +++ b/components/CommandManager/CommandManager/CommandResult.hpp @@ -1,44 +1,49 @@ #ifndef COMMAND_RESULT #define COMMAND_RESULT +#include +#include + class CommandResult { private: - std::optional successMessage; - std::optional errorMessage; - -public: - CommandResult(std::optional success_message, - std::optional error_message) + enum class Status { - if (success_message.has_value()) + SUCCESS, + FAILURE, + }; + + Status status; + std::string message; + + CommandResult(std::string message, Status status) + { + this->status = status; + if (status == Status::SUCCESS) { - this->successMessage = - "{\"message\":\"" + success_message.value() + "\"}"; + // we gotta do it this way, because if we define it as { "result": " {} " } it crashes the compiler, lol + this->message = std::format("{}\"result\":\" {} \"{}", "{", message, "}"); } else - this->successMessage = std::nullopt; - - if (error_message.has_value()) - this->errorMessage = "{\"error\":\"" + error_message.value() + "\"}"; - else - this->errorMessage = std::nullopt; + { + this->message = std::format("{}\"error\":\" {} \"{}", "{", message, "}"); + } } - bool isSuccess() const { return successMessage.has_value(); } +public: + bool isSuccess() const { return status == Status::SUCCESS; } static CommandResult getSuccessResult(std::string message) { - return CommandResult(message, std::nullopt); + return CommandResult(message, Status::SUCCESS); } static CommandResult getErrorResult(std::string message) { - return CommandResult(std::nullopt, message); + return CommandResult(message, Status::FAILURE); } - std::string getSuccessMessage() const { return successMessage.value(); }; - std::string getErrorMessage() const { return errorMessage.value(); } + std::string getResult() const { return this->message; } }; #endif \ No newline at end of file diff --git a/components/CommandManager/CommandManager/Commands.cpp b/components/CommandManager/CommandManager/Commands.cpp index 45c4989..4b81fbc 100644 --- a/components/CommandManager/CommandManager/Commands.cpp +++ b/components/CommandManager/CommandManager/Commands.cpp @@ -1,14 +1,14 @@ #include "Commands.hpp" -CommandResult PingCommand::execute(std::string &jsonPayload) +CommandResult PingCommand::execute(std::string_view jsonPayload) { return CommandResult::getSuccessResult("pong"); } -std::optional setWiFiCommand::parsePayload(std::string &jsonPayload) +std::optional setWiFiCommand::parsePayload(std::string_view jsonPayload) { WifiPayload payload; - cJSON *parsedJson = cJSON_Parse(jsonPayload.c_str()); + cJSON *parsedJson = cJSON_Parse(jsonPayload.data()); if (parsedJson == nullptr) return std::nullopt; @@ -52,7 +52,7 @@ std::optional setWiFiCommand::parsePayload(std::string &jsonPayload return payload; } -CommandResult setWiFiCommand::execute(std::string &jsonPayload) +CommandResult setWiFiCommand::execute(std::string_view jsonPayload) { auto payload = parsePayload(jsonPayload); if (!payload.has_value()) @@ -71,10 +71,10 @@ CommandResult setWiFiCommand::execute(std::string &jsonPayload) return CommandResult::getSuccessResult("Config updated"); } -std::optional deleteWifiCommand::parsePayload(std::string &jsonPayload) +std::optional deleteWifiCommand::parsePayload(std::string_view jsonPayload) { deleteNetworkPayload payload; - cJSON *parsedJson = cJSON_Parse(jsonPayload.c_str()); + cJSON *parsedJson = cJSON_Parse(jsonPayload.data()); if (parsedJson == nullptr) return std::nullopt; @@ -92,7 +92,7 @@ std::optional deleteWifiCommand::parsePayload(std::string return payload; } -CommandResult deleteWifiCommand::execute(std::string &jsonPayload) +CommandResult deleteWifiCommand::execute(std::string_view jsonPayload) { auto payload = parsePayload(jsonPayload); if (!payload.has_value()) @@ -102,10 +102,10 @@ CommandResult deleteWifiCommand::execute(std::string &jsonPayload) return CommandResult::getSuccessResult("Config updated"); } -std::optional updateWifiCommand::parsePayload(std::string &jsonPayload) +std::optional updateWifiCommand::parsePayload(std::string_view jsonPayload) { UpdateWifiPayload payload; - cJSON *parsedJson = cJSON_Parse(jsonPayload.c_str()); + cJSON *parsedJson = cJSON_Parse(jsonPayload.data()); if (parsedJson == nullptr) return std::nullopt; @@ -124,7 +124,7 @@ std::optional updateWifiCommand::parsePayload(std::string &js cJSON *channelObject = cJSON_GetObjectItem(parsedJson, "channel"); cJSON *powerObject = cJSON_GetObjectItem(parsedJson, "power"); - if (ssidObject != nullptr && ssidObject->valuestring == "") + if (ssidObject != nullptr && (strcmp(ssidObject->valuestring, "") == 0)) { // we need ssid to actually connect cJSON_Delete(parsedJson); @@ -142,9 +142,12 @@ std::optional updateWifiCommand::parsePayload(std::string &js if (powerObject != nullptr) payload.power = powerObject->valueint; + + cJSON_Delete(parsedJson); + return payload; } -CommandResult updateWifiCommand::execute(std::string &jsonPayload) +CommandResult updateWifiCommand::execute(std::string_view jsonPayload) { auto payload = parsePayload(jsonPayload); if (!payload.has_value()) @@ -168,15 +171,17 @@ CommandResult updateWifiCommand::execute(std::string &jsonPayload) updatedConfig.channel.has_value() ? updatedConfig.channel.value() : networkToUpdate->channel, updatedConfig.power.has_value() ? updatedConfig.power.value() : networkToUpdate->power, false); + + return CommandResult::getSuccessResult("Config updated"); } else return CommandResult::getErrorResult("Requested network does not exist"); } -std::optional updateAPWiFiCommand::parsePayload(std::string &jsonPayload) +std::optional updateAPWiFiCommand::parsePayload(std::string_view jsonPayload) { UpdateAPWiFiPayload payload; - cJSON *parsedJson = cJSON_Parse(jsonPayload.c_str()); + cJSON *parsedJson = cJSON_Parse(jsonPayload.data()); // todo implement parsing @@ -184,17 +189,17 @@ std::optional updateAPWiFiCommand::parsePayload(std::string return payload; } -CommandResult updateAPWiFiCommand::execute(std::string &jsonPayload) +CommandResult updateAPWiFiCommand::execute(std::string_view jsonPayload) { auto payload = parsePayload(jsonPayload); // todo implement updating return CommandResult::getSuccessResult("Config updated"); } -std::optional setMDNSCommand::parsePayload(std::string &jsonPayload) +std::optional setMDNSCommand::parsePayload(std::string_view jsonPayload) { MDNSPayload payload; - cJSON *parsedJson = cJSON_Parse(jsonPayload.c_str()); + cJSON *parsedJson = cJSON_Parse(jsonPayload.data()); if (parsedJson == nullptr) return std::nullopt; @@ -211,7 +216,7 @@ std::optional setMDNSCommand::parsePayload(std::string &jsonPayload return payload; } -CommandResult setMDNSCommand::execute(std::string &jsonPayload) +CommandResult setMDNSCommand::execute(std::string_view jsonPayload) { auto payload = parsePayload(jsonPayload); if (!payload.has_value()) @@ -222,10 +227,10 @@ CommandResult setMDNSCommand::execute(std::string &jsonPayload) return CommandResult::getSuccessResult("Config updated"); } -std::optional updateCameraCommand::parsePayload(std::string &jsonPayload) +std::optional updateCameraCommand::parsePayload(std::string_view jsonPayload) { UpdateCameraConfigPayload payload; - cJSON *parsedJson = cJSON_Parse(jsonPayload.c_str()); + cJSON *parsedJson = cJSON_Parse(jsonPayload.data()); if (parsedJson == nullptr) return std::nullopt; @@ -251,7 +256,7 @@ std::optional updateCameraCommand::parsePayload(std:: return payload; } -CommandResult updateCameraCommand::execute(std::string &jsonPayload) +CommandResult updateCameraCommand::execute(std::string_view jsonPayload) { auto payload = parsePayload(jsonPayload); if (!payload.has_value()) @@ -272,7 +277,7 @@ CommandResult updateCameraCommand::execute(std::string &jsonPayload) return CommandResult::getSuccessResult("Config updated"); } -CommandResult saveConfigCommand::execute(std::string &jsonPayload) +CommandResult saveConfigCommand::execute(std::string_view jsonPayload) { projectConfig->save(); return CommandResult::getSuccessResult("Config saved"); diff --git a/components/CommandManager/CommandManager/Commands.hpp b/components/CommandManager/CommandManager/Commands.hpp index 030d40c..eaba497 100644 --- a/components/CommandManager/CommandManager/Commands.hpp +++ b/components/CommandManager/CommandManager/Commands.hpp @@ -12,14 +12,16 @@ class Command { public: + Command() = default; virtual ~Command() = default; - virtual CommandResult execute(std::string &jsonPayload) = 0; + virtual CommandResult execute(std::string_view jsonPayload) = 0; }; class PingCommand : public Command { public: - CommandResult execute(std::string &jsonPayload) override; + PingCommand() = default; + CommandResult execute(std::string_view jsonPayload) override; }; class setWiFiCommand : public Command @@ -28,8 +30,8 @@ class setWiFiCommand : public Command public: setWiFiCommand(std::shared_ptr projectConfig) : projectConfig(projectConfig) {}; - CommandResult execute(std::string &jsonPayload) override; - std::optional parsePayload(std::string &jsonPayload); + CommandResult execute(std::string_view jsonPayload) override; + std::optional parsePayload(std::string_view jsonPayload); }; class deleteWifiCommand : public Command @@ -38,8 +40,8 @@ class deleteWifiCommand : public Command public: deleteWifiCommand(std::shared_ptr projectConfig) : projectConfig(projectConfig) {}; - CommandResult execute(std::string &jsonPayload) override; - std::optional parsePayload(std::string &jsonPayload); + CommandResult execute(std::string_view jsonPayload) override; + std::optional parsePayload(std::string_view jsonPayload); }; class updateWifiCommand : public Command @@ -48,8 +50,8 @@ class updateWifiCommand : public Command public: updateWifiCommand(std::shared_ptr projectConfig) : projectConfig(projectConfig) {}; - CommandResult execute(std::string &jsonPayload) override; - std::optional parsePayload(std::string &jsonPayload); + CommandResult execute(std::string_view jsonPayload) override; + std::optional parsePayload(std::string_view jsonPayload); }; class updateAPWiFiCommand : public Command @@ -58,8 +60,8 @@ class updateAPWiFiCommand : public Command public: updateAPWiFiCommand(std::shared_ptr projectConfig) : projectConfig(projectConfig) {}; - CommandResult execute(std::string &jsonPayload) override; - std::optional parsePayload(std::string &jsonPayload); + CommandResult execute(std::string_view jsonPayload) override; + std::optional parsePayload(std::string_view jsonPayload); }; class setMDNSCommand : public Command @@ -68,8 +70,8 @@ class setMDNSCommand : public Command public: setMDNSCommand(std::shared_ptr projectConfig) : projectConfig(projectConfig) {}; - CommandResult execute(std::string &jsonPayload) override; - std::optional parsePayload(std::string &jsonPayload); + CommandResult execute(std::string_view jsonPayload) override; + std::optional parsePayload(std::string_view jsonPayload); }; class updateCameraCommand : public Command @@ -78,8 +80,8 @@ class updateCameraCommand : public Command public: updateCameraCommand(std::shared_ptr projectConfig) : projectConfig(projectConfig) {}; - CommandResult execute(std::string &jsonPayload) override; - std::optional parsePayload(std::string &jsonPayload); + CommandResult execute(std::string_view jsonPayload) override; + std::optional parsePayload(std::string_view jsonPayload); }; class saveConfigCommand : public Command @@ -87,7 +89,7 @@ class saveConfigCommand : public Command public: std::shared_ptr projectConfig; saveConfigCommand(std::shared_ptr projectConfig) : projectConfig(projectConfig) {}; - CommandResult execute(std::string &jsonPayload) override; + CommandResult execute(std::string_view jsonPayload) override; }; // mostlikely missing commands diff --git a/components/RestAPI/RestAPI/RestAPI.cpp b/components/RestAPI/RestAPI/RestAPI.cpp index a66639c..c0a56ce 100644 --- a/components/RestAPI/RestAPI/RestAPI.cpp +++ b/components/RestAPI/RestAPI/RestAPI.cpp @@ -1,5 +1,7 @@ #include "RestAPI.hpp" +#define POST_METHOD "POST" + RestAPI::RestAPI(std::string url, std::shared_ptr commandManager) : command_manager(commandManager) { this->url = url; @@ -78,17 +80,41 @@ void RestAPI::poll() // updates void RestAPI::handle_update_wifi(RequestContext *context) { - mg_http_reply(context->connection, 200, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), "WiFi config updated"); + if (context->method != POST_METHOD) + { + mg_http_reply(context->connection, 401, JSON_RESPONSE, "{%m:%m}", MG_ESC("error"), "Method not allowed"); + return; + } + + auto result = command_manager->executeFromType(CommandType::UPDATE_WIFI, context->body); + int code = result.isSuccess() ? 200 : 500; + mg_http_reply(context->connection, code, JSON_RESPONSE, result.getResult().c_str()); } void RestAPI::handle_update_device(RequestContext *context) { - mg_http_reply(context->connection, 200, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), "Device config updated"); + if (context->method != POST_METHOD) + { + mg_http_reply(context->connection, 401, JSON_RESPONSE, "{%m:%m}", MG_ESC("error"), "Method not allowed"); + return; + } + + auto result = command_manager->executeFromType(CommandType::UPDATE_DEVICE, context->body); + int code = result.isSuccess() ? 200 : 500; + mg_http_reply(context->connection, code, JSON_RESPONSE, result.getResult().c_str()); } void RestAPI::handle_update_camera(RequestContext *context) { - mg_http_reply(context->connection, 200, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), "Device config updated"); + if (context->method != POST_METHOD) + { + mg_http_reply(context->connection, 401, JSON_RESPONSE, "{%m:%m}", MG_ESC("error"), "Method not allowed"); + return; + } + + auto result = command_manager->executeFromType(CommandType::UPDATE_CAMERA, context->body); + int code = result.isSuccess() ? 200 : 500; + mg_http_reply(context->connection, code, JSON_RESPONSE, result.getResult().c_str()); } // gets @@ -135,12 +161,16 @@ void RestAPI::handle_camera_reboot(RequestContext *context) void RestAPI::pong(RequestContext *context) { - mg_http_reply(context->connection, 200, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), "pong"); + CommandResult result = this->command_manager->executeFromType(CommandType::PING, ""); + int code = result.isSuccess() ? 200 : 500; + mg_http_reply(context->connection, code, JSON_RESPONSE, result.getResult().c_str()); } // special void RestAPI::handle_save(RequestContext *context) { - mg_http_reply(context->connection, 200, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), "Config saved"); + CommandResult result = this->command_manager->executeFromType(CommandType::SAVE_CONFIG, ""); + int code = result.isSuccess() ? 200 : 500; + mg_http_reply(context->connection, code, JSON_RESPONSE, result.getResult().c_str()); } \ No newline at end of file