diff --git a/cli.cpp b/cli.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40257c97e970feb82d26accaa8efd41e8f1d16ad --- /dev/null +++ b/cli.cpp @@ -0,0 +1,131 @@ + +#include "cli.h" + +void Cli::resetNextWord () +{ + _currentWordIndex = -1; + _previousWordLength = 0; +} + +const char* Cli::findNextWord () +{ + if (_currentWordIndex >= 0) + // skip current word + while (_currentWordIndex < (int)_currentInput.length()) + { + if (_currentInput[_currentWordIndex] == 32) + break; + _currentWordIndex++; + } + else + _currentWordIndex = 0; + + size_t _previousWordLength = 0; + // skip spaces + while (_currentWordIndex < (int)_currentInput.length()) + { + if (_currentInput[_currentWordIndex] != 32) + break; + _currentWordIndex++; + _previousWordLength++; + } + + const char* ret = _currentWordIndex < (int)_currentInput.length()? _currentInput.c_str() + _currentWordIndex: nullptr; + //if (ret) + // Serial.printf("# found new start of word '%s'\n", ret); + return ret; +} + +void Cli::copyNextToTemp () +{ + findNextWord(); + int start = _currentWordIndex; + findNextWord(); + if (start < _currentWordIndex) + _temp = _currentInput.substring(start, _currentWordIndex); + else + _temp.clear(); +} + +bool Cli::kw (const __FlashStringHelper* keyWord, const char* input) +{ + // return true if input matches keyWord + auto len = strlen_P((PGM_P)keyWord); + return len && strncasecmp_P((PGM_P)keyWord, input, len) == 0; +} + +bool Cli::kw (const __FlashStringHelper* keyWord) +{ + return kw(keyWord, _currentInput.c_str() + _currentWordIndex); +} + +void Cli::syntax () +{ + syntax(_currentInput.c_str() + _currentWordIndex); +} + +void Cli::syntaxFull () +{ + syntax((const char*)nullptr); +} + +void Cli::syntax (const __FlashStringHelper* cmd) +{ + syntax((PGM_P)cmd); +} + +void Cli::syntax (const char* cmd) +{ + if (!cmd || kw(F("AT"), cmd)) Serial.printf("# CLI: AT -> OK\n"); + if (!cmd || kw(F("HELP"), cmd)) Serial.printf("# CLI: HELP [CMD]\n"); + if (!cmd || kw(F("RAT"), cmd)) Serial.printf("# CLI: RAT [ C | I ] [ <rate> [ <unit>(UM/MM/UH/MH) ] ]\n"); + if (!cmd || kw(F("VOL"), cmd)) Serial.printf("# CLI: VOL [ <vol> | <unit>(UL/ML) ]\n"); +} + +void Cli::loop (Stream& input) +{ + while (true) + { + if (!input.available()) + return; + int c = input.read(); + if (c == 13) + break; + if (c >= 32 && c <= 127) + _currentInput += (char)c; + } + + resetNextWord(); + + if (findNextWord()) + { + if (kw(F("AT"))) + { + Serial.printf("OK\n"); + } + else if (kw(F("HELP"))) + { + copyNextToTemp(); + if (_temp.length()) + syntax(_temp.c_str()); + else + syntaxFull(); + } + else if (kw(F("RAT"))) + { + copyNextToTemp(); + } + else if (kw(F("VOL"))) + { + } + else + { + Serial.printf("# CLI: invalid command '%s'\n", _currentInput.c_str() + _currentWordIndex); + } + } + + if (findNextWord()) + Serial.printf("# CLI: garbage at end of line: '%s'\n", _currentInput.c_str() + _currentWordIndex); + resetNextWord(); + _currentInput.clear(); +} diff --git a/cli.h b/cli.h new file mode 100644 index 0000000000000000000000000000000000000000..bdd52b4d84a421f5c39578a9e0536f520ef06a82 --- /dev/null +++ b/cli.h @@ -0,0 +1,39 @@ + +#pragma once + +#include <Arduino.h> + +#include "syringe.h" + +class Cli +{ +private: + + Syringe& syringe; + + String _currentInput; + String _temp; + int _currentWordIndex; + int _previousWordLength; + + void resetNextWord (); + const char* findNextWord (); + void copyNextToTemp (); + bool kw (const __FlashStringHelper* keyWord, const char* input); + bool kw (const __FlashStringHelper* keyWord); + void syntax (); + void syntaxFull (); + void syntax (const __FlashStringHelper* cmd); + void syntax (const char* cmd); + +public: + + Cli (Syringe& syringe, int bufferLen = 32): syringe(syringe) + { + _currentInput.reserve(bufferLen); + _temp.reserve(bufferLen); + resetNextWord(); + } + + void loop (Stream& input); +}; diff --git a/host_gui/make.sh b/host_gui/make.sh index 36a876f3e7075b901c9ecf221333d6a4c26563ec..5cbfdac1256461e83a4792e09e6a395101d54f8a 100755 --- a/host_gui/make.sh +++ b/host_gui/make.sh @@ -3,19 +3,16 @@ pwd=$(pwd) cd ${ESP8266ARDUINO}/tests/host make FORCE32=0 ssl -make -j 10 FORCE32=0 D=1 USERCFLAGS="-I ${ARDUINOLIB}/emuAsync/replacement" ULIBDIRS=${ARDUINOLIB}/emuAsync:${ARDUINOLIB}/ESPUI:${ARDUINOLIB}/ArduinoJson:${ARDUINOLIB}/arduinoWebSockets ${pwd}/../pousseseringue-arduino +make -j 10 FORCE32=0 USERCFLAGS="-I ${ARDUINOLIB}/emuAsync/replacement" ULIBDIRS=${ARDUINOLIB}/emuAsync:${ARDUINOLIB}/ESPUI:${ARDUINOLIB}/ArduinoJson:${ARDUINOLIB}/arduinoWebSockets ${pwd}/../pousseseringue-arduino -(./bin/pousseseringue-arduino/pousseseringue-arduino -b "$@" 2>&1 | grep -v '^http-server loop: conn=') & pid=$! -trap "kill ${pid}" EXIT INT +( + true '----------------------------------------' + true '----------- starting firefox -----------' + true '----------------------------------------' + sleep 5 + firefox -new-window http://localhost:9080 +) & -sleep 1 -true '----------------------------------------' -true '----------- starting firefox -----------' -true '----------------------------------------' -sleep 4 -firefox -new-window http://localhost:9080 +./bin/pousseseringue-arduino/pousseseringue-arduino "$@" -while true; do - true '^C to quit' - read junk -done +stty sane diff --git a/pousseseringue-arduino.cpp b/pousseseringue-arduino.cpp index ed4a1eb9823fe17b28db09610cd6782a1272e4ec..3ca8f5db320778b1d626ea2fcbf5a2506f5e9738 100644 --- a/pousseseringue-arduino.cpp +++ b/pousseseringue-arduino.cpp @@ -56,6 +56,7 @@ #endif // !CORE_MOCK #include "Debouncer.h" // local, debouncer, short counter, long detector #include "syringe.h" +#include "cli.h" #include "common.h" @@ -93,6 +94,7 @@ int rpming = 0; // -1, 0 or +1 // single syringe global instance Syringe syringe; +Cli console(syringe); const char* oledMode () { @@ -320,7 +322,9 @@ void loop() } stepper.run(); #endif // !CORE_MOCK + + console.loop(Serial); webLoop(); - dnsServer.processNextRequest(); // AP redirection + dnsServer.processNextRequest(); // access-point redirection } diff --git a/pousseseringue-arduino.ino b/pousseseringue-arduino.ino index e70951cbf584db88608da47144d6c847bb6d8936..8629455d7b9b3a8250b3441bdd4c7442fc2884e4 100644 --- a/pousseseringue-arduino.ino +++ b/pousseseringue-arduino.ino @@ -7,4 +7,5 @@ #include "web.cpp" #include "syringe.cpp" #include "motor.cpp" + #include "cli.cpp" #endif // !CORE_MOCK diff --git a/syringe.cpp b/syringe.cpp index 7a831b35bb0534fb3399e8761f9798699438bffd..429389d4c216888c695d9c58f3dffc441b155aa6 100644 --- a/syringe.cpp +++ b/syringe.cpp @@ -13,7 +13,7 @@ float Syringe::volumeToDistance(float volume) return distance; } -void Syringe::configureSyringe(Syringe_configuration_t config) +void Syringe::configureSyringe(const Syringe_configuration_t& config) { this->current_configuration = config; this->piston_surface = M_PI * pow(config.diameter,2) / 4.; diff --git a/syringe.h b/syringe.h index 49dea578113e5d65ed020218cd2830f5d604ddd5..caca6dd1f862c2594b9be6a571f8710417d7f49c 100644 --- a/syringe.h +++ b/syringe.h @@ -22,7 +22,7 @@ private: public: // Configuration - void configureSyringe(Syringe_configuration_t config); + void configureSyringe(const Syringe_configuration_t& config); void setInitialContent(float initial_volume); // Actions