Merge branch 'species_stats' of github.com:mcguirepr89/BirdNET-Pi into species_stats
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -2,7 +2,7 @@
|
||||
BirdNET-Pi
|
||||
</h1>
|
||||
<p align="center">
|
||||
A realtime acoustic bird classification system for the Raspberry Pi 4B
|
||||
A realtime acoustic bird classification system for the Raspberry Pi 4B, 3B+, and 0W2
|
||||
</p>
|
||||
<p align="center">
|
||||
<img src="https://user-images.githubusercontent.com/60325264/140656397-bf76bad4-f110-467c-897d-992ff0f96476.png" />
|
||||
@@ -50,22 +50,23 @@ Currently listening in these countries . . . that I know of . . .
|
||||
* Live audio stream & spectrogram
|
||||
* [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 Terminal
|
||||
* [GoTTY](https://github.com/yudai/gotty) Web Terminal
|
||||
* [Tiny File Manager](https://tinyfilemanager.github.io/)
|
||||
* FTP server included
|
||||
* SQLite3 Database
|
||||
* Adminer database maintenance
|
||||
* [Adminer](https://www.adminer.org/) database maintenance
|
||||
* [phpSysInfo](https://github.com/phpsysinfo/phpsysinfo)
|
||||
* [Apprise Notifications](https://github.com/caronc/apprise) supporting 70+ notification platforms
|
||||
* Localization supported
|
||||
|
||||
## Requirements
|
||||
* A Raspberry Pi 4B or Raspberry Pi 3B+ (The 3B+ must run on RaspiOS-ARM64-**Lite**)
|
||||
* An SD Card with the **_64-bit version of RaspiOS_** installed (please use Bullseye) -- Lite is recommended, but the installation works on RaspiOS-ARM64-Full as well. [(Download the latest here)](https://downloads.raspberrypi.org/raspios_lite_arm64/images/)
|
||||
* A Raspberry Pi 4B, Raspberry Pi 3B+, or Raspberry Pi 0W2 (The 3B+ and 0W2 must run on RaspiOS-ARM64-**Lite**)
|
||||
* An SD Card with the **_64-bit version of RaspiOS_** installed (please use Bullseye) -- Lite is recommended, but the installation works on RaspiOS-ARM64-Full as well. Downloads available within the [Raspberry Pi Imager](https://www.raspberrypi.com/software/).
|
||||
* A USB Microphone or Sound Card
|
||||
|
||||
## Installation
|
||||
[A comprehensive installation guide is available here](https://github.com/mcguirepr89/BirdNET-Pi/wiki/Installation-Guide).
|
||||
[Raspberry Pi 0W2 installation guide available here](https://github.com/mcguirepr89/BirdNET-Pi/wiki/RPi0W2-Installation-Guide)
|
||||
|
||||
The system can be installed with:
|
||||
```
|
||||
|
||||
@@ -150,6 +150,10 @@ EXTRACTION_LENGTH=
|
||||
|
||||
AUDIOFMT=mp3
|
||||
|
||||
## DATABASE_LANG is used to set the language for the database
|
||||
|
||||
DATABASE_LANG=en
|
||||
|
||||
## These are just for debugging
|
||||
LAST_RUN=
|
||||
THIS_RUN=
|
||||
|
||||
@@ -82,6 +82,12 @@ button {
|
||||
transition:background-color 0.2s;
|
||||
}
|
||||
|
||||
.disabled{
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
opacity:0.5;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
color: blue;
|
||||
}
|
||||
@@ -687,4 +693,22 @@ dialog::backdrop {
|
||||
|
||||
#gain.centered {
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.updatenumber {
|
||||
margin-left:5px;
|
||||
position:absolute;
|
||||
display:inline-block;
|
||||
background-color:#c8191a;
|
||||
color:white;
|
||||
width:20px;
|
||||
line-height:20px;
|
||||
border-radius:12px;
|
||||
text-align:center;
|
||||
font-size:small;
|
||||
}
|
||||
|
||||
form#views button .updatenumber {
|
||||
position:initial;
|
||||
margin-left:0px;
|
||||
}
|
||||
+22
-2
@@ -1,3 +1,19 @@
|
||||
<?php
|
||||
session_start();
|
||||
$user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd");
|
||||
$home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd");
|
||||
$home = trim($home);
|
||||
if(!isset($_SESSION['behind'])) {
|
||||
$_SESSION['behind'] = trim(shell_exec("sudo git -C ".$home."/BirdNET-Pi fetch > /dev/null 2>&1 && git -C ".$home."/BirdNET-Pi status | sed -n '2 p' | cut -d ' ' -f 7"));
|
||||
}
|
||||
if(intval($_SESSION['behind']) >= 99) {?>
|
||||
<style>
|
||||
.updatenumber {
|
||||
width:30px !important;
|
||||
}
|
||||
</style>
|
||||
<?php }
|
||||
?>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<style>
|
||||
body::-webkit-scrollbar {
|
||||
@@ -31,7 +47,7 @@ body::-webkit-scrollbar {
|
||||
<button type="submit" name="view" value="View Log" form="views">View Log</button>
|
||||
</form>
|
||||
<form action="" method="GET" id="views">
|
||||
<button type="submit" name="view" value="Tools" form="views">Tools</button>
|
||||
<button type="submit" name="view" value="Tools" form="views">Tools<?php if(intval($_SESSION['behind']) >= 50){ $updatediv = ' <div class="updatenumber">'.$_SESSION["behind"].'</div>'; } else { $updatediv = ""; } echo $updatediv; ?></button>
|
||||
</form>
|
||||
<button href="javascript:void(0);" class="icon" onclick="myFunction()"><img src="images/menu.png"></button>
|
||||
</div>
|
||||
@@ -94,7 +110,7 @@ if(isset($_GET['view'])){
|
||||
<form action=\"\" method=\"GET\" 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=\"System Controls\" form=\"views\">System Controls".$updatediv."</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 Maintenance</button></a>
|
||||
@@ -264,10 +280,14 @@ if(isset($_GET['view'])){
|
||||
$tmp = explode(" ",trim($command));
|
||||
$command .= "& sleep 3;sudo systemctl status ".end($tmp);
|
||||
}
|
||||
if($initcommand == "update_birdnet.sh") {
|
||||
unset($_SESSION['behind']);
|
||||
}
|
||||
$results = shell_exec("$command 2>&1");
|
||||
$results = str_replace("FAILURE", "<span style='color:red'>FAILURE</span>", $results);
|
||||
$results = str_replace("failed", "<span style='color:red'>failed</span>",$results);
|
||||
$results = str_replace("active (running)", "<span style='color:green'><b>active (running)</b></span>",$results);
|
||||
$results = str_replace("Your branch is up to date", "<span style='color:limegreen'><b>Your branch is up to date</b></span>",$results);
|
||||
if(strlen($results) == 0) {
|
||||
$results = "This command has no output.";
|
||||
}
|
||||
|
||||
Binary file not shown.
+150
-112
@@ -2,89 +2,112 @@
|
||||
error_reporting(E_ERROR);
|
||||
ini_set('display_errors',1);
|
||||
|
||||
# Basic Settings
|
||||
if(isset($_GET["latitude"])){
|
||||
$latitude = $_GET["latitude"];
|
||||
$longitude = $_GET["longitude"];
|
||||
$birdweather_id = $_GET["birdweather_id"];
|
||||
$apprise_input = $_GET['apprise_input'];
|
||||
$apprise_notification_title = $_GET['apprise_notification_title'];
|
||||
$apprise_notification_body = $_GET['apprise_notification_body'];
|
||||
$flickr_api_key = $_GET['flickr_api_key'];
|
||||
if(isset($_GET['apprise_notify_each_detection'])) {
|
||||
$apprise_notify_each_detection = 1;
|
||||
} else {
|
||||
$apprise_notify_each_detection = 0;
|
||||
}
|
||||
if(isset($_GET['apprise_notify_new_species'])) {
|
||||
$apprise_notify_new_species = 1;
|
||||
} else {
|
||||
$apprise_notify_new_species = 0;
|
||||
}
|
||||
function syslog_shell_exec($cmd, $sudo_user = null) {
|
||||
if ($sudo_user) {
|
||||
$cmd = "sudo -u $sudo_user $cmd";
|
||||
}
|
||||
$output = shell_exec($cmd);
|
||||
|
||||
// logic for setting the date and time based on user inputs from the form below
|
||||
if(isset($_GET['date']) && isset($_GET['time'])) {
|
||||
// can't set the date manually if it's getting it from the internet, disable ntp
|
||||
exec("sudo timedatectl set-ntp false");
|
||||
|
||||
exec("sudo date -s '".$_GET['date']." ".$_GET['time']."'");
|
||||
} else {
|
||||
// user checked 'use time from internet if available,' so make sure that's on
|
||||
if(strlen(trim(exec("sudo timedatectl | grep \"NTP service: active\""))) == 0){
|
||||
exec("sudo timedatectl set-ntp true");
|
||||
sleep(3);
|
||||
if (strlen($output) > 0) {
|
||||
syslog(LOG_INFO, $output);
|
||||
}
|
||||
}
|
||||
|
||||
# Basic Settings
|
||||
if(isset($_GET["latitude"])){
|
||||
$latitude = $_GET["latitude"];
|
||||
$longitude = $_GET["longitude"];
|
||||
$birdweather_id = $_GET["birdweather_id"];
|
||||
$apprise_input = $_GET['apprise_input'];
|
||||
$apprise_notification_title = $_GET['apprise_notification_title'];
|
||||
$apprise_notification_body = $_GET['apprise_notification_body'];
|
||||
$flickr_api_key = $_GET['flickr_api_key'];
|
||||
$language = $_GET["language"];
|
||||
|
||||
if(isset($_GET['apprise_notify_each_detection'])) {
|
||||
$apprise_notify_each_detection = 1;
|
||||
} else {
|
||||
$apprise_notify_each_detection = 0;
|
||||
}
|
||||
if(isset($_GET['apprise_notify_new_species'])) {
|
||||
$apprise_notify_new_species = 1;
|
||||
} else {
|
||||
$apprise_notify_new_species = 0;
|
||||
}
|
||||
|
||||
// logic for setting the date and time based on user inputs from the form below
|
||||
if(isset($_GET['date']) && isset($_GET['time'])) {
|
||||
// can't set the date manually if it's getting it from the internet, disable ntp
|
||||
exec("sudo timedatectl set-ntp false");
|
||||
|
||||
exec("sudo date -s '".$_GET['date']." ".$_GET['time']."'");
|
||||
} else {
|
||||
// user checked 'use time from internet if available,' so make sure that's on
|
||||
if(strlen(trim(exec("sudo timedatectl | grep \"NTP service: active\""))) == 0){
|
||||
exec("sudo timedatectl set-ntp true");
|
||||
sleep(3);
|
||||
}
|
||||
}
|
||||
|
||||
// Update Language settings only if a change is requested
|
||||
if (file_exists('./scripts/thisrun.txt')) {
|
||||
$lang_config = parse_ini_file('./scripts/thisrun.txt');
|
||||
} elseif (file_exists('./scripts/firstrun.ini')) {
|
||||
$lang_config = parse_ini_file('./scripts/firstrun.ini');
|
||||
}
|
||||
if ($language != $lang_config['DATABASE_LANG']){
|
||||
$user = trim(shell_exec("awk -F: '/1000/{print $1}' /etc/passwd"));
|
||||
$home = trim(shell_exec("awk -F: '/1000/{print $6}' /etc/passwd"));
|
||||
|
||||
// Archive old language file
|
||||
syslog_shell_exec("cp -f $home/BirdNET-Pi/model/labels.txt $home/BirdNET-Pi/model/labels.txt.old", $user);
|
||||
|
||||
// Install new language label file
|
||||
syslog_shell_exec("$home/BirdNET-Pi/scripts/install_language_label.sh -l $language", $user);
|
||||
|
||||
syslog(LOG_INFO, "Successfully changed language to '$language'");
|
||||
}
|
||||
|
||||
|
||||
$contents = file_get_contents("/etc/birdnet/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("/APPRISE_NOTIFICATION_TITLE=.*/", "APPRISE_NOTIFICATION_TITLE=\"$apprise_notification_title\"", $contents);
|
||||
$contents = preg_replace("/APPRISE_NOTIFICATION_BODY=.*/", "APPRISE_NOTIFICATION_BODY=\"$apprise_notification_body\"", $contents);
|
||||
$contents = preg_replace("/APPRISE_NOTIFY_EACH_DETECTION=.*/", "APPRISE_NOTIFY_EACH_DETECTION=$apprise_notify_each_detection", $contents);
|
||||
$contents = preg_replace("/APPRISE_NOTIFY_NEW_SPECIES=.*/", "APPRISE_NOTIFY_NEW_SPECIES=$apprise_notify_new_species", $contents);
|
||||
$contents = preg_replace("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents);
|
||||
$contents = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $contents);
|
||||
|
||||
$contents = file_get_contents("/etc/birdnet/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("/APPRISE_NOTIFICATION_TITLE=.*/", "APPRISE_NOTIFICATION_TITLE=\"$apprise_notification_title\"", $contents);
|
||||
$contents = preg_replace("/APPRISE_NOTIFICATION_BODY=.*/", "APPRISE_NOTIFICATION_BODY=\"$apprise_notification_body\"", $contents);
|
||||
$contents = preg_replace("/APPRISE_NOTIFY_EACH_DETECTION=.*/", "APPRISE_NOTIFY_EACH_DETECTION=$apprise_notify_each_detection", $contents);
|
||||
$contents = preg_replace("/APPRISE_NOTIFY_NEW_SPECIES=.*/", "APPRISE_NOTIFY_NEW_SPECIES=$apprise_notify_new_species", $contents);
|
||||
$contents = preg_replace("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents);
|
||||
$contents2 = file_get_contents("./scripts/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("/APPRISE_NOTIFICATION_TITLE=.*/", "APPRISE_NOTIFICATION_TITLE=\"$apprise_notification_title\"", $contents2);
|
||||
$contents2 = preg_replace("/APPRISE_NOTIFICATION_BODY=.*/", "APPRISE_NOTIFICATION_BODY=\"$apprise_notification_body\"", $contents2);
|
||||
$contents2 = preg_replace("/APPRISE_NOTIFY_EACH_DETECTION=.*/", "APPRISE_NOTIFY_EACH_DETECTION=$apprise_notify_each_detection", $contents2);
|
||||
$contents2 = preg_replace("/APPRISE_NOTIFY_NEW_SPECIES=.*/", "APPRISE_NOTIFY_NEW_SPECIES=$apprise_notify_new_species", $contents2);
|
||||
$contents2 = preg_replace("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents2);
|
||||
$contents2 = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $contents2);
|
||||
|
||||
|
||||
$contents2 = file_get_contents("./scripts/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("/APPRISE_NOTIFICATION_TITLE=.*/", "APPRISE_NOTIFICATION_TITLE=\"$apprise_notification_title\"", $contents2);
|
||||
$contents2 = preg_replace("/APPRISE_NOTIFICATION_BODY=.*/", "APPRISE_NOTIFICATION_BODY=\"$apprise_notification_body\"", $contents2);
|
||||
$contents2 = preg_replace("/APPRISE_NOTIFY_EACH_DETECTION=.*/", "APPRISE_NOTIFY_EACH_DETECTION=$apprise_notify_each_detection", $contents2);
|
||||
$contents2 = preg_replace("/APPRISE_NOTIFY_NEW_SPECIES=.*/", "APPRISE_NOTIFY_NEW_SPECIES=$apprise_notify_new_species", $contents2);
|
||||
$contents2 = preg_replace("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents2);
|
||||
$fh = fopen("/etc/birdnet/birdnet.conf", "w");
|
||||
$fh2 = fopen("./scripts/thisrun.txt", "w");
|
||||
fwrite($fh, $contents);
|
||||
fwrite($fh2, $contents2);
|
||||
|
||||
if(isset($apprise_input)){
|
||||
$user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd");
|
||||
$home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd");
|
||||
$home = trim($home);
|
||||
|
||||
$fh = fopen("/etc/birdnet/birdnet.conf", "w");
|
||||
$fh2 = fopen("./scripts/thisrun.txt", "w");
|
||||
fwrite($fh, $contents);
|
||||
fwrite($fh2, $contents2);
|
||||
$appriseconfig = fopen($home."/BirdNET-Pi/apprise.txt", "w");
|
||||
fwrite($appriseconfig, $apprise_input);
|
||||
}
|
||||
|
||||
if(isset($apprise_input)){
|
||||
$user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd");
|
||||
$home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd");
|
||||
$home = trim($home);
|
||||
|
||||
$appriseconfig = fopen($home."/BirdNET-Pi/apprise.txt", "w");
|
||||
fwrite($appriseconfig, $apprise_input);
|
||||
}
|
||||
|
||||
|
||||
$language = $_GET["language"];
|
||||
if ($language != "none"){
|
||||
$user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd");
|
||||
$home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd");
|
||||
$home = trim($home);
|
||||
$command = "sudo -u".$user." mv ".$home."/BirdNET-Pi/model/labels.txt ".$home."/BirdNET-Pi/model/labels.txt.old && sudo -u".$user." unzip ".$home."/BirdNET-Pi/model/labels_l18n.zip ".$language." -d ".$home."/BirdNET-Pi/model && sudo -u".$user." mv ".$home."/BirdNET-Pi/model/".$language." ".$home."/BirdNET-Pi/model/labels.txt";
|
||||
$command_output = `$command`;
|
||||
`sudo restart_services.sh`;
|
||||
}
|
||||
syslog(LOG_INFO, "Restarting Services");
|
||||
shell_exec("sudo restart_services.sh");
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -94,13 +117,13 @@ if ($language != "none"){
|
||||
</head>
|
||||
<div class="settings">
|
||||
<h2>Basic Settings</h2>
|
||||
<form action="" method="GET">
|
||||
<?php
|
||||
<form id="basicform" action="" method="GET">
|
||||
<?php
|
||||
if (file_exists('./scripts/thisrun.txt')) {
|
||||
$config = parse_ini_file('./scripts/thisrun.txt');
|
||||
} elseif (file_exists('./scripts/firstrun.ini')) {
|
||||
$config = parse_ini_file('./scripts/firstrun.ini');
|
||||
}
|
||||
}
|
||||
$user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd");
|
||||
$home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd");
|
||||
$home = trim($home);
|
||||
@@ -157,36 +180,51 @@ https://discordapp.com/api/webhooks/{WebhookID}/{WebhookToken}
|
||||
<h3>Localization</h3>
|
||||
<label for="language">Database Language: </label>
|
||||
<select name="language">
|
||||
<option value="none">Select your language</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_en.txt">English</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>
|
||||
<?php
|
||||
$langs = array(
|
||||
'not-selected' => 'Not Selected',
|
||||
"af" => "Afrikaans",
|
||||
"ca" => "Catalan",
|
||||
"cs" => "Czech",
|
||||
"zh" => "Chinese",
|
||||
"hr" => "Croatian",
|
||||
"da" => "Danish",
|
||||
"nl" => "Dutch",
|
||||
"en" => "English",
|
||||
"et" => "Estonian",
|
||||
"fi" => "Finnish",
|
||||
"fr" => "French",
|
||||
"de" => "German",
|
||||
"hu" => "Hungarian",
|
||||
"is" => "Icelandic",
|
||||
"id" => "Indonesia",
|
||||
"it" => "Italian",
|
||||
"ja" => "Japanese",
|
||||
"lv" => "Latvian",
|
||||
"lt" => "Lithuania",
|
||||
"no" => "Norwegian",
|
||||
"pl" => "Polish",
|
||||
"pt" => "Portugues",
|
||||
"ru" => "Russian",
|
||||
"sk" => "Slovak",
|
||||
"sl" => "Slovenian",
|
||||
"es" => "Spanish",
|
||||
"sv" => "Swedish",
|
||||
"th" => "Thai",
|
||||
"uk" => "Ukrainian"
|
||||
);
|
||||
|
||||
// Create options for each language
|
||||
foreach($langs as $langTag => $langName){
|
||||
$isSelected = "";
|
||||
if($config['DATABASE_LANG'] == $langTag){
|
||||
$isSelected = 'selected="selected"';
|
||||
}
|
||||
|
||||
echo "<option value='{$langTag}' $isSelected>$langName</option>";
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
<br><br>
|
||||
<script>
|
||||
@@ -194,19 +232,19 @@ https://discordapp.com/api/webhooks/{WebhookID}/{WebhookToken}
|
||||
// this disables the input of manual date and time if the user wants to use the internet time
|
||||
var date=document.getElementById("date");
|
||||
var time=document.getElementById("time");
|
||||
if(checkbox.checked) {
|
||||
date.setAttribute("disabled", "disabled");
|
||||
time.setAttribute("disabled", "disabled");
|
||||
} else {
|
||||
if(checkbox.checked) {
|
||||
date.setAttribute("disabled", "disabled");
|
||||
time.setAttribute("disabled", "disabled");
|
||||
} else {
|
||||
date.removeAttribute("disabled");
|
||||
time.removeAttribute("disabled");
|
||||
time.removeAttribute("disabled");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
<?php
|
||||
// if NTP service is active, show the checkboxes as checked, and disable the manual input
|
||||
$tdc = trim(exec("sudo timedatectl | grep \"NTP service: active\""));
|
||||
if (strlen($tdc) > 0) {
|
||||
if (strlen($tdc) > 0) {
|
||||
$checkedvalue = "checked";
|
||||
$disabledvalue = "disabled";
|
||||
} else {
|
||||
@@ -223,7 +261,7 @@ https://discordapp.com/api/webhooks/{WebhookID}/{WebhookToken}
|
||||
|
||||
<input type="hidden" name="status" value="success">
|
||||
<input type="hidden" name="submit" value="settings">
|
||||
<button type="submit" name="view" value="Settings">
|
||||
<button type="submit" id="basicformsubmit" onclick="if(document.getElementById('basicform').checkValidity()){this.innerHTML = 'Updating... please wait.';this.classList.add('disabled')}" name="view" value="Settings">
|
||||
<?php
|
||||
if(isset($_GET['status'])){
|
||||
echo "Success!";
|
||||
|
||||
@@ -11,7 +11,7 @@ cd $my_dir/scripts || exit 1
|
||||
|
||||
if [ "$(uname -m)" != "aarch64" ];then
|
||||
echo "BirdNET-Pi requires a 64-bit OS.
|
||||
It looks like your operating system is using $(uname -m),
|
||||
It looks like your operating system is using $(uname -m),
|
||||
but would need to be aarch64.
|
||||
Please take a look at https://birdnetwiki.pmcgui.xyz for more
|
||||
information"
|
||||
@@ -31,14 +31,12 @@ install_birdnet() {
|
||||
pip3 install -U -r $HOME/BirdNET-Pi/requirements.txt
|
||||
}
|
||||
|
||||
unpack_labels() {
|
||||
unzip $HOME/BirdNET-Pi/model/labels_l18n.zip labels_en.txt \
|
||||
-d $HOME/BirdNET-Pi/model
|
||||
mv $HOME/BirdNET-Pi/model/labels_en.txt $HOME/BirdNET-Pi/model/labels.txt
|
||||
}
|
||||
|
||||
[ -d ${RECS_DIR} ] || mkdir -p ${RECS_DIR} &> /dev/null
|
||||
|
||||
install_birdnet
|
||||
unpack_labels
|
||||
install_birdnet
|
||||
|
||||
cd $my_dir/scripts || exit 1
|
||||
|
||||
./install_language_label.sh -l $DATABASE_LANG || exit 1
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -163,6 +163,8 @@ EXTRACTION_LENGTH=
|
||||
|
||||
AUDIOFMT=mp3
|
||||
|
||||
## DATABASE_LANG is the language used for the bird species database
|
||||
DATABASE_LANG=en
|
||||
|
||||
## These are just for debugging
|
||||
LAST_RUN=
|
||||
@@ -171,7 +173,7 @@ IDFILE=$HOME/BirdNET-Pi/IdentifiedSoFar.txt
|
||||
EOF
|
||||
}
|
||||
|
||||
# Checks for a birdnet.conf file
|
||||
# Checks for a birdnet.conf file
|
||||
if ! [ -f ${birdnet_conf} ];then
|
||||
install_config
|
||||
fi
|
||||
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
usage() { echo "Usage: $0 -l <language i18n id>" 1>&2; exit 1; }
|
||||
|
||||
while getopts "l:" o; do
|
||||
case "${o}" in
|
||||
l)
|
||||
lang=${OPTARG}
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
HOME=$(awk -F: '/1000/ {print $6}' /etc/passwd)
|
||||
|
||||
label_file_name="labels_${lang}.txt"
|
||||
|
||||
unzip -o $HOME/BirdNET-Pi/model/labels_l18n.zip $label_file_name \
|
||||
-d $HOME/BirdNET-Pi/model \
|
||||
&& mv -f $HOME/BirdNET-Pi/model/$label_file_name $HOME/BirdNET-Pi/model/labels.txt \
|
||||
&& logger "[$0] Changed language label file to '$label_file_name'";
|
||||
|
||||
exit 0
|
||||
@@ -5,11 +5,11 @@ source /etc/birdnet/birdnet.conf
|
||||
if [ -z ${REC_CARD} ];then
|
||||
echo "Stream not supported"
|
||||
elif [[ ! -z ${RTSP_STREAM} ]];then
|
||||
ffmpeg -loglevel 52 -ac ${CHANNELS} -i ${RTSP_STREAM} -acodec libmp3lame \
|
||||
ffmpeg -loglevel 32 -ac ${CHANNELS} -i ${RTSP_STREAM} -acodec libmp3lame \
|
||||
-b:a 320k -ac ${CHANNELS} -content_type 'audio/mpeg' \
|
||||
-f mp3 icecast://source:${ICE_PWD}@localhost:8000/stream -re
|
||||
else
|
||||
ffmpeg -loglevel 52 -ac ${CHANNELS} -f alsa -i ${REC_CARD} -acodec libmp3lame \
|
||||
ffmpeg -loglevel 32 -ac ${CHANNELS} -f alsa -i ${REC_CARD} -acodec libmp3lame \
|
||||
-b:a 320k -ac ${CHANNELS} -content_type 'audio/mpeg' \
|
||||
-f mp3 icecast://source:${ICE_PWD}@localhost:8000/stream -re
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('session.gc_maxlifetime', 7200);
|
||||
session_set_cookie_params(7200);
|
||||
session_start();
|
||||
|
||||
+109
-13
@@ -1,3 +1,36 @@
|
||||
<?php
|
||||
if(isset($_GET['ajax_csv'])) {
|
||||
|
||||
$user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd");
|
||||
$home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd");
|
||||
$home = trim($home);
|
||||
$files = scandir($home."/BirdSongs/".date('F-Y')."/".date('j-l')."/", SCANDIR_SORT_ASCENDING);
|
||||
$newest_file = $files[2];
|
||||
|
||||
|
||||
if($newest_file == $_GET['newest_file']) {
|
||||
die();
|
||||
}
|
||||
|
||||
echo "file,".$newest_file."\n";
|
||||
|
||||
$row = 1;
|
||||
if (($handle = fopen($home."/BirdSongs/".date('F-Y')."/".date('j-l')."/".$newest_file.".csv", "r")) !== FALSE) {
|
||||
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
|
||||
if($row != 1){
|
||||
$num = count($data);
|
||||
for ($c=0; $c < $num; $c++) {
|
||||
$exp = explode(';',$data[$c]);
|
||||
echo $exp[0].",".$exp[3].",".$exp[4]."\n";
|
||||
}
|
||||
}
|
||||
$row++;
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
die();
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
// CREDITS: https://codepen.io/jakealbaugh/pen/jvQweW
|
||||
|
||||
@@ -7,6 +40,9 @@ var started = null;
|
||||
var player = null;
|
||||
var gain = 128;
|
||||
const ctx = null;
|
||||
let fps =[];
|
||||
let avgfps;
|
||||
let requestTime;
|
||||
window.onload = function(){
|
||||
// if user agent includes iPhone or Mac use legacy mode
|
||||
if(window.navigator.userAgent.includes("iPhone") || window.navigator.userAgent.includes("Mac")) {
|
||||
@@ -63,32 +99,83 @@ function fitTextOnCanvas(text,fontface,yPosition){
|
||||
CTX.fillText(text,document.body.querySelector('canvas').width - (document.body.querySelector('canvas').width * 0.50),yPosition);
|
||||
}
|
||||
|
||||
function applyText(text) {
|
||||
CTX.fillStyle = 'white';
|
||||
CTX.font = '25px Roboto Flex';
|
||||
fitTextOnCanvas(text,"Roboto Flex",document.body.querySelector('canvas').scrollHeight * 0.35)
|
||||
function applyText(text,x,y,opacity) {
|
||||
console.log("conf: "+opacity)
|
||||
console.log(text+" "+parseInt(x)+" "+y)
|
||||
if(opacity < 0.2) {
|
||||
opacity = 0.2;
|
||||
}
|
||||
CTX.textAlign = "center";
|
||||
CTX.fillStyle = "rgba(255, 255, 255, "+opacity+")";
|
||||
CTX.font = '15px Roboto Flex';
|
||||
//fitTextOnCanvas(text,"Roboto Flex",document.body.querySelector('canvas').scrollHeight * 0.35)
|
||||
CTX.fillText(text,parseInt(x),y)
|
||||
CTX.fillStyle = 'hsl(280, 100%, 10%)';
|
||||
}
|
||||
|
||||
var previous_detection_identifier = null;
|
||||
var add =0;
|
||||
var newest_file;
|
||||
var lastbird;
|
||||
function loadDetectionIfNewExists() {
|
||||
const xhttp = new XMLHttpRequest();
|
||||
xhttp.onload = function() {
|
||||
// if there's a new detection that needs to be updated to the page
|
||||
if(this.responseText.length > 0 && !this.responseText.includes("Database")) {
|
||||
if(previous_detection_identifier != null){
|
||||
applyText(this.responseText.split(",")[0].replace("_"," "));
|
||||
|
||||
var split = this.responseText.split("\n")
|
||||
for(var i = 1;i < split.length; i++) {
|
||||
if(parseInt(split[i].split(",")[0]) >= 0){
|
||||
|
||||
newest_file = split[0].split(",")[1]
|
||||
//applyText(split[i].split(",")[1],document.body.querySelector('canvas').width - ((parseInt(split[i].split(",")[0]))*avgfps), (document.body.querySelector('canvas').height * 0.50))
|
||||
|
||||
d1 = new Date(newest_file.split("-")[0]+"/"+newest_file.split("-")[1]+"/"+newest_file.split("-")[2]+ " "+newest_file.split("-")[4].replace(".wav",""))
|
||||
console.log(d1)
|
||||
d2 = new Date();
|
||||
timeDiff = (d2-d1)/1000;
|
||||
|
||||
// stagger Y placement if a new bird
|
||||
if(split[i].split(",")[1] != lastbird || split[i].split(",")[1].length > 15) {
|
||||
if(add >= 80) {
|
||||
add -= 40;
|
||||
} else {
|
||||
add += 20;
|
||||
}
|
||||
|
||||
if(parseFloat(add + document.body.querySelector('canvas').height * 0.50) > document.body.querySelector('canvas').height || parseFloat(add + document.body.querySelector('canvas').height * 0.50) <= 0) {
|
||||
add = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Date csv file was created + relative detection time of bird + mic delay
|
||||
secago = Math.abs(timeDiff) - split[i].split(",")[0] - 6.8;
|
||||
|
||||
x = document.body.querySelector('canvas').width - ((parseInt(secago))*avgfps);
|
||||
// if the text is too close to the right side of the canvas and will be cut off, wait 3 seconds before adding text
|
||||
if(x > document.body.querySelector('canvas').width - (3*avgfps)) {
|
||||
setTimeout(function (split,i,x) {
|
||||
console.log(split[i])
|
||||
console.log("originally at "+x+", now waiting 2 sec and at "+(x-(3*avgfps)))
|
||||
applyText(split[i].split(",")[1],(x - (3*avgfps)), ((document.body.querySelector('canvas').height * 0.50) + add ), split[i].split(",")[2]);
|
||||
}, 2000, split, i, x)
|
||||
} else {
|
||||
applyText(split[i].split(",")[1],x, ((document.body.querySelector('canvas').height * 0.50) + add ), split[i].split(",")[2])
|
||||
}
|
||||
|
||||
|
||||
lastbird = split[i].split(",")[1]
|
||||
}
|
||||
|
||||
}
|
||||
previous_detection_identifier = this.responseText.split(",")[1];
|
||||
}
|
||||
}
|
||||
xhttp.open("GET", "overview.php?ajax_detections=true&previous_detection_identifier="+previous_detection_identifier+"&only_name=true", true);
|
||||
xhttp.open("GET", "spectrogram.php?ajax_csv=true&newest_file="+newest_file, true);
|
||||
xhttp.send();
|
||||
}
|
||||
|
||||
window.setInterval(function(){
|
||||
loadDetectionIfNewExists();
|
||||
}, 2500);
|
||||
}, 500);
|
||||
|
||||
function initialize() {
|
||||
document.body.querySelector('h1').remove();
|
||||
@@ -102,7 +189,6 @@ function initialize() {
|
||||
|
||||
ANALYSER.fftSize = 2048;
|
||||
|
||||
|
||||
try{
|
||||
process();
|
||||
} catch(e) {
|
||||
@@ -122,8 +208,18 @@ function initialize() {
|
||||
|
||||
loop();
|
||||
|
||||
function loop() {
|
||||
window.requestAnimationFrame(loop);
|
||||
function loop(time) {
|
||||
if (requestTime) {
|
||||
fpsval = Math.round(1000/((performance.now() - requestTime)))
|
||||
if(fpsval > 0){
|
||||
fps.push( fpsval);
|
||||
}
|
||||
}
|
||||
if(fps.length > 0){
|
||||
avgfps = fps.reduce((a, b) => a + b) / fps.length;
|
||||
}
|
||||
requestTime = time;
|
||||
window.requestAnimationFrame((timeRes) => loop(timeRes));
|
||||
let imgData = CTX.getImageData(1, 0, W - 1, H);
|
||||
|
||||
CTX.fillRect(0, 0, W, H);
|
||||
|
||||
+2
-3
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', 0);
|
||||
|
||||
$db = new SQLite3('./scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
|
||||
if($db == False) {
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
<button type="submit" name="submit" value="sudo reboot" onclick="return confirm('Are you sure you want to reboot?')">Reboot</button>
|
||||
</form>
|
||||
<form action="" method="GET">
|
||||
<button type="submit" name="submit" value="update_birdnet.sh" onclick="return confirm('Are you sure you want to update?')">Update</button>
|
||||
<button type="submit" name="submit" value="update_birdnet.sh" onclick="return confirm('Are you sure you want to update?')">Update <?php if($_SESSION['behind'] != "0" && $_SESSION['behind'] != "with"){?><div class="updatenumber"><?php echo $_SESSION['behind']; ?></div><?php } ?></button>
|
||||
</form>
|
||||
<form action="" method="GET">
|
||||
<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="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>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
ini_set('session.gc_maxlifetime', 7200);
|
||||
session_set_cookie_params(7200);
|
||||
session_start();
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', 0);
|
||||
|
||||
$db = new SQLite3('./scripts/birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
|
||||
if($db == False){
|
||||
@@ -128,7 +127,7 @@ if(isset($_GET['ajax_detections']) && $_GET['ajax_detections'] == "true" ) {
|
||||
$flickrjson = json_decode(file_get_contents("https://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=".$config["FLICKR_API_KEY"]."&text=".str_replace(" ", "%20", $engname)."&license=2%2C3%2C4%2C5%2C6%2C9&sort=relevance&per_page=5&orientation=square,portrait&media=photos&format=json&nojsoncallback=1"), true)["photos"]["photo"][0];
|
||||
$modaltext = "https://flickr.com/photos/".$flickrjson["owner"]."/".$flickrjson["id"];
|
||||
$authorlink = "https://flickr.com/people/".$flickrjson["owner"];
|
||||
$imageurl = 'http://farm' .$flickrjson["farm"]. '.static.flickr.com/' .$flickrjson["server"]. '/' .$flickrjson["id"]. '_' .$flickrjson["secret"]. '.jpg';
|
||||
$imageurl = 'https://farm' .$flickrjson["farm"]. '.static.flickr.com/' .$flickrjson["server"]. '/' .$flickrjson["id"]. '_' .$flickrjson["secret"]. '.jpg';
|
||||
array_push($_SESSION['images'], array($comname,$imageurl,$flickrjson["title"], $modaltext, $authorlink));
|
||||
$image = $_SESSION['images'][count($_SESSION['images'])-1];
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ if [ -f $my_dir/privacy_server ] || [ -L /usr/local/bin/privacy_server.py ];then
|
||||
fi
|
||||
|
||||
# Adds python virtual-env to the python systemd services
|
||||
if ! grep 'BirdNET-Pi/birdnet/' $HOME/BirdNET-Pi/templates/birdnet_server.service || ! grep 'BirdNET-Pi/birdnet' $HOME/BirdNET-Pi/templates/chart_viewer.service;then
|
||||
if ! grep 'BirdNET-Pi/birdnet/' $HOME/BirdNET-Pi/templates/birdnet_server.service &>/dev/null || ! grep 'BirdNET-Pi/birdnet' $HOME/BirdNET-Pi/templates/chart_viewer.service &>/dev/null;then
|
||||
sudo -E sed -i "s|ExecStart=.*|ExecStart=$HOME/BirdNET-Pi/birdnet/bin/python3 /usr/local/bin/server.py|" ~/BirdNET-Pi/templates/birdnet_server.service
|
||||
sudo -E sed -i "s|ExecStart=.*|ExecStart=$HOME/BirdNET-Pi/birdnet/bin/python3 /usr/local/bin/daily_plot.py|" ~/BirdNET-Pi/templates/chart_viewer.service
|
||||
sudo systemctl daemon-reload && restart_services.sh
|
||||
@@ -40,6 +40,14 @@ fi
|
||||
if ! grep APPRISE_NOTIFY_NEW_SPECIES /etc/birdnet/birdnet.conf &>/dev/null;then
|
||||
sudo -u$USER echo "APPRISE_NOTIFY_NEW_SPECIES=0 " >> /etc/birdnet/birdnet.conf
|
||||
fi
|
||||
|
||||
# If the config does not contain the DATABASE_LANG setting, we'll want to add it.
|
||||
# Defaults to not-selected, which config.php will know to render as a language option.
|
||||
# The user can then select a language in the web interface and update with that.
|
||||
if ! grep DATABASE_LANG /etc/birdnet/birdnet.conf &>/dev/null;then
|
||||
sudo -u$USER echo "DATABASE_LANG=not-selected" >> /etc/birdnet/birdnet.conf
|
||||
fi
|
||||
|
||||
apprise_installation_status=$(~/BirdNET-Pi/birdnet/bin/python3 -c 'import pkgutil; print("installed" if pkgutil.find_loader("apprise") else "not installed")')
|
||||
if [[ "$apprise_installation_status" = "not installed" ]];then
|
||||
~/BirdNET-Pi/birdnet/bin/pip3 install -U pip
|
||||
@@ -52,7 +60,7 @@ fi
|
||||
if ! grep RTSP_STREAM /etc/birdnet/birdnet.conf &>/dev/null;then
|
||||
sudo -u$USER echo "RTSP_STREAM=" >> /etc/birdnet/birdnet.conf
|
||||
fi
|
||||
if grep bash $HOME/BirdNET-Pi/templates/web_terminal.service;then
|
||||
if grep bash $HOME/BirdNET-Pi/templates/web_terminal.service &>/dev/null;then
|
||||
sudo sed -i '/User/d;s/bash/login/g' $HOME/BirdNET-Pi/templates/web_terminal.service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart web_terminal.service
|
||||
@@ -61,16 +69,15 @@ fi
|
||||
if ! grep FLICKR_API_KEY /etc/birdnet/birdnet.conf &>/dev/null;then
|
||||
sudo -u$USER echo "FLICKR_API_KEY=" >> /etc/birdnet/birdnet.conf
|
||||
fi
|
||||
if systemctl list-unit-files pushed_notifications.service;then
|
||||
if systemctl list-unit-files pushed_notifications.service &>/dev/null;then
|
||||
sudo systemctl disable --now pushed_notifications.service
|
||||
sudo rm -f /usr/lib/systemd/system/pushed_notifications.service
|
||||
sudo rm $HOME/BirdNET-Pi/templates/pushed_notifications.service
|
||||
fi
|
||||
if [ ! -f $HOME/BirdNET-Pi/model/labels.txt ]
|
||||
then
|
||||
unzip $HOME/BirdNET-Pi/model/labels_l18n.zip labels_en.txt \
|
||||
-d $HOME/BirdNET-Pi/model
|
||||
mv $HOME/BirdNET-Pi/model/labels_en.txt $HOME/BirdNET-Pi/model/labels.txt
|
||||
|
||||
if [ ! -f $HOME/BirdNET-Pi/model/labels.txt ];then
|
||||
$my_dir/install_language_label.sh -l $DATABASE_LANG \
|
||||
&& logger "[$0] Installed new language label file for '$DATABASE_LANG'";
|
||||
fi
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ fi
|
||||
cd ~/BirdNET-Pi
|
||||
function remove() {
|
||||
source /etc/birdnet/birdnet.conf
|
||||
find $RECS_DIR -iname *${1}* -exec rm -drfv {} +
|
||||
find $EXTRACTED -iname *${1}* -exec rm -drfv {} +
|
||||
}
|
||||
alias rerc="source ~/.bashrc"
|
||||
alias vimrc="vim ~/.bashrc"
|
||||
|
||||
Reference in New Issue
Block a user