#!/bin/bash
#    Файл является частью библиотеки RubiRobotLib
#
#    © 2017-2018 Слинкин Д.А.
#
#    Утилита управления EV3 (менеджер EV3)
#
#    Подробная информация о лицензировании находится в файле README,
#    входящем в состав библиотеки.
#
#    ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ
#    КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ,
#    ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО
#    КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ 
#    ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ
#    ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ,
#    В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ,
#    ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ
#    ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
# **********************************************************************

######################## функции справки #################
function help
{
 commands=( $(compgen -A function -X !*_help) )
 if [[ -z $1 ]]; then
  shorthelp
  echo 
  echo "Описание команд:"
  echo
  for func in ${commands[@]} ; do
   echo ------------------------------------------------------------------------------
   $func
  done
 else
  if [[ " ${commands[@]} " =~ " $1_help " ]] ; then
   $1_help
  else 
   echo "Неизвестная команда"
  fi
 fi
 end $?
}

function shorthelp
{
 echo "
 Утилита ev3 - многофункциональный менеджер доступа к EV3, часть библиотеки
 RubiRobotLib.
 Предназначена для подготовки и запуска программ на контроллере EV3.
 Коммуникационный канал с EV3 реализован с помощью ssh, компиляция
 программ - с помощью кросскомпилятора FreePascal.

 Использование утилиты ev3:

  ev3 [команда] [параметры]
  ev3x [команда] [параметры]
  ev3nx [команда] [параметры]

 Вызов ev3 без команд и параметров показывает эту справку.

 Вызов ev3 вне терминала, например - запуском с рабочего стола, порождает 
 запуск графического терминала и выполнение утилиты в его пределах. Перед 
 завершением работы графического терминала утилита ожидает нажатия клавиши 
 Enter. 
 ev3nx никогда не порождает графический терминал и может использоваться в 
 сторонних скриптах и программах без каких-либо внешних эффектов. 
 ev3x всегда порождает графический терминал с выполнением утилиты в 
 его пределах.

 ev3 при запуске анализирует свое имя. Если оно является составным 
 (кроме ev3nx и ev3x), то часть имени после 'ev3' считается командой. 
 Например, если существует символическая ссылка ev3connect на утилиту ev3,
 то запуск ev3 с параметром connect и запуск ev3connect приведет к одному
 и тому-же результату:
   ev3 connect
   ev3connect

 Список команд: 
   help, version,
   freepass, connect, drop, reconnect, setip, setpass, fix, ufix,
   fpc, cp, run, silentrun, fpccp, fpccprun, cprun, lazrun,
   shell, silentshell, exists

 Описание каждой команды можно получить с помощью команды help, например:
   ev3 help shell

 Эту справку и описание всех команд можно получить с помощью команды help 
 без параметров, например:
   ev3 help
"
}

function help_help
{
echo "
  ev3 help [команда]
   Выводит описание указанной команды.
   Без указания команды выводит описание всех команд.

   Требования: отсутствуют

   Параметры: команда утилиты ev3
"
}

function version_help
{
echo "
  ev3 version
   Выводит версию библиотеки RubiRobotLib, для которой разработана утилита ev3.

   Требования: отсутствуют

   Параметры: отсутствуют
"
}

function alive_help
{
echo "
  ev3 alive [количеcтво секунд]
   Устанавливает время жизни соединения с роботом при его физическом отключении
   или временной недоступности. Затем выполняет переподключение к роботу, чтобы
   изменения вступили в силу.
   
   Отчет времени жизни начинается в момент, когда робот становится недоступным,
   при этом все текущие действия с роботом замораживаются. Если в течении 
   заданного промежутка времени робот снова станет доступным, все действия с 
   ним  возобновляются с того места, где были приостановлены. В противном
   случае соединение будет аннулировано.

   Запуск без параметров устанавливает время жизни в 300 секунд (5 минут)
   Минимально допустимое значение параметра - 5 секунд. При установке 
   меньшего значения время жизни соединения станет неограниченным.
   Соединение с неограниченнымм временем жизни можно будет аннулировать 
   только перезагрузкой компьютера, с помощью команды ev3 drop или 
   специальными средствами системного администрирования.

   Требования: робот должен быть подключен к компьютеру

   Параметры: время жизни в секундах (опционально)
"
}


