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:
Jason Reiss
Date:
Wed Dec 06 13:33:52 2023 -0600
Revision:
42:23e2df6714f4
Parent:
36:b586cd6e91f3
TestMode: reset appnonce to 0 on reset to accomodate LCTT 3.12.0 and earlier. If the test suite changes to test AppNonce loaded from NVM this will fail tests.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mike Fiore 1:e52ae6584f1c 1 #include "ctype.h"
Jason Reiss 27:5fafd3b26ac3 2 #include "CommandFactory.h"
Mike Fiore 1:e52ae6584f1c 3 #include "CommandTerminal.h"
Mike Fiore 1:e52ae6584f1c 4 #include "Command.h"
Mike Fiore 4:666017851052 5 #include "MTSLog.h"
jenkins@jenkinsdm1 16:d5cf2af81a6d 6 #include "ChannelPlan.h"
Mike Fiore 1:e52ae6584f1c 7 #include <cstdarg>
Mike Fiore 4:666017851052 8 #include <deque>
Jason Reiss 28:c222ca8383f4 9 #include "mts_at_version.h"
Jason Reiss 36:b586cd6e91f3 10 #include "LowPower.h"
Jason Reiss 28:c222ca8383f4 11
Mike Fiore 14:f9a77400b622 12 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 14:f9a77400b622 13 #include "xdot_low_power.h"
Mike Fiore 14:f9a77400b622 14 #endif
Mike Fiore 1:e52ae6584f1c 15
Jason Reiss 36:b586cd6e91f3 16 #if defined(TARGET_MTS_MDOT_F411RE) || defined(TARGET_XDOT_MAX32670)
Jason Reiss 36:b586cd6e91f3 17 #define MTS_DOT_COMMAND_HISTORY_FEATURE 1
Mike Fiore 14:f9a77400b622 18 #endif
Jason Reiss 36:b586cd6e91f3 19
Jason Reiss 36:b586cd6e91f3 20 #if !defined(TARGET_XDOT_L151CC) || defined(MTS_RADIO_DEBUG_COMMANDS) || defined(MTS_CERT_TEST_MODE)
Jason Reiss 36:b586cd6e91f3 21 #define MTS_DOT_ENABLE_LORAWAN_TESTMODE 1
Jason Reiss 36:b586cd6e91f3 22 #endif
Jason Reiss 36:b586cd6e91f3 23
Mike Fiore 1:e52ae6584f1c 24
Mike Fiore 1:e52ae6584f1c 25 const char CommandTerminal::newline[] = "\r\n";
Mike Fiore 1:e52ae6584f1c 26
Mike Fiore 1:e52ae6584f1c 27 // Command error text...
Mike Fiore 1:e52ae6584f1c 28 const char CommandTerminal::command_error[] = "Command not found!\r\n";
Mike Fiore 1:e52ae6584f1c 29
Mike Fiore 1:e52ae6584f1c 30 // Response texts...
Mike Fiore 1:e52ae6584f1c 31 const char CommandTerminal::help[] = "\r\nHelp\r\n";
Mike Fiore 1:e52ae6584f1c 32 const char CommandTerminal::cmd_error[] = "Invalid command\r\n";
Mike Fiore 9:ff62b20f7000 33 const char CommandTerminal::connect[] = "\r\nCONNECT\r\n";
Mike Fiore 9:ff62b20f7000 34 const char CommandTerminal::no_carrier[] = "\r\nNO CARRIER\r\n";
Mike Fiore 1:e52ae6584f1c 35 const char CommandTerminal::done[] = "\r\nOK\r\n";
Mike Fiore 1:e52ae6584f1c 36 const char CommandTerminal::error[] = "\r\nERROR\r\n";
Mike Fiore 1:e52ae6584f1c 37
Mike Fiore 1:e52ae6584f1c 38 // Escape sequence...
Mike Fiore 1:e52ae6584f1c 39 const char CommandTerminal::escape_sequence[] = "+++";
Mike Fiore 1:e52ae6584f1c 40
Mike Fiore 9:ff62b20f7000 41 mts::ATSerial* CommandTerminal::_serialp = NULL;
Mike Fiore 14:f9a77400b622 42 mDot* CommandTerminal::_dot = NULL;
Mike Fiore 14:f9a77400b622 43
Mike Fiore 14:f9a77400b622 44 CommandTerminal::RadioEvent* CommandTerminal::_events = new RadioEvent();
Mike Fiore 9:ff62b20f7000 45
Mike Fiore 9:ff62b20f7000 46 static bool serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 47 static bool peer_to_peer = false;
Jason Reiss 27:5fafd3b26ac3 48 static bool command_processing = false;
Jason Reiss 27:5fafd3b26ac3 49 static bool urc_enabled = false;
Mike Fiore 1:e52ae6584f1c 50
Mike Fiore 14:f9a77400b622 51 std::string CommandTerminal::_errorMessage = "";
Mike Fiore 14:f9a77400b622 52
jenkins@jenkinsdm1 18:63f098f042b2 53 static uint8_t _battery_level = 0xFF;
jenkins@jenkinsdm1 18:63f098f042b2 54
Jason Reiss 23:4f0a981c0349 55 static uint8_t f_data[252]; //max payload 242 plus 10 bytes for format
Jason Reiss 23:4f0a981c0349 56 static uint32_t _rxAddress = 0;
Jason Reiss 28:c222ca8383f4 57 static uint32_t _rxFcnt = 0;
Jason Reiss 23:4f0a981c0349 58
Jason Reiss 27:5fafd3b26ac3 59 #if defined(TARGET_MTS_MDOT_F411RE)
Jason Reiss 36:b586cd6e91f3 60 #define PIN_PACKET_RX D12
Jason Reiss 36:b586cd6e91f3 61 #define PIN_JOIN_STATUS A2
Jason Reiss 36:b586cd6e91f3 62 #define PIN_ON_SLEEP XBEE_ON_SLEEP
Jason Reiss 36:b586cd6e91f3 63 #elif defined(TARGET_XDOT_L151CC)
Jason Reiss 36:b586cd6e91f3 64 #define PIN_PACKET_RX GPIO1
Jason Reiss 36:b586cd6e91f3 65 #define PIN_JOIN_STATUS GPIO0
Jason Reiss 36:b586cd6e91f3 66 #define PIN_ON_SLEEP GPIO2
Jason Reiss 36:b586cd6e91f3 67 #elif defined(TARGET_MAX32630FTHR)
Jason Reiss 36:b586cd6e91f3 68 #define PIN_PACKET_RX LED_RED
Jason Reiss 36:b586cd6e91f3 69 #define PIN_JOIN_STATUS LED3
Jason Reiss 36:b586cd6e91f3 70 #define PIN_ON_SLEEP P5_5
Jason Reiss 36:b586cd6e91f3 71 #elif defined(TARGET_XDOT_MAX32670) || defined(TARGET_XDOTES_MAX32670)
Jason Reiss 36:b586cd6e91f3 72 #define PIN_PACKET_RX GPIO1
Jason Reiss 36:b586cd6e91f3 73 #define PIN_JOIN_STATUS GPIO0
Jason Reiss 36:b586cd6e91f3 74 #define PIN_ON_SLEEP GPIO2
Jason Reiss 36:b586cd6e91f3 75 #elif defined(TARGET_MAX32660EVSYS) || defined(TARGET_MAX32660EVSYS)
Jason Reiss 36:b586cd6e91f3 76 // NO-OP: no pins to define, will default to NC
Jason Reiss 27:5fafd3b26ac3 77 #else
Jason Reiss 36:b586cd6e91f3 78 #error Unsupported target
Jason Reiss 36:b586cd6e91f3 79 #endif
Jason Reiss 36:b586cd6e91f3 80
Jason Reiss 36:b586cd6e91f3 81 #ifndef GPIO_PIN_SET
Jason Reiss 36:b586cd6e91f3 82 #define GPIO_PIN_SET 1
Jason Reiss 36:b586cd6e91f3 83 #endif
Jason Reiss 36:b586cd6e91f3 84
Jason Reiss 36:b586cd6e91f3 85 #ifndef GPIO_PIN_RESET
Jason Reiss 36:b586cd6e91f3 86 #define GPIO_PIN_RESET 0
Jason Reiss 36:b586cd6e91f3 87 #endif
Jason Reiss 36:b586cd6e91f3 88
Jason Reiss 36:b586cd6e91f3 89
Jason Reiss 36:b586cd6e91f3 90 #if defined(PIN_PACKET_RX)
Jason Reiss 36:b586cd6e91f3 91 DigitalOut _packet_rx_pin(PIN_PACKET_RX);
Jason Reiss 36:b586cd6e91f3 92 #define USE_PIN_PACKET_RX 1
Jason Reiss 36:b586cd6e91f3 93 #else
Jason Reiss 36:b586cd6e91f3 94 #define PIN_PACKET_RX NC
Jason Reiss 36:b586cd6e91f3 95 #endif
Jason Reiss 36:b586cd6e91f3 96
Jason Reiss 36:b586cd6e91f3 97 #if defined(PIN_JOIN_STATUS)
Jason Reiss 36:b586cd6e91f3 98 DigitalOut _join_status_pin(PIN_JOIN_STATUS);
Jason Reiss 36:b586cd6e91f3 99 #define USE_PIN_JOIN_STATUS 1
Jason Reiss 36:b586cd6e91f3 100 #else
Jason Reiss 36:b586cd6e91f3 101 #define PIN_JOIN_STATUS NC
Jason Reiss 36:b586cd6e91f3 102 #endif
Jason Reiss 36:b586cd6e91f3 103
Jason Reiss 36:b586cd6e91f3 104 #if defined(PIN_ON_SLEEP)
Jason Reiss 36:b586cd6e91f3 105 DigitalOut _xbee_on_sleep(PIN_ON_SLEEP);
Jason Reiss 36:b586cd6e91f3 106 #define USE_PIN_ON_SLEEP 1
Jason Reiss 36:b586cd6e91f3 107 #else
Jason Reiss 36:b586cd6e91f3 108 #define PIN_ON_SLEEP NC
Jason Reiss 27:5fafd3b26ac3 109 #endif
Jason Reiss 27:5fafd3b26ac3 110
Mike Fiore 14:f9a77400b622 111 void CommandTerminal::setErrorMessage(const char* message) {
Mike Fiore 14:f9a77400b622 112 _errorMessage.assign(message);
Mike Fiore 14:f9a77400b622 113 }
Mike Fiore 14:f9a77400b622 114
Mike Fiore 14:f9a77400b622 115 void CommandTerminal::setErrorMessage(const std::string& message) {
Mike Fiore 14:f9a77400b622 116 _errorMessage.assign(message);
Mike Fiore 1:e52ae6584f1c 117 }
Jason Reiss 23:4f0a981c0349 118
Mike Fiore 14:f9a77400b622 119 CommandTerminal::CommandTerminal(mts::ATSerial& serial) :
Mike Fiore 14:f9a77400b622 120 _serial(serial),
Mike Fiore 14:f9a77400b622 121 _mode(mDot::COMMAND_MODE),
Mike Fiore 14:f9a77400b622 122 _sleep_standby(true),
Mike Fiore 14:f9a77400b622 123 _autoOTAEnabled(false)
Mike Fiore 14:f9a77400b622 124 {
Mike Fiore 14:f9a77400b622 125 _serialp = &serial;
Mike Fiore 14:f9a77400b622 126 }
Mike Fiore 14:f9a77400b622 127
Jason Reiss 28:c222ca8383f4 128 void free_mem() {
Jason Reiss 28:c222ca8383f4 129 // In order to get free mem within RTOS
Jason Reiss 28:c222ca8383f4 130 // we need to get the main thread's stack pointer
Jason Reiss 28:c222ca8383f4 131 // and subtract it with the top of the heap
Jason Reiss 28:c222ca8383f4 132 // ------+-------------------+ Last Address of RAM (INITIAL_SP)
Jason Reiss 28:c222ca8383f4 133 // | Scheduler Stack |
Jason Reiss 28:c222ca8383f4 134 // +-------------------+
Jason Reiss 28:c222ca8383f4 135 // | Main Thread Stack |
Jason Reiss 28:c222ca8383f4 136 // | | |
Jason Reiss 28:c222ca8383f4 137 // | v |
Jason Reiss 28:c222ca8383f4 138 // +-------------------+ <- bottom_of_stack/__get_MSP()
Jason Reiss 28:c222ca8383f4 139 // RAM | |
Jason Reiss 28:c222ca8383f4 140 // | Available RAM |
Jason Reiss 28:c222ca8383f4 141 // | |
Jason Reiss 28:c222ca8383f4 142 // +-------------------+ <- top_of_heap
Jason Reiss 28:c222ca8383f4 143 // | ^ |
Jason Reiss 28:c222ca8383f4 144 // | | |
Jason Reiss 28:c222ca8383f4 145 // | Heap |
Jason Reiss 28:c222ca8383f4 146 // +-------------------+ <- __end__ / HEAP_START (linker defined var)
Jason Reiss 28:c222ca8383f4 147 // | ZI |
Jason Reiss 28:c222ca8383f4 148 // +-------------------+
Jason Reiss 28:c222ca8383f4 149 // | ZI: Shell Stack |
Jason Reiss 28:c222ca8383f4 150 // +-------------------+
Jason Reiss 28:c222ca8383f4 151 // | ZI: Idle Stack |
Jason Reiss 28:c222ca8383f4 152 // +-------------------+
Jason Reiss 28:c222ca8383f4 153 // | ZI: Timer Stack |
Jason Reiss 28:c222ca8383f4 154 // +-------------------+
Jason Reiss 28:c222ca8383f4 155 // | RW |
Jason Reiss 28:c222ca8383f4 156 // ------+===================+ First Address of RAM
Jason Reiss 28:c222ca8383f4 157 // | |
Jason Reiss 28:c222ca8383f4 158 // Flash | |
Jason Reiss 28:c222ca8383f4 159 //
Jason Reiss 28:c222ca8383f4 160
Jason Reiss 28:c222ca8383f4 161 uint32_t bottom_of_stack = __get_MSP();
Jason Reiss 28:c222ca8383f4 162 char* top_of_heap = (char *) malloc(sizeof(char));
Jason Reiss 28:c222ca8383f4 163 uint32_t diff = bottom_of_stack - (uint32_t) top_of_heap;
Jason Reiss 28:c222ca8383f4 164
Jason Reiss 28:c222ca8383f4 165 free((void *) top_of_heap);
Jason Reiss 28:c222ca8383f4 166
Jason Reiss 28:c222ca8383f4 167 CommandTerminal::Serial()->writef("%lu bytes\r\n", diff);
Jason Reiss 28:c222ca8383f4 168 }
Jason Reiss 28:c222ca8383f4 169
Mike Fiore 14:f9a77400b622 170 void CommandTerminal::init() {
Mike Fiore 14:f9a77400b622 171 _dot->setEvents(_events);
Jason Reiss 34:3b696c2b1e4b 172 _serial.rxClear();
Jason Reiss 34:3b696c2b1e4b 173 _serial.txClear();
Mike Fiore 1:e52ae6584f1c 174 }
Mike Fiore 1:e52ae6584f1c 175
Jason Reiss 28:c222ca8383f4 176 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 177 void CommandTerminal::printHelp() {
Mike Fiore 1:e52ae6584f1c 178 const char* name = NULL;
Mike Fiore 1:e52ae6584f1c 179 const char* text = NULL;
Mike Fiore 1:e52ae6584f1c 180 const char* desc = NULL;
Mike Fiore 1:e52ae6584f1c 181 const char* tab = "\t";
Mike Fiore 1:e52ae6584f1c 182
Mike Fiore 1:e52ae6584f1c 183 std::string header("Command");
Mike Fiore 1:e52ae6584f1c 184 header.append(tab);
Mike Fiore 1:e52ae6584f1c 185 header.append(tab);
Mike Fiore 1:e52ae6584f1c 186 header.append("Name");
Mike Fiore 1:e52ae6584f1c 187 header.append(tab);
Mike Fiore 1:e52ae6584f1c 188 header.append(tab);
Mike Fiore 1:e52ae6584f1c 189 header.append(tab);
Mike Fiore 1:e52ae6584f1c 190 header.append("Description");
Mike Fiore 1:e52ae6584f1c 191
Mike Fiore 1:e52ae6584f1c 192 write(newline);
Mike Fiore 1:e52ae6584f1c 193 write(header.c_str());
Mike Fiore 1:e52ae6584f1c 194 write(newline);
Mike Fiore 1:e52ae6584f1c 195 write(newline);
Mike Fiore 14:f9a77400b622 196
jenkins@jenkinsdm1 18:63f098f042b2 197 Command *cmd = NULL;
Jason Reiss 27:5fafd3b26ac3 198 for (int i = 0; i < CommandFactory::NUMBER_OF_CMDS; i++) {
Jason Reiss 27:5fafd3b26ac3 199 cmd = CommandFactory::Create(static_cast<CommandFactory::CmdId_t>(i));
jenkins@jenkinsdm1 18:63f098f042b2 200 name = cmd->name();
jenkins@jenkinsdm1 18:63f098f042b2 201 text = cmd->text();
jenkins@jenkinsdm1 18:63f098f042b2 202 desc = cmd->desc();
Mike Fiore 1:e52ae6584f1c 203 write(text);
Mike Fiore 1:e52ae6584f1c 204 if (strlen(text) < 8)
Mike Fiore 1:e52ae6584f1c 205 write(tab);
Mike Fiore 1:e52ae6584f1c 206 write(tab);
Mike Fiore 1:e52ae6584f1c 207 write(name);
Mike Fiore 1:e52ae6584f1c 208 if (strlen(name) < 8)
Mike Fiore 1:e52ae6584f1c 209 write(tab);
Mike Fiore 1:e52ae6584f1c 210 if (strlen(name) < 16)
Mike Fiore 1:e52ae6584f1c 211 write(tab);
Mike Fiore 1:e52ae6584f1c 212 write(tab);
Mike Fiore 1:e52ae6584f1c 213 write(desc);
Mike Fiore 1:e52ae6584f1c 214 write(newline);
jenkins@jenkinsdm1 18:63f098f042b2 215
jenkins@jenkinsdm1 18:63f098f042b2 216 delete cmd;
Mike Fiore 1:e52ae6584f1c 217 }
Mike Fiore 1:e52ae6584f1c 218
Mike Fiore 1:e52ae6584f1c 219 write(newline);
Mike Fiore 1:e52ae6584f1c 220 }
Jason Reiss 28:c222ca8383f4 221 #endif
Mike Fiore 1:e52ae6584f1c 222
Mike Fiore 1:e52ae6584f1c 223 bool CommandTerminal::writeable() {
Mike Fiore 14:f9a77400b622 224 return _serialp->writeable();
Mike Fiore 1:e52ae6584f1c 225 }
Mike Fiore 1:e52ae6584f1c 226
Mike Fiore 1:e52ae6584f1c 227 bool CommandTerminal::readable() {
Mike Fiore 14:f9a77400b622 228 return _serialp->readable();
Mike Fiore 1:e52ae6584f1c 229 }
Mike Fiore 1:e52ae6584f1c 230
Mike Fiore 1:e52ae6584f1c 231 char CommandTerminal::read() {
Mike Fiore 1:e52ae6584f1c 232 char ch;
Jason Reiss 28:c222ca8383f4 233 _serialp->read(ch);
Mike Fiore 1:e52ae6584f1c 234 return ch;
Mike Fiore 1:e52ae6584f1c 235 }
Mike Fiore 1:e52ae6584f1c 236
Mike Fiore 1:e52ae6584f1c 237 void CommandTerminal::write(const char* message) {
Mike Fiore 1:e52ae6584f1c 238 while (!writeable())
Mike Fiore 1:e52ae6584f1c 239 ;
Mike Fiore 14:f9a77400b622 240 _serialp->write(message, strlen(message));
Mike Fiore 1:e52ae6584f1c 241 }
Mike Fiore 1:e52ae6584f1c 242
Mike Fiore 1:e52ae6584f1c 243 void CommandTerminal::writef(const char* format, ...) {
Jason Reiss 34:3b696c2b1e4b 244 char buff[512];
Mike Fiore 1:e52ae6584f1c 245
Mike Fiore 1:e52ae6584f1c 246 va_list ap;
Mike Fiore 1:e52ae6584f1c 247 va_start(ap, format);
Mike Fiore 1:e52ae6584f1c 248 int size = vsnprintf(buff, 256, format, ap);
Mike Fiore 1:e52ae6584f1c 249 while (!writeable())
Mike Fiore 1:e52ae6584f1c 250 ;
Mike Fiore 14:f9a77400b622 251 _serialp->write(buff, size);
Mike Fiore 1:e52ae6584f1c 252 va_end(ap);
Mike Fiore 1:e52ae6584f1c 253 }
Mike Fiore 1:e52ae6584f1c 254
Mike Fiore 9:ff62b20f7000 255 void CommandTerminal::serialLoop() {
Mike Fiore 1:e52ae6584f1c 256 Timer serial_read_timer;
Mike Fiore 1:e52ae6584f1c 257 std::vector<uint8_t> serial_buffer;
Mike Fiore 9:ff62b20f7000 258 std::vector<uint8_t> data;
Jason Reiss 28:c222ca8383f4 259 std::chrono::milliseconds timeout(0);
Jason Reiss 28:c222ca8383f4 260 std::chrono::milliseconds elapsed_time_ms;
Mike Fiore 1:e52ae6584f1c 261
Mike Fiore 9:ff62b20f7000 262 serial_read_timer.start();
Mike Fiore 1:e52ae6584f1c 263
Mike Fiore 9:ff62b20f7000 264 if (_dot->getStartUpMode() == mDot::SERIAL_MODE) {
Jason Reiss 36:b586cd6e91f3 265 #if defined(USE_PIN_ON_SLEEP)
Mike Fiore 9:ff62b20f7000 266 _xbee_on_sleep = GPIO_PIN_SET;
Jason Reiss 36:b586cd6e91f3 267 #endif
Jason Reiss 28:c222ca8383f4 268 timeout = std::chrono::milliseconds(_dot->getWakeDelay());
Jason Reiss 28:c222ca8383f4 269 elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(serial_read_timer.elapsed_time());
Mike Fiore 1:e52ae6584f1c 270
Mike Fiore 9:ff62b20f7000 271 // wait for timeout or start of serial data
Jason Reiss 28:c222ca8383f4 272 while (!readable() && elapsed_time_ms < timeout && !_serialp->escaped()) {
Jason Reiss 28:c222ca8383f4 273 ThisThread::sleep_for(2ms);
Jason Reiss 28:c222ca8383f4 274 elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(serial_read_timer.elapsed_time());
Mike Fiore 1:e52ae6584f1c 275 }
Mike Fiore 1:e52ae6584f1c 276 }
Mike Fiore 1:e52ae6584f1c 277
Mike Fiore 14:f9a77400b622 278 if (!readable() && _events->SendAck()) {
Mike Fiore 14:f9a77400b622 279 logDebug("SERIAL NOT READABLE and ACK REQUESTED");
Mike Fiore 14:f9a77400b622 280 goto L_SEND;
Mike Fiore 14:f9a77400b622 281 }
Mike Fiore 14:f9a77400b622 282
Mike Fiore 14:f9a77400b622 283 if (readable() && !_serialp->escaped()) {
Mike Fiore 6:e27eaad36a0c 284
Mike Fiore 6:e27eaad36a0c 285 serial_read_timer.reset();
Jason Reiss 28:c222ca8383f4 286 timeout = std::chrono::milliseconds(_dot->getWakeTimeout());
Jason Reiss 28:c222ca8383f4 287
Jason Reiss 28:c222ca8383f4 288 while (true) {
Jason Reiss 28:c222ca8383f4 289 elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(serial_read_timer.elapsed_time());
Jason Reiss 28:c222ca8383f4 290 if ((elapsed_time_ms >= timeout) ) {
Mike Fiore 9:ff62b20f7000 291
Jason Reiss 28:c222ca8383f4 292 break;
Jason Reiss 28:c222ca8383f4 293 }
Jason Reiss 28:c222ca8383f4 294 if (serial_buffer.size() >= _dot->getNextTxMaxSize()) {
Jason Reiss 28:c222ca8383f4 295 break;
Jason Reiss 28:c222ca8383f4 296 }
Jason Reiss 28:c222ca8383f4 297 if (_serialp->escaped()) {
Jason Reiss 28:c222ca8383f4 298 break;
Jason Reiss 28:c222ca8383f4 299 }
Jason Reiss 28:c222ca8383f4 300 if (readable()) {
Mike Fiore 1:e52ae6584f1c 301 serial_buffer.push_back(read());
Mike Fiore 1:e52ae6584f1c 302 serial_read_timer.reset();
Jason Reiss 28:c222ca8383f4 303 } else {
Jason Reiss 28:c222ca8383f4 304 ThisThread::sleep_for(5ms);
Mike Fiore 1:e52ae6584f1c 305 }
Mike Fiore 1:e52ae6584f1c 306 }
Mike Fiore 9:ff62b20f7000 307
Mike Fiore 1:e52ae6584f1c 308 serial_read_timer.stop(), serial_read_timer.reset();
Mike Fiore 1:e52ae6584f1c 309
Mike Fiore 1:e52ae6584f1c 310 if (!serial_buffer.empty()) {
Mike Fiore 9:ff62b20f7000 311 if (_dot->getStartUpMode() == mDot::SERIAL_MODE)
Jason Reiss 36:b586cd6e91f3 312 #if defined(USE_PIN_ON_SLEEP)
Mike Fiore 14:f9a77400b622 313 _xbee_on_sleep = GPIO_PIN_RESET;
Jason Reiss 36:b586cd6e91f3 314 #endif
Mike Fiore 9:ff62b20f7000 315
Mike Fiore 14:f9a77400b622 316 L_SEND:
Mike Fiore 9:ff62b20f7000 317 // wait for any duty cycle limit to expire
Mike Fiore 14:f9a77400b622 318 while (_dot->getNextTxMs() > 0 && !_serialp->escaped()) {
Jason Reiss 28:c222ca8383f4 319 ThisThread::sleep_for(10ms);
Mike Fiore 9:ff62b20f7000 320 }
Mike Fiore 9:ff62b20f7000 321
Mike Fiore 14:f9a77400b622 322 if (_dot->getIsIdle()) {
Mike Fiore 9:ff62b20f7000 323 logDebug("Received serial data, sending out radio.");
Jason Reiss 27:5fafd3b26ac3 324 if(_dot->getRxOutput() == mDot::EXTENDED || _dot->getRxOutput() == mDot::EXTENDED_HEX) {
Jason Reiss 23:4f0a981c0349 325 formatPacketSDSend(serial_buffer);
Jason Reiss 23:4f0a981c0349 326 }
Jason Reiss 28:c222ca8383f4 327
Mike Fiore 9:ff62b20f7000 328 if (_dot->send(serial_buffer, false) != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 329 logDebug("Send failed.");
Mike Fiore 9:ff62b20f7000 330 // If the data should be tossed after send failure, clear buffer
Mike Fiore 9:ff62b20f7000 331 if (_dot->getSerialClearOnError()) {
Mike Fiore 9:ff62b20f7000 332 serial_buffer.clear();
Mike Fiore 9:ff62b20f7000 333 }
Mike Fiore 9:ff62b20f7000 334 } else {
Mike Fiore 1:e52ae6584f1c 335
Mike Fiore 9:ff62b20f7000 336 // wait for send to finish
Jason Reiss 27:5fafd3b26ac3 337 do {
Jason Reiss 28:c222ca8383f4 338 ThisThread::sleep_for(50ms);
Jason Reiss 27:5fafd3b26ac3 339 } while (!_dot->getIsIdle() && !_serialp->escaped());
Mike Fiore 9:ff62b20f7000 340
Mike Fiore 9:ff62b20f7000 341 // call recv to wait for any packet before sending again
Jason Reiss 23:4f0a981c0349 342 if (!_serialp->escaped()) {
Jason Reiss 23:4f0a981c0349 343 data.clear();
Mike Fiore 9:ff62b20f7000 344 _dot->recv(data);
Jason Reiss 23:4f0a981c0349 345 }
Mike Fiore 9:ff62b20f7000 346
Mike Fiore 9:ff62b20f7000 347 // Clear the serial buffer if send is success
Mike Fiore 9:ff62b20f7000 348 serial_buffer.clear();
Mike Fiore 14:f9a77400b622 349
Jason Reiss 27:5fafd3b26ac3 350 // In P2P and Class B & C mode pending data will be sent automatically without uplink
Jason Reiss 27:5fafd3b26ac3 351 if (peer_to_peer != true && _dot->getClass() == "A") {
Mike Fiore 14:f9a77400b622 352 if (_dot->getDataPending()) {
Mike Fiore 14:f9a77400b622 353 logDebug("Data is pending");
Mike Fiore 14:f9a77400b622 354 goto L_SEND;
Mike Fiore 14:f9a77400b622 355 }
Mike Fiore 14:f9a77400b622 356 if (_dot->getAckRequested()) {
Mike Fiore 14:f9a77400b622 357 logDebug("Ack requested");
Mike Fiore 14:f9a77400b622 358 goto L_SEND;
Mike Fiore 14:f9a77400b622 359 }
Jason Reiss 23:4f0a981c0349 360 if (_dot->hasMacCommands()) {
Jason Reiss 23:4f0a981c0349 361 logDebug("Pending MAC answers");
Jason Reiss 23:4f0a981c0349 362 goto L_SEND;
Jason Reiss 23:4f0a981c0349 363 }
Mike Fiore 14:f9a77400b622 364 }
Mike Fiore 9:ff62b20f7000 365 }
Mike Fiore 1:e52ae6584f1c 366 } else {
Mike Fiore 6:e27eaad36a0c 367 logDebug("Radio is busy, cannot send.\r\n");
Jason Reiss 28:c222ca8383f4 368 ThisThread::sleep_for(10ms);
Mike Fiore 1:e52ae6584f1c 369 }
Mike Fiore 1:e52ae6584f1c 370
Mike Fiore 1:e52ae6584f1c 371 } else {
Mike Fiore 6:e27eaad36a0c 372 logDebug("No data received from serial to send.\r\n");
Jason Reiss 34:3b696c2b1e4b 373 ThisThread::sleep_for(10ms);
Mike Fiore 1:e52ae6584f1c 374 }
Mike Fiore 9:ff62b20f7000 375 }
Mike Fiore 9:ff62b20f7000 376
Mike Fiore 14:f9a77400b622 377 if (!_serialp->readable() && _dot->getStartUpMode() == mDot::SERIAL_MODE && !_serialp->escaped()) {
Mike Fiore 14:f9a77400b622 378 sleep(true);
Mike Fiore 1:e52ae6584f1c 379 }
Mike Fiore 9:ff62b20f7000 380
Mike Fiore 14:f9a77400b622 381 if (_serialp->escaped()) {
Mike Fiore 14:f9a77400b622 382 _serialp->clearEscaped();
Mike Fiore 14:f9a77400b622 383 _serialp->rxClear();
Mike Fiore 9:ff62b20f7000 384 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 385 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 386 logDebug("Exit Serial Mode");
Mike Fiore 9:ff62b20f7000 387 write(done);
Mike Fiore 9:ff62b20f7000 388 return;
Mike Fiore 9:ff62b20f7000 389 }
Mike Fiore 9:ff62b20f7000 390
Mike Fiore 9:ff62b20f7000 391 if (!_dot->getNetworkJoinStatus()) {
Mike Fiore 9:ff62b20f7000 392 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 393 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 394 logDebug("Exit Serial Mode");
Mike Fiore 9:ff62b20f7000 395 write(no_carrier);
Mike Fiore 9:ff62b20f7000 396 return;
Mike Fiore 9:ff62b20f7000 397 }
Mike Fiore 1:e52ae6584f1c 398 }
Mike Fiore 1:e52ae6584f1c 399
Mike Fiore 1:e52ae6584f1c 400 bool CommandTerminal::autoJoinCheck() {
Mike Fiore 1:e52ae6584f1c 401
Mike Fiore 1:e52ae6584f1c 402 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 403 int sleep = 1000;
Mike Fiore 1:e52ae6584f1c 404 Timer tmr;
Mike Fiore 9:ff62b20f7000 405 tmr.start();
Mike Fiore 1:e52ae6584f1c 406 int cnt = 0;
Mike Fiore 1:e52ae6584f1c 407
Mike Fiore 1:e52ae6584f1c 408 while (!_dot->getNetworkJoinStatus()) {
Mike Fiore 14:f9a77400b622 409 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 410 write("\r\nJoining network... ");
Mike Fiore 14:f9a77400b622 411 }
Mike Fiore 14:f9a77400b622 412 logInfo("Joining network... ");
Mike Fiore 1:e52ae6584f1c 413
Mike Fiore 9:ff62b20f7000 414 if (_dot->getNextTxMs() > 0) {
Mike Fiore 14:f9a77400b622 415 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 416 writef("\r\nWaiting %lu s before next join attempt\r\n", _dot->getNextTxMs() / 1000);
Mike Fiore 14:f9a77400b622 417 }
Mike Fiore 14:f9a77400b622 418 logInfo("Waiting %lu s before next join attempt", _dot->getNextTxMs() / 1000);
Mike Fiore 9:ff62b20f7000 419
Mike Fiore 9:ff62b20f7000 420 tmr.reset();
Mike Fiore 9:ff62b20f7000 421 while (_dot->getNextTxMs() > 0 && !_serial.escaped()) {
Mike Fiore 14:f9a77400b622 422 osDelay(20);
Mike Fiore 1:e52ae6584f1c 423 }
Mike Fiore 1:e52ae6584f1c 424 }
Mike Fiore 1:e52ae6584f1c 425
Mike Fiore 9:ff62b20f7000 426 if (!_serial.escaped() && _dot->joinNetworkOnce() == mDot::MDOT_OK) {
Mike Fiore 14:f9a77400b622 427 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 428 write("Network Joined\r\n");
Mike Fiore 14:f9a77400b622 429 write(done);
Mike Fiore 14:f9a77400b622 430 }
Mike Fiore 14:f9a77400b622 431 logInfo("Network Joined");
Mike Fiore 1:e52ae6584f1c 432 return false;
Mike Fiore 1:e52ae6584f1c 433 }
Mike Fiore 1:e52ae6584f1c 434
Mike Fiore 14:f9a77400b622 435 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 436 write("Network Join failed\r\n");
Mike Fiore 14:f9a77400b622 437 write(error);
Mike Fiore 14:f9a77400b622 438 }
Mike Fiore 14:f9a77400b622 439 logInfo("Network Join failed");
Mike Fiore 1:e52ae6584f1c 440
Mike Fiore 14:f9a77400b622 441 if (!_serial.escaped() && _dot->getFrequencySubBand() != 0 && _dot->getJoinRetries() > 0 && cnt++ > _dot->getJoinRetries()) {
Mike Fiore 1:e52ae6584f1c 442 cnt = 0;
Mike Fiore 1:e52ae6584f1c 443
jenkins@jenkinsdm1 16:d5cf2af81a6d 444 if (lora::ChannelPlan::IsPlanFixed(_dot->getFrequencyBand())) {
Mike Fiore 1:e52ae6584f1c 445 uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1;
Mike Fiore 9:ff62b20f7000 446 logWarning("Join retries exhausted, switching to sub band %u", band);
Mike Fiore 1:e52ae6584f1c 447 _dot->setFrequencySubBand(band);
Mike Fiore 1:e52ae6584f1c 448 }
Mike Fiore 1:e52ae6584f1c 449 }
Mike Fiore 1:e52ae6584f1c 450
Mike Fiore 1:e52ae6584f1c 451 tmr.reset();
Jason Reiss 36:b586cd6e91f3 452 while (std::chrono::duration_cast<std::chrono::milliseconds>(tmr.elapsed_time()).count() < sleep && !_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 453 osDelay(10);
Mike Fiore 1:e52ae6584f1c 454 }
Mike Fiore 1:e52ae6584f1c 455
Mike Fiore 9:ff62b20f7000 456 if (_serial.escaped()) {
Mike Fiore 9:ff62b20f7000 457 _serial.clearEscaped();
Mike Fiore 9:ff62b20f7000 458 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 459 _mode = mDot::COMMAND_MODE;
Mike Fiore 14:f9a77400b622 460 if (!serial_data_mode) {
Mike Fiore 14:f9a77400b622 461 write("Join Canceled\r\n");
Mike Fiore 14:f9a77400b622 462 write(done);
Mike Fiore 14:f9a77400b622 463 }
Mike Fiore 14:f9a77400b622 464 logInfo("Join Canceled\r\n");
Mike Fiore 9:ff62b20f7000 465 return true;
Mike Fiore 9:ff62b20f7000 466 }
Mike Fiore 1:e52ae6584f1c 467 }
Mike Fiore 1:e52ae6584f1c 468
Mike Fiore 1:e52ae6584f1c 469 return false;
Mike Fiore 1:e52ae6584f1c 470 }
Mike Fiore 1:e52ae6584f1c 471
Jason Reiss 28:c222ca8383f4 472 #define CMD_DEFS_COUNT (13)
Jason Reiss 28:c222ca8383f4 473 #define CMD_DEFS_VARIANT_SIZE (4)
Jason Reiss 28:c222ca8383f4 474 #define CMD_DEFS_LABEL_SIZE (7)
Jason Reiss 28:c222ca8383f4 475
Jason Reiss 28:c222ca8383f4 476 struct CommandDefinition {
Jason Reiss 28:c222ca8383f4 477 const char label[CMD_DEFS_LABEL_SIZE];
Jason Reiss 28:c222ca8383f4 478 const char var[CMD_DEFS_VARIANT_SIZE];
Jason Reiss 28:c222ca8383f4 479 uint8_t max_args;
Jason Reiss 28:c222ca8383f4 480 CommandFactory::CmdId_t id;
Jason Reiss 28:c222ca8383f4 481 };
Jason Reiss 28:c222ca8383f4 482
Jason Reiss 28:c222ca8383f4 483 // Table of commands handled locally
Jason Reiss 28:c222ca8383f4 484 static const CommandDefinition cmd_defs[CMD_DEFS_COUNT] = {
Jason Reiss 28:c222ca8383f4 485 {"", "", 0, CommandFactory::eAT},
Jason Reiss 28:c222ca8383f4 486 {"E", "?01", 0, CommandFactory::eATE},
Jason Reiss 28:c222ca8383f4 487 {"V", "?01", 0, CommandFactory::eATVERBOSE},
Jason Reiss 28:c222ca8383f4 488 {"&K", "?03", 0, CommandFactory::eATK},
Jason Reiss 28:c222ca8383f4 489 {"+URC", "?", 1, CommandFactory::eURC},
Jason Reiss 28:c222ca8383f4 490 {"+LW", "?", 0, CommandFactory::eLW},
Jason Reiss 28:c222ca8383f4 491 {"+SD", "?", 0, CommandFactory::eSD},
Jason Reiss 34:3b696c2b1e4b 492 {"&WP", "", 0, CommandFactory::eATWP},
Jason Reiss 28:c222ca8383f4 493 {"&W", "", 0, CommandFactory::eATW},
Jason Reiss 28:c222ca8383f4 494 {"+SS", "", 0, CommandFactory::eSS},
Jason Reiss 28:c222ca8383f4 495 {"+DP", "?", 0, CommandFactory::eDP},
Jason Reiss 28:c222ca8383f4 496 {"+SLEEP", "", 1, CommandFactory::eSLEEP},
Jason Reiss 28:c222ca8383f4 497 {"+MEM", "?", 0, CommandFactory::eMEM}
Jason Reiss 28:c222ca8383f4 498 };
Jason Reiss 28:c222ca8383f4 499
Jason Reiss 28:c222ca8383f4 500
Jason Reiss 28:c222ca8383f4 501
Mike Fiore 1:e52ae6584f1c 502 void CommandTerminal::start() {
Mike Fiore 1:e52ae6584f1c 503
Mike Fiore 1:e52ae6584f1c 504 char ch;
Mike Fiore 1:e52ae6584f1c 505 bool running = true;
Mike Fiore 1:e52ae6584f1c 506 bool echo = _dot->getEcho();
Mike Fiore 1:e52ae6584f1c 507 std::string command;
Jason Reiss 36:b586cd6e91f3 508 #if defined(MTS_DOT_COMMAND_HISTORY_FEATURE)
Mike Fiore 4:666017851052 509 std::deque<std::string> history;
Mike Fiore 4:666017851052 510 int history_index = -1;
Mike Fiore 14:f9a77400b622 511 #endif
Mike Fiore 1:e52ae6584f1c 512 std::vector<std::string> args;
Mike Fiore 9:ff62b20f7000 513 bool join_canceled = false;
Mike Fiore 1:e52ae6584f1c 514
Mike Fiore 14:f9a77400b622 515 _autoOTAEnabled = _dot->getJoinMode() == mDot::AUTO_OTA;
Mike Fiore 14:f9a77400b622 516
Jason Reiss 34:3b696c2b1e4b 517 if (_dot->getStartUpMode() == mDot::SERIAL_MODE || CommandTerminal::Dot()->getTestModeEnabled()) {
Mike Fiore 9:ff62b20f7000 518
Mike Fiore 9:ff62b20f7000 519 serial_data_mode = true;
Mike Fiore 9:ff62b20f7000 520 _mode = mDot::SERIAL_MODE;
Mike Fiore 1:e52ae6584f1c 521
Mike Fiore 1:e52ae6584f1c 522 std::string escape_buffer;
Mike Fiore 1:e52ae6584f1c 523 char ch;
Mike Fiore 1:e52ae6584f1c 524
Mike Fiore 9:ff62b20f7000 525 if (!_dot->getStandbyFlag()) {
Mike Fiore 9:ff62b20f7000 526 // wake up from power-on/reset
Mike Fiore 9:ff62b20f7000 527
Mike Fiore 9:ff62b20f7000 528 int escape_timeout = 1000;
Mike Fiore 9:ff62b20f7000 529 Timer tmr;
Mike Fiore 9:ff62b20f7000 530 Timer escape_tmr;
Mike Fiore 1:e52ae6584f1c 531
Mike Fiore 9:ff62b20f7000 532 // wait one second for possible escape by user pressing '+' key
Mike Fiore 9:ff62b20f7000 533 tmr.reset();
Mike Fiore 9:ff62b20f7000 534 tmr.start();
Mike Fiore 9:ff62b20f7000 535 escape_tmr.reset();
Mike Fiore 9:ff62b20f7000 536 escape_tmr.start();
Jason Reiss 36:b586cd6e91f3 537 while (std::chrono::duration_cast<std::chrono::milliseconds>(tmr.elapsed_time()).count() < escape_timeout) {
Mike Fiore 9:ff62b20f7000 538 if (_serial.readable()) {
Mike Fiore 9:ff62b20f7000 539 _serial.read(&ch, 1);
Mike Fiore 9:ff62b20f7000 540 escape_buffer += ch;
Mike Fiore 9:ff62b20f7000 541 }
Mike Fiore 1:e52ae6584f1c 542
Mike Fiore 9:ff62b20f7000 543 if (escape_buffer.find("+") != std::string::npos) {
Mike Fiore 9:ff62b20f7000 544 logInfo("Escape detected");
Mike Fiore 9:ff62b20f7000 545 join_canceled = true;
Mike Fiore 9:ff62b20f7000 546 serial_data_mode = false;
Jason Reiss 34:3b696c2b1e4b 547 CommandTerminal::Dot()->setTestModeEnabled(false);
Mike Fiore 9:ff62b20f7000 548 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 549 command.clear();
Mike Fiore 9:ff62b20f7000 550 break;
Mike Fiore 9:ff62b20f7000 551 }
Mike Fiore 9:ff62b20f7000 552
Jason Reiss 36:b586cd6e91f3 553 if (std::chrono::duration_cast<std::chrono::milliseconds>(escape_tmr.elapsed_time()).count() > escape_timeout)
Mike Fiore 9:ff62b20f7000 554 escape_buffer.clear();
Mike Fiore 9:ff62b20f7000 555
Mike Fiore 9:ff62b20f7000 556 osDelay(1);
Mike Fiore 1:e52ae6584f1c 557 }
Mike Fiore 1:e52ae6584f1c 558 }
Mike Fiore 1:e52ae6584f1c 559
Jason Reiss 34:3b696c2b1e4b 560 if (_dot->getTestModeEnabled()) {
Jason Reiss 42:23e2df6714f4 561 CommandTerminal::Dot()->setAppNonce(0);
Jason Reiss 34:3b696c2b1e4b 562 Fota::getInstance()->enable(false);
Jason Reiss 34:3b696c2b1e4b 563 }
Jason Reiss 34:3b696c2b1e4b 564
Jason Reiss 34:3b696c2b1e4b 565 if ((_mode == mDot::SERIAL_MODE || CommandTerminal::Dot()->getTestModeEnabled()) && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
Mike Fiore 9:ff62b20f7000 566 if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 567 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 568 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 569
Mike Fiore 9:ff62b20f7000 570 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
Jason Reiss 36:b586cd6e91f3 571 logWarning("Join Backoff until next join %lu ms", _dot->getNextTxMs());
Mike Fiore 9:ff62b20f7000 572 _serial.writef("Network Not Joined\r\n");
Mike Fiore 9:ff62b20f7000 573 _serial.writef(error);
Mike Fiore 9:ff62b20f7000 574 }
Mike Fiore 9:ff62b20f7000 575 }
Mike Fiore 1:e52ae6584f1c 576 }
Mike Fiore 1:e52ae6584f1c 577
Jason Reiss 34:3b696c2b1e4b 578 if (CommandTerminal::Dot()->getTestModeEnabled() && _dot->getNetworkJoinStatus()) {
Jason Reiss 34:3b696c2b1e4b 579 while (CommandTerminal::Dot()->getTestModeEnabled() && !_events->PacketReceived) {
Jason Reiss 34:3b696c2b1e4b 580 std::vector<uint8_t> data;
Jason Reiss 34:3b696c2b1e4b 581 CommandTerminal::Dot()->send(data, false);
Jason Reiss 34:3b696c2b1e4b 582 osDelay(5000);
Jason Reiss 34:3b696c2b1e4b 583 }
Jason Reiss 34:3b696c2b1e4b 584 }
Jason Reiss 34:3b696c2b1e4b 585
Mike Fiore 9:ff62b20f7000 586 if (_dot->getJoinMode() == mDot::PEER_TO_PEER) {
Mike Fiore 9:ff62b20f7000 587 peer_to_peer = true;
Jason Reiss 27:5fafd3b26ac3 588 Fota::getInstance()->enable(false);
Jason Reiss 27:5fafd3b26ac3 589 CommandTerminal::Dot()->clearMacCommands();
Jason Reiss 27:5fafd3b26ac3 590 CommandTerminal::Dot()->setTxDataRate(CommandTerminal::Dot()->getTxDataRate());
Mike Fiore 9:ff62b20f7000 591 } else {
Mike Fiore 9:ff62b20f7000 592 peer_to_peer = false;
Mike Fiore 9:ff62b20f7000 593 }
Mike Fiore 1:e52ae6584f1c 594 //Run terminal session
Mike Fiore 1:e52ae6584f1c 595 while (running) {
Jason Reiss 28:c222ca8383f4 596
Jason Reiss 34:3b696c2b1e4b 597 if (_events != NULL && CommandTerminal::Dot()->getTestModeEnabled() && !_serial.escaped()) {
Jason Reiss 34:3b696c2b1e4b 598 if (_dot->getNextTxMs() > 0) {
Jason Reiss 34:3b696c2b1e4b 599 osDelay(2000);
Jason Reiss 34:3b696c2b1e4b 600 } else if (!_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
Jason Reiss 34:3b696c2b1e4b 601 if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
Jason Reiss 34:3b696c2b1e4b 602 serial_data_mode = false;
Jason Reiss 34:3b696c2b1e4b 603 _mode = mDot::COMMAND_MODE;
Jason Reiss 34:3b696c2b1e4b 604
Jason Reiss 34:3b696c2b1e4b 605 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
Jason Reiss 34:3b696c2b1e4b 606 _serial.writef("Network Not Joined\r\n");
Jason Reiss 34:3b696c2b1e4b 607 _serial.writef(error);
Jason Reiss 34:3b696c2b1e4b 608 }
Jason Reiss 34:3b696c2b1e4b 609 } else if (_events->PacketReceived) {
Jason Reiss 34:3b696c2b1e4b 610 _events->handleTestModePacket();
Jason Reiss 34:3b696c2b1e4b 611 _events->PacketReceived = false;
Jason Reiss 34:3b696c2b1e4b 612
Jason Reiss 34:3b696c2b1e4b 613 } else {
Jason Reiss 34:3b696c2b1e4b 614 while (CommandTerminal::Dot()->getTestModeEnabled() && !_events->PacketReceived && !_serial.escaped()) {
Jason Reiss 34:3b696c2b1e4b 615 std::vector<uint8_t> data;
Jason Reiss 34:3b696c2b1e4b 616 CommandTerminal::Dot()->send(data, false);
Jason Reiss 34:3b696c2b1e4b 617 osDelay(5000);
Jason Reiss 34:3b696c2b1e4b 618 }
Jason Reiss 34:3b696c2b1e4b 619 }
Jason Reiss 34:3b696c2b1e4b 620 continue;
Jason Reiss 28:c222ca8383f4 621 }
Jason Reiss 28:c222ca8383f4 622
Jason Reiss 28:c222ca8383f4 623 // wait for input to reduce at command idle current
Mike Fiore 9:ff62b20f7000 624 while (!readable() || _mode == mDot::SERIAL_MODE) {
Mike Fiore 14:f9a77400b622 625 if (!join_canceled && _autoOTAEnabled) {
Mike Fiore 9:ff62b20f7000 626 join_canceled = autoJoinCheck();
Mike Fiore 9:ff62b20f7000 627 if (join_canceled)
Mike Fiore 9:ff62b20f7000 628 command.clear();
Mike Fiore 9:ff62b20f7000 629 }
Mike Fiore 1:e52ae6584f1c 630
Mike Fiore 14:f9a77400b622 631 if (!_autoOTAEnabled || (!join_canceled && _autoOTAEnabled)) {
Mike Fiore 9:ff62b20f7000 632 switch (_mode) {
Mike Fiore 9:ff62b20f7000 633 case mDot::SERIAL_MODE:
Mike Fiore 9:ff62b20f7000 634 // signal wakeup, read serial and output to radio
Mike Fiore 9:ff62b20f7000 635 serialLoop();
Mike Fiore 9:ff62b20f7000 636 continue;
Mike Fiore 9:ff62b20f7000 637 break;
Mike Fiore 9:ff62b20f7000 638 default:
Mike Fiore 9:ff62b20f7000 639 break;
Mike Fiore 9:ff62b20f7000 640 }
Mike Fiore 1:e52ae6584f1c 641 }
Mike Fiore 9:ff62b20f7000 642
Mike Fiore 9:ff62b20f7000 643 ch = '\0';
Mike Fiore 1:e52ae6584f1c 644
Jason Reiss 27:5fafd3b26ac3 645 if (_mode != mDot::SERIAL_MODE) {
Jason Reiss 28:c222ca8383f4 646 ThisThread::sleep_for(10ms);
Jason Reiss 27:5fafd3b26ac3 647 }
Mike Fiore 9:ff62b20f7000 648 _serial.escaped();
Mike Fiore 9:ff62b20f7000 649 }
Mike Fiore 1:e52ae6584f1c 650
Mike Fiore 1:e52ae6584f1c 651 // read characters
Mike Fiore 1:e52ae6584f1c 652 if (readable()) {
Mike Fiore 1:e52ae6584f1c 653 ch = read();
Mike Fiore 1:e52ae6584f1c 654
Mike Fiore 4:666017851052 655 if (ch == '\b' || ch == 0x7f) {
Mike Fiore 1:e52ae6584f1c 656 if (!command.empty()) {
Mike Fiore 1:e52ae6584f1c 657 writef("\b \b");
Mike Fiore 1:e52ae6584f1c 658 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 659 }
Mike Fiore 1:e52ae6584f1c 660 continue;
Mike Fiore 4:666017851052 661 } else if (ch == 0x1b || ch == 0x09) {
Mike Fiore 4:666017851052 662 osDelay(20);
Jason Reiss 36:b586cd6e91f3 663
Jason Reiss 36:b586cd6e91f3 664 #if defined(MTS_DOT_COMMAND_HISTORY_FEATURE)
Mike Fiore 4:666017851052 665 // catch escape sequence, or tab
Mike Fiore 9:ff62b20f7000 666 char ch1 = 0x00, ch2 = 0x00;
Mike Fiore 4:666017851052 667
Mike Fiore 4:666017851052 668 if (readable()) {
Mike Fiore 4:666017851052 669 ch1 = read();
Mike Fiore 4:666017851052 670 if (readable())
Mike Fiore 4:666017851052 671 ch2 = read();
Mike Fiore 4:666017851052 672
Mike Fiore 4:666017851052 673 if (ch1 == 0x5b && ch2 == 0x41) {
Mike Fiore 4:666017851052 674 // up key
Mike Fiore 9:ff62b20f7000 675 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 676 writef("\b \b");
Mike Fiore 4:666017851052 677 }
Mike Fiore 4:666017851052 678 if (history.size() > 0) {
Mike Fiore 9:ff62b20f7000 679 if (++history_index >= int(history.size() - 1))
Mike Fiore 4:666017851052 680 history_index = history.size() - 1;
Mike Fiore 4:666017851052 681
Mike Fiore 4:666017851052 682 command = history[history_index];
Jason Reiss 36:b586cd6e91f3 683
Jason Reiss 36:b586cd6e91f3 684 if (command.size() > 128) {
Jason Reiss 36:b586cd6e91f3 685 for (size_t i = 0; i < command.size(); i++) {
Jason Reiss 36:b586cd6e91f3 686 writef("%c", command[i]);
Jason Reiss 36:b586cd6e91f3 687 }
Jason Reiss 36:b586cd6e91f3 688 } else {
Jason Reiss 36:b586cd6e91f3 689 writef("%s", command.c_str());
Jason Reiss 36:b586cd6e91f3 690 }
Mike Fiore 4:666017851052 691 } else {
Mike Fiore 4:666017851052 692 command.clear();
Mike Fiore 4:666017851052 693 }
Mike Fiore 4:666017851052 694 } else if (ch1 == 0x5b && ch2 == 0x42) {
Mike Fiore 4:666017851052 695
Mike Fiore 4:666017851052 696 // down key
Mike Fiore 9:ff62b20f7000 697 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 698 writef("\b \b");
Mike Fiore 4:666017851052 699 }
Mike Fiore 4:666017851052 700
Mike Fiore 4:666017851052 701 if (--history_index < 0) {
Mike Fiore 4:666017851052 702 history_index = -1;
Mike Fiore 4:666017851052 703 command.clear();
Mike Fiore 4:666017851052 704 } else {
Mike Fiore 4:666017851052 705 command = history[history_index];
Jason Reiss 36:b586cd6e91f3 706 if (command.size() > 128) {
Jason Reiss 36:b586cd6e91f3 707 for (size_t i = 0; i < command.size(); i++) {
Jason Reiss 36:b586cd6e91f3 708 writef("%c", command[i]);
Jason Reiss 36:b586cd6e91f3 709 }
Jason Reiss 36:b586cd6e91f3 710
Jason Reiss 36:b586cd6e91f3 711 } else {
Jason Reiss 36:b586cd6e91f3 712 writef("%s", command.c_str());
Jason Reiss 36:b586cd6e91f3 713 }
Mike Fiore 4:666017851052 714 }
Mike Fiore 4:666017851052 715 }
Jason Reiss 36:b586cd6e91f3 716 }
Mike Fiore 14:f9a77400b622 717 #endif
Mike Fiore 9:ff62b20f7000 718 while (readable())
Mike Fiore 9:ff62b20f7000 719 read();
Mike Fiore 4:666017851052 720 continue;
Mike Fiore 1:e52ae6584f1c 721 } else {
Mike Fiore 1:e52ae6584f1c 722 command += ch;
Mike Fiore 1:e52ae6584f1c 723 }
Mike Fiore 1:e52ae6584f1c 724
Mike Fiore 1:e52ae6584f1c 725 // echo chars if enabled
Mike Fiore 1:e52ae6584f1c 726 if (echo && !(ch == '\r' || ch == '\n'))
Mike Fiore 1:e52ae6584f1c 727 writef("%c", ch);
Mike Fiore 1:e52ae6584f1c 728 }
Mike Fiore 1:e52ae6584f1c 729
Mike Fiore 1:e52ae6584f1c 730 // look for end of command line
Mike Fiore 1:e52ae6584f1c 731 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 732 // remove new line or cr character
Mike Fiore 1:e52ae6584f1c 733 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 734 write("\r"); // match standard modem output
Mike Fiore 1:e52ae6584f1c 735 write(newline);
Mike Fiore 1:e52ae6584f1c 736 } else {
Mike Fiore 1:e52ae6584f1c 737 continue;
Mike Fiore 1:e52ae6584f1c 738 }
Mike Fiore 1:e52ae6584f1c 739
Mike Fiore 1:e52ae6584f1c 740 // trim whitespace from command
Mike Fiore 1:e52ae6584f1c 741 mts::Text::trim(command, "\r\n\t ");
Mike Fiore 1:e52ae6584f1c 742
Mike Fiore 1:e52ae6584f1c 743 if (command.size() < 1) {
Mike Fiore 1:e52ae6584f1c 744 command.clear();
Mike Fiore 1:e52ae6584f1c 745 continue;
Mike Fiore 1:e52ae6584f1c 746 }
Mike Fiore 1:e52ae6584f1c 747
Jason Reiss 36:b586cd6e91f3 748 #if defined(USE_PIN_PACKET_RX)
Jason Reiss 36:b586cd6e91f3 749 _packet_rx_pin = GPIO_PIN_RESET;
Jason Reiss 36:b586cd6e91f3 750 #endif
Jason Reiss 27:5fafd3b26ac3 751 command_processing = true;
Jason Reiss 27:5fafd3b26ac3 752
Mike Fiore 1:e52ae6584f1c 753 // parse command and args
Mike Fiore 1:e52ae6584f1c 754 args.clear();
Mike Fiore 1:e52ae6584f1c 755
Mike Fiore 1:e52ae6584f1c 756 // find first '=' character
Mike Fiore 1:e52ae6584f1c 757 size_t delim_index = command.find("=");
Mike Fiore 1:e52ae6584f1c 758 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 759 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 760 } else {
Mike Fiore 1:e52ae6584f1c 761 // find first ' ' character
Mike Fiore 1:e52ae6584f1c 762 delim_index = command.find(" ");
Mike Fiore 1:e52ae6584f1c 763 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 764 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 765 } else {
Mike Fiore 1:e52ae6584f1c 766 args.push_back(command);
Mike Fiore 1:e52ae6584f1c 767 }
Mike Fiore 1:e52ae6584f1c 768 }
Mike Fiore 1:e52ae6584f1c 769
Mike Fiore 1:e52ae6584f1c 770 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 771 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
Mike Fiore 1:e52ae6584f1c 772 args.insert(args.end(), params.begin(), params.end());
Mike Fiore 1:e52ae6584f1c 773 }
Mike Fiore 1:e52ae6584f1c 774
Mike Fiore 1:e52ae6584f1c 775 args[0] = mts::Text::toUpper(args[0]);
Jason Reiss 28:c222ca8383f4 776 bool handled = false;
Mike Fiore 1:e52ae6584f1c 777
Mike Fiore 1:e52ae6584f1c 778 // print help
Mike Fiore 1:e52ae6584f1c 779 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
Jason Reiss 28:c222ca8383f4 780 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 781 printHelp();
Jason Reiss 28:c222ca8383f4 782 #endif
Mike Fiore 1:e52ae6584f1c 783 command.clear();
Jason Reiss 28:c222ca8383f4 784 handled = true;
Jason Reiss 28:c222ca8383f4 785 } else if (args[0].find("AT") == 0) {
Jason Reiss 28:c222ca8383f4 786 const CommandDefinition* def = NULL; // Command to handle if matched
Jason Reiss 28:c222ca8383f4 787 char variant = '\0'; // Variant character
Jason Reiss 28:c222ca8383f4 788 for (int d = 0; (d < CMD_DEFS_COUNT) && (def == NULL); ++d) {
Jason Reiss 28:c222ca8383f4 789 size_t label_size = 2 + strlen(cmd_defs[d].label);
Jason Reiss 28:c222ca8383f4 790 if (args[0].find(cmd_defs[d].label) == 2) {
Jason Reiss 28:c222ca8383f4 791 // Label found following "AT"
Jason Reiss 28:c222ca8383f4 792 for (int v = 0; v < CMD_DEFS_VARIANT_SIZE; ++v) {
Jason Reiss 28:c222ca8383f4 793 if ((args[0][label_size] == cmd_defs[d].var[v]) &&
Jason Reiss 28:c222ca8383f4 794 (args[0][label_size] == '\0' || args[0][label_size + 1] == '\0')) {
Jason Reiss 28:c222ca8383f4 795 // Check for variant characters following label, this includes a NULL
Jason Reiss 28:c222ca8383f4 796 def = &cmd_defs[d];
Jason Reiss 28:c222ca8383f4 797 variant = cmd_defs[d].var[v];
Jason Reiss 28:c222ca8383f4 798 break;
Jason Reiss 28:c222ca8383f4 799 }
Mike Fiore 14:f9a77400b622 800 }
Mike Fiore 4:666017851052 801 }
Mike Fiore 4:666017851052 802 }
Jason Reiss 28:c222ca8383f4 803 if (def != NULL) {
Jason Reiss 28:c222ca8383f4 804 handled = true;
Jason Reiss 28:c222ca8383f4 805 if (args.size() == 2 && args[1].length() == 1 && args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 806 handled = false;
Jason Reiss 28:c222ca8383f4 807 } else if (args.size() - 1 > def->max_args) {
Jason Reiss 28:c222ca8383f4 808 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 809 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 810 #endif
Jason Reiss 28:c222ca8383f4 811 write(error);
Jason Reiss 28:c222ca8383f4 812 } else {
Jason Reiss 28:c222ca8383f4 813 switch (def->id) {
Jason Reiss 28:c222ca8383f4 814 case CommandFactory::eAT:
Jason Reiss 28:c222ca8383f4 815 write(done);
Jason Reiss 28:c222ca8383f4 816 break;
Jason Reiss 28:c222ca8383f4 817 case CommandFactory::eATE:
Jason Reiss 28:c222ca8383f4 818 if (variant == '1' || variant == '0') {
Jason Reiss 28:c222ca8383f4 819 _dot->setEcho(variant == '1');
Jason Reiss 28:c222ca8383f4 820 echo = _dot->getEcho();
Jason Reiss 28:c222ca8383f4 821 } else {
Jason Reiss 28:c222ca8383f4 822 writef("%d\r\n", _dot->getEcho());
Jason Reiss 28:c222ca8383f4 823 }
Jason Reiss 28:c222ca8383f4 824 write(done);
Jason Reiss 28:c222ca8383f4 825 break;
Jason Reiss 28:c222ca8383f4 826 case CommandFactory::eATVERBOSE:
Jason Reiss 28:c222ca8383f4 827 if (variant == '1' || variant == '0') {
Jason Reiss 28:c222ca8383f4 828 _dot->setVerbose(variant == '1');
Jason Reiss 28:c222ca8383f4 829 } else {
Jason Reiss 28:c222ca8383f4 830 writef("%d\r\n", _dot->getVerbose());
Jason Reiss 28:c222ca8383f4 831 }
Jason Reiss 28:c222ca8383f4 832 write(done);
Jason Reiss 28:c222ca8383f4 833 break;
Jason Reiss 28:c222ca8383f4 834 case CommandFactory::eATK:
Jason Reiss 28:c222ca8383f4 835 if (variant == '3' || variant == '0') {
Jason Reiss 28:c222ca8383f4 836 _dot->setFlowControl(variant == '3');
Jason Reiss 28:c222ca8383f4 837 } else {
Jason Reiss 28:c222ca8383f4 838 writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0));
Jason Reiss 28:c222ca8383f4 839 }
Jason Reiss 28:c222ca8383f4 840 write(done);
Jason Reiss 28:c222ca8383f4 841 break;
Jason Reiss 28:c222ca8383f4 842 case CommandFactory::eURC:
Jason Reiss 28:c222ca8383f4 843 if (args.size() == 1) {
Jason Reiss 28:c222ca8383f4 844 writef("%d\r\n", urc_enabled);
Jason Reiss 28:c222ca8383f4 845 write(done);
Jason Reiss 28:c222ca8383f4 846 } else if (args[1].length() == 1) {
Jason Reiss 28:c222ca8383f4 847 if (args[1][0] != '?' && args[1][0] != '0' && args[1][0] != '1') {
Jason Reiss 28:c222ca8383f4 848 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 849 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 850 #endif
Jason Reiss 28:c222ca8383f4 851 write(error);
Jason Reiss 28:c222ca8383f4 852 } else if (args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 853 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 854 write("(0:disable,1:enable)\r\n");
Jason Reiss 28:c222ca8383f4 855 write(done);
Jason Reiss 28:c222ca8383f4 856 #else
Jason Reiss 28:c222ca8383f4 857 write(error);
Jason Reiss 28:c222ca8383f4 858 #endif
Jason Reiss 28:c222ca8383f4 859 } else {
Jason Reiss 28:c222ca8383f4 860 urc_enabled = (args[1][0] == '1');
Jason Reiss 28:c222ca8383f4 861 write(done);
Jason Reiss 28:c222ca8383f4 862 }
Jason Reiss 28:c222ca8383f4 863 } else {
Jason Reiss 28:c222ca8383f4 864 write(error);
Jason Reiss 28:c222ca8383f4 865 }
Jason Reiss 28:c222ca8383f4 866 break;
Jason Reiss 28:c222ca8383f4 867 case CommandFactory::eLW:
Jason Reiss 28:c222ca8383f4 868 writef("%s\r\n", _dot->getMACVersion());
Jason Reiss 28:c222ca8383f4 869 write(done);
Jason Reiss 28:c222ca8383f4 870 break;
Jason Reiss 28:c222ca8383f4 871 case CommandFactory::eMEM:
Jason Reiss 28:c222ca8383f4 872 free_mem();
Jason Reiss 28:c222ca8383f4 873 write(done);
Jason Reiss 28:c222ca8383f4 874 break;
Jason Reiss 28:c222ca8383f4 875 case CommandFactory::eSD:
Jason Reiss 28:c222ca8383f4 876 if (_dot->getNetworkJoinStatus()) {
Jason Reiss 28:c222ca8383f4 877 logDebug("Enter Serial Mode");
Jason Reiss 28:c222ca8383f4 878 write(connect);
Jason Reiss 28:c222ca8383f4 879 serial_data_mode = true;
Jason Reiss 28:c222ca8383f4 880 _serialp->clearEscaped();
Jason Reiss 28:c222ca8383f4 881 _mode = mDot::SERIAL_MODE;
Jason Reiss 28:c222ca8383f4 882 } else {
Jason Reiss 28:c222ca8383f4 883 logDebug("Network Not Joined");
Jason Reiss 28:c222ca8383f4 884 write("Network Not Joined\r\n");
Jason Reiss 28:c222ca8383f4 885 write(error);
Jason Reiss 28:c222ca8383f4 886 }
Jason Reiss 28:c222ca8383f4 887 break;
Jason Reiss 28:c222ca8383f4 888 case CommandFactory::eATW:
Jason Reiss 28:c222ca8383f4 889 if (!_dot->saveConfig()) {
Jason Reiss 28:c222ca8383f4 890 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 891 write("Failed to save to flash");
Jason Reiss 28:c222ca8383f4 892 #endif
Jason Reiss 28:c222ca8383f4 893 write(error);
Jason Reiss 28:c222ca8383f4 894 } else {
Jason Reiss 28:c222ca8383f4 895 write(done);
Jason Reiss 28:c222ca8383f4 896 }
Jason Reiss 28:c222ca8383f4 897 break;
Jason Reiss 36:b586cd6e91f3 898 #if defined(TARGET_MTS_MDOT_F411RE) || defined(TARGET_XDOT_L151CC) || defined(TARGET_XDOT_MAX32670)
Jason Reiss 28:c222ca8383f4 899 case CommandFactory::eATWP:
Jason Reiss 28:c222ca8383f4 900 if (!_dot->saveProtectedConfig()) {
Jason Reiss 28:c222ca8383f4 901 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 902 write("Failed to save to flash");
Jason Reiss 28:c222ca8383f4 903 #endif
Jason Reiss 28:c222ca8383f4 904 write(error);
Jason Reiss 28:c222ca8383f4 905 } else {
Jason Reiss 28:c222ca8383f4 906 write(done);
Jason Reiss 28:c222ca8383f4 907 }
Jason Reiss 28:c222ca8383f4 908 break;
Jason Reiss 36:b586cd6e91f3 909 #endif
Jason Reiss 28:c222ca8383f4 910 case CommandFactory::eSS:
Jason Reiss 28:c222ca8383f4 911 _dot->saveNetworkSession();
Jason Reiss 28:c222ca8383f4 912 write(done);
Jason Reiss 28:c222ca8383f4 913 break;
Jason Reiss 28:c222ca8383f4 914 case CommandFactory::eDP:
Jason Reiss 34:3b696c2b1e4b 915 writef("%d\r\n",
Jason Reiss 34:3b696c2b1e4b 916 _dot->getDataPending() ||
Jason Reiss 34:3b696c2b1e4b 917 _dot->hasMacCommands() ||
Jason Reiss 34:3b696c2b1e4b 918 _dot->getAckRequested());
Jason Reiss 28:c222ca8383f4 919 write(done);
Jason Reiss 28:c222ca8383f4 920 break;
Jason Reiss 28:c222ca8383f4 921 case CommandFactory::eSLEEP: {
Jason Reiss 28:c222ca8383f4 922 bool temp_sleep_standby;
Jason Reiss 28:c222ca8383f4 923 bool valid = false;
Jason Reiss 28:c222ca8383f4 924 if ((args.size() > 1) && (args[1].length() == 1)) {
Jason Reiss 28:c222ca8383f4 925 if ((args[1][0] != '?' && args[1][0] != '0' && args[1][0] != '1')) {
Jason Reiss 28:c222ca8383f4 926 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 927 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 928 #endif
Jason Reiss 28:c222ca8383f4 929 write(error);
Jason Reiss 28:c222ca8383f4 930 } else if (args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 931 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 932 write("(0:deepsleep,1:sleep)\r\n");
Jason Reiss 28:c222ca8383f4 933 write(done);
Jason Reiss 28:c222ca8383f4 934 #else
Jason Reiss 28:c222ca8383f4 935 write(error);
Jason Reiss 28:c222ca8383f4 936 #endif
Jason Reiss 28:c222ca8383f4 937 } else {
Jason Reiss 28:c222ca8383f4 938 valid = true;
Jason Reiss 28:c222ca8383f4 939 temp_sleep_standby = (args[1][0] == '0');
Jason Reiss 28:c222ca8383f4 940 }
Jason Reiss 28:c222ca8383f4 941 } else if (args.size() == 1) {
Jason Reiss 28:c222ca8383f4 942 valid = true;
Jason Reiss 28:c222ca8383f4 943 temp_sleep_standby = _sleep_standby;
Jason Reiss 28:c222ca8383f4 944 } else {
Jason Reiss 28:c222ca8383f4 945 write(error);
Jason Reiss 28:c222ca8383f4 946 }
Jason Reiss 28:c222ca8383f4 947
Jason Reiss 28:c222ca8383f4 948 if (valid) {
Jason Reiss 28:c222ca8383f4 949 if (!_dot->getIsIdle()) {
Jason Reiss 28:c222ca8383f4 950 write("Dot is not idle\r\n");
Jason Reiss 28:c222ca8383f4 951 write(error);
Jason Reiss 28:c222ca8383f4 952 } else {
Jason Reiss 28:c222ca8383f4 953 _sleep_standby = temp_sleep_standby;
Jason Reiss 28:c222ca8383f4 954 #if defined(TARGET_MTS_MDOT_F411RE)
Jason Reiss 28:c222ca8383f4 955 //Read the board ID. If all 0's, it is revision B. This hardware does not support deep sleep.
Jason Reiss 28:c222ca8383f4 956 DigitalIn ID2(PC_4);
Jason Reiss 28:c222ca8383f4 957 DigitalIn ID1(PC_5);
Jason Reiss 28:c222ca8383f4 958 DigitalIn ID0(PD_2);
Jason Reiss 28:c222ca8383f4 959 if(ID2 == 0 && ID1 == 0 && ID0 == 0 && _sleep_standby == 1){
Jason Reiss 28:c222ca8383f4 960 _sleep_standby = 0;
Jason Reiss 28:c222ca8383f4 961 logWarning("This hardware version does not support deep sleep. Using sleep mode instead.");
Jason Reiss 28:c222ca8383f4 962 }
Jason Reiss 28:c222ca8383f4 963 #endif
Jason Reiss 28:c222ca8383f4 964 write(done);
Jason Reiss 28:c222ca8383f4 965 if (_dot->getBaud() < 9600)
Jason Reiss 28:c222ca8383f4 966 osDelay(20);
Jason Reiss 28:c222ca8383f4 967 else if (_dot->getBaud() > 57600)
Jason Reiss 28:c222ca8383f4 968 osDelay(2);
Jason Reiss 28:c222ca8383f4 969 else
Jason Reiss 28:c222ca8383f4 970 osDelay(5);
Jason Reiss 28:c222ca8383f4 971 this->sleep(_sleep_standby);
Jason Reiss 28:c222ca8383f4 972 osDelay(1);
Jason Reiss 28:c222ca8383f4 973 }
Jason Reiss 28:c222ca8383f4 974 }
Jason Reiss 28:c222ca8383f4 975 break;
Jason Reiss 28:c222ca8383f4 976 }
Jason Reiss 28:c222ca8383f4 977 default:
Jason Reiss 28:c222ca8383f4 978 handled = false;
Jason Reiss 28:c222ca8383f4 979 // Unhandled command
Jason Reiss 28:c222ca8383f4 980 // Will only reach here if the table contains commands that do not have explicit cases
Jason Reiss 28:c222ca8383f4 981 break;
Jason Reiss 28:c222ca8383f4 982 }
Jason Reiss 28:c222ca8383f4 983 }
Jason Reiss 36:b586cd6e91f3 984
Jason Reiss 36:b586cd6e91f3 985 #if defined(MTS_DOT_ENABLE_LORAWAN_TESTMODE)
Jason Reiss 28:c222ca8383f4 986 } else if (args[0].find("AT+TM!") == 0 && args[0].length() == 6) {
Jason Reiss 28:c222ca8383f4 987 handled = true;
Jason Reiss 28:c222ca8383f4 988 if ((args.size() > 1) && (args[1].length() == 1)) {
Jason Reiss 28:c222ca8383f4 989 if (args[1][0] == '0' || args[1][0] == '1') {
Jason Reiss 28:c222ca8383f4 990 _dot->setTestModeEnabled(args[1][0] == '1');
Jason Reiss 34:3b696c2b1e4b 991 _dot->saveConfig();
Jason Reiss 28:c222ca8383f4 992 write(done);
Jason Reiss 28:c222ca8383f4 993 } else {
Jason Reiss 28:c222ca8383f4 994 write(error);
Jason Reiss 28:c222ca8383f4 995 }
Jason Reiss 28:c222ca8383f4 996 } else {
Jason Reiss 28:c222ca8383f4 997 writef("%d\r\n", _dot->getTestModeEnabled());
Jason Reiss 28:c222ca8383f4 998 write(done);
Jason Reiss 28:c222ca8383f4 999 }
Jason Reiss 28:c222ca8383f4 1000 #endif
Jason Reiss 28:c222ca8383f4 1001 }
Jason Reiss 28:c222ca8383f4 1002 }
Jason Reiss 28:c222ca8383f4 1003
Jason Reiss 28:c222ca8383f4 1004 if (!handled) {
Mike Fiore 1:e52ae6584f1c 1005 bool found = false;
Mike Fiore 1:e52ae6584f1c 1006 bool query = false;
Mike Fiore 1:e52ae6584f1c 1007
Mike Fiore 1:e52ae6584f1c 1008 std::string lookfor = args[0];
Mike Fiore 1:e52ae6584f1c 1009
Jason Reiss 28:c222ca8383f4 1010 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 1011 // per command help
Jason Reiss 28:c222ca8383f4 1012 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0)) {
Mike Fiore 1:e52ae6584f1c 1013 lookfor = mts::Text::toUpper(args[1]);
Jason Reiss 28:c222ca8383f4 1014 }
Jason Reiss 28:c222ca8383f4 1015 #endif
Mike Fiore 1:e52ae6584f1c 1016 // trim off any trailing '?' and mark as a query command
Mike Fiore 1:e52ae6584f1c 1017 if (args[0].rfind("?") == args[0].length() - 1) {
Mike Fiore 1:e52ae6584f1c 1018 query = true;
Mike Fiore 1:e52ae6584f1c 1019 lookfor = args[0].substr(0, args[0].length() - 1);
Mike Fiore 1:e52ae6584f1c 1020 }
Mike Fiore 1:e52ae6584f1c 1021
Mike Fiore 1:e52ae6584f1c 1022 // search for command
jenkins@jenkinsdm1 18:63f098f042b2 1023 Command *cmd = NULL;
Jason Reiss 27:5fafd3b26ac3 1024 for (int i = 0; i < CommandFactory::NUMBER_OF_CMDS; i++) {
Jason Reiss 27:5fafd3b26ac3 1025 cmd = CommandFactory::Create(static_cast<CommandFactory::CmdId_t>(i));
Mike Fiore 1:e52ae6584f1c 1026
Mike Fiore 1:e52ae6584f1c 1027 // match CMD or CMD? syntax if command is queryable
jenkins@jenkinsdm1 18:63f098f042b2 1028 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) {
Mike Fiore 1:e52ae6584f1c 1029 found = true;
Jason Reiss 28:c222ca8383f4 1030 _errorMessage.clear();
Jason Reiss 28:c222ca8383f4 1031 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 1032 if (args[0] == "HELP") {
jenkins@jenkinsdm1 18:63f098f042b2 1033 writef("%s%s", cmd->help().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 1034 write(done);
Mike Fiore 1:e52ae6584f1c 1035 }
Mike Fiore 1:e52ae6584f1c 1036 else if (args.size() > 1 && args[1] == "?") {
jenkins@jenkinsdm1 18:63f098f042b2 1037 writef("%s%s", cmd->usage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 1038 write(done);
jenkins@jenkinsdm1 18:63f098f042b2 1039 } else if (!cmd->verify(args)) {
Jason Reiss 28:c222ca8383f4 1040 #else
Jason Reiss 28:c222ca8383f4 1041 if (args.size() > 1 && args[1] == "?") {
Jason Reiss 28:c222ca8383f4 1042 write(error);
Jason Reiss 28:c222ca8383f4 1043 } else if (!cmd->verify(args)) {
Jason Reiss 28:c222ca8383f4 1044 #endif
Jason Reiss 28:c222ca8383f4 1045 if (!_errorMessage.empty()) {
Jason Reiss 28:c222ca8383f4 1046 writef("%s%s", _errorMessage.c_str(), newline);
Jason Reiss 28:c222ca8383f4 1047 }
Jason Reiss 28:c222ca8383f4 1048 write(error);
Mike Fiore 1:e52ae6584f1c 1049 } else {
Jason Reiss 28:c222ca8383f4 1050 _errorMessage.clear();
jenkins@jenkinsdm1 18:63f098f042b2 1051 if (cmd->action(args) == 0) {
Mike Fiore 1:e52ae6584f1c 1052 writef("%s", done);
Mike Fiore 1:e52ae6584f1c 1053 } else {
Jason Reiss 28:c222ca8383f4 1054 // Action was not successful
Jason Reiss 28:c222ca8383f4 1055 if (_errorMessage.empty()) {
Jason Reiss 28:c222ca8383f4 1056 // If no error message was set, check for error recorded in mdot
Jason Reiss 28:c222ca8383f4 1057 std::string dot_error = _dot->getLastError();
Jason Reiss 28:c222ca8383f4 1058 if (!dot_error.empty()) {
Jason Reiss 28:c222ca8383f4 1059 writef("%s%s", dot_error.c_str(), newline);
Jason Reiss 28:c222ca8383f4 1060 }
Jason Reiss 28:c222ca8383f4 1061 } else {
Jason Reiss 28:c222ca8383f4 1062 // Command set an error message
Jason Reiss 28:c222ca8383f4 1063 writef("%s%s", _errorMessage.c_str(), newline);
Jason Reiss 28:c222ca8383f4 1064 }
Jason Reiss 28:c222ca8383f4 1065 write(error);
Mike Fiore 1:e52ae6584f1c 1066 }
Mike Fiore 1:e52ae6584f1c 1067 }
Mike Fiore 1:e52ae6584f1c 1068 }
jenkins@jenkinsdm1 18:63f098f042b2 1069
jenkins@jenkinsdm1 18:63f098f042b2 1070 delete cmd;
Jason Reiss 28:c222ca8383f4 1071
Jason Reiss 28:c222ca8383f4 1072 if (found) {
Jason Reiss 28:c222ca8383f4 1073 break;
Jason Reiss 28:c222ca8383f4 1074 }
Mike Fiore 1:e52ae6584f1c 1075 }
Mike Fiore 1:e52ae6584f1c 1076
Mike Fiore 1:e52ae6584f1c 1077 if (!found) {
Jason Reiss 28:c222ca8383f4 1078 write(command_error);
Jason Reiss 28:c222ca8383f4 1079 write(error);
Mike Fiore 1:e52ae6584f1c 1080 }
Mike Fiore 1:e52ae6584f1c 1081 }
Mike Fiore 1:e52ae6584f1c 1082
Jason Reiss 36:b586cd6e91f3 1083 #if defined(USE_PIN_JOIN_STATUS)
Jason Reiss 27:5fafd3b26ac3 1084 _join_status_pin = CommandTerminal::Dot()->getNetworkJoinStatus();
Jason Reiss 36:b586cd6e91f3 1085 #endif
Jason Reiss 27:5fafd3b26ac3 1086 command_processing = false;
Jason Reiss 27:5fafd3b26ac3 1087
Jason Reiss 27:5fafd3b26ac3 1088
Jason Reiss 36:b586cd6e91f3 1089 #if defined(MTS_DOT_COMMAND_HISTORY_FEATURE)
Mike Fiore 4:666017851052 1090 if (history.size() == 0 || history.front() != command)
Mike Fiore 4:666017851052 1091 history.push_front(command);
Mike Fiore 4:666017851052 1092 history_index = -1;
Mike Fiore 1:e52ae6584f1c 1093 command.clear();
Mike Fiore 1:e52ae6584f1c 1094
Mike Fiore 4:666017851052 1095 while (history.size() > 10)
Mike Fiore 4:666017851052 1096 history.pop_back();
Mike Fiore 14:f9a77400b622 1097 #else
Mike Fiore 14:f9a77400b622 1098 command.clear();
Mike Fiore 14:f9a77400b622 1099 #endif
Mike Fiore 1:e52ae6584f1c 1100 }
Mike Fiore 1:e52ae6584f1c 1101 }
Mike Fiore 1:e52ae6584f1c 1102
Mike Fiore 1:e52ae6584f1c 1103 void CommandTerminal::sleep(bool standby) {
Jason Reiss 36:b586cd6e91f3 1104 #if defined(USE_PIN_ON_SLEEP)
Mike Fiore 1:e52ae6584f1c 1105 _xbee_on_sleep = GPIO_PIN_RESET;
Jason Reiss 36:b586cd6e91f3 1106 #endif
Jason Reiss 36:b586cd6e91f3 1107 _serial.rxClear();
Jason Reiss 36:b586cd6e91f3 1108 _serial.txClear();
Jason Reiss 36:b586cd6e91f3 1109
Jason Reiss 36:b586cd6e91f3 1110 LowPower::configExtGpios(_dot->getWakeMode(), _dot->getWakePin());
Jason Reiss 36:b586cd6e91f3 1111 _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby);
Mike Fiore 1:e52ae6584f1c 1112
Mike Fiore 4:666017851052 1113 _serial.rxClear();
Mike Fiore 4:666017851052 1114 _serial.txClear();
Mike Fiore 1:e52ae6584f1c 1115
Jason Reiss 23:4f0a981c0349 1116 Fota::getInstance()->fixEventQueue();
Mike Fiore 14:f9a77400b622 1117 }
Mike Fiore 14:f9a77400b622 1118
Mike Fiore 14:f9a77400b622 1119 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
Jason Reiss 23:4f0a981c0349 1120 switch(format) {
Jason Reiss 23:4f0a981c0349 1121 case(mDot::HEXADECIMAL):
Jason Reiss 23:4f0a981c0349 1122 return mts::Text::bin2hexString(data);
Jason Reiss 23:4f0a981c0349 1123
Jason Reiss 23:4f0a981c0349 1124 case(mDot::BINARY):
Jason Reiss 23:4f0a981c0349 1125 return std::string(data.begin(), data.end());
Jason Reiss 23:4f0a981c0349 1126
Jason Reiss 23:4f0a981c0349 1127 case(mDot::EXTENDED):
Jason Reiss 27:5fafd3b26ac3 1128 return formatPacket(data, false);
Jason Reiss 27:5fafd3b26ac3 1129
Jason Reiss 27:5fafd3b26ac3 1130 case(mDot::EXTENDED_HEX):
Jason Reiss 27:5fafd3b26ac3 1131 return formatPacket(data, true);
Jason Reiss 23:4f0a981c0349 1132
Jason Reiss 23:4f0a981c0349 1133 default:
Jason Reiss 23:4f0a981c0349 1134 return "";
Jason Reiss 23:4f0a981c0349 1135 }
Mike Fiore 1:e52ae6584f1c 1136 }
Mike Fiore 1:e52ae6584f1c 1137
Mike Fiore 1:e52ae6584f1c 1138 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
Mike Fiore 1:e52ae6584f1c 1139 Timer timer;
Mike Fiore 1:e52ae6584f1c 1140
Mike Fiore 1:e52ae6584f1c 1141 timer.start();
Jason Reiss 36:b586cd6e91f3 1142 while (std::chrono::duration_cast<std::chrono::milliseconds>(timer.elapsed_time()).count() < timeout) {
Mike Fiore 1:e52ae6584f1c 1143
Mike Fiore 1:e52ae6584f1c 1144 if (dot != NULL) {
Mike Fiore 1:e52ae6584f1c 1145 if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
Mike Fiore 1:e52ae6584f1c 1146 return false;
Mike Fiore 1:e52ae6584f1c 1147 }
Mike Fiore 1:e52ae6584f1c 1148 }
Mike Fiore 1:e52ae6584f1c 1149
Mike Fiore 9:ff62b20f7000 1150 if (_serialp != NULL && _serialp->escaped()) {
Mike Fiore 9:ff62b20f7000 1151 _serialp->clearEscaped();
Mike Fiore 9:ff62b20f7000 1152 return true;
Mike Fiore 1:e52ae6584f1c 1153 }
Mike Fiore 1:e52ae6584f1c 1154
Jason Reiss 36:b586cd6e91f3 1155 ThisThread::sleep_for(10ms);
Mike Fiore 1:e52ae6584f1c 1156 }
Mike Fiore 1:e52ae6584f1c 1157
Mike Fiore 1:e52ae6584f1c 1158 return false;
Mike Fiore 1:e52ae6584f1c 1159 }
Mike Fiore 1:e52ae6584f1c 1160
Mike Fiore 9:ff62b20f7000 1161 void CommandTerminal::wakeup(void) {
Mike Fiore 9:ff62b20f7000 1162 }
Mike Fiore 9:ff62b20f7000 1163
Jason Reiss 27:5fafd3b26ac3 1164 void CommandTerminal::RadioEvent::RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int16_t snr, lora::DownlinkControl ctrl, uint8_t slot) {
Jason Reiss 27:5fafd3b26ac3 1165 mDotEvent::RxDone(payload, size, rssi, snr, ctrl, slot);
Jason Reiss 27:5fafd3b26ac3 1166 logDebug("RadioEvent - RxDone");
Jason Reiss 27:5fafd3b26ac3 1167 }
Jason Reiss 27:5fafd3b26ac3 1168
Jason Reiss 27:5fafd3b26ac3 1169 void CommandTerminal::RadioEvent::RxTimeout(uint8_t slot) {
Jason Reiss 27:5fafd3b26ac3 1170 mDotEvent::RxTimeout(slot);
Jason Reiss 36:b586cd6e91f3 1171 #if defined(USE_PIN_PACKET_RX)
Jason Reiss 36:b586cd6e91f3 1172 _packet_rx_pin = GPIO_PIN_RESET;
Jason Reiss 36:b586cd6e91f3 1173 #endif
Jason Reiss 27:5fafd3b26ac3 1174 }
Jason Reiss 27:5fafd3b26ac3 1175
Jason Reiss 28:c222ca8383f4 1176 void CommandTerminal::RadioEvent::PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int16_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries, uint32_t address, uint32_t fcnt, bool dupRx) {
Jason Reiss 28:c222ca8383f4 1177 mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, slot, retries, address, fcnt, dupRx);
Jason Reiss 27:5fafd3b26ac3 1178 _rxAddress = address;
Jason Reiss 28:c222ca8383f4 1179 _rxFcnt = fcnt;
Jason Reiss 27:5fafd3b26ac3 1180
jenkins@jenkinsdm1 18:63f098f042b2 1181 if(port == 200 || port == 201 || port == 202) {
Jason Reiss 23:4f0a981c0349 1182 Fota::getInstance()->processCmd(payload, port, size);
Jason Reiss 36:b586cd6e91f3 1183
Jason Reiss 27:5fafd3b26ac3 1184 if (CommandTerminal::Dot()->getRxOutput() < mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1185 return;
Jason Reiss 27:5fafd3b26ac3 1186 }
jenkins@jenkinsdm1 18:63f098f042b2 1187 }
Jason Reiss 36:b586cd6e91f3 1188 #if defined(USE_PIN_PACKET_RX)
Jason Reiss 36:b586cd6e91f3 1189 _packet_rx_pin = GPIO_PIN_SET;
Jason Reiss 36:b586cd6e91f3 1190 #endif
Jason Reiss 27:5fafd3b26ac3 1191
Jason Reiss 36:b586cd6e91f3 1192 if (CommandTerminal::Dot()->getSettings()->Test.TestMode) {
Jason Reiss 36:b586cd6e91f3 1193 if (AckReceived || (PacketReceived && (RxPort != 0 || RxPayloadSize == 0))) {
Jason Reiss 36:b586cd6e91f3 1194 _testDownlinkCounter++;
Jason Reiss 36:b586cd6e91f3 1195 logDebug("Incremented downlink cnt %d", _testDownlinkCounter);
Jason Reiss 36:b586cd6e91f3 1196 } else {
Jason Reiss 36:b586cd6e91f3 1197 logDebug("PacketRx did not increment cnt port: %d size: %d", RxPort, RxPayloadSize);
Jason Reiss 36:b586cd6e91f3 1198 logDebug("PacketRx ACK: %d PKT: %d", AckReceived, PacketReceived);
Jason Reiss 36:b586cd6e91f3 1199 }
Jason Reiss 36:b586cd6e91f3 1200 }
Jason Reiss 27:5fafd3b26ac3 1201
jenkins@jenkinsdm1 18:63f098f042b2 1202 if (serial_data_mode && port != 0) {
Mike Fiore 14:f9a77400b622 1203 if (size > 0) {
Jason Reiss 27:5fafd3b26ac3 1204 while (!CommandTerminal::Serial()->writeable()) ;
Jason Reiss 27:5fafd3b26ac3 1205 if (CommandTerminal::Dot()->getRxOutput() >= mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1206 formatPacket(RxPayload, size, CommandTerminal::Dot()->getRxOutput() == mDot::EXTENDED_HEX);
Jason Reiss 23:4f0a981c0349 1207 } else {
Jason Reiss 23:4f0a981c0349 1208 CommandTerminal::Serial()->write((char*) RxPayload, RxPayloadSize);
Jason Reiss 23:4f0a981c0349 1209 }
Mike Fiore 9:ff62b20f7000 1210 }
Jason Reiss 23:4f0a981c0349 1211 if (!CommandTerminal::Serial()->readable()
Jason Reiss 23:4f0a981c0349 1212 && (_dot->getAckRequested()
Jason Reiss 27:5fafd3b26ac3 1213 || (peer_to_peer == false && _dot->hasMacCommands()))
Jason Reiss 27:5fafd3b26ac3 1214 && (peer_to_peer || _dot->getClass() == "C" || _dot->getSettings()->Session.Class == lora::CLASS_B)) {
Mike Fiore 14:f9a77400b622 1215 _sendAck = true;
Mike Fiore 9:ff62b20f7000 1216 }
Jason Reiss 27:5fafd3b26ac3 1217 } else if (urc_enabled) {
Jason Reiss 27:5fafd3b26ac3 1218 if (!command_processing) {
Jason Reiss 27:5fafd3b26ac3 1219 while (!CommandTerminal::Serial()->writeable()) ;
Jason Reiss 27:5fafd3b26ac3 1220 if (CommandTerminal::Dot()->getRxOutput() >= mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1221 formatPacket(RxPayload, size, CommandTerminal::Dot()->getRxOutput() == mDot::EXTENDED_HEX);
Jason Reiss 27:5fafd3b26ac3 1222 } else {
Jason Reiss 28:c222ca8383f4 1223 CommandTerminal::Serial()->write("RECV\r\n", 6);
Jason Reiss 27:5fafd3b26ac3 1224 }
Jason Reiss 27:5fafd3b26ac3 1225 }
Mike Fiore 9:ff62b20f7000 1226 }
Mike Fiore 1:e52ae6584f1c 1227 }
Mike Fiore 9:ff62b20f7000 1228
Jason Reiss 28:c222ca8383f4 1229 void CommandTerminal::RadioEvent::handleTestModePacket() {
Jason Reiss 36:b586cd6e91f3 1230 #if defined(MTS_DOT_ENABLE_LORAWAN_TESTMODE)
Jason Reiss 36:b586cd6e91f3 1231 // static uint32_t last_rx_seq = 0; // For Class B tests
Jason Reiss 36:b586cd6e91f3 1232 // bool start_test = false;
Jason Reiss 28:c222ca8383f4 1233
Jason Reiss 28:c222ca8383f4 1234 std::string packet = mts::Text::bin2hexString(RxPayload, RxPayloadSize);
Jason Reiss 28:c222ca8383f4 1235
Jason Reiss 36:b586cd6e91f3 1236 CommandTerminal::Dot()->getSettings()->Test.TestMode = true;
Jason Reiss 36:b586cd6e91f3 1237 CommandTerminal::Dot()->setDisableIncrementDR(true);
Jason Reiss 28:c222ca8383f4 1238
Jason Reiss 36:b586cd6e91f3 1239 // last_rx_seq = CommandTerminal::Dot()->getSettings()->Session.UplinkCounter; // for class b tests
Jason Reiss 28:c222ca8383f4 1240
Jason Reiss 36:b586cd6e91f3 1241 uint32_t txPeriod = 5000;
Jason Reiss 36:b586cd6e91f3 1242 bool testConfirmed = false;
Jason Reiss 28:c222ca8383f4 1243
Jason Reiss 36:b586cd6e91f3 1244 std::string cls = "A";
Jason Reiss 36:b586cd6e91f3 1245
Jason Reiss 36:b586cd6e91f3 1246 CommandTerminal::Dot()->setAck(0);
Jason Reiss 36:b586cd6e91f3 1247 CommandTerminal::Dot()->setAdr(true);
Jason Reiss 36:b586cd6e91f3 1248 CommandTerminal::Dot()->setAppPort(224);
Jason Reiss 28:c222ca8383f4 1249
Jason Reiss 36:b586cd6e91f3 1250 Timer sentTimer;
Jason Reiss 36:b586cd6e91f3 1251 sentTimer.start();
Jason Reiss 36:b586cd6e91f3 1252 while (CommandTerminal::Dot()->getSettings()->Test.TestMode) {
Jason Reiss 28:c222ca8383f4 1253 TEST_START:
Jason Reiss 36:b586cd6e91f3 1254 // if (waitingForBeacon && BeaconLocked) {
Jason Reiss 36:b586cd6e91f3 1255 // logInfo("send BeaconRxStatusInd");
Jason Reiss 36:b586cd6e91f3 1256 // _data.clear();
Jason Reiss 36:b586cd6e91f3 1257 // _data.push_back(0x40);
Jason Reiss 36:b586cd6e91f3 1258 // for (size_t i = 0; i < sizeof(BeaconData); ++i) {
Jason Reiss 36:b586cd6e91f3 1259 // _data.push_back(((uint8_t*)&BeaconData)[i]);
Jason Reiss 36:b586cd6e91f3 1260 // }
Jason Reiss 36:b586cd6e91f3 1261 // } else
Jason Reiss 36:b586cd6e91f3 1262
Jason Reiss 36:b586cd6e91f3 1263 if (RxPort == 224) {
Jason Reiss 36:b586cd6e91f3 1264 _data.clear();
Jason Reiss 34:3b696c2b1e4b 1265
Jason Reiss 36:b586cd6e91f3 1266 std::string packet = mts::Text::bin2hexString(RxPayload, RxPayloadSize);
Jason Reiss 36:b586cd6e91f3 1267 logDebug("Test Mode AppPort : %d", CommandTerminal::Dot()->getAppPort());
Jason Reiss 36:b586cd6e91f3 1268 logDebug("Test Mode Packet : %s", packet.c_str());
Jason Reiss 34:3b696c2b1e4b 1269
Jason Reiss 36:b586cd6e91f3 1270 switch (RxPayload[0]) {
Jason Reiss 36:b586cd6e91f3 1271 case 0x00: { // PackageVersionReq
Jason Reiss 36:b586cd6e91f3 1272 _data.push_back(0x00);
Jason Reiss 36:b586cd6e91f3 1273 _data.push_back(0x06);
Jason Reiss 36:b586cd6e91f3 1274 _data.push_back(0x01);
Jason Reiss 36:b586cd6e91f3 1275 break;
Jason Reiss 36:b586cd6e91f3 1276 }
Jason Reiss 36:b586cd6e91f3 1277 case 0x01: { // DutResetReq
Jason Reiss 36:b586cd6e91f3 1278 if (RxPayloadSize == 1) {
Jason Reiss 36:b586cd6e91f3 1279 CommandTerminal::Dot()->resetCpu();
Jason Reiss 28:c222ca8383f4 1280 }
Jason Reiss 36:b586cd6e91f3 1281 break;
Jason Reiss 36:b586cd6e91f3 1282 }
Jason Reiss 36:b586cd6e91f3 1283 case 0x02: { // DutJoinReq
Jason Reiss 36:b586cd6e91f3 1284 if (RxPayloadSize == 1) {
Jason Reiss 36:b586cd6e91f3 1285 while (CommandTerminal::Dot()->getNextTxMs() > 0) {
Jason Reiss 36:b586cd6e91f3 1286 osDelay(1000);
Jason Reiss 28:c222ca8383f4 1287 }
Jason Reiss 36:b586cd6e91f3 1288 CommandTerminal::Dot()->joinNetworkOnce();
Jason Reiss 36:b586cd6e91f3 1289 return;
Jason Reiss 28:c222ca8383f4 1290 }
Jason Reiss 36:b586cd6e91f3 1291 break;
Jason Reiss 36:b586cd6e91f3 1292 }
Jason Reiss 36:b586cd6e91f3 1293 case 0x03: { // SwitchClassReq
Jason Reiss 36:b586cd6e91f3 1294 if (RxPayload[1] < 3) {
Jason Reiss 36:b586cd6e91f3 1295 if (RxPayload[1] == 0x00) {
Jason Reiss 36:b586cd6e91f3 1296 cls = "A";
Jason Reiss 36:b586cd6e91f3 1297 } else {
Jason Reiss 28:c222ca8383f4 1298 cls = RxPayload[1] == 0x01 ? "B" : "C";
Jason Reiss 28:c222ca8383f4 1299 }
Jason Reiss 28:c222ca8383f4 1300 }
Jason Reiss 36:b586cd6e91f3 1301 CommandTerminal::Dot()->setClass(cls);
Jason Reiss 36:b586cd6e91f3 1302 break;
Jason Reiss 36:b586cd6e91f3 1303 }
Jason Reiss 36:b586cd6e91f3 1304 case 0x04: { // ADR Enabled/Disable
Jason Reiss 36:b586cd6e91f3 1305 if (RxPayload[1] == 1)
Jason Reiss 36:b586cd6e91f3 1306 CommandTerminal::Dot()->setAdr(true);
Jason Reiss 36:b586cd6e91f3 1307 else
Jason Reiss 36:b586cd6e91f3 1308 CommandTerminal::Dot()->setAdr(false);
Jason Reiss 36:b586cd6e91f3 1309 break;
Jason Reiss 36:b586cd6e91f3 1310 }
Jason Reiss 36:b586cd6e91f3 1311 case 0x05: { // RegionalDutyCycleCtrlReq
Jason Reiss 36:b586cd6e91f3 1312 if (RxPayload[1] == 0)
Jason Reiss 36:b586cd6e91f3 1313 CommandTerminal::Dot()->setDisableDutyCycle(true);
Jason Reiss 36:b586cd6e91f3 1314 else
Jason Reiss 36:b586cd6e91f3 1315 CommandTerminal::Dot()->setDisableDutyCycle(false);
Jason Reiss 36:b586cd6e91f3 1316 break;
Jason Reiss 36:b586cd6e91f3 1317 }
Jason Reiss 36:b586cd6e91f3 1318 case 0x06: { // TxPeriodicityChangeReq
Jason Reiss 36:b586cd6e91f3 1319 if (RxPayload[1] < 2)
Jason Reiss 36:b586cd6e91f3 1320 // 0, 1 => 5s
Jason Reiss 36:b586cd6e91f3 1321 txPeriod = 5000U;
Jason Reiss 36:b586cd6e91f3 1322 else if (RxPayload[1] < 8)
Jason Reiss 36:b586cd6e91f3 1323 // 2 - 7 => 10s - 60s
Jason Reiss 36:b586cd6e91f3 1324 txPeriod = (RxPayload[1] - 1) * 10000U;
Jason Reiss 36:b586cd6e91f3 1325 else if (RxPayload[1] < 11) {
Jason Reiss 36:b586cd6e91f3 1326 // 8, 9, 10 => 120s, 240s, 480s
Jason Reiss 36:b586cd6e91f3 1327 txPeriod = 120 * (1 << (RxPayload[1] - 8)) * 1000U;
Jason Reiss 28:c222ca8383f4 1328 }
Jason Reiss 36:b586cd6e91f3 1329 break;
Jason Reiss 36:b586cd6e91f3 1330 }
Jason Reiss 36:b586cd6e91f3 1331 case 0x07: { // TxFramesCtrl
Jason Reiss 36:b586cd6e91f3 1332 if (RxPayload[1] == 0) {
Jason Reiss 36:b586cd6e91f3 1333 // NO-OP
Jason Reiss 36:b586cd6e91f3 1334 } else if (RxPayload[1] == 1) {
Jason Reiss 36:b586cd6e91f3 1335 testConfirmed = false;
Jason Reiss 36:b586cd6e91f3 1336 CommandTerminal::Dot()->getSettings()->Network.AckEnabled = 0;
Jason Reiss 36:b586cd6e91f3 1337 } else if (RxPayload[1] == 2) {
Jason Reiss 36:b586cd6e91f3 1338 testConfirmed = true;
Jason Reiss 36:b586cd6e91f3 1339 // if ADR has set nbTrans then use the current setting
Jason Reiss 36:b586cd6e91f3 1340 CommandTerminal::Dot()->getSettings()->Network.AckEnabled = 1;
Jason Reiss 36:b586cd6e91f3 1341 if (CommandTerminal::Dot()->getSettings()->Session.Redundancy == 0) {
Jason Reiss 36:b586cd6e91f3 1342 CommandTerminal::Dot()->getSettings()->Session.Redundancy = 1;
Jason Reiss 28:c222ca8383f4 1343 }
Jason Reiss 28:c222ca8383f4 1344 }
Jason Reiss 36:b586cd6e91f3 1345 break;
Jason Reiss 36:b586cd6e91f3 1346 }
Jason Reiss 36:b586cd6e91f3 1347 case 0x08: { // EchoPayloadReq
Jason Reiss 36:b586cd6e91f3 1348 _data.push_back(0x08);
Jason Reiss 36:b586cd6e91f3 1349 for (size_t i = 1; i < RxPayloadSize; i++) {
Jason Reiss 36:b586cd6e91f3 1350 _data.push_back(RxPayload[i] + 1);
Jason Reiss 28:c222ca8383f4 1351 }
Jason Reiss 36:b586cd6e91f3 1352 break;
Jason Reiss 36:b586cd6e91f3 1353 }
Jason Reiss 36:b586cd6e91f3 1354 case 0x09: { // RxAppCntReq
Jason Reiss 36:b586cd6e91f3 1355 _data.push_back(0x09);
Jason Reiss 36:b586cd6e91f3 1356 _data.push_back(_testDownlinkCounter & 0xFF);
Jason Reiss 36:b586cd6e91f3 1357 _data.push_back(_testDownlinkCounter >> 8);
Jason Reiss 36:b586cd6e91f3 1358 break;
Jason Reiss 36:b586cd6e91f3 1359 }
Jason Reiss 36:b586cd6e91f3 1360 case 0x0A: { // RxAppCntResetReq
Jason Reiss 36:b586cd6e91f3 1361 _testDownlinkCounter = 0;
Jason Reiss 36:b586cd6e91f3 1362 break;
Jason Reiss 36:b586cd6e91f3 1363 }
Jason Reiss 36:b586cd6e91f3 1364 case 0x20: { // LinkCheckReq
Jason Reiss 36:b586cd6e91f3 1365 CommandTerminal::Dot()->addMacCommand(lora::MOTE_MAC_LINK_CHECK_REQ, 0, 0);
Jason Reiss 36:b586cd6e91f3 1366 break;
Jason Reiss 36:b586cd6e91f3 1367 }
Jason Reiss 36:b586cd6e91f3 1368 case 0x21: { // DeviceTimeReq
Jason Reiss 36:b586cd6e91f3 1369 CommandTerminal::Dot()->addDeviceTimeRequest();
Jason Reiss 36:b586cd6e91f3 1370 break;
Jason Reiss 36:b586cd6e91f3 1371 }
Jason Reiss 36:b586cd6e91f3 1372 case 0x22: { // PingSlotInfo
Jason Reiss 36:b586cd6e91f3 1373 CommandTerminal::Dot()->setPingPeriodicity(RxPayload[1]);
Jason Reiss 36:b586cd6e91f3 1374 CommandTerminal::Dot()->addMacCommand(lora::MOTE_MAC_PING_SLOT_INFO_REQ, RxPayload[1], 0);
Jason Reiss 36:b586cd6e91f3 1375 break;
Jason Reiss 36:b586cd6e91f3 1376 }
Jason Reiss 36:b586cd6e91f3 1377 case 0x7D: { // TxCw
Jason Reiss 36:b586cd6e91f3 1378 uint32_t freq = 0;
Jason Reiss 36:b586cd6e91f3 1379 uint16_t timeout = 0;
Jason Reiss 36:b586cd6e91f3 1380 uint8_t power = 0;
Jason Reiss 28:c222ca8383f4 1381
Jason Reiss 36:b586cd6e91f3 1382 timeout = RxPayload[2] << 8 | RxPayload[1];
Jason Reiss 36:b586cd6e91f3 1383 freq = (RxPayload[5] << 16 | RxPayload[4] << 8 | RxPayload[2]) * 100;
Jason Reiss 36:b586cd6e91f3 1384 power = RxPayload[6];
Jason Reiss 36:b586cd6e91f3 1385
Jason Reiss 36:b586cd6e91f3 1386 CommandTerminal::Dot()->sendContinuous(true, timeout * 1000, freq, power);
Jason Reiss 36:b586cd6e91f3 1387 break;
Jason Reiss 36:b586cd6e91f3 1388 }
Jason Reiss 36:b586cd6e91f3 1389 case 0x7E: { // DutFPort224DisableReq
Jason Reiss 36:b586cd6e91f3 1390 _dot->setTestModeEnabled(false);
Jason Reiss 36:b586cd6e91f3 1391 CommandTerminal::Dot()->getSettings()->Test.TestMode = false;
Jason Reiss 36:b586cd6e91f3 1392 _dot->saveConfig();
Jason Reiss 36:b586cd6e91f3 1393 CommandTerminal::Dot()->resetCpu();
Jason Reiss 36:b586cd6e91f3 1394 break;
Jason Reiss 36:b586cd6e91f3 1395 }
Jason Reiss 36:b586cd6e91f3 1396 case 0x7F: { // DutVersionReq
Jason Reiss 36:b586cd6e91f3 1397 std::string version = AT_APPLICATION_VERSION;
Jason Reiss 36:b586cd6e91f3 1398 int temp = 0;
Jason Reiss 28:c222ca8383f4 1399
Jason Reiss 36:b586cd6e91f3 1400 _data.push_back(0x7F);
Jason Reiss 36:b586cd6e91f3 1401 sscanf(&version[0], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1402 _data.push_back(temp); // AT_APP_VERSION_MAJOR; // MAJOR
Jason Reiss 36:b586cd6e91f3 1403 sscanf(&version[2], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1404 _data.push_back(temp); // AT_APP_VERSION_MINOR; // MINOR
Jason Reiss 36:b586cd6e91f3 1405 sscanf(&version[4], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1406 _data.push_back(temp); // AT_APP_VERSION_PATCH; // PATCH
Jason Reiss 36:b586cd6e91f3 1407 if (version.size() > 7) {
Jason Reiss 36:b586cd6e91f3 1408 sscanf(&version[6], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1409 _data.push_back(temp); // AT_APP_VERSION_PATCH; // PATCH
Jason Reiss 36:b586cd6e91f3 1410 } else {
Jason Reiss 36:b586cd6e91f3 1411 _data.push_back(0); // AT_APP_VERSION_PATCH; // PATCH
Jason Reiss 36:b586cd6e91f3 1412 }
Jason Reiss 36:b586cd6e91f3 1413 version = LW_VERSION;
Jason Reiss 36:b586cd6e91f3 1414 sscanf(&version[0], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1415 _data.push_back(temp); // LW_VERSION; // MAJOR
Jason Reiss 36:b586cd6e91f3 1416 sscanf(&version[2], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1417 _data.push_back(temp); // LW_VERSION; // MINOR
Jason Reiss 36:b586cd6e91f3 1418 sscanf(&version[4], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1419 _data.push_back(temp); // LW_VERSION; // PATCH
Jason Reiss 36:b586cd6e91f3 1420 if (version.size() > 7) {
Jason Reiss 36:b586cd6e91f3 1421 sscanf(&version[6], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1422 _data.push_back(temp); // LW_VERSION; // PATCH
Jason Reiss 36:b586cd6e91f3 1423 } else {
Jason Reiss 36:b586cd6e91f3 1424 _data.push_back(0); // LW_VERSION; // PATCH
Jason Reiss 28:c222ca8383f4 1425 }
Jason Reiss 36:b586cd6e91f3 1426 version = RP_VERSION;
Jason Reiss 36:b586cd6e91f3 1427 sscanf(&version[0], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1428 _data.push_back(temp); // RP_VERSION; // MAJOR
Jason Reiss 36:b586cd6e91f3 1429 sscanf(&version[2], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1430 _data.push_back(temp); // RP_VERSION; // MINOR
Jason Reiss 36:b586cd6e91f3 1431 sscanf(&version[4], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1432 _data.push_back(temp); // RP_VERSION; // PATCH
Jason Reiss 36:b586cd6e91f3 1433 if (version.size() > 7) {
Jason Reiss 36:b586cd6e91f3 1434 sscanf(&version[6], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1435 _data.push_back(temp); // RP_VERSION; // PATCH
Jason Reiss 36:b586cd6e91f3 1436 } else {
Jason Reiss 36:b586cd6e91f3 1437 _data.push_back(0); // RP_VERSION; // PATCH
Jason Reiss 28:c222ca8383f4 1438 }
Jason Reiss 36:b586cd6e91f3 1439
Jason Reiss 36:b586cd6e91f3 1440
Jason Reiss 36:b586cd6e91f3 1441 break;
Jason Reiss 36:b586cd6e91f3 1442 }
Jason Reiss 36:b586cd6e91f3 1443 default: {
Jason Reiss 36:b586cd6e91f3 1444 break;
Jason Reiss 36:b586cd6e91f3 1445 }
Jason Reiss 36:b586cd6e91f3 1446 }
Jason Reiss 36:b586cd6e91f3 1447 }
Jason Reiss 36:b586cd6e91f3 1448
Jason Reiss 36:b586cd6e91f3 1449 do {
Jason Reiss 36:b586cd6e91f3 1450 uint32_t loop_timer = 0;
Jason Reiss 36:b586cd6e91f3 1451 loop_timer = std::chrono::duration_cast<std::chrono::milliseconds>(sentTimer.elapsed_time()).count();
Jason Reiss 36:b586cd6e91f3 1452
Jason Reiss 36:b586cd6e91f3 1453 PacketReceived = false;
Jason Reiss 36:b586cd6e91f3 1454 AckReceived = false;
Jason Reiss 36:b586cd6e91f3 1455
Jason Reiss 36:b586cd6e91f3 1456 while (loop_timer < txPeriod || CommandTerminal::Dot()->getNextTxMs() > 0 || !CommandTerminal::Dot()->getIsIdle()) {
Jason Reiss 36:b586cd6e91f3 1457 // if (waitingForBeacon && BeaconLocked) {
Jason Reiss 36:b586cd6e91f3 1458 // goto TEST_START;
Jason Reiss 36:b586cd6e91f3 1459 // }
Jason Reiss 36:b586cd6e91f3 1460 osDelay(500);
Jason Reiss 36:b586cd6e91f3 1461 loop_timer = std::chrono::duration_cast<std::chrono::milliseconds>(sentTimer.elapsed_time()).count();
Jason Reiss 36:b586cd6e91f3 1462
Jason Reiss 36:b586cd6e91f3 1463 if (CommandTerminal::Dot()->getAckRequested() && loop_timer > 5000) {
Jason Reiss 36:b586cd6e91f3 1464 break;
Jason Reiss 28:c222ca8383f4 1465 }
Jason Reiss 28:c222ca8383f4 1466 }
Jason Reiss 28:c222ca8383f4 1467
Jason Reiss 36:b586cd6e91f3 1468 // packet may have been received while waiting, if ACK req then send uplink
Jason Reiss 36:b586cd6e91f3 1469 // else process data
Jason Reiss 36:b586cd6e91f3 1470 if (!PacketReceived || CommandTerminal::Dot()->getAckRequested()) {
Jason Reiss 28:c222ca8383f4 1471
Jason Reiss 28:c222ca8383f4 1472 sentTimer.reset();
Jason Reiss 28:c222ca8383f4 1473
Jason Reiss 36:b586cd6e91f3 1474 if (_data.size() == 0) {
Jason Reiss 34:3b696c2b1e4b 1475 CommandTerminal::Dot()->setAppPort(1);
Jason Reiss 36:b586cd6e91f3 1476 // if (cls == "B") {
Jason Reiss 36:b586cd6e91f3 1477 // // class B tests don't like empty packets
Jason Reiss 36:b586cd6e91f3 1478 _data.push_back(0xFF);
Jason Reiss 36:b586cd6e91f3 1479 // }
Jason Reiss 34:3b696c2b1e4b 1480 } else {
Jason Reiss 34:3b696c2b1e4b 1481 CommandTerminal::Dot()->setAppPort(224);
Jason Reiss 34:3b696c2b1e4b 1482 }
Jason Reiss 34:3b696c2b1e4b 1483
Jason Reiss 36:b586cd6e91f3 1484 PacketReceived = false;
Jason Reiss 36:b586cd6e91f3 1485 AckReceived = false;
Jason Reiss 36:b586cd6e91f3 1486
Jason Reiss 36:b586cd6e91f3 1487 if (CommandTerminal::Dot()->send(_data, testConfirmed) == mDot::MDOT_MAX_PAYLOAD_EXCEEDED) {
Jason Reiss 36:b586cd6e91f3 1488 _data.clear();
Jason Reiss 28:c222ca8383f4 1489 RxPort = 0;
Jason Reiss 28:c222ca8383f4 1490 goto TEST_START;
Jason Reiss 28:c222ca8383f4 1491 }
Jason Reiss 28:c222ca8383f4 1492
Jason Reiss 36:b586cd6e91f3 1493 // For Class B tests
Jason Reiss 36:b586cd6e91f3 1494 // if (PacketReceived) {
Jason Reiss 36:b586cd6e91f3 1495 // last_rx_seq = CommandTerminal::Dot()->getSettings()->Session.UplinkCounter;
Jason Reiss 36:b586cd6e91f3 1496 // }
Jason Reiss 28:c222ca8383f4 1497
Jason Reiss 36:b586cd6e91f3 1498 _data.clear();
Jason Reiss 28:c222ca8383f4 1499
Jason Reiss 34:3b696c2b1e4b 1500 }
Jason Reiss 34:3b696c2b1e4b 1501
Jason Reiss 36:b586cd6e91f3 1502 } while (!AckReceived && CommandTerminal::Dot()->recv(_data) != mDot::MDOT_OK);
Jason Reiss 36:b586cd6e91f3 1503
Jason Reiss 36:b586cd6e91f3 1504
Jason Reiss 36:b586cd6e91f3 1505 if (cls == "B" && !BeaconLocked) {
Jason Reiss 36:b586cd6e91f3 1506 CommandTerminal::Dot()->setClass(cls);
Jason Reiss 28:c222ca8383f4 1507 }
Jason Reiss 36:b586cd6e91f3 1508 }
Jason Reiss 28:c222ca8383f4 1509 #endif
Jason Reiss 28:c222ca8383f4 1510 }
Jason Reiss 28:c222ca8383f4 1511
jenkins@jenkinsdm1 18:63f098f042b2 1512 uint8_t CommandTerminal::getBatteryLevel() {
jenkins@jenkinsdm1 18:63f098f042b2 1513 return _battery_level;
jenkins@jenkinsdm1 18:63f098f042b2 1514 }
jenkins@jenkinsdm1 18:63f098f042b2 1515
Jason Reiss 23:4f0a981c0349 1516 void CommandTerminal::setBatteryLevel(uint8_t battery_level) {
jenkins@jenkinsdm1 18:63f098f042b2 1517 _battery_level = battery_level;
jenkins@jenkinsdm1 18:63f098f042b2 1518 }
jenkins@jenkinsdm1 18:63f098f042b2 1519
Jason Reiss 27:5fafd3b26ac3 1520 void CommandTerminal::formatPacket(uint8_t* payload, uint16_t size, bool hex) {
Jason Reiss 23:4f0a981c0349 1521
Jason Reiss 23:4f0a981c0349 1522 if(_dot->getAckRequested()) {
Jason Reiss 23:4f0a981c0349 1523 f_data[0] = 0;
Jason Reiss 23:4f0a981c0349 1524 } else {
Jason Reiss 23:4f0a981c0349 1525 f_data[0] = 1;
Jason Reiss 23:4f0a981c0349 1526 }
Jason Reiss 23:4f0a981c0349 1527
Jason Reiss 23:4f0a981c0349 1528 f_data[1] = _rxAddress & 0xFF;
Jason Reiss 23:4f0a981c0349 1529 f_data[2] = (_rxAddress >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1530 f_data[3] = (_rxAddress >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1531 f_data[4] = (_rxAddress >> 24) & 0xFF;
Jason Reiss 28:c222ca8383f4 1532 f_data[5] = _rxFcnt & 0xFF;
Jason Reiss 28:c222ca8383f4 1533 f_data[6] = (_rxFcnt >> 8) & 0xFF;
Jason Reiss 28:c222ca8383f4 1534 f_data[7] = (_rxFcnt >> 16) & 0xFF;
Jason Reiss 28:c222ca8383f4 1535 f_data[8] = (_rxFcnt >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1536 f_data[9] = _events->RxPort;
Jason Reiss 23:4f0a981c0349 1537
Jason Reiss 23:4f0a981c0349 1538 for(int i = 0; i < size; i++)
Jason Reiss 23:4f0a981c0349 1539 f_data[i+10] = payload[i];
Jason Reiss 23:4f0a981c0349 1540
Jason Reiss 27:5fafd3b26ac3 1541 if (hex) {
Jason Reiss 27:5fafd3b26ac3 1542 std::string data = "RECV " + mts::Text::bin2hexString(f_data, size + 10) + "\r\n";
Jason Reiss 27:5fafd3b26ac3 1543 CommandTerminal::Serial()->write(data.c_str(), data.size());
Jason Reiss 27:5fafd3b26ac3 1544 } else {
Jason Reiss 27:5fafd3b26ac3 1545 CommandTerminal::Serial()->write((char*)f_data, size + 10);
Jason Reiss 27:5fafd3b26ac3 1546 }
Jason Reiss 23:4f0a981c0349 1547 }
Jason Reiss 23:4f0a981c0349 1548
Jason Reiss 23:4f0a981c0349 1549
Jason Reiss 27:5fafd3b26ac3 1550 std::string CommandTerminal::formatPacket(std::vector<uint8_t> payload, bool hex) {
Jason Reiss 23:4f0a981c0349 1551
Jason Reiss 23:4f0a981c0349 1552 if(_dot->getAckRequested()) {
Jason Reiss 23:4f0a981c0349 1553 f_data[0] = 0;
Jason Reiss 23:4f0a981c0349 1554 } else {
Jason Reiss 23:4f0a981c0349 1555 f_data[0] = 1;
Jason Reiss 23:4f0a981c0349 1556 }
Jason Reiss 23:4f0a981c0349 1557
Jason Reiss 23:4f0a981c0349 1558 f_data[1] = _rxAddress & 0xFF;
Jason Reiss 23:4f0a981c0349 1559 f_data[2] = (_rxAddress >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1560 f_data[3] = (_rxAddress >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1561 f_data[4] = (_rxAddress >> 24) & 0xFF;
Jason Reiss 28:c222ca8383f4 1562 f_data[5] = _rxFcnt & 0xFF;
Jason Reiss 28:c222ca8383f4 1563 f_data[6] = (_rxFcnt >> 8) & 0xFF;
Jason Reiss 28:c222ca8383f4 1564 f_data[7] = (_rxFcnt >> 16) & 0xFF;
Jason Reiss 28:c222ca8383f4 1565 f_data[8] = (_rxFcnt >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1566 f_data[9] = _events->RxPort;
Jason Reiss 23:4f0a981c0349 1567
Jason Reiss 27:5fafd3b26ac3 1568 for(size_t i = 0; i < payload.size(); i++)
Jason Reiss 23:4f0a981c0349 1569 f_data[i+10] = payload.at(i);
Jason Reiss 23:4f0a981c0349 1570
Jason Reiss 27:5fafd3b26ac3 1571 if (hex) {
Jason Reiss 27:5fafd3b26ac3 1572 return mts::Text::bin2hexString(f_data, payload.size() + 10);
Jason Reiss 27:5fafd3b26ac3 1573 } else {
Jason Reiss 27:5fafd3b26ac3 1574 return std::string((char*)f_data, payload.size() + 10);
Jason Reiss 27:5fafd3b26ac3 1575 }
Jason Reiss 27:5fafd3b26ac3 1576
Jason Reiss 23:4f0a981c0349 1577 }
Jason Reiss 23:4f0a981c0349 1578
Jason Reiss 23:4f0a981c0349 1579
Jason Reiss 23:4f0a981c0349 1580
Jason Reiss 23:4f0a981c0349 1581 void CommandTerminal::formatPacketSDSend(std::vector<uint8_t> &payload) {
Jason Reiss 27:5fafd3b26ac3 1582 if (_dot->getRxOutput() == mDot::EXTENDED_HEX) {
Jason Reiss 27:5fafd3b26ac3 1583 int temp;
Jason Reiss 27:5fafd3b26ac3 1584 std::vector<uint8_t> converted;
Jason Reiss 27:5fafd3b26ac3 1585
Jason Reiss 27:5fafd3b26ac3 1586 for (size_t i=0; i < payload.size(); i+=2) {
Jason Reiss 27:5fafd3b26ac3 1587 if (sscanf((char*)&payload[i], "%2x", &temp) == 1) {
Jason Reiss 27:5fafd3b26ac3 1588 converted.push_back((uint8_t)temp);
Jason Reiss 27:5fafd3b26ac3 1589 }
Jason Reiss 27:5fafd3b26ac3 1590 }
Jason Reiss 27:5fafd3b26ac3 1591
Jason Reiss 27:5fafd3b26ac3 1592 payload = converted;
Jason Reiss 27:5fafd3b26ac3 1593 }
Jason Reiss 27:5fafd3b26ac3 1594
Jason Reiss 23:4f0a981c0349 1595 if(payload.size() >= 3) {
Jason Reiss 23:4f0a981c0349 1596 _dot->setAppPort(payload[0]);
Jason Reiss 23:4f0a981c0349 1597 _dot->setRepeat(0);
Jason Reiss 23:4f0a981c0349 1598 _dot->setAck(0);
Jason Reiss 23:4f0a981c0349 1599 switch(payload[1]) {
Jason Reiss 23:4f0a981c0349 1600 case 0:
Jason Reiss 23:4f0a981c0349 1601 _dot->setAck(payload[2]);
Jason Reiss 23:4f0a981c0349 1602 break;
Jason Reiss 23:4f0a981c0349 1603 case 1:
Jason Reiss 23:4f0a981c0349 1604 _dot->setRepeat(payload[2]);
Jason Reiss 23:4f0a981c0349 1605 break;
Jason Reiss 23:4f0a981c0349 1606 default:
Jason Reiss 23:4f0a981c0349 1607 break;
Jason Reiss 23:4f0a981c0349 1608 }
Jason Reiss 23:4f0a981c0349 1609 payload.erase(payload.begin(), payload.begin()+3);
Jason Reiss 23:4f0a981c0349 1610 }
Jason Reiss 27:5fafd3b26ac3 1611
Jason Reiss 23:4f0a981c0349 1612 }
Jason Reiss 23:4f0a981c0349 1613
Jason Reiss 23:4f0a981c0349 1614
Jason Reiss 23:4f0a981c0349 1615
Mike Fiore 9:ff62b20f7000 1616 CommandTerminal::~CommandTerminal() {
Mike Fiore 9:ff62b20f7000 1617 delete _events;
Mike Fiore 9:ff62b20f7000 1618 }