#!/bin/bash
# SIGHTS installer
# Handles installing and updating SIGHTS
#
# Created by the Semi-Autonomous Rescue Team
# This file is part of the SIGHTS project
#
# https://www.sights.dev/
# https://www.github.com/sightsdev
INSTALL_DIR=/opt
MOTION_VER=4.3.2
update_only='false'
developer_versions='false'
internal_update='false'
apt_updated='false'
set -e
print_detected_ip () {
output="Visit http://localhost$1 on the host machine"
hostname=$(hostname -I)
if [[ $hostname ]]
then
for ip in $hostname
do
output="$output or http://$ip$1"
done
output="$output on any device on the local network."
else
output="$output or connect to a network."
fi
echo "$output"
echo
}
enable_ssh () {
echo -e "\nEnabling SSH..."
systemctl enable ssh
echo -e "\nStarting SSH..."
systemctl start ssh
}
install_dependencies () {
echo -e "\nInstalling dependencies..."
apt update
apt install -y git apache2 python3 python3-pip wget gdebi
apt_updated='true'
echo
}
checkout_release () {
# Check out the latest tag (latest versioned release) for each repository.
# Skip if developer versions are enabled (meaning master will be checked out)
if [ $developer_versions == 'false' ]
then
cd sights
git checkout -f master
git checkout `git tag | sort -V | tail -1`
cd ..
fi
}
install_sights_repositories () {
echo -e "\nDownloading SIGHTS repositories..."
# Get SIGHTS
git clone https://github.com/sightsdev/sights
# Checkout to latest stable release
checkout_release
# Install all Python packages required by SIGHTS
echo -e "\nInstalling required Python packages..."
python3 -m pip install -r sights/src/requirements.txt
echo
}
configure_apache () {
echo -e "\nSetting up Apache..."
# This is the site file that defines where the interface is hosted from
# It also sets up a reverse proxy for Supervisor to work correctly
echo -e "\nEnabling SIGHTS site config..."
ln -sf $INSTALL_DIR/sights/src/configs/apache/sights.conf /etc/apache2/sites-enabled/sights.conf
# This is the required option to allow Apache to host from $INSTALL_DIR
echo -e "\nAllowing Apache to host the interface directory..."
# Only append this to the file if it does not already exist
if grep -Fxq "" /etc/apache2/apache2.conf
then
echo -e "Already done..."
else
echo -e "
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
" >> /etc/apache2/apache2.conf
fi
echo -e "\nDisabling Apache default site..."
a2dissite 000-default.conf
echo -e "\nEnabling Apache proxy modules..."
a2enmod proxy
a2enmod proxy_http
echo -e "\nStarting Apache..."
service apache2 restart
service apache2 start
service apache2 reload
echo
print_detected_ip "/"
}
try_install_motion () {
echo -e "\nWould you like to attempt to install a prebuilt Motion package?"
echo -e "Currently only available on Raspberry Pi and x64-based platforms."
echo -e "NOTE: This option is not available for the Jetson Nano"
echo -e "\nOtherwise a manual install will be performed.\n"
read -p "Attempt to install a prebuilt package Motion? [y/n] " choice
case "$choice" in
y|Y ) install_motion_auto;;
n|N ) install_motion_manual;;
* ) echo "Invalid response";;
esac
}
install_motion_auto () {
# Only install prebuilt binaries which are available only on supported OSs
if [ $DETECTED_OS == "ubuntu" ] || [ $DETECTED_OS == "debian" ] || [ $DETECTED_OS == "raspbian" ]
then
if [ $DETECTED_CODENAME == "bionic" ] || [ $DETECTED_CODENAME == "cosmic" ] || [ $DETECTED_CODENAME == "buster" ] || [ $DETECTED_CODENAME == "focal" ]
then
echo -e "\nDownloading Motion..."
if [ $DETECTED_OS == "raspbian" ]
then
# Get the armhf binaries (with the pi prefix) for Raspbian
wget https://github.com/Motion-Project/motion/releases/download/release-${MOTION_VER}/pi_${DETECTED_CODENAME}_motion_${MOTION_VER}-1_armhf.deb -O motion.deb
else
# For x86 systems, just use the normal amd64 binaries
wget https://github.com/Motion-Project/motion/releases/download/release-${MOTION_VER}/${DETECTED_CODENAME}_motion_${MOTION_VER}-1_amd64.deb -O motion.deb
fi
echo -e "\nInstalling Motion..."
gdebi -n ./motion.deb
rm ./motion.deb
configure_motion
else
echo -e "\nUnsupported release"
fi
else
echo -e "\nUnsupported distribution"
fi
echo
print_detected_ip ":8080/"
}
install_motion_manual () {
cd /tmp/
echo -e "\nDownloading build script..."
wget https://raw.githubusercontent.com/Motion-Project/motion-packaging/master/builddeb.sh
chmod +x builddeb.sh
echo -e "\nBuilding Motion..."
./builddeb.sh AdhocBuild AdhocBuild@nowhere.com master y any
rm builddeb.sh
echo -e "\nInstalling Motion..."
gdebi -n *motion*.deb
rm *motion*.deb
cd $INSTALL_DIR
configure_motion
}
configure_motion () {
echo -e "\nCreating symlink for Motion configuration files..."
rm -r /etc/motion
ln -sf $INSTALL_DIR/sights/src/configs/motion /etc
echo -e "\nEnabling Motion daemon flag..."
echo "start_motion_daemon=yes" > /etc/default/motion
echo -e "\nEnabling Motion service..."
systemctl enable motion
echo -e "\nStarting Motion service..."
service motion start
service motion restart
}
install_shellinabox () {
echo -e "\nInstalling ShellInABox..."
if [ $apt_updated == 'false' ]; then
apt update
apt_updated='true'
fi
apt install -y shellinabox
echo -e "\nDisabling ShellInABox SSL..."
sed -i 's/SHELLINABOX_ARGS=.*/SHELLINABOX_ARGS="--no-beep --disable-ssl"/' /etc/default/shellinabox
if [ $DETECTED_OS == "raspbian" ]; then
enable_ssh
fi
echo -e "\nStarting shellinabox service..."
service shellinabox start
echo
print_detected_ip ":4200/"
}
configure_supervisor () {
echo -e "\nCreating symlink for Supervisor configuration files..."
ln -sf $INSTALL_DIR/sights/src/configs/supervisor /etc
echo -e "\nInstalling Supervisor SIGHTS extension..."
python3 -m pip install sights/src/supervisor_plugin
echo -e "\nInstalling Supervisor init script"
cp sights/src/configs/systemd/supervisord /etc/init.d/
chmod 755 /etc/init.d/supervisord
chown root:root /etc/init.d/supervisord
update-rc.d supervisord defaults
echo -e "\nRunning Supervisor"
/etc/init.d/supervisord start
echo
print_detected_ip ":9001/"
}
enable_i2c () {
if [ $DETECTED_OS == "raspbian" ]
then
echo -e '\nEnabling i2c-bcm2708 module...'
if grep -q 'i2c-bcm2708' /etc/modules; then
echo 'i2c-bcm2708 module already enabled.'
else
modprobe i2c-bcm2708
echo 'i2c-bcm2708' >> /etc/modules
echo -e '\nEnabled i2c-bcm2708 module.'
fi
echo -e '\nEnabling i2c-dev module...'
if grep -q 'i2c-dev' /etc/modules; then
echo -e 'i2c-dev module already enabled.'
else
modprobe i2c-dev
echo 'i2c-dev' >> /etc/modules
echo -e 'Enabled i2c-dev module.'
fi
echo -e '\nSetting i2c_arm parameter boot config option...'
if grep -q 'dtparam=i2c_arm=on' /boot/config.txt; then
echo -e 'i2c_arm parameter already set.'
else
echo 'dtparam=i2c_arm=on' >> /boot/config.txt
echo -e '\nSet i2c_arm parameter boot config option...'
fi
echo -e '\nRemoving i2c from blacklists...'
if [ -f /etc/modprobe.d/raspi-blacklist.conf ]; then
sed -i 's/^blacklist spi-bcm2708/#blacklist spi-bcm2708/' /etc/modprobe.d/raspi-blacklist.conf
sed -i 's/^blacklist i2c-bcm2708/#blacklist i2c-bcm2708/' /etc/modprobe.d/raspi-blacklist.conf
else
echo 'File raspi-blacklist.conf does not exist, skip this step.'
fi
else
echo -e '\nThis option can only be used on a Raspberry Pi (running Raspbian).'
echo -e '\nFor other devices or operating systems, consult the manufacturers documentation for enabling I2C.'
fi
}
update () {
echo -e "\nUpdating SIGHTS..."
cd sights
git checkout -f master
git pull
cd $INSTALL_DIR
# Checkout appropriate release (stable or dev)
checkout_release
# Update Supervisor
python3 -m pip install sights/src/supervisor_plugin
# Ensure up to date dependencies are installed
python3 -m pip install -r sights/src/requirements.txt
# If update flag specified, just update, then exit
if [ $internal_update == 'false' ]; then
echo -e "\nRestarting Supervisord and SIGHTS..."
service supervisord restart
fi
echo -e "\nUpdate complete!"
echo
print_detected_ip "/"
}
complete_install () {
install_dependencies
install_sights_repositories
configure_apache
try_install_motion
install_shellinabox
configure_supervisor
echo -e "\nInstallation complete! Reboot to ensure proper functionality."
print_detected_ip "/"
}
# Ensure user is running as root
if [ "$EUID" -ne 0 ]
then echo "Please run as root"
exit
fi
# Setup install directory
if [ ! -d "$INSTALL_DIR" ]; then
echo -e "Creating installation directory at $INSTALL_DIR"
mkdir $INSTALL_DIR
fi
# Go to directory
cd $INSTALL_DIR
# Print welcome message
echo " _____ _____ _____ _ _ _______ _____ "
echo " / ____|_ _/ ____| | | |__ __/ ____|"
echo "| (___ | || | __| |__| | | | | (___ "
echo " \___ \ | || | |_ | __ | | | \___ \ "
echo " ____) |_| || |__| | | | | | | ____) |"
echo "|_____/|_____\_____|_| |_| |_| |_____/ "
echo -e "\nSights interactive installer"
echo -e "Created by the Semi-Autonomous Rescue Team"
DETECTED_OS=$(cat /etc/*-release | grep -E "\bID=" | sed 's/ID=//g')
DETECTED_CODENAME=$(cat /etc/*-release | grep "VERSION_CODENAME" | sed 's/VERSION_CODENAME=//g')
echo -e "\nInstalling as: $SUDO_USER"
echo -e "Detected OS: ${DETECTED_OS^} ${DETECTED_CODENAME^}"
if [ $DETECTED_OS == "ubuntu" ] || [ $DETECTED_OS == "debian" ] || [ $DETECTED_OS == "raspbian" ]
then
echo -e "- Using a supported OS -"
else
echo -e "- Using an unsupported OS -"
fi
echo
# Check provided flags
while test $# -gt 0; do
case "$1" in
--update)
update_only='true'
shift
;;
--dev)
developer_versions='true'
shift
;;
--internal)
internal_update='true'
shift
;;
*)
echo "$1 is not a recognized flag!"
exit 1
;;
esac
done
# If developer versions flag specified, notify and continue
if [ $developer_versions == 'true' ]; then
echo -e "Developer versions will be used."
fi
# If update flag specified, just update, then exit
if [ $update_only == 'true' ]; then
echo -e "Performing an update..."
update
exit 0
fi
options=(
"Complete Install"
"Install Dependencies"
"Install SIGHTS Software"
"Configure Apache"
"Install Motion"
"Setup ShellInABox"
"Configure Supervisor"
"Enable I2C"
"Update"
"Detect IPs"
)
PS3="Enter a number (1-${#options[@]}) or q to quit: "
while true; do
select option in "${options[@]}"; do
case "$REPLY" in
1) complete_install ;;
2) install_dependencies ;;
3) install_sights_repositories ;;
4) configure_apache ;;
5) try_install_motion ;;
6) install_shellinabox ;;
7) configure_supervisor ;;
8) enable_i2c ;;
9) update ;;
10) print_detected_ip "/" ;;
q) exit ;;
esac
break
done
done