Compare commits

..

1 Commits

Author SHA1 Message Date
Ben Meadors
898cac3e0d 2.0 (To be merged Nov 1) 2022-10-29 08:20:32 -05:00
36 changed files with 439 additions and 1079 deletions

View File

@@ -1,20 +0,0 @@
name: Remove old artifacts
on:
schedule:
# Every day at 1am
- cron: '0 1 * * *'
workflow_dispatch:
jobs:
remove-old-artifacts:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Remove old artifacts
uses: c-hive/gha-remove-artifacts@v1
with:
age: '1 month'
skip-tags: true

View File

@@ -15,22 +15,22 @@ jobs:
run: | run: |
git pull --recurse-submodules git pull --recurse-submodules
git submodule update --remote --recursive git submodule update --remote --recursive
- name: Download nanopb - name: Download nanopb
run: | run: |
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz
tar xvzf nanopb-0.4.6-linux-x86.tar.gz tar xvzf nanopb-0.4.6-linux-x86.tar.gz
mv nanopb-0.4.6-linux-x86 nanopb-0.4.6 mv nanopb-0.4.6-linux-x86 nanopb-0.4.6
- name: Re-generate protocol buffers - name: Re-generate protocol buffers
run: | run: |
./bin/regen-protobufs.sh ./bin/regen-protos.sh
- name: Commit update - name: Commit update
run: | run: |
git config --global user.name 'github-actions' git config --global user.name 'github-actions'
git config --global user.email 'bot@noreply.github.com' git config --global user.email 'bot@noreply.github.com'
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
git add protobufs git add proto
git add meshtastic git add meshtastic
git commit -m "Update protobuf submodule" && git push || echo "No changes to commit" git commit -m "Update protobuf submodule" && git push || echo "No changes to commit"

6
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "protobufs"] [submodule "proto"]
path = protobufs path = proto
url = http://github.com/meshtastic/protobufs url = https://github.com/meshtastic/Meshtastic-protobufs.git

View File

@@ -7,7 +7,7 @@
# Add files or directories matching the regex patterns to the blacklist. The # Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths. # regex matches against base names, not paths.
ignore-patterns=mqtt_pb2.py,channel_pb2.py,telemetry_pb2.py,admin_pb2.py,config_pb2.py,deviceonly_pb2.py,apponly_pb2.py,remote_hardware_pb2.py,portnums_pb2.py,mesh_pb2.py,storeforward_pb2.py,cannedmessages_pb2.py,module_config_pb2.py,localonly_pb2.py,node.py,device_metadata_pb2.py ignore-patterns=mqtt_pb2.py,channel_pb2.py,telemetry_pb2.py,admin_pb2.py,config_pb2.py,deviceonly_pb2.py,apponly_pb2.py,remote_hardware_pb2.py,portnums_pb2.py,mesh_pb2.py,storeforward_pb2.py,cannedmessages_pb2.py,module_config_pb2.py,localonly_pb2.py,node.py
@@ -23,7 +23,7 @@ ignore-patterns=mqtt_pb2.py,channel_pb2.py,telemetry_pb2.py,admin_pb2.py,config_
# no Warning level messages displayed, use"--disable=all --enable=classes # no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W" # --disable=W"
# #
disable=invalid-name,fixme,logging-fstring-interpolation,too-many-statements,too-many-branches,too-many-locals,no-member,f-string-without-interpolation,protected-access,pointless-string-statement,too-few-public-methods,broad-except,no-else-return,no-else-raise,bare-except,too-many-public-methods disable=invalid-name,fixme,logging-fstring-interpolation,too-many-statements,too-many-branches,too-many-locals,no-member,f-string-without-interpolation,protected-access,no-self-use,pointless-string-statement,too-few-public-methods,broad-except,no-else-return,no-else-raise,bare-except,too-many-public-methods
[BASIC] [BASIC]

View File

@@ -26,11 +26,11 @@ lint:
slow: slow:
pytest -m unit --durations=5 pytest -m unit --durations=5
protobufs: FORCE proto: FORCE
git submodule update --init --recursive git submodule update --init --recursive
git pull --rebase git pull --rebase
git submodule update --remote --merge git submodule update --remote --merge
./bin/regen-protobufs.sh ./bin/regen-protos.sh
# run the coverage report and open results in a browser # run the coverage report and open results in a browser
cov: cov:

View File

