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 (limited to 'CommandTerminal') 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