function shell_help
{
echo "
  ev3 shell [команда оболочки или программа]
  ev3 sh [команда оболочки или программа]
   Обеспечивает терминальный доступ к EV3 или запуск произвольной команды 
   на EV3.
   В отличии от run и silentrun, команда может быть как исполняемым файлом из 
   произвольного местоположения, так и командой оболочки.

   Требования: робот должен быть подключен к компьютеру

   Параметры: команда или программа (опционально)
"
}

function silentshell_help
{
echo "
  ev3 silentshell [команда оболочки или программа]
  ev3 silsh [команда оболочки или программа]
   Обеспечивает терминальный доступ к EV3 или запуск произвольной команды 
   на EV3.
   В отличии от run и silentrun, команда может быть как исполняемым файлом из 
   произвольного местоположения, так и командой оболочки.
   Подобно silentrun не выводит никаких диагностических сообщений, 
   кроме сообщений запущенной команды.

   Требования: робот должен быть подключен к компьютеру

   Параметры: команда или программа (опционально)
"
}



function setip_help
{
echo "
  ev3 setip [IP-адрес]
  ev3 ip [IP-адрес]
   Позволяет указать временный IP-адрес EV3, если робот не обнаруживается
   автоматически. Действительный IP-адрес EV3 можно увидеть на дисплее робота,
   в случае его успешного подключения к сети. Временный IP-адрес будет
   действовать до тех пор, пока не возникнет одна из следующих ситуаций:
   1) вызвана команда setip с другим IP-адресом
   2) вызвана команда setip без параметров
   3) EV3 перестал быть доступен по заданному IP-адресу, но при этом начал
      обнаруживаться автоматически
   Вызов setip без параметров аннулирует временный IP-адрес EV3

   Требования: отсутствуют

   Параметры: IP-адрес EV3 (опционально)
"
}

function ipexists_help
{
echo "
  ev3 ipexists
  ev3 ipis
   Возвращает IP-адрес EV3, если робот подключен к компьютеру и пустую строку
   в противном случае. В отличие от команды exists Производит проверку только
   по текущему ip-адресу и не пытается обнаружить EV3 по имени ev3dev.local.
   В отсутствии установленного ip-адреса возвращает пустую строку.

   При отсутствии робота в сети проверка длится не менее секунды.
   Рекомендуется использовать при повторных проверках после первичного вызова
   команды exists в случае нестабильной связи, например - при слабом сигнале
   wi-fi.

   Требования: отсутствуют

   Параметры: отсутствуют

"
}


function exists_help
{
echo "
  ev3 exists
  ev3 is
   Возвращает IP-адрес EV3, если робот подключен к компьютеру и пустую строку
   в противном случае. Производит проверку сначала по ip-адресу, в случае 
   неудачи - по имени ev3dev.local. Если провека по имени завершилась удачно,
   аннулирует временный ip-адрес EV3 и устанавливает найденный ip-адрес в 
   качестве основного.

   При отсутствии робота в сети проверка длится не менее 2-х секунд.

   Требования: отсутствуют

   Параметры: отсутствуют

"
}


function fix_help
{
echo "
  ev3 fix
   Пытается исправить ошибки автоматического обнаружения EV3.
   Требует пароль системного администратора.
   Работает при вхождении пользователя в группу wheel.

   Требования: робот должен быть подключен к компьютеру

   Параметры: отсутствуют
"
}

function ufix_help
{
echo "
  ev3 ufix
   Пытается исправить ошибки автоматического обнаружения EV3.
   В отличие от fix, требует пароль текущего пользователя.
   Работает при наличии разрешений пользователю в файле /etc/sudoers.

   Требования: робот должен быть подключен к компьютеру

   Параметры: отсутствуют
"
}


function connect_help
{
echo "
  ev3 connect
  ev3 conn
   Организует высокоскоростной постоянный канал связи с EV3, если таковой
   отсутствует на текущий момент. Неявно вызывается при выполнении большинства
   команд

   Требования: робот должен быть подключен к компьютеру

   Параметры: отсутствуют
"
}

function drop_help
{
echo "
  ev3 drop
   Разрывает все существующие каналы связи с EV3. Рекомендуется вызывать
   в нештатных ситуациях, например - при 'зависании' соединений.
   Неявно вызывается при выполнении команды reconnect.

   Требования: робот должен быть подключен к компьютеру

   Параметры: отсутствуют
"
}

