![](/media/cache/group/MultiTech_Logo_Color_w_Tagline_PNG_1000px.png.50x50_q85.png)
AT command firmware for MultiTech Dot devices.
Fork of mDot_AT_firmware by
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.
Stable library for mDot.
xDot Library
Development library for xDot.
Stable library for xDot.
CommandTerminal/CommandTerminal.cpp@2:e5eebd74d36d, 2015-07-10 (annotated)
- Committer:
- Mike Fiore
- Date:
- Fri Jul 10 09:43:56 2015 -0500
- Revision:
- 2:e5eebd74d36d
- Parent:
- 1:e52ae6584f1c
- Child:
- 4:666017851052
update from rev 6d77074fdfa315ba86bedecc44515b11bfa6e9a0 - add support for commas in payloads of +SEND and +SENDI
Who changed what in which revision?
User | Revision | Line number | New 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 |
1:e52ae6584f1c | 4 | #include <cstdarg> |
Mike Fiore |
1:e52ae6584f1c | 5 | |
Mike Fiore |
1:e52ae6584f1c | 6 | extern "C" { |
Mike Fiore |
1:e52ae6584f1c | 7 | #include "wakeup.h" |
Mike Fiore |
1:e52ae6584f1c | 8 | extern void pin_function(PinName pin, int data); |
Mike Fiore |
1:e52ae6584f1c | 9 | } |
Mike Fiore |
1:e52ae6584f1c | 10 | |
Mike Fiore |
1:e52ae6584f1c | 11 | const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n"; |
Mike Fiore |
1:e52ae6584f1c | 12 | const char CommandTerminal::helpline[] = "Enter '?' for help\r\n"; |
Mike Fiore |
1:e52ae6584f1c | 13 | |
Mike Fiore |
1:e52ae6584f1c | 14 | const char CommandTerminal::newline[] = "\r\n"; |
Mike Fiore |
1:e52ae6584f1c | 15 | |
Mike Fiore |
1:e52ae6584f1c | 16 | // Command error text... |
Mike Fiore |
1:e52ae6584f1c | 17 | const char CommandTerminal::command_error[] = "Command not found!\r\n"; |
Mike Fiore |
1:e52ae6584f1c | 18 | |
Mike Fiore |
1:e52ae6584f1c | 19 | // Response texts... |
Mike Fiore |
1:e52ae6584f1c | 20 | const char CommandTerminal::help[] = "\r\nHelp\r\n"; |
Mike Fiore |
1:e52ae6584f1c | 21 | const char CommandTerminal::cmd_error[] = "Invalid command\r\n"; |
Mike Fiore |
1:e52ae6584f1c | 22 | const char CommandTerminal::done[] = "\r\nOK\r\n"; |
Mike Fiore |
1:e52ae6584f1c | 23 | const char CommandTerminal::error[] = "\r\nERROR\r\n"; |
Mike Fiore |
1:e52ae6584f1c | 24 | |
Mike Fiore |
1:e52ae6584f1c | 25 | // Escape sequence... |
Mike Fiore |
1:e52ae6584f1c | 26 | const char CommandTerminal::escape_sequence[] = "+++"; |
Mike Fiore |
1:e52ae6584f1c | 27 | |
Mike Fiore |
1:e52ae6584f1c | 28 | mts::MTSSerial* CommandTerminal::_serialp = NULL; |
Mike Fiore |
1:e52ae6584f1c | 29 | |
Mike Fiore |
1:e52ae6584f1c | 30 | void CommandTerminal::addCommand(Command* cmd) { |
Mike Fiore |
1:e52ae6584f1c | 31 | _commands.push_back(cmd); |
Mike Fiore |
1:e52ae6584f1c | 32 | } |
Mike Fiore |
1:e52ae6584f1c | 33 | |
Mike Fiore |
1:e52ae6584f1c | 34 | CommandTerminal::CommandTerminal(mts::MTSSerial& serial, mDot* dot) |
Mike Fiore |
1:e52ae6584f1c | 35 | : |
Mike Fiore |
1:e52ae6584f1c | 36 | _serial(serial), |
Mike Fiore |
1:e52ae6584f1c | 37 | _dot(dot), |
Mike Fiore |
1:e52ae6584f1c | 38 | _mode(mDot::COMMAND_MODE), |
Mike Fiore |
1:e52ae6584f1c | 39 | _sleep_standby(false), |
Mike Fiore |
1:e52ae6584f1c | 40 | _xbee_on_sleep(XBEE_ON_SLEEP), |
Mike Fiore |
1:e52ae6584f1c | 41 | _serial_up(false) { |
Mike Fiore |
1:e52ae6584f1c | 42 | |
Mike Fiore |
1:e52ae6584f1c | 43 | _serialp = &serial; |
Mike Fiore |
1:e52ae6584f1c | 44 | |
Mike Fiore |
1:e52ae6584f1c | 45 | wakeup_init(_dot->getSerialWakeInterval()); |
Mike Fiore |
1:e52ae6584f1c | 46 | |
Mike Fiore |
1:e52ae6584f1c | 47 | addCommand(new CmdAttention(_dot)); |
Mike Fiore |
1:e52ae6584f1c | 48 | addCommand(new CmdIdentification(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 49 | addCommand(new CmdResetCpu(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 50 | addCommand(new CmdDummy(_dot, "Enable/Disable Echo", "ATE0/1", "ATE0: disable, ATE1: enable")); |
Mike Fiore |
1:e52ae6584f1c | 51 | addCommand(new CmdDummy(_dot, "Enable/Disable Verbose", "ATV0/1", "ATV0: disable, ATV1: enable")); |
Mike Fiore |
1:e52ae6584f1c | 52 | |
Mike Fiore |
1:e52ae6584f1c | 53 | addCommand(new CmdFactoryDefault(_dot)); |
Mike Fiore |
1:e52ae6584f1c | 54 | addCommand(new CmdSaveConfig(_dot)); |
Mike Fiore |
1:e52ae6584f1c | 55 | addCommand(new CmdDisplayConfig(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 56 | addCommand(new CmdDisplayStats(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 57 | addCommand(new CmdSerialBaudRate(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 58 | addCommand(new CmdDebugBaudRate(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 59 | addCommand(new CmdStartUpMode(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 60 | |
Mike Fiore |
1:e52ae6584f1c | 61 | addCommand(new CmdFrequencyBand(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 62 | addCommand(new CmdFrequencySubBand(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 63 | addCommand(new CmdPublicNetwork(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 64 | addCommand(new CmdDeviceId(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 65 | |
Mike Fiore |
1:e52ae6584f1c | 66 | addCommand(new CmdNetworkAddress(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 67 | addCommand(new CmdNetworkSessionKey(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 68 | addCommand(new CmdDataSessionKey(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 69 | addCommand(new CmdNetworkKey(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 70 | addCommand(new CmdNetworkId(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 71 | |
Mike Fiore |
1:e52ae6584f1c | 72 | addCommand(new CmdJoinRequest(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 73 | addCommand(new CmdJoinRetries(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 74 | addCommand(new CmdNetworkJoinMode(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 75 | addCommand(new CmdNetworkJoinStatus(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 76 | addCommand(new CmdNetworkLinkCheck(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 77 | addCommand(new CmdLinkCheckCount(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 78 | addCommand(new CmdLinkCheckThreshold(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 79 | addCommand(new CmdEncryption(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 80 | |
Mike Fiore |
1:e52ae6584f1c | 81 | addCommand(new CmdRssi(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 82 | addCommand(new CmdSnr(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 83 | addCommand(new CmdDataPending(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 84 | |
Mike Fiore |
1:e52ae6584f1c | 85 | addCommand(new CmdTxDataRate(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 86 | addCommand(new CmdTxPower(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 87 | addCommand(new CmdTxFrequency(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 88 | addCommand(new CmdTxInverted(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 89 | addCommand(new CmdTxWait(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 90 | addCommand(new CmdTxChannel(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 91 | addCommand(new CmdTxNextMs(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 92 | addCommand(new CmdTimeOnAir(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 93 | |
Mike Fiore |
1:e52ae6584f1c | 94 | addCommand(new CmdRxDataRate(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 95 | addCommand(new CmdRxFrequency(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 96 | addCommand(new CmdRxOutput(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 97 | addCommand(new CmdRxInverted(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 98 | |
Mike Fiore |
1:e52ae6584f1c | 99 | addCommand(new CmdErrorCorrection(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 100 | addCommand(new CmdCRC(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 101 | addCommand(new CmdAdaptiveDataRate(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 102 | |
Mike Fiore |
1:e52ae6584f1c | 103 | addCommand(new CmdACKAttempts(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 104 | |
Mike Fiore |
1:e52ae6584f1c | 105 | addCommand(new CmdSendString(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 106 | addCommand(new CmdSendStringHighBW(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 107 | addCommand(new CmdSendBinary(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 108 | addCommand(new CmdSendStringOnInterval(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 109 | addCommand(new CmdReceiveOnce(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 110 | addCommand(new CmdReceiveContinuous(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 111 | |
Mike Fiore |
1:e52ae6584f1c | 112 | addCommand(new CmdDummy(_dot, "Serial Data Mode", "AT+SD", "Reads serial data and sends Lora packets (escape sequence: +++)")); |
Mike Fiore |
1:e52ae6584f1c | 113 | addCommand(new CmdSerialWakeInterval(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 114 | addCommand(new CmdSerialWakeDelay(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 115 | addCommand(new CmdSerialReceiveTimeout(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 116 | addCommand(new CmdPing(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 117 | addCommand(new CmdLogLevel(_dot, serial)); |
Mike Fiore |
1:e52ae6584f1c | 118 | } |
Mike Fiore |
1:e52ae6584f1c | 119 | |
Mike Fiore |
1:e52ae6584f1c | 120 | void CommandTerminal::printHelp() { |
Mike Fiore |
1:e52ae6584f1c | 121 | const char* name = NULL; |
Mike Fiore |
1:e52ae6584f1c | 122 | const char* text = NULL; |
Mike Fiore |
1:e52ae6584f1c | 123 | const char* desc = NULL; |
Mike Fiore |
1:e52ae6584f1c | 124 | const char* tab = "\t"; |
Mike Fiore |
1:e52ae6584f1c | 125 | |
Mike Fiore |
1:e52ae6584f1c | 126 | std::string header("Command"); |
Mike Fiore |
1:e52ae6584f1c | 127 | header.append(tab); |
Mike Fiore |
1:e52ae6584f1c | 128 | header.append(tab); |
Mike Fiore |
1:e52ae6584f1c | 129 | header.append("Name"); |
Mike Fiore |
1:e52ae6584f1c | 130 | header.append(tab); |
Mike Fiore |
1:e52ae6584f1c | 131 | header.append(tab); |
Mike Fiore |
1:e52ae6584f1c | 132 | header.append(tab); |
Mike Fiore |
1:e52ae6584f1c | 133 | header.append("Description"); |
Mike Fiore |
1:e52ae6584f1c | 134 | |
Mike Fiore |
1:e52ae6584f1c | 135 | write(newline); |
Mike Fiore |
1:e52ae6584f1c | 136 | write(header.c_str()); |
Mike Fiore |
1:e52ae6584f1c | 137 | write(newline); |
Mike Fiore |
1:e52ae6584f1c | 138 | write(newline); |
Mike Fiore |
1:e52ae6584f1c | 139 | for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end(); ++it) { |
Mike Fiore |
1:e52ae6584f1c | 140 | name = (*it)->name(); |
Mike Fiore |
1:e52ae6584f1c | 141 | text = (*it)->text(); |
Mike Fiore |
1:e52ae6584f1c | 142 | desc = (*it)->desc(); |
Mike Fiore |
1:e52ae6584f1c | 143 | write(text); |
Mike Fiore |
1:e52ae6584f1c | 144 | if (strlen(text) < 8) |
Mike Fiore |
1:e52ae6584f1c | 145 | write(tab); |
Mike Fiore |
1:e52ae6584f1c | 146 | write(tab); |
Mike Fiore |
1:e52ae6584f1c | 147 | write(name); |
Mike Fiore |
1:e52ae6584f1c | 148 | if (strlen(name) < 8) |
Mike Fiore |
1:e52ae6584f1c | 149 | write(tab); |
Mike Fiore |
1:e52ae6584f1c | 150 | if (strlen(name) < 16) |
Mike Fiore |
1:e52ae6584f1c | 151 | write(tab); |
Mike Fiore |
1:e52ae6584f1c | 152 | write(tab); |
Mike Fiore |
1:e52ae6584f1c | 153 | write(desc); |
Mike Fiore |
1:e52ae6584f1c | 154 | write(newline); |
Mike Fiore |
1:e52ae6584f1c | 155 | } |
Mike Fiore |
1:e52ae6584f1c | 156 | |
Mike Fiore |
1:e52ae6584f1c | 157 | write(newline); |
Mike Fiore |
1:e52ae6584f1c | 158 | } |
Mike Fiore |
1:e52ae6584f1c | 159 | |
Mike Fiore |
1:e52ae6584f1c | 160 | bool CommandTerminal::writeable() { |
Mike Fiore |
1:e52ae6584f1c | 161 | return _serial.writeable(); |
Mike Fiore |
1:e52ae6584f1c | 162 | } |
Mike Fiore |
1:e52ae6584f1c | 163 | |
Mike Fiore |
1:e52ae6584f1c | 164 | bool CommandTerminal::readable() { |
Mike Fiore |
1:e52ae6584f1c | 165 | return _serial.readable(); |
Mike Fiore |
1:e52ae6584f1c | 166 | } |
Mike Fiore |
1:e52ae6584f1c | 167 | |
Mike Fiore |
1:e52ae6584f1c | 168 | char CommandTerminal::read() { |
Mike Fiore |
1:e52ae6584f1c | 169 | char ch; |
Mike Fiore |
1:e52ae6584f1c | 170 | _serial.read(&ch, 1); |
Mike Fiore |
1:e52ae6584f1c | 171 | return ch; |
Mike Fiore |
1:e52ae6584f1c | 172 | } |
Mike Fiore |
1:e52ae6584f1c | 173 | |
Mike Fiore |
1:e52ae6584f1c | 174 | void CommandTerminal::write(const char* message) { |
Mike Fiore |
1:e52ae6584f1c | 175 | while (!writeable()) |
Mike Fiore |
1:e52ae6584f1c | 176 | ; |
Mike Fiore |
1:e52ae6584f1c | 177 | _serial.write(message, strlen(message)); |
Mike Fiore |
1:e52ae6584f1c | 178 | } |
Mike Fiore |
1:e52ae6584f1c | 179 | |
Mike Fiore |
1:e52ae6584f1c | 180 | void CommandTerminal::writef(const char* format, ...) { |
Mike Fiore |
1:e52ae6584f1c | 181 | char buff[256]; |
Mike Fiore |
1:e52ae6584f1c | 182 | |
Mike Fiore |
1:e52ae6584f1c | 183 | va_list ap; |
Mike Fiore |
1:e52ae6584f1c | 184 | va_start(ap, format); |
Mike Fiore |
1:e52ae6584f1c | 185 | int size = vsnprintf(buff, 256, format, ap); |
Mike Fiore |
1:e52ae6584f1c | 186 | while (!writeable()) |
Mike Fiore |
1:e52ae6584f1c | 187 | ; |
Mike Fiore |
1:e52ae6584f1c | 188 | _serial.write(buff, size); |
Mike Fiore |
1:e52ae6584f1c | 189 | va_end(ap); |
Mike Fiore |
1:e52ae6584f1c | 190 | } |
Mike Fiore |
1:e52ae6584f1c | 191 | |
Mike Fiore |
1:e52ae6584f1c | 192 | void CommandTerminal::serial_loop() { |
Mike Fiore |
1:e52ae6584f1c | 193 | Timer serial_read_timer; |
Mike Fiore |
1:e52ae6584f1c | 194 | std::vector<uint8_t> serial_buffer; |
Mike Fiore |
1:e52ae6584f1c | 195 | std::string escape_buffer; |
Mike Fiore |
1:e52ae6584f1c | 196 | Timer escape_timer; |
Mike Fiore |
1:e52ae6584f1c | 197 | int escape_delay = 100; |
Mike Fiore |
1:e52ae6584f1c | 198 | uint8_t max_send_size; |
Mike Fiore |
1:e52ae6584f1c | 199 | |
Mike Fiore |
1:e52ae6584f1c | 200 | _serial_up = true; |
Mike Fiore |
1:e52ae6584f1c | 201 | _xbee_on_sleep = GPIO_PIN_SET; |
Mike Fiore |
1:e52ae6584f1c | 202 | |
Mike Fiore |
1:e52ae6584f1c | 203 | if (_dot->getFrequencyBand() == mDot::FB_915) |
Mike Fiore |
1:e52ae6584f1c | 204 | max_send_size = mDot::MaxLengths_915[_dot->getTxDataRate()]; |
Mike Fiore |
1:e52ae6584f1c | 205 | else |
Mike Fiore |
1:e52ae6584f1c | 206 | max_send_size = mDot::MaxLengths_868[_dot->getTxDataRate()]; |
Mike Fiore |
1:e52ae6584f1c | 207 | |
Mike Fiore |
1:e52ae6584f1c | 208 | DEBUG_PRINTF("Awake\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 209 | wakeup(_sleep_standby); |
Mike Fiore |
1:e52ae6584f1c | 210 | |
Mike Fiore |
1:e52ae6584f1c | 211 | char ch; |
Mike Fiore |
1:e52ae6584f1c | 212 | |
Mike Fiore |
1:e52ae6584f1c | 213 | if (readable()) { |
Mike Fiore |
1:e52ae6584f1c | 214 | ch = read(); |
Mike Fiore |
1:e52ae6584f1c | 215 | serial_buffer.push_back(ch); |
Mike Fiore |
1:e52ae6584f1c | 216 | |
Mike Fiore |
1:e52ae6584f1c | 217 | if (escape_timer.read_ms() > escape_delay && ch == '+') { |
Mike Fiore |
1:e52ae6584f1c | 218 | escape_buffer += ch; |
Mike Fiore |
1:e52ae6584f1c | 219 | escape_timer.reset(); |
Mike Fiore |
1:e52ae6584f1c | 220 | } else { |
Mike Fiore |
1:e52ae6584f1c | 221 | _serial_up = true; |
Mike Fiore |
1:e52ae6584f1c | 222 | escape_buffer.clear(); |
Mike Fiore |
1:e52ae6584f1c | 223 | } |
Mike Fiore |
1:e52ae6584f1c | 224 | |
Mike Fiore |
1:e52ae6584f1c | 225 | if (escape_buffer.length() == 3 && escape_buffer.find(escape_sequence) == 0) { |
Mike Fiore |
1:e52ae6584f1c | 226 | _mode = mDot::COMMAND_MODE; |
Mike Fiore |
1:e52ae6584f1c | 227 | DEBUG_PRINTF("Exit serial mode\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 228 | escape_timer.stop(); |
Mike Fiore |
1:e52ae6584f1c | 229 | escape_buffer.clear(); |
Mike Fiore |
1:e52ae6584f1c | 230 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 231 | return; |
Mike Fiore |
1:e52ae6584f1c | 232 | } |
Mike Fiore |
1:e52ae6584f1c | 233 | } |
Mike Fiore |
1:e52ae6584f1c | 234 | |
Mike Fiore |
1:e52ae6584f1c | 235 | if (_serial_up) { |
Mike Fiore |
1:e52ae6584f1c | 236 | osDelay(_dot->getSerialWakeDelay()); |
Mike Fiore |
1:e52ae6584f1c | 237 | |
Mike Fiore |
1:e52ae6584f1c | 238 | serial_read_timer.start(); |
Mike Fiore |
1:e52ae6584f1c | 239 | while (_serial_up && serial_read_timer.read_ms() < _dot->getSerialReceiveTimeout()) { |
Mike Fiore |
1:e52ae6584f1c | 240 | while (readable() && serial_buffer.size() < max_send_size) { |
Mike Fiore |
1:e52ae6584f1c | 241 | serial_buffer.push_back(read()); |
Mike Fiore |
1:e52ae6584f1c | 242 | serial_read_timer.reset(); |
Mike Fiore |
1:e52ae6584f1c | 243 | } |
Mike Fiore |
1:e52ae6584f1c | 244 | } |
Mike Fiore |
1:e52ae6584f1c | 245 | serial_read_timer.stop(), serial_read_timer.reset(); |
Mike Fiore |
1:e52ae6584f1c | 246 | |
Mike Fiore |
1:e52ae6584f1c | 247 | if (!serial_buffer.empty()) { |
Mike Fiore |
1:e52ae6584f1c | 248 | _serial_up = false; |
Mike Fiore |
1:e52ae6584f1c | 249 | _xbee_on_sleep = GPIO_PIN_RESET; |
Mike Fiore |
1:e52ae6584f1c | 250 | if (!_dot->getIsTransmitting()) { |
Mike Fiore |
1:e52ae6584f1c | 251 | std::vector<uint8_t> recv_buffer; |
Mike Fiore |
1:e52ae6584f1c | 252 | DEBUG_PRINTF("Received serial data, sending out radio.\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 253 | |
Mike Fiore |
1:e52ae6584f1c | 254 | if (!_dot->send(serial_buffer)) |
Mike Fiore |
1:e52ae6584f1c | 255 | DEBUG_PRINTF("Send failed.\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 256 | if (_dot->recv(recv_buffer)) |
Mike Fiore |
1:e52ae6584f1c | 257 | _serial.writef("%s\r\n", formatPacketData(recv_buffer, _dot->getRxOutput()).c_str()); |
Mike Fiore |
1:e52ae6584f1c | 258 | } else { |
Mike Fiore |
1:e52ae6584f1c | 259 | DEBUG_PRINTF("Radio is busy, cannot send.\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 260 | } |
Mike Fiore |
1:e52ae6584f1c | 261 | |
Mike Fiore |
1:e52ae6584f1c | 262 | serial_buffer.clear(); |
Mike Fiore |
1:e52ae6584f1c | 263 | } else { |
Mike Fiore |
1:e52ae6584f1c | 264 | DEBUG_PRINTF("No data received from serial to send.\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 265 | } |
Mike Fiore |
1:e52ae6584f1c | 266 | _serial_up = false; |
Mike Fiore |
1:e52ae6584f1c | 267 | } |
Mike Fiore |
1:e52ae6584f1c | 268 | sleep(_sleep_standby); |
Mike Fiore |
1:e52ae6584f1c | 269 | } |
Mike Fiore |
1:e52ae6584f1c | 270 | |
Mike Fiore |
1:e52ae6584f1c | 271 | bool CommandTerminal::autoJoinCheck() { |
Mike Fiore |
1:e52ae6584f1c | 272 | |
Mike Fiore |
1:e52ae6584f1c | 273 | std::string escape_buffer; |
Mike Fiore |
1:e52ae6584f1c | 274 | char ch; |
Mike Fiore |
1:e52ae6584f1c | 275 | int sleep = 1000; |
Mike Fiore |
1:e52ae6584f1c | 276 | int escape_timeout = 1000; |
Mike Fiore |
1:e52ae6584f1c | 277 | Timer tmr; |
Mike Fiore |
1:e52ae6584f1c | 278 | Timer escape_tmr; |
Mike Fiore |
1:e52ae6584f1c | 279 | int cnt = 0; |
Mike Fiore |
1:e52ae6584f1c | 280 | |
Mike Fiore |
1:e52ae6584f1c | 281 | while (!_dot->getNetworkJoinStatus()) { |
Mike Fiore |
1:e52ae6584f1c | 282 | wakeup(_sleep_standby); |
Mike Fiore |
1:e52ae6584f1c | 283 | write("\r\nJoining network... "); |
Mike Fiore |
1:e52ae6584f1c | 284 | |
Mike Fiore |
1:e52ae6584f1c | 285 | // wait one second for possible escape |
Mike Fiore |
1:e52ae6584f1c | 286 | tmr.reset(); |
Mike Fiore |
1:e52ae6584f1c | 287 | tmr.start(); |
Mike Fiore |
1:e52ae6584f1c | 288 | escape_tmr.reset(); |
Mike Fiore |
1:e52ae6584f1c | 289 | escape_tmr.start(); |
Mike Fiore |
1:e52ae6584f1c | 290 | while (tmr.read_ms() < 1000) { |
Mike Fiore |
1:e52ae6584f1c | 291 | if (_serial.readable()) { |
Mike Fiore |
1:e52ae6584f1c | 292 | _serial.read(&ch, 1); |
Mike Fiore |
1:e52ae6584f1c | 293 | escape_buffer += ch; |
Mike Fiore |
1:e52ae6584f1c | 294 | } |
Mike Fiore |
1:e52ae6584f1c | 295 | |
Mike Fiore |
1:e52ae6584f1c | 296 | if (escape_buffer.find(escape_sequence) != std::string::npos) { |
Mike Fiore |
1:e52ae6584f1c | 297 | _mode = mDot::COMMAND_MODE; |
Mike Fiore |
1:e52ae6584f1c | 298 | write("Join Canceled\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 299 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 300 | return true; |
Mike Fiore |
1:e52ae6584f1c | 301 | } |
Mike Fiore |
1:e52ae6584f1c | 302 | |
Mike Fiore |
1:e52ae6584f1c | 303 | if (escape_tmr.read_ms() > escape_timeout) |
Mike Fiore |
1:e52ae6584f1c | 304 | escape_buffer.clear(); |
Mike Fiore |
1:e52ae6584f1c | 305 | } |
Mike Fiore |
1:e52ae6584f1c | 306 | |
Mike Fiore |
1:e52ae6584f1c | 307 | if (_dot->joinNetworkOnce() == mDot::MDOT_OK) { |
Mike Fiore |
1:e52ae6584f1c | 308 | write("Network Joined\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 309 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 310 | return false; |
Mike Fiore |
1:e52ae6584f1c | 311 | } |
Mike Fiore |
1:e52ae6584f1c | 312 | |
Mike Fiore |
1:e52ae6584f1c | 313 | write("Network Join failed\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 314 | write(error); |
Mike Fiore |
1:e52ae6584f1c | 315 | |
Mike Fiore |
1:e52ae6584f1c | 316 | if (cnt++ > _dot->getJoinRetries()) { |
Mike Fiore |
1:e52ae6584f1c | 317 | cnt = 0; |
Mike Fiore |
1:e52ae6584f1c | 318 | |
Mike Fiore |
1:e52ae6584f1c | 319 | if (_dot->getFrequencyBand() == mDot::FB_915) { |
Mike Fiore |
1:e52ae6584f1c | 320 | uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1; |
Mike Fiore |
1:e52ae6584f1c | 321 | DEBUG_PRINTF("Join retries exhausted, switching to sub band %u\r\n", band); |
Mike Fiore |
1:e52ae6584f1c | 322 | _dot->setFrequencySubBand(band); |
Mike Fiore |
1:e52ae6584f1c | 323 | } |
Mike Fiore |
1:e52ae6584f1c | 324 | |
Mike Fiore |
1:e52ae6584f1c | 325 | if (sleep < 60 * 60 * 1000) |
Mike Fiore |
1:e52ae6584f1c | 326 | sleep *= 2; |
Mike Fiore |
1:e52ae6584f1c | 327 | } |
Mike Fiore |
1:e52ae6584f1c | 328 | |
Mike Fiore |
1:e52ae6584f1c | 329 | tmr.reset(); |
Mike Fiore |
1:e52ae6584f1c | 330 | tmr.start(); |
Mike Fiore |
1:e52ae6584f1c | 331 | escape_tmr.reset(); |
Mike Fiore |
1:e52ae6584f1c | 332 | escape_tmr.start(); |
Mike Fiore |
1:e52ae6584f1c | 333 | while (tmr.read_ms() < sleep) { |
Mike Fiore |
1:e52ae6584f1c | 334 | if (_serial.readable()) { |
Mike Fiore |
1:e52ae6584f1c | 335 | _serial.read(&ch, 1); |
Mike Fiore |
1:e52ae6584f1c | 336 | escape_buffer += ch; |
Mike Fiore |
1:e52ae6584f1c | 337 | } |
Mike Fiore |
1:e52ae6584f1c | 338 | |
Mike Fiore |
1:e52ae6584f1c | 339 | if (escape_buffer.find(escape_sequence) != std::string::npos) { |
Mike Fiore |
1:e52ae6584f1c | 340 | _mode = mDot::COMMAND_MODE; |
Mike Fiore |
1:e52ae6584f1c | 341 | return true; |
Mike Fiore |
1:e52ae6584f1c | 342 | } |
Mike Fiore |
1:e52ae6584f1c | 343 | |
Mike Fiore |
1:e52ae6584f1c | 344 | if (escape_tmr.read_ms() > escape_timeout) |
Mike Fiore |
1:e52ae6584f1c | 345 | escape_buffer.clear(); |
Mike Fiore |
1:e52ae6584f1c | 346 | } |
Mike Fiore |
1:e52ae6584f1c | 347 | |
Mike Fiore |
1:e52ae6584f1c | 348 | } |
Mike Fiore |
1:e52ae6584f1c | 349 | |
Mike Fiore |
1:e52ae6584f1c | 350 | return false; |
Mike Fiore |
1:e52ae6584f1c | 351 | } |
Mike Fiore |
1:e52ae6584f1c | 352 | |
Mike Fiore |
1:e52ae6584f1c | 353 | void CommandTerminal::start() { |
Mike Fiore |
1:e52ae6584f1c | 354 | |
Mike Fiore |
1:e52ae6584f1c | 355 | _dot->resetNetworkSession(); |
Mike Fiore |
1:e52ae6584f1c | 356 | |
Mike Fiore |
1:e52ae6584f1c | 357 | char ch; |
Mike Fiore |
1:e52ae6584f1c | 358 | bool running = true; |
Mike Fiore |
1:e52ae6584f1c | 359 | bool echo = _dot->getEcho(); |
Mike Fiore |
1:e52ae6584f1c | 360 | std::string command; |
Mike Fiore |
1:e52ae6584f1c | 361 | std::vector<std::string> args; |
Mike Fiore |
1:e52ae6584f1c | 362 | |
Mike Fiore |
1:e52ae6584f1c | 363 | if (_dot->getStartUpMode() == mDot::SERIAL_MODE) { |
Mike Fiore |
1:e52ae6584f1c | 364 | command = "AT+SD\n"; |
Mike Fiore |
1:e52ae6584f1c | 365 | |
Mike Fiore |
1:e52ae6584f1c | 366 | std::string escape_buffer; |
Mike Fiore |
1:e52ae6584f1c | 367 | char ch; |
Mike Fiore |
1:e52ae6584f1c | 368 | |
Mike Fiore |
1:e52ae6584f1c | 369 | int escape_timeout = 1000; |
Mike Fiore |
1:e52ae6584f1c | 370 | Timer tmr; |
Mike Fiore |
1:e52ae6584f1c | 371 | Timer escape_tmr; |
Mike Fiore |
1:e52ae6584f1c | 372 | |
Mike Fiore |
1:e52ae6584f1c | 373 | // wait one second for possible escape |
Mike Fiore |
1:e52ae6584f1c | 374 | tmr.reset(); |
Mike Fiore |
1:e52ae6584f1c | 375 | tmr.start(); |
Mike Fiore |
1:e52ae6584f1c | 376 | escape_tmr.reset(); |
Mike Fiore |
1:e52ae6584f1c | 377 | escape_tmr.start(); |
Mike Fiore |
1:e52ae6584f1c | 378 | while (tmr.read_ms() < escape_timeout) { |
Mike Fiore |
1:e52ae6584f1c | 379 | if (_serial.readable()) { |
Mike Fiore |
1:e52ae6584f1c | 380 | _serial.read(&ch, 1); |
Mike Fiore |
1:e52ae6584f1c | 381 | escape_buffer += ch; |
Mike Fiore |
1:e52ae6584f1c | 382 | } |
Mike Fiore |
1:e52ae6584f1c | 383 | |
Mike Fiore |
1:e52ae6584f1c | 384 | if (escape_buffer.find(escape_sequence) != std::string::npos) { |
Mike Fiore |
1:e52ae6584f1c | 385 | _mode = mDot::COMMAND_MODE; |
Mike Fiore |
1:e52ae6584f1c | 386 | command.clear(); |
Mike Fiore |
1:e52ae6584f1c | 387 | break; |
Mike Fiore |
1:e52ae6584f1c | 388 | } |
Mike Fiore |
1:e52ae6584f1c | 389 | |
Mike Fiore |
1:e52ae6584f1c | 390 | if (escape_tmr.read_ms() > escape_timeout) |
Mike Fiore |
1:e52ae6584f1c | 391 | escape_buffer.clear(); |
Mike Fiore |
1:e52ae6584f1c | 392 | |
Mike Fiore |
1:e52ae6584f1c | 393 | osDelay(1); |
Mike Fiore |
1:e52ae6584f1c | 394 | } |
Mike Fiore |
1:e52ae6584f1c | 395 | |
Mike Fiore |
1:e52ae6584f1c | 396 | } |
Mike Fiore |
1:e52ae6584f1c | 397 | |
Mike Fiore |
1:e52ae6584f1c | 398 | bool join_canceled = false; |
Mike Fiore |
1:e52ae6584f1c | 399 | |
Mike Fiore |
1:e52ae6584f1c | 400 | //Run terminal session |
Mike Fiore |
1:e52ae6584f1c | 401 | while (running) { |
Mike Fiore |
1:e52ae6584f1c | 402 | if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) { |
Mike Fiore |
1:e52ae6584f1c | 403 | join_canceled = autoJoinCheck(); |
Mike Fiore |
1:e52ae6584f1c | 404 | if (join_canceled) |
Mike Fiore |
1:e52ae6584f1c | 405 | command.clear(); |
Mike Fiore |
1:e52ae6584f1c | 406 | } |
Mike Fiore |
1:e52ae6584f1c | 407 | |
Mike Fiore |
1:e52ae6584f1c | 408 | if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) { |
Mike Fiore |
1:e52ae6584f1c | 409 | switch (_mode) { |
Mike Fiore |
1:e52ae6584f1c | 410 | case mDot::SERIAL_MODE: |
Mike Fiore |
1:e52ae6584f1c | 411 | // signal wakeup, read serial and output to radio |
Mike Fiore |
1:e52ae6584f1c | 412 | serial_loop(); |
Mike Fiore |
1:e52ae6584f1c | 413 | continue; |
Mike Fiore |
1:e52ae6584f1c | 414 | break; |
Mike Fiore |
1:e52ae6584f1c | 415 | default: |
Mike Fiore |
1:e52ae6584f1c | 416 | break; |
Mike Fiore |
1:e52ae6584f1c | 417 | } |
Mike Fiore |
1:e52ae6584f1c | 418 | } |
Mike Fiore |
1:e52ae6584f1c | 419 | |
Mike Fiore |
1:e52ae6584f1c | 420 | ch = '\0'; |
Mike Fiore |
1:e52ae6584f1c | 421 | |
Mike Fiore |
1:e52ae6584f1c | 422 | // read characters |
Mike Fiore |
1:e52ae6584f1c | 423 | if (readable()) { |
Mike Fiore |
1:e52ae6584f1c | 424 | ch = read(); |
Mike Fiore |
1:e52ae6584f1c | 425 | |
Mike Fiore |
1:e52ae6584f1c | 426 | if (ch == '\b') { |
Mike Fiore |
1:e52ae6584f1c | 427 | if (!command.empty()) { |
Mike Fiore |
1:e52ae6584f1c | 428 | writef("\b \b"); |
Mike Fiore |
1:e52ae6584f1c | 429 | command.erase(command.size() - 1); |
Mike Fiore |
1:e52ae6584f1c | 430 | } |
Mike Fiore |
1:e52ae6584f1c | 431 | continue; |
Mike Fiore |
1:e52ae6584f1c | 432 | } else { |
Mike Fiore |
1:e52ae6584f1c | 433 | command += ch; |
Mike Fiore |
1:e52ae6584f1c | 434 | } |
Mike Fiore |
1:e52ae6584f1c | 435 | |
Mike Fiore |
1:e52ae6584f1c | 436 | // echo chars if enabled |
Mike Fiore |
1:e52ae6584f1c | 437 | if (echo && !(ch == '\r' || ch == '\n')) |
Mike Fiore |
1:e52ae6584f1c | 438 | writef("%c", ch); |
Mike Fiore |
1:e52ae6584f1c | 439 | } |
Mike Fiore |
1:e52ae6584f1c | 440 | |
Mike Fiore |
1:e52ae6584f1c | 441 | // look for end of command line |
Mike Fiore |
1:e52ae6584f1c | 442 | if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) { |
Mike Fiore |
1:e52ae6584f1c | 443 | // remove new line or cr character |
Mike Fiore |
1:e52ae6584f1c | 444 | command.erase(command.size() - 1); |
Mike Fiore |
1:e52ae6584f1c | 445 | write("\r"); // match standard modem output |
Mike Fiore |
1:e52ae6584f1c | 446 | write(newline); |
Mike Fiore |
1:e52ae6584f1c | 447 | } else { |
Mike Fiore |
1:e52ae6584f1c | 448 | continue; |
Mike Fiore |
1:e52ae6584f1c | 449 | } |
Mike Fiore |
1:e52ae6584f1c | 450 | |
Mike Fiore |
1:e52ae6584f1c | 451 | // trim whitespace from command |
Mike Fiore |
1:e52ae6584f1c | 452 | mts::Text::trim(command, "\r\n\t "); |
Mike Fiore |
1:e52ae6584f1c | 453 | |
Mike Fiore |
1:e52ae6584f1c | 454 | if (command.size() < 1) { |
Mike Fiore |
1:e52ae6584f1c | 455 | command.clear(); |
Mike Fiore |
1:e52ae6584f1c | 456 | continue; |
Mike Fiore |
1:e52ae6584f1c | 457 | } |
Mike Fiore |
1:e52ae6584f1c | 458 | |
Mike Fiore |
1:e52ae6584f1c | 459 | // parse command and args |
Mike Fiore |
1:e52ae6584f1c | 460 | args.clear(); |
Mike Fiore |
1:e52ae6584f1c | 461 | |
Mike Fiore |
1:e52ae6584f1c | 462 | // find first '=' character |
Mike Fiore |
1:e52ae6584f1c | 463 | size_t delim_index = command.find("="); |
Mike Fiore |
1:e52ae6584f1c | 464 | if (delim_index != std::string::npos) { |
Mike Fiore |
1:e52ae6584f1c | 465 | args.push_back(command.substr(0, delim_index)); |
Mike Fiore |
1:e52ae6584f1c | 466 | } else { |
Mike Fiore |
1:e52ae6584f1c | 467 | // find first ' ' character |
Mike Fiore |
1:e52ae6584f1c | 468 | delim_index = command.find(" "); |
Mike Fiore |
1:e52ae6584f1c | 469 | if (delim_index != std::string::npos) { |
Mike Fiore |
1:e52ae6584f1c | 470 | args.push_back(command.substr(0, delim_index)); |
Mike Fiore |
1:e52ae6584f1c | 471 | } else { |
Mike Fiore |
1:e52ae6584f1c | 472 | args.push_back(command); |
Mike Fiore |
1:e52ae6584f1c | 473 | } |
Mike Fiore |
1:e52ae6584f1c | 474 | } |
Mike Fiore |
1:e52ae6584f1c | 475 | |
Mike Fiore |
1:e52ae6584f1c | 476 | if (delim_index != std::string::npos) { |
Mike Fiore |
1:e52ae6584f1c | 477 | std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ","); |
Mike Fiore |
1:e52ae6584f1c | 478 | args.insert(args.end(), params.begin(), params.end()); |
Mike Fiore |
1:e52ae6584f1c | 479 | } |
Mike Fiore |
1:e52ae6584f1c | 480 | |
Mike Fiore |
1:e52ae6584f1c | 481 | args[0] = mts::Text::toUpper(args[0]); |
Mike Fiore |
1:e52ae6584f1c | 482 | |
Mike Fiore |
1:e52ae6584f1c | 483 | // print help |
Mike Fiore |
1:e52ae6584f1c | 484 | if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) { |
Mike Fiore |
1:e52ae6584f1c | 485 | printHelp(); |
Mike Fiore |
1:e52ae6584f1c | 486 | command.clear(); |
Mike Fiore |
1:e52ae6584f1c | 487 | } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) { |
Mike Fiore |
1:e52ae6584f1c | 488 | _dot->setEcho(false); |
Mike Fiore |
1:e52ae6584f1c | 489 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 490 | echo = _dot->getEcho(); |
Mike Fiore |
1:e52ae6584f1c | 491 | } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) { |
Mike Fiore |
1:e52ae6584f1c | 492 | _dot->setEcho(true); |
Mike Fiore |
1:e52ae6584f1c | 493 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 494 | echo = _dot->getEcho(); |
Mike Fiore |
1:e52ae6584f1c | 495 | } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) { |
Mike Fiore |
1:e52ae6584f1c | 496 | _dot->setVerbose(false); |
Mike Fiore |
1:e52ae6584f1c | 497 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 498 | } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) { |
Mike Fiore |
1:e52ae6584f1c | 499 | _dot->setVerbose(true); |
Mike Fiore |
1:e52ae6584f1c | 500 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 501 | } else if (args[0] == "AT+SD") { |
Mike Fiore |
1:e52ae6584f1c | 502 | DEBUG_PRINTF("Enter Serial Mode\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 503 | _mode = mDot::SERIAL_MODE; |
Mike Fiore |
1:e52ae6584f1c | 504 | } else { |
Mike Fiore |
1:e52ae6584f1c | 505 | bool found = false; |
Mike Fiore |
1:e52ae6584f1c | 506 | bool query = false; |
Mike Fiore |
1:e52ae6584f1c | 507 | |
Mike Fiore |
1:e52ae6584f1c | 508 | std::string lookfor = args[0]; |
Mike Fiore |
1:e52ae6584f1c | 509 | |
Mike Fiore |
1:e52ae6584f1c | 510 | // per command help |
Mike Fiore |
1:e52ae6584f1c | 511 | if ((args[0].find("?") == 0 || args[0].find("HELP") == 0)) |
Mike Fiore |
1:e52ae6584f1c | 512 | lookfor = mts::Text::toUpper(args[1]); |
Mike Fiore |
1:e52ae6584f1c | 513 | |
Mike Fiore |
1:e52ae6584f1c | 514 | // trim off any trailing '?' and mark as a query command |
Mike Fiore |
1:e52ae6584f1c | 515 | if (args[0].rfind("?") == args[0].length() - 1) { |
Mike Fiore |
1:e52ae6584f1c | 516 | query = true; |
Mike Fiore |
1:e52ae6584f1c | 517 | lookfor = args[0].substr(0, args[0].length() - 1); |
Mike Fiore |
1:e52ae6584f1c | 518 | } |
Mike Fiore |
1:e52ae6584f1c | 519 | |
Mike Fiore |
1:e52ae6584f1c | 520 | // search for command |
Mike Fiore |
1:e52ae6584f1c | 521 | for (std::vector<Command*>::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) { |
Mike Fiore |
1:e52ae6584f1c | 522 | Command* cmd = *it; |
Mike Fiore |
1:e52ae6584f1c | 523 | |
Mike Fiore |
1:e52ae6584f1c | 524 | // match CMD or CMD? syntax if command is queryable |
Mike Fiore |
1:e52ae6584f1c | 525 | if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) { |
Mike Fiore |
1:e52ae6584f1c | 526 | found = true; |
Mike Fiore |
1:e52ae6584f1c | 527 | if (args[0] == "HELP") { |
Mike Fiore |
1:e52ae6584f1c | 528 | writef("%s%s", cmd->help(), newline); |
Mike Fiore |
1:e52ae6584f1c | 529 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 530 | } |
Mike Fiore |
1:e52ae6584f1c | 531 | |
Mike Fiore |
1:e52ae6584f1c | 532 | else if (args.size() > 1 && args[1] == "?") { |
Mike Fiore |
1:e52ae6584f1c | 533 | writef("%s%s", cmd->usage().c_str(), newline); |
Mike Fiore |
1:e52ae6584f1c | 534 | write(done); |
Mike Fiore |
1:e52ae6584f1c | 535 | } else if (!cmd->verify(args)) { |
Mike Fiore |
1:e52ae6584f1c | 536 | writef("%s%s", cmd->errorMessage().c_str(), newline); |
Mike Fiore |
1:e52ae6584f1c | 537 | writef("%s", error); |
Mike Fiore |
1:e52ae6584f1c | 538 | } else { |
Mike Fiore |
1:e52ae6584f1c | 539 | if (cmd->action(args) == 0) { |
Mike Fiore |
1:e52ae6584f1c | 540 | writef("%s", done); |
Mike Fiore |
1:e52ae6584f1c | 541 | } else { |
Mike Fiore |
1:e52ae6584f1c | 542 | writef("%s%s", cmd->errorMessage().c_str(), newline); |
Mike Fiore |
1:e52ae6584f1c | 543 | writef("%s", error); |
Mike Fiore |
1:e52ae6584f1c | 544 | } |
Mike Fiore |
1:e52ae6584f1c | 545 | } |
Mike Fiore |
1:e52ae6584f1c | 546 | } |
Mike Fiore |
1:e52ae6584f1c | 547 | } |
Mike Fiore |
1:e52ae6584f1c | 548 | |
Mike Fiore |
1:e52ae6584f1c | 549 | if (!found) { |
Mike Fiore |
1:e52ae6584f1c | 550 | writef("%s", command_error); |
Mike Fiore |
1:e52ae6584f1c | 551 | writef("%s", error); |
Mike Fiore |
1:e52ae6584f1c | 552 | } |
Mike Fiore |
1:e52ae6584f1c | 553 | } |
Mike Fiore |
1:e52ae6584f1c | 554 | |
Mike Fiore |
1:e52ae6584f1c | 555 | command.clear(); |
Mike Fiore |
1:e52ae6584f1c | 556 | |
Mike Fiore |
1:e52ae6584f1c | 557 | } |
Mike Fiore |
1:e52ae6584f1c | 558 | } |
Mike Fiore |
1:e52ae6584f1c | 559 | |
Mike Fiore |
1:e52ae6584f1c | 560 | std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) { |
Mike Fiore |
2:e5eebd74d36d | 561 | if (format == mDot::HEXADECIMAL) |
Mike Fiore |
1:e52ae6584f1c | 562 | return mts::Text::bin2hexString(data); |
Mike Fiore |
2:e5eebd74d36d | 563 | else |
Mike Fiore |
2:e5eebd74d36d | 564 | return std::string(data.begin(), data.end()); |
Mike Fiore |
1:e52ae6584f1c | 565 | } |
Mike Fiore |
1:e52ae6584f1c | 566 | |
Mike Fiore |
1:e52ae6584f1c | 567 | void CommandTerminal::sleep(bool standby) { |
Mike Fiore |
1:e52ae6584f1c | 568 | _serial_up = false; |
Mike Fiore |
1:e52ae6584f1c | 569 | _xbee_on_sleep = GPIO_PIN_RESET; |
Mike Fiore |
1:e52ae6584f1c | 570 | |
Mike Fiore |
1:e52ae6584f1c | 571 | HAL_PWREx_EnableMainRegulatorLowVoltage(); |
Mike Fiore |
1:e52ae6584f1c | 572 | HAL_PWREx_EnableFlashPowerDown(); |
Mike Fiore |
1:e52ae6584f1c | 573 | HAL_PWREx_EnableLowRegulatorLowVoltage(); |
Mike Fiore |
1:e52ae6584f1c | 574 | |
Mike Fiore |
1:e52ae6584f1c | 575 | DEBUG_PRINTF("Sleep\r\n"); |
Mike Fiore |
1:e52ae6584f1c | 576 | _dot->sleep(); |
Mike Fiore |
1:e52ae6584f1c | 577 | |
Mike Fiore |
1:e52ae6584f1c | 578 | if (standby) { |
Mike Fiore |
1:e52ae6584f1c | 579 | |
Mike Fiore |
1:e52ae6584f1c | 580 | DEBUG_PRINTF("RECORD UPLINK: %lu\r\n", _dot->getUpLinkCounter()); |
Mike Fiore |
1:e52ae6584f1c | 581 | |
Mike Fiore |
1:e52ae6584f1c | 582 | RTC_WriteBackupRegister(RTC_BKP_DR0, _dot->getUpLinkCounter()); |
Mike Fiore |
1:e52ae6584f1c | 583 | |
Mike Fiore |
1:e52ae6584f1c | 584 | HAL_PWR_EnableBkUpAccess(); |
Mike Fiore |
1:e52ae6584f1c | 585 | |
Mike Fiore |
1:e52ae6584f1c | 586 | HAL_EnableDBGStandbyMode(); |
Mike Fiore |
1:e52ae6584f1c | 587 | |
Mike Fiore |
1:e52ae6584f1c | 588 | HAL_PWR_DisableWakeUpPin (PWR_WAKEUP_PIN1); |
Mike Fiore |
1:e52ae6584f1c | 589 | |
Mike Fiore |
1:e52ae6584f1c | 590 | __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // InterruptIn wakeon_serial(XBEE_DIN); |
Mike Fiore |
1:e52ae6584f1c | 591 | // Application is reloaded after wake-up from standby |
Mike Fiore |
1:e52ae6584f1c | 592 | HAL_PWR_EnterSTANDBYMode (); |
Mike Fiore |
1:e52ae6584f1c | 593 | |
Mike Fiore |
1:e52ae6584f1c | 594 | } else { |
Mike Fiore |
1:e52ae6584f1c | 595 | pin_function(PA_0, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 596 | pin_function(PA_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 597 | // pin_function(PA_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 598 | // pin_function(PA_3, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 599 | pin_function(PA_4, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 600 | pin_function(PA_5, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 601 | pin_function(PA_6, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 602 | pin_function(PA_7, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 603 | // pin_function(PA_8, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 604 | // pin_function(PA_9, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 605 | // pin_function(PA_10, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 606 | pin_function(PA_11, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 607 | pin_function(PA_12, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 608 | pin_function(PA_15, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 609 | |
Mike Fiore |
1:e52ae6584f1c | 610 | pin_function(PB_0, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 611 | pin_function(PB_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 612 | pin_function(PB_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 613 | |
Mike Fiore |
1:e52ae6584f1c | 614 | pin_function(PC_1, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 615 | pin_function(PC_4, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 616 | pin_function(PC_5, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 617 | pin_function(PC_9, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 618 | // pin_function(PC_13, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 619 | |
Mike Fiore |
1:e52ae6584f1c | 620 | pin_function(PD_2, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); |
Mike Fiore |
1:e52ae6584f1c | 621 | |
Mike Fiore |
1:e52ae6584f1c | 622 | HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); |
Mike Fiore |
1:e52ae6584f1c | 623 | } |
Mike Fiore |
1:e52ae6584f1c | 624 | |
Mike Fiore |
1:e52ae6584f1c | 625 | wakeup_clear(); |
Mike Fiore |
1:e52ae6584f1c | 626 | EXTI->PR = (1 << 22); |
Mike Fiore |
1:e52ae6584f1c | 627 | |
Mike Fiore |
1:e52ae6584f1c | 628 | // After wake-up from STOP reconfigure the PLL |
Mike Fiore |
1:e52ae6584f1c | 629 | SetSysClock(); |
Mike Fiore |
1:e52ae6584f1c | 630 | } |
Mike Fiore |
1:e52ae6584f1c | 631 | |
Mike Fiore |
1:e52ae6584f1c | 632 | bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) { |
Mike Fiore |
1:e52ae6584f1c | 633 | Timer timer; |
Mike Fiore |
1:e52ae6584f1c | 634 | Timer escape_timer; |
Mike Fiore |
1:e52ae6584f1c | 635 | std::string escape_buffer; |
Mike Fiore |
1:e52ae6584f1c | 636 | int escape_timeout = 1000; |
Mike Fiore |
1:e52ae6584f1c | 637 | |
Mike Fiore |
1:e52ae6584f1c | 638 | timer.start(); |
Mike Fiore |
1:e52ae6584f1c | 639 | while (timer.read_ms() < timeout) { |
Mike Fiore |
1:e52ae6584f1c | 640 | |
Mike Fiore |
1:e52ae6584f1c | 641 | if (dot != NULL) { |
Mike Fiore |
1:e52ae6584f1c | 642 | if (wait == WAIT_SEND && (!dot->getIsTransmitting())) { |
Mike Fiore |
1:e52ae6584f1c | 643 | return false; |
Mike Fiore |
1:e52ae6584f1c | 644 | } |
Mike Fiore |
1:e52ae6584f1c | 645 | } |
Mike Fiore |
1:e52ae6584f1c | 646 | |
Mike Fiore |
1:e52ae6584f1c | 647 | if (_serialp != NULL && _serialp->readable()) { |
Mike Fiore |
1:e52ae6584f1c | 648 | if (escape_buffer == "") |
Mike Fiore |
1:e52ae6584f1c | 649 | escape_timer.start(); |
Mike Fiore |
1:e52ae6584f1c | 650 | char ch; |
Mike Fiore |
1:e52ae6584f1c | 651 | _serialp->read(&ch, 1); |
Mike Fiore |
1:e52ae6584f1c | 652 | escape_buffer += ch; |
Mike Fiore |
1:e52ae6584f1c | 653 | if (escape_buffer == CommandTerminal::escape_sequence) |
Mike Fiore |
1:e52ae6584f1c | 654 | return true; |
Mike Fiore |
1:e52ae6584f1c | 655 | } |
Mike Fiore |
1:e52ae6584f1c | 656 | if (escape_timer.read_ms() > escape_timeout) { |
Mike Fiore |
1:e52ae6584f1c | 657 | escape_buffer = ""; |
Mike Fiore |
1:e52ae6584f1c | 658 | escape_timer.stop(), escape_timer.reset(); |
Mike Fiore |
1:e52ae6584f1c | 659 | } |
Mike Fiore |
1:e52ae6584f1c | 660 | |
Mike Fiore |
1:e52ae6584f1c | 661 | osDelay(10); |
Mike Fiore |
1:e52ae6584f1c | 662 | } |
Mike Fiore |
1:e52ae6584f1c | 663 | |
Mike Fiore |
1:e52ae6584f1c | 664 | return false; |
Mike Fiore |
1:e52ae6584f1c | 665 | } |
Mike Fiore |
1:e52ae6584f1c | 666 | |
Mike Fiore |
1:e52ae6584f1c | 667 | void CommandTerminal::wakeup(bool standby) { |
Mike Fiore |
1:e52ae6584f1c | 668 | HAL_PWREx_DisableMainRegulatorLowVoltage(); |
Mike Fiore |
1:e52ae6584f1c | 669 | HAL_PWREx_DisableFlashPowerDown(); |
Mike Fiore |
1:e52ae6584f1c | 670 | HAL_PWREx_DisableLowRegulatorLowVoltage(); |
Mike Fiore |
1:e52ae6584f1c | 671 | |
Mike Fiore |
1:e52ae6584f1c | 672 | if (standby) { |
Mike Fiore |
1:e52ae6584f1c | 673 | HAL_DisableDBGStandbyMode(); |
Mike Fiore |
1:e52ae6584f1c | 674 | |
Mike Fiore |
1:e52ae6584f1c | 675 | HAL_PWR_EnableWakeUpPin (PWR_WAKEUP_PIN1); |
Mike Fiore |
1:e52ae6584f1c | 676 | } |
Mike Fiore |
1:e52ae6584f1c | 677 | |
Mike Fiore |
1:e52ae6584f1c | 678 | _dot->wakeup(); |
Mike Fiore |
1:e52ae6584f1c | 679 | |
Mike Fiore |
1:e52ae6584f1c | 680 | } |