mirror of
https://github.com/SpudGunMan/meshing-around.git
synced 2026-05-02 19:42:18 +02:00
Merge branch 'lab2' into lab
This commit is contained in:
@@ -440,6 +440,8 @@ I used ideas and snippets from other responder bots and want to call them out!
|
||||
- **[https://github.com/A-c0rN](A-c0rN)**: Assistance with iPAWS and EAS
|
||||
- **Mike O'Connell/skrrt**: For [eas_alert_parser](etc/eas_alert_parser.py) enhanced by **sheer.cold**
|
||||
- **PiDiBi**: For looking at test functions and other suggestions like wxc, CPU use, and alerting ideas.
|
||||
- **WH6GXZ nurse dude**: For bashing on installer
|
||||
- **Josh**: For more bashing on installer!
|
||||
- **Cisien, bitflip, **Woof**, **propstg**, **Josh** and Hailo1999**: For testing and feature ideas on Discord and GitHub.
|
||||
- **Meshtastic Discord Community**: For tossing out ideas and testing code.
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
type = serial
|
||||
port = /dev/ttyACM0
|
||||
# port = /dev/ttyUSB0
|
||||
# port = COM1
|
||||
# hostname = localhost
|
||||
# hostname = meshtastic.local
|
||||
# mac = 00:11:22:33:44:55
|
||||
|
||||
# Additional interface for multi radio support
|
||||
@@ -17,9 +16,9 @@ port = /dev/ttyACM0
|
||||
enabled = False
|
||||
type = serial
|
||||
port = /dev/ttyUSB0
|
||||
#port = /dev/ttyACM1
|
||||
# port = /dev/ttyACM1
|
||||
# port = COM1
|
||||
# hostname = meshtastic.local
|
||||
# hostname = localhost
|
||||
# mac = 00:11:22:33:44:55
|
||||
|
||||
# example, the third interface would be [interface3] up to 9
|
||||
@@ -76,6 +75,8 @@ urlTimeout = 10
|
||||
LogMessagesToFile = False
|
||||
# Logging of system messages to file
|
||||
SyslogToFile = True
|
||||
# logging level for the bot (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||||
sysloglevel = DEBUG
|
||||
# Number of log files to keep in days, 0 to keep all
|
||||
log_backup_count = 32
|
||||
|
||||
@@ -190,6 +191,7 @@ enable_read_news = False
|
||||
news_file_path = news.txt
|
||||
# only return a single random line from the news file
|
||||
news_random_line = False
|
||||
# enable the use of exernal shell commands
|
||||
enable_runShellCmd = False
|
||||
|
||||
[smtp]
|
||||
@@ -238,7 +240,7 @@ splitDelay = 0.0
|
||||
MESSAGE_CHUNK_SIZE = 160
|
||||
# Request Acknowledgement of message OTA
|
||||
wantAck = False
|
||||
# Max lilmit Buffer for radio testing
|
||||
# Max limit buffer for radio testing. 233 is hard limit 2.5+ firmware
|
||||
maxBuffer = 220
|
||||
|
||||
|
||||
|
||||
190
install.sh
190
install.sh
@@ -7,27 +7,42 @@ program_path=$(pwd)
|
||||
printf "\n########################"
|
||||
printf "\nMeshing Around Installer\n"
|
||||
printf "########################\n"
|
||||
printf "\nThis script will try and install the Meshing Around Bot and its dependencies."
|
||||
printf "Installer works best in raspian/debian/ubuntu, if there is a problem, try running the installer again.\n"
|
||||
printf "\nThis script will try and install the Meshing Around Bot and its dependencies.\n"
|
||||
printf "Installer works best in raspian/debian/ubuntu or foxbuntu embedded systems.\n"
|
||||
printf "If there is a problem, try running the installer again.\n"
|
||||
printf "\nChecking for dependencies...\n"
|
||||
|
||||
# check if running on embedded
|
||||
printf "\nAre You installing into an embedded system? (y/n)"
|
||||
read embedded
|
||||
|
||||
if [ $embedded == "y" ]; then
|
||||
printf "\nDetected embedded skipping dependency installation\n"
|
||||
if [ $program_path != "/opt/meshing-around" ]; then
|
||||
printf "\nIt is suggested to project path to /opt/meshing-around\n"
|
||||
printf "Do you want to move the project to /opt/meshing-around? (y/n)"
|
||||
read move
|
||||
if [ $move == "y" ]; then
|
||||
sudo mv $program_path /opt/meshing-around
|
||||
cd /opt/meshing-around
|
||||
printf "\nProject moved to /opt/meshing-around. re-run the installer\n"
|
||||
exit 0
|
||||
fi
|
||||
# check if we are in /opt/meshing-around
|
||||
if [ $program_path != "/opt/meshing-around" ]; then
|
||||
printf "\nIt is suggested to project path to /opt/meshing-around\n"
|
||||
printf "Do you want to move the project to /opt/meshing-around? (y/n)"
|
||||
read move
|
||||
if [[ $(echo "$move" | grep -i "^y") ]]; then
|
||||
sudo mv $program_path /opt/meshing-around
|
||||
cd /opt/meshing-around
|
||||
printf "\nProject moved to /opt/meshing-around. re-run the installer\n"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# check write access to program path
|
||||
if [[ ! -w ${program_path} ]]; then
|
||||
printf "\nInstall path not writable, try running the installer with sudo\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# if hostname = femtofox, then we are on embedded
|
||||
if [[ $(hostname) == "femtofox" ]]; then
|
||||
printf "\nDetected femtofox embedded system\n"
|
||||
embedded="y"
|
||||
else
|
||||
# check if running on embedded
|
||||
printf "\nAre You installing into an embedded system like a luckfox or -native? most should say no here (y/n)"
|
||||
read embedded
|
||||
fi
|
||||
|
||||
if [[ $(echo "${embedded}" | grep -i "^y") ]]; then
|
||||
printf "\nDetected embedded skipping dependency installation\n"
|
||||
else
|
||||
# Check and install dependencies
|
||||
if ! command -v python3 &> /dev/null
|
||||
@@ -67,7 +82,7 @@ cp etc/mesh_bot.tmp etc/mesh_bot.service
|
||||
cp etc/mesh_bot_reporting.tmp etc/mesh_bot_reporting.service
|
||||
|
||||
# generate config file, check if it exists
|
||||
if [ -f config.ini ]; then
|
||||
if [[ -f config.ini ]]; then
|
||||
printf "\nConfig file already exists, moving to backup config.old\n"
|
||||
mv config.ini config.old
|
||||
fi
|
||||
@@ -75,14 +90,21 @@ fi
|
||||
cp config.template config.ini
|
||||
printf "\nConfig files generated!\n"
|
||||
|
||||
# update lat,long in config.ini
|
||||
latlong=$(curl --silent --max-time 20 https://ipinfo.io/loc || echo "48.50,-123.0")
|
||||
IFS=',' read -r lat lon <<< "$latlong"
|
||||
sed -i "s|lat = 48.50|lat = $lat|g" config.ini
|
||||
sed -i "s|lon = -123.0|lon = $lon|g" config.ini
|
||||
echo "lat,long updated in config.ini to $latlong"
|
||||
|
||||
# check if running on embedded
|
||||
if [ $embedded == "y" ]; then
|
||||
if [[ $(echo "${embedded}" | grep -i "^y") ]]; then
|
||||
printf "\nDetected embedded skipping venv\n"
|
||||
else
|
||||
printf "\nDo you want to install the bot in a python virtual environment? (y/n)"
|
||||
printf "\nRecomended install is in a python virtual environment, do you want to use venv? (y/n)"
|
||||
read venv
|
||||
|
||||
if [ $venv == "y" ]; then
|
||||
if [[ $(echo "${venv}" | grep -i "^y") ]]; then
|
||||
# set virtual environment
|
||||
if ! python3 -m venv --help &> /dev/null; then
|
||||
printf "Python3/venv error, please install python3-venv with your OS\n"
|
||||
@@ -91,7 +113,7 @@ else
|
||||
echo "The Following could be messy, or take some time on slower devices."
|
||||
echo "Creating virtual environment..."
|
||||
#check if python3 has venv module
|
||||
if [ -f venv/bin/activate ]; then
|
||||
if [[ -f venv/bin/activate ]]; then
|
||||
printf "\nFound virtual environment for python\n"
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
@@ -103,7 +125,7 @@ else
|
||||
python3 -m venv venv
|
||||
|
||||
# double check for python3-venv
|
||||
if [ -f venv/bin/activate ]; then
|
||||
if [[ -f venv/bin/activate ]]; then
|
||||
printf "\nFound virtual environment for python\n"
|
||||
source venv/bin/activate
|
||||
else
|
||||
@@ -119,15 +141,15 @@ else
|
||||
replace="s|python3 pong_bot.py|/usr/bin/bash launch.sh pong|g"
|
||||
sed -i "$replace" etc/pong_bot.service
|
||||
|
||||
# install dependencies
|
||||
# install dependencies to venv
|
||||
pip install -U -r requirements.txt
|
||||
fi
|
||||
else
|
||||
printf "\nSkipping virtual environment...\n"
|
||||
# install dependencies
|
||||
# install dependencies to system
|
||||
printf "Are you on Raspberry Pi(debian/ubuntu)?\nshould we add --break-system-packages to the pip install command? (y/n)"
|
||||
read rpi
|
||||
if [ $rpi == "y" ]; then
|
||||
if [[ $(echo "${rpi}" | grep -i "^y") ]]; then
|
||||
pip install -U -r requirements.txt --break-system-packages
|
||||
else
|
||||
pip install -U -r requirements.txt
|
||||
@@ -135,9 +157,17 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
printf "\n\n"
|
||||
echo "Which bot do you want to install as a service? Pong Mesh or None? (pong/mesh/n)"
|
||||
read bot
|
||||
# if $1 is passed
|
||||
if [[ $1 == "mesh" ]]; then
|
||||
bot="mesh"
|
||||
elif [[ $1 == "pong" ]]; then
|
||||
bot="pong"
|
||||
else
|
||||
printf "\n\n"
|
||||
echo "Which bot do you want to install as a service? Pong Mesh or None? (pong/mesh/n)"
|
||||
echo "Pong bot is a simple bot for network testing, Mesh bot is a more complex bot more suited for meshing around"
|
||||
read bot
|
||||
fi
|
||||
|
||||
# set the correct path in the service file
|
||||
replace="s|/dir/|$program_path/|g"
|
||||
@@ -145,7 +175,32 @@ sed -i $replace etc/pong_bot.service
|
||||
sed -i $replace etc/mesh_bot.service
|
||||
sed -i $replace etc/mesh_bot_reporting.service
|
||||
# set the correct user in the service file?
|
||||
whoami=$(whoami)
|
||||
|
||||
#ask if we should add a user for the bot
|
||||
if [[ $(echo "${embedded}" | grep -i "^n") ]]; then
|
||||
printf "\nDo you want to add a local user (meshbot) no login, for the bot? (y/n)"
|
||||
read meshbotservice
|
||||
fi
|
||||
|
||||
if [[ $(echo "${meshbotservice}" | grep -i "^y") ]] || [[ $(echo "${embedded}" | grep -i "^y") ]]; then
|
||||
sudo useradd -M meshbot
|
||||
sudo usermod -L meshbot
|
||||
sudo groupadd meshbot
|
||||
sudo usermod -a -G meshbot meshbot
|
||||
whoami="meshbot"
|
||||
echo "Added user meshbot with no home directory"
|
||||
sudo usermod -a -G dialout $whoami
|
||||
sudo usermod -a -G tty $whoami
|
||||
sudo usermod -a -G bluetooth $whoami
|
||||
echo "Added meshbot to dialout, tty, and bluetooth groups"
|
||||
|
||||
sudo chown -R $whoami:$whoami $program_path/logs
|
||||
sudo chown -R $whoami:$whoami $program_path/data
|
||||
echo "Permissions set for meshbot on logs and data directories"
|
||||
else
|
||||
whoami=$(whoami)
|
||||
fi
|
||||
# set the correct user in the service file
|
||||
replace="s|User=pi|User=$whoami|g"
|
||||
sed -i $replace etc/pong_bot.service
|
||||
sed -i $replace etc/mesh_bot.service
|
||||
@@ -154,64 +209,78 @@ replace="s|Group=pi|Group=$whoami|g"
|
||||
sed -i $replace etc/pong_bot.service
|
||||
sed -i $replace etc/mesh_bot.service
|
||||
sed -i $replace etc/mesh_bot_reporting.service
|
||||
sudo systemctl daemon-reload
|
||||
printf "\n service files updated\n"
|
||||
|
||||
if [ $bot == "pong" ]; then
|
||||
echo "useradd -M meshbot"
|
||||
echo "usermod -L meshbot"
|
||||
echo "Added user meshbot with no home directory"
|
||||
if [[ $(echo "${bot}" | grep -i "^p") ]]; then
|
||||
# install service for pong bot
|
||||
sudo cp etc/pong_bot.service /etc/systemd/system/
|
||||
sudo systemctl enable pong_bot.service
|
||||
sudo systemctl daemon-reload
|
||||
echo "to start pong bot service: systemctl start pong_bot"
|
||||
service="pong_bot"
|
||||
fi
|
||||
|
||||
if [ $bot == "mesh" ]; then
|
||||
echo "useradd -M meshbot"
|
||||
echo "usermod -L meshbot"
|
||||
echo "Added user meshbot with no home directory"
|
||||
if [[ $(echo "${bot}" | grep -i "^m") ]]; then
|
||||
# install service for mesh bot
|
||||
sudo cp etc/mesh_bot.service /etc/systemd/system/
|
||||
sudo systemctl enable mesh_bot.service
|
||||
sudo systemctl daemon-reload
|
||||
echo "to start mesh bot service: systemctl start mesh_bot"
|
||||
service="mesh_bot"
|
||||
fi
|
||||
|
||||
# check if running on embedded
|
||||
if [ $embedded == "n" ]; then
|
||||
# check if running on embedded for final steps
|
||||
if [[ $(echo "${embedded}" | grep -i "^n") ]]; then
|
||||
# ask if emoji font should be installed for linux
|
||||
printf "\nDo you want to install the emoji font for debian/ubuntu linux? (y/n)"
|
||||
read emoji
|
||||
if [ $emoji == "y" ]; then
|
||||
if [[ $(echo "${emoji}" | grep -i "^y") ]]; then
|
||||
sudo apt-get install -y fonts-noto-color-emoji
|
||||
echo "Emoji font installed!, reboot to load the font"
|
||||
fi
|
||||
|
||||
|
||||
printf "\nOptionally if you want to install the multi gig LLM Ollama compnents we will execute the following commands\n"
|
||||
printf "\ncurl -fsSL https://ollama.com/install.sh | sh\n"
|
||||
|
||||
printf "ollama pull gemma2:2b\n"
|
||||
printf "Total download is multi GB, recomend pi5/8GB or better for this\n"
|
||||
# ask if the user wants to install the LLM Ollama components
|
||||
printf "\nDo you want to install the LLM Ollama components? (y/n)"
|
||||
read ollama
|
||||
if [ $ollama == "y" ]; then
|
||||
if [[ $(echo "${ollama}" | grep -i "^y") ]]; then
|
||||
curl -fsSL https://ollama.com/install.sh | sh
|
||||
|
||||
# ask if want to install gemma2:2b
|
||||
printf "\n Ollama install done now we can install the Gemma2:2b components, multi GB download\n"
|
||||
printf "\n Ollama install done now we can install the Gemma2:2b components\n"
|
||||
echo "Do you want to install the Gemma2:2b components? (y/n)"
|
||||
read gemma
|
||||
if [ $gemma == "y" ]; then
|
||||
if [[ $(echo "${gemma}" | grep -i "^y") ]]; then
|
||||
ollama pull gemma2:2b
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ $venv == "y" ]; then
|
||||
printf "\nFor running in virtual, launch bot with './launch.sh mesh' in path $program_path\n"
|
||||
if [[ $(echo "${embedded}" | grep -i "^n") ]]; then
|
||||
# document the service install
|
||||
printf "To install the %s service and keep notes, reference following commands:\n\n" "$service" > install_notes.txt
|
||||
printf "sudo cp %s/etc/%s.service /etc/systemd/system/etc/%s.service\n" "$program_path" "$service" "$service" >> install_notes.txt
|
||||
printf "sudo systemctl daemon-reload\n" >> install_notes.txt
|
||||
printf "sudo systemctl enable %s.service\n" "$service" >> install_notes.txt
|
||||
printf "sudo systemctl start %s.service\n" "$service" >> install_notes.txt
|
||||
printf "sudo systemctl status %s.service\n\n" "$service" >> install_notes.txt
|
||||
printf "To see logs and stop the service:\n" >> install_notes.txt
|
||||
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
|
||||
fi
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
read -p "Press enter to complete the installation, these commands saved to install_notes.txt"
|
||||
|
||||
printf "\nGood time to reboot? (y/n)"
|
||||
read reboot
|
||||
if [ $reboot == "y" ]; then
|
||||
if [[ $(echo "${reboot}" | grep -i "^y") ]]; then
|
||||
sudo reboot
|
||||
fi
|
||||
else
|
||||
@@ -219,17 +288,26 @@ else
|
||||
# replace "type = serial" with "type = tcp" in config.ini
|
||||
replace="s|type = serial|type = tcp|g"
|
||||
sed -i "$replace" config.ini
|
||||
# replace "# hostname = 192.168.0.1" with "hostname = localhost" in config.ini
|
||||
replace="s|# hostname = 192.168.0.1|hostname = localhost|g"
|
||||
# replace "# hostname = meshtastic.local" with "hostname = localhost" in config.ini
|
||||
replace="s|# hostname = meshtastic.local|hostname = localhost|g"
|
||||
sed -i "$replace" config.ini
|
||||
printf "\nConfig file updated for embedded\n"
|
||||
|
||||
# Set up the meshing around service
|
||||
#sudo cp /opt/meshing-around/meshing-around.service /etc/systemd/system/meshing-around.service
|
||||
#sudo systemctl enable meshing-around.service
|
||||
sudo cp /opt/meshing-around/etc/$service.service /etc/systemd/system/$service.service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable $service.service
|
||||
sudo systemctl start $service.service
|
||||
printf "Reference following commands:\n\n" "$service" > install_notes.txt
|
||||
printf "sudo systemctl status %s.service\n\n" "$service" >> install_notes.txt
|
||||
printf "To see logs and stop the service:\n" >> install_notes.txt
|
||||
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
|
||||
fi
|
||||
|
||||
printf "\nInstallation complete!\n"
|
||||
|
||||
exit 0
|
||||
# after install shenannigans
|
||||
# add 'bee = True' to config.ini General section. You will likley want to clean the txt up a bit
|
||||
|
||||
@@ -14,6 +14,8 @@ Logging messages to disk or 'Syslog' to disk uses the python native logging func
|
||||
LogMessagesToFile = False
|
||||
# Logging of system messages to file, needed for reporting engine
|
||||
SyslogToFile = True
|
||||
# logging level for the bot (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||||
sysloglevel = DEBUG
|
||||
# Number of log files to keep in days, 0 to keep all
|
||||
log_backup_count = 32
|
||||
```
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
# Meshtastic Autoresponder MESH Bot
|
||||
# K7MHI Kelly Keeton 2024
|
||||
|
||||
try:
|
||||
from pubsub import pub
|
||||
except ImportError:
|
||||
print(f"Important dependencies are not met, try install.sh\n\n Did you mean to './launch.sh mesh' using a virtual environment.")
|
||||
exit(1)
|
||||
|
||||
import asyncio
|
||||
import time # for sleep, get some when you can :)
|
||||
import random
|
||||
from pubsub import pub # pip install pubsub
|
||||
from modules.log import *
|
||||
from modules.system import *
|
||||
|
||||
@@ -767,7 +772,7 @@ def sysinfo(message, message_from_id, deviceID):
|
||||
return "sysinfo command returns system information."
|
||||
else:
|
||||
if enable_runShellCmd and file_monitor_enabled:
|
||||
shellData = call_external_script(message)
|
||||
shellData = call_external_script(None, "sysEnv.sh").rstrip()
|
||||
return get_sysinfo(message_from_id, deviceID) + "\n" + shellData
|
||||
else:
|
||||
return get_sysinfo(message_from_id, deviceID)
|
||||
|
||||
@@ -70,8 +70,12 @@ def call_external_script(message, script="runShell.sh"):
|
||||
script_path = os.path.join(current_working_directory, script)
|
||||
|
||||
if not os.path.exists(script_path):
|
||||
logger.warning(f"FileMon: Script not found: {script_path}")
|
||||
return "sorry I can't do that"
|
||||
# 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"
|
||||
|
||||
output = os.popen(f"bash {script_path} {message}").read()
|
||||
return output
|
||||
except Exception as e:
|
||||
|
||||
@@ -357,6 +357,7 @@ def getWeatherAlertsNOAA(lat=0, lon=0, useDefaultLatLon=False):
|
||||
|
||||
alerts = ""
|
||||
alertxml = xml.dom.minidom.parseString(alert_data.text)
|
||||
|
||||
for i in alertxml.getElementsByTagName("entry"):
|
||||
title = i.getElementsByTagName("title")[0].childNodes[0].nodeValue
|
||||
area_desc = i.getElementsByTagName("cap:areaDesc")[0].childNodes[0].nodeValue
|
||||
|
||||
@@ -3,6 +3,11 @@ from logging.handlers import TimedRotatingFileHandler
|
||||
import re
|
||||
from datetime import datetime
|
||||
from modules.settings import *
|
||||
# if LOGGING_LEVEL is not set in settings.py, default to DEBUG
|
||||
if not LOGGING_LEVEL:
|
||||
LOGGING_LEVEL = "DEBUG"
|
||||
|
||||
LOGGING_LEVEL = getattr(logging, LOGGING_LEVEL)
|
||||
|
||||
class CustomFormatter(logging.Formatter):
|
||||
grey = '\x1b[38;21m'
|
||||
@@ -41,7 +46,7 @@ class plainFormatter(logging.Formatter):
|
||||
|
||||
# Create logger
|
||||
logger = logging.getLogger("MeshBot System Logger")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.setLevel(LOGGING_LEVEL)
|
||||
logger.propagate = False
|
||||
|
||||
msgLogger = logging.getLogger("MeshBot Messages Logger")
|
||||
@@ -56,7 +61,7 @@ today = datetime.now()
|
||||
# Create stdout handler for logging to the console
|
||||
stdout_handler = logging.StreamHandler()
|
||||
# Set level for stdout handler (logs DEBUG level and above)
|
||||
stdout_handler.setLevel(logging.DEBUG)
|
||||
stdout_handler.setLevel(LOGGING_LEVEL)
|
||||
# Set format for stdout handler
|
||||
stdout_handler.setFormatter(CustomFormatter(logFormat))
|
||||
# Add handlers to the logger
|
||||
@@ -65,7 +70,7 @@ logger.addHandler(stdout_handler)
|
||||
if syslog_to_file:
|
||||
# Create file handler for logging to a file
|
||||
file_handler_sys = TimedRotatingFileHandler('logs/meshbot.log', when='midnight', backupCount=log_backup_count)
|
||||
file_handler_sys.setLevel(logging.DEBUG) # DEBUG used by default for system logs to disk
|
||||
file_handler_sys.setLevel(LOGGING_LEVEL) # DEBUG used by default for system logs to disk
|
||||
file_handler_sys.setFormatter(plainFormatter(logFormat))
|
||||
logger.addHandler(file_handler_sys)
|
||||
|
||||
|
||||
@@ -189,6 +189,7 @@ try:
|
||||
log_messages_to_file = config['general'].getboolean('LogMessagesToFile', False) # default off
|
||||
log_backup_count = config['general'].getint('LogBackupCount', 32) # default 32 days
|
||||
syslog_to_file = config['general'].getboolean('SyslogToFile', True) # default on
|
||||
LOGGING_LEVEL = config['general'].get('sysloglevel', 'DEBUG') # default DEBUG
|
||||
urlTimeoutSeconds = config['general'].getint('urlTimeout', 10) # default 10 seconds
|
||||
store_forward_enabled = config['general'].getboolean('StoreForward', True)
|
||||
storeFlimit = config['general'].getint('StoreLimit', 3) # default 3 messages for S&F
|
||||
@@ -208,7 +209,6 @@ 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
|
||||
|
||||
# emergency response
|
||||
emergency_responder_enabled = config['emergencyHandler'].getboolean('enabled', False)
|
||||
emergency_responder_alert_channel = config['emergencyHandler'].getint('alert_channel', 2) # default 2
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# helper functions and init for system related tasks
|
||||
# K7MHI Kelly Keeton 2024
|
||||
|
||||
import meshtastic.serial_interface #pip install meshtastic
|
||||
import meshtastic.serial_interface #pip install meshtastic or use launch.sh for venv
|
||||
import meshtastic.tcp_interface
|
||||
import meshtastic.ble_interface
|
||||
import time
|
||||
@@ -12,6 +12,7 @@ import io # for suppressing output on watchdog
|
||||
from modules.log import *
|
||||
|
||||
# Global Variables
|
||||
debugMetadata = False # packet debug for non text messages
|
||||
trap_list = ("cmd","cmd?") # default trap list
|
||||
help_message = "Bot CMD?:"
|
||||
asyncLoop = asyncio.new_event_loop()
|
||||
@@ -75,7 +76,7 @@ if location_enabled:
|
||||
trap_list = trap_list + trap_list_location # items tide, whereami, wxc, wx
|
||||
help_message = help_message + ", whereami, wx, wxc, rlist"
|
||||
if enableGBalerts:
|
||||
from modules.locationdata_eu import * # from the spudgunman/meshing-around repo
|
||||
from modules.globalalert import * # from the spudgunman/meshing-around repo
|
||||
trap_list = trap_list + trap_list_location_eu
|
||||
#help_message = help_message + ", ukalert, ukwx, ukflood"
|
||||
|
||||
@@ -685,7 +686,7 @@ def handleAlertBroadcast(deviceID=1):
|
||||
ukAlert = alertUk
|
||||
|
||||
if emergencyAlertBrodcastEnabled:
|
||||
if NO_ALERTS not in femaAlert:
|
||||
if NO_ALERTS not in femaAlert and ERROR_FETCHING_DATA not in femaAlert:
|
||||
if isinstance(emergencyAlertBroadcastCh, list):
|
||||
for channel in emergencyAlertBroadcastCh:
|
||||
send_message(femaAlert, int(channel), 0, deviceID)
|
||||
@@ -834,90 +835,92 @@ def displayNodeTelemetry(nodeID=0, rxNode=0, userRequested=False):
|
||||
|
||||
positionMetadata = {}
|
||||
def consumeMetadata(packet, rxNode=0):
|
||||
# keep records of recent telemetry data
|
||||
debugMetadata = False
|
||||
packet_type = ''
|
||||
if packet.get('decoded'):
|
||||
packet_type = packet['decoded']['portnum']
|
||||
nodeID = packet['from']
|
||||
try:
|
||||
# keep records of recent telemetry data
|
||||
packet_type = ''
|
||||
if packet.get('decoded'):
|
||||
packet_type = packet['decoded']['portnum']
|
||||
nodeID = packet['from']
|
||||
|
||||
# TELEMETRY packets
|
||||
if packet_type == 'TELEMETRY_APP':
|
||||
#if debugMetadata: print(f"DEBUG TELEMETRY_APP: {packet}\n\n")
|
||||
# get the telemetry data
|
||||
telemetry_packet = packet['decoded']['telemetry']
|
||||
if telemetry_packet.get('deviceMetrics'):
|
||||
deviceMetrics = telemetry_packet['deviceMetrics']
|
||||
if telemetry_packet.get('localStats'):
|
||||
localStats = telemetry_packet['localStats']
|
||||
# Check if 'numPacketsTx' and 'numPacketsRx' exist and are not zero
|
||||
if localStats.get('numPacketsTx') is not None and localStats.get('numPacketsRx') is not None and localStats['numPacketsTx'] != 0:
|
||||
# Assign the values to the telemetry dictionary
|
||||
keys = [
|
||||
'numPacketsTx', 'numPacketsRx', 'numOnlineNodes',
|
||||
'numOfflineNodes', 'numPacketsTxErr', 'numPacketsRxErr', 'numTotalNodes']
|
||||
|
||||
# TELEMETRY packets
|
||||
if packet_type == 'TELEMETRY_APP':
|
||||
if debugMetadata: print(f"DEBUG TELEMETRY_APP: {packet}\n\n")
|
||||
# get the telemetry data
|
||||
telemetry_packet = packet['decoded']['telemetry']
|
||||
if telemetry_packet.get('deviceMetrics'):
|
||||
deviceMetrics = telemetry_packet['deviceMetrics']
|
||||
if telemetry_packet.get('localStats'):
|
||||
localStats = telemetry_packet['localStats']
|
||||
# Check if 'numPacketsTx' and 'numPacketsRx' exist and are not zero
|
||||
if localStats.get('numPacketsTx') is not None and localStats.get('numPacketsRx') is not None and localStats['numPacketsTx'] != 0:
|
||||
# Assign the values to the telemetry dictionary
|
||||
keys = [
|
||||
'numPacketsTx', 'numPacketsRx', 'numOnlineNodes',
|
||||
'numOfflineNodes', 'numPacketsTxErr', 'numPacketsRxErr', 'numTotalNodes']
|
||||
|
||||
for key in keys:
|
||||
if localStats.get(key) is not None:
|
||||
telemetryData[rxNode][key] = localStats.get(key)
|
||||
|
||||
# POSITION_APP packets
|
||||
if packet_type == 'POSITION_APP':
|
||||
if debugMetadata: print(f"DEBUG POSITION_APP: {packet}\n\n")
|
||||
# get the position data
|
||||
keys = ['altitude', 'groundSpeed', 'precisionBits']
|
||||
position_data = packet['decoded']['position']
|
||||
try:
|
||||
if nodeID not in positionMetadata:
|
||||
positionMetadata[nodeID] = {}
|
||||
|
||||
for key in keys:
|
||||
if localStats.get(key) is not None:
|
||||
telemetryData[rxNode][key] = localStats.get(key)
|
||||
|
||||
# POSITION_APP packets
|
||||
if packet_type == 'POSITION_APP':
|
||||
if debugMetadata: print(f"DEBUG POSITION_APP: {packet}\n\n")
|
||||
# get the position data
|
||||
keys = ['altitude', 'groundSpeed', 'precisionBits']
|
||||
position_data = packet['decoded']['position']
|
||||
try:
|
||||
if nodeID not in positionMetadata:
|
||||
positionMetadata[nodeID] = {}
|
||||
|
||||
for key in keys:
|
||||
positionMetadata[nodeID][key] = position_data.get(key, 0)
|
||||
|
||||
# Keep the positionMetadata dictionary at 5 records
|
||||
if len(positionMetadata) > 20:
|
||||
# Remove the oldest entry
|
||||
oldest_nodeID = next(iter(positionMetadata))
|
||||
del positionMetadata[oldest_nodeID]
|
||||
except Exception as e:
|
||||
logger.debug(f"System: POSITION_APP decode error: {e} packet {packet}")
|
||||
positionMetadata[nodeID][key] = position_data.get(key, 0)
|
||||
|
||||
# Keep the positionMetadata dictionary at 5 records
|
||||
if len(positionMetadata) > 20:
|
||||
# Remove the oldest entry
|
||||
oldest_nodeID = next(iter(positionMetadata))
|
||||
del positionMetadata[oldest_nodeID]
|
||||
except Exception as e:
|
||||
logger.debug(f"System: POSITION_APP decode error: {e} packet {packet}")
|
||||
|
||||
# WAYPOINT_APP packets
|
||||
if packet_type == 'WAYPOINT_APP':
|
||||
if debugMetadata: print(f"DEBUG WAYPOINT_APP: {packet['decoded']['waypoint']}\n\n")
|
||||
# get the waypoint data
|
||||
waypoint_data = packet['decoded']['waypoint']
|
||||
keys = ['latitude', 'longitude',]
|
||||
# WAYPOINT_APP packets
|
||||
if packet_type == 'WAYPOINT_APP':
|
||||
if debugMetadata: print(f"DEBUG WAYPOINT_APP: {packet['decoded']['waypoint']}\n\n")
|
||||
# get the waypoint data
|
||||
waypoint_data = packet['decoded']
|
||||
|
||||
# NEIGHBORINFO_APP
|
||||
if packet_type == 'NEIGHBORINFO_APP':
|
||||
if debugMetadata: print(f"DEBUG NEIGHBORINFO_APP: {packet}\n\n")
|
||||
# get the neighbor info data
|
||||
neighbor_data = packet['decoded']['neighborInfo']
|
||||
|
||||
# TRACEROUTE_APP
|
||||
if packet_type == 'TRACEROUTE_APP':
|
||||
if debugMetadata: print(f"DEBUG TRACEROUTE_APP: {packet}\n\n")
|
||||
# get the traceroute data
|
||||
traceroute_data = packet['decoded']['traceroute']
|
||||
# NEIGHBORINFO_APP
|
||||
if packet_type == 'NEIGHBORINFO_APP':
|
||||
if debugMetadata: print(f"DEBUG NEIGHBORINFO_APP: {packet}\n\n")
|
||||
# get the neighbor info data
|
||||
neighbor_data = packet['decoded']
|
||||
|
||||
# TRACEROUTE_APP
|
||||
if packet_type == 'TRACEROUTE_APP':
|
||||
if debugMetadata: print(f"DEBUG TRACEROUTE_APP: {packet}\n\n")
|
||||
# get the traceroute data
|
||||
traceroute_data = packet['decoded']
|
||||
|
||||
# DETECTION_SENSOR_APP
|
||||
if packet_type == 'DETECTION_SENSOR_APP':
|
||||
if debugMetadata: print(f"DEBUG DETECTION_SENSOR_APP: {packet}\n\n")
|
||||
# get the detection sensor data
|
||||
detection_data = packet['decoded']['detectionSensor']
|
||||
# DETECTION_SENSOR_APP
|
||||
if packet_type == 'DETECTION_SENSOR_APP':
|
||||
if debugMetadata: print(f"DEBUG DETECTION_SENSOR_APP: {packet}\n\n")
|
||||
# get the detection sensor data
|
||||
detection_data = packet['decoded']
|
||||
|
||||
# PAXCOUNTER_APP
|
||||
if packet_type == 'PAXCOUNTER_APP':
|
||||
if debugMetadata: print(f"DEBUG PAXCOUNTER_APP: {packet}\n\n")
|
||||
# get the paxcounter data
|
||||
paxcounter_data = packet['decoded']['paxcounter']
|
||||
# PAXCOUNTER_APP
|
||||
if packet_type == 'PAXCOUNTER_APP':
|
||||
if debugMetadata: print(f"DEBUG PAXCOUNTER_APP: {packet}\n\n")
|
||||
# get the paxcounter data
|
||||
paxcounter_data = packet['decoded']
|
||||
|
||||
# REMOTE_HARDWARE_APP
|
||||
if packet_type == 'REMOTE_HARDWARE_APP':
|
||||
if debugMetadata: print(f"DEBUG REMOTE_HARDWARE_APP: {packet}\n\n")
|
||||
# get the remote hardware data
|
||||
remote_hardware_data = packet['decoded']['remoteHardware']
|
||||
# REMOTE_HARDWARE_APP
|
||||
if packet_type == 'REMOTE_HARDWARE_APP':
|
||||
if debugMetadata: print(f"DEBUG REMOTE_HARDWARE_APP: {packet}\n\n")
|
||||
# get the remote hardware data
|
||||
remote_hardware_data = packet['decoded']
|
||||
except KeyError as e:
|
||||
logger.critical(f"System: Error consuming metadata: {e} Device:{rxNode}")
|
||||
logger.debug(f"System: Error Packet = {packet}")
|
||||
|
||||
def get_sysinfo(nodeID=0, deviceID=1):
|
||||
# Get the system telemetry data for return on the sysinfo command
|
||||
|
||||
@@ -2,9 +2,15 @@
|
||||
# Meshtastic Autoresponder PONG Bot
|
||||
# K7MHI Kelly Keeton 2024
|
||||
|
||||
try:
|
||||
from pubsub import pub
|
||||
except ImportError:
|
||||
print(f"Important dependencies are not met, try install.sh\n\n Did you mean to './launch.sh pong' using a virtual environment.")
|
||||
exit(1)
|
||||
|
||||
import asyncio
|
||||
import time # for sleep, get some when you can :)
|
||||
from pubsub import pub # pip install pubsub
|
||||
import random
|
||||
from modules.log import *
|
||||
from modules.system import *
|
||||
|
||||
|
||||
24
runShell.sh
24
runShell.sh
@@ -4,26 +4,4 @@
|
||||
cd "$(dirname "$0")"
|
||||
program_path=$(pwd)
|
||||
|
||||
# get basic telemetry data. Free space, CPU, RAM, and temperature for a raspberry pi
|
||||
free_space=$(df -h | grep ' /$' | awk '{print $4}')
|
||||
cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
|
||||
ram_usage=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
|
||||
|
||||
# if command vcgencmd is found
|
||||
if command -v vcgencmd &> /dev/null
|
||||
then
|
||||
# get temperature
|
||||
temp=$(vcgencmd measure_temp | sed "s/temp=//" | sed "s/'C//")
|
||||
# temp in fahrenheit
|
||||
tempf=$(echo "scale=2; $temp * 9 / 5 + 32" | bc)
|
||||
else
|
||||
temp=$(paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp) | grep "temp" | awk '{print $2/1000}' | awk '{s+=$1} END {print s/NR}')
|
||||
tempf=$(echo "scale=2; $temp * 9 / 5 + 32" | bc)
|
||||
fi
|
||||
|
||||
|
||||
# print telemetry data
|
||||
printf "Free Space: %s\n" "$free_space"
|
||||
printf "CPU Usage: %.1f%%\n" "$cpu_usage"
|
||||
printf "RAM Usage: %.2f%%\n" "$ram_usage"
|
||||
printf "Temperature: %.1f°C (%.1f°F)\n" "$temp" "$tempf"
|
||||
printf "Running meshing-around demo script for shell scripting\n"
|
||||
30
sysEnv.sh
Normal file
30
sysEnv.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
# meshing-around shell script for sysinfo
|
||||
# runShell.sh
|
||||
cd "$(dirname "$0")"
|
||||
program_path=$(pwd)
|
||||
|
||||
# get basic telemetry data. Free space, CPU, RAM, and temperature for a raspberry pi
|
||||
free_space=$(df -h | grep ' /$' | awk '{print $4}')
|
||||
cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
|
||||
ram_usage=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
|
||||
ram_free=$(echo "scale=2; 100 - $ram_usage" | bc)
|
||||
|
||||
# if command vcgencmd is found, part of raspberrypi tools, use it to get temperature
|
||||
if command -v vcgencmd &> /dev/null
|
||||
then
|
||||
# get temperature
|
||||
temp=$(vcgencmd measure_temp | sed "s/temp=//" | sed "s/'C//")
|
||||
# temp in fahrenheit
|
||||
tempf=$(echo "scale=2; $temp * 9 / 5 + 32" | bc)
|
||||
else
|
||||
# get temperature from thermal zone
|
||||
temp=$(paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp) | grep "temp" | awk '{print $2/1000}' | awk '{s+=$1} END {print s/NR}')
|
||||
tempf=$(echo "scale=2; $temp * 9 / 5 + 32" | bc)
|
||||
fi
|
||||
|
||||
# print telemetry data
|
||||
printf "Disk:%s" "$free_space"
|
||||
printf " RAM:%.2f%%" "$ram_usage"
|
||||
printf " CPU:%.1f%%" "$cpu_usage"
|
||||
printf " CPU-T:%.1f°C (%.1f°F)" "$temp" "$tempf"
|
||||
Reference in New Issue
Block a user