This repository was archived by the owner on Dec 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 47
Expand file tree
/
Copy pathCommandManager.cpp
More file actions
149 lines (126 loc) · 5.1 KB
/
CommandManager.cpp
File metadata and controls
149 lines (126 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "CommandManager.hpp"
std::unique_ptr<ICommand> CommandManager::createCommand(CommandType commandType,
JsonVariant& data) {
switch (commandType) {
case CommandType::PING:
return std::make_unique<PingCommand>();
case CommandType::SET_WIFI:
return std::make_unique<SetWiFiCommand>(this->projectConfig, data);
case CommandType::SET_MDNS:
return std::make_unique<SetMDNSCommand>(this->projectConfig, data);
case CommandType::SAVE_CONFIG:
return std::make_unique<SaveConfigCommand>(this->projectConfig);
case CommandType::SET_FPS:
return std::make_unique<SetFPSCommand>(this->projectConfig, data);
case CommandType::TOGGLE_STREAM:
return std::make_unique<ToggleStreamCommand>(this->streamServer, data);
default:
return nullptr;
}
}
CommandType CommandManager::getCommandType(JsonVariant& command) {
if (!command.containsKey("command"))
return CommandType::None;
if (auto search = commandMap.find(command["command"]);
search != commandMap.end())
return search->second;
return CommandType::None;
}
bool CommandManager::hasDataField(JsonVariant& command) {
return command.containsKey("data");
}
CommandResult CommandManager::handleBatchCommands(
CommandsPayload commandsPayload) {
std::vector<std::unique_ptr<ICommand>> commands;
std::vector<std::string> results = {};
std::vector<std::string> errors = {};
if (!commandsPayload.data.containsKey("commands")) {
std::string error = "Json data sent not supported, lacks commands field";
log_e("%s", error.c_str());
return CommandResult::getErrorResult(error);
}
// we first try to create a command based on the payload
// if it's not supported, we register that as an error
// then, we try to validate the command, if it's succeful
// we add it to the list of commands to execute
// otherwise - you guessed it, error
// we only execute them if no errors were registered
for (JsonVariant commandData :
commandsPayload.data["commands"].as<JsonArray>()) {
auto command_or_result = this->createCommandFromJsonVariant(commandData);
if (auto command_ptr =
std::get_if<std::unique_ptr<ICommand>>(&command_or_result)) {
auto validation_result = (*command_ptr)->validate();
if (validation_result.isSuccess())
commands.emplace_back(std::move((*command_ptr)));
else
errors.push_back(validation_result.getErrorMessage());
} else {
errors.push_back(
std::get<CommandResult>(command_or_result).getErrorMessage());
continue;
}
}
// if we have any errors, consolidate them into a single message and return
if (errors.size() > 0)
return CommandResult::getErrorResult(
Helpers::format_string("\"[%s]\"", this->join_strings(errors, ", ")));
for (auto& valid_command : commands) {
auto result = valid_command->execute();
if (result.isSuccess()) {
results.push_back(result.getSuccessMessage());
} else {
// since we're executing them already, and we've encountered an error
// we should add it to regular results
results.push_back(result.getErrorMessage());
}
}
return CommandResult::getErrorResult(
Helpers::format_string("\"[%s]\"", this->join_strings(results, ", ")));
;
}
CommandResult CommandManager::handleSingleCommand(
CommandsPayload commandsPayload) {
if (!commandsPayload.data.containsKey("command")) {
std::string error = "Json data sent not supported, lacks commands field";
log_e("%s", error.c_str());
CommandResult::getErrorResult(error);
}
JsonVariant commandData = commandsPayload.data;
auto command_or_result = this->createCommandFromJsonVariant(commandData);
if (std::holds_alternative<CommandResult>(command_or_result)) {
return std::get<CommandResult>(command_or_result);
}
auto command =
std::move(std::get<std::unique_ptr<ICommand>>(command_or_result));
auto validation_result = command->validate();
if (!validation_result.isSuccess()) {
return validation_result;
};
return command->execute();
}
std::variant<std::unique_ptr<ICommand>, CommandResult>
CommandManager::createCommandFromJsonVariant(JsonVariant& command) {
auto command_type = this->getCommandType(command);
if (command_type == CommandType::None) {
std::string error =
Helpers::format_string("Command not supported: %s", command["command"]);
log_e("%s", error.c_str());
return CommandResult::getErrorResult(error);
}
if (!this->hasDataField(command)) {
std::string error = Helpers::format_string(
"Command is missing data field: %s", command["command"]);
log_e("%s", error.c_str());
return CommandResult::getErrorResult(error);
}
auto command_data = command["data"].as<JsonVariant>();
auto command_ptr = this->createCommand(command_type, command_data);
if (!command_ptr) {
std::string error = Helpers::format_string("Command is not supported: %s",
command["command"]);
log_e("%s", error.c_str());
return CommandResult::getErrorResult(error);
}
return command_ptr;
}