Skip to content
Snippets Groups Projects
cli.cpp 17.6 KiB
Newer Older
David Gauchard's avatar
David Gauchard committed
#include "fs.h"

void Cli::resetNextWord ()
{
    _currentWordIndex = -1;
}

const char* Cli::findNextWord ()
{
    if (_currentWordIndex >= 0)
        // skip current word
        while (_currentWordIndex < (int)_currentInput.length())
        {
            if (_currentInput[_currentWordIndex] == 32)
                break;
            _currentWordIndex++;
        }
    else
        _currentWordIndex = 0;
    // skip spaces
    while (_currentWordIndex < (int)_currentInput.length())
    {
        if (_currentInput[_currentWordIndex] != 32)
            break;
        _currentWordIndex++;
    }
    const char* ret = _currentWordIndex < (int)_currentInput.length()? _currentInput.c_str() + _currentWordIndex: nullptr;
David Gauchard's avatar
David Gauchard committed
    for (_currentWordEndIndex = _currentWordIndex; _currentInput.c_str()[_currentWordEndIndex] > 32; _currentWordEndIndex++);
David Gauchard's avatar
David Gauchard committed
#if 0
    if (ret)
        Serial.printf("# found new start of word '%s'\n", ret);
    else
        Serial.printf("# no more word?\n");
#endif
    return ret;
}

