![](/media/cache/group/MultiTech_Logo_Color_w_Tagline_PNG_1000px.png.50x50_q85.png)
AT command firmware for MultiTech Dot devices.
Fork of mDot_AT_firmware by
Dot Library Not Included!
Because these example programs can be used for both mDot and xDot devices, the LoRa stack is not included. The libmDot library should be imported if building for mDot devices. The libxDot library should be imported if building for xDot devices. The AT firmware was last tested with mbed-os-5.4.7. Using a version past mbed-os-5.4.7 will cause the build to fail. The library used with the AT firmware has to match the mbed-os version.
Dot Library Version 3 Updates
Dot Library versions 3.x.x require a channel plan to be injected into the stack. The Dot-Examples and Dot-AT-Firmware do this by defining a macro called "CHANNEL_PLAN" that controls the channel plan that will be used in the examples. Available channel plans will be in the Dot Library repository in the plans folder.
Revision 20 and earlier of Dot-Examples and revision 15 and earlier of Dot-AT-Firmware should be used with Dot Library versions prior to 3.0.0.
Fota Library
Th Fota Library must be added to compile for mDot 3.1.0 with Fota support. Latest dev libraries and 3.2.0 release will include Fota with libmDot/libxDot.
AT Firmware Description
This AT Firmware is what ships on mDot and xDot devices. It provides an AT command interface for using the mDot or xDot for LoRa communication.
AT command documentation can be found on Multitech.com.
The firmware changelog can be found here.
The library changelog can be found here.
Dot Libraries
Dot Library Limitations
The commit messages in libmDot-mbed5 and libmDot-dev-mbed5 specify the version of the Dot library the commit contains and the version of mbed-os it was compiled against. We recommend building your application with the version of mbed-os specified in the commit message of the version of the Dot library you're using. This will ensure that you don't run into any runtime issues caused by differences in the mbed-os versions.
Stable and development libraries are available for both mDot and xDot platforms. The library chosen must match the target platform. Compiling for the mDot platform with the xDot library or vice versa will not succeed.
mDot Library
Development library for mDot.
Stable library for mDot.
xDot Library
Development library for xDot.
Stable library for xDot.
CommandTerminal/CommandTerminal.cpp@42:23e2df6714f4, 8 months ago (annotated)
- 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?
User | Revision | Line number | New 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 | } |