#!/bin/bash
#
# octoscript - control octoprint from the command line.
#
# (C) 2013 algspd https://github.com/algspd/OctoScript
# (C) 2014 Aleph Objects, Inc. <code@alephobjects.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Originally by algspd, updated by Aleph Objects to new 1.2 API and extended.
# https://media.readthedocs.org/pdf/octoprint/latest/octoprint.pdf
# http://octoprint.readthedocs.org/en/latest/api/
#

APIKEY=19A7C56E31B74257955E49E5561D019D
HOST=127.0.0.1
PORT=8080
DEV=/dev/ttyACM0
BAUD=115200
COOKIES=/usr/local/share/octoscript/cookies.txt
OCTOSCRIPT=$0
MODE=$1

function usage {
  echo -en "Usage: $0 [MODE] [OPTIONS]

  MODE			OPTIONS
  ====			=======
  - connect		Connect to printer
  - disconnect		Disconnect from printer
  - files		Show details about uploaded files
  - list		List uploaded files
  - upload <FILE>	Upload local <FILE> to octoprint
  - select <NAME>	Select previously uploaded <NAME> for printing
  - print <NAME>	Select previously uploaded <NAME> and start printing
  - delete <NAME>	<NAME> will be removed
  - state		Get extensive printer state information
  - operation		Returns current operational state
  - connection		Get info about printer connection
  - jogx <N>		Jog X axis by N
  - jogy <N>		Jog Y axis by N
  - jogz <N>		Jog Z axis by N
  - jog <N> <N> <N>	Jog printer by X, Y, Z
  - home <AXES>		Home <AXES>. Can be one axes or multiple axis.
  - temp		Get hot end temperature
  - temp <N>		Set hot end temperature to N
  - bedtemp		Get bed temperature
  - bedtemp <N>		Set bed temperature to N (takes ~5 seconds to work)
  - extrude <N>		Extrude N mm
  - retract <N>		Retract N mm
  - start		Start print
  - restart		Restart print
  - pause		Pause print
  - cancel		Cancel print
  - job			Get current print job info

  Example usage:
  $0 connect
  $0 home xy
  $0 jogx 50
  $0 upload widget.gcode
  $0 list
  $0 temp 210
  $0 bedtemp 60
  $0 print widget.gcode
  $0 job
  $0 disconnect

"
  exit 1 
}

if [ $# -lt 1 ] ; then usage ; fi

case $MODE in
#############################################################
##                                                         ##
##  JOB                                                    ##
##                                                         ##
#############################################################
job)
  curl									\
	--get								\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/job"
  echo
;;
#############################################################
##                                                         ##
##  START                                                ##
##                                                         ##
#############################################################
start)
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"start"}'	\
	"http://$HOST:$PORT/api/job"

  echo -e "\nStarting..."
;;
#############################################################
##                                                         ##
##  RESTART                                                ##
##                                                         ##
#############################################################
restart)
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"restart"}'	\
	"http://$HOST:$PORT/api/job"

  echo -e "\nRestarting..."
;;
#############################################################
##                                                         ##
##  PAUSE                                                  ##
##                                                         ##
#############################################################
pause)
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"pause"}'	\
	"http://$HOST:$PORT/api/job"

  echo -e "\nPausing..."
;;
#############################################################
##                                                         ##
##  CANCEL                                                 ##
##                                                         ##
#############################################################
cancel)
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"cancel"}'	\
	"http://$HOST:$PORT/api/job"

  echo -e "\nCancelling..."
;;
#############################################################
##                                                         ##
##  TEMP                                                   ##
##                                                         ##
#############################################################
temp)