void Cli::copyNextToTemp ()
{
David Gauchard's avatar
David Gauchard committed
    if (!findNextWord())
    {
        _temp = emptyString;
        return;
    }
    int start = _currentWordIndex;
David Gauchard's avatar
David Gauchard committed
    int end = _currentWordEndIndex;
    if (start < end)
        _temp = _currentInput.substring(start, end);
    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 (const __FlashStringHelper* cmd)
{
    syntax((PGM_P)cmd);
}

void Cli::syntax (const char* cmd)
{
if (!cmd || kw(F("AT"), cmd))   Serial.printf("%sAT -> OK\n", _msgHeader);
David Gauchard's avatar
David Gauchard committed
    if (!cmd || kw(F("HELP"), cmd)) Serial.printf("%sHELP [CMD]\n", _msgHeader);
    if (!cmd || kw(F("RAT"), cmd))  Serial.printf("%sRAT [ C <rate> [<unit>] ] - set or show rate ([UM]/MM/UH/MH)\n", _msgHeader);
Malaurie Bernard's avatar
Malaurie Bernard committed
    if (!cmd || kw(F("VOL"), cmd))  Serial.printf("%sVOL [ <vol> | <unit> ]    - set the volume to exchange in mL\n", _msgHeader);
    if (!cmd || kw(F("RVOL"), cmd)) Serial.printf("%sRVOL  <vol>               - set relative volume to exchange in mL\n", _msgHeader);
    if (!cmd || kw(F("MM"),  cmd))  Serial.printf("%sMM  [ <len> ]             - set final position in mm\n", _msgHeader);
    if (!cmd || kw(F("RMM"),  cmd)) Serial.printf("%sRMM   <len>               - set relative distance to browse in mm\n", _msgHeader);
    if (!cmd || kw(F("DIA"), cmd))  Serial.printf("%sDIA [ <dia> ]             - set or show inside syringe diameter in mm\n", _msgHeader);
David Gauchard's avatar
David Gauchard committed
    if (!cmd || kw(F("ACC"), cmd))  Serial.printf("%sACC [ <mm/s/s> ]          - set or show acceletaration (mm/s/s) (0<=>oo)\n", _msgHeader);
    if (!cmd || kw(F("RVM"), cmd))  Serial.printf("%sRVM [ <M4|M5> ]           - set or show auger size\n", _msgHeader);
    if (!cmd || kw(F("DIR"), cmd))  Serial.printf("%sDIR [ INF | WDR ]         - set or show direction (INFuse / WithDRaw)\n", _msgHeader);
    if (!cmd || kw(F("FIL"), cmd))  Serial.printf("%sFIL                       - start filling using direction at rate for volume\n", _msgHeader);
David Gauchard's avatar
David Gauchard committed
    if (!cmd || kw(F("STP"), cmd))  Serial.printf("%sSTP                       - stop\n", _msgHeader);
    if (!cmd || kw(F("DIS"), cmd))  Serial.printf("%sDIS                       - show volume dispensed\n", _msgHeader);
    if (!cmd || kw(F("ZERO"), cmd)) Serial.printf("%sZERO                      - go to stopper\n", _msgHeader);
    if (!cmd || kw(F("SET0"), cmd)) Serial.printf("%sSET0                      - change ZERO to current position\n", _msgHeader);
    if (!cmd || kw(F("NLCK"), cmd)) Serial.printf("%sNLCK                      - try to get out from stopper\n", _msgHeader);
    if (!cmd || kw(F("CLKW"), cmd)) Serial.printf("%sCLKW [0 | 1]              - 1: push = rotate clockwise\n", _msgHeader);
    if (!cmd || kw(F("CONF"), cmd)) Serial.printf("%sCONF                      - show configuration\n", _msgHeader);
    if (!cmd || kw(F("FS-LS"), cmd)) Serial.printf("%sFS-LS                    - show all the files\n", _msgHeader);
    if (!cmd || kw(F("FS-CAT"), cmd)) Serial.printf("%sFS-CAT                  - print a file\n", _msgHeader);
    if (!cmd || kw(F("FS-SAVE"), cmd)) Serial.printf("%sFS-SAVE                - save the files\n", _msgHeader);
    if (!cmd || kw(F("FS-LOAD"), cmd)) Serial.printf("%sFS-LOAD                - load the files\n", _msgHeader);
David Gauchard's avatar
David Gauchard committed
}

void Cli::answer (bool ok, const String& error_message) const
{
David Gauchard's avatar
David Gauchard committed
    Serial.printf("%s%s", _msgHeader, ok? "OK": "ERROR");
David Gauchard's avatar
David Gauchard committed
    if (!ok && error_message.length())
        Serial.printf(" (%s)", error_message.c_str());
    Serial.printf("\n");
void Cli::check_emergency ()
David Gauchard's avatar
David Gauchard committed
        Serial.printf("%sin EMERGENCY state, try NLCK command\n", _msgHeader);
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;
David Gauchard's avatar
David Gauchard committed
        // ignore other chars
    if (findNextWord())
    {
        if (kw(F("AT")))
        {
David Gauchard's avatar
David Gauchard committed
            answer(true);
        }
        else if (kw(F("HELP")))
        {
            copyNextToTemp();
            if (_temp.length())
                syntax(_temp.c_str());
            else
David Gauchard's avatar
David Gauchard committed
                syntax();
        else if (kw(F("RAT")))   //*******************RATE*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            if (_temp.equalsIgnoreCase(F("C")))
            {
                copyNextToTemp();
Malaurie Bernard's avatar
Malaurie Bernard committed
                syringe_filled.set_exchange_throughput_uL_per_min(atof(_temp.c_str()));
                copyNextToTemp();
                if (_temp.equalsIgnoreCase(F("us")))
                    syringe_filled.set_exchange_throughput_uL_per_min(syringe_filled.get_exchange_throughput_uL_per_min()/60);
                else if (_temp.equalsIgnoreCase(F("ms")))
                    syringe_filled.set_exchange_throughput_uL_per_min(syringe_filled.get_exchange_throughput_uL_per_min()*1000/60);
                else if (_temp.equalsIgnoreCase(F("um")))
                    ;
                else if (_temp.equalsIgnoreCase(F("mm")))
                    syringe_filled.set_exchange_throughput_uL_per_min(syringe_filled.get_exchange_throughput_uL_per_min()*1000);
                else if (_temp.equalsIgnoreCase(F("uh")))
                    syringe_filled.set_exchange_throughput_uL_per_min(syringe_filled.get_exchange_throughput_uL_per_min()/60);
                else if (_temp.equalsIgnoreCase(F("mh")))
                    syringe_filled.set_exchange_throughput_uL_per_min(syringe_filled.get_exchange_throughput_uL_per_min()*1000/60);
                else
                    syringe_filled.set_exchange_throughput_uL_per_min(-1);

                answer(syringe_filled.check_configuration(), F("invalid 'RAT C rate uL'"));
David Gauchard's avatar
David Gauchard committed
            else if (_temp.length() > 0)
David Gauchard's avatar
David Gauchard committed
                answer(false, F("RAT must be followed by C"));

Malaurie Bernard's avatar
Malaurie Bernard committed
            Serial.printf("%sRAT: %g ul/mn\n", _msgHeader, syringe_filled.get_exchange_throughput_uL_per_min());
Malaurie Bernard's avatar
Malaurie Bernard committed
        else if (kw(F("VOL")))     //*******************EXCHANGE_VOLUME*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");
Malaurie Bernard's avatar
Malaurie Bernard committed
            copyNextToTemp();
            while (_temp.length())
            {
                if (isdigit(_temp[0]))
                {
                    syringe_filled.set_exchange_volume_mL(syringe_filled.distance_mm_to_volume_mL(syringe_filled.step_to_mm(syringe_filled.where_step())) - stof(_temp.c_str()));
                    syringe_filled.save_json();
                    Serial.println("ok");
                }
                else if (_temp.equalsIgnoreCase(F("ul")))
                    ;
                else if (_temp.equalsIgnoreCase(F("ml")))
                    syringe_filled.set_exchange_volume_mL(syringe_filled.get_exchange_volume_mL()*1000);
                else if (_temp.equalsIgnoreCase(F("cl")))
                    syringe_filled.set_exchange_volume_mL(syringe_filled.get_exchange_volume_mL()*10000);
                else if (_temp.equalsIgnoreCase(F("dl")))
                    syringe_filled.set_exchange_volume_mL(syringe_filled.get_exchange_volume_mL()*100000);
                else if (_temp.equalsIgnoreCase(F("l")))
                    syringe_filled.set_exchange_volume_mL(syringe_filled.get_exchange_volume_mL()*1000000);
                syringe_filled.save_json();
                answer(syringe_filled.check_configuration(), F("invalid volume or volume unit"));
                copyNextToTemp();
            }
David Gauchard's avatar
David Gauchard committed
        }
        else if (kw(F("RVOL")))      //*******************RELATIVE_EXCHANGE_VOLUME*******************//
David Gauchard's avatar
David Gauchard committed
        {
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

            syringe_filled.reset_position();
David Gauchard's avatar
David Gauchard committed
            copyNextToTemp();
            while (_temp.length())
            {
                if (isdigit(_temp[0]) || _temp[0] == '-')
                    syringe_filled.set_exchange_volume_mL(atof(_temp.c_str()));
Malaurie Bernard's avatar
Malaurie Bernard committed
                    syringe_filled.save_json();
                }
                answer(syringe_filled.check_configuration(), F("invalid exchange volume"));
David Gauchard's avatar
David Gauchard committed
                copyNextToTemp();
            }

Malaurie Bernard's avatar
Malaurie Bernard committed
            Serial.printf("%sRVOL: %g ml (target)\n", _msgHeader, syringe_filled.get_exchange_volume_mL());
Malaurie Bernard's avatar
Malaurie Bernard committed

         else if (kw(F("MM")))    //*******************DISTANCE_TO_ZERO*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

            copyNextToTemp();
            if (_temp.length())
            {
Malaurie Bernard's avatar
Malaurie Bernard committed
                if (isdigit(_temp[0]) || _temp[0] == '-')
                    syringe_filled.set_exchange_volume_mL(syringe_filled.distance_mm_to_volume_mL(syringe_filled.step_to_mm(syringe_filled.where_step())) + syringe_filled.distance_mm_to_volume_mL(atof(_temp.c_str())));
                answer(syringe_filled.check_configuration(), F("invalid length"));
                copyNextToTemp();
            }
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.save_json();
            Serial.printf("%sMM: %g ml (%g mm) (target)\n", _msgHeader, syringe_filled.get_exchange_volume_mL(), syringe_filled.volume_mL_to_distance_mm(syringe_filled.get_exchange_volume_mL()));
 
David Gauchard's avatar
David Gauchard committed
        }
        else if (kw(F("RMM")))     //*******************RELATIVE_DISTANCE*******************//
David Gauchard's avatar
David Gauchard committed
        {
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            copyNextToTemp();
            if (_temp.length())
            {
                if (isdigit(_temp[0]) || _temp[0] == '-')
                    syringe_filled.set_exchange_volume_mL(syringe_filled.distance_mm_to_volume_mL(atof(_temp.c_str())));
                answer(syringe_filled.check_configuration(), F("invalid exchange length"));
David Gauchard's avatar
David Gauchard committed
                copyNextToTemp();
            }
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.save_json();
            Serial.printf("%sRMM: %g ml (%g mm) (target)\n", _msgHeader, syringe_filled.get_exchange_volume_mL(), syringe_filled.volume_mL_to_distance_mm(syringe_filled.get_exchange_volume_mL()));
            
Malaurie Bernard's avatar
Malaurie Bernard committed
        else if (kw(F("DIA")))           //*******************INTERNAL_DIAMETER*******************//*
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            if (_temp.length())
            {
Malaurie Bernard's avatar
Malaurie Bernard committed
                syringe.set_internal_diameter_mm("cli", atof(_temp.c_str()));
                syringe.save_json();
                answer( syringe.check_configuration("cli"), F("invalid diameter"));
Malaurie Bernard's avatar
Malaurie Bernard committed
            Serial.printf("%sDIA: %g mm\n", _msgHeader, syringe.get_internal_diameter_mm("cli"));
Malaurie Bernard's avatar
Malaurie Bernard committed
        }
David Gauchard's avatar
David Gauchard committed
        else if (kw(F("RVM")))
        {
Malaurie Bernard's avatar
Malaurie Bernard committed
            //syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            copyNextToTemp();
            if (_temp == F("M4"))
Malaurie Bernard's avatar
Malaurie Bernard committed
            {
                syringe_filled.set_lead_screw_pitch_mm(0.7);
                syringe_filled.save_json();
            }
David Gauchard's avatar
David Gauchard committed
            else if (_temp == F("M5"))
Malaurie Bernard's avatar
Malaurie Bernard committed
            {
                syringe_filled.set_lead_screw_pitch_mm(0.8);
                syringe_filled.save_json();
            }
David Gauchard's avatar
David Gauchard committed
            else if (_temp.length() > 0)
                answer(false, F("invalid auger size: M4 or M5 are accepted"));
Malaurie Bernard's avatar
Malaurie Bernard committed
            Serial.printf("%sRVM: %g mm per revolution\n", _msgHeader, syringe_filled.get_lead_screw_pitch_mm());
        else if (kw(F("ACC")))         //*******************ACCELERATION*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            copyNextToTemp();
            if (_temp.length())
                syringe_filled.set_retain_acceleration_mm_per_sec_per_sec(atof(_temp.c_str()));
            Serial.printf("%sACC: %g mm per second per second\n", _msgHeader, syringe_filled.get_retain_acceleration_mm_per_sec_per_sec());
        else if (kw(F("DIR")))          //*******************DIRECTION*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            copyNextToTemp();
            if (_temp.length())
            {
                if (_temp.equalsIgnoreCase(F("inf")))
Malaurie Bernard's avatar
Malaurie Bernard committed
                    syringe_filled.save_json();
                }
David Gauchard's avatar
David Gauchard committed
                else if (_temp.equalsIgnoreCase(F("wdr")))
Malaurie Bernard's avatar
Malaurie Bernard committed
                    syringe_filled.save_json();
                }
                answer(syringe_filled.check_configuration(), F("invalid direction -> INF | WDR"));
David Gauchard's avatar
David Gauchard committed
            Serial.printf("%sDIR: %s\n", _msgHeader,
                syringe_filled.get_push()? "INFuse": "WithDRaw");
        else if (kw(F("FIL")))          //*******************MOUVEMENT*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

            syringe_filled.start_exchange();
David Gauchard's avatar
David Gauchard committed
            answer(true);
        }
        else if (kw(F("STP")))
        {
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            answer(true);
        else if (kw(F("SET0")))
        {
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

        else if (kw(F("DIS")))        //*******************DISTANCE_PARCOURU*******************//
David Gauchard's avatar
David Gauchard committed
        {
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            Serial.printf("%sDIS: I %g W %g UL\n", _msgHeader,
                syringe_filled.get_push()? syringe_filled.distance_mm_to_volume_mL(syringe_filled.step_to_mm(syringe_filled.where_step())): 0,
                syringe_filled.get_push()? 0 : syringe_filled.distance_mm_to_volume_mL(syringe_filled.step_to_mm(syringe_filled.where_step())));
David Gauchard's avatar
David Gauchard committed
        }
        else if (kw(F("ZERO")))      //*******************ZERO*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

            syringe_filled.go_to_limit_switch();
        else if (kw(F("NLCK")))                 //*******************RUN_FROM_EMERGENCY*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

            syringe_filled.run_from_emergency();
        else if (kw(F("CLKW")))              //*******************CLOCKWISE_EQUALS_PUSH*******************//
David Gauchard's avatar
David Gauchard committed
        {
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

David Gauchard's avatar
David Gauchard committed
            copyNextToTemp();
            if (_temp.length() == 1)
            {
                if (_temp[0] == '0' || _temp[0] == '1')
                {
                    syringe_filled.set_clockwise_equals_push(_temp[0] == '1');
Malaurie Bernard's avatar
Malaurie Bernard committed
                    syringe_filled.save_json();
David Gauchard's avatar
David Gauchard committed
                    answer(true);
                }
                else
                    answer(false, F("CLKW: invalid argument"));
            }
            Serial.printf("%sCLKW: push %sclockwise\n", _msgHeader, syringe_filled.get_clockwise_equals_push()? "": "anti-");
David Gauchard's avatar
David Gauchard committed
        }
        else if (kw(F("CONF")))               //*******************SHOW_CONFIGURATION*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe_filled.set_name_syringe("cli");

        else if (kw(F("FS-LS")))             //*******************SHOW_ALL_THE_FILES*******************//
David Gauchard's avatar
David Gauchard committed
        {
            ls(&Serial);
            answer(true);
        }
        else if (kw(F("FS-CAT")))            //*******************PRINT_A_FILE*******************//
David Gauchard's avatar
David Gauchard committed
        {
            copyNextToTemp();
            if (_temp.length() > 0)
            {
                cat(_temp.c_str(), &Serial);
                answer(true);
            }
            else
                answer(false);
        }
        else if (kw(F("FS-SAVE")))      //*******************SAVE_THE_JSON_FILES*******************//
David Gauchard's avatar
David Gauchard committed
        {
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe.save_json();
            syringe_filled.save_json();

        else if (kw(F("FS-LOAD")))      //*******************LOAD_THE_JSON_FILES*******************//
Malaurie Bernard's avatar
Malaurie Bernard committed
            syringe.load_json();
            syringe_filled.load_json();

David Gauchard's avatar
David Gauchard committed
        }
David Gauchard's avatar
David Gauchard committed
            Serial.printf("%sinvalid command '%s'\n", _msgHeader, _currentInput.c_str() + _currentWordIndex);
David Gauchard's avatar
David Gauchard committed

David Gauchard's avatar
David Gauchard committed
        Serial.printf("%sgarbage at end of line: '%s'\n", _msgHeader, _currentInput.c_str() + _currentWordIndex);
    resetNextWord();
    _currentInput.clear();
}