Fix compiling issues, optimize commands a bit, implement some endpoints

TODO break down commands into separate files, implement the rest
This commit is contained in:
Lorow
2024-11-24 23:24:34 +01:00
parent 6b603f5574
commit f453db9476
7 changed files with 116 additions and 69 deletions

View File

@@ -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
)

View File

@@ -36,9 +36,9 @@ std::unique_ptr<Command> 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);
}

View File

@@ -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(projectConfig) {};
std::unique_ptr<Command> 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

View File

@@ -1,44 +1,49 @@
#ifndef COMMAND_RESULT
#define COMMAND_RESULT
#include <format>
#include <string>
class CommandResult
{
private:
std::optional<std::string> successMessage;
std::optional<std::string> errorMessage;
public:
CommandResult(std::optional<std::string> success_message,
std::optional<std::string> 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

View File

@@ -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<WifiPayload> setWiFiCommand::parsePayload(std::string &jsonPayload)
std::optional<WifiPayload> 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<WifiPayload> 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<deleteNetworkPayload> deleteWifiCommand::parsePayload(std::string &jsonPayload)
std::optional<deleteNetworkPayload> 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<deleteNetworkPayload> 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<UpdateWifiPayload> updateWifiCommand::parsePayload(std::string &jsonPayload)
std::optional<UpdateWifiPayload> 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<UpdateWifiPayload> 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<UpdateWifiPayload> 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<UpdateAPWiFiPayload> updateAPWiFiCommand::parsePayload(std::string &jsonPayload)
std::optional<UpdateAPWiFiPayload> 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<UpdateAPWiFiPayload> 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<MDNSPayload> setMDNSCommand::parsePayload(std::string &jsonPayload)
std::optional<MDNSPayload> 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<MDNSPayload> 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<UpdateCameraConfigPayload> updateCameraCommand::parsePayload(std::string &jsonPayload)
std::optional<UpdateCameraConfigPayload> 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<UpdateCameraConfigPayload> 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");

View File

@@ -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(projectConfig) {};
CommandResult execute(std::string &jsonPayload) override;
std::optional<WifiPayload> parsePayload(std::string &jsonPayload);
CommandResult execute(std::string_view jsonPayload) override;
std::optional<WifiPayload> 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(projectConfig) {};
CommandResult execute(std::string &jsonPayload) override;
std::optional<deleteNetworkPayload> parsePayload(std::string &jsonPayload);
CommandResult execute(std::string_view jsonPayload) override;
std::optional<deleteNetworkPayload> 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(projectConfig) {};
CommandResult execute(std::string &jsonPayload) override;
std::optional<UpdateWifiPayload> parsePayload(std::string &jsonPayload);
CommandResult execute(std::string_view jsonPayload) override;
std::optional<UpdateWifiPayload> 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(projectConfig) {};
CommandResult execute(std::string &jsonPayload) override;
std::optional<UpdateAPWiFiPayload> parsePayload(std::string &jsonPayload);
CommandResult execute(std::string_view jsonPayload) override;
std::optional<UpdateAPWiFiPayload> 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(projectConfig) {};
CommandResult execute(std::string &jsonPayload) override;
std::optional<MDNSPayload> parsePayload(std::string &jsonPayload);
CommandResult execute(std::string_view jsonPayload) override;
std::optional<MDNSPayload> 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(projectConfig) {};
CommandResult execute(std::string &jsonPayload) override;
std::optional<UpdateCameraConfigPayload> parsePayload(std::string &jsonPayload);
CommandResult execute(std::string_view jsonPayload) override;
std::optional<UpdateCameraConfigPayload> parsePayload(std::string_view jsonPayload);
};
class saveConfigCommand : public Command
@@ -87,7 +89,7 @@ class saveConfigCommand : public Command
public:
std::shared_ptr<ProjectConfig> projectConfig;
saveConfigCommand(std::shared_ptr<ProjectConfig> projectConfig) : projectConfig(projectConfig) {};
CommandResult execute(std::string &jsonPayload) override;
CommandResult execute(std::string_view jsonPayload) override;
};
// mostlikely missing commands

View File

@@ -1,5 +1,7 @@
#include "RestAPI.hpp"
#define POST_METHOD "POST"
RestAPI::RestAPI(std::string url, std::shared_ptr<CommandManager> 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());
}