* cleanup

* fix & cleanup

* make testable

* please add the install log
This commit is contained in:
Nachtzuster
2025-11-09 19:39:29 +01:00
committed by GitHub
parent b5352ef038
commit edd5c62447
4 changed files with 162 additions and 134 deletions
+1
View File
@@ -31,6 +31,7 @@ Add any other context about the problem or your installation here.
The hardware on which BirdNET-Pi is running goes here. The hardware on which BirdNET-Pi is running goes here.
**Code or log snippets** **Code or log snippets**
The installation creates a log in `~/`, please include it where applicable.
<details> <details>
<summary>log or code</summary> <summary>log or code</summary>
+1 -1
View File
@@ -1,4 +1,4 @@
tflite_runtime-2.6.0-cp39-none-linux_aarch64.whl tflite_runtime
librosa librosa
pytz pytz
tzlocal tzlocal
+4 -4
View File
@@ -146,14 +146,14 @@ def sendAppriseNotifications(species, confidence, confidencepct, path,
def get_todays_count_for(db_path, sci_name): def get_todays_count_for(db_path, sci_name):
today = datetime.now().strftime("%Y-%m-%d") today = datetime.now().strftime("%Y-%m-%d")
select_sql = f"SELECT COUNT(*) FROM detections WHERE Date = DATE('{today}') AND Sci_name = '{sci_name}'" select_sql = f"SELECT COUNT(*) FROM detections WHERE Date = DATE('{today}') AND Sci_Name = '{sci_name}'"
records = get_records(db_path, select_sql) records = get_records(db_path, select_sql)
return records[0][0] if records else 0 return records[0][0] if records else 0
def get_this_weeks_count_for(db_path, sci_name): def get_this_weeks_count_for(db_path, sci_name):
today = datetime.now().strftime("%Y-%m-%d") today = datetime.now().strftime("%Y-%m-%d")
select_sql = f"SELECT COUNT(*) FROM detections WHERE Date >= DATE('{today}', '-7 day') AND Sci_name = '{sci_name}'" select_sql = f"SELECT COUNT(*) FROM detections WHERE Date >= DATE('{today}', '-7 day') AND Sci_Name = '{sci_name}'"
records = get_records(db_path, select_sql) records = get_records(db_path, select_sql)
return records[0][0] if records else 0 return records[0][0] if records else 0
@@ -165,8 +165,8 @@ def get_records(db_path, select_sql):
cur.execute(select_sql) cur.execute(select_sql)
records = cur.fetchall() records = cur.fetchall()
con.close() con.close()
except sqlite3.Error: except sqlite3.Error as e:
print("Database busy") print(f"Database busy: {e}")
timeim.sleep(2) timeim.sleep(2)
records = [] records = []
return records return records
+156 -129
View File
@@ -1,138 +1,165 @@
import os import os
import sqlite3 import sqlite3
import pytest
from scripts.utils.notifications import sendAppriseNotifications
from datetime import datetime from datetime import datetime
import unittest
from unittest.mock import patch
from scripts.utils import notifications
from scripts.utils.notifications import sendAppriseNotifications
def create_test_db(db_file): class TestAppriseNotifications(unittest.TestCase):
""" create a database connection to a SQLite database """
conn = None
try:
conn = sqlite3.connect(db_file)
sql_create_detections_table = """ CREATE TABLE IF NOT EXISTS detections (
id integer PRIMARY KEY,
Com_Name text NOT NULL,
Date date NULL,
Time time NULL
); """
cur = conn.cursor()
cur.execute(sql_create_detections_table)
sql = ''' INSERT INTO detections(Com_Name, Date)
VALUES(?,?) '''
cur = conn.cursor() @classmethod
today = datetime.now().strftime("%Y-%m-%d") # SQLite stores date as YYYY-MM-DD def setUpClass(cls):
cur.execute(sql, ["Great Crested Flycatcher", today]) cls.db_file = "test.db"
conn.commit() cls.apprise_body_file = "test_apprise_body"
cls.apprise_config_file = "test_apprise_config"
except Exception as e: def create_test_db(self):
print(e) """ create a database connection to a SQLite database """
finally: conn = None
if conn: try:
conn.close() conn = sqlite3.connect(self.db_file)
sql_create_detections_table = """ CREATE TABLE IF NOT EXISTS detections (
id integer PRIMARY KEY,
Sci_Name text NOT NULL,
Com_Name text NOT NULL,
Date date NOT NULL,
Time time NULL
); """
cur = conn.cursor()
cur.execute(sql_create_detections_table)
sql = ''' INSERT INTO detections(Sci_Name, Com_Name, Date)
VALUES(?,?,?) '''
today = datetime.now().strftime("%Y-%m-%d") # SQLite stores date as YYYY-MM-DD
cur.execute(sql, ["Myiarchus crinitus", "Great Crested Flycatcher", today])
conn.commit()
except Exception as e:
print(e)
finally:
if conn:
conn.close()
def create_apprise_config(self):
with open(self.apprise_body_file, 'w') as f:
f.write('A $comname ($sciname) was just detected with a confidence of $confidencepct ($reason)')
with open(self.apprise_config_file, 'w') as f:
f.write('a dummy config')
notifications.APPRISE_BODY = self.apprise_body_file
notifications.APPRISE_CONFIG = self.apprise_config_file
def tearDown(self):
if os.path.exists(self.db_file):
os.remove(self.db_file)
if os.path.exists(self.apprise_body_file):
os.remove(self.apprise_body_file)
if os.path.exists(self.apprise_config_file):
os.remove(self.apprise_config_file)
@patch('scripts.utils.notifications.notify')
def test_notifications(self, mock_notify):
self.create_test_db()
self.create_apprise_config()
settings_dict = {
"APPRISE_NOTIFICATION_TITLE": "New backyard bird!",
"APPRISE_NOTIFY_EACH_DETECTION": "0",
"APPRISE_NOTIFY_NEW_SPECIES": "0",
"APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY": "0",
"APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES": "0"
}
sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher",
"0.91",
"91",
"filename",
"1666-06-06",
"06:06:06",
"06",
"-1",
"-1",
"0.7",
"1.25",
"0.0",
settings_dict,
self.db_file)
# No active apprise notifications configured. Confirm no notifications.
self.assertEqual(mock_notify.call_count, 0)
# Add daily notification.
mock_notify.reset_mock()
settings_dict["APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY"] = "1"
sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher",
"0.91",
"91",
"filename",
"1666-06-06",
"06:06:06",
"06",
"-1",
"-1",
"0.7",
"1.25",
"0.0",
settings_dict,
self.db_file)
self.assertEqual(mock_notify.call_count, 1)
self.assertEqual(
mock_notify.call_args_list[0][0][0],
"A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (first time today)"
)
# Add new species notification.
mock_notify.reset_mock()
settings_dict["APPRISE_NOTIFY_NEW_SPECIES"] = "1"
sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher",
"0.91",
"91",
"filename",
"1666-06-06",
"06:06:06",
"06",
"-1",
"-1",
"0.7",
"1.25",
"0.0",
settings_dict,
self.db_file)
self.assertEqual(mock_notify.call_count, 2)
self.assertEqual(
mock_notify.call_args_list[0][0][0],
"A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (first time today)"
)
self.assertEqual(
mock_notify.call_args_list[1][0][0],
"A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (only seen 1 times in last 7d)"
)
# Add each species notification.
mock_notify.reset_mock()
settings_dict["APPRISE_NOTIFY_EACH_DETECTION"] = "1"
sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher",
"0.91",
"91",
"filename",
"1666-06-06",
"06:06:06",
"06",
"-1",
"-1",
"0.7",
"1.25",
"0.0",
settings_dict,
self.db_file)
self.assertEqual(mock_notify.call_count, 3)
@pytest.fixture(autouse=True) if __name__ == '__main__':
def clean_up_after_each_test(): unittest.main()
yield
os.remove("test.db")
def test_notifications(mocker):
notify_call = mocker.patch('scripts.utils.notifications.notify')
create_test_db("test.db")
settings_dict = {
"APPRISE_NOTIFICATION_TITLE": "New backyard bird!",
"APPRISE_NOTIFICATION_BODY": "A $comname ($sciname) was just detected with a confidence of $confidence",
"APPRISE_NOTIFY_EACH_DETECTION": "0",
"APPRISE_NOTIFY_NEW_SPECIES": "0",
"APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY": "0"
}
sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher",
"0.91",
"91",
"filename",
"1666-06-06",
"06:06:06",
"06",
"-1",
"-1",
"0.7",
"1.25",
"0.0",
settings_dict,
"test.db")
# No active apprise notifcations configured. Confirm no notifications.
assert (notify_call.call_count == 0) # No notification should be sent.
# Add daily notification.
notify_call.reset_mock()
settings_dict["APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY"] = "1"
sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher",
"0.91",
"91",
"filename",
"1666-06-06",
"06:06:06",
"06",
"-1",
"-1",
"0.7",
"1.25",
"0.0",
settings_dict,
"test.db")
assert (notify_call.call_count == 1)
assert (
notify_call.call_args_list[0][0][0] == "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (first time today)"
)
# Add new species notification.
notify_call.reset_mock()
settings_dict["APPRISE_NOTIFY_NEW_SPECIES"] = "1"
sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher",
"0.91",
"91",
"filename",
"1666-06-06",
"06:06:06",
"06",
"-1",
"-1",
"0.7",
"1.25",
"0.0",
settings_dict,
"test.db")
assert (notify_call.call_count == 2)
assert (
notify_call.call_args_list[0][0][0] == "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (first time today)"
)
assert (
notify_call.call_args_list[1][0][0] == "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence \
of 91 (only seen 1 times in last 7d)"
)
# Add each species notification.
notify_call.reset_mock()
settings_dict["APPRISE_NOTIFY_EACH_DETECTION"] = "1"
sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher",
"0.91",
"91",
"filename",
"1666-06-06",
"06:06:06",
"06",
"-1",
"-1",
"0.7",
"1.25",
"0.0",
settings_dict,
"test.db")
assert (notify_call.call_count == 3)