From 200048ca27e5d627481a477d8e63aacff58dd5a0 Mon Sep 17 00:00:00 2001 From: frederik Date: Sun, 26 Oct 2025 12:05:17 +0100 Subject: [PATCH] update Detection signature --- scripts/send_test_notification.py | 3 ++- scripts/utils/helpers.py | 8 +++---- scripts/utils/notifications.py | 34 ++++++++++++++--------------- scripts/utils/reporting.py | 2 +- tests/test_apprise_notifications.py | 12 ++++++---- 5 files changed, 31 insertions(+), 28 deletions(-) diff --git a/scripts/send_test_notification.py b/scripts/send_test_notification.py index 20b75bc..789afce 100755 --- a/scripts/send_test_notification.py +++ b/scripts/send_test_notification.py @@ -33,6 +33,7 @@ if __name__ == "__main__": logger.addHandler(handler) logger.setLevel(logging.INFO) - notifications.sendAppriseNotifications(f"{d['Sci_Name']}_{d['Com_Name']}", d['Confidence'], round(d['Confidence'] * 100), d['File_Name'], + notifications.sendAppriseNotifications({d['Sci_Name']}, {d['Com_Name']}, d['Confidence'], + round(d['Confidence'] * 100), d['File_Name'], d['Date'], d['Time'], d['Week'], d['Lat'], d['Lon'], d['Cutoff'], d['Sens'], d['Overlap'], dict(conf), DB_PATH) diff --git a/scripts/utils/helpers.py b/scripts/utils/helpers.py index 59abfa2..e470f90 100644 --- a/scripts/utils/helpers.py +++ b/scripts/utils/helpers.py @@ -61,7 +61,7 @@ def get_settings(settings_path='/etc/birdnet/birdnet.conf', force_reload=False): class Detection: - def __init__(self, file_date, start_time, stop_time, species, confidence): + def __init__(self, file_date, start_time, stop_time, scientific_name, common_name, confidence): self.start = float(start_time) self.stop = float(stop_time) self.datetime = file_date + datetime.timedelta(seconds=self.start) @@ -71,9 +71,9 @@ class Detection: self.week = self.datetime.isocalendar()[1] self.confidence = round(float(confidence), 4) self.confidence_pct = round(self.confidence * 100) - self.species = species - self.scientific_name = species.split('_')[0] - self.common_name = species.split('_')[1] + self.species = scientific_name + self.scientific_name = scientific_name + self.common_name = common_name self.common_name_safe = self.common_name.replace("'", "").replace(" ", "_") self.file_name_extr = None diff --git a/scripts/utils/notifications.py b/scripts/utils/notifications.py index 4f425a5..1becb30 100644 --- a/scripts/utils/notifications.py +++ b/scripts/utils/notifications.py @@ -44,12 +44,12 @@ def notify(body, title, attached=""): ) -def sendAppriseNotifications(species, confidence, confidencepct, path, +def sendAppriseNotifications(sci_name, com_name, confidence, confidencepct, path, date, time, week, latitude, longitude, cutoff, sens, overlap, settings_dict, db_path=DB_PATH): def render_template(template, reason=""): - ret = template.replace("$sciname", sciName) \ - .replace("$comname", comName) \ + ret = template.replace("$sciname", sci_name) \ + .replace("$comname", com_name) \ .replace("$confidencepct", str(confidencepct)) \ .replace("$confidence", str(confidence)) \ .replace("$listenurl", listenurl) \ @@ -74,23 +74,21 @@ def sendAppriseNotifications(species, confidence, confidencepct, path, f = open(APPRISE_BODY, 'r') body = f.read() - sciName, comName = species.split("_") - APPRISE_ONLY_NOTIFY_SPECIES_NAMES = settings_dict.get('APPRISE_ONLY_NOTIFY_SPECIES_NAMES') if APPRISE_ONLY_NOTIFY_SPECIES_NAMES is not None and APPRISE_ONLY_NOTIFY_SPECIES_NAMES.strip() != "": - if any(bird.lower().replace(" ", "") in comName.lower().replace(" ", "") for bird in APPRISE_ONLY_NOTIFY_SPECIES_NAMES.split(",")): + if any(bird.lower().replace(" ", "") in com_name.lower().replace(" ", "") for bird in APPRISE_ONLY_NOTIFY_SPECIES_NAMES.split(",")): return APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2 = settings_dict.get('APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2') if APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2 is not None and APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2.strip() != "": - if not any(bird.lower().replace(" ", "") in comName.lower().replace(" ", "") for bird in APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2.split(",")): + if not any(bird.lower().replace(" ", "") in com_name.lower().replace(" ", "") for bird in APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2.split(",")): return APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES = settings_dict.get('APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES') if APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES != "0": - if species_last_notified.get(comName) is not None: + if species_last_notified.get(com_name) is not None: try: - if int(timeim.time()) - species_last_notified[comName] < int(APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES): + if int(timeim.time()) - species_last_notified[com_name] < int(APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES): return except Exception as e: print("APPRISE NOTIFICATION EXCEPTION: "+str(e)) @@ -109,39 +107,39 @@ def sendAppriseNotifications(species, confidence, confidencepct, path, image_url = "" if "$flickrimage" in body or "$image" in body: - if comName not in images: + if com_name not in images: try: - url = f"http://localhost/api/v1/image/{sciName}" + url = f"http://localhost/api/v1/image/{sci_name}" resp = requests.get(url=url, timeout=10).json() - images[comName] = resp['data']['image_url'] + images[com_name] = resp['data']['image_url'] except Exception as e: print("IMAGE API ERROR: "+str(e)) - image_url = images.get(comName, "") + image_url = images.get(com_name, "") if settings_dict.get('APPRISE_NOTIFY_EACH_DETECTION') == "1": notify_body = render_template(body, "detection") notify_title = render_template(title, "detection") notify(notify_body, notify_title, image_url) - species_last_notified[comName] = int(timeim.time()) + species_last_notified[com_name] = int(timeim.time()) APPRISE_NOTIFICATION_NEW_SPECIES_DAILY_COUNT_LIMIT = 1 # Notifies the first N per day. if settings_dict.get('APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY') == "1": - numberDetections = get_todays_count_for(db_path, sciName) + numberDetections = get_todays_count_for(db_path, sci_name) if 0 < numberDetections <= APPRISE_NOTIFICATION_NEW_SPECIES_DAILY_COUNT_LIMIT: print("send the notification") notify_body = render_template(body, "first time today") notify_title = render_template(title, "first time today") notify(notify_body, notify_title, image_url) - species_last_notified[comName] = int(timeim.time()) + species_last_notified[com_name] = int(timeim.time()) if settings_dict.get('APPRISE_NOTIFY_NEW_SPECIES') == "1": - numberDetections = get_this_weeks_count_for(db_path, sciName) + numberDetections = get_this_weeks_count_for(db_path, sci_name) if 0 < numberDetections <= 5: reason = f"only seen {numberDetections} times in last 7d" notify_body = render_template(body, reason) notify_title = render_template(title, reason) notify(notify_body, notify_title, image_url) - species_last_notified[comName] = int(timeim.time()) + species_last_notified[com_name] = int(timeim.time()) def get_todays_count_for(db_path, sci_name): diff --git a/scripts/utils/reporting.py b/scripts/utils/reporting.py index 171f90f..3edd086 100644 --- a/scripts/utils/reporting.py +++ b/scripts/utils/reporting.py @@ -156,7 +156,7 @@ def apprise(file: ParseFileName, detections: [Detection]): # Apprise of detection if not already alerted this run. if detection.species not in species_apprised_this_run: try: - sendAppriseNotifications(detection.species, str(detection.confidence), str(detection.confidence_pct), + sendAppriseNotifications(detection.scientific_name, detection.common_name, str(detection.confidence), str(detection.confidence_pct), os.path.basename(detection.file_name_extr), detection.date, detection.time, str(detection.week), conf['LATITUDE'], conf['LONGITUDE'], conf['CONFIDENCE'], conf['SENSITIVITY'], conf['OVERLAP'], dict(conf), DB_PATH) diff --git a/tests/test_apprise_notifications.py b/tests/test_apprise_notifications.py index d45ca4c..2b1e836 100644 --- a/tests/test_apprise_notifications.py +++ b/tests/test_apprise_notifications.py @@ -70,7 +70,8 @@ class TestAppriseNotifications(unittest.TestCase): "APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY": "0", "APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES": "0" } - sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", + sendAppriseNotifications("Myiarchus crinitus", + "Great Crested Flycatcher", "0.91", "91", "filename", @@ -91,7 +92,8 @@ class TestAppriseNotifications(unittest.TestCase): # Add daily notification. mock_notify.reset_mock() settings_dict["APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY"] = "1" - sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", + sendAppriseNotifications("Myiarchus crinitus", + "Great Crested Flycatcher", "0.91", "91", "filename", @@ -115,7 +117,8 @@ class TestAppriseNotifications(unittest.TestCase): # Add new species notification. mock_notify.reset_mock() settings_dict["APPRISE_NOTIFY_NEW_SPECIES"] = "1" - sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", + sendAppriseNotifications("Myiarchus crinitus", + "Great Crested Flycatcher", "0.91", "91", "filename", @@ -143,7 +146,8 @@ class TestAppriseNotifications(unittest.TestCase): # Add each species notification. mock_notify.reset_mock() settings_dict["APPRISE_NOTIFY_EACH_DETECTION"] = "1" - sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", + sendAppriseNotifications("Myiarchus crinitus", + "Great Crested Flycatcher", "0.91", "91", "filename",