11#include " CommandManager.hpp"
22
3- CommandManager::CommandManager (ProjectConfig* deviceConfig)
4- : deviceConfig(deviceConfig) {}
3+ std::unique_ptr<ICommand> CommandManager::createCommand (CommandType commandType,
4+ JsonVariant& data) {
5+ switch (commandType) {
6+ case CommandType::PING :
7+ return std::make_unique<PingCommand>();
8+ case CommandType::SET_WIFI :
9+ return std::make_unique<SetWiFiCommand>(this ->projectConfig , data);
10+ case CommandType::SET_MDNS :
11+ return std::make_unique<SetMDNSCommand>(this ->projectConfig , data);
12+ case CommandType::SAVE_CONFIG :
13+ return std::make_unique<SaveConfigCommand>(this ->projectConfig );
14+ }
15+ }
516
6- const CommandType CommandManager::getCommandType (JsonVariant& command) {
17+ CommandType CommandManager::getCommandType (JsonVariant& command) {
718 if (!command.containsKey (" command" ))
819 return CommandType::None;
920
@@ -18,64 +29,87 @@ bool CommandManager::hasDataField(JsonVariant& command) {
1829 return command.containsKey (" data" );
1930}
2031
21- void CommandManager::handleCommands (CommandsPayload commandsPayload) {
32+ std::variant<std::vector<CommandResult>, CommandResult>
33+ CommandManager::handleBatchCommands (CommandsPayload commandsPayload) {
34+ std::vector<CommandResult> results = {};
35+ std::vector<std::string> errors = {};
36+ std::vector<std::unique_ptr<ICommand>> commands;
37+
2238 if (!commandsPayload.data .containsKey (" commands" )) {
23- log_e (" Json data sent not supported, lacks commands field" );
24- return ;
39+ std::string error = " Json data sent not supported, lacks commands field" ;
40+ log_e (" %s" , error.c_str ());
41+ return CommandResult::getErrorResult (
42+ Helpers::format_string (" \" error\" :\" %s\" " , error));
2543 }
2644
2745 for (JsonVariant commandData :
2846 commandsPayload.data [" commands" ].as <JsonArray>()) {
29- this ->handleCommand (commandData);
47+ auto command_or_result = this ->createCommandFromJsonVariant (commandData);
48+
49+ if (auto command_ptr =
50+ std::get_if<std::unique_ptr<ICommand>>(&command_or_result)) {
51+ auto validation_result = (*command_ptr)->validate ();
52+ if (validation_result.isSuccess ())
53+ commands.emplace_back (std::move ((*command_ptr)));
54+ else
55+ errors.push_back (validation_result.getErrorMessage ());
56+ } else {
57+ errors.push_back (
58+ std::get<CommandResult>(command_or_result).getErrorMessage ());
59+ continue ;
60+ }
3061 }
3162
32- this ->deviceConfig ->save ();
33- }
63+ // if we have any errors, consolidate them into a single message and return
64+ if (errors.size () > 0 ) {
65+ return CommandResult::getErrorResult (Helpers::format_string (
66+ " \" error\" :\" [%s]\" " , this ->join_strings (errors, " ," )));
67+ }
3468
35- void CommandManager::handleCommand (JsonVariant command) {
36- auto command_type = this ->getCommandType (command);
69+ for (auto & valid_command : commands) {
70+ results.push_back (valid_command->execute ());
71+ }
3772
38- switch (command_type) {
39- case CommandType::SET_WIFI : {
40- if (!this ->hasDataField (command))
41- // malformed command, lacked data field
42- break ;
73+ return results;
74+ }
4375
44- if (!command[" data" ].containsKey (" ssid" ) ||
45- !command[" data" ].containsKey (" password" ))
46- break ;
76+ CommandResult CommandManager::handleSingleCommand (
77+ CommandsPayload commandsPayload) {
78+ if (!commandsPayload.data .containsKey (" command" )) {
79+ std::string error = " Json data sent not supported, lacks commands field" ;
80+ log_e (" %s" , error.c_str ());
4781
48- std::string customNetworkName = " main " ;
49- if (command[ " data " ]. containsKey ( " network_name " ))
50- customNetworkName = command[ " data " ][ " network_name " ]. as <std::string>();
82+ CommandResult::getErrorResult (
83+ Helpers::format_string ( " \" error \" : \" %s \" " , error));
84+ }
5185
52- this ->deviceConfig ->setWifiConfig (customNetworkName,
53- command[" data" ][" ssid" ],
54- command[" data" ][" password" ],
55- 0 , // channel, should this be zero?
56- 0 , // power, should this be zero?
57- false , false );
86+ JsonVariant commandData = commandsPayload.data [" command" ];
87+ auto command_or_result = this ->createCommandFromJsonVariant (commandData);
5888
59- break ;
60- }
61- case CommandType::SET_MDNS : {
62- if (!this ->hasDataField (command))
63- break ;
89+ if (std::holds_alternative<CommandResult>(command_or_result)) {
90+ return std::get<CommandResult>(command_or_result);
91+ }
6492
65- if (!command[" data" ].containsKey (" hostname" ) ||
66- !strlen (command[" data" ][" hostname" ]))
67- break ;
93+ auto command =
94+ std::move (std::get<std::unique_ptr<ICommand>>(command_or_result));
6895
69- this ->deviceConfig ->setMDNSConfig (command[" data" ][" hostname" ],
70- " openiristracker" , false );
96+ auto validation_result = command->validate ();
97+ if (!validation_result.isSuccess ()) {
98+ return validation_result;
99+ };
71100
72- break ;
73- }
74- case CommandType::PING : {
75- Serial.println (" PONG \n\r " );
76- break ;
77- }
78- default :
79- break ;
101+ return command->execute ();
102+ }
103+
104+ std::variant<std::unique_ptr<ICommand>, CommandResult>
105+ CommandManager::createCommandFromJsonVariant (JsonVariant& command) {
106+ auto command_type = this ->getCommandType (command);
107+ if (command_type == CommandType::None) {
108+ std::string error =
109+ Helpers::format_string (" Command not supported: %s" , command[" command" ]);
110+ log_e (" %s" , error.c_str ());
111+ throw CommandResult::getErrorResult (
112+ Helpers::format_string (" \" error\" :\" %s\" " , error));
80113 }
114+ return this ->createCommand (command_type, command);
81115}
0 commit comments