#! /bin/bash # DESCRIPTION: # Handling Hikvision PTZ-cameras sequences. # Additionally: # - get ds18b20 sensor value over SSH, # - saving pictures to FTP. # This is only a local "proof of conept" for testing and debugging. # # DEPENDENCIES: # - curl # - sshpass # # PARAMETERS: # 1: "qn" - execution without pauses # 2: custom configuration file path # # FUNCTIONS: # ####################################### # Print message and add to log. # Globals: # logs # Arguments: # 1: message to print and logging ####################################### addtologs() { echo "$(date +'%Y.%m.%d-%H:%M:%S') $1" | tee -a "${logs}" } ####################################### # Waiting for press [ENTER]. # Globals: # None # Arguments: # None ####################################### execpause() { read -r -p "Press [ENTER] to continue... " } ####################################### # Exit procedure. # Globals: # show # Arguments: # None ####################################### execquite() { addtologs "execution time is $(($(date +%s)-time)) seconds, exit" if [ "${show}" != "qn" ]; then execpause fi exit } ####################################### # Error exit procedure with Telegram notification. # Globals: # telegramapiurl # telegramchatid # Arguments: # 1: message to print and logging ####################################### execerror() { addtologs "error: $1" curl -s -X POST "${telegramapiurl}/sendMessage" \ -d "chat_id=${telegramchatid}" \ -d "text=$(basename -s .sh "$0") error: $1" \ >> /dev/null 2>&1 execquite } ####################################### # Parsing config file and creating global vars. # Globals: # None # Arguments: # None ####################################### getconfig() { logs=$(grep "logs=" "${conf}" | cut -d= -f2) camuser=$(grep "camuser=" "${conf}" | cut -d= -f2) campass=$(grep "campass=" "${conf}" | cut -d= -f2) camaddr=$(grep "camaddr=" "${conf}" | cut -d= -f2) camport=$(grep "camport=" "${conf}" | cut -d= -f2) ftpuser=$(grep "ftpuser=" "${conf}" | cut -d= -f2) ftppass=$(grep "ftppass=" "${conf}" | cut -d= -f2) ftpaddr=$(grep "ftpaddr=" "${conf}" | cut -d= -f2) ftpport=$(grep "ftpport=" "${conf}" | cut -d= -f2) ftppath=$(grep "ftppath=" "${conf}" | cut -d= -f2) tmpuser=$(grep "tmpuser=" "${conf}" | cut -d= -f2) tmppass=$(grep "tmppass=" "${conf}" | cut -d= -f2) tmpaddr=$(grep "tmpaddr=" "${conf}" | cut -d= -f2) tmpport=$(grep "tmpport=" "${conf}" | cut -d= -f2) tmpnode=$(grep "tmpnode=" "${conf}" | cut -d= -f2) telegramapiurl=$(grep "telegramapiurl=" "${conf}" | cut -d= -f2) telegramchatid=$(grep "telegramchatid=" "${conf}" | cut -d= -f2) } ####################################### # Get ds18b20 sensor value over SSH. # Globals: # tmpaddr # tmpport # tmpuser # tmppass # tmpnode # Arguments: # None # return: # temperature in Celsius ####################################### getairtmp() { temp=$(sshpass -p "${tmppass}" \ ssh "${tmpuser}@${tmpaddr}" -p "${tmpport}" \ -o StrictHostKeyChecking=no -o ConnectTimeout=10 \ "cat /sys/bus/w1/devices/${tmpnode}/temperature" \ ) && temp=$((temp / 1000)) if [ -n "${temp}" ]; then addtologs "getairtmp: air temperature now is ${temp}'C" > /dev/null echo "${temp}" else execerror "getairtmp: air temperature now is ${temp}'C" fi } ####################################### # Get static picture from camera and upload to FTP. # Globals: # camaddr # camport # camuser # campass # ftpaddr # ftpport # ftppath # ftpuser # ftppass # Arguments: # 1: filename prefix ####################################### getcamimg() { local name name=$1 path="${ftppath}/$(date +"%Y")/$(date +"%m")/$(date +"%V")/$(date +"%d")" file="${ftpaddr}:${ftpport}/${path}/${name}_$(date +"%Y.%m.%d_%H-%M-%S").jpeg" url='Streaming/channels/101/picture?snapShotImageType=JPEG&videoResolutionWidth=1920&videoResolutionHeight=1080' if curl -vs "http://$camuser:$campass@$camaddr:$camport/$url" -o tmp \ && curl -T tmp "ftp://$ftpuser:$ftppass@$file" --ftp-create-dirs; then addtologs "getcamimg: save photo to ftp://${file}" rm tmp else execerror "getcamimg: save photo to ftp://${file}" fi } ####################################### # Set message as video overlay text. # Globals: # camaddr # camport # camuser # campass # Arguments: # 1: overlay text content ####################################### setcamtxt() { local message=$1 url='ISAPI/System/Video/inputs/channels/101/overlays/text' xml=' 1 true 00 '"${message}"' ' if curl -d "${xml}" -X PUT "http://$camuser:$campass@$camaddr:$camport/$url" \ | grep -q 'OK'; then addtologs "setcamtxt: ${message}" sleep 5 else execerror "setcamtxt: ${message}" fi } ####################################### # Set camera moving to absolute position. # Globals: # camaddr # camport # camuser # campass # Arguments: # 1: horisontal camera position from 0 to 3600 # 2: vertical camera position from -900 to 2700 # 3: zoom camera position from 0 to 1000 # 4: time to wait # 5: message to print and logging ####################################### setcampos() { local x=$1 local y=$2 local z=$3 local t=$4 local message=$5 url='ISAPI/PTZCtrl/channels/101/absolute' xml=' '"${y}"' '"${x}"' '"${z}"' ' if curl -d "${xml}" -X PUT "http://$camuser:$campass@$camaddr:$camport/$url" \ | grep -q 'OK'; then addtologs "setcampos: ${message}" sleep "${t}" else execerror "setcampos: ${message}" fi } ####################################### # Set camera moving to direction. # Globals: # camaddr # camport # camuser # campass # Arguments: # 1: acceleration of horizontal camera movement from -100 to 100 # 2: acceleration of vertical camera movement from -100 to 100 # 3: acceleration of zoom camera movement from -100 to 100 # 4: time to wait # 5: message to print and logging ####################################### setcammov() { local x=$1 local y=$2 local z=$3 local t=$4 local message=$5 url='ISAPI/PTZCtrl/channels/101/continuous' xml=' '"${x}"' '"${y}"' '"${z}"' ' if curl -d "${xml}" -X PUT "http://$camuser:$campass@$camaddr:$camport/$url" \ | grep -q 'OK'; then addtologs "setcammov: ${message}" sleep "${t}" else execerror "setcammov: ${message}" fi } # ## VARIABLES: # show=$1 conf=$2 if [ -z "${conf}" ] || [ "${conf}" == "-" ]; then conf="$(dirname "$(realpath "$0")")/$(basename -s .sh "$0").conf" fi time=$(date +%s) cd "$(dirname "$(realpath "$0")")" || execerror if [ ! -e "${conf}" ]; then execerror "Not found config file: ${conf}" else getconfig fi if [ -z "${logs}" ];then logs=/dev/null elif [ ! -e "${logs}" ];then touch "${logs}" fi if ! command -v curl &> /dev/null || ! command -v sshpass &> /dev/null; then execerror "Not found dependencies" fi # # MAIN: # setcamtxt "$(getairtmp)'C" setcampos 0 0 10 5.00s 'xx >| 01 Точка - Панорама центр 1x' sleep 1m setcamtxt '' && getcamimg 'point-01' && setcamtxt "$(getairtmp)'C" sleep 4m setcampos 395 0 10 5.00s '01 >| 02 Точка - Панорама право 1x' setcampos 2915 0 10 5.00s '02 >| 03 Точка - Панорама лево 1x' sleep 1m setcamtxt '' && getcamimg 'point-02' && setcamtxt "$(getairtmp)'C" sleep 4m setcammov 25 25 33 6.00s '03 >> 04 Точка - Дорожный переход 8x' setcampos 3060 -85 80 5.00s '03 >| 04 Точка - Дорожный переход 8x' sleep 5m setcammov 99 99 0 2.25s '04 >> 05 Точка - Поля 8x' setcampos 3208 -200 80 5.00s '04 >| 05 Точка - Поля 8x' setcampos 3208 -200 160 5.00s '05 >| 06 Точка - Поля 16x' setcammov -70 0 -33 3.00s '06 >> 07 Точка - Поля 4x' setcampos 3175 -200 40 5.00s '06 >| 07 Точка - Поля 4x' sleep 1m setcamtxt '' && getcamimg 'point-04' && setcamtxt "$(getairtmp)'C" sleep 4m setcampos 2860 -200 40 5.00s '07 >| 08 Точка - Стадион 4x' sleep 1m setcamtxt '' && getcamimg 'point-05' && setcamtxt "$(getairtmp)'C" sleep 4m setcammov 0 -44 33 1.50s '08 >> 09 Точка - Стадион 8x' setcampos 2860 -170 80 5.00s '08 >| 09 Точка - Стадион 8x' sleep 1m setcammov 0 -99 0 7.50s '09 >> 10 Точка - Въезд во двор 8x' setcampos 2805 200 80 5.00s '09 >| 10 Точка - Въезд во двор 8x' sleep 5m setcammov -88 99 0 5.00s '10 >> 11 Точка - Бассейн 8x' setcammov -99 88 0 2.00s '10 >> 11 Точка - Бассейн 8x' setcammov -44 99 0 4.25s '10 >> 11 Точка - Бассейн 8x' setcampos 2510 -20 80 5.00s '10 >| 11 Точка - Бассейн 8x' sleep 1m setcammov -88 99 33 2.50s '11 >> 12 Точка - Общежитие дальнее 16x' setcampos 2415 -200 160 5.00s '11 >| 12 Точка - Общежитие дальнее 16x' sleep 1m setcammov 66 0 0 22.5s '12 >> 13 Точка - Общежите ближнее 16x' setcampos 2640 -200 160 5.00s '12 >| 13 Точка - Общежите ближнее 16x' sleep 1m setcammov 66 0 0 90.5s '13 >> 14 Точка - Крыша магазина 4x' setcammov 99 0 -44 3.25s '13 >> 14 Точка - Крыша магазина 4x' setcampos 335 -200 40 5.00s '13 >| 14 Точка - Крыша магазина 4x' sleep 1m setcamtxt '' && getcamimg 'point-11' && setcamtxt "$(getairtmp)'C" sleep 4m setcammov -99 0 -33 2.50s '14 >> 15 Точка - Панорама верх 1x' setcampos 0 -200 10 5.00s '14 >| 15 Точка - Панорама верх 1x' sleep 1m setcamtxt '' && getcamimg 'point-12' && setcamtxt "$(getairtmp)'C" sleep 4m setcammov 0 -33 0 10.0s '15 >> 01 Точка - Панорама центр 1x' setcampos 0 0 10 5.00s '15 >| 01 Точка - Панорама центр 1x' execquite