Merge branch 'species_stats' of github.com:mcguirepr89/BirdNET-Pi into species_stats
This commit is contained in:
+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
|
||||
|
||||
Reference in New Issue
Block a user