mirror of
https://github.com/SpudGunMan/meshing-around.git
synced 2026-07-06 01:41:45 +02:00
EAS API Alerts
Enable EAS API Messages to Mesh Fix multiping Device 2
This commit is contained in:
@@ -37,8 +37,12 @@ Welcome to the Mesh Bot project! This feature-rich bot is designed to enhance yo
|
||||
- **SNR RF Activity Alerts**: Monitor a radio frequency and get alerts when high SNR RF activity is detected.
|
||||
- **Hamlib Integration**: Use Hamlib (rigctld) to watch the S meter on a connected radio.
|
||||
|
||||
### NOAA EAS Alerts
|
||||
- **EAS Alerts via NOAA API**: Use an internet connected node to message Emergency Alerts from NOAA
|
||||
- **EAS Alerts over the air**: Utalizing external tools to report EAS alerts offline over mesh
|
||||
|
||||
### File Monitor Alerts
|
||||
- **File Mon**: Monitor a flat/text file for changes, brodcast the contents of the message to mesh channel. This could be used to monitor NOAA OTA EAS System and offgrid send these alerts or any others to the mesh. Or to parse data from any other tools capable of writing information to file.
|
||||
- **File Mon**: Monitor a flat/text file for changes, brodcast the contents of the message to mesh channel.
|
||||
|
||||
### Data Reporting
|
||||
- **HTML Generator**: Visualize bot traffic and data flows with a built-in HTML generator for [data reporting](logs/README.md).
|
||||
@@ -215,17 +219,29 @@ file_path = alert.txt
|
||||
broadcastCh = 2,4
|
||||
```
|
||||
#### NOAA EAS
|
||||
To Alert on Mesh with the NOAA EAS API you can set the channels and enable, checks every 30min
|
||||
|
||||
```ini
|
||||
# EAS Alert Broadcast
|
||||
wxAlertBroadcastEnabled = False
|
||||
# EAS Alert Broadcast Channels
|
||||
wxAlertBroadcastCh = 2,4
|
||||
```
|
||||
|
||||
To Monitor EAS with no internet connection see the following notes
|
||||
|
||||
- [EAS2Text](https://github.com/A-c0rN/EAS2Text)
|
||||
- depends on [multimon-ng](https://github.com/EliasOenal/multimon-ng) or [direwolf](https://github.com/wb2osz/direwolf)
|
||||
- [dsame3](https://github.com/jamieden/dsame3)
|
||||
- this can be used with a rtl-sdr to capture alerts
|
||||
- has a sample .ogg file for testing alerts
|
||||
- TODO: fork this and have copy which will just dump the needed data right away?
|
||||
- [EAS2Text](https://github.com/A-c0rN/EAS2Text)
|
||||
- depends on [multimon-ng](https://github.com/EliasOenal/multimon-ng) or [direwolf](https://github.com/wb2osz/direwolf)
|
||||
|
||||
The following shell command can pipe the data using [etc/eas_alert_parser.py](etc/eas_alert_parser.py)
|
||||
```bash
|
||||
sox -t ogg WXR-RWT.ogg -esigned-integer -b16 -r 22050 -t raw - | multimon-ng -a EAS -v 1 -t raw - > raw_NOAA_Alert.txt
|
||||
sox -t ogg WXR-RWT.ogg -esigned-integer -b16 -r 22050 -t raw - | multimon-ng -a EAS -v 1 -t raw - | python ftw.py
|
||||
```
|
||||
|
||||
|
||||
### Scheduler
|
||||
The Scheduler is enabled in the `settings.py` by setting `scheduler_enabled = True`. The actions and settings are via code only at this time. See mesh_bot.py around line [425](https://github.com/SpudGunMan/meshing-around/blob/22983133ee4db3df34f66699f565e506de296197/mesh_bot.py#L425-L435) to edit the schedule. See [schedule documentation](https://schedule.readthedocs.io/en/stable/) for more.
|
||||
|
||||
@@ -281,8 +297,6 @@ For the Ollama LLM:
|
||||
|
||||
```sh
|
||||
pip install ollama
|
||||
pip install langchain
|
||||
pip install langchain-ollama
|
||||
pip install googlesearch-python
|
||||
```
|
||||
|
||||
@@ -325,6 +339,7 @@ sudo apt-get install fonts-noto-color-emoji
|
||||
| `bbspost` | Posts a message to the public board or sends a DM(Mail) Examples: `bbspost $subject #message`, `bbspost @nodeNumber #message`, `bbspost @nodeShortName #message` | ✅ |
|
||||
| `bbsdelete` | Deletes a message. Example: `bbsdelete #4` | ✅ |
|
||||
| `bbsinfo` | Provides stats on BBS delivery and messages (sysop) | ✅ |
|
||||
| `bbllink` | Links Bulletin Messages between BBS Systems | ✅ |
|
||||
|
||||
### Data Lookup
|
||||
| Command | Description | |
|
||||
@@ -373,5 +388,3 @@ I used ideas and snippets from other responder bots and want to call them out!
|
||||
|
||||
### Tools
|
||||
- **Node Backup Management**: [Node Slurper](https://github.com/SpudGunMan/node-slurper)
|
||||
|
||||
|
||||
|
||||
@@ -107,6 +107,10 @@ UseMeteoWxAPI = False
|
||||
useMetric = False
|
||||
# repeaterList lookup location (rbook / artsci)
|
||||
repeaterLookup = rbook
|
||||
# EAS Alert Broadcast
|
||||
wxAlertBroadcastEnabled = False
|
||||
# EAS Alert Broadcast Channels
|
||||
wxAlertBroadcastCh = 2
|
||||
|
||||
# repeater module
|
||||
[repeater]
|
||||
|
||||
@@ -1039,6 +1039,8 @@ async def start_rx():
|
||||
logger.debug(f"System: Radio Detection Enabled using rigctld at {rigControlServerAddress} brodcasting to channels: {sigWatchBroadcastCh} for {get_freq_common_name(get_hamlib('f'))}")
|
||||
if file_monitor_enabled:
|
||||
logger.debug(f"System: File Monitor Enabled for {file_monitor_file_path}, broadcasting to channels: {file_monitor_broadcastCh}")
|
||||
if wxAlertBroadcastEnabled:
|
||||
logger.debug(f"System: Weather Alert Broadcast Enabled on channels {wxAlertBroadcastChannel}")
|
||||
if scheduler_enabled:
|
||||
# Examples of using the scheduler, Times here are in 24hr format
|
||||
# https://schedule.readthedocs.io/en/stable/
|
||||
|
||||
@@ -369,6 +369,23 @@ def getWeatherAlerts(lat=0, lon=0):
|
||||
data = "\n".join(alerts.split("\n")[:numWxAlerts]), alert_num
|
||||
return data
|
||||
|
||||
wxAlertCache = ""
|
||||
def alertBrodcast():
|
||||
# get the latest weather alerts and broadcast them if there are any
|
||||
global wxAlertCache
|
||||
currentAlert = getWeatherAlerts()
|
||||
|
||||
if currentAlert[0] == ERROR_FETCHING_DATA or currentAlert == NO_DATA_NOGPS or currentAlert == NO_ALERTS:
|
||||
wxAlertCache = ""
|
||||
return False
|
||||
# broadcast the alerts send to wxBrodcastCh
|
||||
elif currentAlert[0] != wxAlertCache:
|
||||
logger.debug("Location:Broadcasting weather alerts")
|
||||
wxAlertCache = currentAlert[0]
|
||||
return currentAlert
|
||||
|
||||
return False
|
||||
|
||||
def getActiveWeatherAlertsDetail(lat=0, lon=0):
|
||||
# get the latest details of weather alerts from NOAA
|
||||
alerts = ""
|
||||
|
||||
+3
-1
@@ -51,7 +51,7 @@ if 'sentry' not in config:
|
||||
config.write(open(config_file, 'w'))
|
||||
|
||||
if 'location' not in config:
|
||||
config['location'] = {'enabled': 'True', 'lat': '48.50', 'lon': '-123.0', 'UseMeteoWxAPI': 'False', 'useMetric': 'False', 'NOAAforecastDuration': '4', 'NOAAalertCount': '2', 'NOAAalertsEnabled': 'True'}
|
||||
config['location'] = {'enabled': 'True', 'lat': '48.50', 'lon': '-123.0', 'UseMeteoWxAPI': 'False', 'useMetric': 'False', 'NOAAforecastDuration': '4', 'NOAAalertCount': '2', 'NOAAalertsEnabled': 'True', 'wxAlertBroadcastEnabled': 'False', 'wxAlertBroadcastChannel': '2', 'repeaterLookup': 'rbook'}
|
||||
config.write(open(config_file, 'w'))
|
||||
|
||||
if 'bbs' not in config:
|
||||
@@ -137,6 +137,8 @@ try:
|
||||
numWxAlerts = config['location'].getint('NOAAalertCount', 2) # default 2 alerts
|
||||
wxAlertsEnabled = config['location'].getboolean('NOAAalertsEnabled', True) # default True not enabled yet
|
||||
repeater_lookup = config['location'].get('repeaterLookup', 'rbook') # default repeater lookup source
|
||||
wxAlertBroadcastEnabled = config['location'].getboolean('wxAlertBroadcastEnabled', False) # default False
|
||||
wxAlertBroadcastChannel = config['location'].get('wxAlertBroadcastChannel', 2)
|
||||
|
||||
# bbs
|
||||
bbs_enabled = config['bbs'].getboolean('enabled', False)
|
||||
|
||||
@@ -588,6 +588,41 @@ def handleMultiPing(nodeID=0, deviceID=1):
|
||||
if multiPingList[j]['message_from_id'] == message_id_from:
|
||||
multiPingList.pop(j)
|
||||
break
|
||||
elif count > 1 and deviceID == 2:
|
||||
count -= 1
|
||||
# update count in the list
|
||||
multiPingList[i]['count'] = count
|
||||
|
||||
send_message(f"🔂{count} {type}", publicChannel, message_id_from, 2)
|
||||
if count < 2:
|
||||
# remove the item from the list
|
||||
for j in range(len(multiPingList)):
|
||||
if multiPingList[j]['message_from_id'] == message_id_from:
|
||||
multiPingList.pop(j)
|
||||
break
|
||||
else:
|
||||
# remove the item from the list
|
||||
for j in range(len(multiPingList)):
|
||||
if multiPingList[j]['message_from_id'] == message_id_from:
|
||||
multiPingList.pop(j)
|
||||
break
|
||||
|
||||
def handleWxBroadcast(deviceID=1):
|
||||
# only allow API call every 30 minutes
|
||||
clock = datetime.now()
|
||||
if clock.minute % 30 != 0:
|
||||
return False
|
||||
|
||||
# check for alerts
|
||||
alert = alertBrodcast()
|
||||
if alert:
|
||||
msg = f"🚨 {alert[1]} EAS ALERTs: {alert[0]}"
|
||||
if "," in wxAlertBroadcastChannel:
|
||||
for channel in wxAlertBroadcastChannel.split(","):
|
||||
send_message(msg, channel, 0, deviceID)
|
||||
else:
|
||||
send_message(msg, wxAlertBroadcastChannel, 0, deviceID)
|
||||
return True
|
||||
|
||||
def onDisconnect(interface):
|
||||
global retry_int1, retry_int2
|
||||
@@ -976,6 +1011,9 @@ async def watchdog():
|
||||
# multiPing handler
|
||||
handleMultiPing(0,1)
|
||||
|
||||
if wxAlertBroadcastEnabled:
|
||||
handleWxBroadcast(1)
|
||||
|
||||
# Telemetry data
|
||||
int1Data = displayNodeTelemetry(0, 1)
|
||||
if int1Data != -1 and telemetryData[0]['lastAlert1'] != int1Data:
|
||||
@@ -1005,6 +1043,9 @@ async def watchdog():
|
||||
# multiPing handler
|
||||
handleMultiPing(0,2)
|
||||
|
||||
if wxAlertBroadcastEnabled:
|
||||
handleWxBroadcast(2)
|
||||
|
||||
# Telemetry data
|
||||
int2Data = displayNodeTelemetry(0, 2)
|
||||
if int2Data != -1 and telemetryData[0]['lastAlert2'] != int2Data:
|
||||
@@ -1016,3 +1057,5 @@ async def watchdog():
|
||||
await retry_interface(2)
|
||||
except Exception as e:
|
||||
logger.error(f"System: retrying interface2: {e}")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user