with 36errors

Dependencies:   MTS-Serial libxDot-dev-mbed5-deprecated

Fork of Dot-AT-Firmware by MultiTech

Revision:
9:ff62b20f7000
Parent:
6:e27eaad36a0c
Child:
11:05e0f30c03a6
--- a/CommandTerminal/CommandTerminal.cpp	Mon Apr 04 13:17:44 2016 +0000
+++ b/CommandTerminal/CommandTerminal.cpp	Mon Apr 04 09:00:31 2016 -0500
@@ -3,7 +3,6 @@
 #include "Command.h"
 #include "MTSLog.h"
 #include <cstdarg>
-
 #include <deque>
 
 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
@@ -17,35 +16,43 @@
 // Response texts...
 const char CommandTerminal::help[] = "\r\nHelp\r\n";
 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
+const char CommandTerminal::connect[] = "\r\nCONNECT\r\n";
+const char CommandTerminal::no_carrier[] = "\r\nNO CARRIER\r\n";
 const char CommandTerminal::done[] = "\r\nOK\r\n";
 const char CommandTerminal::error[] = "\r\nERROR\r\n";
 
 // Escape sequence...
 const char CommandTerminal::escape_sequence[] = "+++";
 
-mts::MTSSerial* CommandTerminal::_serialp = NULL;
+mts::ATSerial* CommandTerminal::_serialp = NULL;
+
+static bool serial_data_mode = false;
+static bool peer_to_peer = false;
 
 void CommandTerminal::addCommand(Command* cmd) {
     _commands.push_back(cmd);
 }
 
-CommandTerminal::CommandTerminal(mts::MTSSerial& serial, mDot* dot)
+CommandTerminal::CommandTerminal(mts::ATSerial& serial, mDot* dot)
 :
   _serial(serial),
   _dot(dot),
+  _events(new RadioEvent(serial)),
   _mode(mDot::COMMAND_MODE),
   _idle_thread(idle, NULL, osPriorityLow),
   _sleep_standby(true),
