From fe169266273f9d412484fe6d51012304503fdc70 Mon Sep 17 00:00:00 2001 From: Patrick McGuire Date: Thu, 14 Oct 2021 17:21:57 -0400 Subject: [PATCH] adding update feature --untested from main --- LICENSE | 346 ++++++++++++++++++++++ scripts/install_services.sh | 51 +--- scripts/reconfigure_birdnet.sh | 2 +- scripts/update_birdnet.sh | 122 ++++++++ scripts/update_services.sh | 524 +++++++++++++++++++++++++++++++++ 5 files changed, 1004 insertions(+), 41 deletions(-) create mode 100755 scripts/update_birdnet.sh create mode 100755 scripts/update_services.sh diff --git a/LICENSE b/LICENSE index fafb5ef..7817082 100644 --- a/LICENSE +++ b/LICENSE @@ -235,3 +235,349 @@ NoMachine is installed for personal use only. Please visit the link below to become familiar with the NoMachine v7 End User License Agreement. ============================================================================= https://www.nomachine.com/licensing-7 +============================================================================= + +============================================================================= +phpSysInfo uses the GNU General Public License +============================================================================= + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. +============================================================================= diff --git a/scripts/install_services.sh b/scripts/install_services.sh index b3cc5ec..af55d72 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -92,6 +92,9 @@ create_necessary_dirs() { [ -L ${EXTRACTED}/scripts ] || sudo -u ${USER} ln -s $(dirname ${my_dir})/scripts ${EXTRACTED} [ -L ${EXTRACTED}/spectrogram.php ] || sudo -u ${USER} ln -s $(dirname ${my_dir})/scripts/spectrogram.* ${EXTRACTED} [ -L ${EXTRACTED}/viewdb.php ] || sudo -u ${USER} ln -s $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED} + sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED} + [ -L ${EXTRACTED}/phpsysinfo.ini ] || sudo -u ${USER} cp ${HOME}/phpsysinfo/phpsysinfo.ini.new ${HOME}/phpsysinfo/phpsysinfo.ini + } install_alsa() { @@ -242,10 +245,6 @@ http://birdlog.local { http://extractionlog.local { reverse_proxy localhost:8888 } - -http://birdstats.local { - reverse_proxy localhost:9090 -} EOF systemctl reload caddy } @@ -272,9 +271,6 @@ ExecStart=/bin/bash -c "/usr/bin/avahi-publish -a -R %I $(avahi-resolve -4 -n %H WantedBy=multi-user.target EOF systemctl enable --now avahi-alias@birdnetpi.local.service - systemctl enable --now avahi-alias@birdlog.local.service - systemctl enable --now avahi-alias@extractionlog.local.service - systemctl enable --now avahi-alias@birdstats.local.service } install_spectrogram_service() { @@ -335,35 +331,6 @@ ExecStart=/usr/local/bin/gotty -p 8888 --title-format "Extractions Log" journalc WantedBy=multi-user.target EOF systemctl enable --now extraction_log.service - echo "Installing the birdstats.service" - cat << EOF > /etc/systemd/system/birdstats.service -[Unit] -Description=BirdNET Statistics Log - -[Service] -Restart=on-failure -RestartSec=3 -Type=simple -User=${USER} -Environment=TERM=xterm-256color -ExecStart=/usr/local/bin/gotty -p 9090 --title-format "BirdNET-Pi Statistics" tmux new -A -s birdstats /usr/local/bin/birdnet_stats.sh - -[Install] -WantedBy=multi-user.target -EOF - systemctl enable --now birdstats.service -} - -install_tmux() { - echo "Installing tmux dependencies" - apt -qqy install libevent-2* \ - libevent-dev \ - ncurses-bin \ - ncurses-base \ - ncurses-term \ - libncurses-dev - - cp $(dirname ${my_dir})/templates/tmux.conf /etc/tmux.conf } install_sox() { @@ -381,7 +348,7 @@ install_php() { if ! which pip &> /dev/null || ! which php-fpm7.3;then echo "Installing PHP modules" apt -qq update - apt install -qqy php php-fpm php7.3-mysql + apt install -qqy php php-fpm php7.3-mysql php-xml else echo "PHP and PHP-FPM installed" fi @@ -393,6 +360,11 @@ install_php() { caddy ALL=(ALL) NOPASSWD: ALL EOF chmod 0440 /etc/sudoers.d/010_caddy-nopasswd + if [ -d ${HOME}/phpsysinfo ];then + echo "Fetching phpSysInfo" + sudo -u ${USER} git clone https://github.com/phpsysinfo/phpsysinfo.git \ + ${HOME}/phpsysinfo + fi } install_edit_birdnet_conf() { @@ -406,7 +378,7 @@ RestartSec=3 Type=simple User=pi Environment=TERM=xterm-256color -ExecStart=/usr/local/bin/gotty -w -p 9898 --title-format "Edit birdnet.conf" tmux new -A -s editbirdnet nano /home/pi/BirdNET-Pi/birdnet.conf +ExecStart=/usr/local/bin/gotty -w -p 9898 --title-format "Edit birdnet.conf" nano /home/pi/BirdNET-Pi/birdnet.conf [Install] WantedBy=multi-user.target @@ -501,7 +473,6 @@ install_selected_services() { if [[ "${DO_EXTRACTIONS}" =~ [Yy] ]];then install_extraction_service - create_necessary_dirs fi if [[ "${DO_RECORDING}" =~ [Yy] ]];then @@ -520,7 +491,6 @@ install_selected_services() { install_Caddyfile install_avahi_aliases install_gotty_logs - install_tmux install_sox install_mariadb install_php @@ -541,6 +511,7 @@ install_selected_services() { install_systemd_overrides fi + create_necessary_dirs install_cleanup_cron } diff --git a/scripts/reconfigure_birdnet.sh b/scripts/reconfigure_birdnet.sh index e1695fc..a362fa9 100755 --- a/scripts/reconfigure_birdnet.sh +++ b/scripts/reconfigure_birdnet.sh @@ -3,5 +3,5 @@ source /etc/birdnet/birdnet.conf uninstall.sh ${HOME}/BirdNET-Pi/scripts/install_config.sh -sudo ${HOME}/BirdNET-Pi/scripts/install_services.sh +USER=${USER} HOME=${HOME} sudo ${HOME}/BirdNET-Pi/scripts/install_services.sh echo "BirdNET-Pi has now been reconfigured." diff --git a/scripts/update_birdnet.sh b/scripts/update_birdnet.sh new file mode 100755 index 0000000..214f5f7 --- /dev/null +++ b/scripts/update_birdnet.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Update BirdNET-Pi +source /etc/birdnet/birdnet.conf +trap 'rm -f ${TMPFILE}' EXIT +SCRIPTS=(birdnet_analysis.sh +birdnet_recording.sh +birdnet_stats.sh +cleanup.sh +clear_all_data.php +clear_all_data.sh +createdb.sh +disk_usage.sh +dump_logs.sh +edit_birdnet.conf.php +edit_birdnet.conf.sh +extract_new_birdsounds.sh +install_birdnet.sh +install_config.sh +install_services.sh +install_tmux_services.sh +install_zram_service.sh +livestream.sh +pretty_date.sh +reboot_system.php +reboot_system.sh +reconfigure_birdnet.sh +restart_birdnet_analysis.php +restart_birdnet_analysis.sh +restart_birdnet_recording.php +restart_birdnet_recording.sh +restart_caddy.php +restart_caddy.sh +restart_extraction.php +restart_extraction.sh +restart_services.php +restart_services.sh +shutdown_system.php +shutdown_system.sh +species_notifier.sh +spectrogram.php +spectrogram.sh +tmux +uninstall.sh +update_species.sh +${HOME}/.gotty) + + +SERVICES=(avahi-alias@.service +avahi-alias@birdlog.local.service +avahi-alias@birdnetpi.local.service +avahi-alias@birdstats.local.service +avahi-alias@extractionlog.local.service +avahi-alias@birdterminal.local.service +birdnet_analysis.d +birdnet_analysis.service +birdnet_log.service +birdnet_recording.d +birdnet_recording.service +birdstats.service +birdterminal.service +caddy.d +caddy.service +edit_birdnet_conf.service +extraction_log.service +extraction.d +extraction.service +extraction.timer +livestream.service +spectrogram_viewer.service +${SYSTEMD_MOUNT}) + +remove_services() { + for i in "${SERVICES[@]}"; do + if [ -L /etc/systemd/system/multi-user.target.wants/"${i}" ];then + sudo systemctl kill "${i}" + fi + if [ -f /etc/systemd/system/"${i}" ];then + sudo rm /etc/systemd/system/"${i}" + fi + if [ -d /etc/systemd/system/"${i}" ];then + sudo rm -drf /etc/systemd/system/"${i}" + fi + done + remove_icecast + remove_crons +} + +remove_crons() { + TMPFILE=$(mktemp) + crontab -l | sed -e '/birdnet/,+1d' > "${TMPFILE}" + crontab "${TMPFILE}" +} + +remove_icecast() { + if [ -f /etc/init.d/icecast2 ];then + sudo /etc/init.d/icecast2 stop + sudo systemctl disable --now icecast2 + fi +} + +remove_scripts() { + for i in "${SCRIPTS[@]}";do + if [ -L "/usr/local/bin/${i}" ];then + sudo rm -v "/usr/local/bin/${i}" + fi + done +} + +echo "Updating BirdNET" +remove_services | tee -a /tmp/birdnetupdate.log +remove_scripts | tee -a /tmp/birdnetupdate.log +cd ${HOME}/BirdNET-Pi || exit 1 +#git pull || exit 1 +USER=${USER} sudo ./scripts/update_services.sh | tee -a /tmp/birdnetupdate.log + +echo "Restarting services" +for i in "${SERVICES[@]}";do + if [ -f /etc/systemd/system/"${i}" ];then + sudo systemctl restart ${i} | tee -a /tmp/birdnetupdate.log + fi +done +echo "Update Complete" diff --git a/scripts/update_services.sh b/scripts/update_services.sh new file mode 100755 index 0000000..21faeb8 --- /dev/null +++ b/scripts/update_services.sh @@ -0,0 +1,524 @@ +#!/usr/bin/env bash +# This installs the services that have been selected +#set -x # Uncomment to enable debugging +trap 'rm -f ${TMPFILE}' EXIT +trap 'exit 1' SIGINT SIGHUP +my_dir=$(realpath $(dirname $0)) +TMPFILE=$(mktemp) +nomachine_url="https://download.nomachine.com/download/7.6/Arm/nomachine_7.6.2_3_arm64.deb" +gotty_url="https://github.com/yudai/gotty/releases/download/v1.0.1/gotty_linux_arm.tar.gz" +CONFIG_FILE="$(dirname ${my_dir})/birdnet.conf" + +install_scripts() { + echo "Installing BirdNET-Pi scripts to /usr/local/bin" + ln -sf ${my_dir}/* /usr/local/bin/ + rm /usr/local/bin/index.html +} + +install_mariadb() { + if ! which mysql &> /dev/null;then + echo "Installing MariaDB Server" + apt -qqy update + apt -qqy install mariadb-server + echo "MariaDB Installed" + fi + echo "Initializing the database" +# ${my_dir}/createdb.sh +} + +install_birdnet_analysis() { + echo "Installing the birdnet_analysis.service" + cat << EOF > /etc/systemd/system/birdnet_analysis.service +[Unit] +Description=BirdNET Analysis +[Service] +Restart=always +RuntimeMaxSec=10800 +Type=simple +RestartSec=2 +User=${USER} +ExecStart=/usr/local/bin/birdnet_analysis.sh +[Install] +WantedBy=multi-user.target +EOF + systemctl enable birdnet_analysis.service +} + +install_extraction_service() { + echo "Installing the extraction.service and extraction.timer" + cat << EOF > /etc/systemd/system/extraction.service +[Unit] +Description=BirdNET BirdSound Extraction +[Service] +Restart=on-failure +RestartSec=3 +Type=simple +User=${USER} +ExecStart=/usr/local/bin/extract_new_birdsounds.sh +[Install] +WantedBy=multi-user.target +EOF + cat << EOF > /etc/systemd/system/extraction.timer +[Unit] +Description=BirdNET BirdSound Extraction Timer +Requires=extraction.service + +[Timer] +Unit=extraction.service +OnCalendar=*:*:0/10 + +[Install] +WantedBy=multi-user.target +EOF + systemctl enable extraction.timer + systemctl enable extraction.service + echo "Adding the species_updater.cron" + if ! crontab -u ${USER} -l &> /dev/null;then + crontab -u ${USER} $(dirname ${my_dir})/templates/species_updater.cron &> /dev/null + else + crontab -u ${USER} -l > ${TMPFILE} + cat $(dirname ${my_dir})/templates/species_updater.cron >> ${TMPFILE} + crontab -u ${USER} "${TMPFILE}" &> /dev/null + fi +} + +create_necessary_dirs() { + echo "Creating necessary directories" + [ -d ${EXTRACTED} ] || sudo -u ${USER} mkdir -p ${EXTRACTED} + [ -d ${EXTRACTED}/By_Date ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Date + [ -d ${EXTRACTED}/By_Common_Name ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Common_Name + [ -d ${EXTRACTED}/By_Scientific_Name ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/By_Scientific_Name + [ -d ${PROCESSED} ] || sudo -u ${USER} mkdir -p ${PROCESSED} + [ -L ${EXTRACTED}/scripts ] || sudo -u ${USER} ln -s $(dirname ${my_dir})/scripts ${EXTRACTED} + [ -L ${EXTRACTED}/spectrogram.php ] || sudo -u ${USER} ln -s $(dirname ${my_dir})/scripts/spectrogram.* ${EXTRACTED} + [ -L ${EXTRACTED}/viewdb.php ] || sudo -u ${USER} ln -s $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED} + sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED} + [ -L ${EXTRACTED}/phpsysinfo.ini ] || sudo -u ${USER} cp ${HOME}/phpsysinfo/phpsysinfo.ini.new ${HOME}/phpsysinfo/phpsysinfo.ini +} + +install_alsa() { + echo "Checking for alsa-utils and pulseaudio" + if which arecord &> /dev/null ;then + echo "alsa-utils installed" + else + echo "Installing alsa-utils" + apt -qqq update + apt install -qqy alsa-utils + echo "alsa-utils installed" + fi + if which pulseaudio &> /dev/null;then + echo "PulseAudio installed" + else + echo "Installing pulseaudio" + apt -qqq update + apt install -qqy pulseaudio + echo "PulseAudio installed" + fi +} + +install_recording_service() { + echo "Installing birdnet_recording.service" + cat << EOF > /etc/systemd/system/birdnet_recording.service +[Unit] +Description=BirdNET Recording + +[Service] +Environment=XDG_RUNTIME_DIR=/run/user/1000 +Restart=always +Type=simple +RestartSec=3 +User=${USER} +ExecStart=/usr/local/bin/birdnet_recording.sh + +[Install] +WantedBy=multi-user.target +EOF + systemctl enable birdnet_recording.service +} + + +install_sshfs() { + echo "Checking for SSHFS to mount remote filesystem" + if ! which sshfs &> /dev/null ;then + echo "Installing SSHFS" + apt -qqq update + apt install -qqqy sshfs + fi +} + +setup_sshkeys() { + echo "Setting up SSH keys for SSHFS" + echo "Adding remote host key to ${HOME}/.ssh/known_hosts" + ssh-keyscan -H ${REMOTE_HOST} >> ${HOME}/.ssh/known_hosts + chown ${USER}:${USER} ${HOME}/.ssh/known_hosts &> /dev/null + if [ ! -f ${HOME}/.ssh/id_ed25519.pub ];then + echo "Creating a new key" + ssh-keygen -t ed25519 -f ${HOME}/.ssh/id_ed25519 -P "" + fi + chown -R ${USER}:${USER} ${HOME}/.ssh/ &> /dev/null + echo "Copying public key to ${REMOTE_HOST}" + ssh-copy-id ${REMOTE_USER}@${REMOTE_HOST} +} + +install_systemd_mount() { + echo "Installing systemd.mount" + cat << EOF > /etc/systemd/system/${SYSTEMD_MOUNT} +[Unit] +Description=Mount remote fs with sshfs +DefaultDependencies=no +Conflicts=umount.target +After=network-online.target +Before=umount.target +Wants=network-online.target +[Install] +WantedBy=multi-user.target +[Mount] +What=${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_RECS_DIR} +Where=${RECS_DIR} +Type=fuse.sshfs +Options=delay_connect,_netdev,allow_other,IdentityFile=${HOME}/.ssh/id_ed25519,reconnect,ServerAliveInterval=30,ServerAliveCountMax=5,x-systemd.automount,uid=1000,gid=1000 +TimeoutSec=60 +EOF +} + +install_caddy() { + if ! which caddy &> /dev/null ;then + echo "Installing Caddy" + curl -1sLf \ + 'https://dl.cloudsmith.io/public/caddy/stable/setup.deb.sh' \ + | sudo -E bash + apt -qq update + apt install -qqy caddy + systemctl enable --now caddy + else + echo "Caddy is installed" + systemctl enable --now caddy + fi +} + +install_Caddyfile() { + echo "Installing the Caddyfile" + [ -d /etc/caddy ] || mkdir /etc/caddy + sudo -u ${USER} ln -sf $(dirname ${my_dir})/templates/index.html ${EXTRACTED}/ + if [ -f /etc/caddy/Caddyfile ];then + cp /etc/caddy/Caddyfile{,.original} + fi + HASHWORD=$(caddy hash-password -plaintext ${CADDY_PWD}) + cat << EOF > /etc/caddy/Caddyfile +${EXTRACTIONS_URL} { + root * ${EXTRACTED} + file_server browse + basicauth /Processed* { + birdnet ${HASHWORD} + } + basicauth /scripts* { + birdnet ${HASHWORD} + } + basicauth /stream { + birdnet ${HASHWORD} + } + reverse_proxy /stream localhost:8000 + php_fastcgi unix//run/php/php7.3-fpm.sock +} + +http://birdnetpi.local { + root * ${EXTRACTED} + file_server browse + basicauth /Processed* { + birdnet ${HASHWORD} + } + basicauth /scripts* { + birdnet ${HASHWORD} + } + basicauth /stream { + birdnet ${HASHWORD} + } + reverse_proxy /stream localhost:8000 + php_fastcgi unix//run/php/php7.3-fpm.sock +} + +http://birdlog.local { + reverse_proxy localhost:8080 +} + +http://extractionlog.local { + reverse_proxy localhost:8888 +} +EOF + systemctl reload caddy +} + +install_avahi_aliases() { + echo "Installing Avahi Services" + if ! which avahi-publish &> /dev/null; then + echo "Installing avahi-utils" + apt install -y avahi-utils &> /dev/null + fi + echo "Installing avahi-alias service" + cat << 'EOF' > /etc/systemd/system/avahi-alias@.service +[Unit] +Description=Publish %I as alias for %H.local via mdns +After=network.target network-online.target +Requires=network-online.target + +[Service] +Restart=always +Type=simple +ExecStart=/bin/bash -c "/usr/bin/avahi-publish -a -R %I $(avahi-resolve -4 -n %H.local | cut -f 2)" + +[Install] +WantedBy=multi-user.target +EOF + systemctl enable --now avahi-alias@birdnetpi.local.service +} + +install_spectrogram_service() { + cat << EOF > /etc/systemd/system/spectrogram_viewer.service +[Unit] +Description=BirdNET-Pi Spectrogram Viewer +[Service] +Restart=always +RestartSec=10 +Type=simple +User=${USER} +ExecStart=/usr/local/bin/spectrogram.sh +[Install] +WantedBy=multi-user.target +EOF + systemctl enable --now spectrogram_viewer.service +} + +install_gotty_logs() { + echo "Installing GoTTY logging" + if ! which gotty &> /dev/null;then + echo "Installing GoTTY binary" + wget -c ${gotty_url} -O - | tar -xz -C /usr/local/bin/ + fi + sudo -u ${USER} ln -sf $(dirname ${my_dir})/templates/gotty \ + ${HOME}/.gotty + echo "Installing the birdnet_log.service" + cat << EOF > /etc/systemd/system/birdnet_log.service +[Unit] +Description=BirdNET Analysis Log + +[Service] +Restart=on-failure +RestartSec=3 +Type=simple +User=${USER} +Environment=TERM=xterm-256color +ExecStart=/usr/local/bin/gotty -p 8080 --title-format "BirdNET-Pi Log" journalctl -o cat -fu birdnet_analysis.service + +[Install] +WantedBy=multi-user.target +EOF + systemctl enable --now birdnet_log.service + echo "Installing the extraction_log.service" + cat << EOF > /etc/systemd/system/extraction_log.service +[Unit] +Description=BirdNET Extraction Log + +[Service] +Restart=on-failure +RestartSec=3 +Type=simple +User=${USER} +Environment=TERM=xterm-256color +ExecStart=/usr/local/bin/gotty -p 8888 --title-format "Extractions Log" journalctl -o cat -fu extraction.service + +[Install] +WantedBy=multi-user.target +EOF + systemctl enable --now extraction_log.service +} + +install_sox() { + if which sox &> /dev/null;then + echo "Sox is installed" + else + echo "Installing sox" + apt -qq update + apt install -y sox + echo "Sox installed" + fi +} + +install_php() { + if ! which pip &> /dev/null || ! which php-fpm7.3;then + echo "Installing PHP modules" + apt -qq update + apt install -qqy php php-fpm php7.3-mysql php-xml + else + echo "PHP and PHP-FPM installed" + fi + echo "Configuring PHP for Caddy" + sed -i 's/www-data/caddy/g' /etc/php/7.3/fpm/pool.d/www.conf + systemctl restart php7.3-fpm.service + echo "Adding Caddy sudoers rule" + cat << EOF > /etc/sudoers.d/010_caddy-nopasswd +caddy ALL=(ALL) NOPASSWD: ALL +EOF + chmod 0440 /etc/sudoers.d/010_caddy-nopasswd + if [ ! -d ${HOME}/phpsysinfo ];then + echo "Fetching phpSysInfo" + sudo -u ${USER} git clone https://github.com/phpsysinfo/phpsysinfo.git \ + ${HOME}/phpsysinfo + fi +} + +install_edit_birdnet_conf() { + cat << EOF > /etc/systemd/system/edit_birdnet_conf.service +[Unit] +Description=Edit birdnet.conf + +[Service] +Restart=on-failure +RestartSec=3 +Type=simple +User=pi +Environment=TERM=xterm-256color +ExecStart=/usr/local/bin/gotty -w -p 9898 --title-format "Edit birdnet.conf" nano /home/pi/BirdNET-Pi/birdnet.conf + +[Install] +WantedBy=multi-user.target +EOF +} + + +install_icecast() { + if ! which icecast2;then + echo "Installing IceCast2" + apt -qq update + echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections + apt install -qqy icecast2 + config_icecast + systemctl enable --now icecast2 + /etc/init.d/icecast2 start + else + echo "Icecast2 is installed" + config_icecast + systemctl enable --now icecast2 + /etc/init.d/icecast2 start + fi +} + +config_icecast() { + if [ -f /etc/icecast2/icecast.xml ];then + cp /etc/icecast2/icecast.xml{,.prebirdnetpi} + fi + sed -i 's/>adminbirdnet.*<\/${i}password>/<${i}password>${ICE_PWD}<\/${i}password>/g" /etc/icecast2/icecast.xml + done +} + +install_livestream_service() { + echo "Installing Live Stream service" + cat << EOF > /etc/systemd/system/livestream.service +[Unit] +Description=BirdNET-Pi Live Stream + +[Service] +Environment=XDG_RUNTIME_DIR=/run/user/1000 +Restart=always +Type=simple +RestartSec=3 +User=${USER} +ExecStart=/usr/local/bin/livestream.sh + +[Install] +WantedBy=multi-user.target +EOF + systemctl enable --now livestream.service +} + +install_nomachine() { + echo "Installing NoMachine" + cd ~ + curl -s -O "${nomachine_url}" + apt install -y ${HOME}/nomachine_7.6.2_3_arm64.deb + rm -f ${HOME}/nomachine_7.6.2_3_arm64.deb +} + +install_systemd_overrides() { + for i in caddy birdnet_analysis extraction birdnet_recording;do + if [ -f /etc/systemd/system/${i}.service ];then + [ -d /etc/systemd/system/${i}.d ] || mkdir /etc/systemd/system/${i}.d + echo "Installing the systemd overrides.conf for the ${i}.service" + cat << EOF > /etc/systemd/system/${i}.d/overrides.conf +[Unit] +After=network.target network-online.target ${SYSTEMD_MOUNT} +Requires=network-online.target ${SYSTEMD_MOUNT} +EOF + fi + done +} + +install_cleanup_cron() { + echo "Installing the cleanup.cron" + if ! crontab -u ${USER} -l &> /dev/null;then + crontab -u ${USER} $(dirname ${my_dir})/templates/cleanup.cron &> /dev/null + else + crontab -u ${USER} -l > ${TMPFILE} + cat $(dirname ${my_dir})/templates/cleanup.cron >> ${TMPFILE} + crontab -u ${USER} "${TMPFILE}" &> /dev/null + fi +} + +install_selected_services() { + install_scripts + install_birdnet_analysis + + if [[ "${DO_EXTRACTIONS}" =~ [Yy] ]];then + install_extraction_service + fi + + if [[ "${DO_RECORDING}" =~ [Yy] ]];then + install_alsa + install_recording_service + fi + + if [[ "${REMOTE}" =~ [Yy] ]];then + install_sshfs + setup_sshkeys + install_systemd_mount + fi + + if [ ! -z "${EXTRACTIONS_URL}" ];then + install_caddy + install_Caddyfile + install_avahi_aliases + install_gotty_logs + install_sox + install_mariadb + install_php + install_spectrogram_service + install_edit_birdnet_conf + fi + + if [ ! -z "${ICE_PWD}" ];then + install_icecast + install_livestream_service + fi + + if [[ "${INSTALL_NOMACHINE}" =~ [Yy] ]];then + install_nomachine + fi + + if [[ "${REMOTE}" =~ [Yy] ]];then + install_systemd_overrides + fi + + create_necessary_dirs + install_cleanup_cron +} + +if [ -f ${CONFIG_FILE} ];then + source ${CONFIG_FILE} + USER=${BIRDNET_USER} + HOME="$(getent passwd ${BIRDNET_USER} | cut -d: -f6)" + install_selected_services +else + echo "Unable to find a configuration file. Please make sure that $CONFIG_FILE exists." +fi