mDot AT-Firmware for testing

Dependencies:   MTS-Serial libmDot-mbed5

Fork of Dot-AT-Firmware by MultiTech

Committer:
mfiore
Date:
Mon Aug 22 19:34:26 2016 +0000
Revision:
11:05e0f30c03a6
Parent:
9:ff62b20f7000
Child:
14:f9a77400b622
update libmDot to 2.0.3 and update mbed libs to compatible versions: mbed 121, mbed-rtos 117

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mike Fiore 1:e52ae6584f1c 1 #include "ctype.h"
Mike Fiore 1:e52ae6584f1c 2 #include "CommandTerminal.h"
Mike Fiore 1:e52ae6584f1c 3 #include "Command.h"
Mike Fiore 4:666017851052 4 #include "MTSLog.h"
Mike Fiore 1:e52ae6584f1c 5 #include <cstdarg>
Mike Fiore 4:666017851052 6 #include <deque>
Mike Fiore 1:e52ae6584f1c 7
Mike Fiore 1:e52ae6584f1c 8 const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n";
Mike Fiore 1:e52ae6584f1c 9 const char CommandTerminal::helpline[] = "Enter '?' for help\r\n";
Mike Fiore 1:e52ae6584f1c 10
Mike Fiore 1:e52ae6584f1c 11 const char CommandTerminal::newline[] = "\r\n";
Mike Fiore 1:e52ae6584f1c 12
Mike Fiore 1:e52ae6584f1c 13 // Command error text...
Mike Fiore 1:e52ae6584f1c 14 const char CommandTerminal::command_error[] = "Command not found!\r\n";
Mike Fiore 1:e52ae6584f1c 15
Mike Fiore 1:e52ae6584f1c 16 // Response texts...
Mike Fiore 1:e52ae6584f1c 17 const char CommandTerminal::help[] = "\r\nHelp\r\n";
Mike Fiore 1:e52ae6584f1c 18 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
Mike Fiore 9:ff62b20f7000 19 const char CommandTerminal::connect[] = "\r\nCONNECT\r\n";
Mike Fiore 9:ff62b20f7000 20 const char CommandTerminal::no_carrier[] = "\r\nNO CARRIER\r\n";
Mike Fiore 1:e52ae6584f1c 21 const char CommandTerminal::done[] = "\r\nOK\r\n";
Mike Fiore 1:e52ae6584f1c 22 const char CommandTerminal::error[] = "\r\nERROR\r\n";
Mike Fiore 1:e52ae6584f1c 23
Mike Fiore 1:e52ae6584f1c 24 // Escape sequence...
Mike Fiore 1:e52ae6584f1c 25 const char CommandTerminal::escape_sequence[] = "+++";
Mike Fiore 1:e52ae6584f1c 26
Mike Fiore 9:ff62b20f7000 27 mts::ATSerial* CommandTerminal::_serialp = NULL;
Mike Fiore 9:ff62b20f7000 28
Mike Fiore 9:ff62b20f7000 29 static bool serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 30 static bool peer_to_peer = false;
Mike Fiore 1:e52ae6584f1c 31
Mike Fiore 1:e52ae6584f1c 32 void CommandTerminal::addCommand(Command* cmd) {
Mike Fiore 1:e52ae6584f1c 33 _commands.push_back(cmd);
Mike Fiore 1:e52ae6584f1c 34 }
Mike Fiore 1:e52ae6584f1c 35
Mike Fiore 9:ff62b20f7000 36 CommandTerminal::CommandTerminal(mts::ATSerial& serial, mDot* dot)
Mike Fiore 1:e52ae6584f1c 37 :
Mike Fiore 1:e52ae6584f1c 38 _serial(serial),
Mike Fiore 1:e52ae6584f1c 39 _dot(dot),
Mike Fiore 9:ff62b20f7000 40 _events(new RadioEvent(serial)),
Mike Fiore 1:e52ae6584f1c 41 _mode(mDot::COMMAND_MODE),
Mike Fiore 4:666017851052 42 _idle_thread(idle, NULL, osPriorityLow),
Mike Fiore 4:666017851052 43 _sleep_standby(true),
Mike Fiore 9:ff62b20f7000 44 _xbee_on_sleep(XBEE_ON_SLEEP) {
Mike Fiore 1:e52ae6584f1c 45
Mike Fiore 9:ff62b20f7000 46 _dot->setEvents(_events);
Mike Fiore 9:ff62b20f7000 47 _dot->setWakeupCallback(this, &CommandTerminal::wakeup);
Mike Fiore 1:e52ae6584f1c 48 _serialp = &serial;
Mike Fiore 1:e52ae6584f1c 49
Mike Fiore 1:e52ae6584f1c 50 addCommand(new CmdAttention(_dot));
Mike Fiore 1:e52ae6584f1c 51 addCommand(new CmdIdentification(_dot, serial));
Mike Fiore 1:e52ae6584f1c 52 addCommand(new CmdResetCpu(_dot, serial));
Mike Fiore 9:ff62b20f7000 53 addCommand(new CmdDummy(_dot, "Enable/Disable Echo", "ATE", "ATE0: disable, ATE1: enable"));
Mike Fiore 9:ff62b20f7000 54 addCommand(new CmdDummy(_dot, "Enable/Disable Verbose", "ATV", "ATV0: disable, ATV1: enable"));
Mike Fiore 9:ff62b20f7000 55 addCommand(new CmdDummy(_dot, "Hardware Flow Control", "AT&K", "AT&K0: disable, AT&K3: enable"));
Mike Fiore 1:e52ae6584f1c 56
Mike Fiore 1:e52ae6584f1c 57 addCommand(new CmdFactoryDefault(_dot));
Mike Fiore 1:e52ae6584f1c 58 addCommand(new CmdSaveConfig(_dot));
Mike Fiore 1:e52ae6584f1c 59 addCommand(new CmdDisplayConfig(_dot, serial));
Mike Fiore 1:e52ae6584f1c 60 addCommand(new CmdDisplayStats(_dot, serial));
Mike Fiore 4:666017851052 61 addCommand(new CmdResetStats(_dot, serial));
Mike Fiore 1:e52ae6584f1c 62 addCommand(new CmdSerialBaudRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 63 addCommand(new CmdDebugBaudRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 64 addCommand(new CmdStartUpMode(_dot, serial));
Mike Fiore 1:e52ae6584f1c 65
Mike Fiore 1:e52ae6584f1c 66 addCommand(new CmdFrequencyBand(_dot, serial));
Mike Fiore 1:e52ae6584f1c 67 addCommand(new CmdFrequencySubBand(_dot, serial));
Mike Fiore 1:e52ae6584f1c 68 addCommand(new CmdPublicNetwork(_dot, serial));
Mike Fiore 1:e52ae6584f1c 69 addCommand(new CmdDeviceId(_dot, serial));
Mike Fiore 9:ff62b20f7000 70 addCommand(new CmdDeviceClass(_dot, serial));
Mike Fiore 1:e52ae6584f1c 71
Mike Fiore 9:ff62b20f7000 72 addCommand(new CmdAppPort(_dot, serial));
Mike Fiore 1:e52ae6584f1c 73 addCommand(new CmdNetworkAddress(_dot, serial));
Mike Fiore 1:e52ae6584f1c 74 addCommand(new CmdNetworkSessionKey(_dot, serial));
Mike Fiore 1:e52ae6584f1c 75 addCommand(new CmdDataSessionKey(_dot, serial));
Mike Fiore 9:ff62b20f7000 76 addCommand(new CmdUplinkCounter(_dot, serial));
Mike Fiore 9:ff62b20f7000 77 addCommand(new CmdDownlinkCounter(_dot, serial));
Mike Fiore 9:ff62b20f7000 78 addCommand(new CmdSaveSession(_dot, serial));
Mike Fiore 9:ff62b20f7000 79 addCommand(new CmdRestoreSession(_dot, serial));
Mike Fiore 1:e52ae6584f1c 80 addCommand(new CmdNetworkKey(_dot, serial));
Mike Fiore 1:e52ae6584f1c 81 addCommand(new CmdNetworkId(_dot, serial));
Mike Fiore 1:e52ae6584f1c 82
Mike Fiore 9:ff62b20f7000 83 addCommand(new CmdJoinDelay(_dot, serial));
Mike Fiore 1:e52ae6584f1c 84 addCommand(new CmdJoinRequest(_dot, serial));
Mike Fiore 1:e52ae6584f1c 85 addCommand(new CmdJoinRetries(_dot, serial));
Mike Fiore 4:666017851052 86 addCommand(new CmdJoinByteOrder(_dot, serial));
Mike Fiore 1:e52ae6584f1c 87 addCommand(new CmdNetworkJoinMode(_dot, serial));
Mike Fiore 9:ff62b20f7000 88 addCommand(new CmdPreserveSession(_dot, serial));
Mike Fiore 1:e52ae6584f1c 89 addCommand(new CmdNetworkJoinStatus(_dot, serial));
Mike Fiore 1:e52ae6584f1c 90 addCommand(new CmdNetworkLinkCheck(_dot, serial));
Mike Fiore 1:e52ae6584f1c 91 addCommand(new CmdLinkCheckCount(_dot, serial));
Mike Fiore 1:e52ae6584f1c 92 addCommand(new CmdLinkCheckThreshold(_dot, serial));
Mike Fiore 1:e52ae6584f1c 93 addCommand(new CmdEncryption(_dot, serial));
Mike Fiore 1:e52ae6584f1c 94
Mike Fiore 1:e52ae6584f1c 95 addCommand(new CmdRssi(_dot, serial));
Mike Fiore 1:e52ae6584f1c 96 addCommand(new CmdSnr(_dot, serial));
Mike Fiore 1:e52ae6584f1c 97 addCommand(new CmdDataPending(_dot, serial));
Mike Fiore 1:e52ae6584f1c 98
Mike Fiore 9:ff62b20f7000 99 addCommand(new CmdSessionDataRate(_dot, serial));
Mike Fiore 9:ff62b20f7000 100
Mike Fiore 1:e52ae6584f1c 101 addCommand(new CmdTxDataRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 102 addCommand(new CmdTxPower(_dot, serial));
Mike Fiore 9:ff62b20f7000 103 addCommand(new CmdAntennaGain(_dot, serial));
Mike Fiore 1:e52ae6584f1c 104 addCommand(new CmdTxFrequency(_dot, serial));
Mike Fiore 1:e52ae6584f1c 105 addCommand(new CmdTxInverted(_dot, serial));
Mike Fiore 1:e52ae6584f1c 106 addCommand(new CmdTxWait(_dot, serial));
Mike Fiore 1:e52ae6584f1c 107 addCommand(new CmdTxChannel(_dot, serial));
Mike Fiore 1:e52ae6584f1c 108 addCommand(new CmdTxNextMs(_dot, serial));
Mike Fiore 1:e52ae6584f1c 109 addCommand(new CmdTimeOnAir(_dot, serial));
Mike Fiore 1:e52ae6584f1c 110
Mike Fiore 9:ff62b20f7000 111 addCommand(new CmdRxDelay(_dot, serial));
Mike Fiore 1:e52ae6584f1c 112 addCommand(new CmdRxOutput(_dot, serial));
Mike Fiore 1:e52ae6584f1c 113 addCommand(new CmdRxInverted(_dot, serial));
Mike Fiore 1:e52ae6584f1c 114
Mike Fiore 1:e52ae6584f1c 115 addCommand(new CmdErrorCorrection(_dot, serial));
Mike Fiore 1:e52ae6584f1c 116 addCommand(new CmdCRC(_dot, serial));
Mike Fiore 1:e52ae6584f1c 117 addCommand(new CmdAdaptiveDataRate(_dot, serial));
Mike Fiore 1:e52ae6584f1c 118
Mike Fiore 1:e52ae6584f1c 119 addCommand(new CmdACKAttempts(_dot, serial));
Mike Fiore 9:ff62b20f7000 120 addCommand(new CmdRepeat(_dot, serial));
Mike Fiore 1:e52ae6584f1c 121
Mike Fiore 1:e52ae6584f1c 122 addCommand(new CmdSendString(_dot, serial));
Mike Fiore 1:e52ae6584f1c 123 addCommand(new CmdSendBinary(_dot, serial));
Mike Fiore 1:e52ae6584f1c 124 addCommand(new CmdReceiveOnce(_dot, serial));
Mike Fiore 1:e52ae6584f1c 125
Mike Fiore 9:ff62b20f7000 126 addCommand(new CmdDummy(_dot, "Serial Data Mode", "AT+SD", "Enter serial data mode, exit with '+++'"));
Mike Fiore 9:ff62b20f7000 127 addCommand(new CmdDummy(_dot, "Sleep Mode", "AT+SLEEP", "Enter sleep mode (0:deepsleep,1:sleep)"));
Mike Fiore 9:ff62b20f7000 128 addCommand(new CmdSerialClearOnError(_dot, serial));
Mike Fiore 4:666017851052 129 addCommand(new CmdWakeMode(_dot, serial));
Mike Fiore 4:666017851052 130 addCommand(new CmdWakeInterval(_dot, serial));
Mike Fiore 9:ff62b20f7000 131 addCommand(new CmdWakePin(_dot, serial));
Mike Fiore 4:666017851052 132 addCommand(new CmdWakeDelay(_dot, serial));
Mike Fiore 4:666017851052 133 addCommand(new CmdWakeTimeout(_dot, serial));
Mike Fiore 1:e52ae6584f1c 134 addCommand(new CmdPing(_dot, serial));
Mike Fiore 1:e52ae6584f1c 135 addCommand(new CmdLogLevel(_dot, serial));
Mike Fiore 9:ff62b20f7000 136
Mike Fiore 9:ff62b20f7000 137 addCommand(new CmdDummy(_dot, "***** Test Commands *****", "", ""));
Mike Fiore 9:ff62b20f7000 138 addCommand(new CmdRxDataRate(_dot, serial));
Mike Fiore 9:ff62b20f7000 139 addCommand(new CmdRxFrequency(_dot, serial));
Mike Fiore 9:ff62b20f7000 140 addCommand(new CmdReceiveContinuous(_dot, serial));
Mike Fiore 9:ff62b20f7000 141 addCommand(new CmdSendStringOnInterval(_dot, serial));
Mike Fiore 1:e52ae6584f1c 142 }
Mike Fiore 1:e52ae6584f1c 143
Mike Fiore 1:e52ae6584f1c 144 void CommandTerminal::printHelp() {
Mike Fiore 1:e52ae6584f1c 145 const char* name = NULL;
Mike Fiore 1:e52ae6584f1c 146 const char* text = NULL;
Mike Fiore 1:e52ae6584f1c 147 const char* desc = NULL;
Mike Fiore 1:e52ae6584f1c 148 const char* tab = "\t";
Mike Fiore 1:e52ae6584f1c 149
Mike Fiore 1:e52ae6584f1c 150 std::string header("Command");
Mike Fiore 1:e52ae6584f1c 151 header.append(tab);
Mike Fiore 1:e52ae6584f1c 152 header.append(tab);
Mike Fiore 1:e52ae6584f1c 153 header.append("Name");
Mike Fiore 1:e52ae6584f1c 154 header.append(tab);
Mike Fiore 1:e52ae6584f1c 155 header.append(tab);
Mike Fiore 1:e52ae6584f1c 156 header.append(tab);
Mike Fiore 1:e52ae6584f1c 157 header.append("Description");
Mike Fiore 1:e52ae6584f1c 158
Mike Fiore 1:e52ae6584f1c 159 write(newline);
Mike Fiore 1:e52ae6584f1c 160 write(header.c_str());
Mike Fiore 1:e52ae6584f1c 161 write(newline);
Mike Fiore 1:e52ae6584f1c 162 write(newline);
Mike Fiore 1:e52ae6584f1c 163 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end(); ++it) {
Mike Fiore 1:e52ae6584f1c 164 name = (*it)->name();
Mike Fiore 1:e52ae6584f1c 165 text = (*it)->text();
Mike Fiore 1:e52ae6584f1c 166 desc = (*it)->desc();
Mike Fiore 1:e52ae6584f1c 167 write(text);
Mike Fiore 1:e52ae6584f1c 168 if (strlen(text) < 8)
Mike Fiore 1:e52ae6584f1c 169 write(tab);
Mike Fiore 1:e52ae6584f1c 170 write(tab);
Mike Fiore 1:e52ae6584f1c 171 write(name);
Mike Fiore 1:e52ae6584f1c 172 if (strlen(name) < 8)
Mike Fiore 1:e52ae6584f1c 173 write(tab);
Mike Fiore 1:e52ae6584f1c 174 if (strlen(name) < 16)
Mike Fiore 1:e52ae6584f1c 175 write(tab);
Mike Fiore 1:e52ae6584f1c 176 write(tab);
Mike Fiore 1:e52ae6584f1c 177 write(desc);
Mike Fiore 1:e52ae6584f1c 178 write(newline);
Mike Fiore 1:e52ae6584f1c 179 }
Mike Fiore 1:e52ae6584f1c 180
Mike Fiore 1:e52ae6584f1c 181 write(newline);
Mike Fiore 1:e52ae6584f1c 182 }
Mike Fiore 1:e52ae6584f1c 183
Mike Fiore 1:e52ae6584f1c 184 bool CommandTerminal::writeable() {
Mike Fiore 1:e52ae6584f1c 185 return _serial.writeable();
Mike Fiore 1:e52ae6584f1c 186 }
Mike Fiore 1:e52ae6584f1c 187
Mike Fiore 1:e52ae6584f1c 188 bool CommandTerminal::readable() {
Mike Fiore 1:e52ae6584f1c 189 return _serial.readable();
Mike Fiore 1:e52ae6584f1c 190 }
Mike Fiore 1:e52ae6584f1c 191
Mike Fiore 1:e52ae6584f1c 192 char CommandTerminal::read() {
Mike Fiore 1:e52ae6584f1c 193 char ch;
Mike Fiore 1:e52ae6584f1c 194 _serial.read(&ch, 1);
Mike Fiore 1:e52ae6584f1c 195 return ch;
Mike Fiore 1:e52ae6584f1c 196 }
Mike Fiore 1:e52ae6584f1c 197
Mike Fiore 1:e52ae6584f1c 198 void CommandTerminal::write(const char* message) {
Mike Fiore 1:e52ae6584f1c 199 while (!writeable())
Mike Fiore 1:e52ae6584f1c 200 ;
Mike Fiore 1:e52ae6584f1c 201 _serial.write(message, strlen(message));
Mike Fiore 1:e52ae6584f1c 202 }
Mike Fiore 1:e52ae6584f1c 203
Mike Fiore 1:e52ae6584f1c 204 void CommandTerminal::writef(const char* format, ...) {
Mike Fiore 1:e52ae6584f1c 205 char buff[256];
Mike Fiore 1:e52ae6584f1c 206
Mike Fiore 1:e52ae6584f1c 207 va_list ap;
Mike Fiore 1:e52ae6584f1c 208 va_start(ap, format);
Mike Fiore 1:e52ae6584f1c 209 int size = vsnprintf(buff, 256, format, ap);
Mike Fiore 1:e52ae6584f1c 210 while (!writeable())
Mike Fiore 1:e52ae6584f1c 211 ;
Mike Fiore 1:e52ae6584f1c 212 _serial.write(buff, size);
Mike Fiore 1:e52ae6584f1c 213 va_end(ap);
Mike Fiore 1:e52ae6584f1c 214 }
Mike Fiore 1:e52ae6584f1c 215
Mike Fiore 9:ff62b20f7000 216 void CommandTerminal::serialLoop() {
Mike Fiore 1:e52ae6584f1c 217 Timer serial_read_timer;
Mike Fiore 1:e52ae6584f1c 218 std::vector<uint8_t> serial_buffer;
Mike Fiore 9:ff62b20f7000 219 std::vector<uint8_t> data;
Mike Fiore 9:ff62b20f7000 220 int timeout = 0;
Mike Fiore 1:e52ae6584f1c 221
Mike Fiore 9:ff62b20f7000 222 serial_read_timer.start();
Mike Fiore 1:e52ae6584f1c 223
Mike Fiore 9:ff62b20f7000 224 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
Mike Fiore 9:ff62b20f7000 225 _xbee_on_sleep = GPIO_PIN_SET;
Mike Fiore 1:e52ae6584f1c 226
Mike Fiore 9:ff62b20f7000 227 timeout = _dot->getWakeDelay();
Mike Fiore 1:e52ae6584f1c 228
Mike Fiore 9:ff62b20f7000 229 // wait for timeout or start of serial data
Mike Fiore 9:ff62b20f7000 230 while (!readable() && serial_read_timer.read_ms() < timeout && !_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 231 osDelay(2);
Mike Fiore 1:e52ae6584f1c 232 }
Mike Fiore 1:e52ae6584f1c 233 }
Mike Fiore 1:e52ae6584f1c 234
Mike Fiore 9:ff62b20f7000 235 if (readable() && !_serial.escaped()) {
Mike Fiore 6:e27eaad36a0c 236
Mike Fiore 6:e27eaad36a0c 237 serial_read_timer.reset();
Mike Fiore 6:e27eaad36a0c 238 timeout = _dot->getWakeTimeout();
Mike Fiore 9:ff62b20f7000 239
Mike Fiore 9:ff62b20f7000 240 while (serial_read_timer.read_ms() < timeout && serial_buffer.size() <= _dot->getMaxPacketLength()) {
Mike Fiore 9:ff62b20f7000 241 while (readable() && serial_buffer.size() < _dot->getMaxPacketLength()) {
Mike Fiore 1:e52ae6584f1c 242 serial_buffer.push_back(read());
Mike Fiore 1:e52ae6584f1c 243 serial_read_timer.reset();
Mike Fiore 9:ff62b20f7000 244
Mike Fiore 9:ff62b20f7000 245 if (_serial.escaped())
Mike Fiore 9:ff62b20f7000 246 break;
Mike Fiore 1:e52ae6584f1c 247 }
Mike Fiore 1:e52ae6584f1c 248 }
Mike Fiore 9:ff62b20f7000 249
Mike Fiore 1:e52ae6584f1c 250 serial_read_timer.stop(), serial_read_timer.reset();
Mike Fiore 1:e52ae6584f1c 251
Mike Fiore 1:e52ae6584f1c 252 if (!serial_buffer.empty()) {
Mike Fiore 9:ff62b20f7000 253 if (_dot->getStartUpMode() == mDot::SERIAL_MODE)
Mike Fiore 9:ff62b20f7000 254 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 9:ff62b20f7000 255
Mike Fiore 9:ff62b20f7000 256 // wait for any duty cycle limit to expire
Mike Fiore 9:ff62b20f7000 257 while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 258 osDelay(10);
Mike Fiore 9:ff62b20f7000 259 }
Mike Fiore 9:ff62b20f7000 260
Mike Fiore 1:e52ae6584f1c 261 if (!_dot->getIsTransmitting()) {
Mike Fiore 9:ff62b20f7000 262 logDebug("Received serial data, sending out radio.");
Mike Fiore 9:ff62b20f7000 263
Mike Fiore 9:ff62b20f7000 264 if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 265 logDebug("Send failed.");
Mike Fiore 9:ff62b20f7000 266 // If the data should be tossed after send failure, clear buffer
Mike Fiore 9:ff62b20f7000 267 if (_dot->getSerialClearOnError()) {
Mike Fiore 9:ff62b20f7000 268 serial_buffer.clear();
Mike Fiore 9:ff62b20f7000 269 }
Mike Fiore 9:ff62b20f7000 270 } else {
Mike Fiore 1:e52ae6584f1c 271
Mike Fiore 9:ff62b20f7000 272 // wait for send to finish
Mike Fiore 9:ff62b20f7000 273 while (_dot->getIsTransmitting() && !_serial.escaped())
Mike Fiore 9:ff62b20f7000 274 osDelay(10);
Mike Fiore 9:ff62b20f7000 275
Mike Fiore 9:ff62b20f7000 276 // call recv to wait for any packet before sending again
Mike Fiore 9:ff62b20f7000 277 if (!_serial.escaped())
Mike Fiore 9:ff62b20f7000 278 _dot->recv(data);
Mike Fiore 9:ff62b20f7000 279
Mike Fiore 9:ff62b20f7000 280 // Clear the serial buffer if send is success
Mike Fiore 9:ff62b20f7000 281 serial_buffer.clear();
Mike Fiore 9:ff62b20f7000 282 }
Mike Fiore 1:e52ae6584f1c 283 } else {
Mike Fiore 6:e27eaad36a0c 284 logDebug("Radio is busy, cannot send.\r\n");
Mike Fiore 9:ff62b20f7000 285 osDelay(10);
Mike Fiore 1:e52ae6584f1c 286 }
Mike Fiore 1:e52ae6584f1c 287
Mike Fiore 1:e52ae6584f1c 288 } else {
Mike Fiore 6:e27eaad36a0c 289 logDebug("No data received from serial to send.\r\n");
Mike Fiore 1:e52ae6584f1c 290 }
Mike Fiore 9:ff62b20f7000 291 }
Mike Fiore 9:ff62b20f7000 292
Mike Fiore 9:ff62b20f7000 293 if (!_serial.readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 294 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 9:ff62b20f7000 295 sleep(_sleep_standby);
Mike Fiore 1:e52ae6584f1c 296 }
Mike Fiore 9:ff62b20f7000 297
Mike Fiore 9:ff62b20f7000 298 if (_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 299 _serial.clearEscaped();
Mike Fiore 9:ff62b20f7000 300 _serial.rxClear();
Mike Fiore 9:ff62b20f7000 301 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 302 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 303 logDebug("Exit Serial Mode");
Mike Fiore 9:ff62b20f7000 304 write(done);
Mike Fiore 9:ff62b20f7000 305 return;
Mike Fiore 9:ff62b20f7000 306 }
Mike Fiore 9:ff62b20f7000 307
Mike Fiore 9:ff62b20f7000 308 if (!_dot->getNetworkJoinStatus()) {
Mike Fiore 9:ff62b20f7000 309 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 310 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 311 logDebug("Exit Serial Mode");
Mike Fiore 9:ff62b20f7000 312 write(no_carrier);
Mike Fiore 9:ff62b20f7000 313 return;
Mike Fiore 9:ff62b20f7000 314 }
Mike Fiore 1:e52ae6584f1c 315 }
Mike Fiore 1:e52ae6584f1c 316
Mike Fiore 1:e52ae6584f1c 317 bool CommandTerminal::autoJoinCheck() {
Mike Fiore 1:e52ae6584f1c 318
Mike Fiore 1:e52ae6584f1c 319 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 320 int sleep = 1000;
Mike Fiore 1:e52ae6584f1c 321 Timer tmr;
Mike Fiore 9:ff62b20f7000 322 tmr.start();
Mike Fiore 1:e52ae6584f1c 323 int cnt = 0;
Mike Fiore 1:e52ae6584f1c 324
Mike Fiore 1:e52ae6584f1c 325 while (!_dot->getNetworkJoinStatus()) {
Mike Fiore 1:e52ae6584f1c 326 write("\r\nJoining network... ");
Mike Fiore 1:e52ae6584f1c 327
Mike Fiore 9:ff62b20f7000 328 if (_dot->getNextTxMs() > 0) {
Mike Fiore 9:ff62b20f7000 329 int rand_time = rand() % 10000;
Mike Fiore 9:ff62b20f7000 330 writef("\r\nWaiting %lu s before next join attempt\r\n", (_dot->getNextTxMs() + rand_time) / 1000);
Mike Fiore 9:ff62b20f7000 331
Mike Fiore 9:ff62b20f7000 332 tmr.reset();
Mike Fiore 9:ff62b20f7000 333 while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 334 osDelay(2);
Mike Fiore 1:e52ae6584f1c 335 }
Mike Fiore 1:e52ae6584f1c 336
Mike Fiore 9:ff62b20f7000 337 tmr.reset();
Mike Fiore 9:ff62b20f7000 338 while (tmr.read_ms() < rand_time && !_serial.escaped())
Mike Fiore 9:ff62b20f7000 339 osDelay(10);
Mike Fiore 1:e52ae6584f1c 340 }
Mike Fiore 1:e52ae6584f1c 341
Mike Fiore 9:ff62b20f7000 342 if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) {
Mike Fiore 1:e52ae6584f1c 343 write("Network Joined\r\n");
Mike Fiore 1:e52ae6584f1c 344 write(done);
Mike Fiore 1:e52ae6584f1c 345 return false;
Mike Fiore 1:e52ae6584f1c 346 }
Mike Fiore 1:e52ae6584f1c 347
Mike Fiore 1:e52ae6584f1c 348 write("Network Join failed\r\n");
Mike Fiore 1:e52ae6584f1c 349 write(error);
Mike Fiore 1:e52ae6584f1c 350
Mike Fiore 9:ff62b20f7000 351 if (!_serial.escaped() && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
Mike Fiore 1:e52ae6584f1c 352 cnt = 0;
Mike Fiore 1:e52ae6584f1c 353
Mike Fiore 1:e52ae6584f1c 354 if (_dot->getFrequencyBand() == mDot::FB_915) {
Mike Fiore 1:e52ae6584f1c 355 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
Mike Fiore 9:ff62b20f7000 356 logWarning("Join retries exhausted, switching to sub band %u", band);
Mike Fiore 1:e52ae6584f1c 357 _dot->setFrequencySubBand(band);
Mike Fiore 1:e52ae6584f1c 358 }
Mike Fiore 1:e52ae6584f1c 359
Mike Fiore 1:e52ae6584f1c 360 if (sleep < 60 * 60 * 1000)
Mike Fiore 1:e52ae6584f1c 361 sleep *= 2;
Mike Fiore 1:e52ae6584f1c 362 }
Mike Fiore 1:e52ae6584f1c 363
Mike Fiore 1:e52ae6584f1c 364 tmr.reset();
Mike Fiore 9:ff62b20f7000 365 while (tmr.read_ms() < sleep && !_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 366 osDelay(10);
Mike Fiore 1:e52ae6584f1c 367 }
Mike Fiore 1:e52ae6584f1c 368
Mike Fiore 9:ff62b20f7000 369 if (_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 370 _serial.clearEscaped();
Mike Fiore 9:ff62b20f7000 371 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 372 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 373 write("Join Canceled\r\n");
Mike Fiore 9:ff62b20f7000 374 write(done);
Mike Fiore 9:ff62b20f7000 375 return true;
Mike Fiore 9:ff62b20f7000 376 }
Mike Fiore 1:e52ae6584f1c 377 }
Mike Fiore 1:e52ae6584f1c 378
Mike Fiore 1:e52ae6584f1c 379 return false;
Mike Fiore 1:e52ae6584f1c 380 }
Mike Fiore 1:e52ae6584f1c 381
Mike Fiore 1:e52ae6584f1c 382 void CommandTerminal::start() {
Mike Fiore 1:e52ae6584f1c 383
Mike Fiore 1:e52ae6584f1c 384 char ch;
Mike Fiore 1:e52ae6584f1c 385 bool running = true;
Mike Fiore 1:e52ae6584f1c 386 bool echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 387 std::string command;
Mike Fiore 4:666017851052 388 std::deque<std::string> history;
Mike Fiore 4:666017851052 389 int history_index = -1;
Mike Fiore 1:e52ae6584f1c 390 std::vector<std::string> args;
Mike Fiore 9:ff62b20f7000 391 bool join_canceled = false;
Mike Fiore 1:e52ae6584f1c 392
Mike Fiore 1:e52ae6584f1c 393 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
Mike Fiore 9:ff62b20f7000 394
Mike Fiore 9:ff62b20f7000 395 serial_data_mode = true;
Mike Fiore 9:ff62b20f7000 396 _mode = mDot::SERIAL_MODE;
Mike Fiore 1:e52ae6584f1c 397
Mike Fiore 1:e52ae6584f1c 398 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 399 char ch;
Mike Fiore 1:e52ae6584f1c 400
Mike Fiore 9:ff62b20f7000 401 if (!_dot->getStandbyFlag()) {
Mike Fiore 9:ff62b20f7000 402 // wake up from power-on/reset
Mike Fiore 9:ff62b20f7000 403
Mike Fiore 9:ff62b20f7000 404 int escape_timeout = 1000;
Mike Fiore 9:ff62b20f7000 405 Timer tmr;
Mike Fiore 9:ff62b20f7000 406 Timer escape_tmr;
Mike Fiore 1:e52ae6584f1c 407
Mike Fiore 9:ff62b20f7000 408 // wait one second for possible escape by user pressing '+' key
Mike Fiore 9:ff62b20f7000 409 tmr.reset();
Mike Fiore 9:ff62b20f7000 410 tmr.start();
Mike Fiore 9:ff62b20f7000 411 escape_tmr.reset();
Mike Fiore 9:ff62b20f7000 412 escape_tmr.start();
Mike Fiore 9:ff62b20f7000 413 while (tmr.read_ms() < escape_timeout) {
Mike Fiore 9:ff62b20f7000 414 if (_serial.readable()) {
Mike Fiore 9:ff62b20f7000 415 _serial.read(&ch, 1);
Mike Fiore 9:ff62b20f7000 416 escape_buffer += ch;
Mike Fiore 9:ff62b20f7000 417 }
Mike Fiore 1:e52ae6584f1c 418
Mike Fiore 9:ff62b20f7000 419 if (escape_buffer.find("+") != std::string::npos) {
Mike Fiore 9:ff62b20f7000 420 logInfo("Escape detected");
Mike Fiore 9:ff62b20f7000 421 join_canceled = true;
Mike Fiore 9:ff62b20f7000 422 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 423 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 424 command.clear();
Mike Fiore 9:ff62b20f7000 425 break;
Mike Fiore 9:ff62b20f7000 426 }
Mike Fiore 9:ff62b20f7000 427
Mike Fiore 9:ff62b20f7000 428 if (escape_tmr.read_ms() > escape_timeout)
Mike Fiore 9:ff62b20f7000 429 escape_buffer.clear();
Mike Fiore 9:ff62b20f7000 430
Mike Fiore 9:ff62b20f7000 431 osDelay(1);
Mike Fiore 1:e52ae6584f1c 432 }
Mike Fiore 1:e52ae6584f1c 433 }
Mike Fiore 1:e52ae6584f1c 434
Mike Fiore 9:ff62b20f7000 435 if (_mode == mDot::SERIAL_MODE && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
Mike Fiore 9:ff62b20f7000 436 if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 437 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 438 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 439
Mike Fiore 9:ff62b20f7000 440 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
Mike Fiore 9:ff62b20f7000 441 _serial.writef("Network Not Joined\r\n");
Mike Fiore 9:ff62b20f7000 442 _serial.writef(error);
Mike Fiore 9:ff62b20f7000 443 }
Mike Fiore 9:ff62b20f7000 444 }
Mike Fiore 1:e52ae6584f1c 445 }
Mike Fiore 1:e52ae6584f1c 446
Mike Fiore 9:ff62b20f7000 447 if (_dot->getJoinMode() == mDot::PEER_TO_PEER) {
Mike Fiore 9:ff62b20f7000 448 peer_to_peer = true;
Mike Fiore 9:ff62b20f7000 449 } else {
Mike Fiore 9:ff62b20f7000 450 peer_to_peer = false;
Mike Fiore 9:ff62b20f7000 451 }
Mike Fiore 9:ff62b20f7000 452
Mike Fiore 9:ff62b20f7000 453
Mike Fiore 1:e52ae6584f1c 454
Mike Fiore 1:e52ae6584f1c 455 //Run terminal session
Mike Fiore 1:e52ae6584f1c 456 while (running) {
Mike Fiore 9:ff62b20f7000 457
Mike Fiore 9:ff62b20f7000 458 // wait for input to reduce at command idle current
Mike Fiore 9:ff62b20f7000 459 while (!readable() || _mode == mDot::SERIAL_MODE) {
Mike Fiore 9:ff62b20f7000 460 if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) {
Mike Fiore 9:ff62b20f7000 461 join_canceled = autoJoinCheck();
Mike Fiore 9:ff62b20f7000 462 if (join_canceled)
Mike Fiore 9:ff62b20f7000 463 command.clear();
Mike Fiore 9:ff62b20f7000 464 }
Mike Fiore 1:e52ae6584f1c 465
Mike Fiore 9:ff62b20f7000 466 if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) {
Mike Fiore 9:ff62b20f7000 467 switch (_mode) {
Mike Fiore 9:ff62b20f7000 468 case mDot::SERIAL_MODE:
Mike Fiore 9:ff62b20f7000 469 // signal wakeup, read serial and output to radio
Mike Fiore 9:ff62b20f7000 470 serialLoop();
Mike Fiore 9:ff62b20f7000 471 continue;
Mike Fiore 9:ff62b20f7000 472 break;
Mike Fiore 9:ff62b20f7000 473 default:
Mike Fiore 9:ff62b20f7000 474 break;
Mike Fiore 9:ff62b20f7000 475 }
Mike Fiore 1:e52ae6584f1c 476 }
Mike Fiore 9:ff62b20f7000 477
Mike Fiore 9:ff62b20f7000 478 ch = '\0';
Mike Fiore 1:e52ae6584f1c 479
Mike Fiore 9:ff62b20f7000 480 wait(0.00001); // 10 us
Mike Fiore 9:ff62b20f7000 481 _serial.escaped();
Mike Fiore 9:ff62b20f7000 482 }
Mike Fiore 1:e52ae6584f1c 483
Mike Fiore 1:e52ae6584f1c 484 // read characters
Mike Fiore 1:e52ae6584f1c 485 if (readable()) {
Mike Fiore 1:e52ae6584f1c 486 ch = read();
Mike Fiore 1:e52ae6584f1c 487
Mike Fiore 4:666017851052 488 if (ch == '\b' || ch == 0x7f) {
Mike Fiore 1:e52ae6584f1c 489 if (!command.empty()) {
Mike Fiore 1:e52ae6584f1c 490 writef("\b \b");
Mike Fiore 1:e52ae6584f1c 491 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 492 }
Mike Fiore 1:e52ae6584f1c 493 continue;
Mike Fiore 4:666017851052 494 } else if (ch == 0x1b || ch == 0x09) {
Mike Fiore 4:666017851052 495 osDelay(20);
Mike Fiore 4:666017851052 496 // catch escape sequence, or tab
Mike Fiore 9:ff62b20f7000 497 char ch1 = 0x00, ch2 = 0x00;
Mike Fiore 4:666017851052 498
Mike Fiore 4:666017851052 499 if (readable()) {
Mike Fiore 4:666017851052 500 ch1 = read();
Mike Fiore 4:666017851052 501 if (readable())
Mike Fiore 4:666017851052 502 ch2 = read();
Mike Fiore 4:666017851052 503
Mike Fiore 4:666017851052 504 if (ch1 == 0x5b && ch2 == 0x41) {
Mike Fiore 4:666017851052 505 // up key
Mike Fiore 9:ff62b20f7000 506 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 507 writef("\b \b");
Mike Fiore 4:666017851052 508 }
Mike Fiore 4:666017851052 509 if (history.size() > 0) {
Mike Fiore 9:ff62b20f7000 510 if (++history_index >= int(history.size() - 1))
Mike Fiore 4:666017851052 511 history_index = history.size() - 1;
Mike Fiore 4:666017851052 512
Mike Fiore 4:666017851052 513 command = history[history_index];
Mike Fiore 4:666017851052 514 writef("%s", history[history_index].c_str());
Mike Fiore 4:666017851052 515 } else {
Mike Fiore 4:666017851052 516 command.clear();
Mike Fiore 4:666017851052 517 }
Mike Fiore 4:666017851052 518 } else if (ch1 == 0x5b && ch2 == 0x42) {
Mike Fiore 4:666017851052 519
Mike Fiore 4:666017851052 520 // down key
Mike Fiore 9:ff62b20f7000 521 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 522 writef("\b \b");
Mike Fiore 4:666017851052 523 }
Mike Fiore 4:666017851052 524
Mike Fiore 4:666017851052 525 if (--history_index < 0) {
Mike Fiore 4:666017851052 526 history_index = -1;
Mike Fiore 4:666017851052 527 command.clear();
Mike Fiore 4:666017851052 528 } else {
Mike Fiore 4:666017851052 529 command = history[history_index];
Mike Fiore 4:666017851052 530 writef("%s", history[history_index].c_str());
Mike Fiore 4:666017851052 531 }
Mike Fiore 4:666017851052 532 }
Mike Fiore 4:666017851052 533 }
Mike Fiore 9:ff62b20f7000 534 while (readable())
Mike Fiore 9:ff62b20f7000 535 read();
Mike Fiore 4:666017851052 536 continue;
Mike Fiore 1:e52ae6584f1c 537 } else {
Mike Fiore 1:e52ae6584f1c 538 command += ch;
Mike Fiore 1:e52ae6584f1c 539 }
Mike Fiore 1:e52ae6584f1c 540
Mike Fiore 1:e52ae6584f1c 541 // echo chars if enabled
Mike Fiore 1:e52ae6584f1c 542 if (echo && !(ch == '\r' || ch == '\n'))
Mike Fiore 1:e52ae6584f1c 543 writef("%c", ch);
Mike Fiore 1:e52ae6584f1c 544 }
Mike Fiore 1:e52ae6584f1c 545
Mike Fiore 1:e52ae6584f1c 546 // look for end of command line
Mike Fiore 1:e52ae6584f1c 547 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 548 // remove new line or cr character
Mike Fiore 1:e52ae6584f1c 549 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 550 write("\r"); // match standard modem output
Mike Fiore 1:e52ae6584f1c 551 write(newline);
Mike Fiore 1:e52ae6584f1c 552 } else {
Mike Fiore 1:e52ae6584f1c 553 continue;
Mike Fiore 1:e52ae6584f1c 554 }
Mike Fiore 1:e52ae6584f1c 555
Mike Fiore 1:e52ae6584f1c 556 // trim whitespace from command
Mike Fiore 1:e52ae6584f1c 557 mts::Text::trim(command, "\r\n\t ");
Mike Fiore 1:e52ae6584f1c 558
Mike Fiore 1:e52ae6584f1c 559 if (command.size() < 1) {
Mike Fiore 1:e52ae6584f1c 560 command.clear();
Mike Fiore 1:e52ae6584f1c 561 continue;
Mike Fiore 1:e52ae6584f1c 562 }
Mike Fiore 1:e52ae6584f1c 563
Mike Fiore 1:e52ae6584f1c 564 // parse command and args
Mike Fiore 1:e52ae6584f1c 565 args.clear();
Mike Fiore 1:e52ae6584f1c 566
Mike Fiore 1:e52ae6584f1c 567 // find first '=' character
Mike Fiore 1:e52ae6584f1c 568 size_t delim_index = command.find("=");
Mike Fiore 1:e52ae6584f1c 569 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 570 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 571 } else {
Mike Fiore 1:e52ae6584f1c 572 // find first ' ' character
Mike Fiore 1:e52ae6584f1c 573 delim_index = command.find(" ");
Mike Fiore 1:e52ae6584f1c 574 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 575 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 576 } else {
Mike Fiore 1:e52ae6584f1c 577 args.push_back(command);
Mike Fiore 1:e52ae6584f1c 578 }
Mike Fiore 1:e52ae6584f1c 579 }
Mike Fiore 1:e52ae6584f1c 580
Mike Fiore 1:e52ae6584f1c 581 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 582 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
Mike Fiore 1:e52ae6584f1c 583 args.insert(args.end(), params.begin(), params.end());
Mike Fiore 1:e52ae6584f1c 584 }
Mike Fiore 1:e52ae6584f1c 585
Mike Fiore 1:e52ae6584f1c 586 args[0] = mts::Text::toUpper(args[0]);
Mike Fiore 1:e52ae6584f1c 587
Mike Fiore 1:e52ae6584f1c 588 // print help
Mike Fiore 1:e52ae6584f1c 589 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
Mike Fiore 1:e52ae6584f1c 590 printHelp();
Mike Fiore 1:e52ae6584f1c 591 command.clear();
Mike Fiore 9:ff62b20f7000 592 } else if ((args[0].find("ATE?") == 0 && args[0].length() == 4) || (args[0].find("ATE") == 0 && args[0].length() == 3)) {
Mike Fiore 9:ff62b20f7000 593 writef("%d\r\n", _dot->getEcho());
Mike Fiore 9:ff62b20f7000 594 write(done);
Mike Fiore 1:e52ae6584f1c 595 } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 596 _dot->setEcho(false);
Mike Fiore 1:e52ae6584f1c 597 write(done);
Mike Fiore 1:e52ae6584f1c 598 echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 599 } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 600 _dot->setEcho(true);
Mike Fiore 1:e52ae6584f1c 601 write(done);
Mike Fiore 1:e52ae6584f1c 602 echo = _dot->getEcho();
Mike Fiore 9:ff62b20f7000 603 } else if ((args[0].find("ATV?") == 0 && args[0].length() == 4) || (args[0].find("ATV") == 0 && args[0].length() == 3)) {
Mike Fiore 9:ff62b20f7000 604 writef("%d\r\n", _dot->getVerbose());
Mike Fiore 9:ff62b20f7000 605 write(done);
Mike Fiore 1:e52ae6584f1c 606 } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 607 _dot->setVerbose(false);
Mike Fiore 1:e52ae6584f1c 608 write(done);
Mike Fiore 1:e52ae6584f1c 609 } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) {
Mike Fiore 1:e52ae6584f1c 610 _dot->setVerbose(true);
Mike Fiore 1:e52ae6584f1c 611 write(done);
Mike Fiore 9:ff62b20f7000 612 } else if ((args[0].find("AT&K?") == 0 && args[0].length() == 5) || (args[0].find("AT&K") == 0 && args[0].length() == 4)) {
Mike Fiore 9:ff62b20f7000 613 writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0));
Mike Fiore 9:ff62b20f7000 614 write(done);
Mike Fiore 9:ff62b20f7000 615 } else if (args[0].find("AT&K0") == 0 && args[0].length() == 5) {
Mike Fiore 9:ff62b20f7000 616 _dot->setFlowControl(false);
Mike Fiore 9:ff62b20f7000 617 write(done);
Mike Fiore 9:ff62b20f7000 618 } else if (args[0].find("AT&K3") == 0 && args[0].length() == 5) {
Mike Fiore 9:ff62b20f7000 619 _dot->setFlowControl(true);
Mike Fiore 9:ff62b20f7000 620 write(done);
Mike Fiore 1:e52ae6584f1c 621 } else if (args[0] == "AT+SD") {
Mike Fiore 9:ff62b20f7000 622 if (_dot->getNetworkJoinStatus()) {
Mike Fiore 9:ff62b20f7000 623 logDebug("Enter Serial Mode");
Mike Fiore 9:ff62b20f7000 624 write(connect);
Mike Fiore 9:ff62b20f7000 625 serial_data_mode = true;
Mike Fiore 9:ff62b20f7000 626 _mode = mDot::SERIAL_MODE;
Mike Fiore 9:ff62b20f7000 627 } else {
Mike Fiore 9:ff62b20f7000 628 logDebug("Network Not Joined");
Mike Fiore 9:ff62b20f7000 629 write("Network Not Joined\r\n");
Mike Fiore 9:ff62b20f7000 630 write(error);
Mike Fiore 9:ff62b20f7000 631 }
Mike Fiore 4:666017851052 632 } else if (args[0] == "AT+SLEEP") {
Mike Fiore 9:ff62b20f7000 633 if (args.size() > 2 && (args[1] != "?")) {
Mike Fiore 4:666017851052 634 write("Invalid argument\r\n");
Mike Fiore 4:666017851052 635 write(error);
Mike Fiore 4:666017851052 636 } else {
Mike Fiore 4:666017851052 637 if (args.size() > 1 && args[1] == "?") {
Mike Fiore 9:ff62b20f7000 638 write("(0:deepsleep,1:sleep)\r\n");
Mike Fiore 4:666017851052 639 write(done);
Mike Fiore 4:666017851052 640 } else {
Mike Fiore 4:666017851052 641 _sleep_standby = !(args.size() > 1 && args[1] == "1");
Mike Fiore 9:ff62b20f7000 642 write(done);
Mike Fiore 4:666017851052 643 this->sleep(_sleep_standby);
Mike Fiore 4:666017851052 644 wait(0.1);
Mike Fiore 4:666017851052 645 }
Mike Fiore 4:666017851052 646 }
Mike Fiore 1:e52ae6584f1c 647 } else {
Mike Fiore 1:e52ae6584f1c 648 bool found = false;
Mike Fiore 1:e52ae6584f1c 649 bool query = false;
Mike Fiore 1:e52ae6584f1c 650
Mike Fiore 1:e52ae6584f1c 651 std::string lookfor = args[0];
Mike Fiore 1:e52ae6584f1c 652
Mike Fiore 1:e52ae6584f1c 653 // per command help
Mike Fiore 1:e52ae6584f1c 654 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0))
Mike Fiore 1:e52ae6584f1c 655 lookfor = mts::Text::toUpper(args[1]);
Mike Fiore 1:e52ae6584f1c 656
Mike Fiore 1:e52ae6584f1c 657 // trim off any trailing '?' and mark as a query command
Mike Fiore 1:e52ae6584f1c 658 if (args[0].rfind("?") == args[0].length() - 1) {
Mike Fiore 1:e52ae6584f1c 659 query = true;
Mike Fiore 1:e52ae6584f1c 660 lookfor = args[0].substr(0, args[0].length() - 1);
Mike Fiore 1:e52ae6584f1c 661 }
Mike Fiore 1:e52ae6584f1c 662
Mike Fiore 1:e52ae6584f1c 663 // search for command
Mike Fiore 1:e52ae6584f1c 664 for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) {
Mike Fiore 1:e52ae6584f1c 665 Command* cmd = *it;
Mike Fiore 1:e52ae6584f1c 666
Mike Fiore 1:e52ae6584f1c 667 // match CMD or CMD? syntax if command is queryable
Mike Fiore 1:e52ae6584f1c 668 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) {
Mike Fiore 1:e52ae6584f1c 669 found = true;
Mike Fiore 1:e52ae6584f1c 670 if (args[0] == "HELP") {
Mike Fiore 1:e52ae6584f1c 671 writef("%s%s", cmd->help(), newline);
Mike Fiore 1:e52ae6584f1c 672 write(done);
Mike Fiore 1:e52ae6584f1c 673 }
Mike Fiore 1:e52ae6584f1c 674
Mike Fiore 1:e52ae6584f1c 675 else if (args.size() > 1 && args[1] == "?") {
Mike Fiore 1:e52ae6584f1c 676 writef("%s%s", cmd->usage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 677 write(done);
Mike Fiore 1:e52ae6584f1c 678 } else if (!cmd->verify(args)) {
Mike Fiore 1:e52ae6584f1c 679 writef("%s%s", cmd->errorMessage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 680 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 681 } else {
Mike Fiore 1:e52ae6584f1c 682 if (cmd->action(args) == 0) {
Mike Fiore 1:e52ae6584f1c 683 writef("%s", done);
Mike Fiore 1:e52ae6584f1c 684 } else {
Mike Fiore 1:e52ae6584f1c 685 writef("%s%s", cmd->errorMessage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 686 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 687 }
Mike Fiore 1:e52ae6584f1c 688 }
Mike Fiore 1:e52ae6584f1c 689 }
Mike Fiore 1:e52ae6584f1c 690 }
Mike Fiore 1:e52ae6584f1c 691
Mike Fiore 1:e52ae6584f1c 692 if (!found) {
Mike Fiore 1:e52ae6584f1c 693 writef("%s", command_error);
Mike Fiore 1:e52ae6584f1c 694 writef("%s", error);
Mike Fiore 1:e52ae6584f1c 695 }
Mike Fiore 1:e52ae6584f1c 696 }
Mike Fiore 1:e52ae6584f1c 697
Mike Fiore 4:666017851052 698 if (history.size() == 0 || history.front() != command)
Mike Fiore 4:666017851052 699 history.push_front(command);
Mike Fiore 4:666017851052 700 history_index = -1;
Mike Fiore 1:e52ae6584f1c 701 command.clear();
Mike Fiore 1:e52ae6584f1c 702
Mike Fiore 4:666017851052 703 while (history.size() > 10)
Mike Fiore 4:666017851052 704 history.pop_back();
Mike Fiore 1:e52ae6584f1c 705 }
Mike Fiore 1:e52ae6584f1c 706 }
Mike Fiore 1:e52ae6584f1c 707
Mike Fiore 1:e52ae6584f1c 708 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
Mike Fiore 2:e5eebd74d36d 709 if (format == mDot::HEXADECIMAL)
Mike Fiore 1:e52ae6584f1c 710 return mts::Text::bin2hexString(data);
Mike Fiore 2:e5eebd74d36d 711 else
Mike Fiore 2:e5eebd74d36d 712 return std::string(data.begin(), data.end());
Mike Fiore 1:e52ae6584f1c 713 }
Mike Fiore 1:e52ae6584f1c 714
Mike Fiore 1:e52ae6584f1c 715 void CommandTerminal::sleep(bool standby) {
Mike Fiore 1:e52ae6584f1c 716 _xbee_on_sleep = GPIO_PIN_RESET;
Mike Fiore 1:e52ae6584f1c 717
Mike Fiore 4:666017851052 718 _serial.rxClear();
Mike Fiore 4:666017851052 719 _serial.txClear();
Mike Fiore 1:e52ae6584f1c 720
Mike Fiore 4:666017851052 721 _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby);
Mike Fiore 1:e52ae6584f1c 722 }
Mike Fiore 1:e52ae6584f1c 723
Mike Fiore 1:e52ae6584f1c 724 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
Mike Fiore 1:e52ae6584f1c 725 Timer timer;
Mike Fiore 1:e52ae6584f1c 726
Mike Fiore 1:e52ae6584f1c 727 timer.start();
Mike Fiore 1:e52ae6584f1c 728 while (timer.read_ms() < timeout) {
Mike Fiore 1:e52ae6584f1c 729
Mike Fiore 1:e52ae6584f1c 730 if (dot != NULL) {
Mike Fiore 1:e52ae6584f1c 731 if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
Mike Fiore 1:e52ae6584f1c 732 return false;
Mike Fiore 1:e52ae6584f1c 733 }
Mike Fiore 1:e52ae6584f1c 734 }
Mike Fiore 1:e52ae6584f1c 735
Mike Fiore 9:ff62b20f7000 736 if (_serialp != NULL && _serialp->escaped()) {
Mike Fiore 9:ff62b20f7000 737 _serialp->clearEscaped();
Mike Fiore 9:ff62b20f7000 738 return true;
Mike Fiore 1:e52ae6584f1c 739 }
Mike Fiore 1:e52ae6584f1c 740
Mike Fiore 1:e52ae6584f1c 741 osDelay(10);
Mike Fiore 1:e52ae6584f1c 742 }
Mike Fiore 1:e52ae6584f1c 743
Mike Fiore 1:e52ae6584f1c 744 return false;
Mike Fiore 1:e52ae6584f1c 745 }
Mike Fiore 1:e52ae6584f1c 746
Mike Fiore 9:ff62b20f7000 747 void CommandTerminal::wakeup(void) {
Mike Fiore 9:ff62b20f7000 748 if (_dot->getWakePin() == XBEE_DIN) {
Mike Fiore 9:ff62b20f7000 749 _serial.reattach(XBEE_DOUT, XBEE_DIN);
Mike Fiore 9:ff62b20f7000 750 logInfo("Wakeup pin was serial input");
Mike Fiore 9:ff62b20f7000 751 }
Mike Fiore 9:ff62b20f7000 752 }
Mike Fiore 9:ff62b20f7000 753
Mike Fiore 9:ff62b20f7000 754 void CommandTerminal::RadioEvent::MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) {
Mike Fiore 1:e52ae6584f1c 755
Mike Fiore 9:ff62b20f7000 756 if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
Mike Fiore 9:ff62b20f7000 757 std::string msg = "OK";
Mike Fiore 9:ff62b20f7000 758 switch (info->Status) {
Mike Fiore 9:ff62b20f7000 759 case LORAMAC_EVENT_INFO_STATUS_ERROR:
Mike Fiore 9:ff62b20f7000 760 msg = "ERROR";
Mike Fiore 9:ff62b20f7000 761 break;
Mike Fiore 9:ff62b20f7000 762 case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
Mike Fiore 9:ff62b20f7000 763 msg = "TX_TIMEOUT";
Mike Fiore 9:ff62b20f7000 764 break;
Mike Fiore 9:ff62b20f7000 765 case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
Mike Fiore 9:ff62b20f7000 766 msg = "RX_TIMEOUT";
Mike Fiore 9:ff62b20f7000 767 break;
Mike Fiore 9:ff62b20f7000 768 case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
Mike Fiore 9:ff62b20f7000 769 msg = "RX_ERROR";
Mike Fiore 9:ff62b20f7000 770 break;
Mike Fiore 9:ff62b20f7000 771 case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
Mike Fiore 9:ff62b20f7000 772 msg = "JOIN_FAIL";
Mike Fiore 9:ff62b20f7000 773 break;
Mike Fiore 9:ff62b20f7000 774 case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
Mike Fiore 9:ff62b20f7000 775 msg = "DOWNLINK_FAIL";
Mike Fiore 9:ff62b20f7000 776 break;
Mike Fiore 9:ff62b20f7000 777 case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
Mike Fiore 9:ff62b20f7000 778 msg = "ADDRESS_FAIL";
Mike Fiore 9:ff62b20f7000 779 break;
Mike Fiore 9:ff62b20f7000 780 case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
Mike Fiore 9:ff62b20f7000 781 msg = "MIC_FAIL";
Mike Fiore 9:ff62b20f7000 782 break;
Mike Fiore 9:ff62b20f7000 783 default:
Mike Fiore 9:ff62b20f7000 784 break;
Mike Fiore 9:ff62b20f7000 785 }
Mike Fiore 9:ff62b20f7000 786 logTrace("Event: %s", msg.c_str());
Mike Fiore 9:ff62b20f7000 787
Mike Fiore 9:ff62b20f7000 788 logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
Mike Fiore 9:ff62b20f7000 789 flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
Mike Fiore 9:ff62b20f7000 790 logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
Mike Fiore 9:ff62b20f7000 791 info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
Mike Fiore 9:ff62b20f7000 792 info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
Mike Fiore 9:ff62b20f7000 793 }
Mike Fiore 9:ff62b20f7000 794
Mike Fiore 9:ff62b20f7000 795 if (flags->Bits.Rx) {
Mike Fiore 9:ff62b20f7000 796 if (serial_data_mode) {
Mike Fiore 9:ff62b20f7000 797 logDebug("Rx %d bytes", info->RxBufferSize);
Mike Fiore 9:ff62b20f7000 798 if (info->RxBufferSize > 0) {
Mike Fiore 9:ff62b20f7000 799 _serial.write((char*) info->RxBuffer, info->RxBufferSize);
Mike Fiore 9:ff62b20f7000 800 }
Mike Fiore 9:ff62b20f7000 801 }
Mike Fiore 9:ff62b20f7000 802 }
Mike Fiore 1:e52ae6584f1c 803 }
Mike Fiore 9:ff62b20f7000 804
Mike Fiore 9:ff62b20f7000 805 CommandTerminal::~CommandTerminal() {
Mike Fiore 9:ff62b20f7000 806 delete _events;
Mike Fiore 9:ff62b20f7000 807 }