# No temperature specified, so get current temp
  if [ $# == 1 ]; then 
  curl									\
	--get								\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/printer/tool"				\
	2> /dev/null | grep -e '"actual":' -e '"target":'		\
	| sed 's/    //; s/,//;  s/\"//g'
  fi

  if [ $# -gt 1 ]; then 
  echo
  TOOL0=$2
  TOOL1=0	# only one toolhead

# If octoprint doesn't appear to be running, poll for 30 seconds
  STATE=`$OCTOSCRIPT operation`
  i=0
  while [[ -z $STATE ]] ; do echo -e "\nOctoprint isn't running" ;
    let i=$i+1
      if [ $i -gt 30 ]
        then echo -e "\nStill not running after 30 seconds, aborting..."
        exit
     fi
    sleep 1
    STATE=`$OCTOSCRIPT operation`
  done

# If the printer is in "Connecting" state, poll for 30 seconds
  STATE=`$OCTOSCRIPT operation`
  i=0
  while [ $STATE == "Connecting" ] ; do echo -e "\nStill connecting..." ;
    let i=$i+1
      if [ $i -gt 30 ]
        then echo -e "\nStill connecting after 30 seconds, aborting..."
        exit
     fi
    sleep 1
    STATE=`$OCTOSCRIPT operation`
  done

# Only set the temp if printer is operational
    STATE=`$OCTOSCRIPT operation`
  if [ $STATE == "Operational" ] ; then echo -e "\nOk, operational can set temp"
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"target","targets":{"tool0": '"$TOOL0"',"tool1": '"$TOOL1"'}}'	\
	"http://$HOST:$PORT/api/printer/tool"

  echo -e "\nSetting hot end temperature to $TOOL0"
  fi
  fi
;;
#############################################################
##                                                         ##
##  BEDTEMP                                                ##
##                                                         ##
#############################################################
bedtemp)
# No temperature specified, so get current temp
  if [ $# == 1 ]; then 
  curl									\
	--get								\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/printer/bed"				\
	2> /dev/null | grep -e '"actual":' -e '"target":'		\
	| sed 's/    //; s/,//;  s/\"//g'
  fi

# A temperature was given, so set bed temperature
  if [ $# -gt 1 ]; then 
  STATE=`$OCTOSCRIPT operation`
  i=0
# If octoprint doesn't appear to be running, poll for 30 seconds
  while [[ -z $STATE ]] ; do echo -e "\nOctoprint isn't running" ;
    let i=$i+1
      if [ $i -gt 30 ]
        then echo -e "\nStill not running after 30 seconds, aborting..."
        exit
     fi
    sleep 1
    STATE=`$OCTOSCRIPT operation`
  done
# If the printer is in "Connecting" state, poll for 30 seconds
  STATE=`$OCTOSCRIPT operation`
  i=0
  while [ $STATE == "Connecting" ] ; do echo -e "\nStill connecting..." ;
    let i=$i+1
      if [ $i -gt 30 ]
        then echo -e "\nStill connecting after 30 seconds, aborting..."
        exit
     fi
    sleep 1
    STATE=`$OCTOSCRIPT operation`
  done
# Only set the temp if printer is operational
  STATE=`$OCTOSCRIPT operation`
  if [ $STATE == "Operational" ] ; then echo -e "\nOk, operational can set temp"
  BED=$2
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"target","target": '"$BED"'}'	\
	"http://$HOST:$PORT/api/printer/bed"

  echo -e "\nSetting bed temperature to $BED"
  fi
fi
;;
#############################################################
##                                                         ##
##  RETRACT                                                ##
##                                                         ##
#############################################################
retract)
  if [ $# -lt 2 ]; then usage ; fi
  RETRACT=$2
  if test $RETRACT -gt 0 ; then RETRACT=-$RETRACT ; fi # Make it negative num
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"extrude","amount": '"$RETRACT"'}'	\
	"http://$HOST:$PORT/api/printer/tool"

  echo -e "\nRETRACTING $RETRACT of filament."
;;
#############################################################
##                                                         ##
##  EXTRUDE                                                ##
##                                                         ##
#############################################################
extrude)
  if [ $# -lt 2 ]; then usage ; fi
  EXTRUDE=$2
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"extrude","amount": '"$EXTRUDE"'}'	\
	"http://$HOST:$PORT/api/printer/tool"

  echo -e "\nExtruding $EXTRUDE of filament."
;;
#############################################################
##                                                         ##
##  HOME                                                   ##
##                                                         ##
#############################################################
home)
  if [ $# -lt 2 ]; then usage ; fi
  AXES=$2
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"home","axes":"'"$AXES"'"}'				\
	"http://$HOST:$PORT/api/printer/printhead"

  echo
;;
#############################################################
##                                                         ##
##  JOG                                                    ##
##                                                         ##
#############################################################
jog)
  if [ $# -lt 4 ]; then usage ; fi
  X=$2
  Y=$3
  Z=$4
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"jog","x": '"$X"',"y": '"$Y"',"z": '"$Z"'}'						\
	"http://$HOST:$PORT/api/printer/printhead"

  echo
;;
#############################################################
##                                                         ##
##  JOGX                                                   ##
##                                                         ##
#############################################################
jogx)
  if [ $# -lt 2 ]; then usage ; fi
  X=$2
  Y=0
  Z=0
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"jog","x": '"$X"',"y": '"$Y"',"z": '"$Z"'}'						\
	"http://$HOST:$PORT/api/printer/printhead"
  echo
;;
#############################################################
##                                                         ##
##  JOGY                                                   ##
##                                                         ##
#############################################################
jogy)
  if [ $# -lt 2 ]; then usage ; fi
  X=0
  Y=$2
  Z=0
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"jog","x": '"$X"',"y": '"$Y"',"z": '"$Z"'}'						\
	"http://$HOST:$PORT/api/printer/printhead"
  echo
