diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index 444c418..4650919 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -17,6 +17,7 @@ from .tcp_interface import TCPInterface from .ble_interface import BLEInterface from . import test, remote_hardware from . import portnums_pb2, channel_pb2, mesh_pb2, radioconfig_pb2 +from .util import support_info """We only import the tunnel code if we are on a platform that can run it""" have_tunnel = platform.system() == 'Linux' @@ -195,6 +196,7 @@ def onConnected(interface): closeNow = False # Should we drop the connection after we finish? try: global args + print("Connected to radio") def getNode(): @@ -267,7 +269,7 @@ def onConnected(interface): fieldNames = [] for bit in radioconfig_pb2.PositionFlags.values(): - if (prefs.position_flags & bit): + if prefs.position_flags & bit: fieldNames.append(radioconfig_pb2.PositionFlags.Name(bit)) print(' '.join(fieldNames)) @@ -569,6 +571,11 @@ def common(): parser.print_help(sys.stderr) sys.exit(1) else: + if args.support: + print("") + support_info() + sys.exit(0) + if args.ch_index is not None: global channelIndex channelIndex = int(args.ch_index) @@ -788,6 +795,9 @@ def initParser(): parser.add_argument('--version', action='version', version=f"{pkg_resources.require('meshtastic')[0].version}") + parser.add_argument( + "--support", action='store_true', help="Show support info (useful when troubleshooting an issue)") + args = parser.parse_args() diff --git a/meshtastic/node.py b/meshtastic/node.py index ecd62aa..0631cc4 100644 --- a/meshtastic/node.py +++ b/meshtastic/node.py @@ -1,63 +1,8 @@ -""" -# an API for Meshtastic devices - -Primary class: SerialInterface -Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)" -Source code on [github](https://github.com/meshtastic/Meshtastic-python) - -properties of SerialInterface: - -- radioConfig - Current radio configuration and device settings, if you write to this the new settings will be applied to -the device. -- nodes - The database of received nodes. Includes always up-to-date location and username information for each -node in the mesh. This is a read-only datastructure. -- nodesByNum - like "nodes" but keyed by nodeNum instead of nodeId -- myInfo - Contains read-only information about the local radio device (software version, hardware version, etc) - -# Published PubSub topics - -We use a [publish-subscribe](https://pypubsub.readthedocs.io/en/v4.0.3/) model to communicate asynchronous events. Available -topics: - -- meshtastic.connection.established - published once we've successfully connected to the radio and downloaded the node DB -- meshtastic.connection.lost - published once we've lost our link to the radio -- meshtastic.receive.text(packet) - delivers a received packet as a dictionary, if you only care about a particular -type of packet, you should subscribe to the full topic name. If you want to see all packets, simply subscribe to "meshtastic.receive". -- meshtastic.receive.position(packet) -- meshtastic.receive.user(packet) -- meshtastic.receive.data.portnum(packet) (where portnum is an integer or well known PortNum enum) -- meshtastic.node.updated(node = NodeInfo) - published when a node in the DB changes (appears, location changed, username changed, etc...) - -We receive position, user, or data packets from the mesh. You probably only care about meshtastic.receive.data. The first argument for -that publish will be the packet. Text or binary data packets (from sendData or sendText) will both arrive this way. If you print packet -you'll see the fields in the dictionary. decoded.data.payload will contain the raw bytes that were sent. If the packet was sent with -sendText, decoded.data.text will **also** be populated with the decoded string. For ASCII these two strings will be the same, but for -unicode scripts they can be different. - -# Example Usage -``` -import meshtastic -from pubsub import pub - -def onReceive(packet, interface): # called when a packet arrives - print(f"Received: {packet}") - -def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect to the radio - # defaults to broadcast, specify a destination ID if you wish - interface.sendText("hello mesh") - -pub.subscribe(onReceive, "meshtastic.receive") -pub.subscribe(onConnection, "meshtastic.connection.established") -# By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0 -interface = meshtastic.SerialInterface() - -``` - +""" Node class """ import logging import base64 -from typing import * from google.protobuf.json_format import MessageToJson from . import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2 from .util import pskToString, stripnl, Timeout diff --git a/meshtastic/remote_hardware.py b/meshtastic/remote_hardware.py index 4357607..2e0dac9 100644 --- a/meshtastic/remote_hardware.py +++ b/meshtastic/remote_hardware.py @@ -38,6 +38,7 @@ class RemoteHardwareClient: def _sendHardware(self, nodeid, r, wantResponse=False, onResponse=None): if not nodeid: + # pylint: disable=W1401 raise Exception( "You must set a destination node ID for this operation (use --dest \!xxxxxxxxx)") return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, diff --git a/meshtastic/test/test_int.py b/meshtastic/test/test_int.py index 4f89746..1b4615c 100644 --- a/meshtastic/test/test_int.py +++ b/meshtastic/test/test_int.py @@ -27,3 +27,12 @@ def test_int_help(): return_value, out = subprocess.getstatusoutput('meshtastic --help') assert re.match(r'usage: meshtastic ', out) assert return_value == 0 + + +@pytest.mark.int +def test_int_support(): + """Test '--support'.""" + return_value, out = subprocess.getstatusoutput('meshtastic --support') + assert re.search(r'System', out) + assert re.search(r'Python', out) + assert return_value == 0 diff --git a/meshtastic/util.py b/meshtastic/util.py index 927a28b..c685dfa 100644 --- a/meshtastic/util.py +++ b/meshtastic/util.py @@ -4,10 +4,12 @@ import traceback from queue import Queue import sys import time +import platform import logging import threading import serial import serial.tools.list_ports +import pkg_resources """Some devices such as a seger jlink we never want to accidentally open""" blacklistVids = dict.fromkeys([0x1366]) @@ -111,3 +113,21 @@ class DeferredExecution(): logging.error( f"Unexpected error in deferred execution {sys.exc_info()[0]}") print(traceback.format_exc()) + +def support_info(): + """Print out info that is helping in support of the cli.""" + print('If having issues with meshtastic cli or python library') + print('or wish to make feature requests, visit:') + print('https://github.com/meshtastic/Meshtastic-python/issues') + print('When adding an issue, be sure to include the following info:') + print(' System: {0}'.format(platform.system())) + print(' Platform: {0}'.format(platform.platform())) + print(' Release: {0}'.format(platform.uname().release)) + print(' Machine: {0}'.format(platform.uname().machine)) + print(' meshtastic: v{0}'.format(pkg_resources.require('meshtastic')[0].version)) + print(' Executable: {0}'.format(sys.argv[0])) + print(' Python: {0} {1} {2}'.format(platform.python_version(), + platform.python_implementation(), platform.python_compiler())) + print('') + print('Please add the output from the command: meshtastic --info') + print('')