MultiTech / Mbed OS Dot-AT-Firmware

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. Check the commit messages of the Dot library version used to find the correct mbed-os version to use with it. The mbed-os version must match the version used in that version of Dot library or it will likely cause it to fail to compile or have unexpected problems while running.

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:
Fri Sep 08 08:34:24 2023 -0500
Revision:
36:b586cd6e91f3
Parent:
34:3b696c2b1e4b
Child:
42:23e2df6714f4
Update AT Version to 4.2.1

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 34:3b696c2b1e4b 561 Fota::getInstance()->enable(false);
Jason Reiss 34:3b696c2b1e4b 562 }
Jason Reiss 34:3b696c2b1e4b 563
Jason Reiss 34:3b696c2b1e4b 564 if ((_mode == mDot::SERIAL_MODE || CommandTerminal::Dot()->getTestModeEnabled()) && !_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
Mike Fiore 9:ff62b20f7000 565 if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
Mike Fiore 9:ff62b20f7000 566 serial_data_mode = false;
Mike Fiore 9:ff62b20f7000 567 _mode = mDot::COMMAND_MODE;
Mike Fiore 9:ff62b20f7000 568
Mike Fiore 9:ff62b20f7000 569 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
Jason Reiss 36:b586cd6e91f3 570 logWarning("Join Backoff until next join %lu ms", _dot->getNextTxMs());
Mike Fiore 9:ff62b20f7000 571 _serial.writef("Network Not Joined\r\n");
Mike Fiore 9:ff62b20f7000 572 _serial.writef(error);
Mike Fiore 9:ff62b20f7000 573 }
Mike Fiore 9:ff62b20f7000 574 }
Mike Fiore 1:e52ae6584f1c 575 }
Mike Fiore 1:e52ae6584f1c 576
Jason Reiss 34:3b696c2b1e4b 577 if (CommandTerminal::Dot()->getTestModeEnabled() && _dot->getNetworkJoinStatus()) {
Jason Reiss 34:3b696c2b1e4b 578 while (CommandTerminal::Dot()->getTestModeEnabled() && !_events->PacketReceived) {
Jason Reiss 34:3b696c2b1e4b 579 std::vector<uint8_t> data;
Jason Reiss 34:3b696c2b1e4b 580 CommandTerminal::Dot()->send(data, false);
Jason Reiss 34:3b696c2b1e4b 581 osDelay(5000);
Jason Reiss 34:3b696c2b1e4b 582 }
Jason Reiss 34:3b696c2b1e4b 583 }
Jason Reiss 34:3b696c2b1e4b 584
Mike Fiore 9:ff62b20f7000 585 if (_dot->getJoinMode() == mDot::PEER_TO_PEER) {
Mike Fiore 9:ff62b20f7000 586 peer_to_peer = true;
Jason Reiss 27:5fafd3b26ac3 587 Fota::getInstance()->enable(false);
Jason Reiss 27:5fafd3b26ac3 588 CommandTerminal::Dot()->clearMacCommands();
Jason Reiss 27:5fafd3b26ac3 589 CommandTerminal::Dot()->setTxDataRate(CommandTerminal::Dot()->getTxDataRate());
Mike Fiore 9:ff62b20f7000 590 } else {
Mike Fiore 9:ff62b20f7000 591 peer_to_peer = false;
Mike Fiore 9:ff62b20f7000 592 }
Mike Fiore 1:e52ae6584f1c 593 //Run terminal session
Mike Fiore 1:e52ae6584f1c 594 while (running) {
Jason Reiss 28:c222ca8383f4 595
Jason Reiss 34:3b696c2b1e4b 596 if (_events != NULL && CommandTerminal::Dot()->getTestModeEnabled() && !_serial.escaped()) {
Jason Reiss 34:3b696c2b1e4b 597 if (_dot->getNextTxMs() > 0) {
Jason Reiss 34:3b696c2b1e4b 598 osDelay(2000);
Jason Reiss 34:3b696c2b1e4b 599 } else if (!_dot->getNetworkJoinStatus() && _dot->getJoinMode() == mDot::OTA) {
Jason Reiss 34:3b696c2b1e4b 600 if (_dot->joinNetworkOnce() != mDot::MDOT_OK) {
Jason Reiss 34:3b696c2b1e4b 601 serial_data_mode = false;
Jason Reiss 34:3b696c2b1e4b 602 _mode = mDot::COMMAND_MODE;
Jason Reiss 34:3b696c2b1e4b 603
Jason Reiss 34:3b696c2b1e4b 604 logWarning("Start Up Mode set to SERIAL_MODE, but join failed.");
Jason Reiss 34:3b696c2b1e4b 605 _serial.writef("Network Not Joined\r\n");
Jason Reiss 34:3b696c2b1e4b 606 _serial.writef(error);
Jason Reiss 34:3b696c2b1e4b 607 }
Jason Reiss 34:3b696c2b1e4b 608 } else if (_events->PacketReceived) {
Jason Reiss 34:3b696c2b1e4b 609 _events->handleTestModePacket();
Jason Reiss 34:3b696c2b1e4b 610 _events->PacketReceived = false;
Jason Reiss 34:3b696c2b1e4b 611
Jason Reiss 34:3b696c2b1e4b 612 } else {
Jason Reiss 34:3b696c2b1e4b 613 while (CommandTerminal::Dot()->getTestModeEnabled() && !_events->PacketReceived && !_serial.escaped()) {
Jason Reiss 34:3b696c2b1e4b 614 std::vector<uint8_t> data;
Jason Reiss 34:3b696c2b1e4b 615 CommandTerminal::Dot()->send(data, false);
Jason Reiss 34:3b696c2b1e4b 616 osDelay(5000);
Jason Reiss 34:3b696c2b1e4b 617 }
Jason Reiss 34:3b696c2b1e4b 618 }
Jason Reiss 34:3b696c2b1e4b 619 continue;
Jason Reiss 28:c222ca8383f4 620 }
Jason Reiss 28:c222ca8383f4 621
Jason Reiss 28:c222ca8383f4 622 // wait for input to reduce at command idle current
Mike Fiore 9:ff62b20f7000 623 while (!readable() || _mode == mDot::SERIAL_MODE) {
Mike Fiore 14:f9a77400b622 624 if (!join_canceled && _autoOTAEnabled) {
Mike Fiore 9:ff62b20f7000 625 join_canceled = autoJoinCheck();
Mike Fiore 9:ff62b20f7000 626 if (join_canceled)
Mike Fiore 9:ff62b20f7000 627 command.clear();
Mike Fiore 9:ff62b20f7000 628 }
Mike Fiore 1:e52ae6584f1c 629
Mike Fiore 14:f9a77400b622 630 if (!_autoOTAEnabled || (!join_canceled && _autoOTAEnabled)) {
Mike Fiore 9:ff62b20f7000 631 switch (_mode) {
Mike Fiore 9:ff62b20f7000 632 case mDot::SERIAL_MODE:
Mike Fiore 9:ff62b20f7000 633 // signal wakeup, read serial and output to radio
Mike Fiore 9:ff62b20f7000 634 serialLoop();
Mike Fiore 9:ff62b20f7000 635 continue;
Mike Fiore 9:ff62b20f7000 636 break;
Mike Fiore 9:ff62b20f7000 637 default:
Mike Fiore 9:ff62b20f7000 638 break;
Mike Fiore 9:ff62b20f7000 639 }
Mike Fiore 1:e52ae6584f1c 640 }
Mike Fiore 9:ff62b20f7000 641
Mike Fiore 9:ff62b20f7000 642 ch = '\0';
Mike Fiore 1:e52ae6584f1c 643
Jason Reiss 27:5fafd3b26ac3 644 if (_mode != mDot::SERIAL_MODE) {
Jason Reiss 28:c222ca8383f4 645 ThisThread::sleep_for(10ms);
Jason Reiss 27:5fafd3b26ac3 646 }
Mike Fiore 9:ff62b20f7000 647 _serial.escaped();
Mike Fiore 9:ff62b20f7000 648 }
Mike Fiore 1:e52ae6584f1c 649
Mike Fiore 1:e52ae6584f1c 650 // read characters
Mike Fiore 1:e52ae6584f1c 651 if (readable()) {
Mike Fiore 1:e52ae6584f1c 652 ch = read();
Mike Fiore 1:e52ae6584f1c 653
Mike Fiore 4:666017851052 654 if (ch == '\b' || ch == 0x7f) {
Mike Fiore 1:e52ae6584f1c 655 if (!command.empty()) {
Mike Fiore 1:e52ae6584f1c 656 writef("\b \b");
Mike Fiore 1:e52ae6584f1c 657 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 658 }
Mike Fiore 1:e52ae6584f1c 659 continue;
Mike Fiore 4:666017851052 660 } else if (ch == 0x1b || ch == 0x09) {
Mike Fiore 4:666017851052 661 osDelay(20);
Jason Reiss 36:b586cd6e91f3 662
Jason Reiss 36:b586cd6e91f3 663 #if defined(MTS_DOT_COMMAND_HISTORY_FEATURE)
Mike Fiore 4:666017851052 664 // catch escape sequence, or tab
Mike Fiore 9:ff62b20f7000 665 char ch1 = 0x00, ch2 = 0x00;
Mike Fiore 4:666017851052 666
Mike Fiore 4:666017851052 667 if (readable()) {
Mike Fiore 4:666017851052 668 ch1 = read();
Mike Fiore 4:666017851052 669 if (readable())
Mike Fiore 4:666017851052 670 ch2 = read();
Mike Fiore 4:666017851052 671
Mike Fiore 4:666017851052 672 if (ch1 == 0x5b && ch2 == 0x41) {
Mike Fiore 4:666017851052 673 // up key
Mike Fiore 9:ff62b20f7000 674 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 675 writef("\b \b");
Mike Fiore 4:666017851052 676 }
Mike Fiore 4:666017851052 677 if (history.size() > 0) {
Mike Fiore 9:ff62b20f7000 678 if (++history_index >= int(history.size() - 1))
Mike Fiore 4:666017851052 679 history_index = history.size() - 1;
Mike Fiore 4:666017851052 680
Mike Fiore 4:666017851052 681 command = history[history_index];
Jason Reiss 36:b586cd6e91f3 682
Jason Reiss 36:b586cd6e91f3 683 if (command.size() > 128) {
Jason Reiss 36:b586cd6e91f3 684 for (size_t i = 0; i < command.size(); i++) {
Jason Reiss 36:b586cd6e91f3 685 writef("%c", command[i]);
Jason Reiss 36:b586cd6e91f3 686 }
Jason Reiss 36:b586cd6e91f3 687 } else {
Jason Reiss 36:b586cd6e91f3 688 writef("%s", command.c_str());
Jason Reiss 36:b586cd6e91f3 689 }
Mike Fiore 4:666017851052 690 } else {
Mike Fiore 4:666017851052 691 command.clear();
Mike Fiore 4:666017851052 692 }
Mike Fiore 4:666017851052 693 } else if (ch1 == 0x5b && ch2 == 0x42) {
Mike Fiore 4:666017851052 694
Mike Fiore 4:666017851052 695 // down key
Mike Fiore 9:ff62b20f7000 696 for (size_t i = 0; i < command.size() + 1; i++) {
Mike Fiore 4:666017851052 697 writef("\b \b");
Mike Fiore 4:666017851052 698 }
Mike Fiore 4:666017851052 699
Mike Fiore 4:666017851052 700 if (--history_index < 0) {
Mike Fiore 4:666017851052 701 history_index = -1;
Mike Fiore 4:666017851052 702 command.clear();
Mike Fiore 4:666017851052 703 } else {
Mike Fiore 4:666017851052 704 command = history[history_index];
Jason Reiss 36:b586cd6e91f3 705 if (command.size() > 128) {
Jason Reiss 36:b586cd6e91f3 706 for (size_t i = 0; i < command.size(); i++) {
Jason Reiss 36:b586cd6e91f3 707 writef("%c", command[i]);
Jason Reiss 36:b586cd6e91f3 708 }
Jason Reiss 36:b586cd6e91f3 709
Jason Reiss 36:b586cd6e91f3 710 } else {
Jason Reiss 36:b586cd6e91f3 711 writef("%s", command.c_str());
Jason Reiss 36:b586cd6e91f3 712 }
Mike Fiore 4:666017851052 713 }
Mike Fiore 4:666017851052 714 }
Jason Reiss 36:b586cd6e91f3 715 }
Mike Fiore 14:f9a77400b622 716 #endif
Mike Fiore 9:ff62b20f7000 717 while (readable())
Mike Fiore 9:ff62b20f7000 718 read();
Mike Fiore 4:666017851052 719 continue;
Mike Fiore 1:e52ae6584f1c 720 } else {
Mike Fiore 1:e52ae6584f1c 721 command += ch;
Mike Fiore 1:e52ae6584f1c 722 }
Mike Fiore 1:e52ae6584f1c 723
Mike Fiore 1:e52ae6584f1c 724 // echo chars if enabled
Mike Fiore 1:e52ae6584f1c 725 if (echo && !(ch == '\r' || ch == '\n'))
Mike Fiore 1:e52ae6584f1c 726 writef("%c", ch);
Mike Fiore 1:e52ae6584f1c 727 }
Mike Fiore 1:e52ae6584f1c 728
Mike Fiore 1:e52ae6584f1c 729 // look for end of command line
Mike Fiore 1:e52ae6584f1c 730 if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 731 // remove new line or cr character
Mike Fiore 1:e52ae6584f1c 732 command.erase(command.size() - 1);
Mike Fiore 1:e52ae6584f1c 733 write("\r"); // match standard modem output
Mike Fiore 1:e52ae6584f1c 734 write(newline);
Mike Fiore 1:e52ae6584f1c 735 } else {
Mike Fiore 1:e52ae6584f1c 736 continue;
Mike Fiore 1:e52ae6584f1c 737 }
Mike Fiore 1:e52ae6584f1c 738
Mike Fiore 1:e52ae6584f1c 739 // trim whitespace from command
Mike Fiore 1:e52ae6584f1c 740 mts::Text::trim(command, "\r\n\t ");
Mike Fiore 1:e52ae6584f1c 741
Mike Fiore 1:e52ae6584f1c 742 if (command.size() < 1) {
Mike Fiore 1:e52ae6584f1c 743 command.clear();
Mike Fiore 1:e52ae6584f1c 744 continue;
Mike Fiore 1:e52ae6584f1c 745 }
Mike Fiore 1:e52ae6584f1c 746
Jason Reiss 36:b586cd6e91f3 747 #if defined(USE_PIN_PACKET_RX)
Jason Reiss 36:b586cd6e91f3 748 _packet_rx_pin = GPIO_PIN_RESET;
Jason Reiss 36:b586cd6e91f3 749 #endif
Jason Reiss 27:5fafd3b26ac3 750 command_processing = true;
Jason Reiss 27:5fafd3b26ac3 751
Mike Fiore 1:e52ae6584f1c 752 // parse command and args
Mike Fiore 1:e52ae6584f1c 753 args.clear();
Mike Fiore 1:e52ae6584f1c 754
Mike Fiore 1:e52ae6584f1c 755 // find first '=' character
Mike Fiore 1:e52ae6584f1c 756 size_t delim_index = command.find("=");
Mike Fiore 1:e52ae6584f1c 757 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 758 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 759 } else {
Mike Fiore 1:e52ae6584f1c 760 // find first ' ' character
Mike Fiore 1:e52ae6584f1c 761 delim_index = command.find(" ");
Mike Fiore 1:e52ae6584f1c 762 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 763 args.push_back(command.substr(0, delim_index));
Mike Fiore 1:e52ae6584f1c 764 } else {
Mike Fiore 1:e52ae6584f1c 765 args.push_back(command);
Mike Fiore 1:e52ae6584f1c 766 }
Mike Fiore 1:e52ae6584f1c 767 }
Mike Fiore 1:e52ae6584f1c 768
Mike Fiore 1:e52ae6584f1c 769 if (delim_index != std::string::npos) {
Mike Fiore 1:e52ae6584f1c 770 std::vector<std::string> params = mts::Text::split(command.substr(delim_index + 1), ",");
Mike Fiore 1:e52ae6584f1c 771 args.insert(args.end(), params.begin(), params.end());
Mike Fiore 1:e52ae6584f1c 772 }
Mike Fiore 1:e52ae6584f1c 773
Mike Fiore 1:e52ae6584f1c 774 args[0] = mts::Text::toUpper(args[0]);
Jason Reiss 28:c222ca8383f4 775 bool handled = false;
Mike Fiore 1:e52ae6584f1c 776
Mike Fiore 1:e52ae6584f1c 777 // print help
Mike Fiore 1:e52ae6584f1c 778 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) {
Jason Reiss 28:c222ca8383f4 779 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 780 printHelp();
Jason Reiss 28:c222ca8383f4 781 #endif
Mike Fiore 1:e52ae6584f1c 782 command.clear();
Jason Reiss 28:c222ca8383f4 783 handled = true;
Jason Reiss 28:c222ca8383f4 784 } else if (args[0].find("AT") == 0) {
Jason Reiss 28:c222ca8383f4 785 const CommandDefinition* def = NULL; // Command to handle if matched
Jason Reiss 28:c222ca8383f4 786 char variant = '\0'; // Variant character
Jason Reiss 28:c222ca8383f4 787 for (int d = 0; (d < CMD_DEFS_COUNT) && (def == NULL); ++d) {
Jason Reiss 28:c222ca8383f4 788 size_t label_size = 2 + strlen(cmd_defs[d].label);
Jason Reiss 28:c222ca8383f4 789 if (args[0].find(cmd_defs[d].label) == 2) {
Jason Reiss 28:c222ca8383f4 790 // Label found following "AT"
Jason Reiss 28:c222ca8383f4 791 for (int v = 0; v < CMD_DEFS_VARIANT_SIZE; ++v) {
Jason Reiss 28:c222ca8383f4 792 if ((args[0][label_size] == cmd_defs[d].var[v]) &&
Jason Reiss 28:c222ca8383f4 793 (args[0][label_size] == '\0' || args[0][label_size + 1] == '\0')) {
Jason Reiss 28:c222ca8383f4 794 // Check for variant characters following label, this includes a NULL
Jason Reiss 28:c222ca8383f4 795 def = &cmd_defs[d];
Jason Reiss 28:c222ca8383f4 796 variant = cmd_defs[d].var[v];
Jason Reiss 28:c222ca8383f4 797 break;
Jason Reiss 28:c222ca8383f4 798 }
Mike Fiore 14:f9a77400b622 799 }
Mike Fiore 4:666017851052 800 }
Mike Fiore 4:666017851052 801 }
Jason Reiss 28:c222ca8383f4 802 if (def != NULL) {
Jason Reiss 28:c222ca8383f4 803 handled = true;
Jason Reiss 28:c222ca8383f4 804 if (args.size() == 2 && args[1].length() == 1 && args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 805 handled = false;
Jason Reiss 28:c222ca8383f4 806 } else if (args.size() - 1 > def->max_args) {
Jason Reiss 28:c222ca8383f4 807 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 808 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 809 #endif
Jason Reiss 28:c222ca8383f4 810 write(error);
Jason Reiss 28:c222ca8383f4 811 } else {
Jason Reiss 28:c222ca8383f4 812 switch (def->id) {
Jason Reiss 28:c222ca8383f4 813 case CommandFactory::eAT:
Jason Reiss 28:c222ca8383f4 814 write(done);
Jason Reiss 28:c222ca8383f4 815 break;
Jason Reiss 28:c222ca8383f4 816 case CommandFactory::eATE:
Jason Reiss 28:c222ca8383f4 817 if (variant == '1' || variant == '0') {
Jason Reiss 28:c222ca8383f4 818 _dot->setEcho(variant == '1');
Jason Reiss 28:c222ca8383f4 819 echo = _dot->getEcho();
Jason Reiss 28:c222ca8383f4 820 } else {
Jason Reiss 28:c222ca8383f4 821 writef("%d\r\n", _dot->getEcho());
Jason Reiss 28:c222ca8383f4 822 }
Jason Reiss 28:c222ca8383f4 823 write(done);
Jason Reiss 28:c222ca8383f4 824 break;
Jason Reiss 28:c222ca8383f4 825 case CommandFactory::eATVERBOSE:
Jason Reiss 28:c222ca8383f4 826 if (variant == '1' || variant == '0') {
Jason Reiss 28:c222ca8383f4 827 _dot->setVerbose(variant == '1');
Jason Reiss 28:c222ca8383f4 828 } else {
Jason Reiss 28:c222ca8383f4 829 writef("%d\r\n", _dot->getVerbose());
Jason Reiss 28:c222ca8383f4 830 }
Jason Reiss 28:c222ca8383f4 831 write(done);
Jason Reiss 28:c222ca8383f4 832 break;
Jason Reiss 28:c222ca8383f4 833 case CommandFactory::eATK:
Jason Reiss 28:c222ca8383f4 834 if (variant == '3' || variant == '0') {
Jason Reiss 28:c222ca8383f4 835 _dot->setFlowControl(variant == '3');
Jason Reiss 28:c222ca8383f4 836 } else {
Jason Reiss 28:c222ca8383f4 837 writef("%d\r\n", (_dot->getFlowControl() ? 3 : 0));
Jason Reiss 28:c222ca8383f4 838 }
Jason Reiss 28:c222ca8383f4 839 write(done);
Jason Reiss 28:c222ca8383f4 840 break;
Jason Reiss 28:c222ca8383f4 841 case CommandFactory::eURC:
Jason Reiss 28:c222ca8383f4 842 if (args.size() == 1) {
Jason Reiss 28:c222ca8383f4 843 writef("%d\r\n", urc_enabled);
Jason Reiss 28:c222ca8383f4 844 write(done);
Jason Reiss 28:c222ca8383f4 845 } else if (args[1].length() == 1) {
Jason Reiss 28:c222ca8383f4 846 if (args[1][0] != '?' && args[1][0] != '0' && args[1][0] != '1') {
Jason Reiss 28:c222ca8383f4 847 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 848 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 849 #endif
Jason Reiss 28:c222ca8383f4 850 write(error);
Jason Reiss 28:c222ca8383f4 851 } else if (args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 852 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 853 write("(0:disable,1:enable)\r\n");
Jason Reiss 28:c222ca8383f4 854 write(done);
Jason Reiss 28:c222ca8383f4 855 #else
Jason Reiss 28:c222ca8383f4 856 write(error);
Jason Reiss 28:c222ca8383f4 857 #endif
Jason Reiss 28:c222ca8383f4 858 } else {
Jason Reiss 28:c222ca8383f4 859 urc_enabled = (args[1][0] == '1');
Jason Reiss 28:c222ca8383f4 860 write(done);
Jason Reiss 28:c222ca8383f4 861 }
Jason Reiss 28:c222ca8383f4 862 } else {
Jason Reiss 28:c222ca8383f4 863 write(error);
Jason Reiss 28:c222ca8383f4 864 }
Jason Reiss 28:c222ca8383f4 865 break;
Jason Reiss 28:c222ca8383f4 866 case CommandFactory::eLW:
Jason Reiss 28:c222ca8383f4 867 writef("%s\r\n", _dot->getMACVersion());
Jason Reiss 28:c222ca8383f4 868 write(done);
Jason Reiss 28:c222ca8383f4 869 break;
Jason Reiss 28:c222ca8383f4 870 case CommandFactory::eMEM:
Jason Reiss 28:c222ca8383f4 871 free_mem();
Jason Reiss 28:c222ca8383f4 872 write(done);
Jason Reiss 28:c222ca8383f4 873 break;
Jason Reiss 28:c222ca8383f4 874 case CommandFactory::eSD:
Jason Reiss 28:c222ca8383f4 875 if (_dot->getNetworkJoinStatus()) {
Jason Reiss 28:c222ca8383f4 876 logDebug("Enter Serial Mode");
Jason Reiss 28:c222ca8383f4 877 write(connect);
Jason Reiss 28:c222ca8383f4 878 serial_data_mode = true;
Jason Reiss 28:c222ca8383f4 879 _serialp->clearEscaped();
Jason Reiss 28:c222ca8383f4 880 _mode = mDot::SERIAL_MODE;
Jason Reiss 28:c222ca8383f4 881 } else {
Jason Reiss 28:c222ca8383f4 882 logDebug("Network Not Joined");
Jason Reiss 28:c222ca8383f4 883 write("Network Not Joined\r\n");
Jason Reiss 28:c222ca8383f4 884 write(error);
Jason Reiss 28:c222ca8383f4 885 }
Jason Reiss 28:c222ca8383f4 886 break;
Jason Reiss 28:c222ca8383f4 887 case CommandFactory::eATW:
Jason Reiss 28:c222ca8383f4 888 if (!_dot->saveConfig()) {
Jason Reiss 28:c222ca8383f4 889 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 890 write("Failed to save to flash");
Jason Reiss 28:c222ca8383f4 891 #endif
Jason Reiss 28:c222ca8383f4 892 write(error);
Jason Reiss 28:c222ca8383f4 893 } else {
Jason Reiss 28:c222ca8383f4 894 write(done);
Jason Reiss 28:c222ca8383f4 895 }
Jason Reiss 28:c222ca8383f4 896 break;
Jason Reiss 36:b586cd6e91f3 897 #if defined(TARGET_MTS_MDOT_F411RE) || defined(TARGET_XDOT_L151CC) || defined(TARGET_XDOT_MAX32670)
Jason Reiss 28:c222ca8383f4 898 case CommandFactory::eATWP:
Jason Reiss 28:c222ca8383f4 899 if (!_dot->saveProtectedConfig()) {
Jason Reiss 28:c222ca8383f4 900 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 901 write("Failed to save to flash");
Jason Reiss 28:c222ca8383f4 902 #endif
Jason Reiss 28:c222ca8383f4 903 write(error);
Jason Reiss 28:c222ca8383f4 904 } else {
Jason Reiss 28:c222ca8383f4 905 write(done);
Jason Reiss 28:c222ca8383f4 906 }
Jason Reiss 28:c222ca8383f4 907 break;
Jason Reiss 36:b586cd6e91f3 908 #endif
Jason Reiss 28:c222ca8383f4 909 case CommandFactory::eSS:
Jason Reiss 28:c222ca8383f4 910 _dot->saveNetworkSession();
Jason Reiss 28:c222ca8383f4 911 write(done);
Jason Reiss 28:c222ca8383f4 912 break;
Jason Reiss 28:c222ca8383f4 913 case CommandFactory::eDP:
Jason Reiss 34:3b696c2b1e4b 914 writef("%d\r\n",
Jason Reiss 34:3b696c2b1e4b 915 _dot->getDataPending() ||
Jason Reiss 34:3b696c2b1e4b 916 _dot->hasMacCommands() ||
Jason Reiss 34:3b696c2b1e4b 917 _dot->getAckRequested());
Jason Reiss 28:c222ca8383f4 918 write(done);
Jason Reiss 28:c222ca8383f4 919 break;
Jason Reiss 28:c222ca8383f4 920 case CommandFactory::eSLEEP: {
Jason Reiss 28:c222ca8383f4 921 bool temp_sleep_standby;
Jason Reiss 28:c222ca8383f4 922 bool valid = false;
Jason Reiss 28:c222ca8383f4 923 if ((args.size() > 1) && (args[1].length() == 1)) {
Jason Reiss 28:c222ca8383f4 924 if ((args[1][0] != '?' && args[1][0] != '0' && args[1][0] != '1')) {
Jason Reiss 28:c222ca8383f4 925 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 926 write("Invalid argument\r\n");
Jason Reiss 28:c222ca8383f4 927 #endif
Jason Reiss 28:c222ca8383f4 928 write(error);
Jason Reiss 28:c222ca8383f4 929 } else if (args[1][0] == '?') {
Jason Reiss 28:c222ca8383f4 930 #if MTS_CMD_TERM_VERBOSE
Jason Reiss 28:c222ca8383f4 931 write("(0:deepsleep,1:sleep)\r\n");
Jason Reiss 28:c222ca8383f4 932 write(done);
Jason Reiss 28:c222ca8383f4 933 #else
Jason Reiss 28:c222ca8383f4 934 write(error);
Jason Reiss 28:c222ca8383f4 935 #endif
Jason Reiss 28:c222ca8383f4 936 } else {
Jason Reiss 28:c222ca8383f4 937 valid = true;
Jason Reiss 28:c222ca8383f4 938 temp_sleep_standby = (args[1][0] == '0');
Jason Reiss 28:c222ca8383f4 939 }
Jason Reiss 28:c222ca8383f4 940 } else if (args.size() == 1) {
Jason Reiss 28:c222ca8383f4 941 valid = true;
Jason Reiss 28:c222ca8383f4 942 temp_sleep_standby = _sleep_standby;
Jason Reiss 28:c222ca8383f4 943 } else {
Jason Reiss 28:c222ca8383f4 944 write(error);
Jason Reiss 28:c222ca8383f4 945 }
Jason Reiss 28:c222ca8383f4 946
Jason Reiss 28:c222ca8383f4 947 if (valid) {
Jason Reiss 28:c222ca8383f4 948 if (!_dot->getIsIdle()) {
Jason Reiss 28:c222ca8383f4 949 write("Dot is not idle\r\n");
Jason Reiss 28:c222ca8383f4 950 write(error);
Jason Reiss 28:c222ca8383f4 951 } else {
Jason Reiss 28:c222ca8383f4 952 _sleep_standby = temp_sleep_standby;
Jason Reiss 28:c222ca8383f4 953 #if defined(TARGET_MTS_MDOT_F411RE)
Jason Reiss 28:c222ca8383f4 954 //Read the board ID. If all 0's, it is revision B. This hardware does not support deep sleep.
Jason Reiss 28:c222ca8383f4 955 DigitalIn ID2(PC_4);
Jason Reiss 28:c222ca8383f4 956 DigitalIn ID1(PC_5);
Jason Reiss 28:c222ca8383f4 957 DigitalIn ID0(PD_2);
Jason Reiss 28:c222ca8383f4 958 if(ID2 == 0 && ID1 == 0 && ID0 == 0 && _sleep_standby == 1){
Jason Reiss 28:c222ca8383f4 959 _sleep_standby = 0;
Jason Reiss 28:c222ca8383f4 960 logWarning("This hardware version does not support deep sleep. Using sleep mode instead.");
Jason Reiss 28:c222ca8383f4 961 }
Jason Reiss 28:c222ca8383f4 962 #endif
Jason Reiss 28:c222ca8383f4 963 write(done);
Jason Reiss 28:c222ca8383f4 964 if (_dot->getBaud() < 9600)
Jason Reiss 28:c222ca8383f4 965 osDelay(20);
Jason Reiss 28:c222ca8383f4 966 else if (_dot->getBaud() > 57600)
Jason Reiss 28:c222ca8383f4 967 osDelay(2);
Jason Reiss 28:c222ca8383f4 968 else
Jason Reiss 28:c222ca8383f4 969 osDelay(5);
Jason Reiss 28:c222ca8383f4 970 this->sleep(_sleep_standby);
Jason Reiss 28:c222ca8383f4 971 osDelay(1);
Jason Reiss 28:c222ca8383f4 972 }
Jason Reiss 28:c222ca8383f4 973 }
Jason Reiss 28:c222ca8383f4 974 break;
Jason Reiss 28:c222ca8383f4 975 }
Jason Reiss 28:c222ca8383f4 976 default:
Jason Reiss 28:c222ca8383f4 977 handled = false;
Jason Reiss 28:c222ca8383f4 978 // Unhandled command
Jason Reiss 28:c222ca8383f4 979 // Will only reach here if the table contains commands that do not have explicit cases
Jason Reiss 28:c222ca8383f4 980 break;
Jason Reiss 28:c222ca8383f4 981 }
Jason Reiss 28:c222ca8383f4 982 }
Jason Reiss 36:b586cd6e91f3 983
Jason Reiss 36:b586cd6e91f3 984 #if defined(MTS_DOT_ENABLE_LORAWAN_TESTMODE)
Jason Reiss 28:c222ca8383f4 985 } else if (args[0].find("AT+TM!") == 0 && args[0].length() == 6) {
Jason Reiss 28:c222ca8383f4 986 handled = true;
Jason Reiss 28:c222ca8383f4 987 if ((args.size() > 1) && (args[1].length() == 1)) {
Jason Reiss 28:c222ca8383f4 988 if (args[1][0] == '0' || args[1][0] == '1') {
Jason Reiss 28:c222ca8383f4 989 _dot->setTestModeEnabled(args[1][0] == '1');
Jason Reiss 34:3b696c2b1e4b 990 _dot->saveConfig();
Jason Reiss 28:c222ca8383f4 991 write(done);
Jason Reiss 28:c222ca8383f4 992 } else {
Jason Reiss 28:c222ca8383f4 993 write(error);
Jason Reiss 28:c222ca8383f4 994 }
Jason Reiss 28:c222ca8383f4 995 } else {
Jason Reiss 28:c222ca8383f4 996 writef("%d\r\n", _dot->getTestModeEnabled());
Jason Reiss 28:c222ca8383f4 997 write(done);
Jason Reiss 28:c222ca8383f4 998 }
Jason Reiss 28:c222ca8383f4 999 #endif
Jason Reiss 28:c222ca8383f4 1000 }
Jason Reiss 28:c222ca8383f4 1001 }
Jason Reiss 28:c222ca8383f4 1002
Jason Reiss 28:c222ca8383f4 1003 if (!handled) {
Mike Fiore 1:e52ae6584f1c 1004 bool found = false;
Mike Fiore 1:e52ae6584f1c 1005 bool query = false;
Mike Fiore 1:e52ae6584f1c 1006
Mike Fiore 1:e52ae6584f1c 1007 std::string lookfor = args[0];
Mike Fiore 1:e52ae6584f1c 1008
Jason Reiss 28:c222ca8383f4 1009 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 1010 // per command help
Jason Reiss 28:c222ca8383f4 1011 if ((args[0].find("?") == 0 || args[0].find("HELP") == 0)) {
Mike Fiore 1:e52ae6584f1c 1012 lookfor = mts::Text::toUpper(args[1]);
Jason Reiss 28:c222ca8383f4 1013 }
Jason Reiss 28:c222ca8383f4 1014 #endif
Mike Fiore 1:e52ae6584f1c 1015 // trim off any trailing '?' and mark as a query command
Mike Fiore 1:e52ae6584f1c 1016 if (args[0].rfind("?") == args[0].length() - 1) {
Mike Fiore 1:e52ae6584f1c 1017 query = true;
Mike Fiore 1:e52ae6584f1c 1018 lookfor = args[0].substr(0, args[0].length() - 1);
Mike Fiore 1:e52ae6584f1c 1019 }
Mike Fiore 1:e52ae6584f1c 1020
Mike Fiore 1:e52ae6584f1c 1021 // search for command
jenkins@jenkinsdm1 18:63f098f042b2 1022 Command *cmd = NULL;
Jason Reiss 27:5fafd3b26ac3 1023 for (int i = 0; i < CommandFactory::NUMBER_OF_CMDS; i++) {
Jason Reiss 27:5fafd3b26ac3 1024 cmd = CommandFactory::Create(static_cast<CommandFactory::CmdId_t>(i));
Mike Fiore 1:e52ae6584f1c 1025
Mike Fiore 1:e52ae6584f1c 1026 // match CMD or CMD? syntax if command is queryable
jenkins@jenkinsdm1 18:63f098f042b2 1027 if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) {
Mike Fiore 1:e52ae6584f1c 1028 found = true;
Jason Reiss 28:c222ca8383f4 1029 _errorMessage.clear();
Jason Reiss 28:c222ca8383f4 1030 #if MTS_CMD_TERM_VERBOSE
Mike Fiore 1:e52ae6584f1c 1031 if (args[0] == "HELP") {
jenkins@jenkinsdm1 18:63f098f042b2 1032 writef("%s%s", cmd->help().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 1033 write(done);
Mike Fiore 1:e52ae6584f1c 1034 }
Mike Fiore 1:e52ae6584f1c 1035 else if (args.size() > 1 && args[1] == "?") {
jenkins@jenkinsdm1 18:63f098f042b2 1036 writef("%s%s", cmd->usage().c_str(), newline);
Mike Fiore 1:e52ae6584f1c 1037 write(done);
jenkins@jenkinsdm1 18:63f098f042b2 1038 } else if (!cmd->verify(args)) {
Jason Reiss 28:c222ca8383f4 1039 #else
Jason Reiss 28:c222ca8383f4 1040 if (args.size() > 1 && args[1] == "?") {
Jason Reiss 28:c222ca8383f4 1041 write(error);
Jason Reiss 28:c222ca8383f4 1042 } else if (!cmd->verify(args)) {
Jason Reiss 28:c222ca8383f4 1043 #endif
Jason Reiss 28:c222ca8383f4 1044 if (!_errorMessage.empty()) {
Jason Reiss 28:c222ca8383f4 1045 writef("%s%s", _errorMessage.c_str(), newline);
Jason Reiss 28:c222ca8383f4 1046 }
Jason Reiss 28:c222ca8383f4 1047 write(error);
Mike Fiore 1:e52ae6584f1c 1048 } else {
Jason Reiss 28:c222ca8383f4 1049 _errorMessage.clear();
jenkins@jenkinsdm1 18:63f098f042b2 1050 if (cmd->action(args) == 0) {
Mike Fiore 1:e52ae6584f1c 1051 writef("%s", done);
Mike Fiore 1:e52ae6584f1c 1052 } else {
Jason Reiss 28:c222ca8383f4 1053 // Action was not successful
Jason Reiss 28:c222ca8383f4 1054 if (_errorMessage.empty()) {
Jason Reiss 28:c222ca8383f4 1055 // If no error message was set, check for error recorded in mdot
Jason Reiss 28:c222ca8383f4 1056 std::string dot_error = _dot->getLastError();
Jason Reiss 28:c222ca8383f4 1057 if (!dot_error.empty()) {
Jason Reiss 28:c222ca8383f4 1058 writef("%s%s", dot_error.c_str(), newline);
Jason Reiss 28:c222ca8383f4 1059 }
Jason Reiss 28:c222ca8383f4 1060 } else {
Jason Reiss 28:c222ca8383f4 1061 // Command set an error message
Jason Reiss 28:c222ca8383f4 1062 writef("%s%s", _errorMessage.c_str(), newline);
Jason Reiss 28:c222ca8383f4 1063 }
Jason Reiss 28:c222ca8383f4 1064 write(error);
Mike Fiore 1:e52ae6584f1c 1065 }
Mike Fiore 1:e52ae6584f1c 1066 }
Mike Fiore 1:e52ae6584f1c 1067 }
jenkins@jenkinsdm1 18:63f098f042b2 1068
jenkins@jenkinsdm1 18:63f098f042b2 1069 delete cmd;
Jason Reiss 28:c222ca8383f4 1070
Jason Reiss 28:c222ca8383f4 1071 if (found) {
Jason Reiss 28:c222ca8383f4 1072 break;
Jason Reiss 28:c222ca8383f4 1073 }
Mike Fiore 1:e52ae6584f1c 1074 }
Mike Fiore 1:e52ae6584f1c 1075
Mike Fiore 1:e52ae6584f1c 1076 if (!found) {
Jason Reiss 28:c222ca8383f4 1077 write(command_error);
Jason Reiss 28:c222ca8383f4 1078 write(error);
Mike Fiore 1:e52ae6584f1c 1079 }
Mike Fiore 1:e52ae6584f1c 1080 }
Mike Fiore 1:e52ae6584f1c 1081
Jason Reiss 36:b586cd6e91f3 1082 #if defined(USE_PIN_JOIN_STATUS)
Jason Reiss 27:5fafd3b26ac3 1083 _join_status_pin = CommandTerminal::Dot()->getNetworkJoinStatus();
Jason Reiss 36:b586cd6e91f3 1084 #endif
Jason Reiss 27:5fafd3b26ac3 1085 command_processing = false;
Jason Reiss 27:5fafd3b26ac3 1086
Jason Reiss 27:5fafd3b26ac3 1087
Jason Reiss 36:b586cd6e91f3 1088 #if defined(MTS_DOT_COMMAND_HISTORY_FEATURE)
Mike Fiore 4:666017851052 1089 if (history.size() == 0 || history.front() != command)
Mike Fiore 4:666017851052 1090 history.push_front(command);
Mike Fiore 4:666017851052 1091 history_index = -1;
Mike Fiore 1:e52ae6584f1c 1092 command.clear();
Mike Fiore 1:e52ae6584f1c 1093
Mike Fiore 4:666017851052 1094 while (history.size() > 10)
Mike Fiore 4:666017851052 1095 history.pop_back();
Mike Fiore 14:f9a77400b622 1096 #else
Mike Fiore 14:f9a77400b622 1097 command.clear();
Mike Fiore 14:f9a77400b622 1098 #endif
Mike Fiore 1:e52ae6584f1c 1099 }
Mike Fiore 1:e52ae6584f1c 1100 }
Mike Fiore 1:e52ae6584f1c 1101
Mike Fiore 1:e52ae6584f1c 1102 void CommandTerminal::sleep(bool standby) {
Jason Reiss 36:b586cd6e91f3 1103 #if defined(USE_PIN_ON_SLEEP)
Mike Fiore 1:e52ae6584f1c 1104 _xbee_on_sleep = GPIO_PIN_RESET;
Jason Reiss 36:b586cd6e91f3 1105 #endif
Jason Reiss 36:b586cd6e91f3 1106 _serial.rxClear();
Jason Reiss 36:b586cd6e91f3 1107 _serial.txClear();
Jason Reiss 36:b586cd6e91f3 1108
Jason Reiss 36:b586cd6e91f3 1109 LowPower::configExtGpios(_dot->getWakeMode(), _dot->getWakePin());
Jason Reiss 36:b586cd6e91f3 1110 _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby);
Mike Fiore 1:e52ae6584f1c 1111
Mike Fiore 4:666017851052 1112 _serial.rxClear();
Mike Fiore 4:666017851052 1113 _serial.txClear();
Mike Fiore 1:e52ae6584f1c 1114
Jason Reiss 23:4f0a981c0349 1115 Fota::getInstance()->fixEventQueue();
Mike Fiore 14:f9a77400b622 1116 }
Mike Fiore 14:f9a77400b622 1117
Mike Fiore 14:f9a77400b622 1118 std::string CommandTerminal::formatPacketData(const std::vector<uint8_t>& data, const uint8_t& format) {
Jason Reiss 23:4f0a981c0349 1119 switch(format) {
Jason Reiss 23:4f0a981c0349 1120 case(mDot::HEXADECIMAL):
Jason Reiss 23:4f0a981c0349 1121 return mts::Text::bin2hexString(data);
Jason Reiss 23:4f0a981c0349 1122
Jason Reiss 23:4f0a981c0349 1123 case(mDot::BINARY):
Jason Reiss 23:4f0a981c0349 1124 return std::string(data.begin(), data.end());
Jason Reiss 23:4f0a981c0349 1125
Jason Reiss 23:4f0a981c0349 1126 case(mDot::EXTENDED):
Jason Reiss 27:5fafd3b26ac3 1127 return formatPacket(data, false);
Jason Reiss 27:5fafd3b26ac3 1128
Jason Reiss 27:5fafd3b26ac3 1129 case(mDot::EXTENDED_HEX):
Jason Reiss 27:5fafd3b26ac3 1130 return formatPacket(data, true);
Jason Reiss 23:4f0a981c0349 1131
Jason Reiss 23:4f0a981c0349 1132 default:
Jason Reiss 23:4f0a981c0349 1133 return "";
Jason Reiss 23:4f0a981c0349 1134 }
Mike Fiore 1:e52ae6584f1c 1135 }
Mike Fiore 1:e52ae6584f1c 1136
Mike Fiore 1:e52ae6584f1c 1137 bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) {
Mike Fiore 1:e52ae6584f1c 1138 Timer timer;
Mike Fiore 1:e52ae6584f1c 1139
Mike Fiore 1:e52ae6584f1c 1140 timer.start();
Jason Reiss 36:b586cd6e91f3 1141 while (std::chrono::duration_cast<std::chrono::milliseconds>(timer.elapsed_time()).count() < timeout) {
Mike Fiore 1:e52ae6584f1c 1142
Mike Fiore 1:e52ae6584f1c 1143 if (dot != NULL) {
Mike Fiore 1:e52ae6584f1c 1144 if (wait == WAIT_SEND && (!dot->getIsTransmitting())) {
Mike Fiore 1:e52ae6584f1c 1145 return false;
Mike Fiore 1:e52ae6584f1c 1146 }
Mike Fiore 1:e52ae6584f1c 1147 }
Mike Fiore 1:e52ae6584f1c 1148
Mike Fiore 9:ff62b20f7000 1149 if (_serialp != NULL && _serialp->escaped()) {
Mike Fiore 9:ff62b20f7000 1150 _serialp->clearEscaped();
Mike Fiore 9:ff62b20f7000 1151 return true;
Mike Fiore 1:e52ae6584f1c 1152 }
Mike Fiore 1:e52ae6584f1c 1153
Jason Reiss 36:b586cd6e91f3 1154 ThisThread::sleep_for(10ms);
Mike Fiore 1:e52ae6584f1c 1155 }
Mike Fiore 1:e52ae6584f1c 1156
Mike Fiore 1:e52ae6584f1c 1157 return false;
Mike Fiore 1:e52ae6584f1c 1158 }
Mike Fiore 1:e52ae6584f1c 1159
Mike Fiore 9:ff62b20f7000 1160 void CommandTerminal::wakeup(void) {
Mike Fiore 9:ff62b20f7000 1161 }
Mike Fiore 9:ff62b20f7000 1162
Jason Reiss 27:5fafd3b26ac3 1163 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 1164 mDotEvent::RxDone(payload, size, rssi, snr, ctrl, slot);
Jason Reiss 27:5fafd3b26ac3 1165 logDebug("RadioEvent - RxDone");
Jason Reiss 27:5fafd3b26ac3 1166 }
Jason Reiss 27:5fafd3b26ac3 1167
Jason Reiss 27:5fafd3b26ac3 1168 void CommandTerminal::RadioEvent::RxTimeout(uint8_t slot) {
Jason Reiss 27:5fafd3b26ac3 1169 mDotEvent::RxTimeout(slot);
Jason Reiss 36:b586cd6e91f3 1170 #if defined(USE_PIN_PACKET_RX)
Jason Reiss 36:b586cd6e91f3 1171 _packet_rx_pin = GPIO_PIN_RESET;
Jason Reiss 36:b586cd6e91f3 1172 #endif
Jason Reiss 27:5fafd3b26ac3 1173 }
Jason Reiss 27:5fafd3b26ac3 1174
Jason Reiss 28:c222ca8383f4 1175 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 1176 mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, slot, retries, address, fcnt, dupRx);
Jason Reiss 27:5fafd3b26ac3 1177 _rxAddress = address;
Jason Reiss 28:c222ca8383f4 1178 _rxFcnt = fcnt;
Jason Reiss 27:5fafd3b26ac3 1179
jenkins@jenkinsdm1 18:63f098f042b2 1180 if(port == 200 || port == 201 || port == 202) {
Jason Reiss 23:4f0a981c0349 1181 Fota::getInstance()->processCmd(payload, port, size);
Jason Reiss 36:b586cd6e91f3 1182
Jason Reiss 27:5fafd3b26ac3 1183 if (CommandTerminal::Dot()->getRxOutput() < mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1184 return;
Jason Reiss 27:5fafd3b26ac3 1185 }
jenkins@jenkinsdm1 18:63f098f042b2 1186 }
Jason Reiss 36:b586cd6e91f3 1187 #if defined(USE_PIN_PACKET_RX)
Jason Reiss 36:b586cd6e91f3 1188 _packet_rx_pin = GPIO_PIN_SET;
Jason Reiss 36:b586cd6e91f3 1189 #endif
Jason Reiss 27:5fafd3b26ac3 1190
Jason Reiss 36:b586cd6e91f3 1191 if (CommandTerminal::Dot()->getSettings()->Test.TestMode) {
Jason Reiss 36:b586cd6e91f3 1192 if (AckReceived || (PacketReceived && (RxPort != 0 || RxPayloadSize == 0))) {
Jason Reiss 36:b586cd6e91f3 1193 _testDownlinkCounter++;
Jason Reiss 36:b586cd6e91f3 1194 logDebug("Incremented downlink cnt %d", _testDownlinkCounter);
Jason Reiss 36:b586cd6e91f3 1195 } else {
Jason Reiss 36:b586cd6e91f3 1196 logDebug("PacketRx did not increment cnt port: %d size: %d", RxPort, RxPayloadSize);
Jason Reiss 36:b586cd6e91f3 1197 logDebug("PacketRx ACK: %d PKT: %d", AckReceived, PacketReceived);
Jason Reiss 36:b586cd6e91f3 1198 }
Jason Reiss 36:b586cd6e91f3 1199 }
Jason Reiss 27:5fafd3b26ac3 1200
jenkins@jenkinsdm1 18:63f098f042b2 1201 if (serial_data_mode && port != 0) {
Mike Fiore 14:f9a77400b622 1202 if (size > 0) {
Jason Reiss 27:5fafd3b26ac3 1203 while (!CommandTerminal::Serial()->writeable()) ;
Jason Reiss 27:5fafd3b26ac3 1204 if (CommandTerminal::Dot()->getRxOutput() >= mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1205 formatPacket(RxPayload, size, CommandTerminal::Dot()->getRxOutput() == mDot::EXTENDED_HEX);
Jason Reiss 23:4f0a981c0349 1206 } else {
Jason Reiss 23:4f0a981c0349 1207 CommandTerminal::Serial()->write((char*) RxPayload, RxPayloadSize);
Jason Reiss 23:4f0a981c0349 1208 }
Mike Fiore 9:ff62b20f7000 1209 }
Jason Reiss 23:4f0a981c0349 1210 if (!CommandTerminal::Serial()->readable()
Jason Reiss 23:4f0a981c0349 1211 && (_dot->getAckRequested()
Jason Reiss 27:5fafd3b26ac3 1212 || (peer_to_peer == false && _dot->hasMacCommands()))
Jason Reiss 27:5fafd3b26ac3 1213 && (peer_to_peer || _dot->getClass() == "C" || _dot->getSettings()->Session.Class == lora::CLASS_B)) {
Mike Fiore 14:f9a77400b622 1214 _sendAck = true;
Mike Fiore 9:ff62b20f7000 1215 }
Jason Reiss 27:5fafd3b26ac3 1216 } else if (urc_enabled) {
Jason Reiss 27:5fafd3b26ac3 1217 if (!command_processing) {
Jason Reiss 27:5fafd3b26ac3 1218 while (!CommandTerminal::Serial()->writeable()) ;
Jason Reiss 27:5fafd3b26ac3 1219 if (CommandTerminal::Dot()->getRxOutput() >= mDot::EXTENDED) {
Jason Reiss 27:5fafd3b26ac3 1220 formatPacket(RxPayload, size, CommandTerminal::Dot()->getRxOutput() == mDot::EXTENDED_HEX);
Jason Reiss 27:5fafd3b26ac3 1221 } else {
Jason Reiss 28:c222ca8383f4 1222 CommandTerminal::Serial()->write("RECV\r\n", 6);
Jason Reiss 27:5fafd3b26ac3 1223 }
Jason Reiss 27:5fafd3b26ac3 1224 }
Mike Fiore 9:ff62b20f7000 1225 }
Mike Fiore 1:e52ae6584f1c 1226 }
Mike Fiore 9:ff62b20f7000 1227
Jason Reiss 28:c222ca8383f4 1228 void CommandTerminal::RadioEvent::handleTestModePacket() {
Jason Reiss 36:b586cd6e91f3 1229 #if defined(MTS_DOT_ENABLE_LORAWAN_TESTMODE)
Jason Reiss 36:b586cd6e91f3 1230 // static uint32_t last_rx_seq = 0; // For Class B tests
Jason Reiss 36:b586cd6e91f3 1231 // bool start_test = false;
Jason Reiss 28:c222ca8383f4 1232
Jason Reiss 28:c222ca8383f4 1233 std::string packet = mts::Text::bin2hexString(RxPayload, RxPayloadSize);
Jason Reiss 28:c222ca8383f4 1234
Jason Reiss 36:b586cd6e91f3 1235 CommandTerminal::Dot()->getSettings()->Test.TestMode = true;
Jason Reiss 36:b586cd6e91f3 1236 CommandTerminal::Dot()->setDisableIncrementDR(true);
Jason Reiss 28:c222ca8383f4 1237
Jason Reiss 36:b586cd6e91f3 1238 // last_rx_seq = CommandTerminal::Dot()->getSettings()->Session.UplinkCounter; // for class b tests
Jason Reiss 28:c222ca8383f4 1239
Jason Reiss 36:b586cd6e91f3 1240 uint32_t txPeriod = 5000;
Jason Reiss 36:b586cd6e91f3 1241 bool testConfirmed = false;
Jason Reiss 28:c222ca8383f4 1242
Jason Reiss 36:b586cd6e91f3 1243 std::string cls = "A";
Jason Reiss 36:b586cd6e91f3 1244
Jason Reiss 36:b586cd6e91f3 1245 CommandTerminal::Dot()->setAck(0);
Jason Reiss 36:b586cd6e91f3 1246 CommandTerminal::Dot()->setAdr(true);
Jason Reiss 36:b586cd6e91f3 1247 CommandTerminal::Dot()->setAppPort(224);
Jason Reiss 28:c222ca8383f4 1248
Jason Reiss 36:b586cd6e91f3 1249 Timer sentTimer;
Jason Reiss 36:b586cd6e91f3 1250 sentTimer.start();
Jason Reiss 36:b586cd6e91f3 1251 while (CommandTerminal::Dot()->getSettings()->Test.TestMode) {
Jason Reiss 28:c222ca8383f4 1252 TEST_START:
Jason Reiss 36:b586cd6e91f3 1253 // if (waitingForBeacon && BeaconLocked) {
Jason Reiss 36:b586cd6e91f3 1254 // logInfo("send BeaconRxStatusInd");
Jason Reiss 36:b586cd6e91f3 1255 // _data.clear();
Jason Reiss 36:b586cd6e91f3 1256 // _data.push_back(0x40);
Jason Reiss 36:b586cd6e91f3 1257 // for (size_t i = 0; i < sizeof(BeaconData); ++i) {
Jason Reiss 36:b586cd6e91f3 1258 // _data.push_back(((uint8_t*)&BeaconData)[i]);
Jason Reiss 36:b586cd6e91f3 1259 // }
Jason Reiss 36:b586cd6e91f3 1260 // } else
Jason Reiss 36:b586cd6e91f3 1261
Jason Reiss 36:b586cd6e91f3 1262 if (RxPort == 224) {
Jason Reiss 36:b586cd6e91f3 1263 _data.clear();
Jason Reiss 34:3b696c2b1e4b 1264
Jason Reiss 36:b586cd6e91f3 1265 std::string packet = mts::Text::bin2hexString(RxPayload, RxPayloadSize);
Jason Reiss 36:b586cd6e91f3 1266 logDebug("Test Mode AppPort : %d", CommandTerminal::Dot()->getAppPort());
Jason Reiss 36:b586cd6e91f3 1267 logDebug("Test Mode Packet : %s", packet.c_str());
Jason Reiss 34:3b696c2b1e4b 1268
Jason Reiss 36:b586cd6e91f3 1269 switch (RxPayload[0]) {
Jason Reiss 36:b586cd6e91f3 1270 case 0x00: { // PackageVersionReq
Jason Reiss 36:b586cd6e91f3 1271 _data.push_back(0x00);
Jason Reiss 36:b586cd6e91f3 1272 _data.push_back(0x06);
Jason Reiss 36:b586cd6e91f3 1273 _data.push_back(0x01);
Jason Reiss 36:b586cd6e91f3 1274 break;
Jason Reiss 36:b586cd6e91f3 1275 }
Jason Reiss 36:b586cd6e91f3 1276 case 0x01: { // DutResetReq
Jason Reiss 36:b586cd6e91f3 1277 if (RxPayloadSize == 1) {
Jason Reiss 36:b586cd6e91f3 1278 CommandTerminal::Dot()->resetCpu();
Jason Reiss 28:c222ca8383f4 1279 }
Jason Reiss 36:b586cd6e91f3 1280 break;
Jason Reiss 36:b586cd6e91f3 1281 }
Jason Reiss 36:b586cd6e91f3 1282 case 0x02: { // DutJoinReq
Jason Reiss 36:b586cd6e91f3 1283 if (RxPayloadSize == 1) {
Jason Reiss 36:b586cd6e91f3 1284 while (CommandTerminal::Dot()->getNextTxMs() > 0) {
Jason Reiss 36:b586cd6e91f3 1285 osDelay(1000);
Jason Reiss 28:c222ca8383f4 1286 }
Jason Reiss 36:b586cd6e91f3 1287 CommandTerminal::Dot()->joinNetworkOnce();
Jason Reiss 36:b586cd6e91f3 1288 return;
Jason Reiss 28:c222ca8383f4 1289 }
Jason Reiss 36:b586cd6e91f3 1290 break;
Jason Reiss 36:b586cd6e91f3 1291 }
Jason Reiss 36:b586cd6e91f3 1292 case 0x03: { // SwitchClassReq
Jason Reiss 36:b586cd6e91f3 1293 if (RxPayload[1] < 3) {
Jason Reiss 36:b586cd6e91f3 1294 if (RxPayload[1] == 0x00) {
Jason Reiss 36:b586cd6e91f3 1295 cls = "A";
Jason Reiss 36:b586cd6e91f3 1296 } else {
Jason Reiss 28:c222ca8383f4 1297 cls = RxPayload[1] == 0x01 ? "B" : "C";
Jason Reiss 28:c222ca8383f4 1298 }
Jason Reiss 28:c222ca8383f4 1299 }
Jason Reiss 36:b586cd6e91f3 1300 CommandTerminal::Dot()->setClass(cls);
Jason Reiss 36:b586cd6e91f3 1301 break;
Jason Reiss 36:b586cd6e91f3 1302 }
Jason Reiss 36:b586cd6e91f3 1303 case 0x04: { // ADR Enabled/Disable
Jason Reiss 36:b586cd6e91f3 1304 if (RxPayload[1] == 1)
Jason Reiss 36:b586cd6e91f3 1305 CommandTerminal::Dot()->setAdr(true);
Jason Reiss 36:b586cd6e91f3 1306 else
Jason Reiss 36:b586cd6e91f3 1307 CommandTerminal::Dot()->setAdr(false);
Jason Reiss 36:b586cd6e91f3 1308 break;
Jason Reiss 36:b586cd6e91f3 1309 }
Jason Reiss 36:b586cd6e91f3 1310 case 0x05: { // RegionalDutyCycleCtrlReq
Jason Reiss 36:b586cd6e91f3 1311 if (RxPayload[1] == 0)
Jason Reiss 36:b586cd6e91f3 1312 CommandTerminal::Dot()->setDisableDutyCycle(true);
Jason Reiss 36:b586cd6e91f3 1313 else
Jason Reiss 36:b586cd6e91f3 1314 CommandTerminal::Dot()->setDisableDutyCycle(false);
Jason Reiss 36:b586cd6e91f3 1315 break;
Jason Reiss 36:b586cd6e91f3 1316 }
Jason Reiss 36:b586cd6e91f3 1317 case 0x06: { // TxPeriodicityChangeReq
Jason Reiss 36:b586cd6e91f3 1318 if (RxPayload[1] < 2)
Jason Reiss 36:b586cd6e91f3 1319 // 0, 1 => 5s
Jason Reiss 36:b586cd6e91f3 1320 txPeriod = 5000U;
Jason Reiss 36:b586cd6e91f3 1321 else if (RxPayload[1] < 8)
Jason Reiss 36:b586cd6e91f3 1322 // 2 - 7 => 10s - 60s
Jason Reiss 36:b586cd6e91f3 1323 txPeriod = (RxPayload[1] - 1) * 10000U;
Jason Reiss 36:b586cd6e91f3 1324 else if (RxPayload[1] < 11) {
Jason Reiss 36:b586cd6e91f3 1325 // 8, 9, 10 => 120s, 240s, 480s
Jason Reiss 36:b586cd6e91f3 1326 txPeriod = 120 * (1 << (RxPayload[1] - 8)) * 1000U;
Jason Reiss 28:c222ca8383f4 1327 }
Jason Reiss 36:b586cd6e91f3 1328 break;
Jason Reiss 36:b586cd6e91f3 1329 }
Jason Reiss 36:b586cd6e91f3 1330 case 0x07: { // TxFramesCtrl
Jason Reiss 36:b586cd6e91f3 1331 if (RxPayload[1] == 0) {
Jason Reiss 36:b586cd6e91f3 1332 // NO-OP
Jason Reiss 36:b586cd6e91f3 1333 } else if (RxPayload[1] == 1) {
Jason Reiss 36:b586cd6e91f3 1334 testConfirmed = false;
Jason Reiss 36:b586cd6e91f3 1335 CommandTerminal::Dot()->getSettings()->Network.AckEnabled = 0;
Jason Reiss 36:b586cd6e91f3 1336 } else if (RxPayload[1] == 2) {
Jason Reiss 36:b586cd6e91f3 1337 testConfirmed = true;
Jason Reiss 36:b586cd6e91f3 1338 // if ADR has set nbTrans then use the current setting
Jason Reiss 36:b586cd6e91f3 1339 CommandTerminal::Dot()->getSettings()->Network.AckEnabled = 1;
Jason Reiss 36:b586cd6e91f3 1340 if (CommandTerminal::Dot()->getSettings()->Session.Redundancy == 0) {
Jason Reiss 36:b586cd6e91f3 1341 CommandTerminal::Dot()->getSettings()->Session.Redundancy = 1;
Jason Reiss 28:c222ca8383f4 1342 }
Jason Reiss 28:c222ca8383f4 1343 }
Jason Reiss 36:b586cd6e91f3 1344 break;
Jason Reiss 36:b586cd6e91f3 1345 }
Jason Reiss 36:b586cd6e91f3 1346 case 0x08: { // EchoPayloadReq
Jason Reiss 36:b586cd6e91f3 1347 _data.push_back(0x08);
Jason Reiss 36:b586cd6e91f3 1348 for (size_t i = 1; i < RxPayloadSize; i++) {
Jason Reiss 36:b586cd6e91f3 1349 _data.push_back(RxPayload[i] + 1);
Jason Reiss 28:c222ca8383f4 1350 }
Jason Reiss 36:b586cd6e91f3 1351 break;
Jason Reiss 36:b586cd6e91f3 1352 }
Jason Reiss 36:b586cd6e91f3 1353 case 0x09: { // RxAppCntReq
Jason Reiss 36:b586cd6e91f3 1354 _data.push_back(0x09);
Jason Reiss 36:b586cd6e91f3 1355 _data.push_back(_testDownlinkCounter & 0xFF);
Jason Reiss 36:b586cd6e91f3 1356 _data.push_back(_testDownlinkCounter >> 8);
Jason Reiss 36:b586cd6e91f3 1357 break;
Jason Reiss 36:b586cd6e91f3 1358 }
Jason Reiss 36:b586cd6e91f3 1359 case 0x0A: { // RxAppCntResetReq
Jason Reiss 36:b586cd6e91f3 1360 _testDownlinkCounter = 0;
Jason Reiss 36:b586cd6e91f3 1361 break;
Jason Reiss 36:b586cd6e91f3 1362 }
Jason Reiss 36:b586cd6e91f3 1363 case 0x20: { // LinkCheckReq
Jason Reiss 36:b586cd6e91f3 1364 CommandTerminal::Dot()->addMacCommand(lora::MOTE_MAC_LINK_CHECK_REQ, 0, 0);
Jason Reiss 36:b586cd6e91f3 1365 break;
Jason Reiss 36:b586cd6e91f3 1366 }
Jason Reiss 36:b586cd6e91f3 1367 case 0x21: { // DeviceTimeReq
Jason Reiss 36:b586cd6e91f3 1368 CommandTerminal::Dot()->addDeviceTimeRequest();
Jason Reiss 36:b586cd6e91f3 1369 break;
Jason Reiss 36:b586cd6e91f3 1370 }
Jason Reiss 36:b586cd6e91f3 1371 case 0x22: { // PingSlotInfo
Jason Reiss 36:b586cd6e91f3 1372 CommandTerminal::Dot()->setPingPeriodicity(RxPayload[1]);
Jason Reiss 36:b586cd6e91f3 1373 CommandTerminal::Dot()->addMacCommand(lora::MOTE_MAC_PING_SLOT_INFO_REQ, RxPayload[1], 0);
Jason Reiss 36:b586cd6e91f3 1374 break;
Jason Reiss 36:b586cd6e91f3 1375 }
Jason Reiss 36:b586cd6e91f3 1376 case 0x7D: { // TxCw
Jason Reiss 36:b586cd6e91f3 1377 uint32_t freq = 0;
Jason Reiss 36:b586cd6e91f3 1378 uint16_t timeout = 0;
Jason Reiss 36:b586cd6e91f3 1379 uint8_t power = 0;
Jason Reiss 28:c222ca8383f4 1380
Jason Reiss 36:b586cd6e91f3 1381 timeout = RxPayload[2] << 8 | RxPayload[1];
Jason Reiss 36:b586cd6e91f3 1382 freq = (RxPayload[5] << 16 | RxPayload[4] << 8 | RxPayload[2]) * 100;
Jason Reiss 36:b586cd6e91f3 1383 power = RxPayload[6];
Jason Reiss 36:b586cd6e91f3 1384
Jason Reiss 36:b586cd6e91f3 1385 CommandTerminal::Dot()->sendContinuous(true, timeout * 1000, freq, power);
Jason Reiss 36:b586cd6e91f3 1386 break;
Jason Reiss 36:b586cd6e91f3 1387 }
Jason Reiss 36:b586cd6e91f3 1388 case 0x7E: { // DutFPort224DisableReq
Jason Reiss 36:b586cd6e91f3 1389 _dot->setTestModeEnabled(false);
Jason Reiss 36:b586cd6e91f3 1390 CommandTerminal::Dot()->getSettings()->Test.TestMode = false;
Jason Reiss 36:b586cd6e91f3 1391 _dot->saveConfig();
Jason Reiss 36:b586cd6e91f3 1392 CommandTerminal::Dot()->resetCpu();
Jason Reiss 36:b586cd6e91f3 1393 break;
Jason Reiss 36:b586cd6e91f3 1394 }
Jason Reiss 36:b586cd6e91f3 1395 case 0x7F: { // DutVersionReq
Jason Reiss 36:b586cd6e91f3 1396 std::string version = AT_APPLICATION_VERSION;
Jason Reiss 36:b586cd6e91f3 1397 int temp = 0;
Jason Reiss 28:c222ca8383f4 1398
Jason Reiss 36:b586cd6e91f3 1399 _data.push_back(0x7F);
Jason Reiss 36:b586cd6e91f3 1400 sscanf(&version[0], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1401 _data.push_back(temp); // AT_APP_VERSION_MAJOR; // MAJOR
Jason Reiss 36:b586cd6e91f3 1402 sscanf(&version[2], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1403 _data.push_back(temp); // AT_APP_VERSION_MINOR; // MINOR
Jason Reiss 36:b586cd6e91f3 1404 sscanf(&version[4], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1405 _data.push_back(temp); // AT_APP_VERSION_PATCH; // PATCH
Jason Reiss 36:b586cd6e91f3 1406 if (version.size() > 7) {
Jason Reiss 36:b586cd6e91f3 1407 sscanf(&version[6], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1408 _data.push_back(temp); // AT_APP_VERSION_PATCH; // PATCH
Jason Reiss 36:b586cd6e91f3 1409 } else {
Jason Reiss 36:b586cd6e91f3 1410 _data.push_back(0); // AT_APP_VERSION_PATCH; // PATCH
Jason Reiss 36:b586cd6e91f3 1411 }
Jason Reiss 36:b586cd6e91f3 1412 version = LW_VERSION;
Jason Reiss 36:b586cd6e91f3 1413 sscanf(&version[0], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1414 _data.push_back(temp); // LW_VERSION; // MAJOR
Jason Reiss 36:b586cd6e91f3 1415 sscanf(&version[2], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1416 _data.push_back(temp); // LW_VERSION; // MINOR
Jason Reiss 36:b586cd6e91f3 1417 sscanf(&version[4], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1418 _data.push_back(temp); // LW_VERSION; // PATCH
Jason Reiss 36:b586cd6e91f3 1419 if (version.size() > 7) {
Jason Reiss 36:b586cd6e91f3 1420 sscanf(&version[6], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1421 _data.push_back(temp); // LW_VERSION; // PATCH
Jason Reiss 36:b586cd6e91f3 1422 } else {
Jason Reiss 36:b586cd6e91f3 1423 _data.push_back(0); // LW_VERSION; // PATCH
Jason Reiss 28:c222ca8383f4 1424 }
Jason Reiss 36:b586cd6e91f3 1425 version = RP_VERSION;
Jason Reiss 36:b586cd6e91f3 1426 sscanf(&version[0], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1427 _data.push_back(temp); // RP_VERSION; // MAJOR
Jason Reiss 36:b586cd6e91f3 1428 sscanf(&version[2], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1429 _data.push_back(temp); // RP_VERSION; // MINOR
Jason Reiss 36:b586cd6e91f3 1430 sscanf(&version[4], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1431 _data.push_back(temp); // RP_VERSION; // PATCH
Jason Reiss 36:b586cd6e91f3 1432 if (version.size() > 7) {
Jason Reiss 36:b586cd6e91f3 1433 sscanf(&version[6], "%d", &temp);
Jason Reiss 36:b586cd6e91f3 1434 _data.push_back(temp); // RP_VERSION; // PATCH
Jason Reiss 36:b586cd6e91f3 1435 } else {
Jason Reiss 36:b586cd6e91f3 1436 _data.push_back(0); // RP_VERSION; // PATCH
Jason Reiss 28:c222ca8383f4 1437 }
Jason Reiss 36:b586cd6e91f3 1438
Jason Reiss 36:b586cd6e91f3 1439
Jason Reiss 36:b586cd6e91f3 1440 break;
Jason Reiss 36:b586cd6e91f3 1441 }
Jason Reiss 36:b586cd6e91f3 1442 default: {
Jason Reiss 36:b586cd6e91f3 1443 break;
Jason Reiss 36:b586cd6e91f3 1444 }
Jason Reiss 36:b586cd6e91f3 1445 }
Jason Reiss 36:b586cd6e91f3 1446 }
Jason Reiss 36:b586cd6e91f3 1447
Jason Reiss 36:b586cd6e91f3 1448 do {
Jason Reiss 36:b586cd6e91f3 1449 uint32_t loop_timer = 0;
Jason Reiss 36:b586cd6e91f3 1450 loop_timer = std::chrono::duration_cast<std::chrono::milliseconds>(sentTimer.elapsed_time()).count();
Jason Reiss 36:b586cd6e91f3 1451
Jason Reiss 36:b586cd6e91f3 1452 PacketReceived = false;
Jason Reiss 36:b586cd6e91f3 1453 AckReceived = false;
Jason Reiss 36:b586cd6e91f3 1454
Jason Reiss 36:b586cd6e91f3 1455 while (loop_timer < txPeriod || CommandTerminal::Dot()->getNextTxMs() > 0 || !CommandTerminal::Dot()->getIsIdle()) {
Jason Reiss 36:b586cd6e91f3 1456 // if (waitingForBeacon && BeaconLocked) {
Jason Reiss 36:b586cd6e91f3 1457 // goto TEST_START;
Jason Reiss 36:b586cd6e91f3 1458 // }
Jason Reiss 36:b586cd6e91f3 1459 osDelay(500);
Jason Reiss 36:b586cd6e91f3 1460 loop_timer = std::chrono::duration_cast<std::chrono::milliseconds>(sentTimer.elapsed_time()).count();
Jason Reiss 36:b586cd6e91f3 1461
Jason Reiss 36:b586cd6e91f3 1462 if (CommandTerminal::Dot()->getAckRequested() && loop_timer > 5000) {
Jason Reiss 36:b586cd6e91f3 1463 break;
Jason Reiss 28:c222ca8383f4 1464 }
Jason Reiss 28:c222ca8383f4 1465 }
Jason Reiss 28:c222ca8383f4 1466
Jason Reiss 36:b586cd6e91f3 1467 // packet may have been received while waiting, if ACK req then send uplink
Jason Reiss 36:b586cd6e91f3 1468 // else process data
Jason Reiss 36:b586cd6e91f3 1469 if (!PacketReceived || CommandTerminal::Dot()->getAckRequested()) {
Jason Reiss 28:c222ca8383f4 1470
Jason Reiss 28:c222ca8383f4 1471 sentTimer.reset();
Jason Reiss 28:c222ca8383f4 1472
Jason Reiss 36:b586cd6e91f3 1473 if (_data.size() == 0) {
Jason Reiss 34:3b696c2b1e4b 1474 CommandTerminal::Dot()->setAppPort(1);
Jason Reiss 36:b586cd6e91f3 1475 // if (cls == "B") {
Jason Reiss 36:b586cd6e91f3 1476 // // class B tests don't like empty packets
Jason Reiss 36:b586cd6e91f3 1477 _data.push_back(0xFF);
Jason Reiss 36:b586cd6e91f3 1478 // }
Jason Reiss 34:3b696c2b1e4b 1479 } else {
Jason Reiss 34:3b696c2b1e4b 1480 CommandTerminal::Dot()->setAppPort(224);
Jason Reiss 34:3b696c2b1e4b 1481 }
Jason Reiss 34:3b696c2b1e4b 1482
Jason Reiss 36:b586cd6e91f3 1483 PacketReceived = false;
Jason Reiss 36:b586cd6e91f3 1484 AckReceived = false;
Jason Reiss 36:b586cd6e91f3 1485
Jason Reiss 36:b586cd6e91f3 1486 if (CommandTerminal::Dot()->send(_data, testConfirmed) == mDot::MDOT_MAX_PAYLOAD_EXCEEDED) {
Jason Reiss 36:b586cd6e91f3 1487 _data.clear();
Jason Reiss 28:c222ca8383f4 1488 RxPort = 0;
Jason Reiss 28:c222ca8383f4 1489 goto TEST_START;
Jason Reiss 28:c222ca8383f4 1490 }
Jason Reiss 28:c222ca8383f4 1491
Jason Reiss 36:b586cd6e91f3 1492 // For Class B tests
Jason Reiss 36:b586cd6e91f3 1493 // if (PacketReceived) {
Jason Reiss 36:b586cd6e91f3 1494 // last_rx_seq = CommandTerminal::Dot()->getSettings()->Session.UplinkCounter;
Jason Reiss 36:b586cd6e91f3 1495 // }
Jason Reiss 28:c222ca8383f4 1496
Jason Reiss 36:b586cd6e91f3 1497 _data.clear();
Jason Reiss 28:c222ca8383f4 1498
Jason Reiss 34:3b696c2b1e4b 1499 }
Jason Reiss 34:3b696c2b1e4b 1500
Jason Reiss 36:b586cd6e91f3 1501 } while (!AckReceived && CommandTerminal::Dot()->recv(_data) != mDot::MDOT_OK);
Jason Reiss 36:b586cd6e91f3 1502
Jason Reiss 36:b586cd6e91f3 1503
Jason Reiss 36:b586cd6e91f3 1504 if (cls == "B" && !BeaconLocked) {
Jason Reiss 36:b586cd6e91f3 1505 CommandTerminal::Dot()->setClass(cls);
Jason Reiss 28:c222ca8383f4 1506 }
Jason Reiss 36:b586cd6e91f3 1507 }
Jason Reiss 28:c222ca8383f4 1508 #endif
Jason Reiss 28:c222ca8383f4 1509 }
Jason Reiss 28:c222ca8383f4 1510
jenkins@jenkinsdm1 18:63f098f042b2 1511 uint8_t CommandTerminal::getBatteryLevel() {
jenkins@jenkinsdm1 18:63f098f042b2 1512 return _battery_level;
jenkins@jenkinsdm1 18:63f098f042b2 1513 }
jenkins@jenkinsdm1 18:63f098f042b2 1514
Jason Reiss 23:4f0a981c0349 1515 void CommandTerminal::setBatteryLevel(uint8_t battery_level) {
jenkins@jenkinsdm1 18:63f098f042b2 1516 _battery_level = battery_level;
jenkins@jenkinsdm1 18:63f098f042b2 1517 }
jenkins@jenkinsdm1 18:63f098f042b2 1518
Jason Reiss 27:5fafd3b26ac3 1519 void CommandTerminal::formatPacket(uint8_t* payload, uint16_t size, bool hex) {
Jason Reiss 23:4f0a981c0349 1520
Jason Reiss 23:4f0a981c0349 1521 if(_dot->getAckRequested()) {
Jason Reiss 23:4f0a981c0349 1522 f_data[0] = 0;
Jason Reiss 23:4f0a981c0349 1523 } else {
Jason Reiss 23:4f0a981c0349 1524 f_data[0] = 1;
Jason Reiss 23:4f0a981c0349 1525 }
Jason Reiss 23:4f0a981c0349 1526
Jason Reiss 23:4f0a981c0349 1527 f_data[1] = _rxAddress & 0xFF;
Jason Reiss 23:4f0a981c0349 1528 f_data[2] = (_rxAddress >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1529 f_data[3] = (_rxAddress >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1530 f_data[4] = (_rxAddress >> 24) & 0xFF;
Jason Reiss 28:c222ca8383f4 1531 f_data[5] = _rxFcnt & 0xFF;
Jason Reiss 28:c222ca8383f4 1532 f_data[6] = (_rxFcnt >> 8) & 0xFF;
Jason Reiss 28:c222ca8383f4 1533 f_data[7] = (_rxFcnt >> 16) & 0xFF;
Jason Reiss 28:c222ca8383f4 1534 f_data[8] = (_rxFcnt >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1535 f_data[9] = _events->RxPort;
Jason Reiss 23:4f0a981c0349 1536
Jason Reiss 23:4f0a981c0349 1537 for(int i = 0; i < size; i++)
Jason Reiss 23:4f0a981c0349 1538 f_data[i+10] = payload[i];
Jason Reiss 23:4f0a981c0349 1539
Jason Reiss 27:5fafd3b26ac3 1540 if (hex) {
Jason Reiss 27:5fafd3b26ac3 1541 std::string data = "RECV " + mts::Text::bin2hexString(f_data, size + 10) + "\r\n";
Jason Reiss 27:5fafd3b26ac3 1542 CommandTerminal::Serial()->write(data.c_str(), data.size());
Jason Reiss 27:5fafd3b26ac3 1543 } else {
Jason Reiss 27:5fafd3b26ac3 1544 CommandTerminal::Serial()->write((char*)f_data, size + 10);
Jason Reiss 27:5fafd3b26ac3 1545 }
Jason Reiss 23:4f0a981c0349 1546 }
Jason Reiss 23:4f0a981c0349 1547
Jason Reiss 23:4f0a981c0349 1548
Jason Reiss 27:5fafd3b26ac3 1549 std::string CommandTerminal::formatPacket(std::vector<uint8_t> payload, bool hex) {
Jason Reiss 23:4f0a981c0349 1550
Jason Reiss 23:4f0a981c0349 1551 if(_dot->getAckRequested()) {
Jason Reiss 23:4f0a981c0349 1552 f_data[0] = 0;
Jason Reiss 23:4f0a981c0349 1553 } else {
Jason Reiss 23:4f0a981c0349 1554 f_data[0] = 1;
Jason Reiss 23:4f0a981c0349 1555 }
Jason Reiss 23:4f0a981c0349 1556
Jason Reiss 23:4f0a981c0349 1557 f_data[1] = _rxAddress & 0xFF;
Jason Reiss 23:4f0a981c0349 1558 f_data[2] = (_rxAddress >> 8) & 0xFF;
Jason Reiss 23:4f0a981c0349 1559 f_data[3] = (_rxAddress >> 16) & 0xFF;
Jason Reiss 23:4f0a981c0349 1560 f_data[4] = (_rxAddress >> 24) & 0xFF;
Jason Reiss 28:c222ca8383f4 1561 f_data[5] = _rxFcnt & 0xFF;
Jason Reiss 28:c222ca8383f4 1562 f_data[6] = (_rxFcnt >> 8) & 0xFF;
Jason Reiss 28:c222ca8383f4 1563 f_data[7] = (_rxFcnt >> 16) & 0xFF;
Jason Reiss 28:c222ca8383f4 1564 f_data[8] = (_rxFcnt >> 24) & 0xFF;
Jason Reiss 23:4f0a981c0349 1565 f_data[9] = _events->RxPort;
Jason Reiss 23:4f0a981c0349 1566
Jason Reiss 27:5fafd3b26ac3 1567 for(size_t i = 0; i < payload.size(); i++)
Jason Reiss 23:4f0a981c0349 1568 f_data[i+10] = payload.at(i);
Jason Reiss 23:4f0a981c0349 1569
Jason Reiss 27:5fafd3b26ac3 1570 if (hex) {
Jason Reiss 27:5fafd3b26ac3 1571 return mts::Text::bin2hexString(f_data, payload.size() + 10);
Jason Reiss 27:5fafd3b26ac3 1572 } else {
Jason Reiss 27:5fafd3b26ac3 1573 return std::string((char*)f_data, payload.size() + 10);
Jason Reiss 27:5fafd3b26ac3 1574 }
Jason Reiss 27:5fafd3b26ac3 1575
Jason Reiss 23:4f0a981c0349 1576 }
Jason Reiss 23:4f0a981c0349 1577
Jason Reiss 23:4f0a981c0349 1578
Jason Reiss 23:4f0a981c0349 1579
Jason Reiss 23:4f0a981c0349 1580 void CommandTerminal::formatPacketSDSend(std::vector<uint8_t> &payload) {
Jason Reiss 27:5fafd3b26ac3 1581 if (_dot->getRxOutput() == mDot::EXTENDED_HEX) {
Jason Reiss 27:5fafd3b26ac3 1582 int temp;
Jason Reiss 27:5fafd3b26ac3 1583 std::vector<uint8_t> converted;
Jason Reiss 27:5fafd3b26ac3 1584
Jason Reiss 27:5fafd3b26ac3 1585 for (size_t i=0; i < payload.size(); i+=2) {
Jason Reiss 27:5fafd3b26ac3 1586 if (sscanf((char*)&payload[i], "%2x", &temp) == 1) {
Jason Reiss 27:5fafd3b26ac3 1587 converted.push_back((uint8_t)temp);
Jason Reiss 27:5fafd3b26ac3 1588 }
Jason Reiss 27:5fafd3b26ac3 1589 }
Jason Reiss 27:5fafd3b26ac3 1590
Jason Reiss 27:5fafd3b26ac3 1591 payload = converted;
Jason Reiss 27:5fafd3b26ac3 1592 }
Jason Reiss 27:5fafd3b26ac3 1593
Jason Reiss 23:4f0a981c0349 1594 if(payload.size() >= 3) {
Jason Reiss 23:4f0a981c0349 1595 _dot->setAppPort(payload[0]);
Jason Reiss 23:4f0a981c0349 1596 _dot->setRepeat(0);
Jason Reiss 23:4f0a981c0349 1597 _dot->setAck(0);
Jason Reiss 23:4f0a981c0349 1598 switch(payload[1]) {
Jason Reiss 23:4f0a981c0349 1599 case 0:
Jason Reiss 23:4f0a981c0349 1600 _dot->setAck(payload[2]);
Jason Reiss 23:4f0a981c0349 1601 break;
Jason Reiss 23:4f0a981c0349 1602 case 1:
Jason Reiss 23:4f0a981c0349 1603 _dot->setRepeat(payload[2]);
Jason Reiss 23:4f0a981c0349 1604 break;
Jason Reiss 23:4f0a981c0349 1605 default:
Jason Reiss 23:4f0a981c0349 1606 break;
Jason Reiss 23:4f0a981c0349 1607 }
Jason Reiss 23:4f0a981c0349 1608 payload.erase(payload.begin(), payload.begin()+3);
Jason Reiss 23:4f0a981c0349 1609 }
Jason Reiss 27:5fafd3b26ac3 1610
Jason Reiss 23:4f0a981c0349 1611 }
Jason Reiss 23:4f0a981c0349 1612
Jason Reiss 23:4f0a981c0349 1613
Jason Reiss 23:4f0a981c0349 1614
Mike Fiore 9:ff62b20f7000 1615 CommandTerminal::~CommandTerminal() {
Mike Fiore 9:ff62b20f7000 1616 delete _events;
Mike Fiore 9:ff62b20f7000 1617 }