diff --git a/SOUNDS/alert.wav b/SOUNDS/alert.wav deleted file mode 100644 index ab46098..0000000 Binary files a/SOUNDS/alert.wav and /dev/null differ diff --git a/SOUNDS/wx-tail.wav b/SOUNDS/wx-tail.wav deleted file mode 100644 index ab94440..0000000 Binary files a/SOUNDS/wx-tail.wav and /dev/null differ diff --git a/SkywarnPlus.py b/SkywarnPlus.py index 4a913bd..92f4414 100644 --- a/SkywarnPlus.py +++ b/SkywarnPlus.py @@ -292,7 +292,8 @@ def getAlerts(countyCodes): logger.debug("Checking for alerts in {}".format(countyCodes)) for countyCode in countyCodes: logger.debug("Checking for alerts in {}".format(countyCode)) - url = "https://api.weather.gov/alerts/active?zone={}".format(countyCode) + # url = "https://api.weather.gov/alerts/active?zone={}".format(countyCode) + url = "https://api.weather.gov/alerts/active?area=AR" # THIS RETURNS ALL ACTIVE ALERTS IN THE US logger.debug("Requesting {}".format(url)) response = requests.get(url) logger.debug("Response: {}\n\n".format(response.text)) @@ -324,7 +325,6 @@ def getAlerts(countyCodes): else: severity = severity_mapping_api.get(severity, 0) alerts.append((event, severity)) # Add event to list as a tuple - logger.debug("{}: {} with severity {}".format(countyCode, event, severity)) else: logger.error( "Failed to retrieve alerts for {}, HTTP status code {}, response: {}".format( @@ -332,14 +332,28 @@ def getAlerts(countyCodes): ) ) - # Sort alerts by severity (highest to lowest) and only keep the events - alerts.sort(key=lambda x: x[1], reverse=True) + # Convert list to set to eliminate duplicates, then convert back to list + alerts = list(set(alerts)) + + # Sort by both API-provided severity and 'words' severity + alerts.sort( + key=lambda x: ( + x[1], # API-provided severity + severity_mapping_words.get(x[0].split()[-1], 0) # 'words' severity + ), + reverse=True + ) + + logger.debug("Sorted alerts: (alert), (severity)") + for alert in alerts: + logger.debug(alert) + + # Only keep the events (not the severities) alerts = [alert[0] for alert in alerts[:max_alerts]] # Only keep the first 'max_alerts' alerts return alerts - def sayAlert(alerts): """ Generate and broadcast severe weather alert sounds on Asterisk. @@ -358,8 +372,8 @@ def sayAlert(alerts): alert_count = 0 # Counter for alerts added to combined_sound for alert in alerts: - # Check if alert is in the SayAlertBlockedEvents list - if alert in sayalert_blocked_events: + # Check if alert matches any pattern in the SayAlertBlockedEvents list + if any(fnmatch.fnmatch(alert, blocked_event) for blocked_event in sayalert_blocked_events): logger.debug("SayAlert blocking {} as per configuration".format(alert)) continue @@ -439,8 +453,8 @@ def buildTailmessage(alerts): os.path.join(sounds_path, "ALERTS", "SWP95.wav") ) for alert in alerts: - # Check if alert is in the TailmessageBlockedEvents list - if alert in tailmessage_blocked_events: + # Check if alert matches any pattern in the TailmessageBlockedEvents list + if any(fnmatch.fnmatch(alert, blocked_event) for blocked_event in tailmessage_blocked_events): logger.debug("Alert blocked by TailmessageBlockedEvents: {}".format(alert)) continue diff --git a/config.ini b/config.ini index 2483e63..a6cf2ac 100644 --- a/config.ini +++ b/config.ini @@ -36,7 +36,7 @@ SayAllClear = True ; [Tornado Warning, Severe Thunderstorm Warning, Flood Watch, Special Weather Statement], ; and MaxAlerts = 2, then SkywarnPlus will only process the Tornado Warning and Severe Thunderstorm Warning. ; Example: MaxAlerts = 3 -MaxAlerts = 2 +MaxAlerts = 5 ; Optional alternate path to the directory where sound files are stored ; Default is SkywarnPlus/SOUNDS @@ -47,17 +47,22 @@ MaxAlerts = 2 [Blocking] ; GLOBAL BLOCKING - These alerts will be completely ignored and filtered out of the entire SkywarnPlus workflow ; CASE SENSITIVE list of events to ignore, comma separated. Wildcards can be used, e.g. *Statement, *Advisory -GlobalBlockedEvents = +; Example: GlobalBlockedEvents = *Statement, *Advisory +GlobalBlockedEvents = ; SayAlert Blocking ; These alerts will be blocked from being spoken when they are received ; These alerts will still be added to the tailmessage -SayAlertBlockedEvents = +; CASE SENSITIVE list of events to ignore, comma separated. +; Example: SayAlertBlockedEvents = *Statement, *Advisory +SayAlertBlockedEvents = ; Tailmessage Blocking ; These alerts will be blocked from being added to the tailmessage ; These alerts will still be spoken when they are received -TailmessageBlockedEvents = +; CASE SENSITIVE list of events to ignore, comma separated. +; Example: TailmessageBlockedEvents = *Statement, *Advisory +TailmessageBlockedEvents = ; Tail message settings [Tailmessage] @@ -109,10 +114,13 @@ RptLinkCT = CT-LINK.ulaw CTAlerts = Hurricane Force Wind Warning, Severe Thunderstorm Warning, Tropical Storm Warning, + Coastal Flood Warning, Winter Storm Warning, Thunderstorm Warning, Extreme Wind Warning, Storm Surge Warning, + Dust Storm Warning, + Avalanche Warning, Ice Storm Warning, Hurricane Warning, Blizzard Warning, @@ -141,7 +149,7 @@ Debug = False [Logging] ; Enable more verbose logging ; Either True or False -Debug = True +Debug = False ; Optional alternate log file path ; Default is /tmp/Skywarnplus/SkywarnPlus.log @@ -152,7 +160,7 @@ Debug = True [DEV] ; Delete cached data on startup ; Either True or False -CLEANSLATE = True +CLEANSLATE = False ; Optional alternate TMP directory ; Default is /tmp/SkywarnPlus @@ -160,12 +168,9 @@ CLEANSLATE = True ;TmpDir = /tmp/SkywarnPlus ; Enable to inject the below list of test alerts instead of calling the NWS API -INJECT = True +INJECT = False ; CASE SENSITIVE, comma & newline separated list of alerts to inject -INJECTALERTS = Wind Advisory, - Special Weather Statement, +INJECTALERTS = Tornado Warning, Tornado Watch, - Tornado Warning, - Severe Thunderstorm Warning, - Flood Watch + Severe Thunderstorm Warning