Merge branch 'main' of github.com:mcguirepr89/BirdNET-Pi
I didn't expect to need to merge?
This commit is contained in:
@@ -713,7 +713,7 @@ 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.
|
||||
=============================================================================
|
||||
Caddy, and Adminer use the Apache License Version 2.0
|
||||
Caddy, ,Streamlit, and Adminer use the Apache License Version 2.0
|
||||
=============================================================================
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<h1 align="center">
|
||||
BirdNET-Pi <img src="https://img.shields.io/badge/version-0.11.1-orange" />
|
||||
BirdNET-Pi <img src="https://img.shields.io/badge/Version-0.13-pink" />
|
||||
</h1>
|
||||
<p align="center">
|
||||
A realtime acoustic bird classification system for the Raspberry Pi 4B
|
||||
@@ -47,12 +47,11 @@ If your installation isn't in one of the countries listed above, please let me k
|
||||
* FTP server included
|
||||
* Automatic extraction of detected data (creating audio clips of detected bird sounds)
|
||||
* Spectrograms available for all extractions
|
||||
* MariaDB integration
|
||||
* NoMachine remote desktop (for personal use only)
|
||||
* SQLite3 Database
|
||||
* Live audio stream
|
||||
* Adminer database maintenance
|
||||
* Integrated phpSysInfo
|
||||
* New species mobile notifications from Pushed.co (for iOS users only)
|
||||
* [phpSysInfo](https://github.com/phpsysinfo/phpsysinfo)
|
||||
* New species mobile notifications from [Pushed.co](https://pushed.co/quick-start-guide) (for iOS users only)
|
||||
* Localization supported
|
||||
|
||||
## Requirements
|
||||
@@ -65,7 +64,7 @@ If your installation isn't in one of the countries listed above, please let me k
|
||||
|
||||
The system can be installed with:
|
||||
```
|
||||
curl -s https://raw.githubusercontent.com/mcguirepr89/BirdNET-Pi/main/newinstaller.sh | bash | tee -a installation.log 2>&1 && sudo reboot
|
||||
curl -s https://raw.githubusercontent.com/mcguirepr89/BirdNET-Pi/main/newinstaller.sh | bash
|
||||
```
|
||||
The installer takes care of any and all necessary updates, so you can run that as the very first command upon the first boot, if you'd like.
|
||||
|
||||
|
||||
+3
-57
@@ -4,13 +4,10 @@
|
||||
|
||||
#--------------------- Required: Latitude, and Longitude ----------------------#
|
||||
|
||||
## The shell substitution below guesses these based on your network. THESE NEED
|
||||
## TO BE CHANGED TO STATIC VALUES
|
||||
## Please only go to 4 decimal places. Example:43.3984
|
||||
|
||||
LATITUDE="$(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',')"
|
||||
LONGITUDE="$(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',')"
|
||||
|
||||
LATITUDE=
|
||||
LONGITUDE=
|
||||
|
||||
#--------------------- BirdWeather Station Information -----------------------#
|
||||
#_____________The variable below can be set to have your BirdNET-Pi____________#
|
||||
@@ -28,14 +25,6 @@ BIRDWEATHER_ID=
|
||||
|
||||
CADDY_PWD=
|
||||
|
||||
#------------------------- MariaDB User Passwords ---------------------------#
|
||||
#_____________The variable below sets the password for the_____________________#
|
||||
#_______________________'birder' user on the MariaDB___________________________#
|
||||
|
||||
## DB_PWD is for the 'birder' user. The shell substitution below sets a random
|
||||
## password for you during installation.
|
||||
DB_PWD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;)
|
||||
|
||||
#------------------------- Live Audio Stream --------------------------------#
|
||||
#_____________The variable below configures/enables the live___________________#
|
||||
#_____________________________audio stream.____________________________________#
|
||||
@@ -84,24 +73,6 @@ PUSHED_APP_SECRET=
|
||||
|
||||
RECS_DIR=/home/pi/BirdSongs
|
||||
|
||||
|
||||
#------------------------------ Extraction Service ---------------------------#
|
||||
|
||||
## DO_EXTRACTIONS is simply a setting for enabling the extraction.service.
|
||||
## Set this to Y or y to enable extractions.
|
||||
|
||||
DO_EXTRACTIONS=y
|
||||
|
||||
#----------------------------- Recording Service ----------------------------#
|
||||
#____________________The variable below can be set to enable __________________#
|
||||
#________________________the birdnet_recording.service ________________________#
|
||||
|
||||
## DO_RECORDING is simply a setting for enabling the 24/7
|
||||
## birdnet_recording.service.
|
||||
## Set this to Y or y to enable recording.
|
||||
|
||||
DO_RECORDING=y
|
||||
|
||||
## REC_CARD is the sound card you would want the birdnet_recording.service to
|
||||
## use. Leave this as "default" to use PulseAudio (recommended), or use
|
||||
## the output from "aplay -L" to specify an ALSA device.
|
||||
@@ -118,12 +89,6 @@ PROCESSED=${RECS_DIR}/Processed
|
||||
|
||||
EXTRACTED=${RECS_DIR}/Extracted
|
||||
|
||||
## IDFILE is the file that keeps a complete list of every spececies that
|
||||
## BirdNET has identified from your data-set. It is a relic and not really
|
||||
## used anymore.
|
||||
|
||||
IDFILE=${HOME}/BirdNET-Pi/IdentifiedSoFar.txt
|
||||
|
||||
## OVERLAP is the value in seconds which BirdNET should use when analyzing
|
||||
## the data. The values must be between 0.0-2.9.
|
||||
|
||||
@@ -150,11 +115,6 @@ CHANNELS=2
|
||||
|
||||
FULL_DISK=purge
|
||||
|
||||
## VENV is the python virtual environment wherein all modules and site-packages
|
||||
## have been installed.
|
||||
|
||||
VENV=/home/pi/BirdNET-Pi/birdnet
|
||||
|
||||
## RECORDING_LENGTH sets the length of the recording that BirdNET-Lite will
|
||||
## analyze.
|
||||
|
||||
@@ -185,18 +145,4 @@ BIRDNET_USER=pi
|
||||
## These are just for debugging
|
||||
LAST_RUN=
|
||||
THIS_RUN=
|
||||
|
||||
## DEPRECATED
|
||||
#------------------------------- NoMachine ----------------------------------#
|
||||
#_____________The variable below can be set include NoMachine__________________#
|
||||
#_________________remote desktop software to be installed._____________________#
|
||||
|
||||
# Keep this EMPTY if you do not want to install NoMachine. #
|
||||
|
||||
## INSTALL_NOMACHINE is simply a setting that can be enabled to install
|
||||
## NoMachine alongside the BirdNET-Pi for remote desktop access. This in-
|
||||
## staller assumes personal use. Please reference the LICENSE file included
|
||||
## in this repository for more information.
|
||||
## Set this to Y or y to install NoMachine alongside the BirdNET-Lite
|
||||
|
||||
INSTALL_NOMACHINE=y
|
||||
IDFILE=/home/pi/BirdNET-Pi/IdentifiedSoFar.txt
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML Frames Example - Content</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family:verdana,arial,sans-serif;
|
||||
font-size:10pt;
|
||||
margin:30px;
|
||||
background-color:#ffcc00;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
tbc....
|
||||
<h1>Thanks</h1>
|
||||
stefan kahl
|
||||
patrick mcguire
|
||||
<h1>Similar Systems</h1>
|
||||
<h1>Technical Details</h1>
|
||||
machine learning
|
||||
deep learning
|
||||
<h1>Used Tools</h1>
|
||||
SoX
|
||||
ffmpeg
|
||||
Python
|
||||
Tensorfflow (Lite)
|
||||
Rasberian OS
|
||||
<h1>Disclaimer</h1>
|
||||
<h1>Other Systems</h1>
|
||||
links to other systems
|
||||
|
||||
|
||||
|
||||
<h1>Content</h1>
|
||||
<h2>Replacing the Contents of the Current Frame</h2>
|
||||
<p>Clicking on these links will open the new page within the current frame.</p>
|
||||
<ul>
|
||||
<li><a href="white.html" target="content">Load white page</a></li>
|
||||
<li><a href="green.html" target="content">Load green page</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>Replacing the Whole Frameset</h2>
|
||||
<p>When you click on any of the following links, the whole frameset is replaced with the new website. This is because we're using <code>target="_top"</code> in the anchor links.</p>
|
||||
<ul>
|
||||
<li><a href="http://www.quackit.com" target="_top">Quackit</a></li>
|
||||
<li><a href="http://www.quackit.com/html/templates/frames/" target="_top">HTML Frames Templates</a></li>
|
||||
<li>Learn more about frames with the <a href="http://www.quackit.com/html/tutorial/html_frames.cfm" target="_top">frames tutorial</a><//li>
|
||||
</ul>
|
||||
|
||||
<h2>Open a New Window</h2>
|
||||
<p>These links open in a new browser window. This is because we use <code>target="_blank"</code>.</p>
|
||||
<ul>
|
||||
<li><a href="http://www.code-generator.net" target="_blank">Code Generator</a></li>
|
||||
<li><a href="http://www.zappyhost.com" target="_blank">ZappyHost</a></li>
|
||||
<li><a href="http://www.natural-environment.com" target="_blank">Natural Environment</a></li>
|
||||
<li><a href="http://www.great-workout.com" target="_blank">Great Workout</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,22 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML Frames Example - Footer</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family:verdana,arial,sans-serif;
|
||||
font-size:medium;
|
||||
padding-top: 15px;
|
||||
text-align:center;
|
||||
background-color: rgb(119, 196, 135);
|
||||
color: black;
|
||||
}
|
||||
a {
|
||||
color:black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a href="/stream" target="footer"><h4>Play Live Audio</h4></a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 131 B |
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 869 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96" height="20" role="img" aria-label="version: 0.11.1"><title>version: 0.11.1</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="96" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="51" height="20" fill="#555"/><rect x="51" width="45" height="20" fill="#fe7d37"/><rect width="96" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">version</text><text x="265" y="140" transform="scale(.1)" fill="#fff" textLength="410">version</text><text aria-hidden="true" x="725" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">0.11.1</text><text x="725" y="140" transform="scale(.1)" fill="#fff" textLength="350">0.11.1</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20" role="img" aria-label="Version: 0.13"><title>Version: 0.13</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="51" height="20" fill="#555"/><rect x="51" width="35" height="20" fill="pink"/><rect width="86" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">Version</text><text x="265" y="140" transform="scale(.1)" fill="#fff" textLength="410">Version</text><text aria-hidden="true" x="675" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="250">0.13</text><text x="675" y="140" transform="scale(.1)" fill="#333" textLength="250">0.13</text></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,42 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>BirdNET-Pi</title>
|
||||
<style>
|
||||
* {
|
||||
background-color: background-color: rgb(119, 196, 135);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<!--
|
||||
Note the following:
|
||||
1. Each frame has it's own 'frame' tag.
|
||||
2. Each frame has a name (eg, name="menu"). This is used for when you need to load one frame from another. For example, your left frame might have links that, when clicked on, loads a new page in the right frame. This is acheived by using 'target="content"' within your links/anchor tags.
|
||||
3. Each 'frame' tag has a 'src' attribute. This is where you specify the name of the file to be loaded into that frame when the page first loads.
|
||||
4. You can change the size of the frames by changing the value of the 'cols' and/or 'rows' attribute. A value of "200" sets the frame at 200 pixels. An asterisk (*) specifies that the frame should use up whatever space is left over from the other frames. You can also use percentage values if desired (i.e. 20%,80%)
|
||||
5. To specify a border, set 'frameborder' and 'border' to "1". I included both attributes for maximum browser compatibility.
|
||||
6. The 'framespacing' attribute doesn't work in all browsers, but you can set any numeric value you like here.
|
||||
7. To learn more about HTML frames, check out: http://www.quackit.com/html/tutorial/html_frames.cfm
|
||||
-->
|
||||
<script type="text/javascript">
|
||||
if (screen.width <= 699) {
|
||||
document.location = "/mobile.html";
|
||||
}
|
||||
</script>
|
||||
|
||||
<frameset rows="100,*" frameborder="0" border="0" framespacing="0">
|
||||
<frameset style="background-color: rgb(119, 196, 135);" cols="*,150" frameborder="0" border="0" framespacing="0" />
|
||||
<frame name="topNav" src="top.html" scrolling="off">
|
||||
<frame name="footer" src="footer.html" scrolling="off">
|
||||
</frameset>
|
||||
<frameset cols="150,*" frameborder="0" border="0" framespacing="0">
|
||||
<frame name="menu" src="menu.html" marginheight="0" marginwidth="0" scrolling="auto" noresize>
|
||||
<frame name="content" src="/overview.php" marginheight="0" marginwidth="0" scrolling="auto" noresize>
|
||||
|
||||
<noframes>
|
||||
<p>This section (everything between the 'noframes' tags) will only be displayed if the users' browser doesn't support frames. You can provide a link to a non-frames version of the website here. Feel free to use HTML tags within this section.</p>
|
||||
</noframes>
|
||||
|
||||
</frameset>
|
||||
</html>
|
||||
@@ -0,0 +1,66 @@
|
||||
<title>BirdNET-Pi</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body::-webkit-scrollbar {
|
||||
display:none
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<body>
|
||||
<div class="banner">
|
||||
<div class="logo">
|
||||
<?php if(isset($_GET['logo'])) {
|
||||
echo "<a href=\"https://github.com/mcguirepr89/BirdNET-Pi.git\" target=\"_blank\"><img style=\"width:60;height:60;\" src=\"images/bird.png\"></a>";
|
||||
} else {
|
||||
echo "<a href=\"https://github.com/mcguirepr89/BirdNET-Pi.git\" target=\"_blank\"><img src=\"images/bird.png\"></a>";
|
||||
}?>
|
||||
</div>
|
||||
<div class="stream">
|
||||
<?php
|
||||
if(isset($_GET['stream'])){
|
||||
if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/thisrun.txt');
|
||||
} elseif (file_exists('/home/pi/BirdNET-Pi/firstrun.ini')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/firstrun.ini');
|
||||
}
|
||||
$caddypwd = $config['CADDY_PWD'];
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot listen to the live audio stream';
|
||||
exit;
|
||||
} else {
|
||||
$submittedpwd = $_SERVER['PHP_AUTH_PW'];
|
||||
$submitteduser = $_SERVER['PHP_AUTH_USER'];
|
||||
if($submittedpwd == $caddypwd && $submitteduser == 'birdnet'){
|
||||
echo "
|
||||
<audio controls autoplay><source src=\"/stream\"></audio>
|
||||
</div>
|
||||
<h1><a href=\"\">BirdNET-Pi</a><img src=\"images/version.svg\"></h1>
|
||||
</div>";
|
||||
} else {
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot listen to the live audio stream';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "
|
||||
<form action=\"\" method=\"GET\">
|
||||
<button type=\"submit\" name=\"stream\" value=\"play\">Live Audio</button>
|
||||
</form>
|
||||
</div>
|
||||
<h1><a href=\"\">BirdNET-Pi</a><img src=\"images/version.svg\"></h1>
|
||||
</div>";
|
||||
}
|
||||
if(isset($_GET['log'])) {
|
||||
if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
header("Location: /log");}
|
||||
} elseif(isset($_GET['spectrogram'])){
|
||||
header("Location: /spectrogram.php");
|
||||
} else {
|
||||
echo "
|
||||
<iframe src=\"/views.php\">
|
||||
</div>";
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML Frames Example - Menu</title>
|
||||
<style type="text/css">
|
||||
a {
|
||||
text-decoration:none;
|
||||
margin: 0px 0px 0px 0px;
|
||||
color:black;
|
||||
font-size: small;
|
||||
}
|
||||
body {
|
||||
font-family:verdana,arial,sans-serif;
|
||||
font-size:medium;
|
||||
margin:10px;
|
||||
background-color: rgb(119, 196, 135);
|
||||
text-align: left;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
h3 {
|
||||
margin: 0px 0px -15px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
h4,h5 {
|
||||
text-align: left;
|
||||
margin: 0px 0px 5px 0px;
|
||||
}
|
||||
footer {
|
||||
background: rgb(119, 196, 135);
|
||||
position: fixed;
|
||||
padding-top: 10px;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width:100%;
|
||||
}
|
||||
hr {
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
body::-webkit-scrollbar {
|
||||
display:none
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h5>Extractions</h5>
|
||||
- <a href="/By_Date/" target="content">By Date</a><br>
|
||||
- <a href="/By_Common_Name/" target="content">By Common Name</a><br>
|
||||
- <a href="/By_Scientific_Name/" target="content">By Scientific Name</a><br>
|
||||
- <a href="/Processed/" target="content">Processed</a><br>
|
||||
|
||||
<hr class="solid">
|
||||
|
||||
<h5>System</h5>
|
||||
- <a href="/scripts/" target="content">Tools</a><br>
|
||||
- <a href="/phpsysinfo/" target="content">Info</a><br>
|
||||
- <a href="http://birdnetpi.local:8080" target="content">Log</a><br>
|
||||
|
||||
<hr class="solid">
|
||||
|
||||
<h5>External</h5>
|
||||
- <a href="https://app.birdweather.com" target="_content">BirdWeather</a><br>
|
||||
- <a href="https://github.com/mcguirepr89/BirdNET-Pi" target="_content">Repository</a><br>
|
||||
- <a href="https://github.com/mcguirepr89/BirdNET-Pi/wiki" target="_content">Wiki Help Page</a><br>
|
||||
- <a href="https://v2.wttr.in/" target="content">Wttr.in Report</a><br>
|
||||
- <a href="https://birdnet.cornell.edu" target="_content">BirdNET</a><br>
|
||||
<hr class="solid">
|
||||
|
||||
<h5>Other<br>BirdNET-Pis</h5>
|
||||
- <a href="https://birdnetpi.pmcgui.xyz" target="top">United States</a><br>
|
||||
- <a href="https://birds.naturestation.net" target="top">South Africa</a><br>
|
||||
- <a href="https://birdnet.svardsten.se" target="top">Sweden</a><br>
|
||||
- <a href="https://birdnetgv.ddnss.de" target="top">Germany</a>
|
||||
|
||||
</body>
|
||||
<footer style="font-size: small;">
|
||||
Icon by <a target="_content" style="font-weight: bold" href="https://www.freepik.com" title="Freepik">Freepik</a> from <a target="_content" style="font-weight: bold" href="https://www.flaticon.com/" title="Flaticon">Flaticon.com</a>
|
||||
</footer>
|
||||
|
||||
</html>
|
||||
@@ -1,80 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Menu</title>
|
||||
<style type="text/css">
|
||||
a {
|
||||
text-decoration:none;
|
||||
margin: 0px 0px 0px 0px;
|
||||
color:black;
|
||||
font-size: small;
|
||||
}
|
||||
body {
|
||||
font-family:verdana,arial,sans-serif;
|
||||
font-size:medium;
|
||||
margin:10px;
|
||||
background-color: rgb(119, 196, 135);
|
||||
text-align: left;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
h3 {
|
||||
margin: 0px 0px -15px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
h4,h5 {
|
||||
text-align: center;
|
||||
margin: 0px 0px 5px 0px;
|
||||
}
|
||||
footer {
|
||||
background: rgb(119, 196, 135);
|
||||
position: fixed;
|
||||
padding-top: 10px;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width:100%;
|
||||
}
|
||||
hr {
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
body::-webkit-scrollbar {
|
||||
display:none
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h5>Extraktionen</h5>
|
||||
- <a href="https://birdnetpi.local/By_Date/" target="content">Nach Datum</a><br>
|
||||
- <a href="https://birdnetpi.local/By_Common_Name/" target="content">Nach Namen</a><br>
|
||||
- <a href="https://birdnetpi.local/By_Scientific_Name/" target="content">Nach wiss. Namen</a><br>
|
||||
- <a href="https://birdnetpi.local/Processed/" target="content">Verarbeitet</a><br>
|
||||
|
||||
<hr class="solid">
|
||||
|
||||
<h5>System-Links</h5>
|
||||
- <a href="https://birdnetpi.local/scripts/" target="content">Tools</a><br>
|
||||
- <a href="https://birdnetpi.local/phpsysinfo/" target="content">System Info</a><br>
|
||||
- <a href="https://birdnetpi.local:8080" target="content">BirdNET-Lite Log</a><br>
|
||||
- <a href="https://birdnetpi.local:8888" target="content">Extraction Log</a><br>
|
||||
|
||||
<hr class="solid">
|
||||
|
||||
<h5>Externe Links</h5>
|
||||
- <a href="https://app.birdweather.com" target="_content">BirdWeather</a><br>
|
||||
- <a href="https://github.com/mcguirepr89/BirdNET-Pi" target="_content">Repository</a><br>
|
||||
- <a href="https://github.com/mcguirepr89/BirdNET-Pi/wiki" target="_content">Wiki Hilfe-Seite</a><br>
|
||||
- <a href="https://v2.wttr.in/" target="content">Wttr.in Report</a><br>
|
||||
- <a href="https://birdnet.cornell.edu" target="_content">BirdNET @ Cornell</a><br>
|
||||
<hr class="solid">
|
||||
|
||||
<h5>Andere<br>BirdNET-Pis</h5>
|
||||
- <a href="https://birdnetpi.pmcgui.xyz" target="_content">United States</a><br>
|
||||
- <a href="https://birds.naturestation.net" target="_content">South Africa</a><br>
|
||||
- <a href="https://birdnet.svarsten.se" target="_content">Sweden</a>
|
||||
- <a href="https://birdnetgv.ddnss.de" target="_content">Germany</a>
|
||||
|
||||
</body>
|
||||
<footer style="font-size: small;">
|
||||
Icon by <a target="_content" style="font-weight: bold" href="https://www.freepik.com" title="Freepik">Freepik</a> from <a target="_content" style="font-weight: bold" href="https://www.flaticon.com/" title="Flaticon">Flaticon.com</a>
|
||||
</footer>
|
||||
|
||||
</html>
|
||||
@@ -1,509 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>BirdNET-Pi</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
* { padding: 0; margin: 0; }
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
text-rendering: optimizespeed;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #006ed3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
h1 a:hover {
|
||||
color: #319cff;
|
||||
}
|
||||
|
||||
header,
|
||||
#summary {
|
||||
padding-left: 5%;
|
||||
padding-right: 5%;
|
||||
}
|
||||
|
||||
th:first-child,
|
||||
td:first-child {
|
||||
width: 5%;
|
||||
}
|
||||
|
||||
th:last-child,
|
||||
td:last-child {
|
||||
width: 5%;
|
||||
}
|
||||
|
||||
header {
|
||||
padding-top: 25px;
|
||||
padding-bottom: 10px;
|
||||
background-color: #eef;
|
||||
font-family: Georgia, serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 34px;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding-left: 5%;
|
||||
font-size: 18px;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 12px;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
color: #005;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
h1 a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
h1 a:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.meta {
|
||||
font-size: 12px;
|
||||
font-family: Trebuchet, sans-serif;
|
||||
border-bottom: 1px solid #9C9C9C;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
#filter {
|
||||
padding: 4px;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
tr {
|
||||
border-bottom: 1px dashed #dadada;
|
||||
}
|
||||
|
||||
tbody tr:hover {
|
||||
background-color: #ffffec;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
text-align: left;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
th {
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
font-size: 16px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
th a {
|
||||
color: black;
|
||||
}
|
||||
|
||||
th svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
td {
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
td:nth-child(2) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td:nth-child(3),
|
||||
th:nth-child(3) {
|
||||
#padding: 0 20px 0 20px;
|
||||
width: 0px;
|
||||
}
|
||||
|
||||
th:nth-child(4),
|
||||
td:nth-child(4) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
td:nth-child(2) svg {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
td .name,
|
||||
td .goup {
|
||||
margin-left: 1.75em;
|
||||
word-break: break-all;
|
||||
overflow-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.icon.sort {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
position: relative;
|
||||
top: .2em;
|
||||
}
|
||||
|
||||
.icon.sort .top {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.icon.sort .bottom {
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 40px 20px;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.hideable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
td:nth-child(2) {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
th:nth-child(3),
|
||||
td:nth-child(3) {
|
||||
padding-right: 5%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#filter {
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #101010;
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #151515;
|
||||
}
|
||||
|
||||
tbody tr:hover {
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
header a,
|
||||
th a {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #5796d1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
h1 a:hover {
|
||||
color: #62b2fd;
|
||||
}
|
||||
|
||||
tr {
|
||||
border-bottom: 1px dashed rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
#up-arrow,
|
||||
#down-arrow {
|
||||
fill: #dddddd;
|
||||
}
|
||||
|
||||
#filter {
|
||||
background-color: #151515;
|
||||
color: #ffffff;
|
||||
border: 1px solid #212121;
|
||||
}
|
||||
|
||||
.meta {
|
||||
border-bottom: 1px solid #212121
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload='initFilter()'>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="0" width="0" style="position: absolute;">
|
||||
<defs>
|
||||
<!-- Folder -->
|
||||
<g id="folder" fill-rule="nonzero" fill="none">
|
||||
<path d="M285.22 37.55h-142.6L110.9 0H31.7C14.25 0 0 16.9 0 37.55v75.1h316.92V75.1c0-20.65-14.26-37.55-31.7-37.55z" fill="#FFA000"/>
|
||||
<path d="M285.22 36H31.7C14.25 36 0 50.28 0 67.74v158.7c0 17.47 14.26 31.75 31.7 31.75H285.2c17.44 0 31.7-14.3 31.7-31.75V67.75c0-17.47-14.26-31.75-31.7-31.75z" fill="#FFCA28"/>
|
||||
</g>
|
||||
<g id="folder" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="folder-group" fill-rule="nonzero">
|
||||
<g id="folder-shape">
|
||||
<path d="M285.224876,37.5486902 L142.612438,37.5486902 L110.920785,0 L31.6916529,0 C14.2612438,0 0,16.8969106 0,37.5486902 L0,112.646071 L316.916529,112.646071 L316.916529,75.0973805 C316.916529,54.4456008 302.655285,37.5486902 285.224876,37.5486902 Z" id="Shape" fill="#FFA000"></path>
|
||||
<path d="M285.224876,36 L31.6916529,36 C14.2612438,36 0,50.2838568 0,67.7419039 L0,226.451424 C0,243.909471 14.2612438,258.193328 31.6916529,258.193328 L285.224876,258.193328 C302.655285,258.193328 316.916529,243.909471 316.916529,226.451424 L316.916529,67.7419039 C316.916529,50.2838568 302.655285,36 285.224876,36 Z" id="Shape" fill="#FFCA28"></path>
|
||||
</g>
|
||||
<path d="M126.154134,250.559184 C126.850974,251.883673 127.300549,253.006122 127.772602,254.106122 C128.469442,255.206122 128.919016,256.104082 129.638335,257.002041 C130.559962,258.326531 131.728855,259 133.100057,259 C134.493737,259 135.415364,258.55102 136.112204,257.67551 C136.809044,257.002041 137.258619,255.902041 137.258619,254.577551 C137.258619,253.904082 137.258619,252.804082 137.033832,251.457143 C136.786566,249.908163 136.561779,249.032653 136.561779,248.583673 C136.089726,242.814286 135.864939,237.920408 135.864939,233.273469 C135.864939,225.057143 136.786566,217.514286 138.180246,210.846939 C139.798713,204.202041 141.889234,198.634694 144.429328,193.763265 C147.216689,188.869388 150.678411,184.873469 154.836973,181.326531 C158.995535,177.779592 163.626149,174.883673 168.481552,172.661224 C173.336954,170.438776 179.113983,168.665306 185.587852,167.340816 C192.061722,166.218367 198.760378,165.342857 205.481514,164.669388 C212.18017,164.220408 219.598146,163.995918 228.162535,163.995918 L246.055591,163.995918 L246.055591,195.514286 C246.055591,197.736735 246.752431,199.510204 248.370899,201.059184 C250.214153,202.608163 252.079886,203.506122 254.372715,203.506122 C256.463236,203.506122 258.531277,202.608163 260.172223,201.059184 L326.102289,137.797959 C327.720757,136.24898 328.642384,134.47551 328.642384,132.253061 C328.642384,130.030612 327.720757,128.257143 326.102289,126.708163 L260.172223,63.4469388 C258.553756,61.8979592 256.463236,61 254.395194,61 C252.079886,61 250.236632,61.8979592 248.393377,63.4469388 C246.77491,64.9959184 246.07807,66.7693878 246.07807,68.9918367 L246.07807,100.510204 L228.162535,100.510204 C166.863084,100.510204 129.166282,117.167347 115.274437,150.459184 C110.666301,161.54898 108.350993,175.310204 108.350993,191.742857 C108.350993,205.279592 113.903236,223.912245 124.760454,247.438776 C125.00772,248.112245 125.457294,249.010204 126.154134,250.559184 Z" id="Shape" fill="#FFFFFF" transform="translate(218.496689, 160.000000) scale(-1, 1) translate(-218.496689, -160.000000) "></path>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- File -->
|
||||
<g id="file" stroke="#000" stroke-width="25" fill="#FFF" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M13 24.12v274.76c0 6.16 5.87 11.12 13.17 11.12H239c7.3 0 13.17-4.96 13.17-11.12V136.15S132.6 13 128.37 13H26.17C18.87 13 13 17.96 13 24.12z"/>
|
||||
<path d="M129.37 13L129 113.9c0 10.58 7.26 19.1 16.27 19.1H249L129.37 13z"/>
|
||||
</g>
|
||||
<g id="file-shortcut" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="file-shortcut-group" transform="translate(13.000000, 13.000000)">
|
||||
<g id="file-shortcut-shape" stroke="#000000" stroke-width="25" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M0,11.1214886 L0,285.878477 C0,292.039924 5.87498876,296.999983 13.1728373,296.999983 L225.997983,296.999983 C233.295974,296.999983 239.17082,292.039942 239.17082,285.878477 L239.17082,123.145388 C239.17082,123.145388 119.58541,2.84217094e-14 115.369423,2.84217094e-14 L13.1728576,2.84217094e-14 C5.87500907,-1.71479982e-05 0,4.96022995 0,11.1214886 Z" id="rect1171"></path>
|
||||
<path d="M116.37005,0 L116,100.904964 C116,111.483663 123.258008,120 132.273377,120 L236,120 L116.37005,0 L116.37005,0 Z" id="rect1794"></path>
|
||||
</g>
|
||||
<path d="M47.803141,294.093878 C48.4999811,295.177551 48.9495553,296.095918 49.4216083,296.995918 C50.1184484,297.895918 50.5680227,298.630612 51.2873415,299.365306 C52.2089688,300.44898 53.3778619,301 54.7490634,301 C56.1427436,301 57.0643709,300.632653 57.761211,299.916327 C58.4580511,299.365306 58.9076254,298.465306 58.9076254,297.381633 C58.9076254,296.830612 58.9076254,295.930612 58.6828382,294.828571 C58.4355724,293.561224 58.2107852,292.844898 58.2107852,292.477551 C57.7387323,287.757143 57.5139451,283.753061 57.5139451,279.95102 C57.5139451,273.228571 58.4355724,267.057143 59.8292526,261.602041 C61.44772,256.165306 63.5382403,251.610204 66.0783349,247.62449 C68.8656954,243.620408 72.3274172,240.35102 76.4859792,237.44898 C80.6445412,234.546939 85.2751561,232.177551 90.1305582,230.359184 C94.9859603,228.540816 100.76299,227.089796 107.236859,226.006122 C113.710728,225.087755 120.409385,224.371429 127.13052,223.820408 C133.829177,223.453061 141.247152,223.269388 149.811542,223.269388 L167.704598,223.269388 L167.704598,249.057143 C167.704598,250.87551 168.401438,252.326531 170.019905,253.593878 C171.86316,254.861224 173.728893,255.595918 176.021722,255.595918 C178.112242,255.595918 180.180284,254.861224 181.82123,253.593878 L247.751296,201.834694 C249.369763,200.567347 250.291391,199.116327 250.291391,197.297959 C250.291391,195.479592 249.369763,194.028571 247.751296,192.761224 L181.82123,141.002041 C180.202763,139.734694 178.112242,139 176.044201,139 C173.728893,139 171.885639,139.734694 170.042384,141.002041 C168.423917,142.269388 167.727077,143.720408 167.727077,145.538776 L167.727077,171.326531 L149.811542,171.326531 C88.5120908,171.326531 50.8152886,184.955102 36.9234437,212.193878 C32.3153075,221.267347 30,232.526531 30,245.971429 C30,257.046939 35.5522422,272.291837 46.4094607,291.540816 C46.6567266,292.091837 47.1063009,292.826531 47.803141,294.093878 Z" id="Shape-Copy" fill="#000000" fill-rule="nonzero" transform="translate(140.145695, 220.000000) scale(-1, 1) translate(-140.145695, -220.000000) "></path>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Up arrow -->
|
||||
<g id="up-arrow" transform="translate(-279.22 -208.12)">
|
||||
<path transform="matrix(.22413 0 0 .12089 335.67 164.35)" stroke-width="0" d="m-194.17 412.01h-28.827-28.827l14.414-24.965 14.414-24.965 14.414 24.965z"/>
|
||||
</g>
|
||||
|
||||
<!-- Down arrow -->
|
||||
<g id="down-arrow" transform="translate(-279.22 -208.12)">
|
||||
<path transform="matrix(.22413 0 0 -.12089 335.67 257.93)" stroke-width="0" d="m-194.17 412.01h-28.827-28.827l14.414-24.965 14.414-24.965 14.414 24.965z"/>
|
||||
</g>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
<header>
|
||||
<h1>
|
||||
<a href="https://github.com/mcguirepr89/BirdNET-Lite">🕊 BirdNET-Pi</a>
|
||||
</h1>
|
||||
</header>
|
||||
<hr>
|
||||
<h2>
|
||||
<a href="/overview.php">
|
||||
<span class="name">🐦 Overview</span>
|
||||
</a>
|
||||
</h2>
|
||||
<hr style="border-top: dotted 2px #ccc;">
|
||||
<h2>
|
||||
<a href="/viewday.php">
|
||||
<span class="name">🐦 Today's Top 10</span>
|
||||
</a>
|
||||
</h2>
|
||||
<hr style="border-top: dotted 2px #ccc;">
|
||||
<h2>
|
||||
<a href="/viewdb.php">
|
||||
<span class="name">🐦 View the Database</span>
|
||||
</a>
|
||||
</h2>
|
||||
<hr style="border-top: dotted 2px #ccc;">
|
||||
<h2>
|
||||
<a href="./stream">
|
||||
<span class="name">🔊 Live Audio Stream</span>
|
||||
</a>
|
||||
</h2>
|
||||
<hr style="border-top: dotted 2px #ccc;">
|
||||
<main>
|
||||
<div class="listing">
|
||||
<table aria-describedby="summary">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>
|
||||
<a href="?sort=name&order=asc"><p style="color:#555">Extractions</p></a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="file">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="./By_Common_Name/">
|
||||
<svg width="1.5em" height="1em" version="1.1" viewBox="0 0 317 259"><use xlink:href="#folder"></use></svg>
|
||||
<span class="name">By Common Name</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="file">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="./By_Date/">
|
||||
<svg width="1.5em" height="1em" version="1.1" viewBox="0 0 317 259"><use xlink:href="#folder"></use></svg>
|
||||
<span class="name">By Date</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="file">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="./By_Scientific_Name/">
|
||||
<svg width="1.5em" height="1em" version="1.1" viewBox="0 0 317 259"><use xlink:href="#folder"></use></svg>
|
||||
<span class="name">By Scientific Name</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="file">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="./Processed/">
|
||||
<svg width="1.5em" height="1em" version="1.1" viewBox="0 0 317 259"><use xlink:href="#folder"></use></svg>
|
||||
<span class="name">Processed</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>
|
||||
<a href="?sort=name&order=asc"><p style="color:#555">Tools</p></a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tr class="file">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="./scripts/">
|
||||
<svg width="1.5em" height="1em" version="1.1" viewBox="0 0 317 259"><use xlink:href="#folder"></use></svg>
|
||||
<span class="name">🗎 Scripts</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="file">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="http://birdnetpi.local:8080">
|
||||
<svg width="1.5em" height="1em" version="1.1" viewBox="0 0 317 259"><use xlink:href="#folder"></use></svg>
|
||||
<span class="name">⚙ Analysis Log</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="file">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="http://birdnetpi.local:8888">
|
||||
<svg width="1.5em" height="1em" version="1.1" viewBox="0 0 317 259"><use xlink:href="#folder"></use></svg>
|
||||
<span class="name">⚝ Extraction Log</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="./phpsysinfo">
|
||||
<span class="name">System Information</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="file">
|
||||
<td></td>
|
||||
<td>
|
||||
<form action="/spectrogram.php">
|
||||
<input type="submit" value="Spectrogram View">
|
||||
</form>
|
||||
|
||||
</td>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
Help:<a rel="noopener noreferrer" href="https://github.com/mcguirepr89/BirdNET-Pi/wiki/">🕊 BirdNET-Pi Wiki</a>
|
||||
</footer>
|
||||
<script>
|
||||
var filterEl = document.getElementById('filter');
|
||||
filterEl.focus();
|
||||
|
||||
function initFilter() {
|
||||
if (!filterEl.value) {
|
||||
var filterParam = new URL(window.location.href).searchParams.get('filter');
|
||||
if (filterParam) {
|
||||
filterEl.value = filterParam;
|
||||
}
|
||||
}
|
||||
filter();
|
||||
}
|
||||
|
||||
function filter() {
|
||||
var q = filterEl.value.trim().toLowerCase();
|
||||
var elems = document.querySelectorAll('tr.file');
|
||||
elems.forEach(function(el) {
|
||||
if (!q) {
|
||||
el.style.display = '';
|
||||
return;
|
||||
}
|
||||
var nameEl = el.querySelector('.name');
|
||||
var nameVal = nameEl.textContent.trim().toLowerCase();
|
||||
if (nameVal.indexOf(q) !== -1) {
|
||||
el.style.display = '';
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function localizeDatetime(e, index, ar) {
|
||||
if (e.textContent === undefined) {
|
||||
return;
|
||||
}
|
||||
var d = new Date(e.getAttribute('datetime'));
|
||||
if (isNaN(d)) {
|
||||
d = new Date(e.textContent);
|
||||
if (isNaN(d)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
e.textContent = d.toLocaleString([], {day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit"});
|
||||
}
|
||||
var timeList = Array.prototype.slice.call(document.getElementsByTagName("time"));
|
||||
timeList.forEach(localizeDatetime);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+463
-70
@@ -1,96 +1,489 @@
|
||||
/* style sheet */
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
/* Create two equal columns that floats next to each other */
|
||||
.column2 {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 75%;
|
||||
padding: 5px;
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Create two equal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
width: 50%;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: rgb(219, 255, 235);
|
||||
margin: 0 auto;
|
||||
font-size: large;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: black;
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-left: -150px;
|
||||
text-align: center;
|
||||
color: black;
|
||||
font-size: large;
|
||||
a:hover {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
color: black;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
iframe {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
height: 93%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: transparent;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px;
|
||||
vertical-align: top;
|
||||
background-color: rgb(219, 255, 235);
|
||||
font-weight: lighter;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
border: 2px solid black;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: rgb(219, 255, 235);
|
||||
font-weight: bold;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
h2 {
|
||||
margin-left: 0;
|
||||
text-align: center;
|
||||
color: black;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.column {
|
||||
width: 100%;
|
||||
}
|
||||
/* Create two equal columns that floats next to each other */
|
||||
.column2 {
|
||||
float: center;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
|
||||
audio, video{
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
font-weight: bold;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.centered {
|
||||
text-align: center;
|
||||
display: block;
|
||||
width: auto;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.banner {
|
||||
height: 7%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.banner h1 {
|
||||
padding: .5em;
|
||||
letter-spacing: 5px;
|
||||
}
|
||||
|
||||
.banner audio,.banner form {
|
||||
float: right;
|
||||
width: 120px;
|
||||
margin-left: -120px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.banner button {
|
||||
padding-top: 8px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.banner a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
.logo img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.topnav {
|
||||
background-color: rgb(159, 226, 155);
|
||||
display: flex;
|
||||
flex: 65%;
|
||||
width: 65%;
|
||||
justify-content: space-between;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.topnav form {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.topnav button {
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.topnav button:hover {
|
||||
background-color: rgb(219, 295, 235);
|
||||
color: black;
|
||||
}
|
||||
|
||||
.topnav button.active {
|
||||
background-color: #04AA6D;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.topnav .icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.play table {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.stats table,.viewdb table {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.overview th {
|
||||
background-color: rgb(219, 255, 235);
|
||||
border: 2px solid black;
|
||||
text-align: center;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.overview td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.overview div img {
|
||||
max-height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.overview-stats {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.left-column {
|
||||
flex: 10%;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.right-column {
|
||||
flex: 90%;
|
||||
margin-right: 10%;
|
||||
}
|
||||
|
||||
.stats td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.stats table {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.stats button:hover {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.overview button, .center button{
|
||||
font-weight: bold;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.history table,.history img {
|
||||
width: auto;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.views .centered button {
|
||||
border: 2px solid black;
|
||||
background-color: rgb(219, 255, 235);
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.views .centered button:hover {
|
||||
background-color: rgb(159, 226, 155);
|
||||
color: black;
|
||||
}
|
||||
|
||||
.settings {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.settings h3 {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.settings button {
|
||||
border: 2px solid black;
|
||||
background-color: rgb(219, 255, 235);
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.settings button:hover {
|
||||
background-color: rgb(159, 226, 155);
|
||||
color: black;
|
||||
}
|
||||
|
||||
.customlabels,.customlabels2 {
|
||||
float:left;
|
||||
}
|
||||
|
||||
.customlabels table {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.customlabels td,.customlabels2 td {
|
||||
border:none;
|
||||
background-color: transparent;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.customlabels button,.customlabels2 button {
|
||||
padding: 12px;
|
||||
background-color: rgb(219, 255, 235);
|
||||
border: 2px solid black;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.column1, .column3 {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.smaller {
|
||||
width: 100%;
|
||||
display: none;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.column2 {
|
||||
text-align: center;
|
||||
width: 10%;
|
||||
height: 80%;
|
||||
}
|
||||
|
||||
.column4 {
|
||||
text-align: justify;
|
||||
width: 10%;
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.column1 form,.column3 form {
|
||||
width: 80%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.column1 select,.column3 select {
|
||||
height: 80%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.spectrogram {
|
||||
width:50%
|
||||
}
|
||||
|
||||
.full {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.logbutton, .navbuttons {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.systemcontrols form,.servicecontrols form {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.systemcontrols button,.servicecontrols button {
|
||||
border: 2px solid black;
|
||||
background-color: rgb(219, 255, 235);
|
||||
padding: 12px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.servicecontrols button {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
#body::-webkit-scrollbar {
|
||||
# display:none
|
||||
#}
|
||||
|
||||
@media screen and (max-width: 1290px) {
|
||||
.column1,.column2,.column3,.column4 {
|
||||
height: 90%
|
||||
}
|
||||
.left-column {
|
||||
display: none;
|
||||
}
|
||||
.right-column {
|
||||
flex: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
.overview {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.overview .right-column .chart img {
|
||||
margin-left: 5%;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1000px) {
|
||||
.customlabels form,.customlabels2 form {
|
||||
width: 95%;
|
||||
}
|
||||
.column1, .column3 {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
}
|
||||
.column1 select,.column3 select {
|
||||
height: 70%;
|
||||
}
|
||||
.column2,.column4 {
|
||||
display: none;
|
||||
}
|
||||
.smaller{
|
||||
display: block;
|
||||
}
|
||||
.systemcontrols button,.servicecontrols button {
|
||||
width: 60%;
|
||||
padding: 12px;
|
||||
background-color: rgb(219, 255, 235);
|
||||
}
|
||||
.topnav {
|
||||
flex: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.topnav button {display: none;}
|
||||
.topnav button.icon {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.banner {
|
||||
height: auto;
|
||||
}
|
||||
.banner img {
|
||||
display: none;
|
||||
}
|
||||
.logo img {
|
||||
display: block;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.version {
|
||||
display: none;
|
||||
}
|
||||
.topnav.responsive {position: relative;}
|
||||
.topnav.responsive button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.column1, .column3 {
|
||||
width: 100%;
|
||||
}
|
||||
.systemcontrols button,.servicecontrols button {
|
||||
width: 80%;
|
||||
padding: 12px;
|
||||
background-color: rgb(219, 255, 235);
|
||||
}
|
||||
.stats img {
|
||||
width: 100%;
|
||||
margin-left:auto;
|
||||
margin-rigth:auto;
|
||||
}
|
||||
.viewdb table,.overview img {
|
||||
width: 100%
|
||||
}
|
||||
.banner {
|
||||
height: auto;
|
||||
margin-left: 60px;
|
||||
}
|
||||
.banner img {
|
||||
display: none;
|
||||
}
|
||||
.stream {
|
||||
float: right;
|
||||
display: block;
|
||||
width: 60px;
|
||||
}
|
||||
.logo img {
|
||||
display: block;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.play table,.overview table,.stats table {
|
||||
width: 100%;
|
||||
}
|
||||
.topnav {
|
||||
flex: 100%;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
.topnav button {
|
||||
font-size: large;
|
||||
width: 100%
|
||||
}
|
||||
.topnav button {display: none;}
|
||||
.topnav button.icon {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.topnav.responsive {position: relative;}
|
||||
.topnav.responsive button {
|
||||
display: block;
|
||||
}
|
||||
.left-column {
|
||||
display: none;
|
||||
}
|
||||
.version {display:none;}
|
||||
.left {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
body::-webkit-scrollbar {
|
||||
display:none
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>BirdNET-Pi</title>
|
||||
<style type="text/css">
|
||||
a {
|
||||
font-weight:bold;
|
||||
text-decoration:none;
|
||||
color:black;
|
||||
}
|
||||
body {
|
||||
text-align:center;
|
||||
font-family:verdana,arial,sans-serif;
|
||||
font-size:medium;
|
||||
margin:10px;
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
#content {
|
||||
position: relative;
|
||||
}
|
||||
#content img {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
padding-top: 5px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a href="https://github.com/mcguirepr89/BirdNET-Pi" target="_content">
|
||||
<img alt="BirdNET-Pi" src="images/bird.png" style="position:absolute;left:32.5px;top:15px;">
|
||||
</a>
|
||||
<h1 style="padding-left:150px;margin:0;">BirdNET-Pi</h1>
|
||||
<img style="padding-left: 150px;margin:0;" src="images/version.svg"/>
|
||||
<p style="margin:0;padding-left:150px;padding-top:5px">
|
||||
<a href="/overview.php" target="content">Overview</a> |
|
||||
<a href="/viewdb.php" target="content">Database</a> |
|
||||
<a href="/stats.php" target="content">Species Stats</a> |
|
||||
<a href="/history.php" target="content">History</a> |
|
||||
<a href="/spectrogram.php" target="content">Spectrogram</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>BirdNET-Pi</title>
|
||||
<style type="text/css">
|
||||
a {
|
||||
font-weight:bold;
|
||||
text-decoration:none;
|
||||
color:black;
|
||||
}
|
||||
body {
|
||||
text-align:center;
|
||||
font-family:verdana,arial,sans-serif;
|
||||
font-size:medium;
|
||||
margin:10px;
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
#content {
|
||||
position: relative;
|
||||
}
|
||||
#content img {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
padding-top: 5px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a href="https://github.com/mcguirepr89/BirdNET-Pi" target="_content">
|
||||
<img alt="BirdNET-Pi" src="images/bird.png" style="position:absolute;left:32.5px;top:15px;">
|
||||
</a>
|
||||
<h1 style="padding-left:150px">BirdNET-Pi<img style="padding-left: 5px" src="images/version.svg" class="ribbon"/></h1>
|
||||
</div>
|
||||
<p style="padding-left:150px;">
|
||||
<a href="/overview.php" target="content">Übersicht</a> |
|
||||
<a href="/viewdb.php" target="content">Datenbankansicht</a> |
|
||||
<a href="/viewday.php" target="content">Tagesansicht</a> |
|
||||
<a href="/spectrogram.php" target="content">Spektrogrammansicht</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,189 @@
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<div class="topnav" id="myTopnav">
|
||||
<form action="" method="POST" id="views">
|
||||
<button type="submit" name="view" value="Overview" form="views">Overview</button>
|
||||
</form>
|
||||
<form action="" method="POST" id="views">
|
||||
<button type="submit" name="view" value="Today's Detections" form="views">Today's Detections</button>
|
||||
</form>
|
||||
<form action="" method="POST" id="views">
|
||||
<button type="submit" name="view" value="Best Recordings" form="views">Best Recordings</button>
|
||||
</form>
|
||||
<form action="" method="POST" id="views">
|
||||
<button type="submit" name="view" value="Species Stats" form="views">Species Stats</button>
|
||||
</form>
|
||||
<form action="" method="POST" id="views">
|
||||
<button type="submit" name="view" value="Daily Charts" form="views">Daily Charts</button>
|
||||
</form>
|
||||
<form action="" method="POST" id="views">
|
||||
<button type="submit" name="view" value="Recordings" form="views">Recordings</button>
|
||||
</form>
|
||||
<form action="index.php" method="GET" id="spectrogram">
|
||||
<input type="hidden" name="logo" value="smaller">
|
||||
<button style="float:none;" type="submit" name="spectrogram" value="view" id="spectrogram" form="spectrogram">Spectrogram</button>
|
||||
</form>
|
||||
<form action="index.php" method="GET" id="Log">
|
||||
<input type="hidden" name="logo" value="smaller">
|
||||
<button type="submit" name="log" value="log" form="Log">View Log</button>
|
||||
</form>
|
||||
<form action="" method="POST" id="views">
|
||||
<button type="submit" name="view" value="Tools" form="views">Tools</button>
|
||||
</form>
|
||||
<button href="javascript:void(0);" class="icon" onclick="myFunction()"><img src="images/menu.png"></button>
|
||||
</div>
|
||||
<div class="views">
|
||||
<?php
|
||||
if(isset($_POST['view'])){
|
||||
if($_POST['view'] == "System Info"){header('location:phpsysinfo/index.php');}
|
||||
if($_POST['view'] == "System Controls"){include('scripts/system_controls.php');}
|
||||
if($_POST['view'] == "Services"){include('scripts/service_controls.php');}
|
||||
if($_POST['view'] == "Spectrogram"){include('spectrogram.php');}
|
||||
if($_POST['view'] == "Overview"){include('overview.php');}
|
||||
if($_POST['view'] == "Today's Detections"){include('todays_detections.php');}
|
||||
if($_POST['view'] == "Best Recordings"){echo "<br><br>";include('stats.php');}
|
||||
if($_POST['view'] == "Species Stats"){header('location:/stats');}
|
||||
if($_POST['view'] == "Daily Charts"){include('history.php');}
|
||||
if($_POST['view'] == "Tools"){
|
||||
if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/thisrun.txt');
|
||||
} elseif (file_exists('/home/pi/BirdNET-Pi/firstrun.ini')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/firstrun.ini');
|
||||
}
|
||||
$caddypwd = $config['CADDY_PWD'];
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot edit the settings for this installation';
|
||||
exit;
|
||||
} else {
|
||||
$submittedpwd = $_SERVER['PHP_AUTH_PW'];
|
||||
$submitteduser = $_SERVER['PHP_AUTH_USER'];
|
||||
if($submittedpwd == $caddypwd && $submitteduser == 'birdnet'){
|
||||
$url = $_SERVER['SERVER_NAME']."/scripts/adminer.php";
|
||||
echo "<div class=\"centered\">
|
||||
<form action=\"\" method=\"POST\" id=\"views\">
|
||||
<button type=\"submit\" name=\"view\" value=\"Settings\" form=\"views\">Settings</button>
|
||||
<button type=\"submit\" name=\"view\" value=\"System Info\" form=\"views\">System Info</button>
|
||||
<button type=\"submit\" name=\"view\" value=\"System Controls\" form=\"views\">System Controls</button>
|
||||
<button type=\"submit\" name=\"view\" value=\"Services\" form=\"views\">Services</button>
|
||||
<button type=\"submit\" name=\"view\" value=\"File\" form=\"views\">File Manager</button>
|
||||
<a href=\"scripts/adminer.php\" target=\"_top\"><button type=\"submit\" form=\"\">Database Maintenanace</button></a>
|
||||
<button type=\"submit\" name=\"view\" value=\"Webterm\" form=\"views\">Web Terminal</button>
|
||||
<button type=\"submit\" name=\"view\" value=\"Included\" form=\"views\">Custom Species List</button>
|
||||
<button type=\"submit\" name=\"view\" value=\"Excluded\" form=\"views\">Excluded Species List</button>
|
||||
</form>
|
||||
</div>";
|
||||
} else {
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot edit the settings for this installation';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($_POST['view'] == "Recordings"){include('play.php');}
|
||||
if($_POST['view'] == "Settings"){include('scripts/config.php');}
|
||||
if($_POST['view'] == "Advanced"){include('scripts/advanced.php');}
|
||||
if($_POST['view'] == "Included"){
|
||||
if(isset($_POST['species']) && isset($_POST['add'])){
|
||||
$file = '/home/pi/BirdNET-Pi/include_species_list.txt';
|
||||
$str = file_get_contents("$file");
|
||||
$str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
|
||||
file_put_contents("$file", "$str");
|
||||
if(isset($_POST['species'])){
|
||||
foreach ($_POST['species'] as $selectedOption)
|
||||
file_put_contents("/home/pi/BirdNET-Pi/include_species_list.txt", $selectedOption."\n", FILE_APPEND);
|
||||
}
|
||||
} elseif(isset($_POST['species']) && isset($_POST['del'])){
|
||||
$file = '/home/pi/BirdNET-Pi/include_species_list.txt';
|
||||
$str = file_get_contents("$file");
|
||||
$str = preg_replace('/^\h*\v+/m', '', $str);
|
||||
file_put_contents("$file", "$str");
|
||||
foreach($_POST['species'] as $selectedOption) {
|
||||
$content = file_get_contents("/home/pi/BirdNET-Pi/include_species_list.txt");
|
||||
$newcontent = str_replace($selectedOption, "", "$content");
|
||||
file_put_contents("/home/pi/BirdNET-Pi/include_species_list.txt", "$newcontent");
|
||||
}
|
||||
$file = '/home/pi/BirdNET-Pi/include_species_list.txt';
|
||||
$str = file_get_contents("$file");
|
||||
$str = preg_replace('/^\h*\v+/m', '', $str);
|
||||
file_put_contents("$file", "$str");
|
||||
}
|
||||
include('scripts/include_list.php');
|
||||
}
|
||||
if($_POST['view'] == "Excluded"){
|
||||
if(isset($_POST['species']) && isset($_POST['add'])){
|
||||
$file = '/home/pi/BirdNET-Pi/exclude_species_list.txt';
|
||||
$str = file_get_contents("$file");
|
||||
$str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
|
||||
file_put_contents("$file", "$str");
|
||||
foreach ($_POST['species'] as $selectedOption)
|
||||
file_put_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt", $selectedOption."\n", FILE_APPEND);
|
||||
} elseif (isset($_POST['species']) && isset($_POST['del'])){
|
||||
$file = '/home/pi/BirdNET-Pi/exclude_species_list.txt';
|
||||
$str = file_get_contents("$file");
|
||||
$str = preg_replace('/^\h*\v+/m', '', $str);
|
||||
file_put_contents("$file", "$str");
|
||||
foreach($_POST['species'] as $selectedOption) {
|
||||
$content = file_get_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt");
|
||||
$newcontent = str_replace($selectedOption, "", "$content");
|
||||
file_put_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt", "$newcontent");
|
||||
}
|
||||
$file = '/home/pi/BirdNET-Pi/exclude_species_list.txt';
|
||||
$str = file_get_contents("$file");
|
||||
$str = preg_replace('/^\h*\v+/m', '', $str);
|
||||
file_put_contents("$file", "$str");
|
||||
}
|
||||
include('scripts/exclude_list.php');
|
||||
}
|
||||
if($_POST['view'] == "File"){
|
||||
header('Location: scripts/filemanager/filemanager.php');
|
||||
}
|
||||
if($_POST['view'] == "Webterm"){
|
||||
if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/thisrun.txt');
|
||||
} elseif (file_exists('/home/pi/BirdNET-Pi/firstrun.ini')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/firstrun.ini');
|
||||
}
|
||||
$caddypwd = $config['CADDY_PWD'];
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot access the web terminal';
|
||||
exit;
|
||||
} else {
|
||||
$submittedpwd = $_SERVER['PHP_AUTH_PW'];
|
||||
$submitteduser = $_SERVER['PHP_AUTH_USER'];
|
||||
if($submittedpwd == $caddypwd && $submitteduser == 'birdnet'){
|
||||
#ACCESS THE WEB TERMINAL
|
||||
header("Location: /terminal");
|
||||
} else {
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot access the web terminal';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif(isset($_POST['submit'])) {
|
||||
$command = $_POST['submit'];
|
||||
if(isset($command)){
|
||||
$results = shell_exec("$command 2>&1");
|
||||
echo "<pre>$results</pre>";
|
||||
}
|
||||
ob_end_flush();
|
||||
} else {include('overview.php');}
|
||||
?>
|
||||
<script>
|
||||
function myFunction() {
|
||||
var x = document.getElementById("myTopnav");
|
||||
if (x.className === "topnav") {
|
||||
x.className += " responsive";
|
||||
} else {
|
||||
x.className = "topnav";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
+9
-1
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# Simple new installer
|
||||
|
||||
HOME=/home/pi
|
||||
USER=pi
|
||||
branch=main
|
||||
@@ -8,5 +9,12 @@ if ! which git &> /dev/null;then
|
||||
sudo apt -y install git
|
||||
fi
|
||||
git clone -b ${branch} https://github.com/mcguirepr89/BirdNET-Pi.git ${HOME}/BirdNET-Pi &&
|
||||
cp ${HOME}/BirdNET-Pi/birdnet.conf-defaults ${HOME}/BirdNET-Pi/birdnet.conf &&
|
||||
|
||||
${HOME}/BirdNET-Pi/scripts/install_birdnet.sh
|
||||
if [ ${PIPESTATUS[0]} -eq 0 ];then
|
||||
echo "Installation completed successfully"
|
||||
sudo reboot
|
||||
else
|
||||
echo "The installation exited unsuccessfully."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+6
-1
@@ -1,8 +1,13 @@
|
||||
pip
|
||||
wheel
|
||||
setuptools
|
||||
tflite_runtime-2.6.0-cp39-none-linux_aarch64.whl
|
||||
colorama==0.4.4
|
||||
librosa
|
||||
mysql-connector-python
|
||||
pytz
|
||||
tzlocal
|
||||
pandas
|
||||
seaborn
|
||||
babel
|
||||
streamlit
|
||||
plotly
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
$file='/home/pi/BirdNET-Pi/exclude_species_list.txt';
|
||||
$str=file_get_contents("$file");
|
||||
$str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
|
||||
file_put_contents("$file", "$str");
|
||||
|
||||
if (isset($_POST['species']))
|
||||
foreach ($_POST['species'] as $selectedOption)
|
||||
file_put_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt", $selectedOption."\n", FILE_APPEND);
|
||||
header("Location: {$_SERVER['HTTP_REFERER']}");
|
||||
exit;
|
||||
?>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
$file='/home/pi/BirdNET-Pi/include_species_list.txt';
|
||||
$str=file_get_contents("$file");
|
||||
$str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
|
||||
file_put_contents("$file", "$str");
|
||||
|
||||
if (isset($_POST['species']))
|
||||
foreach ($_POST['species'] as $selectedOption)
|
||||
file_put_contents("/home/pi/BirdNET-Pi/include_species_list.txt", $selectedOption."\n", FILE_APPEND);
|
||||
header("Location: {$_SERVER['HTTP_REFERER']}");
|
||||
exit;
|
||||
?>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+659
-1546
File diff suppressed because one or more lines are too long
+37
-166
@@ -7,6 +7,23 @@ if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
} elseif (file_exists('/home/pi/BirdNET-Pi/firstrun.ini')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/firstrun.ini');
|
||||
}
|
||||
$caddypwd = $config['CADDY_PWD'];
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot edit the settings for this installation';
|
||||
exit;
|
||||
} else {
|
||||
$submittedpwd = $_SERVER['PHP_AUTH_PW'];
|
||||
$submitteduser = $_SERVER['PHP_AUTH_USER'];
|
||||
if($submittedpwd !== $caddypwd || $submitteduser !== 'birdnet'){
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot edit the settings for this installation';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(isset($_POST['submit'])) {
|
||||
$contents = file_get_contents("/home/pi/BirdNET-Pi/birdnet.conf");
|
||||
@@ -25,15 +42,6 @@ if(isset($_POST['submit'])) {
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($_POST["db_pwd"])) {
|
||||
$db_pwd = $_POST["db_pwd"];
|
||||
if(strcmp($db_pwd,$config['DB_PWD']) !== 0) {
|
||||
shell_exec('sudo /usr/local/bin/update_db_pwd_bullseye.sh');
|
||||
$contents = preg_replace("/DB_PWD=.*/", "DB_PWD=$db_pwd", $contents);
|
||||
$contents2 = preg_replace("/DB_PWD=.*/", "DB_PWD=$db_pwd", $contents2);
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($_POST["ice_pwd"])) {
|
||||
$ice_pwd = $_POST["ice_pwd"];
|
||||
if(strcmp($ice_pwd,$config['ICE_PWD']) !== 0) {
|
||||
@@ -42,30 +50,6 @@ if(isset($_POST['submit'])) {
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($_POST["webterminal_url"])) {
|
||||
$webterminal_url = $_POST["webterminal_url"];
|
||||
if(strcmp($webterminal_url,$config['WEBTERMINAL_URL']) !== 0) {
|
||||
$contents = preg_replace("/WEBTERMINAL_URL=.*/", "WEBTERMINAL_URL=$webterminal_url", $contents);
|
||||
$contents2 = preg_replace("/WEBTERMINAL_URL=.*/", "WEBTERMINAL_URL=$webterminal_url", $contents2);
|
||||
$fh = fopen("/home/pi/BirdNET-Pi/birdnet.conf", "w");
|
||||
$fh2 = fopen("/home/pi/BirdNET-Pi/thisrun.txt", "w");
|
||||
fwrite($fh, $contents);
|
||||
fwrite($fh2, $contents2);
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($_POST["birdnetlog_url"])) {
|
||||
$birdnetlog_url = $_POST["birdnetlog_url"];
|
||||
if(strcmp($birdnetlog_url,$config['BIRDNETLOG_URL']) !== 0) {
|
||||
$contents = preg_replace("/BIRDNETLOG_URL=.*/", "BIRDNETLOG_URL=$birdnetlog_url", $contents);
|
||||
$contents2 = preg_replace("/BIRDNETLOG_URL=.*/", "BIRDNETLOG_URL=$birdnetlog_url", $contents2);
|
||||
$fh = fopen("/home/pi/BirdNET-Pi/birdnet.conf", "w");
|
||||
$fh2 = fopen("/home/pi/BirdNET-Pi/thisrun.txt", "w");
|
||||
fwrite($fh, $contents);
|
||||
fwrite($fh2, $contents2);
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($_POST["birdnetpi_url"])) {
|
||||
$birdnetpi_url = $_POST["birdnetpi_url"];
|
||||
if(strcmp($birdnetpi_url,$config['BIRDNETPI_URL']) !== 0) {
|
||||
@@ -155,104 +139,13 @@ if(isset($_POST['submit'])) {
|
||||
$fh2 = fopen("/home/pi/BirdNET-Pi/thisrun.txt", "w");
|
||||
fwrite($fh, $contents);
|
||||
fwrite($fh2, $contents2);
|
||||
@session_start();
|
||||
if(true){
|
||||
$_SESSION['success'] = 1;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* Create two unequal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
.first {
|
||||
width: calc(50% - 70px);
|
||||
}
|
||||
.second {
|
||||
width: calc(50% - 70px);
|
||||
}
|
||||
.
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
a {
|
||||
font-size:large;
|
||||
text-decoration: none;
|
||||
}
|
||||
.block {
|
||||
display: block;
|
||||
width:50%;
|
||||
border: none;
|
||||
padding: 10px 10px;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
form {
|
||||
text-align:left;
|
||||
margin-left:20px;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom:0px;
|
||||
}
|
||||
h3 {
|
||||
margin-left: -10px;
|
||||
text-align:left;
|
||||
}
|
||||
label {
|
||||
float:left;
|
||||
width: 40%;
|
||||
font-weight:bold;
|
||||
}
|
||||
input,select {
|
||||
width: 60%;
|
||||
text-align:center;
|
||||
font-size:large;
|
||||
}
|
||||
@media screen and (max-width: 1000px) {
|
||||
h2,h3 {
|
||||
text-align:center;
|
||||
}
|
||||
form {
|
||||
margin:0;
|
||||
}
|
||||
.column {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
input, label {
|
||||
width: 100%;
|
||||
{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<div class="settings">
|
||||
<?php
|
||||
if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
$newconfig = parse_ini_file('/home/pi/BirdNET-Pi/thisrun.txt');
|
||||
@@ -261,20 +154,17 @@ if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
}
|
||||
?>
|
||||
<h2>Advanced Settings</h2>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<div class="row">
|
||||
<div class="column first">
|
||||
<form action="advanced.php" method="POST">
|
||||
<form action="" method="POST">
|
||||
<h3>Defaults</h3>
|
||||
<label>Full Disk Behavior: </label>
|
||||
<label style="width:30%;" for="purge">
|
||||
<input style="width:15%;" name="full_disk" type="radio" id="purge" value="purge"
|
||||
<label for="purge">
|
||||
<input name="full_disk" type="radio" id="purge" value="purge"
|
||||
<?php
|
||||
if (strcmp($newconfig['FULL_DISK'], "purge") == 0) {
|
||||
echo "checked";
|
||||
}?>>Purge</label>
|
||||
<label style="width:30%;" for="keep">
|
||||
<input style="width:15%" name="full_disk" type="radio" id="keep" value="keep"
|
||||
<label for="keep">
|
||||
<input name="full_disk" type="radio" id="keep" value="keep"
|
||||
<?php
|
||||
if (strcmp($newconfig['FULL_DISK'], "keep") == 0) {
|
||||
echo "checked";
|
||||
@@ -288,7 +178,7 @@ if (strcmp($newconfig['FULL_DISK'], "purge") == 0) {
|
||||
<p>Set Channels to the number of channels supported by your sound card. 32 max.</p>
|
||||
<label for="recording_length">Recording Length: </label>
|
||||
<input name="recording_length" type="number" min="3" max="60" step="1" value="<?php print($newconfig['RECORDING_LENGTH']);?>" required/><br>
|
||||
<p>Set Recording Length in seconds between 6 and 60. Multiples of 3 are recommended, as BirdNET analyzes in 3-second chunks.</p>
|
||||
<p>Set Recording Length in seconds between 6 and 60. Multiples of 3 are recommended, as BirdNET analyzes in 3-second chunks.</p>
|
||||
<label for="extraction_length">Extraction Length: </label>
|
||||
<input name="extraction_length" type="number" min="3" max="<?php print($newconfig['RECORDING_LENGTH']);?>" value="<?php print($newconfig['EXTRACTION_LENGTH']);?>" /><br>
|
||||
<p>Set Extraction Length to something less than your Recording Length. Min=3 Max=Recording Length</p>
|
||||
@@ -302,28 +192,14 @@ foreach($formats as $format){
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<h3>Passwords</h3>
|
||||
<h3>BirdNET-Pi Password</h3>
|
||||
<label for="caddy_pwd">Webpage: </label>
|
||||
<input name="caddy_pwd" type="text" value="<?php print($newconfig['CADDY_PWD']);?>" /><br>
|
||||
<p>This password protects the Live Audio Stream, the Processed extractions, phpSysInfo, your Tools, and WebTerminal. When you update this value, the web server will reload, so wait about 30 seconds and then reload the page.</p>
|
||||
<label for="db_pwd">Database: </label>
|
||||
<input name="db_pwd" type="text" value="<?php print($newconfig['DB_PWD']);?>" required/><br>
|
||||
<p>This password protects the database. When you update this value, it will be updated automatically.</p>
|
||||
<label for="ice_pwd">Live Audio Stream: </label>
|
||||
<input name="ice_pwd" type="text" value="<?php print($newconfig['ICE_PWD']);?>" required/><br>
|
||||
</div>
|
||||
<div class="column second">
|
||||
<h3>Custom URLs</h3>
|
||||
<p>When you update any of the URL settings below, the web server will reload, so be sure to wait at least 30 seconds and then reload the page.</p>
|
||||
<h3>Custom URL</h3>
|
||||
<p>When you update the URL below, the web server will reload, so be sure to wait at least 30 seconds and then go to your new URL.</p>
|
||||
<label for="birdnetpi_url">BirdNET-Pi URL: </label>
|
||||
<input name="birdnetpi_url" type="url" value="<?php print($newconfig['BIRDNETPI_URL']);?>" /><br>
|
||||
<p>This URL is how the main page will be reached. If you want your installation to respond to an IP address, place that here, but be sure to indicate `http://`.<br>Example for IP:http://192.168.0.109<br>Example if you own your own domain:https://birdnetpi.pmcgui.xyz</p>
|
||||
<label for="birdnetlog_url">BirdNET-Lite Log URL: </label>
|
||||
<input name="birdnetlog_url" type="url" value="<?php print($newconfig['BIRDNETLOG_URL']);?>" /><br>
|
||||
<p>This URL is how the log will be reached. Only use this variable if you own your own domain.</p>
|
||||
<label for="webterminal_url">Web Terminal URL: </label>
|
||||
<input name="webterminal_url" type="url" value="<?php print($newconfig['WEBTERMINAL_URL']);?>" /><br>
|
||||
<p>This URL is how the Web browser terminal will be reached. Only use this variable if you own your own domain.</p>
|
||||
<h3>BirdNET-Lite Settings</h3>
|
||||
<label for="overlap">Overlap: </label>
|
||||
<input name="overlap" type="number" min="0.0" max="2.9" step="0.1" value="<?php print($newconfig['OVERLAP']);?>" required/><br>
|
||||
@@ -335,24 +211,19 @@ foreach($formats as $format){
|
||||
<input name="sensitivity" type="number" min="0.5" max="1.5" step="0.01" value="<?php print($newconfig['SENSITIVITY']);?>" required/><br>
|
||||
<p>Min=0.5, Max=1.5</p>
|
||||
<br><br>
|
||||
<button type="submit" name="submit" class="block"><?php
|
||||
|
||||
if(isset($_SESSION['success'])){
|
||||
<input type="hidden" name="view" value="Advanced">
|
||||
<button type="submit" name="submit" value="advanced">
|
||||
<?php
|
||||
if(isset($_POST['submit'])){
|
||||
echo "Success!";
|
||||
unset($_SESSION['success']);
|
||||
} else {
|
||||
echo "Update Settings";
|
||||
}
|
||||
?></button>
|
||||
?>
|
||||
</button>
|
||||
<br>
|
||||
</form>
|
||||
<form action="config.php" style="margin:0;">
|
||||
<button type="submit" class="block">Basic Settings</button>
|
||||
</form>
|
||||
<br>
|
||||
<form action="index.html" style="margin:0;">
|
||||
<button type="submit" class="block">Tools</button>
|
||||
</form>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<button type="submit" name="view" value="Settings">Basic Settings</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
Regular → Executable
+1
@@ -1,3 +1,4 @@
|
||||
#!/home/pi/BirdNET-Pi/birdnet/bin/python3
|
||||
import argparse
|
||||
import socket
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<html lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<head></head>
|
||||
<body style="background-color: rgb(119, 196, 135);font-size:large;">
|
||||
|
||||
A backup is being made that includes all of<br>
|
||||
your extractions and the BirdDB.txt<br>
|
||||
<br></br>
|
||||
The backup is in /home/pi/BirdNET-Pi
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,997 +0,0 @@
|
||||
#!/usr/bin/env -S sudo -E sh
|
||||
# Altered from raspi-config tool below
|
||||
# https://github.com/RPi-Distro/birdnet-pi-config
|
||||
#
|
||||
# See LICENSE file for copyright and license details
|
||||
# Copyright (c) 2012 Alex Bradbury <asb@asbradbury.org>
|
||||
set -x
|
||||
birdnetpi_dir=/home/pi/BirdNET-Pi
|
||||
birders_config=${birdnetpi_dir}/Birders_Guide_Installer_Configuration.txt
|
||||
branch=forms
|
||||
INTERACTIVE=True
|
||||
ASK_TO_REBOOT=0
|
||||
BLACKLIST=/etc/modprobe.d/raspi-blacklist.conf
|
||||
CONFIG=/boot/config.txt
|
||||
|
||||
USER=${SUDO_USER:-$(who -m | awk '{ print $1 }')}
|
||||
|
||||
is_pi () {
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
if [ "$ARCH" = "armhf" ] || [ "$ARCH" = "arm64" ] ; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
if is_pi ; then
|
||||
CMDLINE=/boot/cmdline.txt
|
||||
else
|
||||
CMDLINE=/proc/cmdline
|
||||
fi
|
||||
|
||||
is_pione() {
|
||||
if grep -q "^Revision\s*:\s*00[0-9a-fA-F][0-9a-fA-F]$" /proc/cpuinfo; then
|
||||
return 0
|
||||
elif grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]0[0-36][0-9a-fA-F]$" /proc/cpuinfo ; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
is_pitwo() {
|
||||
grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]04[0-9a-fA-F]$" /proc/cpuinfo
|
||||
return $?
|
||||
}
|
||||
|
||||
is_pizero() {
|
||||
grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]0[9cC][0-9a-fA-F]$" /proc/cpuinfo
|
||||
return $?
|
||||
}
|
||||
|
||||
is_pifour() {
|
||||
grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F]3[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]$" /proc/cpuinfo
|
||||
return $?
|
||||
}
|
||||
|
||||
get_pi_type() {
|
||||
if is_pione; then
|
||||
echo 1
|
||||
elif is_pitwo; then
|
||||
echo 2
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
is_live() {
|
||||
grep -q "boot=live" $CMDLINE
|
||||
return $?
|
||||
}
|
||||
|
||||
is_ssh() {
|
||||
if pstree -p | egrep --quiet --extended-regexp ".*sshd.*\($$\)"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
is_fkms() {
|
||||
if grep -s -q okay /proc/device-tree/soc/v3d@7ec00000/status \
|
||||
/proc/device-tree/soc/firmwarekms@7e600000/status \
|
||||
/proc/device-tree/v3dbus/v3d@7ec04000/status; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
is_pulseaudio() {
|
||||
PS=$(ps ax)
|
||||
echo "$PS" | grep -q pulseaudio
|
||||
return $?
|
||||
}
|
||||
|
||||
has_analog() {
|
||||
if [ $(get_leds) -eq -1 ] ; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
is_installed() {
|
||||
if [ "$(dpkg -l "$1" 2> /dev/null | tail -n 1 | cut -d ' ' -f 1)" != "ii" ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
deb_ver () {
|
||||
ver=`cat /etc/debian_version | cut -d . -f 1`
|
||||
echo $ver
|
||||
}
|
||||
|
||||
calc_wt_size() {
|
||||
# NOTE: it's tempting to redirect stderr to /dev/null, so supress error
|
||||
# output from tput. However in this case, tput detects neither stdout or
|
||||
# stderr is a tty and so only gives default 80, 24 values
|
||||
WT_HEIGHT=18
|
||||
WT_WIDTH=$(tput cols)
|
||||
|
||||
if [ -z "$WT_WIDTH" ] || [ "$WT_WIDTH" -lt 60 ]; then
|
||||
WT_WIDTH=80
|
||||
fi
|
||||
if [ "$WT_WIDTH" -gt 178 ]; then
|
||||
WT_WIDTH=120
|
||||
fi
|
||||
WT_MENU_HEIGHT=$(($WT_HEIGHT-7))
|
||||
}
|
||||
|
||||
do_change_pass() {
|
||||
whiptail --msgbox "You will now be asked to enter a new password for the $USER user" 20 60 1
|
||||
passwd $USER &&
|
||||
whiptail --msgbox "Password changed successfully" 20 60 1
|
||||
}
|
||||
|
||||
do_configure_keyboard() {
|
||||
printf "Reloading keymap. This may take a short while\n"
|
||||
if [ "$INTERACTIVE" = True ]; then
|
||||
dpkg-reconfigure keyboard-configuration
|
||||
else
|
||||
local KEYMAP="$1"
|
||||
sed -i /etc/default/keyboard -e "s/^XKBLAYOUT.*/XKBLAYOUT=\"$KEYMAP\"/"
|
||||
dpkg-reconfigure -f noninteractive keyboard-configuration
|
||||
fi
|
||||
invoke-rc.d keyboard-setup start
|
||||
setsid sh -c 'exec setupcon -k --force <> /dev/tty1 >&0 2>&1'
|
||||
udevadm trigger --subsystem-match=input --action=change
|
||||
return 0
|
||||
}
|
||||
|
||||
do_change_locale() {
|
||||
dpkg-reconfigure locales && \
|
||||
ASK_TO_REBOOT=2 && return 0
|
||||
}
|
||||
|
||||
do_change_timezone() {
|
||||
dpkg-reconfigure tzdata && \
|
||||
return 0
|
||||
}
|
||||
|
||||
get_wifi_country() {
|
||||
CODE=${1:-0}
|
||||
IFACE="$(list_wlan_interfaces | head -n 1)"
|
||||
if [ -z "$IFACE" ]; then
|
||||
whiptail --msgbox "No wireless interface found" 20 60
|
||||
return 1
|
||||
fi
|
||||
if ! wpa_cli -i "$IFACE" status > /dev/null 2>&1; then
|
||||
whiptail --msgbox "Could not communicate with wpa_supplicant" 20 60
|
||||
return 1
|
||||
fi
|
||||
wpa_cli -i "$IFACE" save_config > /dev/null 2>&1
|
||||
COUNTRY="$(wpa_cli -i "$IFACE" get country)"
|
||||
if [ "$COUNTRY" = "FAIL" ]; then
|
||||
return 1
|
||||
fi
|
||||
if [ $CODE = 0 ]; then
|
||||
echo "$COUNTRY"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
do_wifi_country() {
|
||||
IFACE="$(list_wlan_interfaces | head -n 1)"
|
||||
if [ -z "$IFACE" ]; then
|
||||
whiptail --msgbox "No wireless interface found" 20 60
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! wpa_cli -i "$IFACE" status > /dev/null 2>&1; then
|
||||
whiptail --msgbox "Could not communicate with wpa_supplicant" 20 60
|
||||
return 1
|
||||
fi
|
||||
|
||||
oIFS="$IFS"
|
||||
value=$(cat /usr/share/zoneinfo/iso3166.tab | tail -n +26 | tr '\t' '/' | tr '\n' '/')
|
||||
IFS="/"
|
||||
COUNTRY=$(whiptail --menu "Select the country in which the Pi is to be used" 20 60 10 ${value} 3>&1 1>&2 2>&3)
|
||||
if [ $? -eq 0 ];then
|
||||
wpa_cli -i "$IFACE" set country "$COUNTRY"
|
||||
wpa_cli -i "$IFACE" save_config > /dev/null 2>&1
|
||||
if iw reg set "$COUNTRY" 2> /dev/null; then
|
||||
ASK_TO_REBOOT=1
|
||||
fi
|
||||
if hash rfkill 2> /dev/null; then
|
||||
rfkill unblock wifi
|
||||
if is_pi ; then
|
||||
for filename in /var/lib/systemd/rfkill/*:wlan ; do
|
||||
echo 0 > $filename
|
||||
done
|
||||
fi
|
||||
fi
|
||||
whiptail --msgbox "Wireless LAN country set to $COUNTRY" 20 60 1
|
||||
fi
|
||||
IFS=$oIFS
|
||||
}
|
||||
|
||||
get_labels_lang() {
|
||||
oIFS="$IFS"
|
||||
value=$(cat ${birdnetpi_dir}/model/labels_lang.txt | tr ',' ' ' | tr '\n' ' ')
|
||||
IFS=" "
|
||||
get_lang=$(whiptail --menu "Select the file that corresponds to your language" 20 60 10 ${value} 3>&1 1>&2 2>&3)
|
||||
labels_lang=$(awk -F, "/$get_lang/{print \$2}" ${birdnetpi_dir}/model/labels_lang.txt)
|
||||
if [ $? -eq 0 ];then
|
||||
whiptail --msgbox "Your installation will now use $labels_lang" 20 60 1
|
||||
mv ${birdnetpi_dir}/model/labels.txt ${birdnetpi_dir}/model/labels.txt.old
|
||||
unzip ${birdnetpi_dir}/model/labels_l18n.zip ${labels_lang} -d ${birdnetpi_dir}/model
|
||||
mv ${birdnetpi_dir}/model/${labels_lang} ${birdnetpi_dir}/model/labels.txt
|
||||
fi
|
||||
IFS=$oIFS
|
||||
}
|
||||
|
||||
get_ssh() {
|
||||
if service ssh status | grep -q inactive; then
|
||||
echo 1
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
do_ssh() {
|
||||
if [ -e /var/log/regen_ssh_keys.log ] && ! grep -q "^finished" /var/log/regen_ssh_keys.log; then
|
||||
whiptail --msgbox "Initial ssh key generation still running. Please wait and try again." 20 60 2
|
||||
return 1
|
||||
fi
|
||||
DEFAULT=--defaultno
|
||||
if [ $(get_ssh) -eq 0 ]; then
|
||||
DEFAULT=
|
||||
fi
|
||||
whiptail --yesno \
|
||||
"Would you like the SSH server to be enabled?\n\nCaution: Default and weak passwords are a security risk when SSH is enabled!" $DEFAULT 20 60 2
|
||||
RET=$?
|
||||
if [ $RET -eq 0 ]; then
|
||||
ssh-keygen -A &&
|
||||
update-rc.d ssh enable &&
|
||||
invoke-rc.d ssh start &&
|
||||
STATUS=enabled
|
||||
elif [ $RET -eq 1 ]; then
|
||||
update-rc.d ssh disable &&
|
||||
invoke-rc.d ssh stop &&
|
||||
STATUS=disabled
|
||||
else
|
||||
return $RET
|
||||
fi
|
||||
whiptail --msgbox "The SSH server is $STATUS" 20 60 1
|
||||
}
|
||||
|
||||
get_vnc() {
|
||||
if systemctl status vncserver-x11-serviced.service | grep -q -w active; then
|
||||
echo 0
|
||||
else
|
||||
echo 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_config_zram() {
|
||||
if [ -e /etc/udev/rules.d/99-zram.rules ]; then
|
||||
## get current swap allocation from /etc/udev/rules.d/99-zram.rules
|
||||
size="$(awk -F\" '{print $4}' /etc/udev/rules.d/99-zram.rules)"
|
||||
else
|
||||
size="4G"
|
||||
fi
|
||||
new_size=$(whiptail --inputbox "How much memory (G) should the zRAM swap partition have? Choose 1G, 2G, or 4G - 4G recommended" \
|
||||
19 70 -- "$size" 3>&1 1>&2 2>&3)
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_install_zram() {
|
||||
echo "Configuring zram.service"
|
||||
touch /etc/modules-load.d/zram.conf
|
||||
echo 'zram' > /etc/modules-load.d/zram.conf
|
||||
touch /etc/modprobe.d/zram.conf
|
||||
echo 'options zram num_devices=1' > /etc/modprobe.d/zram.conf
|
||||
touch /etc/udev/rules.d/99-zram.rules
|
||||
echo "KERNEL==\"zram0\", ATTR{disksize}=\"${new_size}\",TAG+=\"systemd\"" \
|
||||
> /etc/udev/rules.d/99-zram.rules
|
||||
touch /etc/systemd/system/zram.service
|
||||
echo "Installing zram.service"
|
||||
cat << EOF > /etc/systemd/system/zram.service
|
||||
[Unit]
|
||||
Description=Swap with zram
|
||||
After=multi-user.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=true
|
||||
ExecStartPre=/sbin/mkswap /dev/zram0
|
||||
ExecStart=/sbin/swapon /dev/zram0
|
||||
ExecStop=/sbin/swapoff /dev/zram0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable zram
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_zram_menu() {
|
||||
whiptail --yesno "Would like to enable the zram swapping kernel module?" --defaultno 20 60 2
|
||||
RET=$?
|
||||
if [ $RET -eq 0 ]; then
|
||||
do_config_zram
|
||||
do_install_zram
|
||||
STATUS=enabled
|
||||
elif [ $RET -eq 1 ]; then
|
||||
if [ -e /etc/udev/rules.d/99-zram.rules ];then
|
||||
systemctl disable --now zram
|
||||
fi
|
||||
STATUS=disabled
|
||||
fi
|
||||
whiptail --msgbox "ZRAM swapping is $STATUS" 20 60 1
|
||||
return $RET
|
||||
}
|
||||
|
||||
do_vnc() {
|
||||
DEFAULT=--defaultno
|
||||
if [ $(get_vnc) -eq 0 ]; then
|
||||
DEFAULT=
|
||||
fi
|
||||
whiptail --yesno "Would you like the VNC Server to be enabled?" $DEFAULT 20 60 2
|
||||
RET=$?
|
||||
if [ $RET -eq 0 ]; then
|
||||
if is_installed realvnc-vnc-server || apt-get install realvnc-vnc-server; then
|
||||
systemctl enable vncserver-x11-serviced.service &&
|
||||
systemctl start vncserver-x11-serviced.service &&
|
||||
STATUS=enabled
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
elif [ $RET -eq 1 ]; then
|
||||
if is_installed realvnc-vnc-server; then
|
||||
systemctl disable vncserver-x11-serviced.service
|
||||
systemctl stop vncserver-x11-serviced.service
|
||||
fi
|
||||
STATUS=disabled
|
||||
else
|
||||
return $RET
|
||||
fi
|
||||
whiptail --msgbox "The VNC Server is $STATUS" 20 60 1
|
||||
}
|
||||
|
||||
do_audio() {
|
||||
if is_pulseaudio ; then
|
||||
oIFS="$IFS"
|
||||
list=$(sudo -u $SUDO_USER XDG_RUNTIME_DIR=/run/user/$SUDO_UID pacmd list-sources | grep -B1 -e 'alsa.card_name' -e 'name.*input' | grep -A4 index | sed -e s/*//g | sed s/^[' '\\t]*//g | grep -e index -e card_name | sed s/'index: '//g | sed s/'alsa.card_name = '//g | sed s/\"//g | tr '\n' '\/')
|
||||
if ! [ -z "$list" ] ; then
|
||||
IFS="/"
|
||||
AUDIO_IN=$(whiptail --menu "Choose the audio input" 20 60 10 ${list} 3>&1 1>&2 2>&3)
|
||||
return 0
|
||||
else
|
||||
whiptail --msgbox "No internal audio devices found" 20 60 1
|
||||
return 1
|
||||
fi
|
||||
if [ $? -eq 0 ]; then
|
||||
sudo -u $SUDO_USER XDG_RUNTIME_DIR=/run/user/$SUDO_UID pactl set-default-source "$AUDIO_IN"
|
||||
fi
|
||||
IFS=$oIFS
|
||||
fi
|
||||
sudo -u $SUDO_USER pulseaudio -k
|
||||
}
|
||||
|
||||
list_wlan_interfaces() {
|
||||
for dir in /sys/class/net/*/wireless; do
|
||||
if [ -d "$dir" ]; then
|
||||
basename "$(dirname "$dir")"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
do_wifi_ssid_passphrase() {
|
||||
RET=0
|
||||
IFACE_LIST="$(list_wlan_interfaces)"
|
||||
IFACE="$(echo "$IFACE_LIST" | head -n 1)"
|
||||
|
||||
if [ -z "$IFACE" ]; then
|
||||
whiptail --msgbox "No wireless interface found" 20 60
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! wpa_cli -i "$IFACE" status > /dev/null 2>&1; then
|
||||
whiptail --msgbox "Could not communicate with wpa_supplicant" 20 60
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$(get_wifi_country)" ]; then
|
||||
do_wifi_country
|
||||
fi
|
||||
|
||||
SSID="$1"
|
||||
while [ -z "$SSID" ] ; do
|
||||
SSID=$(whiptail --inputbox "Please enter SSID" 20 60 3>&1 1>&2 2>&3)
|
||||
if [ $? -ne 0 ]; then
|
||||
return 0
|
||||
elif [ -z "$SSID" ]; then
|
||||
whiptail --msgbox "SSID cannot be empty. Please try again." 20 60
|
||||
fi
|
||||
done
|
||||
|
||||
PASSPHRASE="$2"
|
||||
PASSPHRASE=$(whiptail --passwordbox "Please enter passphrase. Leave it empty if none." 20 60 3>&1 1>&2 2>&3)
|
||||
if [ $? -ne 0 ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Escape special characters for embedding in regex below
|
||||
local ssid="$(echo "$SSID" \
|
||||
| sed 's;\\;\\\\;g' \
|
||||
| sed -e 's;\.;\\\.;g' \
|
||||
-e 's;\*;\\\*;g' \
|
||||
-e 's;\+;\\\+;g' \
|
||||
-e 's;\?;\\\?;g' \
|
||||
-e 's;\^;\\\^;g' \
|
||||
-e 's;\$;\\\$;g' \
|
||||
-e 's;\/;\\\/;g' \
|
||||
-e 's;\[;\\\[;g' \
|
||||
-e 's;\];\\\];g' \
|
||||
-e 's;{;\\{;g' \
|
||||
-e 's;};\\};g' \
|
||||
-e 's;(;\\(;g' \
|
||||
-e 's;);\\);g' \
|
||||
-e 's;";\\\\\";g')"
|
||||
|
||||
wpa_cli -i "$IFACE" list_networks \
|
||||
| tail -n +2 | cut -f -2 | grep -P "\t$ssid$" | cut -f1 \
|
||||
| while read ID; do
|
||||
wpa_cli -i "$IFACE" remove_network "$ID" > /dev/null 2>&1
|
||||
done
|
||||
|
||||
ID="$(wpa_cli -i "$IFACE" add_network)"
|
||||
wpa_cli -i "$IFACE" set_network "$ID" ssid "\"$SSID\"" 2>&1 | grep -q "OK"
|
||||
RET=$((RET + $?))
|
||||
|
||||
if [ -z "$PASSPHRASE" ]; then
|
||||
wpa_cli -i "$IFACE" set_network "$ID" key_mgmt NONE 2>&1 | grep -q "OK"
|
||||
RET=$((RET + $?))
|
||||
else
|
||||
wpa_cli -i "$IFACE" set_network "$ID" psk "\"$PASSPHRASE\"" 2>&1 | grep -q "OK"
|
||||
RET=$((RET + $?))
|
||||
fi
|
||||
|
||||
if [ $RET -eq 0 ]; then
|
||||
wpa_cli -i "$IFACE" enable_network "$ID" > /dev/null 2>&1
|
||||
else
|
||||
wpa_cli -i "$IFACE" remove_network "$ID" > /dev/null 2>&1
|
||||
whiptail --msgbox "Failed to set SSID or passphrase" 20 60
|
||||
fi
|
||||
wpa_cli -i "$IFACE" save_config > /dev/null 2>&1
|
||||
|
||||
echo "$IFACE_LIST" | while read IFACE; do
|
||||
wpa_cli -i "$IFACE" reconfigure > /dev/null 2>&1
|
||||
done
|
||||
|
||||
return $RET
|
||||
}
|
||||
|
||||
do_reget_birdnetpi_urls() {
|
||||
birdnetpi_url=$(whiptail --inputbox "Put your domain here. Example: \"https://birdnetpi.pmcgui.xyz\"." \
|
||||
19 70 -- "https://" 3>&1 1>&2 2>&3) extractionlog_url=$(whiptail --inputbox "Put your domain here. Example: \"https://extractionlog.pmcgui.xyz\"." 19 70 -- "https://" 3>&1 1>&2 2>&3) birdnetlog_url=$(whiptail --inputbox "Put your domain here. Example: \"https://birdnetlog.pmcgui.xyz\"." 19 70 -- "https://" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_reget_db_pwd() {
|
||||
db_pwd=$(whiptail --inputbox "Please set the password the 'birder' user will use to access the database." \
|
||||
19 70 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_reget_birdweather_id() {
|
||||
birdweather_id=$(whiptail --inputbox "Input your BirdWeather ID" \
|
||||
19 70 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
do_reget_caddy_pwd() {
|
||||
caddy_pwd=$(whiptail --inputbox "Please set the password for the web interface." \
|
||||
19 70 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
do_reget_lon() {
|
||||
lon="$(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',')"
|
||||
new_lon=$(whiptail --inputbox "Please set the longitude where recordings will take place." \
|
||||
19 70 -- "$lon" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_reget_lat() {
|
||||
lat="$(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',')"
|
||||
new_lat=$(whiptail --inputbox "Please set the latitude where recordings will take place." \
|
||||
19 70 -- "$lat" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_confidence() {
|
||||
confidence="$(awk -F= '/CONFIDENCE=/ {print $2}' ${birdnetpi_dir}/birdnet.conf)"
|
||||
new_confidence=$(whiptail --inputbox "Please set the minimum confidence score BirdNET-Lite should use." \
|
||||
19 70 -- "$confidence" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
do_get_overlap() {
|
||||
overlap="$(awk -F= '/OVERLAP=/ {print $2}' ${birdnetpi_dir}/birdnet.conf)"
|
||||
new_overlap=$(whiptail --inputbox "Please set the overlap BirdNET-Lite should use." \
|
||||
19 70 -- "$overlap" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
do_get_sensitivity() {
|
||||
sensitivity="$(awk -F= '/SENSITIVITY=/ {print $2}' ${birdnetpi_dir}/birdnet.conf)"
|
||||
new_sensitivity=$(whiptail --inputbox "Please set the simoid sensitivty BirdNET-Lite should use." \
|
||||
19 70 -- "$sensitivity" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/rewrite_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_birdnetlog_url() {
|
||||
birdnetlog_url=$(whiptail --inputbox "Put your domain here. Example: \"https://birdnetlog.pmcgui.xyz\"." \
|
||||
19 70 -- "https://" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_extractionlog_url() {
|
||||
extractionlog_url=$(whiptail --inputbox "Put your domain here. Example: \"https://extractionlog.pmcgui.xyz\"." \
|
||||
19 70 -- "https://" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_birdnetpi_url() {
|
||||
birdnetpi_url=$(whiptail --inputbox "Put your domain here. Example: \"https://birdnetpi.pmcgui.xyz\"." \
|
||||
19 70 -- "https://" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_birdweather_id() {
|
||||
birdweather_id=$(whiptail --inputbox "Input your BirdWeather ID" \
|
||||
19 70 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_db_pwd() {
|
||||
db_pwd=$(whiptail --inputbox "Please set the password the 'birder' user will use to access the database." \
|
||||
19 70 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_ice_pwd() {
|
||||
ice_pwd=$(whiptail --inputbox "Please set the password for the live stream." \
|
||||
19 70 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_caddy_pwd() {
|
||||
caddy_pwd=$(whiptail --inputbox "Please set the password for the web interface." \
|
||||
19 70 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
do_get_lon() {
|
||||
lon="$(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',')"
|
||||
new_lon=$(whiptail --inputbox "Please set the longitude where recordings will take place." \
|
||||
19 70 -- "$lon" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_get_lat() {
|
||||
lat="$(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',')"
|
||||
new_lat=$(whiptail --inputbox "Please set the latitude where recordings will take place." \
|
||||
19 70 -- "$lat" 3>&1 1>&2 2>&3) ${birdnetpi_dir}/scripts/write_config.sh
|
||||
if [ $? -eq 0 ];then
|
||||
return 0
|
||||
ASK_TO_REBOOT=2
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_update_os() {
|
||||
apt update && apt -y full-upgrade && \
|
||||
ASK_TO_REBOOT=1
|
||||
}
|
||||
|
||||
do_update_birdnet() {
|
||||
sudo -E -upi ${birdnetpi_dir}/scripts/update_birdnet.sh
|
||||
}
|
||||
|
||||
do_install_birdnet() {
|
||||
sudo -E -upi ${birdnetpi_dir}/Birders_Guide_Installer.sh && \
|
||||
ASK_TO_REBOOT=1
|
||||
}
|
||||
|
||||
insist_on_reboot() {
|
||||
if [ $ASK_TO_REBOOT -eq 2 ]; then
|
||||
whiptail --yesno "You really should reboot. Do that now?" 20 60 2
|
||||
if [ $? -eq 0 ]; then # yes
|
||||
sync
|
||||
reboot
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
do_finish() {
|
||||
if [ $ASK_TO_REBOOT -eq 1 ]; then
|
||||
whiptail --yesno "Would you like to reboot now?" 20 60 2
|
||||
if [ $? -eq 0 ]; then # yes
|
||||
sync
|
||||
reboot
|
||||
fi
|
||||
elif [ $ASK_TO_REBOOT -eq 2 ]; then
|
||||
whiptail --yesno "You really should reboot. Do that now?" 20 60 2
|
||||
if [ $? -eq 0 ]; then # yes
|
||||
sync
|
||||
reboot
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Everything else needs to be run as root
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
printf "Script must be run as root. Try 'sudo birdnet-pi-config'\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
do_advanced_reconfig_menu() {
|
||||
MENU=9
|
||||
while [ $MENU -eq 9 ];do
|
||||
if is_pi ; then
|
||||
FUN=$(whiptail --title "BirdNET-Pi Software Configuration Tool (birdnet-pi-config)" --menu "BirdNET-Pi Configuration Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
|
||||
"Sensitivity" "Set the sigmoid sensitivity" \
|
||||
"Confidence" "Set the minimum confidence score required for a detection" \
|
||||
"Overlap" "Set the analysis overlap in seconds" \
|
||||
"BirdNET-Pi URLs" "Set the URLs your installation should use" \
|
||||
3>&1 1>&2 2>&3)
|
||||
else
|
||||
exit
|
||||
fi
|
||||
RET=$?
|
||||
if [ $RET -eq 1 ]; then
|
||||
return 0
|
||||
MENU=0
|
||||
elif [ $RET -eq 0 ]; then
|
||||
case "$FUN" in
|
||||
Sens*) do_get_sensitivity;;
|
||||
Confi*) do_get_confidence;;
|
||||
Overlap*) do_get_overlap;;
|
||||
Bird*) do_reget_birdnetpi_urls;;
|
||||
*) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
|
||||
esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
do_interface_menu() {
|
||||
MENU=6
|
||||
while [ $MENU -eq 6 ];do
|
||||
if is_pi ; then
|
||||
FUN=$(whiptail --title "BirdNET-Pi Software Configuration Tool (birdnet-pi-config)" --menu "Interfacing Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
|
||||
"SSH" "Enable/disable remote command line access using SSH" \
|
||||
"VNC" "Enable/disable graphical remote access using RealVNC" \
|
||||
3>&1 1>&2 2>&3)
|
||||
else
|
||||
exit
|
||||
fi
|
||||
RET=$?
|
||||
if [ $RET -eq 1 ]; then
|
||||
return 0
|
||||
MENU=0
|
||||
elif [ $RET -eq 0 ]; then
|
||||
case "$FUN" in
|
||||
SSH*) do_ssh ;;
|
||||
VNC*) do_vnc ;;
|
||||
*) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
|
||||
esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
do_advanced_config_menu() {
|
||||
MENU=5
|
||||
while [ $MENU -eq 5 ];do
|
||||
if is_pi ; then
|
||||
FUN=$(whiptail --title "BirdNET-Pi Software Configuration Tool (birdnet-pi-config)" --menu "BirdNET-Pi Configuration Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
|
||||
"Sensitivity" "Set the sigmoid sensitivity" \
|
||||
"Confidence" "Set the minimum confidence score required for a detection" \
|
||||
"Overlap" "Set the analysis overlap in seconds" \
|
||||
"BirdNET-Pi URLs" "Set the URLs your installation should use" \
|
||||
3>&1 1>&2 2>&3)
|
||||
else
|
||||
exit
|
||||
fi
|
||||
RET=$?
|
||||
if [ $RET -eq 1 ]; then
|
||||
return 0
|
||||
MENU=0
|
||||
elif [ $RET -eq 0 ]; then
|
||||
case "$FUN" in
|
||||
Sens*) do_get_sensitivity;;
|
||||
Confi*) do_get_confidence;;
|
||||
Overlap*) do_get_overlap;;
|
||||
Bird*) do_get_birdnetpi_url; do_get_birdnetlog_url; do_get_extractionlog_url;;
|
||||
*) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
|
||||
esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
do_system_menu() {
|
||||
MENU=4
|
||||
while [ $MENU -eq 4 ];do
|
||||
if is_pi ; then
|
||||
FUN=$(whiptail --title "BirdNET-Pi Software Configuration Tool (birdnet-pi-config)" --menu "System Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
|
||||
"Password" "Change password for the '$USER' user" \
|
||||
"Audio" "Select audio device you'd like BirdNET-Pi to use" \
|
||||
"Wireless LAN" "Enter SSID and passphrase" \
|
||||
"Update the OS" "Update the underlying operating system" \
|
||||
"Interface Options" "Enable/Disable SSH and VNC" \
|
||||
"Configure zRAM" "Enable/Disable zRAM" \
|
||||
"Timezone" "Configure time zone" \
|
||||
"Keyboard" "Set keyboard layout to match your keyboard" \
|
||||
"WLAN Country" "Set legal wireless channels for your country" \
|
||||
3>&1 1>&2 2>&3)
|
||||
else
|
||||
exit
|
||||
fi
|
||||
RET=$?
|
||||
if [ $RET -eq 1 ]; then
|
||||
return 0
|
||||
MENU=0
|
||||
elif [ $RET -eq 0 ]; then
|
||||
case "$FUN" in
|
||||
Password*) do_change_pass ;;
|
||||
Audio*) do_audio ;;
|
||||
Wireless*) do_wifi_ssid_passphrase ;;
|
||||
Update*) do_update_os ;;
|
||||
Interface*) do_interface_menu ;;
|
||||
Configure*) do_zram_menu ;;
|
||||
Time*) do_change_timezone; insist_on_reboot ;;
|
||||
Key*) do_configure_keyboard ;;
|
||||
WLAN*) do_wifi_country ;;
|
||||
*) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
|
||||
esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
do_reconfig_birdnet_menu() {
|
||||
MENU=3
|
||||
while [ $MENU -eq 3 ];do
|
||||
if is_pi ; then
|
||||
FUN=$(whiptail --title "BirdNET-Pi Software Configuration Tool (birdnet-pi-config)" --menu "BirdNET-Pi Re-configuration Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
|
||||
"Latitude " "Set the latitude your system should use" \
|
||||
"Longitude" "Set the longitude your system should use" \
|
||||
"Caddy Password" "Set the web interface password" \
|
||||
"Database Password" "Set the password BirdNET-Pi will use to access the DB" \
|
||||
"BirdWeather ID" "Input your BirdWeather ID if you have one" \
|
||||
"Advanced Settings" "Sensitivity, Overlap, Confidence, URLs" \
|
||||
3>&1 1>&2 2>&3)
|
||||
else
|
||||
exit
|
||||
fi
|
||||
RET=$?
|
||||
if [ $RET -eq 1 ]; then
|
||||
return 0
|
||||
MENU=0
|
||||
elif [ $RET -eq 0 ]; then
|
||||
case "$FUN" in
|
||||
Lat*) do_reget_lat;;
|
||||
Lon*) do_reget_lon;;
|
||||
Cad*) do_reget_caddy_pwd;;
|
||||
Data*) do_reget_db_pwd;;
|
||||
Bird*) do_reget_birdweather_id;;
|
||||
Advanced*) do_advanced_reconfig_menu;;
|
||||
*) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
|
||||
esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
do_config_birdnet_menu() {
|
||||
MENU=2
|
||||
while [ $MENU -eq 2 ];do
|
||||
if is_pi ; then
|
||||
FUN=$(whiptail --title "BirdNET-Pi Software Configuration Tool (birdnet-pi-config)" --menu "BirdNET-Pi Configuration Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
|
||||
"Latitude " "Set the latitude your system should use" \
|
||||
"Longitude" "Set the longitude your system should use" \
|
||||
"Caddy Password" "Set the web interface password" \
|
||||
"IceCast2 Password" "Set the IceCast2 password" \
|
||||
"Database Password" "Set the password BirdNET-Pi will use to access the DB" \
|
||||
"BirdWeather ID" "Input your BirdWeather ID if you have one" \
|
||||
"Set Custom URLS" "Designate custom URLs for the web services if you've set that up" \
|
||||
3>&1 1>&2 2>&3)
|
||||
else
|
||||
exit
|
||||
fi
|
||||
RET=$?
|
||||
if [ $RET -eq 1 ]; then
|
||||
return 0
|
||||
MENU=0
|
||||
elif [ $RET -eq 0 ]; then
|
||||
case "$FUN" in
|
||||
Lat*) do_get_lat;;
|
||||
Lon*) do_get_lon;;
|
||||
Cad*) do_get_caddy_pwd;;
|
||||
Ice*) do_get_ice_pwd;;
|
||||
Data*) do_get_db_pwd;;
|
||||
Bird*) do_get_birdweather_id;;
|
||||
Set*) do_get_birdnetpi_url; do_get_birdnetlog_url; do_get_extractionlog_url;;
|
||||
*) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
|
||||
esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
do_internationalisation_menu() {
|
||||
MENU=1
|
||||
while [ $MENU -eq 1 ];do
|
||||
FUN=$(whiptail --title "BirdNET-Pi Software Configuration Tool (birdnet-pi-config)" --menu "Localisation Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \
|
||||
"System Locale" "Configure the system language and regional settings" \
|
||||
"labels.txt" "Set the language to use for species detection" \
|
||||
"Time Zone" "Set the Time Zone" \
|
||||
3>&1 1>&2 2>&3)
|
||||
RET=$?
|
||||
if [ $RET -eq 1 ]; then
|
||||
return 0
|
||||
MENU=0
|
||||
elif [ $RET -eq 0 ]; then
|
||||
case "$FUN" in
|
||||
System*) do_change_locale;;
|
||||
label*) get_labels_lang;;
|
||||
Time*) do_change_timezone;;
|
||||
*) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
|
||||
esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Interactive use loop
|
||||
#
|
||||
[ -e $CONFIG ] || touch $CONFIG
|
||||
calc_wt_size
|
||||
while [ "$USER" = "root" ] || [ -z "$USER" ]; do
|
||||
if ! USER=$(whiptail --inputbox "birdnet-pi-config could not determine the default user.\\n\\nWhat user should these settings apply to?" 20 60 pi 3>&1 1>&2 2>&3); then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
while true; do
|
||||
FUN=$(whiptail --title "BirdNET-Pi Software Configuration Tool (birdnet-pi-config)" --backtitle "$(cat /proc/device-tree/model)" --menu "Setup Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Finish --ok-button Select \
|
||||
"Step 1" "Configure language and timezone" \
|
||||
"Step 2" "Configure BirdNET-Pi before installation" \
|
||||
"Step 3" "Install BirdNET-Pi" \
|
||||
"Step 4" "Reconfigure BirdNET-Pi AFTER installation" \
|
||||
"Step 5" "Update BirdNET-Pi (run this if you changed URLs)" \
|
||||
"System Options" "Configure system settings" \
|
||||
3>&1 1>&2 2>&3)
|
||||
RET=$?
|
||||
if [ $RET -eq 1 ]; then
|
||||
do_finish
|
||||
elif [ $RET -eq 0 ]; then
|
||||
case "$FUN" in
|
||||
*1) do_internationalisation_menu ;;
|
||||
*2) do_config_birdnet_menu ;;
|
||||
*3) do_install_birdnet;;
|
||||
*4) do_reconfig_birdnet_menu ;;
|
||||
*5) do_update_birdnet;;
|
||||
Sys*) do_system_menu ;;
|
||||
*) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
|
||||
esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
|
||||
fi
|
||||
done
|
||||
+26
-27
@@ -95,9 +95,8 @@ run_analysis() {
|
||||
WEEK="$(echo "${WEEK_OF_YEAR} + 4" |bc -l)"
|
||||
fi
|
||||
|
||||
cd ${HOME}/BirdNET-Pi/scripts || exit 1
|
||||
for i in "${files[@]}";do
|
||||
echo "${1}/${i}" > ../analyzing_now.txt
|
||||
echo "${1}/${i}" > /home/pi/BirdNET-Pi/analyzing_now.txt
|
||||
[ -z ${RECORDING_LENGTH} ] && RECORDING_LENGTH=15
|
||||
[ ${RECORDING_LENGTH} == "60" ] && RECORDING_LENGTH=01:00
|
||||
FILE_LENGTH="$(ffmpeg -i ${1}/${i} 2>&1 | awk -F. '/Duration/ {print $1}' | cut -d':' -f3-4)"
|
||||
@@ -131,7 +130,7 @@ run_analysis() {
|
||||
done
|
||||
fi
|
||||
if [ -f ${1}/${i} ] && [ ! -f ${INCLUDE_LIST} ] && [ ! -f ${EXCLUDE_LIST} ] && [ -z $BIRDWEATHER_ID ];then
|
||||
echo "python3 analyze.py \
|
||||
echo "analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -140,7 +139,7 @@ run_analysis() {
|
||||
--overlap "${OVERLAP}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}""
|
||||
"${VENV}"/bin/python analyze.py \
|
||||
analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -150,7 +149,7 @@ run_analysis() {
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}"
|
||||
elif [ -f ${1}/${i} ] && [ -f ${INCLUDELIST} ] && [ ! -f ${EXCLUDE_LIST} ] && [ -z $BIRDWEATHER_ID ];then
|
||||
echo "python3 analyze.py \
|
||||
echo "analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -160,18 +159,18 @@ run_analysis() {
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--include_list "${INCLUDE_LIST}""
|
||||
"${VENV}"/bin/python analyze.py \
|
||||
analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
--lon "${LONGITUDE}" \
|
||||
--week "${WEEK}" \
|
||||
--overlap "${OVERLAP}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--include_list "${INCLUDE_LIST}"
|
||||
--include_list "${INCLUDE_LIST}"
|
||||
elif [ -f ${1}/${i} ] && [ ! -f ${INCLUDE_LIST} ] && [ -f ${EXCLUDE_LIST} ] && [ -z $BIRDWEATHER_ID ];then
|
||||
echo "python3 analyze.py \
|
||||
echo "analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -181,18 +180,18 @@ run_analysis() {
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--exclude_list "${EXCLUDE_LIST}""
|
||||
"${VENV}"/bin/python analyze.py \
|
||||
analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
--lon "${LONGITUDE}" \
|
||||
--week "${WEEK}" \
|
||||
--overlap "${OVERLAP}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--exclude_list "${EXCLUDE_LIST}"
|
||||
--exclude_list "${EXCLUDE_LIST}"
|
||||
elif [ -f ${1}/${i} ] && [ -f ${INCLUDE_LIST} ] && [ -f ${EXCLUDE_LIST} ] && [ -z $BIRDWEATHER_ID ];then
|
||||
echo "python3 analyze.py \
|
||||
echo "analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -203,19 +202,19 @@ run_analysis() {
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--include_list "${INCLUDE_LIST}" \
|
||||
--exclude_list "${EXCLUDE_LIST}""
|
||||
"${VENV}"/bin/python analyze.py \
|
||||
analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
--lon "${LONGITUDE}" \
|
||||
--week "${WEEK}" \
|
||||
--overlap "${OVERLAP}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--include_list "${INCLUDE_LIST}" \
|
||||
--exclude_list "${EXCLUDE_LIST}"
|
||||
elif [ -f ${1}/${i} ] && [ ! -f ${INCLUDE_LIST} ] && [ ! -f ${EXCLUDE_LIST} ] && [ ! -z $BIRDWEATHER_ID ];then
|
||||
echo "python3 analyze.py \
|
||||
echo "analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -225,18 +224,18 @@ run_analysis() {
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--birdweather_id "IN_USE""
|
||||
"${VENV}"/bin/python analyze.py \
|
||||
analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
--lon "${LONGITUDE}" \
|
||||
--week "${WEEK}" \
|
||||
--overlap "${OVERLAP}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--birdweather_id "${BIRDWEATHER_ID}"
|
||||
elif [ -f ${1}/${i} ] && [ -f ${INCLUDE_LIST} ] && [ ! -f ${EXCLUDE_LIST} ] && [ ! -z $BIRDWEATHER_ID ];then
|
||||
echo "python3 analyze.py \
|
||||
echo "analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -247,19 +246,19 @@ run_analysis() {
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--include_list "${INCLUDE_LIST}" \
|
||||
--birdweather_id "IN_USE""
|
||||
"${VENV}"/bin/python analyze.py \
|
||||
analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
--lon "${LONGITUDE}" \
|
||||
--week "${WEEK}" \
|
||||
--overlap "${OVERLAP}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--include_list "${INCLUDE_LIST}" \
|
||||
--birdweather_id "${BIRDWEATHER_ID}"
|
||||
elif [ -f ${1}/${i} ] && [ ! -f ${INCLUDE_LIST} ] && [ -f ${EXCLUDE_LIST} ] && [ ! -z $BIRDWEATHER_ID ];then
|
||||
echo "python3 analyze.py \
|
||||
echo "analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -270,19 +269,19 @@ run_analysis() {
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--exclude_list "${EXCLUDE_LIST}" \
|
||||
--birdweather_id "IN_USE""
|
||||
"${VENV}"/bin/python analyze.py \
|
||||
analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
--lon "${LONGITUDE}" \
|
||||
--week "${WEEK}" \
|
||||
--overlap "${OVERLAP}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--exclude_list "${EXCLUDE_LIST}" \
|
||||
--birdweather_id "${BIRDWEATHER_ID}"
|
||||
elif [ -f ${1}/${i} ] && [ -f ${INCLUDE_LIST} ] && [ -f ${EXCLUDE_LIST} ] && [ ! -z $BIRDWEATHER_ID ];then
|
||||
echo "python3 analyze.py \
|
||||
echo "analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
@@ -294,14 +293,14 @@ run_analysis() {
|
||||
--include_list "${INCLUDE_LIST}" \
|
||||
--exclude_list "${EXCLUDE_LIST}" \
|
||||
--birdweather_id "IN_USE""
|
||||
"${VENV}"/bin/python analyze.py \
|
||||
analyze.py \
|
||||
--i "${1}/${i}" \
|
||||
--o "${1}/${i}.csv" \
|
||||
--lat "${LATITUDE}" \
|
||||
--lon "${LONGITUDE}" \
|
||||
--week "${WEEK}" \
|
||||
--overlap "${OVERLAP}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--sensitivity "${SENSITIVITY}" \
|
||||
--min_conf "${CONFIDENCE}" \
|
||||
--include_list "${INCLUDE_LIST}" \
|
||||
--exclude_list "${EXCLUDE_LIST}" \
|
||||
|
||||
@@ -10,6 +10,8 @@ fi
|
||||
|
||||
[ -z $RECORDING_LENGTH ] && RECORDING_LENGTH=15
|
||||
|
||||
if ! pulseaudio --check;then pulseaudio --start;fi
|
||||
|
||||
if pgrep arecord &> /dev/null ;then
|
||||
echo "Recording"
|
||||
else
|
||||
|
||||
@@ -4,7 +4,7 @@ if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
} elseif (file_exists('/home/pi/BirdNET-Pi/firstrun.ini')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/firstrun.ini');
|
||||
}
|
||||
$template = file_get_contents("email_template");
|
||||
$template = file_get_contents("scripts/email_template");
|
||||
|
||||
foreach($config as $key => $value)
|
||||
{
|
||||
|
||||
+30
-70
@@ -9,82 +9,42 @@ USER=pi
|
||||
my_dir=${HOME}/BirdNET-Pi/scripts
|
||||
echo "Stopping services"
|
||||
sudo systemctl stop birdnet_recording.service
|
||||
sudo systemctl stop birdnet_analysis.service
|
||||
sudo systemctl stop birdnet_server.service
|
||||
echo "Removing all data . . . "
|
||||
sudo rm -drf "${RECS_DIR}"
|
||||
sudo rm -f "${IDFILE}"
|
||||
sudo rm -f $(dirname ${my_dir})/BirdDB.txt
|
||||
|
||||
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 ${EXTRACTED}/Charts ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/Charts
|
||||
[ -d ${PROCESSED} ] || sudo -u ${USER} mkdir -p ${PROCESSED}
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/* ${EXTRACTED}
|
||||
if [ ! -z ${BIRDNETLOG_URL} ];then
|
||||
BIRDNETLOG_URL="$(echo ${BIRDNETLOG_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/$(hostname).local:8080/"${BIRDNETLOG_URL}"/g" $(dirname ${my_dir})/homepage/*.html
|
||||
phpfiles="$(grep -l "$(hostname).local:8080" ${my_dir}/*.php)"
|
||||
for i in "${phpfiles[@]}";do
|
||||
sudo -u${USER} sed -i "s/http:\/\/$(hostname).local:8080/"${BIRDNETLOG_URL}"/g" ${i}
|
||||
done
|
||||
fi
|
||||
if [ ! -z ${WEBTERMINAL_URL} ];then
|
||||
WEBTERMINAL_URL="$(echo ${WEBTERMINAL_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/$(hostname).local:8888/"${WEBTERMINAL_URL}"/g" $(dirname ${my_dir})/homepage/*.html
|
||||
phpfiles="$(grep -l "$(hostname).local:8888" ${my_dir}/*.php)"
|
||||
for i in "${phpfiles[@]}";do
|
||||
sudo -u${USER} sed -i "s/http:\/\/$(hostname).local:8888/"${WEBTERMINAL_URL}"/g" ${i}
|
||||
done
|
||||
fi
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/model/labels.txt ${my_dir}/
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts ${EXTRACTED}
|
||||
if [ -z ${BIRDNETPI_URL} ];then
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
else
|
||||
BIRDNETPI_URL="$(echo ${BIRDNETPI_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
fi
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/spectrogram.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewday.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/history.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/images/favicon.ico ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED}
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html
|
||||
|
||||
echo "Setting Wttr.in URL to "${LATITUDE}", "${LONGITUDE}""
|
||||
sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html
|
||||
chmod -R g+rw $(dirname ${my_dir})
|
||||
chmod -R g+rw ${RECS_DIR}
|
||||
|
||||
echo "Generating BirdDB.txt"
|
||||
if ! [ -f $(dirname ${my_dir})/BirdDB.txt ];then
|
||||
sudo -u ${USER} touch $(dirname ${my_dir})/BirdDB.txt
|
||||
echo "Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap" | sudo -u ${USER} tee -a $(dirname ${my_dir})/BirdDB.txt
|
||||
elif ! grep Date $(dirname ${my_dir})/BirdDB.txt;then
|
||||
sudo -u ${USER} sed -i '1 i\Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap' $(dirname ${my_dir})/BirdDB.txt
|
||||
fi
|
||||
ln -sf $(dirname ${my_dir})/BirdDB.txt ${my_dir}/BirdDB.txt &&
|
||||
chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt
|
||||
[ -d ${EXTRACTED} ] || mkdir -p ${EXTRACTED}
|
||||
[ -d ${EXTRACTED}/By_Date ] || mkdir -p ${EXTRACTED}/By_Date
|
||||
[ -d ${EXTRACTED}/Charts ] || mkdir -p ${EXTRACTED}/Charts
|
||||
[ -d ${PROCESSED} ] || mkdir -p ${PROCESSED}
|
||||
|
||||
ln -fs $(dirname ${my_dir})/homepage/* ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/model/labels.txt ${my_dir}/
|
||||
ln -fs $(dirname ${my_dir})/scripts ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/scripts/play.php ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/scripts/spectrogram.php ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/scripts/history.php ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/homepage/images/favicon.ico ${EXTRACTED}
|
||||
ln -fs ${HOME}/phpsysinfo ${EXTRACTED}
|
||||
ln -fs $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/
|
||||
ln -fs $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/
|
||||
ln -fs $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html
|
||||
sudo chmod -R g+rw $(dirname ${my_dir})
|
||||
sudo chmod -R g+rw ${EXTRACTED}
|
||||
|
||||
echo "Dropping and re-creating database"
|
||||
sudo /home/pi/BirdNET-Pi/scripts/createdb_bullseye.sh
|
||||
createdb.sh
|
||||
echo "Generating BirdDB.txt"
|
||||
touch $(dirname ${my_dir})/BirdDB.txt
|
||||
echo "Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap" > $(dirname ${my_dir})/BirdDB.txt
|
||||
ln -sf $(dirname ${my_dir})/BirdDB.txt ${my_dir}/BirdDB.txt
|
||||
chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt
|
||||
echo "Restarting services"
|
||||
sudo systemctl start birdnet_recording.service
|
||||
restart_services.sh
|
||||
|
||||
+66
-122
@@ -1,125 +1,72 @@
|
||||
<?php
|
||||
session_start();
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
|
||||
# Basic Settings
|
||||
if(isset($_POST["latitude"])){
|
||||
$latitude = $_POST["latitude"];
|
||||
$longitude = $_POST["longitude"];
|
||||
$birdweather_id = $_POST["birdweather_id"];
|
||||
$pushed_app_key = $_POST["pushed_app_key"];
|
||||
$pushed_app_secret = $_POST["pushed_app_secret"];
|
||||
|
||||
$contents = file_get_contents("/home/pi/BirdNET-Pi/birdnet.conf");
|
||||
$contents = preg_replace("/LATITUDE=.*/", "LATITUDE=$latitude", $contents);
|
||||
$contents = preg_replace("/LONGITUDE=.*/", "LONGITUDE=$longitude", $contents);
|
||||
$contents = preg_replace("/BIRDWEATHER_ID=.*/", "BIRDWEATHER_ID=$birdweather_id", $contents);
|
||||
$contents = preg_replace("/PUSHED_APP_KEY=.*/", "PUSHED_APP_KEY=$pushed_app_key", $contents);
|
||||
$contents = preg_replace("/PUSHED_APP_SECRET=.*/", "PUSHED_APP_SECRET=$pushed_app_secret", $contents);
|
||||
|
||||
$contents2 = file_get_contents("/home/pi/BirdNET-Pi/thisrun.txt");
|
||||
$contents2 = preg_replace("/LATITUDE=.*/", "LATITUDE=$latitude", $contents2);
|
||||
$contents2 = preg_replace("/LONGITUDE=.*/", "LONGITUDE=$longitude", $contents2);
|
||||
$contents2 = preg_replace("/BIRDWEATHER_ID=.*/", "BIRDWEATHER_ID=$birdweather_id", $contents2);
|
||||
$contents2 = preg_replace("/PUSHED_APP_KEY=.*/", "PUSHED_APP_KEY=$pushed_app_key", $contents2);
|
||||
$contents2 = preg_replace("/PUSHED_APP_SECRET=.*/", "PUSHED_APP_SECRET=$pushed_app_secret", $contents2);
|
||||
|
||||
$fh = fopen("/home/pi/BirdNET-Pi/birdnet.conf", "w");
|
||||
$fh2 = fopen("/home/pi/BirdNET-Pi/thisrun.txt", "w");
|
||||
fwrite($fh, $contents);
|
||||
fwrite($fh2, $contents2);
|
||||
|
||||
$language = $_POST["language"];
|
||||
if ($language != "none"){
|
||||
$command = "sudo -upi mv /home/pi/BirdNET-Pi/model/labels.txt /home/pi/BirdNET-Pi/model/labels.txt.old && sudo -upi unzip /home/pi/BirdNET-Pi/model/labels_l18n.zip $language -d /home/pi/BirdNET-Pi/model && sudo -upi mv /home/pi/BirdNET-Pi/model/$language /home/pi/BirdNET-Pi/model/labels.txt";
|
||||
$command_output = `$command`;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* Create two unequal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
.first {
|
||||
width: calc(50% - 70px);
|
||||
}
|
||||
.second {
|
||||
width: calc(50% - 30px);
|
||||
}
|
||||
.
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.block {
|
||||
display: block;
|
||||
width:50%;
|
||||
border: none;
|
||||
padding: 10px 10px;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
select {
|
||||
font-size:large;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
select option {
|
||||
font-size:large;
|
||||
}
|
||||
|
||||
form {
|
||||
text-align:left;
|
||||
margin-left:20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom:0px;
|
||||
}
|
||||
h3 {
|
||||
margin-left: -10px;
|
||||
text-align:left;
|
||||
}
|
||||
label {
|
||||
float:left;
|
||||
width:40%;
|
||||
font-weight:bold;
|
||||
}
|
||||
input {
|
||||
width:60%;
|
||||
text-align:center;
|
||||
font-size:large;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
select {
|
||||
width:100%;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom:0px;
|
||||
text-align:center;
|
||||
}
|
||||
form {
|
||||
text-align:left;
|
||||
margin-left:0px;
|
||||
}
|
||||
.column {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
input, label {
|
||||
width:100%;
|
||||
{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<div class="settings">
|
||||
<h2>Basic Settings</h2>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<div class="row">
|
||||
<div class="column first">
|
||||
<form action="write_config.php" method="POST" name="normal">
|
||||
<form action="" method="POST">
|
||||
<?php
|
||||
if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/thisrun.txt');
|
||||
} elseif (file_exists('/home/pi/BirdNET-Pi/firstrun.ini')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/firstrun.ini');
|
||||
} ?>
|
||||
}
|
||||
$caddypwd = $config['CADDY_PWD'];
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot edit the settings for this installation';
|
||||
exit;
|
||||
} else {
|
||||
$submittedpwd = $_SERVER['PHP_AUTH_PW'];
|
||||
$submitteduser = $_SERVER['PHP_AUTH_USER'];
|
||||
if($submittedpwd !== $caddypwd || $submitteduser !== 'birdnet'){
|
||||
header('WWW-Authenticate: Basic realm="My Realm"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo 'You cannot edit the settings for this installation';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<label for="latitude">Latitude: </label>
|
||||
<input name="latitude" type="number" max="90" min="-90" step="0.0001" value="<?php print($config['LATITUDE']);?>" required/><br>
|
||||
<label for="longitude">Longitude: </label>
|
||||
@@ -167,22 +114,19 @@ if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
<option value="labels_uk.txt">Ukrainian</option>
|
||||
</select>
|
||||
<br><br>
|
||||
<button type="submit" name="normal" class="block"><?php
|
||||
if(isset($_SESSION['success'])){
|
||||
<input type="hidden" name="status" value="success">
|
||||
<input type="hidden" name="submit" value="settings">
|
||||
<button type="submit" name="view" value="Settings">
|
||||
<?php
|
||||
if(isset($_POST['status'])){
|
||||
echo "Success!";
|
||||
unset($_SESSION['success']);
|
||||
} else {
|
||||
echo "Update Settings";
|
||||
}
|
||||
?></button>
|
||||
</form>
|
||||
<form action="advanced.php" class="form2">
|
||||
<button type="submit" class="block">Advanced Settings</button>
|
||||
</form>
|
||||
<form action="index.html" class="form2">
|
||||
<button type="submit" class="block">Tools</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
?>
|
||||
</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<button type="submit" name="view" value="Advanced">Advanced Settings</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
source /etc/birdnet/birdnet.conf
|
||||
sqlite3 /home/pi/BirdNET-Pi/scripts/birds.db << EOF
|
||||
DROP TABLE IF EXISTS detections;
|
||||
CREATE TABLE IF NOT EXISTS detections (
|
||||
Date DATE,
|
||||
Time TIME,
|
||||
Sci_Name VARCHAR(100) NOT NULL,
|
||||
Com_Name VARCHAR(100) NOT NULL,
|
||||
Confidence FLOAT,
|
||||
Lat FLOAT,
|
||||
Lon FLOAT,
|
||||
Cutoff FLOAT,
|
||||
Week INT,
|
||||
Sens FLOAT,
|
||||
Overlap FLOAT,
|
||||
File_Name VARCHAR(100) NOT NULL);
|
||||
EOF
|
||||
sudo chown pi:pi /home/pi/BirdNET-Pi/scripts/birds.db
|
||||
sudo chmod g+w /home/pi/BirdNET-Pi/scripts/birds.db
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# This script performs the mysql_secure_installation
|
||||
# Creates the birds database
|
||||
# Creates the detections table
|
||||
# Creates the birder user and grants them appropriate
|
||||
# permissions
|
||||
# If using this script to re-initialize (DROP then CREATE)
|
||||
# the DB, be sure to run this as root or with sudo
|
||||
source /etc/birdnet/birdnet.conf
|
||||
mysql_secure_installation << EOF
|
||||
|
||||
y
|
||||
n
|
||||
y
|
||||
y
|
||||
y
|
||||
y
|
||||
EOF
|
||||
|
||||
mysql << EOF
|
||||
DROP DATABASE IF EXISTS birds;
|
||||
CREATE DATABASE IF NOT EXISTS birds;
|
||||
|
||||
USE birds;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS detections (
|
||||
Date DATE,
|
||||
Time TIME,
|
||||
Sci_Name VARCHAR(100) NOT NULL,
|
||||
Com_Name VARCHAR(100) NOT NULL,
|
||||
Confidence FLOAT,
|
||||
Lat FLOAT,
|
||||
Lon FLOAT,
|
||||
Cutoff FLOAT,
|
||||
Week INT,
|
||||
Sens FLOAT,
|
||||
Overlap FLOAT);
|
||||
GRANT ALL ON birds.* TO 'birder'@'localhost' IDENTIFIED BY '${DB_PWD}' WITH GRANT OPTION;
|
||||
FLUSH PRIVILEGES;
|
||||
exit
|
||||
EOF
|
||||
sudo -u${USER} sed -i "s/databasepassword/${DB_PWD}/g" /home/pi/BirdNET-Pi/scripts/server.py
|
||||
sed -i "s/mysqli.default_host =.*/mysqli.default_host = localhost/g" /etc/php/7.4/fpm/php.ini
|
||||
sed -i "s/mysqli.default_user =.*/mysqli.default_user = birder/g" /etc/php/7.4/fpm/php.ini
|
||||
sed -i "s/mysqli.default_pw =.*/mysqli.default_pw = ${DB_PWD}/g" /etc/php/7.4/fpm/php.ini
|
||||
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
source /etc/birdnet/birdnet.conf
|
||||
|
||||
STAMP="%H:%M:%S"
|
||||
|
||||
[ -z $RECORDING_LENGTH ] && RECORDING_LENGTH=15
|
||||
|
||||
if ! pulseaudio --check;then pulseaudio --start;fi
|
||||
|
||||
CUSTOM_WINDOW_START=(0 3 15 22)
|
||||
CUSTOM_WINDOW_END=(0 7 19 23)
|
||||
RECORDING_DURATION=60
|
||||
PAUSE_DURATION=240
|
||||
|
||||
now=$(date +%H)
|
||||
|
||||
while [ $now -ge ${CUSTOM_WINDOW_START[0]} ] && [ $now -le ${CUSTOM_WINDOW_END[0]} ];do
|
||||
echo $now
|
||||
# If you prefer no directory structure under "Raw", comment out the
|
||||
# lines below and uncommend the commands at the bottom.
|
||||
arecord -f S16_LE -c${CHANNELS} -r48000 -t wav -d $RECORDING_DURATION \
|
||||
--use-strftime ${EXTRACTED}/Raw/%B-%Y/%d-%A/%F-birdnet-${STAMP}.wav
|
||||
|
||||
# Uncomment the lines below if you'd prefer having no directory scructure
|
||||
# under the "Raw" directory. Be sure to comment out the command above.
|
||||
#arecord -f S16_LE -c${CHANNELS} -r48000 -t wav -d $RECORDING_DURATION \
|
||||
# --use-strftime ${EXTRACTED}/Raw/%F-birdnet-${STAMP}.wav
|
||||
sleep $PAUSE_DURATION
|
||||
now=$(date +%H)
|
||||
done
|
||||
while [ $now -ge ${CUSTOM_WINDOW_START[1]} ] && [ $now -le ${CUSTOM_WINDOW_END[1]} ];do
|
||||
echo $now
|
||||
# If you prefer no directory structure under "Raw", comment out the
|
||||
# lines below and uncommend the commands at the bottom.
|
||||
arecord -f S16_LE -c${CHANNELS} -r48000 -t wav -d $RECORDING_DURATION \
|
||||
--use-strftime ${EXTRACTED}/Raw/%B-%Y/%d-%A/%F-birdnet-${STAMP}.wav
|
||||
|
||||
# Uncomment the lines below if you'd prefer having no directory scructure
|
||||
# under the "Raw" directory. Be sure to comment out the command above.
|
||||
#arecord -f S16_LE -c${CHANNELS} -r48000 -t wav -d $RECORDING_DURATION \
|
||||
# --use-strftime ${EXTRACTED}/Raw/%F-birdnet-${STAMP}.wav
|
||||
sleep $PAUSE_DURATION
|
||||
now=$(date +%H)
|
||||
done
|
||||
while [ $now -ge ${CUSTOM_WINDOW_START[2]} ] && [ $now -le ${CUSTOM_WINDOW_END[2]} ];do
|
||||
echo $now
|
||||
# If you prefer no directory structure under "Raw", comment out the
|
||||
# lines below and uncommend the commands at the bottom.
|
||||
arecord -f S16_LE -c${CHANNELS} -r48000 -t wav -d $RECORDING_DURATION \
|
||||
--use-strftime ${EXTRACTED}/Raw/%B-%Y/%d-%A/%F-birdnet-${STAMP}.wav
|
||||
|
||||
# Uncomment the lines below if you'd prefer having no directory scructure
|
||||
# under the "Raw" directory. Be sure to comment out the command above.
|
||||
#arecord -f S16_LE -c${CHANNELS} -r48000 -t wav -d $RECORDING_DURATION \
|
||||
# --use-strftime ${EXTRACTED}/Raw/%F-birdnet-${STAMP}.wav
|
||||
sleep $PAUSE_DURATION
|
||||
now=$(date +%H)
|
||||
done
|
||||
while [ $now -ge ${CUSTOM_WINDOW_START[3]} ] && [ $now -le ${CUSTOM_WINDOW_END[3]} ];do
|
||||
echo $now
|
||||
# If you prefer no directory structure under "Raw", comment out the
|
||||
# lines below and uncommend the commands at the bottom.
|
||||
arecord -f S16_LE -c${CHANNELS} -r48000 -t wav -d $RECORDING_DURATION \
|
||||
--use-strftime ${EXTRACTED}/Raw/%B-%Y/%d-%A/%F-birdnet-${STAMP}.wav
|
||||
|
||||
# Uncomment the lines below if you'd prefer having no directory scructure
|
||||
# under the "Raw" directory. Be sure to comment out the command above.
|
||||
#arecord -f S16_LE -c${CHANNELS} -r48000 -t wav -d $RECORDING_DURATION \
|
||||
# --use-strftime ${EXTRACTED}/Raw/%F-birdnet-${STAMP}.wav
|
||||
sleep $PAUSE_DURATION
|
||||
now=$(date +%H)
|
||||
done
|
||||
|
||||
|
||||
+9
-21
@@ -1,9 +1,8 @@
|
||||
#!/home/pi/BirdNET-Pi/birdnet/bin/python3
|
||||
|
||||
import mysql.connector as sql
|
||||
import sqlite3
|
||||
import os
|
||||
import configparser
|
||||
|
||||
import pandas as pd
|
||||
import seaborn as sns
|
||||
import matplotlib.pyplot as plt
|
||||
@@ -11,25 +10,14 @@ from matplotlib.colors import LogNorm
|
||||
from datetime import datetime
|
||||
import textwrap
|
||||
|
||||
#Extract DB_PWD from thisrun.txt
|
||||
with open('/home/pi/BirdNET-Pi/thisrun.txt', 'r') as f:
|
||||
this_run = f.readlines()
|
||||
db_pwd = str(str(str([i for i in this_run if i.startswith('DB_PWD')]).split('=')[1]).split('\\')[0])
|
||||
conn = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds.db')
|
||||
df = pd.read_sql_query("SELECT * from detections", conn)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT * FROM detections')
|
||||
|
||||
table_rows = cursor.fetchall()
|
||||
|
||||
db_connection = sql.connect(host='localhost',
|
||||
database='birds',
|
||||
user='birder',
|
||||
password=db_pwd)
|
||||
|
||||
|
||||
db_cursor=db_connection.cursor(dictionary=True)
|
||||
|
||||
db_cursor.execute('SELECT * FROM detections')
|
||||
|
||||
table_rows = db_cursor.fetchall()
|
||||
|
||||
df=pd.DataFrame(table_rows)
|
||||
#df=pd.DataFrame(table_rows)
|
||||
|
||||
#Convert Date and Time Fields to Panda's format
|
||||
df['Date']=pd.to_datetime(df['Date'])
|
||||
@@ -97,7 +85,7 @@ heat_frame = pd.DataFrame(data=0, index=heat.index, columns = hours_in_day)
|
||||
heat=(heat+heat_frame).fillna(0)
|
||||
|
||||
#Generatie heatmap plot
|
||||
plot = sns.heatmap(heat, norm=LogNorm(), annot=True, annot_kws={"fontsize":7}, cmap = pal , square = False, cbar=False, linewidths = 0.5, linecolor = "Grey", ax=axs[1], yticklabels = False)
|
||||
plot = sns.heatmap(heat, norm=LogNorm(), annot=True, annot_kws={"fontsize":7}, fmt="g", cmap = pal , square = False, cbar=False, linewidths = 0.5, linecolor = "Grey", ax=axs[1], yticklabels = False)
|
||||
plot.set_xticklabels(plot.get_xticklabels(), rotation = 0, size = 7)
|
||||
|
||||
# Set heatmap border
|
||||
@@ -165,7 +153,7 @@ heat_frame = pd.DataFrame(data=0, index=heat.index, columns = hours_in_day)
|
||||
heat=(heat+heat_frame).fillna(0)
|
||||
|
||||
#Generatie heatmap plot
|
||||
plot = sns.heatmap(heat, norm=LogNorm(), annot=True, annot_kws={"fontsize":7}, cmap = pal , square = False, cbar=False, linewidths = 0.5, linecolor = "Grey", ax=axs[1], yticklabels = False)
|
||||
plot = sns.heatmap(heat, norm=LogNorm(), annot=True, fmt="g", annot_kws={"fontsize":7}, cmap = pal , square = False, cbar=False, linewidths = 0.5, linecolor = "Grey", ax=axs[1], yticklabels = False)
|
||||
plot.set_xticklabels(plot.get_xticklabels(), rotation = 0, size = 7)
|
||||
|
||||
# Set heatmap border
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
$file='/home/pi/BirdNET-Pi/exclude_species_list.txt';
|
||||
$str=file_get_contents("$file");
|
||||
$str = preg_replace('/^\h*\v+/m', '', $str);
|
||||
file_put_contents("$file", "$str");
|
||||
|
||||
if (isset($_POST['species']))
|
||||
foreach($_POST['species'] as $selectedOption) {
|
||||
$content = file_get_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt");
|
||||
$newcontent = str_replace($selectedOption, "", "$content");
|
||||
file_put_contents("/home/pi/BirdNET-Pi/exclude_species_list.txt", "$newcontent");
|
||||
}
|
||||
$file='/home/pi/BirdNET-Pi/exclude_species_list.txt';
|
||||
$str=file_get_contents("$file");
|
||||
//$str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
|
||||
$str = preg_replace('/^\h*\v+/m', '', $str);
|
||||
file_put_contents("$file", "$str");
|
||||
header("Location: {$_SERVER['HTTP_REFERER']}");
|
||||
exit;
|
||||
?>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
$file='/home/pi/BirdNET-Pi/include_species_list.txt';
|
||||
$str=file_get_contents("$file");
|
||||
$str = preg_replace('/^\h*\v+/m', '', $str);
|
||||
file_put_contents("$file", "$str");
|
||||
|
||||
if (isset($_POST['species']))
|
||||
foreach($_POST['species'] as $selectedOption) {
|
||||
$content = file_get_contents("/home/pi/BirdNET-Pi/include_species_list.txt");
|
||||
$newcontent = str_replace($selectedOption, "", "$content");
|
||||
file_put_contents("/home/pi/BirdNET-Pi/include_species_list.txt", "$newcontent");
|
||||
}
|
||||
$file='/home/pi/BirdNET-Pi/include_species_list.txt';
|
||||
$str=file_get_contents("$file");
|
||||
//$str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
|
||||
$str = preg_replace('/^\h*\v+/m', '', $str);
|
||||
file_put_contents("$file", "$str");
|
||||
header("Location: {$_SERVER['HTTP_REFERER']}");
|
||||
exit;
|
||||
?>
|
||||
+48
-112
@@ -1,121 +1,57 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Create two unequal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.first {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.second {
|
||||
width: 10%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.third {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
|
||||
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
width:100%;
|
||||
border: none;
|
||||
background-color: #04AA6D;
|
||||
padding: 20px 20px;
|
||||
color: white;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
select {
|
||||
width:100%
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.column {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div class="customlabels column1">
|
||||
<form action="" method="POST" id="add">
|
||||
<h3>All Species Labels</h3>
|
||||
<select name="species[]" id="species" multiple size="auto">
|
||||
<option>Choose a species below to add to the Excluded Species List</option>
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
|
||||
$filename = 'scripts/labels.txt';
|
||||
$eachline = file($filename, FILE_IGNORE_NEW_LINES);
|
||||
|
||||
foreach($eachline as $lines){echo
|
||||
"<option value='".$lines."'>$lines</option>";}
|
||||
?>
|
||||
</select>
|
||||
<input type="hidden" name="add" value="add">
|
||||
</form>
|
||||
<div class="customlabels smaller">
|
||||
<button type="submit" name="view" value="Excluded" form="add">>>ADD>></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="customlabels column2">
|
||||
<table><td>
|
||||
<button type="submit" name="view" value="Excluded" form="add">>>ADD>></button>
|
||||
<br><br>
|
||||
<button type="submit" name="view" value="Excluded" form="del">REMOVE</button>
|
||||
</td></table>
|
||||
</div>
|
||||
|
||||
<div class="customlabels column3">
|
||||
<form action="" method="POST" id="del">
|
||||
<h3>Excluded Species List</h3>
|
||||
<select name="species[]" id="value2" multiple size="auto">
|
||||
<?php
|
||||
//remove <script></script> and add php start and close tag
|
||||
//comment these two lines when code started working fine
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
|
||||
$filename = 'labels.txt';
|
||||
$eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
||||
|
||||
?>
|
||||
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<div class="row">
|
||||
<div class="column first">
|
||||
<h2>All Species Labels</h2>
|
||||
<form action="add_to_exclude.php" method="POST" id="add">
|
||||
<select name="species[]" id="species" multiple size="30">
|
||||
<option selected value="base">Please Select</option>
|
||||
<?php
|
||||
foreach($eachlines as $lines){
|
||||
echo "<option value='".$lines."'>$lines</option>";
|
||||
$filename = '/home/pi/BirdNET-Pi/exclude_species_list.txt';
|
||||
$eachline = file($filename, FILE_IGNORE_NEW_LINES);
|
||||
foreach($eachline as $lines){
|
||||
echo
|
||||
"<option value='".$lines."'>$lines</option>";
|
||||
}?>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</select>
|
||||
<input type="hidden" name="del" value="del">
|
||||
</form>
|
||||
<div class="customlabels smaller">
|
||||
<button type="submit" name="view" value="Excluded" form="del">REMOVE</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column second">
|
||||
<button type="submit" form="add" class="block">Add to list</button><br>
|
||||
<button type="submit" form="del" class="block">Remove from list</button>
|
||||
</div>
|
||||
|
||||
<div class="column third">
|
||||
<h2>Excluded Species List</h2>
|
||||
<form action="del_from_exclude.php" method="POST" id="del">
|
||||
<select name="species[]" id="value2" multiple size="30">
|
||||
<option selected value="base">Please Select</option>
|
||||
<?php
|
||||
$filename = '/home/pi/BirdNET-Pi/exclude_species_list.txt';
|
||||
$eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
||||
foreach($eachlines as $lines){
|
||||
echo "<option value='".$lines."'>$lines</option>";
|
||||
}?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
+32
-16
@@ -12,29 +12,45 @@ echo "Binary: $binary";
|
||||
revbinary=$(echo $binary|rev)
|
||||
if echo $binary | grep 1 ;then
|
||||
echo "ISSUES DETECTED"
|
||||
if [ ${revbinary:0:1} -eq 1 ];then
|
||||
echo "Under-voltage detected"
|
||||
if [ ${revbinary:0:1} -eq 1 &> /dev/null ];then
|
||||
message="Under-voltage detected"
|
||||
echo "$message"
|
||||
dmesg -H | grep -i voltage
|
||||
fi
|
||||
if [ ${revbinary:1:1} -eq 1 ];then
|
||||
echo "Arm frequency capped"
|
||||
if [ ${revbinary:1:1} -eq 1 &> /dev/null ];then
|
||||
message="Arm frequency capped"
|
||||
echo "$message"
|
||||
dmesg -H | grep -i frequen
|
||||
fi
|
||||
if [ ${revbinary:2:1} -eq 1 ];then
|
||||
echo "Currently Throttled"
|
||||
if [ ${revbinary:2:1} -eq 1 &> /dev/null ];then
|
||||
message="Currently Throttled"
|
||||
echo "$message"
|
||||
dmesg -H | grep -i throttl
|
||||
fi
|
||||
if [ ${revbinary:3:1} -eq 1 ];then
|
||||
echo "Soft temperatue limit active"
|
||||
if [ ${revbinary:3:1} -eq 1 &> /dev/null ];then
|
||||
message="Soft temperatue limit active"
|
||||
echo "$message"
|
||||
dmesg -H | grep -i temperature
|
||||
fi
|
||||
if [ ${revbinary:16:1} -eq 1 ];then
|
||||
echo "Under-voltage has occurred"
|
||||
if [ ${revbinary:16:1} -eq 1 &> /dev/null ];then
|
||||
message="Under-voltage has occurred"
|
||||
echo "$message"
|
||||
dmesg -H | grep -i voltage
|
||||
fi
|
||||
if [ ${revbinary:17:1} -eq 1 ];then
|
||||
echo "Arm frequency capping has occurred"
|
||||
if [ ${revbinary:17:1} -eq 1 &> /dev/null ];then
|
||||
message="Arm frequency capping has occurred"
|
||||
echo "$message"
|
||||
dmesg -H | grep -i frequen
|
||||
fi
|
||||
if [ ${revbinary:18:1} -eq 1 ];then
|
||||
echo "Throttling has occurred"
|
||||
if [ ${revbinary:18:1} -eq 1 &> /dev/null ];then
|
||||
message="Throttling has occurred"
|
||||
echo "$message"
|
||||
dmesg -H | grep -i throttl
|
||||
fi
|
||||
if [ ${revbinary:19:1} -eq 1 ];then
|
||||
echo "Soft temperature limit has occurred"
|
||||
if [ ${revbinary:19:1} -eq 1 &> /dev/null ];then
|
||||
message="Soft temperature limit has occurred"
|
||||
echo "$message"
|
||||
dmesg -H | grep -i temperature
|
||||
fi
|
||||
fi
|
||||
echo "....................................Clock Speeds................................"
|
||||
|
||||
@@ -61,14 +61,18 @@ for h in "${SCAN_DIRS[@]}";do
|
||||
SCIENTIFIC_NAME=""$(echo ${line} \
|
||||
| awk -F\; '!/birdnet/{print $3}')""
|
||||
CONFIDENCE=""$(echo ${line} \
|
||||
| awk -F\; '{print $5}' \
|
||||
| cut -d'.' -f2)""
|
||||
CONFIDENCE_SCORE="${CONFIDENCE:0:2}%"
|
||||
| awk -F\; '{print $5}')""
|
||||
|
||||
#CONFIDENCE_SCORE="${CONFIDENCE:0:2}%"
|
||||
locale_decimal=$(locale decimal_point)
|
||||
if [[ $locale_decimal == "." ]]; then
|
||||
CONFIDENCE_SCORE="$(printf %.0f "$(echo "scale=2; ${CONFIDENCE} * 100" | bc)")"
|
||||
else
|
||||
CONFIDENCE_SCORE="$(printf %.0f "$(echo "scale=2; "${CONFIDENCE}" * 100" | bc | tr '.' ',')")"
|
||||
fi
|
||||
NEWFILE="${COMMON_NAME// /_}-${CONFIDENCE_SCORE}-${OLDFILE//.wav/.${AUDIOFMT}}"
|
||||
echo "NEWFILE=$NEWFILE"
|
||||
NEWSPECIES_BYDATE="${EXTRACTED}/By_Date/${DATE}/${COMMON_NAME// /_}"
|
||||
NEWSPECIES_BY_COMMON="${EXTRACTED}/By_Common_Name/${COMMON_NAME// /_}"
|
||||
NEWSPECIES_BY_SCIENCE="${EXTRACTED}/By_Scientific_Name/${SCIENTIFIC_NAME// /_}"
|
||||
|
||||
# If the extracted file already exists, move on
|
||||
if [[ -f "${NEWSPECIES_BYDATE}/${NEWFILE}" ]];then
|
||||
@@ -85,16 +89,6 @@ for h in "${SCAN_DIRS[@]}";do
|
||||
# it is created
|
||||
[[ -d "${NEWSPECIES_BYDATE}" ]] || mkdir -p "${NEWSPECIES_BYDATE}"
|
||||
|
||||
|
||||
# If a directory does not already exist for the species (by-species),
|
||||
# it is created.
|
||||
[[ -d "${NEWSPECIES_BY_COMMON}" ]] || mkdir -p "${NEWSPECIES_BY_COMMON}"
|
||||
|
||||
# If a directory does not already exist for the species (by-species),
|
||||
# it is created.
|
||||
[[ -d "${NEWSPECIES_BY_SCIENCE}" ]] || mkdir -p "${NEWSPECIES_BY_SCIENCE}"
|
||||
|
||||
|
||||
# If there are already 20 extracted entries for a given species
|
||||
# for today, remove the oldest file and create the new one.
|
||||
# if [[ "$(find ${NEWSPECIES_BYDATE} | wc -l)" -ge 20 ]];then
|
||||
@@ -131,9 +125,6 @@ for h in "${SCAN_DIRS[@]}";do
|
||||
|
||||
sox "${h}/${OLDFILE}" "${NEWSPECIES_BYDATE}/${NEWFILE}" \
|
||||
trim "${START}" "${END}"
|
||||
#ffmpeg -hide_banner -loglevel error -nostdin -i "${h}/${OLDFILE}" \
|
||||
# -acodec copy -ss "${START}" -to "${END}"\
|
||||
# "${NEWSPECIES_BYDATE}/${NEWFILE}"
|
||||
|
||||
# Create spectrogram for extraction
|
||||
sox "${NEWSPECIES_BYDATE}/${NEWFILE}" -n remix 1 rate 24k spectrogram \
|
||||
@@ -141,48 +132,6 @@ for h in "${SCAN_DIRS[@]}";do
|
||||
-c "${NEWSPECIES_BYDATE}/${NEWFILE}" \
|
||||
-o "${NEWSPECIES_BYDATE}/${NEWFILE}.png"
|
||||
|
||||
# Remove the oldest symbolic links that would make the directory have more
|
||||
# than 20 entries.
|
||||
if [[ "$(find ${NEWSPECIES_BY_COMMON} | wc -l)" -ge 40 ]];then
|
||||
echo "20 ${SPECIES}s, already! Removing the oldest by-species and making a new one"
|
||||
cd ${NEWSPECIES_BY_COMMON} || exit 1
|
||||
ls -1t . | tail -n +40 | xargs -r rm -vv
|
||||
ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}"\
|
||||
"${NEWSPECIES_BY_COMMON}/${NEWFILE}"
|
||||
ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}.png"\
|
||||
"${NEWSPECIES_BY_COMMON}/${NEWFILE}.png"
|
||||
echo "Success! New extraction for ${COMMON_NAME}"
|
||||
else
|
||||
# Make symbolic link of the extraction to add to By_Common_Name
|
||||
ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}"\
|
||||
"${NEWSPECIES_BY_COMMON}/${NEWFILE}"
|
||||
ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}.png"\
|
||||
"${NEWSPECIES_BY_COMMON}/${NEWFILE}.png"
|
||||
fi
|
||||
|
||||
# Remove the oldest symbolic links that would made the directory have more
|
||||
# than 20 entries.
|
||||
if [[ "$(find ${NEWSPECIES_BY_SCIENCE} | wc -l)" -ge 40 ]];then
|
||||
echo "20 ${SPECIES}s, already! Removing the oldest by-species and making a new one"
|
||||
cd ${NEWSPECIES_BY_SCIENCE} || exit 1
|
||||
ls -1t . | tail -n +40 | xargs -r rm -vv
|
||||
ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}"\
|
||||
"${NEWSPECIES_BY_SCIENCE}/${NEWFILE}"
|
||||
ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}.png"\
|
||||
"${NEWSPECIES_BY_SCIENCE}/${NEWFILE}.png"
|
||||
echo "Success! New extraction for ${COMMON_NAME}"
|
||||
else
|
||||
ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}"\
|
||||
"${NEWSPECIES_BY_SCIENCE}/${NEWFILE}"
|
||||
ln -fs "${NEWSPECIES_BYDATE}/${NEWFILE}.png"\
|
||||
"${NEWSPECIES_BY_SCIENCE}/${NEWFILE}.png"
|
||||
fi
|
||||
|
||||
|
||||
# Finally, 'a' is incremented by one to allow multiple extractions per
|
||||
# species per minute.
|
||||
#a=$((a + 1))
|
||||
|
||||
done < "${TMPFILE}"
|
||||
|
||||
# Once each line of the TMPFILE has been processed, the TMPFILE is emptied
|
||||
@@ -192,11 +141,11 @@ for h in "${SCAN_DIRS[@]}";do
|
||||
# Rename files that have been processed so that they are not processed on the
|
||||
# next extraction.
|
||||
[[ -d "${PROCESSED}" ]] || mkdir "${PROCESSED}"
|
||||
echo "Moving processed files to ${PROCESSED}"
|
||||
#echo "Moving processed files to ${PROCESSED}"
|
||||
mv ${h}/* ${PROCESSED} &> /dev/null || continue
|
||||
done
|
||||
|
||||
echo "Linking Processed files to "${EXTRACTED}/Processed" web directory"
|
||||
#echo "Linking Processed files to "${EXTRACTED}/Processed" web directory"
|
||||
# After all audio extractions have taken place, a directory is created to house
|
||||
# the original WAVE and .txt files used for this extraction processs.
|
||||
if [[ ! -L ${EXTRACTED}/Processed ]] || [[ ! -e ${EXTRACTED}/Processed ]];then
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
//Default Configuration
|
||||
$CONFIG = '{"lang":"en","error_reporting":false,"show_hidden":false,"hide_Cols":false,"calc_folder":false,"theme":"light"}';
|
||||
<?php
|
||||
//Default Configuration
|
||||
$CONFIG = '{"lang":"en","error_reporting":false,"show_hidden":true,"hide_Cols":false,"calc_folder":false,"theme":"light"}';
|
||||
|
||||
/**
|
||||
* H3K | Tiny File Manager V2.4.6
|
||||
@@ -3342,9 +3342,9 @@ function fm_show_nav_path($path)
|
||||
}
|
||||
?>
|
||||
<nav class="navbar navbar-expand-lg <?php echo $getTheme; ?> mb-4 main-nav <?php echo $isStickyNavBar ?>">
|
||||
<a class="navbar-brand" href="../../">BirdNET-Pi Homepage </a>
|
||||
<a class="navbar-brand" href="../"><?php echo lng('Tools'); ?></a>
|
||||
<a class="navbar-brand" href="http://birdnetpi.local:8888" target="_"><?php echo lng('WebTerminal'); ?></a>
|
||||
<form action="../../views.php" method="POST">
|
||||
<button style="margin-left:80px;" class="navbar-brand" type="submit" name="view" value="Overview">BirdNET-Pi Homepage</button>
|
||||
<button class="navbar-brand" type="submit" name="view" value="Tools"><?php echo lng('Tools'); ?></button></form>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
width: 50%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.block {
|
||||
display: block;
|
||||
width:100%;
|
||||
border: none;
|
||||
padding: 10px 10px;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
select {
|
||||
font-size:large;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
select option {
|
||||
font-size:large;
|
||||
}
|
||||
|
||||
form {
|
||||
text-align:left;
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom:0px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-left: -10px;
|
||||
}
|
||||
label {
|
||||
float:left;
|
||||
width:40%;
|
||||
font-weight:bold;
|
||||
}
|
||||
input {
|
||||
width:60%;
|
||||
text-align:center;
|
||||
font-size:large;
|
||||
}
|
||||
.center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
h1, h2 {
|
||||
text-align:center;
|
||||
}
|
||||
form {
|
||||
text-align:left;
|
||||
margin-left:0px;
|
||||
}
|
||||
select, body, button, input, label {
|
||||
width:100%;
|
||||
{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<?php
|
||||
if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/thisrun.txt');
|
||||
} elseif (file_exists('/home/pi/BirdNET-Pi/firstrun.ini')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/firstrun.ini');
|
||||
} ?>
|
||||
|
||||
<h1 style="float:top;text-align:center;">Welcome!</h1>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<form action="write_config.php" method="POST" name="firstboot">
|
||||
<p style="font-size:large">Thank you for installing BirdNET-Pi!
|
||||
to get started, fill out the Required sections below.</p>
|
||||
<h2>Required</h2>
|
||||
<label for="latitude">Latitude: </label>
|
||||
<input name="latitude" type="number" min="-90" max="90" step="0.0001" value="<?php print($config['LATITUDE']);?>" required/><br>
|
||||
<label for="longitude">Longitude: </label>
|
||||
<input name="longitude" type="number" min="-180" max="180" step="0.0001" value="<?php print($config['LONGITUDE']);?>" required/><br>
|
||||
<h2>Optional Services</h2>
|
||||
<p>The services below are not required, but they are pretty cool.</p>
|
||||
<label for="birdweather_id">BirdWeather ID: </label>
|
||||
<input name="birdweather_id" type="text" value="<?php print($config['BIRDWEATHER_ID']);?>" /><br>
|
||||
<p>app.BirdWeather.com is a weather map for bird sounds. Stations around the world supply audio and video streams to BirdWeather where they are then analyzed by BirdNET and compared to eBird Grid data. BirdWeather catalogues the detections and visualizations so that you can listen to, view, and read about the birds in various regions across the globe! Pretty cool! <a href="mailto:tim@birdweather.com?subject=Request%20BirdWeather%20ID&body=<?php include('birdweather_request.php'); ?>" target="top">Email Tim</a> to request a BirdWeather ID</p>
|
||||
|
||||
<label for="pushed_app_key">Pushed App Key: </label>
|
||||
<input name="pushed_app_key" type="text" value="" /><br>
|
||||
<label for="pushed_app_secret">Pushed App Secret: </label>
|
||||
<input name="pushed_app_secret" type="text" value="" /><br>
|
||||
<p>Pushed.co is used to offer New Species notifications. Sorry Android users, but the Pushed.co Application is only for iOS.</p>
|
||||
<label for="language">Database Language: </label>
|
||||
<select name="language">
|
||||
<option value="none">English</option>
|
||||
<option value="labels_af.txt">Afrikaans</option>
|
||||
<option value="labels_ca.txt">Catalan</option>
|
||||
<option value="labels_cs.txt">Czech</option>
|
||||
<option value="labels_zh.txt">Chinese</option>
|
||||
<option value="labels_hr.txt">Croatian</option>
|
||||
<option value="labels_da.txt">Danish</option>
|
||||
<option value="labels_nl.txt">Dutch</option>
|
||||
<option value="labels_et.txt">Estonian</option>
|
||||
<option value="labels_fi.txt">Finnish</option>
|
||||
<option value="labels_fr.txt">French</option>
|
||||
<option value="labels_de.txt">German</option>
|
||||
<option value="labels_hu.txt">Hungarian</option>
|
||||
<option value="labels_is.txt">Icelandic</option>
|
||||
<option value="labels_id.txt">Indonesia</option>
|
||||
<option value="labels_it.txt">Italian</option>
|
||||
<option value="labels_ja.txt">Japanese</option>
|
||||
<option value="labels_lv.txt">Latvian</option>
|
||||
<option value="labels_lt.txt">Lithuania</option>
|
||||
<option value="labels_no.txt">Norwegian</option>
|
||||
<option value="labels_pl.txt">Polish</option>
|
||||
<option value="labels_pt.txt">Portugues</option>
|
||||
<option value="labels_ru.txt">Russian</option>
|
||||
<option value="labels_sk.txt">Slovak</option>
|
||||
<option value="labels_sl.txt">Slovenian</option>
|
||||
<option value="labels_es.txt">Spanish</option>
|
||||
<option value="labels_sv.txt">Swedish</option>
|
||||
<option value="labels_th.txt">Thai</option>
|
||||
<option value="labels_uk.txt">Ukrainian</option>
|
||||
</select>
|
||||
<br><br>
|
||||
</body>
|
||||
<footer>
|
||||
<button type="submit" name"firstboot" class="block">I Am Finished!</button>
|
||||
</footer>
|
||||
</form>
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# testing getting images dynamically
|
||||
first_call=$(lynx -nonumbers -dump -listonly "https://commons.wikimedia.org/w/index.php?search=${1//_/+}&title=Special:MediaSearch&go=Go&type=image" | sed '11q;d')
|
||||
|
||||
lynx -dump -nonumbers "$(lynx -dump $first_call \
|
||||
| awk '/CiteThisPage/ {print $2}')" \
|
||||
| grep -A10 'Chicago style' \
|
||||
| grep -A10 -e '^$' \
|
||||
| grep -B10 'CBE' \
|
||||
| grep -B10 -e '^$'
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# testing getting images dynamically
|
||||
first_call=$(lynx -dump -listonly "https://commons.wikimedia.org/w/index.php?search=${1//_/+}&title=Special:MediaSearch&go=Go&type=image")
|
||||
lynx -dump -listonly \
|
||||
$(echo "$first_call" \
|
||||
| sed '11q;d' \
|
||||
| awk '{print $2}' ) \
|
||||
| awk '/thumb/ {print $2}' \
|
||||
| head -1 \
|
||||
| xargs echo -n
|
||||
Executable
BIN
Binary file not shown.
+14
-55
@@ -10,85 +10,44 @@ $theDate = date('Y-m-d');
|
||||
}
|
||||
$chart = "Combo-$theDate.png";
|
||||
$chart2 = "Combo2-$theDate.png";
|
||||
$mysqli = mysqli_connect();
|
||||
$mysqli->select_db('birds');
|
||||
|
||||
if ($mysqli->connect_error) {
|
||||
die('Connect Error (' .
|
||||
$mysqli->connect_errno . ') '.
|
||||
$mysqli->connect_error);
|
||||
}
|
||||
$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
|
||||
|
||||
// SQL query to select data from database
|
||||
$statement1 = $db->prepare("SELECT COUNT(*) FROM detections
|
||||
WHERE Date == \"$theDate\"");
|
||||
$result1 = $statement1->execute();
|
||||
$totalcount = $result1->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$sql1 = "SELECT COUNT(*)
|
||||
FROM detections
|
||||
WHERE DATE = \"$theDate\"";
|
||||
$dayscount = $mysqli->query($sql1);
|
||||
|
||||
$mysqli->close();
|
||||
?>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
|
||||
<style>
|
||||
input {
|
||||
width:auto;
|
||||
}
|
||||
center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 100%;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
button,input {
|
||||
font-size: medium;
|
||||
}
|
||||
table,th,td {
|
||||
background-color: rgb(219, 255, 235);
|
||||
}
|
||||
table {
|
||||
width:30%;
|
||||
}
|
||||
hr {
|
||||
border: 1px solid green;
|
||||
width:80%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<form style="margin-left: -150px;text-align:center;" action="" name="submit" method="POST">
|
||||
<div class="history centered">
|
||||
<form action="" method="POST">
|
||||
<input type="date" name="date" value="<?php echo $theDate;?>">
|
||||
<button type="submit" class="block">Submit Date</button>
|
||||
<button type="submit" name="view" value="Daily Charts">Submit Date</button>
|
||||
</form>
|
||||
<div style="margin-left: -150px;">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Total Detections For The Day</th>
|
||||
<?php
|
||||
while($row=$dayscount->fetch_assoc()){
|
||||
?>
|
||||
<td><?php echo $row['COUNT(*)'];?></td>
|
||||
<?php
|
||||
}?>
|
||||
<td><?php echo $totalcount['COUNT(*)'];?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
if (file_exists('/home/pi/BirdSongs/Extracted/Charts/'.$chart)) {
|
||||
echo "<img src=\"/Charts/$chart?nocache=time()\" style=\"height:auto;width: 100%;padding: 5px;margin-left: auto;margin-right: auto;display: block;\">";
|
||||
echo "<img src=\"/Charts/$chart?nocache=time()\" >";
|
||||
} else {
|
||||
echo "<p style=\"text-align:center;margin-left:-150px;\">No Charts for $theDate</p>";
|
||||
echo "<p>No Charts for $theDate</p>";
|
||||
}
|
||||
echo "<hr>";
|
||||
if (file_exists('/home/pi/BirdSongs/Extracted/Charts/'.$chart2)) {
|
||||
echo "<img src=\"/Charts/$chart2?nocache=time()\" style=\"height:auto;width: 100%;padding: 5px;margin-left: auto;margin-right: auto;display: block;\">";
|
||||
echo "<img src=\"/Charts/$chart2?nocache=time()\">";
|
||||
} else {
|
||||
echo "<p style=\"text-align:center;margin-left:-150px;\">No Charts For $theDate</p>";
|
||||
echo "<p>No Charts For $theDate</p>";
|
||||
}?>
|
||||
</div>
|
||||
</html>
|
||||
|
||||
+47
-106
@@ -1,121 +1,62 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Create two unequal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.first {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.second {
|
||||
width: 10%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.third {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
|
||||
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
width:100%;
|
||||
border: none;
|
||||
background-color: #04AA6D;
|
||||
padding: 20px 20px;
|
||||
color: white;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
select {
|
||||
width:100%
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.column {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php
|
||||
//remove <script></script> and add php start and close tag
|
||||
//comment these two lines when code started working fine
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
|
||||
$filename = 'labels.txt';
|
||||
$filename = 'scripts/labels.txt';
|
||||
$eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
||||
|
||||
?>
|
||||
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<div class="row">
|
||||
<div class="column first">
|
||||
<h2>All Species Labels</h2>
|
||||
<form action="add_to_include.php" method="POST" id="add">
|
||||
<select name="species[]" id="species" multiple size="30">
|
||||
<option selected value="base">Please Select</option>
|
||||
<?php
|
||||
foreach($eachlines as $lines){
|
||||
echo "<option value='".$lines."'>$lines</option>";
|
||||
}?>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<div class="customlabels smaller">
|
||||
<br>
|
||||
</div>
|
||||
<body style="height: 90%;">
|
||||
<p>Warning!<br>If this list contains ANY species, the system will ONLY recognize those species. Keep this list EMPTY unless you are ONLY interested in detecting specific species.</p>
|
||||
<div class="customlabels2 column1">
|
||||
<form action="" method="POST" id="add">
|
||||
<h2>All Species Labels</h2>
|
||||
<select name="species[]" id="species" multiple size="30">
|
||||
<option selected value="base">Please Select</option>
|
||||
<?php
|
||||
foreach($eachlines as $lines){echo
|
||||
"<option value='".$lines."'>$lines</option>";}
|
||||
?>
|
||||
</select>
|
||||
<input type="hidden" name="add" value="add">
|
||||
</form>
|
||||
<div class="customlabels2 smaller">
|
||||
<button type="submit" name="view" value="Included" form="add">>>ADD>></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column second">
|
||||
<button type="submit" form="add" class="block">Add to list</button><br>
|
||||
<button type="submit" form="del" class="block">Remove from list</button>
|
||||
</div>
|
||||
<div class="customlabels2 column4">
|
||||
<table><td>
|
||||
<button type="submit" name="view" value="Included" form="add">>>ADD>></button>
|
||||
<br><br>
|
||||
<button type="submit" name="view" value="Included" form="del">REMOVE</button>
|
||||
</td></table>
|
||||
</div>
|
||||
|
||||
<div class="column third">
|
||||
<h2>Included Species List</h2>
|
||||
<form action="del_from_include.php" method="POST" id="del">
|
||||
<select name="species[]" id="value2" multiple size="30">
|
||||
<option selected value="base">Please Select</option>
|
||||
<?php
|
||||
$filename = '/home/pi/BirdNET-Pi/include_species_list.txt';
|
||||
$eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
||||
foreach($eachlines as $lines){
|
||||
echo "<option value='".$lines."'>$lines</option>";
|
||||
}?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="customlabels2 column3">
|
||||
<form action="" method="POST" id="del">
|
||||
<h2>Custom Species List</h2>
|
||||
<select name="species[]" id="value2" multiple size="30">
|
||||
<option selected value="base">Please Select</option>
|
||||
<?php
|
||||
$filename = '/home/pi/BirdNET-Pi/include_species_list.txt';
|
||||
$eachlines = file($filename, FILE_IGNORE_NEW_LINES);
|
||||
foreach($eachlines as $lines){echo
|
||||
"<option value='".$lines."'>$lines</option>";}
|
||||
?>
|
||||
</select>
|
||||
<input type="hidden" name="del" value="del">
|
||||
</form>
|
||||
<div class="customlabels2 smaller">
|
||||
<button type="submit" name="view" value="Included" form="del">REMOVE</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Create two unequal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.first {
|
||||
width: calc(50% - 70px);
|
||||
}
|
||||
|
||||
.second {
|
||||
width: calc(50% - 30px);
|
||||
}
|
||||
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
width:100%;
|
||||
border: none;
|
||||
background-color: #04AA6D;
|
||||
padding: 20px 20px;
|
||||
color: white;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
@media screen and (max-width: 1000px) {
|
||||
.column {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<div class="row">
|
||||
<div class="column first">
|
||||
<form action="/scripts/filemanager/filemanager.php" target="_top">
|
||||
<button type="submit" class="block">File Manager</button>
|
||||
</form>
|
||||
<form action="/scripts/adminer.php" target="_top">
|
||||
<button type="submit" class="block">Database Maintenance</button>
|
||||
</form>
|
||||
<form action="/scripts/config.php">
|
||||
<button type="submit" class="block">Settings</button>
|
||||
</form>
|
||||
<form action="/scripts/system_controls.php">
|
||||
<button type="submit" class="block">System Controls</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="column second">
|
||||
<form action="http://birdnetpi.local:8888" target="top">
|
||||
<button type="submit" class="block">Web Terminal</button>
|
||||
</form>
|
||||
<form action="/scripts/service_controls.php">
|
||||
<button type="submit" class="block">Manage Services</button>
|
||||
</form>
|
||||
<form action="/scripts/include_list.php">
|
||||
<button type="submit" class="block">Included Species List</button>
|
||||
</form>
|
||||
<form action="/scripts/exclude_list.php">
|
||||
<button type="submit" class="block">Excluded Species List</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install BirdNET script
|
||||
set -x # debugging
|
||||
set -x
|
||||
exec > >(tee -i installation-$(date +%F).txt) 2>&1
|
||||
set -e # exit installation if anything fails
|
||||
my_dir=$(realpath $(dirname $0))
|
||||
trap '${my_dir}/dump_logs.sh && echo -e "\n\nExiting the installation. Goodbye!" && exit 1' SIGINT
|
||||
@@ -20,80 +21,15 @@ fi
|
||||
sudo ./install_services.sh || exit 1
|
||||
source /etc/birdnet/birdnet.conf
|
||||
|
||||
APT_DEPS=(swig ffmpeg wget unzip curl cmake make bc)
|
||||
LIBS_MODULES=(libjpeg-dev zlib1g-dev python3-dev python3-pip python3-venv)
|
||||
|
||||
install_deps() {
|
||||
echo " Checking dependencies"
|
||||
sudo apt update &> /dev/null
|
||||
for i in "${LIBS_MODULES[@]}";do
|
||||
if [ $(apt list --installed 2>/dev/null | grep "$i" | wc -l) -le 0 ];then
|
||||
echo " Installing $i"
|
||||
sudo apt -y install ${i} &> /dev/null
|
||||
else
|
||||
echo " $i is installed!"
|
||||
fi
|
||||
done
|
||||
|
||||
for i in "${APT_DEPS[@]}";do
|
||||
if ! which $i &>/dev/null ;then
|
||||
echo " Installing $i"
|
||||
sudo apt -y install ${i} &> /dev/null
|
||||
else
|
||||
echo " $i is installed!"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
install_birdnet() {
|
||||
cd ~/BirdNET-Pi || exit 1
|
||||
echo "Establishing a python virtual environment"
|
||||
python3 -m venv birdnet
|
||||
source ./birdnet/bin/activate
|
||||
echo "Upgrading pip, wheel, and setuptools"
|
||||
pip3 install --upgrade pip~=21.0.0 wheel setuptools
|
||||
python_version="$(awk -F. '{print $2}' <(ls -l $(which /usr/bin/python3)))"
|
||||
echo "python_version=${python_version}"
|
||||
# TFLite Pre-built binaires from https://github.com/PINTO0309/TensorflowLite-bin
|
||||
# Python 3.7
|
||||
if [[ "$python_version" == 7 ]];then
|
||||
echo "Installing the TFLite bin wheel"
|
||||
pip3 install --upgrade tflite_runtime-2.6.0-cp37-none-linux_aarch64.whl
|
||||
fi
|
||||
|
||||
# Python 3.9
|
||||
if [[ "$python_version" == 9 ]];then
|
||||
echo "Installing the TFLite bin wheel"
|
||||
pip3 install --upgrade tflite_runtime-2.6.0-cp39-none-linux_aarch64.whl
|
||||
fi
|
||||
echo "Making sure everything else is installed"
|
||||
pip3 install -U -r /home/pi/BirdNET-Pi/requirements.txt
|
||||
}
|
||||
|
||||
[ -d ${RECS_DIR} ] || mkdir -p ${RECS_DIR} &> /dev/null
|
||||
|
||||
install_deps
|
||||
if [ ! -d ${VENV} ];then
|
||||
install_birdnet
|
||||
fi
|
||||
|
||||
echo " BirdNet is installed!!
|
||||
|
||||
To start the service manually, issue:
|
||||
'sudo systemctl start birdnet_analysis'
|
||||
To monitor the service logs, issue:
|
||||
'journalctl -fu birdnet_analysis'
|
||||
To stop the service manually, issue:
|
||||
'sudo systemctl stop birdnet_analysis'
|
||||
To stop and disable the service, issue:
|
||||
'sudo systemctl disable --now birdnet_analysis.service'
|
||||
|
||||
Visit
|
||||
the BirdNET-Pi homepage at http://birdnetpi.local"
|
||||
echo
|
||||
case $YN in
|
||||
[Yy] ) sudo systemctl start birdnet_analysis.service \
|
||||
&& journalctl -fu birdnet_analysis;;
|
||||
* ) echo " Thanks for installing BirdNET-Pi!!
|
||||
I hope it was helpful!";;
|
||||
esac
|
||||
install_birdnet
|
||||
exit 0
|
||||
|
||||
+73
-294
@@ -6,240 +6,63 @@ trap 'exit 1' SIGINT SIGHUP
|
||||
|
||||
my_dir=$(realpath $(dirname $0))
|
||||
birdnetpi_dir=$(realpath $(dirname $my_dir))
|
||||
BIRDNET_CONF="$(dirname ${my_dir})/birdnet.conf"
|
||||
birdnet_conf="$(dirname ${my_dir})/birdnet.conf"
|
||||
|
||||
get_RECS_DIR() {
|
||||
read -p "What is the full path to your recordings directory (locally)? " RECS_DIR
|
||||
}
|
||||
|
||||
get_LATITUDE() {
|
||||
read -p "What is the latitude where the recordings were made? " LATITUDE
|
||||
}
|
||||
|
||||
get_LONGITUDE() {
|
||||
read -p "What is the longitude where the recordings were made? " LONGITUDE
|
||||
}
|
||||
|
||||
get_DO_EXTRACTIONS() {
|
||||
while true; do
|
||||
read -n1 -p "Do you want this device to perform the extractions? " DO_EXTRACTIONS
|
||||
echo
|
||||
case $DO_EXTRACTIONS in
|
||||
[Yy] ) break;;
|
||||
[Nn] ) break;;
|
||||
* ) echo "You must answer with Yes or No (y or n)";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
get_DO_RECORDING() {
|
||||
while true; do
|
||||
read -n1 -p "Is this device also doing the recording? " DO_RECORDING
|
||||
echo
|
||||
case $DO_RECORDING in
|
||||
[Yy] ) break;;
|
||||
[Nn] ) break;;
|
||||
* ) echo "You must answer with Yes or No (y or n)";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
get_BIRDNETPI_URL() {
|
||||
while true;do
|
||||
read -n1 -p "Would you like to access the extractions via a web browser?
|
||||
|
||||
*Note: It is recommended, (but not required), that you run the web
|
||||
server on the same host that does the extractions. If the extraction
|
||||
service and web server are on different hosts, the \"By_Species\" and
|
||||
\"Processed\" symbolic links won't work. The \"By-Date\" extractions,
|
||||
however, will work as expected." CADDY_SERVICE
|
||||
echo
|
||||
case $CADDY_SERVICE in
|
||||
[Yy] ) read -p "What URL would you like to publish the extractions to?
|
||||
*Note: Set this to http://localhost if you do not want to make the
|
||||
extractions publically available: " BIRDNETPI_URL
|
||||
get_CADDY_PWD
|
||||
get_ICE_PWD
|
||||
break;;
|
||||
[Nn] ) BIRDNETPI_URL= CADDY_PWD= ICE_PWD=;break;;
|
||||
* ) echo "Please answer Yes or No";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
get_CADDY_PWD() {
|
||||
if [ -z ${CADDY_PWD} ]; then
|
||||
while true; do
|
||||
read -p "Please set a password to protect your data: " CADDY_PWD
|
||||
case $CADDY_PWD in
|
||||
"" ) echo "The password cannot be empty. Please try again.";;
|
||||
* ) break;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
get_ICE_PWD() {
|
||||
if [ ! -z ${CADDY_PWD} ] && [[ ${DO_RECORDING} =~ [Yy] ]];then
|
||||
while true; do
|
||||
read -n1 -p "Would you like to enable the live audio streaming service?" LIVE_STREAM
|
||||
echo
|
||||
case $LIVE_STREAM in
|
||||
[Yy] )
|
||||
read -p "Please set the icecast password. Use only alphanumeric characters." ICE_PWD
|
||||
echo
|
||||
case ${ICE_PWD} in
|
||||
"" ) echo "The password cannot be empty. Please try again.";;
|
||||
*) break;;
|
||||
esac
|
||||
break;;
|
||||
[Nn] ) break;;
|
||||
* ) echo "You must answer Yes or No (y or n).";;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
get_DB_PWDS() {
|
||||
if [ ! -z ${DB_PWD} ];then
|
||||
read -p "Please set a password for your database: " DB_PWD
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
get_PUSHED() {
|
||||
while true; do
|
||||
read -n1 -p "Do you have a free App key to receive mobile notifications via Pushed.co?" YN
|
||||
echo
|
||||
case $YN in
|
||||
[Yy] ) read -p "Enter your Pushed.co App Key: " PUSHED_APP_KEY
|
||||
read -p "Enter your Pushed.co App Key Secret: " PUSHED_APP_SECRET
|
||||
break;;
|
||||
[Nn] ) PUSHED_APP_KEY=
|
||||
PUSHED_APP_SECRET=
|
||||
break;;
|
||||
* ) echo "A simple Yea or Nay will do";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
get_INSTALL_NOMACHINE() {
|
||||
while true; do
|
||||
read -n1 -p "Would you like to also install NoMachine for remote desktop access?" INSTALL_NOMACHINE
|
||||
echo
|
||||
case $INSTALL_NOMACHINE in
|
||||
[Yy] ) break;;
|
||||
[Nn] ) break;;
|
||||
* ) echo "You must answer with Yes or No (y or n)";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
get_CHANNELS() {
|
||||
REC_CARD="$(sudo -u pi aplay -L \
|
||||
| grep dsnoop \
|
||||
| cut -d, -f1 \
|
||||
| grep -ve 'vc4' -e 'Head' -e 'PCH' \
|
||||
| uniq)"
|
||||
|
||||
[ -f $(dirname ${my_dir})/soundcard_params.txt ] || touch $(dirname ${my_dir})/soundcard_params.txt
|
||||
SOUND_PARAMS=$(dirname ${my_dir})/soundcard_params.txt
|
||||
SOUND_CARD="$(sudo -u ${USER} aplay -L \
|
||||
| awk -F, '/^hw:/ {print $1}' \
|
||||
| grep -ve 'vc4' -e 'Head' -e 'PCH' \
|
||||
| uniq)"
|
||||
script -c "arecord -D ${SOUND_CARD} --dump-hw-params" -a "${SOUND_PARAMS}" &> /dev/null
|
||||
CHANNELS=$(awk '/CHANN/ { print $2 }' "${SOUND_PARAMS}" | sed 's/\r$//')
|
||||
[ -z REC_CARD ] && REC_CARD=default
|
||||
[ -z CHANNELS ] && CHANNELS=2
|
||||
echo "REC_CARD variable set to ${REC_CARD}"
|
||||
echo "Number of channels available: ${CHANNELS}"
|
||||
}
|
||||
|
||||
|
||||
configure() {
|
||||
get_RECS_DIR
|
||||
get_LATITUDE
|
||||
get_LONGITUDE
|
||||
get_DB_PWDS
|
||||
get_DO_EXTRACTIONS
|
||||
get_DO_RECORDING
|
||||
get_BIRDNETPI_URL
|
||||
get_PUSHED
|
||||
get_INSTALL_NOMACHINE
|
||||
get_CHANNELS
|
||||
}
|
||||
|
||||
install_birdnet_conf() {
|
||||
install_config() {
|
||||
cat << EOF > $(dirname ${my_dir})/birdnet.conf
|
||||
################################################################################
|
||||
# Configuration settings for BirdNET-Pi #
|
||||
################################################################################
|
||||
|
||||
############ CHANGE THE LATITUDE AND LONGITUDE TO STATIC VALUES ################
|
||||
#--------------------- Required: Latitude, and Longitude ----------------------#
|
||||
|
||||
## The shell substitution below guesses these based on your network. THESE NEED
|
||||
## TO BE CHANGED TO STATIC VALUES
|
||||
## Please only go to 4 decimal places. Example:43.3984
|
||||
|
||||
## LATITUDE and LONGITUDE are self-explanatroy. Find them easily at
|
||||
## maps.google.com.
|
||||
## Example: these coordinates would indicate the Eiffel Tower in Paris, France.
|
||||
## LATITUDE=48.858
|
||||
## LONGITUDE=2.294
|
||||
LATITUDE=$(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',')
|
||||
LONGITUDE=$(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',')
|
||||
|
||||
## These are input as shell substitutions so that this will work out of the box.
|
||||
## It guesses your latitude and longitude based off of your network information.
|
||||
## THESE SHOULD BE CHANGED TO STATIC NUMBERS!!!!
|
||||
LATITUDE=${LATITUDE}
|
||||
LONGITUDE=${LONGITUDE}
|
||||
#--------------------- BirdWeather Station Information -----------------------#
|
||||
#_____________The variable below can be set to have your BirdNET-Pi____________#
|
||||
#__________________also act as a BirdWeather listening station_________________#
|
||||
|
||||
## RECS_DIR is the location birdnet_analysis.service will look for the data-set
|
||||
## 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.
|
||||
|
||||
RECS_DIR=${RECS_DIR}
|
||||
BIRDWEATHER_ID=
|
||||
|
||||
#----------------------- Web Interface User Password ------------------------#
|
||||
#____________________The variable below sets the 'birdnet'_____________________#
|
||||
#___________________user password for the live audio stream,___________________#
|
||||
#_________________web tools, system info, and processed files__________________#
|
||||
#____________________The variable below sets the 'birdnet'_____________________#
|
||||
#___________________user password for the Live Audio Stream,___________________#
|
||||
#_________________Tools, System Links, and the Processed files ________________#
|
||||
|
||||
## CADDY_PWD is the plaintext password (that will be hashed) and used to access
|
||||
## certain parts of the web interface
|
||||
|
||||
CADDY_PWD=${CADDY_PWD}
|
||||
|
||||
#------------------------- MariaDB User Passwords ---------------------------#
|
||||
#_____________The variable below sets the password for the_____________________#
|
||||
#_______________________'birder' user on the MariaDB___________________________#
|
||||
|
||||
## DB_PWD is for the 'birder' user
|
||||
DB_PWD=${DB_PWD}
|
||||
CADDY_PWD=
|
||||
|
||||
#------------------------- Live Audio Stream --------------------------------#
|
||||
#_____________The variable below configures/enables the live___________________#
|
||||
#_____________The variable below configures/enables the live___________________#
|
||||
#_____________________________audio stream.____________________________________#
|
||||
|
||||
|
||||
## ICE_PWD is the password that icecast2 will use to authenticate ffmpeg as a
|
||||
## trusted source for the stream. You will never need to enter this manually
|
||||
## anywhere other than here.
|
||||
## anywhere other than here and it stays on 'localhost.'
|
||||
|
||||
ICE_PWD=${ICE_PWD}
|
||||
ICE_PWD=birdnetpi
|
||||
|
||||
#----------------------- Web-hosting/Caddy File-server -----------------------#
|
||||
#________The four variables below can be set to enable internet access_________#
|
||||
#_______The three variables below can be set to enable internet access_________#
|
||||
#____________to your data,(e.g., extractions, raw data, live___________________#
|
||||
#______________audio stream, BirdNET.selection.txt files)______________________#
|
||||
|
||||
|
||||
## BIRDNETPI_URL is the URL where the extractions, data-set, and live-stream
|
||||
## will be web-hosted. If you do not own a domain, or would just prefer to keep
|
||||
## will be web-hosted. If you do not own a domain, or would just prefer to keep
|
||||
## the BirdNET-Pi on your local network, keep this EMPTY.
|
||||
|
||||
BIRDNETPI_URL=${BIRDNETPI_URL}
|
||||
WEBTERMINAL_URL${WEBTERMINAL_URL}
|
||||
BIRDNETLOG_URL=${BIRDNETLOG_URL}
|
||||
BIRDNETPI_URL=
|
||||
BIRDNETLOG_URL=
|
||||
WEBTERMINAL_URL=
|
||||
|
||||
|
||||
#------------------- Mobile Notifications via Pushed.co ---------------------#
|
||||
@@ -251,97 +74,54 @@ BIRDNETLOG_URL=${BIRDNETLOG_URL}
|
||||
|
||||
## Pushed.co App Key and App Secret
|
||||
|
||||
PUSHED_APP_KEY=${PUSHED_APP_KEY}
|
||||
PUSHED_APP_SECRET=${PUSHED_APP_SECRET}
|
||||
PUSHED_APP_KEY=
|
||||
PUSHED_APP_SECRET=
|
||||
|
||||
################################################################################
|
||||
#-------------------------------- Defaults ----------------------------------#
|
||||
################################################################################
|
||||
|
||||
#------------------------------- NoMachine ----------------------------------#
|
||||
#_____________The variable below can be set include NoMachine__________________#
|
||||
#_________________remote desktop software to be installed._____________________#
|
||||
## RECS_DIR is the location birdnet_analysis.service will look for the data-set
|
||||
## it needs to analyze. Be sure this directory is readable and writable for
|
||||
## the BIRDNET_USER.
|
||||
|
||||
# Keep this EMPTY if you do not want to install NoMachine. #
|
||||
RECS_DIR=/home/pi/BirdSongs
|
||||
|
||||
## INSTALL_NOMACHINE is simply a setting that can be enabled to install
|
||||
## NoMachine alongside the BirdNET-Pi for remote desktop access. This in-
|
||||
## staller assumes personal use. Please reference the LICENSE file included
|
||||
## in this repository for more information.
|
||||
## Set this to Y or y to install NoMachine alongside the BirdNET-Lite
|
||||
## REC_CARD is the sound card you would want the birdnet_recording.service to
|
||||
## use. Leave this as "default" to use PulseAudio (recommended), or use
|
||||
## the output from "aplay -L" to specify an ALSA device.
|
||||
|
||||
INSTALL_NOMACHINE=${INSTALL_NOMACHINE}
|
||||
REC_CARD=default
|
||||
|
||||
#
|
||||
#------------------------------ Extraction Service ---------------------------#
|
||||
|
||||
## DO_EXTRACTIONS is simply a setting for enabling the extraction.service.
|
||||
## Set this to Y or y to enable extractions.
|
||||
|
||||
DO_EXTRACTIONS=${DO_EXTRACTIONS}
|
||||
|
||||
#----------------------------- Recording Service ----------------------------#
|
||||
#____________________The variable below can be set to enable __________________#
|
||||
#________________________the birdnet_recording.service ________________________#
|
||||
|
||||
## DO_RECORDING is simply a setting for enabling the 24/7
|
||||
## birdnet_recording.service.
|
||||
## Set this to Y or y to enable recording.
|
||||
|
||||
DO_RECORDING=${DO_RECORDING}
|
||||
|
||||
## REC_CARD is the sound card you would want the birdnet_recording.service to
|
||||
## use. This setting is irrelevant if you are not planning on doing data
|
||||
## collection via recording on this machine. The command substitution below
|
||||
## looks for a USB microphone's dsnoop alsa device. The dsnoop device lets
|
||||
## birdnet_recording.service and livestream.service share the raw audio stream
|
||||
## from the microphone. If you would like to use a different microphone than
|
||||
## what this produces, or if your microphone does not support creating a
|
||||
## dsnoop device, you can set this explicitly from a list of the available
|
||||
## devices from the output of running 'aplay -L'
|
||||
|
||||
REC_CARD=${REC_CARD}
|
||||
|
||||
## PROCESSED is the directory where the formerly 'Analyzed' files are moved
|
||||
## after extractions have been made from them. This includes both WAVE and
|
||||
## PROCESSED is the directory where the formerly 'Analyzed' files are moved
|
||||
## after extractions have been made from them. This includes both WAVE and
|
||||
## BirdNET.selection.txt files.
|
||||
|
||||
PROCESSED=${PROCESSED}
|
||||
PROCESSED=/home/pi/BirdSongs/Processed
|
||||
|
||||
## EXTRACTED is the directory where the extracted audio selections are moved.
|
||||
|
||||
EXTRACTED=${EXTRACTED}
|
||||
|
||||
## IDFILE is the file that keeps a complete list of every spececies that
|
||||
## BirdNET has identified from your data-set. It is persistent across
|
||||
## data-sets, so would need to be whiped clean through deleting or renaming
|
||||
## it. A backup is automatically made from this variable each time it is
|
||||
## updated (structure: ${IDFILE}.bak), and would also need to be removed
|
||||
## or renamed to start a new file between data-sets. Alternately, you can
|
||||
## change this variable between data-sets to preserve records of disparate
|
||||
## data-sets according to name.
|
||||
|
||||
IDFILE=${IDFILE}
|
||||
EXTRACTED=/home/pi/BirdSongs/Extracted
|
||||
|
||||
## OVERLAP is the value in seconds which BirdNET should use when analyzing
|
||||
## the data. The values must be between 0.0-2.9.
|
||||
|
||||
OVERLAP=${OVERLAP}
|
||||
OVERLAP=0.0
|
||||
|
||||
## CONFIDENCE is the minimum confidence level from 0.0-1.0 BirdNET's analysis
|
||||
## CONFIDENCE is the minimum confidence level from 0.0-1.0 BirdNET's analysis
|
||||
## should reach before creating an entry in the BirdNET.selection.txt file.
|
||||
## Don't set this to 1.0 or you won't have any results.
|
||||
|
||||
CONFIDENCE=${CONFIDENCE}
|
||||
CONFIDENCE=0.7
|
||||
|
||||
## SENSITIVITY is the detection sensitivity from 0.5-1.5.
|
||||
|
||||
SENSITIVITY=${SENSITIVITY}
|
||||
SENSITIVITY=1.25
|
||||
|
||||
## CHANNELS holds the variabel that corresponds to the number of channels the
|
||||
## CHANNELS holds the variable that corresponds to the number of channels the
|
||||
## sound card supports.
|
||||
|
||||
CHANNELS=${CHANNELS}
|
||||
CHANNELS=2
|
||||
|
||||
## FULL_DISK can be set to configure how the system reacts to a full disk
|
||||
## purge = Remove the oldest day's worth of recordings
|
||||
@@ -349,46 +129,45 @@ CHANNELS=${CHANNELS}
|
||||
|
||||
FULL_DISK=purge
|
||||
|
||||
## VENV is the virtual environment where the the BirdNET python build is found,
|
||||
## i.e, VENV is the virtual environment miniforge built for BirdNET.
|
||||
## RECORDING_LENGTH sets the length of the recording that BirdNET-Lite will
|
||||
## analyze.
|
||||
|
||||
VENV=/home/pi/BirdNET-Pi/birdnet
|
||||
|
||||
## RECORDING_LENGTH sets the length of the recording that BirdNET-Lite will analyze.
|
||||
RECORDING_LENGTH=${RECORDING_LENGTH}
|
||||
RECORDING_LENGTH=15
|
||||
|
||||
## EXTRACTION_LENGTH sets the length of the audio extractions that will be made
|
||||
## from each BirdNET-Lite detection.
|
||||
EXTRACTION_LENGTH=${EXTRACTION_LENGTH}
|
||||
## from each BirdNET-Lite detection. An empty value will use the default of 6
|
||||
## seconds.
|
||||
|
||||
## BIRDNET_USER should be the non-root user systemd should use to execute each
|
||||
EXTRACTION_LENGTH=
|
||||
|
||||
## AUDIOFMT set the audio format that sox should use for the extractions.
|
||||
## The default is mp3. Available formats are: 8svx aif aifc aiff aiffc al amb
|
||||
## amr-nb amr-wb anb au avr awb caf cdda cdr cvs cvsd cvu dat dvms f32 f4 f64 f8
|
||||
## fap flac fssd gsm gsrt hcom htk ima ircam la lpc lpc10 lu mat mat4 mat5 maud
|
||||
## mp2 mp3 nist ogg paf prc pvf raw s1 s16 s2 s24 s3 s32 s4 s8 sb sd2 sds sf sl
|
||||
## sln smp snd sndfile sndr sndt sou sox sph sw txw u1 u16 u2 u24 u3 u32 u4 u8
|
||||
## ub ul uw vms voc vorbis vox w64 wav wavpcm wv wve xa xi
|
||||
## Note: Most have not been tested.
|
||||
|
||||
AUDIOFMT=mp3
|
||||
|
||||
## BIRDNET_USER should be the non-root user systemd should use to execute each
|
||||
## service.
|
||||
|
||||
BIRDNET_USER=pi
|
||||
|
||||
## These are just for debugging
|
||||
LAST_RUN=${LAST_RUN}
|
||||
THIS_RUN=${THIS_RUN}
|
||||
LAST_RUN=
|
||||
THIS_RUN=
|
||||
IDFILE=/home/pi/BirdNET-Pi/IdentifiedSoFar.txt
|
||||
EOF
|
||||
}
|
||||
|
||||
# Checks for a birdnet.conf file in the BirdNET-Pi directory for a
|
||||
# non-interactive installation. Otherwise,the installation is interactive.
|
||||
if [ -f ${BIRDNET_CONF} ];then
|
||||
source ${BIRDNET_CONF}
|
||||
chmod g+w ${BIRDNET_CONF}
|
||||
sed -i "s/LATITUDE=.*/LATITUDE=${LATITUDE}/g" ${BIRDNET_CONF}
|
||||
sed -i "s/LONGITUDE=.*/LONGITUDE=${LONGITUDE}/g" ${BIRDNET_CONF}
|
||||
sed -i "s/DB_PWD=.*/DB_PWD=${DB_PWD}/g" ${BIRDNET_CONF}
|
||||
#install_birdnet_conf
|
||||
[ -d /etc/birdnet ] || sudo mkdir /etc/birdnet
|
||||
sudo ln -sf $(dirname ${my_dir})/birdnet.conf /etc/birdnet/birdnet.conf
|
||||
grep -ve '^#' -e '^$' /etc/birdnet/birdnet.conf > ${birdnetpi_dir}/firstrun.ini
|
||||
else
|
||||
configure
|
||||
install_birdnet_conf
|
||||
chmod g+w ${BIRDNET_CONF}
|
||||
[ -d /etc/birdnet ] || sudo mkdir /etc/birdnet
|
||||
sudo ln -sf $(dirname ${my_dir})/birdnet.conf /etc/birdnet/birdnet.conf
|
||||
grep -ve '^#' -e '^$' /etc/birdnet/birdnet.conf > ${birdnetpi_dir}/firstrun.ini
|
||||
# Checks for a birdnet.conf file
|
||||
if ! [ -f ${birdnet_conf} ];then
|
||||
install_config
|
||||
fi
|
||||
chmod g+w ${birdnet_conf}
|
||||
[ -d /etc/birdnet ] || sudo mkdir /etc/birdnet
|
||||
sudo ln -sf $(dirname ${my_dir})/birdnet.conf /etc/birdnet/birdnet.conf
|
||||
grep -ve '^#' -e '^$' /etc/birdnet/birdnet.conf > ${birdnetpi_dir}/firstrun.ini
|
||||
|
||||
+141
-284
@@ -7,60 +7,38 @@ USER=pi
|
||||
HOME=/home/pi
|
||||
my_dir=${HOME}/BirdNET-Pi/scripts
|
||||
tmpfile=$(mktemp)
|
||||
nomachine_url="https://download.nomachine.com/download/7.7/Arm/nomachine_7.7.4_1_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_depends() {
|
||||
curl -1sLf \
|
||||
'https://dl.cloudsmith.io/public/caddy/stable/setup.deb.sh' \
|
||||
| sudo -E bash
|
||||
apt -qqq update && apt -qqy upgrade
|
||||
echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections
|
||||
apt install -qqy caddy ftpd sqlite3 php-sqlite3 alsa-utils \
|
||||
pulseaudio avahi-utils sox libsox-fmt-mp3 php php-fpm php-curl php-xml \
|
||||
php-zip icecast2 swig ffmpeg wget unzip curl cmake make bc libjpeg-dev \
|
||||
zlib1g-dev python3-dev python3-pip python3-venv
|
||||
}
|
||||
|
||||
|
||||
set_hostname() {
|
||||
if [ "$(hostname)" == "raspberrypi" ];then
|
||||
echo "Setting hostname to 'birdnetpi'"
|
||||
hostnamectl set-hostname birdnetpi
|
||||
sed -i 's/raspberrypi/birdnetpi/g' /etc/hosts
|
||||
fi
|
||||
}
|
||||
|
||||
install_lynx() {
|
||||
if ! which lynx &> /dev/null;then
|
||||
apt -y install lynx
|
||||
fi
|
||||
}
|
||||
|
||||
install_ftpd() {
|
||||
if ! [ -f /etc/ftpuseres ];then
|
||||
apt -y install ftpd
|
||||
fi
|
||||
}
|
||||
|
||||
update_system() {
|
||||
apt update && apt -y upgrade
|
||||
update_etc_hosts() {
|
||||
sed -ie s/'$(hostname).local'/"$(hostname).local ${BIRDNETPI_URL//https:\/\/} ${WEBTERMINAL_URL//https:\/\/} ${BIRDNETLOG_URL//https:\/\/}"/g /etc/hosts
|
||||
}
|
||||
|
||||
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"
|
||||
source /etc/os-release
|
||||
if [[ "${VERSION_CODENAME}" == "buster" ]];then
|
||||
USER=${USER} ${my_dir}/createdb_buster.sh
|
||||
elif [[ "${VERSION_CODENAME}" == "bullseye" ]];then
|
||||
USER=${USER} ${my_dir}/createdb_bullseye.sh
|
||||
fi
|
||||
systemctl restart php${php_version}-fpm
|
||||
}
|
||||
|
||||
install_birdnet_analysis() {
|
||||
echo "Installing the birdnet_analysis.service"
|
||||
cat << EOF > /etc/systemd/system/birdnet_analysis.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/birdnet_analysis.service
|
||||
[Unit]
|
||||
Description=BirdNET Analysis
|
||||
After=birdnet_server.service
|
||||
@@ -74,12 +52,12 @@ ExecStart=/usr/local/bin/birdnet_analysis.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/birdnet_analysis.service /usr/lib/systemd/system
|
||||
systemctl enable birdnet_analysis.service
|
||||
}
|
||||
|
||||
install_birdnet_server() {
|
||||
echo "Installing the birdnet_server.service"
|
||||
cat << EOF > /etc/systemd/system/birdnet_server.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/birdnet_server.service
|
||||
[Unit]
|
||||
Description=BirdNET Analysis Server
|
||||
Before=birdnet_analysis.service
|
||||
@@ -92,12 +70,12 @@ ExecStart=/usr/local/bin/server.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/birdnet_server.service /usr/lib/systemd/system
|
||||
systemctl enable birdnet_server.service
|
||||
}
|
||||
|
||||
install_extraction_service() {
|
||||
echo "Installing the extraction.service and extraction.timer"
|
||||
cat << EOF > /etc/systemd/system/extraction.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/extraction.service
|
||||
[Unit]
|
||||
Description=BirdNET BirdSound Extraction
|
||||
[Service]
|
||||
@@ -105,27 +83,16 @@ Restart=on-failure
|
||||
RestartSec=3
|
||||
Type=simple
|
||||
User=${USER}
|
||||
ExecStart=/usr/local/bin/extract_new_birdsounds.sh
|
||||
ExecStart=/usr/bin/env bash -c 'while true;do extract_new_birdsounds.sh;sleep 3;done'
|
||||
[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
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/extraction.service /usr/lib/systemd/system
|
||||
systemctl enable extraction.service
|
||||
}
|
||||
|
||||
install_pushed_notifications() {
|
||||
echo "Installing Pushed.co mobile notifications"
|
||||
cat << EOF > /etc/systemd/system/pushed_notifications.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/pushed_notifications.service
|
||||
[Unit]
|
||||
Description=BirdNET-Pi Pushed.co Notifications
|
||||
[Service]
|
||||
@@ -137,6 +104,7 @@ ExecStart=/usr/local/bin/species_notifier.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/pushed_notifications.service /usr/lib/systemd/system
|
||||
systemctl enable pushed_notifications.service
|
||||
}
|
||||
|
||||
@@ -144,61 +112,23 @@ 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 ${EXTRACTED}/Charts ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/Charts
|
||||
[ -d ${PROCESSED} ] || sudo -u ${USER} mkdir -p ${PROCESSED}
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/* ${EXTRACTED}
|
||||
if [ ! -z ${BIRDNETLOG_URL} ];then
|
||||
BIRDNETLOG_URL="$(echo ${BIRDNETLOG_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
fi
|
||||
if [ ! -z ${WEBTERMINAL_URL} ];then
|
||||
WEBTERMINAL_URL="$(echo ${WEBTERMINAL_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
|
||||
fi
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/model/labels.txt ${my_dir}/
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/model/labels.txt ${my_dir}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts ${EXTRACTED}
|
||||
if [ -z ${BIRDNETPI_URL} ];then
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
else
|
||||
BIRDNETPI_URL="$(echo ${BIRDNETPI_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
fi
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/play.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/spectrogram.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewday.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/history.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/images/favicon.ico ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED}
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html
|
||||
|
||||
echo "Setting Wttr.in URL to "${LATITUDE}", "${LONGITUDE}""
|
||||
sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html
|
||||
chmod -R g+rw $(dirname ${my_dir})
|
||||
chmod -R g+rw ${RECS_DIR}
|
||||
}
|
||||
@@ -212,27 +142,10 @@ generate_BirdDB() {
|
||||
sudo -u ${USER} sed -i '1 i\Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap' $(dirname ${my_dir})/BirdDB.txt
|
||||
fi
|
||||
ln -sf $(dirname ${my_dir})/BirdDB.txt ${my_dir}/BirdDB.txt &&
|
||||
chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt
|
||||
chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt
|
||||
}
|
||||
|
||||
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
|
||||
set_login() {
|
||||
if ! [ -d /etc/lightdm ];then
|
||||
systemctl set-default multi-user.target
|
||||
ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
|
||||
@@ -246,7 +159,7 @@ EOF
|
||||
|
||||
install_recording_service() {
|
||||
echo "Installing birdnet_recording.service"
|
||||
cat << EOF > /etc/systemd/system/birdnet_recording.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/birdnet_recording.service
|
||||
[Unit]
|
||||
Description=BirdNET Recording
|
||||
[Service]
|
||||
@@ -259,39 +172,45 @@ ExecStart=/usr/local/bin/birdnet_recording.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/birdnet_recording.service /usr/lib/systemd/system
|
||||
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=2.4.5 && apt-mark hold caddy
|
||||
systemctl enable --now caddy
|
||||
usermod -aG pi caddy
|
||||
else
|
||||
echo "Caddy is installed"
|
||||
systemctl enable --now caddy
|
||||
usermod -aG pi caddy
|
||||
fi
|
||||
install_custom_recording_service() {
|
||||
echo "Installing custom_recording.service"
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/custom_recording.service
|
||||
[Unit]
|
||||
Description=BirdNET Custom Recording
|
||||
[Service]
|
||||
Environment=XDG_RUNTIME_DIR=/run/user/1000
|
||||
Restart=always
|
||||
Type=simple
|
||||
RestartSec=3
|
||||
User=${USER}
|
||||
ExecStart=/usr/local/bin/custom_recording.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/birdnet_recording.service /usr/lib/systemd/system
|
||||
}
|
||||
|
||||
install_Caddyfile() {
|
||||
echo "Installing the Caddyfile"
|
||||
[ -d /etc/caddy ] || mkdir /etc/caddy
|
||||
if [ -f /etc/caddy/Caddyfile ];then
|
||||
cp /etc/caddy/Caddyfile{,.original}
|
||||
fi
|
||||
php_version="$(awk -F'php' '{print $3}' <(ls -l $(which /etc/alternatives/php)))"
|
||||
if ! [ -z ${CADDY_PWD} ];then
|
||||
HASHWORD=$(caddy hash-password -plaintext ${CADDY_PWD})
|
||||
cat << EOF > /etc/caddy/Caddyfile
|
||||
http://localhost http://$(hostname).local ${BIRDNETPI_URL} {
|
||||
root * ${EXTRACTED}
|
||||
file_server browse
|
||||
handle /By_Date/* {
|
||||
file_server browse
|
||||
}
|
||||
handle /Charts/* {
|
||||
file_server browse
|
||||
}
|
||||
basicauth /Processed* {
|
||||
birdnet ${HASHWORD}
|
||||
}
|
||||
@@ -304,8 +223,14 @@ http://localhost http://$(hostname).local ${BIRDNETPI_URL} {
|
||||
basicauth /phpsysinfo* {
|
||||
birdnet ${HASHWORD}
|
||||
}
|
||||
basicauth /terminal* {
|
||||
birdnet ${HASHWORD}
|
||||
}
|
||||
reverse_proxy /stream localhost:8000
|
||||
php_fastcgi unix//run/php/php${php_version}-fpm.sock
|
||||
php_fastcgi unix//run/php/php7.4-fpm.sock
|
||||
reverse_proxy /log* localhost:8080
|
||||
reverse_proxy /stats* localhost:8501
|
||||
reverse_proxy /terminal* localhost:8888
|
||||
}
|
||||
EOF
|
||||
else
|
||||
@@ -313,51 +238,27 @@ EOF
|
||||
http://localhost http://$(hostname).local ${BIRDNETPI_URL} {
|
||||
root * ${EXTRACTED}
|
||||
file_server browse
|
||||
reverse_proxy /stream localhost:8000
|
||||
php_fastcgi unix//run/php/php${php_version}-fpm.sock
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ ! -z ${WEBTERMINAL_URL} ] && [ ! -z ${HASHWORD} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
${WEBTERMINAL_URL} {
|
||||
basicauth {
|
||||
birdnet ${HASHWORD}
|
||||
handle /By_Date/* {
|
||||
file_server browse
|
||||
}
|
||||
reverse_proxy localhost:8888
|
||||
}
|
||||
EOF
|
||||
elif [ ! -z ${WEBTERMINAL_URL} ] && [ -z ${HASHWORD} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
${WEBTERMINAL_URL} {
|
||||
reverse_proxy localhost:8888
|
||||
handle /Charts/* {
|
||||
file_server browse
|
||||
}
|
||||
reverse_proxy /stream localhost:8000
|
||||
php_fastcgi unix//run/php/php7.4-fpm.sock
|
||||
reverse_proxy /log* localhost:8080
|
||||
reverse_proxy /stats* localhost:8501
|
||||
reverse_proxy /terminal* localhost:8888
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ ! -z ${BIRDNETLOG_URL} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
${BIRDNETLOG_URL} {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
systemctl reload caddy
|
||||
}
|
||||
|
||||
update_etc_hosts() {
|
||||
sed -ie s/'$(hostname).local'/"$(hostname).local ${BIRDNETPI_URL//https:\/\/} ${WEBTERMINAL_URL//https:\/\/} ${BIRDNETLOG_URL//https:\/\/}"/g /etc/hosts
|
||||
systemctl enable caddy
|
||||
usermod -aG pi 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
|
||||
cat << 'EOF' > /home/pi/BirdNET-Pi/templates/avahi-alias@.service
|
||||
[Unit]
|
||||
Description=Publish %I as alias for %H.local via mdns
|
||||
After=network.target network-online.target
|
||||
@@ -370,11 +271,30 @@ ExecStart=/bin/bash -c "/usr/bin/avahi-publish -a -R %I $(hostname -I |cut -d' '
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable avahi-alias@"$(hostname)".local.service
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/avahi-alias@.service /usr/lib/systemd/system
|
||||
systemctl enable avahi-alias@"$(hostname)".local.service
|
||||
}
|
||||
|
||||
install_birdnet_stats_service() {
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/birdnet_stats.service
|
||||
[Unit]
|
||||
Description=BirdNET Stats
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Type=simple
|
||||
User=${USER}
|
||||
ExecStart=/home/pi/BirdNET-Pi/birdnet/bin/streamlit run /home/pi/BirdNET-Pi/scripts/plotly_streamlit.py --server.address localhost --server.baseUrlPath "/stats"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/birdnet_stats.service /usr/lib/systemd/system
|
||||
systemctl enable birdnet_stats.service
|
||||
}
|
||||
|
||||
install_spectrogram_service() {
|
||||
cat << EOF > /etc/systemd/system/spectrogram_viewer.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/spectrogram_viewer.service
|
||||
[Unit]
|
||||
Description=BirdNET-Pi Spectrogram Viewer
|
||||
[Service]
|
||||
@@ -386,12 +306,13 @@ ExecStart=/usr/local/bin/spectrogram.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable spectrogram_viewer.service
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/spectrogram_viewer.service /usr/lib/systemd/system
|
||||
systemctl enable spectrogram_viewer.service
|
||||
}
|
||||
|
||||
install_chart_viewer_service() {
|
||||
echo "Installing the chart_viewer.service"
|
||||
cat << EOF > /etc/systemd/system/chart_viewer.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/chart_viewer.service
|
||||
[Unit]
|
||||
Description=BirdNET-Pi Chart Viewer Service
|
||||
[Service]
|
||||
@@ -403,21 +324,16 @@ ExecStart=/usr/local/bin/daily_plot.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/chart_viewer.service /usr/lib/systemd/system
|
||||
systemctl enable chart_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
|
||||
sudo -u ${USER} ln -sf $(dirname ${my_dir})/templates/bashrc \
|
||||
${HOME}/.bashrc
|
||||
echo "Installing the birdnet_log.service"
|
||||
cat << EOF > /etc/systemd/system/birdnet_log.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/birdnet_log.service
|
||||
[Unit]
|
||||
Description=BirdNET Analysis Log
|
||||
[Service]
|
||||
@@ -426,13 +342,13 @@ RestartSec=3
|
||||
Type=simple
|
||||
User=${USER}
|
||||
Environment=TERM=xterm-256color
|
||||
ExecStart=/usr/local/bin/gotty -p 8080 --title-format "BirdNET-Pi Log" birdnet_log.sh
|
||||
ExecStart=/usr/local/bin/gotty --address localhost -p 8080 -P log --title-format "BirdNET-Pi Log" birdnet_log.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/birdnet_log.service /usr/lib/systemd/system
|
||||
systemctl enable birdnet_log.service
|
||||
echo "Installing the web_terminal.service"
|
||||
cat << EOF > /etc/systemd/system/web_terminal.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/web_terminal.service
|
||||
[Unit]
|
||||
Description=BirdNET-Pi Web Terminal
|
||||
[Service]
|
||||
@@ -441,62 +357,28 @@ RestartSec=3
|
||||
Type=simple
|
||||
User=${USER}
|
||||
Environment=TERM=xterm-256color
|
||||
ExecStart=/usr/local/bin/gotty -w -p 8888 --title-format "BirdNET-Pi Terminal" bash
|
||||
ExecStart=/usr/local/bin/gotty --address localhost -w -p 8888 -P terminal --title-format "BirdNET-Pi Terminal" bash
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/web_terminal.service /usr/lib/systemd/system
|
||||
systemctl enable web_terminal.service
|
||||
}
|
||||
|
||||
install_sox() {
|
||||
if which sox | grep mp3 &> /dev/null;then
|
||||
echo "Sox is installed"
|
||||
else
|
||||
echo "Installing sox"
|
||||
apt -qq update
|
||||
apt install -y sox libsox-fmt-mp3
|
||||
echo "Sox installed"
|
||||
fi
|
||||
}
|
||||
|
||||
install_php() {
|
||||
if ! which php &> /dev/null || ! which php-fpm || ! apt list --installed | grep php-xml;then
|
||||
echo "Installing PHP modules"
|
||||
apt -qq update
|
||||
apt install -qqy php php-fpm php-mysql php-xml php-zip
|
||||
else
|
||||
echo "PHP and PHP-FPM installed"
|
||||
fi
|
||||
echo "Configuring PHP for Caddy"
|
||||
sed -i 's/www-data/caddy/g' /etc/php/*/fpm/pool.d/www.conf
|
||||
systemctl restart php7\*-fpm.service
|
||||
echo "Adding Caddy sudoers rule"
|
||||
cat << EOF > /etc/sudoers.d/010_caddy-nopasswd
|
||||
configure_caddy_php() {
|
||||
echo "Configuring PHP for Caddy"
|
||||
sed -i 's/www-data/caddy/g' /etc/php/*/fpm/pool.d/www.conf
|
||||
systemctl restart php7\*-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
|
||||
chmod 0440 /etc/sudoers.d/010_caddy-nopasswd
|
||||
}
|
||||
|
||||
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 icecast2.service
|
||||
/etc/init.d/icecast2 start
|
||||
else
|
||||
echo "Icecast2 is installed"
|
||||
config_icecast
|
||||
systemctl enable icecast2.service
|
||||
/etc/init.d/icecast2 start
|
||||
fi
|
||||
install_phpsysinfo() {
|
||||
sudo -u ${USER} git clone https://github.com/phpsysinfo/phpsysinfo.git \
|
||||
${HOME}/phpsysinfo
|
||||
}
|
||||
|
||||
config_icecast() {
|
||||
@@ -508,11 +390,11 @@ config_icecast() {
|
||||
for i in "${passwords[@]}";do
|
||||
sed -i "s/<${i}password>.*<\/${i}password>/<${i}password>${ICE_PWD}<\/${i}password>/g" /etc/icecast2/icecast.xml
|
||||
done
|
||||
systemctl enable icecast2.service
|
||||
}
|
||||
|
||||
install_livestream_service() {
|
||||
echo "Installing Live Stream service"
|
||||
cat << EOF > /etc/systemd/system/livestream.service
|
||||
cat << EOF > /home/pi/BirdNET-Pi/templates/livestream.service
|
||||
[Unit]
|
||||
Description=BirdNET-Pi Live Stream
|
||||
After=network-online.target
|
||||
@@ -527,72 +409,47 @@ ExecStart=/usr/local/bin/livestream.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
ln -sf /home/pi/BirdNET-Pi/templates/livestream.service /usr/lib/systemd/system
|
||||
systemctl enable livestream.service
|
||||
}
|
||||
|
||||
install_nomachine() {
|
||||
if [ ! -d /usr/share/NX ] && [ -d /etc/lightdm ];then
|
||||
echo "Installing NoMachine"
|
||||
curl -s -o ${HOME}/nomachine.deb -O "${nomachine_url}"
|
||||
apt install -y ${HOME}/nomachine.deb
|
||||
rm -f ${HOME}/nomachine.deb
|
||||
echo "Enabling VNC"
|
||||
systemctl enable --now vncserver-x11-serviced.service
|
||||
fi
|
||||
}
|
||||
|
||||
install_cleanup_cron() {
|
||||
echo "Installing the cleanup.cron"
|
||||
cat $(dirname ${my_dir})/templates/cleanup.cron >> /etc/crontab
|
||||
}
|
||||
|
||||
install_selected_services() {
|
||||
install_services() {
|
||||
set_hostname
|
||||
update_system
|
||||
update_etc_hosts
|
||||
set_login
|
||||
|
||||
install_depends
|
||||
install_scripts
|
||||
install_Caddyfile
|
||||
install_avahi_aliases
|
||||
install_birdnet_analysis
|
||||
install_birdnet_server
|
||||
|
||||
if [[ "${DO_EXTRACTIONS}" =~ [Yy] ]];then
|
||||
install_extraction_service
|
||||
fi
|
||||
|
||||
if [[ "${DO_RECORDING}" =~ [Yy] ]];then
|
||||
install_alsa
|
||||
install_recording_service
|
||||
fi
|
||||
|
||||
install_php
|
||||
install_caddy
|
||||
install_Caddyfile
|
||||
update_etc_hosts
|
||||
install_avahi_aliases
|
||||
install_gotty_logs
|
||||
install_sox
|
||||
install_mariadb
|
||||
install_spectrogram_service
|
||||
install_chart_viewer_service
|
||||
install_pushed_notifications
|
||||
|
||||
if [ ! -z "${ICE_PWD}" ];then
|
||||
install_icecast
|
||||
install_livestream_service
|
||||
fi
|
||||
|
||||
if [[ "${INSTALL_NOMACHINE}" =~ [Yy] ]];then
|
||||
install_nomachine
|
||||
fi
|
||||
install_birdnet_stats_service
|
||||
install_recording_service
|
||||
install_custom_recording_service # But does not enable
|
||||
install_extraction_service
|
||||
install_pushed_notifications
|
||||
install_spectrogram_service
|
||||
install_chart_viewer_service
|
||||
install_gotty_logs
|
||||
install_phpsysinfo
|
||||
install_livestream_service
|
||||
install_cleanup_cron
|
||||
|
||||
create_necessary_dirs
|
||||
generate_BirdDB
|
||||
install_cleanup_cron
|
||||
install_ftpd
|
||||
install_lynx
|
||||
configure_caddy_php
|
||||
config_icecast
|
||||
${my_dir}/createdb.sh
|
||||
}
|
||||
|
||||
if [ -f ${config_file} ];then
|
||||
source ${config_file}
|
||||
install_selected_services
|
||||
install_services
|
||||
else
|
||||
echo "Unable to find a configuration file. Please make sure that $config_file exists."
|
||||
fi
|
||||
|
||||
+105
-107
@@ -5,133 +5,131 @@ error_reporting(E_ALL);
|
||||
header("refresh: 300;");
|
||||
$myDate = date('Y-m-d');
|
||||
$chart = "Combo-$myDate.png";
|
||||
$mysqli = mysqli_connect();
|
||||
$mysqli->select_db('birds');
|
||||
|
||||
if ($mysqli->connect_error) {
|
||||
die('Connect Error (' .
|
||||
$mysqli->connect_errno . ') '.
|
||||
$mysqli->connect_error);
|
||||
$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
|
||||
if($db == False) {
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
|
||||
// SQL query to select data from database
|
||||
$sql0 = "SELECT COUNT(*) AS 'Total' FROM detections";
|
||||
$totalcount = $mysqli->query($sql0);
|
||||
$statement = $db->prepare('SELECT COUNT(*) FROM detections');
|
||||
if($statement == False) {
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result = $statement->execute();
|
||||
$totalcount = $result->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$sql1 = "SELECT Com_Name, Sci_Name, Date, Time FROM detections
|
||||
ORDER BY Date DESC, Time DESC LIMIT 1";
|
||||
$mostrecent = $mysqli->query($sql1);
|
||||
$statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\', \'localtime\')');
|
||||
if($statement2 == False) {
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result2 = $statement2->execute();
|
||||
$todaycount = $result2->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$sql2 = "SELECT COUNT(*) AS 'Total' FROM detections
|
||||
WHERE Date = CURDATE()";
|
||||
$todayscount = $mysqli->query($sql2);
|
||||
$statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == Date(\'now\', \'localtime\') AND TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')');
|
||||
if($statement3 == False) {
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result3 = $statement3->execute();
|
||||
$hourcount = $result3->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$sql3 = "SELECT COUNT(*) AS 'Total' FROM detections
|
||||
WHERE Date = CURDATE()
|
||||
AND Time >= DATE_SUB(NOW(),INTERVAL 1 HOUR)";
|
||||
$lasthourcount = $mysqli->query($sql3);
|
||||
$statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Date, Time, Confidence, File_Name FROM detections ORDER BY Date DESC, Time DESC LIMIT 1');
|
||||
if($statement4 == False) {
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result4 = $statement4->execute();
|
||||
$mostrecent = $result4->fetchArray(SQLITE3_ASSOC);
|
||||
$comname = preg_replace('/ /', '_', $mostrecent['Com_Name']);
|
||||
$sciname = preg_replace('/ /', '_', $mostrecent['Sci_Name']);
|
||||
$comname = preg_replace('/\'/', '', $comname);
|
||||
$filename = "/By_Date/".$mostrecent['Date']."/".$comname."/".$mostrecent['File_Name'];
|
||||
|
||||
$sql4 = "SELECT Com_Name
|
||||
FROM detections
|
||||
WHERE Date = CURDATE()
|
||||
GROUP BY Com_Name";
|
||||
$specieslist = $mysqli->query($sql4);
|
||||
$speciescount = mysqli_num_rows($specieslist);
|
||||
$statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections WHERE Date == Date(\'now\',\'localtime\')');
|
||||
if($statement5 == False) {
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result5 = $statement5->execute();
|
||||
$speciestally = $result5->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$mysqli->close();
|
||||
$statement6 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections');
|
||||
if($statement6 == False) {
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result6 = $statement6->execute();
|
||||
$totalspeciestally = $result6->fetchArray(SQLITE3_ASSOC);
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Overview</title>
|
||||
<!-- CSS FOR STYLING THE PAGE -->
|
||||
<link rel="stylesheet" href="style.css">
|
||||
|
||||
|
||||
<style>
|
||||
a {
|
||||
text-decoration: none;
|
||||
color:black;
|
||||
}
|
||||
.center {
|
||||
display: block;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
width: 90%;
|
||||
padding: 5px;
|
||||
}
|
||||
.center2 {
|
||||
display: block;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
body::-webkit-scrollbar {
|
||||
display:none
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<h2>Overview</h2>
|
||||
<div class="row">
|
||||
<div class="column2">
|
||||
<?php // LOOP TILL END OF DATA
|
||||
while($rows=$mostrecent ->fetch_assoc())
|
||||
{
|
||||
$dbname = preg_replace('/ /', '_', $rows['Com_Name']);
|
||||
$dbname = preg_replace('/\'/', '', $dbname);
|
||||
$dbsciname = preg_replace('/ /', '_', $rows['Sci_Name']);
|
||||
?>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Most Recent Detection</th>
|
||||
<td><a href="/By_Common_Name/<?php echo $dbname;?>"><?php echo $rows['Com_Name'];?></a></td>
|
||||
<td><a href="/By_Date/<?php echo $rows['Date'];?>"/><?php echo $rows['Date'];?></a></td>
|
||||
<td><?php echo $rows['Time'];?></td>
|
||||
<td><a href="https://wikipedia.org/wiki/<?php echo $dbsciname;?>" target="top"/>More Info</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Total</th>
|
||||
<th>Today</th>
|
||||
<th>Last Hour</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Number of Detections</th>
|
||||
<td><?php while ($row = $totalcount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
<td><?php while ($row = $todayscount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
<td><?php while ($row = $lasthourcount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="column">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Species Detected Today</th>
|
||||
<td><?php echo $speciescount;?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overview">
|
||||
<div class="overview-stats">
|
||||
<div class="left-column">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Total</th>
|
||||
<td><?php echo $totalcount['COUNT(*)'];?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Today</th>
|
||||
<form action="" method="POST">
|
||||
<td><input type="hidden" name="view" value="Recordings"><button type="submit" name="date" value="<?php echo date('Y-m-d');?>"><?php echo $todaycount['COUNT(*)'];?></button></td>
|
||||
</form>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Last Hour</th>
|
||||
<td><?php echo $hourcount['COUNT(*)'];?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Species Detected Today</th>
|
||||
<form action="" method="POST">
|
||||
<td><button type="submit" name="view" value="Species Stats"><?php echo $speciestally['COUNT(DISTINCT(Com_Name))'];?></button></td>
|
||||
</form>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Total Number of Species</th>
|
||||
<form action="" method="POST">
|
||||
<td><button type="submit" name="view" value="Species Stats"><?php echo $totalspeciestally['COUNT(DISTINCT(Com_Name))'];?></button></td>
|
||||
</form>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="right-column">
|
||||
<div class="chart">
|
||||
<?php
|
||||
if (file_exists('/home/pi/BirdSongs/Extracted/Charts/'.$chart)) {
|
||||
echo "<img src=\"/Charts/$chart?nocache=time()\" style=\"width: 100%;padding: 5px;margin-left: auto;margin-right: auto;display: block;\">";
|
||||
echo "<img src=\"/Charts/$chart?nocache=time()\">";
|
||||
} else {
|
||||
echo "<p style=\"text-align:center;margin-left:-150px;\">No Detections For Today</p>";
|
||||
echo "<p>No Detections For Today</p>";
|
||||
}
|
||||
?>
|
||||
<h2>Currently Analyzing</h2>
|
||||
<img src='/spectrogram.png?nocache=<?php echo time();?>' style="width: 100%;padding: 5px;">
|
||||
</html>
|
||||
</div>
|
||||
<table>
|
||||
<h3>Most Recent Detection: <span style="font-weight: normal;"><?php echo $mostrecent['Date']." ".$mostrecent['Time'];?></span></h3>
|
||||
<tr>
|
||||
<td>
|
||||
<form action="" method="POST">
|
||||
<input type="hidden" name="view" value="Species Stats">
|
||||
<button type="submit" name="species" value="<?php echo $mostrecent['Com_Name'];?>"><?php echo $mostrecent['Com_Name'];?>: </button>
|
||||
<a href="https://wikipedia.org/wiki/<?php echo $sciname;?>" target="_blank"/><i><?php echo $mostrecent['Sci_Name'];?></i></a>
|
||||
<br>Confidence: <?php echo $mostrecent['Confidence'];?><br>
|
||||
<video controls poster="<?php echo $filename.".png";?>" preload="none" title="<?php echo $filename;?>"><source src="<?php echo $filename;?>"></video></td>
|
||||
</form>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Currently Analyzing</h3>
|
||||
<img src='/spectrogram.png?nocache=<?php echo time();?>' >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
|
||||
if($db == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
|
||||
#By Date
|
||||
if(isset($_POST['bydate'])){
|
||||
$statement = $db->prepare('SELECT DISTINCT(Date) FROM detections GROUP BY Date');
|
||||
if($statement == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result = $statement->execute();
|
||||
$view = "bydate";
|
||||
|
||||
#Specific Date
|
||||
} elseif(isset($_POST['date'])) {
|
||||
$date = $_POST['date'];
|
||||
session_start();
|
||||
$_SESSION['date'] = $date;
|
||||
$statement = $db->prepare("SELECT DISTINCT(Com_Name) FROM detections WHERE Date == \"$date\" ORDER BY Com_Name");
|
||||
if($statement == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result = $statement->execute();
|
||||
$view = "date";
|
||||
|
||||
#By Species
|
||||
} elseif(isset($_POST['byspecies'])) {
|
||||
$statement = $db->prepare('SELECT DISTINCT(Com_Name) FROM detections ORDER BY Com_Name');
|
||||
session_start();
|
||||
if($statement == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result = $statement->execute();
|
||||
$view = "byspecies";
|
||||
|
||||
#Specific Species
|
||||
} elseif(isset($_POST['species'])) {
|
||||
$species = $_POST['species'];
|
||||
session_start();
|
||||
$_SESSION['species'] = $species;
|
||||
$statement = $db->prepare("SELECT * FROM detections WHERE Com_Name == \"$species\" ORDER BY Com_Name");
|
||||
$statement3 = $db->prepare("SELECT Date, Time, Sci_Name, MAX(Confidence), File_Name FROM detections WHERE Com_Name == \"$species\" ORDER BY Com_Name");
|
||||
if($statement == False || $statement3 == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result = $statement->execute();
|
||||
$result3 = $statement3->execute();
|
||||
$view = "species";
|
||||
} else {
|
||||
session_start();
|
||||
session_unset();
|
||||
$view = "choose";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<?php
|
||||
#If no specific species
|
||||
if(!isset($_POST['species'])){
|
||||
?>
|
||||
<div class="play">
|
||||
<table>
|
||||
<tr>
|
||||
<form action="" method="POST">
|
||||
<input type="hidden" name="view" value="Recordings">
|
||||
<?php
|
||||
#By Date
|
||||
if($view == "bydate") {
|
||||
while($results=$result->fetchArray(SQLITE3_ASSOC)){
|
||||
$date = $results['Date'];
|
||||
echo "<td>
|
||||
<button action=\"submit\" name=\"date\" value=\"$date\">$date</button></td></tr>";}
|
||||
|
||||
#By Species
|
||||
} elseif($view == "byspecies") {
|
||||
while($results=$result->fetchArray(SQLITE3_ASSOC)){
|
||||
$name = $results['Com_Name'];
|
||||
echo "<td>
|
||||
<button action=\"submit\" name=\"species\" value=\"$name\">$name</button></td></tr>";}
|
||||
|
||||
#Specific Date
|
||||
} elseif($view == "date") {
|
||||
while($results=$result->fetchArray(SQLITE3_ASSOC)){
|
||||
$name = $results['Com_Name'];
|
||||
echo "<td>
|
||||
<button action=\"submit\" name=\"species\" value=\"$name\">$name</button></td></tr>";}
|
||||
|
||||
#Choose
|
||||
} else {
|
||||
echo "<td>
|
||||
<button action=\"submit\" name=\"byspecies\" value=\"byspecies\">By Species</button></td></tr>
|
||||
<tr><td><button action=\"submit\" name=\"bydate\" value=\"bydate\">By Date</button></td>";
|
||||
}
|
||||
|
||||
echo "</form>
|
||||
</tr>
|
||||
</table>";
|
||||
}
|
||||
|
||||
#Specific Species
|
||||
if(isset($_POST['species'])){
|
||||
$name = $_POST['species'];
|
||||
if(isset($_SESSION['date'])) {
|
||||
$date = $_SESSION['date'];
|
||||
$statement2 = $db->prepare("SELECT * FROM detections where Com_Name == \"$name\" AND Date == \"$date\" ORDER BY Time DESC");
|
||||
} else {
|
||||
$statement2 = $db->prepare("SELECT * FROM detections where Com_Name == \"$name\" ORDER BY Date DESC, Time DESC");}
|
||||
if($statement2 == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result2 = $statement2->execute();
|
||||
echo "<table>
|
||||
<tr>
|
||||
<th>$name</th>
|
||||
</tr>";
|
||||
while($results=$result2->fetchArray(SQLITE3_ASSOC))
|
||||
{
|
||||
$comname = preg_replace('/ /', '_', $results['Com_Name']);
|
||||
$comname = preg_replace('/\'/', '', $comname);
|
||||
$date = $results['Date'];
|
||||
$filename = "/By_Date/".$date."/".$comname."/".$results['File_Name'];
|
||||
$sciname = preg_replace('/ /', '_', $results['Sci_Name']);
|
||||
$sci_name = $results['Sci_Name'];
|
||||
$time = $results['Time'];
|
||||
$confidence = $results['Confidence'];
|
||||
echo "<tr>
|
||||
<td>$date $time<br>$confidence<br>
|
||||
<video controls poster=\"$filename.png\" preload=\"none\" title=\"$filename\"><source src=\"$filename\"></video></td>
|
||||
</tr>";
|
||||
|
||||
}echo "</table>";}?>
|
||||
</div>
|
||||
</html>
|
||||
Executable
+184
@@ -0,0 +1,184 @@
|
||||
#!/home/pi/BirdNET-Pi/birdnet/bin/python3
|
||||
import streamlit as st
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import plotly.graph_objects as go
|
||||
from plotly.subplots import make_subplots
|
||||
from datetime import timedelta, datetime
|
||||
from pathlib import Path
|
||||
import sqlite3
|
||||
from sqlite3 import Connection
|
||||
|
||||
URI_SQLITE_DB = "/home/pi/BirdNET-Pi/scripts/birds.db"
|
||||
|
||||
st.set_page_config(layout='wide')
|
||||
|
||||
# Remove whitespace from the top of the page and sidebar
|
||||
st.markdown("""
|
||||
<style>
|
||||
.css-18e3th9 {
|
||||
padding-top: 2.5rem;
|
||||
padding-bottom: 10rem;
|
||||
padding-left: 5rem;
|
||||
padding-right: 5rem;
|
||||
}
|
||||
.css-1d391kg {
|
||||
padding-top: 3.5rem;
|
||||
padding-right: 1rem;
|
||||
padding-bottom: 3.5rem;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
col1,col2,col3 = st.columns([20,20,20])
|
||||
|
||||
col1.title('BirdNET-Pi', anchor=None)
|
||||
col2.image('/home/pi/BirdNET-Pi/homepage/images/bird.png')
|
||||
col3.text('')
|
||||
|
||||
|
||||
@st.cache(hash_funcs={Connection: id})
|
||||
def get_connection(path:str):
|
||||
return sqlite3.connect(path,check_same_thread=False)
|
||||
|
||||
|
||||
|
||||
|
||||
# def load_data():
|
||||
# df1 = pd.read_csv('/home/pi/BirdNET-Pi/BirdDB.txt', sep=';')
|
||||
# return df1
|
||||
|
||||
def get_data(conn: Connection):
|
||||
df1=pd.read_sql("SELECT * FROM detections", con=conn)
|
||||
return df1
|
||||
|
||||
conn = get_connection(URI_SQLITE_DB)
|
||||
# Read in the cereal data
|
||||
# df = load_data()
|
||||
df=get_data(conn)
|
||||
df2=df.copy()
|
||||
df2['DateTime']=pd.to_datetime(df2['Date'] + " " + df2['Time'])
|
||||
df2=df2.set_index('DateTime')
|
||||
|
||||
|
||||
|
||||
# Filter on date range
|
||||
# Date as calendars
|
||||
# Start_Date = pd.to_datetime(st.sidebar.date_input('Which date do you want to start?', value = df2.index.min()))
|
||||
# End_Date = pd.to_datetime(st.sidebar.date_input('Which date do you want to end?', value = df2.index.max()))
|
||||
|
||||
# Date as slider
|
||||
Start_Date = pd.to_datetime(df2.index.min()).date()
|
||||
End_Date = pd.to_datetime(df2.index.max()).date()
|
||||
Date_Slider = st.slider('Date Range',
|
||||
min_value = Start_Date-timedelta(days=1),
|
||||
max_value = End_Date,
|
||||
value=(Start_Date,
|
||||
End_Date)
|
||||
)
|
||||
|
||||
|
||||
|
||||
filt = (df2.index >= pd.Timestamp(Date_Slider[0])) & (df2.index <= pd.Timestamp(Date_Slider[1]+timedelta(days=1)))
|
||||
df2 = df2[filt]
|
||||
|
||||
#Create species count for selected date range
|
||||
|
||||
Specie_Count=df2['Com_Name'].value_counts()
|
||||
|
||||
#Create species treemap
|
||||
|
||||
# Create Hourly Crosstab
|
||||
hourly=pd.crosstab(df2['Com_Name'],df2.index.hour, dropna=False)
|
||||
|
||||
# Filter on species
|
||||
species = list(hourly.index)
|
||||
|
||||
cols1,cols2= st.columns((1,1))
|
||||
top_N = cols1.slider(
|
||||
'Select Number of Birds to Show',
|
||||
min_value = 1,
|
||||
value=min(10,len(Specie_Count))
|
||||
)
|
||||
|
||||
top_N_species = (df2['Com_Name'].value_counts()[:top_N])
|
||||
|
||||
|
||||
specie = cols2.selectbox('Which bird would you like to explore for the dates '+str(Date_Slider[0])+' to '+str(Date_Slider[1])+'?', species,
|
||||
index=species.index(list(top_N_species.index)[0]))
|
||||
|
||||
|
||||
font_size=15
|
||||
|
||||
|
||||
#specie filter
|
||||
filt=df2['Com_Name']==specie
|
||||
|
||||
df_counts=df2[filt].resample('D').count()
|
||||
|
||||
fig = make_subplots(
|
||||
rows=3, cols =2,
|
||||
specs= [[{"type":"xy","rowspan":3}, {"type":"polar","rowspan":2}], [{"rowspan":1}, {"rowspan":1} ], [None, {"type":"xy","rowspan":1}]],
|
||||
subplot_titles=('<b>Top '+ str(top_N) + ' Species in Date Range '+str(Date_Slider[0])+' to '+str(Date_Slider[1])+'</b>',
|
||||
'Total Detect:'+str('{:,}'.format(sum(df_counts.Time)))+
|
||||
' Confidence Max:'+str('{:.2f}%'.format(max(df2[df2['Com_Name']==specie]['Confidence'])*100))+
|
||||
' '+' Median:'+str('{:.2f}%'.format(np.median(df2[df2['Com_Name']==specie]['Confidence'])*100))
|
||||
)
|
||||
)
|
||||
fig.layout.annotations[1].update(x=0.7,y=0.25, font_size=15)
|
||||
|
||||
#Plot seen species for selected date range and number of species
|
||||
fig.add_trace(go.Bar(y=top_N_species.index, x=top_N_species, orientation='h'), row=1,col=1)
|
||||
|
||||
fig.update_layout(
|
||||
margin=dict(l=0, r=0, t=50, b=0),
|
||||
yaxis={'categoryorder':'total ascending'})
|
||||
# Set 360 degrees, 24 hours for polar plot
|
||||
theta = np.linspace(0.0, 360, 24, endpoint=False)
|
||||
|
||||
d=pd.DataFrame(np.zeros((23,1))).squeeze()
|
||||
detections = hourly.loc[specie]
|
||||
detections=(d+detections).fillna(0)
|
||||
fig.add_trace(go.Barpolar(r = detections, theta=theta), row=1, col=2)
|
||||
|
||||
fig.update_layout(
|
||||
autosize=False,
|
||||
width = 1000,
|
||||
height = 500,
|
||||
showlegend=False,
|
||||
polar = dict(
|
||||
radialaxis = dict(
|
||||
tickfont_size = font_size,
|
||||
showticklabels = True,
|
||||
hoverformat = "#%{theta}: <br>Popularity: %{percent} </br> %{r}"
|
||||
),
|
||||
angularaxis = dict(
|
||||
tickfont_size= font_size,
|
||||
rotation = -90,
|
||||
direction = 'clockwise',
|
||||
tickmode='array',
|
||||
tickvals=[0,15,35,45,60,75,90,105,120,135,150,165,180,195,210,225,240,255,270,285,300,315,330,345],
|
||||
ticktext=['12am','1am','2am','3am','4am','5am', '6am','7am','8am','9am','10am','11am','12pm','1pm','2pm','3pm','4pm','5pm', '6pm','7pm','8pm','9pm','10pm','11pm'],
|
||||
hoverformat = "#%{theta}: <br>Popularity: %{percent} </br> %{r}"
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
daily=pd.crosstab(df2['Com_Name'],df2.index.date, dropna=False)
|
||||
|
||||
fig.add_trace(go.Bar(x=daily.columns, y=daily.loc[specie]), row=3, col=2)
|
||||
|
||||
# container=st.container()
|
||||
# config={'displayModelBar': False}
|
||||
st.plotly_chart(fig, use_container_width=True) #, config=config)
|
||||
|
||||
# cols3,cols4=st.columns((1,1))
|
||||
#
|
||||
# extract_date=Date_Slider
|
||||
#
|
||||
# audio_file = open('/home/pi/BirdSongs/Extracted/By_Date/2022-03-22/Yellow-streaked_Greenbul/Yellow-streaked_Greenbul-77-2022-03-22-birdnet-15:04:28.mp3', 'rb')
|
||||
# audio_bytes = audio_file.read()
|
||||
# cols4.audio(audio_bytes, format='audio/mp3')
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Rebuild DB from BirdDB.txt
|
||||
source /etc/birdnet/birdnet.conf
|
||||
BIRDNET_DIR=/home/pi/BirdNET-Pi
|
||||
sudo ${BIRDNET_DIR}/scripts/createdb_bullseye.sh
|
||||
sudo mysql birds -e "
|
||||
LOAD DATA LOCAL INFILE '/home/pi/BirdNET-Pi/BirdDB.txt'
|
||||
INTO TABLE detections
|
||||
FIELDS TERMINATED BY ';'"
|
||||
@@ -13,7 +13,6 @@ spectrogram_viewer.service
|
||||
pushed_notifications.service
|
||||
livestream.service
|
||||
icecast2.service
|
||||
extraction.timer
|
||||
extraction.service
|
||||
chart_viewer.service
|
||||
birdnet_recording.service
|
||||
@@ -24,6 +23,6 @@ sudo systemctl restart "${i}"
|
||||
done
|
||||
until grep 5050 <(netstat -tulpn 2>&1);do
|
||||
sudo systemctl restart birdnet_server.service
|
||||
sleep 30
|
||||
sleep 45
|
||||
done
|
||||
sudo systemctl restart birdnet_analysis.service
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
# Writes variables to config file
|
||||
set -x
|
||||
birdnetpi_dir=/home/pi/BirdNET-Pi
|
||||
birdnet_conf=${birdnetpi_dir}/birdnet.conf
|
||||
|
||||
if ! [ -z ${new_lat} ];then
|
||||
sed -i s/'^LATITUDE=.*'/"LATITUDE=${new_lat}"/g ${birdnet_conf}
|
||||
fi
|
||||
|
||||
if ! [ -z ${new_lon} ];then
|
||||
sed -i s/'^LONGITUDE=.*'/"LONGITUDE=${new_lon}"/g ${birdnet_conf}
|
||||
fi
|
||||
|
||||
if ! [ -z ${caddy_pwd} ];then
|
||||
sed -i s/'^CADDY_PWD=.*'/"CADDY_PWD=${caddy_pwd}"/g ${birdnet_conf}
|
||||
hash_pwd=$(caddy hash-password -plaintext ${caddy_pwd})
|
||||
sudo sed -i s/'birdnet\ .*'/"birdnet ${hash_pwd}"/g /etc/caddy/Caddyfile
|
||||
sudo systemctl reload caddy
|
||||
fi
|
||||
|
||||
if ! [ -z ${db_pwd} ];then
|
||||
sed -i s/'^DB_PWD=.*'/"DB_PWD=${db_pwd}"/g ${birdnet_conf}
|
||||
${birdnetpi_dir}/scripts/update_db_pwd_bullseye.sh
|
||||
fi
|
||||
|
||||
if ! [ -z ${birdweather_id} ];then
|
||||
sed -i s/'^BIRDWEATHER_ID=.*'/"BIRDWEATHER_ID=${birdweather_id}"/g ${birdnet_conf}
|
||||
fi
|
||||
|
||||
if ! [ -z ${birdnetpi_url} ];then
|
||||
sed -i s/'^BIRDNETPI_URL=.*'/"BIRDNETPI_URL=${birdnetpi_url/\/\//\\\/\\\/}"/g ${birdnet_conf}
|
||||
sed -i s/'^WEBTERMINAL_URL=.*'/"WEBTERMINAL_URL=${extractionlog_url/\/\//\\\/\\\/}"/g ${birdnet_conf}
|
||||
sed -i s/'^BIRDNETLOG_URL=.*'/"BIRDNETLOG_URL=${birdnetlog_url/\/\//\\\/\\\/}"/g ${birdnet_conf}
|
||||
fi
|
||||
|
||||
if ! [ -z ${new_sensitivity} ];then
|
||||
sed -i s/'^SENSITIVITY=.*'/"SENSITIVITY=${new_sensitivity}"/g ${birdnet_conf}
|
||||
fi
|
||||
|
||||
if ! [ -z ${new_confidence} ];then
|
||||
sed -i s/'^CONFIDENCE=.*'/"CONFIDENCE=${new_confidence}"/g ${birdnet_conf}
|
||||
fi
|
||||
+68
-75
@@ -18,10 +18,8 @@ import math
|
||||
import time
|
||||
from decimal import Decimal
|
||||
import json
|
||||
###############################################################################
|
||||
import requests
|
||||
import mysql.connector
|
||||
###############################################################################
|
||||
import sqlite3
|
||||
import datetime
|
||||
from time import sleep
|
||||
import pytz
|
||||
@@ -48,7 +46,7 @@ except:
|
||||
# Open most recent Configuration and grab DB_PWD as a python variable
|
||||
with open('/home/pi/BirdNET-Pi/thisrun.txt', 'r') as f:
|
||||
this_run = f.readlines()
|
||||
db_pwd = str(str(str([i for i in this_run if i.startswith('DB_PWD')]).split('=')[1]).split('\\')[0])
|
||||
audiofmt = "." + str(str(str([i for i in this_run if i.startswith('AUDIOFMT')]).split('=')[1]).split('\\')[0])
|
||||
|
||||
|
||||
def loadModel():
|
||||
@@ -304,7 +302,7 @@ def handle_client(conn, addr):
|
||||
#print('Time:', date_time_obj.time())
|
||||
print('Date-time:', date_time_obj)
|
||||
now = date_time_obj
|
||||
current_date = now.strftime("%Y/%m/%d")
|
||||
current_date = now.strftime("%Y-%m-%d")
|
||||
current_time = now.strftime("%H:%M:%S")
|
||||
current_iso8601 = now.astimezone(get_localzone()).isoformat()
|
||||
|
||||
@@ -331,88 +329,83 @@ def handle_client(conn, addr):
|
||||
myReturn += str(i) + '-' + str(detections[i][0]) + '\n'
|
||||
|
||||
|
||||
|
||||
|
||||
with open('/home/pi/BirdNET-Pi/BirdDB.txt', 'a') as rfile:
|
||||
for d in detections:
|
||||
for entry in detections[d]:
|
||||
if entry[1] >= min_conf and ((entry[0] in INCLUDE_LIST or len(INCLUDE_LIST) == 0) and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0) ):
|
||||
rfile.write(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' \
|
||||
+ str(entry[1]) +";" + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' \
|
||||
+ str(sensitivity) +';' + str(args.overlap) + '\n')
|
||||
|
||||
def insert_variables_into_table(Date, Time, Sci_Name, Com_Name, Confidence, Lat, Lon, Cutoff, Week, Sens, Overlap):
|
||||
try:
|
||||
connection = mysql.connector.connect(host='localhost',
|
||||
database='birds',
|
||||
user='birder',
|
||||
password=db_pwd)
|
||||
cursor = connection.cursor()
|
||||
mySql_insert_query = """INSERT INTO detections (Date, Time, Sci_Name, Com_Name, Confidence, Lat, Lon, Cutoff, Week, Sens, Overlap)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """
|
||||
+ str(args.sensitivity) +';' + str(args.overlap) + '\n')
|
||||
|
||||
record = (Date, Time, Sci_Name, Com_Name, Confidence, Lat, Lon, Cutoff, Week, Sens, Overlap)
|
||||
|
||||
cursor.execute(mySql_insert_query, record)
|
||||
connection.commit()
|
||||
print("Record inserted successfully into detections table")
|
||||
|
||||
|
||||
except mysql.connector.Error as error:
|
||||
print("Failed to insert record into detections table {}".format(error))
|
||||
|
||||
finally:
|
||||
if connection.is_connected():
|
||||
connection.close()
|
||||
print("MySQL connection is closed")
|
||||
|
||||
Date = str(current_date)
|
||||
Time = str(current_time)
|
||||
species = entry[0]
|
||||
sci_name,com_name = species.split('_')
|
||||
insert_variables_into_table(str(current_date), str(current_time), sci_name, com_name, \
|
||||
str(entry[1]), str(args.lat), str(args.lon), str(min_conf), str(week), \
|
||||
str(args.sensitivity), str(args.overlap))
|
||||
Sci_Name,Com_Name = species.split('_')
|
||||
score = entry[1]
|
||||
Confidence = str(round(score*100))
|
||||
Lat = str(args.lat)
|
||||
Lon = str(args.lon)
|
||||
Cutoff = str(args.min_conf)
|
||||
Week = str(args.week)
|
||||
Sens = str(args.sensitivity)
|
||||
Overlap = str(args.overlap)
|
||||
Com_Name = Com_Name.replace("'", "")
|
||||
File_Name = Com_Name.replace(" ", "_") + '-' + Confidence + '-' + \
|
||||
Date.replace("/", "-") + '-birdnet-' + Time + audiofmt
|
||||
|
||||
print(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) +";" + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' + str(args.sensitivity) +';' + str(args.overlap) + '\n')
|
||||
#Connect to SQLite Database
|
||||
try:
|
||||
con = sqlite3.connect('/home/pi/BirdNET-Pi/scripts/birds.db')
|
||||
cur = con.cursor()
|
||||
cur.execute("INSERT INTO detections VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (Date, Time, Sci_Name, Com_Name, str(score), Lat, Lon, Cutoff, Week, Sens, Overlap, File_Name))
|
||||
|
||||
con.commit()
|
||||
con.close()
|
||||
except:
|
||||
print("Database busy")
|
||||
time.sleep(2)
|
||||
print(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) + ';' + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';' + str(args.sensitivity) +';' + str(args.overlap) + Com_Name.replace(" ", "_") + '-' + str(score) + '-' + str(current_date) + '-birdnet-' + str(current_time) + audiofmt + '\n')
|
||||
|
||||
if birdweather_id != "99999":
|
||||
try:
|
||||
|
||||
if soundscape_uploaded is False:
|
||||
# POST soundscape to server
|
||||
soundscape_url = "https://app.birdweather.com/api/v1/stations/" + birdweather_id + "/soundscapes" + "?timestamp=" + current_iso8601
|
||||
|
||||
with open(args.i, 'rb') as f:
|
||||
wav_data = f.read()
|
||||
response = requests.post(url=soundscape_url, data=wav_data, headers={'Content-Type': 'application/octet-stream'})
|
||||
print("Soundscape POST Response Status - ", response.status_code)
|
||||
sdata = response.json()
|
||||
soundscape_id = sdata['soundscape']['id']
|
||||
soundscape_uploaded = True
|
||||
|
||||
# POST detection to server
|
||||
detection_url = "https://app.birdweather.com/api/v1/stations/" + birdweather_id + "/detections"
|
||||
start_time = d.split(';')[0]
|
||||
end_time = d.split(';')[1]
|
||||
post_begin = "{ "
|
||||
now_p_start = now + datetime.timedelta(seconds=float(start_time))
|
||||
current_iso8601 = now_p_start.astimezone(get_localzone()).isoformat()
|
||||
post_timestamp = "\"timestamp\": \"" + current_iso8601 + "\","
|
||||
post_lat = "\"lat\": " + str(args.lat) + ","
|
||||
post_lon = "\"lon\": " + str(args.lon) + ","
|
||||
post_soundscape_id = "\"soundscapeId\": " + str(soundscape_id) + ","
|
||||
post_soundscape_start_time = "\"soundscapeStartTime\": " + start_time + ","
|
||||
post_soundscape_end_time = "\"soundscapeEndTime\": " + end_time + ","
|
||||
post_commonName = "\"commonName\": \"" + entry[0].split('_')[1] + "\","
|
||||
post_scientificName = "\"scientificName\": \"" + entry[0].split('_')[0] + "\","
|
||||
post_algorithm = "\"algorithm\": " + "\"alpha\"" + ","
|
||||
post_confidence = "\"confidence\": " + str(entry[1])
|
||||
post_end = " }"
|
||||
|
||||
post_json = post_begin + post_timestamp + post_lat + post_lon + post_soundscape_id + post_soundscape_start_time + post_soundscape_end_time + post_commonName + post_scientificName + post_algorithm + post_confidence + post_end
|
||||
print(post_json)
|
||||
response = requests.post(detection_url, json=json.loads(post_json))
|
||||
print("Detection POST Response Status - ", response.status_code)
|
||||
|
||||
|
||||
if soundscape_uploaded is False:
|
||||
# POST soundscape to server
|
||||
soundscape_url = "https://app.birdweather.com/api/v1/stations/" + birdweather_id + "/soundscapes" + "?timestamp=" + current_iso8601
|
||||
|
||||
with open(args.i, 'rb') as f:
|
||||
wav_data = f.read()
|
||||
response = requests.post(url=soundscape_url, data=wav_data, headers={'Content-Type': 'application/octet-stream'})
|
||||
print("Soundscape POST Response Status - ", response.status_code)
|
||||
sdata = response.json()
|
||||
soundscape_id = sdata['soundscape']['id']
|
||||
soundscape_uploaded = True
|
||||
|
||||
# POST detection to server
|
||||
detection_url = "https://app.birdweather.com/api/v1/stations/" + birdweather_id + "/detections"
|
||||
start_time = d.split(';')[0]
|
||||
end_time = d.split(';')[1]
|
||||
post_begin = "{ "
|
||||
now_p_start = now + datetime.timedelta(seconds=float(start_time))
|
||||
current_iso8601 = now_p_start.astimezone(get_localzone()).isoformat()
|
||||
post_timestamp = "\"timestamp\": \"" + current_iso8601 + "\","
|
||||
post_lat = "\"lat\": " + str(args.lat) + ","
|
||||
post_lon = "\"lon\": " + str(args.lon) + ","
|
||||
post_soundscape_id = "\"soundscapeId\": " + str(soundscape_id) + ","
|
||||
post_soundscape_start_time = "\"soundscapeStartTime\": " + start_time + ","
|
||||
post_soundscape_end_time = "\"soundscapeEndTime\": " + end_time + ","
|
||||
post_commonName = "\"commonName\": \"" + entry[0].split('_')[1] + "\","
|
||||
post_scientificName = "\"scientificName\": \"" + entry[0].split('_')[0] + "\","
|
||||
post_algorithm = "\"algorithm\": " + "\"alpha\"" + ","
|
||||
post_confidence = "\"confidence\": " + str(entry[1])
|
||||
post_end = " }"
|
||||
|
||||
post_json = post_begin + post_timestamp + post_lat + post_lon + post_soundscape_id + post_soundscape_start_time + post_soundscape_end_time + post_commonName + post_scientificName + post_algorithm + post_confidence + post_end
|
||||
print(post_json)
|
||||
response = requests.post(detection_url, json=json.loads(post_json))
|
||||
print("Detection POST Response Status - ", response.status_code)
|
||||
except:
|
||||
print("Cannot POST right now")
|
||||
conn.send(myReturn.encode(FORMAT))
|
||||
|
||||
#time.sleep(3)
|
||||
|
||||
+85
-106
@@ -1,107 +1,86 @@
|
||||
<html>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Create two unequal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.first {
|
||||
width: calc(50% - 70px);
|
||||
}
|
||||
|
||||
.second {
|
||||
width: calc(50% - 30px);
|
||||
}
|
||||
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
width:100%;
|
||||
border: none;
|
||||
background-color: #04AA6D;
|
||||
padding: 20px 20px;
|
||||
color: white;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.column {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<div class="row">
|
||||
<div class="column first">
|
||||
<form action="" method="POST" onclick="return confirm('Stop core services?')">
|
||||
<input type="hidden" name="submit" value="stop_core_services.sh">
|
||||
<button type="submit" class="block">Stop Core Services</button>
|
||||
</form>
|
||||
<form action="" method="POST" onclick="return confirm('Restart ALL services?')">
|
||||
<input type="hidden" name="submit" value="restart_services.sh">
|
||||
<button type="submit" class="block">Restart ALL Services</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<input type="hidden" name="submit" value="sudo systemctl restart birdnet_analysis.service">
|
||||
<button type="submit" class="block">Restart BirdNET Analysis</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<input type="hidden" name="submit" value="sudo systemctl restart birdnet_recording.service">
|
||||
<button type="submit" class="block">Restart Recording</button>
|
||||
</form>
|
||||
<form action="" method="POST" onclick="return confirm('Restart Caddy? You will be disconnected for about 20 seconds.')">
|
||||
<input type="hidden" name="submit" value="sudo systemctl restart caddy">
|
||||
<button type="submit" class="block">Restart Caddy</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="column second">
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if(isset($_POST['submit'])){
|
||||
$command = $_POST['submit'];
|
||||
if($command == 'restart_services.sh'){
|
||||
$str= "<h3>Restarting Services</h3>
|
||||
<p>Please wait 60-90 seconds</p>";
|
||||
echo str_pad($str, 4096);
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
if(isset($command)){
|
||||
$results = shell_exec("$command 2>&1");
|
||||
echo "<pre>$results</pre>";
|
||||
}
|
||||
}
|
||||
ob_end_flush();
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<br>
|
||||
<br>
|
||||
<div class="servicecontrols">
|
||||
<form action="" method="POST">
|
||||
<h3>Live Audio Stream</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop livestream.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart livestream.service">Restart </button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now livestream.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now livestream.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>Web Terminal</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop web_terminal.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart web_terminal.service">Restart </button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now web_terminal.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now web_terminal.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>BirdNET Log</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop birdnet_log.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart birdnet_log.service">Restart </button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now birdnet_log.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now birdnet_log.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>Extraction Service</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop extraction.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart extraction.service">Restart </button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now extraction.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now extraction.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>BirdNET Analysis Server</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop birdnet_server.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart birdnet_server.service">Restart</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now birdnet_server.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now birdnet_server.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>BirdNET Analysis Client</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop birdnet_analysis.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart birdnet_analysis.service">Restart</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now birdnet_analysis.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now birdnet_analysis.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>Streamlit Statistics</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop birdnet_stats.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart birdnet_stats.service">Restart</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now birdnet_stats.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now birdnet_stats.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>Recording Service</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop birdnet_recording.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart birdnet_recording.service">Restart</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now birdnet_recording.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now birdnet_recording.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>Chart Viewer</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop chart_viewer.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart chart_viewer.service">Restart</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now chart_viewer.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now chart_viewer.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>Spectrogram Viewer</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop spectrogram_viewer.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart spectrogram_viewer.service">Restart</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now spectrogram_viewer.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now spectrogram_viewer.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<h3>Pushed Notifications</h3>
|
||||
<button type="submit" name="submit" value="sudo systemctl stop pushed_notifications.service">Stop</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl restart pushed_notifications.service">Restart</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl disable --now pushed_notifications.service">Disable</button>
|
||||
<button type="submit" name="submit" value="sudo systemctl enable --now pushed_notifications.service">Enable</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<button type="submit" name="submit" value="restart_services.sh" onclick="return confirm('This will take about 90 seconds.')">Restart All Services</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,8 @@ if (file_exists('/home/pi/BirdNET-Pi/thisrun.txt')) {
|
||||
} elseif (file_exists('/home/pi/BirdNET-Pi/firstrun.ini')) {
|
||||
$config = parse_ini_file('/home/pi/BirdNET-Pi/firstrun.ini');
|
||||
}
|
||||
$refreshtime = $config['RECORDING_LENGTH'];
|
||||
header("refresh:$refreshtime");
|
||||
$refresh = $config['RECORDING_LENGTH'];
|
||||
$time = time();
|
||||
echo "<img style=\"width:100%;height:100%\" src=\"/spectrogram.png?nocache=$time\">";
|
||||
header("Refresh: $refresh;");
|
||||
?>
|
||||
<body style='background-color:rgb(119, 196, 135)'>
|
||||
<img src='/spectrogram.png?nocache=<?php echo time();?>' style='display: block; height: 100%; width: 100%;'>
|
||||
|
||||
+102
-233
@@ -3,270 +3,139 @@ ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$mysqli = mysqli_connect();
|
||||
$mysqli->select_db('birds');
|
||||
|
||||
if ($mysqli->connect_error) {
|
||||
die('Connect Error (' .
|
||||
$mysqli->connect_errno . ') '.
|
||||
$mysqli->connect_error);
|
||||
$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
|
||||
if($db == False) {
|
||||
echo "Database busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$statement = $db->prepare('SELECT Date, Time, File_Name, Com_Name, COUNT(*), MAX(Confidence) FROM detections GROUP BY Com_Name ORDER BY COUNT(*) DESC');
|
||||
if($statement == False) {
|
||||
echo "Database busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result = $statement->execute();
|
||||
|
||||
// SQL query to select data from database
|
||||
$sql = "SELECT COUNT(*) AS 'Total' FROM detections
|
||||
ORDER BY Date DESC, Time DESC";
|
||||
$totalcount = $mysqli->query($sql);
|
||||
$statement2 = $db->prepare('SELECT Date, Time, File_Name, Com_Name, COUNT(*), MAX(Confidence) FROM detections GROUP BY Com_Name ORDER BY Com_Name');
|
||||
if($statement == False) {
|
||||
echo "Database busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result2 = $statement2->execute();
|
||||
|
||||
$sql1 = "SELECT Com_Name, COUNT(*), MAX(Confidence)
|
||||
FROM detections
|
||||
GROUP BY Com_Name
|
||||
ORDER BY COUNT(*) DESC";
|
||||
$stats = $mysqli->query($sql1);
|
||||
|
||||
$sql2 = "SELECT COUNT(*) AS 'Total' FROM detections
|
||||
WHERE Date = CURDATE()";
|
||||
$todayscount = $mysqli->query($sql2);
|
||||
|
||||
$sql3 = "SELECT COUNT(*) AS 'Total' FROM detections
|
||||
WHERE Date = CURDATE()
|
||||
AND Time >= DATE_SUB(NOW(),INTERVAL 1 HOUR)";
|
||||
$lasthourcount = $mysqli->query($sql3);
|
||||
|
||||
$sql4 = "SELECT Com_Name, Date, Time, MAX(Confidence)
|
||||
FROM detections
|
||||
GROUP BY Com_Name
|
||||
ORDER BY MAX(Confidence) DESC";
|
||||
$specieslist = $mysqli->query($sql4);
|
||||
$speciescount = mysqli_num_rows($specieslist);
|
||||
|
||||
$sql5 = "SELECT Com_Name,COUNT(*)
|
||||
AS 'Total'
|
||||
FROM detections
|
||||
GROUP BY Com_Name
|
||||
ORDER BY Total DESC";
|
||||
$speciestally = $mysqli->query($sql5);
|
||||
|
||||
$getspecies = "SELECT Com_Name from detections
|
||||
GROUP BY Com_Name";
|
||||
$result = $mysqli->query($getspecies);
|
||||
|
||||
if(isset($_POST['species'])){
|
||||
$selection = $_POST['species'];
|
||||
$specificspecies = "SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence) from detections
|
||||
WHERE Com_Name = \"$selection\"";
|
||||
$specificstats = $mysqli->query($specificspecies);}
|
||||
|
||||
$mysqli->close();
|
||||
$statement3 = $db->prepare("SELECT Com_Name, Sci_Name, COUNT(*), MAX(Confidence), File_Name, Date, Time from detections WHERE Com_Name = \"$selection\"");
|
||||
if($statement3 == False) {
|
||||
echo "Database busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result3 = $statement3->execute();
|
||||
}
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>BirdNET-Pi DB</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<style>
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* Create two unequal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
.first {
|
||||
width: calc(50% - 70px);
|
||||
}
|
||||
.second {
|
||||
width: calc(50% + 70px);
|
||||
}
|
||||
.
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
a {
|
||||
color:black;
|
||||
text-decoration: none;
|
||||
}
|
||||
.block {
|
||||
display: block;
|
||||
width:40%;
|
||||
margin-left:auto;
|
||||
border: none;
|
||||
padding: 5px 5px;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
width:75%;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
select option {
|
||||
font-size:large;
|
||||
}
|
||||
|
||||
select {
|
||||
float:left;
|
||||
display:block;
|
||||
margin-right:auto;
|
||||
font-size:large;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
h3 {
|
||||
margin-bottom:0px;
|
||||
text-align:center;
|
||||
}
|
||||
form {
|
||||
text-align:left;
|
||||
margin-left:0px;
|
||||
width:100%;
|
||||
}
|
||||
.column {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
input, label, img {
|
||||
width:100%;
|
||||
{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
|
||||
<section>
|
||||
<div class="row">
|
||||
<div class="column first">
|
||||
<h3>Number of Detections</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Total</th>
|
||||
<th>Today</th>
|
||||
<th>Last Hour</th>
|
||||
<th>Number of Unique Species</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php while ($row = $totalcount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
<td><?php while ($row = $todayscount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
<td><?php while ($row = $lasthourcount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
<td><?php echo $speciescount;?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Summary</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Common Name</th>
|
||||
<th>Occurrences</th>
|
||||
<th>Max Confidence Score</th>
|
||||
</tr>
|
||||
<?php // LOOP TILL END OF DATA
|
||||
while($rows=$stats ->fetch_assoc())
|
||||
<body>
|
||||
<div class="stats">
|
||||
<div class="column left">
|
||||
<table>
|
||||
<?php
|
||||
while($results=$result2->fetchArray(SQLITE3_ASSOC))
|
||||
{
|
||||
$MAX = sprintf("%.1f%%", $rows['MAX(Confidence)'] * 100);
|
||||
$links = preg_replace('/ /', '_', $rows['Com_Name']);
|
||||
$links = preg_replace('/\'/', '', $links);
|
||||
$comname = preg_replace('/ /', '_', $results['Com_Name']);
|
||||
$comname = preg_replace('/\'/', '', $comname);
|
||||
$filename = "/By_Date/".$results['Date']."/".$comname."/".$results['File_Name'];
|
||||
?>
|
||||
<tr>
|
||||
<td><a href="../By_Common_Name/<?php echo $links;?>"><?php echo $rows['Com_Name'];?></a></td>
|
||||
<td><?php echo $rows['COUNT(*)'];?></td>
|
||||
<td><?php echo $MAX;?></td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<form action="" method="POST">
|
||||
<td><input type="hidden" name="view" value="Species Stats">
|
||||
<button type="submit" name="species" value="<?php echo $results['Com_Name'];?>"><?php echo $results['Com_Name'];?></button>
|
||||
</td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
<div class="column second">
|
||||
<form style="margin:0;width:100%;" action="stats.php" method="POST">
|
||||
<h3>Species Stats</h3>
|
||||
<select name="species" >
|
||||
<option value="<?php if(isset($_POST['species'])){echo $selection;}?>"><?php if(isset($_POST['species'])){echo $selection;}else{echo "--Choose Species--";}?></option>
|
||||
<?php
|
||||
while($row = $result->fetch_assoc()) {
|
||||
?>
|
||||
<option value="<?php echo $row['Com_Name'];?>"><?php echo $row['Com_Name'];?></option>"
|
||||
</form>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="column center">
|
||||
<?php if(!isset($_POST['species'])){
|
||||
?><p class="centered">Choose a species to load images from Wikimedia Commons.</p>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<button type="submit" class="block"/>Show Species Statistics</button>
|
||||
</form>
|
||||
};?>
|
||||
<?php if(isset($_POST['species'])){
|
||||
$species = $_POST['species'];
|
||||
$str = "<h3>$species</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Common Name</th>
|
||||
<th>Scientific Name</th>
|
||||
<th>Occurrences</th>
|
||||
<th>Highest Confidence Score</th>
|
||||
<th>Links</th>
|
||||
</tr>";
|
||||
echo str_pad($str, 4096);
|
||||
ob_flush();
|
||||
flush();
|
||||
|
||||
while($rows = $specificstats->fetch_assoc()) {
|
||||
$count = $rows['COUNT(*)'];
|
||||
$maxconf = $rows['MAX(Confidence)'];
|
||||
$name = $rows['Com_Name'];
|
||||
$sciname = $rows['Sci_Name'];
|
||||
$dbname = preg_replace('/ /', '_', $rows['Com_Name']);
|
||||
$dbname = preg_replace('/\'/', '', $dbname);
|
||||
$dbsciname = preg_replace('/ /', '_', $rows['Sci_Name']);
|
||||
$imagelink = shell_exec("/home/pi/BirdNET-Pi/scripts/get_image.sh $dbsciname");
|
||||
$imagecitation = shell_exec("/home/pi/BirdNET-Pi/scripts/get_citation.sh $dbsciname");
|
||||
$str= "<tr>
|
||||
<td><a href=\"../By_Common_Name/$dbname\"/>$name</a></td>
|
||||
<td><a href=\"../By_Scientific_Name/$dbsciname\"/>$sciname</a></td>
|
||||
<td>$count</td>
|
||||
<td>$maxconf</td>
|
||||
<td><a href=\"https://wikipedia.org/wiki/$dbsciname\" target=\"top\"/>Wikipedia</a>, <a href=\"https://allaboutbirds.org/guide/$dbname\" target=\"top\"/>All About Birds</a>
|
||||
while($results=$result3->fetchArray(SQLITE3_ASSOC)){
|
||||
$count = $results['COUNT(*)'];
|
||||
$maxconf = $results['MAX(Confidence)'];
|
||||
$date = $results['Date'];
|
||||
$time = $results['Time'];
|
||||
$name = $results['Com_Name'];
|
||||
$sciname = $results['Sci_Name'];
|
||||
$dbsciname = preg_replace('/ /', '_', $sciname);
|
||||
$comname = preg_replace('/ /', '_', $results['Com_Name']);
|
||||
$comname = preg_replace('/\'/', '', $comname);
|
||||
$linkname = preg_replace('/_/', '+', $dbsciname);
|
||||
$filename = "/By_Date/".$date."/".$comname."/".$results['File_Name'];
|
||||
echo str_pad("<h3>$species</h3>
|
||||
<table><tr>
|
||||
<td><a href=\"https://wikipedia.org/wiki/$dbsciname\" target=\"top\"/><i>$sciname</i></a><br>
|
||||
<b>Occurrences: </b>$count<br>
|
||||
<b>Max Confidence: </b>$maxconf<br>
|
||||
<b>Best Recording: </b>$date $time<br>
|
||||
<a href=\"https://allaboutbirds.org/guide/$comname\" target=\"top\"/>All About Birds</a><br>
|
||||
<video controls poster=\"$filename.png\" title=\"$filename\"><source src=\"$filename\"></video></td>
|
||||
</tr>
|
||||
</table>";
|
||||
echo str_pad($str, 4096);
|
||||
</table>
|
||||
<p>Loading Images from <a href=\"https://commons.wikimedia.org/w/index.php?search=$linkname&title=Special:MediaSearch&go=Go&type=image\" target=\"_blank\">Wikimedia Commons</a></p>", '6096');
|
||||
|
||||
ob_flush();
|
||||
flush();
|
||||
echo "<img class=\"center\" src=\"$imagelink\">
|
||||
<pre>$imagecitation</pre></td>
|
||||
</div>
|
||||
</div>
|
||||
</div>";
|
||||
$imagelink = "https://commons.wikimedia.org/w/index.php?search=$linkname&title=Special:MediaSearch&go=Go&type=image";
|
||||
$homepage = file_get_contents($imagelink);
|
||||
preg_match_all("{<img\\s*(.*?)src=('.*?'|\".*?\"|[^\\s]+)(.*?)\\s*/?>}ims", $homepage, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $val) {
|
||||
$pos = strpos($val[2],"/");
|
||||
$link = substr($val[2],1,-1);
|
||||
if($pos !== 1 && strpos($link, "upload") == true && strpos($link, "CentralAutoLogin") == false)
|
||||
echo "<img src=\"$link\">";
|
||||
}
|
||||
}}
|
||||
?>
|
||||
|
||||
</section>
|
||||
<br><br><br>
|
||||
<table>
|
||||
<?php
|
||||
while($results=$result->fetchArray(SQLITE3_ASSOC))
|
||||
{
|
||||
$comname = preg_replace('/ /', '_', $results['Com_Name']);
|
||||
$comname = preg_replace('/\'/', '', $comname);
|
||||
$filename = "/By_Date/".$results['Date']."/".$comname."/".$results['File_Name'];
|
||||
?>
|
||||
<tr>
|
||||
<form action="" method="POST">
|
||||
<td><input type="hidden" name="view" value="Species Stats">
|
||||
<button type="submit" name="species" value="<?php echo $results['Com_Name'];?>"><?php echo $results['Com_Name'];?></button><br><b>Occurrences:</b> <?php echo $results['COUNT(*)'];?><br>
|
||||
<b>Max Confidence:</b> <?php echo $results['MAX(Confidence)'];?><br>
|
||||
<b>Best Recording:</b> <?php echo $results['Date']." ".$results['Time'];?><br><video controls poster="<?php echo $filename.".png";?>" preload="none" title="<?php echo $filename;?>"><source src="<?php echo $filename;?>" type="audio/mp3"></video></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ services=(birdnet_recording.service
|
||||
birdnet_analysis.service
|
||||
birdnet_server.service
|
||||
chart_viewer.service
|
||||
extraction.timer
|
||||
extraction.service
|
||||
spectrogram_viewer.service)
|
||||
|
||||
for i in "${services[@]}";do
|
||||
|
||||
+17
-102
@@ -1,103 +1,18 @@
|
||||
<html>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
* {
|
||||
font-family: 'Arial', 'Gill Sans', 'Gill Sans MT',
|
||||
' Calibri', 'Trebuchet MS', 'sans-serif';
|
||||
box-sizing: border-box;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Create two unequal columns that floats next to each other */
|
||||
.column {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.first {
|
||||
width: calc(50% - 70px);
|
||||
}
|
||||
|
||||
.second {
|
||||
width: calc(50% - 30px);
|
||||
}
|
||||
|
||||
/* Clear floats after the columns */
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
body {
|
||||
background-color: rgb(119, 196, 135);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
width:100%;
|
||||
border: none;
|
||||
background-color: #04AA6D;
|
||||
padding: 20px 20px;
|
||||
color: white;
|
||||
font-size: medium;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.column {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
<div class="row">
|
||||
<div class="column first">
|
||||
<form action="" method="POST" onclick="return confirm('Are you sure you want to reboot?')">
|
||||
<input type="hidden" name="submit" value="sudo reboot">
|
||||
<button type="submit" class="block">Reboot</button>
|
||||
</form>
|
||||
<form action="" method="POST" onclick="return confirm('BE SURE TO STASH ANY LOCAL CHANGES YOU HAVE MADE TO THE SYSTEM BEFORE UPDATING!!!')">
|
||||
<input type="hidden" name="submit" value="update_birdnet.sh">
|
||||
<button style="color:blue;" type="submit" class="block">Update</button>
|
||||
</form>
|
||||
<form action="" method="POST" onclick="return confirm('Are you sure you want to shutdown?')">
|
||||
<input type="hidden" name="submit" value="sudo shutdown now">
|
||||
<button style="color: red;" type="submit" class="block">Shutdown</button>
|
||||
</form>
|
||||
<form action="" method="POST" onclick="return confirm('Clear ALL Data? This cannot be undone.')">
|
||||
<input type="hidden" name="submit" value="clear_all_data.sh">
|
||||
<button style="color: red;" type="submit" class="block">Clear ALL data</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="column second">
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if(isset($_POST['submit'])){
|
||||
$command = $_POST['submit'];
|
||||
if($command == 'update_birdnet.sh'){
|
||||
$str= "<h3>Updating . . . </h3>
|
||||
<p>Please wait 60 seconds</p>";
|
||||
echo str_pad($str, 4096);
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
if(isset($command)){
|
||||
$results = shell_exec("$command 2>&1");
|
||||
echo "</div>
|
||||
</div>
|
||||
<pre>$results</pre>";
|
||||
}
|
||||
}
|
||||
ob_end_flush();
|
||||
?>
|
||||
</body>
|
||||
<br>
|
||||
<br>
|
||||
<div class="systemcontrols">
|
||||
<form action="" method="POST">
|
||||
<button type="submit" name="submit" value="sudo reboot" onclick="return confirm('Are you sure you want to reboot?')">Reboot</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<button type="submit" name="submit" value="update_birdnet.sh" onclick="return confirm('BE SURE TO STASH ANY LOCAL CHANGES YOU HAVE MADE TO THE SYSTEM BEFORE UPDATING!!!')" >Update</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<button type="submit" name="submit" value="sudo shutdown now" onclick="return confirm('Are you sure you want to shutdown?')">Shutdown</button>
|
||||
</form>
|
||||
<form action="" method="POST">
|
||||
<button type="submit" name="submit" value="sudo -upi clear_all_data.sh" onclick="return confirm('Clear ALL Data? This cannot be undone.')">Clear ALL data</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$db = new SQLite3('/home/pi/BirdNET-Pi/scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
|
||||
if($db == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
|
||||
$statement0 = $db->prepare('SELECT Time, Com_Name, Sci_Name, Confidence, File_Name FROM detections WHERE Date == Date(\'now\', \'localtime\') ORDER BY Time DESC');
|
||||
if($statement0 == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result0 = $statement0->execute();
|
||||
|
||||
$statement1 = $db->prepare('SELECT COUNT(*) FROM detections');
|
||||
if($statement1 == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result1 = $statement1->execute();
|
||||
$totalcount = $result1->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == DATE(\'now\', \'localtime\')');
|
||||
if($statement2 == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result2 = $statement2->execute();
|
||||
$todaycount = $result2->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Date == Date(\'now\', \'localtime\') AND TIME >= TIME(\'now\', \'localtime\', \'-1 hour\')');
|
||||
if($statement3 == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result3 = $statement3->execute();
|
||||
$hourcount = $result3->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$statement4 = $db->prepare('SELECT Com_Name, Sci_Name, Time, Confidence FROM detections LIMIT 1');
|
||||
if($statement4 == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result4 = $statement4->execute();
|
||||
$mostrecent = $result4->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
$statement5 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections');
|
||||
if($statement4 == False){
|
||||
echo "Database is busy";
|
||||
header("refresh: 0;");
|
||||
}
|
||||
$result5 = $statement5->execute();
|
||||
$speciestally = $result5->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>BirdNET-Pi DB</title>
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<div class="viewdb">
|
||||
<h3>Number of Detections</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Total</th>
|
||||
<th>Today</th>
|
||||
<th>Last Hour</th>
|
||||
<th>Number of Unique Species</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo $totalcount['COUNT(*)'];?></td>
|
||||
<form action="" method="POST">
|
||||
<td><input type="hidden" name="view" value="Recordings"><button type="submit" name="date" value="<?php echo date('Y-m-d');?>"><?php echo $todaycount['COUNT(*)'];?></button></td>
|
||||
</form>
|
||||
<td><?php echo $hourcount['COUNT(*)'];?></td>
|
||||
<form action="" method="POST">
|
||||
<td><button type="submit" name="view" value="Species Stats"><?php echo $speciestally['COUNT(DISTINCT(Com_Name))'];?></button></td>
|
||||
</form>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Today's Detections</h3>
|
||||
<table>
|
||||
<?php
|
||||
while($todaytable=$result0->fetchArray(SQLITE3_ASSOC))
|
||||
{
|
||||
$comname = preg_replace('/ /', '_', $todaytable['Com_Name']);
|
||||
$comname = preg_replace('/\'/', '_', $comname);
|
||||
$filename = "/By_Date/".date('Y-m-d')."/".$comname."/".$todaytable['File_Name'];
|
||||
$sciname = preg_replace('/ /', '_', $todaytable['Sci_Name']);
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo $todaytable['Time'];?><br>
|
||||
<b><a class="a2" href="https://allaboutbirds.org/guide/<?php echo $comname;?>" target="top"><?php echo $todaytable['Com_Name'];?></a></b><br>
|
||||
<a class="a2" href="https://wikipedia.org/wiki/<?php echo $sciname;?>" target="top"><i><?php echo $todaytable['Sci_Name'];?></i></a><br>
|
||||
<b>Confidence:</b> <?php echo $todaytable['Confidence'];?><br>
|
||||
<a href="<?php echo $filename;?>"><img src="<?php echo $filename.".png";?>"></a></td>
|
||||
<?php }?>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1,59 +1,12 @@
|
||||
#!/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)
|
||||
|
||||
services=$(awk '/service/ && /systemctl/ && !/php/ {print $3}' ${my_dir}/install_services.sh | sort)
|
||||
|
||||
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() {
|
||||
sudo sed -i '/birdnet/,+1d' /etc/crontab
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# Stage 1 removes old stuff
|
||||
remove_services
|
||||
remove_scripts
|
||||
|
||||
# Backup labels.txt
|
||||
sudo -u${USER} cp -f ~/BirdNET-Pi/model/labels.txt{,.bak}
|
||||
# Stage 2 does a git pull to fetch new things
|
||||
sudo -u${USER} git -C ${HOME}/BirdNET-Pi checkout -f
|
||||
sudo -u${USER} git -C ${HOME}/BirdNET-Pi pull -f
|
||||
# Trigger the new update_birdnet2.sh
|
||||
sudo -u${USER} ${my_dir}/update_birdnet2.sh
|
||||
sudo -u${USER} git -C /home/pi/BirdNET-Pi stash
|
||||
sudo -u${USER} git -C /home/pi/BirdNET-Pi pull -f
|
||||
sudo systemctl daemon-reload
|
||||
sudo -u${USER} git -C /home/pi/BirdNET-Pi stash pop
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Second stage of update
|
||||
USER=pi
|
||||
birdnet_conf=/home/pi/BirdNET-Pi/birdnet.conf
|
||||
my_dir=${HOME}/BirdNET-Pi/scripts
|
||||
|
||||
# Stage 1 updates the services
|
||||
sudo ${my_dir}/update_services.sh
|
||||
|
||||
# Stage 1.5: adding new birdnet.conf entries
|
||||
if ! grep FULL_DISK ${birdnet_conf} &> /dev/null;then
|
||||
cat << EOF >> ${birdnet_conf}
|
||||
|
||||
## FULL_DISK can be set to configure how the system reacts to a full disk
|
||||
## purge = Remove the oldest day's worth of recordings
|
||||
## keep = Keep all data and `stop_core_services.sh`
|
||||
|
||||
FULL_DISK=purge
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! grep AUDIOFMT ${birdnet_conf} &> /dev/null;then
|
||||
cat<< EOF >> ${birdnet_conf}
|
||||
## AUDIOFMT set the audio format that sox should use for the extractions.
|
||||
## The default is mp3. Available formats are: 8svx aif aifc aiff aiffc al amb
|
||||
## amr-nb amr-wb anb au avr awb caf cdda cdr cvs cvsd cvu dat dvms f32 f4 f64 f8
|
||||
## fap flac fssd gsm gsrt hcom htk ima ircam la lpc lpc10 lu mat mat4 mat5 maud
|
||||
## mp2 mp3 nist ogg paf prc pvf raw s1 s16 s2 s24 s3 s32 s4 s8 sb sd2 sds sf sl
|
||||
## sln smp snd sndfile sndr sndt sou sox sph sw txw u1 u16 u2 u24 u3 u32 u4 u8
|
||||
## ub ul uw vms voc vorbis vox w64 wav wavpcm wv wve xa xi
|
||||
## Note: Most have not been tested.
|
||||
|
||||
AUDIOFMT=mp3
|
||||
EOF
|
||||
fi
|
||||
|
||||
sudo -u${USER} sed -i 's/EXTRACTIONLOG_URL/WEBTERMINAL_URL/g' ${birdnetconf}
|
||||
|
||||
# Replace Backup labels.txt
|
||||
sudo -u${USER} cp -f ~/BirdNET-Pi/model/labels.txt.bak ~/BirdNET-Pi/model/labels.txt
|
||||
|
||||
# Stage 2 restarts the services
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl stop birdnet_recording.service
|
||||
sudo rm -rf ${RECS_DIR}/$(date +%B-%Y/%d-%A)/*
|
||||
services=(web_terminal.service
|
||||
spectrogram_viewer.service
|
||||
pushed_notifications.service
|
||||
livestream.service
|
||||
icecast2.service
|
||||
extraction.timer
|
||||
extraction.service
|
||||
chart_viewer.service
|
||||
birdnet_recording.service
|
||||
birdnet_log.service)
|
||||
|
||||
for i in "${services[@]}";do
|
||||
sudo systemctl restart "${i}"
|
||||
done
|
||||
+22
-70
@@ -14,6 +14,12 @@ cat << EOF > /etc/caddy/Caddyfile
|
||||
http://localhost http://$(hostname).local ${BIRDNETPI_URL} {
|
||||
root * ${EXTRACTED}
|
||||
file_server browse
|
||||
handle /By_Date/* {
|
||||
file_server browse
|
||||
}
|
||||
handle /Charts/* {
|
||||
file_server browse
|
||||
}
|
||||
basicauth /Processed* {
|
||||
birdnet ${HASHWORD}
|
||||
}
|
||||
@@ -26,8 +32,14 @@ http://localhost http://$(hostname).local ${BIRDNETPI_URL} {
|
||||
basicauth /phpsysinfo* {
|
||||
birdnet ${HASHWORD}
|
||||
}
|
||||
basicauth /terminal* {
|
||||
birdnet ${HASHWORD}
|
||||
}
|
||||
reverse_proxy /stream localhost:8000
|
||||
php_fastcgi unix//run/php/php7.4-fpm.sock
|
||||
reverse_proxy /log* localhost:8080
|
||||
reverse_proxy /stats* localhost:8501
|
||||
reverse_proxy /terminal* localhost:8888
|
||||
}
|
||||
EOF
|
||||
else
|
||||
@@ -35,79 +47,19 @@ else
|
||||
http://localhost http://$(hostname).local ${BIRDNETPI_URL} {
|
||||
root * ${EXTRACTED}
|
||||
file_server browse
|
||||
handle /By_Date/* {
|
||||
file_server browse
|
||||
}
|
||||
handle /Charts/* {
|
||||
file_server browse
|
||||
}
|
||||
reverse_proxy /stream localhost:8000
|
||||
php_fastcgi unix//run/php/php7.4-fpm.sock
|
||||
reverse_proxy /log* localhost:8080
|
||||
reverse_proxy /stats* localhost:8501
|
||||
reverse_proxy /terminal* localhost:8888
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ ! -z ${WEBTERMINAL_URL} ] && [ ! -z ${HASHWORD} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
${WEBTERMINAL_URL} {
|
||||
basicauth {
|
||||
birdnet ${HASHWORD}
|
||||
}
|
||||
reverse_proxy localhost:8888
|
||||
}
|
||||
EOF
|
||||
elif [ ! -z ${WEBTERMINAL_URL} ] && [ -z ${HASHWORD} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
${WEBTERMINAL_URL} {
|
||||
reverse_proxy localhost:8888
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ ! -z ${BIRDNETLOG_URL} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
|
||||
${BIRDNETLOG_URL} {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
################################################################################
|
||||
sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f homepage/*
|
||||
sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f scripts/*
|
||||
sudo -u${USER} git -C /home/pi/BirdNET-Pi checkout -f scripts/*/*
|
||||
sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html
|
||||
|
||||
if [ ! -z ${BIRDNETLOG_URL} ];then
|
||||
BIRDNETLOG_URL="$(echo ${BIRDNETLOG_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
else
|
||||
BIRDNETLOG_URL="$(echo http://$(hostname).local:8080 | sed 's/\/\//\\\/\\\//g')"
|
||||
fi
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
|
||||
if [ ! -z ${WEBTERMINAL_URL} ];then
|
||||
WEBTERMINAL_URL="$(echo ${WEBTERMINAL_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
else
|
||||
WEBTERMINAL_URL="$(echo http://$(hostname).local:8888 | sed 's/\/\//\\\/\\\//g')"
|
||||
fi
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
|
||||
|
||||
if [ -z ${BIRDNETPI_URL} ];then
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
else
|
||||
BIRDNETPI_URL="$(echo ${BIRDNETPI_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
fi
|
||||
|
||||
systemctl reload caddy
|
||||
sudo systemctl reload caddy
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Update database password
|
||||
source /etc/birdnet/birdnet.conf
|
||||
|
||||
mysql -e "
|
||||
SET PASSWORD FOR 'birder'@'localhost' = PASSWORD('${DB_PWD}');
|
||||
FLUSH PRIVILEGES";
|
||||
sed -i "s/mysqli.default_host =.*/mysqli.default_host = localhost/g" /etc/php/7.4/fpm/php.ini
|
||||
sed -i "s/mysqli.default_user =.*/mysqli.default_user = birder/g" /etc/php/7.4/fpm/php.ini
|
||||
sed -i "s/mysqli.default_pw =.*/mysqli.default_pw = ${DB_PWD}/g" /etc/php/7.4/fpm/php.ini
|
||||
systemctl restart php7.4-fpm.service
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
$timer=60;
|
||||
header( "refresh:$timer;url=/overview.php" );
|
||||
?>
|
||||
<html lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<head></head>
|
||||
<body style="background-color: rgb(119, 196, 135)">
|
||||
<script>
|
||||
|
||||
function countDown(secs,elem) {
|
||||
|
||||
var element = document.getElementById(elem);
|
||||
|
||||
element.innerHTML = "Update in progress. Please allow another "+secs+" seconds for it to complete.";
|
||||
|
||||
if(secs < 1) {
|
||||
|
||||
clearTimeout(timer);
|
||||
|
||||
element.innerHTML = '<h4>Let\'s see</h4>';
|
||||
|
||||
}
|
||||
|
||||
secs--;
|
||||
|
||||
var timer = setTimeout('countDown('+secs+',"'+elem+'")',1000);
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div id="status"style="font-size:30px;"></div>
|
||||
|
||||
<script>countDown(<?php echo $timer;?>,"status");</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,591 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# This reinstalls the services
|
||||
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.7/Arm/nomachine_7.7.4_1_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_ftpd() {
|
||||
if ! [ -f /etc/ftpuseres ];then
|
||||
apt -y install ftpd
|
||||
fi
|
||||
}
|
||||
|
||||
install_lynx() {
|
||||
if ! which lynx &> /dev/null;then
|
||||
apt -y install lynx
|
||||
fi
|
||||
}
|
||||
|
||||
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 install mariadb-server
|
||||
echo "MariaDB Installed"
|
||||
fi
|
||||
source /etc/os-release
|
||||
if [[ "${VERSION_CODENAME}" == "buster" ]];then
|
||||
USER=${USER} ${my_dir}/update_db_pwd_buster.sh
|
||||
elif [[ "${VERSION_CODENAME}" == "bullseye" ]];then
|
||||
mysql -e "
|
||||
SET PASSWORD FOR 'birder'@'localhost' = PASSWORD('${DB_PWD}');
|
||||
FLUSH PRIVILEGES";
|
||||
sed -i "s/mysqli.default_host =.*/mysqli.default_host = localhost/g" /etc/php/7.4/fpm/php.ini
|
||||
sed -i "s/mysqli.default_user =.*/mysqli.default_user = birder/g" /etc/php/7.4/fpm/php.ini
|
||||
sed -i "s/mysqli.default_pw =.*/mysqli.default_pw = ${DB_PWD}/g" /etc/php/7.4/fpm/php.ini
|
||||
fi
|
||||
}
|
||||
|
||||
install_birdnet_analysis() {
|
||||
echo "Installing the birdnet_analysis.service"
|
||||
cat << EOF > /etc/systemd/system/birdnet_analysis.service
|
||||
[Unit]
|
||||
Description=BirdNET Analysis
|
||||
After=birdnet_server.service
|
||||
Requires=birdnet_server.service
|
||||
[Service]
|
||||
Restart=always
|
||||
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_birdnet_server() {
|
||||
echo "Installing the birdnet_server.service"
|
||||
cat << EOF > /etc/systemd/system/birdnet_server.service
|
||||
[Unit]
|
||||
Description=BirdNET Analysis Server
|
||||
Before=birdnet_analysis.service
|
||||
[Service]
|
||||
Restart=always
|
||||
Type=simple
|
||||
RestartSec=2
|
||||
User=${USER}
|
||||
ExecStart=/usr/local/bin/server.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable birdnet_server.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 pushed_notifications.service
|
||||
}
|
||||
|
||||
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 ${EXTRACTED}/Charts ] || sudo -u ${USER} mkdir -p ${EXTRACTED}/Charts
|
||||
[ -d ${PROCESSED} ] || sudo -u ${USER} mkdir -p ${PROCESSED}
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/* ${EXTRACTED}
|
||||
if [ ! -z ${BIRDNETLOG_URL} ];then
|
||||
BIRDNETLOG_URL="$(echo ${BIRDNETLOG_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8080/${BIRDNETLOG_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
fi
|
||||
if [ ! -z ${WEBTERMINAL_URL} ];then
|
||||
WEBTERMINAL_URL="$(echo ${WEBTERMINAL_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local:8888/${WEBTERMINAL_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
fi
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/model/labels.txt ${my_dir}/
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts ${EXTRACTED}
|
||||
if [ -z ${BIRDNETPI_URL} ];then
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/birdnetpi.local/$(hostname).local/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
else
|
||||
BIRDNETPI_URL="$(echo ${BIRDNETPI_URL} | sed 's/\/\//\\\/\\\//g')"
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/homepage/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.html
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*.php
|
||||
sudo -u${USER} sed -i "s/http:\/\/birdnetpi.local/${BIRDNETPI_URL}/g" $(dirname ${my_dir})/scripts/*/*.php
|
||||
fi
|
||||
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/spectrogram.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewday.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/overview.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/stats.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/viewdb.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/scripts/history.php ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs $(dirname ${my_dir})/homepage/images/favicon.ico ${EXTRACTED}
|
||||
sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED}
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/phpsysinfo.ini ${HOME}/phpsysinfo/
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/green_bootstrap.css ${HOME}/phpsysinfo/templates/
|
||||
sudo -u ${USER} cp -f $(dirname ${my_dir})/templates/index_bootstrap.html ${HOME}/phpsysinfo/templates/html
|
||||
|
||||
echo "Setting Wttr.in URL to "${LATITUDE}", "${LONGITUDE}""
|
||||
sudo -u${USER} sed -i "s/https:\/\/v2.wttr.in\//https:\/\/v2.wttr.in\/"${LATITUDE},${LONGITUDE}"/g" $(dirname ${my_dir})/homepage/menu.html
|
||||
chmod -R g+rw $(dirname ${my_dir})
|
||||
chmod -R g+rw ${RECS_DIR}
|
||||
}
|
||||
|
||||
generate_BirdDB() {
|
||||
echo "Generating BirdDB.txt"
|
||||
if ! [ -f $(dirname ${my_dir})/BirdDB.txt ];then
|
||||
sudo -u ${USER} touch $(dirname ${my_dir})/BirdDB.txt
|
||||
echo "Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap" | sudo -u ${USER} tee -a $(dirname ${my_dir})/BirdDB.txt
|
||||
elif ! grep Date $(dirname ${my_dir})/BirdDB.txt;then
|
||||
sudo -u ${USER} sed -i '1 i\Date;Time;Sci_Name;Com_Name;Confidence;Lat;Lon;Cutoff;Week;Sens;Overlap' $(dirname ${my_dir})/BirdDB.txt
|
||||
fi
|
||||
ln -sf $(dirname ${my_dir})/BirdDB.txt ${my_dir}/BirdDB.txt &&
|
||||
chown pi:pi ${my_dir}/BirdDB.txt && chmod g+rw ${my_dir}/BirdDB.txt
|
||||
}
|
||||
|
||||
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 install -qqy alsa-utils
|
||||
echo "alsa-utils installed"
|
||||
fi
|
||||
if which pulseaudio &> /dev/null;then
|
||||
echo "PulseAudio installed"
|
||||
else
|
||||
echo "Installing pulseaudio"
|
||||
apt install -qqy pulseaudio
|
||||
echo "PulseAudio installed"
|
||||
fi
|
||||
if ! [ -d /etc/lightdm ];then
|
||||
systemctl set-default multi-user.target
|
||||
ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
|
||||
cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << EOF
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=-/sbin/agetty --autologin $USER --noclear %I \$TERM
|
||||
EOF
|
||||
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 install -qqy caddy=2.4.5
|
||||
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
|
||||
php_version="$(awk -F'php' '{print $3}' <(ls -l $(which /etc/alternatives/php)))"
|
||||
if ! [ -z ${CADDY_PWD} ];then
|
||||
HASHWORD=$(caddy hash-password -plaintext ${CADDY_PWD})
|
||||
cat << EOF > /etc/caddy/Caddyfile
|
||||
http://localhost http://$(hostname).local ${BIRDNETPI_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/php${php_version}-fpm.sock
|
||||
}
|
||||
EOF
|
||||
else
|
||||
cat << EOF > /etc/caddy/Caddyfile
|
||||
http://localhost http://$(hostname).local ${BIRDNETPI_URL} {
|
||||
root * ${EXTRACTED}
|
||||
file_server browse
|
||||
reverse_proxy /stream localhost:8000
|
||||
php_fastcgi unix//run/php/php${php_version}-fpm.sock
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ ! -z ${WEBTERMINAL_URL} ] && [ ! -z ${HASHWORD} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
${WEBTERMINAL_URL} {
|
||||
basicauth {
|
||||
birdnet ${HASHWORD}
|
||||
}
|
||||
reverse_proxy localhost:8888
|
||||
}
|
||||
EOF
|
||||
elif [ ! -z ${WEBTERMINAL_URL} ] && [ -z ${HASHWORD} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
${WEBTERMINAL_URL} {
|
||||
reverse_proxy localhost:8888
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
if [ ! -z ${BIRDNETLOG_URL} ];then
|
||||
cat << EOF >> /etc/caddy/Caddyfile
|
||||
|
||||
${BIRDNETLOG_URL} {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
update_etc_hosts() {
|
||||
sed -ie s/'$(hostname).local'/"$(hostname).local ${BIRDNETPI_URL//https:\/\/} ${WEBTERMINAL_URL//https:\/\/} ${BIRDNETLOG_URL//https:\/\/}"/g /etc/hosts
|
||||
}
|
||||
|
||||
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
|
||||
RestartSec=3
|
||||
Type=simple
|
||||
ExecStart=/bin/bash -c "/usr/bin/avahi-publish -a -R %I $(hostname -I |cut -d' ' -f1)"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable avahi-alias@"$(hostname)".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 spectrogram_viewer.service
|
||||
}
|
||||
|
||||
install_chart_viewer_service() {
|
||||
echo "Installing the chart_viewer.service"
|
||||
cat << EOF > /etc/systemd/system/chart_viewer.service
|
||||
[Unit]
|
||||
Description=BirdNET-Pi Chart Viewer Service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
RestartSec=300
|
||||
Type=simple
|
||||
User=pi
|
||||
ExecStart=/usr/local/bin/daily_plot.py
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable chart_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
|
||||
sudo -u ${USER} ln -sf $(dirname ${my_dir})/templates/bashrc \
|
||||
${HOME}/.bashrc
|
||||
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" birdnet_log.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable birdnet_log.service
|
||||
echo "Installing the Web Terminal"
|
||||
cat << EOF > /etc/systemd/system/web_terminal.service
|
||||
[Unit]
|
||||
Description=BirdNET-Pi Web Terminal
|
||||
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Type=simple
|
||||
User=${USER}
|
||||
Environment=TERM=xterm-256color
|
||||
ExecStart=/usr/local/bin/gotty -w -p 8888 --title-format "BirdNET-Pi Terminal" bash
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable web_terminal.service
|
||||
}
|
||||
|
||||
install_sox() {
|
||||
if which sox | grep mp3 &> /dev/null;then
|
||||
echo "Sox is installed"
|
||||
else
|
||||
echo "Installing sox"
|
||||
apt install -y sox libsox-fmt-mp3
|
||||
echo "Sox installed"
|
||||
fi
|
||||
}
|
||||
|
||||
install_php() {
|
||||
if ! which php &> /dev/null || ! which php-fpm || ! apt list --installed | grep php-xml;then
|
||||
echo "Installing PHP modules"
|
||||
apt install -qqy php php-fpm php-mysql php-xml php-zip
|
||||
else
|
||||
echo "PHP and PHP-FPM installed"
|
||||
fi
|
||||
echo "Configuring PHP for Caddy"
|
||||
sed -i 's/www-data/caddy/g' /etc/php/*/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_icecast() {
|
||||
if ! which icecast2;then
|
||||
echo "Installing IceCast2"
|
||||
echo "icecast2 icecast2/icecast-setup boolean false" | debconf-set-selections
|
||||
apt install -qqy icecast2
|
||||
config_icecast
|
||||
systemctl enable icecast2.service
|
||||
/etc/init.d/icecast2 start
|
||||
else
|
||||
echo "Icecast2 is installed"
|
||||
config_icecast
|
||||
systemctl enable icecast2.service
|
||||
/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/>admin</>birdnet</g' /etc/icecast2/icecast.xml
|
||||
passwords=("source-" "relay-" "admin-" "master-" "")
|
||||
for i in "${passwords[@]}";do
|
||||
sed -i "s/<${i}password>.*<\/${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
|
||||
After=network-online.target
|
||||
Requires=network-online.target
|
||||
|
||||
[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 livestream.service
|
||||
}
|
||||
|
||||
install_nomachine() {
|
||||
if [ ! -d /usr/share/NX ] && [ -d /etc/lightdm ];then
|
||||
echo "Installing NoMachine"
|
||||
curl -s -o ${HOME}/nomachine.deb -O "${nomachine_url}"
|
||||
apt install -y ${HOME}/nomachine.deb
|
||||
rm -f ${HOME}/nomachine.deb
|
||||
echo "Enabling VNC"
|
||||
systemctl enable --now vncserver-x11-serviced.service
|
||||
fi
|
||||
}
|
||||
|
||||
install_cleanup_cron() {
|
||||
echo "Installing the cleanup.cron"
|
||||
cat $(dirname ${my_dir})/templates/cleanup.cron >> /etc/crontab
|
||||
}
|
||||
|
||||
install_selected_services() {
|
||||
sudo apt -qqqq update
|
||||
install_scripts
|
||||
install_birdnet_analysis
|
||||
install_birdnet_server
|
||||
|
||||
if [[ "${DO_EXTRACTIONS}" =~ [Yy] ]];then
|
||||
install_extraction_service
|
||||
fi
|
||||
|
||||
if [[ "${DO_RECORDING}" =~ [Yy] ]];then
|
||||
install_alsa
|
||||
install_recording_service
|
||||
fi
|
||||
|
||||
install_php
|
||||
install_caddy
|
||||
install_Caddyfile
|
||||
update_etc_hosts
|
||||
install_avahi_aliases
|
||||
install_gotty_logs
|
||||
install_sox
|
||||
install_mariadb
|
||||
install_spectrogram_service
|
||||
install_chart_viewer_service
|
||||
install_pushed_notifications
|
||||
|
||||
if [ ! -z "${ICE_PWD}" ];then
|
||||
install_icecast
|
||||
install_livestream_service
|
||||
fi
|
||||
|
||||
if [[ "${INSTALL_NOMACHINE}" =~ [Yy] ]];then
|
||||
install_nomachine
|
||||
fi
|
||||
|
||||
create_necessary_dirs
|
||||
generate_BirdDB
|
||||
install_cleanup_cron
|
||||
install_ftpd
|
||||
install_lynx
|
||||
}
|
||||
|
||||
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
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
$timer=30;
|
||||
header( "refresh:$timer;url=/advanced.php" );
|
||||
?>
|
||||
<html lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<head></head>
|
||||
<body style="background-color: rgb(119, 196, 135)">
|
||||
<script>
|
||||
|
||||
function countDown(secs,elem) {
|
||||
|
||||
var element = document.getElementById(elem);
|
||||
|
||||
element.innerHTML = "Updating settings... Please allow another "+secs+" seconds for it to complete.";
|
||||
|
||||
if(secs < 1) {
|
||||
|
||||
clearTimeout(timer);
|
||||
|
||||
element.innerHTML = '<h4>Let\'s see</h4>';
|
||||
|
||||
}
|
||||
|
||||
secs--;
|
||||
|
||||
var timer = setTimeout('countDown('+secs+',"'+elem+'")',1000);
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div id="status"style="font-size:30px;"></div>
|
||||
|
||||
<script>countDown(<?php echo $timer;?>,"status");</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Update the species list
|
||||
#set -x
|
||||
trap 'rm -f "$TMPFILE"' EXIT
|
||||
source /etc/birdnet/birdnet.conf
|
||||
db=birds
|
||||
dbuser=birder
|
||||
dbpassword=${DB_PWD}
|
||||
|
||||
mysql -u${dbuser} -p${dbpassword} ${db} \
|
||||
-e 'SELECT Com_Name
|
||||
FROM detections
|
||||
GROUP BY Com_Name' |\
|
||||
tail -n+2 > ${IDFILE}
|
||||
sqlite3 /home/pi/BirdNET-Pi/scripts/birds.db "SELECT DISTINCT(Com_Name) FROM detections" | sort > ${IDFILE}
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
header("refresh: 30;");
|
||||
$mysqli = mysqli_connect();
|
||||
$mysqli->select_db('birds');
|
||||
|
||||
if ($mysqli->connect_error) {
|
||||
die('Connect Error (' .
|
||||
$mysqli->connect_errno . ') '.
|
||||
$mysqli->connect_error);
|
||||
}
|
||||
|
||||
// SQL query to select data from database
|
||||
$sql = "SELECT COUNT(*) AS 'Total' FROM detections
|
||||
ORDER BY Date DESC, Time DESC";
|
||||
$totalcount = $mysqli->query($sql);
|
||||
|
||||
$sql1 = "SELECT Date, Time, Sci_Name, Com_Name, MAX(Confidence)
|
||||
FROM detections
|
||||
WHERE Date = CURDATE()
|
||||
GROUP BY Date, Time, Sci_Name, Com_Name
|
||||
ORDER BY Time DESC";
|
||||
$mosttable = $mysqli->query($sql1);
|
||||
|
||||
$sql2 = "SELECT COUNT(*) AS 'Total' FROM detections
|
||||
WHERE Date = CURDATE()";
|
||||
$todayscount = $mysqli->query($sql2);
|
||||
|
||||
$sql3 = "SELECT COUNT(*) AS 'Total' FROM detections
|
||||
WHERE Date = CURDATE()
|
||||
AND Time >= DATE_SUB(NOW(),INTERVAL 1 HOUR)";
|
||||
$lasthourcount = $mysqli->query($sql3);
|
||||
|
||||
$sql4 = "SELECT Com_Name, Date, Time, MAX(Confidence)
|
||||
FROM detections
|
||||
GROUP BY Com_Name
|
||||
ORDER BY MAX(Confidence) DESC";
|
||||
$specieslist = $mysqli->query($sql4);
|
||||
$speciescount = mysqli_num_rows($specieslist);
|
||||
|
||||
$sql5 = "SELECT Com_Name,COUNT(*)
|
||||
AS 'Total'
|
||||
FROM detections
|
||||
GROUP BY Com_Name
|
||||
ORDER BY Total DESC";
|
||||
$speciestally = $mysqli->query($sql5);
|
||||
|
||||
$mysqli->close();
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>BirdNET-Pi DB</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<style>
|
||||
a {
|
||||
text-decoration:none;
|
||||
color:black;
|
||||
}
|
||||
.a2 { color:blue;}
|
||||
</style>
|
||||
</head>
|
||||
<body style="background-color: rgb(119, 196, 135);">
|
||||
|
||||
<section>
|
||||
<h2>Number of Detections</h2>
|
||||
<div class="row">
|
||||
<div class="column2">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Total</th>
|
||||
<th>Today</th>
|
||||
<th>Last Hour</th>
|
||||
<th>Number of Unique Species</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php while ($row = $totalcount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
<td><?php while ($row = $todayscount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
<td><?php while ($row = $lasthourcount->fetch_assoc()) { echo $row['Total']; };?></td>
|
||||
<td><?php echo $speciescount;?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Today's Detections</h2>
|
||||
<!-- TABLE CONSTRUCTION-->
|
||||
<table>
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>Scientific Name</th>
|
||||
<th>Common Name</th>
|
||||
<th>Confidence</th>
|
||||
<th>Links</th>
|
||||
</tr>
|
||||
<!-- PHP CODE TO FETCH DATA FROM ROWS-->
|
||||
<?php // LOOP TILL END OF DATA
|
||||
while($rows=$mosttable ->fetch_assoc())
|
||||
{
|
||||
$Confidence = sprintf("%.1f%%", $rows['MAX(Confidence)'] * 100);
|
||||
$dbname = preg_replace('/ /', '_', $rows['Com_Name']);
|
||||
$dbname = preg_replace('/\'/', '', $dbname);
|
||||
$dbsciname = preg_replace('/ /', '_', $rows['Sci_Name']);
|
||||
?>
|
||||
<tr>
|
||||
<!--FETCHING DATA FROM EACH
|
||||
ROW OF EVERY COLUMN-->
|
||||
<td><?php echo $rows['Time'];?></td>
|
||||
<td><a href="/By_Scientific_Name/<?php echo $dbsciname;?>"/><?php echo $rows['Sci_Name'];?></a></td>
|
||||
<td><a href="/By_Common_Name/<?php echo $dbname;?>"/><?php echo $rows['Com_Name'];?></a></td>
|
||||
<td><?php echo $Confidence;?></td>
|
||||
<td><a class="a2" href="https://allaboutbirds.org/guide/<?php echo $dbname;?>" target="top">All About Birds</a>, <a class="a2" href="https://wikipedia.org/wiki/<?php echo $dbsciname;?>" target="top">Wikipedia</a></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
@@ -1,167 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# BirdNET-Pi Welcome Wiz!
|
||||
#trap 'systemctl --user disable birdnet-pi-config-gui.service' EXIT 0
|
||||
set -x
|
||||
|
||||
birdnet_config=/home/pi/BirdNET-Pi/birdnet.conf
|
||||
|
||||
zenity --title="Welcome!" --ok-label="Next" --window-icon=/usr/share/pixmaps/red-cardinal32.png \
|
||||
--info --text="
|
||||
Thank for you installing BirdNET-Pi\!" --no-wrap --icon-name=red-cardinal
|
||||
|
||||
[ $? -eq 1 ] && exit 1
|
||||
|
||||
overview() {
|
||||
zenity --title="Configuration Wizard" --window-icon=/usr/share/pixmaps/red-cardinal32.png --width=300 --ok-label="Exit" \
|
||||
--extra-button="Next" --info --text="This will walk you through the following steps:
|
||||
|
||||
1) Change the 'pi' user password
|
||||
|
||||
2) Setting your Language, Country, Timezone, Keyboard, and WiFi Country (if applicable)
|
||||
|
||||
3) Connect to WiFi (if applicable) / Set Date and Time (if applicable)
|
||||
|
||||
4) Set BirdNET-Pi's latitude and longitude
|
||||
|
||||
5) Set the web interface and database passwords
|
||||
|
||||
6) Updating the system to use your new birdnet.conf file" --no-wrap --icon-name=red-cardinal
|
||||
|
||||
if [ $? -eq 0 ];then
|
||||
exit 0
|
||||
elif [ $? -eq 1 ];then
|
||||
open_rpi_configuration && change_password
|
||||
fi
|
||||
}
|
||||
|
||||
change_password() {
|
||||
zenity --title="Change the 'pi' user password" \
|
||||
--window-icon=/usr/share/pixmaps/red-cardinal32.png --ok-label="Back" \
|
||||
--extra-button="Continue" --info --text="Click the button labeled \"Change Password...\"
|
||||
and enter your new password in each box." --no-wrap --icon-name=red-cardinal
|
||||
|
||||
if [ $? -eq 1 ];then
|
||||
change_locale
|
||||
else
|
||||
overview
|
||||
fi
|
||||
}
|
||||
|
||||
change_locale() {
|
||||
zenity --title="Setting Language, Country, Timezone, Keyboard, and WiFI Country" \
|
||||
--window-icon=/usr/share/pixmaps/red-cardinal32.png --ok-label="Back" \
|
||||
--extra-button="Continue" --info --text="Use the right-most tab labeled \"Localisation\"
|
||||
|
||||
1) Locale: Set your Language and Country -- leave Character Set as \"UTF-8\"
|
||||
|
||||
2) Timezone: Set your Area and Location
|
||||
|
||||
3) Keyboard: Set your keyboard
|
||||
|
||||
4) WiFi Country: Choose your country from the list" --no-wrap --icon-name=red-cardinal
|
||||
|
||||
if [ $? -eq 1 ];then
|
||||
sync_clock
|
||||
else
|
||||
change_password
|
||||
fi
|
||||
}
|
||||
|
||||
sync_clock() {
|
||||
zenity --title="Connecting to WiFi/Setting the Date and Time" --window-icon=/usr/share/pixmaps/red-cardinal32.png \
|
||||
--question --ok-label="Automatically" --cancel-label="Manually" --icon-name=red-cardinal --text="Should the installation update the date and time Automatically (using the internet),
|
||||
or will you do this Manually?" --no-wrap
|
||||
if [ $? -eq 1 ];then
|
||||
get_date_and_time
|
||||
else
|
||||
setup_wifi
|
||||
fi
|
||||
}
|
||||
|
||||
get_date_and_time() {
|
||||
full_date="$(zenity --forms --title="Set the current time" --window-icon=/usr/share/pixmaps/red-cardinal32.png --add-calendar=Calendar --add-combo="Current Hour (24h)" --combo-values="01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23" --add-combo="Current Minute" --combo-values="00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59" --add-combo="Current Second" --combo-values="00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59")"
|
||||
current_date="$(echo ${full_date} | awk -F\| '{print $1}')"
|
||||
if ! [ -z $current_date ];then
|
||||
current_time="$(echo ${full_date} | awk -F\| '{print $1" "$2":"$3":"$4}')"
|
||||
sudo date -s "${current_time}"
|
||||
get_latitude
|
||||
else
|
||||
sync_clock
|
||||
fi
|
||||
}
|
||||
|
||||
setup_wifi() {
|
||||
sudo systemctl start dhcpcd
|
||||
wifi_list=""
|
||||
until [[ "${wifi_list}" == "Continue" ]];do
|
||||
wifi_list="$(zenity --title="Connect to WiFi" --extra-button="Refresh WiFi List" --window-icon=/usr/share/pixmaps/red-cardinal32.png --info --text="Use the Networking Icon in the bottom right corner of
|
||||
the screen to select your WiFi network. Enter the credentials to connect when prompted.
|
||||
|
||||
If you are currently connected to BirdNET-Pi via its Access Point and VNC/NoMachine,
|
||||
this connection will be severed as soon as the new connection is made.
|
||||
Simply connect your VNC/NoMachine client to the network which you are
|
||||
currently configuring BirdNET-Pi to use, and you will be able to resume the setup.
|
||||
|
||||
Press \"Continue\" AFTER you have connected." --ok-label="Continue" --no-wrap)"
|
||||
[ -z ${wifi_list} ] && break
|
||||
if [[ "${wifi_list}" == "Refresh WiFi List" ]];then
|
||||
sudo systemctl restart dhcpcd
|
||||
fi
|
||||
done
|
||||
|
||||
get_latitude
|
||||
}
|
||||
|
||||
open_rpi_configuration() {
|
||||
if ! pgrep rc_gui;then
|
||||
env SUDO_ASKPASS=/usr/lib/rc-gui/pwdrcg.sh sudo -AE rc_gui &
|
||||
sleep 1.5
|
||||
fi
|
||||
}
|
||||
|
||||
get_latitude() {
|
||||
new_lat="$(zenity --cancel-label="Back" --ok-label="Set" --title="Enter Your Latitude" --window-icon=/usr/share/pixmaps/red-cardinal32.png --width=300 --entry --text="Enter your Latitude.
|
||||
|
||||
A network guess: $(curl -s4 ifconfig.co/json | awk '/lat/ {print $2}' | tr -d ',')")"
|
||||
|
||||
if [ -n "$new_lat" ];then
|
||||
get_longitude
|
||||
else
|
||||
change_locale
|
||||
fi
|
||||
}
|
||||
|
||||
get_longitude() {
|
||||
new_lon="$(zenity --cancel-label="Back" --ok-label="Set" --title="Enter Your Longitude" --window-icon=/usr/share/pixmaps/red-cardinal32.png --width=300 --entry --text="Enter your Longitude.
|
||||
|
||||
A network guess: $(curl -s4 ifconfig.co/json | awk '/lon/ {print $2}' | tr -d ',')")"
|
||||
|
||||
if [ -n "$new_lon" ];then
|
||||
set_caddy_pwd
|
||||
else
|
||||
get_latitude
|
||||
fi
|
||||
}
|
||||
|
||||
set_caddy_pwd() {
|
||||
caddy_pwd="$(zenity --cancel-label="Back" --ok-label="Set" --title="Set Web Password" --window-icon=/usr/share/pixmaps/red-cardinal32.png --width=300 --entry --text="Set a new password for the web interface")"
|
||||
|
||||
if [ -n "${caddy_pwd}" ];then
|
||||
set_db_pwd
|
||||
else
|
||||
get_longitude
|
||||
fi
|
||||
}
|
||||
|
||||
set_db_pwd() {
|
||||
db_pwd="$(zenity --cancel-label="Back" --ok-label="Set" --title="Set The Database Password" --window-icon=/usr/share/pixmaps/red-cardinal32.png --width=300 --entry --text="Set a new password for the databse.")"
|
||||
|
||||
if [ -n "${db_pwd}" ];then
|
||||
rearview
|
||||
else
|
||||
set_caddy_pwd
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
overview
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors',1);
|
||||
|
||||
$latitude = $_POST["latitude"];
|
||||
$longitude = $_POST["longitude"];
|
||||
$birdweather_id = $_POST["birdweather_id"];
|
||||
$pushed_app_key = $_POST["pushed_app_key"];
|
||||
$pushed_app_secret = $_POST["pushed_app_secret"];
|
||||
|
||||
$contents = file_get_contents("/home/pi/BirdNET-Pi/birdnet.conf");
|
||||
$contents = preg_replace("/LATITUDE=.*/", "LATITUDE=$latitude", $contents);
|
||||
$contents = preg_replace("/LONGITUDE=.*/", "LONGITUDE=$longitude", $contents);
|
||||
$contents = preg_replace("/BIRDWEATHER_ID=.*/", "BIRDWEATHER_ID=$birdweather_id", $contents);
|
||||
$contents = preg_replace("/PUSHED_APP_KEY=.*/", "PUSHED_APP_KEY=$pushed_app_key", $contents);
|
||||
$contents = preg_replace("/PUSHED_APP_SECRET=.*/", "PUSHED_APP_SECRET=$pushed_app_secret", $contents);
|
||||
|
||||
$contents2 = file_get_contents("/home/pi/BirdNET-Pi/thisrun.txt");
|
||||
$contents2 = preg_replace("/LATITUDE=.*/", "LATITUDE=$latitude", $contents2);
|
||||
$contents2 = preg_replace("/LONGITUDE=.*/", "LONGITUDE=$longitude", $contents2);
|
||||
$contents2 = preg_replace("/BIRDWEATHER_ID=.*/", "BIRDWEATHER_ID=$birdweather_id", $contents2);
|
||||
$contents2 = preg_replace("/PUSHED_APP_KEY=.*/", "PUSHED_APP_KEY=$pushed_app_key", $contents2);
|
||||
$contents2 = preg_replace("/PUSHED_APP_SECRET=.*/", "PUSHED_APP_SECRET=$pushed_app_secret", $contents2);
|
||||
|
||||
$fh = fopen("/home/pi/BirdNET-Pi/birdnet.conf", "w");
|
||||
$fh2 = fopen("/home/pi/BirdNET-Pi/thisrun.txt", "w");
|
||||
fwrite($fh, $contents);
|
||||
fwrite($fh2, $contents2);
|
||||
session_start();
|
||||
$_SESSION['success'] = 1;
|
||||
if(isset($_POST["normal"])){
|
||||
header('Location:config.php');
|
||||
}else{
|
||||
header('Location:../../');
|
||||
}
|
||||
|
||||
$language = $_POST["language"];
|
||||
if ($language != "none"){
|
||||
$command = "sudo -upi mv /home/pi/BirdNET-Pi/model/labels.txt /home/pi/BirdNET-Pi/model/labels.txt.old && sudo -upi unzip /home/pi/BirdNET-Pi/model/labels_l18n.zip $language -d /home/pi/BirdNET-Pi/model && sudo -upi mv /home/pi/BirdNET-Pi/model/$language /home/pi/BirdNET-Pi/model/labels.txt";
|
||||
$command_output = `$command`;
|
||||
session_start();
|
||||
$_SESSION['success'] = 1;
|
||||
if(isset($_POST["normal"])){
|
||||
header('Location:config.php');
|
||||
}else{
|
||||
header('Location:../../');
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
[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
|
||||
@@ -112,3 +112,8 @@ if ! shopt -oq posix; then
|
||||
fi
|
||||
fi
|
||||
cd ~/BirdNET-Pi
|
||||
function remove() {
|
||||
find /home/pi/BirdSongs -iname *${1}* -exec rm -drfv {} +
|
||||
}
|
||||
alias rerc="source ~/.bashrc"
|
||||
alias vimrc="vim ~/.bashrc"
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=BirdNET Analysis
|
||||
Requires=${SYSTEMD_MOUNT}
|
||||
After=network-online.target ${SYSTEMD_MOUNT}
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
Type=simple
|
||||
RestartSec=1
|
||||
User=${BIRDNET_USER}
|
||||
ExecStart=/usr/local/bin/birdnet_analysis.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=BirdNET Analysis Log
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Type=simple
|
||||
User=${BIRDNET_USER}
|
||||
Environment=TERM=xterm-256color
|
||||
ExecStart=/usr/local/bin/gotty -p 8080 --title-format "BirdNET-Lite Log" journalctl -fu birdnet_analysis.service
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=BirdNET Recording
|
||||
[Service]
|
||||
Environment=XDG_RUNTIME_DIR=/run/user/1000
|
||||
Restart=always
|
||||
Type=simple
|
||||
RestartSec=3
|
||||
User=${BIRDNET_USER}
|
||||
ExecStart=/usr/local/bin/birdnet_recording.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=BirdNET Statistics Log
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Type=simple
|
||||
User=${BIRDNET_USER}
|
||||
Environment=TERM=xterm-256color
|
||||
ExecStart=/usr/local/bin/gotty -p 9090 --title-format "BirdNET-Lite Statistics" /usr/local/bin/birdnet_stats.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=A BirdNET-Lite Web Terminal
|
||||
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Type=simple
|
||||
User=${BIRDNET_USER}
|
||||
Environment=TERM=xterm-256color
|
||||
ExecStart=/usr/local/bin/gotty -w --title-format "Login!" -p 9111 tmux new -A -s Login sudo bash -c login
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,10 +0,0 @@
|
||||
[Unit]
|
||||
Description=BirdNET BirdSound Extraction
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Type=simple
|
||||
User=${BIRDNET_USER}
|
||||
ExecStart=/usr/local/bin/extract_new_birdsounds.sh
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,8 +0,0 @@
|
||||
[Unit]
|
||||
Description=BirdNET BirdSound Extraction Timer
|
||||
Requires=extraction.service
|
||||
[Timer]
|
||||
Unit=extraction.service
|
||||
OnCalendar=*:*:0/10
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=BirdNET Extraction Log
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Type=simple
|
||||
User=${BIRDNET_USER}
|
||||
Environment=TERM=xterm-256color
|
||||
ExecStart=/usr/local/bin/gotty -p 8888 --title-format "Extractions Log" journalctl -fu extraction.service
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=BirdNET-Pi Live Stream
|
||||
[Service]
|
||||
Environment=XDG_RUNTIME_DIR=/run/user/1000
|
||||
Restart=always
|
||||
Type=simple
|
||||
RestartSec=3
|
||||
User=${BIRDNET_USER}
|
||||
ExecStart=ffmpeg -loglevel 52 -ac 2 -f alsa -i ${REC_CARD} -acodec libmp3lame -b:a 320k -ac 2 -content_type 'audio/mpeg' -f mp3 icecast://source:${ICE_PWD}@localhost:8000/stream -re
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -397,7 +397,7 @@ HIDE_TOTALS=false
|
||||
; Example : HIDE_NETWORK_INTERFACE="eth0,sit0"
|
||||
; HIDE_NETWORK_INTERFACE=true //hide all network interfaces
|
||||
;
|
||||
HIDE_NETWORK_INTERFACE="lo"
|
||||
HIDE_NETWORK_INTERFACE=""
|
||||
|
||||
|
||||
; Use a regular expression in the name of a hidden network interface (e.g. HIDE_NETWORK_INTERFACE="docker.*")
|
||||
@@ -785,7 +785,7 @@ USE_REGEX=false
|
||||
;
|
||||
; string contains a list of process names that are checked, names are seperated by a comma (on WinNT names must end with '.exe')
|
||||
;
|
||||
PROCESSES="avahi-daemon,gotty,sshd,mariadbd,ffmpeg,vncserver-x11-serviced,nxd,bash"
|
||||
PROCESSES="avahi-daemon,gotty,sshd,ffmpeg,icecast2,arecord,server.py"
|
||||
|
||||
|
||||
[quotas]
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
[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
|
||||
+13
@@ -1,3 +1,16 @@
|
||||
# 0.13
|
||||
- Removed secondary and tertiary custom URLs
|
||||
- Added new custom-compiled GoTTY binary
|
||||
- All new web interface
|
||||
- SQLite database replaced MariaDB
|
||||
- Better service controls
|
||||
- Spectrogram views
|
||||
- Privacy server.py for testing
|
||||
- New mobile view
|
||||
- Moved (nearly) all CSS to style.css
|
||||
- Added "try/except" to server.py to fail BirdWeather
|
||||
POSTing gracefully and not kill the service
|
||||
|
||||
# main v.11.1
|
||||
- `server.py` socket
|
||||
- Removed DB password from scripts
|
||||
|
||||
Reference in New Issue
Block a user