Merge pull request #1 from Mason10198/develop

Develop
pull/17/head
Mason10198 3 years ago committed by GitHub
commit bb20c520ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -4,6 +4,7 @@
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files # User-specific files
template.ini
*.rsuser *.rsuser
*.suo *.suo
*.user *.user

@ -0,0 +1,6 @@
{
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
"python.formatting.provider": "none"
}

@ -10,7 +10,7 @@ Tested on ASL 1.01, ASL 2.0.0, and HAMVOIP 1.7-01.
- **Performance**: Designed for minimal impact on internet bandwidth and storage, reducing unnecessary I/O operations. - **Performance**: Designed for minimal impact on internet bandwidth and storage, reducing unnecessary I/O operations.
- **Alert Coverage**: Allows specifying multiple counties for alerts, ensuring broad coverage. - **Alert Coverage**: Allows specifying multiple counties for alerts, ensuring broad coverage.
- **Alert Priority**: Alerts are automatically sorted by severity (Warning, Watch, Advisory, Statement), so you always hear the most important alerts first. - **Alert Priority**: Alerts are automatically sorted by severity (Warning, Watch, Advisory, Statement), so you always hear the most important alerts first.
- **Alert Filtering**: Provides advanced options to block or filter alerts using regular expressions and wildcards. - **Alert Filtering**: Provides advanced options to block or filter alerts from specific functions using regular expressions and wildcards.
- **Remote Control**: Includes a control script that can be mapped to DTMF commands, allowing instant over-the-air control of your system. - **Remote Control**: Includes a control script that can be mapped to DTMF commands, allowing instant over-the-air control of your system.
- **Automatic Courtesy Tones**: Changes repeater courtesy tones based on active alerts. - **Automatic Courtesy Tones**: Changes repeater courtesy tones based on active alerts.
- **Duplicate Filtering**: Ensures the same alert is never broadcast twice. - **Duplicate Filtering**: Ensures the same alert is never broadcast twice.

@ -55,7 +55,11 @@ if not os.path.exists(tmp_dir):
os.makedirs(tmp_dir) os.makedirs(tmp_dir)
# List of blocked events # List of blocked events
blocked_events = config["Blocking"].get("BlockedEvents").split(",") global_blocked_events = config["Blocking"].get("GlobalBlockedEvents").split(",")
sayalert_blocked_events = config["Blocking"].get("SayAlertBlockedEvents").split(",")
tailmessage_blocked_events = (
config["Blocking"].get("TailmessageBlockedEvents").split(",")
)
# Configuration for tailmessage # Configuration for tailmessage
tailmessage_config = config["Tailmessage"] tailmessage_config = config["Tailmessage"]
# Flag to enable/disable tailmessage # Flag to enable/disable tailmessage
@ -252,7 +256,9 @@ logger.debug("Base directory: {}".format(baseDir))
logger.debug("Temporary directory: {}".format(tmp_dir)) logger.debug("Temporary directory: {}".format(tmp_dir))
logger.debug("Sounds path: {}".format(sounds_path)) logger.debug("Sounds path: {}".format(sounds_path))
logger.debug("Tailmessage path: {}".format(tailmessage_file)) logger.debug("Tailmessage path: {}".format(tailmessage_file))
logger.debug("Blocked events: {}".format(blocked_events)) logger.debug("Global Blocked events: {}".format(global_blocked_events))
logger.debug("SayAlert Blocked events: {}".format(sayalert_blocked_events))
logger.debug("Tailmessage Blocked events: {}".format(tailmessage_blocked_events))
def getAlerts(countyCodes): def getAlerts(countyCodes):
@ -292,10 +298,12 @@ def getAlerts(countyCodes):
expires_time = parser.isoparse(expires) expires_time = parser.isoparse(expires)
if expires_time > current_time: if expires_time > current_time:
event = feature["properties"]["event"] event = feature["properties"]["event"]
for blocked_event in blocked_events: for global_blocked_event in global_blocked_events:
if fnmatch.fnmatch(event, blocked_event): if fnmatch.fnmatch(event, global_blocked_event):
logger.debug( logger.debug(
"Blocking {} as per configuration".format(event) "Globally Blocking {} as per configuration".format(
event
)
) )
break break
else: else:
@ -328,7 +336,14 @@ def sayAlert(alerts):
os.path.join(sounds_path, "ALERTS", "SWP95.wav") os.path.join(sounds_path, "ALERTS", "SWP95.wav")
) )
alert_count = 0 # Counter for alerts added to combined_sound
for alert in alerts: for alert in alerts:
# Check if alert is in the SayAlertBlockedEvents list
if alert in sayalert_blocked_events:
logger.debug("SayAlert blocking {} as per configuration".format(alert))
continue
try: try:
index = WS.index(alert) index = WS.index(alert)
audio_file = AudioSegment.from_wav( audio_file = AudioSegment.from_wav(
@ -336,6 +351,7 @@ def sayAlert(alerts):
) )
combined_sound += sound_effect + audio_file combined_sound += sound_effect + audio_file
logger.debug("Added {} (SWP{}.wav) to alert sound".format(alert, WA[index])) logger.debug("Added {} (SWP{}.wav) to alert sound".format(alert, WA[index]))
alert_count += 1 # Increment the counter
except ValueError: except ValueError:
logger.error("Alert not found: {}".format(alert)) logger.error("Alert not found: {}".format(alert))
except FileNotFoundError: except FileNotFoundError:
@ -345,26 +361,29 @@ def sayAlert(alerts):
) )
) )
logger.debug("Exporting alert sound to {}".format(alert_file)) if alert_count == 0: # Check the counter instead of combined_sound.empty()
converted_combined_sound = convert_audio(combined_sound) logger.debug("SayAlert: All alerts were blocked, not broadcasting any alerts.")
converted_combined_sound.export(alert_file, format="wav") else:
logger.debug("Exporting alert sound to {}".format(alert_file))
converted_combined_sound = convert_audio(combined_sound)
converted_combined_sound.export(alert_file, format="wav")
logger.debug("Replacing tailmessage with silence") logger.debug("Replacing tailmessage with silence")
silence = AudioSegment.silent(duration=100) silence = AudioSegment.silent(duration=100)
converted_silence = convert_audio(silence) converted_silence = convert_audio(silence)
converted_silence.export(tailmessage_file, format="wav") converted_silence.export(tailmessage_file, format="wav")
node_numbers = config["Asterisk"]["Nodes"].split(",") node_numbers = config["Asterisk"]["Nodes"].split(",")
for node_number in node_numbers: for node_number in node_numbers:
logger.info("Broadcasting alert on node {}".format(node_number)) logger.info("Broadcasting alert on node {}".format(node_number))
command = '/usr/sbin/asterisk -rx "rpt localplay {} {}"'.format( command = '/usr/sbin/asterisk -rx "rpt localplay {} {}"'.format(
node_number.strip(), os.path.splitext(os.path.abspath(alert_file))[0] node_number.strip(), os.path.splitext(os.path.abspath(alert_file))[0]
) )
subprocess.run(command, shell=True) subprocess.run(command, shell=True)
# This keeps Asterisk from playing the tailmessage immediately after the alert # This keeps Asterisk from playing the tailmessage immediately after the alert
logger.info("Waiting 30 seconds for Asterisk to make announcement...") logger.info("Waiting 30 seconds for Asterisk to make announcement...")
time.sleep(30) time.sleep(30)
def sayAllClear(): def sayAllClear():
@ -401,6 +420,11 @@ def buildTailmessage(alerts):
os.path.join(sounds_path, "ALERTS", "SWP95.wav") os.path.join(sounds_path, "ALERTS", "SWP95.wav")
) )
for alert in alerts: for alert in alerts:
# Check if alert is in the TailmessageBlockedEvents list
if alert in tailmessage_blocked_events:
logger.debug("Alert blocked by TailmessageBlockedEvents: {}".format(alert))
continue
try: try:
index = WS.index(alert) index = WS.index(alert)
audio_file = AudioSegment.from_wav( audio_file = AudioSegment.from_wav(
@ -416,6 +440,11 @@ def buildTailmessage(alerts):
sounds_path, WA[index] sounds_path, WA[index]
) )
) )
if combined_sound.empty():
logger.debug(
"BuildTailmessage: All alerts were blocked, creating silent tailmessage"
)
combined_sound = AudioSegment.silent(duration=100)
logger.debug("Exporting tailmessage to {}".format(tailmessage_file)) logger.debug("Exporting tailmessage to {}".format(tailmessage_file))
converted_combined_sound = convert_audio(combined_sound) converted_combined_sound = convert_audio(combined_sound)
converted_combined_sound.export(tailmessage_file, format="wav") converted_combined_sound.export(tailmessage_file, format="wav")

@ -35,8 +35,19 @@ SayAllClear = True
; Blocking settings ; Blocking settings
[Blocking] [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 ; CASE SENSITIVE list of events to ignore, comma separated. Wildcards can be used, e.g. *Statement, *Advisory
BlockedEvents = 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 =
; Tailmessage Blocking
; These alerts will be blocked from being added to the tailmessage
; These alerts will still be spoken when they are received
TailmessageBlockedEvents =
; Tail message settings ; Tail message settings
[Tailmessage] [Tailmessage]

Loading…
Cancel
Save

Powered by TurnKey Linux.