diff --git a/Birders_Guide_Installer.sh b/Birders_Guide_Installer.sh index 36998d7..c45aa57 100755 --- a/Birders_Guide_Installer.sh +++ b/Birders_Guide_Installer.sh @@ -194,7 +194,7 @@ BIRDNET_USER=pi ## it needs to analyze. Be sure this directory is readable and writable for ## the BIRDNET_USER. If you are going to be accessing a remote data-set, you ## still need to set this, as this will be where the remote directory gets -## mounted locally. See REMOTE_RECS_DIR below for mounting remote data-sets. +## mounted locally. RECS_DIR=${HOME}/BirdSongs @@ -219,7 +219,7 @@ DO_EXTRACTIONS=y ################################################################################ #----------------------------- Recording Service ----------------------------# -#_______________The two variables below can be set to enable __________________# +#____________________The variable below can be set to enable __________________# #________________________the birdnet_recording.service ________________________# # Keep this EMPTY if you do not want this device to perform the recording. # @@ -230,51 +230,6 @@ DO_EXTRACTIONS=y DO_RECORDING=y -## TIMESTAMP_FORMAT is the format the recording service will use to name its -## files. Setting this variable to "12" will name the recorded (and extracted) -## files using the 12-hour AM/PM time format. Setting this variable to "24" -## will name the files using the 24-hour time format. See examples below: -# -## TIMESTAMP_FORMAT=12 -## example filename: 236-Northern_Cardinal-86%2021-09-30-birdnet-01:00:19pm.wav -# -## TIMESTAMP_FORMAT=24 -## example filename: 236-Northern_Cardinal-86%2021-09-30-birdnet-13:00:19.wav - - -TIMESTAMP_FORMAT=24 - - -################################################################################ -#----------------- Mounting a remote directory with systemd -----------------# -#_______________The four variables below can be set to enable a_______________# -#___________________systemd.mount for analysis, extraction,____________________# -#______________________________or file-serving_________________________________# - -# Leave these settings EMPTY if your data-set is local. # - -## REMOTE is simply a setting for enabling the systemd.mount to use a remote -## filesystem for the data storage and service. -## Set this to Y or y to enable the systemd.mount. - -REMOTE= - -## REMOTE_HOST is the IP address, hostname, or domain name SSH should use to -## connect for FUSE to mount its remote directories locally. - -REMOTE_HOST= - -## REMOTE_USER is the user SSH will use to connect to the REMOTE_HOST. - -REMOTE_USER= - -## REMOTE_RECS_DIR is the directory on the REMOTE_HOST which contains the -## data-set SSHFS should mount to this system for local access. This is NOT the -## directory where you will access the data on this machine. See RECS_DIR for -## that. - -REMOTE_RECS_DIR= - ################################################################################ #----------------------- Web-hosting/Caddy File-server -----------------------# #__________The two variables below can be set to enable web access_____________# diff --git a/LICENSE b/LICENSE index fafb5ef..bc0bb80 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 v2.0 +============================================================================= + + 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/README.md b/README.md index 728bb64..0a7e5e0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # BirdNET-Pi -![version](https://img.shields.io/badge/version-0.1-blue) +![version](https://img.shields.io/badge/version-0.2-orange) A realtime acoustic bird classification system for the Raspberry Pi 4B @@ -14,6 +14,8 @@ The BirdNET-Pi project is built on the [TFLite version of BirdNET](https://githu * MariaDB integration * NoMachine remote desktop (for personal use only) * Live audio stream +* Integrated phpSysInfo +* New species mobile notifications from Pushed.co (for iOS users only) * Localisation supported ## Requirements diff --git a/Testing_UPDATER b/Testing_UPDATER new file mode 100644 index 0000000..1f7ec48 --- /dev/null +++ b/Testing_UPDATER @@ -0,0 +1 @@ +I hope this works:) diff --git a/birdnet.conf-defaults b/birdnet.conf-defaults index 463931b..f3de83c 100644 --- a/birdnet.conf-defaults +++ b/birdnet.conf-defaults @@ -13,7 +13,7 @@ BIRDNET_USER= ## it needs to analyze. Be sure this directory is readable and writable for ## the BIRDNET_USER. If you are going to be accessing a remote data-set, you ## still need to set this, as this will be where the remote directory gets -## mounted locally. See REMOTE_RECS_DIR below for mounting remote data-sets. +## mounted locally. RECS_DIR= @@ -40,7 +40,7 @@ DO_EXTRACTIONS= ################################################################################ #----------------------------- Recording Service ----------------------------# -#_______________The two variables below can be set to enable __________________# +#____________________The variable below can be set to enable __________________# #________________________the birdnet_recording.service ________________________# # Keep this EMPTY if you do not want this device to perform the recording. # @@ -51,50 +51,6 @@ DO_EXTRACTIONS= DO_RECORDING= -## TIMESTAMP_FORMAT is the format the recording service will use to name its -## files. Setting this variable to "12" will name the recorded (and extracted) -## files using the 12-hour AM/PM time format. Setting this variable to "24" -## will name the files using the 24-hour time format. See examples below: -# -## TIMESTAMP_FORMAT=12 -## example filename: 236-Northern_Cardinal-86%2021-09-30-birdnet-01:00:19pm.wav -# -## TIMESTAMP_FORMAT=24 -## example filename: 236-Northern_Cardinal-86%2021-09-30-birdnet-13:00:19.wav - - -TIMESTAMP_FORMAT= - -################################################################################ -#----------------- Mounting a remote directory with systemd -----------------# -#_______________The four variables below can be set to enable a________________# -#___________________systemd.mount for analysis, extraction,____________________# -#______________________________or file-serving_________________________________# - -# Leave these settings EMPTY if your data-set is local. # - -## REMOTE is simply a setting for enabling the systemd.mount to use a remote -## filesystem for the data storage and service. -## Set this to Y or y to enable the systemd.mount. - -REMOTE= - -## REMOTE_HOST is the IP address, hostname, or domain name SSH should use to -## connect for FUSE to mount its remote directories locally. - -REMOTE_HOST= - -## REMOTE_USER is the user SSH will use to connect to the REMOTE_HOST. - -REMOTE_USER= - -## REMOTE_RECS_DIR is the directory on the REMOTE_HOST which contains the -## data-set SSHFS should mount to this system for local access. This is NOT the -## directory where you will access the data on this machine. See RECS_DIR for -## that. - -REMOTE_RECS_DIR= - ################################################################################ #----------------------- Web-hosting/Caddy File-server -----------------------# #__________The two variables below can be set to enable web access_____________# diff --git a/scripts/clear_all_data.sh b/scripts/clear_all_data.sh index de0b816..d7b0035 100755 --- a/scripts/clear_all_data.sh +++ b/scripts/clear_all_data.sh @@ -21,6 +21,9 @@ sudo -u ${BIRDNET_USER} ln -s /home/pi/BirdNET-Pi/templates/index.html ${EXTRACT [ -L ${EXTRACTED}/spectrogram.php ] || sudo -u ${BIRDNET_USER} ln -s /home/pi/BirdNET-Pi/scripts/spectrogram.php ${EXTRACTED} [ -L ${EXTRACTED}/spectrogram.sh ] || sudo -u ${BIRDNET_USER} ln -s /home/pi/BirdNET-Pi/scripts/spectrogram.sh ${EXTRACTED} [ -L ${EXTRACTED}/viewdb.php ] || sudo -u ${BIRDNET_USER} ln -s /home/pi/BirdNET-Pi/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 + sudo -u ${BIRDNET_USER} cp ~/BirdNET-Pi/templates/index.html ${EXTRACTED}/ echo "Dropping and re-creating database" diff --git a/scripts/extract_new_birdsounds.sh b/scripts/extract_new_birdsounds.sh index d337240..8353385 100755 --- a/scripts/extract_new_birdsounds.sh +++ b/scripts/extract_new_birdsounds.sh @@ -129,7 +129,7 @@ for h in "${SCAN_DIRS[@]}";do "${NEWSPECIES_BYDATE}/${NEWFILE}" # Create spectrogram for extraction - sox "${NEWSPECIES_BYDATE}/${NEWFILE}" -n spectrogram \ + sox "${NEWSPECIES_BYDATE}/${NEWFILE}" -n remix 1 rate 24k spectrogram \ -t "${COMMON_NAME}" \ -c "${NEWSPECIES_BYDATE}/${NEWFILE}" \ -o "${NEWSPECIES_BYDATE}/${NEWFILE}.png" diff --git a/scripts/index.html b/scripts/index.html index 982c2c2..7c52582 100644 --- a/scripts/index.html +++ b/scripts/index.html @@ -1,8 +1,13 @@ +
-
+ + +
+ +
@@ -18,20 +23,23 @@ -
+
-
- +
-
+ + +
+ +
-
+
diff --git a/scripts/install_config.sh b/scripts/install_config.sh index 0e1b968..2dafe15 100755 --- a/scripts/install_config.sh +++ b/scripts/install_config.sh @@ -31,17 +31,6 @@ get_DO_EXTRACTIONS() { done } -get_TIMESTAMP_FORMAT() { - read -n2 -p "Would you like recordings to be time stamped in 12-hour AM/PM -or 24-hour format? " TIMESTAMP_FORMAT - echo - case $TIMESTAMP_FORMAT in - 12 ) ;; - 24 ) ;; - * ) TIMESTAMP_FORMAT=24;; - esac -} - get_DO_RECORDING() { while true; do read -n1 -p "Is this device also doing the recording? " DO_RECORDING @@ -54,22 +43,6 @@ get_DO_RECORDING() { done } -get_REMOTE() { - while true; do - read -n1 -p "Are the recordings mounted on a remote file system?" REMOTE - echo - case $REMOTE in - [Yy] ) - read -p "What is the remote hostname or IP address for the recorder? " REMOTE_HOST - read -p "Who is the remote user? " REMOTE_USER - read -p "What is the absolute path of the recordings directory on the remote host? " REMOTE_RECS_DIR - break;; - [Nn] ) break;; - * ) echo "Please answer Yes or No (y or n)";; - esac - done -} - get_EXTRACTIONS_URL() { while true;do read -n1 -p "Would you like to access the extractions via a web browser? @@ -192,8 +165,6 @@ configure() { get_DB_PWDS get_DO_EXTRACTIONS get_DO_RECORDING - get_TIMESTAMP_FORMAT - get_REMOTE get_EXTRACTIONS_URL get_PUSHED get_INSTALL_NOMACHINE @@ -242,7 +213,7 @@ DO_EXTRACTIONS=${DO_EXTRACTIONS} ################################################################################ #----------------------------- Recording Service ----------------------------# -#_______________The two variables below can be set to enable __________________# +#____________________The variable below can be set to enable __________________# #________________________the birdnet_recording.service ________________________# # Keep this EMPTY if you do not want this device to perform the recording. # @@ -253,51 +224,6 @@ DO_EXTRACTIONS=${DO_EXTRACTIONS} DO_RECORDING=${DO_RECORDING} -## TIMESTAMP_FORMAT is the format the recording service will use to name its -## files. Setting this variable to "12" will name the recorded (and extracted) -## files using the 12-hour AM/PM time format. Setting this variable to "24" -## will name the files using the 24-hour time format. See examples below: -# -## TIMESTAMP_FORMAT=12 -## example filename: 236-Northern_Cardinal-86%2021-09-30-birdnet-01:00:19pm.wav -# -## TIMESTAMP_FORMAT=24 -## example filename: 236-Northern_Cardinal-86%2021-09-30-birdnet-13:00:19.wav - - -TIMESTAMP_FORMAT=${TIMESTAMP_FORMAT} - - -################################################################################ -#----------------- Mounting a remote directory with systemd -----------------# -#_______________The four variables below can be set to enable a_______________# -#___________________systemd.mount for analysis, extraction,____________________# -#______________________________or file-serving_________________________________# - -# Leave these settings EMPTY if your data-set is local. # - -## REMOTE is simply a setting for enabling the systemd.mount to use a remote -## filesystem for the data storage and service. -## Set this to Y or y to enable the systemd.mount. - -REMOTE=${REMOTE} - -## REMOTE_HOST is the IP address, hostname, or domain name SSH should use to -## connect for FUSE to mount its remote directories locally. - -REMOTE_HOST=${REMOTE_HOST} - -## REMOTE_USER is the user SSH will use to connect to the REMOTE_HOST. - -REMOTE_USER=${REMOTE_USER} - -## REMOTE_RECS_DIR is the directory on the REMOTE_HOST which contains the -## data-set SSHFS should mount to this system for local access. This is NOT the -## directory where you will access the data on this machine. See RECS_DIR for -## that. - -REMOTE_RECS_DIR=${REMOTE_RECS_DIR} - ################################################################################ #----------------------- Web-hosting/Caddy File-server -----------------------# #__________The two variables below can be set to enable web access_____________# diff --git a/scripts/install_services.sh b/scripts/install_services.sh index b3cc5ec..388e029 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -1,13 +1,15 @@ #!/usr/bin/env bash # This installs the services that have been selected #set -x # Uncomment to enable debugging -trap 'rm -f ${TMPFILE}' EXIT +trap 'rm -f ${tmpfile}' EXIT trap 'exit 1' SIGINT SIGHUP -my_dir=$(realpath $(dirname $0)) -TMPFILE=$(mktemp) +USER=pi +HOME=/home/pi +my_dir=${HOME}/BirdNET-Pi/scripts +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" +config_file="$(dirname ${my_dir})/birdnet.conf" install_scripts() { echo "Installing BirdNET-Pi scripts to /usr/local/bin" @@ -72,14 +74,23 @@ 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 +} + +install_pushed_notifications() { + echo "Installing Pushed.co mobile notifications" + cat << EOF > /etc/systemd/system/pushed_notifications.service +[Unit] +Description=BirdNET-Pi Pushed.co Notifications +[Service] +Restart=on-success +RestartSec=3 +Type=simple +User=pi +ExecStart=/usr/local/bin/species_notifier.sh +[Install] +WantedBy=multi-user.target +EOF + systemctl enable --now pushed_notifications } create_necessary_dirs() { @@ -89,9 +100,13 @@ create_necessary_dirs() { [ -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}/index.html ] || sudo -u ${USER} ln -s $(dirname ${my_dir})/templates/index.html ${EXTRACTED} [ -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() { @@ -134,51 +149,6 @@ 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" @@ -197,7 +167,6 @@ install_caddy() { 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 @@ -215,6 +184,9 @@ ${EXTRACTIONS_URL} { basicauth /stream { birdnet ${HASHWORD} } + basicauth /phpsysinfo* { + birdnet ${HASHWORD} + } reverse_proxy /stream localhost:8000 php_fastcgi unix//run/php/php7.3-fpm.sock } @@ -231,21 +203,12 @@ http://birdnetpi.local { basicauth /stream { birdnet ${HASHWORD} } + basicauth /phpsysinfo* { + 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 -} - -http://birdstats.local { - reverse_proxy localhost:9090 -} EOF systemctl reload caddy } @@ -272,9 +235,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 +295,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() { @@ -378,10 +309,10 @@ install_sox() { } install_php() { - if ! which pip &> /dev/null || ! which php-fpm7.3;then + if ! which php &> /dev/null || ! which php-fpm7.3 || ! apt list --installed | grep php-xml;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 +324,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 +342,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 @@ -463,25 +399,12 @@ EOF } 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 + if [ ! -d /usr/share/NX ];then + echo "Installing NoMachine" + curl -s -o ${HOME}/nomachine.deb -O "${nomachine_url}" + apt install -y ${HOME}/nomachine.deb + rm -f ${HOME}/nomachine.deb + fi } install_cleanup_cron() { @@ -489,9 +412,9 @@ install_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 + crontab -u ${USER} -l > ${tmpfile} + cat $(dirname ${my_dir})/templates/cleanup.cron >> ${tmpfile} + crontab -u ${USER} "${tmpfile}" &> /dev/null fi } @@ -501,7 +424,6 @@ install_selected_services() { if [[ "${DO_EXTRACTIONS}" =~ [Yy] ]];then install_extraction_service - create_necessary_dirs fi if [[ "${DO_RECORDING}" =~ [Yy] ]];then @@ -509,23 +431,17 @@ install_selected_services() { 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_tmux install_sox install_mariadb install_php install_spectrogram_service install_edit_birdnet_conf + install_pushed_notifications fi if [ ! -z "${ICE_PWD}" ];then @@ -537,18 +453,13 @@ install_selected_services() { 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)" +if [ -f ${config_file} ];then + source ${config_file} install_selected_services else - echo "Unable to find a configuration file. Please make sure that $CONFIG_FILE exists." + echo "Unable to find a configuration file. Please make sure that $config_file exists." fi 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/species_notifier.sh b/scripts/species_notifier.sh index 089a4a9..a7a01bc 100755 --- a/scripts/species_notifier.sh +++ b/scripts/species_notifier.sh @@ -1,26 +1,26 @@ #!/usr/bin/env bash # Sends a notification if a new species is detected #set -x -trap 'rm -f $TMPFILE' SIGINT SIGHUP EXIT - +trap 'rm -f $lastcheck' EXIT source /etc/birdnet/birdnet.conf -TMPFILE=$(mktemp) +lastcheck="$(mktemp)" [ -f ${IDFILE} ] || touch ${IDFILE} -cat "${IDFILE}" > "${TMPFILE}" -/usr/local/bin/update_species.sh > /dev/null +cp ${IDFILE} ${lastcheck} + +/home/pi/BirdNET-Pi/scripts/update_species.sh + +if ! diff ${IDFILE} ${lastcheck} &> /dev/null;then + SPECIES=$(diff ${IDFILE} ${lastcheck} \ + | tail -n+2 |\ + awk '{for(i=2;i<=NF;++i)printf $i""FS ; print ""}' ) -if ! diff "${IDFILE}" "${TMPFILE}" &> /dev/null; then - SPECIES=("$(diff "${IDFILE}" "${TMPFILE}" \ - | grep "Common Name" \ - | sort \ - | awk '{for(i=4;i<=NF;++i)printf $i""FS ; print ""}')") - NOTIFICATION="New Species Detection: "${SPECIES[@]}"" echo "Sending the following notification: ${NOTIFICATION}" + if [ ! -z ${PUSHED_APP_KEY} ];then curl -X POST \ --form-string "app_key=${PUSHED_APP_KEY}" \ @@ -30,3 +30,4 @@ ${NOTIFICATION}" https://api.pushed.co/1/push fi fi + diff --git a/scripts/spectrogram.sh b/scripts/spectrogram.sh index c8b6667..db36975 100755 --- a/scripts/spectrogram.sh +++ b/scripts/spectrogram.sh @@ -3,4 +3,5 @@ source /etc/birdnet/birdnet.conf analyzing_now="$(cat /home/pi/BirdNET-Pi/analyzing_now.txt)" spectrogram_png=${EXTRACTED}/spectrogram.png -sudo -u pi sox "${analyzing_now}" -n spectrogram -t "Currently Analyzing" -c "${analyzing_now}" -o "${spectrogram_png}" +#sudo -u pi sox "${analyzing_now}" -n spectrogram -t "Currently Analyzing" -c "${analyzing_now}" -o "${spectrogram_png}" +sudo -u pi sox "${analyzing_now}" -n remix 1 rate 24k spectrogram -t "Currently Analyzing" -c "${analyzing_now}" -o "${spectrogram_png}" diff --git a/scripts/stop_core_services.php b/scripts/stop_core_services.php new file mode 100644 index 0000000..e335b68 --- /dev/null +++ b/scripts/stop_core_services.php @@ -0,0 +1,4 @@ + diff --git a/scripts/stop_core_services.sh b/scripts/stop_core_services.sh new file mode 100755 index 0000000..2f2c8f4 --- /dev/null +++ b/scripts/stop_core_services.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Restarts ALL services and removes ALL unprocessed audio + + +services=(birdnet_recording.service +birdnet_analysis.service +extraction.timer) + +for i in "${services[@]}";do + sudo systemctl stop ${i} +done +sudo rm -rf ${RECS_DIR}/$(date +%B-%Y/%d-%A)/* diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh index 3f04091..ed8fc6c 100755 --- a/scripts/uninstall.sh +++ b/scripts/uninstall.sh @@ -51,21 +51,19 @@ 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 +pushed_notifications.service spectrogram_viewer.service ${SYSTEMD_MOUNT}) diff --git a/scripts/update_birdnet.php b/scripts/update_birdnet.php new file mode 100644 index 0000000..ff20b68 --- /dev/null +++ b/scripts/update_birdnet.php @@ -0,0 +1,4 @@ + /tmp/phpupdate.log 2&>1"); +header('Location: http://birdnetpi.local/index.html?success=true'); +?> diff --git a/scripts/update_birdnet.sh b/scripts/update_birdnet.sh new file mode 100755 index 0000000..aeb041d --- /dev/null +++ b/scripts/update_birdnet.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash +# Update BirdNET-Pi +source /etc/birdnet/birdnet.conf +trap 'rm -f ${tmpfile}' EXIT +trap 'exit 1' SIGINT SIGHUP +USER=pi +HOME=/home/pi +my_dir=${HOME}/BirdNET-Pi/scripts +tmpfile=$(mktemp) + +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) + + +# Change this to sourcing from current uninstall.sh +# Create a pre-update services array for disabling +# Create a post-update services array for restarting +services=(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.service +birdnet_log.service +birdnet_recording.service +birdstats.service +birdterminal.service +edit_birdnet_conf.service +extraction_log.service +extraction.service +extraction.timer +livestream.service +pushed_notifications.service +spectrogram_viewer.service) + +remove_services() { + for i in "${services[@]}"; do + if [ -L /etc/systemd/system/multi-user.target.wants/"${i}" ];then + sudo systemctl kill "${i}" + sudo systemctl disable "${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() { + crontab -u${USER} -l | sed -e '/birdnet/,+1d' > "${tmpfile}" + crontab -u${USER} "${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 +} + +restart_services() { + for i in ${services[@]};do + sudo systemctl restart ${i} + done +} + +# Stage 1 removes old stuff +remove_services +remove_scripts + +# Stage 2 does a git pull to fetch new things +sudo -u${USER} git -C ${HOME}/BirdNET-Pi pull || exit 1 + +# Stage 3 updates the services +sudo ${my_dir}/update_services.sh + +# Stage 4 restarts the services +services=(avahi-alias@birdnetpi.local.service +birdnet_analysis.service +birdnet_log.service +birdnet_recording.service +edit_birdnet_conf.service +extraction_log.service +extraction.service +extraction.timer +livestream.service +pushed_notifications.service +spectrogram_viewer.service) + +restart_services + diff --git a/scripts/update_services.sh b/scripts/update_services.sh new file mode 100755 index 0000000..97e3b4c --- /dev/null +++ b/scripts/update_services.sh @@ -0,0 +1,462 @@ +#!/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 +USER=pi +HOME=/home/pi +my_dir=${HOME}/BirdNET-Pi/scripts +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 +} + +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 +} + +install_pushed_notifications() { + echo "Installing Pushed.co mobile notifications" + cat << EOF > /etc/systemd/system/pushed_notifications.service +[Unit] +Description=BirdNET-Pi Pushed.co Notifications +[Service] +Restart=on-success +RestartSec=3 +Type=simple +User=pi +ExecStart=/usr/local/bin/species_notifier.sh +[Install] +WantedBy=multi-user.target +EOF + systemctl enable --now pushed_notifications +} + +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}/index.html ] || sudo -u ${USER} ln -s $(dirname ${my_dir})/templates/index.html ${EXTRACTED} + [ -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_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 + 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} + } + basicauth /phpsysinfo* { + 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} + } + basicauth /phpsysinfo* { + birdnet ${HASHWORD} + } + reverse_proxy /stream localhost:8000 + php_fastcgi unix//run/php/php7.3-fpm.sock +} +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 php &> /dev/null || ! which php-fpm7.3 || ! apt list --installed | grep php-xml;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 + 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() { + if [ ! -d /usr/share/NX ];then + echo "Installing NoMachine" + curl -s -o ${HOME}/nomachine.deb -O "${nomachine_url}" + apt install -y ${HOME}/nomachine.deb + rm -f ${HOME}/nomachine.deb + fi +} + +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 [ ! -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 + install_pushed_notifications + fi + + if [ ! -z "${ICE_PWD}" ];then + install_icecast + install_livestream_service + fi + + if [[ "${INSTALL_NOMACHINE}" =~ [Yy] ]];then + install_nomachine + fi + + create_necessary_dirs + install_cleanup_cron +} + +if [ -f ${config_file} ];then + source ${config_file} + install_selected_services +else + echo "Unable to find a configuration file. Please make sure that $config_file exists." +fi diff --git a/scripts/update_species.sh b/scripts/update_species.sh index 0c5f028..cc4b945 100755 --- a/scripts/update_species.sh +++ b/scripts/update_species.sh @@ -1,20 +1,14 @@ #!/usr/bin/env bash # Update the species list #set -x -trap 'rm -f "$TMPFILE"' SIGINT SIGTERM EXIT - +trap 'rm -f "$TMPFILE"' EXIT source /etc/birdnet/birdnet.conf +db=birds +dbuser=birder +dbpassword=${DB_PWD} -TMPFILE=$(mktemp) || exit 1 - -[ -f ${IDFILE} ] || touch ${IDFILE} - -if [ $(find ${PROCESSED} -name '*csv' | wc -l) -ge 1 ] &> /dev/null;then - sort $(find ${PROCESSED} ${ANALYZED} ${EXTRACTED} -name '*csv') \ - | awk -F\; '!/Scientific/ {print"Common Name: " $4 "\nScientific Name: " $3""}' \ - | uniq > "$TMPFILE" - cat "$TMPFILE" | awk '!visited[$0]++' > "$IDFILE" - cat "$IDFILE" -else - cat "$IDFILE" -fi +mysql -u${dbuser} -p${dbpassword} ${db} \ + -e 'SELECT Com_Name + FROM detections + GROUP BY Com_Name' |\ + tail -n+2 > ${IDFILE} diff --git a/scripts/viewdb.php b/scripts/viewdb.php index 9703232..ac70b0f 100644 --- a/scripts/viewdb.php +++ b/scripts/viewdb.php @@ -53,14 +53,10 @@ $mysqli->close(); + BirdNET-Pi DB