sentry_alert.sh

this enhances the sentry to optionally run a shell command you would create in the script/directory which will fire every time the alert fires. sentry_alert_near.sh and sentry_alert_far.sh are the needed files. it will error and remind you it cant find them.
This commit is contained in:
SpudGunMan
2025-10-21 14:21:09 -07:00
parent 82d519279e
commit d4fd484706
5 changed files with 47 additions and 18 deletions

View File

@@ -38,7 +38,7 @@ Welcome to the Mesh Bot project! This feature-rich bot is designed to enhance yo
- **GeoMeasuring**: HowFar from point to point using collected GPS packets on the bot to plot a course or space. Find Center of points for Fox&Hound direction finding.
### Proximity Alerts
- **Location-Based Alerts**: Get notified when members arrive back at a configured lat/long, perfect for remote locations like campsites, or put a geo-fence up for another.
- **Location-Based Alerts**: Get notified when members arrive back at a configured lat/long, perfect for remote locations like campsites, or put a geo-fence. You can also run a script or send a email.
- **High Flying Alerts**: Get notified when nodes with high altitude are seen on mesh
- **Voice/Command Triggers**: The following keywords can be used via voice (VOX) to trigger bot functions "Hey Chirpy!"
- Say "Hey Chirpy.."

View File

@@ -127,21 +127,28 @@ alert_interface = 1
[sentry]
# detect anyone close to the bot
SentryEnabled = True
reqLocationEnabled = False
emailSentryAlerts = False
# radius in meters to detect someone close to the bot
SentryRadius = 100
# device interface and channel to send the alert message to
SentryInterface = 1
SentryChannel = 2
# holdoff time multiplied by seconds(20) of the watchdog
SentryHoldoff = 9
emailSentryAlerts = False
# Enable detection sensor alert, requires external GPIO sensor connected to node
detectionSensorAlert = False
# list of ignored nodes numbers ex: 2813308004,4258675309
sentryIgnoreList =
# list of watched nodes numbers ex: 2813308004,4258675309
sentryWatchList =
# Enable detection sensor alert, requires external sensor connected to node
detectionSensorAlert = False
# radius in meters to detect someone close to the bot
SentryRadius = 100
# holdoff time multiplied by seconds(20) of the watchdog
SentryHoldoff = 9
# Enable running external shell command when sentry alert is triggered
cmdShellSentryAlerts = False
# External shell command to run when sentry alert is triggered
sentryAlertNear = sentry_alert_near.sh
sentryAlertAway = sentry_alert_away.sh
# HighFlying Node alert
highFlyingAlert = True

View File

@@ -70,28 +70,33 @@ async def watch_file():
return content
await asyncio.sleep(1) # Check every
def call_external_script(message, script="script/runShell.sh"):
# Call an external script with the message as an argument this is a example only
def call_external_script(message, script="runShell.sh"):
# If no path is given, assume script/ directory
if "/" not in script and "\\" not in script:
script = os.path.join("script", script)
try:
current_working_directory = os.getcwd()
script_path = os.path.join(current_working_directory, script)
if not os.path.exists(script_path):
# try the raw script name
# Try the raw script name
script_path = script
if not os.path.exists(script_path):
logger.warning(f"FileMon: Script not found: {script_path}")
return "sorry I can't do that"
# Use subprocess.run for better resource management
result = subprocess.run(
["bash", script_path, message],
capture_output=True,
text=True,
timeout=10
)
if result.returncode != 0:
logger.error(f"FileMon: Script error: {result.stderr.strip()}")
return None
output = result.stdout.strip()
return output
return output if output else None
except Exception as e:
logger.warning(f"FileMon: Error calling external script: {e}")
return None

View File

@@ -282,6 +282,9 @@ try:
highfly_check_openskynetwork = config['sentry'].getboolean('highflyOpenskynetwork', True) # default True check with OpenSkyNetwork if highfly detected
detctionSensorAlert = config['sentry'].getboolean('detectionSensorAlert', False) # default False
reqLocationEnabled = config['sentry'].getboolean('reqLocationEnabled', False) # default False
cmdShellSentryAlerts = config['sentry'].getboolean('cmdShellSentryAlerts', False) # default False
sentryAlertNear = config['sentry'].get('sentryAlertNear', 'sentry_alert_near.sh') # default sentry_alert_near.sh
sentryAlertFar = config['sentry'].get('sentryAlertFar', 'sentry_alert_far.sh') # default sentry_alert_far.sh
# location
location_enabled = config['location'].getboolean('enabled', True)

View File

@@ -290,7 +290,7 @@ if voxDetectionEnabled:
from modules.radio import * # from the spudgunman/meshing-around repo
# File Monitor Configuration
if file_monitor_enabled or read_news_enabled or bee_enabled or enable_runShellCmd:
if file_monitor_enabled or read_news_enabled or bee_enabled or enable_runShellCmd or cmdShellSentryAlerts:
from modules.filemon import * # from the spudgunman/meshing-around repo
if read_news_enabled:
trap_list = trap_list + trap_list_filemon # items readnews
@@ -2021,14 +2021,14 @@ async def handleSentinel(deviceID):
if str(node_id) in sentryIgnoreList:
return
# Message conditions
if distance >= sentry_radius and str(node_id) and str(node_id) in sentryWatchList:
# Outside zone
detectedNearby = f"{get_name_from_number(node_id, 'long', deviceID)}, {get_name_from_number(node_id, 'short', deviceID)}, {node_id}, {decimal_to_hex(node_id)} at {distance}m (OUTSIDE ZONE)"
elif distance <= sentry_radius and str(node_id) not in sentryWatchList:
# Inside the zone
detectedNearby = f"{get_name_from_number(node_id, 'long', deviceID)}, {get_name_from_number(node_id, 'short', deviceID)}, {node_id}, {decimal_to_hex(node_id)} at {distance}m (INSIDE ZONE)"
#logger.debug(f"handleSentinel: loop={handleSentinel_loop}/{sentry_holdoff}, detectedNearby={detectedNearby} closest_nodes={closest_nodes}")
if detectedNearby:
handleSentinel_loop += 1
@@ -2039,12 +2039,26 @@ async def handleSentinel(deviceID):
metadata = positionMetadata[node_id]
if metadata.get('precisionBits') is not None:
resolution = metadata.get('precisionBits')
# Send message alert
logger.warning(f"System: {detectedNearby} on Interface{deviceID} Accuracy is {resolution}bits")
send_message(f"Sentry{deviceID}: {detectedNearby}", secure_channel, 0, secure_interface)
# Send email alerts
if enableSMTP and email_sentry_alerts:
for email in sysopEmails:
send_email(email, f"Sentry{deviceID}: {detectedNearby}")
handleSentinel_loop = 0
# Execute external script alerts
if cmdShellSentryAlerts and distance <= sentry_radius:
# inside zone
call_external_script('', script=sentryAlertNear)
logger.info(f"System: Sentry Script Alert {sentryAlertNear} for NodeID:{node_id} on Interface{deviceID}")
elif cmdShellSentryAlerts and distance >= sentry_radius:
# outside zone
call_external_script('', script=sentryAlertFar)
logger.info(f"System: Sentry Script Alert {sentryAlertFar} for NodeID:{node_id} on Interface{deviceID}")
handleSentinel_loop = 0 # Loop reset
else:
handleSentinel_loop = 0 # Reset if nothing detected