This commit is contained in:
lloydbayley
2023-05-03 23:02:05 +10:00
18 changed files with 83 additions and 25 deletions
+1 -1
View File
@@ -66,7 +66,7 @@ Currently listening in these countries . . . that I know of . . .
* **Automatic extraction and cataloguing** of bird sounds * **Automatic extraction and cataloguing** of bird sounds
* **Tools to visualize your recorded bird data** and analyze trends * **Tools to visualize your recorded bird data** and analyze trends
* **Live audio stream and spectrogram** * **Live audio stream and spectrogram**
* **Automatic disk space management** that periodically purges old audio files to manage disk space * **Automatic disk space management** that periodically purges old audio files
* [BirdWeather](https://app.birdweather.com) integration -- you can request a BirdWeather ID from BirdNET-Pi's "Tools" > "Settings" page * [BirdWeather](https://app.birdweather.com) integration -- you can request a BirdWeather ID from BirdNET-Pi's "Tools" > "Settings" page
* Web interface access to all data and logs provided by [Caddy](https://caddyserver.com) * Web interface access to all data and logs provided by [Caddy](https://caddyserver.com)
* [GoTTY](https://github.com/yudai/gotty) Web Terminal * [GoTTY](https://github.com/yudai/gotty) Web Terminal
+1
View File
@@ -78,6 +78,7 @@ APPRISE_WEEKLY_REPORT=1
APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=0 APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=0
APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=0 APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=0
APPRISE_ONLY_NOTIFY_SPECIES_NAMES="" APPRISE_ONLY_NOTIFY_SPECIES_NAMES=""
APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=""
#---------------------- Flickr Images API Configuration -----------------------# #---------------------- Flickr Images API Configuration -----------------------#
## If FLICKR_API_KEY is set, the web interface will try and display bird images ## If FLICKR_API_KEY is set, the web interface will try and display bird images
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10 -5
View File
@@ -54,6 +54,7 @@ if(isset($_GET["latitude"])){
$model = $_GET["model"]; $model = $_GET["model"];
$sf_thresh = $_GET["sf_thresh"]; $sf_thresh = $_GET["sf_thresh"];
$only_notify_species_names = $_GET['only_notify_species_names']; $only_notify_species_names = $_GET['only_notify_species_names'];
$only_notify_species_names_2 = $_GET['only_notify_species_names_2'];
if(isset($_GET['apprise_notify_each_detection'])) { if(isset($_GET['apprise_notify_each_detection'])) {
$apprise_notify_each_detection = 1; $apprise_notify_each_detection = 1;
@@ -120,7 +121,7 @@ if(isset($_GET["latitude"])){
// Archive old language file // Archive old language file
syslog_shell_exec("cp -f $home/BirdNET-Pi/model/labels.txt $home/BirdNET-Pi/model/labels.txt.old", $user); syslog_shell_exec("cp -f $home/BirdNET-Pi/model/labels.txt $home/BirdNET-Pi/model/labels.txt.old", $user);
if($model == "BirdNET_GLOBAL_3K_V2.2_Model_FP16"){ if($model == "BirdNET_GLOBAL_3K_V2.3_Model_FP16"){
// Install new language label file // Install new language label file
syslog_shell_exec("sudo chmod +x $home/BirdNET-Pi/scripts/install_language_label_nm.sh && $home/BirdNET-Pi/scripts/install_language_label_nm.sh -l $language", $user); syslog_shell_exec("sudo chmod +x $home/BirdNET-Pi/scripts/install_language_label_nm.sh && $home/BirdNET-Pi/scripts/install_language_label_nm.sh -l $language", $user);
} else { } else {
@@ -150,6 +151,7 @@ if(isset($_GET["latitude"])){
$contents = preg_replace("/MODEL=.*/", "MODEL=$model", $contents); $contents = preg_replace("/MODEL=.*/", "MODEL=$model", $contents);
$contents = preg_replace("/SF_THRESH=.*/", "SF_THRESH=$sf_thresh", $contents); $contents = preg_replace("/SF_THRESH=.*/", "SF_THRESH=$sf_thresh", $contents);
$contents = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"$only_notify_species_names\"", $contents); $contents = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"$only_notify_species_names\"", $contents);
$contents = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=\"$only_notify_species_names_2\"", $contents);
$contents2 = file_get_contents("./scripts/thisrun.txt"); $contents2 = file_get_contents("./scripts/thisrun.txt");
$contents2 = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents2); $contents2 = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents2);
@@ -169,6 +171,7 @@ if(isset($_GET["latitude"])){
$contents2 = preg_replace("/MODEL=.*/", "MODEL=$model", $contents2); $contents2 = preg_replace("/MODEL=.*/", "MODEL=$model", $contents2);
$contents2 = preg_replace("/SF_THRESH=.*/", "SF_THRESH=$sf_thresh", $contents2); $contents2 = preg_replace("/SF_THRESH=.*/", "SF_THRESH=$sf_thresh", $contents2);
$contents2 = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"$only_notify_species_names\"", $contents2); $contents2 = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"$only_notify_species_names\"", $contents2);
$contents2 = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=\"$only_notify_species_names_2\"", $contents2);
@@ -325,7 +328,7 @@ if (!isset($_SERVER['PHP_AUTH_USER'])) {
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
document.getElementById('modelsel').addEventListener('change', function() { document.getElementById('modelsel').addEventListener('change', function() {
if(this.value == "BirdNET_GLOBAL_3K_V2.2_Model_FP16"){ if(this.value == "BirdNET_GLOBAL_3K_V2.3_Model_FP16"){
document.getElementById("soft").style.display="unset"; document.getElementById("soft").style.display="unset";
} else { } else {
document.getElementById("soft").style.display="none"; document.getElementById("soft").style.display="none";
@@ -357,7 +360,7 @@ function sendTestNotification(e) {
<label for="model">Select a Model: </label> <label for="model">Select a Model: </label>
<select id="modelsel" name="model"> <select id="modelsel" name="model">
<?php <?php
$models = array("BirdNET_6K_GLOBAL_MODEL", "BirdNET_GLOBAL_3K_V2.2_Model_FP16"); $models = array("BirdNET_6K_GLOBAL_MODEL", "BirdNET_GLOBAL_3K_V2.3_Model_FP16");
foreach($models as $modelName){ foreach($models as $modelName){
$isSelected = ""; $isSelected = "";
if($config['MODEL'] == $modelName){ if($config['MODEL'] == $modelName){
@@ -473,7 +476,7 @@ function runProcess() {
<dt>BirdNET_6K_GLOBAL_MODEL (2020)</dt><br> <dt>BirdNET_6K_GLOBAL_MODEL (2020)</dt><br>
<dd id="ddnewline">This is the BirdNET-Lite model, with bird sound recognition for more than 6,000 species worldwide. This is the default option and will generally work very for people in most of the world.</dd> <dd id="ddnewline">This is the BirdNET-Lite model, with bird sound recognition for more than 6,000 species worldwide. This is the default option and will generally work very for people in most of the world.</dd>
<br> <br>
<dt>BirdNET_GLOBAL_3K_V2.2_Model_FP16 (2022)</dt><br> <dt>BirdNET_GLOBAL_3K_V2.3_Model_FP16 (2022)</dt><br>
<dd id="ddnewline">This is the BirdNET-Analyzer model, a newer work-in-progress project with aims to improve on the BirdNET-Lite model. Currently it only supports about 3,500 species worldwide, meaning for some regions (North America, Europe, Australia) it will usually outperform the BirdNET-Lite model, but for other regions it will be worse.</dd><br> <dd id="ddnewline">This is the BirdNET-Analyzer model, a newer work-in-progress project with aims to improve on the BirdNET-Lite model. Currently it only supports about 3,500 species worldwide, meaning for some regions (North America, Europe, Australia) it will usually outperform the BirdNET-Lite model, but for other regions it will be worse.</dd><br>
<dt>[ In-depth technical write-up on the models <a target="_blank" href="https://github.com/mcguirepr89/BirdNET-Pi/wiki/BirdNET-Pi:-some-theory-on-classification-&-some-practical-hints">here</a> ]</dt> <dt>[ In-depth technical write-up on the models <a target="_blank" href="https://github.com/mcguirepr89/BirdNET-Pi/wiki/BirdNET-Pi:-some-theory-on-classification-&-some-practical-hints">here</a> ]</dt>
</dl> </dl>
@@ -550,7 +553,9 @@ https://discordapp.com/api/webhooks/{WebhookID}/{WebhookToken}
<label for="minimum_time_limit">Minimum time between notifications of the same species (sec):</label> <label for="minimum_time_limit">Minimum time between notifications of the same species (sec):</label>
<input type="number" id="minimum_time_limit" name="minimum_time_limit" value="<?php echo $config['APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES'];?>" min="0"><br> <input type="number" id="minimum_time_limit" name="minimum_time_limit" value="<?php echo $config['APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES'];?>" min="0"><br>
<label for="only_notify_species_names">Exclude these species (comma separated common names):</label> <label for="only_notify_species_names">Exclude these species (comma separated common names):</label>
<input type="text" id="only_notify_species_names" placeholder="Northern Cardinal,American Crow,Carolina Chickadee" name="only_notify_species_names" value="<?php echo $config['APPRISE_ONLY_NOTIFY_SPECIES_NAMES'];?>" size=96><br> <input type="text" id="only_notify_species_names" placeholder="Mourning Dove,American Crow" name="only_notify_species_names" value="<?php echo $config['APPRISE_ONLY_NOTIFY_SPECIES_NAMES'];?>" size=96><br>
<label for="only_notify_species_names_2">ONLY notify for these species (comma separated common names):</label>
<input type="text" id="only_notify_species_names_2" placeholder="Northern Cardinal,Carolina Chickadee,Eastern Bluebird" name="only_notify_species_names_2" value="<?php echo $config['APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2'];?>" size=96><br>
<br> <br>
+1
View File
@@ -106,6 +106,7 @@ APPRISE_WEEKLY_REPORT=1
APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=0 APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=0
APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=0 APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=0
APPRISE_ONLY_NOTIFY_SPECIES_NAMES="" APPRISE_ONLY_NOTIFY_SPECIES_NAMES=""
APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=""
#---------------------- Flickr Images API Configuration -----------------------# #---------------------- Flickr Images API Configuration -----------------------#
## If FLICKR_API_KEY is set, the web interface will try and display bird images ## If FLICKR_API_KEY is set, the web interface will try and display bird images
+3 -3
View File
@@ -309,8 +309,8 @@ body::-webkit-scrollbar {
</style> </style>
</head> </head>
<div class="overview"> <div class="overview">
<dialog style="margin-top: 5px;max-height: 100vh; <dialog style="margin-top: 5px;max-height: 95vh;
overflow-y: auto;" id="attribution-dialog"> overflow-y: auto;overscroll-behavior:contain" id="attribution-dialog">
<h1 id="modalHeading"></h1> <h1 id="modalHeading"></h1>
<p id="modalText"></p> <p id="modalText"></p>
<button onclick="hideDialog()">Close</button> <button onclick="hideDialog()">Close</button>
@@ -349,7 +349,7 @@ body::-webkit-scrollbar {
function setModalText(iter, title, text, authorlink, photolink, licenseurl) { function setModalText(iter, title, text, authorlink, photolink, licenseurl) {
document.getElementById('modalHeading').innerHTML = "Photo: \""+decodeURIComponent(title.replaceAll("+"," "))+"\" Attribution"; document.getElementById('modalHeading').innerHTML = "Photo: \""+decodeURIComponent(title.replaceAll("+"," "))+"\" Attribution";
document.getElementById('modalText').innerHTML = "<div><img style='border-radius:5px;max-height: calc(100vh - 15rem);display: block;margin: 0 auto;' src='"+photolink+"'></div><br><div>Image link: <a target='_blank' href="+text+">"+text+"</a><br>Author link: <a target='_blank' href="+authorlink+">"+authorlink+"</a><br>License URL: <a href="+licenseurl+" target='_blank'>"+licenseurl+"</a></div>"; document.getElementById('modalText').innerHTML = "<div><img style='border-radius:5px;max-height: calc(100vh - 15rem);display: block;margin: 0 auto;' src='"+photolink+"'></div><br><div style='white-space:nowrap'>Image link: <a target='_blank' href="+text+">"+text+"</a><br>Author link: <a target='_blank' href="+authorlink+">"+authorlink+"</a><br>License URL: <a href="+licenseurl+" target='_blank'>"+licenseurl+"</a></div>";
last_photo_link = text; last_photo_link = text;
showDialog(); showDialog();
} }
+3 -3
View File
@@ -231,7 +231,7 @@ function toggleLock(filename, type, elem) {
elem.setAttribute("onclick", elem.getAttribute("onclick").replace("add","del")); elem.setAttribute("onclick", elem.getAttribute("onclick").replace("add","del"));
} else { } else {
elem.setAttribute("src","images/unlock.svg"); elem.setAttribute("src","images/unlock.svg");
elem.setAttribute("title", "This file is not excluded from being purged."); elem.setAttribute("title", "This file will be deleted when disk space needs to be freed.");
elem.setAttribute("onclick", elem.getAttribute("onclick").replace("del","add")); elem.setAttribute("onclick", elem.getAttribute("onclick").replace("del","add"));
} }
} }
@@ -489,7 +489,7 @@ echo "<table>
if($config["FULL_DISK"] == "purge") { if($config["FULL_DISK"] == "purge") {
if(!in_array($filename_formatted, $disk_check_exclude_arr)) { if(!in_array($filename_formatted, $disk_check_exclude_arr)) {
$imageicon = "images/unlock.svg"; $imageicon = "images/unlock.svg";
$title = "This file is not excluded from being purged."; $title = "This file will be deleted when disk space needs to be freed (>95% usage).";
$type = "add"; $type = "add";
} else { } else {
$imageicon = "images/lock.svg"; $imageicon = "images/lock.svg";
@@ -564,7 +564,7 @@ echo "<table>
if($config["FULL_DISK"] == "purge") { if($config["FULL_DISK"] == "purge") {
if(!in_array($filename_formatted, $disk_check_exclude_arr)) { if(!in_array($filename_formatted, $disk_check_exclude_arr)) {
$imageicon = "images/unlock.svg"; $imageicon = "images/unlock.svg";
$title = "This file is not excluded from being purged."; $title = "This file will be deleted when disk space needs to be freed (>95% usage).";
$type = "add"; $type = "add";
} else { } else {
$imageicon = "images/lock.svg"; $imageicon = "images/lock.svg";
+4 -4
View File
@@ -71,7 +71,7 @@ def loadModel():
print('LOADING TF LITE MODEL...', end=' ') print('LOADING TF LITE MODEL...', end=' ')
# Load TFLite model and allocate tensors. # Load TFLite model and allocate tensors.
# model will either be BirdNET_GLOBAL_3K_V2.2_Model_FP16 (new) or BirdNET_6K_GLOBAL_MODEL (old) # model will either be BirdNET_GLOBAL_3K_V2.3_Model_FP16 (new) or BirdNET_6K_GLOBAL_MODEL (old)
modelpath = userDir + '/BirdNET-Pi/model/'+model+'.tflite' modelpath = userDir + '/BirdNET-Pi/model/'+model+'.tflite'
myinterpreter = tflite.Interpreter(model_path=modelpath, num_threads=2) myinterpreter = tflite.Interpreter(model_path=modelpath, num_threads=2)
myinterpreter.allocate_tensors() myinterpreter.allocate_tensors()
@@ -104,7 +104,7 @@ def loadMetaModel():
global M_OUTPUT_LAYER_INDEX global M_OUTPUT_LAYER_INDEX
# Load TFLite model and allocate tensors. # Load TFLite model and allocate tensors.
M_INTERPRETER = tflite.Interpreter(model_path=userDir + '/BirdNET-Pi/model/BirdNET_GLOBAL_3K_V2.2_MData_Model_FP16.tflite') M_INTERPRETER = tflite.Interpreter(model_path=userDir + '/BirdNET-Pi/model/BirdNET_GLOBAL_3K_V2.3_MData_Model_FP16.tflite')
M_INTERPRETER.allocate_tensors() M_INTERPRETER.allocate_tensors()
# Get input and output tensors. # Get input and output tensors.
@@ -272,7 +272,7 @@ def analyzeAudioData(chunks, lat, lon, week, sensitivity, overlap,):
start = time.time() start = time.time()
print('ANALYZING AUDIO...', end=' ', flush=True) print('ANALYZING AUDIO...', end=' ', flush=True)
if model == "BirdNET_GLOBAL_3K_V2.2_Model_FP16": if model == "BirdNET_GLOBAL_3K_V2.3_Model_FP16":
if len(PREDICTED_SPECIES_LIST) == 0 or len(INCLUDE_LIST) != 0: if len(PREDICTED_SPECIES_LIST) == 0 or len(INCLUDE_LIST) != 0:
predictSpeciesList(lat,lon,week) predictSpeciesList(lat,lon,week)
@@ -584,7 +584,7 @@ def handle_client(conn, addr):
post_commonName = "\"commonName\": \"" + entry[0].split('_')[1].split("/")[0] + "\"," post_commonName = "\"commonName\": \"" + entry[0].split('_')[1].split("/")[0] + "\","
post_scientificName = "\"scientificName\": \"" + entry[0].split('_')[0] + "\"," post_scientificName = "\"scientificName\": \"" + entry[0].split('_')[0] + "\","
if model == "BirdNET_GLOBAL_3K_V2.2_Model_FP16": if model == "BirdNET_GLOBAL_3K_V2.3_Model_FP16":
post_algorithm = "\"algorithm\": " + "\"2p2\"" + "," post_algorithm = "\"algorithm\": " + "\"2p2\"" + ","
else: else:
post_algorithm = "\"algorithm\": " + "\"alpha\"" + "," post_algorithm = "\"algorithm\": " + "\"alpha\"" + ","
+1 -1
View File
@@ -31,7 +31,7 @@ def loadMetaModel():
global CLASSES global CLASSES
# Load TFLite model and allocate tensors. # Load TFLite model and allocate tensors.
M_INTERPRETER = tflite.Interpreter(model_path=userDir + '/BirdNET-Pi/model/BirdNET_GLOBAL_3K_V2.2_MData_Model_FP16.tflite') M_INTERPRETER = tflite.Interpreter(model_path=userDir + '/BirdNET-Pi/model/BirdNET_GLOBAL_3K_V2.3_MData_Model_FP16.tflite')
M_INTERPRETER.allocate_tensors() M_INTERPRETER.allocate_tensors()
# Get input and output tensors. # Get input and output tensors.
+3 -2
View File
@@ -142,7 +142,8 @@ tr:first-child td {
</style> </style>
</div> </div>
<dialog id="attribution-dialog"> <dialog style="margin-top: 5px;max-height: 95vh;
overflow-y: auto;overscroll-behavior:contain" id="attribution-dialog">
<h1 id="modalHeading"></h1> <h1 id="modalHeading"></h1>
<p id="modalText"></p> <p id="modalText"></p>
<button onclick="hideDialog()">Close</button> <button onclick="hideDialog()">Close</button>
@@ -162,7 +163,7 @@ function hideDialog() {
function setModalText(iter, title, text, authorlink) { function setModalText(iter, title, text, authorlink) {
document.getElementById('modalHeading').innerHTML = "Photo "+iter+": \""+title+"\" Attribution"; document.getElementById('modalHeading').innerHTML = "Photo "+iter+": \""+title+"\" Attribution";
document.getElementById('modalText').innerHTML = "Image link: <a target='_blank' href="+text+">"+text+"</a><br>Author link: <a target='_blank' href="+authorlink+">"+authorlink+"</a>"; document.getElementById('modalText').innerHTML = "<div style='white-space:nowrap'>Image link: <a target='_blank' href="+text+">"+text+"</a><br>Author link: <a target='_blank' href="+authorlink+">"+authorlink+"</a></div>";
showDialog(); showDialog();
} }
</script> </script>
+8
View File
@@ -44,4 +44,12 @@ function update() {
<form action="" method="GET"> <form action="" method="GET">
<button type="submit" name="submit" value="sudo clear_all_data.sh" onclick="return confirm('Clear ALL Data? Note that this cannot be undone and will take up to 90 seconds.')">Clear ALL data</button> <button type="submit" name="submit" value="sudo clear_all_data.sh" onclick="return confirm('Clear ALL Data? Note that this cannot be undone and will take up to 90 seconds.')">Clear ALL data</button>
</form> </form>
<?php
$cmd="cd ".$home."/BirdNET-Pi && sudo -u ".$user." git rev-list --max-count=1 HEAD";
$curr_hash = shell_exec($cmd);
?>
<p style="font-size:11px;text-align:center"></br></br>Running version: </p>
<a href="https://github.com/mcguirepr89/BirdNET-Pi/commit/<?php echo $curr_hash; ?>" target="_blank">
<p style="font-size:11px;text-align:center;box-sizing: border-box"><?php echo $curr_hash; ?></p>
</a>
</div> </div>
+30 -6
View File
@@ -230,6 +230,7 @@ if(isset($_GET['ajax_detections']) && $_GET['ajax_detections'] == "true" ) {
$comname = preg_replace('/ /', '_', $todaytable['Com_Name']); $comname = preg_replace('/ /', '_', $todaytable['Com_Name']);
$comname = preg_replace('/\'/', '_', $comname); $comname = preg_replace('/\'/', '_', $comname);
$filename = "/By_Date/".date('Y-m-d')."/".$comname."/".$todaytable['File_Name']; $filename = "/By_Date/".date('Y-m-d')."/".$comname."/".$todaytable['File_Name'];
$filename_formatted = $todaytable['Date']."/".$comname."/".$todaytable['File_Name'];
$sciname = preg_replace('/ /', '_', $todaytable['Sci_Name']); $sciname = preg_replace('/ /', '_', $todaytable['Sci_Name']);
$args = "&license=2%2C3%2C4%2C5%2C6%2C9&orientation=square,portrait"; $args = "&license=2%2C3%2C4%2C5%2C6%2C9&orientation=square,portrait";
$comnameprefix = "%20bird"; $comnameprefix = "%20bird";
@@ -308,7 +309,9 @@ if(isset($_GET['ajax_detections']) && $_GET['ajax_detections'] == "true" ) {
?> ?>
<?php if(isset($_GET['display_limit']) && is_numeric($_GET['display_limit'])){ ?> <?php if(isset($_GET['display_limit']) && is_numeric($_GET['display_limit'])){ ?>
<tr class="relative" id="<?php echo $iterations; ?>"> <tr class="relative" id="<?php echo $iterations; ?>">
<td class="relative"><a target="_blank" href="index.php?filename=<?php echo $todaytable['File_Name']; ?>"><img class="copyimage" title="Open in new tab" width=25 src="images/copy.png"></a> <td class="relative">
<img style='cursor:pointer;right:45px' src='images/delete.svg' onclick='deleteDetection("<?php echo $filename_formatted; ?>")' class="copyimage" width=25 title='Delete Detection'>
<a target="_blank" href="index.php?filename=<?php echo $todaytable['File_Name']; ?>"><img class="copyimage" title="Open in new tab" width=25 src="images/copy.png"></a>
<div class="centered_image_container"> <div class="centered_image_container">
@@ -419,8 +422,8 @@ die();
</style> </style>
</head> </head>
<div class="viewdb"> <div class="viewdb">
<dialog style="margin-top: 5px;max-height: 100vh; <dialog style="margin-top: 5px;max-height: 95vh;
overflow-y: auto;" id="attribution-dialog"> overflow-y: auto;overscroll-behavior:contain" id="attribution-dialog">
<h1 id="modalHeading"></h1> <h1 id="modalHeading"></h1>
<p id="modalText"></p> <p id="modalText"></p>
<button style="font-weight:bold;color:blue" onclick="hideDialog()">Close</button> <button style="font-weight:bold;color:blue" onclick="hideDialog()">Close</button>
@@ -431,6 +434,25 @@ die();
<script src="static/chartjs-plugin-trendline.min.js"></script> <script src="static/chartjs-plugin-trendline.min.js"></script>
<script> <script>
function deleteDetection(filename,copylink=false) {
if (confirm("Are you sure you want to delete this detection from the database?") == true) {
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
if(this.responseText == "OK"){
if(copylink == true) {
window.top.close();
} else {
location.reload();
}
} else {
alert("Database busy.")
}
}
xhttp.open("GET", "play.php?deletefile="+filename, true);
xhttp.send();
}
}
var last_photo_link; var last_photo_link;
var dialog = document.querySelector('dialog'); var dialog = document.querySelector('dialog');
dialogPolyfill.registerDialog(dialog); dialogPolyfill.registerDialog(dialog);
@@ -461,9 +483,9 @@ die();
function setModalText(iter, title, text, authorlink, photolink, licenseurl) { function setModalText(iter, title, text, authorlink, photolink, licenseurl) {
document.getElementById('modalHeading').innerHTML = "Photo: \""+decodeURIComponent(title.replaceAll("+"," "))+"\" Attribution"; document.getElementById('modalHeading').innerHTML = "Photo: \""+decodeURIComponent(title.replaceAll("+"," "))+"\" Attribution";
<?php if($kiosk == false) { ?> <?php if($kiosk == false) { ?>
document.getElementById('modalText').innerHTML = "<div><img style='border-radius:5px;max-height: calc(100vh - 15rem);display: block;margin: 0 auto;' src='"+photolink+"'></div><br><div>Image link: <a target='_blank' href="+text+">"+text+"</a><br>Author link: <a target='_blank' href="+authorlink+">"+authorlink+"</a><br>License URL: <a href="+licenseurl+" target='_blank'>"+licenseurl+"</a></div>"; document.getElementById('modalText').innerHTML = "<div><img style='border-radius:5px;max-height: calc(100vh - 15rem);display: block;margin: 0 auto;' src='"+photolink+"'></div><br><div style='white-space:nowrap'>Image link: <a target='_blank' href="+text+">"+text+"</a><br>Author link: <a target='_blank' href="+authorlink+">"+authorlink+"</a><br>License URL: <a href="+licenseurl+" target='_blank'>"+licenseurl+"</a></div>";
<?php } else { ?> <?php } else { ?>
document.getElementById('modalText').innerHTML = "<div><img style='border-radius:5px;max-height: calc(100vh - 15rem);display: block;margin: 0 auto;' src='"+photolink+"'></div><br><div>Image link: <a target='_blank'>"+text+"</a><br>Author link: <a target='_blank'>"+authorlink+"</a><br>License URL: <a target='_blank'>"+licenseurl+"</a></div>"; document.getElementById('modalText').innerHTML = "<div><img style='border-radius:5px;max-height: calc(100vh - 15rem);display: block;margin: 0 auto;' src='"+photolink+"'></div><br><div style='white-space:nowrap'>Image link: <a target='_blank'>"+text+"</a><br>Author link: <a target='_blank'>"+authorlink+"</a><br>License URL: <a target='_blank'>"+licenseurl+"</a></div>";
<?php } ?> <?php } ?>
last_photo_link = text; last_photo_link = text;
showDialog(); showDialog();
@@ -570,7 +592,9 @@ function searchDetections(searchvalue) {
function loadDetections(detections_limit, element=undefined) { function loadDetections(detections_limit, element=undefined) {
const xhttp = new XMLHttpRequest(); const xhttp = new XMLHttpRequest();
xhttp.onload = function() { xhttp.onload = function() {
document.getElementsByClassName("legacyview")[0].style.display="unset"; <?php if($kiosk == false) { ?>
document.getElementsByClassName("legacyview")[0].style.display="unset";
<?php } ?>
if(typeof element !== "undefined") if(typeof element !== "undefined")
{ {
element.remove(); element.remove();
+13
View File
@@ -190,6 +190,9 @@ fi
if ! grep APPRISE_ONLY_NOTIFY_SPECIES_NAMES /etc/birdnet/birdnet.conf &>/dev/null;then if ! grep APPRISE_ONLY_NOTIFY_SPECIES_NAMES /etc/birdnet/birdnet.conf &>/dev/null;then
sudo -u$USER echo "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"\"" >> /etc/birdnet/birdnet.conf sudo -u$USER echo "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"\"" >> /etc/birdnet/birdnet.conf
fi fi
if ! grep APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2 /etc/birdnet/birdnet.conf &>/dev/null;then
sudo -u$USER echo "APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=\"\"" >> /etc/birdnet/birdnet.conf
fi
if ! grep RTSP_STREAM_TO_LIVESTREAM /etc/birdnet/birdnet.conf &>/dev/null;then if ! grep RTSP_STREAM_TO_LIVESTREAM /etc/birdnet/birdnet.conf &>/dev/null;then
sudo -u$USER echo "RTSP_STREAM_TO_LIVESTREAM=\"0\"" >> /etc/birdnet/birdnet.conf sudo -u$USER echo "RTSP_STREAM_TO_LIVESTREAM=\"0\"" >> /etc/birdnet/birdnet.conf
@@ -214,5 +217,15 @@ if ! grep LogLevel_SpectrogramViewerService /etc/birdnet/birdnet.conf &>/dev/nul
sudo -u$USER echo "LogLevel_SpectrogramViewerService=\"error\"" >> /etc/birdnet/birdnet.conf sudo -u$USER echo "LogLevel_SpectrogramViewerService=\"error\"" >> /etc/birdnet/birdnet.conf
fi fi
if grep -q '^MODEL=BirdNET_GLOBAL_3K_V2.2_Model_FP16$' /etc/birdnet/birdnet.conf;then
language=$(grep "^DATABASE_LANG=" /etc/birdnet/birdnet.conf | cut -d= -f2)
sed -i 's/BirdNET_GLOBAL_3K_V2.2_Model_FP16/BirdNET_GLOBAL_3K_V2.3_Model_FP16/' /etc/birdnet/birdnet.conf
sed -i 's/BirdNET_GLOBAL_3K_V2.2_Model_FP16/BirdNET_GLOBAL_3K_V2.3_Model_FP16/' $HOME/BirdNET-Pi/scripts/thisrun.txt
sed -i 's/BirdNET_GLOBAL_3K_V2.2_Model_FP16/BirdNET_GLOBAL_3K_V2.3_Model_FP16/' $HOME/BirdNET-Pi/birdnet.conf
cp -f $HOME/BirdNET-Pi/model/labels.txt $HOME/BirdNET-Pi/model/labels.txt.old
sudo chmod +x $HOME/BirdNET-Pi/scripts/install_language_label_nm.sh && $HOME/BirdNET-Pi/scripts/install_language_label_nm.sh -l "$language"
fi
sudo systemctl daemon-reload sudo systemctl daemon-reload
restart_services.sh restart_services.sh
+5
View File
@@ -52,6 +52,11 @@ def sendAppriseNotifications(species, confidence, path, date, time, week, latitu
if any(bird.lower().replace(" ", "") in comName.lower().replace(" ", "") for bird in APPRISE_ONLY_NOTIFY_SPECIES_NAMES.split(",")): if any(bird.lower().replace(" ", "") in comName.lower().replace(" ", "") for bird in APPRISE_ONLY_NOTIFY_SPECIES_NAMES.split(",")):
return return
APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2 = settings_dict.get('APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2')
if APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2 is not None and APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2.strip() != "":
if not any(bird.lower().replace(" ", "") in comName.lower().replace(" ", "") for bird in APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2.split(",")):
return
APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES = settings_dict.get('APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES') APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES = settings_dict.get('APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES')
if APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES != "0": if APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES != "0":
if species_last_notified.get(comName) is not None: if species_last_notified.get(comName) is not None: