Meshtastic events all handled mostly now and outputting to stdout, debugging and testing finished

This commit is contained in:
Dionysus 2024-04-28 04:51:02 -04:00
parent c244fa63fe
commit ce9519afda
Signed by: acidvegas
GPG Key ID: EF4B922DB85DC9DE
2 changed files with 99 additions and 45 deletions

View File

@ -1,4 +1,4 @@
# Meshtastic # Meshtastic Utilities
> Experiments with Meshtastic, MQTT, Lora, & more.... > Experiments with Meshtastic, MQTT, Lora, & more....
## WORK-IN-PROGRESS ## WORK-IN-PROGRESS
@ -25,6 +25,7 @@ The goal is to experiment with the possibilities of Python as a means of interfa
## Updates ## Updates
- Threw in an IRC skeleton where the serial controller will interface with. Will have to consider how handle asyncronous comms over serial... - Threw in an IRC skeleton where the serial controller will interface with. Will have to consider how handle asyncronous comms over serial...
- Working reconnection on disconnection! - Working reconnection on disconnection!
- Most events are handled and outputted to stdout, debugging and testing finished
___ ___
###### Mirrors for this repository: [acid.vegas](https://git.acid.vegas/meshtastic) • [SuperNETs](https://git.supernets.org/acidvegas/meshtastic) • [GitHub](https://github.com/acidvegas/meshtastic) • [GitLab](https://gitlab.com/acidvegas/meshtastic) • [Codeberg](https://codeberg.org/acidvegas/meshtastic) ###### Mirrors for this repository: [acid.vegas](https://git.acid.vegas/meshtastic) • [SuperNETs](https://git.supernets.org/acidvegas/meshtastic) • [GitHub](https://github.com/acidvegas/meshtastic) • [GitLab](https://gitlab.com/acidvegas/meshtastic) • [Codeberg](https://codeberg.org/acidvegas/meshtastic)

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# Meshtastic Serial Interface - Developed by Acidvegas in Python (https://git.acid.vegas/meshtastic) # Meshtastic Serial Interface - Developed by Acidvegas in Python (https://git.acid.vegas)
import argparse import argparse
import logging import logging
@ -21,7 +21,7 @@ except ImportError:
# Initialize logging # Initialize logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s | %(levelname)9s | %(funcName)s | %(message)s') logging.basicConfig(level=logging.INFO, format='%(asctime)s | %(levelname)9s | %(funcName)s | %(message)s', datefmt='%Y-%m-%d %I:%M:%S')
def now(): def now():
@ -91,18 +91,15 @@ class MeshtasticClient(object):
'''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_data, 'meshtastic.receive.data.portnum')
pub.subscribe(self.event_disconnect, 'meshtastic.connection.lost') pub.subscribe(self.event_disconnect, 'meshtastic.connection.lost')
pub.subscribe(self.event_node, 'meshtastic.node') pub.subscribe(self.event_node, 'meshtastic.node')
pub.subscribe(self.event_packet, 'meshtastic.receive') pub.subscribe(self.event_position, 'meshtastic.receive.position')
pub.subscribe(self.event_text, 'meshtastic.receive.text')
pub.subscribe(self.event_user, 'meshtastic.receive.user')
logging.debug('Listening for Meshtastic events...') logging.debug('Listening for Meshtastic events...')
# The meshtastic.receive topics can be broken down further:
# pub.subscribe(self.on_text, 'meshtastic.receive.text')
# pub.subscribe(self.on_position, 'meshtastic.receive.position')
# pub.subscribe(self.on_user, 'meshtastic.receive.user')
# pub.subscribe(self.on_data, 'meshtastic.receive.data.portnum')
def event_connect(self, interface, topic=pub.AUTO_TOPIC): def event_connect(self, interface, topic=pub.AUTO_TOPIC):
''' '''
@ -116,6 +113,17 @@ class MeshtasticClient(object):
logging.info(f'Found a total of {len(self.nodes):,} nodes') logging.info(f'Found a total of {len(self.nodes):,} nodes')
def event_data(self, packet: dict, interface):
'''
Callback function for data updates
:param packet: Data information
:param interface: Meshtastic interface
'''
logging.info(f'Data update: {data}')
def event_disconnect(self, interface, topic=pub.AUTO_TOPIC): def event_disconnect(self, interface, topic=pub.AUTO_TOPIC):
''' '''
Callback function for connection lost Callback function for connection lost
@ -125,7 +133,6 @@ class MeshtasticClient(object):
''' '''
logging.warning('Lost connection to radio!') logging.warning('Lost connection to radio!')
logging.info('Reconnecting in 10 seconds...')
time.sleep(10) time.sleep(10)
@ -133,7 +140,6 @@ class MeshtasticClient(object):
self.connect('serial' if args.serial else 'tcp', args.serial if args.serial else args.tcp) self.connect('serial' if args.serial else 'tcp', args.serial if args.serial else args.tcp)
def event_node(self, node): def event_node(self, node):
''' '''
Callback function for node updates Callback function for node updates
@ -146,30 +152,78 @@ class MeshtasticClient(object):
logging.info(f'Node found: {node["user"]["id"]} - {node["user"]["shortName"].ljust(4)} - {node["user"]["longName"]}') logging.info(f'Node found: {node["user"]["id"]} - {node["user"]["shortName"].ljust(4)} - {node["user"]["longName"]}')
def event_packet(self, packet: dict): def event_position(self, packet: dict, interface):
'''
Callback function for position updates
:param packet: Position information
:param interface: Meshtastic interface
'''
sender = packet['from']
msg = packet['decoded']['payload'].hex()
id = self.nodes[sender]['user']['id'] if sender in self.nodes else '!unk '
name = self.nodes[sender]['user']['longName'] if sender in self.nodes else 'UNK'
longitude = packet['decoded']['position']['longitudeI'] / 1e7
latitude = packet['decoded']['position']['latitudeI'] / 1e7
altitude = packet['decoded']['position']['altitude']
snr = packet['rxSnr']
rssi = packet['rxRssi']
logging.info(f'{id} - {name}: {longitude}, {latitude}, {altitude}m (SNR: {snr}, RSSI: {rssi}) - {msg}')
def event_text(self, packet: dict, interface):
''' '''
Callback function for received packets Callback function for received packets
:param packet: Packet received :param packet: Packet received
''' '''
# Handle incoming text messages
if packet['decoded']['portnum'] == 'TEXT_MESSAGE_APP':
sender = packet['from'] sender = packet['from']
msg = packet['decoded']['payload'].decode('utf-8') msg = packet['decoded']['payload'].decode('utf-8')
id = self.nodes[sender]['user']['id'] if sender in self.nodes else '!unk '
name = self.nodes[sender]['user']['longName'] if sender in self.nodes else 'UNK'
logging.info(f'{id} - {name}: {msg}')
# Message from self
if sender == self.interface.myInfo.my_node_num:
print(f'{now()} {self.nodes[sender]}: {msg}') # Can do custom formatting here or ignore the message, just an example
# Message from others def event_user(self, packet: dict, interface):
if sender in self.nodes: '''
print(f'{now()} {self.nodes[sender]}: {msg}') Callback function for user updates
# Unknown sender :param user: User information
else: '''
# TODO: Trigger request for node update here
print(f'{now()} UNK: {msg}') '''
{
'from' : 862341900,
'to' : 4294967295,
'decoded' : {
'portnum' : 'NODEINFO_APP',
'payload' : b'\n\t!33664b0c\x12\x08HELLDIVE\x1a\x04H3LL"\x06d\xe83fK\x0c(+8\x03',
'wantResponse' : True,
'user' : {
'id' : '!33664b0c',
'longName' : 'HELLDIVE',
'shortName' : 'H3LL',
'macaddr' : 'ZOgzZksM',
'hwModel' : 'HELTEC_V3',
'role' : 'ROUTER_CLIENT',
'raw' : 'rm this'
}
},
'id' : 1612906268,
'rxTime' : 1714279638,
'rxSnr' : 6.25,
'hopLimit' : 3,
'rxRssi' : -38,
'hopStart' : 3,
'raw' : 'rm this'
}
'''
# Not sure what to do with this yet...
pass
@ -197,11 +251,10 @@ if __name__ == '__main__':
while True: while True:
time.sleep(60) time.sleep(60)
except KeyboardInterrupt: except KeyboardInterrupt:
pass # Exit the loop on Ctrl+C
finally:
if mesh.interface:
try: try:
mesh.interface.close() mesh.interface.close()
logging.info('Connection to radio interface closed!')
except: except:
pass pass
finally:
logging.info('Connection to radio lost')