function reconnect_help
{
echo "
  ev3 reconnect
  ev3 reconn
   последовательно вызывает команды drop и connect

   Псевдоним: reconn
"
}

function setpass_help
{
echo "
  ev3 setpass [пароль]
  ev3 spw [пароль]
   Позволяет указать пароль, который будет использоваться в дальнейшем для 
   доступа к EV3. Без этой команды пользователь будет должен каждый раз 
   вводить пароль при любой попытке доступа к EV3. Штатный пароль: maker
   Вызов setpass без параметров аннулирует указанный ранее пароль.
   Пароль, заданный setpass игнорируется, если ранее был организован 
   постоянный беспарольный доступ к EV3 с помощью команды freepass.

   Требования: отсутствуют

   Параметры: пароль доступа к EV3 (опционально)
"
}

function freepass_help
{
echo "
  ev3 freepass
  ev3 fpw
   Организует беспарольное соединение с EV3, рекомендуется применять однократно
   при первом подключении к роботу. Без использования данной команды каждое
   действие на роботе будет запрашивать пароль. Штатный пароль: maker

   Требования: робот должен быть подключен к компьютеру

   Параметры: отсутствуют
"
}

function fpc_help
{
echo "
  ev3 fpc [файл]
   компилирует программу с возможностью исполнения на EV3

   Требования: на компьютере должен быть установлен кросскомпилятор, утилиты
   сборки и библиотеки EV3. Все указанное устанавливается и настраивается
   автоматически при штатной установке кросскомпилятора RubiRobotCross.

   Параметры: абсолютное или относительное имя файла исходного кода программы
   на FreePascal, с использованием возможностей библиотеки RubiRobotLib.
"
}

function cp_help
{
echo "
  ev3 cp [файл]
   копирует локальный файл на EV3 в каталог /home/robot

   Требования: робот должен быть подключен к компьютеру

   Параметры: абсолютное или относительное имя локального файла
"
}

function run_help
{
echo "
  ev3 run [файл]
   запускает в псевдотерминале исполняемый файл на EV3, из каталога /home/robot.
   Информирует пользователя о начале запуска программы и о ее завершении.

   Требования: робот должен быть подключен к компьютеру, исполняемый файл должен
   находится на EV3 в каталоге /home/robot

   Параметры: имя исполняемого файла на EV3
"
}

function silentrun_help
{
echo "
  ev3 silentrun [файл]
  ev3 silrun [файл]
   запускает в псевдотерминале исполняемый файл на EV3, из каталога /home/robot.
   Не выводит информационных и диагностических сообщений.

   Требования: робот должен быть подключен к компьютеру, исполняемый файл должен
   находится на EV3 в каталоге /home/robot

   Параметры: имя исполняемого файла на EV3
"
}

function lazrun_help
{
echo "
  ev3 lazrun [файл]
   Копирует локальный исполняемый файл на EV3 в каталог /home/robot и запускает
   его в псевдотерминале. Копирование происходит, только если исполняемый файл 
   изменился с момента последнего выполнения команды lazrun. По завершении
   программы ожидает нажатия клавиши Enter. Применяется как способ запуска
   программ для EV3 из среды Lazarus.

   Требования: робот должен быть подключен к компьютеру

   Параметры: абсолютное или относительное имя локального исполняемого файла
"
}

function fpccp_help
{
echo "
  ev3 fpccp [файл]
  ev3 fpcp [файл]
   Последовательно выполняет команды fpc и cp, компилируя программу и размещая 
   локальный исполняемый файл на EV3 в каталоге /home/robot

   Требования: робот должен быть подключен к компьютеру

   Параметры: абсолютное или относительное имя локального файла исходного кода 
   программы на FreePascal, с использованием возможностей библиотеки RubiRobotLib.
"
}

function fpccprun_help
{
echo "
  ev3 fpccprun [файл]
  ev3 fpcprun [файл]
   Последовательно выполняет команды fpc, cp и run, компилируя программу,
   размещая локальный исполняемый файл на EV3 в каталоге /home/robot и 
   запуская его в псевдотерминале.

   Требования: робот должен быть подключен к компьютеру

   Параметры: абсолютное или относительное имя локального файла исходного кода
   программы на FreePascal, с использованием возможностей библиотеки RubiRobotLib.
"
}

