AT command firmware for MultiTech Dot devices.

Fork of mDot_AT_firmware by MultiTech

Dot Library Not Included!

Because these example programs can be used for both mDot and xDot devices, the LoRa stack is not included. The libmDot library should be imported if building for mDot devices. The libxDot library should be imported if building for xDot devices. The AT firmware was last tested with mbed-os-5.4.7. Using a version past mbed-os-5.4.7 will cause the build to fail. The library used with the AT firmware has to match the mbed-os version.

Dot Library Version 3 Updates

Dot Library versions 3.x.x require a channel plan to be injected into the stack. The Dot-Examples and Dot-AT-Firmware do this by defining a macro called "CHANNEL_PLAN" that controls the channel plan that will be used in the examples. Available channel plans will be in the Dot Library repository in the plans folder.

Revision 20 and earlier of Dot-Examples and revision 15 and earlier of Dot-AT-Firmware should be used with Dot Library versions prior to 3.0.0.

Fota Library

Th Fota Library must be added to compile for mDot 3.1.0 with Fota support. Latest dev libraries and 3.2.0 release will include Fota with libmDot/libxDot.

AT Firmware Description

This AT Firmware is what ships on mDot and xDot devices. It provides an AT command interface for using the mDot or xDot for LoRa communication.

AT command documentation can be found on Multitech.com.

The firmware changelog can be found here. The library changelog can be found here.

Dot Libraries

Dot Library Limitations

The commit messages in libmDot-mbed5 and libmDot-dev-mbed5 specify the version of the Dot library the commit contains and the version of mbed-os it was compiled against. We recommend building your application with the version of mbed-os specified in the commit message of the version of the Dot library you're using. This will ensure that you don't run into any runtime issues caused by differences in the mbed-os versions.

Stable and development libraries are available for both mDot and xDot platforms. The library chosen must match the target platform. Compiling for the mDot platform with the xDot library or vice versa will not succeed.

mDot Library

Development library for mDot.

libmDot-dev

Stable library for mDot.

libmDot

xDot Library

Development library for xDot.

libxDot-dev

Stable library for xDot.

libxDot

Committer:
Mike Fiore
Date:
Mon Apr 04 09:00:31 2016 -0500
Revision:
9:ff62b20f7000
Parent:
6:e27eaad36a0c
Child:
11:05e0f30c03a6
update to version 1.0.8 of AT firmware

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 9:ff62b20f7000 803 delete[] info->RxBuffer;
Mike Fiore 9:ff62b20f7000 804 }
Mike Fiore 1:e52ae6584f1c 805 }
Mike Fiore 9:ff62b20f7000 806
Mike Fiore 9:ff62b20f7000 807 CommandTerminal::~CommandTerminal() {
Mike Fiore 9:ff62b20f7000 808 delete _events;
Mike Fiore 9:ff62b20f7000 809 }