@@ -2,8 +2,8 @@
[![codecov](https://codecov.io/gh/meshtastic/Meshtastic-python/branch/master/graph/badge.svg?token=TIWPJL73KV)](https://codecov.io/gh/meshtastic/Meshtastic-python) [![codecov](https://codecov.io/gh/meshtastic/Meshtastic-python/branch/master/graph/badge.svg?token=TIWPJL73KV)](https://codecov.io/gh/meshtastic/Meshtastic-python)
![PyPI - Downloads](https://img.shields.io/pypi/dm/meshtastic) ![PyPI - Downloads](https://img.shields.io/pypi/dm/meshtastic)
[![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/python/ci.yml?branch=master&label=actions&logo=github&color=yellow)](https://github.com/meshtastic/python/actions/workflows/ci.yml) [![CI](https://img.shields.io/github/workflow/status/meshtastic/Meshtastic-python/CI?label=actions&logo=github&color=yellow)](https://github.com/meshtastic/Meshtastic-python/actions/workflows/ci.yml)
[![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/python)](https://cla-assistant.io/meshtastic/python) [![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/Meshtastic-python)](https://cla-assistant.io/meshtastic/Meshtastic-python)
[![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/) [![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/)
[![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss) [![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
@@ -14,10 +14,12 @@ This small library (and example application) provides an easy API for sending an
It also provides access to any of the operations/data available in the device user interface or the Android application. It also provides access to any of the operations/data available in the device user interface or the Android application.
Events are delivered using a publish-subscribe model, and you can subscribe to only the message types you are interested in. Events are delivered using a publish-subscribe model, and you can subscribe to only the message types you are interested in.
**[Getting Started Guide](https://meshtastic.org/docs/software/python/cli/installation)**
**[Getting Started Guide](https://meshtastic.org/docs/software/python/python-installation)**
**[Documentation/API Reference](https://python.meshtastic.org/)** **[Documentation/API Reference](https://python.meshtastic.org/)**
## Stats ## Stats
![Alt](https://repobeats.axiom.co/api/embed/c71ee8fc4a79690402e5d2807a41eec5e96d9039.svg "Repobeats analytics image") ![Alt](https://repobeats.axiom.co/api/embed/3d64492daee3a603497071b45e6cdb81d9b2d421.svg "Repobeats analytics image")

View File

@@ -1,19 +1,15 @@
#!/bin/bash #!/bin/bash
#Uncomment to run hack ./nanopb-0.4.6/generator-bin/protoc -I=proto --python_out meshtastic `ls proto/*.proto`
#gsed -i 's/import "\//import ".\//g' ./protobufs/meshtastic/*
#gsed -i 's/package meshtastic;//g' ./protobufs/meshtastic/*
./nanopb-0.4.6/generator-bin/protoc -I=protobufs --python_out ./ ./protobufs/meshtastic/*.proto
# workaround for import bug in protoc https://github.com/protocolbuffers/protobuf/issues/1491#issuecomment-690618628 # workaround for import bug in protoc https://github.com/protocolbuffers/protobuf/issues/1491#issuecomment-690618628
if [[ $OSTYPE == 'darwin'* ]]; then if [[ $OSTYPE == 'darwin'* ]]; then
sed -i '' -E 's/^(import.*_pb2)/from . \1/' meshtastic/*.py sed -i '' -E 's/^(import.*_pb2)/from . \1/' meshtastic/*.py
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/protobufs/issues/27) # automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/Meshtastic-protobufs/issues/27)
sed -i '' -E "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py sed -i '' -E "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py
else else
sed -i -e 's/^import.*_pb2/from . \0/' meshtastic/*.py sed -i -e 's/^import.*_pb2/from . \0/' meshtastic/*.py
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/protobufs/issues/27) # automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/Meshtastic-protobufs/issues/27)
sed -i -e "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py sed -i -e "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py
fi fi

View File

@@ -3,7 +3,7 @@
Primary class: SerialInterface Primary class: SerialInterface
Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)" Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)"
Source code on [github](https://github.com/meshtastic/python) Source code on [github](https://github.com/meshtastic/Meshtastic-python)
properties of SerialInterface: properties of SerialInterface:
@@ -182,7 +182,6 @@ protocols = {
portnums_pb2.PortNum.ADMIN_APP: KnownProtocol("admin", admin_pb2.AdminMessage), portnums_pb2.PortNum.ADMIN_APP: KnownProtocol("admin", admin_pb2.AdminMessage),
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing), portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol("telemetry", telemetry_pb2.Telemetry), portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol("telemetry", telemetry_pb2.Telemetry),
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol("remotehw", remote_hardware_pb2.HardwareMessage), portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol("remotehw", remote_hardware_pb2.HardwareMessage),
portnums_pb2.PortNum.SIMULATOR_APP: KnownProtocol("simulator", mesh_pb2.Compressed), portnums_pb2.PortNum.SIMULATOR_APP: KnownProtocol("simulator", mesh_pb2.Compressed)
portnums_pb2.PortNum.TRACEROUTE_APP: KnownProtocol("traceroute", mesh_pb2.RouteDiscovery)
} }

View File

@@ -53,11 +53,10 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # pylint: disable=W0613
print(f"Connection changed: {topic.getName()}") print(f"Connection changed: {topic.getName()}")
def getPref(node, comp_name): def getPref(config, comp_name):
"""Get a channel or preferences value""" """Get a channel or preferences value"""
name = splitCompoundName(comp_name) name = splitCompoundName(comp_name)
wholeField = name[0] == name[1] # We want the whole field
camel_name = meshtastic.util.snake_to_camel(name[1]) camel_name = meshtastic.util.snake_to_camel(name[1])
# Note: protobufs has the keys in snake_case, so snake internally # Note: protobufs has the keys in snake_case, so snake internally
@@ -65,49 +64,26 @@ def getPref(node, comp_name):
logging.debug(f'snake_name:{snake_name} camel_name:{camel_name}') logging.debug(f'snake_name:{snake_name} camel_name:{camel_name}')
logging.debug(f'use camel:{Globals.getInstance().get_camel_case()}') logging.debug(f'use camel:{Globals.getInstance().get_camel_case()}')
# First validate the input objDesc = config.DESCRIPTOR
localConfig = node.localConfig print()
moduleConfig = node.moduleConfig config_type = objDesc.fields_by_name.get(name[0])
found = False pref = False
for config in [localConfig, moduleConfig]: if config_type:
objDesc = config.DESCRIPTOR pref = config_type.message_type.fields_by_name.get(snake_name)
config_type = objDesc.fields_by_name.get(name[0])
pref = False
if config_type:
pref = config_type.message_type.fields_by_name.get(snake_name)
if pref or wholeField:
found = True
break
if not found: if (not pref) or (not config_type):
if Globals.getInstance().get_camel_case():
print(f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have an attribute {snake_name}.")
else:
print(f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have attribute {snake_name}.")
print("Choices are...")
printConfig(localConfig)
printConfig(moduleConfig)
return False return False
# Check if we need to request the config # read the value
if len(config.ListFields()) != 0: config_values = getattr(config, config_type.name)
# read the value pref_value = getattr(config_values, pref.name)
config_values = getattr(config, config_type.name)
if not wholeField: if Globals.getInstance().get_camel_case():
pref_value = getattr(config_values, pref.name) print(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}")
if Globals.getInstance().get_camel_case(): logging.debug(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}")
print(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}") else:
logging.debug(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}") print(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
else: logging.debug(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
print(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
logging.debug(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
else:
print(f"{str(config_type.name)}:\n{str(config_values)}")
logging.debug(f"{str(config_type.name)}: {str(config_values)}")
else:
# Always show whole field for remote node
node.requestConfig(config_type)
return True return True
def splitCompoundName(comp_name): def splitCompoundName(comp_name):
@@ -201,7 +177,6 @@ def setPref(config, comp_name, valStr):
def onConnected(interface): def onConnected(interface):
"""Callback invoked when we connect to a radio""" """Callback invoked when we connect to a radio"""
closeNow = False # Should we drop the connection after we finish? closeNow = False # Should we drop the connection after we finish?
waitForAckNak = False # Should we wait for an acknowledgment if we send to a remote node?
try: try:
our_globals = Globals.getInstance() our_globals = Globals.getInstance()
args = our_globals.get_args() args = our_globals.get_args()
@@ -216,7 +191,6 @@ def onConnected(interface):
alt = 0 alt = 0
lat = 0.0 lat = 0.0
lon = 0.0 lon = 0.0
# TODO: use getNode(args.dest) to be able to set it for a remote node
localConfig = interface.localNode.localConfig localConfig = interface.localNode.localConfig
if args.setalt: if args.setalt:
alt = int(args.setalt) alt = int(args.setalt)
@@ -241,29 +215,19 @@ def onConnected(interface):
if args.set_owner: if args.set_owner:
closeNow = True closeNow = True
waitForAckNak = True
print(f"Setting device owner to {args.set_owner}") print(f"Setting device owner to {args.set_owner}")
interface.getNode(args.dest, False).setOwner(args.set_owner) interface.getNode(args.dest).setOwner(args.set_owner)
if args.set_owner_short: if args.set_owner_short:
closeNow = True closeNow = True
waitForAckNak = True
print(f"Setting device owner short to {args.set_owner_short}") print(f"Setting device owner short to {args.set_owner_short}")
interface.getNode(args.dest, False).setOwner(long_name=None, short_name=args.set_owner_short) interface.getNode(args.dest).setOwner(long_name=None, short_name=args.set_owner_short)
# TODO: add to export-config and configure # TODO: add to export-config and configure
if args.set_canned_message: if args.set_canned_message:
closeNow = True closeNow = True
waitForAckNak = True
print(f"Setting canned plugin message to {args.set_canned_message}") print(f"Setting canned plugin message to {args.set_canned_message}")
interface.getNode(args.dest, False).set_canned_message(args.set_canned_message) interface.getNode(args.dest).set_canned_message(args.set_canned_message)
# TODO: add to export-config and configure
if args.set_ringtone:
closeNow = True
waitForAckNak = True
print(f"Setting ringtone to {args.set_ringtone}")
interface.getNode(args.dest, False).set_ringtone(args.set_ringtone)
if args.pos_fields: if args.pos_fields:
# If --pos-fields invoked with args, set position fields # If --pos-fields invoked with args, set position fields
@@ -307,40 +271,27 @@ def onConnected(interface):
if args.reboot: if args.reboot:
closeNow = True closeNow = True
waitForAckNak = True interface.getNode(args.dest).reboot()
interface.getNode(args.dest, False).reboot()
if args.reboot_ota: if args.reboot_ota:
closeNow = True closeNow = True
waitForAckNak = True interface.getNode(args.dest).rebootOTA();
interface.getNode(args.dest, False).rebootOTA()
if args.shutdown: if args.shutdown:
closeNow = True closeNow = True
waitForAckNak = True interface.getNode(args.dest).shutdown()
interface.getNode(args.dest, False).shutdown()
if args.device_metadata: if args.device_metadata:
closeNow = True closeNow = True
interface.getNode(args.dest, False).getMetadata() interface.getNode(args.dest).getMetadata()
if args.begin_edit:
closeNow = True
interface.getNode(args.dest, False).beginSettingsTransaction()
if args.commit_edit:
closeNow = True
interface.getNode(args.dest, False).commitSettingsTransaction()
if args.factory_reset: if args.factory_reset:
closeNow = True closeNow = True
waitForAckNak = True interface.getNode(args.dest).factoryReset()
interface.getNode(args.dest, False).factoryReset()
if args.reset_nodedb: if args.reset_nodedb:
closeNow = True closeNow = True
waitForAckNak = True interface.getNode(args.dest).resetNodeDb()
interface.getNode(args.dest, False).resetNodeDb()
if args.sendtext: if args.sendtext:
closeNow = True closeNow = True
@@ -361,13 +312,6 @@ def onConnected(interface):
interface.sendData(payload, args.dest, portNum=portnums_pb2.PortNum.REPLY_APP, interface.sendData(payload, args.dest, portNum=portnums_pb2.PortNum.REPLY_APP,
wantAck=True, wantResponse=True) wantAck=True, wantResponse=True)
if args.traceroute:
loraConfig = getattr(interface.localNode.localConfig, 'lora')
hopLimit = getattr(loraConfig, 'hop_limit')
dest = str(args.traceroute)
print(f"Sending traceroute request to {dest} (this could take a while)")
interface.sendTraceRoute(dest, hopLimit)
if args.gpio_wrb or args.gpio_rd or args.gpio_watch: if args.gpio_wrb or args.gpio_rd or args.gpio_watch:
if args.dest == BROADCAST_ADDR: if args.dest == BROADCAST_ADDR:
meshtastic.util.our_exit("Warning: Must use a destination node ID.") meshtastic.util.our_exit("Warning: Must use a destination node ID.")
@@ -406,26 +350,18 @@ def onConnected(interface):
# handle settings # handle settings
if args.set: if args.set:
closeNow = True closeNow = True
waitForAckNak = True node = interface.getNode(args.dest)
node = interface.getNode(args.dest, False)
# Handle the int/float/bool arguments # Handle the int/float/bool arguments
pref = None pref = None
for pref in args.set: for pref in args.set:
found = False found = setPref(node.localConfig, pref[0], pref[1])
field = splitCompoundName(pref[0].lower())[0] if not found:
for config in [node.localConfig, node.moduleConfig]: found = setPref(node.moduleConfig, pref[0], pref[1])
config_type = config.DESCRIPTOR.fields_by_name.get(field)
if config_type:
if len(config.ListFields()) == 0:
node.requestConfig(config.DESCRIPTOR.fields_by_name.get(field))
found = setPref(config, pref[0], pref[1])
if found:
break
if found: if found:
print("Writing modified preferences to device") print("Writing modified preferences to device")
node.writeConfig(field) interface.getNode(args.dest).writeConfig(splitCompoundName(pref[0].lower())[0])
else: else:
if Globals.getInstance().get_camel_case(): if Globals.getInstance().get_camel_case():
print(f"{node.localConfig.__class__.__name__} and {node.moduleConfig.__class__.__name__} do not have an attribute {pref[0]}.") print(f"{node.localConfig.__class__.__name__} and {node.moduleConfig.__class__.__name__} do not have an attribute {pref[0]}.")
@@ -440,22 +376,17 @@ def onConnected(interface):
configuration = yaml.safe_load(file) configuration = yaml.safe_load(file)
closeNow = True closeNow = True
interface.getNode(args.dest, False).beginSettingsTransaction()
if 'owner' in configuration: if 'owner' in configuration:
print(f"Setting device owner to {configuration['owner']}") print(f"Setting device owner to {configuration['owner']}")
waitForAckNak = True interface.getNode(args.dest).setOwner(configuration['owner'])
interface.getNode(args.dest, False).setOwner(configuration['owner'])
if 'owner_short' in configuration: if 'owner_short' in configuration:
print(f"Setting device owner short to {configuration['owner_short']}") print(f"Setting device owner short to {configuration['owner_short']}")
waitForAckNak = True interface.getNode(args.dest).setOwner(long_name=None, short_name=configuration['owner_short'])
interface.getNode(args.dest, False).setOwner(long_name=None, short_name=configuration['owner_short'])
if 'ownerShort' in configuration: if 'ownerShort' in configuration:
print(f"Setting device owner short to {configuration['ownerShort']}") print(f"Setting device owner short to {configuration['ownerShort']}")
waitForAckNak = True interface.getNode(args.dest).setOwner(long_name=None, short_name=configuration['ownerShort'])
interface.getNode(args.dest, False).setOwner(long_name=None, short_name=configuration['ownerShort'])
if 'channel_url' in configuration: if 'channel_url' in configuration:
print("Setting channel url to", configuration['channel_url']) print("Setting channel url to", configuration['channel_url'])
@@ -491,17 +422,16 @@ def onConnected(interface):
localConfig = interface.getNode(args.dest).localConfig localConfig = interface.getNode(args.dest).localConfig
for section in configuration['config']: for section in configuration['config']:
for pref in configuration['config'][section]: for pref in configuration['config'][section]:
setPref(localConfig, f"{meshtastic.util.camel_to_snake(section)}.{pref}", str(configuration['config'][section][pref])) setPref(localConfig, f"{section}.{pref}", str(configuration['config'][section][pref]))
interface.getNode(args.dest).writeConfig(meshtastic.util.camel_to_snake(section)) interface.getNode(args.dest).writeConfig(section)
if 'module_config' in configuration: if 'module_config' in configuration:
moduleConfig = interface.getNode(args.dest).moduleConfig moduleConfig = interface.getNode(args.dest).moduleConfig
for section in configuration['module_config']: for section in configuration['module_config']:
for pref in configuration['module_config'][section]: for pref in configuration['module_config'][section]:
setPref(moduleConfig, f"{meshtastic.util.camel_to_snake(section)}.{pref}", str(configuration['module_config'][section][pref])) setPref(moduleConfig, f"{section}.{pref}", str(configuration['module_config'][section][pref]))
interface.getNode(args.dest).writeConfig(meshtastic.util.camel_to_snake(section)) interface.getNode(args.dest).writeConfig(section)
interface.getNode(args.dest, False).commitSettingsTransaction()
print("Writing modified configuration to device") print("Writing modified configuration to device")
if args.export_config: if args.export_config:
@@ -619,38 +549,41 @@ def onConnected(interface):
print("") print("")
interface.getNode(args.dest).get_canned_message() interface.getNode(args.dest).get_canned_message()
if args.get_ringtone:
closeNow = True
print("")
interface.getNode(args.dest).get_ringtone()
if args.info: if args.info:
print("") print("")
# If we aren't trying to talk to our local node, don't show it # If we aren't trying to talk to our local node, don't show it
if args.dest == BROADCAST_ADDR: if args.dest == BROADCAST_ADDR:
interface.showInfo() interface.showInfo()
print("")
interface.getNode(args.dest).showInfo() print("")
closeNow = True interface.getNode(args.dest).showInfo()
print("") closeNow = True # FIXME, for now we leave the link up while talking to remote nodes
else: print("")
print("Showing info of remote node is not supported.")
print("Use the '--get' command for a specific configuration (e.g. 'lora') instead.")
if args.get: if args.get:
closeNow = True closeNow = True
node = interface.getNode(args.dest, False) localConfig = interface.getNode(args.dest).localConfig
for pref in args.get: moduleConfig = interface.getNode(args.dest).moduleConfig
found = getPref(node, pref[0])
if found: # Handle the int/float/bool arguments
for pref in args.get:
found = getPref(localConfig, pref[0])
if not found:
found = getPref(moduleConfig, pref[0])
if not found:
if Globals.getInstance().get_camel_case():
print(f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have an attribute {pref[0]}.")
else:
print(f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have attribute {pref[0]}.")
print("Choices are...")
printConfig(localConfig)
printConfig(moduleConfig)
else:
print("Completed getting preferences") print("Completed getting preferences")
if args.nodes: if args.nodes:
closeNow = True closeNow = True
if args.dest != BROADCAST_ADDR:
print("Showing node list of a remote node is not supported.")
return
interface.showNodes() interface.showNodes()
if args.qr: if args.qr:
@@ -671,10 +604,6 @@ def onConnected(interface):
else: else:
tunnel.Tunnel(interface, subnet=args.tunnel_net) tunnel.Tunnel(interface, subnet=args.tunnel_net)
if args.dest != BROADCAST_ADDR and waitForAckNak:
print(f"Waiting for an acknowledgment from remote node (this could take a while)")
interface.getNode(args.dest, False).iface.waitForAckNak()
# if the user didn't ask for serial debugging output, we might want to exit after we've done our operation # if the user didn't ask for serial debugging output, we might want to exit after we've done our operation
if (not args.seriallog) and closeNow: if (not args.seriallog) and closeNow:
interface.close() # after running command then exit interface.close() # after running command then exit
@@ -684,7 +613,6 @@ def onConnected(interface):
interface.close() # close the connection now, so that our app exits interface.close() # close the connection now, so that our app exits
def printConfig(config): def printConfig(config):
"""print configuration"""
objDesc = config.DESCRIPTOR objDesc = config.DESCRIPTOR
for config_section in objDesc.fields: for config_section in objDesc.fields:
if config_section.name != "version": if config_section.name != "version":
@@ -757,7 +685,7 @@ def export_config(interface):
configObj["config"] = config configObj["config"] = config
else: else:
configObj["config"] = config configObj["config"] = config
module_config = MessageToDict(interface.localNode.moduleConfig) module_config = MessageToDict(interface.localNode.moduleConfig)
if module_config: if module_config:
# Convert inner keys to correct snake/camelCase # Convert inner keys to correct snake/camelCase
@@ -896,9 +824,6 @@ def initParser():
parser.add_argument("--get-canned-message", help="Show the canned message plugin message", parser.add_argument("--get-canned-message", help="Show the canned message plugin message",
action="store_true") action="store_true")
parser.add_argument("--get-ringtone", help="Show the stored ringtone",
action="store_true")
parser.add_argument("--nodes", help="Print Node List in a pretty formatted table", parser.add_argument("--nodes", help="Print Node List in a pretty formatted table",
action="store_true") action="store_true")
@@ -936,7 +861,7 @@ def initParser():
"--ch-set", help=("Set a channel parameter. To see channel settings available:'--ch-set all all --ch-index 0'. " "--ch-set", help=("Set a channel parameter. To see channel settings available:'--ch-set all all --ch-index 0'. "
"Can set the 'psk' using this command. To disable encryption on primary channel:'--ch-set psk none --ch-index 0'. " "Can set the 'psk' using this command. To disable encryption on primary channel:'--ch-set psk none --ch-index 0'. "
"To set encryption with a new random key on second channel:'--ch-set psk random --ch-index 1'. " "To set encryption with a new random key on second channel:'--ch-set psk random --ch-index 1'. "
"To set encryption back to the default:'--ch-set psk default --ch-index 0'. To set encryption with your " "To set encryption back to the default:'--ch-set default --ch-index 0'. To set encryption with your "
"own key: '--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --ch-index 0'."), "own key: '--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --ch-index 0'."),
nargs=2, action='append') nargs=2, action='append')
@@ -965,10 +890,7 @@ def initParser():
"--set-owner", help="Set device owner name", action="store") "--set-owner", help="Set device owner name", action="store")
parser.add_argument( parser.add_argument(
"--set-canned-message", help="Set the canned messages plugin message (up to 200 characters).", action="store") "--set-canned-message", help="Set the canned messages plugin message (up to 1000 characters).", action="store")
parser.add_argument(
"--set-ringtone", help="Set the Notification Ringtone (up to 230 characters).", action="store")
parser.add_argument( parser.add_argument(
"--set-owner-short", help="Set device owner short name", action="store") "--set-owner-short", help="Set device owner short name", action="store")
@@ -985,12 +907,6 @@ def initParser():
parser.add_argument( parser.add_argument(
"--sendping", help="Send a ping message (which requests a reply)", action="store_true") "--sendping", help="Send a ping message (which requests a reply)", action="store_true")
parser.add_argument(
"--traceroute", help="Traceroute from connected node to a destination. " \
"You need pass the destination ID as argument, like " \
"this: '--traceroute !ba4bf9d0' " \
"Only nodes that have the encryption key can be traced.")
parser.add_argument( parser.add_argument(
"--reboot", help="Tell the destination node to reboot", action="store_true") "--reboot", help="Tell the destination node to reboot", action="store_true")
@@ -1003,15 +919,9 @@ def initParser():
parser.add_argument( parser.add_argument(
"--device-metadata", help="Get the device metadata from the node", action="store_true") "--device-metadata", help="Get the device metadata from the node", action="store_true")
parser.add_argument(
"--begin-edit", help="Tell the node to open a transaction to edit settings", action="store_true")
parser.add_argument(
"--commit-edit", help="Tell the node to commit open settings transaction", action="store_true")
parser.add_argument( parser.add_argument(
"--factory-reset", help="Tell the destination node to install the default config", action="store_true") "--factory-reset", help="Tell the destination node to install the default config", action="store_true")
parser.add_argument( parser.add_argument(
"--reset-nodedb", help="Tell the destination node clear its list of nodes", action="store_true") "--reset-nodedb", help="Tell the destination node clear its list of nodes", action="store_true")

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/admin.proto # source: admin.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -12,45 +12,35 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
from meshtastic import channel_pb2 as meshtastic_dot_channel__pb2 from . import channel_pb2 as channel__pb2
from meshtastic import config_pb2 as meshtastic_dot_config__pb2 from . import config_pb2 as config__pb2
from meshtastic import mesh_pb2 as meshtastic_dot_mesh__pb2 from . import device_metadata_pb2 as device__metadata__pb2
from meshtastic import module_config_pb2 as meshtastic_dot_module__config__pb2 from . import mesh_pb2 as mesh__pb2
from meshtastic import connection_status_pb2 as meshtastic_dot_connection__status__pb2 from . import module_config_pb2 as module__config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16meshtastic/admin.proto\x1a\x18meshtastic/channel.proto\x1a\x17meshtastic/config.proto\x1a\x15meshtastic/mesh.proto\x1a\x1emeshtastic/module_config.proto\x1a\"meshtastic/connection_status.proto\"\xd8\x0c\n\x0c\x41\x64minMessage\x12\x1d\n\x13get_channel_request\x18\x01 \x01(\rH\x00\x12(\n\x14get_channel_response\x18\x02 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x03 \x01(\x08H\x00\x12#\n\x12get_owner_response\x18\x04 \x01(\x0b\x32\x05.UserH\x00\x12\x36\n\x12get_config_request\x18\x05 \x01(\x0e\x32\x18.AdminMessage.ConfigTypeH\x00\x12&\n\x13get_config_response\x18\x06 \x01(\x0b\x32\x07.ConfigH\x00\x12\x43\n\x19get_module_config_request\x18\x07 \x01(\x0e\x32\x1e.AdminMessage.ModuleConfigTypeH\x00\x12\x33\n\x1aget_module_config_response\x18\x08 \x01(\x0b\x32\r.ModuleConfigH\x00\x12\x34\n*get_canned_message_module_messages_request\x18\n \x01(\x08H\x00\x12\x35\n+get_canned_message_module_messages_response\x18\x0b \x01(\tH\x00\x12%\n\x1bget_device_metadata_request\x18\x0c \x01(\x08H\x00\x12\x37\n\x1cget_device_metadata_response\x18\r \x01(\x0b\x32\x0f.DeviceMetadataH\x00\x12\x1e\n\x14get_ringtone_request\x18\x0e \x01(\x08H\x00\x12\x1f\n\x15get_ringtone_response\x18\x0f \x01(\tH\x00\x12.\n$get_device_connection_status_request\x18\x10 \x01(\x08H\x00\x12H\n%get_device_connection_status_response\x18\x11 \x01(\x0b\x32\x17.DeviceConnectionStatusH\x00\x12&\n\x0cset_ham_mode\x18\x12 \x01(\x0b\x32\x0e.HamParametersH\x00\x12\x1a\n\tset_owner\x18 \x01(\x0b\x32\x05.UserH\x00\x12\x1f\n\x0bset_channel\x18! \x01(\x0b\x32\x08.ChannelH\x00\x12\x1d\n\nset_config\x18\" \x01(\x0b\x32\x07.ConfigH\x00\x12*\n\x11set_module_config\x18# \x01(\x0b\x32\r.ModuleConfigH\x00\x12,\n\"set_canned_message_module_messages\x18$ \x01(\tH\x00\x12\x1e\n\x14set_ringtone_message\x18% \x01(\tH\x00\x12\x1d\n\x13\x62\x65gin_edit_settings\x18@ \x01(\x08H\x00\x12\x1e\n\x14\x63ommit_edit_settings\x18\x41 \x01(\x08H\x00\x12\x1c\n\x12reboot_ota_seconds\x18_ \x01(\x05H\x00\x12\x18\n\x0e\x65xit_simulator\x18` \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18\x61 \x01(\x05H\x00\x12\x1a\n\x10shutdown_seconds\x18\x62 \x01(\x05H\x00\x12\x17\n\rfactory_reset\x18\x63 \x01(\x05H\x00\x12\x16\n\x0cnodedb_reset\x18\x64 \x01(\x05H\x00\"\x95\x01\n\nConfigType\x12\x11\n\rDEVICE_CONFIG\x10\x00\x12\x13\n\x0fPOSITION_CONFIG\x10\x01\x12\x10\n\x0cPOWER_CONFIG\x10\x02\x12\x12\n\x0eNETWORK_CONFIG\x10\x03\x12\x12\n\x0e\x44ISPLAY_CONFIG\x10\x04\x12\x0f\n\x0bLORA_CONFIG\x10\x05\x12\x14\n\x10\x42LUETOOTH_CONFIG\x10\x06\"\xd3\x01\n\x10ModuleConfigType\x12\x0f\n\x0bMQTT_CONFIG\x10\x00\x12\x11\n\rSERIAL_CONFIG\x10\x01\x12\x13\n\x0f\x45XTNOTIF_CONFIG\x10\x02\x12\x17\n\x13STOREFORWARD_CONFIG\x10\x03\x12\x14\n\x10RANGETEST_CONFIG\x10\x04\x12\x14\n\x10TELEMETRY_CONFIG\x10\x05\x12\x14\n\x10\x43\x41NNEDMSG_CONFIG\x10\x06\x12\x10\n\x0c\x41UDIO_CONFIG\x10\x07\x12\x19\n\x15REMOTEHARDWARE_CONFIG\x10\x08\x42\x11\n\x0fpayload_variant\"[\n\rHamParameters\x12\x11\n\tcall_sign\x18\x01 \x01(\t\x12\x10\n\x08tx_power\x18\x02 \x01(\x05\x12\x11\n\tfrequency\x18\x03 \x01(\x02\x12\x12\n\nshort_name\x18\x04 \x01(\tB`\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61\x64min.proto\x1a\rchannel.proto\x1a\x0c\x63onfig.proto\x1a\x15\x64\x65vice_metadata.proto\x1a\nmesh.proto\x1a\x13module_config.proto\"\xe8\n\n\x0c\x41\x64minMessage\x12\x1d\n\x13get_channel_request\x18\x01 \x01(\rH\x00\x12(\n\x14get_channel_response\x18\x02 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x03 \x01(\x08H\x00\x12#\n\x12get_owner_response\x18\x04 \x01(\x0b\x32\x05.UserH\x00\x12\x36\n\x12get_config_request\x18\x05 \x01(\x0e\x32\x18.AdminMessage.ConfigTypeH\x00\x12&\n\x13get_config_response\x18\x06 \x01(\x0b\x32\x07.ConfigH\x00\x12\x43\n\x19get_module_config_request\x18\x07 \x01(\x0e\x32\x1e.AdminMessage.ModuleConfigTypeH\x00\x12\x33\n\x1aget_module_config_response\x18\x08 \x01(\x0b\x32\r.ModuleConfigH\x00\x12\x34\n*get_canned_message_module_messages_request\x18\n \x01(\x08H\x00\x12\x35\n+get_canned_message_module_messages_response\x18\x0b \x01(\tH\x00\x12%\n\x1bget_device_metadata_request\x18\x0c \x01(\x08H\x00\x12\x37\n\x1cget_device_metadata_response\x18\r \x01(\x0b\x32\x0f.DeviceMetadataH\x00\x12\x1a\n\tset_owner\x18 \x01(\x0b\x32\x05.UserH\x00\x12\x1f\n\x0bset_channel\x18! \x01(\x0b\x32\x08.ChannelH\x00\x12\x1d\n\nset_config\x18\" \x01(\x0b\x32\x07.ConfigH\x00\x12*\n\x11set_module_config\x18# \x01(\x0b\x32\r.ModuleConfigH\x00\x12,\n\"set_canned_message_module_messages\x18$ \x01(\tH\x00\x12\x1c\n\x12\x63onfirm_set_config\x18@ \x01(\x08H\x00\x12#\n\x19\x63onfirm_set_module_config\x18\x41 \x01(\x08H\x00\x12\x1d\n\x13\x63onfirm_set_channel\x18\x42 \x01(\x08H\x00\x12\x1b\n\x11\x63onfirm_set_radio\x18\x43 \x01(\x08H\x00\x12\x1c\n\x12reboot_ota_seconds\x18_ \x01(\x05H\x00\x12\x18\n\x0e\x65xit_simulator\x18` \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18\x61 \x01(\x05H\x00\x12\x1a\n\x10shutdown_seconds\x18\x62 \x01(\x05H\x00\x12\x17\n\rfactory_reset\x18\x63 \x01(\x05H\x00\x12\x16\n\x0cnodedb_reset\x18\x64 \x01(\x05H\x00\"\x95\x01\n\nConfigType\x12\x11\n\rDEVICE_CONFIG\x10\x00\x12\x13\n\x0fPOSITION_CONFIG\x10\x01\x12\x10\n\x0cPOWER_CONFIG\x10\x02\x12\x12\n\x0eNETWORK_CONFIG\x10\x03\x12\x12\n\x0e\x44ISPLAY_CONFIG\x10\x04\x12\x0f\n\x0bLORA_CONFIG\x10\x05\x12\x14\n\x10\x42LUETOOTH_CONFIG\x10\x06\"\xa6\x01\n\x10ModuleConfigType\x12\x0f\n\x0bMQTT_CONFIG\x10\x00\x12\x11\n\rSERIAL_CONFIG\x10\x01\x12\x13\n\x0f\x45XTNOTIF_CONFIG\x10\x02\x12\x17\n\x13STOREFORWARD_CONFIG\x10\x03\x12\x14\n\x10RANGETEST_CONFIG\x10\x04\x12\x14\n\x10TELEMETRY_CONFIG\x10\x05\x12\x14\n\x10\x43\x41NNEDMSG_CONFIG\x10\x06\x42\x11\n\x0fpayload_variantBH\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
_ADMINMESSAGE = DESCRIPTOR.message_types_by_name['AdminMessage'] _ADMINMESSAGE = DESCRIPTOR.message_types_by_name['AdminMessage']
_HAMPARAMETERS = DESCRIPTOR.message_types_by_name['HamParameters']
_ADMINMESSAGE_CONFIGTYPE = _ADMINMESSAGE.enum_types_by_name['ConfigType'] _ADMINMESSAGE_CONFIGTYPE = _ADMINMESSAGE.enum_types_by_name['ConfigType']
_ADMINMESSAGE_MODULECONFIGTYPE = _ADMINMESSAGE.enum_types_by_name['ModuleConfigType'] _ADMINMESSAGE_MODULECONFIGTYPE = _ADMINMESSAGE.enum_types_by_name['ModuleConfigType']
AdminMessage = _reflection.GeneratedProtocolMessageType('AdminMessage', (_message.Message,), { AdminMessage = _reflection.GeneratedProtocolMessageType('AdminMessage', (_message.Message,), {
'DESCRIPTOR' : _ADMINMESSAGE, 'DESCRIPTOR' : _ADMINMESSAGE,
'__module__' : 'meshtastic.admin_pb2' '__module__' : 'admin_pb2'
# @@protoc_insertion_point(class_scope:AdminMessage) # @@protoc_insertion_point(class_scope:AdminMessage)
}) })
_sym_db.RegisterMessage(AdminMessage) _sym_db.RegisterMessage(AdminMessage)
HamParameters = _reflection.GeneratedProtocolMessageType('HamParameters', (_message.Message,), {
'DESCRIPTOR' : _HAMPARAMETERS,
'__module__' : 'meshtastic.admin_pb2'
# @@protoc_insertion_point(class_scope:HamParameters)
})
_sym_db.RegisterMessage(HamParameters)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\013AdminProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\013AdminProtosH\003Z\"github.com/meshtastic/go/generated'
_ADMINMESSAGE._serialized_start=169 _ADMINMESSAGE._serialized_start=101
_ADMINMESSAGE._serialized_end=1793 _ADMINMESSAGE._serialized_end=1485
_ADMINMESSAGE_CONFIGTYPE._serialized_start=1411 _ADMINMESSAGE_CONFIGTYPE._serialized_start=1148
_ADMINMESSAGE_CONFIGTYPE._serialized_end=1560 _ADMINMESSAGE_CONFIGTYPE._serialized_end=1297
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_start=1563 _ADMINMESSAGE_MODULECONFIGTYPE._serialized_start=1300
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_end=1774 _ADMINMESSAGE_MODULECONFIGTYPE._serialized_end=1466
_HAMPARAMETERS._serialized_start=1795
_HAMPARAMETERS._serialized_end=1886
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/apponly.proto # source: apponly.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -12,18 +12,18 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
from meshtastic import channel_pb2 as meshtastic_dot_channel__pb2 from . import channel_pb2 as channel__pb2
from meshtastic import config_pb2 as meshtastic_dot_config__pb2 from . import config_pb2 as config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18meshtastic/apponly.proto\x1a\x18meshtastic/channel.proto\x1a\x17meshtastic/config.proto\"Y\n\nChannelSet\x12\"\n\x08settings\x18\x01 \x03(\x0b\x32\x10.ChannelSettings\x12\'\n\x0blora_config\x18\x02 \x01(\x0b\x32\x12.Config.LoRaConfigBb\n\x13\x63om.geeksville.meshB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rapponly.proto\x1a\rchannel.proto\x1a\x0c\x63onfig.proto\"Y\n\nChannelSet\x12\"\n\x08settings\x18\x01 \x03(\x0b\x32\x10.ChannelSettings\x12\'\n\x0blora_config\x18\x02 \x01(\x0b\x32\x12.Config.LoRaConfigBJ\n\x13\x63om.geeksville.meshB\rAppOnlyProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
_CHANNELSET = DESCRIPTOR.message_types_by_name['ChannelSet'] _CHANNELSET = DESCRIPTOR.message_types_by_name['ChannelSet']
ChannelSet = _reflection.GeneratedProtocolMessageType('ChannelSet', (_message.Message,), { ChannelSet = _reflection.GeneratedProtocolMessageType('ChannelSet', (_message.Message,), {
'DESCRIPTOR' : _CHANNELSET, 'DESCRIPTOR' : _CHANNELSET,
'__module__' : 'meshtastic.apponly_pb2' '__module__' : 'apponly_pb2'
# @@protoc_insertion_point(class_scope:ChannelSet) # @@protoc_insertion_point(class_scope:ChannelSet)
}) })
_sym_db.RegisterMessage(ChannelSet) _sym_db.RegisterMessage(ChannelSet)
@@ -31,7 +31,7 @@ _sym_db.RegisterMessage(ChannelSet)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rAppOnlyProtosH\003Z\"github.com/meshtastic/go/generated'
_CHANNELSET._serialized_start=79 _CHANNELSET._serialized_start=46
_CHANNELSET._serialized_end=168 _CHANNELSET._serialized_end=135
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/cannedmessages.proto # source: cannedmessages.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -14,14 +14,14 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/cannedmessages.proto\"-\n\x19\x43\x61nnedMessageModuleConfig\x12\x10\n\x08messages\x18\x01 \x01(\tBn\n\x13\x63om.geeksville.meshB\x19\x43\x61nnedMessageConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x63\x61nnedmessages.proto\"-\n\x19\x43\x61nnedMessageModuleConfig\x12\x10\n\x08messages\x18\x01 \x01(\tBV\n\x13\x63om.geeksville.meshB\x19\x43\x61nnedMessageConfigProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
_CANNEDMESSAGEMODULECONFIG = DESCRIPTOR.message_types_by_name['CannedMessageModuleConfig'] _CANNEDMESSAGEMODULECONFIG = DESCRIPTOR.message_types_by_name['CannedMessageModuleConfig']
CannedMessageModuleConfig = _reflection.GeneratedProtocolMessageType('CannedMessageModuleConfig', (_message.Message,), { CannedMessageModuleConfig = _reflection.GeneratedProtocolMessageType('CannedMessageModuleConfig', (_message.Message,), {
'DESCRIPTOR' : _CANNEDMESSAGEMODULECONFIG, 'DESCRIPTOR' : _CANNEDMESSAGEMODULECONFIG,
'__module__' : 'meshtastic.cannedmessages_pb2' '__module__' : 'cannedmessages_pb2'
# @@protoc_insertion_point(class_scope:CannedMessageModuleConfig) # @@protoc_insertion_point(class_scope:CannedMessageModuleConfig)
}) })
_sym_db.RegisterMessage(CannedMessageModuleConfig) _sym_db.RegisterMessage(CannedMessageModuleConfig)
@@ -29,7 +29,7 @@ _sym_db.RegisterMessage(CannedMessageModuleConfig)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\031CannedMessageConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\031CannedMessageConfigProtosH\003Z\"github.com/meshtastic/go/generated'
_CANNEDMESSAGEMODULECONFIG._serialized_start=35 _CANNEDMESSAGEMODULECONFIG._serialized_start=24
_CANNEDMESSAGEMODULECONFIG._serialized_end=80 _CANNEDMESSAGEMODULECONFIG._serialized_end=69
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/channel.proto # source: channel.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18meshtastic/channel.proto\"\x83\x01\n\x0f\x43hannelSettings\x12\x17\n\x0b\x63hannel_num\x18\x01 \x01(\rB\x02\x18\x01\x12\x0b\n\x03psk\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\n\n\x02id\x18\x04 \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x05 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x06 \x01(\x08\"\x8b\x01\n\x07\x43hannel\x12\r\n\x05index\x18\x01 \x01(\x05\x12\"\n\x08settings\x18\x02 \x01(\x0b\x32\x10.ChannelSettings\x12\x1b\n\x04role\x18\x03 \x01(\x0e\x32\r.Channel.Role\"0\n\x04Role\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07PRIMARY\x10\x01\x12\r\n\tSECONDARY\x10\x02\x42\x62\n\x13\x63om.geeksville.meshB\rChannelProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rchannel.proto\"\x83\x01\n\x0f\x43hannelSettings\x12\x17\n\x0b\x63hannel_num\x18\x01 \x01(\rB\x02\x18\x01\x12\x0b\n\x03psk\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\n\n\x02id\x18\x04 \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x05 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x06 \x01(\x08\"\x8b\x01\n\x07\x43hannel\x12\r\n\x05index\x18\x01 \x01(\x05\x12\"\n\x08settings\x18\x02 \x01(\x0b\x32\x10.ChannelSettings\x12\x1b\n\x04role\x18\x03 \x01(\x0e\x32\r.Channel.Role\"0\n\x04Role\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07PRIMARY\x10\x01\x12\r\n\tSECONDARY\x10\x02\x42J\n\x13\x63om.geeksville.meshB\rChannelProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
@@ -23,14 +23,14 @@ _CHANNEL = DESCRIPTOR.message_types_by_name['Channel']
_CHANNEL_ROLE = _CHANNEL.enum_types_by_name['Role'] _CHANNEL_ROLE = _CHANNEL.enum_types_by_name['Role']
ChannelSettings = _reflection.GeneratedProtocolMessageType('ChannelSettings', (_message.Message,), { ChannelSettings = _reflection.GeneratedProtocolMessageType('ChannelSettings', (_message.Message,), {
'DESCRIPTOR' : _CHANNELSETTINGS, 'DESCRIPTOR' : _CHANNELSETTINGS,
'__module__' : 'meshtastic.channel_pb2' '__module__' : 'channel_pb2'
# @@protoc_insertion_point(class_scope:ChannelSettings) # @@protoc_insertion_point(class_scope:ChannelSettings)
}) })
_sym_db.RegisterMessage(ChannelSettings) _sym_db.RegisterMessage(ChannelSettings)
Channel = _reflection.GeneratedProtocolMessageType('Channel', (_message.Message,), { Channel = _reflection.GeneratedProtocolMessageType('Channel', (_message.Message,), {
'DESCRIPTOR' : _CHANNEL, 'DESCRIPTOR' : _CHANNEL,
'__module__' : 'meshtastic.channel_pb2' '__module__' : 'channel_pb2'
# @@protoc_insertion_point(class_scope:Channel) # @@protoc_insertion_point(class_scope:Channel)
}) })
_sym_db.RegisterMessage(Channel) _sym_db.RegisterMessage(Channel)
@@ -38,13 +38,13 @@ _sym_db.RegisterMessage(Channel)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rChannelProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rChannelProtosH\003Z\"github.com/meshtastic/go/generated'
_CHANNELSETTINGS.fields_by_name['channel_num']._options = None _CHANNELSETTINGS.fields_by_name['channel_num']._options = None
_CHANNELSETTINGS.fields_by_name['channel_num']._serialized_options = b'\030\001' _CHANNELSETTINGS.fields_by_name['channel_num']._serialized_options = b'\030\001'
_CHANNELSETTINGS._serialized_start=29 _CHANNELSETTINGS._serialized_start=18
_CHANNELSETTINGS._serialized_end=160 _CHANNELSETTINGS._serialized_end=149
_CHANNEL._serialized_start=163 _CHANNEL._serialized_start=152
_CHANNEL._serialized_end=302 _CHANNEL._serialized_end=291
_CHANNEL_ROLE._serialized_start=254 _CHANNEL_ROLE._serialized_start=243
_CHANNEL_ROLE._serialized_end=302 _CHANNEL_ROLE._serialized_end=291
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,85 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/connection_status.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/connection_status.proto\"\x85\x02\n\x16\x44\x65viceConnectionStatus\x12(\n\x04wifi\x18\x01 \x01(\x0b\x32\x15.WifiConnectionStatusH\x00\x88\x01\x01\x12\x30\n\x08\x65thernet\x18\x02 \x01(\x0b\x32\x19.EthernetConnectionStatusH\x01\x88\x01\x01\x12\x32\n\tbluetooth\x18\x03 \x01(\x0b\x32\x1a.BluetoothConnectionStatusH\x02\x88\x01\x01\x12,\n\x06serial\x18\x04 \x01(\x0b\x32\x17.SerialConnectionStatusH\x03\x88\x01\x01\x42\x07\n\x05_wifiB\x0b\n\t_ethernetB\x0c\n\n_bluetoothB\t\n\x07_serial\"\\\n\x14WifiConnectionStatus\x12(\n\x06status\x18\x01 \x01(\x0b\x32\x18.NetworkConnectionStatus\x12\x0c\n\x04ssid\x18\x02 \x01(\t\x12\x0c\n\x04rssi\x18\x03 \x01(\x05\"D\n\x18\x45thernetConnectionStatus\x12(\n\x06status\x18\x01 \x01(\x0b\x32\x18.NetworkConnectionStatus\"{\n\x17NetworkConnectionStatus\x12\x12\n\nip_address\x18\x01 \x01(\x07\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x12\x19\n\x11is_mqtt_connected\x18\x03 \x01(\x08\x12\x1b\n\x13is_syslog_connected\x18\x04 \x01(\x08\"L\n\x19\x42luetoothConnectionStatus\x12\x0b\n\x03pin\x18\x01 \x01(\r\x12\x0c\n\x04rssi\x18\x02 \x01(\x05\x12\x14\n\x0cis_connected\x18\x03 \x01(\x08\"<\n\x16SerialConnectionStatus\x12\x0c\n\x04\x62\x61ud\x18\x01 \x01(\r\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x42\x65\n\x13\x63om.geeksville.meshB\x10\x43onnStatusProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_DEVICECONNECTIONSTATUS = DESCRIPTOR.message_types_by_name['DeviceConnectionStatus']
_WIFICONNECTIONSTATUS = DESCRIPTOR.message_types_by_name['WifiConnectionStatus']
_ETHERNETCONNECTIONSTATUS = DESCRIPTOR.message_types_by_name['EthernetConnectionStatus']
_NETWORKCONNECTIONSTATUS = DESCRIPTOR.message_types_by_name['NetworkConnectionStatus']
_BLUETOOTHCONNECTIONSTATUS = DESCRIPTOR.message_types_by_name['BluetoothConnectionStatus']
_SERIALCONNECTIONSTATUS = DESCRIPTOR.message_types_by_name['SerialConnectionStatus']
DeviceConnectionStatus = _reflection.GeneratedProtocolMessageType('DeviceConnectionStatus', (_message.Message,), {
'DESCRIPTOR' : _DEVICECONNECTIONSTATUS,
'__module__' : 'meshtastic.connection_status_pb2'
# @@protoc_insertion_point(class_scope:DeviceConnectionStatus)
})
_sym_db.RegisterMessage(DeviceConnectionStatus)
WifiConnectionStatus = _reflection.GeneratedProtocolMessageType('WifiConnectionStatus', (_message.Message,), {
'DESCRIPTOR' : _WIFICONNECTIONSTATUS,
'__module__' : 'meshtastic.connection_status_pb2'
# @@protoc_insertion_point(class_scope:WifiConnectionStatus)
})
_sym_db.RegisterMessage(WifiConnectionStatus)
EthernetConnectionStatus = _reflection.GeneratedProtocolMessageType('EthernetConnectionStatus', (_message.Message,), {
'DESCRIPTOR' : _ETHERNETCONNECTIONSTATUS,
'__module__' : 'meshtastic.connection_status_pb2'
# @@protoc_insertion_point(class_scope:EthernetConnectionStatus)
})
_sym_db.RegisterMessage(EthernetConnectionStatus)
NetworkConnectionStatus = _reflection.GeneratedProtocolMessageType('NetworkConnectionStatus', (_message.Message,), {
'DESCRIPTOR' : _NETWORKCONNECTIONSTATUS,
'__module__' : 'meshtastic.connection_status_pb2'
# @@protoc_insertion_point(class_scope:NetworkConnectionStatus)
})
_sym_db.RegisterMessage(NetworkConnectionStatus)
BluetoothConnectionStatus = _reflection.GeneratedProtocolMessageType('BluetoothConnectionStatus', (_message.Message,), {
'DESCRIPTOR' : _BLUETOOTHCONNECTIONSTATUS,
'__module__' : 'meshtastic.connection_status_pb2'
# @@protoc_insertion_point(class_scope:BluetoothConnectionStatus)
})
_sym_db.RegisterMessage(BluetoothConnectionStatus)
SerialConnectionStatus = _reflection.GeneratedProtocolMessageType('SerialConnectionStatus', (_message.Message,), {
'DESCRIPTOR' : _SERIALCONNECTIONSTATUS,
'__module__' : 'meshtastic.connection_status_pb2'
# @@protoc_insertion_point(class_scope:SerialConnectionStatus)
})
_sym_db.RegisterMessage(SerialConnectionStatus)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\020ConnStatusProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_DEVICECONNECTIONSTATUS._serialized_start=39
_DEVICECONNECTIONSTATUS._serialized_end=300
_WIFICONNECTIONSTATUS._serialized_start=302
_WIFICONNECTIONSTATUS._serialized_end=394
_ETHERNETCONNECTIONSTATUS._serialized_start=396
_ETHERNETCONNECTIONSTATUS._serialized_end=464
_NETWORKCONNECTIONSTATUS._serialized_start=466
_NETWORKCONNECTIONSTATUS._serialized_end=589
_BLUETOOTHCONNECTIONSTATUS._serialized_start=591
_BLUETOOTHCONNECTIONSTATUS._serialized_end=667
_SERIALCONNECTIONSTATUS._serialized_start=669
_SERIALCONNECTIONSTATUS._serialized_end=729
# @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/device_metadata.proto # source: device_metadata.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -12,18 +12,16 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
from meshtastic import config_pb2 as meshtastic_dot_config__pb2
from meshtastic import mesh_pb2 as meshtastic_dot_mesh__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/device_metadata.proto\x1a\x17meshtastic/config.proto\x1a\x15meshtastic/mesh.proto\"\xfc\x01\n\x0e\x44\x65viceMetadata\x12\x18\n\x10\x66irmware_version\x18\x01 \x01(\t\x12\x1c\n\x14\x64\x65vice_state_version\x18\x02 \x01(\r\x12\x13\n\x0b\x63\x61nShutdown\x18\x03 \x01(\x08\x12\x0f\n\x07hasWifi\x18\x04 \x01(\x08\x12\x14\n\x0chasBluetooth\x18\x05 \x01(\x08\x12\x13\n\x0bhasEthernet\x18\x06 \x01(\x08\x12\'\n\x04role\x18\x07 \x01(\x0e\x32\x19.Config.DeviceConfig.Role\x12\x16\n\x0eposition_flags\x18\x08 \x01(\r\x12 \n\x08hw_model\x18\t \x01(\x0e\x32\x0e.HardwareModelBi\n\x13\x63om.geeksville.meshB\x14\x44\x65viceMetadataProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x64\x65vice_metadata.proto\"H\n\x0e\x44\x65viceMetadata\x12\x18\n\x10\x66irmware_version\x18\x01 \x01(\t\x12\x1c\n\x14\x64\x65vice_state_version\x18\x02 \x01(\rBQ\n\x13\x63om.geeksville.meshB\x14\x44\x65viceMetadataProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
_DEVICEMETADATA = DESCRIPTOR.message_types_by_name['DeviceMetadata'] _DEVICEMETADATA = DESCRIPTOR.message_types_by_name['DeviceMetadata']
DeviceMetadata = _reflection.GeneratedProtocolMessageType('DeviceMetadata', (_message.Message,), { DeviceMetadata = _reflection.GeneratedProtocolMessageType('DeviceMetadata', (_message.Message,), {
'DESCRIPTOR' : _DEVICEMETADATA, 'DESCRIPTOR' : _DEVICEMETADATA,
'__module__' : 'meshtastic.device_metadata_pb2' '__module__' : 'device_metadata_pb2'
# @@protoc_insertion_point(class_scope:DeviceMetadata) # @@protoc_insertion_point(class_scope:DeviceMetadata)
}) })
_sym_db.RegisterMessage(DeviceMetadata) _sym_db.RegisterMessage(DeviceMetadata)
@@ -31,7 +29,7 @@ _sym_db.RegisterMessage(DeviceMetadata)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\024DeviceMetadataProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\024DeviceMetadataProtosH\003Z\"github.com/meshtastic/go/generated'
_DEVICEMETADATA._serialized_start=85 _DEVICEMETADATA._serialized_start=25
_DEVICEMETADATA._serialized_end=337 _DEVICEMETADATA._serialized_end=97
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/deviceonly.proto # source: deviceonly.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf.internal import enum_type_wrapper from google.protobuf.internal import enum_type_wrapper
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
@@ -13,12 +13,11 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
from meshtastic import channel_pb2 as meshtastic_dot_channel__pb2 from . import channel_pb2 as channel__pb2
from meshtastic import localonly_pb2 as meshtastic_dot_localonly__pb2 from . import mesh_pb2 as mesh__pb2
from meshtastic import mesh_pb2 as meshtastic_dot_mesh__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bmeshtastic/deviceonly.proto\x1a\x18meshtastic/channel.proto\x1a\x1ameshtastic/localonly.proto\x1a\x15meshtastic/mesh.proto\"\xe0\x01\n\x0b\x44\x65viceState\x12\x1c\n\x07my_node\x18\x02 \x01(\x0b\x32\x0b.MyNodeInfo\x12\x14\n\x05owner\x18\x03 \x01(\x0b\x32\x05.User\x12\x1a\n\x07node_db\x18\x04 \x03(\x0b\x32\t.NodeInfo\x12\"\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12$\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07no_save\x18\t \x01(\x08\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08\":\n\x0b\x43hannelFile\x12\x1a\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x08.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\xf6\x01\n\x08OEMStore\x12\x16\n\x0eoem_icon_width\x18\x01 \x01(\r\x12\x17\n\x0foem_icon_height\x18\x02 \x01(\r\x12\x15\n\roem_icon_bits\x18\x03 \x01(\x0c\x12\x1e\n\x08oem_font\x18\x04 \x01(\x0e\x32\x0c.ScreenFonts\x12\x10\n\x08oem_text\x18\x05 \x01(\t\x12\x13\n\x0boem_aes_key\x18\x06 \x01(\x0c\x12&\n\x10oem_local_config\x18\x07 \x01(\x0b\x32\x0c.LocalConfig\x12\x33\n\x17oem_local_module_config\x18\x08 \x01(\x0b\x32\x12.LocalModuleConfig*>\n\x0bScreenFonts\x12\x0e\n\nFONT_SMALL\x10\x00\x12\x0f\n\x0b\x46ONT_MEDIUM\x10\x01\x12\x0e\n\nFONT_LARGE\x10\x02\x42_\n\x13\x63om.geeksville.meshB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x64\x65viceonly.proto\x1a\rchannel.proto\x1a\nmesh.proto\"\xe0\x01\n\x0b\x44\x65viceState\x12\x1c\n\x07my_node\x18\x02 \x01(\x0b\x32\x0b.MyNodeInfo\x12\x14\n\x05owner\x18\x03 \x01(\x0b\x32\x05.User\x12\x1a\n\x07node_db\x18\x04 \x03(\x0b\x32\t.NodeInfo\x12\"\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12$\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07no_save\x18\t \x01(\x08\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08\":\n\x0b\x43hannelFile\x12\x1a\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x08.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\x99\x01\n\x08OEMStore\x12\x16\n\x0eoem_icon_width\x18\x01 \x01(\r\x12\x17\n\x0foem_icon_height\x18\x02 \x01(\r\x12\x15\n\roem_icon_bits\x18\x03 \x01(\x0c\x12\x1e\n\x08oem_font\x18\x04 \x01(\x0e\x32\x0c.ScreenFonts\x12\x10\n\x08oem_text\x18\x05 \x01(\t\x12\x13\n\x0boem_aes_key\x18\x06 \x01(\x0c*>\n\x0bScreenFonts\x12\x0e\n\nFONT_SMALL\x10\x00\x12\x0f\n\x0b\x46ONT_MEDIUM\x10\x01\x12\x0e\n\nFONT_LARGE\x10\x02\x42G\n\x13\x63om.geeksville.meshB\nDeviceOnlyH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
_SCREENFONTS = DESCRIPTOR.enum_types_by_name['ScreenFonts'] _SCREENFONTS = DESCRIPTOR.enum_types_by_name['ScreenFonts']
ScreenFonts = enum_type_wrapper.EnumTypeWrapper(_SCREENFONTS) ScreenFonts = enum_type_wrapper.EnumTypeWrapper(_SCREENFONTS)
@@ -32,21 +31,21 @@ _CHANNELFILE = DESCRIPTOR.message_types_by_name['ChannelFile']
_OEMSTORE = DESCRIPTOR.message_types_by_name['OEMStore'] _OEMSTORE = DESCRIPTOR.message_types_by_name['OEMStore']
DeviceState = _reflection.GeneratedProtocolMessageType('DeviceState', (_message.Message,), { DeviceState = _reflection.GeneratedProtocolMessageType('DeviceState', (_message.Message,), {
'DESCRIPTOR' : _DEVICESTATE, 'DESCRIPTOR' : _DEVICESTATE,
'__module__' : 'meshtastic.deviceonly_pb2' '__module__' : 'deviceonly_pb2'
# @@protoc_insertion_point(class_scope:DeviceState) # @@protoc_insertion_point(class_scope:DeviceState)
}) })
_sym_db.RegisterMessage(DeviceState) _sym_db.RegisterMessage(DeviceState)
ChannelFile = _reflection.GeneratedProtocolMessageType('ChannelFile', (_message.Message,), { ChannelFile = _reflection.GeneratedProtocolMessageType('ChannelFile', (_message.Message,), {
'DESCRIPTOR' : _CHANNELFILE, 'DESCRIPTOR' : _CHANNELFILE,
'__module__' : 'meshtastic.deviceonly_pb2' '__module__' : 'deviceonly_pb2'
# @@protoc_insertion_point(class_scope:ChannelFile) # @@protoc_insertion_point(class_scope:ChannelFile)
}) })
_sym_db.RegisterMessage(ChannelFile) _sym_db.RegisterMessage(ChannelFile)
OEMStore = _reflection.GeneratedProtocolMessageType('OEMStore', (_message.Message,), { OEMStore = _reflection.GeneratedProtocolMessageType('OEMStore', (_message.Message,), {
'DESCRIPTOR' : _OEMSTORE, 'DESCRIPTOR' : _OEMSTORE,
'__module__' : 'meshtastic.deviceonly_pb2' '__module__' : 'deviceonly_pb2'
# @@protoc_insertion_point(class_scope:OEMStore) # @@protoc_insertion_point(class_scope:OEMStore)
}) })
_sym_db.RegisterMessage(OEMStore) _sym_db.RegisterMessage(OEMStore)
@@ -54,13 +53,13 @@ _sym_db.RegisterMessage(OEMStore)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nDeviceOnlyH\003Z\"github.com/meshtastic/go/generated'
_SCREENFONTS._serialized_start=644 _SCREENFONTS._serialized_start=490
_SCREENFONTS._serialized_end=706 _SCREENFONTS._serialized_end=552
_DEVICESTATE._serialized_start=109 _DEVICESTATE._serialized_start=48
_DEVICESTATE._serialized_end=333 _DEVICESTATE._serialized_end=272
_CHANNELFILE._serialized_start=335 _CHANNELFILE._serialized_start=274
_CHANNELFILE._serialized_end=393 _CHANNELFILE._serialized_end=332
_OEMSTORE._serialized_start=396 _OEMSTORE._serialized_start=335
_OEMSTORE._serialized_end=642 _OEMSTORE._serialized_end=488
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/localonly.proto # source: localonly.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -12,11 +12,11 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
from meshtastic import config_pb2 as meshtastic_dot_config__pb2 from . import config_pb2 as config__pb2
from meshtastic import module_config_pb2 as meshtastic_dot_module__config__pb2 from . import module_config_pb2 as module__config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1ameshtastic/localonly.proto\x1a\x17meshtastic/config.proto\x1a\x1emeshtastic/module_config.proto\"\xb0\x02\n\x0bLocalConfig\x12$\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32\x14.Config.DeviceConfig\x12(\n\x08position\x18\x02 \x01(\x0b\x32\x16.Config.PositionConfig\x12\"\n\x05power\x18\x03 \x01(\x0b\x32\x13.Config.PowerConfig\x12&\n\x07network\x18\x04 \x01(\x0b\x32\x15.Config.NetworkConfig\x12&\n\x07\x64isplay\x18\x05 \x01(\x0b\x32\x15.Config.DisplayConfig\x12 \n\x04lora\x18\x06 \x01(\x0b\x32\x12.Config.LoRaConfig\x12*\n\tbluetooth\x18\x07 \x01(\x0b\x32\x17.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\"\x81\x04\n\x11LocalModuleConfig\x12&\n\x04mqtt\x18\x01 \x01(\x0b\x32\x18.ModuleConfig.MQTTConfig\x12*\n\x06serial\x18\x02 \x01(\x0b\x32\x1a.ModuleConfig.SerialConfig\x12G\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32(.ModuleConfig.ExternalNotificationConfig\x12\x37\n\rstore_forward\x18\x04 \x01(\x0b\x32 .ModuleConfig.StoreForwardConfig\x12\x31\n\nrange_test\x18\x05 \x01(\x0b\x32\x1d.ModuleConfig.RangeTestConfig\x12\x30\n\ttelemetry\x18\x06 \x01(\x0b\x32\x1d.ModuleConfig.TelemetryConfig\x12\x39\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32!.ModuleConfig.CannedMessageConfig\x12(\n\x05\x61udio\x18\t \x01(\x0b\x32\x19.ModuleConfig.AudioConfig\x12;\n\x0fremote_hardware\x18\n \x01(\x0b\x32\".ModuleConfig.RemoteHardwareConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBd\n\x13\x63om.geeksville.meshB\x0fLocalOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0flocalonly.proto\x1a\x0c\x63onfig.proto\x1a\x13module_config.proto\"\xb0\x02\n\x0bLocalConfig\x12$\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32\x14.Config.DeviceConfig\x12(\n\x08position\x18\x02 \x01(\x0b\x32\x16.Config.PositionConfig\x12\"\n\x05power\x18\x03 \x01(\x0b\x32\x13.Config.PowerConfig\x12&\n\x07network\x18\x04 \x01(\x0b\x32\x15.Config.NetworkConfig\x12&\n\x07\x64isplay\x18\x05 \x01(\x0b\x32\x15.Config.DisplayConfig\x12 \n\x04lora\x18\x06 \x01(\x0b\x32\x12.Config.LoRaConfig\x12*\n\tbluetooth\x18\x07 \x01(\x0b\x32\x17.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\"\x9a\x03\n\x11LocalModuleConfig\x12&\n\x04mqtt\x18\x01 \x01(\x0b\x32\x18.ModuleConfig.MQTTConfig\x12*\n\x06serial\x18\x02 \x01(\x0b\x32\x1a.ModuleConfig.SerialConfig\x12G\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32(.ModuleConfig.ExternalNotificationConfig\x12\x37\n\rstore_forward\x18\x04 \x01(\x0b\x32 .ModuleConfig.StoreForwardConfig\x12\x31\n\nrange_test\x18\x05 \x01(\x0b\x32\x1d.ModuleConfig.RangeTestConfig\x12\x30\n\ttelemetry\x18\x06 \x01(\x0b\x32\x1d.ModuleConfig.TelemetryConfig\x12\x39\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32!.ModuleConfig.CannedMessageConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBL\n\x13\x63om.geeksville.meshB\x0fLocalOnlyProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
@@ -24,14 +24,14 @@ _LOCALCONFIG = DESCRIPTOR.message_types_by_name['LocalConfig']
_LOCALMODULECONFIG = DESCRIPTOR.message_types_by_name['LocalModuleConfig'] _LOCALMODULECONFIG = DESCRIPTOR.message_types_by_name['LocalModuleConfig']
LocalConfig = _reflection.GeneratedProtocolMessageType('LocalConfig', (_message.Message,), { LocalConfig = _reflection.GeneratedProtocolMessageType('LocalConfig', (_message.Message,), {
'DESCRIPTOR' : _LOCALCONFIG, 'DESCRIPTOR' : _LOCALCONFIG,
'__module__' : 'meshtastic.localonly_pb2' '__module__' : 'localonly_pb2'
# @@protoc_insertion_point(class_scope:LocalConfig) # @@protoc_insertion_point(class_scope:LocalConfig)
}) })
_sym_db.RegisterMessage(LocalConfig) _sym_db.RegisterMessage(LocalConfig)
LocalModuleConfig = _reflection.GeneratedProtocolMessageType('LocalModuleConfig', (_message.Message,), { LocalModuleConfig = _reflection.GeneratedProtocolMessageType('LocalModuleConfig', (_message.Message,), {
'DESCRIPTOR' : _LOCALMODULECONFIG, 'DESCRIPTOR' : _LOCALMODULECONFIG,
'__module__' : 'meshtastic.localonly_pb2' '__module__' : 'localonly_pb2'
# @@protoc_insertion_point(class_scope:LocalModuleConfig) # @@protoc_insertion_point(class_scope:LocalModuleConfig)
}) })
_sym_db.RegisterMessage(LocalModuleConfig) _sym_db.RegisterMessage(LocalModuleConfig)
@@ -39,9 +39,9 @@ _sym_db.RegisterMessage(LocalModuleConfig)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017LocalOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017LocalOnlyProtosH\003Z\"github.com/meshtastic/go/generated'
_LOCALCONFIG._serialized_start=88 _LOCALCONFIG._serialized_start=55
_LOCALCONFIG._serialized_end=392 _LOCALCONFIG._serialized_end=359
_LOCALMODULECONFIG._serialized_start=395 _LOCALMODULECONFIG._serialized_start=362
_LOCALMODULECONFIG._serialized_end=908 _LOCALMODULECONFIG._serialized_end=772
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -18,7 +18,7 @@ from google.protobuf.json_format import MessageToJson
import meshtastic.node import meshtastic.node
from meshtastic import portnums_pb2, mesh_pb2 from meshtastic import portnums_pb2, mesh_pb2
from meshtastic.util import stripnl, Timeout, Acknowledgment, our_exit, remove_keys_from_dict, convert_mac_addr from meshtastic.util import stripnl, Timeout, our_exit, remove_keys_from_dict, convert_mac_addr
from meshtastic.__init__ import LOCAL_ADDR, BROADCAST_NUM, BROADCAST_ADDR, ResponseHandler, publishingThread, OUR_APP_VERSION, protocols from meshtastic.__init__ import LOCAL_ADDR, BROADCAST_NUM, BROADCAST_ADDR, ResponseHandler, publishingThread, OUR_APP_VERSION, protocols
class MeshInterface: class MeshInterface:
@@ -47,12 +47,12 @@ class MeshInterface:
self.responseHandlers = {} # A map from request ID to the handler self.responseHandlers = {} # A map from request ID to the handler
self.failure = None # If we've encountered a fatal exception it will be kept here self.failure = None # If we've encountered a fatal exception it will be kept here
self._timeout = Timeout() self._timeout = Timeout()
self._acknowledgment = Acknowledgment()
self.heartbeatTimer = None self.heartbeatTimer = None
random.seed() # FIXME, we should not clobber the random seedval here, instead tell user they must call it random.seed() # FIXME, we should not clobber the random seedval here, instead tell user they must call it
self.currentPacketId = random.randint(0, 0xffffffff) self.currentPacketId = random.randint(0, 0xffffffff)
self.nodesByNum = None self.nodesByNum = None
self.configId = None self.configId = None
self.defaultHopLimit = 3
self.gotResponse = False # used in gpio read self.gotResponse = False # used in gpio read
self.mask = None # used in gpio read and gpio watch self.mask = None # used in gpio read and gpio watch
@@ -137,20 +137,7 @@ class MeshInterface:
"Latitude": formatFloat(pos.get("latitude"), 4, "°"), "Latitude": formatFloat(pos.get("latitude"), 4, "°"),
"Longitude": formatFloat(pos.get("longitude"), 4, "°"), "Longitude": formatFloat(pos.get("longitude"), 4, "°"),
"Altitude": formatFloat(pos.get("altitude"), 0, " m"), "Altitude": formatFloat(pos.get("altitude"), 0, " m"),
}) "Battery": formatFloat(pos.get("batteryLevel"), 2, "%"),
metrics = node.get('deviceMetrics')
if metrics:
batteryLevel = metrics.get('batteryLevel')
if batteryLevel is not None:
if batteryLevel == 0:
batteryString = "Powered"
else:
batteryString = str(batteryLevel)+"%"
row.update({"Battery": batteryString})
row.update({
"Channel util.": formatFloat(metrics.get('channelUtilization'), 2, "%"),
"Tx air util.": formatFloat(metrics.get('airUtilTx'), 2, "%"),
}) })
row.update({ row.update({
@@ -170,24 +157,23 @@ class MeshInterface:
return table return table
def getNode(self, nodeId, requestChannels=True): def getNode(self, nodeId):
"""Return a node object which contains device settings and channel info""" """Return a node object which contains device settings and channel info"""
if nodeId in (LOCAL_ADDR, BROADCAST_ADDR): if nodeId in (LOCAL_ADDR, BROADCAST_ADDR):
return self.localNode return self.localNode
else: else:
n = meshtastic.node.Node(self, nodeId) n = meshtastic.node.Node(self, nodeId)
# Only request device settings and channel info when necessary logging.debug("About to requestConfig")
if requestChannels: n.requestConfig()
logging.debug("About to requestChannels") if not n.waitForConfig():
n.requestChannels() our_exit("Error: Timed out waiting for node config")
if not n.waitForConfig():
our_exit("Error: Timed out waiting for channels")
return n return n
def sendText(self, text: AnyStr, def sendText(self, text: AnyStr,
destinationId=BROADCAST_ADDR, destinationId=BROADCAST_ADDR,
wantAck=False, wantAck=False,
wantResponse=False, wantResponse=False,
hopLimit=None,
onResponse=None, onResponse=None,
channelIndex=0): channelIndex=0):
"""Send a utf8 string to some other node, if the node has a display it """Send a utf8 string to some other node, if the node has a display it
@@ -209,17 +195,21 @@ class MeshInterface:
Returns the sent packet. The id field will be populated in this packet Returns the sent packet. The id field will be populated in this packet
and can be used to track future message acks/naks. and can be used to track future message acks/naks.
""" """
if hopLimit is None:
hopLimit = self.defaultHopLimit
return self.sendData(text.encode("utf-8"), destinationId, return self.sendData(text.encode("utf-8"), destinationId,
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP, portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
wantAck=wantAck, wantAck=wantAck,
wantResponse=wantResponse, wantResponse=wantResponse,
hopLimit=hopLimit,
onResponse=onResponse, onResponse=onResponse,
channelIndex=channelIndex) channelIndex=channelIndex)
def sendData(self, data, destinationId=BROADCAST_ADDR, def sendData(self, data, destinationId=BROADCAST_ADDR,
portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False, portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
wantResponse=False, wantResponse=False,
hopLimit=None,
onResponse=None, onResponse=None,
channelIndex=0): channelIndex=0):
"""Send a data packet to some other node """Send a data packet to some other node
@@ -244,6 +234,8 @@ class MeshInterface:
Returns the sent packet. The id field will be populated in this packet Returns the sent packet. The id field will be populated in this packet
and can be used to track future message acks/naks. and can be used to track future message acks/naks.
""" """
if hopLimit is None:
hopLimit = self.defaultHopLimit
if getattr(data, "SerializeToString", None): if getattr(data, "SerializeToString", None):
logging.debug(f"Serializing protobuf as data: {stripnl(data)}") logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
@@ -266,7 +258,8 @@ class MeshInterface:
if onResponse is not None: if onResponse is not None:
self._addResponseHandler(meshPacket.id, onResponse) self._addResponseHandler(meshPacket.id, onResponse)
p = self._sendPacket(meshPacket, destinationId, wantAck=wantAck) p = self._sendPacket(meshPacket, destinationId,
wantAck=wantAck, hopLimit=hopLimit)
return p return p
def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0, def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
@@ -305,43 +298,20 @@ class MeshInterface:
wantAck=wantAck, wantAck=wantAck,
wantResponse=wantResponse) wantResponse=wantResponse)
def sendTraceRoute(self, dest, hopLimit):
"""Send the trace route"""
r = mesh_pb2.RouteDiscovery()
self.sendData(r, destinationId=dest, portNum=portnums_pb2.PortNum.TRACEROUTE_APP,
wantResponse=True, onResponse=self.onResponseTraceRoute)
# extend timeout based on number of nodes, limit by configured hopLimit
waitFactor = min(len(self.nodes)-1, hopLimit)
self.waitForTraceRoute(waitFactor)
def onResponseTraceRoute(self, p):
"""on response for trace route"""
routeDiscovery = mesh_pb2.RouteDiscovery()
routeDiscovery.ParseFromString(p["decoded"]["payload"])
asDict = google.protobuf.json_format.MessageToDict(routeDiscovery)
print("Route traced:")
routeStr = self._nodeNumToId(p["to"])
if "route" in asDict:
for nodeNum in asDict["route"]:
routeStr += " --> " + self._nodeNumToId(nodeNum)
routeStr += " --> " + self._nodeNumToId(p["from"])
print(routeStr)
self._acknowledgment.receivedTraceRoute = True
def _addResponseHandler(self, requestId, callback): def _addResponseHandler(self, requestId, callback):
self.responseHandlers[requestId] = ResponseHandler(callback) self.responseHandlers[requestId] = ResponseHandler(callback)
def _sendPacket(self, meshPacket, def _sendPacket(self, meshPacket,
destinationId=BROADCAST_ADDR, destinationId=BROADCAST_ADDR,
wantAck=False): wantAck=False, hopLimit=None):
"""Send a MeshPacket to the specified node (or if unspecified, broadcast). """Send a MeshPacket to the specified node (or if unspecified, broadcast).
You probably don't want this - use sendData instead. You probably don't want this - use sendData instead.
Returns the sent packet. The id field will be populated in this packet and Returns the sent packet. The id field will be populated in this packet and
can be used to track future message acks/naks. can be used to track future message acks/naks.
""" """
if hopLimit is None:
hopLimit = self.defaultHopLimit
# We allow users to talk to the local node before we've completed the full connection flow... # We allow users to talk to the local node before we've completed the full connection flow...
if(self.myInfo is not None and destinationId != self.myInfo.my_node_num): if(self.myInfo is not None and destinationId != self.myInfo.my_node_num):
@@ -375,8 +345,6 @@ class MeshInterface:
meshPacket.to = nodeNum meshPacket.to = nodeNum
meshPacket.want_ack = wantAck meshPacket.want_ack = wantAck
loraConfig = getattr(self.localNode.localConfig, 'lora')
hopLimit = getattr(loraConfig, 'hop_limit')
meshPacket.hop_limit = hopLimit meshPacket.hop_limit = hopLimit
# if the user hasn't set an ID for this packet (likely and recommended), # if the user hasn't set an ID for this packet (likely and recommended),
@@ -398,18 +366,6 @@ class MeshInterface:
if not success: if not success:
raise Exception("Timed out waiting for interface config") raise Exception("Timed out waiting for interface config")
def waitForAckNak(self):
"""Wait for the ack/nak"""
success = self._timeout.waitForAckNak(self._acknowledgment)
if not success:
raise Exception("Timed out waiting for an acknowledgment")
def waitForTraceRoute(self, waitFactor):
"""Wait for trace route"""
success = self._timeout.waitForTraceRoute(waitFactor, self._acknowledgment)
if not success:
raise Exception("Timed out waiting for traceroute")
def getMyNodeInfo(self): def getMyNodeInfo(self):
"""Get info about my node.""" """Get info about my node."""
if self.myInfo is None: if self.myInfo is None:
@@ -522,7 +478,7 @@ class MeshInterface:
Done with initial config messages, now send regular MeshPackets Done with initial config messages, now send regular MeshPackets
to ask for settings and channels to ask for settings and channels
""" """
self.localNode.requestChannels() self.localNode.requestConfig()
def _handleFromRadio(self, fromRadioBytes): def _handleFromRadio(self, fromRadioBytes):
""" """
@@ -615,10 +571,6 @@ class MeshInterface:
self.localNode.moduleConfig.telemetry.CopyFrom(fromRadio.moduleConfig.telemetry) self.localNode.moduleConfig.telemetry.CopyFrom(fromRadio.moduleConfig.telemetry)
elif fromRadio.moduleConfig.HasField("canned_message"): elif fromRadio.moduleConfig.HasField("canned_message"):
self.localNode.moduleConfig.canned_message.CopyFrom(fromRadio.moduleConfig.canned_message) self.localNode.moduleConfig.canned_message.CopyFrom(fromRadio.moduleConfig.canned_message)
elif fromRadio.moduleConfig.HasField("audio"):
self.localNode.moduleConfig.audio.CopyFrom(fromRadio.moduleConfig.audio)
elif fromRadio.moduleConfig.HasField("remote_hardware"):
self.localNode.moduleConfig.remote_hardware.CopyFrom(fromRadio.moduleConfig.remote_hardware)
else: else:
logging.debug("Unexpected FromRadio payload") logging.debug("Unexpected FromRadio payload")
@@ -765,8 +717,7 @@ class MeshInterface:
# we keep the responseHandler in dict until we get a non ack # we keep the responseHandler in dict until we get a non ack
handler = self.responseHandlers.pop(requestId, None) handler = self.responseHandlers.pop(requestId, None)
if handler is not None: if handler is not None:
if not isAck or (isAck and handler.__name__ == "onAckNak"): handler.callback(asDict)
handler.callback(asDict)
logging.debug(f"Publishing {topic}: packet={stripnl(asDict)} ") logging.debug(f"Publishing {topic}: packet={stripnl(asDict)} ")
publishingThread.queueWork(lambda: pub.sendMessage( publishingThread.queueWork(lambda: pub.sendMessage(

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/mqtt.proto # source: mqtt.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -12,17 +12,17 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
from meshtastic import mesh_pb2 as meshtastic_dot_mesh__pb2 from . import mesh_pb2 as mesh__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15meshtastic/mqtt.proto\x1a\x15meshtastic/mesh.proto\"V\n\x0fServiceEnvelope\x12\x1b\n\x06packet\x18\x01 \x01(\x0b\x32\x0b.MeshPacket\x12\x12\n\nchannel_id\x18\x02 \x01(\t\x12\x12\n\ngateway_id\x18\x03 \x01(\tB_\n\x13\x63om.geeksville.meshB\nMQTTProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nmqtt.proto\x1a\nmesh.proto\"V\n\x0fServiceEnvelope\x12\x1b\n\x06packet\x18\x01 \x01(\x0b\x32\x0b.MeshPacket\x12\x12\n\nchannel_id\x18\x02 \x01(\t\x12\x12\n\ngateway_id\x18\x03 \x01(\tBG\n\x13\x63om.geeksville.meshB\nMQTTProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
_SERVICEENVELOPE = DESCRIPTOR.message_types_by_name['ServiceEnvelope'] _SERVICEENVELOPE = DESCRIPTOR.message_types_by_name['ServiceEnvelope']
ServiceEnvelope = _reflection.GeneratedProtocolMessageType('ServiceEnvelope', (_message.Message,), { ServiceEnvelope = _reflection.GeneratedProtocolMessageType('ServiceEnvelope', (_message.Message,), {
'DESCRIPTOR' : _SERVICEENVELOPE, 'DESCRIPTOR' : _SERVICEENVELOPE,
'__module__' : 'meshtastic.mqtt_pb2' '__module__' : 'mqtt_pb2'
# @@protoc_insertion_point(class_scope:ServiceEnvelope) # @@protoc_insertion_point(class_scope:ServiceEnvelope)
}) })
_sym_db.RegisterMessage(ServiceEnvelope) _sym_db.RegisterMessage(ServiceEnvelope)
@@ -30,7 +30,7 @@ _sym_db.RegisterMessage(ServiceEnvelope)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nMQTTProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nMQTTProtosH\003Z\"github.com/meshtastic/go/generated'
_SERVICEENVELOPE._serialized_start=48 _SERVICEENVELOPE._serialized_start=26
_SERVICEENVELOPE._serialized_end=134 _SERVICEENVELOPE._serialized_end=112
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -6,7 +6,7 @@ import base64
import time import time
from google.protobuf.json_format import MessageToJson from google.protobuf.json_format import MessageToJson
from meshtastic import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2, localonly_pb2 from meshtastic import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2, localonly_pb2
from meshtastic.util import pskToString, stripnl, Timeout, our_exit, fromPSK, camel_to_snake from meshtastic.util import pskToString, stripnl, Timeout, our_exit, fromPSK
class Node: class Node:
@@ -26,9 +26,8 @@ class Node:
self.partialChannels = None self.partialChannels = None
self.noProto = noProto self.noProto = noProto
self.cannedPluginMessage = None self.cannedPluginMessage = None
self.cannedPluginMessageMessages = None self.cannedPluginMessageMessages = None
self.ringtone = None
self.ringtonePart = None
self.gotResponse = None self.gotResponse = None
@@ -61,60 +60,13 @@ class Node:
print(f"Module preferences: {prefs}\n") print(f"Module preferences: {prefs}\n")
self.showChannels() self.showChannels()
def requestChannels(self): def requestConfig(self):
"""Send regular MeshPackets to ask channels.""" """Send regular MeshPackets to ask for settings and channels."""
logging.debug(f"requestChannels for nodeNum:{self.nodeNum}") logging.debug(f"requestConfig for nodeNum:{self.nodeNum}")
self.channels = None self.channels = None
self.partialChannels = [] # We keep our channels in a temp array until finished self.partialChannels = [] # We keep our channels in a temp array until finished
self._requestChannel(0) self._requestChannel(0)
def onResponseRequestSettings(self, p):
"""Handle the response packets for requesting settings _requestSettings()"""
logging.debug(f'onResponseRequestSetting() p:{p}')
if "routing" in p["decoded"]:
if p["decoded"]["routing"]["errorReason"] != "NONE":
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
self.iface._acknowledgment.receivedNak = True
else:
self.iface._acknowledgment.receivedAck = True
print("")
adminMessage = p["decoded"]["admin"]
if "getConfigResponse" in adminMessage:
resp = adminMessage["getConfigResponse"]
field = list(resp.keys())[0]
config_type = self.localConfig.DESCRIPTOR.fields_by_name.get(camel_to_snake(field))
config_values = getattr(self.localConfig, config_type.name)
elif "getModuleConfigResponse" in adminMessage:
resp = adminMessage["getModuleConfigResponse"]
field = list(resp.keys())[0]
config_type = self.moduleConfig.DESCRIPTOR.fields_by_name.get(camel_to_snake(field))
config_values = getattr(self.moduleConfig, config_type.name)
else:
print("Did not receive a valid response. Make sure to have a shared channel named 'admin'.")
return
for key, value in resp[field].items():
setattr(config_values, camel_to_snake(key), value)
print(f"{str(camel_to_snake(field))}:\n{str(config_values)}")
def requestConfig(self, configType):
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onResponseRequestSettings
print("Requesting current config from remote node (this can take a while).")
msgIndex = configType.index
if configType.containing_type.full_name == "LocalConfig":
p = admin_pb2.AdminMessage()
p.get_config_request = msgIndex
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
else:
p = admin_pb2.AdminMessage()
p.get_module_config_request = msgIndex
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
if onResponse:
self.iface.waitForAckNak()
def turnOffEncryptionOnPrimaryChannel(self): def turnOffEncryptionOnPrimaryChannel(self):
"""Turn off encryption on primary channel.""" """Turn off encryption on primary channel."""
@@ -229,20 +181,6 @@ class Node:
logging.debug("Wrote module: canned_message") logging.debug("Wrote module: canned_message")
time.sleep(0.3) time.sleep(0.3)
if self.moduleConfig.audio:
p = admin_pb2.AdminMessage()
p.set_module_config.audio.CopyFrom(self.moduleConfig.audio)
self._sendAdmin(p)
logging.debug("Wrote module: audio")
time.sleep(0.3)
if self.moduleConfig.remote_hardware:
p = admin_pb2.AdminMessage()
p.set_module_config.remote_hardware.CopyFrom(self.moduleConfig.remote_hardware)
self._sendAdmin(p)
logging.debug("Wrote module: remote_hardware")
time.sleep(0.3)
def writeConfig(self, config_name): def writeConfig(self, config_name):
"""Write the current (edited) localConfig to the device""" """Write the current (edited) localConfig to the device"""
if self.localConfig is None: if self.localConfig is None:
@@ -278,19 +216,11 @@ class Node:
p.set_module_config.telemetry.CopyFrom(self.moduleConfig.telemetry) p.set_module_config.telemetry.CopyFrom(self.moduleConfig.telemetry)
elif config_name == 'canned_message': elif config_name == 'canned_message':
p.set_module_config.canned_message.CopyFrom(self.moduleConfig.canned_message) p.set_module_config.canned_message.CopyFrom(self.moduleConfig.canned_message)
elif config_name == 'audio':
p.set_module_config.audio.CopyFrom(self.moduleConfig.audio)
elif config_name == 'remote_hardware':
p.set_module_config.remote_hardware.CopyFrom(self.moduleConfig.remote_hardware)
else: else:
our_exit(f"Error: No valid config with name {config_name}") our_exit(f"Error: No valid config with name {config_name}")
logging.debug(f"Wrote: {config_name}") logging.debug(f"Wrote: {config_name}")
if self == self.iface.localNode: self._sendAdmin(p)
onResponse = None
else:
onResponse = self.onAckNak
self._sendAdmin(p, onResponse=onResponse)
def writeChannel(self, channelIndex, adminIndex=0): def writeChannel(self, channelIndex, adminIndex=0):
"""Write the current (edited) channel to the device""" """Write the current (edited) channel to the device"""
@@ -360,30 +290,38 @@ class Node:
def setOwner(self, long_name=None, short_name=None, is_licensed=False): def setOwner(self, long_name=None, short_name=None, is_licensed=False):
"""Set device owner name""" """Set device owner name"""
logging.debug(f"in setOwner nodeNum:{self.nodeNum}") logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
p = admin_pb2.AdminMessage() nChars = 3
minChars = 2
nChars = 4
if long_name is not None: if long_name is not None:
long_name = long_name.strip() long_name = long_name.strip()
if short_name is None:
words = long_name.split()
if len(long_name) <= nChars:
short_name = long_name
elif len(words) >= minChars:
short_name = ''.join(map(lambda word: word[0], words))
else:
trans = str.maketrans(dict.fromkeys('aeiouAEIOU'))
short_name = long_name[0] + long_name[1:].translate(trans)
if len(short_name) < nChars:
short_name = long_name[:nChars]
p = admin_pb2.AdminMessage()
if long_name is not None:
p.set_owner.long_name = long_name p.set_owner.long_name = long_name
p.set_owner.is_licensed = is_licensed
if short_name is not None: if short_name is not None:
short_name = short_name.strip() short_name = short_name.strip()
if len(short_name) > nChars: if len(short_name) > nChars:
short_name = short_name[:nChars] short_name = short_name[:nChars]
print(f"Maximum is 4 characters, truncated to {short_name}")
p.set_owner.short_name = short_name p.set_owner.short_name = short_name
p.set_owner.is_licensed = is_licensed
# Note: These debug lines are used in unit tests # Note: These debug lines are used in unit tests
logging.debug(f'p.set_owner.long_name:{p.set_owner.long_name}:') logging.debug(f'p.set_owner.long_name:{p.set_owner.long_name}:')
logging.debug(f'p.set_owner.short_name:{p.set_owner.short_name}:') logging.debug(f'p.set_owner.short_name:{p.set_owner.short_name}:')
logging.debug(f'p.set_owner.is_licensed:{p.set_owner.is_licensed}') logging.debug(f'p.set_owner.is_licensed:{p.set_owner.is_licensed}')
# If sending to a remote node, wait for ACK/NAK return self._sendAdmin(p)
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def getURL(self, includeAll: bool = True): def getURL(self, includeAll: bool = True):
"""The sharable URL that describes the current channel""" """The sharable URL that describes the current channel"""
@@ -398,14 +336,14 @@ class Node:
some_bytes = channelSet.SerializeToString() some_bytes = channelSet.SerializeToString()
s = base64.urlsafe_b64encode(some_bytes).decode('ascii') s = base64.urlsafe_b64encode(some_bytes).decode('ascii')
s = s.replace("=", "").replace("+", "-").replace("/", "_") s = s.replace("=", "").replace("+", "-").replace("/", "_")
return f"https://meshtastic.org/e/#{s}" return f"https://www.meshtastic.org/e/#{s}"
def setURL(self, url): def setURL(self, url):
"""Set mesh network URL""" """Set mesh network URL"""
if self.localConfig is None: if self.localConfig is None:
our_exit("Warning: No Config has been read") our_exit("Warning: No Config has been read")
# URLs are of the form https://meshtastic.org/d/#{base64_channel_set} # URLs are of the form https://www.meshtastic.org/d/#{base64_channel_set}
# Split on '/#' to find the base64 encoded channel settings # Split on '/#' to find the base64 encoded channel settings
splitURL = url.split("/#") splitURL = url.split("/#")
b64 = splitURL[-1] b64 = splitURL[-1]
@@ -440,73 +378,6 @@ class Node:
p.set_config.lora.CopyFrom(channelSet.lora_config) p.set_config.lora.CopyFrom(channelSet.lora_config)
self._sendAdmin(p) self._sendAdmin(p)
def onResponseRequestRingtone(self, p):
"""Handle the response packet for requesting ringtone part 1"""
logging.debug(f'onResponseRequestRingtone() p:{p}')
errorFound = False
if "routing" in p["decoded"]:
if p["decoded"]["routing"]["errorReason"] != "NONE":
errorFound = True
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
if errorFound is False:
if "decoded" in p:
if "admin" in p["decoded"]:
if "raw" in p["decoded"]["admin"]:
self.ringtonePart = p["decoded"]["admin"]["raw"].get_ringtone_response
logging.debug(f'self.ringtonePart:{self.ringtonePart}')
self.gotResponse = True
def get_ringtone(self):
"""Get the ringtone. Concatenate all pieces together and return a single string."""
logging.debug(f'in get_ringtone()')
if not self.ringtone:
p1 = admin_pb2.AdminMessage()
p1.get_ringtone_request = True
self.gotResponse = False
self._sendAdmin(p1, wantResponse=True, onResponse=self.onResponseRequestRingtone)
while self.gotResponse is False:
time.sleep(0.1)
logging.debug(f'self.ringtone:{self.ringtone}')
self.ringtone = ""
if self.ringtonePart:
self.ringtone += self.ringtonePart
print(f'ringtone:{self.ringtone}')
logging.debug(f'ringtone:{self.ringtone}')
return self.ringtone
def set_ringtone(self, ringtone):
"""Set the ringtone. The ringtone length must be less than 230 character."""
if len(ringtone) > 230:
our_exit("Warning: The ringtone must be less than 230 characters.")
# split into chunks
chunks = []
chunks_size = 230
for i in range(0, len(ringtone), chunks_size):
chunks.append(ringtone[i: i + chunks_size])
# for each chunk, send a message to set the values
#for i in range(0, len(chunks)):
for i, chunk in enumerate(chunks):
p = admin_pb2.AdminMessage()
# TODO: should be a way to improve this
if i == 0:
p.set_ringtone_message = chunk
logging.debug(f"Setting ringtone '{chunk}' part {i+1}")
# If sending to a remote node, wait for ACK/NAK
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def onResponseRequestCannedMessagePluginMessageMessages(self, p): def onResponseRequestCannedMessagePluginMessageMessages(self, p):
"""Handle the response packet for requesting canned message plugin message part 1""" """Handle the response packet for requesting canned message plugin message part 1"""
logging.debug(f'onResponseRequestCannedMessagePluginMessageMessages() p:{p}') logging.debug(f'onResponseRequestCannedMessagePluginMessageMessages() p:{p}')
@@ -568,12 +439,7 @@ class Node:
p.set_canned_message_module_messages = chunk p.set_canned_message_module_messages = chunk
logging.debug(f"Setting canned message '{chunk}' part {i+1}") logging.debug(f"Setting canned message '{chunk}' part {i+1}")
# If sending to a remote node, wait for ACK/NAK self._sendAdmin(p)
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def exitSimulator(self): def exitSimulator(self):
"""Tell a simulator node to exit (this message """Tell a simulator node to exit (this message
@@ -590,38 +456,7 @@ class Node:
p.reboot_seconds = secs p.reboot_seconds = secs
logging.info(f"Telling node to reboot in {secs} seconds") logging.info(f"Telling node to reboot in {secs} seconds")
# If sending to a remote node, wait for ACK/NAK return self._sendAdmin(p)
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def beginSettingsTransaction(self):
"""Tell the node to open a transaction to edit settings."""
p = admin_pb2.AdminMessage()
p.begin_edit_settings = True
logging.info(f"Telling open a transaction to edit settings")
# If sending to a remote node, wait for ACK/NAK
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def commitSettingsTransaction(self):
"""Tell the node to commit the open transaction for editing settings."""
p = admin_pb2.AdminMessage()
p.commit_edit_settings = True
logging.info(f"Telling node to commit open transaction for editing settings")
# If sending to a remote node, wait for ACK/NAK
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def rebootOTA(self, secs: int = 10): def rebootOTA(self, secs: int = 10):
"""Tell the node to reboot into factory firmware.""" """Tell the node to reboot into factory firmware."""
@@ -629,12 +464,7 @@ class Node:
p.reboot_ota_seconds = secs p.reboot_ota_seconds = secs
logging.info(f"Telling node to reboot to OTA in {secs} seconds") logging.info(f"Telling node to reboot to OTA in {secs} seconds")
# If sending to a remote node, wait for ACK/NAK return self._sendAdmin(p)
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def shutdown(self, secs: int = 10): def shutdown(self, secs: int = 10):
"""Tell the node to shutdown.""" """Tell the node to shutdown."""
@@ -642,15 +472,10 @@ class Node:
p.shutdown_seconds = secs p.shutdown_seconds = secs
logging.info(f"Telling node to shutdown in {secs} seconds") logging.info(f"Telling node to shutdown in {secs} seconds")
# If sending to a remote node, wait for ACK/NAK return self._sendAdmin(p)
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def getMetadata(self): def getMetadata(self, secs: int = 10):
"""Get the node's metadata.""" """Tell the node to shutdown."""
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.get_device_metadata_request = True p.get_device_metadata_request = True
logging.info(f"Requesting device metadata") logging.info(f"Requesting device metadata")
@@ -663,12 +488,7 @@ class Node:
p.factory_reset = True p.factory_reset = True
logging.info(f"Telling node to factory reset") logging.info(f"Telling node to factory reset")
# If sending to a remote node, wait for ACK/NAK return self._sendAdmin(p)
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def resetNodeDb(self): def resetNodeDb(self):
"""Tell the node to reset its list of nodes.""" """Tell the node to reset its list of nodes."""
@@ -676,12 +496,7 @@ class Node:
p.nodedb_reset = True p.nodedb_reset = True
logging.info(f"Telling node to reset the NodeDB") logging.info(f"Telling node to reset the NodeDB")
# If sending to a remote node, wait for ACK/NAK return self._sendAdmin(p)
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def _fixupChannels(self): def _fixupChannels(self):
"""Fixup indexes and add disabled channels as needed""" """Fixup indexes and add disabled channels as needed"""
@@ -736,7 +551,7 @@ class Node:
return # Don't try to parse this routing message return # Don't try to parse this routing message
lastTried = 0 lastTried = 0
if len(self.partialChannels) > 0: if len(self.partialChannels) > 0:
lastTried = self.partialChannels[-1].index lastTried = self.partialChannels[-1]
logging.debug(f"Retrying previous channel request.") logging.debug(f"Retrying previous channel request.")
self._requestChannel(lastTried) self._requestChannel(lastTried)
return return
@@ -765,18 +580,6 @@ class Node:
else: else:
self._requestChannel(index + 1) self._requestChannel(index + 1)
def onAckNak(self, p):
if p["decoded"]["routing"]["errorReason"] != "NONE":
print(f'Received a NAK, error reason: {p["decoded"]["routing"]["errorReason"]}')
self.iface._acknowledgment.receivedNak = True
else:
if int(p["from"]) == self.iface.localNode.nodeNum:
print(f'Received an implicit ACK. Packet will likely arrive, but cannot be guaranteed.')
self.iface._acknowledgment.receivedImplAck = True
else:
print(f'Received an ACK.')
self.iface._acknowledgment.receivedAck = True
def _requestChannel(self, channelNum: int): def _requestChannel(self, channelNum: int):
"""Done with initial config messages, now send regular """Done with initial config messages, now send regular
MeshPackets to ask for settings""" MeshPackets to ask for settings"""
@@ -794,7 +597,7 @@ class Node:
# pylint: disable=R1710 # pylint: disable=R1710
def _sendAdmin(self, p: admin_pb2.AdminMessage, wantResponse=True, def _sendAdmin(self, p: admin_pb2.AdminMessage, wantResponse=False,
onResponse=None, adminIndex=0): onResponse=None, adminIndex=0):
"""Send an admin message to the specified node (or the local node if destNodeNum is zero)""" """Send an admin message to the specified node (or the local node if destNodeNum is zero)"""
@@ -804,10 +607,10 @@ class Node:
if adminIndex == 0: # unless a special channel index was used, we want to use the admin index if adminIndex == 0: # unless a special channel index was used, we want to use the admin index
adminIndex = self.iface.localNode._getAdminChannelIndex() adminIndex = self.iface.localNode._getAdminChannelIndex()
logging.debug(f'adminIndex:{adminIndex}') logging.debug(f'adminIndex:{adminIndex}')
return self.iface.sendData(p, self.nodeNum, return self.iface.sendData(p, self.nodeNum,
portNum=portnums_pb2.PortNum.ADMIN_APP, portNum=portnums_pb2.PortNum.ADMIN_APP,
wantAck=False, wantAck=True,
wantResponse=wantResponse, wantResponse=wantResponse,
onResponse=onResponse, onResponse=onResponse,
channelIndex=adminIndex) channelIndex=adminIndex)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/portnums.proto # source: portnums.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf.internal import enum_type_wrapper from google.protobuf.internal import enum_type_wrapper
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
@@ -15,7 +15,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19meshtastic/portnums.proto*\xa4\x03\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eportnums.proto*\x81\x03\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42\x45\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
_PORTNUM = DESCRIPTOR.enum_types_by_name['PortNum'] _PORTNUM = DESCRIPTOR.enum_types_by_name['PortNum']
PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM) PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM)
@@ -28,7 +28,6 @@ ROUTING_APP = 5
ADMIN_APP = 6 ADMIN_APP = 6
TEXT_MESSAGE_COMPRESSED_APP = 7 TEXT_MESSAGE_COMPRESSED_APP = 7
WAYPOINT_APP = 8 WAYPOINT_APP = 8
AUDIO_APP = 9
REPLY_APP = 32 REPLY_APP = 32
IP_TUNNEL_APP = 33 IP_TUNNEL_APP = 33
SERIAL_APP = 64 SERIAL_APP = 64
@@ -37,7 +36,6 @@ RANGE_TEST_APP = 66
TELEMETRY_APP = 67 TELEMETRY_APP = 67
ZPS_APP = 68 ZPS_APP = 68
SIMULATOR_APP = 69 SIMULATOR_APP = 69
TRACEROUTE_APP = 70
PRIVATE_APP = 256 PRIVATE_APP = 256
ATAK_FORWARDER = 257 ATAK_FORWARDER = 257
MAX = 511 MAX = 511
@@ -46,7 +44,7 @@ MAX = 511
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsH\003Z\"github.com/meshtastic/go/generated'
_PORTNUM._serialized_start=30 _PORTNUM._serialized_start=19
_PORTNUM._serialized_end=450 _PORTNUM._serialized_end=404
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -23,7 +23,7 @@ def onGPIOreceive(packet, interface):
#print(f'mask:{interface.mask}') #print(f'mask:{interface.mask}')
value = int(gpioValue) & int(interface.mask) value = int(gpioValue) & int(interface.mask)
print(f'Received RemoteHardware type={hw["type"]}, gpio_value={gpioValue} value={value}') print(f'Received RemoteHardware typ={hw["typ"]}, gpio_value={gpioValue} value={value}')
interface.gotResponse = True interface.gotResponse = True
@@ -66,7 +66,7 @@ class RemoteHardwareClient:
""" """
logging.debug(f'writeGPIOs nodeid:{nodeid} mask:{mask} vals:{vals}') logging.debug(f'writeGPIOs nodeid:{nodeid} mask:{mask} vals:{vals}')
r = remote_hardware_pb2.HardwareMessage() r = remote_hardware_pb2.HardwareMessage()
r.type = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
r.gpio_mask = mask r.gpio_mask = mask
r.gpio_value = vals r.gpio_value = vals
return self._sendHardware(nodeid, r) return self._sendHardware(nodeid, r)
@@ -75,7 +75,7 @@ class RemoteHardwareClient:
"""Read the specified bits from GPIO inputs on the device""" """Read the specified bits from GPIO inputs on the device"""
logging.debug(f'readGPIOs nodeid:{nodeid} mask:{mask}') logging.debug(f'readGPIOs nodeid:{nodeid} mask:{mask}')
r = remote_hardware_pb2.HardwareMessage() r = remote_hardware_pb2.HardwareMessage()
r.type = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
r.gpio_mask = mask r.gpio_mask = mask
return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse) return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)
@@ -83,7 +83,7 @@ class RemoteHardwareClient:
"""Watch the specified bits from GPIO inputs on the device for changes""" """Watch the specified bits from GPIO inputs on the device for changes"""
logging.debug(f'watchGPIOs nodeid:{nodeid} mask:{mask}') logging.debug(f'watchGPIOs nodeid:{nodeid} mask:{mask}')
r = remote_hardware_pb2.HardwareMessage() r = remote_hardware_pb2.HardwareMessage()
r.type = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
r.gpio_mask = mask r.gpio_mask = mask
self.iface.mask = mask self.iface.mask = mask
return self._sendHardware(nodeid, r) return self._sendHardware(nodeid, r)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/remote_hardware.proto # source: remote_hardware.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/remote_hardware.proto\"\xcb\x01\n\x0fHardwareMessage\x12#\n\x04type\x18\x01 \x01(\x0e\x32\x15.HardwareMessage.Type\x12\x11\n\tgpio_mask\x18\x02 \x01(\x04\x12\x12\n\ngpio_value\x18\x03 \x01(\x04\"l\n\x04Type\x12\t\n\x05UNSET\x10\x00\x12\x0f\n\x0bWRITE_GPIOS\x10\x01\x12\x0f\n\x0bWATCH_GPIOS\x10\x02\x12\x11\n\rGPIOS_CHANGED\x10\x03\x12\x0e\n\nREAD_GPIOS\x10\x04\x12\x14\n\x10READ_GPIOS_REPLY\x10\x05\x42\x63\n\x13\x63om.geeksville.meshB\x0eRemoteHardwareZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15remote_hardware.proto\"\xcb\x01\n\x0fHardwareMessage\x12#\n\x04type\x18\x01 \x01(\x0e\x32\x15.HardwareMessage.Type\x12\x11\n\tgpio_mask\x18\x02 \x01(\x04\x12\x12\n\ngpio_value\x18\x03 \x01(\x04\"l\n\x04Type\x12\t\n\x05UNSET\x10\x00\x12\x0f\n\x0bWRITE_GPIOS\x10\x01\x12\x0f\n\x0bWATCH_GPIOS\x10\x02\x12\x11\n\rGPIOS_CHANGED\x10\x03\x12\x0e\n\nREAD_GPIOS\x10\x04\x12\x14\n\x10READ_GPIOS_REPLY\x10\x05\x42K\n\x13\x63om.geeksville.meshB\x0eRemoteHardwareH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
@@ -22,7 +22,7 @@ _HARDWAREMESSAGE = DESCRIPTOR.message_types_by_name['HardwareMessage']
_HARDWAREMESSAGE_TYPE = _HARDWAREMESSAGE.enum_types_by_name['Type'] _HARDWAREMESSAGE_TYPE = _HARDWAREMESSAGE.enum_types_by_name['Type']
HardwareMessage = _reflection.GeneratedProtocolMessageType('HardwareMessage', (_message.Message,), { HardwareMessage = _reflection.GeneratedProtocolMessageType('HardwareMessage', (_message.Message,), {
'DESCRIPTOR' : _HARDWAREMESSAGE, 'DESCRIPTOR' : _HARDWAREMESSAGE,
'__module__' : 'meshtastic.remote_hardware_pb2' '__module__' : 'remote_hardware_pb2'
# @@protoc_insertion_point(class_scope:HardwareMessage) # @@protoc_insertion_point(class_scope:HardwareMessage)
}) })
_sym_db.RegisterMessage(HardwareMessage) _sym_db.RegisterMessage(HardwareMessage)
@@ -30,9 +30,9 @@ _sym_db.RegisterMessage(HardwareMessage)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016RemoteHardwareZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016RemoteHardwareH\003Z\"github.com/meshtastic/go/generated'
_HARDWAREMESSAGE._serialized_start=37 _HARDWAREMESSAGE._serialized_start=26
_HARDWAREMESSAGE._serialized_end=240 _HARDWAREMESSAGE._serialized_end=229
_HARDWAREMESSAGE_TYPE._serialized_start=132 _HARDWAREMESSAGE_TYPE._serialized_start=121
_HARDWAREMESSAGE_TYPE._serialized_end=240 _HARDWAREMESSAGE_TYPE._serialized_end=229
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/rtttl.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16meshtastic/rtttl.proto\"\x1f\n\x0bRTTTLConfig\x12\x10\n\x08ringtone\x18\x01 \x01(\tBf\n\x13\x63om.geeksville.meshB\x11RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_RTTTLCONFIG = DESCRIPTOR.message_types_by_name['RTTTLConfig']
RTTTLConfig = _reflection.GeneratedProtocolMessageType('RTTTLConfig', (_message.Message,), {
'DESCRIPTOR' : _RTTTLCONFIG,
'__module__' : 'meshtastic.rtttl_pb2'
# @@protoc_insertion_point(class_scope:RTTTLConfig)
})
_sym_db.RegisterMessage(RTTTLConfig)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\021RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_RTTTLCONFIG._serialized_start=26
_RTTTLCONFIG._serialized_end=57
# @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/storeforward.proto # source: storeforward.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import descriptor_pool as _descriptor_pool
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dmeshtastic/storeforward.proto\"\xbe\x06\n\x0fStoreAndForward\x12,\n\x02rr\x18\x01 \x01(\x0e\x32 .StoreAndForward.RequestResponse\x12,\n\x05stats\x18\x02 \x01(\x0b\x32\x1b.StoreAndForward.StatisticsH\x00\x12+\n\x07history\x18\x03 \x01(\x0b\x32\x18.StoreAndForward.HistoryH\x00\x12/\n\theartbeat\x18\x04 \x01(\x0b\x32\x1a.StoreAndForward.HeartbeatH\x00\x12\x0f\n\x05\x65mpty\x18\x05 \x01(\x08H\x00\x1a\xcd\x01\n\nStatistics\x12\x16\n\x0emessages_total\x18\x01 \x01(\r\x12\x16\n\x0emessages_saved\x18\x02 \x01(\r\x12\x14\n\x0cmessages_max\x18\x03 \x01(\r\x12\x0f\n\x07up_time\x18\x04 \x01(\r\x12\x10\n\x08requests\x18\x05 \x01(\r\x12\x18\n\x10requests_history\x18\x06 \x01(\r\x12\x11\n\theartbeat\x18\x07 \x01(\x08\x12\x12\n\nreturn_max\x18\x08 \x01(\r\x12\x15\n\rreturn_window\x18\t \x01(\r\x1aI\n\x07History\x12\x18\n\x10history_messages\x18\x01 \x01(\r\x12\x0e\n\x06window\x18\x02 \x01(\r\x12\x14\n\x0clast_request\x18\x03 \x01(\r\x1a.\n\tHeartbeat\x12\x0e\n\x06period\x18\x01 \x01(\r\x12\x11\n\tsecondary\x18\x02 \x01(\r\"\x89\x02\n\x0fRequestResponse\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0cROUTER_ERROR\x10\x01\x12\x14\n\x10ROUTER_HEARTBEAT\x10\x02\x12\x0f\n\x0bROUTER_PING\x10\x03\x12\x0f\n\x0bROUTER_PONG\x10\x04\x12\x0f\n\x0bROUTER_BUSY\x10\x05\x12\x12\n\x0eROUTER_HISTORY\x10\x06\x12\x10\n\x0cROUTER_STATS\x10\x07\x12\x10\n\x0c\x43LIENT_ERROR\x10@\x12\x12\n\x0e\x43LIENT_HISTORY\x10\x41\x12\x10\n\x0c\x43LIENT_STATS\x10\x42\x12\x0f\n\x0b\x43LIENT_PING\x10\x43\x12\x0f\n\x0b\x43LIENT_PONG\x10\x44\x12\x10\n\x0c\x43LIENT_ABORT\x10jB\t\n\x07variantBj\n\x13\x63om.geeksville.meshB\x15StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12storeforward.proto\"\x8a\x06\n\x0fStoreAndForward\x12,\n\x02rr\x18\x01 \x01(\x0e\x32 .StoreAndForward.RequestResponse\x12*\n\x05stats\x18\x02 \x01(\x0b\x32\x1b.StoreAndForward.Statistics\x12)\n\x07history\x18\x03 \x01(\x0b\x32\x18.StoreAndForward.History\x12-\n\theartbeat\x18\x04 \x01(\x0b\x32\x1a.StoreAndForward.Heartbeat\x1a\xcd\x01\n\nStatistics\x12\x16\n\x0emessages_total\x18\x01 \x01(\r\x12\x16\n\x0emessages_saved\x18\x02 \x01(\r\x12\x14\n\x0cmessages_max\x18\x03 \x01(\r\x12\x0f\n\x07up_time\x18\x04 \x01(\r\x12\x10\n\x08requests\x18\x05 \x01(\r\x12\x18\n\x10requests_history\x18\x06 \x01(\r\x12\x11\n\theartbeat\x18\x07 \x01(\x08\x12\x12\n\nreturn_max\x18\x08 \x01(\r\x12\x15\n\rreturn_window\x18\t \x01(\r\x1aI\n\x07History\x12\x18\n\x10history_messages\x18\x01 \x01(\r\x12\x0e\n\x06window\x18\x02 \x01(\r\x12\x14\n\x0clast_request\x18\x03 \x01(\r\x1a.\n\tHeartbeat\x12\x0e\n\x06period\x18\x01 \x01(\r\x12\x11\n\tsecondary\x18\x02 \x01(\r\"\xf7\x01\n\x0fRequestResponse\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0cROUTER_ERROR\x10\x01\x12\x14\n\x10ROUTER_HEARTBEAT\x10\x02\x12\x0f\n\x0bROUTER_PING\x10\x03\x12\x0f\n\x0bROUTER_PONG\x10\x04\x12\x0f\n\x0bROUTER_BUSY\x10\x05\x12\x12\n\x0eROUTER_HISTORY\x10\x06\x12\x10\n\x0c\x43LIENT_ERROR\x10\x65\x12\x12\n\x0e\x43LIENT_HISTORY\x10\x66\x12\x10\n\x0c\x43LIENT_STATS\x10g\x12\x0f\n\x0b\x43LIENT_PING\x10h\x12\x0f\n\x0b\x43LIENT_PONG\x10i\x12\x10\n\x0c\x43LIENT_ABORT\x10jBR\n\x13\x63om.geeksville.meshB\x15StoreAndForwardProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
@@ -27,26 +27,26 @@ StoreAndForward = _reflection.GeneratedProtocolMessageType('StoreAndForward', (_
'Statistics' : _reflection.GeneratedProtocolMessageType('Statistics', (_message.Message,), { 'Statistics' : _reflection.GeneratedProtocolMessageType('Statistics', (_message.Message,), {
'DESCRIPTOR' : _STOREANDFORWARD_STATISTICS, 'DESCRIPTOR' : _STOREANDFORWARD_STATISTICS,
'__module__' : 'meshtastic.storeforward_pb2' '__module__' : 'storeforward_pb2'
# @@protoc_insertion_point(class_scope:StoreAndForward.Statistics) # @@protoc_insertion_point(class_scope:StoreAndForward.Statistics)
}) })
, ,
'History' : _reflection.GeneratedProtocolMessageType('History', (_message.Message,), { 'History' : _reflection.GeneratedProtocolMessageType('History', (_message.Message,), {
'DESCRIPTOR' : _STOREANDFORWARD_HISTORY, 'DESCRIPTOR' : _STOREANDFORWARD_HISTORY,
'__module__' : 'meshtastic.storeforward_pb2' '__module__' : 'storeforward_pb2'
# @@protoc_insertion_point(class_scope:StoreAndForward.History) # @@protoc_insertion_point(class_scope:StoreAndForward.History)
}) })
, ,
'Heartbeat' : _reflection.GeneratedProtocolMessageType('Heartbeat', (_message.Message,), { 'Heartbeat' : _reflection.GeneratedProtocolMessageType('Heartbeat', (_message.Message,), {
'DESCRIPTOR' : _STOREANDFORWARD_HEARTBEAT, 'DESCRIPTOR' : _STOREANDFORWARD_HEARTBEAT,
'__module__' : 'meshtastic.storeforward_pb2' '__module__' : 'storeforward_pb2'
# @@protoc_insertion_point(class_scope:StoreAndForward.Heartbeat) # @@protoc_insertion_point(class_scope:StoreAndForward.Heartbeat)
}) })
, ,
'DESCRIPTOR' : _STOREANDFORWARD, 'DESCRIPTOR' : _STOREANDFORWARD,
'__module__' : 'meshtastic.storeforward_pb2' '__module__' : 'storeforward_pb2'
# @@protoc_insertion_point(class_scope:StoreAndForward) # @@protoc_insertion_point(class_scope:StoreAndForward)
}) })
_sym_db.RegisterMessage(StoreAndForward) _sym_db.RegisterMessage(StoreAndForward)
@@ -57,15 +57,15 @@ _sym_db.RegisterMessage(StoreAndForward.Heartbeat)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\025StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\025StoreAndForwardProtosH\003Z\"github.com/meshtastic/go/generated'
_STOREANDFORWARD._serialized_start=34 _STOREANDFORWARD._serialized_start=23
_STOREANDFORWARD._serialized_end=864 _STOREANDFORWARD._serialized_end=801
_STOREANDFORWARD_STATISTICS._serialized_start=257 _STOREANDFORWARD_STATISTICS._serialized_start=223
_STOREANDFORWARD_STATISTICS._serialized_end=462 _STOREANDFORWARD_STATISTICS._serialized_end=428
_STOREANDFORWARD_HISTORY._serialized_start=464 _STOREANDFORWARD_HISTORY._serialized_start=430
_STOREANDFORWARD_HISTORY._serialized_end=537 _STOREANDFORWARD_HISTORY._serialized_end=503
_STOREANDFORWARD_HEARTBEAT._serialized_start=539 _STOREANDFORWARD_HEARTBEAT._serialized_start=505
_STOREANDFORWARD_HEARTBEAT._serialized_end=585 _STOREANDFORWARD_HEARTBEAT._serialized_end=551
_STOREANDFORWARD_REQUESTRESPONSE._serialized_start=588 _STOREANDFORWARD_REQUESTRESPONSE._serialized_start=554
_STOREANDFORWARD_REQUESTRESPONSE._serialized_end=853 _STOREANDFORWARD_REQUESTRESPONSE._serialized_end=801
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/telemetry.proto # source: telemetry.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf.internal import enum_type_wrapper from google.protobuf.internal import enum_type_wrapper
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
@@ -15,7 +15,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1ameshtastic/telemetry.proto\"i\n\rDeviceMetrics\x12\x15\n\rbattery_level\x18\x01 \x01(\r\x12\x0f\n\x07voltage\x18\x02 \x01(\x02\x12\x1b\n\x13\x63hannel_utilization\x18\x03 \x01(\x02\x12\x13\n\x0b\x61ir_util_tx\x18\x04 \x01(\x02\"\x9b\x01\n\x12\x45nvironmentMetrics\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\x19\n\x11relative_humidity\x18\x02 \x01(\x02\x12\x1b\n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02\x12\x16\n\x0egas_resistance\x18\x04 \x01(\x02\x12\x0f\n\x07voltage\x18\x05 \x01(\x02\x12\x0f\n\x07\x63urrent\x18\x06 \x01(\x02\"\xbf\x02\n\x11\x41irQualityMetrics\x12\x15\n\rpm10_standard\x18\x01 \x01(\r\x12\x15\n\rpm25_standard\x18\x02 \x01(\r\x12\x16\n\x0epm100_standard\x18\x03 \x01(\r\x12\x1a\n\x12pm10_environmental\x18\x04 \x01(\r\x12\x1a\n\x12pm25_environmental\x18\x05 \x01(\r\x12\x1b\n\x13pm100_environmental\x18\x06 \x01(\r\x12\x16\n\x0eparticles_03um\x18\x07 \x01(\r\x12\x16\n\x0eparticles_05um\x18\x08 \x01(\r\x12\x16\n\x0eparticles_10um\x18\t \x01(\r\x12\x16\n\x0eparticles_25um\x18\n \x01(\r\x12\x16\n\x0eparticles_50um\x18\x0b \x01(\r\x12\x17\n\x0fparticles_100um\x18\x0c \x01(\r\"\xb5\x01\n\tTelemetry\x12\x0c\n\x04time\x18\x01 \x01(\x07\x12(\n\x0e\x64\x65vice_metrics\x18\x02 \x01(\x0b\x32\x0e.DeviceMetricsH\x00\x12\x32\n\x13\x65nvironment_metrics\x18\x03 \x01(\x0b\x32\x13.EnvironmentMetricsH\x00\x12\x31\n\x13\x61ir_quality_metrics\x18\x04 \x01(\x0b\x32\x12.AirQualityMetricsH\x00\x42\t\n\x07variant*\xc7\x01\n\x13TelemetrySensorType\x12\x10\n\x0cSENSOR_UNSET\x10\x00\x12\n\n\x06\x42ME280\x10\x01\x12\n\n\x06\x42ME680\x10\x02\x12\x0b\n\x07MCP9808\x10\x03\x12\n\n\x06INA260\x10\x04\x12\n\n\x06INA219\x10\x05\x12\n\n\x06\x42MP280\x10\x06\x12\t\n\x05SHTC3\x10\x07\x12\t\n\x05LPS22\x10\x08\x12\x0b\n\x07QMC6310\x10\t\x12\x0b\n\x07QMI8658\x10\n\x12\x0c\n\x08QMC5883L\x10\x0b\x12\t\n\x05SHT31\x10\x0c\x12\x0c\n\x08PMSA003I\x10\rBd\n\x13\x63om.geeksville.meshB\x0fTelemetryProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0ftelemetry.proto\"i\n\rDeviceMetrics\x12\x15\n\rbattery_level\x18\x01 \x01(\r\x12\x0f\n\x07voltage\x18\x02 \x01(\x02\x12\x1b\n\x13\x63hannel_utilization\x18\x03 \x01(\x02\x12\x13\n\x0b\x61ir_util_tx\x18\x04 \x01(\x02\"\x9b\x01\n\x12\x45nvironmentMetrics\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\x19\n\x11relative_humidity\x18\x02 \x01(\x02\x12\x1b\n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02\x12\x16\n\x0egas_resistance\x18\x04 \x01(\x02\x12\x0f\n\x07voltage\x18\x05 \x01(\x02\x12\x0f\n\x07\x63urrent\x18\x06 \x01(\x02\"\x82\x01\n\tTelemetry\x12\x0c\n\x04time\x18\x01 \x01(\x07\x12(\n\x0e\x64\x65vice_metrics\x18\x02 \x01(\x0b\x32\x0e.DeviceMetricsH\x00\x12\x32\n\x13\x65nvironment_metrics\x18\x03 \x01(\x0b\x32\x13.EnvironmentMetricsH\x00\x42\t\n\x07variant*\xa0\x01\n\x13TelemetrySensorType\x12\x10\n\x0cSENSOR_UNSET\x10\x00\x12\n\n\x06\x42ME280\x10\x01\x12\n\n\x06\x42ME680\x10\x02\x12\x0b\n\x07MCP9808\x10\x03\x12\n\n\x06INA260\x10\x04\x12\n\n\x06INA219\x10\x05\x12\n\n\x06\x42MP280\x10\x06\x12\t\n\x05SHTC3\x10\x07\x12\t\n\x05LPS22\x10\x08\x12\x0b\n\x07QMC6310\x10\t\x12\x0b\n\x07QMI8658\x10\nBL\n\x13\x63om.geeksville.meshB\x0fTelemetryProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
_TELEMETRYSENSORTYPE = DESCRIPTOR.enum_types_by_name['TelemetrySensorType'] _TELEMETRYSENSORTYPE = DESCRIPTOR.enum_types_by_name['TelemetrySensorType']
TelemetrySensorType = enum_type_wrapper.EnumTypeWrapper(_TELEMETRYSENSORTYPE) TelemetrySensorType = enum_type_wrapper.EnumTypeWrapper(_TELEMETRYSENSORTYPE)
@@ -30,39 +30,28 @@ SHTC3 = 7
LPS22 = 8 LPS22 = 8
QMC6310 = 9 QMC6310 = 9
QMI8658 = 10 QMI8658 = 10
QMC5883L = 11
SHT31 = 12
PMSA003I = 13
_DEVICEMETRICS = DESCRIPTOR.message_types_by_name['DeviceMetrics'] _DEVICEMETRICS = DESCRIPTOR.message_types_by_name['DeviceMetrics']
_ENVIRONMENTMETRICS = DESCRIPTOR.message_types_by_name['EnvironmentMetrics'] _ENVIRONMENTMETRICS = DESCRIPTOR.message_types_by_name['EnvironmentMetrics']
_AIRQUALITYMETRICS = DESCRIPTOR.message_types_by_name['AirQualityMetrics']
_TELEMETRY = DESCRIPTOR.message_types_by_name['Telemetry'] _TELEMETRY = DESCRIPTOR.message_types_by_name['Telemetry']
DeviceMetrics = _reflection.GeneratedProtocolMessageType('DeviceMetrics', (_message.Message,), { DeviceMetrics = _reflection.GeneratedProtocolMessageType('DeviceMetrics', (_message.Message,), {
'DESCRIPTOR' : _DEVICEMETRICS, 'DESCRIPTOR' : _DEVICEMETRICS,
'__module__' : 'meshtastic.telemetry_pb2' '__module__' : 'telemetry_pb2'
# @@protoc_insertion_point(class_scope:DeviceMetrics) # @@protoc_insertion_point(class_scope:DeviceMetrics)
}) })
_sym_db.RegisterMessage(DeviceMetrics) _sym_db.RegisterMessage(DeviceMetrics)
EnvironmentMetrics = _reflection.GeneratedProtocolMessageType('EnvironmentMetrics', (_message.Message,), { EnvironmentMetrics = _reflection.GeneratedProtocolMessageType('EnvironmentMetrics', (_message.Message,), {
'DESCRIPTOR' : _ENVIRONMENTMETRICS, 'DESCRIPTOR' : _ENVIRONMENTMETRICS,
'__module__' : 'meshtastic.telemetry_pb2' '__module__' : 'telemetry_pb2'
# @@protoc_insertion_point(class_scope:EnvironmentMetrics) # @@protoc_insertion_point(class_scope:EnvironmentMetrics)
}) })
_sym_db.RegisterMessage(EnvironmentMetrics) _sym_db.RegisterMessage(EnvironmentMetrics)
AirQualityMetrics = _reflection.GeneratedProtocolMessageType('AirQualityMetrics', (_message.Message,), {
'DESCRIPTOR' : _AIRQUALITYMETRICS,
'__module__' : 'meshtastic.telemetry_pb2'
# @@protoc_insertion_point(class_scope:AirQualityMetrics)
})
_sym_db.RegisterMessage(AirQualityMetrics)
Telemetry = _reflection.GeneratedProtocolMessageType('Telemetry', (_message.Message,), { Telemetry = _reflection.GeneratedProtocolMessageType('Telemetry', (_message.Message,), {
'DESCRIPTOR' : _TELEMETRY, 'DESCRIPTOR' : _TELEMETRY,
'__module__' : 'meshtastic.telemetry_pb2' '__module__' : 'telemetry_pb2'
# @@protoc_insertion_point(class_scope:Telemetry) # @@protoc_insertion_point(class_scope:Telemetry)
}) })
_sym_db.RegisterMessage(Telemetry) _sym_db.RegisterMessage(Telemetry)
@@ -70,15 +59,13 @@ _sym_db.RegisterMessage(Telemetry)
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017TelemetryProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017TelemetryProtosH\003Z\"github.com/meshtastic/go/generated'
_TELEMETRYSENSORTYPE._serialized_start=802 _TELEMETRYSENSORTYPE._serialized_start=418
_TELEMETRYSENSORTYPE._serialized_end=1001 _TELEMETRYSENSORTYPE._serialized_end=578
_DEVICEMETRICS._serialized_start=30 _DEVICEMETRICS._serialized_start=19
_DEVICEMETRICS._serialized_end=135 _DEVICEMETRICS._serialized_end=124
_ENVIRONMENTMETRICS._serialized_start=138 _ENVIRONMENTMETRICS._serialized_start=127
_ENVIRONMENTMETRICS._serialized_end=293 _ENVIRONMENTMETRICS._serialized_end=282
_AIRQUALITYMETRICS._serialized_start=296 _TELEMETRY._serialized_start=285
_AIRQUALITYMETRICS._serialized_end=615 _TELEMETRY._serialized_end=415
_TELEMETRY._serialized_start=618
_TELEMETRY._serialized_end=799
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -23,7 +23,7 @@ def test_RemoteHardwareClient():
def test_onGPIOreceive(capsys): def test_onGPIOreceive(capsys):
"""Test onGPIOreceive""" """Test onGPIOreceive"""
iface = MagicMock(autospec=SerialInterface) iface = MagicMock(autospec=SerialInterface)
packet = {'decoded': {'remotehw': {'type': 'foo', 'gpioValue': '4096' }}} packet = {'decoded': {'remotehw': {'typ': 'foo', 'gpioValue': '4096' }}}
onGPIOreceive(packet, iface) onGPIOreceive(packet, iface)
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert re.search(r'Received RemoteHardware', out) assert re.search(r'Received RemoteHardware', out)

View File

@@ -159,42 +159,6 @@ class Timeout:
time.sleep(self.sleepInterval) time.sleep(self.sleepInterval)
return False return False
def waitForAckNak(self, acknowledgment, attrs=('receivedAck', 'receivedNak', 'receivedImplAck')):
"""Block until an ACK or NAK has been received. Returns True if ACK or NAK has been received."""
self.reset()
while time.time() < self.expireTime:
if any(map(lambda a: getattr(acknowledgment, a, None), attrs)):
acknowledgment.reset()
return True
time.sleep(self.sleepInterval)
return False
def waitForTraceRoute(self, waitFactor, acknowledgment, attr='receivedTraceRoute'):
"""Block until traceroute response is received. Returns True if traceroute response has been received."""
self.expireTimeout *= waitFactor
self.reset()
while time.time() < self.expireTime:
if getattr(acknowledgment, attr, None):
acknowledgment.reset()
return True
time.sleep(self.sleepInterval)
return False
class Acknowledgment:
"A class that records which type of acknowledgment was just received, if any."
def __init__(self):
"""initialize"""
self.receivedAck = False
self.receivedNak = False
self.receivedImplAck = False
self.receivedTraceRoute = False
def reset(self):
"""reset"""
self.receivedAck = False
self.receivedNak = False
self.receivedImplAck = False
self.receivedTraceRoute = False
class DeferredExecution(): class DeferredExecution():
"""A thread that accepts closures to run, and runs them as they are received""" """A thread that accepts closures to run, and runs them as they are received"""
@@ -232,7 +196,7 @@ def support_info():
print('') print('')
print('If having issues with meshtastic cli or python library') print('If having issues with meshtastic cli or python library')
print('or wish to make feature requests, visit:') print('or wish to make feature requests, visit:')
print('https://github.com/meshtastic/python/issues') print('https://github.com/meshtastic/Meshtastic-python/issues')
print('When adding an issue, be sure to include the following info:') print('When adding an issue, be sure to include the following info:')
print(f' System: {platform.system()}') print(f' System: {platform.system()}')
print(f' Platform: {platform.platform()}') print(f' Platform: {platform.platform()}')

View File

@@ -1,38 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/xmodem.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17meshtastic/xmodem.proto\"\xab\x01\n\x06XModem\x12 \n\x07\x63ontrol\x18\x01 \x01(\x0e\x32\x0f.XModem.Control\x12\x0b\n\x03seq\x18\x02 \x01(\r\x12\r\n\x05\x63rc16\x18\x03 \x01(\r\x12\x0e\n\x06\x62uffer\x18\x04 \x01(\x0c\"S\n\x07\x43ontrol\x12\x07\n\x03NUL\x10\x00\x12\x07\n\x03SOH\x10\x01\x12\x07\n\x03STX\x10\x02\x12\x07\n\x03\x45OT\x10\x04\x12\x07\n\x03\x41\x43K\x10\x06\x12\x07\n\x03NAK\x10\x15\x12\x07\n\x03\x43\x41N\x10\x18\x12\t\n\x05\x43TRLZ\x10\x1a\x42\x61\n\x13\x63om.geeksville.meshB\x0cXmodemProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_XMODEM = DESCRIPTOR.message_types_by_name['XModem']
_XMODEM_CONTROL = _XMODEM.enum_types_by_name['Control']
XModem = _reflection.GeneratedProtocolMessageType('XModem', (_message.Message,), {
'DESCRIPTOR' : _XMODEM,
'__module__' : 'meshtastic.xmodem_pb2'
# @@protoc_insertion_point(class_scope:XModem)
})
_sym_db.RegisterMessage(XModem)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\014XmodemProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_XMODEM._serialized_start=28
_XMODEM._serialized_end=199
_XMODEM_CONTROL._serialized_start=116
_XMODEM_CONTROL._serialized_end=199
# @@protoc_insertion_point(module_scope)

1
proto Submodule

Submodule proto added at a79e3aef81

Submodule protobufs deleted from 8aa371de2d

View File

@@ -12,16 +12,16 @@ with open("README.md", "r") as fh:
# This call to setup() does all the work # This call to setup() does all the work
setup( setup(
name="meshtastic", name="meshtastic",
version="2.1.1", version="2.0.0",
description="Python API & client shell for talking to Meshtastic devices", description="Python API & client shell for talking to Meshtastic devices",
long_description=long_description, long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
url="https://github.com/meshtastic/python", url="https://github.com/meshtastic/Meshtastic-python",
author="Meshtastic Developers", author="Kevin Hester",
author_email="contact@meshtastic.org", author_email="kevinh@geeksville.com",
license="GPL-3.0-only", license="MIT",
classifiers=[ classifiers=[
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "License :: OSI Approved :: MIT License",
"Development Status :: 4 - Beta", "Development Status :: 4 - Beta",
"Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.8",

View File

@@ -1,5 +1,5 @@
readme.txt for single standalone executable zip files that can be readme.txt for single standalone executable zip files that can be
downloaded from https://github.com/meshtastic/python/releases downloaded from https://github.com/meshtastic/Meshtastic-python/releases
If you do not want to install python and/or the python libraries, you can download one of these If you do not want to install python and/or the python libraries, you can download one of these
files to run the Meshtastic command line interface (CLI) as a standalone executable. files to run the Meshtastic command line interface (CLI) as a standalone executable.