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}
>
Notify each new infrequent species detection (<5 visits per week)
>
- Notify each new species detection of the day
+ Notify each species first detection of the day
>
- Notify each new detection
+ Notify each new detection
+ >
+ Send weekly report
Send Test Notification
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 "".$com_name."".$scount." ";
+ }
+ }
+ if($newspeciescount == 0) {
+ echo "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