diff --git a/FIRMWARE.md b/FIRMWARE.md
@@ -0,0 +1,38 @@
+# Meshtastic Firmware Hacks
+
+### Custom Boot Logo & Message
+- Download & install [PlatformIO](https://platformio.org/platformio-ide)
+
+- `git clone https://github.com/meshtastic/firmware.git`
+
+- `cd firmware && git submodule update --init`
+
+- Use [XMB Viewer](https://windows87.github.io/xbm-viewer-converter/) to convert an image to XMB
+
+- The data from this goes in `firmware/src/graphics/img/icon.xbm`
+
+### Custom boot message
+- Navigate to `firmware/src/graphics/Screen.cpp`
+
+- Find & replace `const char *title = "meshtastic.org";` with your custom message.
+
+### Custom screen color
+ - Navigate to `src/graphics/TFTDisplay.cpp`
+
+ - Find & replace `#define TFT_MESH COLOR565(0x67, 0xEA, 0x94)` with your custom color.
+
+ ### Custom alert sound (for T-Deck & devices with a buzzer)
+ - From the mobile app, click the 3 dots on the top right, and select `Radio configuration`
+ - Under `Module configuration`, select `External Notification`
+- Scroll down & you will see a `Ringtone` option that takes [RTTTL](https://en.wikipedia.org/wiki/Ring_Tone_Text_Transfer_Language) formatted tones.
+
+As far as I know, at the time of writing this, the onyl way to change the Ringtone is from the App...
+
+ ## Compile & flash firmware
+ - Select `PlatformIO: Pick Project Environment` & select your board.
+ - Run `PLatformIO: Build` to compile the firmware.
+ - Place device in DFU mode & plug in to the computer
+ - Do `PlatformIO: Upload` to send the firmware to the device
+ - Press the RESET button or reboot your device.
+
+ See [here](https://meshtastic.org/docs/development/firmware/build/) for more information building & flashing custom firmware.
+\ No newline at end of file
diff --git a/FIRMWARE_HACKS.md b/FIRMWARE_HACKS.md
@@ -1,39 +0,0 @@
-# Meshtastic Firmware Hacks
-
-### Custom Boot Logo & Message
-- Download & install [PlatformIO](https://platformio.org/platformio-ide)
-
-- `git clone https://github.com/meshtastic/firmware.git`
-
-- `cd firmware && git submodule update --init`
-
-- Use [XMB Viewer](https://windows87.github.io/xbm-viewer-converter/) to convert an image to XMB
-
-- The data from this goes in `firmware/src/graphics/img/icon.xbm`
-
-### Custom boot message
-- Navigate to `firmware/src/graphics/Screen.cpp`
-
-- Find & replace `const char *title = "meshtastic.org";` with your custom message.
-
-### Custom screen color
- - Navigate to `src/graphics/TFTDisplay.cpp`
-
- - Find & replace `#define TFT_MESH COLOR565(0x67, 0xEA, 0x94)` with your custom color.
-
- ### Custom alert sound (for T-Deck & devices with a buzzer)
- - From the mobile app, click the 3 dots on the top right, and select `Radio configuration`
- - Under `Module configuration`, select `External Notification`
-- Scroll down & you will see a `Ringtone` option that takes [RTTTL](https://en.wikipedia.org/wiki/Ring_Tone_Text_Transfer_Language) formatted tones.
-
-As far as I know, at the time of writing this, the onyl way to change the Ringtone is from the App...
-
-
- ## Compile & flash firmware
- - Select `PlatformIO: Pick Project Environment` & select your board.
- - Run `PLatformIO: Build` to compile the firmware.
- - Place device in DFU mode & plug in to the computer
- - Do `PlatformIO: Upload` to send the firmware to the device
- - Press the RESET button or reboot your device.
-
- See [here](https://meshtastic.org/docs/development/firmware/build/) for more information building & flashing custom firmware.
-\ No newline at end of file
diff --git a/README.md b/README.md
@@ -1,28 +1,25 @@
# Meshtastic Utilities
-> Experiments with Meshtastic, MQTT, Lora, & more....
-## WORK-IN-PROGRESS
-
-## Information
This repository serves as a collection of resources created in my journey to learn & utilize [LoRa](https://en.wikipedia.org/wiki/LoRa) based communications with [Meshtastic](https://meshtastic.org).
The goal here is to create simple & clean modules to interface with the hardware in a way that can be used to expand the possibilities of the devices capabilities.
The hardware I am experimenting with: [Lilygo T-Deck](https://www.lilygo.cc/products/t-deck), [Lilygo T-Beam](https://www.lilygo.cc/products/t-beam-v1-1-esp32-lora-module), [Heltec Lora 32 v3](https://heltec.org/project/wifi-lora-32-v3/), and [RAK Wireless 4631](https://store.rakwireless.com/products/wisblock-core-modules?variant=42440631419078)
-## Notes to self & developers
-- The node id formula is: f'!{hex(node_num)[2:]}'
+## Documentation
+- [Firmware Hacks & Customization](./FIRMWARE.md)
+- [Setup Hardware](./SETUP.md)
+
-## Hardware & Software related Issues
+## Bugs & Issues
- T-Deck must have Wifi turned off when going mobile. Upon leaving my house with WiFi still enabled, the UI & connection was EXTREMELY laggy & poor. Couldn't even type well...
- T-Deck using a custom MQTT with TLS & auth will cause a reboot loop *(Need to fix this ASAP)*
- `event_node` event is called **AS** we are defining the interface, so using `self.interface` in that callback will error.
## Roadmap
-- Asyncronous meshtastic interface *(Priority)*
+- Asyncronous meshtastic interface
- MQTT interface with working decryption
- Documentation on MQTT bridging for high availability
-- Create a simple setup script to provision new devices over serial
- Bridge for IRC to allow channel messages to relay over Meshtastic & all Meshtastic events to relay into IRC. *(IRC to Meshtastic will require a command like `!mesh <message here>` to avoid overloading the traffic over LoRa)*
___
diff --git a/SETUP.md b/SETUP.md
@@ -0,0 +1,41 @@
+# Setup Hardware
+
+It is recommended that you provision your hardware using the serial interface over USB by using the [Meshtastic CLI Tool](https://pypi.org/project/meshtastic/). This is very specific because currently, at the time of writing this repository, changes made via the [web interface](https://client.meshtastic.org) do not work sometimes. When you "save" your settings, the device will reboot with the old settings still. I have had zero issues making changes over serial with the CLI interface.
+
+- `pip install meshtastic` to install the CLI tool
+- Plug in your device *(Make sure the USB cable you are using allows data transfer & not just power)*
+- Run the commands below *(Each command will make the device reboot after setting it)*
+
+###### NAME
+```
+meshtastic --set-owner 'CHANGEME' --set-owner-short 'CHNG'
+```
+
+**Note:** Short name can only be 4 alphanumeric characters.
+
+###### LORA
+```
+meshtastic --set lora.region US
+```
+
+###### CHANNEL
+```
+meshtastic --ch-set name "SUPERNETS" --ch-set psk "CHANGEME" --ch-set uplink_enabled true --ch-set downlink_enabled true --ch-index 0
+```
+
+###### WIFI
+```
+meshtastic --set network.wifi_enabled true --set network.wifi_ssid "CHANGEME" --set network.wifi_psk "CHANGEME"
+```
+
+###### MQTT
+```
+meshtastic --set mqtt.enabled true --set mqtt.address "CHANGEME" --set mqtt.username "CHANGEME" --set mqtt.password "CHANGEME" --set mqtt.tls_enabled true --set mqtt.root "msh/CHANGEME" --set mqtt.encryption_enabled true
+```
+
+###### BLUETOOTH
+```
+meshtastic --set bluetooth.enabled true
+```
+
+**Note:** Only enable this on devices are not using Wifi *(mobile devices)* because with ESP32 chips, I don't think Wifi & Bluetooth can function side-by-side together.
diff --git a/meshapi.py b/meshapi.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python
+# Meshtastic Serial Interface - Developed by Acidvegas in Python (https://git.acid.vegas)
+
+import argparse
+import logging
+import os
+import time
+
+try:
+ import meshtastic
+except ImportError:
+ raise ImportError('meshtastic library not found (pip install meshtastic)')
+
+try:
+ from pubsub import pub
+except ImportError:
+ raise ImportError('pubsub library not found (pip install pypubsub)')
+
+
+# Initialize logging
+logging.basicConfig(level=logging.INFO, format='%(asctime)s | %(levelname)9s | %(funcName)s | %(message)s', datefmt='%Y-%m-%d %I:%M:%S')
+
+
+def now():
+ '''Returns the current date and time in a formatted string'''
+
+ return time.strftime('%Y-%m-%d %H:%M:%S')
+
+
+class MeshtasticClient(object):
+ def __init__(self, option: str, value: str):
+ self.interface = None
+ self.me = {}
+ self.nodes = {}
+
+ self.interface_option = option
+ self.interface_value = value
+
+ if self.interface_option == 'serial':
+ from meshtastic.serial_interface import SerialInterface as MeshInterface
+ from meshtastic.util import findPorts
+ elif self.interface_option == 'tcp':
+ from meshtastic.tcp_interface import TCPInterface as MeshInterface
+
+
+ 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
+ '''
+
+ while True:
+ try:
+ if option == 'serial':
+ if devices := findPorts():
+ if not os.path.exists(args.serial) or not args.serial in devices:
+ raise Exception(f'Invalid serial port specified: {args.serial} (Available: {devices})')
+ else:
+ raise Exception('No serial devices found')
+ self.interface = SerialInterface(value)
+
+ elif option == 'tcp':
+ self.interface = TCPInterface(value)
+
+ else:
+ raise SystemExit('Invalid interface option')
+
+ except Exception as e:
+ logging.error(f'Failed to connect to the radio: {e}')
+ logging.error('Retrying in 15 seconds...')
+ time.sleep(15)
+
+ else:
+ self.me = self.interface.getMyNodeInfo()
+ break
+
+
+ def send(self, message: str):
+ '''
+ Send a message to the Meshtastic interface
+
+ :param message: The message to send
+ '''
+
+ if len(message) > 255:
+ logging.warning('Message exceeds 255 characters')
+ message = message[:255]
+
+ self.interface.sendText(message)
+
+ logging.info(f'Sent broadcast message: {message}')
+
+
+ def listen(self):
+ '''Create the Meshtastic callback subscriptions'''
+
+ 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_node, 'meshtastic.node')
+ 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...')
+
+
+ def event_connect(self, interface, topic=pub.AUTO_TOPIC):
+ '''
+ Callback function for connection established
+
+ :param interface: Meshtastic interface
+ :param topic: PubSub topic
+ '''
+
+ logging.info(f'Connected to the {self.me["user"]["longName"]} radio on {self.me["user"]["hwModel"]} hardware')
+ 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):
+ '''
+ Callback function for connection lost
+
+ :param interface: Meshtastic interface
+ :param topic: PubSub topic
+ '''
+
+ logging.warning('Lost connection to radio!')
+
+ time.sleep(10)
+
+ # TODO: Consider storing the interface option and value in a class variable since we don't want to reference the args object inside the class
+ self.connect('serial' if args.serial else 'tcp', args.serial if args.serial else args.tcp)
+
+
+ def event_node(self, node):
+ '''
+ Callback function for node updates
+
+ :param node: Node information
+ '''
+
+ # Node ID Formula = f'!{hex(node_num)[2:]}'
+
+ self.nodes[node['num']] = node
+
+ logging.info(f'Node found: {node["user"]["id"]} - {node["user"]["shortName"].ljust(4)} - {node["user"]["longName"]}')
+ print(node)
+
+
+ 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
+
+ :param packet: Packet received
+ '''
+
+ sender = packet['from']
+ to = packet['to']
+ 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'
+ target = self.nodes[to]['user']['longName'] if to in self.nodes else 'UNK'
+
+ logging.info(f'{id} {name} -> {target}: {msg}')
+ print(packet)
+
+
+ def event_user(self, packet: dict, interface):
+ '''
+ Callback function for user updates
+
+ :param user: User information
+ '''
+
+ '''
+ {
+ '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
+
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Meshtastic Interfacing Tool')
+ parser.add_argument('--serial', help='Use serial interface') # Typically /dev/ttyUSB0 or /dev/ttyACM0
+ parser.add_argument('--tcp', help='Use TCP interface') # Can be an IP address or hostname (meshtastic.local)
+ args = parser.parse_args()
+
+ # Ensure one interface is specified
+ if (not args.serial and not args.tcp) or (args.serial and args.tcp):
+ raise SystemExit('Must specify either --serial or --tcp interface')
+
+ # Initialize the Meshtastic client
+ mesh = MeshtasticClient()
+
+ # Listen for Meshtastic events
+ mesh.listen()
+
+ # Connect to the Meshtastic interface
+ mesh.connect('serial' if args.serial else 'tcp', args.serial if args.serial else args.tcp)
+
+ # Keep-alive loop
+ try:
+ while True:
+ time.sleep(60)
+ except KeyboardInterrupt:
+ try:
+ mesh.interface.close()
+ except:
+ pass
+ finally:
+ logging.info('Connection to radio lost')
+
+'''
+Notes:
+ conf = self.interface.localNode.localConfig
+ ok = interface.getNode('^local')
+ print(ok.channels)
+'''
+\ No newline at end of file
diff --git a/meshmqtt.py b/meshmqtt.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+# Meshtastic MQTT Interface - Developed by Acidvegas in Python (https://git.acid.vegas/meshtastic)
+
+import base64
+import random
+
+try:
+ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+ from cryptography.hazmat.backends import default_backend
+except ImportError:
+ raise ImportError('cryptography library not found (pip install cryptography)')
+
+try:
+ from meshtastic import mesh_pb2, mqtt_pb2, portnums_pb2, telemetry_pb2
+except ImportError:
+ raise ImportError('meshtastic library not found (pip install meshtastic)')
+
+try:
+ import paho.mqtt.client as mqtt
+except ImportError:
+ raise ImportError('paho-mqtt library not found (pip install paho-mqtt)')
+
+
+# MQTT Configuration
+MQTT_BROKER = 'localhost'
+MQTT_PORT = 1883
+MQTT_USERNAME = 'username'
+MQTT_PASSWORD = 'password'
+MQTT_ROOT_TOPIC = 'msh/US/2/c/'
+CHANNEL_KEY = 'channel_key'
+
+
+def on_connect(client, userdata, flags, rc, properties):
+ '''
+ Callback for when the client receives a CONNACK response from the server.
+
+ :param client: The client instance for this callback
+ :param userdata: The private user data as set in Client() or user_data_set()
+ :param flags: Response flags sent by the broker
+ :param rc: The connection result
+ :param properties: The properties returned by the broker
+ '''
+
+ if rc == 0:
+ print('Connected to MQTT broker')
+
+ else:
+ print(f"Failed to connect to MQTT broker with result code {str(rc)}")
+
+
+def on_message(client, userdata, msg):
+ '''
+ Callback for when a PUBLISH message is received from the server.
+
+ :param client: The client instance for this callback
+ :param userdata: The private user data as set in Client() or user_data_set()
+ :param msg: An instance of MQTTMessage. This is a class with members topic, payload, qos, retain.
+ '''
+
+ service_envelope = mqtt_pb2.ServiceEnvelope()
+
+ try:
+ service_envelope.ParseFromString(msg.payload)
+ print(service_envelope)
+
+ message_packet = service_envelope.packet
+ print(message_packet)
+
+ except Exception as e:
+ print(f'error on message: {e}')
+
+ else:
+ if message_packet.HasField('encrypted') and not message_packet.HasField('decoded'): # Do we need to check for both?
+ pass # Need to finish this
+
+
+
+if __name__ == '__main__':
+ client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
+ client.on_connect = on_connect
+ client.username_pw_set(username=MQTT_USERNAME, password=MQTT_PASSWORD)
+ client.connect(MQTT_BROKER, MQTT_PORT, 60)
+ client.on_message = on_message
+ client.subscribe(MQTT_ROOT_TOPIC, 0) # This is the topic that the Meshtastic device is publishing to
+
+ # Keep-alive loop
+ while client.loop() == 0:
+ pass
+\ No newline at end of file
diff --git a/meshtastic_serial.py b/meshtastic_serial.py
@@ -1,264 +0,0 @@
-#!/usr/bin/env python
-# Meshtastic Serial Interface - Developed by Acidvegas in Python (https://git.acid.vegas)
-
-import argparse
-import logging
-import os
-import time
-
-try:
- import meshtastic
- from meshtastic.serial_interface import SerialInterface
- from meshtastic.util import findPorts
- from meshtastic.tcp_interface import TCPInterface
-except ImportError:
- raise ImportError('meshtastic library not found (pip install meshtastic)')
-
-try:
- from pubsub import pub
-except ImportError:
- raise ImportError('pubsub library not found (pip install pypubsub)')
-
-
-# Initialize logging
-logging.basicConfig(level=logging.INFO, format='%(asctime)s | %(levelname)9s | %(funcName)s | %(message)s', datefmt='%Y-%m-%d %I:%M:%S')
-
-
-class MeshtasticClient(object):
- def __init__(self):
- self.interface = None
- self.me = {}
- self.nodes = {}
-
-
- 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
- '''
-
- while True:
- try:
- if option == 'serial':
- if devices := findPorts():
- if not os.path.exists(args.serial) or not args.serial in devices:
- raise Exception(f'Invalid serial port specified: {args.serial} (Available: {devices})')
- else:
- raise Exception('No serial devices found')
- self.interface = SerialInterface(value)
-
- elif option == 'tcp':
- self.interface = TCPInterface(value)
-
- else:
- raise SystemExit('Invalid interface option')
-
- except Exception as e:
- logging.error(f'Failed to connect to the Meshtastic interface: {e}')
- logging.error('Retrying in 10 seconds...')
- time.sleep(10)
-
- else:
- self.me = self.interface.getMyNodeInfo()
- break
-
-
- def sendmsg(self, message: str, destination: int, channelIndex: int = 0):
- '''
- Send a message to the Meshtastic interface
-
- :param message: The message to send
- '''
-
- if len(message) > 255:
- logging.warning('Message exceeds 255 characters')
- message = message[:255]
-
- self.interface.sendText(message, destination, wantAck=True, channelIndex=channelIndex) # Do we need wantAck?
-
- logging.info(f'Sent broadcast message: {message}')
-
-
- def listen(self):
- '''Create the Meshtastic callback subscriptions'''
-
- 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_node, 'meshtastic.node')
- 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...')
-
-
- def event_connect(self, interface, topic=pub.AUTO_TOPIC):
- '''
- Callback function for connection established
-
- :param interface: Meshtastic interface
- :param topic: PubSub topic
- '''
-
- logging.info(f'Connected to the {self.me["user"]["longName"]} radio on {self.me["user"]["hwModel"]} hardware')
- 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: {packet}')
-
-
- def event_disconnect(self, interface, topic=pub.AUTO_TOPIC):
- '''
- Callback function for connection lost
-
- :param interface: Meshtastic interface
- :param topic: PubSub topic
- '''
-
- logging.warning('Lost connection to radio!')
-
- time.sleep(10)
-
- # TODO: Consider storing the interface option and value in a class variable since we don't want to reference the args object inside the class
- self.connect('serial' if args.serial else 'tcp', args.serial if args.serial else args.tcp)
-
-
- def event_node(self, node):
- '''
- Callback function for node updates
-
- :param node: Node information
- '''
-
- self.nodes[node['num']] = node
-
- logging.info(f'Node recieved: {node["user"]["id"]} - {node["user"]["shortName"].ljust(4)} - {node["user"]["longName"]}')
-
-
- 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() # What exactly is contained in this payload?
- 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'Position recieved: {id} - {name}: {longitude}, {latitude}, {altitude}m (SNR: {snr}, RSSI: {rssi}) - {msg}')
-
-
- def event_text(self, packet: dict, interface):
- '''
- Callback function for received packets
-
- :param packet: Packet received
- '''
-
- sender = packet['from']
- to = packet['to']
- 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'
- target = self.nodes[to]['user']['longName'] if to in self.nodes else 'UNK'
-
- logging.info(f'Message recieved: {id} {name} -> {target}: {msg}')
- print(packet)
-
-
- def event_user(self, packet: dict, interface):
- '''
- Callback function for user updates
-
- :param user: User information
- '''
-
- '''
- {
- '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
-
-
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser(description='Meshtastic Interfacing Tool')
- parser.add_argument('--serial', help='Use serial interface') # Typically /dev/ttyUSB0 or /dev/ttyACM0
- parser.add_argument('--tcp', help='Use TCP interface') # Can be an IP address or hostname (meshtastic.local)
- args = parser.parse_args()
-
- # Ensure one interface is specified
- if (not args.serial and not args.tcp) or (args.serial and args.tcp):
- raise SystemExit('Must specify either --serial or --tcp interface')
-
- # Initialize the Meshtastic client
- mesh = MeshtasticClient()
-
- # Listen for Meshtastic events
- mesh.listen()
-
- # Connect to the Meshtastic interface
- mesh.connect('serial' if args.serial else 'tcp', args.serial if args.serial else args.tcp)
-
- # Keep-alive loop
- try:
- while True:
- time.sleep(60)
- except KeyboardInterrupt:
- try:
- mesh.interface.close()
- except:
- pass
- finally:
- logging.info('Connection to radio lost')
-
-'''
-Notes:
- conf = self.interface.localNode.localConfig
- ok = interface.getNode('^local')
- print(ok.channels)
-'''
-\ No newline at end of file
| | | | | | |