Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: NCP5623B GpsParser ISL29011 libmDot-mbed5 MTS-Serial MMA845x DOGS102 MPL3115A2
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 CmdJoinDelay(_dot, _serial)); 00056 addCommand(new CmdDeviceId(_dot, _serial)); 00057 00058 addCommand(new CmdNetworkAddress(_dot, _serial)); 00059 addCommand(new CmdNetworkSessionKey(_dot, _serial)); 00060 addCommand(new CmdDataSessionKey(_dot, _serial)); 00061 addCommand(new CmdNetworkKey(_dot, _serial)); 00062 addCommand(new CmdNetworkId(_dot, _serial)); 00063 00064 addCommand(new CmdNetworkJoinMode(_dot, _serial)); 00065 addCommand(new CmdTxDataRate(_dot, _serial)); 00066 addCommand(new CmdTxPower(_dot, _serial)); 00067 00068 addCommand(new CmdMinimumSize(_dot, _serial)); 00069 addCommand(new CmdMaximumSize(_dot, _serial)); 00070 addCommand(new CmdMinimumPower(_dot, _serial)); 00071 addCommand(new CmdMaximumPower(_dot, _serial)); 00072 addCommand(new CmdData(_dot, _serial)); 00073 addCommand(new CmdGetSurveyDataFile(_dot, _serial)); 00074 addCommand(new CmdDeleteSurveyDataFile(_dot, _serial)); 00075 addCommand(new CmdDummy(_dot, "Exit to main menu", "AT+EXIT", "Exit configuration and return to the main menu")); 00076 00077 #if MTS_RADIO_DEBUG_COMMANDS 00078 addCommand(new CmdWriteProtectedConfig(_dot)); 00079 addCommand(new CmdSendContinuous(_dot)); 00080 addCommand(new CmdTxFrequency(_dot)); 00081 #endif 00082 } 00083 00084 void ModeConfig::printHelp() { 00085 const char* name = NULL; 00086 const char* text = NULL; 00087 const char* desc = NULL; 00088 const char* tab = "\t"; 00089 00090 std::string header("Command"); 00091 header.append(tab); 00092 header.append(tab); 00093 header.append("Name"); 00094 header.append(tab); 00095 header.append(tab); 00096 header.append(tab); 00097 header.append("Description"); 00098 00099 write(newline); 00100 write(header.c_str()); 00101 write(newline); 00102 write(newline); 00103 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end(); ++it) { 00104 name = (*it)->name(); 00105 text = (*it)->text(); 00106 desc = (*it)->desc(); 00107 write(text); 00108 if (strlen(text) < 8) 00109 write(tab); 00110 write(tab); 00111 write(name); 00112 if (strlen(name) < 8) 00113 write(tab); 00114 if (strlen(name) < 16) 00115 write(tab); 00116 write(tab); 00117 write(desc); 00118 write(newline); 00119 } 00120 00121 write(newline); 00122 } 00123 00124 bool ModeConfig::writeable() { 00125 return _serial.writeable(); 00126 } 00127 00128 bool ModeConfig::readable() { 00129 return _serial.readable(); 00130 } 00131 00132 char ModeConfig::read() { 00133 char ch; 00134 _serial.read(&ch, 1); 00135 return ch; 00136 } 00137 00138 void ModeConfig::write(const char* message) { 00139 while (!writeable()) 00140 ; 00141 _serial.write(message, strlen(message)); 00142 } 00143 00144 void ModeConfig::writef(const char* format, ...) { 00145 char buff[256]; 00146 00147 va_list ap; 00148 va_start(ap, format); 00149 int size = vsnprintf(buff, 256, format, ap); 00150 while (!writeable()) 00151 ; 00152 _serial.write(buff, size); 00153 va_end(ap); 00154 } 00155 00156 bool ModeConfig::start() { 00157 char ch; 00158 bool running = true; 00159 bool echo = _dot->getEcho(); 00160 std::string command; 00161 std::deque<std::string> history; 00162 int history_index = -1; 00163 std::vector<std::string> args; 00164 00165 osSignalClear(_main_id, buttonSignal); 00166 00167 _lc.display(); 00168 00169 //Run terminal session 00170 while (running) { 00171 _lc.roll(); 00172 00173 osEvent e = Thread::signal_wait(buttonSignal, 20); 00174 if (e.status == osEventSignal) { 00175 ButtonHandler::ButtonEvent _be = _buttons->getButtonEvent(); 00176 switch (_be) { 00177 case ButtonHandler::sw1_press: 00178 _band = _dot->getFrequencyBand(); 00179 break; 00180 case ButtonHandler::sw2_press: 00181 _band = _dot->getFrequencyBand(); 00182 break; 00183 case ButtonHandler::sw1_hold: 00184 _band = _dot->getFrequencyBand(); 00185 return true; 00186 default: 00187 break; 00188 } 00189 } 00190 00191 ch = '\0'; 00192 00193 // read characters 00194 if (readable()) { 00195 ch = read(); 00196 00197 if (ch == '\b' || ch == 0x7f) { 00198 if (!command.empty()) { 00199 writef("\b \b"); 00200 command.erase(command.size() - 1); 00201 } 00202 continue; 00203 } else if (ch == 0x1b || ch == 0x09) { 00204 osDelay(20); 00205 // catch escape sequence, or tab 00206 char ch1, ch2; 00207 00208 if (readable()) { 00209 ch1 = read(); 00210 if (readable()) 00211 ch2 = read(); 00212 00213 if (ch1 == 0x5b && ch2 == 0x41) { 00214 // up key 00215 for (int i = 0; i < command.size()+1; i++) { 00216 writef("\b \b"); 00217 } 00218 if (history.size() > 0) { 00219 if (++history_index >= history.size() - 1) 00220 history_index = history.size() - 1; 00221 00222 command = history[history_index]; 00223 writef("%s", history[history_index].c_str()); 00224 } else { 00225 command.clear(); 00226 } 00227 } else if (ch1 == 0x5b && ch2 == 0x42) { 00228 00229 // down key 00230 for (int i = 0; i < command.size()+1; i++) { 00231 writef("\b \b"); 00232 } 00233 00234 if (--history_index < 0) { 00235 history_index = -1; 00236 command.clear(); 00237 } else { 00238 command = history[history_index]; 00239 writef("%s", history[history_index].c_str()); 00240 } 00241 } 00242 } 00243 while (readable()) read(); 00244 continue; 00245 } else { 00246 command += ch; 00247 } 00248 00249 // echo chars if enabled 00250 if (echo && !(ch == '\r' || ch == '\n')) 00251 writef("%c", ch); 00252 } 00253 00254 // look for end of command line 00255 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) { 00256 // remove new line or cr character 00257 command.erase(command.size() - 1); 00258 write("\r"); // match standard modem output 00259 write(newline); 00260 } else { 00261 continue; 00262 } 00263 00264 // trim whitespace from command 00265 mts::Text::trim(command, "\r\n\t "); 00266 00267 if (command.size() < 1) { 00268 command.clear(); 00269 continue; 00270 } 00271 00272 // parse command and args 00273 args.clear(); 00274 00275 // find first '=' character 00276 size_t delim_index = command.find("="); 00277 if (delim_index != std::string::npos) { 00278 args.push_back(command.substr(0, delim_index)); 00279 } else { 00280 // find first ' ' character 00281 delim_index = command.find(" "); 00282 if (delim_index != std::string::npos) { 00283 args.push_back(command.substr(0, delim_index)); 00284 } else { 00285 args.push_back(command); 00286 } 00287 } 00288 00289 if (delim_index != std::string::npos) { 00290 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ","); 00291 args.insert(args.end(), params.begin(), params.end()); 00292 } 00293 00294 args[0] = mts::Text::toUpper(args[0]); 00295 00296 // print help 00297 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) { 00298 printHelp(); 00299 command.clear(); 00300 } else if (args[0].find("AT+EXIT") == 0 && args[0].length() == 7) { 00301 write(done); 00302 _band = _dot->getFrequencyBand(); 00303 return true; 00304 } else { 00305 bool found = false; 00306 bool query = false; 00307 00308 std::string lookfor = args[0]; 00309 00310 // per command help 00311 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0)) 00312 lookfor = mts::Text::toUpper(args[1]); 00313 00314 // trim off any trailing '?' and mark as a query command 00315 if (args[0].rfind("?") == args[0].length() - 1) { 00316 query = true; 00317 lookfor = args[0].substr(0, args[0].length() - 1); 00318 } 00319 00320 // search for command 00321 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) { 00322 Command* cmd = *it; 00323 00324 // match CMD or CMD? syntax if command is queryable 00325 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) { 00326 found = true; 00327 if (args[0] == "HELP") { 00328 writef("%s%s", cmd->help(), newline); 00329 write(done); 00330 } 00331 00332 else if (args.size() > 1 && args[1] == "?") { 00333 writef("%s%s", cmd->usage().c_str(), newline); 00334 write(done); 00335 } else if (!cmd->verify(args)) { 00336 writef("%s%s", cmd->errorMessage().c_str(), newline); 00337 writef("%s", error); 00338 } else { 00339 if (cmd->action(args) == 0) { 00340 writef("%s", done); 00341 } else { 00342 writef("%s%s", cmd->errorMessage().c_str(), newline); 00343 writef("%s", error); 00344 } 00345 } 00346 } 00347 } 00348 00349 if (!found) { 00350 writef("%s", command_error); 00351 writef("%s", error); 00352 } 00353 } 00354 00355 if (history.size() == 0 || history.front() != command) 00356 history.push_front(command); 00357 history_index = -1; 00358 command.clear(); 00359 00360 while (history.size() > 10) 00361 history.pop_back(); 00362 00363 } 00364 _band = _dot->getFrequencyBand(); 00365 return false; 00366 }
Generated on Tue Jul 12 2022 17:02:18 by
1.7.2

