#!/usr/bin/env bash # Crow's Nest # A multiple Cam and Stream Service for mainsailOS # Written by Stephan Wendel aka KwadFan # Copyright 2021 # https://github.com/mainsail-crew/crowsnest # GPL V3 # Version 2 ######## # shellcheck enable=requires-variable-braces ## disabeld SC2086 for some lines because there we want 'word splitting' set -e ## Debug # set -x # Global Vars BASE_USER=$(whoami) TITLE="crowsnest - A Webcam Daemon for Raspberry Pi OS" ### Non root if [ ${UID} == '0' ]; then echo -e "DO NOT RUN THIS SCRIPT AS ROOT!\nExiting..." exit 1 fi ### noninteractive Check if [ -z "${DEBIAN_FRONTEND}" ]; then export DEBIAN_FRONTEND=noninteractive fi ### Functions ### Messages ### Welcome Message function welcome_msg { echo -e "${TITLE}\n" echo -e "\tSome Parts of the Installer requires 'root' privileges." echo -e "\tYou will be prompted for your 'sudo' password, if needed.\n" } function detect_msg { echo -e "Found an existing 'webcamd'. This will be removed." echo -e "Since we dont use mjpg-streamer it will also removed." echo -e "You can use KIAUH for example to reinstall.\n" } function goodbye_msg { echo -e "\nInstallation complete.\n\tPlease reboot your machine!" echo -e "I hope you enjoy crowsnest, GoodBye ..." } ### Installer ### General ## These two functions are reused from custompios common.sh ## Credits to guysoft! ## https://github.com/guysoft/CustomPiOS function install_cleanup_trap() { # kills all child processes of the current process on SIGINT or SIGTERM trap 'cleanup' SIGINT SIGTERM } function cleanup() { # make sure that all child processed die when we die echo -e "Killed by user ...\r\nGoodBye ...\r" # shellcheck disable=2046 [ -n "$(jobs -pr)" ] && kill $(jobs -pr) && sleep 5 && kill -9 $(jobs -pr) } ## function err_exit { if [ "${1}" != "0" ]; then echo -e "ERROR: Error ${1} occured on line ${2}" echo -e "ERROR: Stopping $(basename "$0")." echo -e "Goodbye..." fi # shellcheck disable=2046 [ -n "$(jobs -pr)" ] && kill $(jobs -pr) && sleep 5 && kill -9 $(jobs -pr) exit 1 } ### Init ERR Trap trap 'err_exit $? $LINENO' ERR ### Import config from custompios. function import_config { if [ -f "${HOME}/crowsnest/custompios/crowsnest/config" ]; then # shellcheck source-path=file_templates/custompios/crowsnest/config source "$PWD"/custompios/crowsnest/config else echo -e "${TITLE}\n" echo -e "OOPS!\nConfiguration File missing! Exiting..." echo -e "Try to git clone a second time please ...\n" exit 1 fi } ### Detect webcamd. function detect_existing_webcamd { local remove if [ -x "/usr/local/bin/webcamd" ] && [ -d "${HOME}/mjpg-streamer" ]; then detect_msg read -rp "Do you want to remove existing 'webcamd'? (YES/NO) " remove if [ "${remove}" = "YES" ]; then echo -en "\nStopping webcamd.service ...\r" # sudo systemctl stop webcamd.service &> /dev/null echo -e "Stopping webcamd.service ... \t[OK]\r" remove_existing_webcamd else echo -e "\nYou answered '${remove}'! Installation will be aborted..." echo -e "GoodBye...\n" exit 1 fi fi } ### Remove existing webcamd function remove_existing_webcamd { if [ -x "/usr/local/bin/webcamd" ]; then echo -en "Removing 'webcamd' ...\r" sudo rm -f /usr/local/bin/webcamd > /dev/null echo -e "Removing 'webcamd' ... \t\t[OK]\r" fi if [ -d "${HOME}/mjpg-streamer" ]; then echo -en "Removing 'mjpg-streamer' ...\r" sudo rm -rf "${HOME}"/mjpg-streamer > /dev/null echo -e "Removing 'mjpg-streamer' ... \t[OK]\r" fi if [ -f "/etc/systemd/system/webcamd.service" ]; then echo -en "Removing 'webcamd.service' ...\r" sudo rm -f /etc/systemd/system/webcamd.service > /dev/null echo -e "Removing 'webcamd.service' ... \t[OK]\r" fi if [ -f "/var/log/webcamd.log" ]; then echo -en "Removing 'webcamd.log' ...\r" sudo rm -f /var/log/webcamd.log > /dev/null sudo rm -f "${HOME}"/klipper_logs/webcamd.log > /dev/null echo -e "Removing 'webcamd.log' ... \t[OK]\r" fi if [ -f "/etc/logrotate.d/webcamd" ]; then echo -en "Removing 'webcamd' logrotate...\r" sudo rm -f /etc/logrotate.d/webcamd > /dev/null echo -e "Removing 'webcamd' logrotate ... \t[OK]\r" fi echo -e "\nOld 'webcamd' completly removed." echo -e "webcam.txt kept,but no longer necessary ..." } ### Install Dependencies ## Enable buster-backports ( needed for golang-go > 1.11 ) function enable_backports { local template sources template="${HOME}/crowsnest/file_templates/buster-backports.list" sources="/etc/apt/sources.list.d/" if [ "$(grep -c "buster" /etc/apt/sources.list)" -ne "0" ]; then echo -e "\n'Debian 10 Buster' ( or based of ) detected ..." echo -e "We need to install Debian Backports for golang >=1.11\n" echo -en "Adding buster-backports to 'apt' ...\r" sudo cp "${template}" "${sources}" &> /dev/null echo -e "Adding buster-backports to 'apt' ... [OK]\r" echo -e "Adding buster-backports keyring to 'apt' ...\r" sudo apt-key adv --keyserver keyring.debian.org --recv-keys 648ACFD622F3D138 sudo apt-key adv --keyserver keyring.debian.org --recv-keys 0E98404D386FA1D9 echo -e "Adding buster-backports keyring to 'apt' ... [OK]\r" echo -e "\nRunning 'apt update' to initialize backports ..." sudo apt update fi } function install_crowsnest { local template servicefile logrotatefile bin_path webcamd_bin bin_path="/usr/local/bin" webcamd_bin="${HOME}/crowsnest/webcamd" template="$PWD/sample_configs/${CROWSNEST_DEFAULT_CONF}" servicefile="$PWD/file_templates/webcamd.service" logrotatefile="${HOME}/crowsnest/file_templates/logrotate_webcamd" echo -e "\nInstall webcamd Service ..." ## Install Dependencies echo -e "Installing 'crowsnest' Dependencies ..." # shellcheck disable=2086 sudo apt install --yes --no-install-recommends $CROWSNEST_CROWSNEST_DEPS > /dev/null echo -e "Installing 'crowsnest' Dependencies ... [OK]" ## Link webcamd to $PATH echo -en "Linking webcamd ...\r" sudo ln -sf "${webcamd_bin}" "${bin_path}" > /dev/null echo -e "Linking webcamd ... [OK]\r" ## Copy webcam.conf # Make sure not to overwrite existing! if [ ! -f "${CROWSNEST_DEFAULT_CONF_DIR}/webcam.conf" ]; then echo -en "Copying webcam.conf ...\r" # shellcheck disable=2086 sudo -u "${BASE_USER}" cp -rf $PWD/sample_configs/${CROWSNEST_DEFAULT_CONF} "${CROWSNEST_DEFAULT_CONF_DIR}"/webcam.conf echo -e "Copying webcam.conf ... [OK]\r" fi ## Link webcamd.service echo -en "Copying webcamd.service file ...\r" sudo cp -rf "${servicefile}" /etc/systemd/system/webcamd.service > /dev/null echo -e "Copying webcamd.service file ... [OK]\r" ## Link logrotate echo -en "Linking logrotate file ...\r" sudo cp -rf "${logrotatefile}" /etc/logrotate.d/webcamd echo -e "Linking logrotate file ... [OK]\r" echo -en "Reload systemd to enable new deamon ...\r" sudo systemctl daemon-reload echo -e "Reload systemd to enable new daemon ... [OK]" echo -en "Enable webcamd.service on boot ...\r" sudo systemctl enable webcamd.service echo -e "Enable webcamd.service on boot ... [OK]\r" } function install_ustreamer { local bin_path ustreamer_bin ustreamer_dump_bin ustreamer_bin="${HOME}/ustreamer/ustreamer" ustreamer_dump_bin="${HOME}/ustreamer/ustreamer-dump" bin_path="/usr/local/bin" echo -e "\nInstalling ustreamer ..." echo -e "Installing ustreamer Dependencies ..." # shellcheck disable=2086 sudo apt install --yes --no-install-recommends $CROWSNEST_USTREAMER_DEPS > /dev/null echo -e "Installing ustreamer Dependencies ... \t[OK]" echo -e "Cloning ustreamer Repo ..." pushd "${HOME}" > /dev/null git clone "${CROWSNEST_USTREAMER_REPO_SHIP}" --depth=1 popd > /dev/null echo -e "Cloning ustreamer Repo ... [OK]" pushd "${HOME}"/ustreamer > /dev/null echo -e "Compiling ustreamer ..." if [ "${CROWSNEST_USTREAMER_WITH_OMX}" = "y" ] && \ [ "${CROWSNEST_USTREAMER_WITH_GPIO}" = "y" ]; then echo -e "Compile ustreamer with OMX and GPIO Support..." WITH_OMX=1 WITH_GPIO=1 make -j"$(nproc)" elif [ "${CROWSNEST_USTREAMER_WITH_OMX}" = "y" ] && \ [ "${CROWSNEST_USTREAMER_WITH_GPIO}" = "n" ]; then echo -e "Compile ustreamer with OMX Support..." WITH_OMX=1 make -j"$(nproc)" else echo -e"Compile ustreamer without OMX and GPIO Support..." make -j"$(nproc)" fi popd > /dev/null echo -en "Linking ustreamer ...\r" sudo ln -sf "${ustreamer_bin}" "${bin_path}" > /dev/null sudo ln -sf "${ustreamer_dump_bin}" "${bin_path}" > /dev/null echo -e "Linking ustreamer ... [OK]\r" echo -e "Installing ustreamer ... [OK]" } function install_v4l2rtspserver { local bin_path v4l2rtsp_bin v4l2rtsp_bin="${HOME}/v4l2rtspserver/v4l2rtspserver" bin_path="/usr/local/bin" echo -e "\nInstalling v4l2rtspserver ..." echo -e "Installing v4l2rtspserver Dependencies ..." # shellcheck disable=2086 sudo apt install --yes --no-install-recommends $CROWSNEST_V4L2RTSP_DEPS > /dev/null echo -e "Installing v4l2rtspserver Dependencies ... \t[OK]" echo -e "Cloning v4l2rtspserver Repo ..." pushd "${HOME}" > /dev/null git clone "${CROWSNEST_V4L2RTSP_REPO_SHIP}" --depth=1 popd > /dev/null echo -e "Cloning v4l2rtspserver Repo ... [OK]" pushd "${HOME}"/v4l2rtspserver > /dev/null echo -e "Compiling v4l2rtspserver ..." cmake . && make -j"$(nproc)" popd > /dev/null echo -en "Linking v4l2rtspserver ...\r" sudo ln -sf "${v4l2rtsp_bin}" "${bin_path}" > /dev/null echo -e "Linking v4l2rtspserver ... [OK]\r" echo -e "Installing v4l2rtspserver ... [OK]" } ## Stay for later use. # function install_rtspsimple { # local bin_path rtsp_bin # bin_path="/usr/local/bin" # rtsp_bin="${CROWSNEST_RTSPSIMPLE_DIR}/rtsp-simple-server" # # We are using armv6l Version to be downwards compatible. # ## Install Dependencies # echo -e "Installing 'rtsp-simple-server' Dependencies ..." # sudo apt install --yes --no-install-recommends $CROWSNEST_RTSPSIMPLE_DEPS > /dev/null # echo -e "Installing 'rtsp-simple-server' Dependencies ... [OK]" # # Download Release Binary # echo -e "Download 'rtsp-simple-server' ..." # curl -o /tmp/rtsp-simple-server.tar.gz -L "${CROWSNEST_RTSPSIMPLE_RELEASE}" # echo -e "Download 'rtsp-simple-server' ... [OK]" # echo -en "Unpacking 'rtsp-simple-server' ...\r" # mkdir -p "${CROWSNEST_RTSPSIMPLE_DIR}" > /dev/null # tar xfz /tmp/rtsp-simple-server.tar.gz -C "${CROWSNEST_RTSPSIMPLE_DIR}" > /dev/null # echo -e "Unpacking 'rtsp-simple-server' ... [OK]" # echo -en "Linking 'rtsp-simple-server' ...\r" # sudo ln -sf "${rtsp_bin}" "${bin_path}" > /dev/null # echo -e "Linking 'rtsp-simple-server' ... [OK]\r" # } function install_raspicam_fix { sudo sh -c 'echo "bcm2835-v4l2" >> /etc/modules' } #### MAIN install_cleanup_trap import_config welcome_msg detect_existing_webcamd ## Golang not needed for now! # enable_backports echo -e "Running apt update first ..." sudo apt update install_crowsnest install_ustreamer install_v4l2rtspserver # install_rtspsimple install_raspicam_fix goodbye_msg exit 0