function cprun_help
{
echo "
   ev3 cprun [файл]
   Последовательно выполняет команды cp и run, размещая локальный
   исполняемый файл на EV3 в каталоге /home/robot и запуская его 
   в псевдотерминале.

   Требования: робот должен быть подключен к компьютеру

   Параметры: абсолютное или относительное имя исполняемого файла
"
}

############### вспомогательные функции ##################
function end
{
 if [[ -n $xwin ]] ; then
  echo
  echo "Для выхода нажмите Enter"
  read
 fi
 exit $1
}

function resolveEV3
{
# echo resolve
 ev3ip=`resolve -t 1 -s ev3dev.local`
 ev3pinged=$?
 if [[ -n $ev3ip ]] ; then
   echo $ev3ip > ~/.ssh/ev3ip
 fi
 return $ev3pinged
}

function checkConnect
{
 # скоростная проверка на доступность
 if ! ev3exists ; then
   connError
   end 1
 fi
}

function prepare
{
 ev3cp="scp"
 ev3cphost="robot@ev3dev.local"
 ev3sh="ssh"
 ev3shopt="-t"
 if [[ -f ~/.ssh/ev3alive ]] ; then
  let ev3alive=$(<~/.ssh/ev3alive)/5
 else
  ev3alive=60
 fi
 ev3extra="-o ControlMaster=auto -o ControlPath=~/.ssh/master-%r@%h:%p"
 ev3extra="$ev3extra -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" 
 ev3extra="$ev3extra -o ServerAliveInterval=$ev3alive -o ServerAliveCountMax=5"
 ev3shhost=$ev3cphost
 if [[ -f ~/.ssh/ev3pass ]] ; then
  ev3sh="sshpass -p$(<~/.ssh/ev3pass) $ev3sh"
  ev3cp="sshpass -p$(<~/.ssh/ev3pass) $ev3cp"
 fi

 if [[ -f ~/.ssh/ev3ip ]] ; then
  ev3ip=`cat ~/.ssh/ev3ip`
  if ev3exists ; then
   ev3cphost="robot@"$ev3ip
   ev3shhost=$ev3cphost
  else
   if ! resolveEV3 ; then
    return 1
   fi
  fi
 else
  if ! resolveEV3 ; then
   return 1
  else 
   ev3cphost="robot@"$ev3ip
   ev3shhost=$ev3cphost
  fi
 fi
 return 0
}

function connError
{
   echo "
!! EV3 недоступен, возможные причины:
!!   1) EV3 физически не подключен к компьютеру (USB-соединение)
!!   2) EV3 не подключен к беспроводной сети (wi-fi - соединение)
!!   3) компьютер не подключен к беспроводной сети (wi-fi - соединение)
!!   4) EV3 и компьютер подключены к разным беспроводным сетям 
!!      (wi-fi - соединение)
!!   5) на EV3 не настроено сетевое подключение к компьютеру или 
!!      к беспроводной сети
!!   6) на компьютере не настроено сетевое подключение к EV3 (USB-соединение)
!!   Исправьте проблему и попробуйте еще раз
!! Если ни одна из этих ошибок не обнаружена, но робот подключен к сети и
!! отбражает на дисплее IP-адрес, попробуйте принудительно указать адрес робота
!! командой ev3 setip IP-адрес"
}

############################# функции исполнения команд ################################

function setip
{
 if [[ -n "$1" ]] ; then
  echo $1 > ~/.ssh/ev3ip
  echo "Установлен временный IP-адрес EV3: $1"
  echo "Будет аннулирован при автоматическом определении IP-адреса EV3"
 else
  if ! resolveEV3 ; then
   rm -f ~/.ssh/ev3ip
   echo "Аннулирован временный IP-адрес EV3"
  fi
 fi
}


function ev3exists
{
 #echo exists
 [[ -z $ev3pinged ]] || return $ev3pinged
 ping -W 1 -c 1 $ev3ip >/dev/null 2>&1
 ev3pinged=$?
# echo $ev3pinged
 return $ev3pinged
}

function ev3ipexists
{
 #echo exists
 [[ -f ~/.ssh/ev3ip ]] || return 1
 ev3ip=$(<~/.ssh/ev3ip)
 ping -W 1 -c 1 $ev3ip >/dev/null 2>&1
 return $?
}



