mirror of
https://github.com/SpudGunMan/meshing-around.git
synced 2026-05-15 05:35:39 +02:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9de72a26d0 | |||
| cd8a5bafcf | |||
| 8a7b858edb | |||
| ab48622d23 | |||
| 6eeba2fdbe | |||
| b26d0d9f9d | |||
| cda29f7b16 | |||
| aaca4b5cb4 | |||
| 55460ee730 | |||
| 94b0102205 | |||
| dcd1c4235c | |||
| 4549e6786f | |||
| 2e7685e1ad | |||
| 4708557bb3 | |||
| 2467b2f984 | |||
| fdd94b95b0 | |||
| dd3cc524ff | |||
| 0b71ec18a9 | |||
| 2e11d5a4fc | |||
| 5cc46fed8f | |||
| 191837f1a6 | |||
| 890843e394 | |||
| 85585db723 | |||
| 1719767a47 |
@@ -10,7 +10,7 @@ Along with network testing, this bot has a lot of other features, like simple ma
|
|||||||
|
|
||||||
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` 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` function. There is a small message board to fit in the constraints of Meshtastic for posting bulletin messages with `bbspost $subject #message`.
|
||||||
|
|
||||||
Store and forward-like message re-play with `messages`, and there is a repeater module for dual radio bots to cross post messages.
|
Store and forward-like message re-play with `messages`, and there is a repeater module for dual radio bots to cross post messages. Messages are also logged locally to disk.
|
||||||
|
|
||||||
The bot can also be used to monitor a frequency and let you know when activity is seen. Using Hamlib to watch the S meter on a connected radio. You can send alerts to channels when a frequency is detected for 20 seconds within the thresholds set in config.ini
|
The bot can also be used to monitor a frequency and let you know when activity is seen. Using Hamlib to watch the S meter on a connected radio. You can send alerts to channels when a frequency is detected for 20 seconds within the thresholds set in config.ini
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ StoreLimit = 3
|
|||||||
zuluTime = True
|
zuluTime = True
|
||||||
# wait time for URL requests
|
# wait time for URL requests
|
||||||
URL_TIMEOUT = 10
|
URL_TIMEOUT = 10
|
||||||
|
# logging to file of the non Bot messages
|
||||||
|
LogMessagesToFile = False
|
||||||
|
|
||||||
[bbs]
|
[bbs]
|
||||||
enabled = True
|
enabled = True
|
||||||
|
|||||||
+81
-74
@@ -5,11 +5,12 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import time # for sleep, get some when you can :)
|
import time # for sleep, get some when you can :)
|
||||||
from pubsub import pub # pip install pubsub
|
from pubsub import pub # pip install pubsub
|
||||||
from modules.settings import *
|
from modules.log import *
|
||||||
from modules.system import *
|
from modules.system import *
|
||||||
|
|
||||||
def auto_response(message, snr, rssi, hop, message_from_id, channel_number, deviceID):
|
def auto_response(message, snr, rssi, hop, message_from_id, channel_number, deviceID):
|
||||||
#Auto response to messages
|
#Auto response to messages
|
||||||
|
bot_response = ""
|
||||||
if "ping" in message.lower():
|
if "ping" in message.lower():
|
||||||
#Check if the user added @foo to the message
|
#Check if the user added @foo to the message
|
||||||
if "@" in message:
|
if "@" in message:
|
||||||
@@ -22,11 +23,6 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
|
|||||||
bot_response = "🏓PONG, " + f"SNR:{snr} RSSI:{rssi}"
|
bot_response = "🏓PONG, " + f"SNR:{snr} RSSI:{rssi}"
|
||||||
else:
|
else:
|
||||||
bot_response = "🏓PONG, " + hop
|
bot_response = "🏓PONG, " + hop
|
||||||
elif "ack" in message.lower():
|
|
||||||
if hop == "Direct":
|
|
||||||
bot_response = "🏓ACK-ACK! " + f"SNR:{snr} RSSI:{rssi}"
|
|
||||||
else:
|
|
||||||
bot_response = "🏓ACK-ACK! " + hop
|
|
||||||
elif "pong" in message.lower():
|
elif "pong" in message.lower():
|
||||||
bot_response = "🏓PING!!"
|
bot_response = "🏓PING!!"
|
||||||
elif "motd" in message.lower():
|
elif "motd" in message.lower():
|
||||||
@@ -57,7 +53,7 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
|
|||||||
elif "cmd" in message.lower() or "cmd?" in message.lower():
|
elif "cmd" in message.lower() or "cmd?" in message.lower():
|
||||||
bot_response = help_message
|
bot_response = help_message
|
||||||
elif "sun" in message.lower():
|
elif "sun" in message.lower():
|
||||||
location = get_node_location(message_from_id, deviceID)
|
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||||
bot_response = get_sun(str(location[0]),str(location[1]))
|
bot_response = get_sun(str(location[0]),str(location[1]))
|
||||||
elif "hfcond" in message.lower():
|
elif "hfcond" in message.lower():
|
||||||
bot_response = hf_band_conditions()
|
bot_response = hf_band_conditions()
|
||||||
@@ -75,31 +71,31 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
|
|||||||
if interface2_enabled:
|
if interface2_enabled:
|
||||||
bot_response += " P2:" + str(chutil2) + "%"
|
bot_response += " P2:" + str(chutil2) + "%"
|
||||||
elif "whereami" in message.lower():
|
elif "whereami" in message.lower():
|
||||||
location = get_node_location(message_from_id, deviceID)
|
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||||
where = where_am_i(str(location[0]),str(location[1]))
|
where = where_am_i(str(location[0]),str(location[1]))
|
||||||
bot_response = where
|
bot_response = where
|
||||||
elif "tide" in message.lower():
|
elif "tide" in message.lower():
|
||||||
location = get_node_location(message_from_id, deviceID)
|
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||||
tide = get_tide(str(location[0]),str(location[1]))
|
tide = get_tide(str(location[0]),str(location[1]))
|
||||||
bot_response = tide
|
bot_response = tide
|
||||||
elif "moon" in message.lower():
|
elif "moon" in message.lower():
|
||||||
location = get_node_location(message_from_id, deviceID)
|
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||||
moon = get_moon(str(location[0]),str(location[1]))
|
moon = get_moon(str(location[0]),str(location[1]))
|
||||||
bot_response = moon
|
bot_response = moon
|
||||||
elif "wxalert" in message.lower():
|
elif "wxalert" in message.lower():
|
||||||
location = get_node_location(message_from_id, deviceID)
|
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||||
weatherAlert = getActiveWeatherAlertsDetail(str(location[0]),str(location[1]))
|
weatherAlert = getActiveWeatherAlertsDetail(str(location[0]),str(location[1]))
|
||||||
bot_response = weatherAlert
|
bot_response = weatherAlert
|
||||||
elif "wxa" in message.lower():
|
elif "wxa" in message.lower():
|
||||||
location = get_node_location(message_from_id, deviceID)
|
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||||
weatherAlert = getWeatherAlerts(str(location[0]),str(location[1]))
|
weatherAlert = getWeatherAlerts(str(location[0]),str(location[1]))
|
||||||
bot_response = weatherAlert
|
bot_response = weatherAlert
|
||||||
elif "wxc" in message.lower():
|
elif "wxc" in message.lower():
|
||||||
location = get_node_location(message_from_id, deviceID)
|
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||||
weather = get_weather(str(location[0]),str(location[1]),1)
|
weather = get_weather(str(location[0]),str(location[1]),1)
|
||||||
bot_response = weather
|
bot_response = weather
|
||||||
elif "wx" in message.lower():
|
elif "wx" in message.lower():
|
||||||
location = get_node_location(message_from_id, deviceID)
|
location = get_node_location(message_from_id, deviceID, channel_number)
|
||||||
weather = get_weather(str(location[0]),str(location[1]))
|
weather = get_weather(str(location[0]),str(location[1]))
|
||||||
bot_response = weather
|
bot_response = weather
|
||||||
elif "joke" in message.lower():
|
elif "joke" in message.lower():
|
||||||
@@ -108,18 +104,18 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
|
|||||||
bot_response = bbs_list_messages()
|
bot_response = bbs_list_messages()
|
||||||
elif "bbspost" in message.lower():
|
elif "bbspost" in message.lower():
|
||||||
# Check if the user added a subject to the message
|
# Check if the user added a subject to the message
|
||||||
if "$" in message:
|
if "$" in message and not "example:" in message:
|
||||||
subject = message.split("$")[1].split("#")[0]
|
subject = message.split("$")[1].split("#")[0]
|
||||||
subject = subject.rstrip()
|
subject = subject.rstrip()
|
||||||
if "#" in message:
|
if "#" in message:
|
||||||
body = message.split("#")[1]
|
body = message.split("#")[1]
|
||||||
body = body.rstrip()
|
body = body.rstrip()
|
||||||
print(f"{log_timestamp()} System: BBS Post: {subject} Body: {body}")
|
logger.info(f"System: BBS Post: {subject} Body: {body}")
|
||||||
bot_response = bbs_post_message(subject,body,message_from_id)
|
bot_response = bbs_post_message(subject,body,message_from_id)
|
||||||
else:
|
elif not "example:" in message:
|
||||||
bot_response = "example: bbspost $subject #message"
|
bot_response = "example: bbspost $subject #message"
|
||||||
# Check if the user added a node number to the message
|
# Check if the user added a node number to the message
|
||||||
elif "@" in message:
|
elif "@" in message and not "example:" in message:
|
||||||
toNode = message.split("@")[1].split("#")[0]
|
toNode = message.split("@")[1].split("#")[0]
|
||||||
toNode = toNode.rstrip()
|
toNode = toNode.rstrip()
|
||||||
if "#" in message:
|
if "#" in message:
|
||||||
@@ -127,25 +123,33 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
|
|||||||
bot_response = bbs_post_dm(toNode, body, message_from_id)
|
bot_response = bbs_post_dm(toNode, body, message_from_id)
|
||||||
else:
|
else:
|
||||||
bot_response = "example: bbspost @nodeNumber #message"
|
bot_response = "example: bbspost @nodeNumber #message"
|
||||||
else:
|
elif not "example:" in message:
|
||||||
bot_response = "example: bbspost $subject #message, or bbspost @nodeNumber #message"
|
bot_response = "example: bbspost $subject #message, or bbspost @nodeNumber #message"
|
||||||
|
|
||||||
elif "bbsread" in message.lower():
|
elif "bbsread" in message.lower():
|
||||||
# Check if the user added a message number to the message
|
# Check if the user added a message number to the message
|
||||||
if "#" in message:
|
if "#" in message and not "example:" in message:
|
||||||
messageID = int(message.split("#")[1])
|
messageID = int(message.split("#")[1])
|
||||||
bot_response = bbs_read_message(messageID)
|
bot_response = bbs_read_message(messageID)
|
||||||
else:
|
elif not "example:" in message:
|
||||||
bot_response = "Please add a message number ex: bbsread #14"
|
bot_response = "Please add a message number example: bbsread #14"
|
||||||
elif "bbsdelete" in message.lower():
|
elif "bbsdelete" in message.lower():
|
||||||
# Check if the user added a message number to the message
|
# Check if the user added a message number to the message
|
||||||
if "#" in message:
|
if "#" in message and not "example:" in message:
|
||||||
messageID = int(message.split("#")[1])
|
messageID = int(message.split("#")[1])
|
||||||
bot_response = bbs_delete_message(messageID, message_from_id)
|
bot_response = bbs_delete_message(messageID, message_from_id)
|
||||||
|
elif not "example:" in message:
|
||||||
|
bot_response = "Please add a message number example: bbsdelete #14"
|
||||||
|
elif "ack" in message.lower():
|
||||||
|
if hop == "Direct":
|
||||||
|
bot_response = "🏓ACK-ACK! " + f"SNR:{snr} RSSI:{rssi}"
|
||||||
else:
|
else:
|
||||||
bot_response = "Please add a message number ex: bbsdelete #14"
|
bot_response = "🏓ACK-ACK! " + hop
|
||||||
elif "testing" in message.lower() or "test" in message.lower():
|
elif "testing" in message.lower() or "test" in message.lower():
|
||||||
bot_response = "🏓Testing 1,2,3"
|
if hop == "Direct":
|
||||||
|
bot_response = "🏓Testing 1,2,3 " + f"SNR:{snr} RSSI:{rssi}"
|
||||||
|
else:
|
||||||
|
bot_response = "🏓Testing 1,2,3 " + hop
|
||||||
else:
|
else:
|
||||||
bot_response = "I'm sorry, I'm afraid I can't do that."
|
bot_response = "I'm sorry, I'm afraid I can't do that."
|
||||||
|
|
||||||
@@ -192,7 +196,7 @@ def onReceive(packet, interface):
|
|||||||
if msg:
|
if msg:
|
||||||
# wait a 700ms to avoid message collision from lora-ack.
|
# wait a 700ms to avoid message collision from lora-ack.
|
||||||
time.sleep(0.7)
|
time.sleep(0.7)
|
||||||
print(f"{log_timestamp()} System: BBS DM Found: {msg[1]} For: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
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)
|
message = "Mail: " + msg[1] + " From: " + get_name_from_number(msg[2], 'long', rxNode)
|
||||||
bbs_delete_dm(msg[0], msg[1])
|
bbs_delete_dm(msg[0], msg[1])
|
||||||
send_message(message, channel_number, message_from_id, rxNode)
|
send_message(message, channel_number, message_from_id, rxNode)
|
||||||
@@ -203,31 +207,29 @@ def onReceive(packet, interface):
|
|||||||
message_bytes = packet['decoded']['payload']
|
message_bytes = packet['decoded']['payload']
|
||||||
message_string = message_bytes.decode('utf-8')
|
message_string = message_bytes.decode('utf-8')
|
||||||
message_from_id = packet['from']
|
message_from_id = packet['from']
|
||||||
try:
|
|
||||||
snr = packet['rxSnr']
|
|
||||||
rssi = packet['rxRssi']
|
|
||||||
except KeyError:
|
|
||||||
snr = 0
|
|
||||||
rssi = 0
|
|
||||||
|
|
||||||
|
# get the signal strength and snr if available
|
||||||
|
if packet.get('rxSnr') or packet.get('rxRssi'):
|
||||||
|
snr = packet.get('rxSnr', 0)
|
||||||
|
rssi = packet.get('rxRssi', 0)
|
||||||
|
|
||||||
|
# check if the packet has a channel flag use it
|
||||||
if packet.get('channel'):
|
if packet.get('channel'):
|
||||||
channel_number = packet['channel']
|
channel_number = packet.get('channel', 0)
|
||||||
else:
|
|
||||||
channel_number = publicChannel
|
|
||||||
|
|
||||||
# check if the packet has a hop count flag use it
|
# check if the packet has a hop count flag use it
|
||||||
if packet.get('hopsAway'):
|
if packet.get('hopsAway'):
|
||||||
hop_away = packet['hopsAway']
|
hop_away = packet.get('hopsAway', 0)
|
||||||
else:
|
else:
|
||||||
# if the packet does not have a hop count try other methods
|
# if the packet does not have a hop count try other methods
|
||||||
hop_away = 0
|
hop_away = 0
|
||||||
if packet.get('hopLimit'):
|
if packet.get('hopLimit'):
|
||||||
hop_limit = packet['hopLimit']
|
hop_limit = packet.get('hopLimit', 0)
|
||||||
else:
|
else:
|
||||||
hop_limit = 0
|
hop_limit = 0
|
||||||
|
|
||||||
if packet.get('hopStart'):
|
if packet.get('hopStart'):
|
||||||
hop_start = packet['hopStart']
|
hop_start = packet.get('hopStart', 0)
|
||||||
else:
|
else:
|
||||||
hop_start = 0
|
hop_start = 0
|
||||||
|
|
||||||
@@ -245,26 +247,29 @@ def onReceive(packet, interface):
|
|||||||
|
|
||||||
if message_string == help_message or message_string == welcome_message or "CMD?:" in message_string:
|
if message_string == help_message or message_string == welcome_message or "CMD?:" in message_string:
|
||||||
# ignore help and welcome messages
|
# ignore help and welcome messages
|
||||||
print(f"{log_timestamp()} Got Own Welcome/Help header. From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
logger.warning(f"Got Own Welcome/Help header. From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
# If the packet is a DM (Direct Message) respond to it, otherwise validate its a message for us on the channel
|
# If the packet is a DM (Direct Message) respond to it, otherwise validate its a message for us on the channel
|
||||||
if packet['to'] == myNodeNum1 or packet['to'] == myNodeNum2:
|
if packet['to'] == myNodeNum1 or packet['to'] == myNodeNum2:
|
||||||
# message is DM to us
|
# message is DM to us
|
||||||
|
|
||||||
# check if the message contains a trap word, DMs are always responded to
|
# check if the message contains a trap word, DMs are always responded to
|
||||||
if messageTrap(message_string):
|
if messageTrap(message_string):
|
||||||
print(f"{log_timestamp()} Received DM: {message_string} on Device:{rxNode} Channel: {channel_number} From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
logger.info(f"Device:{rxNode} Channel: {channel_number} " + CustomFormatter.green + f"Received DM: " + CustomFormatter.white + f"{message_string} " + CustomFormatter.purple +\
|
||||||
|
"From: " + CustomFormatter.white + f"{get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
# respond with DM
|
# respond with DM
|
||||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||||
else:
|
else:
|
||||||
# respond with welcome message on DM
|
# respond with welcome message on DM
|
||||||
print(f"{log_timestamp()} Ignoring DM: {message_string} on Device:{rxNode} From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
logger.warning(f"Device:{rxNode} Ignoring DM: {message_string} From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
send_message(welcome_message, channel_number, message_from_id, rxNode)
|
send_message(welcome_message, channel_number, message_from_id, rxNode)
|
||||||
|
msgLogger.info(f"Device:{rxNode} Channel:{channel_number} | {get_name_from_number(message_from_id, 'long', rxNode)} | {message_string}")
|
||||||
else:
|
else:
|
||||||
# message is on a channel
|
# message is on a channel
|
||||||
if messageTrap(message_string):
|
if messageTrap(message_string):
|
||||||
print(f"{log_timestamp()} Received On Device:{rxNode} Channel {channel_number}: {message_string} From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
# message is for bot to respond to
|
||||||
|
logger.info(f"Device:{rxNode} Channel:{channel_number} " + CustomFormatter.green + "Received: " + CustomFormatter.white + f"{message_string} " + CustomFormatter.purple +\
|
||||||
|
"From: " + CustomFormatter.white + f"{get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
if useDMForResponse:
|
if useDMForResponse:
|
||||||
# respond to channel message via direct message
|
# respond to channel message via direct message
|
||||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||||
@@ -272,7 +277,7 @@ def onReceive(packet, interface):
|
|||||||
# or respond to channel message on the channel itself
|
# or respond to channel message on the channel itself
|
||||||
if channel_number == publicChannel and antiSpam:
|
if channel_number == publicChannel and antiSpam:
|
||||||
# warning user spamming default channel
|
# warning user spamming default channel
|
||||||
print(f"{log_timestamp()} System: Warning spamming default channel not allowed. sending DM to {get_name_from_number(message_from_id, 'long', rxNode)}")
|
logger.error(f"System: AntiSpam protection, sending DM to: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
|
|
||||||
# respond to channel message via direct message
|
# respond to channel message via direct message
|
||||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||||
@@ -280,8 +285,8 @@ def onReceive(packet, interface):
|
|||||||
# respond to channel message on the channel itself
|
# respond to channel message on the channel itself
|
||||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, 0, rxNode)
|
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, 0, rxNode)
|
||||||
else:
|
else:
|
||||||
|
# message is not for bot to respond to
|
||||||
# ignore the message but add it to the message history and repeat it if enabled
|
# ignore the message but add it to the message history and repeat it if enabled
|
||||||
# add the message to the message history but limit
|
|
||||||
if zuluTime:
|
if zuluTime:
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
else:
|
else:
|
||||||
@@ -302,47 +307,49 @@ def onReceive(packet, interface):
|
|||||||
# if channel found in the repeater list repeat the message
|
# if channel found in the repeater list repeat the message
|
||||||
if str(channel_number) in repeater_channels:
|
if str(channel_number) in repeater_channels:
|
||||||
if rxNode == 1:
|
if rxNode == 1:
|
||||||
print(f"{log_timestamp()} Repeating message on Device2 Channel:{channel_number}")
|
logger.debug(f"Repeating message on Device2 Channel:{channel_number}")
|
||||||
send_message(rMsg, channel_number, 0, 2)
|
send_message(rMsg, channel_number, 0, 2)
|
||||||
elif rxNode == 2:
|
elif rxNode == 2:
|
||||||
print(f"{log_timestamp()} Repeating message on Device1 Channel:{channel_number}")
|
logger.debug(f"Repeating message on Device1 Channel:{channel_number}")
|
||||||
send_message(rMsg, channel_number, 0, 1)
|
send_message(rMsg, channel_number, 0, 1)
|
||||||
|
msgLogger.info(f"Device:{rxNode} Channel:{channel_number} | {get_name_from_number(message_from_id, 'long', rxNode)} | {message_string}")
|
||||||
else:
|
else:
|
||||||
print(f"{log_timestamp()} System: Ignoring incoming Device:{rxNode} Channel:{channel_number} Message: {message_string} From: {get_name_from_number(message_from_id)}")
|
# nothing to do for us
|
||||||
|
logger.info(f"Device:{rxNode} Channel:{channel_number} " + CustomFormatter.green + "Ignoring Message:" + CustomFormatter.white +\
|
||||||
|
f" {message_string} " + CustomFormatter.purple + "From:" + CustomFormatter.white + f" {get_name_from_number(message_from_id)}")
|
||||||
|
msgLogger.info(f"Device:{rxNode} Channel:{channel_number} | {get_name_from_number(message_from_id, 'long', rxNode)} | {message_string}")
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
print(f"{log_timestamp()} System: Error processing packet: {e} Device:{rxNode}")
|
logger.critical(f"System: Error processing packet: {e} Device:{rxNode}")
|
||||||
print(packet) # print the packet for debugging
|
print(packet) # print the packet for debugging
|
||||||
print("END of packet \n")
|
print("END of packet \n")
|
||||||
|
|
||||||
async def start_rx():
|
async def start_rx():
|
||||||
print ("\nMeshtastic Autoresponder Bot CTL+C to exit\n")
|
print (CustomFormatter.bold_white + f"\nMeshtastic Autoresponder Bot CTL+C to exit\n" + CustomFormatter.reset)
|
||||||
if bbs_enabled:
|
|
||||||
print(f"System: BBS Enabled, {bbsdb} has {len(bbs_messages)} messages. Direct Mail Messages waiting: {(len(bbs_dm) - 1)}")
|
|
||||||
if solar_conditions_enabled:
|
|
||||||
print(f"System: Celestial Telemetry Enabled")
|
|
||||||
if location_enabled:
|
|
||||||
print(f"System: Location Telemetry Enabled")
|
|
||||||
if dad_jokes_enabled:
|
|
||||||
print(f"System: Dad Jokes Enabled!")
|
|
||||||
if store_forward_enabled:
|
|
||||||
print(f"System: Store and Forward Enabled using limit: {storeFlimit}")
|
|
||||||
if useDMForResponse:
|
|
||||||
print(f"System: Respond by DM only")
|
|
||||||
if repeater_enabled and interface2_enabled:
|
|
||||||
print(f"System: Repeater Enabled for Channels: {repeater_channels}")
|
|
||||||
if radio_dectection_enabled:
|
|
||||||
print(f"System: Radio Detection Enabled using rigctld at {rigControlServerAddress} brodcasting to channels: {sigWatchBrodcastCh} for {get_freq_common_name(get_hamlib('f'))}")
|
|
||||||
|
|
||||||
# Start the receive subscriber using pubsub via meshtastic library
|
# Start the receive subscriber using pubsub via meshtastic library
|
||||||
pub.subscribe(onReceive, 'meshtastic.receive')
|
pub.subscribe(onReceive, 'meshtastic.receive')
|
||||||
|
logger.info(f"System: Autoresponder Started for Device1 {get_name_from_number(myNodeNum1, 'long', 1)},"
|
||||||
msg = (f"{log_timestamp()} System: Autoresponder Started for Device1 {get_name_from_number(myNodeNum1, 'long', 1)},"
|
f"{get_name_from_number(myNodeNum1, 'short', 1)}. NodeID: {myNodeNum1}, {decimal_to_hex(myNodeNum1)}")
|
||||||
f"{get_name_from_number(myNodeNum1, 'short', 1)}. NodeID: {myNodeNum1}, {decimal_to_hex(myNodeNum1)}")
|
|
||||||
print (msg)
|
|
||||||
if interface2_enabled:
|
if interface2_enabled:
|
||||||
msg = (f"{log_timestamp()} System: Autoresponder Started for Device2 {get_name_from_number(myNodeNum2, 'long', 2)},"
|
logger.info(f"System: Autoresponder Started for Device2 {get_name_from_number(myNodeNum2, 'long', 2)},"
|
||||||
f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}")
|
f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}")
|
||||||
print (msg)
|
if log_messages_to_file:
|
||||||
|
logger.debug(f"System: Logging Messages to disk")
|
||||||
|
if bbs_enabled:
|
||||||
|
logger.debug(f"System: BBS Enabled, {bbsdb} has {len(bbs_messages)} messages. Direct Mail Messages waiting: {(len(bbs_dm) - 1)}")
|
||||||
|
if solar_conditions_enabled:
|
||||||
|
logger.debug(f"System: Celestial Telemetry Enabled")
|
||||||
|
if location_enabled:
|
||||||
|
logger.debug(f"System: Location Telemetry Enabled")
|
||||||
|
if dad_jokes_enabled:
|
||||||
|
logger.debug(f"System: Dad Jokes Enabled!")
|
||||||
|
if store_forward_enabled:
|
||||||
|
logger.debug(f"System: Store and Forward Enabled using limit: {storeFlimit}")
|
||||||
|
if useDMForResponse:
|
||||||
|
logger.debug(f"System: Respond by DM only")
|
||||||
|
if repeater_enabled and interface2_enabled:
|
||||||
|
logger.debug(f"System: Repeater Enabled for Channels: {repeater_channels}")
|
||||||
|
if radio_dectection_enabled:
|
||||||
|
logger.debug(f"System: Radio Detection Enabled using rigctld at {rigControlServerAddress} brodcasting to channels: {sigWatchBrodcastCh} for {get_freq_common_name(get_hamlib('f'))}")
|
||||||
|
|
||||||
# here we go loopty loo
|
# here we go loopty loo
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
+9
-9
@@ -2,7 +2,7 @@
|
|||||||
# K7MHI Kelly Keeton 2024
|
# K7MHI Kelly Keeton 2024
|
||||||
|
|
||||||
import pickle # pip install pickle
|
import pickle # pip install pickle
|
||||||
from modules.settings import *
|
from modules.log import *
|
||||||
|
|
||||||
trap_list_bbs = ("bbslist", "bbspost", "bbsread", "bbsdelete", "bbshelp")
|
trap_list_bbs = ("bbslist", "bbspost", "bbsread", "bbsdelete", "bbshelp")
|
||||||
|
|
||||||
@@ -18,14 +18,14 @@ def load_bbsdb():
|
|||||||
bbs_messages = pickle.load(f)
|
bbs_messages = pickle.load(f)
|
||||||
except:
|
except:
|
||||||
bbs_messages = [[1, "Welcome to meshBBS", "Welcome to the BBS, please post a message!",0]]
|
bbs_messages = [[1, "Welcome to meshBBS", "Welcome to the BBS, please post a message!",0]]
|
||||||
print ("\nSystem: Creating new bbsdb.pkl")
|
logger.debug("\nSystem: Creating new bbsdb.pkl")
|
||||||
with open('bbsdb.pkl', 'wb') as f:
|
with open('bbsdb.pkl', 'wb') as f:
|
||||||
pickle.dump(bbs_messages, f)
|
pickle.dump(bbs_messages, f)
|
||||||
|
|
||||||
def save_bbsdb():
|
def save_bbsdb():
|
||||||
global bbs_messages
|
global bbs_messages
|
||||||
# save the bbs messages to the database file
|
# save the bbs messages to the database file
|
||||||
print ("System: Saving bbsdb.pkl\n")
|
logger.debug("System: Saving bbsdb.pkl\n")
|
||||||
with open('bbsdb.pkl', 'wb') as f:
|
with open('bbsdb.pkl', 'wb') as f:
|
||||||
pickle.dump(bbs_messages, f)
|
pickle.dump(bbs_messages, f)
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ def bbs_delete_message(messageID = 0, fromNode = 0):
|
|||||||
|
|
||||||
return "Msg #" + str(messageID) + " deleted."
|
return "Msg #" + str(messageID) + " deleted."
|
||||||
else:
|
else:
|
||||||
print (f"!!System: node {fromNode}, tried to delete a message: {bbs_messages[messageID - 1]} and was dropped.")
|
logger.warning(f"System: node {fromNode}, tried to delete a message: {bbs_messages[messageID - 1]} and was dropped.")
|
||||||
return "You are not authorized to delete this message."
|
return "You are not authorized to delete this message."
|
||||||
else:
|
else:
|
||||||
return "Please specify a message number to delete."
|
return "Please specify a message number to delete."
|
||||||
@@ -75,12 +75,12 @@ def bbs_post_message(subject, message, fromNode):
|
|||||||
|
|
||||||
# Check the BAN list for naughty nodes and silently drop the message
|
# Check the BAN list for naughty nodes and silently drop the message
|
||||||
if str(fromNode) in bbs_ban_list:
|
if str(fromNode) in bbs_ban_list:
|
||||||
print (f"!!System: Naughty node {fromNode}, tried to post a message: {subject}, {message} and was dropped.")
|
logger.warning(f"System: Naughty node {fromNode}, tried to post a message: {subject}, {message} and was dropped.")
|
||||||
return "Message posted. ID is: " + str(messageID)
|
return "Message posted. ID is: " + str(messageID)
|
||||||
|
|
||||||
# append the message to the list
|
# append the message to the list
|
||||||
bbs_messages.append([messageID, subject, message, fromNode])
|
bbs_messages.append([messageID, subject, message, fromNode])
|
||||||
print (f"System: NEW Message Posted, subject: {subject}, message: {message} from {fromNode}")
|
logger.info(f"System: NEW Message Posted, subject: {subject}, message: {message} from {fromNode}")
|
||||||
|
|
||||||
# save the bbsdb
|
# save the bbsdb
|
||||||
save_bbsdb()
|
save_bbsdb()
|
||||||
@@ -100,7 +100,7 @@ def bbs_read_message(messageID = 0):
|
|||||||
def save_bbsdm():
|
def save_bbsdm():
|
||||||
global bbs_dm
|
global bbs_dm
|
||||||
# save the bbs messages to the database file
|
# save the bbs messages to the database file
|
||||||
print ("System: Saving Updated BBS Direct Messages bbsdm.pkl")
|
logger.debug("System: Saving Updated BBS Direct Messages bbsdm.pkl")
|
||||||
with open('bbsdm.pkl', 'wb') as f:
|
with open('bbsdm.pkl', 'wb') as f:
|
||||||
pickle.dump(bbs_dm, f)
|
pickle.dump(bbs_dm, f)
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ def load_bbsdm():
|
|||||||
bbs_dm = pickle.load(f)
|
bbs_dm = pickle.load(f)
|
||||||
except:
|
except:
|
||||||
bbs_dm = [[1234567890, "Message", 1234567890]]
|
bbs_dm = [[1234567890, "Message", 1234567890]]
|
||||||
print ("\nSystem: Creating new bbsdm.pkl")
|
logger.debug("\nSystem: Creating new bbsdm.pkl")
|
||||||
with open('bbsdm.pkl', 'wb') as f:
|
with open('bbsdm.pkl', 'wb') as f:
|
||||||
pickle.dump(bbs_dm, f)
|
pickle.dump(bbs_dm, f)
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ def bbs_post_dm(toNode, message, fromNode):
|
|||||||
global bbs_dm
|
global bbs_dm
|
||||||
# Check the BAN list for naughty nodes and silently drop the message
|
# Check the BAN list for naughty nodes and silently drop the message
|
||||||
if str(fromNode) in bbs_ban_list:
|
if str(fromNode) in bbs_ban_list:
|
||||||
print (f"!!System: Naughty node {fromNode}, tried to post a message: {message} and was dropped.")
|
logger.warning(f"System: Naughty node {fromNode}, tried to post a message: {message} and was dropped.")
|
||||||
return "DM Posted for node " + str(toNode)
|
return "DM Posted for node " + str(toNode)
|
||||||
|
|
||||||
# append the message to the list
|
# append the message to the list
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
from modules.settings import *
|
||||||
|
|
||||||
|
class CustomFormatter(logging.Formatter):
|
||||||
|
grey = '\x1b[38;21m'
|
||||||
|
white = '\x1b[38;5;231m'
|
||||||
|
blue = '\x1b[38;5;39m'
|
||||||
|
yellow = '\x1b[38;5;226m'
|
||||||
|
red = '\x1b[38;5;196m'
|
||||||
|
green = '\x1b[38;5;46m'
|
||||||
|
purple = '\x1b[38;5;129m'
|
||||||
|
bold_red = '\x1b[31;1m'
|
||||||
|
bold_white = '\x1b[37;1m'
|
||||||
|
reset = '\x1b[0m'
|
||||||
|
|
||||||
|
def __init__(self, fmt):
|
||||||
|
super().__init__()
|
||||||
|
self.fmt = fmt
|
||||||
|
self.FORMATS = {
|
||||||
|
logging.DEBUG: self.blue + self.fmt + self.reset,
|
||||||
|
logging.INFO: self.white + self.fmt + self.reset,
|
||||||
|
logging.WARNING: self.yellow + self.fmt + self.reset,
|
||||||
|
logging.ERROR: self.red + self.fmt + self.reset,
|
||||||
|
logging.CRITICAL: self.bold_red + self.fmt + self.reset
|
||||||
|
}
|
||||||
|
|
||||||
|
def format(self, record):
|
||||||
|
log_fmt = self.FORMATS.get(record.levelno)
|
||||||
|
formatter = logging.Formatter(log_fmt)
|
||||||
|
return formatter.format(record)
|
||||||
|
|
||||||
|
# Create logger
|
||||||
|
logger = logging.getLogger("MeshBot System Logger")
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
logger.propagate = False
|
||||||
|
|
||||||
|
msgLogger = logging.getLogger("MeshBot Messages Logger")
|
||||||
|
msgLogger.setLevel(logging.INFO)
|
||||||
|
msgLogger.propagate = False
|
||||||
|
|
||||||
|
# Define format for logs
|
||||||
|
logFormat = '%(asctime)s | %(levelname)8s | %(message)s'
|
||||||
|
msgLogFormat = '%(asctime)s | %(message)s'
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
# Set format for stdout handler
|
||||||
|
stdout_handler.setFormatter(CustomFormatter(logFormat))
|
||||||
|
|
||||||
|
# Create file handler for logging to a file
|
||||||
|
today = datetime.now()
|
||||||
|
file_handler = logging.FileHandler('messages{}.log'.format(today.strftime('%Y_%m_%d')))
|
||||||
|
file_handler.setLevel(logging.INFO)
|
||||||
|
file_handler.setFormatter(logging.Formatter(msgLogFormat))
|
||||||
|
|
||||||
|
# Add handlers to the logger
|
||||||
|
logger.addHandler(stdout_handler)
|
||||||
|
if log_messages_to_file:
|
||||||
|
msgLogger.addHandler(file_handler)
|
||||||
+1
-1
@@ -72,6 +72,7 @@ try:
|
|||||||
bbsdb = config['bbs'].get('bbsdb', 'bbsdb.pkl')
|
bbsdb = config['bbs'].get('bbsdb', 'bbsdb.pkl')
|
||||||
dad_jokes_enabled = config['general'].getboolean('DadJokes', False)
|
dad_jokes_enabled = config['general'].getboolean('DadJokes', False)
|
||||||
store_forward_enabled = config['general'].getboolean('StoreForward', False)
|
store_forward_enabled = config['general'].getboolean('StoreForward', False)
|
||||||
|
log_messages_to_file = config['general'].getboolean('LogMessagesToFile', True) # default True
|
||||||
config['general'].get('motd', MOTD)
|
config['general'].get('motd', MOTD)
|
||||||
urlTimeoutSeconds = config['general'].getint('URL_TIMEOUT', 10) # default 10 seconds
|
urlTimeoutSeconds = config['general'].getint('URL_TIMEOUT', 10) # default 10 seconds
|
||||||
forecastDuration = config['general'].getint('DAYS_OF_WEATHER', 4) # default days of weather
|
forecastDuration = config['general'].getint('DAYS_OF_WEATHER', 4) # default days of weather
|
||||||
@@ -92,4 +93,3 @@ except KeyError as e:
|
|||||||
print(f"System: Check the config.ini against config.template file for missing sections or values.")
|
print(f"System: Check the config.ini against config.template file for missing sections or values.")
|
||||||
print(f"System: Exiting...")
|
print(f"System: Exiting...")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|||||||
+72
-59
@@ -4,10 +4,9 @@
|
|||||||
import meshtastic.serial_interface #pip install meshtastic
|
import meshtastic.serial_interface #pip install meshtastic
|
||||||
import meshtastic.tcp_interface
|
import meshtastic.tcp_interface
|
||||||
import meshtastic.ble_interface
|
import meshtastic.ble_interface
|
||||||
from datetime import datetime
|
|
||||||
import time
|
import time
|
||||||
import asyncio
|
import asyncio
|
||||||
from modules.settings import *
|
from modules.log import *
|
||||||
|
|
||||||
# Global Variables
|
# Global Variables
|
||||||
trap_list = ("cmd","cmd?") # default trap list
|
trap_list = ("cmd","cmd?") # default trap list
|
||||||
@@ -68,10 +67,10 @@ try:
|
|||||||
elif interface1_type == 'ble':
|
elif interface1_type == 'ble':
|
||||||
interface1 = meshtastic.ble_interface.BLEInterface(mac1)
|
interface1 = meshtastic.ble_interface.BLEInterface(mac1)
|
||||||
else:
|
else:
|
||||||
print(f"System: Interface Type: {interface1_type} not supported. Validate your config against config.template Exiting")
|
logger.critical(f"System: Interface Type: {interface1_type} not supported. Validate your config against config.template Exiting")
|
||||||
exit()
|
exit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"System: Critical Error script abort. Initalizing Interface1 {e}")
|
logger.critical(f"System: script abort. Initalizing Interface1 {e}")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
# Interface2 Configuration
|
# Interface2 Configuration
|
||||||
@@ -84,10 +83,10 @@ if interface2_enabled:
|
|||||||
elif interface2_type == 'ble':
|
elif interface2_type == 'ble':
|
||||||
interface2 = meshtastic.ble_interface.BLEInterface(mac2)
|
interface2 = meshtastic.ble_interface.BLEInterface(mac2)
|
||||||
else:
|
else:
|
||||||
print(f"System: Interface Type: {interface2_type} not supported. Validate your config against config.template Exiting")
|
logger.critical(f"System: Interface Type: {interface2_type} not supported. Validate your config against config.template Exiting")
|
||||||
exit()
|
exit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"System: Critical Error script abort. Initalizing Interface2 {e}")
|
logger.critical(f"System: script abort. Initalizing Interface2 {e}")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
#Get the node number of the device, check if the device is connected
|
#Get the node number of the device, check if the device is connected
|
||||||
@@ -95,7 +94,7 @@ try:
|
|||||||
myinfo = interface1.getMyNodeInfo()
|
myinfo = interface1.getMyNodeInfo()
|
||||||
myNodeNum1 = myinfo['num']
|
myNodeNum1 = myinfo['num']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"System: Critical Error script abort. {e}")
|
logger.critical(f"System: script abort. {e}")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
if interface2_enabled:
|
if interface2_enabled:
|
||||||
@@ -103,17 +102,11 @@ if interface2_enabled:
|
|||||||
myinfo2 = interface2.getMyNodeInfo()
|
myinfo2 = interface2.getMyNodeInfo()
|
||||||
myNodeNum2 = myinfo2['num']
|
myNodeNum2 = myinfo2['num']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"System: Critical Error script abort. {e}")
|
logger.critical(f"System: script abort. {e}")
|
||||||
exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
myNodeNum2 = 777
|
myNodeNum2 = 777
|
||||||
|
|
||||||
def log_timestamp():
|
|
||||||
if zuluTime:
|
|
||||||
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
else:
|
|
||||||
return datetime.now().strftime("%Y-%m-%d %I:%M:%S%p")
|
|
||||||
|
|
||||||
def decimal_to_hex(decimal_number):
|
def decimal_to_hex(decimal_number):
|
||||||
return f"!{decimal_number:08x}"
|
return f"!{decimal_number:08x}"
|
||||||
|
|
||||||
@@ -171,7 +164,7 @@ def get_node_list(nodeInt=1):
|
|||||||
item = (node_name, last_heard, snr)
|
item = (node_name, last_heard, snr)
|
||||||
node_list1.append(item)
|
node_list1.append(item)
|
||||||
else:
|
else:
|
||||||
print (f"{log_timestamp()} System: No nodes found")
|
logger.warning(f"System: No nodes found")
|
||||||
return ERROR_FETCHING_DATA
|
return ERROR_FETCHING_DATA
|
||||||
|
|
||||||
if nodeInt == 2:
|
if nodeInt == 2:
|
||||||
@@ -189,12 +182,18 @@ def get_node_list(nodeInt=1):
|
|||||||
item = (node_name, last_heard, snr)
|
item = (node_name, last_heard, snr)
|
||||||
node_list2.append(item)
|
node_list2.append(item)
|
||||||
else:
|
else:
|
||||||
print (f"{log_timestamp()} System: No nodes found")
|
logger.warning(f"System: No nodes found")
|
||||||
return ERROR_FETCHING_DATA
|
return ERROR_FETCHING_DATA
|
||||||
|
|
||||||
node_list1.sort(key=lambda x: x[1], reverse=True)
|
try:
|
||||||
#print (f"Node List: {node_list1[:5]}\n")
|
#print (f"Node List: {node_list1[:5]}\n")
|
||||||
node_list2.sort(key=lambda x: x[1], reverse=True)
|
node_list1.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
#print (f"Node List: {node_list1[:5]}\n")
|
||||||
|
node_list2.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"System: Error sorting node list: {e}")
|
||||||
|
print (f"Node List1: {node_list1[:5]}\n")
|
||||||
|
print (f"Node List2: {node_list2[:5]}\n")
|
||||||
|
|
||||||
# make a nice list for the user
|
# make a nice list for the user
|
||||||
for x in node_list1[:SITREP_NODE_COUNT]:
|
for x in node_list1[:SITREP_NODE_COUNT]:
|
||||||
@@ -208,7 +207,7 @@ def get_node_list(nodeInt=1):
|
|||||||
|
|
||||||
return node_list
|
return node_list
|
||||||
|
|
||||||
def get_node_location(number, nodeInt=1):
|
def get_node_location(number, nodeInt=1, channel=0):
|
||||||
# Get the location of a node by its number from nodeDB on device
|
# Get the location of a node by its number from nodeDB on device
|
||||||
latitude = latitudeValue
|
latitude = latitudeValue
|
||||||
longitude = longitudeValue
|
longitude = longitudeValue
|
||||||
@@ -222,15 +221,26 @@ def get_node_location(number, nodeInt=1):
|
|||||||
latitude = node['position']['latitude']
|
latitude = node['position']['latitude']
|
||||||
longitude = node['position']['longitude']
|
longitude = node['position']['longitude']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print (f"{log_timestamp()} System: Error getting location data for {number}")
|
logger.error(f"System: Error getting location data for {number}")
|
||||||
print (f"System: location data for {number} is {latitude},{longitude}")
|
logger.debug(f"System: location data for {number} is {latitude},{longitude}")
|
||||||
position = [latitude,longitude]
|
position = [latitude,longitude]
|
||||||
return position
|
return position
|
||||||
else:
|
else:
|
||||||
print (f"{log_timestamp()} System: No location data for {number}")
|
logger.warning(f"System: No location data for {number} using default location")
|
||||||
|
|
||||||
|
# request location data
|
||||||
|
try:
|
||||||
|
logger.debug(f"System: Requesting location data for {number}")
|
||||||
|
if nodeInt == 1:
|
||||||
|
interface1.sendPosition(destinationId=number, wantResponse=False, channelIndex=channel)
|
||||||
|
if nodeInt == 2:
|
||||||
|
interface2.sendPosition(destinationId=number, wantResponse=False, channelIndex=channel)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"System: Error requesting location data for {number}. Error: {e}")
|
||||||
|
|
||||||
return position
|
return position
|
||||||
else:
|
else:
|
||||||
print (f"{log_timestamp()} System: No nodes found")
|
logger.warning(f"System: No nodes found")
|
||||||
return position
|
return position
|
||||||
if nodeInt == 2:
|
if nodeInt == 2:
|
||||||
if interface2.nodes:
|
if interface2.nodes:
|
||||||
@@ -241,21 +251,23 @@ def get_node_location(number, nodeInt=1):
|
|||||||
latitude = node['position']['latitude']
|
latitude = node['position']['latitude']
|
||||||
longitude = node['position']['longitude']
|
longitude = node['position']['longitude']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print (f"{log_timestamp()} System: Error getting location data for {number}")
|
logger.error(f"System: Error getting location data for {number}")
|
||||||
print (f"System: location data for {number} is {latitude},{longitude}")
|
logger.info(f"System: location data for {number} is {latitude},{longitude}")
|
||||||
position = [latitude,longitude]
|
position = [latitude,longitude]
|
||||||
return position
|
return position
|
||||||
else:
|
else:
|
||||||
print (f"{log_timestamp()} System: No location data for {number}")
|
logger.warning(f"System: No location data for {number}")
|
||||||
return position
|
return position
|
||||||
else:
|
else:
|
||||||
print (f"{log_timestamp()} System: No nodes found")
|
logger.warning(f"System: No nodes found")
|
||||||
return position
|
return position
|
||||||
|
|
||||||
def send_message(message, ch, nodeid=0, nodeInt=1):
|
def send_message(message, ch, nodeid=0, nodeInt=1):
|
||||||
|
if message == "":
|
||||||
|
return
|
||||||
# if message over MESSAGE_CHUNK_SIZE characters, split it into multiple messages
|
# if message over MESSAGE_CHUNK_SIZE characters, split it into multiple messages
|
||||||
if len(message) > MESSAGE_CHUNK_SIZE:
|
if len(message) > MESSAGE_CHUNK_SIZE:
|
||||||
print (f"{log_timestamp()} System: Splitting Message, Message Length: {len(message)}")
|
logger.debug(f"System: Splitting Message, Message Length: {len(message)}")
|
||||||
|
|
||||||
# split the message into MESSAGE_CHUNK_SIZE 160 character chunks
|
# split the message into MESSAGE_CHUNK_SIZE 160 character chunks
|
||||||
message = message.replace('\n', ' NEWLINE ') # replace newlines with NEWLINE to keep them in split chunks
|
message = message.replace('\n', ' NEWLINE ') # replace newlines with NEWLINE to keep them in split chunks
|
||||||
@@ -281,14 +293,15 @@ def send_message(message, ch, nodeid=0, nodeInt=1):
|
|||||||
for m in message_list:
|
for m in message_list:
|
||||||
if nodeid == 0:
|
if nodeid == 0:
|
||||||
#Send to channel
|
#Send to channel
|
||||||
print (f"{log_timestamp()} System: Sending Device:{nodeInt} Channel:{ch} Multi-Chunk Message: {m}")
|
logger.info(f"Device:{nodeInt} Channel:{ch} " + CustomFormatter.red + "Sending Multi-Chunk Message: " + CustomFormatter.white + f"{m}")
|
||||||
if nodeInt == 1:
|
if nodeInt == 1:
|
||||||
interface1.sendText(text=m, channelIndex=ch)
|
interface1.sendText(text=m, channelIndex=ch)
|
||||||
if nodeInt == 2:
|
if nodeInt == 2:
|
||||||
interface2.sendText(text=m, channelIndex=ch)
|
interface2.sendText(text=m, channelIndex=ch)
|
||||||
else:
|
else:
|
||||||
# Send to DM
|
# Send to DM
|
||||||
print (f"{log_timestamp()} System: Sending DM Device:{nodeInt} Multi-Chunk Message: {m} To: {get_name_from_number(nodeid, 'long', nodeInt)}")
|
logger.info(f"Device:{nodeInt} " + CustomFormatter.red + "Sending Multi-Chunk DM: " + CustomFormatter.white + f"{m}" + CustomFormatter.purple +\
|
||||||
|
" To: " + CustomFormatter.white + f"{get_name_from_number(nodeid, 'long', nodeInt)}")
|
||||||
if nodeInt == 1:
|
if nodeInt == 1:
|
||||||
interface1.sendText(text=m, channelIndex=ch, destinationId=nodeid)
|
interface1.sendText(text=m, channelIndex=ch, destinationId=nodeid)
|
||||||
if nodeInt == 2:
|
if nodeInt == 2:
|
||||||
@@ -296,14 +309,15 @@ def send_message(message, ch, nodeid=0, nodeInt=1):
|
|||||||
else: # message is less than MESSAGE_CHUNK_SIZE characters
|
else: # message is less than MESSAGE_CHUNK_SIZE characters
|
||||||
if nodeid == 0:
|
if nodeid == 0:
|
||||||
# Send to channel
|
# Send to channel
|
||||||
print (f"{log_timestamp()} System: Sending Device:{nodeInt} Channel:{ch} Message: {message}")
|
logger.info(f"Device:{nodeInt} Channel:{ch} " + CustomFormatter.red + "Sending: " + CustomFormatter.white + f"{message}")
|
||||||
if nodeInt == 1:
|
if nodeInt == 1:
|
||||||
interface1.sendText(text=message, channelIndex=ch)
|
interface1.sendText(text=message, channelIndex=ch)
|
||||||
if nodeInt == 2:
|
if nodeInt == 2:
|
||||||
interface2.sendText(text=message, channelIndex=ch)
|
interface2.sendText(text=message, channelIndex=ch)
|
||||||
else:
|
else:
|
||||||
# Send to DM
|
# Send to DM
|
||||||
print (f"{log_timestamp()} System: Sending DM Device:{nodeInt} {message} To: {get_name_from_number(nodeid, 'long', nodeInt)}")
|
logger.info(f"Device:{nodeInt} " + CustomFormatter.red + "Sending DM: " + CustomFormatter.white + f"{message}" + CustomFormatter.purple +\
|
||||||
|
" To: " + CustomFormatter.white + f"{get_name_from_number(nodeid, 'long', nodeInt)}")
|
||||||
if nodeInt == 1:
|
if nodeInt == 1:
|
||||||
interface1.sendText(text=message, channelIndex=ch, destinationId=nodeid)
|
interface1.sendText(text=message, channelIndex=ch, destinationId=nodeid)
|
||||||
if nodeInt == 2:
|
if nodeInt == 2:
|
||||||
@@ -337,32 +351,31 @@ def messageTrap(msg):
|
|||||||
|
|
||||||
def exit_handler():
|
def exit_handler():
|
||||||
# Close the interface and save the BBS messages
|
# Close the interface and save the BBS messages
|
||||||
print(f"\n{log_timestamp()} System: Closing Autoresponder\n")
|
logger.debug(f"\nSystem: Closing Autoresponder\n")
|
||||||
try:
|
try:
|
||||||
interface1.close()
|
interface1.close()
|
||||||
print(f"{log_timestamp()} System: Interface1 Closed")
|
logger.debug(f"System: Interface1 Closed")
|
||||||
if interface2_enabled:
|
if interface2_enabled:
|
||||||
interface2.close()
|
interface2.close()
|
||||||
print(f"{log_timestamp()} System: Interface2 Closed")
|
logger.debug(f"System: Interface2 Closed")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error closing: {e}")
|
logger.error(f"System: closing: {e}")
|
||||||
if bbs_enabled:
|
if bbs_enabled:
|
||||||
save_bbsdb()
|
save_bbsdb()
|
||||||
save_bbsdm()
|
save_bbsdm()
|
||||||
print(f"{log_timestamp()} System: BBS Messages Saved")
|
logger.debug(f"System: BBS Messages Saved")
|
||||||
print(f"{log_timestamp()} System: Exiting")
|
logger.debug(f"System: Exiting")
|
||||||
asyncLoop.stop()
|
asyncLoop.stop()
|
||||||
asyncLoop.close()
|
asyncLoop.close()
|
||||||
exit (0)
|
exit (0)
|
||||||
|
|
||||||
|
|
||||||
async def handleSignalWatcher():
|
async def handleSignalWatcher():
|
||||||
global lastHamLibAlert, antiSpam, sigWatchBrodcastCh
|
global lastHamLibAlert, antiSpam, sigWatchBrodcastCh
|
||||||
# monitor rigctld for signal strength and frequency
|
# monitor rigctld for signal strength and frequency
|
||||||
while True:
|
while True:
|
||||||
msg = await signalWatcher()
|
msg = await signalWatcher()
|
||||||
if msg != ERROR_FETCHING_DATA and msg is not None:
|
if msg != ERROR_FETCHING_DATA and msg is not None:
|
||||||
print(f"{log_timestamp()} System: Detected Alert from Hamlib {msg}")
|
logger.debug(f"System: Detected Alert from Hamlib {msg}")
|
||||||
|
|
||||||
# check we are not spammig the channel limit messages to once per minute
|
# check we are not spammig the channel limit messages to once per minute
|
||||||
if time.time() - lastHamLibAlert > 60:
|
if time.time() - lastHamLibAlert > 60:
|
||||||
@@ -375,14 +388,14 @@ async def handleSignalWatcher():
|
|||||||
if interface2_enabled:
|
if interface2_enabled:
|
||||||
send_message(msg, int(ch), 0, 2)
|
send_message(msg, int(ch), 0, 2)
|
||||||
else:
|
else:
|
||||||
print(f"{log_timestamp()} System: antiSpam prevented Alert from Hamlib {msg}")
|
logger.error(f"System: antiSpam prevented Alert from Hamlib {msg}")
|
||||||
else:
|
else:
|
||||||
if antiSpam and sigWatchBrodcastCh != publicChannel:
|
if antiSpam and sigWatchBrodcastCh != publicChannel:
|
||||||
send_message(msg, int(sigWatchBrodcastCh), 0, 1)
|
send_message(msg, int(sigWatchBrodcastCh), 0, 1)
|
||||||
if interface2_enabled:
|
if interface2_enabled:
|
||||||
send_message(msg, int(sigWatchBrodcastCh), 0, 2)
|
send_message(msg, int(sigWatchBrodcastCh), 0, 2)
|
||||||
else:
|
else:
|
||||||
print(f"{log_timestamp()} System: antiSpam prevented Alert from Hamlib {msg}")
|
logger.error(f"System: antiSpam prevented Alert from Hamlib {msg}")
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
pass
|
pass
|
||||||
@@ -398,7 +411,7 @@ async def retry_interface(nodeID=1):
|
|||||||
try:
|
try:
|
||||||
interface1.close()
|
interface1.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error closing interface1: {e}")
|
logger.error(f"System: closing interface1: {e}")
|
||||||
if nodeID==2:
|
if nodeID==2:
|
||||||
if interface2 is not None:
|
if interface2 is not None:
|
||||||
retry_int2 = True
|
retry_int2 = True
|
||||||
@@ -406,15 +419,15 @@ async def retry_interface(nodeID=1):
|
|||||||
try:
|
try:
|
||||||
interface2.close()
|
interface2.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error closing interface2: {e}")
|
logger.error(f"System: closing interface2: {e}")
|
||||||
|
|
||||||
|
|
||||||
print(f"{log_timestamp()} System: Retrying interface in 15 seconds")
|
logger.debug(f"System: Retrying interface in 15 seconds")
|
||||||
if max_retry_count1 == 0:
|
if max_retry_count1 == 0:
|
||||||
print(f"{log_timestamp()} System: Max retry count reached for interface1")
|
logger.critical(f"System: Max retry count reached for interface1")
|
||||||
exit_handler()
|
exit_handler()
|
||||||
if max_retry_count2 == 0:
|
if max_retry_count2 == 0:
|
||||||
print(f"{log_timestamp()} System: Max retry count reached for interface2")
|
logger.critical(f"System: Max retry count reached for interface2")
|
||||||
exit_handler()
|
exit_handler()
|
||||||
# wait 15 seconds before retrying
|
# wait 15 seconds before retrying
|
||||||
await asyncio.sleep(15)
|
await asyncio.sleep(15)
|
||||||
@@ -423,32 +436,32 @@ async def retry_interface(nodeID=1):
|
|||||||
try:
|
try:
|
||||||
if nodeID==1 and retry_int1:
|
if nodeID==1 and retry_int1:
|
||||||
interface1 = None
|
interface1 = None
|
||||||
print(f"{log_timestamp()} System: Retrying Interface1")
|
logger.debug(f"System: Retrying Interface1")
|
||||||
if interface1_type == 'serial':
|
if interface1_type == 'serial':
|
||||||
interface1 = meshtastic.serial_interface.SerialInterface(port1)
|
interface1 = meshtastic.serial_interface.SerialInterface(port1)
|
||||||
elif interface1_type == 'tcp':
|
elif interface1_type == 'tcp':
|
||||||
interface1 = meshtastic.tcp_interface.TCPInterface(hostname1)
|
interface1 = meshtastic.tcp_interface.TCPInterface(hostname1)
|
||||||
elif interface1_type == 'ble':
|
elif interface1_type == 'ble':
|
||||||
interface1 = meshtastic.ble_interface.BLEInterface(mac1)
|
interface1 = meshtastic.ble_interface.BLEInterface(mac1)
|
||||||
print(f"{log_timestamp()} System: Interface1 Opened!")
|
logger.debug(f"System: Interface1 Opened!")
|
||||||
retry_int1 = False
|
retry_int1 = False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error opening interface1 on: {e}")
|
logger.error(f"System: opening interface1 on: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if nodeID==2 and retry_int2:
|
if nodeID==2 and retry_int2:
|
||||||
interface2 = None
|
interface2 = None
|
||||||
print(f"{log_timestamp()} System: Retrying Interface2")
|
logger.debug(f"System: Retrying Interface2")
|
||||||
if interface2_type == 'serial':
|
if interface2_type == 'serial':
|
||||||
interface2 = meshtastic.serial_interface.SerialInterface(port2)
|
interface2 = meshtastic.serial_interface.SerialInterface(port2)
|
||||||
elif interface2_type == 'tcp':
|
elif interface2_type == 'tcp':
|
||||||
interface2 = meshtastic.tcp_interface.TCPInterface(hostname2)
|
interface2 = meshtastic.tcp_interface.TCPInterface(hostname2)
|
||||||
elif interface2_type == 'ble':
|
elif interface2_type == 'ble':
|
||||||
interface2 = meshtastic.ble_interface.BLEInterface(mac2)
|
interface2 = meshtastic.ble_interface.BLEInterface(mac2)
|
||||||
print(f"{log_timestamp()} System: Interface2 Opened!")
|
logger.debug(f"System: Interface2 Opened!")
|
||||||
retry_int2 = False
|
retry_int2 = False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error opening interface2: {e}")
|
logger.error(f"System: opening interface2: {e}")
|
||||||
|
|
||||||
# this is a workaround because .localNode.getMetadata spits out a lot of debug info which cant be suppressed
|
# this is a workaround because .localNode.getMetadata spits out a lot of debug info which cant be suppressed
|
||||||
|
|
||||||
@@ -471,21 +484,21 @@ async def watchdog():
|
|||||||
# watchdog for connection to the interface
|
# watchdog for connection to the interface
|
||||||
while True:
|
while True:
|
||||||
await asyncio.sleep(20)
|
await asyncio.sleep(20)
|
||||||
#print(f"{log_timestamp()} System: watchdog running\r", end="")
|
#print(f"MeshBot System: watchdog running\r", end="")
|
||||||
if interface1 is not None and not retry_int1:
|
if interface1 is not None and not retry_int1:
|
||||||
try:
|
try:
|
||||||
with suppress_stdout():
|
with suppress_stdout():
|
||||||
interface1.localNode.getMetadata()
|
interface1.localNode.getMetadata()
|
||||||
#if "device_state_version:" not in meta:
|
#if "device_state_version:" not in meta:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error communicating with interface1, trying to reconnect: {e}")
|
logger.error(f"System: communicating with interface1, trying to reconnect: {e}")
|
||||||
retry_int1 = True
|
retry_int1 = True
|
||||||
|
|
||||||
if retry_int1:
|
if retry_int1:
|
||||||
try:
|
try:
|
||||||
await retry_interface(1)
|
await retry_interface(1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error retrying interface1: {e}")
|
logger.error(f"System: retrying interface1: {e}")
|
||||||
|
|
||||||
if interface2_enabled:
|
if interface2_enabled:
|
||||||
if interface2 is not None and not retry_int2:
|
if interface2 is not None and not retry_int2:
|
||||||
@@ -493,12 +506,12 @@ async def watchdog():
|
|||||||
with suppress_stdout():
|
with suppress_stdout():
|
||||||
interface2.localNode.getMetadata()
|
interface2.localNode.getMetadata()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error communicating with interface2, trying to reconnect: {e}")
|
logger.error(f"System: communicating with interface2, trying to reconnect: {e}")
|
||||||
retry_int2 = True
|
retry_int2 = True
|
||||||
|
|
||||||
if retry_int2:
|
if retry_int2:
|
||||||
try:
|
try:
|
||||||
await retry_interface(2)
|
await retry_interface(2)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{log_timestamp()} System: Error retrying interface2: {e}")
|
logger.error(f"System: retrying interface2: {e}")
|
||||||
|
|
||||||
|
|||||||
+43
-26
@@ -5,7 +5,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import time # for sleep, get some when you can :)
|
import time # for sleep, get some when you can :)
|
||||||
from pubsub import pub # pip install pubsub
|
from pubsub import pub # pip install pubsub
|
||||||
from modules.settings import *
|
from modules.log import *
|
||||||
from modules.system import *
|
from modules.system import *
|
||||||
|
|
||||||
def auto_response(message, snr, rssi, hop, message_from_id, channel_number, deviceID):
|
def auto_response(message, snr, rssi, hop, message_from_id, channel_number, deviceID):
|
||||||
@@ -22,11 +22,6 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
|
|||||||
bot_response = "🏓PONG, " + f"SNR:{snr} RSSI:{rssi}"
|
bot_response = "🏓PONG, " + f"SNR:{snr} RSSI:{rssi}"
|
||||||
else:
|
else:
|
||||||
bot_response = "🏓PONG, " + hop
|
bot_response = "🏓PONG, " + hop
|
||||||
elif "ack" in message.lower():
|
|
||||||
if hop == "Direct":
|
|
||||||
bot_response = "🏓ACK-ACK! " + f"SNR:{snr} RSSI:{rssi}"
|
|
||||||
else:
|
|
||||||
bot_response = "🏓ACK-ACK! " + hop
|
|
||||||
elif "pong" in message.lower():
|
elif "pong" in message.lower():
|
||||||
bot_response = "🏓Ping!!"
|
bot_response = "🏓Ping!!"
|
||||||
elif "motd" in message.lower():
|
elif "motd" in message.lower():
|
||||||
@@ -48,8 +43,16 @@ def auto_response(message, snr, rssi, hop, message_from_id, channel_number, devi
|
|||||||
bot_response += "Port2:\n" + str(get_node_list(2))
|
bot_response += "Port2:\n" + str(get_node_list(2))
|
||||||
chutil2 = interface2.nodes.get(decimal_to_hex(myNodeNum2), {}).get("deviceMetrics", {}).get("channelUtilization", 0)
|
chutil2 = interface2.nodes.get(decimal_to_hex(myNodeNum2), {}).get("deviceMetrics", {}).get("channelUtilization", 0)
|
||||||
chutil2 = "{:.2f}".format(chutil2)
|
chutil2 = "{:.2f}".format(chutil2)
|
||||||
|
elif "ack" in message.lower():
|
||||||
|
if hop == "Direct":
|
||||||
|
bot_response = "🏓ACK-ACK! " + f"SNR:{snr} RSSI:{rssi}"
|
||||||
|
else:
|
||||||
|
bot_response = "🏓ACK-ACK! " + hop
|
||||||
elif "testing" in message.lower() or "test" in message.lower():
|
elif "testing" in message.lower() or "test" in message.lower():
|
||||||
bot_response = "🏓Testing 1,2,3"
|
if hop == "Direct":
|
||||||
|
bot_response = "🏓Testing 1,2,3 " + f"SNR:{snr} RSSI:{rssi}"
|
||||||
|
else:
|
||||||
|
bot_response = "🏓Testing 1,2,3 " + hop
|
||||||
else:
|
else:
|
||||||
bot_response = "I'm sorry, I'm afraid I can't do that."
|
bot_response = "I'm sorry, I'm afraid I can't do that."
|
||||||
|
|
||||||
@@ -131,7 +134,7 @@ def onReceive(packet, interface):
|
|||||||
|
|
||||||
if message_string == help_message or message_string == welcome_message or "CMD?:" in message_string:
|
if message_string == help_message or message_string == welcome_message or "CMD?:" in message_string:
|
||||||
# ignore help and welcome messages
|
# ignore help and welcome messages
|
||||||
print(f"{log_timestamp()} Got Own Welcome/Help header. Device:{rxNode} From: {get_name_from_number(message_from_id)}")
|
logger.warning(f"Got Own Welcome/Help header. From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
# If the packet is a DM (Direct Message) respond to it, otherwise validate its a message for us on the channel
|
# If the packet is a DM (Direct Message) respond to it, otherwise validate its a message for us on the channel
|
||||||
@@ -140,25 +143,29 @@ def onReceive(packet, interface):
|
|||||||
|
|
||||||
# check if the message contains a trap word, DMs are always responded to
|
# check if the message contains a trap word, DMs are always responded to
|
||||||
if messageTrap(message_string):
|
if messageTrap(message_string):
|
||||||
print(f"{log_timestamp()} Received DM: {message_string} on Device:{rxNode} Channel: {channel_number} From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
logger.info(f"Device:{rxNode} Channel: {channel_number} " + CustomFormatter.green + f"Received DM: " + CustomFormatter.white + f"{message_string} " + CustomFormatter.purple +\
|
||||||
|
"From: " + CustomFormatter.white + f"{get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
# respond with DM
|
# respond with DM
|
||||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||||
else:
|
else:
|
||||||
# respond with welcome message on DM
|
# respond with welcome message on DM
|
||||||
print(f"{log_timestamp()} Ignoring DM: {message_string} on Device:{rxNode} From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
logger.warning(f"Device:{rxNode} Ignoring DM: {message_string} From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
send_message(welcome_message, channel_number, message_from_id, rxNode)
|
send_message(welcome_message, channel_number, message_from_id, rxNode)
|
||||||
|
msgLogger.info(f"Device:{rxNode} Channel:{channel_number} | {get_name_from_number(message_from_id, 'long', rxNode)} | {message_string}")
|
||||||
else:
|
else:
|
||||||
# message is on a channel
|
# message is on a channel
|
||||||
if messageTrap(message_string):
|
if messageTrap(message_string):
|
||||||
print(f"{log_timestamp()} Received On Device:{rxNode} Channel {channel_number}: {message_string} From: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
# message is for bot to respond to
|
||||||
|
logger.info(f"Device:{rxNode} Channel:{channel_number} " + CustomFormatter.green + "Received: " + CustomFormatter.white + f"{message_string} " + CustomFormatter.purple +\
|
||||||
|
"From: " + CustomFormatter.white + f"{get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
if useDMForResponse:
|
if useDMForResponse:
|
||||||
# respond to channel message via direct message
|
# respond to channel message via direct message
|
||||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||||
else:
|
else:
|
||||||
# or respond to channel message on the channel itself
|
# or respond to channel message on the channel itself
|
||||||
if channel_number == publicChannel:
|
if channel_number == publicChannel and antiSpam:
|
||||||
# warning user spamming default channel
|
# warning user spamming default channel
|
||||||
print(f"{log_timestamp()} System: Warning spamming default channel not allowed. sending DM to {get_name_from_number(message_from_id, 'long', rxNode)}")
|
logger.error(f"System: AntiSpam protection, sending DM to: {get_name_from_number(message_from_id, 'long', rxNode)}")
|
||||||
|
|
||||||
# respond to channel message via direct message
|
# respond to channel message via direct message
|
||||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, message_from_id, rxNode)
|
||||||
@@ -166,8 +173,8 @@ def onReceive(packet, interface):
|
|||||||
# respond to channel message on the channel itself
|
# respond to channel message on the channel itself
|
||||||
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, 0, rxNode)
|
send_message(auto_response(message_string, snr, rssi, hop, message_from_id, channel_number, rxNode), channel_number, 0, rxNode)
|
||||||
else:
|
else:
|
||||||
|
# message is not for bot to respond to
|
||||||
# ignore the message but add it to the message history and repeat it if enabled
|
# ignore the message but add it to the message history and repeat it if enabled
|
||||||
# add the message to the message history but limit
|
|
||||||
if zuluTime:
|
if zuluTime:
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
else:
|
else:
|
||||||
@@ -188,30 +195,40 @@ def onReceive(packet, interface):
|
|||||||
time.sleep(0.7)
|
time.sleep(0.7)
|
||||||
if str(channel_number) in repeater_channels:
|
if str(channel_number) in repeater_channels:
|
||||||
if rxNode == 1:
|
if rxNode == 1:
|
||||||
print(f"{log_timestamp()} Repeating message on Device2 Channel:{channel_number}")
|
logger.debug(f"Repeating message on Device2 Channel:{channel_number}")
|
||||||
send_message(rMsg, channel_number, 0, 2)
|
send_message(rMsg, channel_number, 0, 2)
|
||||||
elif rxNode == 2:
|
elif rxNode == 2:
|
||||||
print(f"{log_timestamp()} Repeating message on Device1 Channel:{channel_number}")
|
logger.debug(f"Repeating message on Device1 Channel:{channel_number}")
|
||||||
send_message(rMsg, channel_number, 0, 1)
|
send_message(rMsg, channel_number, 0, 1)
|
||||||
else:
|
else:
|
||||||
print(f"{log_timestamp()} System: Ignoring incoming Device:{rxNode} Channel:{channel_number} Message: {message_string} From: {get_name_from_number(message_from_id)}")
|
# nothing to do for us
|
||||||
|
logger.info(f"Ignoring Device:{rxNode} Channel:{channel_number} " + CustomFormatter.green + "Message:" + CustomFormatter.white +\
|
||||||
|
f" {message_string} " + CustomFormatter.purple + "From:" + CustomFormatter.white + f" {get_name_from_number(message_from_id)}")
|
||||||
|
msgLogger.info(f"Device:{rxNode} Channel:{channel_number} | {get_name_from_number(message_from_id, 'long', rxNode)} | {message_string}")
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
print(f"{log_timestamp()} System: Error processing packet: {e} Device:{rxNode}")
|
logger.critical(f"System: Error processing packet: {e} Device:{rxNode}")
|
||||||
print(packet) # print the packet for debugging
|
print(packet) # print the packet for debugging
|
||||||
print("END of packet \n")
|
print("END of packet \n")
|
||||||
|
|
||||||
async def start_rx():
|
async def start_rx():
|
||||||
|
print (CustomFormatter.bold_white + f"\nMeshtastic Autoresponder Bot CTL+C to exit\n" + CustomFormatter.reset)
|
||||||
# Start the receive subscriber using pubsub via meshtastic library
|
# Start the receive subscriber using pubsub via meshtastic library
|
||||||
pub.subscribe(onReceive, 'meshtastic.receive')
|
pub.subscribe(onReceive, 'meshtastic.receive')
|
||||||
|
logger.info(f"System: Autoresponder Started for Device1 {get_name_from_number(myNodeNum1, 'long', 1)},"
|
||||||
msg = (f"{log_timestamp()} System: Autoresponder Started for Device1 {get_name_from_number(myNodeNum1, 'long', 1)},"
|
f"{get_name_from_number(myNodeNum1, 'short', 1)}. NodeID: {myNodeNum1}, {decimal_to_hex(myNodeNum1)}")
|
||||||
f"{get_name_from_number(myNodeNum1, 'short', 1)}. NodeID: {myNodeNum1}, {decimal_to_hex(myNodeNum1)}")
|
|
||||||
print (msg)
|
|
||||||
if interface2_enabled:
|
if interface2_enabled:
|
||||||
msg = (f"{log_timestamp()} System: Autoresponder Started for Device2 {get_name_from_number(myNodeNum2, 'long', 2)},"
|
logger.info(f"System: Autoresponder Started for Device2 {get_name_from_number(myNodeNum2, 'long', 2)},"
|
||||||
f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}")
|
f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}")
|
||||||
print (msg)
|
if log_messages_to_file:
|
||||||
|
logger.debug(f"System: Logging Messages to disk")
|
||||||
|
if store_forward_enabled:
|
||||||
|
logger.debug(f"System: Store and Forward Enabled using limit: {storeFlimit}")
|
||||||
|
if useDMForResponse:
|
||||||
|
logger.debug(f"System: Respond by DM only")
|
||||||
|
if repeater_enabled and interface2_enabled:
|
||||||
|
logger.debug(f"System: Repeater Enabled for Channels: {repeater_channels}")
|
||||||
|
if radio_dectection_enabled:
|
||||||
|
logger.debug(f"System: Radio Detection Enabled using rigctld at {rigControlServerAddress} brodcasting to channels: {sigWatchBrodcastCh} for {get_freq_common_name(get_hamlib('f'))}")
|
||||||
|
|
||||||
# here we go loopty loo
|
# here we go loopty loo
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
Reference in New Issue
Block a user