From dd557b5a21d64cd49b1179ac891ffb2c63dee6d8 Mon Sep 17 00:00:00 2001 From: Leon Lindenfelser Date: Fri, 13 Nov 2015 08:14:28 -0600 Subject: Added CommandTerminal with unneccessary commands removed --- CommandTerminal/CmdAttention.cpp | 16 + CommandTerminal/CmdAttention.h | 17 + CommandTerminal/CmdDataSessionKey.cpp | 56 +++ CommandTerminal/CmdDataSessionKey.h | 20 + CommandTerminal/CmdDeviceId.cpp | 57 +++ CommandTerminal/CmdDeviceId.h | 21 + CommandTerminal/CmdDisplayConfig.cpp | 106 +++++ CommandTerminal/CmdDisplayConfig.h | 19 + CommandTerminal/CmdFactoryDefault.cpp | 15 + CommandTerminal/CmdFactoryDefault.h | 16 + CommandTerminal/CmdFrequencySubBand.cpp | 60 +++ CommandTerminal/CmdFrequencySubBand.h | 20 + CommandTerminal/CmdIdentification.cpp | 20 + CommandTerminal/CmdIdentification.h | 17 + CommandTerminal/CmdNetworkAddress.cpp | 72 ++++ CommandTerminal/CmdNetworkAddress.h | 20 + CommandTerminal/CmdNetworkId.cpp | 110 +++++ CommandTerminal/CmdNetworkId.h | 20 + CommandTerminal/CmdNetworkJoinMode.cpp | 55 +++ CommandTerminal/CmdNetworkJoinMode.h | 20 + CommandTerminal/CmdNetworkKey.cpp | 110 +++++ CommandTerminal/CmdNetworkKey.h | 22 + CommandTerminal/CmdNetworkSessionKey.cpp | 57 +++ CommandTerminal/CmdNetworkSessionKey.h | 20 + CommandTerminal/CmdPublicNetwork.cpp | 52 +++ CommandTerminal/CmdPublicNetwork.h | 21 + CommandTerminal/CmdSaveConfig.cpp | 17 + CommandTerminal/CmdSaveConfig.h | 17 + CommandTerminal/CmdTxDataRate.cpp | 89 ++++ CommandTerminal/CmdTxDataRate.h | 20 + CommandTerminal/CmdTxPower.cpp | 62 +++ CommandTerminal/CmdTxPower.h | 21 + CommandTerminal/Command.cpp | 128 ++++++ CommandTerminal/Command.h | 98 +++++ CommandTerminal/CommandTerminal.cpp | 631 +++++++++++++++++++++++++++++ CommandTerminal/CommandTerminal.h | 118 ++++++ CommandTerminal/Commands.h | 19 + CommandTerminal/Test/TestCommandTerminal.h | 82 ++++ 38 files changed, 2341 insertions(+) create mode 100644 CommandTerminal/CmdAttention.cpp create mode 100644 CommandTerminal/CmdAttention.h create mode 100644 CommandTerminal/CmdDataSessionKey.cpp create mode 100644 CommandTerminal/CmdDataSessionKey.h create mode 100644 CommandTerminal/CmdDeviceId.cpp create mode 100644 CommandTerminal/CmdDeviceId.h create mode 100644 CommandTerminal/CmdDisplayConfig.cpp create mode 100644 CommandTerminal/CmdDisplayConfig.h create mode 100644 CommandTerminal/CmdFactoryDefault.cpp create mode 100644 CommandTerminal/CmdFactoryDefault.h create mode 100644 CommandTerminal/CmdFrequencySubBand.cpp create mode 100644 CommandTerminal/CmdFrequencySubBand.h create mode 100644 CommandTerminal/CmdIdentification.cpp create mode 100644 CommandTerminal/CmdIdentification.h create mode 100644 CommandTerminal/CmdNetworkAddress.cpp create mode 100644 CommandTerminal/CmdNetworkAddress.h create mode 100644 CommandTerminal/CmdNetworkId.cpp create mode 100644 CommandTerminal/CmdNetworkId.h create mode 100644 CommandTerminal/CmdNetworkJoinMode.cpp create mode 100644 CommandTerminal/CmdNetworkJoinMode.h create mode 100644 CommandTerminal/CmdNetworkKey.cpp create mode 100644 CommandTerminal/CmdNetworkKey.h create mode 100644 CommandTerminal/CmdNetworkSessionKey.cpp create mode 100644 CommandTerminal/CmdNetworkSessionKey.h create mode 100644 CommandTerminal/CmdPublicNetwork.cpp create mode 100644 CommandTerminal/CmdPublicNetwork.h create mode 100644 CommandTerminal/CmdSaveConfig.cpp create mode 100644 CommandTerminal/CmdSaveConfig.h create mode 100644 CommandTerminal/CmdTxDataRate.cpp create mode 100644 CommandTerminal/CmdTxDataRate.h create mode 100644 CommandTerminal/CmdTxPower.cpp create mode 100644 CommandTerminal/CmdTxPower.h create mode 100644 CommandTerminal/Command.cpp create mode 100644 CommandTerminal/Command.h create mode 100644 CommandTerminal/CommandTerminal.cpp create mode 100644 CommandTerminal/CommandTerminal.h create mode 100644 CommandTerminal/Commands.h create mode 100644 CommandTerminal/Test/TestCommandTerminal.h diff --git a/CommandTerminal/CmdAttention.cpp b/CommandTerminal/CmdAttention.cpp new file mode 100644 index 0000000..892e891 --- /dev/null +++ b/CommandTerminal/CmdAttention.cpp @@ -0,0 +1,16 @@ +#include "CmdAttention.h" + +CmdAttention::CmdAttention(mDot* dot) : Command(dot, "Attention", "AT", "Attention") +{ + _help = std::string(text()) + ": " + std::string(desc()); +} + +CmdAttention::CmdAttention(mDot* dot, const char* name, const char* text, const char* desc) : Command(dot, name, text, desc) +{ + +} + +uint32_t CmdAttention::action(std::vector args) { + return 0; +} + diff --git a/CommandTerminal/CmdAttention.h b/CommandTerminal/CmdAttention.h new file mode 100644 index 0000000..76fd1d2 --- /dev/null +++ b/CommandTerminal/CmdAttention.h @@ -0,0 +1,17 @@ +#ifndef __CMDATTENTION_H__ +#define __CMDATTENTION_H__ + +#include "Command.h" + +class CmdAttention : public Command { + +public: + + CmdAttention(mDot* dot); + CmdAttention(mDot* dot, const char* name, const char* text, const char* desc); + virtual uint32_t action(std::vector args); + +private: +}; + +#endif // __CMDATTENTION_H__ diff --git a/CommandTerminal/CmdDataSessionKey.cpp b/CommandTerminal/CmdDataSessionKey.cpp new file mode 100644 index 0000000..d663406 --- /dev/null +++ b/CommandTerminal/CmdDataSessionKey.cpp @@ -0,0 +1,56 @@ +#include "CmdDataSessionKey.h" + +CmdDataSessionKey::CmdDataSessionKey(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Data Session Key", "AT+DSK", "Data session encryption key (16 bytes)"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(hex:16)"; + _queryable = true; +} + +uint32_t CmdDataSessionKey::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Data Session Key: "); + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getDataSessionKey(), ".").c_str()); + } + else if (args.size() == 2) + { + int32_t code; + std::vector NewKey; + + // Read in the key components... + readByteArray(args[1], NewKey, KEY_LENGTH); + + if ((code = _dot->setDataSessionKey(NewKey)) == mDot::MDOT_OK) { + _serial.writef("Set Data Session Key: "); + _serial.writef("%s\r\n", mts::Text::bin2hexString(NewKey, ".").c_str()); + } else { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdDataSessionKey::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) { + if (!isHexString(args[1], 16)) { + setErrorMessage("Invalid key, expects (hex:16)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} diff --git a/CommandTerminal/CmdDataSessionKey.h b/CommandTerminal/CmdDataSessionKey.h new file mode 100644 index 0000000..704af6e --- /dev/null +++ b/CommandTerminal/CmdDataSessionKey.h @@ -0,0 +1,20 @@ +#ifndef __CMDDATASESSIONKEY_H__ +#define __CMDDATASESSIONKEY_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdDataSessionKey : public Command { + +public: + + CmdDataSessionKey(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDDATASESSIONKEY_H__ diff --git a/CommandTerminal/CmdDeviceId.cpp b/CommandTerminal/CmdDeviceId.cpp new file mode 100644 index 0000000..05d2301 --- /dev/null +++ b/CommandTerminal/CmdDeviceId.cpp @@ -0,0 +1,57 @@ +#include "CmdDeviceId.h" +#include + +CmdDeviceId::CmdDeviceId(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Device ID", "AT+DI", "Device EUI (unique, set at factory) (8 bytes)"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(hex:8)"; + _queryable = true; +} + +uint32_t CmdDeviceId::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("%s: ", name()); + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getDeviceId(), ":").c_str()); + } +#ifdef DEBUG_MAC + else if (args.size() == 2) + { + int32_t code; + std::vector NewEUI; + + // Read in the key components... + readByteArray(args[1], NewEUI, EUI_LENGTH); + + if ((code = _dot->setDeviceId(NewEUI)) == mDot::MDOT_OK) { + _serial.writef("Set %s: ", name()); + _serial.writef("%s\r\n", mts::Text::bin2hexString(NewEUI, ":").c_str()); + } else { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } +#endif + return 0; +} + +bool CmdDeviceId::verify(std::vector args) +{ + if (args.size() == 1) + return true; + +#ifdef DEBUG_MAC + if (args.size() == 2 && isHexString(args[1], 8)) + return true; + + setErrorMessage("Invalid id, expects (hex:8)"); +#else + setErrorMessage("Invalid arguments"); +#endif + + return false; +} diff --git a/CommandTerminal/CmdDeviceId.h b/CommandTerminal/CmdDeviceId.h new file mode 100644 index 0000000..9e1ad74 --- /dev/null +++ b/CommandTerminal/CmdDeviceId.h @@ -0,0 +1,21 @@ +#ifndef __CMDDEVICEID_H__ +#define __CMDDEVICEID_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdDeviceId : public Command { + +public: + + CmdDeviceId(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + + mts::MTSSerial& _serial; +}; + +#endif // __CMDDEVICEID_H__ diff --git a/CommandTerminal/CmdDisplayConfig.cpp b/CommandTerminal/CmdDisplayConfig.cpp new file mode 100644 index 0000000..6ef6e92 --- /dev/null +++ b/CommandTerminal/CmdDisplayConfig.cpp @@ -0,0 +1,106 @@ +#include "CmdDisplayConfig.h" + +CmdDisplayConfig::CmdDisplayConfig(mDot* dot, mts::MTSSerial& serial) +: + Command(dot, "Display Settings", "AT&V", "Displays current settings and status"), + _serial(serial) { + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "TABLE"; +} + +uint32_t CmdDisplayConfig::action(std::vector args) { + _serial.writef("Device ID:\t\t"); + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getDeviceId(), ":").c_str()); + + _serial.writef("Frequency Band:\t\t%s\r\n", mDot::FrequencyBandStr(_dot->getFrequencyBand()).c_str()); + _serial.writef("Frequency Sub Band:\t%u\r\n", _dot->getFrequencySubBand()); + + _serial.writef("Public Network:\t\t%s\r\n", _dot->getPublicNetwork() ? "on" : "off"); + _serial.writef("Start Up Mode:\t\t%s\r\n", mDot::ModeStr(_dot->getStartUpMode()).c_str()); + + _serial.writef("Network Address:\t%s\r\n", mts::Text::bin2hexString(_dot->getNetworkAddress()).c_str()); + + _serial.writef("Network ID:\t\t"); + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getNetworkId(), ":").c_str()); + + _serial.writef("Network ID Passphrase:\t%s\r\n", _dot->getNetworkName().c_str()); + + _serial.writef("Network Key:\t\t"); + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getNetworkKey(), ".").c_str()); + + _serial.writef("Network Key Passphrase:\t%s\r\n", _dot->getNetworkPassphrase().c_str()); + + _serial.writef("Network Session Key:\t"); + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getNetworkSessionKey(), ".").c_str()); + + _serial.writef("Data Session Key:\t"); + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getDataSessionKey(), ".").c_str()); + + _serial.writef("Network Join Mode:\t%s\r\n", mDot::JoinModeStr(_dot->getJoinMode()).c_str()); + + _serial.writef("Network Join Retries:\t%u\r\n", _dot->getJoinRetries()); + + _serial.writef("Join Byte Order:\t%s\r\n", _dot->getJoinByteOrder() ? "MSB" : "LSB"); + + _serial.writef("Link Check Threshold:\t"); + if (_dot->getLinkCheckThreshold() == 0) { + _serial.writef("off\r\n"); + } else { + _serial.writef("%lu\r\n", _dot->getLinkCheckThreshold()); + } + + _serial.writef("Link Check Count:\t"); + if (_dot->getLinkCheckCount() == 0) { + _serial.writef("off\r\n"); + } else { + _serial.writef("%lu packets\r\n", _dot->getLinkCheckCount()); + } + + _serial.writef("Error Correction:\t"); + if (_dot->getFec() == 0) { + _serial.writef("off\r\n"); + } else { + _serial.writef("%u bytes\r\n", _dot->getFec()); + } + + _serial.writef("ACK Retries:\t\t"); + if (_dot->getAck() == 0) { + _serial.writef("off\r\n"); + } else { + _serial.writef("%u\r\n", _dot->getAck()); + } + + _serial.writef("Encryption:\t\t%s\r\n", _dot->getAesEncryption() ? "on" : "off"); + _serial.writef("CRC:\t\t\t%s\r\n", _dot->getCrc() ? "on" : "off"); + _serial.writef("Adaptive Data Rate:\t%s\r\n", _dot->getAdr() ? "on" : "off"); + _serial.writef("Command Echo:\t\t%s\r\n", _dot->getEcho() ? "on" : "off"); + _serial.writef("Verbose Response:\t%s\r\n", _dot->getVerbose() ? "on" : "off"); + + _serial.writef("Tx Frequency:\t\t%lu\r\n", _dot->getTxFrequency()); + _serial.writef("Tx Data Rate:\t\t%s\r\n", mDot::DataRateStr(_dot->getTxDataRate()).c_str()); + _serial.writef("Tx Power:\t\t%u\r\n", _dot->getTxPower()); + _serial.writef("Tx Wait:\t\t%s\r\n", _dot->getTxWait() ? "on" : "off"); + + _serial.writef("Tx Inverted Signal:\t%s\r\n", _dot->getTxInverted() ? "on" : "off"); + + _serial.writef("Rx Frequency:\t\t%lu\r\n", _dot->getRxFrequency()); + _serial.writef("Rx Data Rate:\t\t%s\r\n", mDot::DataRateStr(_dot->getRxDataRate()).c_str()); + _serial.writef("Rx Inverted Signal:\t%s\r\n", _dot->getRxInverted() ? "on" : "off"); + + _serial.writef("Rx Output Style:\t%s\r\n", mDot::RxOutputStr(_dot->getRxOutput()).c_str()); + + _serial.writef("Debug Baud Rate:\t%lu\r\n", _dot->getDebugBaud()); + _serial.writef("Serial Baud Rate:\t%lu\r\n", _dot->getBaud()); + + _serial.writef("Wake Mode:\t\t%s\r\n", _dot->getWakeMode() == 0 ? "INTERVAL" : "INTERRUPT"); + _serial.writef("Wake Interval:\t\t%lu s\r\n", _dot->getWakeInterval()); + _serial.writef("Wake Delay:\t\t%lu ms\r\n", _dot->getWakeDelay()); + _serial.writef("Wake Timeout:\t\t%u ms\r\n", _dot->getWakeTimeout()); + + //_serial.writef("Wake Pin:\t\t%s\r\n", mDot::pinName2Str(_dot->getWakePin()).c_str()); + + _serial.writef("Log Level:\t\t%ld\r\n", _dot->getLogLevel()); + + return 0; +} + diff --git a/CommandTerminal/CmdDisplayConfig.h b/CommandTerminal/CmdDisplayConfig.h new file mode 100644 index 0000000..05e7ac9 --- /dev/null +++ b/CommandTerminal/CmdDisplayConfig.h @@ -0,0 +1,19 @@ +#ifndef __CMDDISPLAYCONFIG_H__ +#define __CMDDISPLAYCONFIG_H__ + +#include "Command.h" + +class CmdDisplayConfig : public Command { + +public: + + CmdDisplayConfig(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + +private: + + mts::MTSSerial& _serial; + +}; + +#endif // __CMDDISPLAYCONFIG_H__ diff --git a/CommandTerminal/CmdFactoryDefault.cpp b/CommandTerminal/CmdFactoryDefault.cpp new file mode 100644 index 0000000..53b6ede --- /dev/null +++ b/CommandTerminal/CmdFactoryDefault.cpp @@ -0,0 +1,15 @@ +#include "CmdFactoryDefault.h" + +CmdFactoryDefault::CmdFactoryDefault(mDot* dot) : Command(dot, "Reset Factory Defaults", "AT&F", "Reset current configuration to factory defaults") +{ + _help = std::string(text()) + ": " + std::string(desc()); +} + + +uint32_t CmdFactoryDefault::action(std::vector args) +{ + _dot->resetConfig(); + _dot->resetNetworkSession(); + return 0; +} + diff --git a/CommandTerminal/CmdFactoryDefault.h b/CommandTerminal/CmdFactoryDefault.h new file mode 100644 index 0000000..8957ae3 --- /dev/null +++ b/CommandTerminal/CmdFactoryDefault.h @@ -0,0 +1,16 @@ +#ifndef __CmdFactoryDefault_H__ +#define __CmdFactoryDefault_H__ + +#include "Command.h" + +class CmdFactoryDefault : public Command { + +public: + + CmdFactoryDefault(mDot* dot); + virtual uint32_t action(std::vector args); + +private: +}; + +#endif // __CmdFactoryDefault_H__ diff --git a/CommandTerminal/CmdFrequencySubBand.cpp b/CommandTerminal/CmdFrequencySubBand.cpp new file mode 100644 index 0000000..fb9f0ba --- /dev/null +++ b/CommandTerminal/CmdFrequencySubBand.cpp @@ -0,0 +1,60 @@ +#include "CmdFrequencySubBand.h" + +CmdFrequencySubBand::CmdFrequencySubBand(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Frequency Sub-band", "AT+FSB", "Set the frequency sub-band for US 915, (0:ALL, 1-8)"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(0-8)"; + _queryable = true; +} + +uint32_t CmdFrequencySubBand::action(std::vector args) +{ + + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Frequency Sub Band: "); + + _serial.writef("%u\r\n", _dot->getFrequencySubBand()); + } + else if (args.size() == 2) + { + int32_t code; + uint32_t band; + sscanf(args[1].c_str(), "%lu", &band); + + if ((code = _dot->setFrequencySubBand(band)) != mDot::MDOT_OK) { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdFrequencySubBand::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + uint32_t band; + if (sscanf(args[1].c_str(), "%u", &band) != 1) { + setErrorMessage("Invalid arguments"); + return false; + } + + if (band < mDot::FSB_ALL || band > mDot::FSB_8) { + setErrorMessage("Invalid channel band, expects (0-8)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} diff --git a/CommandTerminal/CmdFrequencySubBand.h b/CommandTerminal/CmdFrequencySubBand.h new file mode 100644 index 0000000..14d50c9 --- /dev/null +++ b/CommandTerminal/CmdFrequencySubBand.h @@ -0,0 +1,20 @@ +#ifndef __CMDFREQUENCYSUBBAND_H__ +#define __CMDFREQUENCYSUBBAND_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdFrequencySubBand : public Command { + +public: + + CmdFrequencySubBand(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDFREQUENCYSUBBAND_H__ diff --git a/CommandTerminal/CmdIdentification.cpp b/CommandTerminal/CmdIdentification.cpp new file mode 100644 index 0000000..a765b30 --- /dev/null +++ b/CommandTerminal/CmdIdentification.cpp @@ -0,0 +1,20 @@ +#include "CmdIdentification.h" +#include "version.h" + +CmdIdentification::CmdIdentification(mDot* dot, mts::MTSSerial& serial) : Command(dot, "Request Id", "ATI", "Request Identification"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); +} + +uint32_t CmdIdentification::action(std::vector args) +{ + std::string version = MTDOT_BOX_VERSION; +#ifdef DEBUG_MAC + version += "-debug"; +#endif + _serial.writef("MultiTech mDot\r\n"); + _serial.writef("Firmware: %s\r\n", version.c_str()); + _serial.writef("Library : %s\r\n", _dot->getId().c_str()); + + return 0; +} diff --git a/CommandTerminal/CmdIdentification.h b/CommandTerminal/CmdIdentification.h new file mode 100644 index 0000000..b553ba1 --- /dev/null +++ b/CommandTerminal/CmdIdentification.h @@ -0,0 +1,17 @@ +#ifndef __CMDIDENTIFICATION_H__ +#define __CMDIDENTIFICATION_H__ + +#include "Command.h" + +class CmdIdentification : public Command { + +public: + + CmdIdentification(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDIDENTIFICATION_H__ diff --git a/CommandTerminal/CmdNetworkAddress.cpp b/CommandTerminal/CmdNetworkAddress.cpp new file mode 100644 index 0000000..07c0591 --- /dev/null +++ b/CommandTerminal/CmdNetworkAddress.cpp @@ -0,0 +1,72 @@ +#include "CmdNetworkAddress.h" +#include + +CmdNetworkAddress::CmdNetworkAddress(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Network Address", "AT+NA", "Network address (devAddr in LoraMac) (4 bytes)"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(hex:4)"; + _queryable = true; +} + +uint32_t CmdNetworkAddress::action(std::vector args) +{ + std::vector addr; + + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Network Address: "); + + addr = _dot->getNetworkAddress(); + + _serial.writef("%02x:%02x:%02x:%02x\r\n", addr[0], addr[1], addr[2], addr[3]); + } + else if (args.size() == 2) + { + int32_t code; + uint8_t temp; + uint32_t step = 2; + + if (args[1].find(":") != std::string::npos || args[1].find(".") != std::string::npos || args[1].find("-") != std::string::npos) + step = 3; + + // Convert the ASCII hex data to binary... + for (size_t i = 0; i < args[1].size(); i += step) + { + sscanf(&args[1][i], "%02x", &temp); + addr.push_back(temp); + } + + if ((code = _dot->setNetworkAddress(addr)) == mDot::MDOT_OK) { + _serial.writef("Set Network Address: "); + _serial.writef("%02x:%02x:%02x:%02x\r\n", addr[0], addr[1], addr[2], addr[3]); + } else { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdNetworkAddress::verify(std::vector args) +{ + if (args.size() == 1) { + return true; + } + + if (args.size() == 2) { + if (!isHexString(args[1], 4)) + { + setErrorMessage("Invalid address, expects (hex:4)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} diff --git a/CommandTerminal/CmdNetworkAddress.h b/CommandTerminal/CmdNetworkAddress.h new file mode 100644 index 0000000..7be2dd0 --- /dev/null +++ b/CommandTerminal/CmdNetworkAddress.h @@ -0,0 +1,20 @@ +#ifndef __CMDNETWORKADDRESS_H__ +#define __CMDNETWORKADDRESS_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdNetworkAddress : public Command { + +public: + + CmdNetworkAddress(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDNETWORKADDRESS_H__ diff --git a/CommandTerminal/CmdNetworkId.cpp b/CommandTerminal/CmdNetworkId.cpp new file mode 100644 index 0000000..fffe9f7 --- /dev/null +++ b/CommandTerminal/CmdNetworkId.cpp @@ -0,0 +1,110 @@ +#include "CmdNetworkId.h" + +CmdNetworkId::CmdNetworkId(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Network ID", "AT+NI", "Configured Network EUI/Name (App EUI in LoraMac) AT+NI=0,hex AT+NI=1,network_name (Net ID = crc64(network_name)) (8 bytes)"), + _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(0,(hex:8)),(1,(string:128))"; + _queryable = true; +} + +uint32_t CmdNetworkId::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Network ID: "); + + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getNetworkId(), ":").c_str()); + + if (!_dot->getNetworkName().empty()) + _serial.writef("Passphrase: '%s'\r\n", _dot->getNetworkName().c_str()); + } + else + { + int32_t code; + + if (args[1].find("1") == 0 && args[1].size() == 1) + { + std::string text; + if (args.size() > 3) + { + // passphrase was split on commas + for (size_t i = 2; i < args.size(); i++) + { + text.append(args[i]); + if (i < args.size() - 1) + text.append(","); + } + } + else + { + text = args[2]; + } + + if ((code = _dot->setNetworkName(text)) == mDot::MDOT_OK) + { + _serial.writef("Set Network Name: "); + _serial.writef("%s\r\n", text.c_str()); + } + else + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + + } + else + { + std::vector NewKey; + readByteArray(args[2], NewKey, EUI_LENGTH); + if ((code = _dot->setNetworkId(NewKey)) == mDot::MDOT_OK) + { + _serial.writef("Set Network ID: "); + _serial.writef("%s\r\n", mts::Text::bin2hexString(NewKey, ".").c_str()); + } + else + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + } + + return 0; +} + +bool CmdNetworkId::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 3) { + if (args[1] != "0" && args[1] != "1") { + setErrorMessage("Invalid type, expects (0,1)"); + return false; + } + if (args[1] == "0" && !isHexString(args[2], 8)) { + setErrorMessage("Invalid ID, expects (hex:8"); + return false; + } + + if (args[1] == "1" && args[2].size() < 8) { + setErrorMessage("Invalid name, expects minimum 8 characters"); + return false; + } + + if (args[1] == "1" && args[2].size() > 128) { + setErrorMessage("Invalid name, expects (string:128)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} diff --git a/CommandTerminal/CmdNetworkId.h b/CommandTerminal/CmdNetworkId.h new file mode 100644 index 0000000..09acdc6 --- /dev/null +++ b/CommandTerminal/CmdNetworkId.h @@ -0,0 +1,20 @@ +#ifndef __CMDNETWORKID_H__ +#define __CMDNETWORKID_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdNetworkId : public Command { + +public: + + CmdNetworkId(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDNETWORKID_H__ diff --git a/CommandTerminal/CmdNetworkJoinMode.cpp b/CommandTerminal/CmdNetworkJoinMode.cpp new file mode 100644 index 0000000..b5efdf6 --- /dev/null +++ b/CommandTerminal/CmdNetworkJoinMode.cpp @@ -0,0 +1,55 @@ +#include "CmdNetworkJoinMode.h" + +CmdNetworkJoinMode::CmdNetworkJoinMode(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Network Join Mode", "AT+NJM", "0: Manual configuration, 1: OTA Network Join, 2: Auto OTA Network Join on start up (default: 1)"), + _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(0-2)"; + _queryable = true; +} + +uint32_t CmdNetworkJoinMode::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("%s: ", name()); + + _serial.writef("%u\r\n", _dot->getJoinMode()); + } + else if (args.size() == 2) + { + int32_t code; + uint8_t mode = (args[1] == "1") ? 1 : 0; + mode = (args[1] == "2" ? 2 : mode); + if ((code = _dot->setJoinMode(mode)) != mDot::MDOT_OK) + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdNetworkJoinMode::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + if (!(args[1] == "0" || args[1] == "1" || args[1] == "2")) + { + setErrorMessage("Invalid parameter, expects (0: Manual, 1: OTA, 2: Auto OTA)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} diff --git a/CommandTerminal/CmdNetworkJoinMode.h b/CommandTerminal/CmdNetworkJoinMode.h new file mode 100644 index 0000000..81d00d0 --- /dev/null +++ b/CommandTerminal/CmdNetworkJoinMode.h @@ -0,0 +1,20 @@ +#ifndef __CMDNETWORKJOINMODE_H__ +#define __CMDNETWORKJOINMODE_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdNetworkJoinMode : public Command { + +public: + + CmdNetworkJoinMode(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDNETWORKJOINMODE_H__ diff --git a/CommandTerminal/CmdNetworkKey.cpp b/CommandTerminal/CmdNetworkKey.cpp new file mode 100644 index 0000000..f85725c --- /dev/null +++ b/CommandTerminal/CmdNetworkKey.cpp @@ -0,0 +1,110 @@ +#include "CmdNetworkKey.h" + +CmdNetworkKey::CmdNetworkKey(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Network Key", "AT+NK", "Configured network key/passphrase (App Key in LoraMac) ## AT+NK=0,hex AT+NK=1,passphrase (Net key = cmac(passphrase)) (16 bytes)"), + _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(0,(hex:16)),(1,(string:128))"; + _queryable = true; +} + +uint32_t CmdNetworkKey::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Network Key: "); + + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getNetworkKey(), ".").c_str()); + if (!_dot->getNetworkPassphrase().empty()) + _serial.writef("Passphrase: '%s'\r\n", _dot->getNetworkPassphrase().c_str()); + + } + else if (args.size() == 3) + { + int32_t code; + + if (args[1].find("1") == 0 && args[1].size() == 1) + { + std::string text; + if (args.size() > 3) + { + // passphrase was split on commas + for (size_t i = 2; i < args.size(); i++) + { + text.append(args[i]); + if (i < args.size() - 1) + text.append(","); + } + } + else + { + text = args[2]; + } + + if ((code = _dot->setNetworkPassphrase(text)) == mDot::MDOT_OK) + { + _serial.writef("Set Network Passphrase: "); + _serial.writef("%s\r\n", text.c_str()); + } + else + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + else + { + std::vector NewKey; + readByteArray(args[2], NewKey, KEY_LENGTH); + if ((code = _dot->setNetworkKey(NewKey)) == mDot::MDOT_OK) + { + _serial.writef("Set Network Key: "); + _serial.writef("%s\r\n", mts::Text::bin2hexString(NewKey, ".").c_str()); + } + else + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + } + + return 0; +} + +bool CmdNetworkKey::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 3) { + if (args[1] != "0" && args[1] != "1") { + setErrorMessage("Invalid type, expects (0,1)"); + return false; + } + if (args[1] == "0" && !isHexString(args[2], 16)) { + setErrorMessage("Invalid key, expects (hex:16)"); + return false; + } + + if (args[1] == "1" && args[2].size() < 8) { + setErrorMessage("Invalid name, expects minimum 8 characters"); + return false; + } + + if (args[1] == "1" && (args[2].size() > 128 || args[2].size() < 8)) { + setErrorMessage("Invalid passphrase, expects (string:8-128)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} + diff --git a/CommandTerminal/CmdNetworkKey.h b/CommandTerminal/CmdNetworkKey.h new file mode 100644 index 0000000..f2874cc --- /dev/null +++ b/CommandTerminal/CmdNetworkKey.h @@ -0,0 +1,22 @@ + +#ifndef __CMDNETWORKKEY_H__ +#define __CMDNETWORKKEY_H__ + + +#include "Command.h" + +class CommandTerminal; + +class CmdNetworkKey : public Command { + +public: + + CmdNetworkKey(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDNETWORKKEY_H__ diff --git a/CommandTerminal/CmdNetworkSessionKey.cpp b/CommandTerminal/CmdNetworkSessionKey.cpp new file mode 100644 index 0000000..4d42505 --- /dev/null +++ b/CommandTerminal/CmdNetworkSessionKey.cpp @@ -0,0 +1,57 @@ +#include "CmdNetworkSessionKey.h" + +CmdNetworkSessionKey::CmdNetworkSessionKey(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Network Session Key", "AT+NSK", "Network session encryption key (16 bytes)"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(hex:16)"; + _queryable = true; +} + +uint32_t CmdNetworkSessionKey::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Network Session Key: "); + + _serial.writef("%s\r\n", mts::Text::bin2hexString(_dot->getNetworkSessionKey(), ".").c_str()); + } + else if (args.size() == 2) + { + int32_t code; + std::vector NewKey; + + // Read in the key components... + readByteArray(args[1], NewKey, KEY_LENGTH); + + if ((code = _dot->setNetworkSessionKey(NewKey)) == mDot::MDOT_OK) { + _serial.writef("Set Network Session Key: "); + _serial.writef("%s\r\n", mts::Text::bin2hexString(NewKey, ".").c_str()); + } else { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdNetworkSessionKey::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) { + if (!isHexString(args[1], 16)) { + setErrorMessage("Invalid key, expects (hex:16)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} diff --git a/CommandTerminal/CmdNetworkSessionKey.h b/CommandTerminal/CmdNetworkSessionKey.h new file mode 100644 index 0000000..4d8cc46 --- /dev/null +++ b/CommandTerminal/CmdNetworkSessionKey.h @@ -0,0 +1,20 @@ +#ifndef __CMDNETWORKSESSIONKEY_H__ +#define __CMDNETWORKSESSIONKEY_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdNetworkSessionKey : public Command { + +public: + + CmdNetworkSessionKey(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDNETWORKSESSIONKEY_H__ diff --git a/CommandTerminal/CmdPublicNetwork.cpp b/CommandTerminal/CmdPublicNetwork.cpp new file mode 100644 index 0000000..74bbeee --- /dev/null +++ b/CommandTerminal/CmdPublicNetwork.cpp @@ -0,0 +1,52 @@ +#include "CmdPublicNetwork.h" + +CmdPublicNetwork::CmdPublicNetwork(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Public Network", "AT+PN", "Enable/disable public network mode. (0: off, 1: on)"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(0,1)"; + _queryable = true; +} + +uint32_t CmdPublicNetwork::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("%s: ", name()); + + _serial.writef("%d\r\n", _dot->getPublicNetwork()); + } + else if (args.size() == 2) + { + int32_t code; + bool enable = (args[1] == "1"); + + if ((code = _dot->setPublicNetwork(enable)) != mDot::MDOT_OK) { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdPublicNetwork::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + if (args[1] != "1" && args[1] != "0") { + setErrorMessage("Invalid parameter, expects (0: off, 1: on)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} diff --git a/CommandTerminal/CmdPublicNetwork.h b/CommandTerminal/CmdPublicNetwork.h new file mode 100644 index 0000000..9efec06 --- /dev/null +++ b/CommandTerminal/CmdPublicNetwork.h @@ -0,0 +1,21 @@ +#ifndef __CMDPUBLICNETWORK_H__ +#define __CMDPUBLICNETWORK_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdPublicNetwork : public Command { + +public: + + CmdPublicNetwork(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + + mts::MTSSerial& _serial; +}; + +#endif // __CMDPUBLICNETWORK_H__ diff --git a/CommandTerminal/CmdSaveConfig.cpp b/CommandTerminal/CmdSaveConfig.cpp new file mode 100644 index 0000000..712ba09 --- /dev/null +++ b/CommandTerminal/CmdSaveConfig.cpp @@ -0,0 +1,17 @@ +#include "CmdSaveConfig.h" + +CmdSaveConfig::CmdSaveConfig(mDot* dot) : Command(dot, "Save Configuration", "AT&W", "Save configuration to flash memory") +{ + _help = std::string(text()) + ": " + std::string(desc()); +} + + +uint32_t CmdSaveConfig::action(std::vector args) +{ + if (!_dot->saveConfig()) { + setErrorMessage("Failed to save to flash"); + return 1; + } + + return 0; +} diff --git a/CommandTerminal/CmdSaveConfig.h b/CommandTerminal/CmdSaveConfig.h new file mode 100644 index 0000000..dbf9671 --- /dev/null +++ b/CommandTerminal/CmdSaveConfig.h @@ -0,0 +1,17 @@ + +#ifndef __CmdSaveConfig_H__ +#define __CmdSaveConfig_H__ + +#include "Command.h" + +class CmdSaveConfig : public Command { + +public: + + CmdSaveConfig(mDot* dot); + virtual uint32_t action(std::vector args); + +private: +}; + +#endif // __CmdSaveConfig_H__ diff --git a/CommandTerminal/CmdTxDataRate.cpp b/CommandTerminal/CmdTxDataRate.cpp new file mode 100644 index 0000000..2d38f42 --- /dev/null +++ b/CommandTerminal/CmdTxDataRate.cpp @@ -0,0 +1,89 @@ +#include "CmdTxDataRate.h" + +CmdTxDataRate::CmdTxDataRate(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Tx Data Rate", "AT+TXDR", "Set the Tx data rate for all channels"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + + if (_dot->getFrequencyBand() == mDot::FB_915) + _usage = "(7-10)"; + else + _usage = "(7-12)"; + _queryable = true; +} + +uint32_t CmdTxDataRate::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Tx Data Rate: "); + + _serial.writef("%s\r\n", mDot::DataRateStr(_dot->getTxDataRate()).c_str()); + } + else if (args.size() == 2) + { + int32_t code; + uint8_t datarate = 0; + uint8_t i; + + for (i = 0; i < 8; i++) + { + if (mDot::DataRateStr(i).find(args[1].c_str()) != std::string::npos) + { + datarate = i; + break; + } + } + + if ((code = _dot->setTxDataRate(datarate)) != mDot::MDOT_OK) + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdTxDataRate::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + uint8_t i; + int datarate = -1; + for (i = 0; i < 8; i++) + { + if (mDot::DataRateStr(i).find(args[1].c_str()) != std::string::npos) + { + datarate = i; + break; + } + } + + if (datarate < 0) + { + if (_dot->getFrequencyBand() == mDot::FB_915) + setErrorMessage("Invalid data rate, expects (7-10)"); + else + setErrorMessage("Invalid data rate, expects (7-12)"); + return false; + } + + if (_dot->getFrequencyBand() == mDot::FB_915) { + if (datarate < 2) { + setErrorMessage("Invalid data rate, expects (7-10)"); + return false; + } + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} diff --git a/CommandTerminal/CmdTxDataRate.h b/CommandTerminal/CmdTxDataRate.h new file mode 100644 index 0000000..e848b9a --- /dev/null +++ b/CommandTerminal/CmdTxDataRate.h @@ -0,0 +1,20 @@ +#ifndef __CMDTXDATARATE_H__ +#define __CMDTXDATARATE_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdTxDataRate : public Command { + +public: + + CmdTxDataRate(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDTXDATARATE_H__ diff --git a/CommandTerminal/CmdTxPower.cpp b/CommandTerminal/CmdTxPower.cpp new file mode 100644 index 0000000..8816b46 --- /dev/null +++ b/CommandTerminal/CmdTxPower.cpp @@ -0,0 +1,62 @@ +#include "CmdTxPower.h" + +CmdTxPower::CmdTxPower(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Tx Power", "AT+TXP", "Set the Tx power for all channels"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(2-20)"; + _queryable = true; +} + +uint32_t CmdTxPower::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Tx Power: "); + + _serial.writef("%lu\r\n", _dot->getTxPower()); + } + else if (args.size() == 2) + { + int32_t code; + uint32_t power = 0; + sscanf(args[1].c_str(), "%lu", &power); + + if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdTxPower::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + uint32_t power = 0; + if (sscanf(args[1].c_str(), "%lu", &power) != 1) { + setErrorMessage("Invalid argument"); + return false; + } + + if (power < 2 || power > 20) + { + setErrorMessage("Invalid power, expects (2-20)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} + diff --git a/CommandTerminal/CmdTxPower.h b/CommandTerminal/CmdTxPower.h new file mode 100644 index 0000000..4b12b08 --- /dev/null +++ b/CommandTerminal/CmdTxPower.h @@ -0,0 +1,21 @@ +#ifndef __CMDTXPOWER_H__ +#define __CMDTXPOWER_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdTxPower: public Command +{ + +public: + + CmdTxPower(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDTXPOWER_H__ diff --git a/CommandTerminal/Command.cpp b/CommandTerminal/Command.cpp new file mode 100644 index 0000000..5282f45 --- /dev/null +++ b/CommandTerminal/Command.cpp @@ -0,0 +1,128 @@ +#include "Command.h" +#include + +const char Command::newline[] = "\r\n"; + +Command::Command(mDot* dot) : _dot(dot) +{ + _usage = "NONE"; + _queryable = false; +} + +Command::Command(mDot* dot, const char* name, const char* text, const char* desc) : + _dot(dot), _name(name), _text(text), _desc(desc) +{ + _usage = "NONE"; + _queryable = false; +} + +std::string &Command::errorMessage() +{ + return _errorMessage; +} + +void Command::setErrorMessage(const char* message) +{ + _errorMessage.assign(message); +} + +void Command::setErrorMessage(const std::string& message) +{ + _errorMessage.assign(message); +} + +const std::string Command::usage() const +{ + std::string usage(_text); + usage.append(": "); + usage.append(_usage); + return usage; +} + +const bool Command::queryable() +{ + return _queryable; +} + +void Command::readByteArray(const std::string& input, std::vector& out, size_t len) +{ + // if input length is greater than expected byte output + // there must be a delimiter included + if (input.length() > len * 2) + { + std::vector < std::string > bytes; + if (input.find(" ") != std::string::npos) + bytes = mts::Text::split(input, " "); + else if (input.find(":") != std::string::npos) + bytes = mts::Text::split(input, ":"); + else if (input.find("-") != std::string::npos) + bytes = mts::Text::split(input, "-"); + else if (input.find(".") != std::string::npos) + bytes = mts::Text::split(input, "."); + + if (bytes.size() != len) { + return; + } + + uint8_t temp; + // Read in the key components... + for (size_t i = 0; i < len; i++) + { + sscanf(bytes[i].c_str(), "%02x", &temp); + out.push_back(temp); + } + } + else + { + // no delims + uint8_t temp; + + // Read in the key components... + for (size_t i = 0; i < len; i++) + { + if (i * 2 < input.size()) + { + sscanf(input.substr(i * 2).c_str(), "%02x", &temp); + out.push_back(temp); + } + } + } +} + +bool Command::isHexString(const std::string& str, size_t bytes) { + size_t numDelims = bytes - 1; + size_t minSize = bytes * 2; + size_t maxSize = minSize + numDelims; + + if (str.size() == minSize) { + return str.find_first_not_of("0123456789abcdefABCDEF") == std::string::npos; + } + else if (str.size() == maxSize) { + if (str.find_first_of(":-.") == std::string::npos) { + // no delim found + return false; + } + if (str.find(":") != std::string::npos && std::count(str.begin(), str.end(), ':') != numDelims) { + return false; + } + if (str.find(".") != std::string::npos && std::count(str.begin(), str.end(), '.') != numDelims) { + return false; + } + if (str.find("-") != std::string::npos && std::count(str.begin(), str.end(), '-') != numDelims) { + return false; + } + + return str.find_first_not_of("0123456789abcdefABCDEF:-.") == std::string::npos; + } + + return false; +} + +bool Command::verify(std::vector args) { + if (args.size() == 1) + return true; + + setErrorMessage("Invalid arguments"); + return false; +} + diff --git a/CommandTerminal/Command.h b/CommandTerminal/Command.h new file mode 100644 index 0000000..bf46158 --- /dev/null +++ b/CommandTerminal/Command.h @@ -0,0 +1,98 @@ +/** + ****************************************************************************** + * File Name : Command.h + * Date : 18/04/2014 10:57:12 + * Description : This file provides code for command line prompt + ****************************************************************************** + * + * COPYRIGHT(c) 2014 MultiTech Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +#include "mbed.h" +#include "mDot.h" +#include "MTSSerial.h" +#include "MTSText.h" +#include +#include +#include +#include "limits.h" +#include "debug.h" + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __command_H +#define __command_H + +#define KEY_LENGTH 16 +#define EUI_LENGTH 8 +#define PASSPHRASE_LENGTH 128 + +class Command { + + public: + + Command(mDot* dot); + Command(mDot* dot, const char* name, const char* text, const char* desc); + virtual ~Command() {}; + + const char* name() const { return _name; }; + const char* text() const { return _text; }; + const char* desc() const { return _desc; }; + const char* help() const { return _help.c_str(); }; + + virtual uint32_t action(std::vector args) = 0; + virtual bool verify(std::vector args); + const std::string usage() const; + std::string& errorMessage(); + const bool queryable(); + + static const char newline[]; + static void readByteArray(const std::string& input, std::vector& out, size_t len); + + static bool isHexString(const std::string& str, size_t bytes); + static bool isBaudRate(uint32_t baud); + + protected: + + void setErrorMessage(const char* message); + void setErrorMessage(const std::string& message); + std::string _help; + std::string _usage; + bool _queryable; + mDot* _dot; + + private: + + const char* _name; + const char* _text; + const char* _desc; + std::string _errorMessage; + +}; + +#endif /*__ command_H */ + +/************************ (C) COPYRIGHT MultiTech Systems, Inc *****END OF FILE****/ diff --git a/CommandTerminal/CommandTerminal.cpp b/CommandTerminal/CommandTerminal.cpp new file mode 100644 index 0000000..65509bb --- /dev/null +++ b/CommandTerminal/CommandTerminal.cpp @@ -0,0 +1,631 @@ +#include "ctype.h" +#include "CommandTerminal.h" +#include "Command.h" +#include "MTSLog.h" +#include +#include + +const char CommandTerminal::banner[] = "\r\n\nMultiTech Systems LoRa XBee Module\r\n\n"; +const char CommandTerminal::helpline[] = "Enter '?' for help\r\n"; + +const char CommandTerminal::newline[] = "\r\n"; + +// Command error text... +const char CommandTerminal::command_error[] = "Command not found!\r\n"; + +// Response texts... +const char CommandTerminal::help[] = "\r\nHelp\r\n"; +const char CommandTerminal::cmd_error[] = "Invalid command\r\n"; +const char CommandTerminal::done[] = "\r\nOK\r\n"; +const char CommandTerminal::error[] = "\r\nERROR\r\n"; + +// Escape sequence... +const char CommandTerminal::escape_sequence[] = "+++"; + +mts::MTSSerial* CommandTerminal::_serialp = NULL; + +void CommandTerminal::addCommand(Command* cmd) { + _commands.push_back(cmd); +} + +CommandTerminal::CommandTerminal(mts::MTSSerial& serial, mDot* dot) +: + _serial(serial), + _dot(dot), + _mode(mDot::COMMAND_MODE), + _idle_thread(idle, NULL, osPriorityLow), + _sleep_standby(true), + _xbee_on_sleep(XBEE_ON_SLEEP), + _serial_up(false) { + + _serialp = &serial; + + addCommand(new CmdAttention(_dot)); + addCommand(new CmdIdentification(_dot, serial)); + addCommand(new CmdFactoryDefault(_dot)); + addCommand(new CmdSaveConfig(_dot)); + addCommand(new CmdDisplayConfig(_dot, serial)); + + addCommand(new CmdFrequencySubBand(_dot, serial)); + addCommand(new CmdPublicNetwork(_dot, serial)); + addCommand(new CmdDeviceId(_dot, serial)); + + addCommand(new CmdNetworkAddress(_dot, serial)); + addCommand(new CmdNetworkSessionKey(_dot, serial)); + addCommand(new CmdDataSessionKey(_dot, serial)); + addCommand(new CmdNetworkKey(_dot, serial)); + addCommand(new CmdNetworkId(_dot, serial)); + + addCommand(new CmdNetworkJoinMode(_dot, serial)); + addCommand(new CmdTxDataRate(_dot, serial)); + addCommand(new CmdTxPower(_dot, serial)); +} + +void CommandTerminal::printHelp() { + const char* name = NULL; + const char* text = NULL; + const char* desc = NULL; + const char* tab = "\t"; + + std::string header("Command"); + header.append(tab); + header.append(tab); + header.append("Name"); + header.append(tab); + header.append(tab); + header.append(tab); + header.append("Description"); + + write(newline); + write(header.c_str()); + write(newline); + write(newline); + for (std::vector::iterator it = _commands.begin(); it != _commands.end(); ++it) { + name = (*it)->name(); + text = (*it)->text(); + desc = (*it)->desc(); + write(text); + if (strlen(text) < 8) + write(tab); + write(tab); + write(name); + if (strlen(name) < 8) + write(tab); + if (strlen(name) < 16) + write(tab); + write(tab); + write(desc); + write(newline); + } + + write(newline); +} + +bool CommandTerminal::writeable() { + return _serial.writeable(); +} + +bool CommandTerminal::readable() { + return _serial.readable(); +} + +char CommandTerminal::read() { + char ch; + _serial.read(&ch, 1); + return ch; +} + +void CommandTerminal::write(const char* message) { + while (!writeable()) + ; + _serial.write(message, strlen(message)); +} + +void CommandTerminal::writef(const char* format, ...) { + char buff[256]; + + va_list ap; + va_start(ap, format); + int size = vsnprintf(buff, 256, format, ap); + while (!writeable()) + ; + _serial.write(buff, size); + va_end(ap); +} + +void CommandTerminal::serial_loop() { + Timer serial_read_timer; + std::vector serial_buffer; + std::string escape_buffer; + Timer escape_timer; + int escape_delay = 100; + uint8_t max_send_size; + + _serial_up = true; + _xbee_on_sleep = GPIO_PIN_SET; + + if (_dot->getFrequencyBand() == mDot::FB_915) + max_send_size = mDot::MaxLengths_915[_dot->getTxDataRate()]; + else + max_send_size = mDot::MaxLengths_868[_dot->getTxDataRate()]; + + logDebug("Awake\r\n"); + wakeup(_sleep_standby); + + char ch; + + if (readable()) { + ch = read(); + serial_buffer.push_back(ch); + + if (escape_timer.read_ms() > escape_delay && ch == '+') { + escape_buffer += ch; + escape_timer.reset(); + } else { + _serial_up = true; + escape_buffer.clear(); + } + + if (escape_buffer.length() == 3 && escape_buffer.find(escape_sequence) == 0) { + _mode = mDot::COMMAND_MODE; + logDebug("Exit serial mode\r\n"); + escape_timer.stop(); + escape_buffer.clear(); + write(done); + return; + } + } + + if (_serial_up) { + serial_read_timer.start(); + uint32_t timeout = _dot->getWakeDelay(); + + // wait for timeout or start of serial data + while (!readable() && serial_read_timer.read_ms() < timeout) { + osDelay(10); + } + + serial_read_timer.reset(); + timeout = _dot->getWakeTimeout(); + while (_serial_up && serial_read_timer.read_ms() < timeout) { + while (readable() && serial_buffer.size() < max_send_size) { + serial_buffer.push_back(read()); + serial_read_timer.reset(); + } + } + serial_read_timer.stop(), serial_read_timer.reset(); + + if (!serial_buffer.empty()) { + _serial_up = false; + _xbee_on_sleep = GPIO_PIN_RESET; + if (!_dot->getIsTransmitting()) { + std::vector recv_buffer; + logDebug("Received serial data, sending out radio.\r\n"); + + if (_dot->send(serial_buffer) != mDot::MDOT_OK) + logDebug("Send failed.\r\n"); + + if (_dot->recv(recv_buffer)) + _serial.writef("%s\r\n", formatPacketData(recv_buffer, _dot->getRxOutput()).c_str()); + } else { + logDebug("Radio is busy, cannot send.\r\n"); + } + + serial_buffer.clear(); + } else { + logDebug("No data received from serial to send.\r\n"); + } + _serial_up = false; + } + sleep(_sleep_standby); +} + +bool CommandTerminal::autoJoinCheck() { + + std::string escape_buffer; + char ch; + int sleep = 1000; + int escape_timeout = 1000; + Timer tmr; + Timer escape_tmr; + int cnt = 0; + + while (!_dot->getNetworkJoinStatus()) { + wakeup(_sleep_standby); + write("\r\nJoining network... "); + + // wait one second for possible escape + tmr.reset(); + tmr.start(); + escape_tmr.reset(); + escape_tmr.start(); + while (tmr.read_ms() < 1000) { + if (_serial.readable()) { + _serial.read(&ch, 1); + escape_buffer += ch; + } + + if (escape_buffer.find(escape_sequence) != std::string::npos) { + _mode = mDot::COMMAND_MODE; + write("Join Canceled\r\n"); + write(done); + return true; + } + + if (escape_tmr.read_ms() > escape_timeout) + escape_buffer.clear(); + } + + if (_dot->joinNetworkOnce() == mDot::MDOT_OK) { + write("Network Joined\r\n"); + write(done); + return false; + } + + write("Network Join failed\r\n"); + write(error); + + if (cnt++ > _dot->getJoinRetries()) { + cnt = 0; + + if (_dot->getFrequencyBand() == mDot::FB_915) { + uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1; + logDebug("Join retries exhausted, switching to sub band %u\r\n", band); + _dot->setFrequencySubBand(band); + } + + if (sleep < 60 * 60 * 1000) + sleep *= 2; + } + + tmr.reset(); + tmr.start(); + escape_tmr.reset(); + escape_tmr.start(); + while (tmr.read_ms() < sleep) { + if (_serial.readable()) { + _serial.read(&ch, 1); + escape_buffer += ch; + } + + if (escape_buffer.find(escape_sequence) != std::string::npos) { + _mode = mDot::COMMAND_MODE; + return true; + } + + if (escape_tmr.read_ms() > escape_timeout) + escape_buffer.clear(); + } + + } + + return false; +} + +void CommandTerminal::start() { + + wakeup(_sleep_standby); + + char ch; + bool running = true; + bool echo = _dot->getEcho(); + std::string command; + std::deque history; + int history_index = -1; + std::vector args; + + if (_dot->getStartUpMode() == mDot::SERIAL_MODE) { + command = "AT+SD\n"; + + std::string escape_buffer; + char ch; + + int escape_timeout = 1000; + Timer tmr; + Timer escape_tmr; + + // wait one second for possible escape + tmr.reset(); + tmr.start(); + escape_tmr.reset(); + escape_tmr.start(); + while (tmr.read_ms() < escape_timeout) { + if (_serial.readable()) { + _serial.read(&ch, 1); + escape_buffer += ch; + } + + if (escape_buffer.find(escape_sequence) != std::string::npos) { + _mode = mDot::COMMAND_MODE; + command.clear(); + break; + } + + if (escape_tmr.read_ms() > escape_timeout) + escape_buffer.clear(); + + osDelay(1); + } + + } + + bool join_canceled = false; + + //Run terminal session + while (running) { + if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) { + join_canceled = autoJoinCheck(); + if (join_canceled) + command.clear(); + } + + if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) { + switch (_mode) { + case mDot::SERIAL_MODE: + // signal wakeup, read serial and output to radio + serial_loop(); + continue; + break; + default: + break; + } + } + + ch = '\0'; + + // read characters + if (readable()) { + ch = read(); + + if (ch == '\b' || ch == 0x7f) { + if (!command.empty()) { + writef("\b \b"); + command.erase(command.size() - 1); + } + continue; + } else if (ch == 0x1b || ch == 0x09) { + osDelay(20); + // catch escape sequence, or tab + char ch1, ch2; + + if (readable()) { + ch1 = read(); + if (readable()) + ch2 = read(); + + if (ch1 == 0x5b && ch2 == 0x41) { + // up key + for (int i = 0; i < command.size()+1; i++) { + writef("\b \b"); + } + if (history.size() > 0) { + if (++history_index >= history.size() - 1) + history_index = history.size() - 1; + + command = history[history_index]; + writef("%s", history[history_index].c_str()); + } else { + command.clear(); + } + } else if (ch1 == 0x5b && ch2 == 0x42) { + + // down key + for (int i = 0; i < command.size()+1; i++) { + writef("\b \b"); + } + + if (--history_index < 0) { + history_index = -1; + command.clear(); + } else { + command = history[history_index]; + writef("%s", history[history_index].c_str()); + } + } + } + while (readable()) read(); + continue; + } else { + command += ch; + } + + // echo chars if enabled + if (echo && !(ch == '\r' || ch == '\n')) + writef("%c", ch); + } + + // look for end of command line + if (command.find("\n") != std::string::npos || command.find("\r") != std::string::npos) { + // remove new line or cr character + command.erase(command.size() - 1); + write("\r"); // match standard modem output + write(newline); + } else { + continue; + } + + // trim whitespace from command + mts::Text::trim(command, "\r\n\t "); + + if (command.size() < 1) { + command.clear(); + continue; + } + + // parse command and args + args.clear(); + + // find first '=' character + size_t delim_index = command.find("="); + if (delim_index != std::string::npos) { + args.push_back(command.substr(0, delim_index)); + } else { + // find first ' ' character + delim_index = command.find(" "); + if (delim_index != std::string::npos) { + args.push_back(command.substr(0, delim_index)); + } else { + args.push_back(command); + } + } + + if (delim_index != std::string::npos) { + std::vector params = mts::Text::split(command.substr(delim_index + 1), ","); + args.insert(args.end(), params.begin(), params.end()); + } + + args[0] = mts::Text::toUpper(args[0]); + + // print help + if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) { + printHelp(); + command.clear(); + } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) { + _dot->setEcho(false); + write(done); + echo = _dot->getEcho(); + } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) { + _dot->setEcho(true); + write(done); + echo = _dot->getEcho(); + } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) { + _dot->setVerbose(false); + write(done); + } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) { + _dot->setVerbose(true); + write(done); + } else if (args[0] == "AT+SD") { + logDebug("Enter Serial Mode\r\n"); + _mode = mDot::SERIAL_MODE; + } else if (args[0] == "AT+SLEEP") { + if (args.size() > 1 && (args[1] != "?")) { + write("Invalid argument\r\n"); + write(error); + } else { + if (args.size() > 1 && args[1] == "?") { + write("AT+SLEEP: NONE\r\n"); + write(done); + } else { + _sleep_standby = !(args.size() > 1 && args[1] == "1"); + this->sleep(_sleep_standby); + wait(0.1); + write(done); + } + } + } else { + bool found = false; + bool query = false; + + std::string lookfor = args[0]; + + // per command help + if ((args[0].find("?") == 0 || args[0].find("HELP") == 0)) + lookfor = mts::Text::toUpper(args[1]); + + // trim off any trailing '?' and mark as a query command + if (args[0].rfind("?") == args[0].length() - 1) { + query = true; + lookfor = args[0].substr(0, args[0].length() - 1); + } + + // search for command + for (std::vector::iterator it = _commands.begin(); it != _commands.end() && !found; ++it) { + Command* cmd = *it; + + // match CMD or CMD? syntax if command is queryable + if (lookfor == cmd->text() && (!query || (query && cmd->queryable()))) { + found = true; + if (args[0] == "HELP") { + writef("%s%s", cmd->help(), newline); + write(done); + } + + else if (args.size() > 1 && args[1] == "?") { + writef("%s%s", cmd->usage().c_str(), newline); + write(done); + } else if (!cmd->verify(args)) { + writef("%s%s", cmd->errorMessage().c_str(), newline); + writef("%s", error); + } else { + if (cmd->action(args) == 0) { + writef("%s", done); + } else { + writef("%s%s", cmd->errorMessage().c_str(), newline); + writef("%s", error); + } + } + } + } + + if (!found) { + writef("%s", command_error); + writef("%s", error); + } + } + + if (history.size() == 0 || history.front() != command) + history.push_front(command); + history_index = -1; + command.clear(); + + while (history.size() > 10) + history.pop_back(); + + } +} + +std::string CommandTerminal::formatPacketData(const std::vector& data, const uint8_t& format) { + if (format == mDot::HEXADECIMAL) + return mts::Text::bin2hexString(data); + else + return std::string(data.begin(), data.end()); +} + +void CommandTerminal::sleep(bool standby) { + _serial_up = false; + _xbee_on_sleep = GPIO_PIN_RESET; + + _serial.rxClear(); + _serial.txClear(); + + _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby); +} + +bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) { + Timer timer; + Timer escape_timer; + std::string escape_buffer; + int escape_timeout = 1000; + + timer.start(); + while (timer.read_ms() < timeout) { + + if (dot != NULL) { + if (wait == WAIT_SEND && (!dot->getIsTransmitting())) { + return false; + } + } + + if (_serialp != NULL && _serialp->readable()) { + if (escape_buffer == "") + escape_timer.start(); + char ch; + _serialp->read(&ch, 1); + escape_buffer += ch; + if (escape_buffer == CommandTerminal::escape_sequence) + return true; + } + if (escape_timer.read_ms() > escape_timeout) { + escape_buffer = ""; + escape_timer.stop(), escape_timer.reset(); + } + + osDelay(10); + } + + return false; +} + +void CommandTerminal::wakeup(bool standby) { + +} diff --git a/CommandTerminal/CommandTerminal.h b/CommandTerminal/CommandTerminal.h new file mode 100644 index 0000000..e64ec41 --- /dev/null +++ b/CommandTerminal/CommandTerminal.h @@ -0,0 +1,118 @@ +/** + ****************************************************************************** + * File Name : command.h + * Date : 18/04/2014 10:57:12 + * Description : This file provides code for command line prompt + ****************************************************************************** + * + * COPYRIGHT(c) 2014 MultiTech Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +#include "mbed.h" +#include "MTSSerial.h" +#include "Commands.h" +#include "mDot.h" + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __command_terminal_H__ +#define __command_terminal_H__ + +class CommandTerminal { + +public: + + enum WaitType { + WAIT_JOIN, + WAIT_RECV, + WAIT_LINK, + WAIT_SEND, + WAIT_NA + }; + + CommandTerminal(mts::MTSSerial& serial, mDot* dot); + + // Command prompt text... + static const char banner[]; + static const char helpline[]; + static const char prompt[]; + + // Command error text... + static const char command_error[]; + + // Response texts... + static const char help[]; + static const char cmd_error[]; + static const char newline[]; + static const char done[]; + static const char error[]; + + // Escape sequence + static const char escape_sequence[]; + + static std::string formatPacketData(const std::vector& data, const uint8_t& format); + static bool waitForEscape(int timeout, mDot* dot=NULL, WaitType wait=WAIT_NA); + + void start(); + +private: + + static void idle(void const* args) { + while (1) + __WFI(); + } + + mts::MTSSerial& _serial; + static mts::MTSSerial* _serialp; + + mDot* _dot; + mDot::Mode _mode; + std::vector _commands; + Thread _idle_thread; + bool _sleep_standby; + DigitalOut _xbee_on_sleep; + bool _serial_up; + + void addCommand(Command* cmd); + + void serial_loop(); + bool autoJoinCheck(); + + void printHelp(); + + bool readable(); + bool writeable(); + char read(); + void write(const char* message); + void writef(const char* format, ... ); + + void sleep(bool standby); + void wakeup(bool standby); + +}; + +#endif // __command_terminal_H__ + diff --git a/CommandTerminal/Commands.h b/CommandTerminal/Commands.h new file mode 100644 index 0000000..5b699f4 --- /dev/null +++ b/CommandTerminal/Commands.h @@ -0,0 +1,19 @@ +#include "Command.h" + +#include "CmdAttention.h" +#include "CmdIdentification.h" + +#include "CmdFactoryDefault.h" +#include "CmdSaveConfig.h" +#include "CmdDisplayConfig.h" +#include "CmdDeviceId.h" +#include "CmdPublicNetwork.h" +#include "CmdNetworkAddress.h" +#include "CmdNetworkSessionKey.h" +#include "CmdDataSessionKey.h" +#include "CmdNetworkKey.h" +#include "CmdNetworkId.h" +#include "CmdNetworkJoinMode.h" +#include "CmdTxDataRate.h" +#include "CmdTxPower.h" +#include "CmdFrequencySubBand.h" diff --git a/CommandTerminal/Test/TestCommandTerminal.h b/CommandTerminal/Test/TestCommandTerminal.h new file mode 100644 index 0000000..0d5e801 --- /dev/null +++ b/CommandTerminal/Test/TestCommandTerminal.h @@ -0,0 +1,82 @@ +#ifndef TESTCOMMANDTERMINAL_H +#define TESTCOMMANDTERMINAL_H + +#include +#include + +#include "Commands.h" + +class MockSerial +{ + +public: + std::string read_buff; + std::string write_buff; + + int read(char* buff, int len) + { + + return 0; + } + + int write(char* buff) + { + write_buff.append(buff); + return 0; + } + + int writef(char* buff) + { + printf("MockSerial writef\r\n"); + write_buff.append(buff); + return 0; + } +}; + +class TestCommandTerminal: public TestCollection +{ +public: + TestCommandTerminal(); + ~TestCommandTerminal(); + + virtual void run(); + +}; + +TestCommandTerminal::TestCommandTerminal() : + TestCollection("CommandTerminal") +{ +} + +TestCommandTerminal::~TestCommandTerminal() +{ +} + +void TestCommandTerminal::run() +{ + MockSerial test_serial; + + Test::start("Test AT"); + CmdAttention at_cmd; + Test::assertTrue(std::string("AT").compare(at_cmd.text()) == 0); + std::vector < std::string > args; + args.push_back("AT"); + args.push_back("IGNORED"); + Test::assertTrue(at_cmd.verify(args)); + Test::assertTrue(at_cmd.action(args) == 0); + Test::end(); + +// Test::start("Test ATI"); +// printf("testing ati\r\n"); +// CmdIdentification ati_cmd((mts::MTSSerial&)test_serial); +// printf("cmd created\r\n"); +// Test::assertTrue(at_cmd.verify(args)); +// printf("verified\r\n"); +// Test::assertTrue(at_cmd.action(args) == 0); +// printf("actionied\r\n"); +// Test::assertTrue(test_serial.write_buff.find("MultiTech") == 0); +// Test::end(); + +} + +#endif /* TESTCOMMANDTERMINAL_H */ -- cgit v1.2.3 From a37b4b2a208989c45484f90dab141ca0191e7714 Mon Sep 17 00:00:00 2001 From: Leon Lindenfelser Date: Fri, 13 Nov 2015 14:39:22 -0600 Subject: CommandTerminal working on debug port --- main.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/main.cpp b/main.cpp index 5049cc2..f5f00c5 100644 --- a/main.cpp +++ b/main.cpp @@ -4,6 +4,7 @@ // MTS headers #include "mDot.h" #include "MTSLog.h" +#include "CommandTerminal.h" // sensor headers #include "ISL29011.h" #include "MMA845x.h" @@ -34,6 +35,9 @@ ButtonHandler* buttons; // Serial debug port Serial debug(USBTX, USBRX); +mts::MTSSerial serial(USBTX, USBRX, 512, 512); + + int main() { debug.baud(115200); @@ -50,6 +54,20 @@ int main() { osThreadId main_id = Thread::gettid(); buttons = new ButtonHandler(main_id); + + + mDot* dot = mDot::getInstance(); + if(dot){ + logInfo("dot created"); + CommandTerminal term(serial, dot); + term.start(); + } + else { + logInfo("Radio Init Failed!"); + } + + + while (true) { char buf[16]; size_t size; @@ -59,12 +77,15 @@ int main() { ButtonEvent ev = buttons->getButtonEvent(); switch (ev) { case sw1_press: + logInfo("SW1 press"); size = snprintf(buf, sizeof(buf), "SW1 press"); break; case sw1_hold: + logInfo("SW1 hold"); size = snprintf(buf, sizeof(buf), "SW1 hold"); break; case sw2_press: + logInfo("SW2 press"); size = snprintf(buf, sizeof(buf), "SW2 press"); break; } -- cgit v1.2.3 From e6bfab044122be837c2235a6bf634b369c753e9c Mon Sep 17 00:00:00 2001 From: Leon Lindenfelser Date: Fri, 13 Nov 2015 15:36:55 -0600 Subject: Removed unnecessary sleep, wakeup, serial loop, format data etc from command terminal --- CommandTerminal/CommandTerminal.cpp | 284 ------------------------------------ CommandTerminal/CommandTerminal.h | 11 -- 2 files changed, 295 deletions(-) diff --git a/CommandTerminal/CommandTerminal.cpp b/CommandTerminal/CommandTerminal.cpp index 65509bb..265009e 100644 --- a/CommandTerminal/CommandTerminal.cpp +++ b/CommandTerminal/CommandTerminal.cpp @@ -34,8 +34,6 @@ CommandTerminal::CommandTerminal(mts::MTSSerial& serial, mDot* dot) _dot(dot), _mode(mDot::COMMAND_MODE), _idle_thread(idle, NULL, osPriorityLow), - _sleep_standby(true), - _xbee_on_sleep(XBEE_ON_SLEEP), _serial_up(false) { _serialp = &serial; @@ -133,179 +131,7 @@ void CommandTerminal::writef(const char* format, ...) { va_end(ap); } -void CommandTerminal::serial_loop() { - Timer serial_read_timer; - std::vector serial_buffer; - std::string escape_buffer; - Timer escape_timer; - int escape_delay = 100; - uint8_t max_send_size; - - _serial_up = true; - _xbee_on_sleep = GPIO_PIN_SET; - - if (_dot->getFrequencyBand() == mDot::FB_915) - max_send_size = mDot::MaxLengths_915[_dot->getTxDataRate()]; - else - max_send_size = mDot::MaxLengths_868[_dot->getTxDataRate()]; - - logDebug("Awake\r\n"); - wakeup(_sleep_standby); - - char ch; - - if (readable()) { - ch = read(); - serial_buffer.push_back(ch); - - if (escape_timer.read_ms() > escape_delay && ch == '+') { - escape_buffer += ch; - escape_timer.reset(); - } else { - _serial_up = true; - escape_buffer.clear(); - } - - if (escape_buffer.length() == 3 && escape_buffer.find(escape_sequence) == 0) { - _mode = mDot::COMMAND_MODE; - logDebug("Exit serial mode\r\n"); - escape_timer.stop(); - escape_buffer.clear(); - write(done); - return; - } - } - - if (_serial_up) { - serial_read_timer.start(); - uint32_t timeout = _dot->getWakeDelay(); - - // wait for timeout or start of serial data - while (!readable() && serial_read_timer.read_ms() < timeout) { - osDelay(10); - } - - serial_read_timer.reset(); - timeout = _dot->getWakeTimeout(); - while (_serial_up && serial_read_timer.read_ms() < timeout) { - while (readable() && serial_buffer.size() < max_send_size) { - serial_buffer.push_back(read()); - serial_read_timer.reset(); - } - } - serial_read_timer.stop(), serial_read_timer.reset(); - - if (!serial_buffer.empty()) { - _serial_up = false; - _xbee_on_sleep = GPIO_PIN_RESET; - if (!_dot->getIsTransmitting()) { - std::vector recv_buffer; - logDebug("Received serial data, sending out radio.\r\n"); - - if (_dot->send(serial_buffer) != mDot::MDOT_OK) - logDebug("Send failed.\r\n"); - - if (_dot->recv(recv_buffer)) - _serial.writef("%s\r\n", formatPacketData(recv_buffer, _dot->getRxOutput()).c_str()); - } else { - logDebug("Radio is busy, cannot send.\r\n"); - } - - serial_buffer.clear(); - } else { - logDebug("No data received from serial to send.\r\n"); - } - _serial_up = false; - } - sleep(_sleep_standby); -} - -bool CommandTerminal::autoJoinCheck() { - - std::string escape_buffer; - char ch; - int sleep = 1000; - int escape_timeout = 1000; - Timer tmr; - Timer escape_tmr; - int cnt = 0; - - while (!_dot->getNetworkJoinStatus()) { - wakeup(_sleep_standby); - write("\r\nJoining network... "); - - // wait one second for possible escape - tmr.reset(); - tmr.start(); - escape_tmr.reset(); - escape_tmr.start(); - while (tmr.read_ms() < 1000) { - if (_serial.readable()) { - _serial.read(&ch, 1); - escape_buffer += ch; - } - - if (escape_buffer.find(escape_sequence) != std::string::npos) { - _mode = mDot::COMMAND_MODE; - write("Join Canceled\r\n"); - write(done); - return true; - } - - if (escape_tmr.read_ms() > escape_timeout) - escape_buffer.clear(); - } - - if (_dot->joinNetworkOnce() == mDot::MDOT_OK) { - write("Network Joined\r\n"); - write(done); - return false; - } - - write("Network Join failed\r\n"); - write(error); - - if (cnt++ > _dot->getJoinRetries()) { - cnt = 0; - - if (_dot->getFrequencyBand() == mDot::FB_915) { - uint8_t band = ((_dot->getFrequencySubBand()) % 8) + 1; - logDebug("Join retries exhausted, switching to sub band %u\r\n", band); - _dot->setFrequencySubBand(band); - } - - if (sleep < 60 * 60 * 1000) - sleep *= 2; - } - - tmr.reset(); - tmr.start(); - escape_tmr.reset(); - escape_tmr.start(); - while (tmr.read_ms() < sleep) { - if (_serial.readable()) { - _serial.read(&ch, 1); - escape_buffer += ch; - } - - if (escape_buffer.find(escape_sequence) != std::string::npos) { - _mode = mDot::COMMAND_MODE; - return true; - } - - if (escape_tmr.read_ms() > escape_timeout) - escape_buffer.clear(); - } - - } - - return false; -} - void CommandTerminal::start() { - - wakeup(_sleep_standby); - char ch; bool running = true; bool echo = _dot->getEcho(); @@ -315,8 +141,6 @@ void CommandTerminal::start() { std::vector args; if (_dot->getStartUpMode() == mDot::SERIAL_MODE) { - command = "AT+SD\n"; - std::string escape_buffer; char ch; @@ -349,28 +173,8 @@ void CommandTerminal::start() { } - bool join_canceled = false; - //Run terminal session while (running) { - if (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA) { - join_canceled = autoJoinCheck(); - if (join_canceled) - command.clear(); - } - - if (_dot->getJoinMode() != mDot::AUTO_OTA || (!join_canceled && _dot->getJoinMode() == mDot::AUTO_OTA)) { - switch (_mode) { - case mDot::SERIAL_MODE: - // signal wakeup, read serial and output to radio - serial_loop(); - continue; - break; - default: - break; - } - } - ch = '\0'; // read characters @@ -480,38 +284,6 @@ void CommandTerminal::start() { if ((args[0].find("?") == 0 || args[0].find("HELP") == 0) && args.size() == 1) { printHelp(); command.clear(); - } else if (args[0].find("ATE0") == 0 && args[0].length() == 4) { - _dot->setEcho(false); - write(done); - echo = _dot->getEcho(); - } else if (args[0].find("ATE1") == 0 && args[0].length() == 4) { - _dot->setEcho(true); - write(done); - echo = _dot->getEcho(); - } else if (args[0].find("ATV0") == 0 && args[0].length() == 4) { - _dot->setVerbose(false); - write(done); - } else if (args[0].find("ATV1") == 0 && args[0].length() == 4) { - _dot->setVerbose(true); - write(done); - } else if (args[0] == "AT+SD") { - logDebug("Enter Serial Mode\r\n"); - _mode = mDot::SERIAL_MODE; - } else if (args[0] == "AT+SLEEP") { - if (args.size() > 1 && (args[1] != "?")) { - write("Invalid argument\r\n"); - write(error); - } else { - if (args.size() > 1 && args[1] == "?") { - write("AT+SLEEP: NONE\r\n"); - write(done); - } else { - _sleep_standby = !(args.size() > 1 && args[1] == "1"); - this->sleep(_sleep_standby); - wait(0.1); - write(done); - } - } } else { bool found = false; bool query = false; @@ -573,59 +345,3 @@ void CommandTerminal::start() { } } - -std::string CommandTerminal::formatPacketData(const std::vector& data, const uint8_t& format) { - if (format == mDot::HEXADECIMAL) - return mts::Text::bin2hexString(data); - else - return std::string(data.begin(), data.end()); -} - -void CommandTerminal::sleep(bool standby) { - _serial_up = false; - _xbee_on_sleep = GPIO_PIN_RESET; - - _serial.rxClear(); - _serial.txClear(); - - _dot->sleep(_dot->getWakeInterval(), _dot->getWakeMode(), standby); -} - -bool CommandTerminal::waitForEscape(int timeout, mDot* dot, WaitType wait) { - Timer timer; - Timer escape_timer; - std::string escape_buffer; - int escape_timeout = 1000; - - timer.start(); - while (timer.read_ms() < timeout) { - - if (dot != NULL) { - if (wait == WAIT_SEND && (!dot->getIsTransmitting())) { - return false; - } - } - - if (_serialp != NULL && _serialp->readable()) { - if (escape_buffer == "") - escape_timer.start(); - char ch; - _serialp->read(&ch, 1); - escape_buffer += ch; - if (escape_buffer == CommandTerminal::escape_sequence) - return true; - } - if (escape_timer.read_ms() > escape_timeout) { - escape_buffer = ""; - escape_timer.stop(), escape_timer.reset(); - } - - osDelay(10); - } - - return false; -} - -void CommandTerminal::wakeup(bool standby) { - -} diff --git a/CommandTerminal/CommandTerminal.h b/CommandTerminal/CommandTerminal.h index e64ec41..0fcb9c4 100644 --- a/CommandTerminal/CommandTerminal.h +++ b/CommandTerminal/CommandTerminal.h @@ -73,9 +73,6 @@ public: // Escape sequence static const char escape_sequence[]; - static std::string formatPacketData(const std::vector& data, const uint8_t& format); - static bool waitForEscape(int timeout, mDot* dot=NULL, WaitType wait=WAIT_NA); - void start(); private: @@ -92,15 +89,10 @@ private: mDot::Mode _mode; std::vector _commands; Thread _idle_thread; - bool _sleep_standby; - DigitalOut _xbee_on_sleep; bool _serial_up; void addCommand(Command* cmd); - void serial_loop(); - bool autoJoinCheck(); - void printHelp(); bool readable(); @@ -108,9 +100,6 @@ private: char read(); void write(const char* message); void writef(const char* format, ... ); - - void sleep(bool standby); - void wakeup(bool standby); }; -- cgit v1.2.3 From f484beed77531d7ef2da65cf049fe9c4ac6b7d08 Mon Sep 17 00:00:00 2001 From: Leon Lindenfelser Date: Mon, 16 Nov 2015 16:18:09 -0600 Subject: Added all the new dotbox commands with some detail work still needed --- CommandTerminal/CmdData.cpp | 55 +++++++++++++++++++++++++ CommandTerminal/CmdData.h | 21 ++++++++++ CommandTerminal/CmdDeleteSurveyDataFile.cpp | 21 ++++++++++ CommandTerminal/CmdDeleteSurveyDataFile.h | 20 ++++++++++ CommandTerminal/CmdExit.cpp | 19 +++++++++ CommandTerminal/CmdExit.h | 20 ++++++++++ CommandTerminal/CmdGetSurveyDataFile.cpp | 19 +++++++++ CommandTerminal/CmdGetSurveyDataFile.h | 20 ++++++++++ CommandTerminal/CmdMaximumPower.cpp | 62 +++++++++++++++++++++++++++++ CommandTerminal/CmdMaximumPower.h | 21 ++++++++++ CommandTerminal/CmdMaximumSize.cpp | 62 +++++++++++++++++++++++++++++ CommandTerminal/CmdMaximumSize.h | 21 ++++++++++ CommandTerminal/CmdMinimumPower.cpp | 62 +++++++++++++++++++++++++++++ CommandTerminal/CmdMinimumPower.h | 21 ++++++++++ CommandTerminal/CmdMinimumSize.cpp | 62 +++++++++++++++++++++++++++++ CommandTerminal/CmdMinimumSize.h | 21 ++++++++++ CommandTerminal/CommandTerminal.cpp | 10 +++++ CommandTerminal/Commands.h | 9 +++++ 18 files changed, 546 insertions(+) create mode 100644 CommandTerminal/CmdData.cpp create mode 100644 CommandTerminal/CmdData.h create mode 100644 CommandTerminal/CmdDeleteSurveyDataFile.cpp create mode 100644 CommandTerminal/CmdDeleteSurveyDataFile.h create mode 100644 CommandTerminal/CmdExit.cpp create mode 100644 CommandTerminal/CmdExit.h create mode 100644 CommandTerminal/CmdGetSurveyDataFile.cpp create mode 100644 CommandTerminal/CmdGetSurveyDataFile.h create mode 100644 CommandTerminal/CmdMaximumPower.cpp create mode 100644 CommandTerminal/CmdMaximumPower.h create mode 100644 CommandTerminal/CmdMaximumSize.cpp create mode 100644 CommandTerminal/CmdMaximumSize.h create mode 100644 CommandTerminal/CmdMinimumPower.cpp create mode 100644 CommandTerminal/CmdMinimumPower.h create mode 100644 CommandTerminal/CmdMinimumSize.cpp create mode 100644 CommandTerminal/CmdMinimumSize.h diff --git a/CommandTerminal/CmdData.cpp b/CommandTerminal/CmdData.cpp new file mode 100644 index 0000000..339fc4b --- /dev/null +++ b/CommandTerminal/CmdData.cpp @@ -0,0 +1,55 @@ +#include "CmdData.h" + +CmdData::CmdData(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Data", "AT+DATA", "Enable/disable sending survey data results packet to the network server upon each successful survey. (0: off, 1: on)"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(0,1)"; + _queryable = true; +} + +uint32_t CmdData::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("%s: ", name()); +//ToDo: Change from _dot->getPublicNetwork() to the structure we will use for this. + _serial.writef("%d\r\n", _dot->getPublicNetwork()); + } + else if (args.size() == 2) + { + int32_t code; + bool enable = (args[1] == "1"); + + if ((code = _dot->setPublicNetwork(enable)) != mDot::MDOT_OK) { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; + +} + +bool CmdData::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + if (args[1] != "1" && args[1] != "0") { + setErrorMessage("Invalid parameter, expects (0: off, 1: on)"); + return false; + } + + return true; + } + + setErrorMessage("Invalid arguments"); + return false; + +} + diff --git a/CommandTerminal/CmdData.h b/CommandTerminal/CmdData.h new file mode 100644 index 0000000..ac2a874 --- /dev/null +++ b/CommandTerminal/CmdData.h @@ -0,0 +1,21 @@ +#ifndef __CMDDATA_H__ +#define __CMDDATA_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdData: public Command +{ + +public: + + CmdData(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDDATA_H__ diff --git a/CommandTerminal/CmdDeleteSurveyDataFile.cpp b/CommandTerminal/CmdDeleteSurveyDataFile.cpp new file mode 100644 index 0000000..d6eca22 --- /dev/null +++ b/CommandTerminal/CmdDeleteSurveyDataFile.cpp @@ -0,0 +1,21 @@ +#include "CmdDeleteSurveyDataFile.h" + +CmdDeleteSurveyDataFile::CmdDeleteSurveyDataFile(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Delete Survey Data File", "AT+DSDF", "Delete the survey data file"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); +} + +uint32_t CmdDeleteSurveyDataFile::action(std::vector args) +{ +//ToDo: Delete the file. + if (!_dot->saveConfig()) { + setErrorMessage("Failed to save to flash"); + return 1; + } + + return 0; + +} + + diff --git a/CommandTerminal/CmdDeleteSurveyDataFile.h b/CommandTerminal/CmdDeleteSurveyDataFile.h new file mode 100644 index 0000000..a0e1663 --- /dev/null +++ b/CommandTerminal/CmdDeleteSurveyDataFile.h @@ -0,0 +1,20 @@ +#ifndef __CMDDELETESURVEYDATAFILE_H__ +#define __CMDDELETESURVEYDATAFILE_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdDeleteSurveyDataFile: public Command +{ + +public: + + CmdDeleteSurveyDataFile(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDDELETESURVEYDATAFILE_H__ diff --git a/CommandTerminal/CmdExit.cpp b/CommandTerminal/CmdExit.cpp new file mode 100644 index 0000000..46923b3 --- /dev/null +++ b/CommandTerminal/CmdExit.cpp @@ -0,0 +1,19 @@ +#include "CmdExit.h" + +CmdExit::CmdExit(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Exit", "AT+EXIT", "Exit from command mode to main menu"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); +} + +uint32_t CmdExit::action(std::vector args) +{ +//ToDo: Probably setting or clearing a flag to indicate to some other task to shut down command mode and display the main menu. + if (!_dot->saveConfig()) { + setErrorMessage("Failed to save to flash"); + return 1; + } + + return 0; + +} diff --git a/CommandTerminal/CmdExit.h b/CommandTerminal/CmdExit.h new file mode 100644 index 0000000..20231db --- /dev/null +++ b/CommandTerminal/CmdExit.h @@ -0,0 +1,20 @@ +#ifndef __CMDEXIT_H__ +#define __CMDEXIT_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdExit: public Command +{ + +public: + + CmdExit(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDEXIT_H__ diff --git a/CommandTerminal/CmdGetSurveyDataFile.cpp b/CommandTerminal/CmdGetSurveyDataFile.cpp new file mode 100644 index 0000000..11d9ae3 --- /dev/null +++ b/CommandTerminal/CmdGetSurveyDataFile.cpp @@ -0,0 +1,19 @@ +#include "CmdGetSurveyDataFile.h" + +CmdGetSurveyDataFile::CmdGetSurveyDataFile(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Get Survey Data File", "AT+GSDF", "Outputs the survey data file to the command port"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); +} + +uint32_t CmdGetSurveyDataFile::action(std::vector args) +{ +//ToDo: Output the file contents line by line. + if (!_dot->saveConfig()) { + setErrorMessage("Failed to save to flash"); + return 1; + } + + return 0; + +} diff --git a/CommandTerminal/CmdGetSurveyDataFile.h b/CommandTerminal/CmdGetSurveyDataFile.h new file mode 100644 index 0000000..ff4cf57 --- /dev/null +++ b/CommandTerminal/CmdGetSurveyDataFile.h @@ -0,0 +1,20 @@ +#ifndef __CMDGETSURVEYDATAFILE_H__ +#define __CMDGETSURVEYDATAFILE_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdGetSurveyDataFile: public Command +{ + +public: + + CmdGetSurveyDataFile(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDGETSURVEYDATAFILE_H__ diff --git a/CommandTerminal/CmdMaximumPower.cpp b/CommandTerminal/CmdMaximumPower.cpp new file mode 100644 index 0000000..832fbfb --- /dev/null +++ b/CommandTerminal/CmdMaximumPower.cpp @@ -0,0 +1,62 @@ +#include "CmdMaximumPower.h" + +CmdMaximumPower::CmdMaximumPower(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Maximum Power", "AT+MAXPWR", "Set the maximum transmit power for sweep survey mode"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(2-20)"; + _queryable = true; +} + +uint32_t CmdMaximumPower::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Maximum Power: "); +//ToDo: Change from _dot->getTxPower() to the structure we will use for this. + _serial.writef("%lu\r\n", _dot->getTxPower()); + } + else if (args.size() == 2) + { + int32_t code; + uint32_t power = 0; + sscanf(args[1].c_str(), "%lu", &power); + + if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdMaximumPower::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + uint32_t power = 0; + if (sscanf(args[1].c_str(), "%lu", &power) != 1) { + setErrorMessage("Invalid argument"); + return false; + } + + if (power < 2 || power > 20) + { + setErrorMessage("Invalid maximum transmit power for sweep survey mode, expects (2-20)"); + return false; + } +//ToDo: Output warning if < minimum size. + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} + diff --git a/CommandTerminal/CmdMaximumPower.h b/CommandTerminal/CmdMaximumPower.h new file mode 100644 index 0000000..f5d3bca --- /dev/null +++ b/CommandTerminal/CmdMaximumPower.h @@ -0,0 +1,21 @@ +#ifndef __CMDMAXIMUMPOWER_H__ +#define __CMDMAXIMUMPOWER_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdMaximumPower: public Command +{ + +public: + + CmdMaximumPower(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDMAXIMUMPOWER_H__ diff --git a/CommandTerminal/CmdMaximumSize.cpp b/CommandTerminal/CmdMaximumSize.cpp new file mode 100644 index 0000000..b8be63b --- /dev/null +++ b/CommandTerminal/CmdMaximumSize.cpp @@ -0,0 +1,62 @@ +#include "CmdMaximumSize.h" + +CmdMaximumSize::CmdMaximumSize(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Maximum Size", "AT+MAXSIZE", "Set the maximum payload size for sweep survey mode"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(11-242)"; + _queryable = true; +} + +uint32_t CmdMaximumSize::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Maximum Size: "); +//ToDo: Change from _dot->getTxPower() to the structure we will use for this. + _serial.writef("%lu\r\n", _dot->getTxPower()); + } + else if (args.size() == 2) + { + int32_t code; + uint32_t power = 0; + sscanf(args[1].c_str(), "%lu", &power); + + if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdMaximumSize::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + uint32_t power = 0; + if (sscanf(args[1].c_str(), "%lu", &power) != 1) { + setErrorMessage("Invalid argument"); + return false; + } + + if (power < 11 || power > 242) + { + setErrorMessage("Invalid maximum payload size, expects (11-242)"); + return false; + } +//ToDo: Output warning if < minimum size. + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} + diff --git a/CommandTerminal/CmdMaximumSize.h b/CommandTerminal/CmdMaximumSize.h new file mode 100644 index 0000000..4a7e416 --- /dev/null +++ b/CommandTerminal/CmdMaximumSize.h @@ -0,0 +1,21 @@ +#ifndef __CMDMAXIMUMSIZE_H__ +#define __CMDMAXIMUMSIZE_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdMaximumSize: public Command +{ + +public: + + CmdMaximumSize(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDMAXIMUMSIZE_H__ diff --git a/CommandTerminal/CmdMinimumPower.cpp b/CommandTerminal/CmdMinimumPower.cpp new file mode 100644 index 0000000..96aa28e --- /dev/null +++ b/CommandTerminal/CmdMinimumPower.cpp @@ -0,0 +1,62 @@ +#include "CmdMinimumPower.h" + +CmdMinimumPower::CmdMinimumPower(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Minimum Power", "AT+MINPWR", "Set the minimum transmit power for sweep survey mode"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(2-20)"; + _queryable = true; +} + +uint32_t CmdMinimumPower::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Minimum Power: "); +//ToDo: Change from _dot->getTxPower() to the structure we will use for this. + _serial.writef("%lu\r\n", _dot->getTxPower()); + } + else if (args.size() == 2) + { + int32_t code; + uint32_t power = 0; + sscanf(args[1].c_str(), "%lu", &power); + + if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdMinimumPower::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + uint32_t power = 0; + if (sscanf(args[1].c_str(), "%lu", &power) != 1) { + setErrorMessage("Invalid argument"); + return false; + } + + if (power < 2 || power > 20) + { + setErrorMessage("Invalid minimum transmit power for sweep survey mode, expects (2-20)"); + return false; + } +//ToDo: Output warning if > maximum power. + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} + diff --git a/CommandTerminal/CmdMinimumPower.h b/CommandTerminal/CmdMinimumPower.h new file mode 100644 index 0000000..a8656ee --- /dev/null +++ b/CommandTerminal/CmdMinimumPower.h @@ -0,0 +1,21 @@ +#ifndef __CMDMINIMUMPOWER_H__ +#define __CMDMINIMUMPOWER_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdMinimumPower: public Command +{ + +public: + + CmdMinimumPower(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDMINIMUMPOWER_H__ diff --git a/CommandTerminal/CmdMinimumSize.cpp b/CommandTerminal/CmdMinimumSize.cpp new file mode 100644 index 0000000..7091bd8 --- /dev/null +++ b/CommandTerminal/CmdMinimumSize.cpp @@ -0,0 +1,62 @@ +#include "CmdMinimumSize.h" + +CmdMinimumSize::CmdMinimumSize(mDot* dot, mts::MTSSerial& serial) : + Command(dot, "Minimum Size", "AT+MINSIZE", "Set the minimum payload size for sweep survey mode"), _serial(serial) +{ + _help = std::string(text()) + ": " + std::string(desc()); + _usage = "(11-242)"; + _queryable = true; +} + +uint32_t CmdMinimumSize::action(std::vector args) +{ + if (args.size() == 1) + { + if (_dot->getVerbose()) + _serial.writef("Minimum Size: "); +//ToDo: Change from _dot->getTxPower() to the structure we will use for this. + _serial.writef("%lu\r\n", _dot->getTxPower()); + } + else if (args.size() == 2) + { + int32_t code; + uint32_t power = 0; + sscanf(args[1].c_str(), "%lu", &power); + + if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + { + std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); + setErrorMessage(error); + return 1; + } + } + + return 0; +} + +bool CmdMinimumSize::verify(std::vector args) +{ + if (args.size() == 1) + return true; + + if (args.size() == 2) + { + uint32_t power = 0; + if (sscanf(args[1].c_str(), "%lu", &power) != 1) { + setErrorMessage("Invalid argument"); + return false; + } + + if (power < 11 || power > 242) + { + setErrorMessage("Invalid minimum payload size, expects (11-242)"); + return false; + } +//ToDo: Output warning if > maximum size. + return true; + } + + setErrorMessage("Invalid arguments"); + return false; +} + diff --git a/CommandTerminal/CmdMinimumSize.h b/CommandTerminal/CmdMinimumSize.h new file mode 100644 index 0000000..ec5d3aa --- /dev/null +++ b/CommandTerminal/CmdMinimumSize.h @@ -0,0 +1,21 @@ +#ifndef __CMDMINIMUMSIZE_H__ +#define __CMDMINIMUMSIZE_H__ + +#include "Command.h" + +class CommandTerminal; + +class CmdMinimumSize: public Command +{ + +public: + + CmdMinimumSize(mDot* dot, mts::MTSSerial& serial); + virtual uint32_t action(std::vector args); + virtual bool verify(std::vector args); + +private: + mts::MTSSerial& _serial; +}; + +#endif // __CMDMINIMUMSIZE_H__ diff --git a/CommandTerminal/CommandTerminal.cpp b/CommandTerminal/CommandTerminal.cpp index 265009e..28c047f 100644 --- a/CommandTerminal/CommandTerminal.cpp +++ b/CommandTerminal/CommandTerminal.cpp @@ -57,6 +57,16 @@ CommandTerminal::CommandTerminal(mts::MTSSerial& serial, mDot* dot) addCommand(new CmdNetworkJoinMode(_dot, serial)); addCommand(new CmdTxDataRate(_dot, serial)); addCommand(new CmdTxPower(_dot, serial)); + + addCommand(new CmdMinimumSize(_dot, serial)); + addCommand(new CmdMaximumSize(_dot, serial)); + addCommand(new CmdMinimumPower(_dot, serial)); + addCommand(new CmdMaximumPower(_dot, serial)); + addCommand(new CmdData(_dot, serial)); + addCommand(new CmdGetSurveyDataFile(_dot, serial)); + addCommand(new CmdDeleteSurveyDataFile(_dot, serial)); + addCommand(new CmdExit(_dot, serial)); + } void CommandTerminal::printHelp() { diff --git a/CommandTerminal/Commands.h b/CommandTerminal/Commands.h index 5b699f4..3797036 100644 --- a/CommandTerminal/Commands.h +++ b/CommandTerminal/Commands.h @@ -17,3 +17,12 @@ #include "CmdTxDataRate.h" #include "CmdTxPower.h" #include "CmdFrequencySubBand.h" + +#include "CmdMinimumSize.h" +#include "CmdMaximumSize.h" +#include "CmdMinimumPower.h" +#include "CmdMaximumPower.h" +#include "CmdData.h" +#include "CmdGetSurveyDataFile.h" +#include "CmdDeleteSurveyDataFile.h" +#include "CmdExit.h" -- cgit v1.2.3 From ce5c78c53be8d66da4a2cccdf18b622c0b77e773 Mon Sep 17 00:00:00 2001 From: Leon Lindenfelser Date: Wed, 18 Nov 2015 11:16:11 -0600 Subject: Added functionality to get the guts of these commands working with storage mapped into unused mDot commands. Over write the mDot defaults in these storage locations with the appropriate defaults for these 5 commands. --- CommandTerminal/CmdData.cpp | 7 ++++--- CommandTerminal/CmdFactoryDefault.cpp | 8 ++++++++ CommandTerminal/CmdMaximumPower.cpp | 15 ++++++++++----- CommandTerminal/CmdMaximumSize.cpp | 24 +++++++++++++++--------- CommandTerminal/CmdMinimumPower.cpp | 14 ++++++++++---- CommandTerminal/CmdMinimumSize.cpp | 23 ++++++++++++++--------- 6 files changed, 61 insertions(+), 30 deletions(-) diff --git a/CommandTerminal/CmdData.cpp b/CommandTerminal/CmdData.cpp index 339fc4b..4b31de6 100644 --- a/CommandTerminal/CmdData.cpp +++ b/CommandTerminal/CmdData.cpp @@ -1,5 +1,7 @@ #include "CmdData.h" +//SPECIAL NOTE: +Data is stored in the LoraConfig StartUpMode field. We decided to use 5 LoRaConfig locations, +// that are not used for the DotBox, for the 5 DotBox settings... +minsize, +maxsize, +minpwr, +maxpwr and +data. CmdData::CmdData(mDot* dot, mts::MTSSerial& serial) : Command(dot, "Data", "AT+DATA", "Enable/disable sending survey data results packet to the network server upon each successful survey. (0: off, 1: on)"), _serial(serial) { @@ -14,15 +16,14 @@ uint32_t CmdData::action(std::vector args) { if (_dot->getVerbose()) _serial.writef("%s: ", name()); -//ToDo: Change from _dot->getPublicNetwork() to the structure we will use for this. - _serial.writef("%d\r\n", _dot->getPublicNetwork()); + _serial.writef("%d\r\n", _dot->getStartUpMode()); } else if (args.size() == 2) { int32_t code; bool enable = (args[1] == "1"); - if ((code = _dot->setPublicNetwork(enable)) != mDot::MDOT_OK) { + if ((code = _dot->setStartUpMode(enable)) != mDot::MDOT_OK) { std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); setErrorMessage(error); return 1; diff --git a/CommandTerminal/CmdFactoryDefault.cpp b/CommandTerminal/CmdFactoryDefault.cpp index 53b6ede..3e366e8 100644 --- a/CommandTerminal/CmdFactoryDefault.cpp +++ b/CommandTerminal/CmdFactoryDefault.cpp @@ -9,6 +9,14 @@ CmdFactoryDefault::CmdFactoryDefault(mDot* dot) : Command(dot, "Reset Factory De uint32_t CmdFactoryDefault::action(std::vector args) { _dot->resetConfig(); + +//Factory defaults for the DotBox. + _dot->setWakeDelay(242); //DotBox +MaxSize is stored here. Default is 242. + _dot->setWakeInterval(11); //DotBox +MinSize is stored here. Default is 11. + _dot->setWakeMode(20); //DotBox +MaxPwr is stored here. Default is 20. + _dot->setWakeTimeout(2); //DotBox +MinPwr is stored here. Default is 2. + _dot->setStartUpMode(0); //DotBox +Data is stored here. Default is 0. + _dot->resetNetworkSession(); return 0; } diff --git a/CommandTerminal/CmdMaximumPower.cpp b/CommandTerminal/CmdMaximumPower.cpp index 832fbfb..d12c11f 100644 --- a/CommandTerminal/CmdMaximumPower.cpp +++ b/CommandTerminal/CmdMaximumPower.cpp @@ -1,5 +1,7 @@ #include "CmdMaximumPower.h" +//SPECIAL NOTE: Maximum power is stored in the LoraConfig WakeMode field. We decided to use 5 LoRaConfig locations, +// that are not used for the DotBox, for the 5 DotBox settings... +minsize, +maxsize, +minpwr, +maxpwr and +data. CmdMaximumPower::CmdMaximumPower(mDot* dot, mts::MTSSerial& serial) : Command(dot, "Maximum Power", "AT+MAXPWR", "Set the maximum transmit power for sweep survey mode"), _serial(serial) { @@ -14,16 +16,14 @@ uint32_t CmdMaximumPower::action(std::vector args) { if (_dot->getVerbose()) _serial.writef("Maximum Power: "); -//ToDo: Change from _dot->getTxPower() to the structure we will use for this. - _serial.writef("%lu\r\n", _dot->getTxPower()); + _serial.writef("%lu\r\n", _dot->getWakeMode()); } else if (args.size() == 2) { int32_t code; uint32_t power = 0; sscanf(args[1].c_str(), "%lu", &power); - - if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + if ((code = _dot->setWakeMode(power)) != mDot::MDOT_OK) { std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); setErrorMessage(error); @@ -52,7 +52,12 @@ bool CmdMaximumPower::verify(std::vector args) setErrorMessage("Invalid maximum transmit power for sweep survey mode, expects (2-20)"); return false; } -//ToDo: Output warning if < minimum size. + if (power < _dot->getWakeTimeout()) //WakeTimeout holds the MinPower setting. + { + setErrorMessage("+MAXPWR cannot be less than +MINPWR. Please decrease +MINPWR first."); + return false; + } + return true; } diff --git a/CommandTerminal/CmdMaximumSize.cpp b/CommandTerminal/CmdMaximumSize.cpp index b8be63b..3679c72 100644 --- a/CommandTerminal/CmdMaximumSize.cpp +++ b/CommandTerminal/CmdMaximumSize.cpp @@ -1,5 +1,7 @@ #include "CmdMaximumSize.h" +//SPECIAL NOTE: Maximum size is stored in the LoraConfig WakeDelay field. We decided to use 5 LoRaConfig locations, +// that are not used for the DotBox, for the 5 DotBox settings... +minsize, +maxsize, +minpwr, +maxpwr and +data. CmdMaximumSize::CmdMaximumSize(mDot* dot, mts::MTSSerial& serial) : Command(dot, "Maximum Size", "AT+MAXSIZE", "Set the maximum payload size for sweep survey mode"), _serial(serial) { @@ -14,16 +16,15 @@ uint32_t CmdMaximumSize::action(std::vector args) { if (_dot->getVerbose()) _serial.writef("Maximum Size: "); -//ToDo: Change from _dot->getTxPower() to the structure we will use for this. - _serial.writef("%lu\r\n", _dot->getTxPower()); + _serial.writef("%lu\r\n", _dot->getWakeDelay()); } else if (args.size() == 2) { int32_t code; - uint32_t power = 0; - sscanf(args[1].c_str(), "%lu", &power); + uint32_t size = 0; + sscanf(args[1].c_str(), "%lu", &size); - if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + if ((code = _dot->setWakeDelay(size)) != mDot::MDOT_OK) { std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); setErrorMessage(error); @@ -41,18 +42,23 @@ bool CmdMaximumSize::verify(std::vector args) if (args.size() == 2) { - uint32_t power = 0; - if (sscanf(args[1].c_str(), "%lu", &power) != 1) { + uint32_t size = 0; + if (sscanf(args[1].c_str(), "%lu", &size) != 1) { setErrorMessage("Invalid argument"); return false; } - if (power < 11 || power > 242) + if (size < 11 || size > 242) { setErrorMessage("Invalid maximum payload size, expects (11-242)"); return false; } -//ToDo: Output warning if < minimum size. + if (size < _dot->getWakeInterval()) //WakeInterval holds the MinSize setting. + { + setErrorMessage("+MAXSIZE cannot be less than +MINSIZE. Please decrease +MINSIZE first."); + return false; + } + return true; } diff --git a/CommandTerminal/CmdMinimumPower.cpp b/CommandTerminal/CmdMinimumPower.cpp index 96aa28e..f3c997e 100644 --- a/CommandTerminal/CmdMinimumPower.cpp +++ b/CommandTerminal/CmdMinimumPower.cpp @@ -1,5 +1,7 @@ #include "CmdMinimumPower.h" +//SPECIAL NOTE: Minimum power is stored in the LoraConfig WakeTimeout field. We decided to use 5 LoRaConfig locations, +// that are not used for the DotBox, for the 5 DotBox settings... +minsize, +maxsize, +minpwr, +maxpwr and +data. CmdMinimumPower::CmdMinimumPower(mDot* dot, mts::MTSSerial& serial) : Command(dot, "Minimum Power", "AT+MINPWR", "Set the minimum transmit power for sweep survey mode"), _serial(serial) { @@ -14,8 +16,7 @@ uint32_t CmdMinimumPower::action(std::vector args) { if (_dot->getVerbose()) _serial.writef("Minimum Power: "); -//ToDo: Change from _dot->getTxPower() to the structure we will use for this. - _serial.writef("%lu\r\n", _dot->getTxPower()); + _serial.writef("%lu\r\n", _dot->getWakeTimeout()); } else if (args.size() == 2) { @@ -23,7 +24,7 @@ uint32_t CmdMinimumPower::action(std::vector args) uint32_t power = 0; sscanf(args[1].c_str(), "%lu", &power); - if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + if ((code = _dot->setWakeTimeout(power)) != mDot::MDOT_OK) { std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); setErrorMessage(error); @@ -52,7 +53,12 @@ bool CmdMinimumPower::verify(std::vector args) setErrorMessage("Invalid minimum transmit power for sweep survey mode, expects (2-20)"); return false; } -//ToDo: Output warning if > maximum power. + if (power > _dot->getWakeMode()) //WakeMode holds the MaxPower setting. + { + setErrorMessage("+MINPWR cannot be greater than +MAXPWR. Please increase +MAXPWR first."); + return false; + } + return true; } diff --git a/CommandTerminal/CmdMinimumSize.cpp b/CommandTerminal/CmdMinimumSize.cpp index 7091bd8..5315af7 100644 --- a/CommandTerminal/CmdMinimumSize.cpp +++ b/CommandTerminal/CmdMinimumSize.cpp @@ -1,5 +1,7 @@ #include "CmdMinimumSize.h" +//SPECIAL NOTE: Minimum size is stored in the LoraConfig WakeInterval field. We decided to use 5 LoRaConfig locations, +// that are not used for the DotBox, for the 5 DotBox settings... +minsize, +maxsize, +minpwr, +maxpwr and +data. CmdMinimumSize::CmdMinimumSize(mDot* dot, mts::MTSSerial& serial) : Command(dot, "Minimum Size", "AT+MINSIZE", "Set the minimum payload size for sweep survey mode"), _serial(serial) { @@ -14,16 +16,15 @@ uint32_t CmdMinimumSize::action(std::vector args) { if (_dot->getVerbose()) _serial.writef("Minimum Size: "); -//ToDo: Change from _dot->getTxPower() to the structure we will use for this. - _serial.writef("%lu\r\n", _dot->getTxPower()); + _serial.writef("%lu\r\n", _dot->getWakeInterval()); } else if (args.size() == 2) { int32_t code; - uint32_t power = 0; - sscanf(args[1].c_str(), "%lu", &power); + uint32_t size = 0; + sscanf(args[1].c_str(), "%lu", &size); - if ((code = _dot->setTxPower(power)) != mDot::MDOT_OK) + if ((code = _dot->setWakeInterval(size)) != mDot::MDOT_OK) { std::string error = mDot::getReturnCodeString(code) + " - " + _dot->getLastError(); setErrorMessage(error); @@ -41,18 +42,22 @@ bool CmdMinimumSize::verify(std::vector args) if (args.size() == 2) { - uint32_t power = 0; - if (sscanf(args[1].c_str(), "%lu", &power) != 1) { + uint32_t size = 0; + if (sscanf(args[1].c_str(), "%lu", &size) != 1) { setErrorMessage("Invalid argument"); return false; } - if (power < 11 || power > 242) + if (size < 11 || size > 242) { setErrorMessage("Invalid minimum payload size, expects (11-242)"); return false; } -//ToDo: Output warning if > maximum size. + if (size > _dot->getWakeDelay()) //WakeDelay holds the MaxSize setting. + { + setErrorMessage("+MINSIZE cannot be greater than +MAXSIZE. Please increase +MAXSIZE first."); + return false; + } return true; } -- cgit v1.2.3