From 022568f5928c27fe982818cadc47fbc31a89bc35 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Mon, 27 Nov 2023 14:07:47 +0100 Subject: [PATCH 01/17] Unfinished modifications. --- .../Network/src/Network/FtpServer.h | 2 +- .../Network/src/Network/TcpClient.h | 1 - .../Network/src/Network/TelnetServer.cpp | 53 ++-- .../Network/src/Network/TelnetServer.h | 12 +- Sming/Core/Debug.cpp | 109 --------- Sming/Core/Debug.h | 112 --------- Sming/Core/HardwareSerial.cpp | 54 ++-- Sming/Core/HardwareSerial.h | 6 +- Sming/Services/CommandProcessing/Command.h | 55 +++++ .../CommandProcessing/CommandDelegate.h | 50 ---- .../CommandProcessing/CommandExecutor.cpp | 122 --------- .../CommandProcessing/CommandExecutor.h | 43 ---- .../CommandProcessing/CommandHandler.cpp | 182 -------------- .../CommandProcessing/CommandOutput.cpp | 44 ---- .../CommandProcessing/CommandOutput.h | 43 ---- .../CommandProcessingDependencies.h | 8 - .../CommandProcessingIncludes.h | 14 -- Sming/Services/CommandProcessing/Handler.cpp | 231 ++++++++++++++++++ .../{CommandHandler.h => Handler.h} | 145 ++++++++--- .../app/ExampleCommand.cpp | 46 ---- .../app/application.cpp | 148 ++++------- .../include/ExampleCommand.h | 21 -- 22 files changed, 488 insertions(+), 1013 deletions(-) delete mode 100644 Sming/Core/Debug.cpp delete mode 100644 Sming/Core/Debug.h create mode 100644 Sming/Services/CommandProcessing/Command.h delete mode 100644 Sming/Services/CommandProcessing/CommandDelegate.h delete mode 100644 Sming/Services/CommandProcessing/CommandExecutor.cpp delete mode 100644 Sming/Services/CommandProcessing/CommandExecutor.h delete mode 100644 Sming/Services/CommandProcessing/CommandHandler.cpp delete mode 100644 Sming/Services/CommandProcessing/CommandOutput.cpp delete mode 100644 Sming/Services/CommandProcessing/CommandOutput.h delete mode 100644 Sming/Services/CommandProcessing/CommandProcessingDependencies.h delete mode 100644 Sming/Services/CommandProcessing/CommandProcessingIncludes.h create mode 100644 Sming/Services/CommandProcessing/Handler.cpp rename Sming/Services/CommandProcessing/{CommandHandler.h => Handler.h} (55%) delete mode 100644 samples/CommandProcessing_Debug/app/ExampleCommand.cpp delete mode 100644 samples/CommandProcessing_Debug/include/ExampleCommand.h diff --git a/Sming/Components/Network/src/Network/FtpServer.h b/Sming/Components/Network/src/Network/FtpServer.h index e096311f2c..7d0e9492a0 100644 --- a/Sming/Components/Network/src/Network/FtpServer.h +++ b/Sming/Components/Network/src/Network/FtpServer.h @@ -42,7 +42,7 @@ class CustomFtpServer : public TcpServer TcpConnection* createClient(tcp_pcb* clientTcp) override; /** - * @brief Handle an incomding command + * @brief Handle an incoming command * @param cmd The command identifier, e.g. LIST * @param data Any command arguments * @param connection The associated TCP connection to receive any response diff --git a/Sming/Components/Network/src/Network/TcpClient.h b/Sming/Components/Network/src/Network/TcpClient.h index 74b93fa14c..4d1d3becf9 100644 --- a/Sming/Components/Network/src/Network/TcpClient.h +++ b/Sming/Components/Network/src/Network/TcpClient.h @@ -19,7 +19,6 @@ #include "TcpConnection.h" class TcpClient; -class ReadWriteStream; class IpAddress; using TcpClientEventDelegate = Delegate; diff --git a/Sming/Components/Network/src/Network/TelnetServer.cpp b/Sming/Components/Network/src/Network/TelnetServer.cpp index 345a50ed41..0edb1d7186 100644 --- a/Sming/Components/Network/src/Network/TelnetServer.cpp +++ b/Sming/Components/Network/src/Network/TelnetServer.cpp @@ -12,30 +12,21 @@ ****/ #include "TelnetServer.h" -#include "Debug.h" - -void TelnetServer::enableDebug(bool reqStatus) -{ - telnetDebug = reqStatus; - if(telnetDebug && curClient != nullptr) /* only setSetDebug when already connected */ - { - Debug.setDebug(DebugPrintCharDelegate(&TelnetServer::wrchar, this)); - } else { - Debug.setDebug(Serial); - } -} +#include "TcpClientStream.h" void TelnetServer::enableCommand(bool reqStatus) { -#if ENABLE_CMD_EXECUTOR - if(reqStatus && curClient != nullptr && commandExecutor == nullptr) { - commandExecutor = new CommandExecutor(curClient); + if(!reqStatus && commandHandler != nullptr) { + delete commandHandler; + commandHandler = nullptr; + return; } - if(!reqStatus && commandExecutor != nullptr) { - delete commandExecutor; - commandExecutor = nullptr; + + if(reqStatus && curClient != nullptr && commandHandler == nullptr) { + commandHandler = new CommandProcessing::Handler(); + commandHandler->setOutputStream(new TcpClientStream(*curClient)); } -#endif + telnetCommand = reqStatus; } @@ -52,26 +43,19 @@ void TelnetServer::onClient(TcpClient* client) } else { curClient = client; curClient->setTimeOut(USHRT_MAX); - curClient->sendString("Welcome to Sming / ESP6266 Telnet\r\n"); + curClient->sendString("Welcome to Sming Telnet\r\n"); if(telnetCommand) { -#if ENABLE_CMD_EXECUTOR - commandExecutor = new CommandExecutor(client); -#endif - } - if(telnetDebug) { - Debug.setDebug(DebugPrintCharDelegate(&TelnetServer::wrchar, this)); + commandHandler = new CommandProcessing::Handler(); + commandHandler->setOutputStream(new TcpClientStream(*client)); } - Debug.printf("This is debug after telnet start\r\n"); } } void TelnetServer::onClientComplete(TcpClient& client, bool successful) { if(&client == curClient) { -#if ENABLE_CMD_EXECUTOR - delete commandExecutor; - commandExecutor = nullptr; -#endif + delete commandHandler; + commandHandler = nullptr; curClient = nullptr; debug_d("TelnetServer onClientComplete %s", client.getRemoteIp().toString().c_str()); } else { @@ -80,7 +64,6 @@ void TelnetServer::onClientComplete(TcpClient& client, bool successful) debug_d("TelnetServer onClientComplete %s", client.getRemoteIp().toString().c_str()); TcpServer::onClientComplete(client, successful); - Debug.setDebug(Serial); } void TelnetServer::wrchar(char c) @@ -94,10 +77,8 @@ bool TelnetServer::onClientReceive(TcpClient& client, char* data, int size) { debug_d("TelnetServer onClientReceive : %s, %d bytes \r\n", client.getRemoteIp().toString().c_str(), size); debug_d("Data : %s", data); -#if ENABLE_CMD_EXECUTOR - if(commandExecutor != nullptr) { - commandExecutor->executorReceive(data, size); + if(commandHandler != nullptr) { + commandHandler->process(data, size); } -#endif return true; } diff --git a/Sming/Components/Network/src/Network/TelnetServer.h b/Sming/Components/Network/src/Network/TelnetServer.h index 04942e3bac..beafe8a03a 100644 --- a/Sming/Components/Network/src/Network/TelnetServer.h +++ b/Sming/Components/Network/src/Network/TelnetServer.h @@ -21,8 +21,8 @@ #include "TcpClient.h" #include "TcpServer.h" -#include "SystemClock.h" -#include "Services/CommandProcessing/CommandExecutor.h" +#include +#include #ifndef TELNETSERVER_MAX_COMMANDSIZE #define TELNETSERVER_MAX_COMMANDSIZE 64 @@ -33,7 +33,10 @@ using TelnetServerCommandDelegate = Delegate - -DebugClass::DebugClass() -{ - debugf("DebugClass Instantiating"); - setDebug(Serial); -} - -void DebugClass::initCommand() -{ -#if ENABLE_CMD_EXECUTOR - commandHandler.registerCommand(CommandDelegate(F("debug"), F("New debug in development"), F("Debug"), - CommandFunctionDelegate(&DebugClass::processDebugCommands, this))); -#endif -} - -void DebugClass::start() -{ - started = true; - println(_F("Debug started")); -} - -void DebugClass::stop() -{ - println(_F("Debug stopped")); - started = false; -} - -void DebugClass::setDebug(DebugPrintCharDelegate reqDelegate) -{ - debugOut.debugStream = nullptr; - debugOut.debugDelegate = reqDelegate; - print(_F("Welcome to DebugDelegate\r\n")); -} - -void DebugClass::setDebug(Stream& reqStream) -{ - debugOut.debugDelegate = nullptr; - debugOut.debugStream = &reqStream; - print(_F("Welcome to DebugStream")); -} - -void DebugClass::printPrefix() -{ - if(useDebugPrefix) { - uint32_t curMillis = millis(); - printf(_F("Dbg %4u.%03u : "), curMillis / 1000, curMillis % 1000); - } -} - -size_t DebugClass::write(uint8_t c) -{ - if(started) { - if(newDebugLine) { - newDebugLine = false; - printPrefix(); - } - if(c == '\n') { - newDebugLine = true; - } - if(debugOut.debugDelegate) { - debugOut.debugDelegate(c); - return 1; - } - if(debugOut.debugStream) { - debugOut.debugStream->write(c); - return 1; - } - } - - return 0; -} - -void DebugClass::processDebugCommands(String commandLine, CommandOutput* commandOutput) -{ - Vector commandToken; - int numToken = splitString(commandLine, ' ', commandToken); - - if(numToken == 1) { - commandOutput->print(_F("Debug Commands available : \r\n")); - commandOutput->print(_F("on : Start Debug output\r\n")); - commandOutput->print(_F("off : Stop Debug output\r\n")); - commandOutput->print(_F("serial : Send Debug output to Serial\r\n")); - } else { - if(commandToken[1] == "on") { - start(); - commandOutput->print(_F("Debug started\r\n")); - } else if(commandToken[1] == _F("off")) { - commandOutput->print(_F("Debug stopped\r\n")); - stop(); - } else if(commandToken[1] == _F("serial")) { - setDebug(Serial); - commandOutput->print(_F("Debug set to Serial")); - }; - } -} - -DebugClass Debug; diff --git a/Sming/Core/Debug.h b/Sming/Core/Debug.h deleted file mode 100644 index 831056e3e6..0000000000 --- a/Sming/Core/Debug.h +++ /dev/null @@ -1,112 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * Debug.h - * - ****/ - -#pragma once - -#include "HardwareSerial.h" -#include "Clock.h" -#include "WString.h" -#include "Services/CommandProcessing/CommandProcessingIncludes.h" - -/** @brief Delegate constructor usage: (&YourClass::method, this) - * Handler function for debug print - * @ingroup event_handlers - */ -using DebugPrintCharDelegate = Delegate; - -/** @brief Structure for debug options - * @ingroup structures - */ -struct DebugOuputOptions { - DebugPrintCharDelegate debugDelegate; ///< Function to handle debug output - Stream* debugStream{nullptr}; ///< Debug output stream -}; - -/** @brief Debug prefix state - * @ingroup constants - */ -enum eDBGPrefix { - eDBGnoPrefix = 0, ///< Do not use debug prefix - eDBGusePrefix = 1 ///< Use debug prefix -}; - -/** @defgroup debug Debug functions - * @brief Provides debug functions - * @{ -*/ - -/** @brief Provides debug output to stream (e.g. Serial) or delegate function handler. - * - * Debug output may be prefixed with an elapsed timestamp. Use standard print methods to produce debug output. - * Sming CLI (command handler) may be enabled to provide control of debug output to end user. - */ -class DebugClass : public Print -{ -public: - /** @brief Instantiate a debug object - * @note Default output is Serial stream - */ - DebugClass(); - - /** @brief Enable control of debug output from CLI command handler output - */ - void initCommand(); - - /** @brief Start debug output - */ - void start(); - - /** @brief Stop debug output - */ - void stop(); - - /** @brief Get debug status - * @retval bool True if debug enabled - */ - bool status() - { - return started; - } - - /** @brief Configure debug to use delegate handler for its output - * @param reqDelegate Function to handle debug output - * @note Disables stream output - */ - void setDebug(DebugPrintCharDelegate reqDelegate); - - /** @brief Configures debug to use stream for its output - * @param reqStream Stream for debug output - * @note Disables delegate handler - */ - void setDebug(Stream& reqStream); - - /* implementation of write for Print Class */ - size_t write(uint8_t) override; - -private: - bool started = false; - bool useDebugPrefix = true; - bool newDebugLine = true; - DebugOuputOptions debugOut; - void printPrefix(); - void processDebugCommands(String commandLine, CommandOutput* commandOutput); -}; - -/** @brief Global instance of Debug object - * @note Use Debug.function to access Debug functions - * @note Example: - * @code - * Debug.start(); - * Debug.printf("My value is %d", myVal); - @endcode -*/ -extern DebugClass Debug; - -/** @} */ diff --git a/Sming/Core/HardwareSerial.cpp b/Sming/Core/HardwareSerial.cpp index b305cfbe0c..ef2fde8998 100644 --- a/Sming/Core/HardwareSerial.cpp +++ b/Sming/Core/HardwareSerial.cpp @@ -16,16 +16,16 @@ #include "m_printf.h" #if ENABLE_CMD_EXECUTOR -#include +#include #endif HardwareSerial Serial(UART_ID_0); HardwareSerial::~HardwareSerial() { -#if ENABLE_CMD_EXECUTOR - delete commandExecutor; -#endif +//#if ENABLE_CMD_EXECUTOR +// delete commandExecutor; +//#endif } bool HardwareSerial::begin(uint32_t baud, SerialFormat format, SerialMode mode, uint8_t txPin, uint8_t rxPin) @@ -123,14 +123,14 @@ void HardwareSerial::invokeCallbacks() if(HWSDelegate) { HWSDelegate(*this, receivedChar, smg_uart_rx_available(uart)); } -#if ENABLE_CMD_EXECUTOR - if(commandExecutor) { - int c; - while((c = smg_uart_read_char(uart)) >= 0) { - commandExecutor->executorReceive(c); - } - } -#endif +//#if ENABLE_CMD_EXECUTOR +// if(commandExecutor) { +// int c; +// while((c = smg_uart_read_char(uart)) >= 0) { +// commandExecutor->executorReceive(c); +// } +// } +//#endif } } @@ -190,11 +190,11 @@ void HardwareSerial::staticCallbackHandler(smg_uart_t* uart, uint32_t status) bool HardwareSerial::updateUartCallback() { uint16_t mask = 0; -#if ENABLE_CMD_EXECUTOR - if(HWSDelegate || commandExecutor) { -#else +//#if ENABLE_CMD_EXECUTOR +// if(HWSDelegate || commandExecutor) { +//#else if(HWSDelegate) { -#endif +//#endif mask |= UART_STATUS_RXFIFO_FULL | UART_STATUS_RXFIFO_TOUT | UART_STATUS_RXFIFO_OVF; } @@ -211,15 +211,15 @@ bool HardwareSerial::updateUartCallback() void HardwareSerial::commandProcessing(bool reqEnable) { -#if ENABLE_CMD_EXECUTOR - if(reqEnable) { - if(!commandExecutor) { - commandExecutor = new CommandExecutor(this); - } - } else { - delete commandExecutor; - commandExecutor = nullptr; - } - updateUartCallback(); -#endif +//#if ENABLE_CMD_EXECUTOR +// if(reqEnable) { +// if(!commandExecutor) { +// commandExecutor = new CommandExecutor(this); +// } +// } else { +// delete commandExecutor; +// commandExecutor = nullptr; +// } +// updateUartCallback(); +//#endif } diff --git a/Sming/Core/HardwareSerial.h b/Sming/Core/HardwareSerial.h index 055e9e6708..a3b623684a 100644 --- a/Sming/Core/HardwareSerial.h +++ b/Sming/Core/HardwareSerial.h @@ -50,7 +50,7 @@ using StreamDataReceivedDelegate = Delegate; -class CommandExecutor; +//class CommandExecutor; // clang-format off #define SERIAL_CONFIG_MAP(XX) \ @@ -341,7 +341,7 @@ class HardwareSerial : public ReadWriteStream * @note Command processing provides a CLI to the system * @see commandHandler */ - void commandProcessing(bool reqEnable); + void commandProcessing(bool reqEnable) SMING_DEPRECATED; /** @brief Set handler for received data * @param dataReceivedDelegate Function to handle received data @@ -449,7 +449,7 @@ class HardwareSerial : public ReadWriteStream int uartNr = UART_NO; TransmitCompleteDelegate transmitComplete = nullptr; ///< Callback for transmit completion StreamDataReceivedDelegate HWSDelegate = nullptr; ///< Callback for received data - CommandExecutor* commandExecutor = nullptr; ///< Callback for command execution (received data) +// CommandExecutor* commandExecutor = nullptr; ///< Callback for command execution (received data) smg_uart_t* uart = nullptr; uart_options_t options = _BV(UART_OPT_TXWAIT); size_t txSize = DEFAULT_TX_BUFFER_SIZE; diff --git a/Sming/Services/CommandProcessing/Command.h b/Sming/Services/CommandProcessing/Command.h new file mode 100644 index 0000000000..b5fefd289a --- /dev/null +++ b/Sming/Services/CommandProcessing/Command.h @@ -0,0 +1,55 @@ +/* + * CommandDelegate.h + * + * Created on: 2 jul. 2015 + * Author: Herman + */ +/** @addtogroup commandhandler + * @{ + */ + +#pragma once + +#include +#include + +namespace CommandProcessing +{ + +/** @brief Command delegate class */ +class Command +{ +public: + /** @brief Command delegate function + * @param commandLine Command line entered by user at CLI, including command and parameters + * @param commandOutput Pointer to the CLI print stream + * @note CommandFunctionDelegate defines the structure of a function that handles individual commands + * @note Can use standard print functions on commandOutput + */ + using Callback = Delegate; + + + /** Instantiate a command delegate + * @param reqName Command name - the text a user types to invoke the command + * @param reqHelp Help message shown by CLI "help" command + * @param reqGroup The command group to which this command belongs + * @param reqFunction Delegate that should be invoked (triggered) when the command is entered by a user + */ + Command(String reqName, String reqHelp, String reqGroup, Callback reqFunction) + : name(reqName), description(reqHelp), group(reqGroup), callback(reqFunction) + { + } + + Command() + { + } + + String name; ///< Command name + String description; ///< Command help + String group; ///< Command group + Callback callback; ///< Command Delegate (function that is called when command is invoked) +}; + +} // namespace CommandProcessing + +/** @} */ diff --git a/Sming/Services/CommandProcessing/CommandDelegate.h b/Sming/Services/CommandProcessing/CommandDelegate.h deleted file mode 100644 index c43e2d0751..0000000000 --- a/Sming/Services/CommandProcessing/CommandDelegate.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * CommandDelegate.h - * - * Created on: 2 jul. 2015 - * Author: Herman - */ -/** @addtogroup commandhandler - * @{ - */ - -#pragma once - -#include -#include -#include "CommandOutput.h" - -/** @brief Command delegate function - * @param commandLine Command line entered by user at CLI, including command and parameters - * @param commandOutput Pointer to the CLI print stream - * @note CommandFunctionDelegate defines the structure of a function that handles individual commands - * @note Can use standard print functions on commandOutput - */ -using CommandFunctionDelegate = Delegate; - -/** @brief Command delegate class */ -class CommandDelegate -{ -public: - /** Instantiate a command delegate - * @param reqName Command name - the text a user types to invoke the command - * @param reqHelp Help message shown by CLI "help" command - * @param reqGroup The command group to which this command belongs - * @param reqFunction Delegate that should be invoked (triggered) when the command is entered by a user - */ - CommandDelegate(String reqName, String reqHelp, String reqGroup, CommandFunctionDelegate reqFunction) - : commandName(reqName), commandHelp(reqHelp), commandGroup(reqGroup), commandFunction(reqFunction) - { - } - - CommandDelegate() - { - } - - String commandName; ///< Command name - String commandHelp; ///< Command help - String commandGroup; ///< Command group - CommandFunctionDelegate commandFunction; ///< Command Delegate (function that is called when command is invoked) -}; - -/** @} */ diff --git a/Sming/Services/CommandProcessing/CommandExecutor.cpp b/Sming/Services/CommandProcessing/CommandExecutor.cpp deleted file mode 100644 index 4cb49e78ce..0000000000 --- a/Sming/Services/CommandProcessing/CommandExecutor.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * CommandExecutor.cpp - * - * Created on: 2 jul. 2015 - * Author: Herman - */ - -#include "CommandExecutor.h" -#include "HardwareSerial.h" -#include - -CommandExecutor::CommandExecutor() -{ - commandHandler.registerSystemCommands(); -} - -CommandExecutor::CommandExecutor(Stream* reqStream) : CommandExecutor() -{ - commandOutput.reset(new CommandOutput(reqStream)); - if(commandHandler.getVerboseMode() != SILENT) { - commandOutput->println(_F("Welcome to the Stream Command executor")); - } -} - -#ifndef DISABLE_NETWORK -CommandExecutor::CommandExecutor(TcpClient* cmdClient) : CommandExecutor() -{ - commandOutput.reset(new CommandOutput(cmdClient)); - if(commandHandler.getVerboseMode() != SILENT) { - commandOutput->println(_F("Welcome to the Tcp Command executor")); - } -} - -CommandExecutor::CommandExecutor(WebsocketConnection* reqSocket) -{ - commandOutput.reset(new CommandOutput(reqSocket)); - if(commandHandler.getVerboseMode() != SILENT) { - reqSocket->sendString(_F("Welcome to the Websocket Command Executor")); - } -} -#endif - -int CommandExecutor::executorReceive(char* recvData, int recvSize) -{ - int receiveReturn = 0; - for(int recvIdx = 0; recvIdx < recvSize; recvIdx++) { - receiveReturn = executorReceive(recvData[recvIdx]); - if(receiveReturn != 0) { - break; - } - } - return receiveReturn; -} - -int CommandExecutor::executorReceive(const String& recvString) -{ - int receiveReturn = 0; - for(unsigned recvIdx = 0; recvIdx < recvString.length(); recvIdx++) { - receiveReturn = executorReceive(recvString[recvIdx]); - if(receiveReturn != 0) { - break; - } - } - return receiveReturn; -} - -int CommandExecutor::executorReceive(char recvChar) -{ - if(recvChar == 27) // ESC -> delete current commandLine - { - commandBuf.clear(); - if(commandHandler.getVerboseMode() == VERBOSE) { - commandOutput->println(); - commandOutput->print(commandHandler.getCommandPrompt()); - } - } else if(recvChar == commandHandler.getCommandEOL()) { - String command(commandBuf.getBuffer(), commandBuf.getLength()); - commandBuf.clear(); - processCommandLine(command); - } else if(recvChar == '\b' || recvChar == 0x7f) { - if(commandBuf.backspace()) { - commandOutput->print(_F("\b \b")); - } - } else { - if(commandBuf.addChar(recvChar)) { - commandOutput->print(recvChar); - } - } - return 0; -} - -void CommandExecutor::processCommandLine(const String& cmdString) -{ - if(cmdString.length() == 0) { - commandOutput->println(); - } else { - debugf("Received full Command line, size = %u,cmd = %s", cmdString.length(), cmdString.c_str()); - String cmdCommand; - int cmdLen = cmdString.indexOf(' '); - if(cmdLen < 0) { - cmdCommand = cmdString; - } else { - cmdCommand = cmdString.substring(0, cmdLen); - } - - debugf("CommandExecutor : executing command %s", cmdCommand.c_str()); - - CommandDelegate cmdDelegate = commandHandler.getCommandDelegate(cmdCommand); - - if(!cmdDelegate.commandFunction) { - commandOutput->print(_F("Command not found, cmd = '")); - commandOutput->print(cmdCommand); - commandOutput->println('\''); - } else { - cmdDelegate.commandFunction(cmdString, commandOutput.get()); - } - } - - if(commandHandler.getVerboseMode() == VERBOSE) { - commandOutput->print(commandHandler.getCommandPrompt()); - } -} diff --git a/Sming/Services/CommandProcessing/CommandExecutor.h b/Sming/Services/CommandProcessing/CommandExecutor.h deleted file mode 100644 index a04ac0e6c4..0000000000 --- a/Sming/Services/CommandProcessing/CommandExecutor.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * CommandExecutor.h - * - * Created on: 2 jul. 2015 - * Author: Herman - */ - -#pragma once - -#include "CommandHandler.h" -#include "CommandOutput.h" -#include -#include - -#ifndef DISABLE_NETWORK -#include -#endif - -#define MAX_COMMANDSIZE 64 - -class CommandExecutor -{ -public: - CommandExecutor(const CommandExecutor&) = delete; - CommandExecutor& operator=(const CommandExecutor&) = delete; - -#ifndef DISABLE_NETWORK - CommandExecutor(TcpClient* cmdClient); - CommandExecutor(WebsocketConnection* reqSocket); -#endif - CommandExecutor(Stream* reqStream); - - int executorReceive(char* recvData, int recvSize); - int executorReceive(char recvChar); - int executorReceive(const String& recvString); - void setCommandEOL(char reqEOL); - -private: - CommandExecutor(); - void processCommandLine(const String& cmdString); - LineBuffer commandBuf; - std::unique_ptr commandOutput; -}; diff --git a/Sming/Services/CommandProcessing/CommandHandler.cpp b/Sming/Services/CommandProcessing/CommandHandler.cpp deleted file mode 100644 index c1ba3406ea..0000000000 --- a/Sming/Services/CommandProcessing/CommandHandler.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * CommandHandler.cpp - * - * Created on: 2 jul. 2015 - * Author: Herman - */ - -#include "CommandHandler.h" -#include "CommandDelegate.h" -#include -#include -#include - -#ifndef DISABLE_NETWORK -#include -#endif - -#ifndef LWIP_HASH_STR -#define LWIP_HASH_STR "" -#endif - -CommandHandler::CommandHandler() - : currentPrompt(F("Sming>")), currentWelcomeMessage(F("Welcome to the Sming CommandProcessing\r\n")) -{ -} - -void CommandHandler::registerSystemCommands() -{ - String system = F("system"); - registerCommand(CommandDelegate(F("status"), F("Displays System Information"), system, - CommandFunctionDelegate(&CommandHandler::procesStatusCommand, this))); - registerCommand(CommandDelegate(F("echo"), F("Displays command entered"), system, - CommandFunctionDelegate(&CommandHandler::procesEchoCommand, this))); - registerCommand(CommandDelegate(F("help"), F("Displays all available commands"), system, - CommandFunctionDelegate(&CommandHandler::procesHelpCommand, this))); - registerCommand(CommandDelegate(F("debugon"), F("Set Serial debug on"), system, - CommandFunctionDelegate(&CommandHandler::procesDebugOnCommand, this))); - registerCommand(CommandDelegate(F("debugoff"), F("Set Serial debug off"), system, - CommandFunctionDelegate(&CommandHandler::procesDebugOffCommand, this))); - registerCommand(CommandDelegate(F("command"), F("Use verbose/silent/prompt as command options"), system, - CommandFunctionDelegate(&CommandHandler::processCommandOptions, this))); -} - -CommandDelegate CommandHandler::getCommandDelegate(const String& commandString) -{ - if(registeredCommands.contains(commandString)) { - debugf("Returning Delegate for %s \r\n", commandString.c_str()); - return registeredCommands[commandString]; - } else { - debugf("Command %s not recognized, returning NULL\r\n", commandString.c_str()); - return CommandDelegate("", "", "", nullptr); - } -} - -bool CommandHandler::registerCommand(CommandDelegate reqDelegate) -{ - if(registeredCommands.contains(reqDelegate.commandName)) { - // Command already registered, don't allow duplicates - debugf("Commandhandler duplicate command %s", reqDelegate.commandName.c_str()); - return false; - } else { - registeredCommands[reqDelegate.commandName] = reqDelegate; - debugf("Commandhandlercommand %s registered", reqDelegate.commandName.c_str()); - return true; - } -} - -bool CommandHandler::unregisterCommand(CommandDelegate reqDelegate) -{ - if(!registeredCommands.contains(reqDelegate.commandName)) { - // Command not registered, cannot remove - return false; - } else { - registeredCommands.remove(reqDelegate.commandName); - // (*registeredCommands)[reqDelegate.commandName] = reqDelegate; - return true; - } -} - -void CommandHandler::procesHelpCommand(String commandLine, CommandOutput* commandOutput) -{ - debugf("HelpCommand entered"); - commandOutput->println(_F("Commands available are :")); - for(unsigned idx = 0; idx < registeredCommands.count(); idx++) { - commandOutput->print(registeredCommands.valueAt(idx).commandName); - commandOutput->print(" | "); - commandOutput->print(registeredCommands.valueAt(idx).commandGroup); - commandOutput->print(" | "); - commandOutput->print(registeredCommands.valueAt(idx).commandHelp); - commandOutput->print("\r\n"); - } -} - -void CommandHandler::procesStatusCommand(String commandLine, CommandOutput* commandOutput) -{ - debugf("StatusCommand entered"); - commandOutput->println(_F("System information : ESP8266 Sming Framework")); - commandOutput->println(_F("Sming Framework Version : " SMING_VERSION)); - commandOutput->print(_F("ESP SDK version : ")); - commandOutput->print(system_get_sdk_version()); - commandOutput->println(); -#ifndef DISABLE_NETWORK - commandOutput->printf(_F("lwIP version : %d.%d.%d(%s)\r\n"), LWIP_VERSION_MAJOR, LWIP_VERSION_MINOR, - LWIP_VERSION_REVISION, LWIP_HASH_STR); -#endif - commandOutput->print(_F("Time = ")); - commandOutput->print(SystemClock.getSystemTimeString()); - commandOutput->println(); - commandOutput->printf(_F("System Start Reason : %d\r\n"), system_get_rst_info()->reason); -} - -void CommandHandler::procesEchoCommand(String commandLine, CommandOutput* commandOutput) -{ - debugf("HelpCommand entered"); - commandOutput->print(_F("You entered : '")); - commandOutput->print(commandLine); - commandOutput->println('\''); -} - -void CommandHandler::procesDebugOnCommand(String commandLine, CommandOutput* commandOutput) -{ - Serial.systemDebugOutput(true); - commandOutput->println(_F("Debug set to : On")); -} - -void CommandHandler::procesDebugOffCommand(String commandLine, CommandOutput* commandOutput) -{ - Serial.systemDebugOutput(false); - commandOutput->println(_F("Debug set to : Off")); -} - -void CommandHandler::processCommandOptions(String commandLine, CommandOutput* commandOutput) -{ - Vector commandToken; - int numToken = splitString(commandLine, ' ', commandToken); - bool errorCommand = false; - bool printUsage = false; - - switch(numToken) { - case 2: - if(commandToken[1] == _F("help")) { - printUsage = true; - } - if(commandToken[1] == _F("verbose")) { - commandHandler.setVerboseMode(VERBOSE); - commandOutput->println(_F("Verbose mode selected")); - break; - } - if(commandToken[1] == _F("silent")) { - commandHandler.setVerboseMode(SILENT); - commandOutput->println(_F("Silent mode selected")); - break; - } - errorCommand = true; - break; - case 3: - if(commandToken[1] != _F("prompt")) { - errorCommand = true; - break; - } - commandHandler.setCommandPrompt(commandToken[2]); - commandOutput->print(_F("Prompt set to : ")); - commandOutput->print(commandToken[2]); - commandOutput->println(); - break; - default: - errorCommand = true; - } - if(errorCommand) { - commandOutput->print(_F("Unknown command : ")); - commandOutput->print(commandLine); - commandOutput->println(); - } - if(printUsage) { - commandOutput->println(_F("command usage : \r\n")); - commandOutput->println(_F("command verbose : Set verbose mode")); - commandOutput->println(_F("command silent : Set silent mode")); - commandOutput->println(_F("command prompt 'new prompt' : Set prompt to use")); - } -} - -CommandHandler commandHandler; diff --git a/Sming/Services/CommandProcessing/CommandOutput.cpp b/Sming/Services/CommandProcessing/CommandOutput.cpp deleted file mode 100644 index a8bf385103..0000000000 --- a/Sming/Services/CommandProcessing/CommandOutput.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * CommandOutput.cpp - * - * Created on: 5 jul. 2015 - * Author: Herman - */ - -#include "CommandOutput.h" -#include - -CommandOutput::CommandOutput(Stream* reqStream) : outputStream(reqStream) -{ -} - -CommandOutput::~CommandOutput() -{ - debugf("destruct"); -} - -size_t CommandOutput::write(uint8_t outChar) -{ - if(outputStream) { - return outputStream->write(outChar); - } - -#ifndef DISABLE_NETWORK - if(outputTcpClient) { - char outBuf[1] = {char(outChar)}; - return outputTcpClient->write(outBuf, 1); - } - if(outputSocket) { - if(outChar == '\r') { - outputSocket->sendString(tempSocket); - tempSocket = ""; - } else { - tempSocket += char(outChar); - } - - return 1; - } -#endif - - return 0; -} diff --git a/Sming/Services/CommandProcessing/CommandOutput.h b/Sming/Services/CommandProcessing/CommandOutput.h deleted file mode 100644 index 9ae25228e0..0000000000 --- a/Sming/Services/CommandProcessing/CommandOutput.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * CommandOutput.h - * - * Created on: 5 jul. 2015 - * Author: Herman - */ - -#pragma once - -#include -#include - -#ifndef DISABLE_NETWORK -#include -#include -#endif - -class CommandOutput : public Print -{ -public: -#ifndef DISABLE_NETWORK - CommandOutput(TcpClient* reqClient) : outputTcpClient(reqClient) - { - } - - CommandOutput(WebsocketConnection* reqSocket) : outputSocket(reqSocket) - { - } - -#endif - - CommandOutput(Stream* reqStream); - ~CommandOutput(); - - size_t write(uint8_t outChar); - -#ifndef DISABLE_NETWORK - TcpClient* outputTcpClient = nullptr; - WebsocketConnection* outputSocket = nullptr; -#endif - Stream* outputStream = nullptr; - String tempSocket = ""; -}; diff --git a/Sming/Services/CommandProcessing/CommandProcessingDependencies.h b/Sming/Services/CommandProcessing/CommandProcessingDependencies.h deleted file mode 100644 index 00a48271bb..0000000000 --- a/Sming/Services/CommandProcessing/CommandProcessingDependencies.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * CommandProcessingDependencies.h - * - * Created on: 2 jul. 2015 - * Author: Herman - */ - -#pragma once diff --git a/Sming/Services/CommandProcessing/CommandProcessingIncludes.h b/Sming/Services/CommandProcessing/CommandProcessingIncludes.h deleted file mode 100644 index 6061ee7ec9..0000000000 --- a/Sming/Services/CommandProcessing/CommandProcessingIncludes.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * CommandProcessingIncludes.h - * - * Created on: 2 jul. 2015 - * Author: Herman - */ - -#pragma once - -#include "CommandOutput.h" -#include "CommandProcessingDependencies.h" -#include "CommandDelegate.h" -#include "CommandExecutor.h" -#include "CommandHandler.h" diff --git a/Sming/Services/CommandProcessing/Handler.cpp b/Sming/Services/CommandProcessing/Handler.cpp new file mode 100644 index 0000000000..95b91ec4d6 --- /dev/null +++ b/Sming/Services/CommandProcessing/Handler.cpp @@ -0,0 +1,231 @@ +/* + * CommandHandler.cpp + * + * Created on: 2 jul. 2015 + * Author: Herman + */ + +#include +#include +#include +#include +#include "Handler.h" + +namespace CommandProcessing +{ + +Handler::Handler() + : currentPrompt(F("Sming>")), currentWelcomeMessage(F("Welcome to the Sming CommandProcessing\r\n")) +{ +} + +size_t Handler::process(char recvChar) +{ + auto& output = getOutputStream(); + + if(recvChar == 27) // ESC -> delete current commandLine + { + commandBuf.clear(); + if(getVerboseMode() == VERBOSE) { + output.println(); + output.print(getCommandPrompt()); + } + } else if(recvChar == getCommandEOL()) { + String command(commandBuf.getBuffer(), commandBuf.getLength()); + commandBuf.clear(); + processCommandLine(command); + } else if(recvChar == '\b' || recvChar == 0x7f) { + if(commandBuf.backspace()) { + output.print(_F("\b \b")); + } + } else { + if(commandBuf.addChar(recvChar) && localEcho) { + output.print(recvChar); + } + } + return 1; +} + +void Handler::processCommandLine(const String& cmdString) +{ + if(cmdString.length() == 0) { + outputStream->println(); + } else { + debug_d("Received full Command line, size = %u,cmd = %s", cmdString.length(), cmdString.c_str()); + String cmdCommand; + int cmdLen = cmdString.indexOf(' '); + if(cmdLen < 0) { + cmdCommand = cmdString; + } else { + cmdCommand = cmdString.substring(0, cmdLen); + } + + debug_d("CommandExecutor : executing command %s", cmdCommand.c_str()); + + Command cmdDelegate = getCommandDelegate(cmdCommand); + + if(!cmdDelegate.callback) { + outputStream->print(_F("Command not found, cmd = '")); + outputStream->print(cmdCommand); + outputStream->println('\''); + } else { + cmdDelegate.callback(cmdString, *outputStream); + } + } + + if(getVerboseMode() == VERBOSE) { + outputStream->print(getCommandPrompt()); + } +} + +void Handler::registerSystemCommands() +{ + String system = F("system"); + registerCommand(Command(F("status"), F("Displays System Information"), system, + Command::Callback(&Handler::procesStatusCommand, this))); + registerCommand(Command(F("echo"), F("Displays command entered"), system, + Command::Callback(&Handler::procesEchoCommand, this))); + registerCommand(Command(F("help"), F("Displays all available commands"), system, + Command::Callback(&Handler::procesHelpCommand, this))); + registerCommand(Command(F("debugon"), F("Set Serial debug on"), system, + Command::Callback(&Handler::procesDebugOnCommand, this))); + registerCommand(Command(F("debugoff"), F("Set Serial debug off"), system, + Command::Callback(&Handler::procesDebugOffCommand, this))); + registerCommand(Command(F("command"), F("Use verbose/silent/prompt as command options"), system, + Command::Callback(&Handler::processCommandOptions, this))); +} + +Command Handler::getCommandDelegate(const String& commandString) +{ + if(registeredCommands.contains(commandString)) { + debug_d("Returning Delegate for %s \r\n", commandString.c_str()); + return registeredCommands[commandString]; + } else { + debug_d("Command %s not recognized, returning NULL\r\n", commandString.c_str()); + return Command("", "", "", nullptr); + } +} + +bool Handler::registerCommand(Command reqDelegate) +{ + if(registeredCommands.contains(reqDelegate.name)) { + // Command already registered, don't allow duplicates + debug_d("Commandhandler duplicate command %s", reqDelegate.name.c_str()); + return false; + } else { + registeredCommands[reqDelegate.name] = reqDelegate; + debug_d("Commandhandlercommand %s registered", reqDelegate.name.c_str()); + return true; + } +} + +bool Handler::unregisterCommand(Command reqDelegate) +{ + if(!registeredCommands.contains(reqDelegate.name)) { + // Command not registered, cannot remove + return false; + } else { + registeredCommands.remove(reqDelegate.name); + // (*registeredCommands)[reqDelegate.commandName] = reqDelegate; + return true; + } +} + +void Handler::procesHelpCommand(String commandLine, ReadWriteStream& outputStream) +{ + debug_d("HelpCommand entered"); + outputStream.println(_F("Commands available are :")); + for(unsigned idx = 0; idx < registeredCommands.count(); idx++) { + outputStream.print(registeredCommands.valueAt(idx).name); + outputStream.print(" | "); + outputStream.print(registeredCommands.valueAt(idx).group); + outputStream.print(" | "); + outputStream.print(registeredCommands.valueAt(idx).description); + outputStream.print("\r\n"); + } +} + +void Handler::procesStatusCommand(String commandLine, ReadWriteStream& outputStream) +{ + debug_d("StatusCommand entered"); + outputStream.println(_F("Sming Framework Version : " SMING_VERSION)); + outputStream.print(_F("ESP SDK version : ")); + outputStream.print(system_get_sdk_version()); + outputStream.println(); + outputStream.print(_F("Time = ")); + outputStream.print(SystemClock.getSystemTimeString()); + outputStream.println(); + outputStream.printf(_F("System Start Reason : %d\r\n"), system_get_rst_info()->reason); +} + +void Handler::procesEchoCommand(String commandLine, ReadWriteStream& outputStream) +{ + debug_d("HelpCommand entered"); + outputStream.print(_F("You entered : '")); + outputStream.print(commandLine); + outputStream.println('\''); +} + +void Handler::procesDebugOnCommand(String commandLine, ReadWriteStream& outputStream) +{ +// Serial.systemDebugOutput(true); +// outputStream.println(_F("Debug set to : On")); +} + +void Handler::procesDebugOffCommand(String commandLine, ReadWriteStream& outputStream) +{ +// Serial.systemDebugOutput(false); +// outputStream.println(_F("Debug set to : Off")); +} + +void Handler::processCommandOptions(String commandLine, ReadWriteStream& outputStream) +{ + Vector commandToken; + int numToken = splitString(commandLine, ' ', commandToken); + bool errorCommand = false; + bool printUsage = false; + + switch(numToken) { + case 2: + if(commandToken[1] == _F("help")) { + printUsage = true; + } + if(commandToken[1] == _F("verbose")) { + setVerboseMode(VERBOSE); + outputStream.println(_F("Verbose mode selected")); + break; + } + if(commandToken[1] == _F("silent")) { + setVerboseMode(SILENT); + outputStream.println(_F("Silent mode selected")); + break; + } + errorCommand = true; + break; + case 3: + if(commandToken[1] != _F("prompt")) { + errorCommand = true; + break; + } + setCommandPrompt(commandToken[2]); + outputStream.print(_F("Prompt set to : ")); + outputStream.print(commandToken[2]); + outputStream.println(); + break; + default: + errorCommand = true; + } + if(errorCommand) { + outputStream.print(_F("Unknown command : ")); + outputStream.print(commandLine); + outputStream.println(); + } + if(printUsage) { + outputStream.println(_F("command usage : \r\n")); + outputStream.println(_F("command verbose : Set verbose mode")); + outputStream.println(_F("command silent : Set silent mode")); + outputStream.println(_F("command prompt 'new prompt' : Set prompt to use")); + } +} + +} // namespace CommandProcessing diff --git a/Sming/Services/CommandProcessing/CommandHandler.h b/Sming/Services/CommandProcessing/Handler.h similarity index 55% rename from Sming/Services/CommandProcessing/CommandHandler.h rename to Sming/Services/CommandProcessing/Handler.h index 8c6d2d4919..ed98356b10 100644 --- a/Sming/Services/CommandProcessing/CommandHandler.h +++ b/Sming/Services/CommandProcessing/Handler.h @@ -6,45 +6,106 @@ */ /** @defgroup commandhandler Command Handler * @brief Provide command line interface - - Command handler provides a common command line interface. CLI is available for the following remote access methods: - - Serial - - Telnet - - Websockets - - By default, CLI is disabled. Enable CLI by calling "commandProcessing" on the appropriate access class object, e.g. - - Serial.commandProcessing(true) - Commands can be added to and removed from the command handler. Each command will trigger a defined Delegate. - A welcome message may be shown when a user connects and end of line character may be defined. An automatic "help" display is available. * @{ */ #pragma once -#include "CommandDelegate.h" #include -#include -#include +#include +#include +#include +#include +#include "Command.h" + +namespace CommandProcessing +{ + +constexpr size_t MAX_COMMANDSIZE=64; /** @brief Verbose mode */ -enum VerboseMode { - VERBOSE, ///< Verbose mode - SILENT ///< Silent mode -}; + /** @brief Command handler class */ -class CommandHandler +class Handler { public: - /** @brief Instantiate a CommandHandler + /** @brief Verbose mode */ - CommandHandler(); + enum VerboseMode { + VERBOSE, ///< Verbose mode + SILENT ///< Silent mode + }; + + + /** + * @brief Instantiate a CommandHandler + */ + Handler(); + + Handler(ReadWriteStream* stream, bool owned = true): outputStream(stream), ownedStream(owned) + { + } + + Handler(const Handler&) = delete; + + ~Handler() + { + if(ownedStream) { + delete outputStream; + } + } + + // I/O methods + + /** + * @brief sets the output stream + * @param stream pointer to the output stream + * @param owned specifies if the output stream should be deleted in this class(owned=true) + */ + void setOutputStream(ReadWriteStream* stream, bool owned = true) + { + if(outputStream != nullptr && ownedStream) { + delete outputStream; + } - CommandHandler(const CommandHandler&) = delete; + outputStream = stream; + ownedStream = owned; + } + + ReadWriteStream& getOutputStream() + { + if(outputStream == nullptr) { + outputStream = new MemoryDataStream(); + ownedStream = true; + } + + return *outputStream; + } + + size_t process(char charToWrite); + + /** @brief Write chars to stream + * @param buffer Pointer to buffer to write to the stream + * @param size Quantity of chars to write + * @retval size_t Quantity of chars processed + */ + size_t process(const char* buffer, size_t size) + { + size_t retval = 0; + for(size_t i = 0; i < size; i++) { + if(process(buffer[i]) != 1) { + break; + } + retval++; + } + return retval; + } + + // Command registration/de-registration methods /** @brief Add a new command to the command handler * @param reqDelegate Command delegate to register @@ -52,12 +113,12 @@ class CommandHandler * @note If command already exists, it will not be replaced and function will fail. Call unregisterCommand first if you want to replace a command. */ - bool registerCommand(CommandDelegate reqDelegate); + bool registerCommand(Command reqDelegate); /** @brief Remove a command from the command handler * @brief reqDelegate Delegate to remove from command handler */ - bool unregisterCommand(CommandDelegate reqDelegate); + bool unregisterCommand(Command reqDelegate); /** @brief Register default system commands * @note Adds the following system commands to the command handler @@ -74,7 +135,7 @@ class CommandHandler * @param commandString Command to query * @retval CommandDelegate The command delegate matching the command */ - CommandDelegate getCommandDelegate(const String& commandString); + Command getCommandDelegate(const String& commandString); /** @brief Get the verbose mode * @retval VerboseMode Verbose mode @@ -148,28 +209,32 @@ class CommandHandler currentWelcomeMessage = reqWelcomeMessage; } - // int deleteGroup(String reqGroup); - private: - HashMap registeredCommands; - void procesHelpCommand(String commandLine, CommandOutput* commandOutput); - void procesStatusCommand(String commandLine, CommandOutput* commandOutput); - void procesEchoCommand(String commandLine, CommandOutput* commandOutput); - void procesDebugOnCommand(String commandLine, CommandOutput* commandOutput); - void procesDebugOffCommand(String commandLine, CommandOutput* commandOutput); - void processCommandOptions(String commandLine, CommandOutput* commandOutput); - - VerboseMode verboseMode = VERBOSE; + HashMap registeredCommands; String currentPrompt; #ifdef ARCH_HOST - char currentEOL = '\n'; + char currentEOL{'\n'}; #else - char currentEOL = '\r'; + char currentEOL{'\r'}; #endif + VerboseMode verboseMode{VERBOSE}; + bool localEcho{true}; String currentWelcomeMessage; + + ReadWriteStream* outputStream{nullptr}; + bool ownedStream = true; + LineBuffer commandBuf; + + void procesHelpCommand(String commandLine, ReadWriteStream& outputStream); + void procesStatusCommand(String commandLine, ReadWriteStream& outputStream); + void procesEchoCommand(String commandLine, ReadWriteStream& outputStream); + void procesDebugOnCommand(String commandLine, ReadWriteStream& outputStream); + void procesDebugOffCommand(String commandLine, ReadWriteStream& outputStream); + void processCommandOptions(String commandLine, ReadWriteStream& outputStream); + + void processCommandLine(const String& cmdString); }; -/** @brief Global instance of CommandHandler */ -extern CommandHandler commandHandler; +} // namespace CommandProcessing /** @} */ diff --git a/samples/CommandProcessing_Debug/app/ExampleCommand.cpp b/samples/CommandProcessing_Debug/app/ExampleCommand.cpp deleted file mode 100644 index 9bc37bbb82..0000000000 --- a/samples/CommandProcessing_Debug/app/ExampleCommand.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Debug.cpp - * - */ - -#include - -ExampleCommand::ExampleCommand() -{ - debugf("ExampleCommand Instantiating"); -} - -ExampleCommand::~ExampleCommand() -{ -} - -void ExampleCommand::initCommand() -{ - commandHandler.registerCommand( - CommandDelegate("example", "Example Command from Class", "Application", - CommandFunctionDelegate(&ExampleCommand::processExampleCommands, this))); -} - -void ExampleCommand::processExampleCommands(String commandLine, CommandOutput* commandOutput) -{ - Vector commandToken; - int numToken = splitString(commandLine, ' ', commandToken); - - if(numToken == 1) { - commandOutput->printf("Example Commands available : \r\n"); - commandOutput->printf("on : Set example status ON\r\n"); - commandOutput->printf("off : Set example status OFF\r\n"); - commandOutput->printf("status : Show example status\r\n"); - } else { - if(commandToken[1] == "on") { - status = true; - commandOutput->printf("Status ON\r\n"); - } else if(commandToken[1] == "off") { - status = false; - commandOutput->printf("Status OFF\r\n"); - } else if(commandToken[1] == "status") { - String tempString = status ? "ON" : "OFF"; - commandOutput->printf("Example Status is %s\r\n", tempString.c_str()); - }; - } -} diff --git a/samples/CommandProcessing_Debug/app/application.cpp b/samples/CommandProcessing_Debug/app/application.cpp index e9b3ad4e32..8b6e54e9ee 100644 --- a/samples/CommandProcessing_Debug/app/application.cpp +++ b/samples/CommandProcessing_Debug/app/application.cpp @@ -1,8 +1,8 @@ #include +#include #include #include -#include -#include +//#include // If you want, you can define WiFi settings globally in Eclipse Environment Variables #ifndef WIFI_SSID @@ -10,127 +10,63 @@ #define WIFI_PWD "PleaseEnterPass" #endif +CommandProcessing::Handler commandHandler; + +namespace +{ + HttpServer server; FtpServer ftp; TelnetServer telnet; Timer msgTimer; -ExampleCommand exampleCommand; +bool exampleStatus = true; -void onIndex(HttpRequest& request, HttpResponse& response) -{ - TemplateFileStream* tmpl = new TemplateFileStream("index.html"); - auto& vars = tmpl->variables(); - //vars["counter"] = String(counter); - response.sendNamedStream(tmpl); // this template object will be deleted automatically -} +// Example Command -void onFile(HttpRequest& request, HttpResponse& response) +void processExampleCommand(String commandLine, ReadWriteStream& commandOutput) { - String file = request.uri.getRelativePath(); - - if(file[0] == '.') - response.code = HTTP_STATUS_FORBIDDEN; - else { - response.setCache(86400, true); // It's important to use cache for better performance. - response.sendFile(file); + Vector commandToken; + int numToken = splitString(commandLine, ' ', commandToken); + + if(numToken == 1) { + commandOutput.printf("Example Commands available : \r\n"); + commandOutput.printf("on : Set example status ON\r\n"); + commandOutput.printf("off : Set example status OFF\r\n"); + commandOutput.printf("status : Show example status\r\n"); + } else { + if(commandToken[1] == "on") { + exampleStatus = true; + commandOutput.printf("Status ON\r\n"); + } else if(commandToken[1] == "off") { + exampleStatus = false; + commandOutput.printf("Status OFF\r\n"); + } else if(commandToken[1] == "status") { + String tempString = exampleStatus ? "ON" : "OFF"; + commandOutput.printf("Example Status is %s\r\n", tempString.c_str()); + }; } } -int msgCount = 0; - -void wsConnected(WebsocketConnection& socket) -{ - Serial.println(_F("Socket connected")); -} - -void wsMessageReceived(WebsocketConnection& socket, const String& message) -{ - Serial.println(_F("WebsocketConnection message received:")); - Serial.println(message); - String response = "Echo: " + message; - socket.sendString(response); -} - -void wsBinaryReceived(WebsocketConnection& socket, uint8_t* data, size_t size) -{ - Serial << _F("Websocket binary data received, size: ") << size << endl; -} - -void wsDisconnected(WebsocketConnection& socket) -{ - Serial.println(_F("Socket disconnected")); -} - -void processApplicationCommands(String commandLine, CommandOutput* commandOutput) -{ - commandOutput->println(_F("This command is handle by the application")); -} - -void StartServers() -{ - server.listen(80); - server.paths.set("/", onIndex); - server.paths.setDefault(onFile); - - // Web Sockets configuration - WebsocketResource* wsResource = new WebsocketResource(); - wsResource->setConnectionHandler(wsConnected); - wsResource->setMessageHandler(wsMessageReceived); - wsResource->setBinaryHandler(wsBinaryReceived); - wsResource->setDisconnectionHandler(wsDisconnected); - - server.paths.set("/ws", wsResource); - - Serial.println(_F("\r\n=== WEB SERVER STARTED ===")); - Serial.println(WifiStation.getIP()); - Serial.println(_F("==============================\r\n")); - - // Start FTP server - ftp.listen(21); - ftp.addUser("me", "123"); // FTP account - - Serial.println(_F("\r\n=== FTP SERVER STARTED ===")); - Serial.println(_F("==============================\r\n")); - - telnet.listen(23); - telnet.enableDebug(true); - - Serial.println(_F("\r\n=== TelnetServer SERVER STARTED ===")); - Serial.println(_F("==============================\r\n")); -} - -void startExampleApplicationCommand() -{ - exampleCommand.initCommand(); - commandHandler.registerCommand( - CommandDelegate(F("example"), F("Example Command from Class"), F("Application"), processApplicationCommands)); -} - -void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) -{ - StartServers(); - - startExampleApplicationCommand(); -} +} // namespace void init() { - spiffs_mount(); // Mount file system, in order to work with files - - Serial.begin(SERIAL_BAUD_RATE); // 115200 by default - - commandHandler.registerSystemCommands(); - Debug.setDebug(Serial); + Serial.begin(SERIAL_BAUD_RATE); // Begin serial output + // Set verbosity Serial.systemDebugOutput(true); // Enable debug output to serial - Serial.commandProcessing(true); + commandHandler.setVerboseMode(CommandProcessing::Handler::VerboseMode::VERBOSE); - WifiStation.enable(true); - WifiStation.config(WIFI_SSID, WIFI_PWD); - WifiAccessPoint.enable(false); + // Register Input/Output streams + commandHandler.setOutputStream(&Serial, false); + Serial.onDataReceived([](Stream& source, char arrivedChar, uint16_t availableCharsCount) { + while(availableCharsCount--) { + commandHandler.process(source.read()); + } + }); - // Run our method when station was connected to AP - WifiEvents.onStationGotIP(gotIP); + commandHandler.registerSystemCommands(); + commandHandler.registerCommand(CommandProcessing::Command("example", "Example Command", "Application", processExampleCommand)); } diff --git a/samples/CommandProcessing_Debug/include/ExampleCommand.h b/samples/CommandProcessing_Debug/include/ExampleCommand.h deleted file mode 100644 index f16501af40..0000000000 --- a/samples/CommandProcessing_Debug/include/ExampleCommand.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * ExampleCommand.h - * - */ - -#pragma once - -#include "WString.h" -#include - -class ExampleCommand -{ -public: - ExampleCommand(); - virtual ~ExampleCommand(); - void initCommand(); - -private: - bool status = true; - void processExampleCommands(String commandLine, CommandOutput* commandOutput); -}; From a7d8d9c277c5ba5c6bc678f9ab8638c06ddda5d5 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Mon, 27 Nov 2023 14:17:07 +0100 Subject: [PATCH 02/17] Telnet server is badly written and not useful in its current state. --- .../Network/src/Network/TelnetServer.cpp | 84 ------------------- .../Network/src/Network/TelnetServer.h | 55 ------------ .../app/application.cpp | 2 - 3 files changed, 141 deletions(-) delete mode 100644 Sming/Components/Network/src/Network/TelnetServer.cpp delete mode 100644 Sming/Components/Network/src/Network/TelnetServer.h diff --git a/Sming/Components/Network/src/Network/TelnetServer.cpp b/Sming/Components/Network/src/Network/TelnetServer.cpp deleted file mode 100644 index 0edb1d7186..0000000000 --- a/Sming/Components/Network/src/Network/TelnetServer.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * TelnetServer.cpp - * - * Created on: 18 apr. 2015 - * Author: Herman - * - ****/ - -#include "TelnetServer.h" -#include "TcpClientStream.h" - -void TelnetServer::enableCommand(bool reqStatus) -{ - if(!reqStatus && commandHandler != nullptr) { - delete commandHandler; - commandHandler = nullptr; - return; - } - - if(reqStatus && curClient != nullptr && commandHandler == nullptr) { - commandHandler = new CommandProcessing::Handler(); - commandHandler->setOutputStream(new TcpClientStream(*curClient)); - } - - telnetCommand = reqStatus; -} - -void TelnetServer::onClient(TcpClient* client) -{ - debug_d("TelnetServer onClient %s", client->getRemoteIp().toString().c_str()); - - TcpServer::onClient(client); - - if(curClient != nullptr) { - debug_d("TCP Client already connected"); - client->sendString("Telnet Client already connected\r\n"); - client->close(); - } else { - curClient = client; - curClient->setTimeOut(USHRT_MAX); - curClient->sendString("Welcome to Sming Telnet\r\n"); - if(telnetCommand) { - commandHandler = new CommandProcessing::Handler(); - commandHandler->setOutputStream(new TcpClientStream(*client)); - } - } -} - -void TelnetServer::onClientComplete(TcpClient& client, bool successful) -{ - if(&client == curClient) { - delete commandHandler; - commandHandler = nullptr; - curClient = nullptr; - debug_d("TelnetServer onClientComplete %s", client.getRemoteIp().toString().c_str()); - } else { - debug_d("Telnet server unconnected client close"); - } - - debug_d("TelnetServer onClientComplete %s", client.getRemoteIp().toString().c_str()); - TcpServer::onClientComplete(client, successful); -} - -void TelnetServer::wrchar(char c) -{ - char ca[2]; - ca[0] = c; - curClient->write(ca, 1); -} - -bool TelnetServer::onClientReceive(TcpClient& client, char* data, int size) -{ - debug_d("TelnetServer onClientReceive : %s, %d bytes \r\n", client.getRemoteIp().toString().c_str(), size); - debug_d("Data : %s", data); - if(commandHandler != nullptr) { - commandHandler->process(data, size); - } - return true; -} diff --git a/Sming/Components/Network/src/Network/TelnetServer.h b/Sming/Components/Network/src/Network/TelnetServer.h deleted file mode 100644 index beafe8a03a..0000000000 --- a/Sming/Components/Network/src/Network/TelnetServer.h +++ /dev/null @@ -1,55 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * TelnetServer.h - * - * Created on: 18 apr. 2015 - * Author: Herman - * - ****/ - -/** @defgroup telnetserver Telnet server - * @brief Provides Telnet server - * @ingroup tcpserver - * @{ - */ - -#pragma once - -#include "TcpClient.h" -#include "TcpServer.h" -#include -#include - -#ifndef TELNETSERVER_MAX_COMMANDSIZE -#define TELNETSERVER_MAX_COMMANDSIZE 64 -#endif - -using TelnetServerCommandDelegate = Delegate; - -class TelnetServer : public TcpServer -{ -public: - void enableDebug(bool reqStatus) SMING_DEPRECATED - { - } - - void enableCommand(bool reqStatus); - -private: - void onClient(TcpClient* client) override; - bool onClientReceive(TcpClient& client, char* data, int size) override; - void onClientComplete(TcpClient& client, bool successful) override; - - void wrchar(char c); - -private: - TcpClient* curClient = nullptr; - CommandProcessing::Handler* commandHandler = nullptr; - bool telnetCommand = true; -}; - -/** @} */ diff --git a/samples/CommandProcessing_Debug/app/application.cpp b/samples/CommandProcessing_Debug/app/application.cpp index 8b6e54e9ee..782ebe541d 100644 --- a/samples/CommandProcessing_Debug/app/application.cpp +++ b/samples/CommandProcessing_Debug/app/application.cpp @@ -1,6 +1,5 @@ #include #include -#include #include //#include @@ -17,7 +16,6 @@ namespace HttpServer server; FtpServer ftp; -TelnetServer telnet; Timer msgTimer; From a2c6f6480022365bbe6e7e1acc79171e881c5ba1 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Fri, 1 Dec 2023 14:57:24 +0100 Subject: [PATCH 03/17] Further rewriting of the command processing component. --- .../Http/Websocket/WebsocketResource.cpp | 2 - .../Http/Websocket/WsCommandHandlerResource.h | 51 --------------- Sming/Services/CommandProcessing/Handler.h | 5 ++ .../app/application.cpp | 9 +-- .../HttpServer_WebSockets/app/application.cpp | 63 +++++++++++++++++++ 5 files changed, 70 insertions(+), 60 deletions(-) delete mode 100644 Sming/Components/Network/src/Network/Http/Websocket/WsCommandHandlerResource.h diff --git a/Sming/Components/Network/src/Network/Http/Websocket/WebsocketResource.cpp b/Sming/Components/Network/src/Network/Http/Websocket/WebsocketResource.cpp index 24288d2997..4d2586dccd 100644 --- a/Sming/Components/Network/src/Network/Http/Websocket/WebsocketResource.cpp +++ b/Sming/Components/Network/src/Network/Http/Websocket/WebsocketResource.cpp @@ -35,8 +35,6 @@ int WebsocketResource::checkHeaders(HttpServerConnection& connection, HttpReques connection.userData = (void*)socket; connection.setUpgradeCallback(HttpServerProtocolUpgradeCallback(&WebsocketConnection::onConnected, socket)); - // TODO: Re-Enable Command Executor... - return 0; } diff --git a/Sming/Components/Network/src/Network/Http/Websocket/WsCommandHandlerResource.h b/Sming/Components/Network/src/Network/Http/Websocket/WsCommandHandlerResource.h deleted file mode 100644 index d14a666935..0000000000 --- a/Sming/Components/Network/src/Network/Http/Websocket/WsCommandHandlerResource.h +++ /dev/null @@ -1,51 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * WsCommandHandlerResource.h - * - * @author: 2017 - Slavey Karadzhov - * - ****/ - -#pragma once - -#include "../HttpResource.h" -#include "WebsocketConnection.h" -#include "WString.h" -#include "Services/CommandProcessing/CommandProcessingIncludes.h" // TODO: .... - -class WsCommandHandlerResource : protected WebsocketResource -{ -public: - WsCommandHandlerResource() : WebsocketResource() - { - wsMessage = WebsocketMessageDelegate(&WsCommandHandlerResource::onMessage, this); - } - -protected: - int checkHeaders(HttpServerConnection& connection, HttpRequest& request, HttpResponse& response) override - { - int err = WebsocketResource::checkHeaders(connection, request, response); - if(err != 0) { - return err; - } - - WebsocketConnection* socket = (WebsocketConnection*)connection.userData; - if(socket != nullptr) { - socket->setMessageHandler(); - - // create new command handler - } - } - - void onMessage(WebsocketConnection& connection, const String& message) - { - commandExecutor.executorReceive(message + "\r"); - } - -private: - CommandExecutor commandExecutor; -}; diff --git a/Sming/Services/CommandProcessing/Handler.h b/Sming/Services/CommandProcessing/Handler.h index ed98356b10..c509fdbc37 100644 --- a/Sming/Services/CommandProcessing/Handler.h +++ b/Sming/Services/CommandProcessing/Handler.h @@ -105,6 +105,11 @@ class Handler return retval; } + String process(const String& data) + { + + } + // Command registration/de-registration methods /** @brief Add a new command to the command handler diff --git a/samples/CommandProcessing_Debug/app/application.cpp b/samples/CommandProcessing_Debug/app/application.cpp index 782ebe541d..7f6dfd504e 100644 --- a/samples/CommandProcessing_Debug/app/application.cpp +++ b/samples/CommandProcessing_Debug/app/application.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include //#include @@ -58,12 +58,7 @@ void init() commandHandler.setVerboseMode(CommandProcessing::Handler::VerboseMode::VERBOSE); // Register Input/Output streams - commandHandler.setOutputStream(&Serial, false); - Serial.onDataReceived([](Stream& source, char arrivedChar, uint16_t availableCharsCount) { - while(availableCharsCount--) { - commandHandler.process(source.read()); - } - }); + CommandProcessing::enable(commandHandler, Serial); commandHandler.registerSystemCommands(); commandHandler.registerCommand(CommandProcessing::Command("example", "Example Command", "Application", processExampleCommand)); diff --git a/samples/HttpServer_WebSockets/app/application.cpp b/samples/HttpServer_WebSockets/app/application.cpp index 77062a5bfd..d9f7ad19fa 100644 --- a/samples/HttpServer_WebSockets/app/application.cpp +++ b/samples/HttpServer_WebSockets/app/application.cpp @@ -2,6 +2,11 @@ #include #include "CUserData.h" +#if ENABLE_CMD_EXECUTOR +#include +CommandProcessing::Handler commandHandler; +#endif + // If you want, you can define WiFi settings globally in Eclipse Environment Variables #ifndef WIFI_SSID #define WIFI_SSID "PleaseEnterSSID" // Put your SSID and password here @@ -76,6 +81,55 @@ void wsMessageReceived(WebsocketConnection& socket, const String& message) } } +#if ENABLE_CMD_EXECUTOR +void wsCommandReceived(WebsocketConnection& socket, const String& message) +{ + commandProcessing.process(message.c_str(), message.length()); + + Serial.println(_F("WebSocket message received:")); + Serial.println(message); + + if(message == _F("shutdown")) { + String message(F("The server is shutting down...")); + socket.broadcast(message); + + // Don't shutdown immediately, wait a bit to allow messages to propagate + auto timer = new SimpleTimer; + timer->initializeMs<1000>( + [](void* timer) { + delete static_cast(timer); + server.shutdown(); + }, + timer); + timer->startOnce(); + return; + } + + String response = F("Echo: ") + message; + socket.sendString(response); + + //Normally you would use dynamic cast but just be careful not to convert to wrong object type! + auto user = reinterpret_cast(socket.getUserData()); + if(user != nullptr) { + user->printMessage(socket, message); + } +} + + +void processShutdownCommand(String commandLine, ReadWriteStream& commandOutput) +{ + // Don't shutdown immediately, wait a bit to allow messages to propagate + auto timer = new SimpleTimer; + timer->initializeMs<1000>( + [](void* timer) { + delete static_cast(timer); + server.shutdown(); + }, + timer); + timer->startOnce(); +} +#endif + void wsBinaryReceived(WebsocketConnection& socket, uint8_t* data, size_t size) { Serial << _F("Websocket binary data received, size: ") << size << endl; @@ -106,6 +160,10 @@ void startWebServer() auto wsResource = new WebsocketResource(); wsResource->setConnectionHandler(wsConnected); wsResource->setMessageHandler(wsMessageReceived); +#if ENABLE_CMD_EXECUTOR + wsResource->setMessageHandler(wsCommandReceived); +#endif + wsResource->setBinaryHandler(wsBinaryReceived); wsResource->setDisconnectionHandler(wsDisconnected); @@ -127,6 +185,11 @@ void init() { spiffs_mount(); // Mount file system, in order to work with files +#if ENABLE_CMD_EXECUTOR + commandHandler.registerSystemCommands(); + commandHanledr.registerCommand(CommandProcessing::Command("shutdown", "Shutdown Server Command", "Application", processShutdownCommand)); +#endif + Serial.begin(SERIAL_BAUD_RATE); // 115200 by default Serial.systemDebugOutput(true); // Enable debug output to serial From 79eb781278d40dc92b09d884f545d070eae68929 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Fri, 1 Dec 2023 15:27:04 +0100 Subject: [PATCH 04/17] Get rid of command processing in HardwareSerial. --- Sming/Core/HardwareSerial.cpp | 38 ------------------- Sming/Core/HardwareSerial.h | 10 ++++- Sming/Services/CommandProcessing/Handler.cpp | 17 +++++++++ Sming/Services/CommandProcessing/Handler.h | 5 +-- .../app/application.cpp | 2 - .../HttpServer_WebSockets/app/application.cpp | 22 +---------- 6 files changed, 27 insertions(+), 67 deletions(-) diff --git a/Sming/Core/HardwareSerial.cpp b/Sming/Core/HardwareSerial.cpp index ef2fde8998..c83a51c570 100644 --- a/Sming/Core/HardwareSerial.cpp +++ b/Sming/Core/HardwareSerial.cpp @@ -15,19 +15,8 @@ #include "Platform/System.h" #include "m_printf.h" -#if ENABLE_CMD_EXECUTOR -#include -#endif - HardwareSerial Serial(UART_ID_0); -HardwareSerial::~HardwareSerial() -{ -//#if ENABLE_CMD_EXECUTOR -// delete commandExecutor; -//#endif -} - bool HardwareSerial::begin(uint32_t baud, SerialFormat format, SerialMode mode, uint8_t txPin, uint8_t rxPin) { end(); @@ -123,14 +112,6 @@ void HardwareSerial::invokeCallbacks() if(HWSDelegate) { HWSDelegate(*this, receivedChar, smg_uart_rx_available(uart)); } -//#if ENABLE_CMD_EXECUTOR -// if(commandExecutor) { -// int c; -// while((c = smg_uart_read_char(uart)) >= 0) { -// commandExecutor->executorReceive(c); -// } -// } -//#endif } } @@ -190,11 +171,7 @@ void HardwareSerial::staticCallbackHandler(smg_uart_t* uart, uint32_t status) bool HardwareSerial::updateUartCallback() { uint16_t mask = 0; -//#if ENABLE_CMD_EXECUTOR -// if(HWSDelegate || commandExecutor) { -//#else if(HWSDelegate) { -//#endif mask |= UART_STATUS_RXFIFO_FULL | UART_STATUS_RXFIFO_TOUT | UART_STATUS_RXFIFO_OVF; } @@ -208,18 +185,3 @@ bool HardwareSerial::updateUartCallback() return mask != 0; } - -void HardwareSerial::commandProcessing(bool reqEnable) -{ -//#if ENABLE_CMD_EXECUTOR -// if(reqEnable) { -// if(!commandExecutor) { -// commandExecutor = new CommandExecutor(this); -// } -// } else { -// delete commandExecutor; -// commandExecutor = nullptr; -// } -// updateUartCallback(); -//#endif -} diff --git a/Sming/Core/HardwareSerial.h b/Sming/Core/HardwareSerial.h index a3b623684a..553a0b6a87 100644 --- a/Sming/Core/HardwareSerial.h +++ b/Sming/Core/HardwareSerial.h @@ -116,7 +116,9 @@ class HardwareSerial : public ReadWriteStream { } - ~HardwareSerial(); + ~HardwareSerial() + { + } void setPort(int uartPort) { @@ -340,8 +342,12 @@ class HardwareSerial : public ReadWriteStream * @param reqEnable True to enable command processing * @note Command processing provides a CLI to the system * @see commandHandler + * + * @deprecated include and use `CommandProcessing::enable(Handler, Serial)` instead. */ - void commandProcessing(bool reqEnable) SMING_DEPRECATED; + void commandProcessing(bool reqEnable) SMING_DEPRECATED + { + } /** @brief Set handler for received data * @param dataReceivedDelegate Function to handle received data diff --git a/Sming/Services/CommandProcessing/Handler.cpp b/Sming/Services/CommandProcessing/Handler.cpp index 95b91ec4d6..09a0908b75 100644 --- a/Sming/Services/CommandProcessing/Handler.cpp +++ b/Sming/Services/CommandProcessing/Handler.cpp @@ -46,6 +46,23 @@ size_t Handler::process(char recvChar) return 1; } +String Handler::processNow(const char* buffer, size_t size) +{ + if(outputStream != nullptr && outputStream->getStreamType() != eSST_MemoryWritable) { + debug_e("Cannot use this method when output stream is set"); + } + + size_t processed = process(buffer, size); + if(processed == size) { + String output; + if(outputStream->moveString(output)) { + return output; + } + } + + return nullptr; +} + void Handler::processCommandLine(const String& cmdString) { if(cmdString.length() == 0) { diff --git a/Sming/Services/CommandProcessing/Handler.h b/Sming/Services/CommandProcessing/Handler.h index c509fdbc37..937909d0d7 100644 --- a/Sming/Services/CommandProcessing/Handler.h +++ b/Sming/Services/CommandProcessing/Handler.h @@ -105,10 +105,7 @@ class Handler return retval; } - String process(const String& data) - { - - } + String processNow(const char* buffer, size_t size); // Command registration/de-registration methods diff --git a/samples/CommandProcessing_Debug/app/application.cpp b/samples/CommandProcessing_Debug/app/application.cpp index 7f6dfd504e..ac84739ddc 100644 --- a/samples/CommandProcessing_Debug/app/application.cpp +++ b/samples/CommandProcessing_Debug/app/application.cpp @@ -1,7 +1,5 @@ #include #include -#include -//#include // If you want, you can define WiFi settings globally in Eclipse Environment Variables #ifndef WIFI_SSID diff --git a/samples/HttpServer_WebSockets/app/application.cpp b/samples/HttpServer_WebSockets/app/application.cpp index d9f7ad19fa..39e1155bb7 100644 --- a/samples/HttpServer_WebSockets/app/application.cpp +++ b/samples/HttpServer_WebSockets/app/application.cpp @@ -84,26 +84,7 @@ void wsMessageReceived(WebsocketConnection& socket, const String& message) #if ENABLE_CMD_EXECUTOR void wsCommandReceived(WebsocketConnection& socket, const String& message) { - commandProcessing.process(message.c_str(), message.length()); - - Serial.println(_F("WebSocket message received:")); - Serial.println(message); - - if(message == _F("shutdown")) { - String message(F("The server is shutting down...")); - socket.broadcast(message); - - // Don't shutdown immediately, wait a bit to allow messages to propagate - auto timer = new SimpleTimer; - timer->initializeMs<1000>( - [](void* timer) { - delete static_cast(timer); - server.shutdown(); - }, - timer); - timer->startOnce(); - return; - } + String response = commandProcessing.processNow(message.c_str(), message.length()); String response = F("Echo: ") + message; socket.sendString(response); @@ -115,7 +96,6 @@ void wsCommandReceived(WebsocketConnection& socket, const String& message) } } - void processShutdownCommand(String commandLine, ReadWriteStream& commandOutput) { // Don't shutdown immediately, wait a bit to allow messages to propagate From 79afaeb2a49ab74260524bde0c4ca9ff0547dd1c Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Fri, 1 Dec 2023 16:30:41 +0100 Subject: [PATCH 05/17] Tested improvements. Documentation should be improved. --- Sming/Kconfig | 6 ----- Sming/Services/CommandProcessing/Utils.h | 19 ++++++++++++++ Sming/component.mk | 9 ++----- .../services/command-processing/index.rst | 25 ++++++------------- samples/HttpServer_WebSockets/Kconfig | 11 ++++++++ .../HttpServer_WebSockets/app/application.cpp | 14 +++++------ samples/HttpServer_WebSockets/component.mk | 5 ++++ 7 files changed, 50 insertions(+), 39 deletions(-) create mode 100644 Sming/Services/CommandProcessing/Utils.h create mode 100644 samples/HttpServer_WebSockets/Kconfig diff --git a/Sming/Kconfig b/Sming/Kconfig index 9a4bfd12cd..993af06be2 100644 --- a/Sming/Kconfig +++ b/Sming/Kconfig @@ -43,12 +43,6 @@ mainmenu "${SMING_SOC} Sming Framework Configuration" This will recompile your application to use the revised baud rate. Note that this will change the default speed used for both flashing and serial comms. - config ENABLE_CMD_EXECUTOR - bool "Enable command executor functionality" - default y - help - This facility requires documenting! - config TASK_QUEUE_LENGTH int "Length of task queue" default 10 diff --git a/Sming/Services/CommandProcessing/Utils.h b/Sming/Services/CommandProcessing/Utils.h new file mode 100644 index 0000000000..297d25bdc1 --- /dev/null +++ b/Sming/Services/CommandProcessing/Utils.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Handler.h" +#include + +namespace CommandProcessing +{ + +void enable(Handler& commandHandler, HardwareSerial& serial) +{ + commandHandler.setOutputStream(&serial, false); + Serial.onDataReceived([&commandHandler](Stream& source, char arrivedChar, uint16_t availableCharsCount) { + while(availableCharsCount--) { + commandHandler.process(source.read()); + } + }); +} + +} // namespace CommandProcessing diff --git a/Sming/component.mk b/Sming/component.mk index c0e95cf705..095f887e65 100644 --- a/Sming/component.mk +++ b/Sming/component.mk @@ -31,13 +31,8 @@ COMPONENT_DOXYGEN_INPUT := \ Wiring \ System -# => Disable CommandExecutor functionality if not used and save some ROM and RAM -COMPONENT_VARS += ENABLE_CMD_EXECUTOR -ENABLE_CMD_EXECUTOR ?= 1 -ifeq ($(ENABLE_CMD_EXECUTOR),1) -COMPONENT_SRCDIRS += Services/CommandProcessing -endif -GLOBAL_CFLAGS += -DENABLE_CMD_EXECUTOR=$(ENABLE_CMD_EXECUTOR) +# => CommandProcessing functionality +COMPONENT_SRCDIRS += Services/CommandProcessing # RELINK_VARS += DISABLE_NETWORK diff --git a/docs/source/framework/services/command-processing/index.rst b/docs/source/framework/services/command-processing/index.rst index 42eb48fcb8..e5ee8b3697 100644 --- a/docs/source/framework/services/command-processing/index.rst +++ b/docs/source/framework/services/command-processing/index.rst @@ -6,33 +6,22 @@ Command Executor Introduction ------------ -Command handler provides a common command line interface. CLI is available for the following remote access methods: +Command handler provides a common command line interface (CLI). Command line must be text. Commands should be separated with a single character. +CLI can be used with: - Serial -- Telnet - Websockets -By default, CLI is disabled. Enable CLI by calling "commandProcessing" on the appropriate access class object, e.g:: - - Serial.commandProcessing(true) +and all communication protocols that are exchanging text data. Commands can be added to and removed from the command handler. Each command will trigger a defined Delegate. A welcome message may be shown when a user connects and end of line character may be defined. An automatic "help" display is available. -Build Variables ---------------- - -.. envvar:: ENABLE_CMD_EXECUTOR - - Default: 1 (ON) - - This feature enables execution of certain commands by registering token handlers for text - received via serial, websocket or telnet connection. If this feature - is not used additional RAM/Flash can be obtained by setting - ``ENABLE_CMD_EXECUTOR=0``. This will save ~1KB RAM and ~3KB of flash - memory. - +For more examples take a look at the +:sample:`CommandProcessing_Debug` +and :sample:`HttpServer_WebSockets` +samples. API Documentation ----------------- diff --git a/samples/HttpServer_WebSockets/Kconfig b/samples/HttpServer_WebSockets/Kconfig new file mode 100644 index 0000000000..8744832f6b --- /dev/null +++ b/samples/HttpServer_WebSockets/Kconfig @@ -0,0 +1,11 @@ +# +# For a description of the syntax of this configuration file, +# see kconfig/kconfig-language.txt. +# +mainmenu "Sample Configuration" + + menu "Command Hanler" + config ENABLE_CMD_HANDLER + bool "Enable command handler functionality" + default y + endmenu \ No newline at end of file diff --git a/samples/HttpServer_WebSockets/app/application.cpp b/samples/HttpServer_WebSockets/app/application.cpp index 39e1155bb7..775038c0f3 100644 --- a/samples/HttpServer_WebSockets/app/application.cpp +++ b/samples/HttpServer_WebSockets/app/application.cpp @@ -2,7 +2,7 @@ #include #include "CUserData.h" -#if ENABLE_CMD_EXECUTOR +#if ENABLE_CMD_HANDLER #include CommandProcessing::Handler commandHandler; #endif @@ -81,12 +81,10 @@ void wsMessageReceived(WebsocketConnection& socket, const String& message) } } -#if ENABLE_CMD_EXECUTOR +#if ENABLE_CMD_HANDLER void wsCommandReceived(WebsocketConnection& socket, const String& message) { - String response = commandProcessing.processNow(message.c_str(), message.length()); - - String response = F("Echo: ") + message; + String response = commandHandler.processNow(message.c_str(), message.length()); socket.sendString(response); //Normally you would use dynamic cast but just be careful not to convert to wrong object type! @@ -140,7 +138,7 @@ void startWebServer() auto wsResource = new WebsocketResource(); wsResource->setConnectionHandler(wsConnected); wsResource->setMessageHandler(wsMessageReceived); -#if ENABLE_CMD_EXECUTOR +#if ENABLE_CMD_HANDLER wsResource->setMessageHandler(wsCommandReceived); #endif @@ -165,9 +163,9 @@ void init() { spiffs_mount(); // Mount file system, in order to work with files -#if ENABLE_CMD_EXECUTOR +#if ENABLE_CMD_HANDLER commandHandler.registerSystemCommands(); - commandHanledr.registerCommand(CommandProcessing::Command("shutdown", "Shutdown Server Command", "Application", processShutdownCommand)); + commandHandler.registerCommand(CommandProcessing::Command("shutdown", "Shutdown Server Command", "Application", processShutdownCommand)); #endif Serial.begin(SERIAL_BAUD_RATE); // 115200 by default diff --git a/samples/HttpServer_WebSockets/component.mk b/samples/HttpServer_WebSockets/component.mk index 372d718852..c69e94fac2 100644 --- a/samples/HttpServer_WebSockets/component.mk +++ b/samples/HttpServer_WebSockets/component.mk @@ -1 +1,6 @@ HWCONFIG := spiffs-2m + +COMPONENT_VARS += ENABLE_CMD_HANDLER +ENABLE_CMD_HANDLER ?= 1 + +APP_CFLAGS += -DENABLE_CMD_HANDLER=$(ENABLE_CMD_HANDLER) \ No newline at end of file From b418f62605a3a786d3ec2ff6c242157d0d77ab96 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Fri, 1 Dec 2023 16:42:53 +0100 Subject: [PATCH 06/17] CS fixes and removing typos. --- Sming/Core/HardwareSerial.h | 1 - Sming/Services/CommandProcessing/Command.h | 10 ++++---- Sming/Services/CommandProcessing/Handler.cpp | 24 +++++++++---------- Sming/Services/CommandProcessing/Handler.h | 7 ++---- Sming/Services/CommandProcessing/Utils.h | 1 - .../app/application.cpp | 4 ++-- .../HttpServer_WebSockets/app/application.cpp | 3 ++- 7 files changed, 21 insertions(+), 29 deletions(-) diff --git a/Sming/Core/HardwareSerial.h b/Sming/Core/HardwareSerial.h index 553a0b6a87..f913c549c1 100644 --- a/Sming/Core/HardwareSerial.h +++ b/Sming/Core/HardwareSerial.h @@ -455,7 +455,6 @@ class HardwareSerial : public ReadWriteStream int uartNr = UART_NO; TransmitCompleteDelegate transmitComplete = nullptr; ///< Callback for transmit completion StreamDataReceivedDelegate HWSDelegate = nullptr; ///< Callback for received data -// CommandExecutor* commandExecutor = nullptr; ///< Callback for command execution (received data) smg_uart_t* uart = nullptr; uart_options_t options = _BV(UART_OPT_TXWAIT); size_t txSize = DEFAULT_TX_BUFFER_SIZE; diff --git a/Sming/Services/CommandProcessing/Command.h b/Sming/Services/CommandProcessing/Command.h index b5fefd289a..9c40fee95f 100644 --- a/Sming/Services/CommandProcessing/Command.h +++ b/Sming/Services/CommandProcessing/Command.h @@ -15,7 +15,6 @@ namespace CommandProcessing { - /** @brief Command delegate class */ class Command { @@ -28,7 +27,6 @@ class Command */ using Callback = Delegate; - /** Instantiate a command delegate * @param reqName Command name - the text a user types to invoke the command * @param reqHelp Help message shown by CLI "help" command @@ -44,10 +42,10 @@ class Command { } - String name; ///< Command name - String description; ///< Command help - String group; ///< Command group - Callback callback; ///< Command Delegate (function that is called when command is invoked) + String name; ///< Command name + String description; ///< Command help + String group; ///< Command group + Callback callback; ///< Command Delegate (function that is called when command is invoked) }; } // namespace CommandProcessing diff --git a/Sming/Services/CommandProcessing/Handler.cpp b/Sming/Services/CommandProcessing/Handler.cpp index 09a0908b75..9213ae192f 100644 --- a/Sming/Services/CommandProcessing/Handler.cpp +++ b/Sming/Services/CommandProcessing/Handler.cpp @@ -13,9 +13,7 @@ namespace CommandProcessing { - -Handler::Handler() - : currentPrompt(F("Sming>")), currentWelcomeMessage(F("Welcome to the Sming CommandProcessing\r\n")) +Handler::Handler() : currentPrompt(F("Sming>")), currentWelcomeMessage(F("Welcome to the Sming CommandProcessing\r\n")) { } @@ -99,17 +97,17 @@ void Handler::registerSystemCommands() { String system = F("system"); registerCommand(Command(F("status"), F("Displays System Information"), system, - Command::Callback(&Handler::procesStatusCommand, this))); + Command::Callback(&Handler::procesStatusCommand, this))); registerCommand(Command(F("echo"), F("Displays command entered"), system, - Command::Callback(&Handler::procesEchoCommand, this))); + Command::Callback(&Handler::procesEchoCommand, this))); registerCommand(Command(F("help"), F("Displays all available commands"), system, - Command::Callback(&Handler::procesHelpCommand, this))); + Command::Callback(&Handler::procesHelpCommand, this))); registerCommand(Command(F("debugon"), F("Set Serial debug on"), system, - Command::Callback(&Handler::procesDebugOnCommand, this))); + Command::Callback(&Handler::procesDebugOnCommand, this))); registerCommand(Command(F("debugoff"), F("Set Serial debug off"), system, - Command::Callback(&Handler::procesDebugOffCommand, this))); + Command::Callback(&Handler::procesDebugOffCommand, this))); registerCommand(Command(F("command"), F("Use verbose/silent/prompt as command options"), system, - Command::Callback(&Handler::processCommandOptions, this))); + Command::Callback(&Handler::processCommandOptions, this))); } Command Handler::getCommandDelegate(const String& commandString) @@ -185,14 +183,14 @@ void Handler::procesEchoCommand(String commandLine, ReadWriteStream& outputStrea void Handler::procesDebugOnCommand(String commandLine, ReadWriteStream& outputStream) { -// Serial.systemDebugOutput(true); -// outputStream.println(_F("Debug set to : On")); + // Serial.systemDebugOutput(true); + // outputStream.println(_F("Debug set to : On")); } void Handler::procesDebugOffCommand(String commandLine, ReadWriteStream& outputStream) { -// Serial.systemDebugOutput(false); -// outputStream.println(_F("Debug set to : Off")); + // Serial.systemDebugOutput(false); + // outputStream.println(_F("Debug set to : Off")); } void Handler::processCommandOptions(String commandLine, ReadWriteStream& outputStream) diff --git a/Sming/Services/CommandProcessing/Handler.h b/Sming/Services/CommandProcessing/Handler.h index 937909d0d7..a55b4996aa 100644 --- a/Sming/Services/CommandProcessing/Handler.h +++ b/Sming/Services/CommandProcessing/Handler.h @@ -22,13 +22,11 @@ namespace CommandProcessing { - -constexpr size_t MAX_COMMANDSIZE=64; +constexpr size_t MAX_COMMANDSIZE = 64; /** @brief Verbose mode */ - /** @brief Command handler class */ class Handler { @@ -40,13 +38,12 @@ class Handler SILENT ///< Silent mode }; - /** * @brief Instantiate a CommandHandler */ Handler(); - Handler(ReadWriteStream* stream, bool owned = true): outputStream(stream), ownedStream(owned) + Handler(ReadWriteStream* stream, bool owned = true) : outputStream(stream), ownedStream(owned) { } diff --git a/Sming/Services/CommandProcessing/Utils.h b/Sming/Services/CommandProcessing/Utils.h index 297d25bdc1..d66b7c333e 100644 --- a/Sming/Services/CommandProcessing/Utils.h +++ b/Sming/Services/CommandProcessing/Utils.h @@ -5,7 +5,6 @@ namespace CommandProcessing { - void enable(Handler& commandHandler, HardwareSerial& serial) { commandHandler.setOutputStream(&serial, false); diff --git a/samples/CommandProcessing_Debug/app/application.cpp b/samples/CommandProcessing_Debug/app/application.cpp index ac84739ddc..2f54c28fe5 100644 --- a/samples/CommandProcessing_Debug/app/application.cpp +++ b/samples/CommandProcessing_Debug/app/application.cpp @@ -11,7 +11,6 @@ CommandProcessing::Handler commandHandler; namespace { - HttpServer server; FtpServer ftp; @@ -59,5 +58,6 @@ void init() CommandProcessing::enable(commandHandler, Serial); commandHandler.registerSystemCommands(); - commandHandler.registerCommand(CommandProcessing::Command("example", "Example Command", "Application", processExampleCommand)); + commandHandler.registerCommand( + CommandProcessing::Command("example", "Example Command", "Application", processExampleCommand)); } diff --git a/samples/HttpServer_WebSockets/app/application.cpp b/samples/HttpServer_WebSockets/app/application.cpp index 775038c0f3..a2d848e9a1 100644 --- a/samples/HttpServer_WebSockets/app/application.cpp +++ b/samples/HttpServer_WebSockets/app/application.cpp @@ -165,7 +165,8 @@ void init() #if ENABLE_CMD_HANDLER commandHandler.registerSystemCommands(); - commandHandler.registerCommand(CommandProcessing::Command("shutdown", "Shutdown Server Command", "Application", processShutdownCommand)); + commandHandler.registerCommand( + CommandProcessing::Command("shutdown", "Shutdown Server Command", "Application", processShutdownCommand)); #endif Serial.begin(SERIAL_BAUD_RATE); // 115200 by default From 78c013774538e1d557e4e1aac7219a92c5e31808 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Mon, 4 Dec 2023 13:05:29 +0100 Subject: [PATCH 07/17] Refactored the ArduCam application. --- Sming/Services/CommandProcessing/Handler.h | 2 +- samples/Arducam/app/ArduCamCommand.cpp | 136 ++++++++++----------- samples/Arducam/app/application.cpp | 34 +++--- samples/Arducam/include/ArduCamCommand.h | 23 ++-- 4 files changed, 95 insertions(+), 100 deletions(-) diff --git a/Sming/Services/CommandProcessing/Handler.h b/Sming/Services/CommandProcessing/Handler.h index a55b4996aa..b932ce3da5 100644 --- a/Sming/Services/CommandProcessing/Handler.h +++ b/Sming/Services/CommandProcessing/Handler.h @@ -47,7 +47,7 @@ class Handler { } - Handler(const Handler&) = delete; + Handler(const Handler& rhs) = delete; ~Handler() { diff --git a/samples/Arducam/app/ArduCamCommand.cpp b/samples/Arducam/app/ArduCamCommand.cpp index 961fb0a2e7..eefab3ae65 100644 --- a/samples/Arducam/app/ArduCamCommand.cpp +++ b/samples/Arducam/app/ArduCamCommand.cpp @@ -3,12 +3,10 @@ #include #include -ArduCamCommand::ArduCamCommand(ArduCAM* CAM) +ArduCamCommand::ArduCamCommand(ArduCAM& CAM, CommandProcessing::Handler& commandHandler) + : myCAM(CAM), commandHandler(&commandHandler), imgSize(OV2640_320x240), imgType(JPEG) { - debugf("ArduCamCommand Instantiating"); - myCAM = CAM; - imgSize = OV2640_320x240; - imgType = JPEG; + debug_d("ArduCamCommand Instantiating"); } ArduCamCommand::~ArduCamCommand() @@ -17,22 +15,20 @@ ArduCamCommand::~ArduCamCommand() void ArduCamCommand::initCommand() { - commandHandler.registerCommand(CommandDelegate("set", "ArduCAM config commands", "Application", - CommandFunctionDelegate(&ArduCamCommand::processSetCommands, this))); - // commandHandler.registerCommand( - // CommandDelegate("out", "ArduCAM output commands", "Application", - // CommandFunctionDelegate(&ArduCamCommand::processOutCommands,this))); + commandHandler->registerCommand( + CommandProcessing::Command("set", "ArduCAM config commands", "Application", + CommandProcessing::Command::Callback(&ArduCamCommand::processSetCommands, this))); } -void ArduCamCommand::showSettings(CommandOutput* commandOutput) +void ArduCamCommand::showSettings(ReadWriteStream& commandOutput) { // review settings - commandOutput->printf("ArduCam Settings:\n"); - commandOutput->printf(" img Type: [%s]\n", getImageType()); - commandOutput->printf(" img Size: [%s]\n", getImageSize()); + commandOutput.printf("ArduCam Settings:\n"); + commandOutput.printf(" img Type: [%s]\n", getImageType()); + commandOutput.printf(" img Size: [%s]\n", getImageSize()); }; -void ArduCamCommand::processSetCommands(String commandLine, CommandOutput* commandOutput) +void ArduCamCommand::processSetCommands(String commandLine, ReadWriteStream& commandOutput) { Vector commandToken; int numToken = splitString(commandLine, ' ', commandToken); @@ -43,8 +39,8 @@ void ArduCamCommand::processSetCommands(String commandLine, CommandOutput* comma } // handle command -> set else if(commandToken[1] == "help") { - *commandOutput << _F("set img [bmp|jpeg]") << endl; - *commandOutput << _F("set size [160|176|320|352|640|800|1024|1280|1600]") << endl; + commandOutput << _F("set img [bmp|jpeg]") << endl; + commandOutput << _F("set size [160|176|320|352|640|800|1024|1280|1600]") << endl; } // handle command -> set @@ -53,14 +49,14 @@ void ArduCamCommand::processSetCommands(String commandLine, CommandOutput* comma if(commandToken[2] == "bmp") { // TODO: set image size and init cam // settings->setImageType(BMP); - set_format(BMP); + setFormat(BMP); } else if(commandToken[2] == "jpg") { - set_format(JPEG); + setFormat(JPEG); } else { - *commandOutput << _F("invalid image format [") << commandToken[2] << ']' << endl; + commandOutput << _F("invalid image format [") << commandToken[2] << ']' << endl; } } else { - *commandOutput << _F("Syntax: set img [bmp|jpeg]") << endl; + commandOutput << _F("Syntax: set img [bmp|jpeg]") << endl; } showSettings(commandOutput); } @@ -70,130 +66,130 @@ void ArduCamCommand::processSetCommands(String commandLine, CommandOutput* comma if(numToken == 3) { if(commandToken[2] == "160") { imgSize = OV2640_160x120; - myCAM->OV2640_set_JPEG_size(OV2640_160x120); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_160x120); + setFormat(JPEG); } else if(commandToken[2] == "176") { imgSize = OV2640_176x144; - myCAM->OV2640_set_JPEG_size(OV2640_176x144); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_176x144); + setFormat(JPEG); } else if(commandToken[2] == "320") { imgSize = OV2640_320x240; - myCAM->OV2640_set_JPEG_size(OV2640_320x240); + myCAM.OV2640_set_JPEG_size(OV2640_320x240); } else if(commandToken[2] == "352") { imgSize = OV2640_352x288; - myCAM->OV2640_set_JPEG_size(OV2640_352x288); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_352x288); + setFormat(JPEG); } else if(commandToken[2] == "640") { imgSize = OV2640_640x480; - myCAM->OV2640_set_JPEG_size(OV2640_640x480); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_640x480); + setFormat(JPEG); } else if(commandToken[2] == "800") { imgSize = OV2640_800x600; - myCAM->OV2640_set_JPEG_size(OV2640_800x600); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_800x600); + setFormat(JPEG); } else if(commandToken[2] == "1024") { imgSize = OV2640_1024x768; - myCAM->OV2640_set_JPEG_size(OV2640_1024x768); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_1024x768); + setFormat(JPEG); } else if(commandToken[2] == "1280") { imgSize = OV2640_1280x1024; - myCAM->OV2640_set_JPEG_size(OV2640_1280x1024); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_1280x1024); + setFormat(JPEG); } else if(commandToken[2] == "1600") { imgSize = OV2640_1600x1200; - myCAM->OV2640_set_JPEG_size(OV2640_1600x1200); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_1600x1200); + setFormat(JPEG); } else { - *commandOutput << _F("invalid size definition[") << commandToken[2] << ']' << endl; + commandOutput << _F("invalid size definition[") << commandToken[2] << ']' << endl; } } else { - *commandOutput << _F("Syntax: set size [160|176|320|352|640|800|1024|1280|1600]") << endl; + commandOutput << _F("Syntax: set size [160|176|320|352|640|800|1024|1280|1600]") << endl; } showSettings(commandOutput); } } -void ArduCamCommand::set_size(String size) +void ArduCamCommand::setSize(String size) { if(size == "160x120") { imgSize = OV2640_160x120; - myCAM->OV2640_set_JPEG_size(OV2640_160x120); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_160x120); + setFormat(JPEG); } else if(size == "176x144") { imgSize = OV2640_176x144; - myCAM->OV2640_set_JPEG_size(OV2640_176x144); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_176x144); + setFormat(JPEG); } else if(size == "320x240") { imgSize = OV2640_320x240; - myCAM->OV2640_set_JPEG_size(OV2640_320x240); + myCAM.OV2640_set_JPEG_size(OV2640_320x240); } else if(size == "352x288") { imgSize = OV2640_352x288; - myCAM->OV2640_set_JPEG_size(OV2640_352x288); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_352x288); + setFormat(JPEG); } else if(size == "640x480") { imgSize = OV2640_640x480; - myCAM->OV2640_set_JPEG_size(OV2640_640x480); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_640x480); + setFormat(JPEG); } else if(size == "800x600") { imgSize = OV2640_800x600; - myCAM->OV2640_set_JPEG_size(OV2640_800x600); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_800x600); + setFormat(JPEG); } else if(size == "1024x768") { imgSize = OV2640_1024x768; - myCAM->OV2640_set_JPEG_size(OV2640_1024x768); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_1024x768); + setFormat(JPEG); } else if(size == "1280x1024") { imgSize = OV2640_1280x1024; - myCAM->OV2640_set_JPEG_size(OV2640_1280x1024); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_1280x1024); + setFormat(JPEG); } else if(size == "1600x1200") { imgSize = OV2640_1600x1200; - myCAM->OV2640_set_JPEG_size(OV2640_1600x1200); - set_format(JPEG); + myCAM.OV2640_set_JPEG_size(OV2640_1600x1200); + setFormat(JPEG); } else { debugf("ERROR: invalid size definition[%s]\r\n", size.c_str()); } } -void ArduCamCommand::set_type(String type) +void ArduCamCommand::setType(String type) { if(type == "BMP") { - myCAM->set_format(BMP); + myCAM.set_format(BMP); if(imgType != BMP) { // reset the cam - myCAM->InitCAM(); + myCAM.InitCAM(); imgType = BMP; imgSize = OV2640_320x240; } } else { - myCAM->set_format(JPEG); + myCAM.set_format(JPEG); // reset the cam if(imgType != JPEG) { // reset the cam - myCAM->InitCAM(); - myCAM->OV2640_set_JPEG_size(imgSize); + myCAM.InitCAM(); + myCAM.OV2640_set_JPEG_size(imgSize); imgType = JPEG; } } } -void ArduCamCommand::set_format(uint8 type) +void ArduCamCommand::setFormat(uint8 type) { if(type == BMP) { - myCAM->set_format(BMP); + myCAM.set_format(BMP); if(imgType != BMP) { // reset the cam - myCAM->InitCAM(); + myCAM.InitCAM(); imgType = BMP; imgSize = OV2640_320x240; } } else { - myCAM->set_format(JPEG); + myCAM.set_format(JPEG); // reset the cam if(imgType != JPEG) { // reset the cam - myCAM->InitCAM(); - myCAM->OV2640_set_JPEG_size(imgSize); + myCAM.InitCAM(); + myCAM.OV2640_set_JPEG_size(imgSize); imgType = JPEG; } } diff --git a/samples/Arducam/app/application.cpp b/samples/Arducam/app/application.cpp index 228601605b..f0ad2f6c0a 100644 --- a/samples/Arducam/app/application.cpp +++ b/samples/Arducam/app/application.cpp @@ -1,6 +1,5 @@ #include -#include -#include +#include //#include "CamSettings.h" #include @@ -37,14 +36,13 @@ #define CAM_CS 16 // this pins are free to change -TelnetServer telnet; HttpServer server; -HexDump hdump; +CommandProcessing::Handler commandHandler; +HexDump hdump; ArduCAM myCAM(OV2640, CAM_CS); - -ArduCamCommand arduCamCommand(&myCAM); +ArduCamCommand arduCamCommand(myCAM, commandHandler); SPISettings spiSettings(20000000, MSBFIRST, SPI_MODE0); @@ -56,6 +54,13 @@ void startApplicationCommand() arduCamCommand.initCommand(); } +bool processTelnetInput(TcpClient& client, char* data, int size) +{ + return client.sendString(commandHandler.processNow(data, size)); +} + +TcpServer telnetServer(processTelnetInput); + /* * initCam() * @@ -143,11 +148,11 @@ void onCamSetup(HttpRequest& request, HttpResponse& response) if(request.method == HTTP_POST) { type = request.getPostParameter("type"); debugf("set type %s", type.c_str()); - arduCamCommand.set_type(type); + arduCamCommand.setType(type); size = request.getPostParameter("size"); debugf("set size %s", size.c_str()); - arduCamCommand.set_size(size); + arduCamCommand.setSize(size); } response.sendString("OK"); @@ -234,9 +239,7 @@ void StartServers() Serial.println(WifiStation.getIP()); Serial.println(_F("==============================\r\n")); - telnet.listen(23); - telnet.enableDebug(true); - + telnetServer.listen(23); Serial.println(_F("\r\n=== TelnetServer SERVER STARTED ===")); Serial.println(_F("==============================\r\n")); } @@ -252,12 +255,11 @@ void init() spiffs_mount(); // Mount file system, in order to work with files Serial.begin(SERIAL_BAUD_RATE); // 115200 by default - Serial.systemDebugOutput(true); // Allow debug output to serial - - Debug.setDebug(Serial); - Serial.systemDebugOutput(true); // Enable debug output to serial - Serial.commandProcessing(true); + + // Process commands from serial + commandHandler.setVerboseMode(CommandProcessing::Handler::VerboseMode::VERBOSE); + CommandProcessing::enable(commandHandler, Serial); WifiStation.enable(true); WifiStation.config(WIFI_SSID, WIFI_PWD); diff --git a/samples/Arducam/include/ArduCamCommand.h b/samples/Arducam/include/ArduCamCommand.h index 80493ea1fc..7e680c47cd 100644 --- a/samples/Arducam/include/ArduCamCommand.h +++ b/samples/Arducam/include/ArduCamCommand.h @@ -3,36 +3,33 @@ * */ -#ifndef ARDUCAM_COMMAND_H_ -#define ARDUCAM_COMMAND_H_ +#pragma once #include "WString.h" -#include -#include +#include #include class ArduCamCommand { public: - ArduCamCommand(ArduCAM* CAM); + ArduCamCommand(ArduCAM& CAM, CommandProcessing::Handler& commandHandler); virtual ~ArduCamCommand(); void initCommand(); const char* getContentType(); - void set_size(String size); - void set_type(String type); + void setSize(String size); + void setType(String type); private: bool status = true; - ArduCAM* myCAM; + ArduCAM myCAM; + CommandProcessing::Handler* commandHandler{nullptr}; uint8 imgType; uint8 imgSize; - void processSetCommands(String commandLine, CommandOutput* commandOutput); + void processSetCommands(String commandLine, ReadWriteStream& commandOutput); - void set_format(uint8 type); - void showSettings(CommandOutput* commandOutput); + void setFormat(uint8 type); + void showSettings(ReadWriteStream& commandOutput); const char* getImageType(); const char* getImageSize(); }; - -#endif /* SMINGCORE_DEBUG_H_ */ From 1c82234dc3cc22946ec913f0721a8bdf32224b5d Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Mon, 4 Dec 2023 15:22:16 +0100 Subject: [PATCH 08/17] Moving Command Processing to Component. --- Sming/Components/CommandProcessing/README.rst | 62 ++++++++ .../Components/CommandProcessing/component.mk | 13 ++ .../Components/CommandProcessing/samples/.cs | 0 .../samples/Arducam/.clang-format | 100 +++++++++++++ .../samples/Arducam/.gdb_history | 0 .../samples}/Arducam/Makefile | 0 .../samples}/Arducam/README.rst | 0 .../samples}/Arducam/app/ArduCamCommand.cpp | 0 .../samples}/Arducam/app/application.cpp | 13 +- .../samples/Arducam/component.mk | 3 + .../samples}/Arducam/include/ArduCamCommand.h | 2 +- .../samples}/Arducam/web/build/Sming.png | Bin .../web/build/grids-responsive-min.css | 0 .../samples}/Arducam/web/build/index.html | 0 .../samples}/Arducam/web/build/layout.css | 0 .../samples}/Arducam/web/build/minified.js | 0 .../samples}/Arducam/web/build/pure-min.css | 0 .../samples/CommandLine/.clang-format | 100 +++++++++++++ .../samples/CommandLine}/Makefile | 0 .../samples/CommandLine/README.rst | 4 + .../samples/CommandLine}/app/application.cpp | 14 +- .../samples/CommandLine/component.mk | 2 + .../samples/CommandLine}/files/index.html | 0 .../CommandLine}/web/build/bootstrap.css.gz | Bin .../samples/CommandLine}/web/build/index.html | 0 .../CommandLine}/web/build/jquery.js.gz | Bin .../CommandLine}/web/dev/bootstrap.css | 0 .../samples/CommandLine}/web/dev/index.html | 0 .../samples/CommandLine}/web/dev/jquery.js | 0 .../samples/TelnetServer/.clang-format | 100 +++++++++++++ .../samples/TelnetServer}/Makefile | 0 .../samples/TelnetServer/README.rst | 4 + .../samples/TelnetServer/app/application.cpp | 69 +++++++++ .../samples/TelnetServer/component.mk | 1 + Sming/Components/CommandProcessing/src/.cs | 0 .../src}/CommandProcessing/Command.h | 0 .../src}/CommandProcessing/Handler.cpp | 8 +- .../src}/CommandProcessing/Handler.h | 8 +- .../src}/CommandProcessing/Utils.h | 0 Sming/component.mk | 3 - .../services/command-processing/index.rst | 5 +- samples/Arducam/component.mk | 3 - samples/CommandProcessing_Debug/README.rst | 4 - samples/CommandProcessing_Debug/component.mk | 1 - .../HttpServer_WebSockets/app/application.cpp | 2 +- samples/HttpServer_WebSockets/component.mk | 4 + samples/Telnet_Server/README.rst | 4 - samples/Telnet_Server/app/application.cpp | 134 ------------------ 48 files changed, 486 insertions(+), 177 deletions(-) create mode 100644 Sming/Components/CommandProcessing/README.rst create mode 100644 Sming/Components/CommandProcessing/component.mk create mode 100644 Sming/Components/CommandProcessing/samples/.cs create mode 100644 Sming/Components/CommandProcessing/samples/Arducam/.clang-format create mode 100644 Sming/Components/CommandProcessing/samples/Arducam/.gdb_history rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/Makefile (100%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/README.rst (100%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/app/ArduCamCommand.cpp (100%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/app/application.cpp (97%) create mode 100644 Sming/Components/CommandProcessing/samples/Arducam/component.mk rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/include/ArduCamCommand.h (93%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/web/build/Sming.png (100%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/web/build/grids-responsive-min.css (100%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/web/build/index.html (100%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/web/build/layout.css (100%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/web/build/minified.js (100%) rename {samples => Sming/Components/CommandProcessing/samples}/Arducam/web/build/pure-min.css (100%) create mode 100644 Sming/Components/CommandProcessing/samples/CommandLine/.clang-format rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/Makefile (100%) create mode 100644 Sming/Components/CommandProcessing/samples/CommandLine/README.rst rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/app/application.cpp (77%) create mode 100644 Sming/Components/CommandProcessing/samples/CommandLine/component.mk rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/files/index.html (100%) rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/web/build/bootstrap.css.gz (100%) rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/web/build/index.html (100%) rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/web/build/jquery.js.gz (100%) rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/web/dev/bootstrap.css (100%) rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/web/dev/index.html (100%) rename {samples/CommandProcessing_Debug => Sming/Components/CommandProcessing/samples/CommandLine}/web/dev/jquery.js (100%) create mode 100644 Sming/Components/CommandProcessing/samples/TelnetServer/.clang-format rename {samples/Telnet_Server => Sming/Components/CommandProcessing/samples/TelnetServer}/Makefile (100%) create mode 100644 Sming/Components/CommandProcessing/samples/TelnetServer/README.rst create mode 100644 Sming/Components/CommandProcessing/samples/TelnetServer/app/application.cpp create mode 100644 Sming/Components/CommandProcessing/samples/TelnetServer/component.mk create mode 100644 Sming/Components/CommandProcessing/src/.cs rename Sming/{Services => Components/CommandProcessing/src}/CommandProcessing/Command.h (100%) rename Sming/{Services => Components/CommandProcessing/src}/CommandProcessing/Handler.cpp (98%) rename Sming/{Services => Components/CommandProcessing/src}/CommandProcessing/Handler.h (97%) rename Sming/{Services => Components/CommandProcessing/src}/CommandProcessing/Utils.h (100%) delete mode 100644 samples/Arducam/component.mk delete mode 100644 samples/CommandProcessing_Debug/README.rst delete mode 100644 samples/CommandProcessing_Debug/component.mk delete mode 100644 samples/Telnet_Server/README.rst delete mode 100644 samples/Telnet_Server/app/application.cpp diff --git a/Sming/Components/CommandProcessing/README.rst b/Sming/Components/CommandProcessing/README.rst new file mode 100644 index 0000000000..366d617daf --- /dev/null +++ b/Sming/Components/CommandProcessing/README.rst @@ -0,0 +1,62 @@ +Command Processing +================== + +.. highlight:: c++ + +Introduction +------------ + +Command handler provides a common command line interface (CLI). Command line must be text. Commands should be separated with a single character. +CLI can be used with: + +- Serial +- Network (Websockets, Telnet) + +and all communication protocols that are exchanging text data. + +Commands can be added to and removed from the command handler. Each command will trigger a defined Delegate. + +A welcome message may be shown when a user connects and end-of-line (EOL) character may be defined. An automatic "help" display is available. + +For more examples take a look at the +:sample:`CommandProcessing`, +:sample:`TelnetServer` +and :sample:`HttpServer_WebSockets` +samples. + + +Using +----- + +1. Add these lines to your application componenent.mk file:: + + COMPONENT_DEPENDS += CommandProcessing + +2. Add these lines to your application:: + + #include + +3. Basic example:: + + #include + + CommandProcessing::Handler commandHandler; + + void processShutdownCommand(String commandLine, ReadWriteStream& commandOutput) + { + // ... + } + + void init() + { + commandHandler.registerSystemCommands(); + commandHandler.registerCommand(CommandProcessing::Command("shutdown", "Shutdown Server Command", "Application", processShutdownCommand)); + } + +API Documentation +----------------- + +.. doxygengroup:: commandhandler + :content-only: + :members: + diff --git a/Sming/Components/CommandProcessing/component.mk b/Sming/Components/CommandProcessing/component.mk new file mode 100644 index 0000000000..3abdb1f5cf --- /dev/null +++ b/Sming/Components/CommandProcessing/component.mk @@ -0,0 +1,13 @@ +COMPONENT_SRCDIRS := \ + src \ + $(call ListAllSubDirs,$(COMPONENT_PATH)/src) \ + +COMPONENT_INCDIRS := $(COMPONENT_SRCDIRS) + + +COMPONENT_DEPENDS := FlashString + +COMPONENT_DOXYGEN_INPUT := src + +COMPONENT_DOCFILES := \ + docs/* \ No newline at end of file diff --git a/Sming/Components/CommandProcessing/samples/.cs b/Sming/Components/CommandProcessing/samples/.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Sming/Components/CommandProcessing/samples/Arducam/.clang-format b/Sming/Components/CommandProcessing/samples/Arducam/.clang-format new file mode 100644 index 0000000000..517c4fb57a --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/Arducam/.clang-format @@ -0,0 +1,100 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AccessModifierOffset: -4 +# AlignAfterOpenBracket: Align +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +# AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: None +# AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true +# AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true +# AfterUnion: false +# BeforeCatch: false + BeforeElse: true + IndentBraces: false +# AfterExternBlock: true # available in v7 +# BreakBeforeBinaryOperators: None +BreakBeforeBraces: Linux +# BreakBeforeTernaryOperators: true +# BreakConstructorInitializersBeforeComma: false +ColumnLimit: 120 +# CommentPragmas: '^ IWYU pragma:' +# ConstructorInitializerAllOnOneLineOrOnePerLine: false +# ConstructorInitializerIndentWidth: 4 +# ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +# IncludeCategories: +# - Regex: '^"(llvm|llvm-c|clang|clang-c)/' +# Priority: 2 +# - Regex: '^(<|"(gtest|isl|json)/)' +# Priority: 3 +# - Regex: '.*' +# Priority: 1 +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +# MacroBlockBegin: '' +# MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# ObjCBlockIndentWidth: 2 +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: false +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +# SpaceBeforeInheritanceColon: false # available in v7 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Always +# RawStringFormats: # available in v7 +# - Language: Cpp +# Delimiters: +# - 'cc' +# - 'cpp' +# BasedOnStyle: llvm +# CanonicalDelimiter: 'cc' +# SpaceBeforeRangeBasedForLoopColon: false # available in v7 +... + diff --git a/Sming/Components/CommandProcessing/samples/Arducam/.gdb_history b/Sming/Components/CommandProcessing/samples/Arducam/.gdb_history new file mode 100644 index 0000000000..e69de29bb2 diff --git a/samples/Arducam/Makefile b/Sming/Components/CommandProcessing/samples/Arducam/Makefile similarity index 100% rename from samples/Arducam/Makefile rename to Sming/Components/CommandProcessing/samples/Arducam/Makefile diff --git a/samples/Arducam/README.rst b/Sming/Components/CommandProcessing/samples/Arducam/README.rst similarity index 100% rename from samples/Arducam/README.rst rename to Sming/Components/CommandProcessing/samples/Arducam/README.rst diff --git a/samples/Arducam/app/ArduCamCommand.cpp b/Sming/Components/CommandProcessing/samples/Arducam/app/ArduCamCommand.cpp similarity index 100% rename from samples/Arducam/app/ArduCamCommand.cpp rename to Sming/Components/CommandProcessing/samples/Arducam/app/ArduCamCommand.cpp diff --git a/samples/Arducam/app/application.cpp b/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp similarity index 97% rename from samples/Arducam/app/application.cpp rename to Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp index f0ad2f6c0a..98633f3c75 100644 --- a/samples/Arducam/app/application.cpp +++ b/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp @@ -1,5 +1,5 @@ #include -#include +#include //#include "CamSettings.h" #include @@ -36,6 +36,9 @@ #define CAM_CS 16 // this pins are free to change +namespace +{ + HttpServer server; CommandProcessing::Handler commandHandler; @@ -225,7 +228,7 @@ void onFavicon(HttpRequest& request, HttpResponse& response) * telnet can be used to configure camera settings * using ArdCammCommand handler */ -void StartServers() +void startServers() { server.listen(80); server.paths.set("/", onIndex); @@ -247,7 +250,9 @@ void StartServers() // Will be called when station is fully operational void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) { - StartServers(); + startServers(); +} + } void init() @@ -258,7 +263,7 @@ void init() Serial.systemDebugOutput(true); // Enable debug output to serial // Process commands from serial - commandHandler.setVerboseMode(CommandProcessing::Handler::VerboseMode::VERBOSE); + commandHandler.setVerbose(true); CommandProcessing::enable(commandHandler, Serial); WifiStation.enable(true); diff --git a/Sming/Components/CommandProcessing/samples/Arducam/component.mk b/Sming/Components/CommandProcessing/samples/Arducam/component.mk new file mode 100644 index 0000000000..cdae913e95 --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/Arducam/component.mk @@ -0,0 +1,3 @@ +ARDUINO_LIBRARIES := ArduCAM CommandProcessing +HWCONFIG = spiffs-2m +SPIFF_FILES = web/build diff --git a/samples/Arducam/include/ArduCamCommand.h b/Sming/Components/CommandProcessing/samples/Arducam/include/ArduCamCommand.h similarity index 93% rename from samples/Arducam/include/ArduCamCommand.h rename to Sming/Components/CommandProcessing/samples/Arducam/include/ArduCamCommand.h index 7e680c47cd..83f15001b7 100644 --- a/samples/Arducam/include/ArduCamCommand.h +++ b/Sming/Components/CommandProcessing/samples/Arducam/include/ArduCamCommand.h @@ -6,7 +6,7 @@ #pragma once #include "WString.h" -#include +#include #include class ArduCamCommand diff --git a/samples/Arducam/web/build/Sming.png b/Sming/Components/CommandProcessing/samples/Arducam/web/build/Sming.png similarity index 100% rename from samples/Arducam/web/build/Sming.png rename to Sming/Components/CommandProcessing/samples/Arducam/web/build/Sming.png diff --git a/samples/Arducam/web/build/grids-responsive-min.css b/Sming/Components/CommandProcessing/samples/Arducam/web/build/grids-responsive-min.css similarity index 100% rename from samples/Arducam/web/build/grids-responsive-min.css rename to Sming/Components/CommandProcessing/samples/Arducam/web/build/grids-responsive-min.css diff --git a/samples/Arducam/web/build/index.html b/Sming/Components/CommandProcessing/samples/Arducam/web/build/index.html similarity index 100% rename from samples/Arducam/web/build/index.html rename to Sming/Components/CommandProcessing/samples/Arducam/web/build/index.html diff --git a/samples/Arducam/web/build/layout.css b/Sming/Components/CommandProcessing/samples/Arducam/web/build/layout.css similarity index 100% rename from samples/Arducam/web/build/layout.css rename to Sming/Components/CommandProcessing/samples/Arducam/web/build/layout.css diff --git a/samples/Arducam/web/build/minified.js b/Sming/Components/CommandProcessing/samples/Arducam/web/build/minified.js similarity index 100% rename from samples/Arducam/web/build/minified.js rename to Sming/Components/CommandProcessing/samples/Arducam/web/build/minified.js diff --git a/samples/Arducam/web/build/pure-min.css b/Sming/Components/CommandProcessing/samples/Arducam/web/build/pure-min.css similarity index 100% rename from samples/Arducam/web/build/pure-min.css rename to Sming/Components/CommandProcessing/samples/Arducam/web/build/pure-min.css diff --git a/Sming/Components/CommandProcessing/samples/CommandLine/.clang-format b/Sming/Components/CommandProcessing/samples/CommandLine/.clang-format new file mode 100644 index 0000000000..517c4fb57a --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/CommandLine/.clang-format @@ -0,0 +1,100 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AccessModifierOffset: -4 +# AlignAfterOpenBracket: Align +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +# AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: None +# AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true +# AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true +# AfterUnion: false +# BeforeCatch: false + BeforeElse: true + IndentBraces: false +# AfterExternBlock: true # available in v7 +# BreakBeforeBinaryOperators: None +BreakBeforeBraces: Linux +# BreakBeforeTernaryOperators: true +# BreakConstructorInitializersBeforeComma: false +ColumnLimit: 120 +# CommentPragmas: '^ IWYU pragma:' +# ConstructorInitializerAllOnOneLineOrOnePerLine: false +# ConstructorInitializerIndentWidth: 4 +# ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +# IncludeCategories: +# - Regex: '^"(llvm|llvm-c|clang|clang-c)/' +# Priority: 2 +# - Regex: '^(<|"(gtest|isl|json)/)' +# Priority: 3 +# - Regex: '.*' +# Priority: 1 +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +# MacroBlockBegin: '' +# MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# ObjCBlockIndentWidth: 2 +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: false +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +# SpaceBeforeInheritanceColon: false # available in v7 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Always +# RawStringFormats: # available in v7 +# - Language: Cpp +# Delimiters: +# - 'cc' +# - 'cpp' +# BasedOnStyle: llvm +# CanonicalDelimiter: 'cc' +# SpaceBeforeRangeBasedForLoopColon: false # available in v7 +... + diff --git a/samples/CommandProcessing_Debug/Makefile b/Sming/Components/CommandProcessing/samples/CommandLine/Makefile similarity index 100% rename from samples/CommandProcessing_Debug/Makefile rename to Sming/Components/CommandProcessing/samples/CommandLine/Makefile diff --git a/Sming/Components/CommandProcessing/samples/CommandLine/README.rst b/Sming/Components/CommandProcessing/samples/CommandLine/README.rst new file mode 100644 index 0000000000..1c1b9048d8 --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/CommandLine/README.rst @@ -0,0 +1,4 @@ +CommandLine +=========== + +Demonstrates Sming's CommandProcessing capability via HTTP, FTP and serial interfaces. diff --git a/samples/CommandProcessing_Debug/app/application.cpp b/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp similarity index 77% rename from samples/CommandProcessing_Debug/app/application.cpp rename to Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp index 2f54c28fe5..68231f204f 100644 --- a/samples/CommandProcessing_Debug/app/application.cpp +++ b/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp @@ -1,20 +1,10 @@ #include -#include - -// If you want, you can define WiFi settings globally in Eclipse Environment Variables -#ifndef WIFI_SSID -#define WIFI_SSID "PleaseEnterSSID" // Put your SSID and password here -#define WIFI_PWD "PleaseEnterPass" -#endif +#include CommandProcessing::Handler commandHandler; namespace { -HttpServer server; -FtpServer ftp; - -Timer msgTimer; bool exampleStatus = true; @@ -52,7 +42,7 @@ void init() // Set verbosity Serial.systemDebugOutput(true); // Enable debug output to serial - commandHandler.setVerboseMode(CommandProcessing::Handler::VerboseMode::VERBOSE); + commandHandler.setVerbose(true); // Register Input/Output streams CommandProcessing::enable(commandHandler, Serial); diff --git a/Sming/Components/CommandProcessing/samples/CommandLine/component.mk b/Sming/Components/CommandProcessing/samples/CommandLine/component.mk new file mode 100644 index 0000000000..e9d588c3b4 --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/CommandLine/component.mk @@ -0,0 +1,2 @@ +COMPONENT_DEPENDS := CommandProcessing +HWCONFIG := spiffs-2m diff --git a/samples/CommandProcessing_Debug/files/index.html b/Sming/Components/CommandProcessing/samples/CommandLine/files/index.html similarity index 100% rename from samples/CommandProcessing_Debug/files/index.html rename to Sming/Components/CommandProcessing/samples/CommandLine/files/index.html diff --git a/samples/CommandProcessing_Debug/web/build/bootstrap.css.gz b/Sming/Components/CommandProcessing/samples/CommandLine/web/build/bootstrap.css.gz similarity index 100% rename from samples/CommandProcessing_Debug/web/build/bootstrap.css.gz rename to Sming/Components/CommandProcessing/samples/CommandLine/web/build/bootstrap.css.gz diff --git a/samples/CommandProcessing_Debug/web/build/index.html b/Sming/Components/CommandProcessing/samples/CommandLine/web/build/index.html similarity index 100% rename from samples/CommandProcessing_Debug/web/build/index.html rename to Sming/Components/CommandProcessing/samples/CommandLine/web/build/index.html diff --git a/samples/CommandProcessing_Debug/web/build/jquery.js.gz b/Sming/Components/CommandProcessing/samples/CommandLine/web/build/jquery.js.gz similarity index 100% rename from samples/CommandProcessing_Debug/web/build/jquery.js.gz rename to Sming/Components/CommandProcessing/samples/CommandLine/web/build/jquery.js.gz diff --git a/samples/CommandProcessing_Debug/web/dev/bootstrap.css b/Sming/Components/CommandProcessing/samples/CommandLine/web/dev/bootstrap.css similarity index 100% rename from samples/CommandProcessing_Debug/web/dev/bootstrap.css rename to Sming/Components/CommandProcessing/samples/CommandLine/web/dev/bootstrap.css diff --git a/samples/CommandProcessing_Debug/web/dev/index.html b/Sming/Components/CommandProcessing/samples/CommandLine/web/dev/index.html similarity index 100% rename from samples/CommandProcessing_Debug/web/dev/index.html rename to Sming/Components/CommandProcessing/samples/CommandLine/web/dev/index.html diff --git a/samples/CommandProcessing_Debug/web/dev/jquery.js b/Sming/Components/CommandProcessing/samples/CommandLine/web/dev/jquery.js similarity index 100% rename from samples/CommandProcessing_Debug/web/dev/jquery.js rename to Sming/Components/CommandProcessing/samples/CommandLine/web/dev/jquery.js diff --git a/Sming/Components/CommandProcessing/samples/TelnetServer/.clang-format b/Sming/Components/CommandProcessing/samples/TelnetServer/.clang-format new file mode 100644 index 0000000000..517c4fb57a --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/TelnetServer/.clang-format @@ -0,0 +1,100 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AccessModifierOffset: -4 +# AlignAfterOpenBracket: Align +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +# AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: None +# AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true +# AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true +# AfterUnion: false +# BeforeCatch: false + BeforeElse: true + IndentBraces: false +# AfterExternBlock: true # available in v7 +# BreakBeforeBinaryOperators: None +BreakBeforeBraces: Linux +# BreakBeforeTernaryOperators: true +# BreakConstructorInitializersBeforeComma: false +ColumnLimit: 120 +# CommentPragmas: '^ IWYU pragma:' +# ConstructorInitializerAllOnOneLineOrOnePerLine: false +# ConstructorInitializerIndentWidth: 4 +# ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +# IncludeCategories: +# - Regex: '^"(llvm|llvm-c|clang|clang-c)/' +# Priority: 2 +# - Regex: '^(<|"(gtest|isl|json)/)' +# Priority: 3 +# - Regex: '.*' +# Priority: 1 +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +# MacroBlockBegin: '' +# MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# ObjCBlockIndentWidth: 2 +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: false +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +# SpaceBeforeInheritanceColon: false # available in v7 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Always +# RawStringFormats: # available in v7 +# - Language: Cpp +# Delimiters: +# - 'cc' +# - 'cpp' +# BasedOnStyle: llvm +# CanonicalDelimiter: 'cc' +# SpaceBeforeRangeBasedForLoopColon: false # available in v7 +... + diff --git a/samples/Telnet_Server/Makefile b/Sming/Components/CommandProcessing/samples/TelnetServer/Makefile similarity index 100% rename from samples/Telnet_Server/Makefile rename to Sming/Components/CommandProcessing/samples/TelnetServer/Makefile diff --git a/Sming/Components/CommandProcessing/samples/TelnetServer/README.rst b/Sming/Components/CommandProcessing/samples/TelnetServer/README.rst new file mode 100644 index 0000000000..9852111d82 --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/TelnetServer/README.rst @@ -0,0 +1,4 @@ +Arducam +======= + +A demonstration application for controlling ArduCAM camera modules via web or telnet interface. diff --git a/Sming/Components/CommandProcessing/samples/TelnetServer/app/application.cpp b/Sming/Components/CommandProcessing/samples/TelnetServer/app/application.cpp new file mode 100644 index 0000000000..958990ea19 --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/TelnetServer/app/application.cpp @@ -0,0 +1,69 @@ +#include +#include + +// If you want, you can define WiFi settings globally in Eclipse Environment Variables +#ifndef WIFI_SSID +#define WIFI_SSID "PleaseEnterSSID" // Put your SSID and password here +#define WIFI_PWD "PleaseEnterPass" +#endif + +namespace +{ + +CommandProcessing::Handler commandHandler; + +bool processTelnetInput(TcpClient& client, char* data, int size) +{ + return client.sendString(commandHandler.processNow(data, size)); +} + +void processExampleCommand(String commandLine, ReadWriteStream& commandOutput) +{ + Vector commandToken; + int numToken = splitString(commandLine, ' ', commandToken); + + if(numToken == 1) { + commandOutput.println("example: No parameters provided"); + return; + } + + commandOutput.printf("example: %d parameters provided\r\n", numToken); +} + +void initCommands() +{ + commandHandler.registerSystemCommands(); + commandHandler.registerCommand(CommandProcessing::Command("example", "Example Command", "Application", processExampleCommand)); +} + +TcpServer telnetServer(processTelnetInput); + +// Will be called when station is fully operational +void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) +{ + telnetServer.listen(23); + Serial.println(_F("\r\n=== TelnetServer SERVER STARTED ===")); + Serial.println(_F("==============================\r\n")); +} + +} // namespace + + +void init() +{ + Serial.begin(SERIAL_BAUD_RATE); // 115200 by default + Serial.systemDebugOutput(true); // Enable debug output to serial + + // Process commands from serial + commandHandler.setVerbose(true); + CommandProcessing::enable(commandHandler, Serial); + + WifiStation.enable(true); + WifiStation.config(WIFI_SSID, WIFI_PWD); + WifiAccessPoint.enable(false); + + WifiEvents.onStationGotIP(gotIP); + + // set command handlers for cam + initCommands(); +} diff --git a/Sming/Components/CommandProcessing/samples/TelnetServer/component.mk b/Sming/Components/CommandProcessing/samples/TelnetServer/component.mk new file mode 100644 index 0000000000..f65c7f99ec --- /dev/null +++ b/Sming/Components/CommandProcessing/samples/TelnetServer/component.mk @@ -0,0 +1 @@ +COMPONENT_DEPENDS := CommandProcessing Network diff --git a/Sming/Components/CommandProcessing/src/.cs b/Sming/Components/CommandProcessing/src/.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Sming/Services/CommandProcessing/Command.h b/Sming/Components/CommandProcessing/src/CommandProcessing/Command.h similarity index 100% rename from Sming/Services/CommandProcessing/Command.h rename to Sming/Components/CommandProcessing/src/CommandProcessing/Command.h diff --git a/Sming/Services/CommandProcessing/Handler.cpp b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.cpp similarity index 98% rename from Sming/Services/CommandProcessing/Handler.cpp rename to Sming/Components/CommandProcessing/src/CommandProcessing/Handler.cpp index 9213ae192f..86e42b4f74 100644 --- a/Sming/Services/CommandProcessing/Handler.cpp +++ b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.cpp @@ -24,7 +24,7 @@ size_t Handler::process(char recvChar) if(recvChar == 27) // ESC -> delete current commandLine { commandBuf.clear(); - if(getVerboseMode() == VERBOSE) { + if(isVerbose()) { output.println(); output.print(getCommandPrompt()); } @@ -88,7 +88,7 @@ void Handler::processCommandLine(const String& cmdString) } } - if(getVerboseMode() == VERBOSE) { + if(isVerbose()) { outputStream->print(getCommandPrompt()); } } @@ -206,12 +206,12 @@ void Handler::processCommandOptions(String commandLine, ReadWriteStream& outputS printUsage = true; } if(commandToken[1] == _F("verbose")) { - setVerboseMode(VERBOSE); + setVerbose(true); outputStream.println(_F("Verbose mode selected")); break; } if(commandToken[1] == _F("silent")) { - setVerboseMode(SILENT); + setVerbose(false); outputStream.println(_F("Silent mode selected")); break; } diff --git a/Sming/Services/CommandProcessing/Handler.h b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h similarity index 97% rename from Sming/Services/CommandProcessing/Handler.h rename to Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h index b932ce3da5..ee361c93c3 100644 --- a/Sming/Services/CommandProcessing/Handler.h +++ b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h @@ -139,7 +139,7 @@ class Handler /** @brief Get the verbose mode * @retval VerboseMode Verbose mode */ - VerboseMode getVerboseMode() + bool isVerbose() { return verboseMode; } @@ -147,9 +147,9 @@ class Handler /** @brief Set the verbose mode * @param reqVerboseMode Verbose mode to set */ - void setVerboseMode(VerboseMode reqVerboseMode) + void setVerbose(bool mode) { - verboseMode = reqVerboseMode; + verboseMode = mode; } /** @brief Get the command line prompt @@ -216,7 +216,7 @@ class Handler #else char currentEOL{'\r'}; #endif - VerboseMode verboseMode{VERBOSE}; + bool verboseMode{false}; bool localEcho{true}; String currentWelcomeMessage; diff --git a/Sming/Services/CommandProcessing/Utils.h b/Sming/Components/CommandProcessing/src/CommandProcessing/Utils.h similarity index 100% rename from Sming/Services/CommandProcessing/Utils.h rename to Sming/Components/CommandProcessing/src/CommandProcessing/Utils.h diff --git a/Sming/component.mk b/Sming/component.mk index 095f887e65..e6d132a69e 100644 --- a/Sming/component.mk +++ b/Sming/component.mk @@ -31,9 +31,6 @@ COMPONENT_DOXYGEN_INPUT := \ Wiring \ System -# => CommandProcessing functionality -COMPONENT_SRCDIRS += Services/CommandProcessing - # RELINK_VARS += DISABLE_NETWORK DISABLE_NETWORK ?= 0 diff --git a/docs/source/framework/services/command-processing/index.rst b/docs/source/framework/services/command-processing/index.rst index e5ee8b3697..4b253eca04 100644 --- a/docs/source/framework/services/command-processing/index.rst +++ b/docs/source/framework/services/command-processing/index.rst @@ -10,7 +10,7 @@ Command handler provides a common command line interface (CLI). Command line mus CLI can be used with: - Serial -- Websockets +- Network (Websockets, Telnet) and all communication protocols that are exchanging text data. @@ -19,7 +19,8 @@ Commands can be added to and removed from the command handler. Each command will A welcome message may be shown when a user connects and end of line character may be defined. An automatic "help" display is available. For more examples take a look at the -:sample:`CommandProcessing_Debug` +:sample:`CommandProcessing`, +:sample:`TelnetServer` and :sample:`HttpServer_WebSockets` samples. diff --git a/samples/Arducam/component.mk b/samples/Arducam/component.mk deleted file mode 100644 index 76533c24f2..0000000000 --- a/samples/Arducam/component.mk +++ /dev/null @@ -1,3 +0,0 @@ -ARDUINO_LIBRARIES := ArduCAM -HWCONFIG = spiffs-2m -SPIFF_FILES = web/build diff --git a/samples/CommandProcessing_Debug/README.rst b/samples/CommandProcessing_Debug/README.rst deleted file mode 100644 index 6686ed6a04..0000000000 --- a/samples/CommandProcessing_Debug/README.rst +++ /dev/null @@ -1,4 +0,0 @@ -CommandProcessing Debug -======================= - -Demonstrates Sming's command handling capability via HTTP, FTP and Telnet interfaces. diff --git a/samples/CommandProcessing_Debug/component.mk b/samples/CommandProcessing_Debug/component.mk deleted file mode 100644 index 372d718852..0000000000 --- a/samples/CommandProcessing_Debug/component.mk +++ /dev/null @@ -1 +0,0 @@ -HWCONFIG := spiffs-2m diff --git a/samples/HttpServer_WebSockets/app/application.cpp b/samples/HttpServer_WebSockets/app/application.cpp index a2d848e9a1..193966e636 100644 --- a/samples/HttpServer_WebSockets/app/application.cpp +++ b/samples/HttpServer_WebSockets/app/application.cpp @@ -3,7 +3,7 @@ #include "CUserData.h" #if ENABLE_CMD_HANDLER -#include +#include CommandProcessing::Handler commandHandler; #endif diff --git a/samples/HttpServer_WebSockets/component.mk b/samples/HttpServer_WebSockets/component.mk index c69e94fac2..25bbd74f26 100644 --- a/samples/HttpServer_WebSockets/component.mk +++ b/samples/HttpServer_WebSockets/component.mk @@ -3,4 +3,8 @@ HWCONFIG := spiffs-2m COMPONENT_VARS += ENABLE_CMD_HANDLER ENABLE_CMD_HANDLER ?= 1 +ifeq ($(ENABLE_CMD_HANDLER), 1) + COMPONENT_DEPENDS += CommandProcessing +endif + APP_CFLAGS += -DENABLE_CMD_HANDLER=$(ENABLE_CMD_HANDLER) \ No newline at end of file diff --git a/samples/Telnet_Server/README.rst b/samples/Telnet_Server/README.rst deleted file mode 100644 index 10803fd21c..0000000000 --- a/samples/Telnet_Server/README.rst +++ /dev/null @@ -1,4 +0,0 @@ -Telnet Server -============= - -Demonstrates a simple Telnet server application. diff --git a/samples/Telnet_Server/app/application.cpp b/samples/Telnet_Server/app/application.cpp deleted file mode 100644 index dfa10d920c..0000000000 --- a/samples/Telnet_Server/app/application.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include "Services/CommandProcessing/CommandProcessingIncludes.h" -#include - -// If you want, you can define WiFi settings globally in Eclipse Environment Variables -#ifndef WIFI_SSID -#define WIFI_SSID "PleaseEnterSSID" // Put you SSID and Password here -#define WIFI_PWD "PleaseEnterPass" -#endif - -Timer memoryTimer; -int savedHeap = 0; - -void checkHeap() -{ - int currentHeap = system_get_free_heap_size(); - if(currentHeap != savedHeap) { - Debug << _F("Heap change, current = ") << currentHeap << endl; - savedHeap = currentHeap; - } -} - -void applicationCommand(String commandLine, CommandOutput* commandOutput) -{ - *commandOutput << _F("Hello from Telnet Example application") << endl - << _F("You entered : '") << commandLine << '\'' << endl - << _F("Tokenized commandLine is : ") << endl; - - Vector commandToken; - unsigned numToken = splitString(commandLine, ' ', commandToken); - for(unsigned i = 0; i < numToken; i++) { - *commandOutput << i << " : " << commandToken[i] << endl; - } -} - -void appheapCommand(String commandLine, CommandOutput* commandOutput) -{ - Vector commandToken; - int numToken = splitString(commandLine, ' ', commandToken); - if(numToken != 2) { - commandOutput->println(_F("Usage appheap on/off/now")); - } else if(commandToken[1] == "on") { - commandOutput->println(_F("Timer heap display started")); - savedHeap = 0; - memoryTimer.initializeMs(250, checkHeap).start(); - } else if(commandToken[1] == "off") { - commandOutput->println(_F("Timer heap display stopped")); - savedHeap = 0; - memoryTimer.stop(); - } else if(commandToken[1] == "now") { - *commandOutput << _F("Heap current free = ") << system_get_free_heap_size() << endl; - } else { - commandOutput->println(_F("Usage appheap on/off/now")); - } -} - -void tcpServerClientConnected(TcpClient* client) -{ - debugf("Application onClientCallback : %s\r\n", client->getRemoteIp().toString().c_str()); -} - -bool tcpServerClientReceive(TcpClient& client, char* data, int size) -{ - debugf("Application DataCallback : %s, %d bytes \r\n", client.getRemoteIp().toString().c_str(), size); - debugf("Data : %s", data); - client.sendString(F("sendString data\r\n"), false); - client.writeString(F("writeString data\r\n"), 0); - if(strcmp(data, "close") == 0) { - debugf("Closing client"); - client.close(); - }; - return true; -} - -void tcpServerClientComplete(TcpClient& client, bool successful) -{ - debugf("Application CompleteCallback : %s \r\n", client.getRemoteIp().toString().c_str()); -} - -TcpServer tcpServer(tcpServerClientConnected, tcpServerClientReceive, tcpServerClientComplete); -TelnetServer telnetServer; - -void startServers() -{ - tcpServer.listen(8023); - - Serial.println(_F("\r\n" - "=== TCP SERVER Port 8023 STARTED ===")); - Serial.println(WifiStation.getIP()); - Serial.println(_F("====================================\r\n")); - - telnetServer.listen(23); - - Serial.println(_F("\r\n" - "=== Telnet SERVER Port 23 STARTED ===")); - Serial.println(WifiStation.getIP()); - Serial.println(_F("=====================================\r\n")); - - commandHandler.registerCommand(CommandDelegate( - F("application"), F("This command is defined by the application\r\n"), F("testGroup"), applicationCommand)); -} - -void connectFail(const String& ssid, MacAddress bssid, WifiDisconnectReason reason) -{ - debugf("I'm NOT CONNECTED!"); -} - -void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) -{ - startServers(); -} - -void init() -{ - Serial.begin(SERIAL_BAUD_RATE); // 115200 by default - Serial.systemDebugOutput(true); // Enable debug output to serial - Serial.commandProcessing(true); - WifiStation.enable(true); - WifiStation.config(WIFI_SSID, WIFI_PWD); - WifiAccessPoint.enable(false); - - // Run our method when station was connected to AP - WifiEvents.onStationDisconnect(connectFail); - WifiEvents.onStationGotIP(gotIP); - Debug.setDebug(Serial); - Debug.initCommand(); - Debug.start(); - Debug.println(_F("This is the debug output")); - telnetServer.enableDebug(true); /* is default but here to show possibility */ - commandHandler.registerCommand(CommandDelegate(F("appheap"), F("Usage appheap on/off/now for heapdisplay\r\n"), - F("testGroup"), appheapCommand)); - memoryTimer.initializeMs(250, checkHeap).start(); -} From 0e9cfebd1d4a3b21e836cdca8fc62d7ee894f81f Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Mon, 4 Dec 2023 16:57:05 +0100 Subject: [PATCH 09/17] Get rid of Debug utility. --- .../ModbusMaster/samples/generic/app/application.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Sming/Libraries/ModbusMaster/samples/generic/app/application.cpp b/Sming/Libraries/ModbusMaster/samples/generic/app/application.cpp index 3d8d826030..ddefd7a32b 100644 --- a/Sming/Libraries/ModbusMaster/samples/generic/app/application.cpp +++ b/Sming/Libraries/ModbusMaster/samples/generic/app/application.cpp @@ -1,5 +1,4 @@ #include -#include #include #define MODBUS_COM_SPEED 115200 @@ -105,11 +104,6 @@ void init() SERIAL_TX_ONLY); // 115200 by default, GPIO1,GPIO3, see Serial.swap(), HardwareSerial debugComPort.systemDebugOutput(true); - Debug.setDebug(debugComPort); - Debug.initCommand(); - Debug.start(); - Debug.printf("This is the debug output\r\n"); - mbMaster.preTransmission(preTransmission); mbMaster.postTransmission(postTransmission); mbMaster.logReceive(mbLogReceive); From 81c68c0faa21f1e625954fa0de1522f51ce2b50b Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Mon, 4 Dec 2023 17:58:58 +0100 Subject: [PATCH 10/17] Get rid of Debug.h --- Sming/Libraries/CS5460/samples/generic/app/application.cpp | 2 -- Sming/Libraries/modbusino/samples/generic/app/application.cpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/Sming/Libraries/CS5460/samples/generic/app/application.cpp b/Sming/Libraries/CS5460/samples/generic/app/application.cpp index 3defc39983..ea0bec20a1 100644 --- a/Sming/Libraries/CS5460/samples/generic/app/application.cpp +++ b/Sming/Libraries/CS5460/samples/generic/app/application.cpp @@ -1,5 +1,4 @@ #include -#include #include CS5460 powerMeter(PIN_NDEFINED, PIN_NDEFINED, PIN_NDEFINED, PIN_NDEFINED); @@ -16,7 +15,6 @@ void init() Serial.begin(SERIAL_BAUD_RATE, SERIAL_8N1, SERIAL_FULL); // 115200 by default, GPIO1,GPIO3, see Serial.swap(), HardwareSerial Serial.systemDebugOutput(true); - Debug.setDebug(Serial); powerMeter.init(); powerMeter.setCurrentGain(190.84); //0.25 / shunt (0.00131) diff --git a/Sming/Libraries/modbusino/samples/generic/app/application.cpp b/Sming/Libraries/modbusino/samples/generic/app/application.cpp index 6405541879..0a0d3e9f41 100644 --- a/Sming/Libraries/modbusino/samples/generic/app/application.cpp +++ b/Sming/Libraries/modbusino/samples/generic/app/application.cpp @@ -1,5 +1,4 @@ #include -#include #include #define ARRLEN 3 @@ -17,8 +16,6 @@ void init() { debugComPort.begin(SERIAL_BAUD_RATE, SERIAL_8N1, SERIAL_TX_ONLY); debugComPort.systemDebugOutput(true); - Debug.setDebug(debugComPort); - Debug.start(); mbSlave.setup(SERIAL_BAUD_RATE); mbSlave.setRxCallback(mbPrint); } From 6aa0791642aef15a61145bf742c8e3816e20fb2f Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Tue, 5 Dec 2023 10:37:07 +0100 Subject: [PATCH 11/17] Remove deprecated enum. --- .../CommandProcessing/src/CommandProcessing/Handler.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h index ee361c93c3..243548ab92 100644 --- a/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h +++ b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h @@ -31,13 +31,6 @@ constexpr size_t MAX_COMMANDSIZE = 64; class Handler { public: - /** @brief Verbose mode - */ - enum VerboseMode { - VERBOSE, ///< Verbose mode - SILENT ///< Silent mode - }; - /** * @brief Instantiate a CommandHandler */ From 9c5519de83a6ee1b354a0dfbefc80f521ae9788e Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Tue, 5 Dec 2023 10:50:17 +0100 Subject: [PATCH 12/17] Patch for now the USB library. --- Sming/Libraries/USB.patch | 115 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 Sming/Libraries/USB.patch diff --git a/Sming/Libraries/USB.patch b/Sming/Libraries/USB.patch new file mode 100644 index 0000000000..03bf285c67 --- /dev/null +++ b/Sming/Libraries/USB.patch @@ -0,0 +1,115 @@ +diff --git a/component.mk b/component.mk +index 7f92e46..910e866 100644 +--- a/component.mk ++++ b/component.mk +@@ -27,6 +27,10 @@ CFG_TUSB_MCU := OPT_MCU_NONE + GLOBAL_CFLAGS += -DTUP_DCD_ENDPOINT_MAX=16 + endif + ++ ++COMPONENT_VARS += ENABLE_CMD_EXECUTOR ++ENABLE_CMD_EXECUTOR ?= 1 ++ + COMPONENT_VARS += USB_DEBUG_LEVEL + USB_DEBUG_LEVEL ?= 0 + +diff --git a/samples/Basic_Device/app/application.cpp b/samples/Basic_Device/app/application.cpp +index c294b25..81ec7bf 100644 +--- a/samples/Basic_Device/app/application.cpp ++++ b/samples/Basic_Device/app/application.cpp +@@ -231,7 +231,9 @@ void init() + timer.initializeMs<3000>(InterruptCallback([]() { + debug_i("Alive"); + // Un-comment this to demonstrated how to send keystrokes to the connected PC! +- // sendText(); ++#if CFG_TUD_HID ++ sendText(); ++#endif + })); + timer.start(); + } +diff --git a/src/USB/CDC/UsbSerial.cpp b/src/USB/CDC/UsbSerial.cpp +index b163726..29a27d6 100644 +--- a/src/USB/CDC/UsbSerial.cpp ++++ b/src/USB/CDC/UsbSerial.cpp +@@ -24,10 +24,6 @@ + #include "Platform/System.h" + #include + +-#if ENABLE_CMD_EXECUTOR +-#include +-#endif +- + namespace USB::CDC + { + UsbSerial::UsbSerial() +@@ -72,10 +68,10 @@ void UsbSerial::processEvents() + receiveCallback(*this, peek(), available()); + } + #if ENABLE_CMD_EXECUTOR +- if(commandExecutor) { ++ if(commandHandler) { + uint8_t ch; + while(readBytes(&ch, 1)) { +- commandExecutor->executorReceive(ch); ++ commandHandler->process(ch); + } + } + #endif +@@ -114,11 +110,11 @@ void UsbSerial::commandProcessing(bool reqEnable) + { + #if ENABLE_CMD_EXECUTOR + if(reqEnable) { +- if(!commandExecutor) { +- commandExecutor.reset(new CommandExecutor(this)); ++ if(commandHandler) { ++ CommandProcessing::enable(commandHandler, *this); + } + } else { +- commandExecutor.reset(); ++ commandHandler = nullptr; + } + #endif + } +diff --git a/src/USB/CDC/UsbSerial.h b/src/USB/CDC/UsbSerial.h +index daa3616..45f0216 100644 +--- a/src/USB/CDC/UsbSerial.h ++++ b/src/USB/CDC/UsbSerial.h +@@ -24,6 +24,10 @@ + #include + #include + ++#if ENABLE_CMD_EXECUTOR ++#include ++#endif ++ + namespace USB::CDC + { + enum class Event { +@@ -44,7 +48,14 @@ public: + using TransmitComplete = Delegate; + + UsbSerial(); +- ~UsbSerial(); ++ ++#if ENABLE_CMD_EXECUTOR ++ UsbSerial(CommandProcessing::CommandHandler& commandHandler): commandHandler(&commandHandler) ++ { ++ } ++#endif ++ ++ virtual ~UsbSerial(); + + /** + * @brief Sets receiving buffer size +@@ -131,7 +142,9 @@ private: + + DataReceived receiveCallback; + TransmitComplete transmitCompleteCallback; +- std::unique_ptr commandExecutor; ++#if ENABLE_CMD_EXECUTOR ++ CommandProcessing::CommandHandler* commandHandler{nullptr}; ++#endif + uint16_t status{0}; + BitSet eventMask; + }; From a8e649567cbc9b15da76ce933faf9080cebe5efd Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Tue, 5 Dec 2023 12:10:58 +0100 Subject: [PATCH 13/17] Apply CS fixes. --- .../CommandProcessing/samples/Arducam/app/application.cpp | 3 +-- .../samples/CommandLine/app/application.cpp | 1 - .../samples/TelnetServer/app/application.cpp | 5 ++--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp b/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp index 98633f3c75..9b8c7731d3 100644 --- a/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp +++ b/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp @@ -38,7 +38,6 @@ namespace { - HttpServer server; CommandProcessing::Handler commandHandler; @@ -253,7 +252,7 @@ void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) startServers(); } -} +} // namespace void init() { diff --git a/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp b/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp index 68231f204f..7c1b66d452 100644 --- a/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp +++ b/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp @@ -5,7 +5,6 @@ CommandProcessing::Handler commandHandler; namespace { - bool exampleStatus = true; // Example Command diff --git a/Sming/Components/CommandProcessing/samples/TelnetServer/app/application.cpp b/Sming/Components/CommandProcessing/samples/TelnetServer/app/application.cpp index 958990ea19..4c339ff3b7 100644 --- a/Sming/Components/CommandProcessing/samples/TelnetServer/app/application.cpp +++ b/Sming/Components/CommandProcessing/samples/TelnetServer/app/application.cpp @@ -9,7 +9,6 @@ namespace { - CommandProcessing::Handler commandHandler; bool processTelnetInput(TcpClient& client, char* data, int size) @@ -33,7 +32,8 @@ void processExampleCommand(String commandLine, ReadWriteStream& commandOutput) void initCommands() { commandHandler.registerSystemCommands(); - commandHandler.registerCommand(CommandProcessing::Command("example", "Example Command", "Application", processExampleCommand)); + commandHandler.registerCommand( + CommandProcessing::Command("example", "Example Command", "Application", processExampleCommand)); } TcpServer telnetServer(processTelnetInput); @@ -48,7 +48,6 @@ void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) } // namespace - void init() { Serial.begin(SERIAL_BAUD_RATE); // 115200 by default From b6719dfa3d9255167a38d244276252dde714af7b Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Tue, 5 Dec 2023 14:38:32 +0100 Subject: [PATCH 14/17] Removing accidental files. --- .../samples/Arducam/.clang-format | 100 ------------------ .../samples/Arducam/.gdb_history | 0 .../samples/CommandLine/.clang-format | 100 ------------------ .../samples/TelnetServer/.clang-format | 100 ------------------ Sming/Core/HardwareSerial.h | 2 - 5 files changed, 302 deletions(-) delete mode 100644 Sming/Components/CommandProcessing/samples/Arducam/.clang-format delete mode 100644 Sming/Components/CommandProcessing/samples/Arducam/.gdb_history delete mode 100644 Sming/Components/CommandProcessing/samples/CommandLine/.clang-format delete mode 100644 Sming/Components/CommandProcessing/samples/TelnetServer/.clang-format diff --git a/Sming/Components/CommandProcessing/samples/Arducam/.clang-format b/Sming/Components/CommandProcessing/samples/Arducam/.clang-format deleted file mode 100644 index 517c4fb57a..0000000000 --- a/Sming/Components/CommandProcessing/samples/Arducam/.clang-format +++ /dev/null @@ -1,100 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: LLVM -AccessModifierOffset: -4 -# AlignAfterOpenBracket: Align -# AlignConsecutiveAssignments: false -# AlignConsecutiveDeclarations: false -AlignEscapedNewlinesLeft: false -AlignOperands: true -AlignTrailingComments: true -# AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -# AlwaysBreakAfterDefinitionReturnType: None -# AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -# AlwaysBreakTemplateDeclarations: false -BinPackArguments: true -BinPackParameters: true -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: true -# AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: true -# AfterUnion: false -# BeforeCatch: false - BeforeElse: true - IndentBraces: false -# AfterExternBlock: true # available in v7 -# BreakBeforeBinaryOperators: None -BreakBeforeBraces: Linux -# BreakBeforeTernaryOperators: true -# BreakConstructorInitializersBeforeComma: false -ColumnLimit: 120 -# CommentPragmas: '^ IWYU pragma:' -# ConstructorInitializerAllOnOneLineOrOnePerLine: false -# ConstructorInitializerIndentWidth: 4 -# ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -# DerivePointerAlignment: false -# DisableFormat: false -# ExperimentalAutoDetectBinPacking: false -# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] -# IncludeCategories: -# - Regex: '^"(llvm|llvm-c|clang|clang-c)/' -# Priority: 2 -# - Regex: '^(<|"(gtest|isl|json)/)' -# Priority: 3 -# - Regex: '.*' -# Priority: 1 -IndentCaseLabels: false -IndentWidth: 4 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: false -# MacroBlockBegin: '' -# MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -# NamespaceIndentation: None -# ObjCBlockIndentWidth: 2 -# ObjCSpaceAfterProperty: false -# ObjCSpaceBeforeProtocolList: true -# PenaltyBreakBeforeFirstCallParameter: 19 -# PenaltyBreakComment: 300 -# PenaltyBreakFirstLessLess: 120 -# PenaltyBreakString: 1000 -# PenaltyExcessCharacter: 1000000 -# PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Left -ReflowComments: false -SortIncludes: false -SpaceAfterCStyleCast: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: Never -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -# SpaceBeforeInheritanceColon: false # available in v7 -SpacesInAngles: false -SpacesInContainerLiterals: false -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Always -# RawStringFormats: # available in v7 -# - Language: Cpp -# Delimiters: -# - 'cc' -# - 'cpp' -# BasedOnStyle: llvm -# CanonicalDelimiter: 'cc' -# SpaceBeforeRangeBasedForLoopColon: false # available in v7 -... - diff --git a/Sming/Components/CommandProcessing/samples/Arducam/.gdb_history b/Sming/Components/CommandProcessing/samples/Arducam/.gdb_history deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Sming/Components/CommandProcessing/samples/CommandLine/.clang-format b/Sming/Components/CommandProcessing/samples/CommandLine/.clang-format deleted file mode 100644 index 517c4fb57a..0000000000 --- a/Sming/Components/CommandProcessing/samples/CommandLine/.clang-format +++ /dev/null @@ -1,100 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: LLVM -AccessModifierOffset: -4 -# AlignAfterOpenBracket: Align -# AlignConsecutiveAssignments: false -# AlignConsecutiveDeclarations: false -AlignEscapedNewlinesLeft: false -AlignOperands: true -AlignTrailingComments: true -# AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -# AlwaysBreakAfterDefinitionReturnType: None -# AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -# AlwaysBreakTemplateDeclarations: false -BinPackArguments: true -BinPackParameters: true -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: true -# AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: true -# AfterUnion: false -# BeforeCatch: false - BeforeElse: true - IndentBraces: false -# AfterExternBlock: true # available in v7 -# BreakBeforeBinaryOperators: None -BreakBeforeBraces: Linux -# BreakBeforeTernaryOperators: true -# BreakConstructorInitializersBeforeComma: false -ColumnLimit: 120 -# CommentPragmas: '^ IWYU pragma:' -# ConstructorInitializerAllOnOneLineOrOnePerLine: false -# ConstructorInitializerIndentWidth: 4 -# ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -# DerivePointerAlignment: false -# DisableFormat: false -# ExperimentalAutoDetectBinPacking: false -# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] -# IncludeCategories: -# - Regex: '^"(llvm|llvm-c|clang|clang-c)/' -# Priority: 2 -# - Regex: '^(<|"(gtest|isl|json)/)' -# Priority: 3 -# - Regex: '.*' -# Priority: 1 -IndentCaseLabels: false -IndentWidth: 4 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: false -# MacroBlockBegin: '' -# MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -# NamespaceIndentation: None -# ObjCBlockIndentWidth: 2 -# ObjCSpaceAfterProperty: false -# ObjCSpaceBeforeProtocolList: true -# PenaltyBreakBeforeFirstCallParameter: 19 -# PenaltyBreakComment: 300 -# PenaltyBreakFirstLessLess: 120 -# PenaltyBreakString: 1000 -# PenaltyExcessCharacter: 1000000 -# PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Left -ReflowComments: false -SortIncludes: false -SpaceAfterCStyleCast: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: Never -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -# SpaceBeforeInheritanceColon: false # available in v7 -SpacesInAngles: false -SpacesInContainerLiterals: false -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Always -# RawStringFormats: # available in v7 -# - Language: Cpp -# Delimiters: -# - 'cc' -# - 'cpp' -# BasedOnStyle: llvm -# CanonicalDelimiter: 'cc' -# SpaceBeforeRangeBasedForLoopColon: false # available in v7 -... - diff --git a/Sming/Components/CommandProcessing/samples/TelnetServer/.clang-format b/Sming/Components/CommandProcessing/samples/TelnetServer/.clang-format deleted file mode 100644 index 517c4fb57a..0000000000 --- a/Sming/Components/CommandProcessing/samples/TelnetServer/.clang-format +++ /dev/null @@ -1,100 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: LLVM -AccessModifierOffset: -4 -# AlignAfterOpenBracket: Align -# AlignConsecutiveAssignments: false -# AlignConsecutiveDeclarations: false -AlignEscapedNewlinesLeft: false -AlignOperands: true -AlignTrailingComments: true -# AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -# AlwaysBreakAfterDefinitionReturnType: None -# AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -# AlwaysBreakTemplateDeclarations: false -BinPackArguments: true -BinPackParameters: true -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: true -# AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: true -# AfterUnion: false -# BeforeCatch: false - BeforeElse: true - IndentBraces: false -# AfterExternBlock: true # available in v7 -# BreakBeforeBinaryOperators: None -BreakBeforeBraces: Linux -# BreakBeforeTernaryOperators: true -# BreakConstructorInitializersBeforeComma: false -ColumnLimit: 120 -# CommentPragmas: '^ IWYU pragma:' -# ConstructorInitializerAllOnOneLineOrOnePerLine: false -# ConstructorInitializerIndentWidth: 4 -# ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -# DerivePointerAlignment: false -# DisableFormat: false -# ExperimentalAutoDetectBinPacking: false -# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] -# IncludeCategories: -# - Regex: '^"(llvm|llvm-c|clang|clang-c)/' -# Priority: 2 -# - Regex: '^(<|"(gtest|isl|json)/)' -# Priority: 3 -# - Regex: '.*' -# Priority: 1 -IndentCaseLabels: false -IndentWidth: 4 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: false -# MacroBlockBegin: '' -# MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -# NamespaceIndentation: None -# ObjCBlockIndentWidth: 2 -# ObjCSpaceAfterProperty: false -# ObjCSpaceBeforeProtocolList: true -# PenaltyBreakBeforeFirstCallParameter: 19 -# PenaltyBreakComment: 300 -# PenaltyBreakFirstLessLess: 120 -# PenaltyBreakString: 1000 -# PenaltyExcessCharacter: 1000000 -# PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Left -ReflowComments: false -SortIncludes: false -SpaceAfterCStyleCast: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: Never -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -# SpaceBeforeInheritanceColon: false # available in v7 -SpacesInAngles: false -SpacesInContainerLiterals: false -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Always -# RawStringFormats: # available in v7 -# - Language: Cpp -# Delimiters: -# - 'cc' -# - 'cpp' -# BasedOnStyle: llvm -# CanonicalDelimiter: 'cc' -# SpaceBeforeRangeBasedForLoopColon: false # available in v7 -... - diff --git a/Sming/Core/HardwareSerial.h b/Sming/Core/HardwareSerial.h index f913c549c1..c42dc8e27b 100644 --- a/Sming/Core/HardwareSerial.h +++ b/Sming/Core/HardwareSerial.h @@ -50,8 +50,6 @@ using StreamDataReceivedDelegate = Delegate; -//class CommandExecutor; - // clang-format off #define SERIAL_CONFIG_MAP(XX) \ XX(5N1) XX(6N1) XX(7N1) XX(8N1) XX(5N2) XX(6N2) XX(7N2) XX(8N2) XX(5E1) XX(6E1) XX(7E1) XX(8E1) \ From 7ba5fdf8a815b574b8fb466a80581cb8a14397f4 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Tue, 5 Dec 2023 15:39:01 +0100 Subject: [PATCH 15/17] Migration document. --- Sming/Components/CommandProcessing/README.rst | 2 +- .../samples/TelnetServer/README.rst | 6 +- docs/source/upgrading/4.7-5.1.rst | 63 +++++++++++++++++++ docs/source/upgrading/index.rst | 1 + 4 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 docs/source/upgrading/4.7-5.1.rst diff --git a/Sming/Components/CommandProcessing/README.rst b/Sming/Components/CommandProcessing/README.rst index 366d617daf..bdaad7ee9c 100644 --- a/Sming/Components/CommandProcessing/README.rst +++ b/Sming/Components/CommandProcessing/README.rst @@ -19,7 +19,7 @@ Commands can be added to and removed from the command handler. Each command will A welcome message may be shown when a user connects and end-of-line (EOL) character may be defined. An automatic "help" display is available. For more examples take a look at the -:sample:`CommandProcessing`, +:sample:`CommandLine`, :sample:`TelnetServer` and :sample:`HttpServer_WebSockets` samples. diff --git a/Sming/Components/CommandProcessing/samples/TelnetServer/README.rst b/Sming/Components/CommandProcessing/samples/TelnetServer/README.rst index 9852111d82..0a80ec3087 100644 --- a/Sming/Components/CommandProcessing/samples/TelnetServer/README.rst +++ b/Sming/Components/CommandProcessing/samples/TelnetServer/README.rst @@ -1,4 +1,4 @@ -Arducam -======= +TelnetServer +============ -A demonstration application for controlling ArduCAM camera modules via web or telnet interface. +A demonstration of a telnet server built using ``CommandProcessing``. diff --git a/docs/source/upgrading/4.7-5.1.rst b/docs/source/upgrading/4.7-5.1.rst new file mode 100644 index 0000000000..a1c8aa0c87 --- /dev/null +++ b/docs/source/upgrading/4.7-5.1.rst @@ -0,0 +1,63 @@ +From v4.7 to v5.1 +================= + +.. highlight:: c++ + +Command Processing +------------------ + +The CommandProcessing service has been refactored and moved to a component. +This means that the following classes ``CommandHandler``, ``CommandExecutor`` and ``CommandOutput`` are no longer available. + + +Enabling +~~~~~~~~ + +The command processing component used to be enabled by setting the directive ``ENABLE_CMD_EXECUTOR`` to 1 in your ``component.mk`` file or during compilation. +This has to be replaced with the directive ``COMPONENT_DEPENDS += CommandProcessing`` in your ``component.mk`` file. + + +Including Header Files +~~~~~~~~~~~~~~~~~~~~~~~ + +To include the command processing headers in your C/C++ application we used to do the following + +For example:: + + #include + +becomes:: + + #include + + +Usage +~~~~~ + +There is no longer a global instance of commandHandler. This means that you will need to create one yourself when you need it. +This can be done using the code below:: + + CommandProcessing::CommandHandler commandHandler; + +In order to register a command the old example code:: + + commandHandler.registerCommand( + CommandDelegate("example", "Example Command", "Application", processExampleCommand)); + +becomes:: + + commandHandler.registerCommand( + CommandProcessing::Command("example", "Example Command", "Application", processExampleCommand)); + +HardwareSerial no longer is dependent on CommandProcessing classes. And the following command will no longer work:: + + Serial.commandProcessing(true); + +The line above has to be replaced with:: + + CommandProcessing::enable(commandProcessing, Serial); + +See the modified samples +:sample:`CommandLine`, +:sample:`TelnetServer` +and :sample:`HttpServer_WebSockets` for details. diff --git a/docs/source/upgrading/index.rst b/docs/source/upgrading/index.rst index a53c6a896f..9677ddf287 100644 --- a/docs/source/upgrading/index.rst +++ b/docs/source/upgrading/index.rst @@ -7,6 +7,7 @@ For newer versions we have dedicated pages. .. toctree:: :maxdepth: 1 + 4.7-5.1 4.6-4.7 4.5-4.6 4.4-4.5 From 5ed7c3ce1a2d83942dc4bd04c9b8e88663d28b9a Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Tue, 5 Dec 2023 15:59:08 +0100 Subject: [PATCH 16/17] Remove old command processing documentation. --- .../services/command-processing/index.rst | 32 ------------------- docs/source/framework/services/index.rst | 1 - 2 files changed, 33 deletions(-) delete mode 100644 docs/source/framework/services/command-processing/index.rst diff --git a/docs/source/framework/services/command-processing/index.rst b/docs/source/framework/services/command-processing/index.rst deleted file mode 100644 index 4b253eca04..0000000000 --- a/docs/source/framework/services/command-processing/index.rst +++ /dev/null @@ -1,32 +0,0 @@ -Command Executor -================ - -.. highlight:: c++ - -Introduction ------------- - -Command handler provides a common command line interface (CLI). Command line must be text. Commands should be separated with a single character. -CLI can be used with: - -- Serial -- Network (Websockets, Telnet) - -and all communication protocols that are exchanging text data. - -Commands can be added to and removed from the command handler. Each command will trigger a defined Delegate. - -A welcome message may be shown when a user connects and end of line character may be defined. An automatic "help" display is available. - -For more examples take a look at the -:sample:`CommandProcessing`, -:sample:`TelnetServer` -and :sample:`HttpServer_WebSockets` -samples. - -API Documentation ------------------ - -.. doxygengroup:: commandhandler - :content-only: - :members: diff --git a/docs/source/framework/services/index.rst b/docs/source/framework/services/index.rst index 03fd153d9a..5a1a05d18f 100644 --- a/docs/source/framework/services/index.rst +++ b/docs/source/framework/services/index.rst @@ -4,5 +4,4 @@ Services .. toctree:: :maxdepth: 1 - command-processing/index profiling/index From 993c9b7b5d085d5ec33ae5e3b326bb488c5b7f17 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 11 Dec 2023 07:24:22 +0000 Subject: [PATCH 17/17] Review command processing restructure PR (#99) * Review suggestions * Remove command processing from USB library --------- Co-authored-by: mikee47 --- .../Components/CommandProcessing/component.mk | 3 - .../samples/Arducam/app/ArduCamCommand.cpp | 30 +---- .../samples/Arducam/app/application.cpp | 2 - .../samples/Arducam/include/ArduCamCommand.h | 4 +- .../samples/CommandLine/README.rst | 2 +- .../samples/CommandLine/app/application.cpp | 28 ++--- .../src/CommandProcessing/Handler.cpp | 62 ++++------ .../src/CommandProcessing/Handler.h | 8 +- .../src/CommandProcessing/Utils.cpp | 15 +++ .../src/CommandProcessing/Utils.h | 10 +- Sming/Core/HardwareSerial.h | 4 - Sming/Libraries/USB | 2 +- Sming/Libraries/USB.patch | 115 ------------------ 13 files changed, 66 insertions(+), 219 deletions(-) create mode 100644 Sming/Components/CommandProcessing/src/CommandProcessing/Utils.cpp delete mode 100644 Sming/Libraries/USB.patch diff --git a/Sming/Components/CommandProcessing/component.mk b/Sming/Components/CommandProcessing/component.mk index 3abdb1f5cf..71c9f17265 100644 --- a/Sming/Components/CommandProcessing/component.mk +++ b/Sming/Components/CommandProcessing/component.mk @@ -4,9 +4,6 @@ COMPONENT_SRCDIRS := \ COMPONENT_INCDIRS := $(COMPONENT_SRCDIRS) - -COMPONENT_DEPENDS := FlashString - COMPONENT_DOXYGEN_INPUT := src COMPONENT_DOCFILES := \ diff --git a/Sming/Components/CommandProcessing/samples/Arducam/app/ArduCamCommand.cpp b/Sming/Components/CommandProcessing/samples/Arducam/app/ArduCamCommand.cpp index eefab3ae65..c4bd3cddb3 100644 --- a/Sming/Components/CommandProcessing/samples/Arducam/app/ArduCamCommand.cpp +++ b/Sming/Components/CommandProcessing/samples/Arducam/app/ArduCamCommand.cpp @@ -23,9 +23,9 @@ void ArduCamCommand::initCommand() void ArduCamCommand::showSettings(ReadWriteStream& commandOutput) { // review settings - commandOutput.printf("ArduCam Settings:\n"); - commandOutput.printf(" img Type: [%s]\n", getImageType()); - commandOutput.printf(" img Size: [%s]\n", getImageSize()); + commandOutput << _F("ArduCam Settings:") << endl + << _F(" img Type: [") << getImageType() << ']' << endl + << _F(" img Size: [") << getImageSize() << ']' << endl; }; void ArduCamCommand::processSetCommands(String commandLine, ReadWriteStream& commandOutput) @@ -61,7 +61,6 @@ void ArduCamCommand::processSetCommands(String commandLine, ReadWriteStream& com showSettings(commandOutput); } - // handle command -> settings else if(commandToken[1] == "size") { if(numToken == 3) { if(commandToken[2] == "160") { @@ -109,7 +108,7 @@ void ArduCamCommand::processSetCommands(String commandLine, ReadWriteStream& com } } -void ArduCamCommand::setSize(String size) +void ArduCamCommand::setSize(const String& size) { if(size == "160x120") { imgSize = OV2640_160x120; @@ -151,26 +150,9 @@ void ArduCamCommand::setSize(String size) } } -void ArduCamCommand::setType(String type) +void ArduCamCommand::setType(const String& type) { - if(type == "BMP") { - myCAM.set_format(BMP); - if(imgType != BMP) { - // reset the cam - myCAM.InitCAM(); - imgType = BMP; - imgSize = OV2640_320x240; - } - } else { - myCAM.set_format(JPEG); - // reset the cam - if(imgType != JPEG) { - // reset the cam - myCAM.InitCAM(); - myCAM.OV2640_set_JPEG_size(imgSize); - imgType = JPEG; - } - } + setFormat(type == "BMP" ? BMP : JPEG); } void ArduCamCommand::setFormat(uint8 type) diff --git a/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp b/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp index 9b8c7731d3..fdc8ca2ac3 100644 --- a/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp +++ b/Sming/Components/CommandProcessing/samples/Arducam/app/application.cpp @@ -1,7 +1,6 @@ #include #include -//#include "CamSettings.h" #include #include @@ -42,7 +41,6 @@ HttpServer server; CommandProcessing::Handler commandHandler; -HexDump hdump; ArduCAM myCAM(OV2640, CAM_CS); ArduCamCommand arduCamCommand(myCAM, commandHandler); diff --git a/Sming/Components/CommandProcessing/samples/Arducam/include/ArduCamCommand.h b/Sming/Components/CommandProcessing/samples/Arducam/include/ArduCamCommand.h index 83f15001b7..e3f3ffc1c9 100644 --- a/Sming/Components/CommandProcessing/samples/Arducam/include/ArduCamCommand.h +++ b/Sming/Components/CommandProcessing/samples/Arducam/include/ArduCamCommand.h @@ -16,8 +16,8 @@ class ArduCamCommand virtual ~ArduCamCommand(); void initCommand(); const char* getContentType(); - void setSize(String size); - void setType(String type); + void setSize(const String& size); + void setType(const String& type); private: bool status = true; diff --git a/Sming/Components/CommandProcessing/samples/CommandLine/README.rst b/Sming/Components/CommandProcessing/samples/CommandLine/README.rst index 1c1b9048d8..29324f136a 100644 --- a/Sming/Components/CommandProcessing/samples/CommandLine/README.rst +++ b/Sming/Components/CommandProcessing/samples/CommandLine/README.rst @@ -1,4 +1,4 @@ CommandLine =========== -Demonstrates Sming's CommandProcessing capability via HTTP, FTP and serial interfaces. +Demonstrates Sming's CommandProcessing capability via serial interface. diff --git a/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp b/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp index 7c1b66d452..c91c116de1 100644 --- a/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp +++ b/Sming/Components/CommandProcessing/samples/CommandLine/app/application.cpp @@ -14,22 +14,22 @@ void processExampleCommand(String commandLine, ReadWriteStream& commandOutput) Vector commandToken; int numToken = splitString(commandLine, ' ', commandToken); + // First token is "example" if(numToken == 1) { - commandOutput.printf("Example Commands available : \r\n"); - commandOutput.printf("on : Set example status ON\r\n"); - commandOutput.printf("off : Set example status OFF\r\n"); - commandOutput.printf("status : Show example status\r\n"); + commandOutput << _F("Example Commands available :") << endl; + commandOutput << _F("on : Set example status ON") << endl; + commandOutput << _F("off : Set example status OFF") << endl; + commandOutput << _F("status : Show example status") << endl; + } else if(commandToken[1] == "on") { + exampleStatus = true; + commandOutput << _F("Status ON") << endl; + } else if(commandToken[1] == "off") { + exampleStatus = false; + commandOutput << _F("Status OFF") << endl; + } else if(commandToken[1] == "status") { + commandOutput << _F("Example Status is ") << (exampleStatus ? "ON" : "OFF") << endl; } else { - if(commandToken[1] == "on") { - exampleStatus = true; - commandOutput.printf("Status ON\r\n"); - } else if(commandToken[1] == "off") { - exampleStatus = false; - commandOutput.printf("Status OFF\r\n"); - } else if(commandToken[1] == "status") { - String tempString = exampleStatus ? "ON" : "OFF"; - commandOutput.printf("Example Status is %s\r\n", tempString.c_str()); - }; + commandOutput << _F("Bad command") << endl; } } diff --git a/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.cpp b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.cpp index 86e42b4f74..540d7b3d49 100644 --- a/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.cpp +++ b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.cpp @@ -96,18 +96,15 @@ void Handler::processCommandLine(const String& cmdString) void Handler::registerSystemCommands() { String system = F("system"); - registerCommand(Command(F("status"), F("Displays System Information"), system, - Command::Callback(&Handler::procesStatusCommand, this))); - registerCommand(Command(F("echo"), F("Displays command entered"), system, - Command::Callback(&Handler::procesEchoCommand, this))); - registerCommand(Command(F("help"), F("Displays all available commands"), system, - Command::Callback(&Handler::procesHelpCommand, this))); - registerCommand(Command(F("debugon"), F("Set Serial debug on"), system, - Command::Callback(&Handler::procesDebugOnCommand, this))); - registerCommand(Command(F("debugoff"), F("Set Serial debug off"), system, - Command::Callback(&Handler::procesDebugOffCommand, this))); - registerCommand(Command(F("command"), F("Use verbose/silent/prompt as command options"), system, - Command::Callback(&Handler::processCommandOptions, this))); + registerCommand({F("status"), F("Displays System Information"), system, {&Handler::procesStatusCommand, this}}); + registerCommand({F("echo"), F("Displays command entered"), system, {&Handler::procesEchoCommand, this}}); + registerCommand({F("help"), F("Displays all available commands"), system, {&Handler::procesHelpCommand, this}}); + registerCommand({F("debugon"), F("Set Serial debug on"), system, {&Handler::procesDebugOnCommand, this}}); + registerCommand({F("debugoff"), F("Set Serial debug off"), system, {&Handler::procesDebugOffCommand, this}}); + registerCommand({F("command"), + F("Use verbose/silent/prompt as command options"), + system, + {&Handler::processCommandOptions, this}}); } Command Handler::getCommandDelegate(const String& commandString) @@ -150,35 +147,24 @@ void Handler::procesHelpCommand(String commandLine, ReadWriteStream& outputStrea { debug_d("HelpCommand entered"); outputStream.println(_F("Commands available are :")); - for(unsigned idx = 0; idx < registeredCommands.count(); idx++) { - outputStream.print(registeredCommands.valueAt(idx).name); - outputStream.print(" | "); - outputStream.print(registeredCommands.valueAt(idx).group); - outputStream.print(" | "); - outputStream.print(registeredCommands.valueAt(idx).description); - outputStream.print("\r\n"); + for(auto cmd : registeredCommands) { + outputStream << cmd->name << " | " << cmd->group << " | " << cmd->description << endl; } } void Handler::procesStatusCommand(String commandLine, ReadWriteStream& outputStream) { debug_d("StatusCommand entered"); - outputStream.println(_F("Sming Framework Version : " SMING_VERSION)); - outputStream.print(_F("ESP SDK version : ")); - outputStream.print(system_get_sdk_version()); - outputStream.println(); - outputStream.print(_F("Time = ")); - outputStream.print(SystemClock.getSystemTimeString()); - outputStream.println(); - outputStream.printf(_F("System Start Reason : %d\r\n"), system_get_rst_info()->reason); + outputStream << _F("Sming Framework Version : " SMING_VERSION) << endl; + outputStream << _F("ESP SDK version : ") << system_get_sdk_version() << endl; + outputStream << _F("Time = ") << SystemClock.getSystemTimeString() << endl; + outputStream << _F("System Start Reason : ") << system_get_rst_info()->reason << endl; } void Handler::procesEchoCommand(String commandLine, ReadWriteStream& outputStream) { debug_d("HelpCommand entered"); - outputStream.print(_F("You entered : '")); - outputStream.print(commandLine); - outputStream.println('\''); + outputStream << _F("You entered : '") << commandLine << '\'' << endl; } void Handler::procesDebugOnCommand(String commandLine, ReadWriteStream& outputStream) @@ -223,23 +209,19 @@ void Handler::processCommandOptions(String commandLine, ReadWriteStream& outputS break; } setCommandPrompt(commandToken[2]); - outputStream.print(_F("Prompt set to : ")); - outputStream.print(commandToken[2]); - outputStream.println(); + outputStream << _F("Prompt set to : ") << commandToken[2] << endl; break; default: errorCommand = true; } if(errorCommand) { - outputStream.print(_F("Unknown command : ")); - outputStream.print(commandLine); - outputStream.println(); + outputStream << _F("Unknown command : ") << commandLine << endl; } if(printUsage) { - outputStream.println(_F("command usage : \r\n")); - outputStream.println(_F("command verbose : Set verbose mode")); - outputStream.println(_F("command silent : Set silent mode")); - outputStream.println(_F("command prompt 'new prompt' : Set prompt to use")); + outputStream << _F("command usage :") << endl + << _F("command verbose : Set verbose mode") << endl + << _F("command silent : Set silent mode") << endl + << _F("command prompt 'new prompt' : Set prompt to use") << endl; } } diff --git a/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h index 243548ab92..25a7f6569e 100644 --- a/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h +++ b/Sming/Components/CommandProcessing/src/CommandProcessing/Handler.h @@ -132,7 +132,7 @@ class Handler /** @brief Get the verbose mode * @retval VerboseMode Verbose mode */ - bool isVerbose() + bool isVerbose() const { return verboseMode; } @@ -150,7 +150,7 @@ class Handler * @note This is what is shown on the command line before user input * Default is Sming> */ - String getCommandPrompt() + const String& getCommandPrompt() const { return currentPrompt; } @@ -169,7 +169,7 @@ class Handler * @retval char The EOL character * @note Only supports one EOL, unlike Windows */ - char getCommandEOL() + char getCommandEOL() const { return currentEOL; } @@ -187,7 +187,7 @@ class Handler * @retval String The welcome message that is shown when clients connect * @note Only if verbose mode is enabled */ - String getCommandWelcomeMessage() + const String& getCommandWelcomeMessage() const { return currentWelcomeMessage; } diff --git a/Sming/Components/CommandProcessing/src/CommandProcessing/Utils.cpp b/Sming/Components/CommandProcessing/src/CommandProcessing/Utils.cpp new file mode 100644 index 0000000000..d044b19a52 --- /dev/null +++ b/Sming/Components/CommandProcessing/src/CommandProcessing/Utils.cpp @@ -0,0 +1,15 @@ +#include "Utils.h" + +namespace CommandProcessing +{ +void enable(Handler& commandHandler, HardwareSerial& serial) +{ + commandHandler.setOutputStream(&serial, false); + Serial.onDataReceived([&commandHandler](Stream& source, char arrivedChar, uint16_t availableCharsCount) { + while(availableCharsCount--) { + commandHandler.process(source.read()); + } + }); +} + +} // namespace CommandProcessing diff --git a/Sming/Components/CommandProcessing/src/CommandProcessing/Utils.h b/Sming/Components/CommandProcessing/src/CommandProcessing/Utils.h index d66b7c333e..7ffd2cbac4 100644 --- a/Sming/Components/CommandProcessing/src/CommandProcessing/Utils.h +++ b/Sming/Components/CommandProcessing/src/CommandProcessing/Utils.h @@ -5,14 +5,6 @@ namespace CommandProcessing { -void enable(Handler& commandHandler, HardwareSerial& serial) -{ - commandHandler.setOutputStream(&serial, false); - Serial.onDataReceived([&commandHandler](Stream& source, char arrivedChar, uint16_t availableCharsCount) { - while(availableCharsCount--) { - commandHandler.process(source.read()); - } - }); -} +void enable(Handler& commandHandler, HardwareSerial& serial); } // namespace CommandProcessing diff --git a/Sming/Core/HardwareSerial.h b/Sming/Core/HardwareSerial.h index c42dc8e27b..4416c338b2 100644 --- a/Sming/Core/HardwareSerial.h +++ b/Sming/Core/HardwareSerial.h @@ -114,10 +114,6 @@ class HardwareSerial : public ReadWriteStream { } - ~HardwareSerial() - { - } - void setPort(int uartPort) { end(); diff --git a/Sming/Libraries/USB b/Sming/Libraries/USB index 9055f1b444..ae08687c90 160000 --- a/Sming/Libraries/USB +++ b/Sming/Libraries/USB @@ -1 +1 @@ -Subproject commit 9055f1b4443d3bd5fbdd08147c74a6f0528a6a8a +Subproject commit ae08687c900582a94db86d4cff1c492317e52307 diff --git a/Sming/Libraries/USB.patch b/Sming/Libraries/USB.patch deleted file mode 100644 index 03bf285c67..0000000000 --- a/Sming/Libraries/USB.patch +++ /dev/null @@ -1,115 +0,0 @@ -diff --git a/component.mk b/component.mk -index 7f92e46..910e866 100644 ---- a/component.mk -+++ b/component.mk -@@ -27,6 +27,10 @@ CFG_TUSB_MCU := OPT_MCU_NONE - GLOBAL_CFLAGS += -DTUP_DCD_ENDPOINT_MAX=16 - endif - -+ -+COMPONENT_VARS += ENABLE_CMD_EXECUTOR -+ENABLE_CMD_EXECUTOR ?= 1 -+ - COMPONENT_VARS += USB_DEBUG_LEVEL - USB_DEBUG_LEVEL ?= 0 - -diff --git a/samples/Basic_Device/app/application.cpp b/samples/Basic_Device/app/application.cpp -index c294b25..81ec7bf 100644 ---- a/samples/Basic_Device/app/application.cpp -+++ b/samples/Basic_Device/app/application.cpp -@@ -231,7 +231,9 @@ void init() - timer.initializeMs<3000>(InterruptCallback([]() { - debug_i("Alive"); - // Un-comment this to demonstrated how to send keystrokes to the connected PC! -- // sendText(); -+#if CFG_TUD_HID -+ sendText(); -+#endif - })); - timer.start(); - } -diff --git a/src/USB/CDC/UsbSerial.cpp b/src/USB/CDC/UsbSerial.cpp -index b163726..29a27d6 100644 ---- a/src/USB/CDC/UsbSerial.cpp -+++ b/src/USB/CDC/UsbSerial.cpp -@@ -24,10 +24,6 @@ - #include "Platform/System.h" - #include - --#if ENABLE_CMD_EXECUTOR --#include --#endif -- - namespace USB::CDC - { - UsbSerial::UsbSerial() -@@ -72,10 +68,10 @@ void UsbSerial::processEvents() - receiveCallback(*this, peek(), available()); - } - #if ENABLE_CMD_EXECUTOR -- if(commandExecutor) { -+ if(commandHandler) { - uint8_t ch; - while(readBytes(&ch, 1)) { -- commandExecutor->executorReceive(ch); -+ commandHandler->process(ch); - } - } - #endif -@@ -114,11 +110,11 @@ void UsbSerial::commandProcessing(bool reqEnable) - { - #if ENABLE_CMD_EXECUTOR - if(reqEnable) { -- if(!commandExecutor) { -- commandExecutor.reset(new CommandExecutor(this)); -+ if(commandHandler) { -+ CommandProcessing::enable(commandHandler, *this); - } - } else { -- commandExecutor.reset(); -+ commandHandler = nullptr; - } - #endif - } -diff --git a/src/USB/CDC/UsbSerial.h b/src/USB/CDC/UsbSerial.h -index daa3616..45f0216 100644 ---- a/src/USB/CDC/UsbSerial.h -+++ b/src/USB/CDC/UsbSerial.h -@@ -24,6 +24,10 @@ - #include - #include - -+#if ENABLE_CMD_EXECUTOR -+#include -+#endif -+ - namespace USB::CDC - { - enum class Event { -@@ -44,7 +48,14 @@ public: - using TransmitComplete = Delegate; - - UsbSerial(); -- ~UsbSerial(); -+ -+#if ENABLE_CMD_EXECUTOR -+ UsbSerial(CommandProcessing::CommandHandler& commandHandler): commandHandler(&commandHandler) -+ { -+ } -+#endif -+ -+ virtual ~UsbSerial(); - - /** - * @brief Sets receiving buffer size -@@ -131,7 +142,9 @@ private: - - DataReceived receiveCallback; - TransmitComplete transmitCompleteCallback; -- std::unique_ptr commandExecutor; -+#if ENABLE_CMD_EXECUTOR -+ CommandProcessing::CommandHandler* commandHandler{nullptr}; -+#endif - uint16_t status{0}; - BitSet eventMask; - };