changeset 436:e09c156e04f4 better_scripting

Attempt at unified script for all things bela
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 17 Jun 2016 18:40:04 +0100
parents cea66c2af560
children
files scripts/bela.sh
diffstat 1 files changed, 362 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/bela.sh	Fri Jun 17 18:40:04 2016 +0100
@@ -0,0 +1,362 @@
+#/bin/ksh
+
+# set defaults unless variables are already set
+[ -z "$BBB_ADDRESS" ] && BBB_ADDRESS="root@192.168.7.2"
+[ -z "$BBB_BELA_HOME" ] && BBB_BELA_HOME="~/Bela/"
+[ -z "$BBB_SCREEN_NAME" ] && BBB_SCREEN_NAME="Bela"
+[ -z "$RUN_PROJECT" ] && RUN_PROJECT=1
+[ -z "$COMMAND_ARGS" ] && COMMAND_ARGS=
+[ -z "$RUN_IN_FOREGROUND" ] && RUN_IN_FOREGROUND=1
+[ -z "$RUN_WITHOUT_SCREEN" ] && RUN_WITHOUT_SCREEN=0
+[ -z "$BBB_PROJECT_HOME" ] && BBB_PROJECT_HOME="${BBB_BELA_HOME}/projects/"
+[ -z "$BBB_DEFAULT_PROJECT_NAME" ] && BBB_DEFAULT_PROJECT_NAME="scriptUploadedProject"
+[ -z "$BBB_PROJECT_NAME" ] && BBB_PROJECT_NAME=$BBB_DEFAULT_PROJECT_NAME
+[ -z "$BELA_SAFE_MODE" ] && BELA_SAFE_MODE=1 
+#script folder SF
+SF="./"
+
+trap "echo; exit" 2
+usage(){
+	THIS_SCRIPT=`basename "$0"`
+	echo "Usage: $THIS_SCRIPT $*"
+	[ -z $* ] && SEARCH_STRING="^##bela " || SEARCH_STRING="^##[#]\?bela $*" 
+	echo $SEARCH_STRING
+	grep "$SEARCH_STRING" $THIS_SCRIPT | sed s/^###/\ \ \.\\// | sed s/^##/\.\\//
+}
+FULL_INVOCATION="$0 $*"
+MAKE_COMMAND="make --no-print-directory -C \"$BBB_BELA_HOME\""
+
+beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
+contains() { case $2 in *"$1"*) true;; *) false;; esac; }
+count_words(){
+	[ -z "$1" ] && { echo "Count words requires one argument (string)"; exit 1; }
+	_RET1=`echo $1 | wc -w`
+	_RET1="${_RET1#"${_RET1%%[![:space:]]*}"}"
+	return 0
+}
+folder_exists(){
+	[ -z $1 ] && { echo "folder_exists requires one argument (folder)"; exit 1; }
+	ls $1 >/dev/null 2>&1 
+	return $?
+}
+find_project_folder(){
+	[ -z $2 ] && { echo "find_project_folder requires two arguments (projectName, searchPath)"; exit 1; }
+}
+
+find_project(){
+#find_project(projectName, breakFirst) sets globals _RET1 with the local paths and _RET2 with the remote paths and _RET3 with the total number of matches. If breakFirst==1 it puts at most one result in either _RET1 or _RET2 accordingly
+	[ -z $1 ] && { echo "find_project requires one argument (projectName)"; exit 1; }
+	PROJECT=$1; shift
+	[ -z $1 ] && BREAK=0 || { BREAK=$1; shift; } 
+
+	PRIORITY="../projects/ ../examples/"
+	LOCALS=
+	for F in "" $PRIORITY
+	do
+		FOLDER="${F}${PROJECT}"
+		folder_exists $FOLDER && { LOCALS="$LOCALS $FOLDER"; [ $BREAK -ne 0 ] && break; }
+	done
+	# do the same thing remotely
+	if [ $BREAK -eq 0 ] || [ -z $LOCALS ] 
+	then
+		REMOTES=`ssh $BBB_ADDRESS '
+			REMOTES=
+			PROJECT='$PROJECT'
+			for F in "" ~/Bela/projects/ ~/Bela/examples/
+			do
+				FOLDER=${F}${PROJECT}
+				ls $FOLDER >/dev/null 2>&1 && { REMOTES="$REMOTES $FOLDER";
+				[ '$BREAK' -ne 0 ] && break; }
+			done
+			echo $REMOTES'`
+	fi
+	count_words "$LOCALS $REMOTES" && FOUND=$_RET1
+	echo $FOUND________ 
+	[ $FOUND -eq 0 ] && return 1 
+	
+	STR=
+	n=0
+	[ -z "$LOCALS" ] || STR="On your computer: \n"
+	for a in $LOCALS
+	do
+		n=$((n+1))
+		STR="$STR($n) $a\n"
+	done
+	[ -z "$REMOTES" ] || STR="${STR}On Bela: \n"
+	for a in $REMOTES
+	do
+		n=$((n+1))
+		STR="$STR($n) $a\n"
+	done
+
+	_RET1=${LOCALS}
+	_RET2=${REMOTES}
+	_RET3=$FOUND
+	_RET4=$STR
+	return 0
+}
+
+sequential(){
+	echo "ABORT"
+	exit 1
+	if [ -z $1 ] || [ -z $1 ];
+	then
+		echo "sequential should be called with two arguments (start, stop)"
+	fi
+	COUNTER=$1; shift
+	STOP=$1; shift
+	_RET1=
+
+}
+
+interactive(){
+#interactive(count=1) waits for user input, validates it and sets returned value in _RET1
+	[ -z $1 ] && COUNT=1 || COUNT=$1
+	STR=
+	[ $COUNT -eq 1 ] && STR="(y/n): " || STR="(enter a number between 1 and $COUNT): "
+	while { printf "$STR"; read REPLY; }
+	do
+		if [ $COUNT -eq 1 ]
+		then
+			case $REPLY in
+				y|Y)
+					REPLY=1
+					break;
+				;;
+				n|N)
+					REPLY=0
+					break;
+				;;
+				*)
+					echo "wrong value"
+					continue
+				;;
+			esac
+		else
+			case $REPLY in
+			#check it is a string
+			''|*[!0-9]*) 
+				continue
+			;;
+			*)
+				# check range
+				if [ $REPLY -lt 1 ] || [ $REPLY -gt $COUNT ]
+				then
+					continue
+				else
+					break
+				fi
+			;;
+			esac
+		fi
+	done
+	_RET1=$REPLY
+	return 0
+}
+get_one_project(){
+#getOneProject(projectName) returns true if it finds a project, false otherwise. Fills _RET1 with the project path and _RET2 with the project location (local or remote)
+	[ -z $1 ] && { echo "get_one_project() requires one argument (projectName)"; exit 1; }
+	PROJECT=$1; shift
+
+	if [ $SAFE -eq 0 ]; 
+	then
+		find_project $PROJECT 1 || return 1
+	else 
+		find_project $PROJECT 0 || return 1
+		if [ $_RET3 -ge 1 ] # it is >= 1 
+		then
+			LOCALS=$_RET1
+			REMOTES=$_RET2
+			COUNT=$_RET3
+			STR="There are $COUNT projects with this name:\n$_RET4\nWhich one do you want to build? "
+			printf "$STR"
+			interactive $COUNT  
+			SELECTED=$_RET1
+			LOCAL_COUNT=`echo $LOCALS | wc -w`
+			[ $SELECTED -le $LOCAL_COUNT ] &&\
+				LOCATION=local||LOCATION=remote
+			set -- $LOCALS $REMOTES
+			eval "PROJECT_PATH=\$${SELECTED}"
+		fi
+	fi	
+	_RET1=$PROJECT_PATH
+	_RET2=$LOCATION
+}
+copy_project(){
+	printf ""
+}
+
+build_project_remote(){
+	printf ""
+}
+
+run(){
+## run (project, runFolder, runMode, arguments)
+	[ -z $1 ] && { echo "run requires one argument (projectName)"; exit 1; }
+	PROJECT=$1; RUN_FOLDER=$2; MODE=$3; shift 3; CL=$*
+	PROJECT_NAME=`basename $PROJECT`
+	get_one_project $PROJECT  || { echo "Could not find a project called \"$PROJECT\", try specifying the full path to it"; exit 1; }
+	PROJECT_PATH=$_RET1
+	LOCATION=$_RET2
+	case $LOCATION in
+	local)
+		echo ${SF}build_project.sh -p $PROJECT_NAME -c "$CL" $MODE $PROJECT_PATH
+		${SF}build_project.sh -p $PROJECT_NAME -c "$CL" $MODE $PROJECT_PATH
+	;;
+	remote)
+		ssh -t $BBB_ADDRESS $MAKE_COMMAND FULLPATH=
+	;;
+	*)
+		echo "Invalid LOCATION"
+		exit 1
+	;;
+	esac
+	echo PROJECT_PATH=$PROJECT_PATH NAME=$PROJECT_NAME RUN_FOLDER=$RUN_FOLDER MODE=$MODE CL=$CL 
+}
+
+get_ip(){
+# get_ip (fullAddress)
+	[ -z $1 ] && { echo "get_ip requires one argument (fullAddress)"; return 1; }
+	_RET1=`echo $1 | sed s/.*@//`
+}
+
+check_board_connected(){
+# Check if the board is alive and set the date
+	get_ip $BBB_ADDRESS && IP=$_RET1 || return 1
+	printf "Checking that the board is running on $IP..."
+	ssh -o ConnectTimeout=5 $BBB_ADDRESS "date -s \"`date '+%Y%m%d %T'`\" > /dev/null" &&\
+		echo ok || { printf "no\nBela does not respond on " get_ip $BBB_ADDRESS", check that the board is connected, up and running and the IP address is correct"; return 1; } 
+}
+
+#start from here
+#create a shorthand alias for BELA_SAFE_MODE
+SAFE=$BELA_SAFE_MODE
+[ $SAFE -eq 1 ] && check_board_connected || exit
+OPT=$1
+shift
+case $OPT in
+run)
+##bela run ... -- runs the specified project. The project can be stored on the computer or on the board. 
+###bela run <projectName> <commandLineOptions> -- runs the project in a detachable screen
+	[ -z $1 ] && { usage run; echo "What project do you want to run?"; exit 1; }
+	PROJECT=$1
+	shift
+	RUNMODE=
+	#find if the next argument is a run mode or a command line options
+	case $1 in 
+	fg|foreground)
+###bela run fg <projectName> <commandLineOptions> -- runs project in the foreground
+		RUNMODE=-f
+		shift
+	;;
+	bg|background)
+###bela run bg <projectName> <commandLineOptions> -- runs project in the background
+		RUNMODE=-b
+		shift
+	;;
+	esac;
+	run $PROJECT "" "$RUNMODE" $*
+	exit $?
+;;
+heavy)
+##bela heavy ... -- runs a Pd patch with heavy
+###bela heavy <projectName> <commandLineOptions> -- runs <projectName> with <options> (optional)
+	[ -z $1 ] && { usage $OPT; echo "What project do you want to build with heavy?"; exit 1; }
+	echo TODO
+	exit 1;
+;;
+libpd | pyo)
+##bela libpd ... -- runs a Pd patch with libpd
+###bela libpd <projectName> <commandLineOptions> -- runs <projectName> with <options> (optional)
+##bela pyo ... -- runs a python pyo project
+###bela pyo <projectName> <commandLineOptions> -- runs <projectName> with <options> (optional)
+	[ -z $1 ] && { usage $OPT; echo "What project do you want to run with $OPT?"; exit 1; }
+	PD_PROJECT=$1
+	shift
+	run basic_${OPT} $PD_PROJECT "" $* 
+	exit $?
+;;
+info)
+##bela info <projectName> -- gives info on a project
+	echo TODO
+	exit 1;
+;;
+ide)
+##bela ide ... -- controls the bela IDE, which is accessible through a web browser
+	[ -z $1 ] && { usage ide; echo "What do you want to do with the ide?"; exit 1; }
+	OPT=$1
+	shift
+	T=
+	case $OPT in 
+	startup)
+###bela ide startup -- activates the IDE when the board boots
+###bela ide startup no -- disables the IDE at boot
+		[ -z $1 ] && MAKE_TARGET=idestartup ||\
+	   		{ [ no = $1 ] && MAKE_TARGET=idenostartup ||\
+	   			{ usage ide startup; echo "unknown option $1"; exit 1; }
+			}
+	;;
+	start)
+###bela ide start -- starts/restarts the IDE
+		MAKE_TARGET=idestart
+	;;
+	connect)
+###bela ide connect -- connects the terminal to the running IDE session. Useful for debugging
+		T=-t
+		MAKE_TARGET=ideconnect
+	;;
+	stop)
+###bela ide stop -- stops the IDE if it is currently running
+		MAKE_TARGET=idestop
+	;;
+
+	#TODO: open address
+	*)
+		usage ide; echo "What do you want to do with the ide?"; exit 1
+	esac
+	ssh $T $BBB_ADDRESS $MAKE_COMMAND $MAKE_TARGET
+	exit $?
+;;
+startup)
+##bela startup ... -- sets a project to run at boot 
+###bela startup <projectName> <commandLineOptions> -- sets a project to run at boot 
+###bela startup restart <projectName> <commandLineOptions> -- sets a project to run at boot and restarts it if it crashes.
+###bela startup no -- disables the project at boot
+	# startup can take a projectName (either local or remote) or "no" 
+	[ -z $1 ] && { usage startup; echo "What program do you want to run at startup?"; exit 1; } 
+	[ $1 = no ] && { ssh -t $BBB_ADDRESS $MAKE_COMMAND nostartup ; exit $?; }
+	TARGET=startup
+	[ $1 = restart ] && { TARGET=startuploop; shift; }
+	PROJECT=$1; shift
+	CL=$*
+	#TODO: check if PROJECT exists remotely, otherwise copy it from here
+	ssh $BBB_ADDRESS $MAKE_COMMAND startup PROJECT=$PROJECT CL="$CL"
+	exit $?
+;;
+stop)
+##bela stop -- stops the Bela project that is currently running (if any)
+	ssh $BBB_ADDRESS $MAKE_COMMAND stop
+	exit $?
+;;
+connect)
+##bela connect -- connects to the Bela project that is currently running in the background (if any)
+	ssh -t $BBB_ADDRESS $MAKE_COMMAND connect
+	exit $?
+;;
+shutdown)
+##bela shutdown -- safely shuts down the board
+	ssh $BBB_ADDRESS halt
+	exit $?
+;;
+date)
+##bela date -- sets the date on the board
+	check_board_connected $BBB_ADDRESS &&\
+		{ echo "Date set correctly"; exit 0; } ||\
+		{ echo "Error while setting the date. Current date on the board is `ssh $BBB_ADDRESS date`"; exit 1; } 
+;;
+esac
+usage
+
+#bela options projectName
+#bela update
+#bela update ide