mirror of
https://github.com/SpudGunMan/meshing-around.git
synced 2026-03-28 17:32:36 +01:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
409d07436e | ||
|
|
5ab0001f2b | ||
|
|
5e34537af7 | ||
|
|
1764bdf4f3 | ||
|
|
2290f07351 | ||
|
|
ee01051cf7 | ||
|
|
de50a52fa6 | ||
|
|
8eabfaa9c4 | ||
|
|
ca7114b058 | ||
|
|
8b94dc8111 | ||
|
|
5b26aabb00 | ||
|
|
67b3c67348 | ||
|
|
860cceec59 | ||
|
|
53a0535e55 | ||
|
|
621f4ad916 | ||
|
|
118857ec15 | ||
|
|
1be13be92a | ||
|
|
895fc3fd37 | ||
|
|
0e0bda60ad | ||
|
|
903767f4b3 | ||
|
|
f54d362ea0 | ||
|
|
60bb68c6b5 | ||
|
|
feb9a1d9b3 | ||
|
|
d055c35c96 | ||
|
|
27820daaf4 | ||
|
|
56e8e1c0d5 | ||
|
|
4545b8f4a4 | ||
|
|
6ed48d49ce |
@@ -38,6 +38,7 @@ Welcome to the Mesh Bot project! This feature-rich bot is designed to enhance yo
|
||||
|
||||
### Proximity Alerts
|
||||
- **Location-Based Alerts**: Get notified when members arrive back at a configured lat/long, perfect for remote locations like campsites.
|
||||
- **High Flying Alerts**: Get notified when nodes with high altitude are seen on mesh
|
||||
|
||||
### CheckList / Check In Out
|
||||
- **Asset Tracking**: Maintain a list of node/asset checkin and checkout. Usefull for accountability of people, assets. Radio-Net, FEMA, Trailhead.
|
||||
@@ -181,6 +182,8 @@ SentryRadius = 100 # radius in meters to detect someone close to the bot
|
||||
SentryChannel = 9 # holdoff time multiplied by seconds(20) of the watchdog
|
||||
SentryHoldoff = 2 # channel to send a message to when the watchdog is triggered
|
||||
sentryIgnoreList = # list of ignored nodes numbers ex: 2813308004,4258675309
|
||||
highFlyingAlert = True # HighFlying Node alert
|
||||
highFlyingAlertAltitude = 2000 # Altitude in meters to trigger the alert
|
||||
```
|
||||
|
||||
### E-Mail / SMS Settings
|
||||
@@ -479,6 +482,7 @@ I used ideas and snippets from other responder bots and want to call them out!
|
||||
- **Josh**: For more bashing on installer!
|
||||
- **dj505**: trying it on windows!
|
||||
- **mikecarper**: ideas, and testing. hamtest
|
||||
- **c.merphy360**: high altitude alerts
|
||||
- **Cisien, bitflip, **Woof**, **propstg**, **trs2982**, **Josh** and Hailo1999**: For testing and feature ideas on Discord and GitHub.
|
||||
- **Meshtastic Discord Community**: For tossing out ideas and testing code.
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@ ollama = False
|
||||
# ollamaModel = llama3.1
|
||||
# server instance to use (defaults to local machine install)
|
||||
ollamaHostName = http://localhost:11434
|
||||
# Produce LLM replies to messages that aren't commands?
|
||||
# If False, the LLM only replies to the "ask:" and "askai" commands.
|
||||
llmReplyToNonCommands = True
|
||||
|
||||
# StoreForward Enabled and Limits
|
||||
StoreForward = True
|
||||
@@ -103,6 +106,12 @@ SentryChannel = 2
|
||||
SentryHoldoff = 9
|
||||
# list of ignored nodes numbers ex: 2813308004,4258675309
|
||||
sentryIgnoreList =
|
||||
# HighFlying Node alert
|
||||
highFlyingAlert = True
|
||||
# Altitude in meters to trigger the alert
|
||||
highFlyingAlertAltitude = 2000
|
||||
# Channel to send Alert when the high flying node is detected
|
||||
highFlyingAlertChannel = 2
|
||||
|
||||
[bbs]
|
||||
enabled = True
|
||||
@@ -190,7 +199,7 @@ reverse_in_out = False
|
||||
# QRZ Hello to new nodes with message
|
||||
enabled = False
|
||||
qrz_db = data/qrz.db
|
||||
qrz_hello_string = "send CMD or DM me for more info."
|
||||
qrz_hello_string = "MeshBot says Hello! DM for more info."
|
||||
# Training mode will not send the hello message to new nodes
|
||||
training = True
|
||||
|
||||
@@ -291,7 +300,9 @@ splitDelay = 0.0
|
||||
MESSAGE_CHUNK_SIZE = 160
|
||||
# Request Acknowledgement of message OTA
|
||||
wantAck = False
|
||||
# Max limit buffer for radio testing. 233 is hard limit 2.5+ firmware
|
||||
# Max limit buffer for radio testing
|
||||
maxBuffer = 200
|
||||
#Enable Extra logging of Hop count data
|
||||
enableHopLogs = False
|
||||
|
||||
|
||||
|
||||
@@ -350,7 +350,8 @@ def get_database_info():
|
||||
os.path.join(base_dir, 'mmind_hs.pkl'),
|
||||
os.path.join(base_dir, 'golfsim_hs.pkl'),
|
||||
os.path.join(base_dir, 'bbsdb.pkl'),
|
||||
os.path.join(base_dir, 'bbsdm.pkl')]
|
||||
os.path.join(base_dir, 'bbsdm.pkl'),
|
||||
os.path.join(base_dir, 'qrz.db')]
|
||||
|
||||
for file in databaseFiles:
|
||||
try:
|
||||
@@ -371,6 +372,16 @@ def get_database_info():
|
||||
bbsdb = pickle.load(f)
|
||||
elif 'bbsdm' in file:
|
||||
bbsdm = pickle.load(f)
|
||||
elif 'qrz.db' in file:
|
||||
# open the qrz.db sqllite file
|
||||
import sqlite3
|
||||
conn = sqlite3.connect(file)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT * FROM qrz")
|
||||
qrz_db = cursor.fetchall()
|
||||
# convert to a list of strings
|
||||
qrz_db = [f"{row[0]}: {row[1]} {row[2]}" for row in qrz_db]
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"Warning issue reading database file: {str(e)}")
|
||||
if 'lemonstand' in file:
|
||||
@@ -425,7 +436,8 @@ def get_database_info():
|
||||
'golfsim_score': golfsim_score,
|
||||
'banList': banList,
|
||||
'adminList': adminList,
|
||||
'sentryIgnoreList': sentryIgnoreList
|
||||
'sentryIgnoreList': sentryIgnoreList,
|
||||
'qrz_db': qrz_db if 'qrz_db' in locals() else "no data"
|
||||
}
|
||||
|
||||
def generate_main_html(log_data, system_info):
|
||||
@@ -913,6 +925,11 @@ def generate_database_html(database_info):
|
||||
<tr><td>Mastermind</td><td>${mmind_score}</td></tr>
|
||||
<tr><td>Golf Simulator</td><td>${golfsim_score}</td></tr>
|
||||
</table>
|
||||
<h1>QRZ Database</h1>
|
||||
<p>QRZ Database holds heard nodeID and Shortname</p>
|
||||
<table>
|
||||
<tr><td>${qrz_db}</td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
@@ -359,7 +359,8 @@ def get_database_info():
|
||||
os.path.join(base_dir, 'mmind_hs.pkl'),
|
||||
os.path.join(base_dir, 'golfsim_hs.pkl'),
|
||||
os.path.join(base_dir, 'bbsdb.pkl'),
|
||||
os.path.join(base_dir, 'bbsdm.pkl')]
|
||||
os.path.join(base_dir, 'bbsdm.pkl'),
|
||||
os.path.join(base_dir, 'qrz.db')]
|
||||
|
||||
for file in databaseFiles:
|
||||
try:
|
||||
@@ -380,6 +381,16 @@ def get_database_info():
|
||||
bbsdb = pickle.load(f)
|
||||
elif 'bbsdm' in file:
|
||||
bbsdm = pickle.load(f)
|
||||
elif 'qrz.db' in file:
|
||||
#open the qrz.db sqllite file
|
||||
import sqlite3
|
||||
conn = sqlite3.connect(file)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT * FROM qrz")
|
||||
qrz_db = cursor.fetchall()
|
||||
# convert to a list of strings
|
||||
qrz_db = [f"{row[0]}: {row[1]} {row[2]}" for row in qrz_db]
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"Warning issue reading database file: {str(e)}")
|
||||
if 'lemonstand' in file:
|
||||
@@ -434,7 +445,8 @@ def get_database_info():
|
||||
'golfsim_score': golfsim_score,
|
||||
'banList': banList,
|
||||
'adminList': adminList,
|
||||
'sentryIgnoreList': sentryIgnoreList
|
||||
'sentryIgnoreList': sentryIgnoreList,
|
||||
'qrz_db': qrz_db if 'qrz_db' in locals() else "no data"
|
||||
}
|
||||
|
||||
def generate_main_html(log_data, system_info):
|
||||
@@ -1207,6 +1219,11 @@ def generate_database_html(database_info):
|
||||
<tr><td>Mastermind</td><td>${mmind_score}</td></tr>
|
||||
<tr><td>Golf Simulator</td><td>${golfsim_score}</td></tr>
|
||||
</table>
|
||||
<h1>QRZ Database</h1>
|
||||
<p>QRZ Database holds heard nodeID and Shortname</p>
|
||||
<table>
|
||||
<tr><td>${qrz_db}</td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
12
install.sh
12
install.sh
@@ -4,6 +4,7 @@
|
||||
# install.sh
|
||||
cd "$(dirname "$0")"
|
||||
program_path=$(pwd)
|
||||
chronjob="0 1 * * * /usr/bin/python3 $program_path/etc/report_generator5.py"
|
||||
printf "\n########################"
|
||||
printf "\nMeshing Around Installer\n"
|
||||
printf "########################\n"
|
||||
@@ -278,6 +279,8 @@ if [[ $(echo "${embedded}" | grep -i "^n") ]]; then
|
||||
printf "sudo journalctl -u %s.service\n" "$service" >> install_notes.txt
|
||||
printf "sudo systemctl stop %s.service\n" "$service" >> install_notes.txt
|
||||
printf "sudo systemctl disable %s.service\n" "$service" >> install_notes.txt
|
||||
printf "Reporting chron job added to run report_generator5.py\n" >> install_notes.txt
|
||||
printf "chronjob: %s\n" "$chronjob" >> install_notes.txt
|
||||
|
||||
if [[ $(echo "${venv}" | grep -i "^y") ]]; then
|
||||
printf "\nFor running on venv, virtual launch bot with './launch.sh mesh' in path $program_path\n" >> install_notes.txt
|
||||
@@ -307,6 +310,14 @@ else
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable $service.service
|
||||
sudo systemctl start $service.service
|
||||
# check if the cron job already exists
|
||||
if ! crontab -l | grep -q "$chronjob"; then
|
||||
# add the cron job to run the report_generator5.py script
|
||||
(crontab -l 2>/dev/null; echo "$chronjob") | crontab -
|
||||
printf "\nAdded cron job to run report_generator5.py\n"
|
||||
else
|
||||
printf "\nCron job already exists, skipping\n"
|
||||
fi
|
||||
printf "Reference following commands:\n\n" "$service" > install_notes.txt
|
||||
printf "sudo systemctl status %s.service\n" "$service" >> install_notes.txt
|
||||
printf "sudo systemctl start %s.service\n" "$service" >> install_notes.txt
|
||||
@@ -330,7 +341,6 @@ exit 0
|
||||
# sudo systemctl stop mesh_bot_reporting
|
||||
# sudo systemctl disable mesh_bot_reporting
|
||||
# sudo rm /etc/systemd/system/mesh_bot.service
|
||||
# sudo rm /etc/systemd/system/mesh_bot_reporting.service
|
||||
# sudo rm /etc/systemd/system/mesh_bot_w3.service
|
||||
# sudo rm /etc/systemd/system/pong_bot.service
|
||||
# sudo systemctl daemon-reload
|
||||
|
||||
@@ -20,7 +20,6 @@ restrictedResponse = "🤖only available in a Direct Message📵" # "" for none
|
||||
|
||||
# Global Variables
|
||||
DEBUGpacket = False # Debug print the packet rx
|
||||
DEBUGhops = False # Debug print hop info and bad hop count packets
|
||||
|
||||
def auto_response(message, snr, rssi, hop, pkiStatus, message_from_id, channel_number, deviceID, isDM):
|
||||
global cmdHistory
|
||||
@@ -805,7 +804,7 @@ def handle_bbspost(message, message_from_id, deviceID):
|
||||
toNode = int(toNode.strip("!"),16)
|
||||
except ValueError as e:
|
||||
toNode = 0
|
||||
elif toNode.isalpha() or not toNode.isnumeric():
|
||||
elif toNode.isalpha() or not toNode.isnumeric() or len(toNode) < 5:
|
||||
# try short name
|
||||
toNode = get_num_from_short_name(toNode, deviceID)
|
||||
|
||||
@@ -1194,7 +1193,7 @@ def onReceive(packet, interface):
|
||||
else:
|
||||
hop_start = 0
|
||||
|
||||
if DEBUGhops:
|
||||
if enableHopLogs:
|
||||
logger.debug(f"System: Packet HopDebugger: hop_away:{hop_away} hop_limit:{hop_limit} hop_start:{hop_start}")
|
||||
if hop_away == 0 and hop_limit == 0 and hop_start == 0:
|
||||
logger.debug(f"System: Packet HopDebugger: No hop count found in PACKET {packet} END PACKET")
|
||||
@@ -1244,7 +1243,7 @@ def onReceive(packet, interface):
|
||||
playingGame = False
|
||||
|
||||
if not playingGame:
|
||||
if llm_enabled:
|
||||
if llm_enabled and llmReplyToNonCommands:
|
||||
# respond with LLM
|
||||
llm = handle_llm(message_from_id, channel_number, rxNode, message_string, publicChannel)
|
||||
send_message(llm, channel_number, message_from_id, rxNode)
|
||||
@@ -1407,6 +1406,8 @@ async def start_rx():
|
||||
logger.debug(f"System: MOTD Enabled using {MOTD}")
|
||||
if sentry_enabled:
|
||||
logger.debug(f"System: Sentry Mode Enabled {sentry_radius}m radius reporting to channel:{secure_channel}")
|
||||
if highfly_enabled:
|
||||
logger.debug(f"System: HighFly Enabled using {highfly_altitude}m limit reporting to channel:{highfly_channel}")
|
||||
if store_forward_enabled:
|
||||
logger.debug(f"System: Store and Forward Enabled using limit: {storeFlimit}")
|
||||
if useDMForResponse:
|
||||
|
||||
@@ -31,7 +31,7 @@ def read_file(file_monitor_file_path, random_line_only=False):
|
||||
|
||||
def read_news():
|
||||
# read the news file on demand
|
||||
return read_file(news_file_path, read_news_enabled)
|
||||
return read_file(news_file_path, news_random_line_only)
|
||||
|
||||
|
||||
def write_news(content, append=False):
|
||||
|
||||
@@ -164,7 +164,7 @@ class PlayerVP:
|
||||
return self.show_hand()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
return "ex:1,3,4 deals them new, and keeps 2,5 or (N)o to keep current (H)and"
|
||||
|
||||
# Method for scoring hand, calculating winnings, and outputting message
|
||||
@@ -390,7 +390,7 @@ def playVideoPoker(nodeID, message):
|
||||
else:
|
||||
if drawCount <= 1:
|
||||
msg = player.redraw(deck, message)
|
||||
if msg.startswith("Send Card"):
|
||||
if msg.startswith("ex:"):
|
||||
# if returned error message, return it
|
||||
return msg
|
||||
drawCount += 1
|
||||
@@ -403,7 +403,7 @@ def playVideoPoker(nodeID, message):
|
||||
if drawCount == 2:
|
||||
# this is the last draw will carry on to endGame for scoring
|
||||
msg = player.redraw(deck, message) + f"\n"
|
||||
if msg.startswith("Send Card"):
|
||||
if msg.startswith("ex:"):
|
||||
# if returned error message, return it
|
||||
return msg
|
||||
# redraw done
|
||||
|
||||
@@ -467,6 +467,7 @@ def getIpawsAlert(lat=0, lon=0, shortAlerts = False):
|
||||
# get the latest IPAWS alert from FEMA
|
||||
alert = ''
|
||||
alerts = []
|
||||
linked_data = ''
|
||||
|
||||
# set the API URL for IPAWS
|
||||
namespace = "urn:oasis:names:tc:emergency:cap:1.2"
|
||||
@@ -496,15 +497,22 @@ def getIpawsAlert(lat=0, lon=0, shortAlerts = False):
|
||||
link += "?pin=" + ipawsPIN
|
||||
# get the linked alert data from FEMA
|
||||
linked_data = requests.get(link, timeout=urlTimeoutSeconds)
|
||||
if not linked_data.ok:
|
||||
if not linked_data.ok or not linked_data.text.strip():
|
||||
# if the linked data is not ok, skip this alert
|
||||
#logger.warning(f"System: iPAWS Error fetching linked alert data from {link}")
|
||||
continue
|
||||
else:
|
||||
linked_xml = xml.dom.minidom.parseString(linked_data.text)
|
||||
# this alert is a full CAP alert
|
||||
except (requests.exceptions.RequestException):
|
||||
logger.warning(f"System: iPAWS Error fetching embedded alert data from {link}")
|
||||
continue
|
||||
|
||||
# this alert is a full CAP alert
|
||||
linked_xml = xml.dom.minidom.parseString(linked_data.text)
|
||||
except xml.parsers.expat.ExpatError:
|
||||
logger.warning(f"System: iPAWS Error parsing XML from {link}")
|
||||
continue
|
||||
except Exception as e:
|
||||
logger.debug(f"System: iPAWS Error processing alert data from {link}: {e}")
|
||||
continue
|
||||
|
||||
for info in linked_xml.getElementsByTagName("info"):
|
||||
# extract values from XML
|
||||
@@ -539,10 +547,15 @@ def getIpawsAlert(lat=0, lon=0, shortAlerts = False):
|
||||
if (sameVal in mySAME) or (geocode_value in mySAME):
|
||||
# ignore the FEMA test alerts
|
||||
if ignoreFEMAenable:
|
||||
ignore_alert = False
|
||||
for word in ignoreFEMAwords:
|
||||
if word.lower() in headline.lower():
|
||||
logger.debug(f"System: Ignoring FEMA Alert: {headline} containing {word} at {areaDesc}")
|
||||
continue
|
||||
ignore_alert = True
|
||||
break
|
||||
|
||||
if ignore_alert:
|
||||
continue
|
||||
|
||||
# add to alerts list
|
||||
alerts.append({
|
||||
@@ -632,32 +645,36 @@ def get_volcano_usgs(lat=0, lon=0):
|
||||
try:
|
||||
volcano_data = requests.get(usgs_volcano_url, timeout=urlTimeoutSeconds)
|
||||
if not volcano_data.ok:
|
||||
logger.warning("System: USGS fetching volcano alerts from USGS")
|
||||
logger.warning("System: Issue with fetching volcano alerts from USGS")
|
||||
return ERROR_FETCHING_DATA
|
||||
except (requests.exceptions.RequestException):
|
||||
logger.warning("System: USGS fetching volcano alerts from USGS")
|
||||
logger.warning("System: Issue with fetching volcano alerts from USGS")
|
||||
return ERROR_FETCHING_DATA
|
||||
volcano_json = volcano_data.json()
|
||||
# extract alerts from main feed
|
||||
for alert in volcano_json:
|
||||
# check ignore list
|
||||
if ignoreUSGSEnable:
|
||||
for word in ignoreUSGSwords:
|
||||
if word.lower() in alert['volcano_name_appended'].lower():
|
||||
logger.debug(f"System: Ignoring USGS Alert: {alert['volcano_name_appended']} containing {word}")
|
||||
continue
|
||||
# check if the alert lat long is within the range of bot latitudeValue and longitudeValue
|
||||
if (alert['latitude'] >= latitudeValue - 10 and alert['latitude'] <= latitudeValue + 10) and (alert['longitude'] >= longitudeValue - 10 and alert['longitude'] <= longitudeValue + 10):
|
||||
volcano_name = alert['volcano_name_appended']
|
||||
alert_level = alert['alert_level']
|
||||
color_code = alert['color_code']
|
||||
cap_severity = alert['cap_severity']
|
||||
synopsis = alert['synopsis']
|
||||
# format Alert
|
||||
alerts += f"🌋🚨: {volcano_name}, {alert_level} {color_code}, {cap_severity}.\n{synopsis}\n"
|
||||
else:
|
||||
#logger.debug(f"System: USGS volcano alert not in range: {alert['volcano_name_appended']}")
|
||||
continue
|
||||
if volcano_json and isinstance(volcano_json, list):
|
||||
for alert in volcano_json:
|
||||
# check ignore list
|
||||
if ignoreUSGSEnable:
|
||||
for word in ignoreUSGSwords:
|
||||
if word.lower() in alert['volcano_name_appended'].lower():
|
||||
logger.debug(f"System: Ignoring USGS Alert: {alert['volcano_name_appended']} containing {word}")
|
||||
continue
|
||||
# check if the alert lat long is within the range of bot latitudeValue and longitudeValue
|
||||
if (alert['latitude'] >= latitudeValue - 10 and alert['latitude'] <= latitudeValue + 10) and (alert['longitude'] >= longitudeValue - 10 and alert['longitude'] <= longitudeValue + 10):
|
||||
volcano_name = alert['volcano_name_appended']
|
||||
alert_level = alert['alert_level']
|
||||
color_code = alert['color_code']
|
||||
cap_severity = alert['cap_severity']
|
||||
synopsis = alert['synopsis']
|
||||
# format Alert
|
||||
alerts += f"🌋🚨: {volcano_name}, {alert_level} {color_code}, {cap_severity}.\n{synopsis}\n"
|
||||
else:
|
||||
#logger.debug(f"System: USGS volcano alert not in range: {alert['volcano_name_appended']}")
|
||||
continue
|
||||
else:
|
||||
logger.debug("Location:Error fetching volcano data from USGS")
|
||||
return NO_ALERTS
|
||||
if alerts == "":
|
||||
return NO_ALERTS
|
||||
# trim off last newline
|
||||
|
||||
@@ -222,6 +222,7 @@ try:
|
||||
llm_enabled = config['general'].getboolean('ollama', False) # https://ollama.com
|
||||
llmModel = config['general'].get('ollamaModel', 'gemma2:2b') # default gemma2:2b
|
||||
ollamaHostName = config['general'].get('ollamaHostName', 'http://localhost:11434') # default localhost
|
||||
llmReplyToNonCommands = config['general'].getboolean('llmReplyToNonCommands', True)
|
||||
# emergency response
|
||||
emergency_responder_enabled = config['emergencyHandler'].getboolean('enabled', False)
|
||||
emergency_responder_alert_channel = config['emergencyHandler'].getint('alert_channel', 2) # default 2
|
||||
@@ -235,6 +236,9 @@ try:
|
||||
sentryIgnoreList = config['sentry'].get('sentryIgnoreList', '').split(',')
|
||||
sentry_radius = config['sentry'].getint('SentryRadius', 100) # default 100 meters
|
||||
email_sentry_alerts = config['sentry'].getboolean('emailSentryAlerts', False) # default False
|
||||
highfly_enabled = config['sentry'].getboolean('highFlyingAlert', True) # default True
|
||||
highfly_altitude = config['sentry'].getint('highFlyingAlertAltitude', 2000) # default 2000 meters
|
||||
highfly_channel = config['sentry'].getint('highFlyingAlertChannel', 2) # default 2
|
||||
|
||||
# location
|
||||
location_enabled = config['location'].getboolean('enabled', True)
|
||||
@@ -285,7 +289,7 @@ try:
|
||||
# qrz hello
|
||||
qrz_hello_enabled = config['qrz'].getboolean('enabled', False)
|
||||
qrz_db = config['qrz'].get('qrz_db', 'data/qrz.db')
|
||||
qrz_hello_string = config['qrz'].get('qrz_hello_string', 'send CMD or DM me for more info.')
|
||||
qrz_hello_string = config['qrz'].get('qrz_hello_string', 'MeshBot says Hello! DM for more info.')
|
||||
train_qrz = config['qrz'].getboolean('training', True)
|
||||
|
||||
# E-Mail Settings
|
||||
@@ -330,7 +334,7 @@ try:
|
||||
# file monitor
|
||||
file_monitor_enabled = config['fileMon'].getboolean('filemon_enabled', False)
|
||||
file_monitor_file_path = config['fileMon'].get('file_path', 'alert.txt') # default alert.txt
|
||||
file_monitor_broadcastCh = config['fileMon'].getint('broadcastCh', 2) # default 2
|
||||
file_monitor_broadcastCh = config['fileMon'].get('broadcastCh', '2').split(',') # default Channel 2
|
||||
read_news_enabled = config['fileMon'].getboolean('enable_read_news', False) # default disabled
|
||||
news_file_path = config['fileMon'].get('news_file_path', 'news.txt') # default news.txt
|
||||
news_random_line_only = config['fileMon'].getboolean('news_random_line', False) # default False
|
||||
@@ -353,6 +357,7 @@ try:
|
||||
MESSAGE_CHUNK_SIZE = config['messagingSettings'].getint('MESSAGE_CHUNK_SIZE', 160) # default 160
|
||||
wantAck = config['messagingSettings'].getboolean('wantAck', False) # default False
|
||||
maxBuffer = config['messagingSettings'].getint('maxBuffer', 220) # default 220
|
||||
enableHopLogs = config['messagingSettings'].getboolean('enableHopLogs', False) # default False
|
||||
|
||||
except KeyError as e:
|
||||
print(f"System: Error reading config file: {e}")
|
||||
|
||||
@@ -978,6 +978,12 @@ def consumeMetadata(packet, rxNode=0):
|
||||
|
||||
for key in keys:
|
||||
positionMetadata[nodeID][key] = position_data.get(key, 0)
|
||||
|
||||
# if altitude is over 2000 send a log and message for high-flying nodes
|
||||
if position_data.get('altitude', 0) > highfly_altitude and highfly_enabled:
|
||||
logger.info(f"System: High Altitude {position_data['altitude']}m on Device: {rxNode} NodeID: {nodeID}")
|
||||
send_message(f"High Altitude {position_data['altitude']}m on Device:{rxNode} Node:{get_name_from_number(nodeID,'short',rxNode)}", highfly_channel, 0, rxNode)
|
||||
time.sleep(responseDelay)
|
||||
|
||||
# Keep the positionMetadata dictionary at a maximum size of 20
|
||||
if len(positionMetadata) > 20:
|
||||
@@ -1096,7 +1102,7 @@ async def handleFileWatcher():
|
||||
# if fileWatchBroadcastCh list contains multiple channels, broadcast to all
|
||||
if type(file_monitor_broadcastCh) is list:
|
||||
for ch in file_monitor_broadcastCh:
|
||||
if antiSpam and ch != publicChannel:
|
||||
if antiSpam and int(ch) != publicChannel:
|
||||
send_message(msg, int(ch), 0, 1)
|
||||
time.sleep(responseDelay)
|
||||
if multiple_interface:
|
||||
@@ -1151,7 +1157,7 @@ async def retry_interface(nodeID):
|
||||
if interface_type == 'serial':
|
||||
globals()[f'interface{nodeID}'] = meshtastic.serial_interface.SerialInterface(globals().get(f'port{nodeID}'))
|
||||
elif interface_type == 'tcp':
|
||||
globals()[f'interface{nodeID}'] = meshtastic.tcp_interface.TCPInterface(globals().get(f'hostname{nodeID}'))
|
||||
globals()[f'interface{nodeID}'] = meshtastic.tcp_interface.TCPInterface(globals().get(f'host{nodeID}'))
|
||||
elif interface_type == 'ble':
|
||||
globals()[f'interface{nodeID}'] = meshtastic.ble_interface.BLEInterface(globals().get(f'mac{nodeID}'))
|
||||
logger.debug(f"System: Interface{nodeID} Opened!")
|
||||
|
||||
Reference in New Issue
Block a user