Added dynamic interface with tcp and upcomming mqtt hooking. add outgoing messages aswell.
This commit is contained in:
parent
1b0616daca
commit
8eb954124f
@ -171,9 +171,10 @@ class Bot():
|
|||||||
await self.action(target, 'explodes')
|
await self.action(target, 'explodes')
|
||||||
elif msg == '!ping':
|
elif msg == '!ping':
|
||||||
await self.sendmsg(target, 'Pong!')
|
await self.sendmsg(target, 'Pong!')
|
||||||
elif msg.startswith('!say') and len(msg.split()) > 1: # Only allow !say if there is something to say
|
elif msg.startswith('!mesh') and len(msg.split()) > 1:
|
||||||
option = ' '.join(msg.split()[1:]) # Everything after !say is stored here
|
message = ' '.join(msg.split()[1:])
|
||||||
await self.sendmsg(target, option)
|
# Implement outgoing meshtastic message here
|
||||||
|
#await self.sendmesh(message)
|
||||||
self.last = time.time() # Update the last command time if it starts with ! character to prevent command flooding
|
self.last = time.time() # Update the last command time if it starts with ! character to prevent command flooding
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ try:
|
|||||||
import meshtastic
|
import meshtastic
|
||||||
from meshtastic.serial_interface import SerialInterface
|
from meshtastic.serial_interface import SerialInterface
|
||||||
from meshtastic.util import findPorts
|
from meshtastic.util import findPorts
|
||||||
|
from meshtastic.tcp_interface import TCPInterface
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError('meshtastic library not found (pip install meshtastic)')
|
raise ImportError('meshtastic library not found (pip install meshtastic)')
|
||||||
|
|
||||||
@ -29,11 +30,40 @@ def now():
|
|||||||
return time.strftime('%Y-%m-%d %H:%M:%S')
|
return time.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
|
||||||
class Meshtastic(object):
|
class MeshtasticClient(object):
|
||||||
def __init__(self, serial: str):
|
def __init__(self):
|
||||||
self.interface = None # We will define the interface in the run() function
|
self.interface = None # We will define the interface in the connect() function
|
||||||
self.nodes = {} # Nodes will populate with the on_node() callback
|
self.nodes = {} # Nodes will populate with the event_node() callback
|
||||||
self.serial = serial # Serial device to use for the Meshtastic interface
|
|
||||||
|
|
||||||
|
def connect(self, option: str, value: str):
|
||||||
|
'''
|
||||||
|
Connect to the Meshtastic interface
|
||||||
|
|
||||||
|
:param option: The interface option to connect to
|
||||||
|
:param value: The value of the interface option
|
||||||
|
'''
|
||||||
|
|
||||||
|
if option == 'serial':
|
||||||
|
if devices := findPorts():
|
||||||
|
if not os.path.exists(args.serial) or not args.serial in devices:
|
||||||
|
raise SystemExit(f'Invalid serial device: {args.serial} (Available: {devices})') # Show available devices if the specified device is invalid
|
||||||
|
else:
|
||||||
|
raise SystemExit('No serial devices found')
|
||||||
|
self.interface = SerialInterface(value)
|
||||||
|
|
||||||
|
elif option == 'tcp':
|
||||||
|
self.interface = TCPInterface(value)
|
||||||
|
|
||||||
|
elif option == 'mqtt':
|
||||||
|
raise NotImplementedError('MQTT interface not implemented yet')
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise SystemExit('Invalid interface option')
|
||||||
|
|
||||||
|
logging.info(f'Connected to radio over {option} from {value}:')
|
||||||
|
|
||||||
|
logging.debug(self.interface.nodes[self.interface.myInfo.my_node_num]) # Print the node info of the connected radio
|
||||||
|
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
@ -51,34 +81,32 @@ class Meshtastic(object):
|
|||||||
else:
|
else:
|
||||||
logging.warning('No Meshtastic interface to close')
|
logging.warning('No Meshtastic interface to close')
|
||||||
|
|
||||||
|
logging.info('Disconnected from radio')
|
||||||
|
|
||||||
def run(self):
|
|
||||||
'''Start the Meshtastic interface and subscribe to the callback functions'''
|
|
||||||
|
|
||||||
if devices := findPorts():
|
def send(self, message: str):
|
||||||
if not os.path.exists(args.serial) or not args.serial in devices:
|
'''
|
||||||
raise SystemExit(f'Invalid serial device: {args.serial} (Available: {devices})') # Show available devices if the specified device is invalid
|
Send a message to the Meshtastic interface
|
||||||
else:
|
|
||||||
raise SystemExit('No serial devices found')
|
|
||||||
|
|
||||||
# Initialize the Meshtastic interface
|
:param message: The message to send
|
||||||
self.interface = SerialInterface(self.serial)
|
'''
|
||||||
|
|
||||||
# Interface over TCP instead of serial:
|
if len(message) > 255:
|
||||||
#from meshtastic.tcp_interface import TCPInterface
|
logging.warning('Message exceeds 255 characters')
|
||||||
#self.interface = TCPInterface(args.tcp)
|
message = message[:255]
|
||||||
|
|
||||||
logging.info('Meshtastic interface started over serial on {self.serial}')
|
self.interface.sendText(message)
|
||||||
|
|
||||||
# Get the current node information
|
logging.info(f'Sent broadcast message: {message}')
|
||||||
me = self.interface.nodes[self.interface.myInfo.my_node_num]
|
|
||||||
logging.debug(me)
|
|
||||||
|
def listen(self):
|
||||||
|
'''Create the Meshtastic callback subscriptions'''
|
||||||
|
|
||||||
# Create the Meshtastic callback subscriptions
|
|
||||||
pub.subscribe(self.event_connect, 'meshtastic.connection.established')
|
pub.subscribe(self.event_connect, 'meshtastic.connection.established')
|
||||||
pub.subscribe(self.event_disconnect, 'meshtastic.connection.lost')
|
pub.subscribe(self.event_disconnect, 'meshtastic.connection.lost')
|
||||||
pub.subscribe(self.on_node, 'meshtastic.node.updated')
|
pub.subscribe(self.event_node, 'meshtastic.node.updated')
|
||||||
pub.subscribe(self.on_packet, 'meshtastic.receive')
|
pub.subscribe(self.event_packet, 'meshtastic.receive')
|
||||||
|
|
||||||
logging.debug('Listening for Meshtastic events...')
|
logging.debug('Listening for Meshtastic events...')
|
||||||
|
|
||||||
@ -97,7 +125,9 @@ class Meshtastic(object):
|
|||||||
:param topic: PubSub topic
|
:param topic: PubSub topic
|
||||||
'''
|
'''
|
||||||
|
|
||||||
logging.info('Connection established')
|
me = interface.nodes[interface.myInfo.my_node_num]['user']['longName']
|
||||||
|
|
||||||
|
logging.info(f'Connected to \'{me}\' radio')
|
||||||
|
|
||||||
|
|
||||||
def event_disconnect(self, interface, topic=pub.AUTO_TOPIC):
|
def event_disconnect(self, interface, topic=pub.AUTO_TOPIC):
|
||||||
@ -108,10 +138,33 @@ class Meshtastic(object):
|
|||||||
:param topic: PubSub topic
|
:param topic: PubSub topic
|
||||||
'''
|
'''
|
||||||
|
|
||||||
logging.warning('Connection lost')
|
logging.warning('Lost connection to radio')
|
||||||
|
|
||||||
|
|
||||||
def on_packet(self, packet: dict):
|
def event_node(self, interface, topic=pub.AUTO_TOPIC):
|
||||||
|
'''
|
||||||
|
Callback function for node updates
|
||||||
|
|
||||||
|
:param interface: Meshtastic interface
|
||||||
|
:param topic: PubSub topic
|
||||||
|
'''
|
||||||
|
|
||||||
|
if not interface.nodes:
|
||||||
|
logging.warning('No nodes found')
|
||||||
|
return
|
||||||
|
|
||||||
|
for node in interface.nodes.values():
|
||||||
|
short = node['user']['shortName']
|
||||||
|
long = node['user']['longName'].encode('ascii', 'ignore').decode().rstrip()
|
||||||
|
num = node['num']
|
||||||
|
id = node['user']['id']
|
||||||
|
mac = node['user']['macaddr']
|
||||||
|
hw = node['user']['hwModel']
|
||||||
|
|
||||||
|
self.nodes[num] = long # we store the node updates in a dictionary so we can parse the names of who sent incomming messages
|
||||||
|
|
||||||
|
|
||||||
|
def event_packet(self, packet: dict):
|
||||||
'''
|
'''
|
||||||
Callback function for received packets
|
Callback function for received packets
|
||||||
|
|
||||||
@ -137,41 +190,46 @@ class Meshtastic(object):
|
|||||||
print(f'{now()} UNK: {msg}')
|
print(f'{now()} UNK: {msg}')
|
||||||
|
|
||||||
|
|
||||||
def on_node(self, interface, topic=pub.AUTO_TOPIC):
|
def event_position(self, packet: dict):
|
||||||
'''
|
'''
|
||||||
Callback function for node updates
|
Callback function for received position packets
|
||||||
|
|
||||||
:param interface: Meshtastic interface
|
:param packet: Packet received
|
||||||
:param topic: PubSub topic
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if not interface.nodes:
|
# Handle incoming position messages
|
||||||
logging.warning('No nodes found')
|
pass
|
||||||
return
|
|
||||||
|
|
||||||
for node in interface.nodes.values():
|
|
||||||
short = node['user']['shortName']
|
|
||||||
long = node['user']['longName'].encode('ascii', 'ignore').decode().rstrip()
|
|
||||||
num = node['num']
|
|
||||||
id = node['user']['id']
|
|
||||||
mac = node['user']['macaddr']
|
|
||||||
hw = node['user']['hwModel']
|
|
||||||
|
|
||||||
self.nodes[num] = long # we store the node updates in a dictionary so we can parse the names of who sent incomming messages
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(description='Meshtastic Interface')
|
parser = argparse.ArgumentParser(description='Meshtastic Interface')
|
||||||
parser.add_argument('--serial', default='/dev/ttyACM0', help='Use serial interface')
|
|
||||||
parser.add_argument('--tcp', default='meshtastic.local'. help='Use TCP interface')
|
# Interface options
|
||||||
|
parser.add_argument('--serial', help='Use serial interface')
|
||||||
|
parser.add_argument('--tcp', help='Use TCP interface')
|
||||||
|
parser.add_argument('--mqtt', help='Use MQTT interface')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Define the Meshtastic client
|
if not args.serial and not args.tcp and not args.mqtt:
|
||||||
mesh = Meshtastic(args.serial)
|
raise SystemExit('No interface specified')
|
||||||
|
|
||||||
# Initialize the Meshtastic interface
|
if (args.serial and args.tcp) or (args.serial and args.mqtt) or (args.tcp and args.mqtt):
|
||||||
mesh.run()
|
raise SystemExit('Only one interface option can be specified (--serial, --tcp, or --mqtt)')
|
||||||
|
|
||||||
|
# Initialize the Meshtastic client
|
||||||
|
mesh = MeshtasticClient()
|
||||||
|
|
||||||
|
# Determine the interface option and value
|
||||||
|
option = 'serial' if args.serial else 'tcp' if args.tcp else 'mqtt'
|
||||||
|
value = args.serial if args.serial else args.tcp if args.tcp else args.mqtt
|
||||||
|
|
||||||
|
# Start the Meshtastic interface
|
||||||
|
mesh.connect(option, value)
|
||||||
|
|
||||||
# Keep-alive loop
|
# Keep-alive loop
|
||||||
try:
|
try:
|
||||||
|
Loading…
Reference in New Issue
Block a user