few changes for RTS/CTS control
Dependencies: MTS-Serial libmDot mbed-rtos mbed
Fork of mDot_AT_firmware by
CommandTerminal.cpp
00001 #include "ctype.h" 00002 #include "CommandTerminal.h" 00003 #include "Command.h" 00004 #include "MTSLog.h" 00005 #include <cstdarg> 00006 #include <deque> 00007 00008 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n"; 00009 const char CommandTerminal::helpline[] = "Enter '?' for help\r\n"; 00010 00011 const char CommandTerminal::newline[] = "\r\n"; 00012 00013 // Command error text... 00014 const char CommandTerminal::command_error[] = "Command not found!\r\n"; 00015 00016 // Response texts... 00017 const char CommandTerminal::help[] = "\r\nHelp\r\n"; 00018 const char CommandTerminal::cmd_error[] = "Invalid command\r\n"; 00019 const char CommandTerminal::connect[] = "\r\nCONNECT\r\n"; 00020 const char CommandTerminal::no_carrier[] = "\r\nNO CARRIER\r\n"; 00021 const char CommandTerminal::done[] = "\r\nOK\r\n"; 00022 const char CommandTerminal::error[] = "\r\nERROR\r\n"; 00023 00024 // Escape sequence... 00025 const char CommandTerminal::escape_sequence[] = "+++"; 00026 00027 mts::ATSerial* CommandTerminal::_serialp = NULL; 00028 00029 static bool serial_data_mode = false; 00030 static bool peer_to_peer = false; 00031 00032 void CommandTerminal::addCommand(Command* cmd) { 00033 _commands.push_back(cmd); 00034 } 00035 00036 CommandTerminal::CommandTerminal(mts::ATSerial& serial, mDot* dot) 00037 : 00038 _serial(serial), 00039 _dot(dot), 00040 _events(new RadioEvent(serial)), 00041 _mode(mDot::COMMAND_MODE), 00042 _idle_thread(idle, NULL, osPriorityLow), 00043 _sleep_standby(true), 00044 _xbee_on_sleep(XBEE_ON_SLEEP) { 00045 00046 _dot->setEvents(_events); 00047 _dot->setWakeupCallback(this, &CommandTerminal::wakeup); 00048 _serialp = &serial; 00049 00050 addCommand(new CmdAttention(_dot)); 00051 addCommand(new CmdIdentification(_dot, serial)); 00052 addCommand(new CmdResetCpu(_dot, serial)); 00053 addCommand(new CmdDummy(_dot, "Enable/Disable Echo", "ATE", "ATE0: disable, ATE1: enable")); 00054 addCommand(new CmdDummy(_dot, "Enable/Disable Verbose", "ATV", "ATV0: disable, ATV1: enable")); 00055 addCommand(new CmdDummy(_dot, "Hardware Flow Control", "AT&K", "AT&K0: disable, AT&K3: enable")); 00056 00057 addCommand(new CmdFactoryDefault(_dot)); 00058 addCommand(new CmdSaveConfig(_dot)); 00059 addCommand(new CmdDisplayConfig(_dot, serial)); 00060 addCommand(new CmdDisplayStats(_dot, serial)); 00061 addCommand(new CmdResetStats(_dot, serial)); 00062 addCommand(new CmdSerialBaudRate(_dot, serial)); 00063 addCommand(new CmdDebugBaudRate(_dot, serial)); 00064 addCommand(new CmdStartUpMode(_dot, serial)); 00065 00066 addCommand(new CmdFrequencyBand(_dot, serial)); 00067 addCommand(new CmdFrequencySubBand(_dot, serial)); 00068 addCommand(new CmdPublicNetwork(_dot, serial)); 00069 addCommand(new CmdDeviceId(_dot, serial)); 00070 addCommand(new CmdDeviceClass(_dot, serial)); 00071 00072 addCommand(new CmdAppPort(_dot, serial)); 00073 addCommand(new CmdNetworkAddress(_dot, serial)); 00074 addCommand(new CmdNetworkSessionKey(_dot, serial)); 00075 addCommand(new CmdDataSessionKey(_dot, serial)); 00076 addCommand(new CmdUplinkCounter(_dot, serial)); 00077 addCommand(new CmdDownlinkCounter(_dot, serial)); 00078 addCommand(new CmdSaveSession(_dot, serial)); 00079 addCommand(new CmdRestoreSession(_dot, serial)); 00080 addCommand(new CmdNetworkKey(_dot, serial)); 00081 addCommand(new CmdNetworkId(_dot, serial)); 00082 00083 addCommand(new CmdJoinDelay(_dot, serial)); 00084 addCommand(new CmdJoinRequest(_dot, serial)); 00085 addCommand(new CmdJoinRetries(_dot, serial)); 00086 addCommand(new CmdJoinByteOrder(_dot, serial)); 00087 addCommand(new CmdNetworkJoinMode(_dot, serial)); 00088 addCommand(new CmdPreserveSession(_dot, serial)); 00089 addCommand(new CmdNetworkJoinStatus(_dot, serial)); 00090 addCommand(new CmdNetworkLinkCheck(_dot, serial)); 00091 addCommand(new CmdLinkCheckCount(_dot, serial)); 00092 addCommand(new CmdLinkCheckThreshold(_dot, serial)); 00093 addCommand(new CmdEncryption(_dot, serial)); 00094 00095 addCommand(new CmdRssi(_dot, serial)); 00096 addCommand(new CmdSnr(_dot, serial)); 00097 addCommand(new CmdDataPending(_dot, serial)); 00098 00099 addCommand(new CmdSessionDataRate(_dot, serial)); 00100 00101 addCommand(new CmdTxDataRate(_dot, serial)); 00102 addCommand(new CmdTxPower(_dot, serial)); 00103 addCommand(new CmdAntennaGain(_dot, serial)); 00104 addCommand(new CmdTxFrequency(_dot, serial)); 00105 addCommand(new CmdTxInverted(_dot, serial)); 00106 addCommand(new CmdTxWait(_dot, serial)); 00107 addCommand(new CmdTxChannel(_dot, serial)); 00108 addCommand(new CmdTxNextMs(_dot, serial)); 00109 addCommand(new CmdTimeOnAir(_dot, serial)); 00110 00111 addCommand(new CmdRxDelay(_dot, serial)); 00112 addCommand(new CmdRxOutput(_dot, serial)); 00113 addCommand(new CmdRxInverted(_dot, serial)); 00114 00115 addCommand(new CmdErrorCorrection(_dot, serial)); 00116 addCommand(new CmdCRC(_dot, serial)); 00117 addCommand(new CmdAdaptiveDataRate(_dot, serial)); 00118 00119 addCommand(new CmdACKAttempts(_dot, serial)); 00120 addCommand(new CmdRepeat(_dot, serial)); 00121 00122 addCommand(new CmdSendString(_dot, serial)); 00123 addCommand(new CmdSendBinary(_dot, serial)); 00124 addCommand(new CmdReceiveOnce(_dot, serial)); 00125 00126 addCommand(new CmdDummy(_dot, "Serial Data Mode", "AT+SD", "Enter serial data mode, exit with '+++'")); 00127 addCommand(new CmdDummy(_dot, "Sleep Mode", "AT+SLEEP", "Enter sleep mode (0:deepsleep,1:sleep)")); 00128 addCommand(new CmdSerialClearOnError(_dot, serial)); 00129 addCommand(new CmdWakeMode(_dot, serial)); 00130 addCommand(new CmdWakeInterval(_dot, serial)); 00131 addCommand(new CmdWakePin(_dot, serial)); 00132 addCommand(new CmdWakeDelay(_dot, serial)); 00133 addCommand(new CmdWakeTimeout(_dot, serial)); 00134 addCommand(new CmdPing(_dot, serial)); 00135 addCommand(new CmdLogLevel(_dot, serial)); 00136 00137 addCommand(new CmdDummy(_dot, "***** Test Commands *****", "", "")); 00138 addCommand(new CmdRxDataRate(_dot, serial)); 00139 addCommand(new CmdRxFrequency(_dot, serial)); 00140 addCommand(new CmdReceiveContinuous(_dot, serial)); 00141 addCommand(new CmdSendStringOnInterval(_dot, serial)); 00142 } 00143 00144 void CommandTerminal::printHelp() { 00145 const char* name = NULL; 00146 const char* text = NULL; 00147 const char* desc = NULL; 00148 const char* tab = "\t"; 00149 00150 std::string header("Command"); 00151 header.append(tab); 00152 header.append(tab); 00153 header.append("Name"); 00154 header.append(tab); 00155 header.append(tab); 00156 header.append(tab); 00157 header.append("Description"); 00158 00159 write(newline); 00160 write(header.c_str()); 00161 write(newline); 00162 write(newline); 00163 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end(); ++it) { 00164 name = (*it)->name(); 00165 text = (*it)->text(); 00166 desc = (*it)->desc(); 00167 write(text); 00168 if (strlen(text) < 8) 00169 write(tab); 00170 write(tab); 00171 write(name); 00172 if (strlen(name) < 8) 00173 write(tab); 00174 if (strlen(name) < 16) 00175 write(tab); 00176 write(tab); 00177 write(desc); 00178 write(newline); 00179 } 00180 00181 write(newline); 00182 } 00183 00184 bool CommandTerminal::writeable() { 00185 return _serial.writeable(); 00186 } 00187 00188 bool CommandTerminal::readable() { 00189 return _serial.readable(); 00190 } 00191 00192 char CommandTerminal::read() { 00193 char ch; 00194 _serial.read(&ch, 1); 00195 return ch; 00196 } 00197 00198 void CommandTerminal::write(const char* message) { 00199 while (!writeable()) 00200 ; 00201 _serial.write(message, strlen(message)); 00202 } 00203 00204 void CommandTerminal::writef(const char* format, ...) { 00205 char buff[256]; 00206 00207 va_list ap; 00208 va_start(ap, format); 00209 int size = vsnprintf(buff, 256, format, ap); 00210 while (!writeable()) 00211 ; 00212 _serial.write(buff, size); 00213 va_end(ap); 00214 } 00215 00216 void CommandTerminal::serialLoop() { 00217 Timer serial_read_timer; 00218 std::vector<uint8_t> serial_buffer; 00219 std::vector<uint8_t> data; 00220 int timeout = 0; 00221 00222 serial_read_timer.start(); 00223 00224 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) { 00225 _xbee_on_sleep = GPIO_PIN_SET; 00226 00227 timeout = _dot->getWakeDelay(); 00228 00229 // wait for timeout or start of serial data 00230 while (!readable() && serial_read_timer.read_ms() < timeout && !_serial.escaped()) { 00231 osDelay(2); 00232 } 00233 } 00234 00235 if (readable() && !_serial.escaped()) { 00236 00237 serial_read_timer.reset(); 00238 timeout = _dot->getWakeTimeout(); 00239 00240 while (serial_read_timer.read_ms() < timeout && serial_buffer.size() <= _dot->getMaxPacketLength()) { 00241 while (readable() && serial_buffer.size() < _dot->getMaxPacketLength()) { 00242 serial_buffer.push_back(read()); 00243 serial_read_timer.reset(); 00244 00245 if (_serial.escaped()) 00246 break; 00247 } 00248 } 00249 00250 serial_read_timer.stop(), serial_read_timer.reset(); 00251 00252 if (!serial_buffer.empty()) { 00253 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) 00254 _xbee_on_sleep = GPIO_PIN_RESET; 00255 00256 // wait for any duty cycle limit to expire 00257 while (_dot->getNextTxMs() > 0 && !_serial.escaped()) { 00258 osDelay(10); 00259 } 00260 00261 if (!_dot->getIsTransmitting()) { 00262 logDebug("Received serial data, sending out radio."); 00263 00264 if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) { 00265 logDebug("Send failed."); 00266 // If the data should be tossed after send failure, clear buffer 00267 if (_dot->getSerialClearOnError()) { 00268 serial_buffer.clear(); 00269 } 00270 } else { 00271 00272 // wait for send to finish 00273 while (_dot->getIsTransmitting() && !_serial.escaped()) 00274 osDelay(10); 00275 00276 // call recv to wait for any packet before sending again 00277 if (!_serial.escaped()) 00278 _dot->recv(data); 00279 00280 // Clear the serial buffer if send is success 00281 serial_buffer.clear(); 00282 } 00283 } else { 00284 logDebug("Radio is busy, cannot send.\r\n"); 00285 osDelay(10); 00286 } 00287 00288 } else { 00289 logDebug("No data received from serial to send.\r\n"); 00290 } 00291 } 00292 00293 if (!_serial.readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serial.escaped()) { 00294 _xbee_on_sleep = GPIO_PIN_RESET; 00295 sleep(_sleep_standby); 00296 } 00297 00298 if (_serial.escaped()) { 00299 _serial.clearEscaped(); 00300 _serial.rxClear(); 00301 serial_data_mode = false; 00302 _mode = mDot::COMMAND_MODE; 00303 logDebug("Exit Serial Mode"); 00304 write(done); 00305 return; 00306 } 00307 00308 if (!_dot->getNetworkJoinStatus()) { 00309 serial_data_mode = false; 00310 _mode = mDot::COMMAND_MODE; 00311 logDebug("Exit Serial Mode"); 00312 write(no_carrier); 00313 return; 00314 } 00315 } 00316 00317 bool CommandTerminal::autoJoinCheck() { 00318 00319 std::string escape_buffer; 00320 int sleep = 1000; 00321 Timer tmr; 00322 tmr.start(); 00323 int cnt = 0; 00324 00325 while (!_dot->getNetworkJoinStatus()) { 00326 write("\r\nJoining network... "); 00327 00328 if (_dot->getNextTxMs() > 0) { 00329 int rand_time = rand() % 10000; 00330 writef("\r\nWaiting %lu s before next join attempt\r\n", (_dot->getNextTxMs() + rand_time) / 1000); 00331 00332 tmr.reset(); 00333 while (_dot->getNextTxMs() > 0 && !_serial.escaped()) { 00334 osDelay(2); 00335 } 00336 00337 tmr.reset(); 00338 while (tmr.read_ms() < rand_time && !_serial.escaped()) 00339 osDelay(10); 00340 } 00341 00342 if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) { 00343 write("Network Joined\r\n"); 00344 write(done); 00345 return false; 00346 } 00347 00348 write("Network Join failed\r\n"); 00349 write(error); 00350 00351 if (!_serial.escaped() && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) { 00352 cnt = 0; 00353 00354 if (_dot->getFrequencyBand() == mDot::FB_915) { 00355 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1; 00356 logWarning("Join retries exhausted, switching to sub band %u", band); 00357 _dot->setFrequencySubBand(band); 00358 } 00359 00360 if (sleep < 60 * 60 * 1000) 00361 sleep *= 2; 00362 } 00363 00364 tmr.reset(); 00365 while (tmr.read_ms() < sleep && !_serial.escaped()) { 00366 osDelay(10); 00367 } 00368 00369 if (_serial.escaped()) { 00370 _serial.clearEscaped(); 00371 serial_data_mode = false; 00372 _mode = mDot::COMMAND_MODE; 00373 write("Join Canceled\r\n"); 00374 write(done); 00375 return true; 00376 } 00377 } 00378 00379 return false; 00380 } 00381 00382 void CommandTerminal::start() { 00383 00384 char ch; 00385 bool running = true; 00386 bool echo = _dot->getEcho(); 00387 std::string command; 00388 std::deque<std::string> history; 00389 int history_index = -1; 00390 std::vector<std::string> args; 00391 bool join_canceled = false; 00392 00393 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) { 00394 00395 serial_data_mode = true; 00396 _mode = mDot::SERIAL_MODE; 00397 00398 std::string escape_buffer; 00399 char ch; 00400 00401 if (!_dot->getStandbyFlag()) { 00402 // wake up from power-on/reset 00403 00404 int escape_timeout = 1000; 00405 Timer tmr; 00406 Timer escape_tmr; 00407 00408 // wait one second for possible escape by user pressing '+' key 00409 tmr.reset(); 00410 tmr.start(); 00411 escape_tmr.reset(); 00412 escape_tmr.start(); 00413 while (tmr.read_ms() < escape_timeout) { 00414 if (_serial.readable()) { 00415 _serial.read(&ch, 1); 00416 escape_buffer += ch; 00417 } 00418 00419 if (escape_buffer.find("+") != std::string::npos) { 00420 logInfo("Escape detected"); 00421 join_canceled = true; 00422 serial_data_mode = false; 00423 _mode = mDot::COMMAND_MODE; 00424 command.clear(); 00425 break; 00426 } 00427 00428 if (escape_tmr.read_ms() > escape_timeout) 00429 escape_buffer.clear(); 00430 00431 osDelay(1); 00432 } 00433 } 00434 00435 if (_mode == mDot::SERIAL_MODE && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) { 00436 if (_dot->joinNetworkOnce() != mDot::MDOT_OK) { 00437 serial_data_mode = false; 00438 _mode = mDot::COMMAND_MODE; 00439 00440 logWarning("Start Up Mode set to SERIAL_MODE, but join failed."); 00441 _serial.writef("Network Not Joined\r\n"); 00442 _serial.writef(error); 00443 } 00444 } 00445 } 00446 00447 if (_dot->getJoinMode() == mDot::PEER_TO_PEER) { 00448 peer_to_peer = true; 00449 } else { 00450 peer_to_peer = false; 00451 } 00452 00453 00454 00455 //Run terminal session 00456 while (running) { 00457 00458 // wait for input to reduce at command idle current 00459 while (!readable() || _mode == mDot::SERIAL_MODE) { 00460 if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) { 00461 join_canceled = autoJoinCheck(); 00462 if (join_canceled) 00463 command.clear(); 00464 } 00465 00466 if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) { 00467 switch (_mode) { 00468 case mDot::SERIAL_MODE: 00469 // signal wakeup, read serial and output to radio 00470 serialLoop(); 00471 continue; 00472 break; 00473 default: 00474 break; 00475 } 00476 } 00477 00478 ch = '\0'; 00479 00480 wait(0.00001); // 10 us 00481 _serial.escaped(); 00482 } 00483 00484 // read characters 00485 if (readable()) { 00486 ch = read(); 00487 00488 if (ch == '\b' || ch == 0x7f) { 00489 if (!command.empty()) { 00490 writef("\b \b"); 00491 command.erase(command.size() - 1); 00492 } 00493 continue; 00494 } else if (ch == 0x1b || ch == 0x09) { 00495 osDelay(20); 00496 // catch escape sequence, or tab 00497 char ch1 = 0x00, ch2 = 0x00; 00498 00499 if (readable()) { 00500 ch1 = read(); 00501 if (readable()) 00502 ch2 = read(); 00503 00504 if (ch1 == 0x5b && ch2 == 0x41) { 00505 // up key 00506 for (size_t i = 0; i < command.size() + 1; i++) { 00507 writef("\b \b"); 00508 } 00509 if (history.size() > 0) { 00510 if (++history_index >= int(history.size() - 1)) 00511 history_index = history.size() - 1; 00512 00513 command = history[history_index]; 00514 writef("%s", history[history_index].c_str()); 00515 } else { 00516 command.clear(); 00517 } 00518 } else if (ch1 == 0x5b && ch2 == 0x42) { 00519 00520 // down key 00521 for (size_t i = 0; i < command.size() + 1; i++) { 00522 writef("\b \b"); 00523 } 00524 00525 if (--history_index < 0) { 00526 history_index = -1; 00527 command.clear(); 00528 } else { 00529 command = history[history_index]; 00530 writef("%s", history[history_index].c_str()); 00531 } 00532 } 00533 } 00534 while (readable()) 00535 read(); 00536 continue; 00537 } else { 00538 command += ch; 00539 } 00540 00541 // echo chars if enabled 00542 if (echo && !(ch == '\r' || ch == '\n')) 00543 writef("%c", ch); 00544 } 00545 00546 // look for end of command line 00547 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) { 00548 // remove new line or cr character 00549 command.erase(command.size() - 1); 00550 write("\r"); // match standard modem output 00551 write(newline); 00552 } else { 00553 continue; 00554 } 00555 00556 // trim whitespace from command 00557 mts::Text::trim(command, "\r\n\t "); 00558 00559 if (command.size() < 1) { 00560 command.clear(); 00561 continue; 00562 } 00563 00564 // parse command and args 00565 args.clear(); 00566 00567 // find first '=' character 00568 size_t delim_index = command.find("="); 00569 if (delim_index != std::string::npos) { 00570 args.push_back(command.substr(0, delim_index)); 00571 } else { 00572 // find first ' ' character 00573 delim_index = command.find(" "); 00574 if (delim_index != std::string::npos) { 00575 args.push_back(command.substr(0, delim_index)); 00576 } else { 00577 args.push_back(command); 00578 } 00579 } 00580 00581 if (delim_index != std::string::npos) { 00582 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ","); 00583 args.insert(args.end(), params.begin(), params.end()); 00584 } 00585 00586 args[0] = mts::Text::toUpper(args[0]); 00587 00588 // print help 00589 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) { 00590 printHelp(); 00591 command.clear(); 00592 } else if ((args[0].find("ATE?") == 0 && args[0].length() == 4) || (args[0].find("ATE") == 0 && args[0].length() == 3)) { 00593 writef("%d\r\n", _dot->getEcho()); 00594 write(done); 00595 } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) { 00596 _dot->setEcho(false); 00597 write(done); 00598 echo = _dot->getEcho(); 00599 } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) { 00600 _dot->setEcho(true); 00601 write(done); 00602 echo = _dot->getEcho(); 00603 } else if ((args[0].find("ATV?") == 0 && args[0].length() == 4) || (args[0].find("ATV") == 0 && args[0].length() == 3)) { 00604 writef("%d\r\n", _dot->getVerbose()); 00605 write(done); 00606 } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) { 00607 _dot->setVerbose(false); 00608 write(done); 00609 } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) { 00610 _dot->setVerbose(true); 00611 write(done); 00612 } else if ((args[0].find("AT&K?") == 0 && args[0].length() == 5) || (args[0].find("AT&K") == 0 && args[0].length() == 4)) { 00613 writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0)); 00614 write(done); 00615 } else if (args[0].find("AT&K0") == 0 && args[0].length() == 5) { 00616 _dot->setFlowControl(false); 00617 write(done); 00618 } else if (args[0].find("AT&K3") == 0 && args[0].length() == 5) { 00619 _dot->setFlowControl(true); 00620 write(done); 00621 } else if (args[0] == "AT+SD") { 00622 if (_dot->getNetworkJoinStatus()) { 00623 logDebug("Enter Serial Mode"); 00624 write(connect); 00625 serial_data_mode = true; 00626 _mode = mDot::SERIAL_MODE; 00627 } else { 00628 logDebug("Network Not Joined"); 00629 write("Network Not Joined\r\n"); 00630 write(error); 00631 } 00632 } else if (args[0] == "AT+SLEEP") { 00633 if (args.size() > 2 && (args[1] != "?")) { 00634 write("Invalid argument\r\n"); 00635 write(error); 00636 } else { 00637 if (args.size() > 1 && args[1] == "?") { 00638 write("(0:deepsleep,1:sleep)\r\n"); 00639 write(done); 00640 } else { 00641 _sleep_standby = !(args.size() > 1 && args[1] == "1"); 00642 write(done); 00643 this->sleep(_sleep_standby); 00644 wait(0.1); 00645 } 00646 } 00647 } else { 00648 bool found = false; 00649 bool query = false; 00650 00651 std::string lookfor = args[0]; 00652 00653 // per command help 00654 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0)) 00655 lookfor = mts::Text::toUpper(args[1]); 00656 00657 // trim off any trailing '?' and mark as a query command 00658 if (args[0].rfind("?") == args[0].length() - 1) { 00659 query = true; 00660 lookfor = args[0].substr(0, args[0].length() - 1); 00661 } 00662 00663 // search for command 00664 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) { 00665 Command* cmd = *it; 00666 00667 // match CMD or CMD? syntax if command is queryable 00668 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) { 00669 found = true; 00670 if (args[0] == "HELP") { 00671 writef("%s%s", cmd->help(), newline); 00672 write(done); 00673 } 00674 00675 else if (args.size() > 1 && args[1] == "?") { 00676 writef("%s%s", cmd->usage().c_str(), newline); 00677 write(done); 00678 } else if (!cmd->verify(args)) { 00679 writef("%s%s", cmd->errorMessage().c_str(), newline); 00680 writef("%s", error); 00681 } else { 00682 if (cmd->action(args) == 0) { 00683 writef("%s", done); 00684 } else { 00685 writef("%s%s", cmd->errorMessage().c_str(), newline); 00686 writef("%s", error); 00687 } 00688 } 00689 } 00690 } 00691 00692 if (!found) { 00693 writef("%s", command_error); 00694 writef("%s", error); 00695 } 00696 } 00697 00698 if (history.size() == 0 || history.front() != command) 00699 history.push_front(command); 00700 history_index = -1; 00701 command.clear(); 00702 00703 while (history.size() > 10) 00704 history.pop_back(); 00705 } 00706 } 00707 00708 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) { 00709 if (format == mDot::HEXADECIMAL) 00710 return mts::Text::bin2hexString(data); 00711 else 00712 return std::string(data.begin(), data.end()); 00713 } 00714 00715 void CommandTerminal::sleep(bool standby) { 00716 _xbee_on_sleep = GPIO_PIN_RESET; 00717 00718 _serial.rxClear(); 00719 _serial.txClear(); 00720 00721 _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby); 00722 } 00723 00724 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) { 00725 Timer timer; 00726 00727 timer.start(); 00728 while (timer.read_ms() < timeout) { 00729 00730 if (dot != NULL) { 00731 if (wait == WAIT_SEND && (!dot->getIsTransmitting())) { 00732 return false; 00733 } 00734 } 00735 00736 if (_serialp != NULL && _serialp->escaped()) { 00737 _serialp->clearEscaped(); 00738 return true; 00739 } 00740 00741 osDelay(10); 00742 } 00743 00744 return false; 00745 } 00746 00747 void CommandTerminal::wakeup(void) { 00748 if (_dot->getWakePin() == XBEE_DIN) { 00749 _serial.reattach(XBEE_DOUT, XBEE_DIN); 00750 logInfo("Wakeup pin was serial input"); 00751 } 00752 } 00753 00754 void CommandTerminal::RadioEvent::MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) { 00755 00756 if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) { 00757 std::string msg = "OK"; 00758 switch (info->Status) { 00759 case LORAMAC_EVENT_INFO_STATUS_ERROR: 00760 msg = "ERROR"; 00761 break; 00762 case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT: 00763 msg = "TX_TIMEOUT"; 00764 break; 00765 case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT: 00766 msg = "RX_TIMEOUT"; 00767 break; 00768 case LORAMAC_EVENT_INFO_STATUS_RX_ERROR: 00769 msg = "RX_ERROR"; 00770 break; 00771 case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL: 00772 msg = "JOIN_FAIL"; 00773 break; 00774 case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL: 00775 msg = "DOWNLINK_FAIL"; 00776 break; 00777 case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL: 00778 msg = "ADDRESS_FAIL"; 00779 break; 00780 case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL: 00781 msg = "MIC_FAIL"; 00782 break; 00783 default: 00784 break; 00785 } 00786 logTrace("Event: %s", msg.c_str()); 00787 00788 logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d", 00789 flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept); 00790 logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d", 00791 info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize, 00792 info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways); 00793 } 00794 00795 if (flags->Bits.Rx) { 00796 if (serial_data_mode) { 00797 logDebug("Rx %d bytes", info->RxBufferSize); 00798 if (info->RxBufferSize > 0) { 00799 _serial.write((char*) info->RxBuffer, info->RxBufferSize); 00800 } 00801 } 00802 00803 delete[] info->RxBuffer; 00804 } 00805 } 00806 00807 CommandTerminal::~CommandTerminal() { 00808 delete _events; 00809 }
Generated on Tue Jul 12 2022 16:01:24 by 1.7.2