Merge branch 'SpudGunMan:main' into main

This commit is contained in:
Nestpebble
2024-09-13 23:28:47 +01:00
committed by GitHub
5 changed files with 56 additions and 29 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ The feature-rich bot requires the internet for full functionality. These respond
Along with network testing, this bot has a lot of other fun features, like simple mail messaging you can leave for another device, and when that device is seen, it can send the mail as a DM. Or a scheduler to send weather or a reminder weekly for the VHF net.
The bot is also capable of using dual radio/nodes, so you can monitor two networks at the same time and send messages to nodes using the same `bbspost @nodeNumber #message` or `bbspost @nodeShportName #message` function. There is a small message board to fit in the constraints of Meshtastic for posting bulletin messages with `bbspost $subject #message`.
The bot is also capable of using dual radio/nodes, so you can monitor two networks at the same time and send messages to nodes using the same `bbspost @nodeNumber #message` or `bbspost @nodeShortName #message` function. There is a small message board to fit in the constraints of Meshtastic for posting bulletin messages with `bbspost $subject #message`.
Look up data using wiki results or interact with [Ollama](https://ollama.com) LLM AI see the [OllamaDocs](https://github.com/ollama/ollama/tree/main/docs) If Ollama is enabled you can DM the bot directly. The default model for mesh-bot which is currently `gemma2:2b`
@@ -32,7 +32,7 @@ Any messages that are over 160 characters are chunked into 160 message bytes to
- `bbshelp` returns the following
- `bbslist` list the messages by ID and subject
- `bbsread` read a message example use: `bbsread #1`
- `bbspost` post a message to public board or send a DM example use: `bbspost $subject #message, or bbspost @nodeNumber #message or bbspost @nodeShportName #message`
- `bbspost` post a message to public board or send a DM example use: `bbspost $subject #message, or bbspost @nodeNumber #message or bbspost @nodeShortName #message`
- `bbsdelete` delete a message example use: `bbsdelete #4`
- Other functions
- `whereami` returns the address of location of sender if known
+45 -20
View File
@@ -8,6 +8,8 @@ from pubsub import pub # pip install pubsub
from modules.log import *
from modules.system import *
responseDelay = 0.7 # delay in seconds for response to avoid message collision
def auto_response(message, snr, rssi, hop, message_from_id, channel_number, deviceID):
#Auto response to messages
message_lower = message.lower()
@@ -57,8 +59,8 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
# run the first command after sorting
bot_response = command_handler[cmds[0]['cmd']]()
# wait a 700ms to avoid message collision from lora-ack
time.sleep(0.7)
# wait a responseDelay to avoid message collision from lora-ack
time.sleep(responseDelay)
return bot_response
@@ -104,30 +106,49 @@ def handle_wiki(message):
return get_wikipedia_summary(search)
else:
return "Please add a search term example:wiki: travelling gnome"
llmRunCounter = 0
llmTotalRuntime = []
llmLocationTable = {}
def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel):
global llmRunCounter, llmTotalRuntime, llmLocationTable
if location_enabled:
location = get_node_location(message_from_id, deviceID)
# if message_from_id is is the llmLocationTable use the location from the table to save on API calls
if message_from_id in llmLocationTable:
location = llmLocationTable[message_from_id]
location_name = llmLocationTable[message_from_id]
else:
location_name = where_am_i(str(location[0]), str(location[1]), short = True)
llmLocationTable.append({message_from_id: location_name})
if NO_DATA_NOGPS in location_name:
location_name = "no location provided "
if NO_DATA_NOGPS in location_name:
location_name = "no location provided "
else:
location_name = "no location provided "
location_name = "no location provided"
if "ask:" in message.lower():
user_input = message.split(":")[1]
elif "askai" in message.lower():
user_input = message.replace("askai", "")
else:
# likely a DM
user_input = message
# if the message_from_id is not in the llmLocationTable send the welcome message
if not message_from_id in llmLocationTable:
if (channel_number == publicChannel and antiSpam) or useDMForResponse:
# send via DM
send_message(welcome_message, channel_number, message_from_id, deviceID)
time.sleep(responseDelay)
else:
# send via channel
send_message(welcome_message, channel_number, 0, deviceID)
time.sleep(responseDelay)
# add the node to the llmLocationTable for future use
llmLocationTable[message_from_id] = location_name
user_input = user_input.strip()
if len(user_input) < 1:
@@ -138,20 +159,24 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel
averageRuntime = sum(llmTotalRuntime) / len(llmTotalRuntime)
if averageRuntime > 25:
msg = f"Please wait, average query time is: {int(averageRuntime)} seconds"
if channel_number == publicChannel:
if (channel_number == publicChannel and antiSpam) or useDMForResponse:
# send via DM
send_message(msg, channel_number, message_from_id, deviceID)
time.sleep(responseDelay)
else:
# send via channel
send_message(msg, channel_number, 0, deviceID)
time.sleep(responseDelay)
else:
msg = "Please wait, response could take 3+ minutes. Fund the SysOp's GPU budget!"
if channel_number == publicChannel:
# send via DM
send_message(msg, channel_number, message_from_id, deviceID)
else:
# send via channel
send_message(msg, channel_number, 0, deviceID)
msg = "Please wait, response could take 30+ seconds. Fund the SysOp's GPU budget!"
if (channel_number == publicChannel and antiSpam) or useDMForResponse:
# send via DM
send_message(msg, channel_number, message_from_id, deviceID)
time.sleep(responseDelay)
else:
# send via channel
send_message(msg, channel_number, 0, deviceID)
time.sleep(responseDelay)
start = time.time()
@@ -342,8 +367,8 @@ def onReceive(packet, interface):
msg = bbs_check_dm(message_from_id)
if msg:
# wait a 700ms to avoid message collision from lora-ack.
time.sleep(0.7)
# wait a responseDelay to avoid message collision from lora-ack.
time.sleep(responseDelay)
logger.info(f"System: BBS DM Found: {msg[1]} For: {get_name_from_number(message_from_id, 'long', rxNode)}")
message = "Mail: " + msg[1] + " From: " + get_name_from_number(msg[2], 'long', rxNode)
bbs_delete_dm(msg[0], msg[1])
@@ -462,8 +487,8 @@ def onReceive(packet, interface):
# repeat the message on the other device
if repeater_enabled and interface2_enabled:
# wait a 700ms to avoid message collision from lora-ack.
time.sleep(0.7)
# wait a responseDelay to avoid message collision from lora-ack.
time.sleep(responseDelay)
rMsg = (f"{message_string} From:{get_name_from_number(message_from_id, 'short', rxNode)}")
# if channel found in the repeater list repeat the message
if str(channel_number) in repeater_channels:
+2 -2
View File
@@ -105,9 +105,9 @@ def llm_query(input, nodeID=0, location_name=None):
if googleResults:
logger.debug(f"System: External LLM Query: {input} From:{nodeID} with context from google")
logger.debug(f"System: LLM Query: {input} From:{nodeID} with context from google")
else:
logger.debug(f"System: External LLM Query: {input} From:{nodeID}")
logger.debug(f"System: LLM Query: {input} From:{nodeID}")
response = ""
result = ""
+1 -1
View File
@@ -28,7 +28,7 @@ def where_am_i(lat=0, lon=0, short=False):
location = geolocator.reverse(lat + ", " + lon)
address = location.raw['address']
address_components = ['city', 'state', 'county', 'country']
whereIam = f"City: {address.get('city', '')} State: {address.get('state', '')} County: {address.get('county', '')} Country: {address.get('country', '')}"
whereIam = f"City: {address.get('city', '')}. State: {address.get('state', '')}. County: {address.get('county', '')}. Country: {address.get('country', '')}."
return whereIam
if float(lat) == latitudeValue and float(lon) == longitudeValue:
+6 -4
View File
@@ -8,6 +8,8 @@ from pubsub import pub # pip install pubsub
from modules.log import *
from modules.system import *
responseDelay = 0.7 # delay in seconds for response to avoid message collision
def auto_response(message, snr, rssi, hop, message_from_id, channel_number, deviceID):
# Auto response to messages
message_lower = message.lower()
@@ -37,8 +39,8 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
# run the first command after sorting
bot_response = command_handler[cmds[0]['cmd']]()
# wait a 700ms to avoid message collision from lora-ack
time.sleep(0.7)
# wait a responseDelay to avoid message collision from lora-ack
time.sleep(responseDelay)
return bot_response
@@ -252,8 +254,8 @@ def onReceive(packet, interface):
# repeat the message on the other device
if repeater_enabled and interface2_enabled:
# wait a 700ms to avoid message collision from lora-ack.
time.sleep(0.7)
# wait a responseDelay to avoid message collision from lora-ack.
time.sleep(responseDelay)
rMsg = (f"{message_string} From:{get_name_from_number(message_from_id, 'short', rxNode)}")
# if channel found in the repeater list repeat the message
if str(channel_number) in repeater_channels: