diff --git a/birdnet.conf-defaults b/birdnet.conf-defaults index 446a7c8..7d2105a 100644 --- a/birdnet.conf-defaults +++ b/birdnet.conf-defaults @@ -62,6 +62,7 @@ APPRISE_NOTIFICATION_TITLE="New BirdNET-Pi Detection" APPRISE_NOTIFICATION_BODY="A \$sciname \$comname was just detected with a confidence of \$confidence" APPRISE_NOTIFY_EACH_DETECTION=0 APPRISE_NOTIFY_NEW_SPECIES=0 +APPRISE_WEEKLY_REPORT=0 #---------------------- Flickr Images API Configuration -----------------------# ## If FLICKR_API_KEY is set, the web interface will try and display bird images diff --git a/homepage/views.php b/homepage/views.php index a5d3fcf..32f53d6 100644 --- a/homepage/views.php +++ b/homepage/views.php @@ -107,6 +107,7 @@ if(isset($_GET['view'])){ if($_GET['view'] == "Overview"){include('overview.php');} if($_GET['view'] == "Today's Detections"){include('todays_detections.php');} if($_GET['view'] == "Species Stats"){include('stats.php');} + if($_GET['view'] == "Weekly Report"){include('weekly_report.php');} if($_GET['view'] == "Streamlit"){echo "";} if($_GET['view'] == "Daily Charts"){include('history.php');} if($_GET['view'] == "Tools"){ diff --git a/scripts/clear_all_data.sh b/scripts/clear_all_data.sh index d574f5e..7108534 100755 --- a/scripts/clear_all_data.sh +++ b/scripts/clear_all_data.sh @@ -34,6 +34,7 @@ sudo -u ${USER} ln -fs $my_dir/overview.php ${EXTRACTED} sudo -u ${USER} ln -fs $my_dir/stats.php ${EXTRACTED} sudo -u ${USER} ln -fs $my_dir/todays_detections.php ${EXTRACTED} sudo -u ${USER} ln -fs $my_dir/history.php ${EXTRACTED} +sudo -u ${USER} ln -fs $my_dir/weekly_report.php ${EXTRACTED} sudo -u ${USER} ln -fs $my_dir/homepage/images/favicon.ico ${EXTRACTED} sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED} sudo -u ${USER} ln -fs $(dirname $my_dir)/templates/phpsysinfo.ini ${HOME}/phpsysinfo/ diff --git a/scripts/config.php b/scripts/config.php index 023499e..2aafa7f 100644 --- a/scripts/config.php +++ b/scripts/config.php @@ -46,6 +46,11 @@ if(isset($_GET["latitude"])){ } else { $apprise_notify_new_species_each_day = 0; } + if(isset($_GET['apprise_weekly_report'])) { + $apprise_weekly_report = 1; + } else { + $apprise_weekly_report = 0; + } if(isset($timezone)) { shell_exec("sudo timedatectl set-timezone ".$timezone); @@ -101,6 +106,7 @@ if(isset($_GET["latitude"])){ $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("/APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=.*/", "APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=$apprise_notify_new_species_each_day", $contents); + $contents = preg_replace("/APPRISE_WEEKLY_REPORT=.*/", "APPRISE_WEEKLY_REPORT=$apprise_weekly_report", $contents); $contents = preg_replace("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents); $contents = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $contents); $contents = preg_replace("/FLICKR_FILTER_EMAIL=.*/", "FLICKR_FILTER_EMAIL=$flickr_filter_email", $contents); @@ -114,6 +120,7 @@ if(isset($_GET["latitude"])){ $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("/APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=.*/", "APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=$apprise_notify_new_species_each_day", $contents2); + $contents2 = preg_replace("/APPRISE_WEEKLY_REPORT=.*/", "APPRISE_WEEKLY_REPORT=$apprise_weekly_report", $contents2); $contents2 = preg_replace("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents2); $contents2 = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $contents2); $contents2 = preg_replace("/FLICKR_FILTER_EMAIL=.*/", "FLICKR_FILTER_EMAIL=$flickr_filter_email", $contents2); @@ -329,9 +336,11 @@ https://discordapp.com/api/webhooks/{WebhookID}/{WebhookToken} >
> -
+
> -

+
+ > +


diff --git a/scripts/install_config.sh b/scripts/install_config.sh index 4d4c43d..a85781c 100755 --- a/scripts/install_config.sh +++ b/scripts/install_config.sh @@ -75,6 +75,7 @@ APPRISE_NOTIFICATION_TITLE="New BirdNET-Pi Detection" APPRISE_NOTIFICATION_BODY="A \$sciname \$comname was just detected with a confidence of \$confidence" APPRISE_NOTIFY_EACH_DETECTION=0 APPRISE_NOTIFY_NEW_SPECIES=0 +APPRISE_WEEKLY_REPORT=0 #---------------------- Flickr Images API Configuration -----------------------# ## If FLICKR_API_KEY is set, the web interface will try and display bird images diff --git a/scripts/install_services.sh b/scripts/install_services.sh index 3f5eec3..9a7f4c8 100755 --- a/scripts/install_services.sh +++ b/scripts/install_services.sh @@ -111,6 +111,7 @@ create_necessary_dirs() { sudo -u ${USER} ln -fs $my_dir/scripts/stats.php ${EXTRACTED} sudo -u ${USER} ln -fs $my_dir/scripts/todays_detections.php ${EXTRACTED} sudo -u ${USER} ln -fs $my_dir/scripts/history.php ${EXTRACTED} + sudo -u ${USER} ln -fs $my_dir/scripts/weekly_report.php ${EXTRACTED} sudo -u ${USER} ln -fs $my_dir/homepage/images/favicon.ico ${EXTRACTED} sudo -u ${USER} ln -fs ${HOME}/phpsysinfo ${EXTRACTED} sudo -u ${USER} ln -fs $my_dir/templates/phpsysinfo.ini ${HOME}/phpsysinfo/ @@ -408,6 +409,10 @@ install_cleanup_cron() { sed "s/\$USER/$USER/g" $my_dir/templates/cleanup.cron >> /etc/crontab } +install_weekly_cron() { + sed "s/\$USER/$USER/g" $my_dir/templates/weekly_report.cron >> /etc/crontab +} + chown_things() { chown -R $USER:$USER $HOME/Bird* } @@ -433,6 +438,7 @@ install_services() { install_phpsysinfo install_livestream_service install_cleanup_cron + install_weekly_cron create_necessary_dirs generate_BirdDB diff --git a/scripts/update_birdnet_snippets.sh b/scripts/update_birdnet_snippets.sh index de95c67..a2c8cea 100755 --- a/scripts/update_birdnet_snippets.sh +++ b/scripts/update_birdnet_snippets.sh @@ -98,6 +98,15 @@ if [[ "$pytest_installation_status" = "not installed" ]];then $HOME/BirdNET-Pi/birdnet/bin/pip3 install pytest==7.1.2 pytest-mock==3.7.0 fi +[ -L ~/BirdSongs/Extracted/weekly_report.php ] || ln -sf ~/BirdNET-Pi/scripts/weekly_report.php ~/BirdSongs/Extracted + +if ! grep weekly_report /etc/crontab &>/dev/null;then + sed "s/\$USER/$USER/g" $HOME/BirdNET-Pi/templates/weekly_report.cron | sudo tee -a /etc/crontab +fi +if ! grep APPRISE_WEEKLY_REPORT /etc/birdnet/birdnet.conf &>/dev/null;then + sudo -u$USER echo "APPRISE_WEEKLY_REPORT=1" >> /etc/birdnet/birdnet.conf +fi + if ! grep SILENCE_UPDATE_INDICATOR /etc/birdnet/birdnet.conf &>/dev/null;then sudo -u$USER echo "SILENCE_UPDATE_INDICATOR=0" >> /etc/birdnet/birdnet.conf fi diff --git a/scripts/weekly_report.php b/scripts/weekly_report.php new file mode 100644 index 0000000..4968c3f --- /dev/null +++ b/scripts/weekly_report.php @@ -0,0 +1,259 @@ +prepare('SELECT DISTINCT(Com_Name), COUNT(*) FROM detections WHERE Date BETWEEN "'.date("Y-m-d",$startdate).'" AND "'.date("Y-m-d",$enddate).'" GROUP By Com_Name ORDER BY COUNT(*) DESC'); + if($statement1 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result1 = $statement1->execute(); + + $statement4 = $db->prepare('SELECT DISTINCT(Com_Name), COUNT(*) FROM detections WHERE Date BETWEEN "'.date("Y-m-d",$startdate).'" AND "'.date("Y-m-d",$enddate).'"'); + if($statement4 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result4 = $statement4->execute(); + $totalcount = $result4->fetchArray(SQLITE3_ASSOC)['COUNT(*)']; + + $statement5 = $db->prepare('SELECT DISTINCT(Com_Name), COUNT(*) FROM detections WHERE Date BETWEEN "'.date("Y-m-d",$startdate- (7*86400)).'" AND "'.date("Y-m-d",$enddate- (7*86400)).'"'); + if($statement5 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result5 = $statement5->execute(); + $priortotalcount = $result5->fetchArray(SQLITE3_ASSOC)['COUNT(*)']; + + $statement6 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections WHERE Date BETWEEN "'.date("Y-m-d",$startdate).'" AND "'.date("Y-m-d",$enddate).'"'); + if($statement6 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result6 = $statement6->execute(); + $totalspeciestally = $result6->fetchArray(SQLITE3_ASSOC)['COUNT(DISTINCT(Com_Name))']; + + $statement7 = $db->prepare('SELECT COUNT(DISTINCT(Com_Name)) FROM detections WHERE Date BETWEEN "'.date("Y-m-d",$startdate- (7*86400)).'" AND "'.date("Y-m-d",$enddate- (7*86400)).'"'); + if($statement7 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result7= $statement7->execute(); + $priortotalspeciestally = $result7->fetchArray(SQLITE3_ASSOC)['COUNT(DISTINCT(Com_Name))']; + + $percentagedifftotal = round((1 - $priortotalcount / $totalcount) * 100); + + if($percentagedifftotal > 0) { + $percentagedifftotal = "+".$percentagedifftotal."%"; + } else { + $percentagedifftotal = "-".abs($percentagedifftotal)."%"; + } + + $percentagedifftotaldistinctspecies = round((1 - $priortotalspeciestally / $totalspeciestally) * 100); + if($percentagedifftotaldistinctspecies > 0) { + $percentagedifftotaldistinctspecies = "+".$percentagedifftotaldistinctspecies."%"; + } else { + $percentagedifftotaldistinctspecies = "-".abs($percentagedifftotaldistinctspecies)."%"; + } + + $detections = []; + $i = 0; + while($detection=$result1->fetchArray(SQLITE3_ASSOC)) + { + $detections[$detection["Com_Name"]] = $detection["COUNT(*)"]; + } + + echo "# BirdNET-Pi: Week ".date('W', $enddate)." Report\n"; + + echo "Total Detections: ".$totalcount." (".$percentagedifftotal.")
"; + echo "Unique Species Detected: ".$totalspeciestally." (".$percentagedifftotaldistinctspecies.")

"; + + echo "= Top 10 Species =
"; + + $i = 0; + foreach($detections as $com_name=>$scount) + { + $i++; + + if($i <= 10) { + $statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Com_Name == "'.$com_name.'" AND Date BETWEEN "'.date("Y-m-d",$startdate - (7*86400)).'" AND "'.date("Y-m-d",$enddate - (7*86400)).'"'); + if($statement2 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result2 = $statement2->execute(); + $totalcount = $result2->fetchArray(SQLITE3_ASSOC); + $priorweekcount = $totalcount['COUNT(*)']; + + $percentagediff = round((1 - $priorweekcount / $scount) * 100); + + if($percentagediff > 0) { + $percentagediff = "+".$percentagediff."%"; + } else { + $percentagediff = "-".abs($percentagediff)."%"; + } + + echo $com_name." - ".$scount." (".$percentagediff.")
"; + } + } + + echo "
= Species Detected for the First Time =
"; + + $newspeciescount=0; + foreach($detections as $com_name=>$scount) + { + $statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Com_Name == "'.$com_name.'" AND Date NOT BETWEEN "'.date("Y-m-d",$startdate).'" AND "'.date("Y-m-d",$enddate).'"'); + if($statement3 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result3 = $statement3->execute(); + $totalcount = $result3->fetchArray(SQLITE3_ASSOC); + $nonthisweekcount = $totalcount['COUNT(*)']; + + if($nonthisweekcount == 0) { + $newspeciescount++; + echo $com_name." - ".$scount."
"; + } + } + if($newspeciescount == 0) { + echo "No new species were seen this week."; + } + + echo "
* data from ".date('F jS, Y',$startdate)." — ".date('F jS, Y',$enddate).".
"; + echo '* percentages are calculated relative to week '.(date('W', $enddate) - 1).'.'; + + die(); +} + +?> +
Week ".date('W', $enddate)." Report".date('F jS, Y',$startdate)." — ".date('F jS, Y',$enddate)."
"; +?>
prepare('SELECT DISTINCT(Com_Name), COUNT(*) FROM detections WHERE Date BETWEEN "'.date("Y-m-d",$startdate).'" AND "'.date("Y-m-d",$enddate).'" GROUP By Com_Name ORDER BY COUNT(*) DESC'); +} else { + $statement1 = $db->prepare('SELECT DISTINCT(Com_Name), COUNT(*) FROM detections WHERE Date BETWEEN "'.date("Y-m-d",$startdate).'" AND "'.date("Y-m-d",$enddate).'" GROUP By Com_Name ORDER BY COUNT(*) ASC'); +} +if($statement1 == False){ + echo "Database is busy"; + header("refresh: 0;"); +} +$result1 = $statement1->execute(); + +$detections = []; +$i = 0; +while($detection=$result1->fetchArray(SQLITE3_ASSOC)) +{ + if($debug == true){ + if($i > 10) { + break; + } + } + $i++; + $detections[$detection["Com_Name"]] = $detection["COUNT(*)"]; + +} +?> +
+ +
+ + + + + + + + $scount) + { + $i++; + if($i <= 10) { + $statement2 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Com_Name == "'.$com_name.'" AND Date BETWEEN "'.date("Y-m-d",$startdate - (7*86400)).'" AND "'.date("Y-m-d",$enddate - (7*86400)).'"'); + if($statement2 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result2 = $statement2->execute(); + $totalcount = $result2->fetchArray(SQLITE3_ASSOC); + $priorweekcount = $totalcount['COUNT(*)']; + + $percentagediff = round((1 - $priorweekcount / $scount) * 100); + + if($percentagediff > 0) { + $percentagediff = "+".$percentagediff."%"; + } else { + $percentagediff = "-".abs($percentagediff)."%"; + } + + echo ""; + } + } + ?> + +
"; ?>
".$com_name."
".$scount." (".$percentagediff.")
+
+ + + + + + + + + $scount) + { + $statement3 = $db->prepare('SELECT COUNT(*) FROM detections WHERE Com_Name == "'.$com_name.'" AND Date NOT BETWEEN "'.date("Y-m-d",$startdate).'" AND "'.date("Y-m-d",$enddate).'"'); + if($statement3 == False){ + echo "Database is busy"; + header("refresh: 0;"); + } + $result3 = $statement3->execute(); + $totalcount = $result3->fetchArray(SQLITE3_ASSOC); + $nonthisweekcount = $totalcount['COUNT(*)']; + + if($nonthisweekcount == 0) { + $newspeciescount++; + echo ""; + } + } + if($newspeciescount == 0) { + echo ""; + } + ?> + +
"; ?>
".$com_name."
".$scount."
No new species were seen this week.
+
+ + +
+
+
* percentages are calculated relative to week +
\ No newline at end of file diff --git a/scripts/weekly_report.sh b/scripts/weekly_report.sh new file mode 100755 index 0000000..8bfaee7 --- /dev/null +++ b/scripts/weekly_report.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +source /etc/birdnet/birdnet.conf +if [ ${APPRISE_WEEKLY_REPORT} == 1 ];then + NOTIFICATION=$(curl 'localhost/views.php?view=Weekly%20Report&ascii=true') + NOTIFICATION=${NOTIFICATION#*#} + firstLine=`echo "${NOTIFICATION}" | head -1` + NOTIFICATION=`echo "${NOTIFICATION}" | tail -n +2` + $HOME/BirdNET-Pi/birdnet/bin/apprise -vv -t "${firstLine}" -b "${NOTIFICATION}" --input-format=html --config=$HOME/BirdNET-Pi/apprise.txt +fi \ No newline at end of file diff --git a/templates/weekly_report.cron b/templates/weekly_report.cron new file mode 100644 index 0000000..7c4f50d --- /dev/null +++ b/templates/weekly_report.cron @@ -0,0 +1,2 @@ +#birdnet +0 1 * * 1 $USER /usr/local/bin/weekly_report.sh >/dev/null 2>&1