;;
#############################################################
##                                                         ##
##  JOGZ                                                   ##
##                                                         ##
#############################################################
jogz)
  if [ $# -lt 2 ]; then usage ; fi
  X=0
  Y=0
  Z=$2
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"jog","x": '"$X"',"y": '"$Y"',"z": '"$Z"'}'						\
	"http://$HOST:$PORT/api/printer/printhead"
  echo
;;
#############################################################
##                                                         ##
##  DELETE                                                 ##
##                                                         ##
#############################################################
delete)
  if [ $# -lt 2 ]; then usage; fi
  ARGFILE=$2
  curl									\
	--request DELETE						\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/files/local/$ARGFILE"

  echo
;;
#############################################################
##                                                         ##
##  SELECT                                                 ##
##                                                         ##
#############################################################
select)
  if [ $# -lt 2 ]; then
    usage
  fi
  ARGFILE=$2
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"select"}'						\
	"http://$HOST:$PORT/api/files/local/$ARGFILE"

  echo
;;
#############################################################
##                                                         ##
##  PRINT                                                  ##
##                                                         ##
#############################################################
print)
  if [ $# -lt 2 ]; then usage ; fi
ARGFILE=$2
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"select","print":true}'				\
	"http://$HOST:$PORT/api/files/local/$ARGFILE"

  echo
;;
#############################################################
##                                                         ##
##  UPLOAD                                                 ##
##                                                         ##
#############################################################
upload)
  if [ $# -lt 2 ]; then usage ; fi
  ARGFILE=$2
  filename=$(basename "$ARGFILE")
  extension="${filename##*.}"
  filename="${filename%.*}"
  if [[ $extension != gcode ]] && [[ $extension != g ]] && [[ $extension != gco ]];then
    echo "WARNING: You should name files like \"$filename.gcode\", \"$filename.g\", or \"$filename.gco\""
  fi
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "X-Api-Key: $APIKEY"					\
	--form								\
	"file=@$ARGFILE"						\
	--form "select=false"						\
	--form "print=false"						\
	"http://$HOST:$PORT/api/files/local"
  echo
;;
#############################################################
##                                                         ##
##  OPERATION                                              ##
##                                                         ##
#############################################################
operation)
  curl									\
	--get								\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/connection"				\
	2> /dev/null | grep -e '"state":'				\
	| sed 's/    //; s/,//;  s/\"//g'				\
	| cut -f 2 -d " " 
;;
#############################################################
##                                                         ##
##  CONNECTION                                             ##
##                                                         ##
#############################################################
connection)
  curl									\
	--get								\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/connection"
  echo
;;
#############################################################
##                                                         ##
##  STATE                                                  ##
##                                                         ##
#############################################################
state)
  curl									\
	--get								\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/printer"
  echo
;;
#############################################################
##                                                         ##
##  FILES                                                  ##
##                                                         ##
#############################################################
files)
  curl									\
	--get								\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/files"
;;
#############################################################
##                                                         ##
##  LIST                                                   ##
##                                                         ##
#############################################################
list)
  curl									\
	--get								\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	"http://$HOST:$PORT/api/files"					\
	2> /dev/null | grep '"name":' | sed 's/.*: "// ; s/",//'
;;
#############################################################
##                                                         ##
##  CONNECT                                                ##
##                                                         ##
#############################################################
connect)
STATE=`$OCTOSCRIPT operation`
  if [[ -z $STATE ]] ; then echo -e "\nOctoprint isn't running" ; exit ; fi
  if [ $STATE == "Operational" ] ; then echo -e "\nAlready connected" ; exit ; fi
  if [ $STATE == "Connecting" ] ; then echo -e "\nAlready connecting" ; exit ; fi
  if [ $STATE == "Closed" ] ; then \
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"connect","port":"'"$DEV"'","baudrate": '"$BAUD"',"save":true,"autoconnect":true}'	\
	"http://$HOST:$PORT/api/connection"

	echo -e "\nConnecting..."
  fi
;;
#############################################################
##                                                         ##
##  DISCONNECT                                             ##
##                                                         ##
#############################################################
disconnect)
  curl									\
	--request POST							\
	--cookie $COOKIES						\
	--header "Content-Type: application/json"			\
	--header "X-Api-Key: $APIKEY"					\
	--data								\
	'{"command":"disconnect"}'					\
	"http://$HOST:$PORT/api/connection"

	echo -e "\nDisconnecting..."
;;
#############################################################
##                                                         ##
##  USAGE                                                  ##
##                                                         ##
#############################################################
*)
usage
;;
esac

#############################################################
##                                                         ##
##  TODO                                                   ##
##                                                         ##
#############################################################
# SD Print, upload, delete
# User keys
# Get file info
# Set up for second extruder
# Arbitrary gcode commands (not in current API?)
