Custom Channel Plan version of MTDOT Box firmware
Dependencies: DOGS102 GpsParser ISL29011 MMA845x MPL3115A2 MTS-Serial NCP5623B libmDot-Custom mDot_Channel_Plans
Fork of MTDOT-BOX-EVB-Factory-Firmware by
ModeConfig.cpp
00001 /* Copyright (c) <2016> <MultiTech Systems>, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "ModeConfig.h" 00020 #include "ctype.h" 00021 #include "Command.h" 00022 #include "ButtonHandler.h" 00023 #include <cstdarg> 00024 #include <deque> 00025 00026 const char ModeConfig::newline[] = "\r\n"; 00027 00028 // Command error text... 00029 const char ModeConfig::command_error[] = "Command not found!\r\n"; 00030 00031 // Response texts... 00032 const char ModeConfig::done[] = "\r\nOK\r\n"; 00033 const char ModeConfig::error[] = "\r\nERROR\r\n"; 00034 00035 void ModeConfig::addCommand(Command* cmd) { 00036 _commands.push_back(cmd); 00037 } 00038 00039 ModeConfig::ModeConfig(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps, SensorHandler* sensors) 00040 : Mode(lcd, buttons, dot, lora, gps, sensors), 00041 _lc(lcd), 00042 _serial(USBTX, USBRX, 512, 512) 00043 { 00044 _serial.baud(115200); 00045 00046 addCommand(new CmdAttention(_dot)); 00047 addCommand(new CmdIdentification(_dot, _serial)); 00048 addCommand(new CmdFactoryDefault(_dot)); 00049 addCommand(new CmdSaveConfig(_dot)); 00050 addCommand(new CmdDisplayConfig(_dot, _serial)); 00051 00052 addCommand(new CmdFrequencyBand(_dot, _serial)); 00053 addCommand(new CmdFrequencySubBand(_dot, _serial)); 00054 addCommand(new CmdPublicNetwork(_dot, _serial)); 00055 addCommand(new CmdDeviceId(_dot, _serial)); 00056 00057 addCommand(new CmdNetworkAddress(_dot, _serial)); 00058 addCommand(new CmdNetworkSessionKey(_dot, _serial)); 00059 addCommand(new CmdDataSessionKey(_dot, _serial)); 00060 addCommand(new CmdNetworkKey(_dot, _serial)); 00061 addCommand(new CmdNetworkId(_dot, _serial)); 00062 00063 addCommand(new CmdNetworkJoinMode(_dot, _serial)); 00064 addCommand(new CmdTxDataRate(_dot, _serial)); 00065 addCommand(new CmdTxPower(_dot, _serial)); 00066 00067 addCommand(new CmdMinimumSize(_dot, _serial)); 00068 addCommand(new CmdMaximumSize(_dot, _serial)); 00069 addCommand(new CmdMinimumPower(_dot, _serial)); 00070 addCommand(new CmdMaximumPower(_dot, _serial)); 00071 addCommand(new CmdData(_dot, _serial)); 00072 addCommand(new CmdGetSurveyDataFile(_dot, _serial)); 00073 addCommand(new CmdDeleteSurveyDataFile(_dot, _serial)); 00074 addCommand(new CmdDummy(_dot, "Exit to main menu", "AT+EXIT", "Exit configuration and return to the main menu")); 00075 00076 #if MTS_RADIO_DEBUG_COMMANDS 00077 addCommand(new CmdWriteProtectedConfig(_dot)); 00078 addCommand(new CmdSendContinuous(_dot)); 00079 addCommand(new CmdTxFrequency(_dot)); 00080 #endif 00081 } 00082 00083 void ModeConfig::printHelp() { 00084 const char* name = NULL; 00085 const char* text = NULL; 00086 const char* desc = NULL; 00087 const char* tab = "\t"; 00088 00089 std::string header("Command"); 00090 header.append(tab); 00091 header.append(tab); 00092 header.append("Name"); 00093 header.append(tab); 00094 header.append(tab); 00095 header.append(tab); 00096 header.append("Description"); 00097 00098 write(newline); 00099 write(header.c_str()); 00100 write(newline); 00101 write(newline); 00102 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end(); ++it) { 00103 name = (*it)->name(); 00104 text = (*it)->text(); 00105 desc = (*it)->desc(); 00106 write(text); 00107 if (strlen(text) < 8) 00108 write(tab); 00109 write(tab); 00110 write(name); 00111 if (strlen(name) < 8) 00112 write(tab); 00113 if (strlen(name) < 16) 00114 write(tab); 00115 write(tab); 00116 write(desc); 00117 write(newline); 00118 } 00119 00120 write(newline); 00121 } 00122 00123 bool ModeConfig::writeable() { 00124 return _serial.writeable(); 00125 } 00126 00127 bool ModeConfig::readable() { 00128 return _serial.readable(); 00129 } 00130 00131 char ModeConfig::read() { 00132 char ch; 00133 _serial.read(&ch, 1); 00134 return ch; 00135 } 00136 00137 void ModeConfig::write(const char* message) { 00138 while (!writeable()) 00139 ; 00140 _serial.write(message, strlen(message)); 00141 } 00142 00143 void ModeConfig::writef(const char* format, ...) { 00144 char buff[256]; 00145 00146 va_list ap; 00147 va_start(ap, format); 00148 int size = vsnprintf(buff, 256, format, ap); 00149 while (!writeable()) 00150 ; 00151 _serial.write(buff, size); 00152 va_end(ap); 00153 } 00154 00155 bool ModeConfig::start() { 00156 char ch; 00157 bool running = true; 00158 bool echo = _dot->getEcho(); 00159 std::string command; 00160 std::deque<std::string> history; 00161 int history_index = -1; 00162 std::vector<std::string> args; 00163 00164 osSignalClear(_main_id, buttonSignal); 00165 00166 _lc.display(); 00167 00168 //Run terminal session 00169 while (running) { 00170 _lc.roll(); 00171 00172 osEvent e = Thread::signal_wait(buttonSignal, 20); 00173 if (e.status == osEventSignal) { 00174 ButtonHandler::ButtonEvent _be = _buttons->getButtonEvent(); 00175 switch (_be) { 00176 case ButtonHandler::sw1_press: 00177 break; 00178 case ButtonHandler::sw2_press: 00179 break; 00180 case ButtonHandler::sw1_hold: 00181 return true; 00182 default: 00183 break; 00184 } 00185 } 00186 00187 ch = '\0'; 00188 00189 // read characters 00190 if (readable()) { 00191 ch = read(); 00192 00193 if (ch == '\b' || ch == 0x7f) { 00194 if (!command.empty()) { 00195 writef("\b \b"); 00196 command.erase(command.size() - 1); 00197 } 00198 continue; 00199 } else if (ch == 0x1b || ch == 0x09) { 00200 osDelay(20); 00201 // catch escape sequence, or tab 00202 char ch1, ch2; 00203 00204 if (readable()) { 00205 ch1 = read(); 00206 if (readable()) 00207 ch2 = read(); 00208 00209 if (ch1 == 0x5b && ch2 == 0x41) { 00210 // up key 00211 for (int i = 0; i < command.size()+1; i++) { 00212 writef("\b \b"); 00213 } 00214 if (history.size() > 0) { 00215 if (++history_index >= history.size() - 1) 00216 history_index = history.size() - 1; 00217 00218 command = history[history_index]; 00219 writef("%s", history[history_index].c_str()); 00220 } else { 00221 command.clear(); 00222 } 00223 } else if (ch1 == 0x5b && ch2 == 0x42) { 00224 00225 // down key 00226 for (int i = 0; i < command.size()+1; i++) { 00227 writef("\b \b"); 00228 } 00229 00230 if (--history_index < 0) { 00231 history_index = -1; 00232 command.clear(); 00233 } else { 00234 command = history[history_index]; 00235 writef("%s", history[history_index].c_str()); 00236 } 00237 } 00238 } 00239 while (readable()) read(); 00240 continue; 00241 } else { 00242 command += ch; 00243 } 00244 00245 // echo chars if enabled 00246 if (echo && !(ch == '\r' || ch == '\n')) 00247 writef("%c", ch); 00248 } 00249 00250 // look for end of command line 00251 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) { 00252 // remove new line or cr character 00253 command.erase(command.size() - 1); 00254 write("\r"); // match standard modem output 00255 write(newline); 00256 } else { 00257 continue; 00258 } 00259 00260 // trim whitespace from command 00261 mts::Text::trim(command, "\r\n\t "); 00262 00263 if (command.size() < 1) { 00264 command.clear(); 00265 continue; 00266 } 00267 00268 // parse command and args 00269 args.clear(); 00270 00271 // find first '=' character 00272 size_t delim_index = command.find("="); 00273 if (delim_index != std::string::npos) { 00274 args.push_back(command.substr(0, delim_index)); 00275 } else { 00276 // find first ' ' character 00277 delim_index = command.find(" "); 00278 if (delim_index != std::string::npos) { 00279 args.push_back(command.substr(0, delim_index)); 00280 } else { 00281 args.push_back(command); 00282 } 00283 } 00284 00285 if (delim_index != std::string::npos) { 00286 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ","); 00287 args.insert(args.end(), params.begin(), params.end()); 00288 } 00289 00290 args[0] = mts::Text::toUpper(args[0]); 00291 00292 // print help 00293 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) { 00294 printHelp(); 00295 command.clear(); 00296 } else if (args[0].find("AT+EXIT") == 0 && args[0].length() == 7) { 00297 write(done); 00298 return true; 00299 } else { 00300 bool found = false; 00301 bool query = false; 00302 00303 std::string lookfor = args[0]; 00304 00305 // per command help 00306 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0)) 00307 lookfor = mts::Text::toUpper(args[1]); 00308 00309 // trim off any trailing '?' and mark as a query command 00310 if (args[0].rfind("?") == args[0].length() - 1) { 00311 query = true; 00312 lookfor = args[0].substr(0, args[0].length() - 1); 00313 } 00314 00315 // search for command 00316 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) { 00317 Command* cmd = *it; 00318 00319 // match CMD or CMD? syntax if command is queryable 00320 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) { 00321 found = true; 00322 if (args[0] == "HELP") { 00323 writef("%s%s", cmd->help(), newline); 00324 write(done); 00325 } 00326 00327 else if (args.size() > 1 && args[1] == "?") { 00328 writef("%s%s", cmd->usage().c_str(), newline); 00329 write(done); 00330 } else if (!cmd->verify(args)) { 00331 writef("%s%s", cmd->errorMessage().c_str(), newline); 00332 writef("%s", error); 00333 } else { 00334 if (cmd->action(args) == 0) { 00335 writef("%s", done); 00336 } else { 00337 writef("%s%s", cmd->errorMessage().c_str(), newline); 00338 writef("%s", error); 00339 } 00340 } 00341 } 00342 } 00343 00344 if (!found) { 00345 writef("%s", command_error); 00346 writef("%s", error); 00347 } 00348 } 00349 00350 if (history.size() == 0 || history.front() != command) 00351 history.push_front(command); 00352 history_index = -1; 00353 command.clear(); 00354 00355 while (history.size() > 10) 00356 history.pop_back(); 00357 00358 } 00359 return false; 00360 }
Generated on Tue Jul 12 2022 13:07:49 by 1.7.2