#!/bin/bash ## QBO Installer Raspberry Pi Model 4B, Raspian buster, Python 3.7 and OpenCV 4.1.1 v1.0 # Parameters REPO_QBO="https://gitlab.com/thecorpora/QBO.git" PATH_LIBTTSPICO="http://ftp.debian.org/debian/pool/non-free/s/svox/" NAME_LIBTTSPICO_DATA="libttspico-data_1.0+git20130326-9_all.deb" NAME_LIBTTSPICO="libttspico0_1.0+git20130326-9_armhf.deb" NAME_LIBTTSPICO_UTILS="libttspico-utils_1.0+git20130326-9_armhf.deb" REPO_SND-I2S_RPI="https://github.com/opencardev/snd-i2s_rpi.git" REPO_SNOWBOY="https://github.com/Kitt-AI/snowboy" REPO_MYCROFT="https://github.com/MycroftAI/mycroft-core.git" OPENCV_VERSION="4.1.1" ZIP_OPENCV="https://github.com/opencv/opencv/archive/4.1.1.zip" ZIP_OPENCV_CONTRIB="https://github.com/opencv/opencv_contrib/archive/4.1.1.zip" # Functions function INSTALL_OR_UPDATE_DEPENDENCIES { # Removing rpi-update apt-get remove rpi-update -y # Update packages apt-get update apt-get upgrade -y # Install apt dependencies apt-get install -y raspberrypi-kernel-headers git python-pip python-pil python-opencv python-numpy python-pigpio python-zbar python-urllib3 python-serial python-simplejson python-pyasn1-modules python-yaml alsa-base esound-common portaudio19-dev flac espeak libwebsockets-dev winbind libnss-winbind samba libffi-dev libssl-dev libmpg123-dev swig swig3.0 sox python-pyaudio libatlas-base-dev ffmpeg libhdf5-serial-dev hdf5-tools -y # Install libttspico-utils wget ${PATH_LIBTTSPICO}${NAME_LIBTTSPICO_DATA} wget ${PATH_LIBTTSPICO}${NAME_LIBTTSPICO} wget ${PATH_LIBTTSPICO}${NAME_LIBTTSPICO_UTILS} sudo dpkg -i ${NAME_LIBTTSPICO_DATA} sudo dpkg -i ${NAME_LIBTTSPICO} sudo dpkg -i ${NAME_LIBTTSPICO_UTILS} # Install python dependencies pip3 install --upgrade pip pip3 install apiai argparse google-assistant-grpc google-assistant-library google-assistant-sdk google-oauth SpeechRecognition PyAudio Django djangorestframework pyyaml pyOpenSSL pyasn1 watson-developer-cloud youtube-dl dialogflow pyasn1 tensorflow # Remove old packages apt-get autoclean -y apt-get autoremove --purge -y apt-get clean all -y # Check if kernel changed if [ ! -d "/lib/modules/$(uname -r)" ] then # Show Warning printf "\n**WARNING**\nThe kernel has changed after updating the system.\nPlease, reboot the system and re-run the install/update script.\n" # Wait to user confirmation read -n 1 -s -r -p "Press any key to reboot" # Reboot & exit reboot exit 1 fi # Avoid future kernel updates #apt-mark hold raspberrypi-kernel raspberrypi-kernel-headers } function INSTALL_OPENCV { # Python3 for Mycroft installation alias python=python3 alias pip=pip3 # Install OpenCV 4 dependencies apt-get update && sudo apt-get upgrade apt-get install -y build-essential cmake unzip pkg-config apt-get install -y libjpeg-dev libpng-dev libtiff-dev apt-get install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev apt-get install -y libxvidcore-dev libx264-dev apt-get install -y libgtk-3-dev apt-get install -y libcanberra-gtk* apt-get install -y libatlas-base-dev gfortran apt-get install -y python3-dev # Download OpenCV cd /tmp wget -O opencv.zip ${ZIP_OPENCV} wget -O opencv_contrib.zip ${ZIP_OPENCV_CONTRIB} unzip opencv.zip unzip opencv_contrib.zip # Install NumPy pip3 install numpy # CMake and compile OpenCV cd /tmp/opencv-${OPENCV_VERSION} mkdir build cd build cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D SOURCE_DIR=/tmp/opencv-${OPENCV_VERSION}/ \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D OPENCV_EXTRA_MODULES_PATH=/tmp/opencv_contrib-${OPENCV_VERSION}/modules \ -D ENABLE_NEON=ON \ -D ENABLE_VFPV3=ON \ -D BUILD_TESTS=OFF \ -D OPENCV_ENABLE_NONFREE=ON \ -D INSTALL_PYTHON_EXAMPLES=OFF \ -D OPENCV_SKIP_PYTHON_LOADER=ON \ -D OPENCV_PYTHON2_INSTALL_PATH=/usr/local/lib/python2.7/dist-packages \ -D OPENCV_PYTHON3_INSTALL_PATH=/usr/local/lib/python3.7/dist-packages \ -D BUILD_EXAMPLES=OFF .. \ -DCMAKE_SHARED_LINKER_FLAGS='-latomic' sed -i 's/CONF_SWAPSIZE=100/CONF_SWAPSIZE=2048/g' /etc/dphys-swapfile /etc/init.d/dphys-swapfile stop /etc/init.d/dphys-swapfile start make -j4 make install ldconfig sed -i 's/CONF_SWAPSIZE=2048/CONF_SWAPSIZE=100/g' /etc/dphys-swapfile /etc/init.d/dphys-swapfile stop /etc/init.d/dphys-swapfile start # Remove sources cd /tmp rm -Rf opencv* # Link OpenCV cd /usr/lib/python3/dist-packages/ ln -s /usr/local/python/cv2/python-3.7/cv2.cpython-37m-arm-linux-gnueabihf.so cv2.so } function INSTALL_I2S_AUDIO_KERNEL_MODULE { # Download source code for snd-i2s_rpi mkdir /tmp/snd-i2s_rpi /usr/bin/git clone ${REPO_SND-I2S_RPI} /tmp/snd-i2s_rpi # Compile, Install & Clean make all --directory=/tmp/snd-i2s_rpi make install --directory=/tmp/snd-i2s_rpi # Remove sources rm -Rf /tmp/snd-i2s_rpi # Enable snd-i2s_rpi depmod -a if [ -z `cat /etc/modules | grep snd-i2s_rpi` ] then echo "snd-i2s_rpi" >> /etc/modules fi modprobe snd-i2s_rpi } function INSTALL_SNOWBOY { # Remove if exist & Install Snowboy library rm -f /opt/qbo/snowboy rm -Rf /opt/snowboy /usr/bin/git clone ${REPO_SNOWBOY} /opt/snowboy # Install library python3 /opt/snowboy/setup.py install # Make libraries make all --directory=/opt/snowboy/swig/Python3 # Create link sudo -u qbo ln -s /opt/snowboy/examples/Python3 /opt/qbo/snowboy # Adapt for Python 3 sed -i 's/import snowboy/import snowboy.snowboy/g' /opt/qbo/snowboy/snowboythreaded.py sed -i 's/import snowboy/import snowboy.snowboy/g' /opt/qbo/snowboy/snowboydecoder.py sed -i 's/import snowboy/import snowboy.snowboy/g' /opt/qbo/snowboy/snowboydecoder_arecord.py } function INSTALL_MYCROFT { # Cloning MyCroft repository /usr/bin/git clone -b master ${REPO_MYCROFT} /opt/qbo/mycroft-core # Python3 for Mycroft installation alias python=python3 alias pip=pip3 # Install Mycroft # This requires user input! bash /opt/qbo/mycroft-core/dev_setup.sh --allow-root pip3 install --upgrade pip pip3 install certifi monotonic sed -i 's/paplay %1 --stream-name=mycroft-voice/aplay -D convertQBO %1/g' /opt/qbo/mycroft-core/mycroft/configuration/mycroft.conf } function ADD_CHROME_TO_STARTUP { if [ -f /home/pi/.config/lxsession/LXDE-pi/autostart ] then if [ -z `cat /home/pi/.config/lxsession/LXDE-pi/autostart | grep chromium`] then echo "@/usr/bin/chromium-browser --kiosk --noerrordialogs --incognito --disable-infobars --disable-session-crashed-bubble http://localhost:8000" >> /home/pi/.config/lxsession/LXDE-pi/autostart else printf "Already configured chromium at startup.\n" fi else mkdir -p /home/pi/.config/lxsession/LXDE-pi/ echo "@lxpanel --profile LXDE-pi" > /home/pi/.config/lxsession/LXDE-pi/autostart echo "@pcmanfm --desktop --profile LXDE-pi" >> /home/pi/.config/lxsession/LXDE-pi/autostart echo "@xscreensaver -no-splash" >> /home/pi/.config/lxsession/LXDE-pi/autostart echo "@point-rpi" >> /home/pi/.config/lxsession/LXDE-pi/autostart echo "@/usr/bin/chromium-browser --kiosk --noerrordialogs --incognito --disable-infobars --disable-session-crashed-bubble http://localhost:8000" >> /home/pi/.config/lxsession/LXDE-pi/autostart fi } function INSTALL { # Clean screen clear # Presentation printf "\n ** QBO Installer **\n\nThis software will update the Raspbian, install the dependencies\nand install the QBO Software. Once the installation is complete,\nthe system will reboot and the QBO Software will be ready.\n\nNOTICE: It is recommended to perform this installation\non a clean Raspbian Stretch image.\n\n" read -n 1 -s -r -p "Press any key to continue" clear # Additional Screen if install from development repositories if [ ${REPO_QBO_BRANCH} == "develop" ] then printf "\n ** QBO Installer **\n\n**WARNING**\nAre you sure you want to install from the development repositories?\nThe development version is unstable and may contain critical errors.\n\n" read -n 1 -s -r -p "Press any key to continue or Ctrl+C to cancel" clear fi # Setting default value for DISTRO DISTRO='undefined' # Presentation printf "\n ** QBO Installer **\n\nSelect the distribution of QBO Software to install:\n\n\t[1] Standalone: Main version. It works with Google services.\n\t[2] IBM Watson: This distribution only works with IBM Watson services.\n\n\n" # Ask distribution while [ ${DISTRO} != 'standalone' ] && [ ${DISTRO} != 'ibmwatson' ] do read -r -p "Enter number of distribution and press enter: " DISTRONUM case "$DISTRONUM" in 1) DISTRO='standalone' ;; 2) DISTRO='ibmwatson' ;; *) printf "\n **WARNING** The entered value is wrong.\n\n" esac done # Installing dependencies printf "Installing dependencies...\n" INSTALL_OR_UPDATE_DEPENDENCIES # Install OpenCV 4 INSTALL_OPENCV # Show action info printf "Enabling i2c-dev & bcm2835 modules...\n" # Load modules required by qbo echo "i2c-dev" >> /etc/modules echo "snd-bcm2835" >> /etc/modules modprobe i2c-dev modprobe snd-bcm2835 # Show action info printf "Settings hdmi config...\n" # Settings hdmi & i2s config sed -i 's/#hdmi_force_hotplug=1/hdmi_force_hotplug=1/g' /boot/config.txt sed -i 's/#hdmi_group=1/hdmi_group=2/g' /boot/config.txt sed -i 's/#hdmi_mode=1/hdmi_mode=82/g' /boot/config.txt # Show action info printf "Enabling i2s-audio module...\n" # Enable i2s audio sed -i 's/#dtparam=i2s=on/dtparam=i2s=on/g' /boot/config.txt printf "\n# Enable i2s-mmap audio\ndtoverlay=i2s-mmap\n" >> /boot/config.txt # Installing i2s-audio kernel module printf "Installing i2s-audio kernel module...\n" INSTALL_I2S_AUDIO_KERNEL_MODULE # Show action info printf "Setting asound.conf...\n" # Setting asound config echo " pcm.!default { pcm \"hw:1,0\" } pcm.dmicQBO { type hw card sndrpisimplecar channels 2 rate 16000 format S16_LE } pcm.dmicQBO_sv { type softvol slave.pcm dmicQBO control { name \"Boost Capture Volume\" card snd_rpi_i2s_card } min_dB -10.0 max_dB 30.0 } pcm_slave.sl1 { pcm \"hw:1,0\" channels 2 rate 16000 format S16_LE } pcm.convertQBO { type plug slave sl1 } " > /etc/asound.conf # Show action infoq printf "Setting alsa.conf...\n" # Setting alsa config sed -i 's/pcm.front cards.pcm.front/#pcm.front cards.pcm.front/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.rear cards.pcm.rear/#pcm.rear cards.pcm.rear/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.center_lfe cards.pcm.center_lfe/#pcm.center_lfe cards.pcm.center_lfe/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.side cards.pcm.side/#pcm.side cards.pcm.side/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.surround21 cards.pcm.surround21/#pcm.surround21 cards.pcm.surround21/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.surround40 cards.pcm.surround40/#pcm.surround40 cards.pcm.surround40/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.surround41 cards.pcm.surround41/#pcm.surround41 cards.pcm.surround41/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.surround50 cards.pcm.surround50/#pcm.surround50 cards.pcm.surround50/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.surround51 cards.pcm.surround51/#pcm.surround51 cards.pcm.surround51/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.surround71 cards.pcm.surround71/#pcm.surround71 cards.pcm.surround71/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.iec958 cards.pcm.iec958/#pcm.iec958 cards.pcm.iec958/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.spdif iec958/#pcm.spdif iec958/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.hdmi cards.pcm.hdmi/#pcm.hdmi cards.pcm.hdmi/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.modem cards.pcm.modem/#pcm.modem cards.pcm.modem/g' /usr/share/alsa/alsa.conf sed -i 's/pcm.phoneline cards.pcm.phoneline/#pcm.phoneline cards.pcm.phoneline/g' /usr/share/alsa/alsa.conf # Show action info printf "Disabling console serial service...\n" # Disabling console serial service systemctl stop serial-getty@ttyS0.service systemctl disable serial-getty@ttyS0.service sed -i 's/ console=serial0,115200 / /g' /boot/cmdline.txt # Show action info printf "Creating user qbo...\n" # Creating user qbo adduser --system --home /opt/qbo --shell /bin/bash --disabled-password --disabled-login qbo usermod -G adm,dialout,sudo,audio,video,plugdev,input,netdev,spi,i2c,gpio qbo printf "\n# Allow qbo user to exec commands\nqbo ALL=(ALL) NOPASSWD: ALL\n" >> /etc/sudoers # Default Python 3 printf "alias pip=pip3\n" >> ~/.bashrc printf "alias python=python3\n" >> ~/.bashrc # Show action info printf "Cloning repository...\n" # Cloning Q.bo repository /usr/bin/git clone -b ${REPO_QBO_BRANCH} ${REPO_QBO} /opt/qbo chown -R qbo:nogroup /opt/qbo # Adapt for Python 3 sed -i 's/python2/python3/g' /opt/qbo/Start.py sed -i 's/python /python3 /g' /opt/qbo/scripts/QBO_PiFaceFast.sh sed -i 's/except (IOError, ImportError), e:/except (IOError, ImportError) as e:/g' /opt/qbo/web/panel/views/moves_views.py sed -i 's/import thread/import _thread/g' /opt/qbo/PiFaceFast.py sed -i 's/print"\(.*\)$/print("\1)/g' /opt/qbo/PiFaceFast.py sed -i 's/print "\(.*\)$/print("\1)/g' /opt/qbo/PiFaceFast.py sed -i 's/ThreadedDetector/HotwordDetector/g' /opt/qbo/PiFaceFast.py sed -i 's/snowboythreaded/snowboydecoder/g' /opt/qbo/PiFaceFast.py sed -i 's/cv2.cv.CV_CAP_PROP_FRAME_WIDTH/cv2.CAP_PROP_FRAME_WIDTH/g' /opt/qbo/PiFaceFast.py sed -i 's/cv2.cv.CV_CAP_PROP_FRAME_HEIGHT/cv2.CAP_PROP_FRAME_HEIGHT/g' /opt/qbo/PiFaceFast.py sed -i 's/cv2.CV_CAP_PROP_BUFFERSIZE/cv2.CAP_PROP_BUFFERSIZE/g' /opt/qbo/PiFaceFast.py sed -i 's/cv2.cv.CV_HAAR_DO_CANNY_PRUNING/0/g' /opt/qbo/PiFaceFast.py sed -i 's/cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT/0/g' /opt/qbo/PiFaceFast.py sed -i 's/cv2.cv.CV_HAAR_DO_ROUGH_SEARCH/0/g' /opt/qbo/PiFaceFast.py sed -i 's/faceOffset_X >> 1/int(faceOffset_X) >> 1/g' /opt/qbo/PiFaceFast.py sed -i 's/faceOffset_Y >> 1/int(faceOffset_Y) >> 1/g' /opt/qbo/PiFaceFast.py sed -i 's/print "\(.*\)$/print("\1)/g' /opt/qbo/assistants/QboDialogFlowV2.py sed -i 's/python/python3/g' /opt/qbo/assistants/QboDialogFlowV2.py sed -i 's/python2/python3/g' /opt/qbo/assistants/QboGAssistant.py sed -i 's/python/python3/g' /opt/qbo/assistants/QboMyCroft.py sed -i 's/python2/python3/g' /opt/qbo/assistants/QboTalk.py sed -i "s/print '\(.*\)$/print('\1)/g" /opt/qbo/assistants/QboTalk.py sed -i 's/print "\(.*\)$/print("\1)/g' /opt/qbo/assistants/QboTalk.py sed -i 's/python2/python3/g' /opt/qbo/assistants/QboTalkMycroft.py sed -i 's/python2/python3/g' /opt/qbo/assistants/QboWatson.py sed -i 's/print "\(.*\)$/print("\1)/g' /opt/qbo/assistants/QboWatson.py sed -i 's/print"\(.*\)$/print("\1)/g' /opt/qbo/controller/QboController.py sed -i 's/print "\(.*\)$/print("\1)/g' /opt/qbo/controller/QboController.py sed -i 's/self.cmd_params.has_key(cmd) == False/cmd not in self.cmd_params/g' /opt/qbo/controller/QboController.py sed -i 's/for i in rdBuffer/for x in rdBuffer/g' /opt/qbo/controller/QboController.py sed -i 's/x = ord(i)//g' /opt/qbo/controller/QboController.py sed -i 's/Angle & 0xff, (Angle >> 8) & 0xff/Angle % 256, (Angle \/ 256) % 256/g' /opt/qbo/controller/QboController.py sed -i 's/data\[i\] & 0xff/int(data\[i\]i) & 0xff/g' /opt/qbo/controller/QboController.py sed -i 's/with self.m as source:/self.r.adjust_for_ambient_noise(self.m)/g' /opt/qbo/assistants/QboTalk.py sed -i 's/self.r.adjust_for_ambient_noise(source)//g' /opt/qbo/assistants/QboTalk.py sed -i 's/\taudio = self.r.listen(source=source, timeout=2)/audio = self.r.listen(source=self.m, timeout=2)/g' /opt/qbo/assistants/QboTalk.py # Show action info printf "Creating pipes...\n" # Creating Pipes sudo -u qbo mkdir /opt/qbo/pipes sudo -u qbo mkfifo /opt/qbo/pipes/pipe_cmd sudo -u qbo mkfifo /opt/qbo/pipes/pipe_feel sudo -u qbo mkfifo /opt/qbo/pipes/pipe_findFace sudo -u qbo mkfifo /opt/qbo/pipes/pipe_listen sudo -u qbo mkfifo /opt/qbo/pipes/pipe_say # Show action info printf "Creating logs folder & setting logrotate...\n" # Creating logs directory sudo -u qbo mkdir /opt/qbo/logs echo " /opt/qbo/logs/*.log { rotate 12 weekly missingok notifempty compress delaycompress copytruncate create 0640 qbo nogroup }" > /etc/logrotate.d/qbo # Show action info printf "Compile websocket...\n" # Compile websocket sudo -u qbo make all --directory=/opt/qbo/websocket # Installing snowboy printf "Installing snowboy...\n" INSTALL_SNOWBOY # Installing Mycroft printf "Installing Mycroft...\n" INSTALL_MYCROFT # Show action info printf "Changing hostname...\n" # Set qbo hostname echo "qbo" > /etc/hostname sed -i 's/files mdns4_minimal/files wins mdns4_minimal/g' /etc/nsswitch.conf sed -i 's/raspberrypi/qbo/g' /etc/hosts # Show action info printf "Setting Crontab...\n" # Set crontab echo "@reboot qbo /opt/qbo/Start.py" >> /etc/crontab echo "@reboot qbo python3 /opt/qbo/web/manage.py runserver 0.0.0.0:8000" >> /etc/crontab echo "* * * * * qbo bash /opt/qbo/scripts/WiFiSearchQR.sh" >> /etc/crontab echo "0 15 * * * root bash /opt/qbo/scripts/UpdateMyCroft.sh" >> /etc/crontab # Show action info printf "Create config.yml...\n" # Create config.yml case "$DISTRO" in standalone) sudo -u qbo echo "{distro: standalone, language: english, microphoneGain: 100, camera: 0, servoSpeed: 100, tokenAPIai: , gassistant_proyectid: , dialogflowv2_projectid: , startWith: interactive-dialogflow, volume: 100 }" > /opt/qbo/config.yml chown qbo:nogroup /opt/qbo/config.yml ;; ibmwatson) sudo -u qbo echo "{distro: ibmwatson, language: english, microphoneGain: 100, camera: 0, servoSpeed: 100, AssistantUsername: , AssistantPassword: , AssistantWorkspace: , TextToSpeechUsername: , TextToSpeechPassword: , SpeechToTextUsername: , SpeechToTextPassword: , SpeechToTextListeningTime: , VisualRecognitionAPIKey: , startWith: interactive-dialogflow, volume: 100 }" > /opt/qbo/config.yml chown qbo:nogroup /opt/qbo/config.yml ;; *) printf "\n\n **CRITICAL ERROR** Distribution undefined\n\n" exit 1 esac # Add Chrome to startup printf "Adding chrome to startup...\n" ADD_CHROME_TO_STARTUP # Show action info printf "Complete! Rebooting in 5 seconds...\n" # Removing installer if [ -f "`pwd`/`basename "$0"`" ] then rm -f "`pwd`/`basename "$0"`" fi # Wait 5 seconds & reboot sleep 5 reboot } function UPDATE { # Get current branch CURRENT_BRANCH=`git -C /opt/qbo rev-parse --abbrev-ref HEAD` # Obtain changes from origin printf "Downloading updates...\n" sudo -u qbo /usr/bin/git -C /opt/qbo fetch origin # Obtain if QBO_Installer file changed QBO_INSTALLER_CHANGED=`sudo -u qbo /usr/bin/git -C /opt/qbo diff origin/${CURRENT_BRANCH} --name-only | grep QBO_Installer.sh | wc -l` # Applying changes printf "Applying updates...\n" QBO_CODE_CHANGED=`sudo -u qbo /usr/bin/git -C /opt/qbo merge FETCH_HEAD | grep -v -c "Already up-to-date."` # Check if QBO_Installer file changed, process of update is restarted if [ ${QBO_INSTALLER_CHANGED} == "1" ] && [ ${QBO_CODE_CHANGED} -gt "0" ] then printf "New installer detected. Restarting update process ...\n" /opt/qbo/scripts/QBO_Installer.sh update exit 1 fi # Updating dependencies printf "Updating dependencies...\n" INSTALL_OR_UPDATE_DEPENDENCIES # Clean previous version & Compile websocket printf "Compile websocket...\n" sudo -u qbo make clean --directory=/opt/qbo/websocket sudo -u qbo make all --directory=/opt/qbo/websocket # Updating snowboy printf "Updating snowboy...\n" INSTALL_SNOWBOY # Updating Mycroft printf "Updating Mycroft...\n" INSTALL_MYCROFT # Updating startup with Chrome printf "Updating startup with Chrome...\n" ADD_CHROME_TO_STARTUP # Show action info printf "Complete! Rebooting in 3 seconds...\n" # Speak sudo -u qbo /opt/qbo/Speak.py update # Wait 3 seconds & reboot sleep 3 reboot } function UPDATE_CHANGELOG { # Get current branch CURRENT_BRANCH=`git -C /opt/qbo rev-parse --abbrev-ref HEAD` # Obtain changes from origin sudo -u qbo /usr/bin/git -C /opt/qbo fetch origin > /dev/null 2>&1 # Show changes sudo -u qbo /usr/bin/git -C /opt/qbo log HEAD..origin/${CURRENT_BRANCH} --pretty=format:"%cd - %s" --date=format:"%d/%m/%Y %H:%M" } function UPDATE_CHANGE_BRANCH { # Screen if update from development repositories if [ ${REPO_QBO_BRANCH} == "develop" ] then printf "**WARNING**\n\nAre you sure you want to update from the development repositories? The development version is unstable and may contain critical errors.\n\n" read -n 1 -s -r -p "Press any key to continue or Ctrl+C to cancel" clear fi # Obtain changes from origin printf "Downloading updates...\n" sudo -u qbo /usr/bin/git -C /opt/qbo fetch origin # Checkout branch printf "Changing branch...\n" sudo -u qbo /usr/bin/git -C /opt/qbo checkout ${REPO_QBO_BRANCH} # Restart process update printf "Restarting update process ...\n" /opt/qbo/scripts/QBO_Installer.sh update exit 1 } function GASSISTANT_CREDENTIALS { # Command to generate credentials sudo -u qbo /usr/local/bin/google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype --scope https://www.googleapis.com/auth/gcm --save --headless --client-secrets ${GOOGLE_CLIENT_SECRET_FILE} } # Script init if [ `whoami` == "root" ] then if [ `lsb_release -i -s` == "Raspbian" ] then if [ -e /dev/ttyS0 ] then case "$1" in install) if [ -d "/opt/qbo" ] then printf "An installation of the QBO Software has been found. If you want to reinstall it, first remove that installation, or reinstall Raspbian.\n" exit 1 fi case "$2" in develop) REPO_QBO_BRANCH="develop" ;; *) REPO_QBO_BRANCH="master" esac INSTALL ;; update) if [ ! -d "/opt/qbo" ] then printf "The QBO Software installed has not been found. Please install the QBO software before trying to update it.\n" exit 1 fi case "$2" in changelog) UPDATE_CHANGELOG ;; develop) REPO_QBO_BRANCH="develop" UPDATE_CHANGE_BRANCH ;; master) REPO_QBO_BRANCH="master" UPDATE_CHANGE_BRANCH ;; *) UPDATE esac ;; gassistant) if [ ! -d "/opt/qbo" ] then printf "The QBO Software installed has not been found. Please install the QBO software before trying to register gassistant it.\n" exit 1 fi if [ ! -e "$2" ] then printf "The specified file does not exist.\n" exit 1 fi GOOGLE_CLIENT_SECRET_FILE=$2 GASSISTANT_CREDENTIALS ;; *) echo $"Usage: $0 {install|install develop|update|update changelog|update develop|update master|gassistant [path credentials json file]}" exit 1 esac else echo "You must enable the SERIAL interface. Run 'sudo raspi-config' and activate it in Interfacing Options." echo "You may have to restart the computer once you enable it." fi else echo "Qbo program can only be installed on Raspberry pi devices running with Raspbian." fi else echo "Only superuser ROOT can execute this script. Try: 'sudo bash QBO_Installer.sh'" fi