function connect
{
 checkConnect
# if [[ -z `cat /proc/net/unix | grep "master-robot@"` ]] ; then
 if [[ -z `pgrep -f "ssh.*master.*robot@"` ]] ; then
  ssh-add >/dev/null 2>&1
  if ! $ev3sh $ev3extra -qfnN $ev3shhost >/dev/null 2>&1 ; then
   connError
   end 1
  else
   echo "Установлен постоянный канал связи с EV3. Приятного общения ;)"
  fi
 fi
 return 0
}


function drop
{
 pkill -f "ssh.*robot@"
 echo "Все каналы доступа к EV3 аннулированы"
 return 0
}

function reconnect
{
 drop
 connect
 return 0
}

function setpass
{
 if [[ -z $1 ]] ; then
  rm -f ~/.ssh/ev3pass
  echo "Аннулирован пароль доступа к EV3"
 else
  echo $@ >~/.ssh/ev3pass
  echo "Установлен пароль доступа к EV3"
 fi
 return 0
}

function alive
{
 if [[ -z $1 ]] ; then
  rm -f ~/.ssh/ev3alive
  echo "Время жизни соединения: 300 секунд"
 else
  echo $1 >~/.ssh/ev3alive
  echo "Время жизни соединения: $1 секунд"
 fi
 reconnect
 return 0
}

function freepass
{
 echo "-- Организация свободного доступа к EV3"
 checkConnect

 echo Если EV3 запросит пароль, введите слово maker
 cat /dev/zero | ssh-keygen -q -N "" >/dev/null 2>&1
 ssh-add >/dev/null 2>&1

 drop
 if ssh-copy-id $ev3extra $ev3shhost >/dev/null 2>&1 ; then
  echo "Свободный доступ к EV3 успешно реализован, "
  echo "подключение к роботу теперь не требует ввода пароля"
 else
  connError
 fi
 return 0
}


function fix
{
 drop
 su - -c "service avahi-daemon restart"
 checkConnect && connect
 return $?
}

function ufix
{
 drop
 sudo service avahi-daemon restart
 checkConnect && connect
 return $?
}

function _fpc
{
 ppcarm -XX $@
 return $?
}


function _cp
{
 checkConnect
 [ -z $2 ] || connect
 $ev3cp $ev3extra $1 $ev3cphost:/home/robot/ 2>/dev/null \
 && echo "Программа $1 успешно скопирована на robot@ev3dev.local:/home/robot/"
 return $?
}


function run
{
 checkConnect
 [ -z $2 ] || connect
 elf=`basename $1`
 echo -e "Запуск программы robot@ev3dev.local:/home/robot/$elf на исполнение:"
 $ev3sh $ev3extra $ev3shopt $ev3shhost " echo '----------------------' && ./$elf" 2>/dev/null \
 && echo -e "---------------------- \nПрограмма robot@ev3dev.local:/home/robot/$elf завершена" 
 return $?
}


function silentrun
{
 connect >/dev/null
 ev3exists || end 1
 $ev3sh $ev3extra $ev3shopt $ev3shhost "./$1" 2>/dev/null
 return $?
}


function lazrun
{
 checkConnect
 [ -z $2 ] || connect
 elf=`basename $1`
 lastmod=/tmp/$elf.lastmod
 sec=`stat -c "%Y" $1`
 lastsec=`stat -c "%Y" $lastmod 2>/dev/null`
 if [[ "$lastsec" == "" ]]
 then
  lastsec=0
  echo "Отладка: Первый запуск"
 fi
 if (($sec > $lastsec))
 then
  echo "Отладка: Программа изменена, копирую на EV3"
  $ev3cp $ev3extra $1 $ev3cphost:/home/robot/ 2>/dev/null || return 1 
 fi
 touch $lastmod
 echo "Отладка: Запуск программы"
 $ev3sh $ev3extra $ev3shopt $ev3shhost " echo '----------------------' && ./$elf" 2>/dev/null 
 echo "----------------------"
 echo "Отладка: Программа завершена, нажмите  клавишу Enter"
 read
 return 0
}


############### начало #################