-  _xbee_on_sleep(XBEE_ON_SLEEP),
-  _serial_up(false) {
+  _xbee_on_sleep(XBEE_ON_SLEEP) {
 
+    _dot->setEvents(_events);
+    _dot->setWakeupCallback(this, &CommandTerminal::wakeup);
     _serialp = &serial;
 
     addCommand(new CmdAttention(_dot));
     addCommand(new CmdIdentification(_dot, serial));
     addCommand(new CmdResetCpu(_dot, serial));
-    addCommand(new CmdDummy(_dot, "Enable/Disable Echo", "ATE0/1", "ATE0: disable, ATE1: enable"));
-    addCommand(new CmdDummy(_dot, "Enable/Disable Verbose", "ATV0/1", "ATV0: disable, ATV1: enable"));
+    addCommand(new CmdDummy(_dot, "Enable/Disable Echo", "ATE", "ATE0: disable, ATE1: enable"));
+    addCommand(new CmdDummy(_dot, "Enable/Disable Verbose", "ATV", "ATV0: disable, ATV1: enable"));
+    addCommand(new CmdDummy(_dot, "Hardware Flow Control", "AT&K", "AT&K0: disable, AT&K3: enable"));
 
     addCommand(new CmdFactoryDefault(_dot));
     addCommand(new CmdSaveConfig(_dot));
@@ -60,17 +67,25 @@
     addCommand(new CmdFrequencySubBand(_dot, serial));
     addCommand(new CmdPublicNetwork(_dot, serial));
     addCommand(new CmdDeviceId(_dot, serial));
+    addCommand(new CmdDeviceClass(_dot, serial));
 
+    addCommand(new CmdAppPort(_dot, serial));
     addCommand(new CmdNetworkAddress(_dot, serial));
     addCommand(new CmdNetworkSessionKey(_dot, serial));
     addCommand(new CmdDataSessionKey(_dot, serial));
+    addCommand(new CmdUplinkCounter(_dot, serial));
+    addCommand(new CmdDownlinkCounter(_dot, serial));
+    addCommand(new CmdSaveSession(_dot, serial));
+    addCommand(new CmdRestoreSession(_dot, serial));
     addCommand(new CmdNetworkKey(_dot, serial));
     addCommand(new CmdNetworkId(_dot, serial));
 
+    addCommand(new CmdJoinDelay(_dot, serial));
     addCommand(new CmdJoinRequest(_dot, serial));
     addCommand(new CmdJoinRetries(_dot, serial));
     addCommand(new CmdJoinByteOrder(_dot, serial));
     addCommand(new CmdNetworkJoinMode(_dot, serial));
+    addCommand(new CmdPreserveSession(_dot, serial));
     addCommand(new CmdNetworkJoinStatus(_dot, serial));
     addCommand(new CmdNetworkLinkCheck(_dot, serial));
     addCommand(new CmdLinkCheckCount(_dot, serial));
@@ -81,8 +96,11 @@
     addCommand(new CmdSnr(_dot, serial));
     addCommand(new CmdDataPending(_dot, serial));
 
+    addCommand(new CmdSessionDataRate(_dot, serial));
+
     addCommand(new CmdTxDataRate(_dot, serial));
     addCommand(new CmdTxPower(_dot, serial));
+    addCommand(new CmdAntennaGain(_dot, serial));
     addCommand(new CmdTxFrequency(_dot, serial));
     addCommand(new CmdTxInverted(_dot, serial));
     addCommand(new CmdTxWait(_dot, serial));
@@ -90,8 +108,7 @@
     addCommand(new CmdTxNextMs(_dot, serial));
     addCommand(new CmdTimeOnAir(_dot, serial));
 
-    addCommand(new CmdRxDataRate(_dot, serial));
-    addCommand(new CmdRxFrequency(_dot, serial));
+    addCommand(new CmdRxDelay(_dot, serial));
     addCommand(new CmdRxOutput(_dot, serial));
     addCommand(new CmdRxInverted(_dot, serial));
 
@@ -100,23 +117,28 @@
     addCommand(new CmdAdaptiveDataRate(_dot, serial));
 
     addCommand(new CmdACKAttempts(_dot, serial));
+    addCommand(new CmdRepeat(_dot, serial));
 
     addCommand(new CmdSendString(_dot, serial));
-    addCommand(new CmdSendStringHighBW(_dot, serial));
     addCommand(new CmdSendBinary(_dot, serial));
-    addCommand(new CmdSendStringOnInterval(_dot, serial));
     addCommand(new CmdReceiveOnce(_dot, serial));
-    addCommand(new CmdReceiveContinuous(_dot, serial));
 
-    addCommand(new CmdDummy(_dot, "Serial Data Mode", "AT+SD", "Reads serial data, sends packet, then sleeps using wake settings"));
-    addCommand(new CmdDummy(_dot, "Sleep Mode", "AT+SLEEP", "Enter sleep mode"));
+    addCommand(new CmdDummy(_dot, "Serial Data Mode", "AT+SD", "Enter serial data mode, exit with '+++'"));
+    addCommand(new CmdDummy(_dot, "Sleep Mode", "AT+SLEEP", "Enter sleep mode (0:deepsleep,1:sleep)"));
+    addCommand(new CmdSerialClearOnError(_dot, serial));
     addCommand(new CmdWakeMode(_dot, serial));
     addCommand(new CmdWakeInterval(_dot, serial));
-    // addCommand(new CmdWakePin(_dot, serial));
+    addCommand(new CmdWakePin(_dot, serial));
     addCommand(new CmdWakeDelay(_dot, serial));
     addCommand(new CmdWakeTimeout(_dot, serial));
     addCommand(new CmdPing(_dot, serial));
     addCommand(new CmdLogLevel(_dot, serial));
+
+    addCommand(new CmdDummy(_dot, "***** Test Commands *****", "", ""));
+    addCommand(new CmdRxDataRate(_dot, serial));
+    addCommand(new CmdRxFrequency(_dot, serial));
+    addCommand(new CmdReceiveContinuous(_dot, serial));
+    addCommand(new CmdSendStringOnInterval(_dot, serial));
 }
 
 void CommandTerminal::printHelp() {
@@ -191,129 +213,133 @@
     va_end(ap);
 }
 
-void CommandTerminal::serial_loop() {
+void CommandTerminal::serialLoop() {
     Timer serial_read_timer;
     std::vector<uint8_t> serial_buffer;
-    std::string escape_buffer;
-    Timer escape_timer;
-    int escape_delay = 100;
-    uint8_t max_send_size;
-
-    _serial_up = true;
-    _xbee_on_sleep = GPIO_PIN_SET;
+    std::vector<uint8_t> data;
+    int timeout = 0;
 
-    if (_dot->getFrequencyBand() == mDot::FB_915)
-        max_send_size = mDot::MaxLengths_915[_dot->getTxDataRate()];
-    else
-        max_send_size = mDot::MaxLengths_868[_dot->getTxDataRate()];
-
-    logDebug("Awake\r\n");
-    wakeup(_sleep_standby);
-
-    char ch;
+    serial_read_timer.start();
 
-    if (readable()) {
-        ch = read();
-        serial_buffer.push_back(ch);
+    if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
+        _xbee_on_sleep = GPIO_PIN_SET;
 
-        if (escape_timer.read_ms() > escape_delay && ch == '+') {
-            escape_buffer += ch;
-            escape_timer.reset();
-        } else {
-            _serial_up = true;
-            escape_buffer.clear();
-        }
+        timeout = _dot->getWakeDelay();
 
-        if (escape_buffer.length() == 3 && escape_buffer.find(escape_sequence) == 0) {
-            _mode = mDot::COMMAND_MODE;
-            logDebug("Exit serial mode\r\n");
-            escape_timer.stop();
-            escape_buffer.clear();
-            write(done);
-            return;
+        // wait for timeout or start of serial data
+        while (!readable() && serial_read_timer.read_ms() < timeout && !_serial.escaped()) {
+            osDelay(2);
         }
     }
 
-    if (_serial_up) {
-        serial_read_timer.start();
-        uint32_t timeout = _dot->getWakeDelay();
-
-        // wait for timeout or start of serial data
-        while (!readable() && serial_read_timer.read_ms() < timeout) {
-            osDelay(10);
-        }
+    if (readable() && !_serial.escaped()) {
 
         serial_read_timer.reset();
         timeout = _dot->getWakeTimeout();
-        while (_serial_up && serial_read_timer.read_ms() < timeout) {
-            while (readable() && serial_buffer.size() < max_send_size) {
+
+        while (serial_read_timer.read_ms() < timeout && serial_buffer.size() <= _dot->getMaxPacketLength()) {
+            while (readable() && serial_buffer.size() < _dot->getMaxPacketLength()) {
                 serial_buffer.push_back(read());
                 serial_read_timer.reset();
+
+                if (_serial.escaped())
+                    break;
             }
         }
+
         serial_read_timer.stop(), serial_read_timer.reset();
 
         if (!serial_buffer.empty()) {
-            _serial_up = false;
-            _xbee_on_sleep = GPIO_PIN_RESET;
+            if (_dot->getStartUpMode() == mDot::SERIAL_MODE)
+                _xbee_on_sleep = GPIO_PIN_RESET;
+
+            // wait for any duty cycle limit to expire
+            while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
+                osDelay(10);
+            }
+
             if (!_dot->getIsTransmitting()) {
-                std::vector<uint8_t> recv_buffer;
-                logDebug("Received serial data, sending out radio.\r\n");
+                logDebug("Received serial data, sending out radio.");
+
+                if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) {
+                    logDebug("Send failed.");
+                    // If the data should be tossed after send failure, clear buffer
+                    if (_dot->getSerialClearOnError()) {
+                        serial_buffer.clear();
+                    }
+                } else {
 
-                if (_dot->send(serial_buffer) != mDot::MDOT_OK)
-                    logDebug("Send failed.\r\n");
-                if (_dot->recv(recv_buffer))
-                    _serial.writef("%s\r\n", formatPacketData(recv_buffer, _dot->getRxOutput()).c_str());
+                    // wait for send to finish
+                    while (_dot->getIsTransmitting() && !_serial.escaped())
+                        osDelay(10);
+
+                    // call recv to wait for any packet before sending again
+                    if (!_serial.escaped())
+                        _dot->recv(data);
+
+                    // Clear the serial buffer if send is success
+                    serial_buffer.clear();
+                }
             } else {
                 logDebug("Radio is busy, cannot send.\r\n");
+                osDelay(10);
             }
 
-            serial_buffer.clear();
         } else {
             logDebug("No data received from serial to send.\r\n");
         }
-        _serial_up = false;
+    }
+
+    if (!_serial.readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serial.escaped()) {
+        _xbee_on_sleep = GPIO_PIN_RESET;
+        sleep(_sleep_standby);
     }
-    sleep(_sleep_standby);
+
+    if (_serial.escaped()) {
+        _serial.clearEscaped();
+        _serial.rxClear();
+        serial_data_mode = false;
+        _mode = mDot::COMMAND_MODE;
+        logDebug("Exit Serial Mode");
+        write(done);
+        return;
+    }
+
+    if (!_dot->getNetworkJoinStatus()) {
+        serial_data_mode = false;
+        _mode = mDot::COMMAND_MODE;
+        logDebug("Exit Serial Mode");
+        write(no_carrier);
+        return;
+    }
 }
 
 bool CommandTerminal::autoJoinCheck() {
 
     std::string escape_buffer;
-    char ch;
     int sleep = 1000;
-    int escape_timeout = 1000;
     Timer tmr;
-    Timer escape_tmr;
+    tmr.start();
     int cnt = 0;
 
     while (!_dot->getNetworkJoinStatus()) {
-        wakeup(_sleep_standby);
         write("\r\nJoining network... ");
 
-        // wait one second for possible escape
-        tmr.reset();
-        tmr.start();
-        escape_tmr.reset();
-        escape_tmr.start();
-        while (tmr.read_ms() < 1000) {
-            if (_serial.readable()) {
-                _serial.read(&ch, 1);
-                escape_buffer += ch;
+        if (_dot->getNextTxMs() > 0) {
+            int rand_time = rand() % 10000;
+            writef("\r\nWaiting %lu s before next join attempt\r\n", (_dot->getNextTxMs() + rand_time) / 1000);
+
+            tmr.reset();
+            while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
+                osDelay(2);
             }
 
-            if (escape_buffer.find(escape_sequence) != std::string::npos) {
-                _mode = mDot::COMMAND_MODE;
-                write("Join Canceled\r\n");
-                write(done);
-                return true;
-            }
-
-            if (escape_tmr.read_ms() > escape_timeout)
-                escape_buffer.clear();
+            tmr.reset();
+            while (tmr.read_ms() < rand_time && !_serial.escaped())
+                osDelay(10);
         }
 
-        if (_dot->joinNetworkOnce() == mDot::MDOT_OK) {
+        if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) {
             write("Network Joined\r\n");
             write(done);
             return false;
@@ -322,12 +348,12 @@
         write("Network Join failed\r\n");
         write(error);
 
-        if (cnt++ > _dot->getJoinRetries()) {
+        if (!_serial.escaped() && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
             cnt = 0;
 
             if (_dot->getFrequencyBand() == mDot::FB_915) {
                 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
-                logDebug("Join retries exhausted, switching to sub band %u\r\n", band);
+                logWarning("Join retries exhausted, switching to sub band %u", band);
                 _dot->setFrequencySubBand(band);
             }
 
@@ -336,24 +362,18 @@
         }
 
         tmr.reset();
-        tmr.start();
-        escape_tmr.reset();
-        escape_tmr.start();
-        while (tmr.read_ms() < sleep) {
-            if (_serial.readable()) {
-                _serial.read(&ch, 1);
-                escape_buffer += ch;
-            }
-
-            if (escape_buffer.find(escape_sequence) != std::string::npos) {
-                _mode = mDot::COMMAND_MODE;
-                return true;
-            }
-
-            if (escape_tmr.read_ms() > escape_timeout)
-                escape_buffer.clear();
+        while (tmr.read_ms() < sleep && !_serial.escaped()) {
+            osDelay(10);
         }
 
+        if (_serial.escaped()) {
+            _serial.clearEscaped();
+            serial_data_mode = false;
+            _mode = mDot::COMMAND_MODE;
+            write("Join Canceled\r\n");
+            write(done);
+            return true;
+        }
     }
 
     return false;
@@ -361,8 +381,6 @@
 
 void CommandTerminal::start() {
 
-    wakeup(_sleep_standby);
-
     char ch;
     bool running = true;
     bool echo = _dot->getEcho();
@@ -370,65 +388,98 @@
     std::deque<std::string> history;
     int history_index = -1;
     std::vector<std::string> args;
+    bool join_canceled = false;
 
     if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
-        command = "AT+SD\n";
+
+        serial_data_mode = true;
+        _mode = mDot::SERIAL_MODE;
 
         std::string escape_buffer;
         char ch;
 
-        int escape_timeout = 1000;
-        Timer tmr;
-        Timer escape_tmr;
+        if (!_dot->getStandbyFlag()) {
+            // wake up from power-on/reset
+
+            int escape_timeout = 1000;
+            Timer tmr;
+            Timer escape_tmr;
 
-        // wait one second for possible escape
-        tmr.reset();
-        tmr.start();
-        escape_tmr.reset();
-        escape_tmr.start();
-        while (tmr.read_ms() < escape_timeout) {
-            if (_serial.readable()) {
-                _serial.read(&ch, 1);
-                escape_buffer += ch;
-            }
+            // wait one second for possible escape by user pressing '+' key
+            tmr.reset();
+            tmr.start();
+            escape_tmr.reset();
+            escape_tmr.start();
+            while (tmr.read_ms() < escape_timeout) {
+                if (_serial.readable()) {
+                    _serial.read(&ch, 1);
+                    escape_buffer += ch;
+                }
 
-            if (escape_buffer.find(escape_sequence) != std::string::npos) {
-                _mode = mDot::COMMAND_MODE;
-                command.clear();
-                break;
+                if (escape_buffer.find("+") != std::string::npos) {
+                    logInfo("Escape detected");
+                    join_canceled = true;
+                    serial_data_mode = false;
+                    _mode = mDot::COMMAND_MODE;
+                    command.clear();
+                    break;
+                }
+
+                if (escape_tmr.read_ms() > escape_timeout)
+                    escape_buffer.clear();
+
+                osDelay(1);
             }
-
-            if (escape_tmr.read_ms() > escape_timeout)
-                escape_buffer.clear();
-
-            osDelay(1);
         }
 
+        if (_mode == mDot::SERIAL_MODE && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
+            if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
+                serial_data_mode = false;
+                _mode = mDot::COMMAND_MODE;
+
+                logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
+                _serial.writef("Network Not Joined\r\n");
+                _serial.writef(error);
+            }
+        }
     }
 
-    bool join_canceled = false;
+    if (_dot->getJoinMode() == mDot::PEER_TO_PEER) {
+        peer_to_peer = true;
+    } else {
+        peer_to_peer = false;
+    }
+
+
 
     //Run terminal session
     while (running) {
-        if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) {
-            join_canceled = autoJoinCheck();
-            if (join_canceled)
-                command.clear();
-        }
+
+        // wait for input to reduce at command idle current
+        while (!readable() || _mode == mDot::SERIAL_MODE) {
+            if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) {
+                join_canceled = autoJoinCheck();
+                if (join_canceled)
+                    command.clear();
+            }
 
-        if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) {
-            switch (_mode) {
-                case mDot::SERIAL_MODE:
-                    // signal wakeup, read serial and output to radio
-                    serial_loop();
-                    continue;
-                    break;
-                default:
-                    break;
+            if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) {
+                switch (_mode) {
+                    case mDot::SERIAL_MODE:
+                        // signal wakeup, read serial and output to radio
+                        serialLoop();
+                        continue;
+                        break;
+                    default:
+                        break;
+                }
             }
-        }
+
+            ch = '\0';
 
-        ch = '\0';
+            wait(0.00001); // 10 us
+            _serial.escaped();
+        }
 
         // read characters
         if (readable()) {
@@ -443,7 +494,7 @@
             } else if (ch == 0x1b || ch == 0x09) {
                 osDelay(20);
                 // catch escape sequence, or tab
-                char ch1, ch2;
+                char ch1 = 0x00, ch2 = 0x00;
 
                 if (readable()) {
                     ch1 = read();
@@ -452,11 +503,11 @@
 
                     if (ch1 == 0x5b && ch2 == 0x41) {
                         // up key
-                        for (int i = 0; i < command.size()+1; i++) {
+                        for (size_t i = 0; i < command.size() + 1; i++) {
                             writef("\b \b");
                         }
                         if (history.size() > 0) {
-                            if (++history_index >= history.size() - 1)
+                            if (++history_index >= int(history.size() - 1))
                                 history_index = history.size() - 1;
 
                             command = history[history_index];
@@ -467,7 +518,7 @@
                     } else if (ch1 == 0x5b && ch2 == 0x42) {
 
                         // down key
-                        for (int i = 0; i < command.size()+1; i++) {
+                        for (size_t i = 0; i < command.size() + 1; i++) {
                             writef("\b \b");
                         }
 
@@ -480,7 +531,8 @@
                         }
                     }
                 }
-                while (readable()) read();
+                while (readable())
+                    read();
                 continue;
             } else {
                 command += ch;
@@ -537,6 +589,9 @@
         if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
             printHelp();
             command.clear();
+        } else if ((args[0].find("ATE?") == 0 && args[0].length() == 4) || (args[0].find("ATE") == 0 && args[0].length() == 3)) {
+            writef("%d\r\n", _dot->getEcho());
+            write(done);
         } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) {
             _dot->setEcho(false);
             write(done);
@@ -545,28 +600,48 @@
             _dot->setEcho(true);
             write(done);
             echo = _dot->getEcho();
+        } else if ((args[0].find("ATV?") == 0 && args[0].length() == 4) || (args[0].find("ATV") == 0 && args[0].length() == 3)) {
+            writef("%d\r\n", _dot->getVerbose());
+            write(done);
         } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) {
             _dot->setVerbose(false);
             write(done);
         } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) {
             _dot->setVerbose(true);
             write(done);
+        } else if ((args[0].find("AT&K?") == 0 && args[0].length() == 5) || (args[0].find("AT&K") == 0 && args[0].length() == 4)) {
+            writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0));
+            write(done);
+        } else if (args[0].find("AT&K0") == 0 && args[0].length() == 5) {
+            _dot->setFlowControl(false);
+            write(done);
+        } else if (args[0].find("AT&K3") == 0 && args[0].length() == 5) {
+            _dot->setFlowControl(true);
+            write(done);
         } else if (args[0] == "AT+SD") {
-            logDebug("Enter Serial Mode\r\n");
-            _mode = mDot::SERIAL_MODE;
+            if (_dot->getNetworkJoinStatus()) {
+                logDebug("Enter Serial Mode");
+                write(connect);
+                serial_data_mode = true;
+                _mode = mDot::SERIAL_MODE;
+            } else {
+                logDebug("Network Not Joined");
+                write("Network Not Joined\r\n");
+                write(error);
+            }
         } else if (args[0] == "AT+SLEEP") {
-            if (args.size() > 1 && (args[1] != "?")) {
+            if (args.size() > 2 && (args[1] != "?")) {
                 write("Invalid argument\r\n");
                 write(error);
             } else {
                 if (args.size() > 1 && args[1] == "?") {
-                    write("AT+SLEEP: NONE\r\n");
+                    write("(0:deepsleep,1:sleep)\r\n");
                     write(done);
                 } else {
                     _sleep_standby = !(args.size() > 1 && args[1] == "1");
+                    write(done);
                     this->sleep(_sleep_standby);
                     wait(0.1);
-                    write(done);
                 }
             }
         } else {
@@ -638,7 +713,6 @@
 }
 
 void CommandTerminal::sleep(bool standby) {
-    _serial_up = false;
     _xbee_on_sleep = GPIO_PIN_RESET;
 
     _serial.rxClear();
@@ -649,9 +723,6 @@
 
 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
     Timer timer;
-    Timer escape_timer;
-    std::string escape_buffer;
-    int escape_timeout = 1000;
 
     timer.start();
     while (timer.read_ms() < timeout) {
@@ -662,18 +733,9 @@
             }
         }
 
-        if (_serialp != NULL && _serialp->readable()) {
-            if (escape_buffer == "")
-                escape_timer.start();
-            char ch;
-            _serialp->read(&ch, 1);
-            escape_buffer += ch;
-            if (escape_buffer == CommandTerminal::escape_sequence)
-                return true;
-        }
-        if (escape_timer.read_ms() > escape_timeout) {
-            escape_buffer = "";
-            escape_timer.stop(), escape_timer.reset();
+        if (_serialp != NULL && _serialp->escaped()) {
+            _serialp->clearEscaped();
+            return true;
         }
 
         osDelay(10);
@@ -682,6 +744,66 @@
     return false;
 }
 
-void CommandTerminal::wakeup(bool standby) {
+void CommandTerminal::wakeup(void) {
+    if (_dot->getWakePin() == XBEE_DIN) {
+        _serial.reattach(XBEE_DOUT, XBEE_DIN);
+        logInfo("Wakeup pin was serial input");
+    }
+}
+
+void CommandTerminal::RadioEvent::MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) {
 
+    if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
+        std::string msg = "OK";
+        switch (info->Status) {
+            case LORAMAC_EVENT_INFO_STATUS_ERROR:
+                msg = "ERROR";
+                break;
+            case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
+                msg = "TX_TIMEOUT";
+                break;
+            case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
+                msg = "RX_TIMEOUT";
+                break;
+            case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
+                msg = "RX_ERROR";
+                break;
+            case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
+                msg = "JOIN_FAIL";
+                break;
+            case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
+                msg = "DOWNLINK_FAIL";
+                break;
+            case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
+                msg = "ADDRESS_FAIL";
+                break;
+            case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
+                msg = "MIC_FAIL";
+                break;
+            default:
+                break;
+        }
+        logTrace("Event: %s", msg.c_str());
+
+        logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
+                 flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
+        logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
+                 info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
+                 info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
+    }
+
+    if (flags->Bits.Rx) {
+        if (serial_data_mode) {
+            logDebug("Rx %d bytes", info->RxBufferSize);
+            if (info->RxBufferSize > 0) {
+                _serial.write((char*) info->RxBuffer, info->RxBufferSize);
+            }
+        }
+
+        delete[] info->RxBuffer;
+    }
 }
+
+CommandTerminal::~CommandTerminal() {
+    delete _events;
+}