MultiTech / Mbed OS mDot_AT_firmware_CUSTOM

Dependencies:   libmDot-Custom MTS-Serial

Fork of mDot_AT_firmware_CUSTOM by Jason Reiss

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CommandTerminal.cpp Source File

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 #if defined(TARGET_XDOT_L151CC)
00008 #include "xdot_low_power.h"
00009 #endif
00010 
00011 #if defined(TARGET_MTS_MDOT_F411RE)
00012 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
00013 #else
00014 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa xDot Module\r\n\n";
00015 #endif
00016 const char CommandTerminal::helpline[] = "Enter '?' for help\r\n";
00017 
00018 const char CommandTerminal::newline[] = "\r\n";
00019 
00020 // Command error text...
00021 const char CommandTerminal::command_error[] = "Command not found!\r\n";
00022 
00023 // Response texts...
00024 const char CommandTerminal::help[] = "\r\nHelp\r\n";
00025 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
00026 const char CommandTerminal::connect[] = "\r\nCONNECT\r\n";
00027 const char CommandTerminal::no_carrier[] = "\r\nNO CARRIER\r\n";
00028 const char CommandTerminal::done[] = "\r\nOK\r\n";
00029 const char CommandTerminal::error[] = "\r\nERROR\r\n";
00030 
00031 // Escape sequence...
00032 const char CommandTerminal::escape_sequence[] = "+++";
00033 
00034 mts::ATSerial* CommandTerminal::_serialp = NULL;
00035 mDot* CommandTerminal::_dot = NULL;
00036 
00037 CommandTerminal::RadioEvent* CommandTerminal::_events = new RadioEvent();
00038 
00039 static bool serial_data_mode = false;
00040 static bool peer_to_peer = false;
00041 
00042 std::string CommandTerminal::_errorMessage = "";
00043 
00044 void CommandTerminal::setErrorMessage(const char* message) {
00045     _errorMessage.assign(message);
00046 }
00047 
00048 void CommandTerminal::setErrorMessage(const std::string& message) {
00049     _errorMessage.assign(message);
00050 }
00051 
00052 const Command CommandTerminal::_commands[NO_OF_COMMANDS] = {
00053     CmdAttention(),
00054     CmdIdentification(),
00055     CmdResetCpu(),
00056     CmdDummy("Enable/Disable Echo", "ATE", "ATE0: disable, ATE1: enable", "(0,1)"),
00057     CmdDummy("Enable/Disable Verbose", "ATV", "ATV0: disable, ATV1: enable", "(0,1)"),
00058     CmdDummy("Hardware Flow Control", "AT&K", "AT&K0: disable, AT&K3: enable", "(0,3)"),
00059 
00060     CmdFactoryDefault(),
00061     CmdSaveConfig(),
00062     CmdDisplayConfig(),
00063     CmdDisplayStats(),
00064     CmdResetStats(),
00065     CmdSerialBaudRate(),
00066     CmdDebugBaudRate(),
00067     CmdStartUpMode(),
00068 
00069     CmdFrequencyBand(),
00070     CmdFrequencySubBand(),
00071     CmdPublicNetwork(),
00072     CmdDeviceId(),
00073     CmdDeviceClass(),
00074 
00075     CmdAppPort(),
00076     CmdNetworkAddress(),
00077     CmdNetworkSessionKey(),
00078     CmdDataSessionKey(),
00079     CmdUplinkCounter(),
00080     CmdDownlinkCounter(),
00081     CmdSaveSession(),
00082     CmdRestoreSession(),
00083     CmdNetworkKey(),
00084     CmdNetworkId(),
00085 
00086     CmdJoinDelay(),
00087 // Remove join settings commands until valid case for changing default settings
00088 //    CmdJoinRx1Offset(),
00089 //    CmdJoinRx2Datarate(),
00090 //    CmdJoinRx2Frequency(),
00091     CmdJoinRequest(),
00092     CmdJoinRetries(),
00093     CmdJoinByteOrder(),
00094     CmdNetworkJoinMode(),
00095     CmdPreserveSession(),
00096     CmdNetworkJoinStatus(),
00097     CmdNetworkLinkCheck(),
00098     CmdLinkCheckCount(),
00099     CmdLinkCheckThreshold(),
00100     CmdEncryption(),
00101 
00102     CmdRssi(),
00103     CmdSnr(),
00104     CmdDataPending(),
00105 
00106     CmdSessionDataRate(),
00107     CmdChannelMask(),
00108 
00109     CmdTxDataRate(),
00110     CmdTxPower(),
00111     CmdAntennaGain(),
00112     CmdTxFrequency(),
00113     CmdTxInverted(),
00114     CmdTxWait(),
00115     CmdTxChannel(),
00116     CmdTxNextMs(),
00117     CmdTimeOnAir(),
00118 
00119     CmdRxDelay(),
00120     CmdRxOutput(),
00121     CmdRxInverted(),
00122 
00123     CmdErrorCorrection(),
00124     CmdCRC(),
00125     CmdAdaptiveDataRate(),
00126 
00127     CmdACKAttempts(),
00128     CmdRepeat(),
00129     CmdMacCmd(),
00130 
00131     CmdSendString(),
00132     CmdSendBinary(),
00133     CmdReceiveOnce(),
00134 
00135     CmdDummy("Serial Data Mode", "AT+SD", "Enter serial data mode, exit with '+++'", "NONE"),
00136     CmdDummy("Sleep Mode", "AT+SLEEP", "Enter sleep mode (0:deepsleep,1:sleep)", "(0,1)"),
00137     CmdSerialClearOnError(),
00138     CmdWakeMode(),
00139     CmdWakeInterval(),
00140     CmdWakePin(),
00141     CmdWakeDelay(),
00142     CmdWakeTimeout(),
00143     CmdPing(),
00144     CmdLogLevel(),
00145 
00146     CmdDummy("***** Test Commands *****", "", "", ""),
00147     CmdRxDataRate(),
00148     CmdRxFrequency(),
00149     CmdReceiveContinuous(),
00150     CmdSendStringOnInterval(),
00151 
00152 #ifdef MTS_RADIO_DEBUG_COMMANDS
00153     CmdDummy("***** Debug Commands *****", "", "", ""),
00154     CmdSendContinuous(),
00155     CmdWriteProtectedConfig(),
00156     CmdDumpRegisters(),
00157     CmdEraseFlash(),
00158     CmdDisableDutyCycle(),
00159 #endif
00160 
00161 };
00162 
00163 const verify_ptr_t CommandTerminal::_verify[NO_OF_COMMANDS] = {
00164     CmdDummy::verify,
00165     CmdDummy::verify,
00166     CmdDummy::verify,
00167     CmdDummy::verify,
00168     CmdDummy::verify,
00169     CmdDummy::verify,
00170 
00171     CmdDummy::verify,
00172     CmdDummy::verify,
00173     CmdDummy::verify,
00174     CmdDummy::verify,
00175     CmdDummy::verify,
00176     CmdSerialBaudRate::verify,
00177     CmdDebugBaudRate::verify,
00178     CmdStartUpMode::verify,
00179 
00180     CmdFrequencyBand::verify,
00181     CmdFrequencySubBand::verify,
00182     CmdPublicNetwork::verify,
00183     CmdDeviceId::verify,
00184     CmdDeviceClass::verify,
00185 
00186     CmdAppPort::verify,
00187     CmdNetworkAddress::verify,
00188     CmdNetworkSessionKey::verify,
00189     CmdDataSessionKey::verify,
00190     CmdUplinkCounter::verify,
00191     CmdDownlinkCounter::verify,
00192     CmdDummy::verify,
00193     CmdDummy::verify,
00194     CmdNetworkKey::verify,
00195     CmdNetworkId::verify,
00196 
00197     CmdJoinDelay::verify,
00198 // Remove join settings commands until valid case for changing default settings
00199 //    CmdJoinRx1Offset::verify,
00200 //    CmdJoinRx2Datarate::verify,
00201 //    CmdJoinRx2Frequency::verify,
00202     CmdJoinRequest::verify,
00203     CmdJoinRetries::verify,
00204     CmdJoinByteOrder::verify,
00205     CmdNetworkJoinMode::verify,
00206     CmdPreserveSession::verify,
00207     CmdDummy::verify,
00208     CmdDummy::verify,
00209     CmdLinkCheckCount::verify,
00210     CmdLinkCheckThreshold::verify,
00211     CmdEncryption::verify,
00212 
00213     CmdDummy::verify,
00214     CmdDummy::verify,
00215     CmdDummy::verify,
00216 
00217     CmdSessionDataRate::verify,
00218     CmdChannelMask::verify,
00219 
00220     CmdTxDataRate::verify,
00221     CmdTxPower::verify,
00222     CmdAntennaGain::verify,
00223     CmdTxFrequency::verify,
00224     CmdTxInverted::verify,
00225     CmdTxWait::verify,
00226     CmdTxChannel::verify,
00227     CmdTxNextMs::verify,
00228     CmdTimeOnAir::verify,
00229 
00230     CmdRxDelay::verify,
00231     CmdRxOutput::verify,
00232     CmdRxInverted::verify,
00233 
00234     CmdErrorCorrection::verify,
00235     CmdCRC::verify,
00236     CmdAdaptiveDataRate::verify,
00237 
00238     CmdACKAttempts::verify,
00239     CmdRepeat::verify,
00240     CmdMacCmd::verify,
00241 
00242     CmdSendString::verify,
00243     CmdSendBinary::verify,
00244     CmdReceiveOnce::verify,
00245 
00246     CmdDummy::verify,
00247     CmdDummy::verify,
00248     CmdSerialClearOnError::verify,
00249     CmdWakeMode::verify,
00250     CmdWakeInterval::verify,
00251     CmdWakePin::verify,
00252     CmdWakeDelay::verify,
00253     CmdWakeTimeout::verify,
00254     CmdDummy::verify,
00255     CmdLogLevel::verify,
00256 
00257     CmdDummy::verify,
00258     CmdRxDataRate::verify,
00259     CmdRxFrequency::verify,
00260     CmdReceiveContinuous::verify,
00261     CmdSendStringOnInterval::verify,
00262 
00263 #ifdef MTS_RADIO_DEBUG_COMMANDS
00264     CmdDummy::verify,
00265     CmdSendContinuous::verify,
00266     CmdDummy::verify,
00267     CmdDummy::verify,
00268     CmdEraseFlash::verify,
00269     CmdDisableDutyCycle::verify,
00270 #endif
00271 
00272 };
00273 
00274 const action_ptr_t CommandTerminal::_action[NO_OF_COMMANDS] = {
00275     CmdAttention::action,
00276     CmdIdentification::action,
00277     CmdResetCpu::action,
00278     CmdDummy::action,
00279     CmdDummy::action,
00280     CmdDummy::action,
00281 
00282     CmdFactoryDefault::action,
00283     CmdSaveConfig::action,
00284     CmdDisplayConfig::action,
00285     CmdDisplayStats::action,
00286     CmdResetStats::action,
00287     CmdSerialBaudRate::action,
00288     CmdDebugBaudRate::action,
00289     CmdStartUpMode::action,
00290 
00291     CmdFrequencyBand::action,
00292     CmdFrequencySubBand::action,
00293     CmdPublicNetwork::action,
00294     CmdDeviceId::action,
00295     CmdDeviceClass::action,
00296 
00297     CmdAppPort::action,
00298     CmdNetworkAddress::action,
00299     CmdNetworkSessionKey::action,
00300     CmdDataSessionKey::action,
00301     CmdUplinkCounter::action,
00302     CmdDownlinkCounter::action,
00303     CmdSaveSession::action,
00304     CmdRestoreSession::action,
00305     CmdNetworkKey::action,
00306     CmdNetworkId::action,
00307 
00308     CmdJoinDelay::action,
00309 // Remove join settings commands until valid case for changing default settings
00310 //    CmdJoinRx1Offset::action,
00311 //    CmdJoinRx2Datarate::action,
00312 //    CmdJoinRx2Frequency::action,
00313     CmdJoinRequest::action,
00314     CmdJoinRetries::action,
00315     CmdJoinByteOrder::action,
00316     CmdNetworkJoinMode::action,
00317     CmdPreserveSession::action,
00318     CmdNetworkJoinStatus::action,
00319     CmdNetworkLinkCheck::action,
00320     CmdLinkCheckCount::action,
00321     CmdLinkCheckThreshold::action,
00322     CmdEncryption::action,
00323 
00324     CmdRssi::action,
00325     CmdSnr::action,
00326     CmdDataPending::action,
00327 
00328     CmdSessionDataRate::action,
00329     CmdChannelMask::action,
00330 
00331     CmdTxDataRate::action,
00332     CmdTxPower::action,
00333     CmdAntennaGain::action,
00334     CmdTxFrequency::action,
00335     CmdTxInverted::action,
00336     CmdTxWait::action,
00337     CmdTxChannel::action,
00338     CmdTxNextMs::action,
00339     CmdTimeOnAir::action,
00340 
00341     CmdRxDelay::action,
00342     CmdRxOutput::action,
00343     CmdRxInverted::action,
00344 
00345     CmdErrorCorrection::action,
00346     CmdCRC::action,
00347     CmdAdaptiveDataRate::action,
00348 
00349     CmdACKAttempts::action,
00350     CmdRepeat::action,
00351     CmdMacCmd::action,
00352 
00353     CmdSendString::action,
00354     CmdSendBinary::action,
00355     CmdReceiveOnce::action,
00356 
00357     CmdDummy::action,
00358     CmdDummy::action,
00359     CmdSerialClearOnError::action,
00360     CmdWakeMode::action,
00361     CmdWakeInterval::action,
00362     CmdWakePin::action,
00363     CmdWakeDelay::action,
00364     CmdWakeTimeout::action,
00365     CmdPing::action,
00366     CmdLogLevel::action,
00367 
00368     CmdDummy::action,
00369     CmdRxDataRate::action,
00370     CmdRxFrequency::action,
00371     CmdReceiveContinuous::action,
00372     CmdSendStringOnInterval::action,
00373 
00374 #ifdef MTS_RADIO_DEBUG_COMMANDS
00375     CmdDummy::action,
00376     CmdSendContinuous::action,
00377     CmdWriteProtectedConfig::action,
00378     CmdDumpRegisters::action,
00379     CmdEraseFlash::action,
00380     CmdDisableDutyCycle::action,
00381 #endif
00382 
00383 };
00384 
00385 CommandTerminal::CommandTerminal(mts::ATSerial& serial) :
00386   _serial(serial),
00387   _mode(mDot::COMMAND_MODE),
00388   _sleep_standby(true),
00389 #if defined(TARGET_MTS_MDOT_F411RE)
00390   _xbee_on_sleep(XBEE_ON_SLEEP),
00391 #else
00392   _xbee_on_sleep(GPIO2),
00393 #endif
00394   _autoOTAEnabled(false),
00395   _idle_thread(idle, NULL, osPriorityLow)
00396 {
00397     _serialp = &serial;
00398 }
00399 
00400 void CommandTerminal::init() {
00401     _dot->setEvents(_events);
00402 }
00403 
00404 void CommandTerminal::printHelp() {
00405     const char* name = NULL;
00406     const char* text = NULL;
00407     const char* desc = NULL;
00408     const char* tab = "\t";
00409 
00410     std::string header("Command");
00411     header.append(tab);
00412     header.append(tab);
00413     header.append("Name");
00414     header.append(tab);
00415     header.append(tab);
00416     header.append(tab);
00417     header.append("Description");
00418 
00419     write(newline);
00420     write(header.c_str());
00421     write(newline);
00422     write(newline);
00423 
00424     for (int i = 0; i < NO_OF_COMMANDS; i++) {
00425         name = _commands[i].name();
00426         text = _commands[i].text();
00427         desc = _commands[i].desc();
00428         write(text);
00429         if (strlen(text) < 8)
00430             write(tab);
00431         write(tab);
00432         write(name);
00433         if (strlen(name) < 8)
00434             write(tab);
00435         if (strlen(name) < 16)
00436             write(tab);
00437         write(tab);
00438         write(desc);
00439         write(newline);
00440     }
00441 
00442     write(newline);
00443 }
00444 
00445 bool CommandTerminal::writeable() {
00446     return _serialp->writeable();
00447 }
00448 
00449 bool CommandTerminal::readable() {
00450     return _serialp->readable();
00451 }
00452 
00453 char CommandTerminal::read() {
00454     char ch;
00455     _serialp->read(&ch, 1);
00456     return ch;
00457 }
00458 
00459 void CommandTerminal::write(const char* message) {
00460     while (!writeable())
00461         ;
00462     _serialp->write(message, strlen(message));
00463 }
00464 
00465 void CommandTerminal::writef(const char* format, ...) {
00466     char buff[256];
00467 
00468     va_list ap;
00469     va_start(ap, format);
00470     int size = vsnprintf(buff, 256, format, ap);
00471     while (!writeable())
00472         ;
00473     _serialp->write(buff, size);
00474     va_end(ap);
00475 }
00476 
00477 void CommandTerminal::serialLoop() {
00478     Timer serial_read_timer;
00479     std::vector<uint8_t> serial_buffer;
00480     std::vector<uint8_t> data;
00481     int timeout = 0;
00482 
00483     serial_read_timer.start();
00484 
00485     if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
00486         _xbee_on_sleep = GPIO_PIN_SET;
00487 
00488         timeout = _dot->getWakeDelay();
00489 
00490         // wait for timeout or start of serial data
00491         while (!readable() && serial_read_timer.read_ms() < timeout && !_serialp->escaped()) {
00492             osDelay(2);
00493         }
00494     }
00495 
00496     if (!readable() && _events->SendAck()) {
00497         logDebug("SERIAL NOT READABLE and ACK REQUESTED");
00498         goto L_SEND;
00499     }
00500 
00501     if (readable() && !_serialp->escaped()) {
00502 
00503         serial_read_timer.reset();
00504         timeout = _dot->getWakeTimeout();
00505 
00506         while (serial_read_timer.read_ms() < timeout && serial_buffer.size() <= _dot->getMaxPacketLength()) {
00507             while (readable() && serial_buffer.size() < _dot->getMaxPacketLength()) {
00508                 serial_buffer.push_back(read());
00509                 serial_read_timer.reset();
00510 
00511                 if (_serialp->escaped())
00512                     break;
00513             }
00514         }
00515 
00516         serial_read_timer.stop(), serial_read_timer.reset();
00517 
00518         if (!serial_buffer.empty()) {
00519             if (_dot->getStartUpMode() == mDot::SERIAL_MODE)
00520                  _xbee_on_sleep = GPIO_PIN_RESET;
00521 
00522 L_SEND:
00523             // wait for any duty cycle limit to expire
00524             while (_dot->getNextTxMs() > 0 && !_serialp->escaped()) {
00525                 osDelay(10);
00526             }
00527 
00528             if (_dot->getIsIdle()) {
00529                 logDebug("Received serial data, sending out radio.");
00530 
00531                 if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) {
00532                     logDebug("Send failed.");
00533                     // If the data should be tossed after send failure, clear buffer
00534                     if (_dot->getSerialClearOnError()) {
00535                         serial_buffer.clear();
00536                     }
00537                 } else {
00538 
00539                     // wait for send to finish
00540                     while (!_dot->getIsIdle() && !_serialp->escaped()) {
00541                         osDelay(10);
00542                     }
00543 
00544                     // call recv to wait for any packet before sending again
00545                     if (!_serialp->escaped())
00546                         _dot->recv(data);
00547 
00548                     // Clear the serial buffer if send is success
00549                     serial_buffer.clear();
00550 
00551                     // In class C mode pending data will be sent automatically without uplink
00552                     if (_dot->getClass() != "C") {
00553                         if (_dot->getDataPending()) {
00554                             logDebug("Data is pending");
00555                             goto L_SEND;
00556                         }
00557                         if (_dot->getAckRequested()) {
00558                             logDebug("Ack requested");
00559                             goto L_SEND;
00560                         }
00561                     }
00562                 }
00563             } else {
00564                 logDebug("Radio is busy, cannot send.\r\n");
00565                 osDelay(10);
00566             }
00567 
00568         } else {
00569             logDebug("No data received from serial to send.\r\n");
00570         }
00571     }
00572 
00573     if (!_serialp->readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serialp->escaped()) {
00574         sleep(true);
00575     }
00576 
00577     if (_serialp->escaped()) {
00578         _serialp->clearEscaped();
00579         _serialp->rxClear();
00580         serial_data_mode = false;
00581         _mode = mDot::COMMAND_MODE;
00582         logDebug("Exit Serial Mode");
00583         write(done);
00584         return;
00585     }
00586 
00587     if (!_dot->getNetworkJoinStatus()) {
00588         serial_data_mode = false;
00589         _mode = mDot::COMMAND_MODE;
00590         logDebug("Exit Serial Mode");
00591         write(no_carrier);
00592         return;
00593     }
00594 }
00595 
00596 bool CommandTerminal::autoJoinCheck() {
00597 
00598     std::string escape_buffer;
00599     int sleep = 1000;
00600     Timer tmr;
00601     tmr.start();
00602     int cnt = 0;
00603 
00604     while (!_dot->getNetworkJoinStatus()) {
00605         if (!serial_data_mode) {
00606             write("\r\nJoining network... ");
00607         }
00608         logInfo("Joining network... ");
00609 
00610         if (_dot->getNextTxMs() > 0) {
00611             if (!serial_data_mode) {
00612                 writef("\r\nWaiting %lu s before next join attempt\r\n", _dot->getNextTxMs() / 1000);
00613             }
00614             logInfo("Waiting %lu s before next join attempt", _dot->getNextTxMs() / 1000);
00615 
00616             tmr.reset();
00617             while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
00618                 osDelay(20);
00619             }
00620         }
00621 
00622         if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) {
00623             if (!serial_data_mode) {
00624                 write("Network Joined\r\n");
00625                 write(done);
00626             }
00627             logInfo("Network Joined");
00628             return false;
00629         }
00630 
00631         if (!serial_data_mode) {
00632             write("Network Join failed\r\n");
00633             write(error);
00634         }
00635         logInfo("Network Join failed");
00636 
00637         if (!_serial.escaped() && _dot->getFrequencySubBand() != 0 && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
00638             cnt = 0;
00639 
00640             if (_dot->getFrequencyBand() == mDot::FIXED ) {
00641                 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
00642                 logWarning("Join retries exhausted, switching to sub band %u", band);
00643                 _dot->setFrequencySubBand(band);
00644             }
00645         }
00646 
00647         tmr.reset();
00648         while (tmr.read_ms() < sleep && !_serial.escaped()) {
00649             osDelay(10);
00650         }
00651 
00652         if (_serial.escaped()) {
00653             _serial.clearEscaped();
00654             serial_data_mode = false;
00655             _mode = mDot::COMMAND_MODE;
00656             if (!serial_data_mode) {
00657                 write("Join Canceled\r\n");
00658                 write(done);
00659             }
00660             logInfo("Join Canceled\r\n");
00661             return true;
00662         }
00663     }
00664 
00665     return false;
00666 }
00667 
00668 void CommandTerminal::start() {
00669 
00670     char ch;
00671     bool running = true;
00672     bool echo = _dot->getEcho();
00673     std::string command;
00674     std::deque<std::string> history;
00675     int history_index = -1;
00676     std::vector<std::string> args;
00677     bool join_canceled = false;
00678 
00679     _autoOTAEnabled = _dot->getJoinMode() == mDot::AUTO_OTA;
00680 
00681     if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
00682 
00683         serial_data_mode = true;
00684         _mode = mDot::SERIAL_MODE;
00685 
00686         std::string escape_buffer;
00687         char ch;
00688 
00689         if (!_dot->getStandbyFlag()) {
00690             // wake up from power-on/reset
00691 
00692             int escape_timeout = 1000;
00693             Timer tmr;
00694             Timer escape_tmr;
00695 
00696             // wait one second for possible escape by user pressing '+' key
00697             tmr.reset();
00698             tmr.start();
00699             escape_tmr.reset();
00700             escape_tmr.start();
00701             while (tmr.read_ms() < escape_timeout) {
00702                 if (_serial.readable()) {
00703                     _serial.read(&ch, 1);
00704                     escape_buffer += ch;
00705                 }
00706 
00707                 if (escape_buffer.find("+") != std::string::npos) {
00708                     logInfo("Escape detected");
00709                     join_canceled = true;
00710                     serial_data_mode = false;
00711                     _mode = mDot::COMMAND_MODE;
00712                     command.clear();
00713                     break;
00714                 }
00715 
00716                 if (escape_tmr.read_ms() > escape_timeout)
00717                     escape_buffer.clear();
00718 
00719                 osDelay(1);
00720             }
00721         }
00722 
00723         if (_mode == mDot::SERIAL_MODE && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
00724             if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
00725                 serial_data_mode = false;
00726                 _mode = mDot::COMMAND_MODE;
00727 
00728                 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
00729                 _serial.writef("Network Not Joined\r\n");
00730                 _serial.writef(error);
00731             }
00732         }
00733     }
00734 
00735     if (_dot->getJoinMode() == mDot::PEER_TO_PEER) {
00736         peer_to_peer = true;
00737     } else {
00738         peer_to_peer = false;
00739     }
00740 
00741     //Run terminal session
00742     while (running) {
00743 
00744         // wait for input to reduce at command idle current
00745         while (!readable() || _mode == mDot::SERIAL_MODE) {
00746             if (!join_canceled && _autoOTAEnabled) {
00747                 join_canceled = autoJoinCheck();
00748                 if (join_canceled)
00749                     command.clear();
00750             }
00751 
00752             if (!_autoOTAEnabled || (!join_canceled && _autoOTAEnabled)) {
00753                 switch (_mode) {
00754                     case mDot::SERIAL_MODE:
00755                         // signal wakeup, read serial and output to radio
00756                         serialLoop();
00757                         continue;
00758                     default:
00759                         break;
00760                 }
00761             }
00762 
00763             ch = '\0';
00764 
00765             wait(0.00001); // 10 us
00766             _serial.escaped();
00767         }
00768 
00769         // read characters
00770         if (readable()) {
00771             ch = read();
00772 
00773             if (ch == '\b' || ch == 0x7f) {
00774                 if (!command.empty()) {
00775                     writef("\b \b");
00776                     command.erase(command.size() - 1);
00777                 }
00778                 continue;
00779             } else if (ch == 0x1b || ch == 0x09) {
00780                 osDelay(20);
00781                 // catch escape sequence, or tab
00782                 char ch1 = 0x00, ch2 = 0x00;
00783 
00784                 if (readable()) {
00785                     ch1 = read();
00786                     if (readable())
00787                         ch2 = read();
00788 
00789                     if (ch1 == 0x5b && ch2 == 0x41) {
00790                         // up key
00791                         for (size_t i = 0; i < command.size() + 1; i++) {
00792                             writef("\b \b");
00793                         }
00794                         if (history.size() > 0) {
00795                             if (++history_index >= int(history.size() - 1))
00796                                 history_index = history.size() - 1;
00797 
00798                             command = history[history_index];
00799                             writef("%s", history[history_index].c_str());
00800                         } else {
00801                             command.clear();
00802                         }
00803                     } else if (ch1 == 0x5b && ch2 == 0x42) {
00804 
00805                         // down key
00806                         for (size_t i = 0; i < command.size() + 1; i++) {
00807                             writef("\b \b");
00808                         }
00809 
00810                         if (--history_index < 0) {
00811                             history_index = -1;
00812                             command.clear();
00813                         } else {
00814                             command = history[history_index];
00815                             writef("%s", history[history_index].c_str());
00816                         }
00817                     }
00818                 }
00819                 while (readable())
00820                     read();
00821                 continue;
00822             } else {
00823                 command += ch;
00824             }
00825 
00826             // echo chars if enabled
00827             if (echo && !(ch == '\r' || ch == '\n'))
00828                 writef("%c", ch);
00829         }
00830 
00831         // look for end of command line
00832         if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
00833             // remove new line or cr character
00834             command.erase(command.size() - 1);
00835             write("\r"); // match standard modem output
00836             write(newline);
00837         } else {
00838             continue;
00839         }
00840 
00841         // trim whitespace from command
00842         mts::Text::trim(command, "\r\n\t ");
00843 
00844         if (command.size() < 1) {
00845             command.clear();
00846             continue;
00847         }
00848 
00849         // parse command and args
00850         args.clear();
00851 
00852         // find first '=' character
00853         size_t delim_index = command.find("=");
00854         if (delim_index != std::string::npos) {
00855             args.push_back(command.substr(0, delim_index));
00856         } else {
00857             // find first ' ' character
00858             delim_index = command.find(" ");
00859             if (delim_index != std::string::npos) {
00860                 args.push_back(command.substr(0, delim_index));
00861             } else {
00862                 args.push_back(command);
00863             }
00864         }
00865 
00866         if (delim_index != std::string::npos) {
00867             std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
00868             args.insert(args.end(), params.begin(), params.end());
00869         }
00870 
00871         args[0] = mts::Text::toUpper(args[0]);
00872 
00873         // print help
00874         if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
00875             printHelp();
00876             command.clear();
00877         } else if ((args[0].find("ATE?") == 0 && args[0].length() == 4) || (args[0].find("ATE") == 0 && args[0].length() == 3)) {
00878             writef("%d\r\n", _dot->getEcho());
00879             write(done);
00880         } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) {
00881             _dot->setEcho(false);
00882             write(done);
00883             echo = _dot->getEcho();
00884         } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) {
00885             _dot->setEcho(true);
00886             write(done);
00887             echo = _dot->getEcho();
00888         } else if ((args[0].find("ATV?") == 0 && args[0].length() == 4) || (args[0].find("ATV") == 0 && args[0].length() == 3)) {
00889             writef("%d\r\n", _dot->getVerbose());
00890             write(done);
00891         } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) {
00892             _dot->setVerbose(false);
00893             write(done);
00894         } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) {
00895             _dot->setVerbose(true);
00896             write(done);
00897         } else if ((args[0].find("AT&K?") == 0 && args[0].length() == 5) || (args[0].find("AT&K") == 0 && args[0].length() == 4)) {
00898             writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0));
00899             write(done);
00900         } else if (args[0].find("AT&K0") == 0 && args[0].length() == 5) {
00901             _dot->setFlowControl(false);
00902             write(done);
00903         } else if (args[0].find("AT&K3") == 0 && args[0].length() == 5) {
00904             _dot->setFlowControl(true);
00905             write(done);
00906         } else if (args[0] == "AT+SD") {
00907             if (_dot->getNetworkJoinStatus()) {
00908                 logDebug("Enter Serial Mode");
00909                 write(connect);
00910                 serial_data_mode = true;
00911                 _mode = mDot::SERIAL_MODE;
00912             } else {
00913                 logDebug("Network Not Joined");
00914                 write("Network Not Joined\r\n");
00915                 write(error);
00916             }
00917         } else if (args[0] == "AT+SLEEP") {
00918             if (args.size() > 2 && (args[1] != "?")) {
00919                 write("Invalid argument\r\n");
00920                 write(error);
00921             } else {
00922                 if (args.size() > 1 && args[1] == "?") {
00923                     write("(0:deepsleep,1:sleep)\r\n");
00924                     write(done);
00925                 } else {
00926                     _sleep_standby = !(args.size() > 1 && args[1] == "1");
00927                     write(done);
00928                     osDelay(5);
00929                     this->sleep(_sleep_standby);
00930                     osDelay(1);
00931                 }
00932             }
00933         } else {
00934             bool found = false;
00935             bool query = false;
00936 
00937             std::string lookfor = args[0];
00938 
00939             // per command help
00940             if ((args[0].find("?") == 0 || args[0].find("HELP") == 0))
00941                 lookfor = mts::Text::toUpper(args[1]);
00942 
00943             // trim off any trailing '?' and mark as a query command
00944             if (args[0].rfind("?") == args[0].length() - 1) {
00945                 query = true;
00946                 lookfor = args[0].substr(0, args[0].length() - 1);
00947             }
00948 
00949             // search for command
00950             for (int i = 0; i < NO_OF_COMMANDS; i++) {
00951 
00952                 // match CMD or CMD? syntax if command is queryable
00953                 if (lookfor == _commands[i].text() && (!query || (query && _commands[i].queryable()))) {
00954                     found = true;
00955                     if (args[0] == "HELP") {
00956                         writef("%s%s", _commands[i].help().c_str(), newline);
00957                         write(done);
00958                     }
00959 
00960                     else if (args.size() > 1 && args[1] == "?") {
00961                         writef("%s%s", _commands[i].usage().c_str(), newline);
00962                         write(done);
00963                     } else if (!_verify[i](args)) {
00964                         writef("%s%s", _errorMessage.c_str(), newline);
00965                         writef("%s", error);
00966                     } else {
00967                         if (_action[i](args) == 0) {
00968                             writef("%s", done);
00969                         } else {
00970                             writef("%s%s", _errorMessage.c_str(), newline);
00971                             writef("%s", error);
00972                         }
00973                     }
00974                 }
00975             }
00976 
00977             if (!found) {
00978                 writef("%s", command_error);
00979                 writef("%s", error);
00980             }
00981         }
00982 
00983         if (history.size() == 0 || history.front() != command)
00984             history.push_front(command);
00985         history_index = -1;
00986         command.clear();
00987 
00988         while (history.size() > 10)
00989             history.pop_back();
00990     }
00991 }
00992 
00993 void CommandTerminal::sleep(bool standby) {
00994     _xbee_on_sleep = GPIO_PIN_RESET;
00995 
00996     _serial.rxClear();
00997     _serial.txClear();
00998 
00999 #if defined(TARGET_XDOT_L151CC)
01000     xdot_save_gpio_state();
01001 
01002     /* GPIO Ports Clock Enable */
01003     __GPIOA_CLK_ENABLE();
01004     __GPIOB_CLK_ENABLE();
01005     __GPIOC_CLK_ENABLE();
01006     __GPIOH_CLK_ENABLE();
01007 
01008     GPIO_InitTypeDef GPIO_InitStruct;
01009 
01010     // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
01011     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
01012     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01013     GPIO_InitStruct.Pull = GPIO_NOPULL;
01014     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01015 
01016     // I2C_SDA & I2C_SCL to analog nopull
01017     GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
01018     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01019     GPIO_InitStruct.Pull = GPIO_NOPULL;
01020     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
01021 
01022     // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
01023     GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
01024     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01025     GPIO_InitStruct.Pull = GPIO_NOPULL;
01026     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
01027 
01028     // iterate through potential wake pins - leave the configured wake pin alone if one is needed
01029     if (_dot->getWakePin() != WAKE || _dot->getWakeMode() == mDot::RTC_ALARM) {
01030         GPIO_InitStruct.Pin = GPIO_PIN_0;
01031         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01032         GPIO_InitStruct.Pull = GPIO_NOPULL;
01033         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01034     }
01035     if (_dot->getWakePin() != GPIO0 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01036         GPIO_InitStruct.Pin = GPIO_PIN_4;
01037         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01038         GPIO_InitStruct.Pull = GPIO_NOPULL;
01039         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01040     }
01041     if (_dot->getWakePin() != GPIO1 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01042         GPIO_InitStruct.Pin = GPIO_PIN_5;
01043         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01044         GPIO_InitStruct.Pull = GPIO_NOPULL;
01045         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01046     }
01047     if (_dot->getWakePin() != GPIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01048         GPIO_InitStruct.Pin = GPIO_PIN_0;
01049         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01050         GPIO_InitStruct.Pull = GPIO_NOPULL;
01051         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
01052     }
01053     if (_dot->getWakePin() != GPIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01054         GPIO_InitStruct.Pin = GPIO_PIN_2;
01055         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01056         GPIO_InitStruct.Pull = GPIO_NOPULL;
01057         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
01058     }
01059     if (_dot->getWakePin() != UART1_RX || _dot->getWakeMode() == mDot::RTC_ALARM) {
01060         GPIO_InitStruct.Pin = GPIO_PIN_10;
01061         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01062         GPIO_InitStruct.Pull = GPIO_NOPULL;
01063         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01064     }
01065 #else
01066     uint32_t portA[6];
01067     uint32_t portB[6];
01068     uint32_t portC[6];
01069     uint32_t portD[6];
01070     uint32_t portH[6];
01071 
01072     //Save the GPIO state.
01073     portA[0] = GPIOA->MODER;
01074     portA[1] = GPIOA->OTYPER;
01075     portA[2] = GPIOA->OSPEEDR;
01076     portA[3] = GPIOA->PUPDR;
01077     portA[4] = GPIOA->AFR[0];
01078     portA[5] = GPIOA->AFR[1];
01079 
01080     portB[0] = GPIOB->MODER;
01081     portB[1] = GPIOB->OTYPER;
01082     portB[2] = GPIOB->OSPEEDR;
01083     portB[3] = GPIOB->PUPDR;
01084     portB[4] = GPIOB->AFR[0];
01085     portB[5] = GPIOB->AFR[1];
01086 
01087     portC[0] = GPIOC->MODER;
01088     portC[1] = GPIOC->OTYPER;
01089     portC[2] = GPIOC->OSPEEDR;
01090     portC[3] = GPIOC->PUPDR;
01091     portC[4] = GPIOC->AFR[0];
01092     portC[5] = GPIOC->AFR[1];
01093 
01094     portD[0] = GPIOD->MODER;
01095     portD[1] = GPIOD->OTYPER;
01096     portD[2] = GPIOD->OSPEEDR;
01097     portD[3] = GPIOD->PUPDR;
01098     portD[4] = GPIOD->AFR[0];
01099     portD[5] = GPIOD->AFR[1];
01100 
01101     portH[0] = GPIOH->MODER;
01102     portH[1] = GPIOH->OTYPER;
01103     portH[2] = GPIOH->OSPEEDR;
01104     portH[3] = GPIOH->PUPDR;
01105     portH[4] = GPIOH->AFR[0];
01106     portH[5] = GPIOH->AFR[1];
01107 
01108     /* GPIO Ports Clock Enable */
01109     __GPIOA_CLK_ENABLE();
01110     __GPIOB_CLK_ENABLE();
01111     __GPIOC_CLK_ENABLE();
01112 
01113     GPIO_InitTypeDef GPIO_InitStruct;
01114 
01115     // Set port A pins to analog nopull
01116     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 
01117                 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
01118     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01119     GPIO_InitStruct.Pull = GPIO_NOPULL;
01120     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);    
01121 
01122     // Set port B pins to analog nopull
01123     GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
01124     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01125     GPIO_InitStruct.Pull = GPIO_NOPULL;
01126     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
01127 
01128     // Set port C pins to analog nopull
01129     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
01130     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01131     GPIO_InitStruct.Pull = GPIO_NOPULL;
01132     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
01133 
01134     // iterate through potential wake pins - leave the configured wake pin alone if one is needed
01135     // XBEE_DIN - PA3
01136     // XBEE_DIO2 - PA5
01137     // XBEE_DIO3 - PA4
01138     // XBEE_DIO4 - PA7
01139     // XBEE_DIO5 - PC1
01140     // XBEE_DIO6 - PA1
01141     // XBEE_DIO7 - PA0
01142     // XBEE_SLEEPRQ - PA11
01143                 
01144     if (_dot->getWakePin() != XBEE_DIN || _dot->getWakeMode() == mDot::RTC_ALARM) {
01145         GPIO_InitStruct.Pin = GPIO_PIN_3;
01146         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01147         GPIO_InitStruct.Pull = GPIO_NOPULL;
01148         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01149     }
01150 
01151     if (_dot->getWakePin() != XBEE_DIO2 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01152         GPIO_InitStruct.Pin = GPIO_PIN_5;
01153         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01154         GPIO_InitStruct.Pull = GPIO_NOPULL;
01155         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01156     }
01157 
01158     if (_dot->getWakePin() != XBEE_DIO3 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01159         GPIO_InitStruct.Pin = GPIO_PIN_4;
01160         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01161         GPIO_InitStruct.Pull = GPIO_NOPULL;
01162         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01163     }
01164 
01165          if (_dot->getWakePin() != XBEE_DIO4 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01166         GPIO_InitStruct.Pin = GPIO_PIN_7;
01167         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01168         GPIO_InitStruct.Pull = GPIO_NOPULL;
01169         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01170     }
01171 
01172      if (_dot->getWakePin() != XBEE_DIO5 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01173         GPIO_InitStruct.Pin = GPIO_PIN_1;
01174         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01175         GPIO_InitStruct.Pull = GPIO_NOPULL;
01176         HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
01177     }
01178 
01179      if (_dot->getWakePin() != XBEE_DIO6 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01180         GPIO_InitStruct.Pin = GPIO_PIN_1;
01181         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01182         GPIO_InitStruct.Pull = GPIO_NOPULL;
01183         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01184     }
01185 
01186      if (_dot->getWakePin() != XBEE_DIO7 || _dot->getWakeMode() == mDot::RTC_ALARM) {
01187         GPIO_InitStruct.Pin = GPIO_PIN_0;
01188         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01189         GPIO_InitStruct.Pull = GPIO_NOPULL;
01190         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01191     }
01192 
01193      if (_dot->getWakePin() != XBEE_SLEEPRQ|| _dot->getWakeMode() == mDot::RTC_ALARM) {
01194         GPIO_InitStruct.Pin = GPIO_PIN_11;
01195         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
01196         GPIO_InitStruct.Pull = GPIO_NOPULL;
01197         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
01198     }
01199  
01200 #endif
01201     _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby);
01202 
01203 #if defined(TARGET_XDOT_L151CC)
01204     xdot_restore_gpio_state();
01205 #else
01206     //Restore the GPIO state.
01207     GPIOA->MODER = portA[0];
01208     GPIOA->OTYPER = portA[1];
01209     GPIOA->OSPEEDR = portA[2];
01210     GPIOA->PUPDR = portA[3];
01211     GPIOA->AFR[0] = portA[4];
01212     GPIOA->AFR[1] = portA[5];
01213 
01214     GPIOB->MODER = portB[0];
01215     GPIOB->OTYPER = portB[1];
01216     GPIOB->OSPEEDR = portB[2];
01217     GPIOB->PUPDR = portB[3];
01218     GPIOB->AFR[0] = portB[4];
01219     GPIOB->AFR[1] = portB[5];
01220 
01221     GPIOC->MODER = portC[0];
01222     GPIOC->OTYPER = portC[1];
01223     GPIOC->OSPEEDR = portC[2];
01224     GPIOC->PUPDR = portC[3];
01225     GPIOC->AFR[0] = portC[4];
01226     GPIOC->AFR[1] = portC[5];
01227 
01228     GPIOD->MODER = portD[0];
01229     GPIOD->OTYPER = portD[1];
01230     GPIOD->OSPEEDR = portD[2];
01231     GPIOD->PUPDR = portD[3];
01232     GPIOD->AFR[0] = portD[4];
01233     GPIOD->AFR[1] = portD[5];
01234 
01235     GPIOH->MODER = portH[0];
01236     GPIOH->OTYPER = portH[1];
01237     GPIOH->OSPEEDR = portH[2];
01238     GPIOH->PUPDR = portH[3];
01239     GPIOH->AFR[0] = portH[4];
01240     GPIOH->AFR[1] = portH[5];
01241 #endif
01242 
01243     _serial.rxClear();
01244     _serial.txClear();
01245 }
01246 
01247 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
01248     if (format == mDot::HEXADECIMAL)
01249         return mts::Text::bin2hexString(data);
01250     else
01251         return std::string(data.begin(), data.end());
01252 }
01253 
01254 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
01255     Timer timer;
01256 
01257     timer.start();
01258     while (timer.read_ms() < timeout) {
01259 
01260         if (dot != NULL) {
01261             if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
01262                 return false;
01263             }
01264         }
01265 
01266         if (_serialp != NULL && _serialp->escaped()) {
01267             _serialp->clearEscaped();
01268             return true;
01269         }
01270 
01271         osDelay(10);
01272     }
01273 
01274     return false;
01275 }
01276 
01277 void CommandTerminal::wakeup(void) {
01278 }
01279 
01280 void CommandTerminal::RadioEvent::PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries) {
01281     mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, retries);
01282 
01283     if (serial_data_mode) {
01284         logDebug("Rx %d bytes", size);
01285         if (size > 0) {
01286             CommandTerminal::Serial()->write((char*) RxPayload, RxPayloadSize);
01287         }
01288         if (!CommandTerminal::Serial()->readable() && _dot->getAckRequested() && _dot->getClass() == "C") {
01289             _sendAck = true;
01290         }
01291     }
01292 }
01293 
01294 CommandTerminal::~CommandTerminal() {
01295     delete _events;
01296 }