if [[ `basename $0` != "ev3nx" ]] ; then
## ++ код от автора makeself.sh, с модификациями ####
    if tty -s && [[ `basename $0` != "ev3x" ]] || [[ $1 == "--xwin" ]] ; then                 # Do we have a terminal?
        :
    else
        if test x"$DISPLAY" != x -a x"$xterm_loop" = x; then  # No, but do we have X?
            if xset q > /dev/null 2>&1; then # Check for valid DISPLAY variable
                GUESS_XTERMS="xterm rxvt dtterm eterm Eterm kvt konsole aterm"
                for a in $GUESS_XTERMS; do
                    if type $a >/dev/null 2>&1; then
                        XTERM=$a
                        break
                    fi
                done
                chmod a+x $0 || echo Please add execution rights on $0
                initargs=$@
                if test `echo "$0" | cut -c1` = "/"; then # Spawn a terminal!
                    (exec $XTERM -maximized -title "$label" -e "$0" --xwin $initargs) &
                else
                    (exec $XTERM -maximized -title "$label" -e "./$0" --xwin $initargs) &
                fi
                
                exit
            fi
        fi
    fi
## -- код от автора makeself.sh, с модификациями ####
fi

if [[ "$1" == "--xwin" ]] ; then
 xwin=1
 shift
fi



file=`basename "$0"`
command=${file#ev3}
if [[ -z "$command" || "$command" == "nx" || "$command" == "x" ]] ; then
  command=$1
  shift
fi

if [[ -z $command ]] ; then
 shorthelp
 end 0

fi



#### команды без предустановок ####
case $command in
 "setip"|"ip" )
  setip $1
 ;;

 "ipexists"|"ipis" )
 if ev3ipexists ; then
  echo $ev3ip
  end 0
 else  
  end 1
 fi
 ;;



 "version" )
  cat ~/.ssh/ev3ver 2>/dev/null
 ;;

 "drop" )
  drop
 ;;

 "fpc" )
 if [[ -z "$1" ]] ; then
  echo "Пропущено имя файла для компиляции"
  end 1
 fi
 _fpc $@
 ;;

 "setpass"|"spw" )
  setpass $@
 ;;

  "help" )
  help $@
 ;;


esac

prepare

#### команды с предустановками ####

case $command in

  "alive" )
  alive $@
 ;;

 "fix" )
  fix
 ;;

 "ufix" )
  ufix
 ;;

 "freepass"|"fpw" )
  freepass
 ;;

 "connect"|"conn" )
  connect
 ;;

 "reconnect"|"reconn" )
  reconnect
 ;;

 "cp" )
 if [[ -z "$1" ]] ; then
  echo "Пропущено имя файла для копирования на EV3"
  end 1
 fi
 _cp $1 "connect"
 ;;

 "run" )
 if [[ -z "$1" ]] ; then
  echo "Пропущено имя файла для запуска на EV3"
  end 1
 fi
 run $1 "connect"
 ;;

 "silentrun"|"silrun" )
 if [[ -z "$1" ]] ; then
  end 1
 fi
 silentrun $1
 ;;


 "fpccp"|"fpcp" )
 elf=${@: -1}
 if [[ -z "$1" ]] ; then
  echo "Пропущено имя файла для компиляции"
  end 1
 fi
 elf=${elf%.*}
 _fpc $@ && _cp $elf "connect"
 
 ;;
 
 "fpccprun"|"fpcprun" )
 elf=${@: -1}
 if [[ -z "$1" ]] ; then
  echo "Пропущено имя файла для компиляции"
  end 1
 fi
 elf=${elf%.*}
 _fpc $@ && _cp $elf "connect" && run $elf

 ;;

 "cprun" )
 if [[ -z "$1" ]] ; then
  echo "Пропущено имя файла для копирования"
  end 1
 fi
 _cp $1 "connect" && run $1
 
 ;;
 
 "lazrun" )
 if [[ -z "$1" ]] ; then
  echo "Пропущено имя файла для запуска на EV3"
  end 1
 fi
 lazrun $1 "connect"
 end 0
 ;;

 "shell"|"sh" )
 connect
 ev3exists || exit 1
 $ev3sh $ev3extra $ev3shhost $@ 2>/dev/null
 ;;

 "silentshell"|"silsh" )
 connect  >/dev/null 2>&1
 ev3exists || exit 1
 $ev3sh $ev3extra $ev3shhost "$@" 2>/dev/null
 ;;

 "exists"|"is" )
 if ev3exists ; then
  echo $ev3ip
  end 0
 else  
  end 1
 fi
 ;;
 
esac

end 0