#!/usr/bin/env bash # Automated installer and updater for the WeatherFlow PiConsole. Modified # heavily from the PiHole and PiVPN installers. # Copyright (C) 2018-2023 Peter Davis # 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 . # DEFINE INSTALLER PREAMBLE # ------------------------------------------------------------------------------ # -e option instructs bash to immediately exit if any command [1] has a non-zero # exit status. set -e # Define installer colors if [[ -f "${coltable}" ]]; then source ${coltable} else COL_NC='\e[0m' COL_LIGHT_GREEN='\e[1;32m' COL_LIGHT_RED='\e[1;31m' COL_LIGHT_YELLOW='\e[1;33m' TICK="[${COL_LIGHT_GREEN}✓${COL_NC}]" CROSS="[${COL_LIGHT_RED}✗${COL_NC}]" EXCLAMATION="[${COL_LIGHT_YELLOW}!${COL_NC}]" INFO="[i]" DONE="${COL_LIGHT_GREEN} done!${COL_NC}" OVER="\\r\\033[K" fi # Find the number of rows and columns in terminal. Will default to 80x24 if it # can not be detected. if (tput lines &> /dev/null); then rows=$(tput lines) else rows=$(printf '%d' 80) fi if (tput cols &> /dev/null); then columns=$(tput cols) else columns=$(printf '%d' 24) fi # Divide the number of rows and columns by two so # the dialogs take up half of the screen. r=$(( rows / 2 )) c=$(( columns / 2 )) # Unless the screen is tiny r=$(( r < 20 ? 20 : r )) c=$(( c < 70 ? 70 : c )) # DEFINE INSTALLER VARIABLES # ------------------------------------------------------------------------------ # Download and install directories CONSOLEDIR=/home/${USER}/wfpiconsole VENVDIR=${CONSOLEDIR}/venv/ DLDIR=${CONSOLEDIR}/temp/ # Package manager commands PKG_MANAGER="apt-get" PKG_UPDATE_CACHE="${PKG_MANAGER} update" PKG_UPDATE_INSTALL="${PKG_MANAGER} dist-upgrade -y" PKG_UPDATE_COUNT="${PKG_MANAGER} -s -o Debug::NoLocking=true upgrade | grep -c ^Inst || true" PKG_NEW_INSTALL=(${PKG_MANAGER} --yes install) # Python commands PYTHON_SYS=python3 PYTHON_VENV=${VENVDIR}bin/python3 PIP_INSTALL="-m pip install --no-cache-dir" PIP_UPDATE="-m pip install --upgrade --no-cache-dir" # wfpiconsole and Kivy dependencies WFPICONSOLE_DEPENDENCIES=(git curl rng-tools build-essential python3-dev python3-pip python3-setuptools libssl-dev libffi-dev libatlas-base-dev libopenblas-dev jq) # Python modules and versions PYTHON_MODULES=(websockets==11.0.3 numpy==1.26.0 pytz==2023.3 tzlocal==5.1 ephem==4.1.5 packaging==23.2 cryptography==41.0.4 pyOpenSSL==23.2.0 certifi==2023.7.22) # Kivy source and version KIVY_VERSION="2.2.0" KIVY_SOURCE="kivy[base]=="$KIVY_VERSION # Github repositories WFPICONSOLE_REPO="https://github.com/peted-davis/WeatherFlow_PiConsole.git" WFPICONSOLE_TAGS="https://api.github.com/repos/peted-davis/WeatherFlow_PiConsole/tags" WFPICONSOLE_RAW="https://raw.githubusercontent.com/peted-davis/WeatherFlow_PiConsole" WFPICONSOLE_MAIN_UPDATE=$WFPICONSOLE_RAW"/main/wfpiconsole.sh" WFPICONSOLE_BETA_UPDATE=$WFPICONSOLE_RAW"/develop/wfpiconsole.sh" # CHECK IF INPUT IS VALID COMMAND # ------------------------------------------------------------------------------ is_command() { command -v "$1" >/dev/null 2>&1 } # CLEAN UP AFTER COMPLETED OR FAILED INSTALLATION # ------------------------------------------------------------------------------ clean_up() { rm -f python_command error_log module_list } # UPDATE LOCAL PACKAGES USING apt-get update # ------------------------------------------------------------------------------ update_packages() { # Update local package cache. Return error if cache cannot be updated local str="Checking for updated packages" printf " %b %s..." "${INFO}" "${str}" if (sudo ${PKG_UPDATE_CACHE} &> error_log); then # Alert user if there are updates to install updates_to_install=$(eval ${PKG_UPDATE_COUNT}) if [[ "$updates_to_install" -gt "0" ]]; then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" if [[ "$updates_to_install" -eq "1" ]]; then local str="$updates_to_install updated package available. Use 'sudo apt upgrade' to install" else local str="$updates_to_install updated packages available. Use 'sudo apt upgrade' to install" fi printf " %b %s\\n" "${INFO}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" local str="No updated packages found" printf " %b %s\\n" "${INFO}" "${str}" fi else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to update local package cache. Please check your internet connection\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$(/dev/null | grep "ok installed" &> /dev/null; then printf "%b %b Checking for %s\\n" "${OVER}" "${TICK}" "${i}" else echo -e "${OVER} ${INFO} Checking for $i (will be installed)" install_array+=("${i}") fi done # Only install dependent packages that are missing from the system to avoid # unecessary downloading if [[ "${#install_array[@]}" -gt 0 ]]; then if ! (sudo debconf-apt-progress --logfile error_log -- "${PKG_NEW_INSTALL[@]}" "${install_array[@]}"); then printf " %b\\nError: Unable to install dependent packages\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log); then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to install Python virtual environment\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log); then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to update Python package manager: pip\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log); then printf "%b %b %s %s\\n" "${OVER}" "${TICK}" "${str}" "${module}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to install Python module: $module\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( module_list # Update required Python modules for i in "${arg_array[@]}"; do module=$(echo $i | cut -d"[" -f 1 | cut -d"=" -f 1) required_version=$(echo $i | cut -d"=" -f 3) if grep -iF $module module_list &> /dev/null; then current_version=$(grep -iF $module module_list | cut -d"=" -f 3) if [[ "$current_version" != "$required_version" ]]; then local str="Updating Python module" printf " %b %s %s..." "${INFO}" "${str}" "${module}" if (${PYTHON_VENV} ${PIP_INSTALL} "$i" &> error_log); then printf "%b %b %s %s\\n" "${OVER}" "${TICK}" "${str}" "${module}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to update Python module: $module\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log); then printf "%b %b %s %s\\n" "${OVER}" "${TICK}" "${str}" "${module}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to install Python module: $module\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( /dev/null; then kivy_version=$(${PYTHON_VENV} -m pip show kivy | grep Version | cut -d" " -f2) if [[ "$KIVY_VERSION" == "$kivy_version" ]]; then printf "%b %b %s \\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s (will be updated)" "${OVER}" "${INFO}" "${str}" local update_kivy=true fi else printf "%b %b %s (will be installed)" "${OVER}" "${INFO}" "${str}" local install_kivy=true fi # Install Kivy Python library if [[ "$update_kivy" = true ]] || [[ "$install_kivy" = true ]]; then if [[ "$update_kivy" = true ]]; then local str="Updating Kivy Python library" else local str="Installing Kivy Python library" fi printf "\\n %b %s..." "${INFO}" "${str}" if (${PYTHON_VENV} ${PIP_INSTALL} ${KIVY_SOURCE} &> error_log); then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to install Kivy Python library\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log; then : else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to update Kivy configuration for touch screen\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$(> python_command echo "Config = configparser.ConfigParser()" >> python_command echo "Config.read('$config_file')" >> python_command echo "Config.remove_section('input')" >> python_command echo "Config.add_section('input')" >> python_command echo "Config.set('input','mouse','mouse')" >> python_command echo "Config.set('input','mtdev_%(name)s','probesysfs,provider=mtdev')" >> python_command echo "Config.set('input','hid_%(name)s','probesysfs,provider=hidinput')" >> python_command echo "with open('$config_file','w') as configfile:" >> python_command echo " Config.write(configfile)" >> python_command echo "configfile.close()" >> python_command # Run Python command to modify Kivy config for the Raspberry Pi touchscreen if (${PYTHON_VENV} python_command &> error_log); then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to update Kivy configuration for touch screen\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log || return $? fi git -C ${CONSOLEDIR} reset --hard "$(git -C ${CONSOLEDIR} describe --abbrev=0 --tags)" &> error_log || return $? fi return # Else, get the latest version of the WeatherFlow PiConsole else local str="Updating WeatherFlow PiConsole to ${COL_LIGHT_GREEN}${latest_version}${COL_NC}" printf "\\n\\n %b %b..." "${INFO}" "${str}" if (is_repo ${CONSOLEDIR}); then if (update_repo_latest_tag ${CONSOLEDIR} &> error_log); then status=1; fi else if (create_repo ${CONSOLEDIR} ${WFPICONSOLE_REPO} &> error_log); then status=1; fi fi if [[ $status -eq 1 ]]; then printf "%b %b %b\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %b\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to update WeatherFlow PiConsole\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log); then if (update_repo_latest_tag ${CONSOLEDIR} &> error_log); then status=1; fi else if (create_repo ${CONSOLEDIR} ${WFPICONSOLE_REPO} &> error_log); then status=1; fi fi if [[ $status -eq 1 ]]; then printf "%b %b %b\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %b\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to install WeatherFlow PiConsole\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log); then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to install wfpiconsole.service file\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log); then if (sudo systemctl start wfpiconsole &> error_log); then printf "%b %b %s\\n\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to enable WeatherFlow PiConsole service file\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log); then printf "%b %b %s\\n\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to disable WeatherFlow PiConsole service file\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$( error_log || local rc=$? else local rc=1 fi return "${rc:-0}" } # CREATE NEW GIT REPOSITORY AT LATEST MAIN BRANCH RELEASE # ------------------------------------------------------------------------------ create_repo() { # If the directory already exists, turn it into a git directory, otherwise # clone the git repository directly local directory=${1} local repository=${2} if [[ -d ${directory} ]]; then git clone --no-checkout ${repository} ${directory}/temp &> error_log || return $? mv ${directory}/temp/.git ${directory}/.git rmdir ${directory}/temp git -C ${directory} reset --hard HEAD &> error_log || return $? else git clone ${repository} ${directory} &> error_log || return $? fi # Checkout the main branch if required and reset code to latest tag local current_branch=$(git rev-parse --abbrev-ref HEAD) if [[ "${current_branch}" != "main" ]]; then git -C ${directory} checkout main &> error_log || return $? fi git -C ${directory} reset --hard "$(git -C ${directory} describe --abbrev=0 --tags)" &> error_log || return $? } # UPDATE GIT REPOSITORY TO LATEST MAIN BRANCH RELEASE # ------------------------------------------------------------------------------ update_repo_latest_tag() { # Clear all changes from files that are tracked in the local git repository # and remove Python bytecode local directory=${1} find ${directory} -type d -name __pycache__ -exec rm -r {} + git -C ${directory} checkout . &> error_log || return $? # Checkout the main branch if required and pull latest commits. Reset code # to most recent release local current_branch=$(git -C ${directory} rev-parse --abbrev-ref HEAD) if [[ "${current_branch}" != "main" ]]; then git -C ${directory} checkout main &> error_log || return $? fi git -C ${directory} pull &> error_log || return $? # Remove all untracked files and folders git -C ${directory} clean --force -d &> error_log || true } # SWITCH GIT REPOSITORY TO LATEST MAIN BRANCH COMMIT # ------------------------------------------------------------------------------ switch_repo_stable() { # Clear all changes from files that are tracked in the local git repository # and remove Python bytecode local directory=${1} find ${directory} -type d -name __pycache__ -exec rm -r {} + git -C ${directory} checkout . &> error_log || return $? # Checkout the main branch if required and pull latest commits local current_branch=$(git -C ${directory} rev-parse --abbrev-ref HEAD) if [[ "${current_branch}" != "main" ]]; then git -C ${directory} checkout main &> error_log || return $? fi git -C ${directory} pull &> error_log || return $? # Remove all untracked files and folders git -C ${directory} clean --force -d &> error_log || true } # SWITCH GIT REPOSITORY TO LATEST DEVELOP BRANCH COMMIT # ------------------------------------------------------------------------------ switch_repo_beta() { # Clear all changes from files that are tracked in the local git repository # and remove Python bytecode local directory=${1} find ${directory} -type d -name __pycache__ -exec rm -r {} + git -C ${directory} checkout . &> error_log || return $? # Checkout the develop branch if required and pull latest commits local current_branch=$(git -C ${directory} rev-parse --abbrev-ref HEAD) if [[ "${current_branch}" != "develop" ]]; then git -C ${directory} checkout develop &> error_log || return $? fi git -C ${directory} pull &> error_log || return $? # Remove all untracked files and folders git -C ${directory} clean --force -d &> error_log || true } # DISPLAY REQUIRED PROCESS STARTING DIALOGUE # ------------------------------------------------------------------------------ process_starting() { # Display installation starting dialogue case $1 in install) whiptail --msgbox --backtitle "Welcome" --title "WeatherFlow PiConsole automated installer" \ "\\n\\nThanks for checking out the WeatherFlow PiConsole. This script will guide you through the installation process on your Raspberry Pi." ${r} ${c} printf "\\n" printf " ================================ \\n" printf " Installing WeatherFlow PiConsole \\n" printf " ================================ \\n\\n" ;; # Display update starting dialogue run_update) printf "\\n" printf " ============================== \\n" printf " Updating WeatherFlow PiConsole \\n" printf " ============================== \\n\\n" ;; # Display stable starting dialogue stable) printf "\\n" printf " ============================== \\n" printf " Switching to the stable branch \\n" printf " ============================== \\n\\n" ;; # Display update starting dialogue run_beta) printf "\\n" printf " ============================ \\n" printf " Switching to the beta branch \\n" printf " ============================ \\n\\n" ;; # Display autostart-enable starting dialogue autostart-enable) printf "\\n" printf " ====================================== \\n" printf " Enabling console autostart during boot \\n" printf " ====================================== \\n\\n" ;; # Display autostart-disable starting dialogue autostart-disable) printf "\\n" printf " ======================================= \\n" printf " Disabling console autostart during boot \\n" printf " ======================================= \\n\\n" esac } # DISPLAY REQUIRED PROCESS COMPLETE DIALOGUE # ------------------------------------------------------------------------------ process_complete() { # Display installation complete dialogue case $1 in install) printf " \\n" printf " ============================================ \\n" printf " WeatherFlow PiConsole installation complete! \\n" printf " Start the console with: 'wfpiconsole start' \\n" printf " ============================================ \\n\\n" ;; # Display update complete dialogue run_update) printf " \\n" printf " ============================================= \\n" printf " WeatherFlow PiConsole update complete! \\n" printf " Restart the console with: 'wfpiconsole start' \\n" printf " or 'wfpiconsole autostart-enable' \\n" printf " ============================================= \\n\\n" ;; # Display patch complete dialogue stable) printf " \\n" printf " ============================================= \\n" printf " Switch to stable branch complete! \\n" printf " Restart the console with: 'wfpiconsole start' \\n" printf " or 'wfpiconsole autostart-enable' \\n" printf " ============================================= \\n\\n" ;; # Display beta complete dialogue run_beta) printf " \\n" printf " ============================================= \\n" printf " Switch to beta branch complete! \\n" printf " Restart the console with: 'wfpiconsole start' \\n" printf " or 'wfpiconsole autostart-enable' \\n" printf " ============================================= \\n\\n" ;; # Display autostart-enable complete dialogue autostart-enable) printf " ==================================================== \\n" printf " WeatherFlow PiConsole autostart sucesfully enabled \\n" printf " Console will now start automatically at boot up \\n" printf " Starting console for current session. Please wait... \\n" printf " ==================================================== \\n\\n" ;; # Display autostart-disable complete dialogue autostart-disable) printf " =================================================== \\n" printf " WeatherFlow PiConsole autostart sucesfully disabled \\n" printf " Use 'wfpiconsole stop' to halt current session \\n" printf " =================================================== \\n\\n" esac } # START THE WeatherFlow PiConsole # ------------------------------------------------------------------------------ start () { cd $CONSOLEDIR && rm -f wfpiconsole.log ${PYTHON_VENV} main.py |& tee wfpiconsole.log } # STOP THE WeatherFlow PiConsole # ------------------------------------------------------------------------------ stop () { if (sudo systemctl | grep wfpiconsole.service &> error_log); then sudo systemctl stop wfpiconsole.service else pkill -HUP -f main.py fi clean_up } # INSTALL THE WeatherFlow PiConsole # ------------------------------------------------------------------------------ install() { # Display installation starting dialogue process_starting ${FUNCNAME[0]} # Check for and ask user if they wish to install any updated local packages update_packages # Install required packages install_packages # Install Python virtual environment install_python_venv # Install required Python modules install_python_modules # Install Kivy Python library install_kivy # Get the latest version of the WeatherFlow PiConsole and install get_latest_version # Edit and install wfpiconsole.service file install_service_file # Clean up after update clean_up # Display installation complete dialogue process_complete ${FUNCNAME[0]} } # UPDATE THE WeatherFlow PiConsole TO THE LATEST STABLE VERSION # ------------------------------------------------------------------------------ update() { # Fetch the latest update code directly from the main Github branch. This # ensures that changes in dependencies are addressed during this update curl -sSL $WFPICONSOLE_MAIN_UPDATE | bash -s run_update } run_update() { # Display installation starting dialogue process_starting ${FUNCNAME[0]} # Check for and ask user if they wish to install any updated local packages update_packages # Check if any new dependencies are required install_packages # Install Python virtual environment install_python_venv # Update Python modules as required update_python_modules # Install Kivy Python library install_kivy # Get the latest version of the WeatherFlow PiConsole and install get_latest_version # Edit and install wfpiconsole.service file install_service_file # Clean up after installation clean_up # Display update complete dialogue process_complete ${FUNCNAME[0]} } # SWITCH THE WeatherFlow PiConsole TO THE STABLE BRANCH # ------------------------------------------------------------------------------ stable() { # Display installation starting dialogue process_starting ${FUNCNAME[0]} # Get the latest patch for the WeatherFlow PiConsole and install switch_stable_branch # Clean up after installation clean_up # Display update complete dialogue process_complete ${FUNCNAME[0]} } # SWITCH THE WeatherFlow PiConsole TO THE BETA BRANCH # ------------------------------------------------------------------------------ beta() { # Fetch the latest beta update code directly from the develop Github branch. # This ensures that changes in dependencies are addressed during this update curl -sSL $WFPICONSOLE_BETA_UPDATE | bash -s run_beta } run_beta() { # Display installation starting dialogue process_starting ${FUNCNAME[0]} # Check for and ask user if they wish to install any updated local packages update_packages # Check if any new dependencies are required install_packages # Install Python virtual environment install_python_venv # Update Python modules as required update_python_modules # Install Kivy Python library install_kivy # Switch to the WeatherFlow PiConsole beta branch switch_beta_branch # Clean up after installation clean_up # Display update complete dialogue process_complete ${FUNCNAME[0]} } # SET THE WeatherFlow PiConsole TO START AUTOMATICALLY # ------------------------------------------------------------------------------ autostart-enable () { # Display autostart-enable starting dialogue process_starting ${FUNCNAME[0]} # Enable wfpiconsole service enable_service # Clean up after enabling autostart clean_up # Display autostart-enable complete dialogue process_complete ${FUNCNAME[0]} } # DISABLE THE WeatherFlow PiConsole FROM STARTING AUTOMATICALLY # ------------------------------------------------------------------------------ autostart-disable () { # Display autostart-disable starting dialogue process_starting ${FUNCNAME[0]} # Disable wfpiconsole service disable_service # Clean up after disabling autostart clean_up # Display autostart-disable complete dialogue process_complete ${FUNCNAME[0]} } # SCRIPT USAGE # ------------------------------------------------------------------------------ help_func() { echo "Usage: wfpiconsole [options] Example: 'wfpiconsole update' Options: start : Start the WeatherFlow PiConsole stop : Stop the WeatherFlow PiConsole install : Install the WeatherFlow PiConsole update : Update the WeatherFlow PiConsole stable : Switch the WeatherFlow PiConsole to the stable branch beta : Switch the WeatherFlow PiConsole to the beta branch autostart-enable : Set the WeatherFlow PiConsole to autostart at boot autostart-disable : Stop the WeatherFlow PiConsole autostarting at boot" exit 0 } # SCRIPT CALLED WITH NO ARGUMENTS. PRINT HELP FUNCTION # ------------------------------------------------------------------------------ if [ $# -eq 0 ]; then printf "Unrecognised usage\\n" help_func fi # ENSURE ROOT ACCESS IS AVAILABLE # ------------------------------------------------------------------------------ # Ensure script has not been called from an elevated prompt or with sudo if [[ "${EUID}" -eq 0 ]]; then printf "\\n" printf " %bError: Unable to $1 the WeatherFlow PiConsole.\\n\\n%b" "${COL_LIGHT_RED}" "${COL_NC}" printf " This script is not designed for elevated privileges\\n" printf " Please run this script again with as a regular user\\n\\n" clean_up exit 1 fi # Ensure sudo command is available and script can be elevated to root privileges if [[ ! -x "$(command -v sudo)" ]]; then printf "\\n" printf " %bError: Unable to $1 the WeatherFlow PiConsole.\\n\\n%b" "${COL_LIGHT_RED}" "${COL_NC}" printf " sudo is needed to $1 the WeatherFlow PiConsole\\n" printf " Please install sudo and run this script again Pi\\n\\n" clean_up exit 1 fi if [[ "${1}" != "start" ]]; then if (sudo true); then if [[ "${1}" != "stop" ]] && [[ "${1}" != "update" ]] && [[ "${1}" != "beta" ]]; then printf "\\n %b Root user check passed\\n" "${TICK}" fi else printf "\\n %b %b Root user check failed\\n" "${OVER}" "${CROSS}" printf " %bError: Unable to ${1} the WeatherFlow PiConsole \\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "\\n" clean_up exit 1 fi fi # CHECK OS/HARDWARE AND ADD REQUIRED REPOSITORIES WHEN INSTALL OR UPDATING # ------------------------------------------------------------------------------ if [[ "${1}" == "install" ]] || [[ "${1}" == "run_update" ]] || [[ "${1}" == "run_beta" ]] || [[ "${1}" == "stable" ]] ; then # Check compatability of architecture/OS/Raspberry Pi ARCHITECTURE=$(dpkg --print-architecture) if [[ $ARCHITECTURE = armhf ]] || [[ $ARCHITECTURE = x86_64 ]] || [[ $ARCHITECTURE = i*86 ]]; then printf " %b Architecture check passed (%b)\\n" "${TICK}" "${ARCHITECTURE}" elif [[ $ARCHITECTURE = arm64 ]] || [[ $ARCHITECTURE = amd64 ]]; then printf " %b Architecture check warning (%b)\\n" "${EXCLAMATION}" "${ARCHITECTURE}" else printf " %b Architecture check failed (%b)\\n\\n" "${CROSS}" "${ARCHITECTURE}" clean_up exit 1 fi MODEL_FILE=/proc/device-tree/model if [ -f $MODEL_FILE ]; then HARDWARE=$(tr -d '\0' < $MODEL_FILE) if [[ $HARDWARE == *"Raspberry Pi 3"* ]] || [[ $HARDWARE == *"Raspberry Pi 4"* ]] ; then SUPPORTED_RASPBERRY_PI="true" else SUPPORTED_RASPBERRY_PI="false" fi fi OS=$(. /etc/os-release && echo $PRETTY_NAME) if [[ $HARDWARE == *"Raspberry Pi"* ]] && [[ $OS == *"buster"* ]]; then printf " %b OS check failed (%b)\\n\\n" "${CROSS}" "${OS}" printf " %b ERROR: The latest version of the PiConsole is no longer\\n" "${CROSS}" printf " compatible with Raspberry Pi OS (Buster). Please upgrade\\n" printf " your OS\\n\\n" clean_up exit 1 elif is_command apt-get ; then printf " %b OS check passed (%b)\\n" "${TICK}" "${OS}" else printf " %b OS check failed (%b)\\n\\n" "${CROSS}" "${OS}" clean_up exit 1 fi if [[ $SUPPORTED_RASPBERRY_PI == "true" ]]; then printf " %b Raspberry Pi check passed (%b)\\n" "${TICK}" "${HARDWARE}" elif [[ $SUPPORTED_RASPBERRY_PI == "false" ]]; then printf " %b Raspberry Pi check warning (%b)\\n" "${EXCLAMATION}" "${HARDWARE}" fi # Print warning if unsupported architecture/Raspberry Pi detected if [[ $ARCHITECTURE = arm64 ]] || [[ $ARCHITECTURE = amd64 ]] || [[ $SUPPORTED_RASPBERRY_PI == "false" ]]; then printf "\n %b WARNING: unsupported architecture or Raspberry Pi detected\n" "${EXCLAMATION}" printf " No support is available for errors encountered while running\n" printf " the PiConsole\n" fi # Add "universe" repository when running Ubtuntu if required if echo $OS | grep -iF "Ubuntu" &> /dev/null; then if ! (find /etc/apt/ -name *.list | xargs cat | grep universe &> /dev/null); then str="Enabling Universe repository in Ubuntu" printf " %b %s..." "${INFO}" "${str}" if (sudo add-apt-repository universe &> error_log); then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf " %bError: Unable to enabling Universe repository.\\n\\n %b" "${COL_LIGHT_RED}" "${COL_NC}" printf "%s\\n\\n" "$(