diff --git a/examples/install-service.sh b/examples/install-service.sh index 7da0f41..61988df 100755 --- a/examples/install-service.sh +++ b/examples/install-service.sh @@ -1,268 +1,127 @@ -#!/bin/bash +#!/usr/bin/env bash +set -euo pipefail + +# Fan SHIM Installer for Debian 12+ +# Updated for Python 3.11–3.13 compatibility -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" ON_THRESHOLD=65 OFF_THRESHOLD=55 -HYSTERESIS=5 DELAY=2 +BRIGHTNESS=255 +LOW_TEMP=$OFF_THRESHOLD +HIGH_TEMP=$ON_THRESHOLD PREEMPT="no" -POSITIONAL_ARGS=() NOLED="no" NOBUTTON="no" -BRIGHTNESS=255 EXTCOLOURS="no" -PYTHON="python3" -PIP="pip3" PSUTIL_MIN_VERSION="5.6.7" - -ON_THRESHOLD_SET=false -OFF_THRESHOLD_SET=false - -SERVICE_PATH=/etc/systemd/system/pimoroni-fanshim.service - -USAGE="sudo ./install-service.sh --off-threshold --on-threshold --delay --brightness --low-temp --high-temp --venv (--preempt) (--noled) (--nobutton) (--extended-colours)" - -# Convert Python path to absolute for systemd -PYTHON=`type -P $PYTHON` - +SERVICE_PATH="/etc/systemd/system/pimoroni-fanshim.service" + +PYTHON=$(command -v python3 || true) +PIP=$(command -v pip3 || true) + +USAGE="Usage: sudo ./install-fanshim-service.sh [options] +Options: + --on-threshold Temperature (°C) to turn fan ON (default 65) + --off-threshold Temperature (°C) to turn fan OFF (default 55) + --delay Poll delay in seconds (default 2) + --brightness LED brightness (0–255, default 255) + --preempt Allow fan preemption + --noled Disable LED + --nobutton Disable button support + --extended-colours Enable extended LED colour scheme + --venv Use Python virtual environment + -h, --help Show this help message +" + +# Parse arguments while [[ $# -gt 0 ]]; do - K="$1" - case $K in - -p|--preempt) - if [ "$2" == "yes" ] || [ "$2" == "no" ]; then - PREEMPT="$2" - shift - else - PREEMPT="yes" - fi - shift - ;; - -l|--noled) - if [ "$2" == "yes" ] || [ "$2" == "no" ]; then - NOLED="$2" - shift - else - NOLED="yes" - fi - shift - ;; - -b|--nobutton) - if [ "$2" == "yes" ] || [ "$2" == "no" ]; then - NOBUTTON="$2" - shift - else - NOBUTTON="yes" - fi - shift - ;; - -o|--on-threshold) - ON_THRESHOLD="$2" - ON_THRESHOLD_SET=true - shift - shift - ;; - -f|--off-threshold) - OFF_THRESHOLD="$2" - OFF_THRESHOLD_SET=true - shift - shift - ;; - -G|--low-temp) - LOW_TEMP="$2" - shift - shift - ;; - -R|--high-temp) - HIGH_TEMP="$2" - shift - shift - ;; - -d|--delay) - DELAY="$2" - shift - shift - ;; - -r|--brightness) - BRIGHTNESS="$2" - shift - shift - ;; - --venv) - VENV="$(realpath ${2%/})/bin" - PYTHON="$VENV/python3" - PIP="$VENV/pip3" - shift - shift - ;; - -x|--extended-colours) - if [ "$2" == "yes" ] || [ "$2" == "no" ]; then - EXTCOLOURS="$2" - shift - else - EXTCOLOURS="yes" - fi - shift - ;; - *) - if [[ $1 == -* ]]; then - printf "Unrecognised option: $1\n"; - printf "Usage: $USAGE\n"; - exit 1 - fi - POSITIONAL_ARGS+=("$1") - shift - esac + case "$1" in + --on-threshold) ON_THRESHOLD="$2"; shift 2;; + --off-threshold) OFF_THRESHOLD="$2"; shift 2;; + --delay) DELAY="$2"; shift 2;; + --brightness) BRIGHTNESS="$2"; shift 2;; + --preempt) PREEMPT="yes"; shift;; + --noled) NOLED="yes"; shift;; + --nobutton) NOBUTTON="yes"; shift;; + --extended-colours) EXTCOLOURS="yes"; shift;; + --venv) VENV="$(realpath "${2%/}")/bin"; PYTHON="$VENV/python3"; PIP="$VENV/pip3"; shift 2;; + -h|--help) echo "$USAGE"; exit 0;; + *) echo "Unknown option: $1"; echo "$USAGE"; exit 1;; + esac done -if ! ( type -P "$PYTHON" > /dev/null ) ; then - if [ "$PYTHON" == "python3" ]; then - printf "Fan SHIM controller requires Python 3\n" - printf "You should run: 'sudo apt install python3'\n" - else - printf "Cannot find virtual environment.\n" - printf "Set to base of virtual environment i.e. /bin/python3.\n" - fi - exit 1 +# Verify Python and pip +echo "Checking Python environment..." +if ! command -v "$PYTHON" >/dev/null 2>&1; then + echo "Python 3 not found. Installing..." + sudo apt install -y python3 fi -if ! ( type -P "$PIP" > /dev/null ) ; then - printf "Fan SHIM controller requires Python 3 pip\n" - if [ "$PIP" == "pip3" ]; then - printf "You should run: 'sudo apt install python3-pip'\n" - else - printf "Ensure that your virtual environment has pip3 installed.\n" - fi - exit 1 +if ! command -v "$PIP" >/dev/null 2>&1; then + echo "pip3 not found. Installing..." + sudo apt install -y python3-pip fi -set -- "${POSITIONAL_ARGS[@]}" - -EXTRA_ARGS="" - -if [ "$PREEMPT" == "yes" ]; then - EXTRA_ARGS+=' --preempt' -fi - -if [ "$NOLED" == "yes" ]; then - EXTRA_ARGS+=' --noled' -fi - -if [ "$NOBUTTON" == "yes" ]; then - EXTRA_ARGS+=' --nobutton' -fi - -if [ "$EXTCOLOURS" == "yes" ]; then - EXTRA_ARGS+=' --extended-colours' -fi - -if ! [ "$1" == "" ]; then - if [ $ON_THRESHOLD_SET ]; then - printf "Refusing to overwrite explicitly set On Threshold ($ON_THRESHOLD) with positional argument!\n" - printf "Please double-check your arguments and use one or the other!\n" - exit 1 - fi - ON_THRESHOLD=$1 -fi - -if ! [ "$2" == "" ]; then - if [ $OFF_THRESHOLD_SET ]; then - printf "Refusing to overwrite explicitly set Off Threshold ($OFF_THRESHOLD) with positional argument!\n" - printf "Please double-check your arguments and use one or the other!\n" - exit 1 - fi - (( OFF_THRESHOLD = ON_THRESHOLD - $2 )) -fi - -if [ "$LOW_TEMP" == "" ]; then - LOW_TEMP=$OFF_THRESHOLD -fi - -if [ "$HIGH_TEMP" == "" ]; then - HIGH_TEMP=$ON_THRESHOLD -fi - -cat << EOF -Setting up with: -Off Threshold: $OFF_THRESHOLD C -On Threshold: $ON_THRESHOLD C -Low Temp: $LOW_TEMP C -High Temp: $HIGH_TEMP C -Delay: $DELAY seconds -Preempt: $PREEMPT -Disable LED: $NOLED -Disable Button: $NOBUTTON -Brightness: $BRIGHTNESS -Extended Colours: $EXTCOLOURS - -To change these options, run: -$USAGE - -Or edit: $SERVICE_PATH - +# Install dependencies +echo "Installing required Debian packages..." +sudo apt install -y python3-rpi.gpio python3-spidev python3-psutil python3-setuptools + +echo "Upgrading Python packages..." +sudo "$PIP" install --upgrade psutil "rpi.gpio>=0.7.0" fanshim >/dev/null 2>&1 || true + +# Summary +cat <= 0.7.0 (for Pi 4 support)\n" -$PYTHON - <=0.7.0" -else - printf "rpi.gpio >= 0.7.0 already installed\n" -fi - -printf "Checking for Fan SHIM\n" -$PYTHON - > /dev/null 2>&1 </dev/null -if [ $? -ne 0 ]; then - printf "Installing Fan SHIM\n" - $PIP install fanshim -else - printf "Fan SHIM already installed\n" -fi - -printf "Checking for psutil >= $PSUTIL_MIN_VERSION\n" -$PYTHON - > /dev/null 2>&1 <= parse_version('$PSUTIL_MIN_VERSION')) -EOF - -if [ $? -ne 0 ]; then - printf "Installing psutil\n" - $PIP install --ignore-installed psutil -else - printf "psutil >= $PSUTIL_MIN_VERSION already installed\n" -fi +sudo systemctl daemon-reload +sudo systemctl enable pimoroni-fanshim.service +sudo systemctl restart pimoroni-fanshim.service -printf "\nInstalling service to: $SERVICE_PATH\n" -echo "$UNIT_FILE" > $SERVICE_PATH -systemctl daemon-reload -systemctl enable --no-pager pimoroni-fanshim.service -systemctl restart --no-pager pimoroni-fanshim.service -systemctl status --no-pager pimoroni-fanshim.service +echo "Installation complete." +sudo systemctl status --no-pager pimoroni-fanshim.service diff --git a/install.sh b/install.sh index 11e66b9..d022004 100755 --- a/install.sh +++ b/install.sh @@ -1,131 +1,95 @@ -#!/bin/bash +#!/usr/bin/env bash +set -euo pipefail -CONFIG=/boot/config.txt -DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"` +CONFIG="/boot/config.txt" +DATESTAMP=$(date "+%Y-%m-%d-%H-%M-%S") CONFIG_BACKUP=false -CODENAME=`lsb_release -sc` - -if [ $? -ne 0 ]; then - printf "Error parsing configuration...\n" - exit 1 -fi +CODENAME=$(lsb_release -sc 2>/dev/null || echo "unknown") function do_config_backup { - if [ ! $CONFIG_BACKUP == true ]; then - CONFIG_BACKUP=true - FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt" - printf "Backing up $CONFIG to $FILENAME\n" - cp $CONFIG $FILENAME - fi + if [ "$CONFIG_BACKUP" != true ] && [ -f "$CONFIG" ]; then + CONFIG_BACKUP=true + FILENAME="config.preinstall-${LIBRARY_NAME}-${DATESTAMP}.txt" + echo "Backing up $CONFIG to $FILENAME" + cp "$CONFIG" "$FILENAME" + fi } function apt_pkg_install { - PACKAGES=() - PACKAGES_IN=("$@") - for ((i = 0; i < ${#PACKAGES_IN[@]}; i++)); do - PACKAGE="${PACKAGES_IN[$i]}" - printf "Checking for $PACKAGE\n" - dpkg -L $PACKAGE > /dev/null 2>&1 - if [ "$?" == "1" ]; then - PACKAGES+=("$PACKAGE") - fi - done - PACKAGES="${PACKAGES[@]}" - if ! [ "$PACKAGES" == "" ]; then - echo "Installing missing packages: $PACKAGES" - sudo apt update - sudo apt install -y $PACKAGES - fi + local missing=() + for pkg in "$@"; do + if ! dpkg -s "$pkg" >/dev/null 2>&1; then + missing+=("$pkg") + fi + done + if [ "${#missing[@]}" -gt 0 ]; then + echo "Installing missing packages: ${missing[*]}" + sudo apt update + sudo apt install -y "${missing[@]}" + fi } -if [[ $CODENAME != "bullseye" ]]; then - apt_pkg_install python-configparser -fi +# Ensure python3 and pip3 exist +apt_pkg_install python3 python3-pip python3-setuptools -CONFIG_VARS=`python - <=0.7.0 (for Pi 4 support)\n" - python - <=0.7.0" - else - printf "rpi.gpio >= 0.7.0 already installed\n" - fi +eval "$CONFIG_VARS" - apt_pkg_install "${PY2_DEPS[@]}" - python setup.py install -fi +echo "$LIBRARY_NAME $LIBRARY_VERSION Python Library: Installer" +echo -if [ -f "/usr/bin/python3" ]; then - printf "Installing for Python 3..\n" - apt_pkg_install "${PY3_DEPS[@]}" - python3 setup.py install +if [ "$(id -u)" -ne 0 ]; then + echo "Script must be run as root. Try: sudo ./install.sh" + exit 1 fi +cd library + +echo "Installing for Python 3..." +apt_pkg_install "${PY3_DEPS[@]}" +python3 setup.py install + cd .. -for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do - CMD="${SETUP_CMDS[$i]}" - # Attempt to catch anything that touches /boot/config.txt and trigger a backup - if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG"* ]] || [[ "$CMD" == *"\$CONFIG"* ]]; then - do_config_backup - fi - eval $CMD +for CMD in "${SETUP_CMDS[@]}"; do + if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG"* ]]; then + do_config_backup + fi + eval "$CMD" done -for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do - CONFIG_LINE="${CONFIG_TXT[$i]}" - if ! [ "$CONFIG_LINE" == "" ]; then - do_config_backup - sed -i 's/^#$CONFIG_LINE/$CONFIG_LINE/' $CONFIG - if ! grep -q -E "^$CONFIG_LINE" $CONFIG; then - printf "$CONFIG_LINE\n" >> $CONFIG - fi - fi +for LINE in "${CONFIG_TXT[@]}"; do + if [ -n "$LINE" ]; then + do_config_backup + if ! grep -q -E "^${LINE}" "$CONFIG" 2>/dev/null; then + echo "$LINE" >>"$CONFIG" + echo "Added: $LINE" + fi + fi done -printf "Done!\n" +echo "Done."