Compare commits

..

105 Commits

Author SHA1 Message Date
mkinney
8ec5dbbf38 Merge pull request #307 from mkinney/master
there is no tlora_v2.1
2022-03-15 20:13:51 -07:00
Mike Kinney
0c760f3721 there is no tlora_v2.1 2022-03-15 20:11:14 -07:00
mkinney
c45568731f Merge pull request #306 from mkinney/master
regen protobuf code; tlora v1 vendor/product id fix
2022-03-15 19:57:45 -07:00
Mike Kinney
ef4c9dc338 fix the vendor and product id for tlora v1 2022-03-15 19:54:18 -07:00
Mike Kinney
89de553aba regen python based on updated protobufs 2022-03-15 19:30:54 -07:00
mkinney
247e7b2605 Merge pull request #303 from mkinney/supported_devices_fixes
fix some tlora entries
2022-03-15 19:27:42 -07:00
Mike Kinney
f81ba64b91 fix some tlora entries 2022-03-15 19:25:04 -07:00
Jm Casler
d6fbca1bf1 updating proto submodule to latest 2022-03-15 15:46:02 -07:00
Jm Casler
6fbf78fa19 updating proto submodule to latest 2022-03-14 18:05:28 -07:00
github-actions
e38a614c37 bump version 2022-03-11 23:08:22 +00:00
mkinney
d8b9665946 Merge pull request #299 from mkinney/master
update to latest protobufs
2022-03-11 15:07:34 -08:00
Mike Kinney
e655beb01c update to latest protobufs 2022-03-11 15:04:09 -08:00
mkinney
aa1dcb7f99 Merge pull request #298 from mkinney/master
refactor code to util; add duplicate check
2022-03-08 10:53:33 -08:00
Mike Kinney
1a2519d647 refactor code to util 2022-03-08 10:45:11 -08:00
Mike Kinney
a3572efaa6 add duplicate check 2022-03-08 10:44:14 -08:00
github-actions
e28f0d5509 bump version 2022-03-08 06:16:57 +00:00
mkinney
789a14054f Update release.yml 2022-03-07 22:16:03 -08:00
github-actions
4655b5c732 bump version 2022-03-08 06:04:02 +00:00
mkinney
81ebd8c8e7 Merge pull request #296 from mkinney/fix_release_version
keep sha ref and use it for subsequent checkouts
2022-03-07 22:02:28 -08:00
Mike Kinney
7998520e4a keep sha ref and use it for subsequent checkouts 2022-03-07 21:59:46 -08:00
mkinney
460196a62b Merge pull request #295 from mkinney/bug_when_ports_not_sorted
do not checkout the code again
2022-03-07 21:48:28 -08:00
Mike Kinney
22f43851bd do not checkout the code again 2022-03-07 21:44:11 -08:00
mkinney
91bb63eb97 Merge pull request #294 from mkinney/bug_when_ports_not_sorted
fix when ports are not sorted
2022-03-07 21:25:42 -08:00
Mike Kinney
ede1b5f08b fix when ports are not sorted 2022-03-07 21:21:41 -08:00
mkinney
a26c157c65 Merge pull request #292 from mkinney/handle_ignore_incoming
handle ignore_incoming repeated field
2022-03-03 17:14:09 -08:00
Mike Kinney
bcf00a1f8d handle ignore_incoming repeated field 2022-03-03 17:11:22 -08:00
Jm Casler
749a94e6e4 updating proto submodule to latest 2022-03-02 18:49:49 -08:00
github-actions
fc9d1e077c bump version 2022-03-02 21:56:05 +00:00
mkinney
a40f0b4038 Merge pull request #291 from mkinney/1_3_python
min req of python is 3.7 now; bump nanopb version
2022-03-02 13:55:09 -08:00
Mike Kinney
dbf54396f3 min req of python is 3.7 now; bump nanopb version 2022-03-02 13:29:19 -08:00
github-actions
3fe881e45a bump version 2022-03-02 19:43:05 +00:00
mkinney
af03c5163c Merge pull request #290 from mkinney/master
change version per pypi reqs
2022-03-02 11:42:09 -08:00
Mike Kinney
58de84945f change version per pypi reqs 2022-03-02 11:39:07 -08:00
github-actions
a2d4252002 bump version 2022-03-02 19:32:52 +00:00
mkinney
0689fc19a9 Merge pull request #289 from mkinney/1_3_initial
got lint and pytest working
2022-03-02 11:31:49 -08:00
Mike Kinney
68530f6e11 change medium to mid 2022-03-02 11:29:38 -08:00
Mike Kinney
fd752bedc5 change version format 2022-03-02 11:24:13 -08:00
Mike Kinney
cac880eb1a change to alpha 2022-03-02 11:15:47 -08:00
Mike Kinney
2c66cd4a95 change the name not the package 2022-03-02 10:50:08 -08:00
Mike Kinney
64e428f182 change package name and version 2022-03-02 10:44:35 -08:00
Mike Kinney
6f2efdcefe got lint and pytest working 2022-03-02 10:28:07 -08:00
github-actions
9214b2ffcc bump version 2022-03-02 00:20:31 +00:00
mkinney
cfb14d4b77 Merge pull request #287 from mkinney/changes_to_smokevirt
increase timeout; ensure secondary channel is deleted before trying t…
2022-03-01 16:19:14 -08:00
Mike Kinney
5965615e17 increase timeout; ensure secondary channel is deleted before trying to add it 2022-03-02 00:04:21 +00:00
Jm Casler
40eb7d8515 updating proto submodule to latest 2022-02-28 22:03:42 -08:00
Jm Casler
e2f36a9bea updating proto submodule to latest 2022-02-28 19:36:02 -08:00
Jm Casler
a0ba644488 updating proto submodule to latest 2022-02-27 10:01:44 -08:00
Jm Casler
2f67f344b7 updating proto submodule to latest 2022-02-27 09:57:16 -08:00
Jm Casler
8bb208aed1 updating proto submodule to latest 2022-02-27 09:52:34 -08:00
Jm Casler
48b145a592 updating proto submodule to latest 2022-02-27 01:00:38 -08:00
Jm Casler
65de9200fb updating proto submodule to latest 2022-02-27 00:48:57 -08:00
Jm Casler
e51d7a7a18 updating proto submodule to latest 2022-02-27 00:38:09 -08:00
Jm Casler
c4af50d63a updating proto submodule to latest 2022-02-26 21:22:33 -08:00
Jm Casler
933fe8953a updating proto submodule to latest 2022-02-26 21:09:20 -08:00
mkinney
66aa492d50 Merge pull request #283 from mkinney/add_cm
add cm
2022-02-25 23:44:13 -08:00
Mike Kinney
730934f520 add cm 2022-02-25 23:36:05 -08:00
mkinney
d2ec09eaf8 Merge pull request #281 from prampec/extend_canned_message_length
Canned message - Extend messages length
2022-02-25 22:58:57 -08:00
mkinney
7fd3b313b2 Update release.yml 2022-02-25 22:15:36 -08:00
github-actions
89f1549741 bump version 2022-02-26 06:11:26 +00:00
github-actions
e91015f5c8 bump version 2022-02-26 06:07:50 +00:00
mkinney
d9c3edfb12 Update release.yml 2022-02-25 22:06:27 -08:00
mkinney
cbf9696f47 Merge pull request #282 from mkinney/master
improve the release process
2022-02-25 22:04:48 -08:00
Mike Kinney
24e556b9a7 improve the release process 2022-02-25 22:01:21 -08:00
mkinney
eaf29512b6 Update standalone_readme.txt 2022-02-25 21:38:23 -08:00
Jm Casler
0c1e0ec375 updating proto submodule to latest 2022-02-22 17:10:04 -08:00
Balazs Kelemen
b56a054f50 Canned message - Extend messages length 2022-02-21 22:06:03 +01:00
Jm Casler
33ff4e36de updating proto submodule to latest 2022-02-20 01:32:53 -08:00
Jm Casler
bf879934e6 updating proto submodule to latest 2022-02-19 23:48:24 -08:00
Jm Casler
b878fa3a80 updating proto submodule to latest 2022-02-19 23:17:50 -08:00
Jm Casler
901849f176 updating proto submodule to latest 2022-02-19 23:10:53 -08:00
Jm Casler
371c0d22c2 updating proto submodule to latest 2022-02-19 22:55:38 -08:00
mkinney
4f7f38e0a7 Update setup.py 2022-02-18 11:16:49 -08:00
mkinney
85dca2e14e Merge pull request #278 from mkinney/fix_smoke1
add detection of duplicate ports to findPorts; fix smoke1 test
2022-02-18 11:16:25 -08:00
Mike Kinney
e53a5023f1 add detection of duplicate ports to findPorts; fix smoke1 test 2022-02-18 11:13:48 -08:00
mkinney
ce8b75d96d Merge pull request #277 from mkinney/win11_delay_only
only delay on win11
2022-02-18 10:12:16 -08:00
Mike Kinney
26f65c4fee only delay on win11 2022-02-18 10:08:53 -08:00
mkinney
1ba1e51ca4 Merge pull request #276 from mkinney/keep_devpath_on_serial
keep the devPath used on serial connections
2022-02-18 10:03:43 -08:00
Mike Kinney
f674afc412 keep the devPath used on serial connections 2022-02-18 09:59:09 -08:00
mkinney
db90b898e1 Update setup.py 2022-02-16 10:16:10 -08:00
mkinney
71621c2225 Merge pull request #269 from mkinney/two_serials
if we have a duplicate serial port use the appropriate one
2022-02-16 10:12:57 -08:00
Mike Kinney
ed36fca4a2 remove testing prints 2022-02-16 10:10:32 -08:00
Mike Kinney
fdd3699ba5 if we have a duplicate serial port use the appropriate one 2022-02-16 10:08:57 -08:00
Jm Casler
7d4b39643b updating proto submodule to latest 2022-02-14 20:35:46 -08:00
Jm Casler
7698cd2c7d updating proto submodule to latest 2022-02-14 20:08:31 -08:00
Jm Casler
03c744df54 updating proto submodule to latest 2022-02-14 19:55:21 -08:00
Jm Casler
90978d1f35 updating proto submodule to latest 2022-02-14 19:42:06 -08:00
Jm Casler
68a2bf271a updating proto submodule to latest 2022-02-14 17:59:45 -08:00
Jm Casler
8301384c53 updating proto submodule to latest 2022-02-14 16:59:26 -08:00
Jm Casler
045592212a updating proto submodule to latest 2022-02-14 16:56:59 -08:00
mkinney
45d879e607 Update setup.py 2022-02-12 21:19:20 -08:00
mkinney
3e44ee1eba Merge pull request #266 from mkinney/increase_sleep_for_win11
increase sleep for win11
2022-02-12 21:18:53 -08:00
Mike Kinney
36c5fc8d3c increase sleep for win11 2022-02-12 21:16:11 -08:00
mkinney
38ceb85ad9 Update setup.py 2022-02-10 15:15:46 -08:00
mkinney
6d18d9226d Merge pull request #263 from mkinney/add_rak11200
Add rak11200
2022-02-10 15:15:15 -08:00
Mike Kinney
6d5ed2129a add rak11200 2022-02-10 15:12:28 -08:00
Mike Kinney
5cfb6ffa11 add examples to lint and fix warnings 2022-02-10 14:51:22 -08:00
mkinney
363b268ccf Update setup.py 2022-02-03 10:03:31 -08:00
mkinney
e6cddb0084 Merge pull request #260 from mkinney/update_protobufs
update protobufs to latest
2022-02-03 10:01:31 -08:00
Mike Kinney
5e77bf62b9 update protobufs to latest 2022-02-03 09:59:03 -08:00
github-actions
4905c0b179 Update protobuf submodule 2022-02-03 15:00:36 +00:00
Ben Meadors
43ab3be804 Update update_protobufs.yml 2022-02-03 08:59:32 -06:00
github-actions
14a6e581bc Update protobuf submodule 2022-02-03 14:38:02 +00:00
mkinney
cadad32bdb Update setup.py 2022-02-01 17:44:37 -08:00
mkinney
71c6411d1a Merge pull request #257 from mkinney/add_techo_info
add T-Echo info
2022-02-01 17:41:19 -08:00
Mike Kinney
85e8fad16f add T-Echo info 2022-02-01 17:18:05 -08:00
51 changed files with 6010 additions and 567 deletions

View File

@@ -35,7 +35,7 @@ jobs:
which meshtastic
meshtastic --version
- name: Run pylint
run: pylint meshtastic
run: pylint meshtastic examples/
- name: Run tests with pytest
run: pytest --cov=meshtastic
- name: Generate coverage report

View File

@@ -1,66 +1,79 @@
name: Make Release
on:
workflow_dispatch:
inputs:
version:
description: "Release version (Example: 1.0.0, must match 'version' in setup.py)"
required: true
default: '1.0.0'
on: workflow_dispatch
jobs:
release_create:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
upload_url: ${{ steps.create_release.outputs.upload_url }}
new_sha: ${{ steps.commit_updated.outputs.sha }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Bump version
run: >-
bin/bump_version.py
- name: Commit updated version.py
id: commit_updated
run: |
git config --global user.name 'github-actions'
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 add setup.py
git commit -m "bump version" && git push || echo "No changes to commit"
git log -n 1 --pretty=format:"%H" | tail -n 1 | awk '{print "::set-output name=sha::"$0}'
- name: Get version
id: get_version
run: >-
bin/show_version.py
- name: Create GitHub release
uses: actions/create-release@v1
id: create_release
with:
draft: true
prerelease: true
release_name: ${{ github.event.inputs.version}}
tag_name: ${{ github.event.inputs.version}}
release_name: Meshtastic Python ${{ steps.get_version.outputs.version }}
tag_name: ${{ steps.get_version.outputs.version }}
body: |
Autogenerated by github action, developer should edit as required before publishing...
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
publish_to_pypi:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install pypa/build
run: >-
python -m
pip install
build
--user
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Build a binary wheel and a source tarball
run: >-
python -m
build
--sdist
--wheel
--outdir dist/
.
- name: Install pypa/build
run: >-
python -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
build
--sdist
--wheel
--outdir dist/
.
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
build-and-publish-mac:
@@ -69,7 +82,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: ${{ needs.release_create.outputs.new_sha }}
- name: Set up Python 3.9
uses: actions/setup-python@v2
@@ -114,7 +129,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: ${{ needs.release_create.outputs.new_sha }}
- name: Set up Python 3.9
uses: actions/setup-python@v2
@@ -137,7 +154,7 @@ jobs:
asset_path: dist/meshtastic
asset_name: meshtastic_ubuntu
asset_content_type: application/zip
- name: Add readme.txt to release
uses: actions/upload-release-asset@v1
env:
@@ -146,7 +163,7 @@ jobs:
upload_url: ${{ needs.release_create.outputs.upload_url }}
asset_path: standalone_readme.txt
asset_name: readme.txt
asset_content_type: text/plain
asset_content_type: text/plain
build-and-publish-windows:
runs-on: windows-latest
@@ -154,7 +171,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: ${{ needs.release_create.outputs.new_sha }}
- name: Set up Python 3.9
uses: actions/setup-python@v2

View File

@@ -32,4 +32,5 @@ jobs:
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 add proto
git add meshtastic
git commit -m "Update protobuf submodule" && git push || echo "No changes to commit"

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@ dist
log_*
.eggs
nanopb-0.4.4
nanopb-0.4.5
.*swp
.coverage
*.py-E

View File

@@ -7,7 +7,7 @@
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=mqtt_pb2.py,channel_pb2.py,environmental_measurement_pb2.py,admin_pb2.py,radioconfig_pb2.py,deviceonly_pb2.py,apponly_pb2.py,remote_hardware_pb2.py,portnums_pb2.py,mesh_pb2.py,storeforward_pb2.py,cannedmessages_pb2.py
ignore-patterns=mqtt_pb2.py,channel_pb2.py,telemetry_pb2.py,admin_pb2.py,radioconfig_pb2.py,deviceonly_pb2.py,apponly_pb2.py,remote_hardware_pb2.py,portnums_pb2.py,mesh_pb2.py,storeforward_pb2.py,cannedmessages_pb2.py
@@ -23,7 +23,7 @@ ignore-patterns=mqtt_pb2.py,channel_pb2.py,environmental_measurement_pb2.py,admi
# no Warning level messages displayed, use"--disable=all --enable=classes
# --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,no-self-use,pointless-string-statement,too-few-public-methods,broad-except,no-else-return,no-else-raise,bare-except
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]
@@ -41,7 +41,7 @@ bad-names=foo,bar,baz,toto,tutu,tata
max-line-length=150
# Maximum number of lines in a module
max-module-lines=1200
max-module-lines=1400

View File

@@ -16,12 +16,18 @@ docs:
# lint the codebase
lint:
pylint meshtastic
pylint meshtastic examples
# show the slowest unit tests
slow:
pytest -m unit --durations=5
proto: FORCE
git submodule update --init --recursive
git pull --rebase
git submodule update --remote --merge
./bin/regen-protos.sh
# run the coverage report and open results in a browser
cov:
pytest --cov-report html --cov=meshtastic

25
bin/bump_version.py Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env python
"""Bump the version number"""
version_filename = "setup.py"
lines = None
with open(version_filename, 'r', encoding='utf-8') as f:
lines = f.readlines()
with open(version_filename, 'w', encoding='utf-8') as f:
for line in lines:
if line.lstrip().startswith("version="):
# get rid of quotes around the version
line = line.replace('"', '')
# get rid of trailing comma
line = line.replace(",", "")
# split on '='
words = line.split("=")
# split the version into parts (by period)
v = words[1].split(".")
ver = f'{v[0]}.{v[1]}.{int(v[2]) + 1}'
f.write(f' version="{ver}",\n')
else:
f.write(line)

View File

@@ -1,6 +1,6 @@
#!/bin/bash
./nanopb-0.4.4/generator-bin/protoc -I=proto --python_out meshtastic `ls proto/*.proto`
./nanopb-0.4.5/generator-bin/protoc -I=proto --python_out meshtastic `ls proto/*.proto`
# workaround for import bug in protoc https://github.com/protocolbuffers/protobuf/issues/1491#issuecomment-690618628

20
bin/show_version.py Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env python
"""Show the version number"""
version_filename = "setup.py"
lines = None
with open(version_filename, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
if line.lstrip().startswith("version="):
# get rid of quotes around the version
line2 = line.replace('"', '')
# get rid of the trailing comma
line2 = line2.replace(',', '')
# split on =
words = line2.split("=")
# Note: This format is for github actions
print(f'::set-output name=version::{words[1].strip()}')

23
examples/info_example.py Normal file
View File

@@ -0,0 +1,23 @@
"""Simple program to demo how to use meshtastic library.
To run: python examples/info.py
"""
import meshtastic
import meshtastic.serial_interface
iface = meshtastic.serial_interface.SerialInterface()
# call showInfo() just to ensure values are populated
#info = iface.showInfo()
if iface.myInfo:
#print(f'myInfo:{iface.myInfo}')
print(f'firmware_version:{iface.myInfo.firmware_version}')
if iface.nodes:
for n in iface.nodes.values():
if n['num'] == iface.myInfo.my_node_num:
print(n['user']['hwModel'])
break
iface.close()

View File

@@ -13,7 +13,7 @@ if len(sys.argv) < 2:
print(f"usage: {sys.argv[0]} host")
sys.exit(1)
def onConnection(interface, topic=pub.AUTO_TOPIC):
def onConnection(interface, topic=pub.AUTO_TOPIC): # pylint: disable=unused-argument
"""This is called when we (re)connect to the radio."""
print(interface.myInfo)
interface.close()

View File

@@ -14,11 +14,11 @@ if len(sys.argv) < 2:
print(f"usage: {sys.argv[0]} host")
sys.exit(1)
def onReceive(packet, interface):
def onReceive(packet, interface): # pylint: disable=unused-argument
"""called when a packet arrives"""
print(f"Received: {packet}")
def onConnection(interface, topic=pub.AUTO_TOPIC):
def onConnection(interface, topic=pub.AUTO_TOPIC): # pylint: disable=unused-argument
"""called when we (re)connect to the radio"""
# defaults to broadcast, specify a destination ID if you wish
interface.sendText("hello mesh")

View File

@@ -3,9 +3,7 @@
"""
import sys
import meshtastic
from meshtastic.supported_device import get_unique_vendor_ids, active_ports_on_supported_devices
from meshtastic.util import detect_supported_devices
from meshtastic.util import detect_supported_devices, get_unique_vendor_ids, active_ports_on_supported_devices
# simple arg check
if len(sys.argv) != 1:

6
examples/show_ports.py Normal file
View File

@@ -0,0 +1,6 @@
"""Simple program to show serial ports.
"""
from meshtastic.util import findPorts
print(findPorts())

52
info/mac/rak11200.txt Normal file
View File

@@ -0,0 +1,52 @@
% ioreg -p IOUSB > /tmp/a
# only a solid red light (pins GRND and BOOT0 jumpered)
% ioreg -p IOUSB > /tmp/b
# solid red light and solid green light
% ioreg -p IOUSB > /tmp/c
# nothing plugged in
% diff /tmp/a /tmp/c
13c13
< +-o AppleUSBXHCI Root Hub Simulation@14000000 <class AppleUSBRootHubDevice, id 0x100000589, registered, matched, active, busy 0 (15 ms), retain 11>
---
> +-o AppleUSBXHCI Root Hub Simulation@14000000 <class AppleUSBRootHubDevice, id 0x100000589, registered, matched, active, busy 0 (15 ms), retain 10>
18d17
< +-o USB Serial@14300000 <class AppleUSBDevice, id 0x100004ca4, registered, matched, active, busy 0 (10 ms), retain 12>
% diff /tmp/b /tmp/c
13c13
< +-o AppleUSBXHCI Root Hub Simulation@14000000 <class AppleUSBRootHubDevice, id 0x100000589, registered, matched, active, busy 0 (15 ms), retain 11>
---
> +-o AppleUSBXHCI Root Hub Simulation@14000000 <class AppleUSBRootHubDevice, id 0x100000589, registered, matched, active, busy 0 (15 ms), retain 10>
18d17
< +-o USB Serial@14300000 <class AppleUSBDevice, id 0x100004ce5, registered, matched, active, busy 0 (11 ms), retain 12>
system_profiler SPUSBDataType > /tmp/d
# red solid
system_profiler SPUSBDataType > /tmp/e
# nothing
% diff /tmp/d /tmp/e
38,48d37
< USB Serial:
<
< Product ID: 0x7523
< Vendor ID: 0x1a86
< Version: 2.64
< Speed: Up to 12 Mb/s
< Location ID: 0x14300000 / 33
< Current Available (mA): 500
< Current Required (mA): 98
< Extra Operating Current (mA): 0

40
info/mac/techo.txt Normal file
View File

@@ -0,0 +1,40 @@
in boot mode:
% mount
<snip>
/dev/disk122 on /Volumes/TECHOBOOT (msdos, local, nodev, nosuid, noowners)
% ls -al /Volumes/TECHOBOOT
total 3735
drwxrwxrwx@ 1 bob staff 2048 Feb 1 16:47 .
drwxr-xr-x 5 root wheel 160 Feb 1 16:47 ..
drwxrwxrwx 1 bob staff 512 Feb 1 16:47 .fseventsd
-rwxrwxrwx 1 bob staff 1908736 Oct 13 08:37 CURRENT.UF2
-rwxrwxrwx 1 bob staff 129 Oct 13 08:37 INDEX.HTM
-rwxrwxrwx 1 bob staff 237 Oct 13 08:37 INFO_UF2.TXT
# nothing plugged in
% ioreg -p IOUSB > /tmp/a
# not boot mode
% ioreg -p IOUSB > /tmp/b
# bootmode
% ioreg -p IOUSB > /tmp/c
% diff /tmp/a /tmp/b
<snip>
> | +-o TTGO_eink@14300000 <class AppleUSBDevice, id 0x100060fe4, registered, matched, active, busy 0 (18 ms), retain 14>
% diff /tmp/a /tmp/c
<snip>
> | +-o T-Echo v1@14300000 <class AppleUSBDevice, id 0x100061000, registered, matched, active, busy 0 (25 ms), retain 16>
contents of: INFO_UF2.TXT
UF2 Bootloader 0.6.1-2-g1224915 lib/nrfx (v2.0.0) lib/tinyusb (0.10.1-293-gaf8e5a90) lib/uf2 (remotes/origin/configupdate-9-gadbb8c7)
Model: LilyGo T-Echo
Board-ID: nRF52840-TEcho-v1
SoftDevice: S140 version 6.1.1
Date: Oct 13 2021

141
info/ubuntu/techo.txt Normal file
View File

@@ -0,0 +1,141 @@
$ lsusb
Bus 002 Device 005: ID 046d:c31c Logitech, Inc. Keyboard K120
Bus 002 Device 002: ID 8087:8000 Intel Corp.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 107: ID 239a:0029
Bus 001 Device 002: ID 8087:8008 Intel Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ lsusb -d 239a: -v
Bus 001 Device 107: ID 239a:0029
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2
bDeviceProtocol 1 Interface Association
bMaxPacketSize0 64
idVendor 0x239a
idProduct 0x0029
bcdDevice 1.00
iManufacturer 1
iProduct 2
iSerial 3
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0062
bNumInterfaces 3
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 0
iFunction 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 0
iInterface 4
CDC Header:
bcdCDC 1.20
CDC Call Management:
bmCapabilities 0x00
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 8 Mass Storage
bInterfaceSubClass 6 SCSI
bInterfaceProtocol 80 Bulk-Only
iInterface 5
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0

View File

@@ -13,7 +13,8 @@ Bus 001 Device 002: ID 8087:8008 Intel Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
(venv) mikekinney@top:~/Meshtastic-python/info/ubuntu$ lsusb -d 1a86: -v
$ lsusb -d 1a86: -v
Bus 001 Device 099: ID 1a86:55d4 QinHeng Electronics
Couldn't open device, some information will be missing

302
info/windows/techo.txt Normal file
View File

@@ -0,0 +1,302 @@
PS > Get-PnpDevice -PresentOnly | Format-List >a
PS > Get-PnpDevice -PresentOnly | Format-List >b
PS > Compare-Object (get-content a) (get-content b)
Note: Not in boot mode
InputObject Side
Indi
cato
r
----------- ----
DeviceID : USB\VID_239A&PID_4405\D02012062C578951 =>
PNPDeviceID : USB\VID_239A&PID_4405\D02012062C578951 =>
HardwareID : {USB\VID_239A&PID_4405&REV_0100, USB\VID_239A&PID_4405} =>
InstanceId : USB\VID_239A&PID_4405\D02012062C578951 =>
Caption : USB Composite Device =>
Description : USB Composite Device =>
Name : USB Composite Device =>
ClassGuid : {36fc9e60-c465-11cf-8056-444553540000} =>
CompatibleID : {USB\DevClass_00&SubClass_00&Prot_00, USB\DevClass_00&SubClass_00, USB\DevClass_00, =>
USB\COMPOSITE} =>
Manufacturer : (Standard USB Host Controller) =>
PNPClass : USB =>
Service : usbccgp =>
Class : USB =>
FriendlyName : USB Composite Device =>
Caption : USB Serial Device (COM10) =>
Description : USB Serial Device =>
Name : USB Serial Device (COM10) =>
DeviceID : USB\VID_239A&PID_4405&MI_00\6&1B68A3E6&0&0000 =>
PNPDeviceID : USB\VID_239A&PID_4405&MI_00\6&1B68A3E6&0&0000 =>
ClassGuid : {4d36e978-e325-11ce-bfc1-08002be10318} =>
CompatibleID : {USB\Class_02&SubClass_02&Prot_00, USB\Class_02&SubClass_02, USB\Class_02} =>
HardwareID : {USB\VID_239A&PID_4405&REV_0100&MI_00, USB\VID_239A&PID_4405&MI_00} =>
PNPClass : Ports =>
Service : usbser =>
Class : Ports =>
FriendlyName : USB Serial Device (COM10) =>
InstanceId : USB\VID_239A&PID_4405&MI_00\6&1B68A3E6&0&0000 =>
InstallDate : =>
Status : OK =>
Availability : =>
ConfigManagerErrorCode : CM_PROB_NONE =>
ConfigManagerUserConfig : False =>
CreationClassName : Win32_PnPEntity =>
ErrorCleared : =>
ErrorDescription : =>
LastErrorCode : =>
PowerManagementCapabilities : =>
PowerManagementSupported : =>
StatusInfo : =>
SystemCreationClassName : Win32_ComputerSystem =>
SystemName : DESKTOP-FRFQN8H =>
Present : True =>
PSComputerName : =>
Problem : CM_PROB_NONE =>
ProblemDescription : =>
InstallDate : =>
Status : OK =>
Availability : =>
ConfigManagerErrorCode : CM_PROB_NONE =>
ConfigManagerUserConfig : False =>
CreationClassName : Win32_PnPEntity =>
ErrorCleared : =>
ErrorDescription : =>
LastErrorCode : =>
PowerManagementCapabilities : =>
PowerManagementSupported : =>
StatusInfo : =>
SystemCreationClassName : Win32_ComputerSystem =>
SystemName : DESKTOP-FRFQN8H =>
Manufacturer : Microsoft =>
Present : True =>
PSComputerName : =>
Problem : CM_PROB_NONE =>
ProblemDescription : =>
=>
in boot mode
PS > Get-PnpDevice -PresentOnly | Format-List >c
PS > Compare-Object (get-content a) (get-content c)
InputObject
-----------
Caption : Adafruit nRF UF2 USB Device
Name : Adafruit nRF UF2 USB Device
DeviceID : USBSTOR\DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0\7&10304CB2&0&D02012062C578951&0
PNPDeviceID : USBSTOR\DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0\7&10304CB2&0&D02012062C578951&0
CompatibleID : {USBSTOR\Disk, USBSTOR\RAW, GenDisk}
HardwareID : {USBSTOR\DiskAdafruitnRF_UF2_________1.0_, USBSTOR\DiskAdafruitnRF_UF2_________,
USBSTOR\DiskAdafruit, USBSTOR\AdafruitnRF_UF2_________1...}
FriendlyName : Adafruit nRF UF2 USB Device
InstanceId : USBSTOR\DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0\7&10304CB2&0&D02012062C578951&0
Caption : USB Mass Storage Device
Description : USB Mass Storage Device
Name : USB Mass Storage Device
DeviceID : USB\VID_239A&PID_0029&MI_02\6&2AE8D65&0&0002
PNPDeviceID : USB\VID_239A&PID_0029&MI_02\6&2AE8D65&0&0002
CompatibleID : {USB\Class_08&SubClass_06&Prot_50, USB\Class_08&SubClass_06, USB\Class_08}
HardwareID : {USB\VID_239A&PID_0029&REV_0100&MI_02, USB\VID_239A&PID_0029&MI_02}
Manufacturer : Compatible USB storage device
Service : USBSTOR
FriendlyName : USB Mass Storage Device
InstanceId : USB\VID_239A&PID_0029&MI_02\6&2AE8D65&0&0002
Caption : USB Serial Device (COM11)
Description : USB Serial Device
Name : USB Serial Device (COM11)
DeviceID : USB\VID_239A&PID_0029&MI_00\6&2AE8D65&0&0000
PNPDeviceID : USB\VID_239A&PID_0029&MI_00\6&2AE8D65&0&0000
ClassGuid : {4d36e978-e325-11ce-bfc1-08002be10318}
CompatibleID : {USB\Class_02&SubClass_02&Prot_00, USB\Class_02&SubClass_02, USB\Class_02}
HardwareID : {USB\VID_239A&PID_0029&REV_0100&MI_00, USB\VID_239A&PID_0029&MI_00}
PNPClass : Ports
Service : usbser
Class : Ports
FriendlyName : USB Serial Device (COM11)
InstanceId : USB\VID_239A&PID_0029&MI_00\6&2AE8D65&0&0000
ClassGuid : {36fc9e60-c465-11cf-8056-444553540000}
PNPClass : USB
Class : USB
Caption : USB Composite Device
Description : USB Composite Device
Name : USB Composite Device
DeviceID : USB\VID_239A&PID_0029\D02012062C578951
PNPDeviceID : USB\VID_239A&PID_0029\D02012062C578951
ClassGuid : {36fc9e60-c465-11cf-8056-444553540000}
CompatibleID : {USB\DevClass_00&SubClass_00&Prot_00, USB\DevClass_00&SubClass_00, USB\DevClass_00,
USB\COMPOSITE}
HardwareID : {USB\VID_239A&PID_0029&REV_0100, USB\VID_239A&PID_0029}
Manufacturer : (Standard USB Host Controller)
PNPClass : USB
Service : usbccgp
Class : USB
FriendlyName : USB Composite Device
InstanceId : USB\VID_239A&PID_0029\D02012062C578951
DeviceID : STORAGE\VOLUME\_??_USBSTOR#DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0#7&10304CB2&0&D02012062C
578951&0#{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}
PNPDeviceID : STORAGE\VOLUME\_??_USBSTOR#DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0#7&10304CB2&0&D02012062C
578951&0#{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}
InstanceId : STORAGE\VOLUME\_??_USBSTOR#DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0#7&10304CB2&0&D02012062C
578951&0#{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}
Caption : Volume
Description : Volume
Name : Volume
ClassGuid : {71a27cdd-812a-11d0-bec7-08002be2092f}
HardwareID : {STORAGE\Volume}
PNPClass : Volume
Service : volume
Class : Volume
FriendlyName : Volume
Description : Disk drive
ClassGuid : {4d36e967-e325-11ce-bfc1-08002be10318}
Manufacturer : (Standard disk drives)
PNPClass : DiskDrive
Service : disk
Class : DiskDrive
Caption : TECHOBOOT
Description : nRF UF2
Name : TECHOBOOT
DeviceID : SWD\WPDBUSENUM\_??_USBSTOR#DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0#7&10304CB2&0&D02012062C
578951&0#{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}
PNPDeviceID : SWD\WPDBUSENUM\_??_USBSTOR#DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0#7&10304CB2&0&D02012062C
578951&0#{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}
ClassGuid : {eec5ad98-8080-425f-922a-dabf3de3f69a}
CompatibleID : {wpdbusenum\fs, SWD\Generic}
HardwareID :
Manufacturer : Adafruit
PNPClass : WPD
Service : WUDFWpdFs
Class : WPD
FriendlyName : TECHOBOOT
InstanceId : SWD\WPDBUSENUM\_??_USBSTOR#DISK&VEN_ADAFRUIT&PROD_NRF_UF2&REV_1.0#7&10304CB2&0&D02012062C
578951&0#{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}
CompatibleID :
InstallDate :
Status : OK
Availability :
ConfigManagerErrorCode : CM_PROB_NONE
ConfigManagerUserConfig : False
CreationClassName : Win32_PnPEntity
ErrorCleared :
ErrorDescription :
LastErrorCode :
PowerManagementCapabilities :
PowerManagementSupported :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : DESKTOP-FRFQN8H
Present : True
PSComputerName :
Problem : CM_PROB_NONE
ProblemDescription :
InstallDate :
Status : OK
Availability :
ConfigManagerErrorCode : CM_PROB_NONE
ConfigManagerUserConfig : False
CreationClassName : Win32_PnPEntity
ErrorCleared :
ErrorDescription :
LastErrorCode :
PowerManagementCapabilities :
PowerManagementSupported :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : DESKTOP-FRFQN8H
Present : True
PSComputerName :
Problem : CM_PROB_NONE
ProblemDescription :
InstallDate :
Status : OK
Availability :
ConfigManagerErrorCode : CM_PROB_NONE
ConfigManagerUserConfig : False
CreationClassName : Win32_PnPEntity
ErrorCleared :
ErrorDescription :
LastErrorCode :
PowerManagementCapabilities :
PowerManagementSupported :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : DESKTOP-FRFQN8H
Present : True
PSComputerName :
Problem : CM_PROB_NONE
ProblemDescription :
InstallDate :
Status : OK
Availability :
ConfigManagerErrorCode : CM_PROB_NONE
ConfigManagerUserConfig : False
CreationClassName : Win32_PnPEntity
ErrorCleared :
ErrorDescription :
LastErrorCode :
PowerManagementCapabilities :
PowerManagementSupported :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : DESKTOP-FRFQN8H
Manufacturer : Microsoft
Present : True
PSComputerName :
Problem : CM_PROB_NONE
ProblemDescription :
InstallDate :
Status : OK
Availability :
ConfigManagerErrorCode : CM_PROB_NONE
ConfigManagerUserConfig : False
CreationClassName : Win32_PnPEntity
ErrorCleared :
ErrorDescription :
LastErrorCode :
PowerManagementCapabilities :
PowerManagementSupported :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : DESKTOP-FRFQN8H
Present : True
PSComputerName :
Problem : CM_PROB_NONE
ProblemDescription :
InstallDate :
Status : OK
Availability :
ConfigManagerErrorCode : CM_PROB_NONE
ConfigManagerUserConfig : False
CreationClassName : Win32_PnPEntity
ErrorCleared :
ErrorDescription :
LastErrorCode :
PowerManagementCapabilities :
PowerManagementSupported :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : DESKTOP-FRFQN8H
Manufacturer : Microsoft
Present : True
PSComputerName :
Problem : CM_PROB_NONE
ProblemDescription :
PS > Get-Volume
DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus SizeRemaining Size
----------- ------------ -------------- --------- ------------ ----------------- ------------- ----
Recovery NTFS Fixed Healthy OK 301.99 MB 854 MB
C NTFS Fixed Healthy OK 22.3 GB 56.67 GB
D TECHOBOOT FAT Removable Healthy OK 30.05 MB 31.88 MB

View File

@@ -1,8 +1,8 @@
Run from Windows 10
PS C:\Users\mikekinney> Get-PnpDevice -PresentOnly | Format-List > a
PS C:\Users\mikekinney> Get-PnpDevice -PresentOnly | Format-List > b
PS C:\Users\mikekinney> Compare-Object (get-content a) (Get-Content b)
PS > Get-PnpDevice -PresentOnly | Format-List > a
PS > Get-PnpDevice -PresentOnly | Format-List > b
PS > Compare-Object (get-content a) (Get-Content b)
InputObject SideIndicator
----------- -------------

View File

@@ -79,7 +79,7 @@ from google.protobuf.json_format import MessageToJson
from meshtastic.util import fixme, catchAndIgnore, stripnl, DeferredExecution, Timeout
from meshtastic.node import Node
from meshtastic import (mesh_pb2, portnums_pb2, apponly_pb2, admin_pb2,
environmental_measurement_pb2, remote_hardware_pb2,
telemetry_pb2, remote_hardware_pb2,
channel_pb2, radioconfig_pb2, util)
@@ -181,7 +181,6 @@ protocols = {
portnums_pb2.PortNum.NODEINFO_APP: KnownProtocol("user", mesh_pb2.User, _onNodeInfoReceive),
portnums_pb2.PortNum.ADMIN_APP: KnownProtocol("admin", admin_pb2.AdminMessage),
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
portnums_pb2.PortNum.ENVIRONMENTAL_MEASUREMENT_APP: KnownProtocol("environmental", environmental_measurement_pb2.EnvironmentalMeasurement),
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol(
"remotehw", remote_hardware_pb2.HardwareMessage)
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol("telemetry", telemetry_pb2.Telemetry),
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol("remotehw", remote_hardware_pb2.HardwareMessage)
}

View File

@@ -139,11 +139,22 @@ def setPref(attributes, name, valStr):
for temp_name in sorted(names):
print(f" {temp_name}")
return
try:
setattr(attributes, snake_name, val)
except TypeError:
# The setter didn't like our arg type guess try again as a string
setattr(attributes, snake_name, valStr)
# note: 'ignore_incoming' is a repeating field
if snake_name != 'ignore_incoming':
try:
setattr(attributes, snake_name, val)
except TypeError:
# The setter didn't like our arg type guess try again as a string
setattr(attributes, snake_name, valStr)
else:
if val == 0:
# clear values
print("Clearing ignore_incoming list")
del attributes.ignore_incoming[:]
else:
print(f"Adding '{val}' to the ignore_incoming list")
attributes.ignore_incoming.extend([val])
if Globals.getInstance().get_camel_case():
print(f"Set {camel_name} to {valStr}")
@@ -200,6 +211,12 @@ def onConnected(interface):
print(f"Setting device owner short to {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
if args.set_canned_message:
closeNow = True
print(f"Setting canned plugin message to {args.set_canned_message}")
interface.getNode(args.dest).set_canned_message(args.set_canned_message)
if args.pos_fields:
# If --pos-fields invoked with args, set position fields
closeNow = True
@@ -433,8 +450,8 @@ def onConnected(interface):
print(f"Deleting channel {channelIndex}")
ch = interface.getNode(args.dest).deleteChannel(channelIndex)
ch_changes = [args.ch_longslow, args.ch_longfast,
args.ch_mediumslow, args.ch_mediumfast,
ch_changes = [args.ch_vlongslow, args.ch_longslow, args.ch_longfast,
args.ch_midslow, args.ch_midfast,
args.ch_shortslow, args.ch_shortfast]
any_primary_channel_changes = any(x for x in ch_changes)
if args.ch_set or any_primary_channel_changes or args.ch_enable or args.ch_disable:
@@ -475,23 +492,26 @@ def onConnected(interface):
ch.settings.CopyFrom(chs)
# handle the simple channel set commands
if args.ch_vlongslow:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.VLongSlow)
if args.ch_longslow:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.Bw125Cr48Sf4096)
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.LongSlow)
if args.ch_longfast:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.Bw31_25Cr48Sf512)
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.LongFast)
if args.ch_mediumslow:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.Bw250Cr46Sf2048)
if args.ch_midslow:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.MidSlow)
if args.ch_mediumfast:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.Bw250Cr47Sf1024)
if args.ch_midfast:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.MidFast)
if args.ch_shortslow:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.Bw125Cr45Sf128)
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.ShortSlow)
if args.ch_shortfast:
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.Bw500Cr45Sf128)
setSimpleChannel(channel_pb2.ChannelSettings.ModemConfig.ShortFast)
# Handle the channel settings
for pref in (args.ch_set or []):
@@ -510,6 +530,11 @@ def onConnected(interface):
print(f"Writing modified channels to device")
interface.getNode(args.dest).writeChannel(channelIndex)
if args.get_canned_message:
closeNow = True
print("")
interface.getNode(args.dest).get_canned_message()
if args.info:
print("")
# If we aren't trying to talk to our local node, don't show it
@@ -746,6 +771,9 @@ def initParser():
parser.add_argument("--info", help="Read and display the radio config information",
action="store_true")
parser.add_argument("--get-canned-message", help="Show the canned message plugin message",
action="store_true")
parser.add_argument("--nodes", help="Print Node List in a pretty formatted table",
action="store_true")
@@ -787,6 +815,9 @@ def initParser():
"own key: '--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --ch-index 0'."),
nargs=2, action='append')
parser.add_argument(
"--ch-vlongslow", help="Change to the very long-range and slow channel", action='store_true')
parser.add_argument(
"--ch-longslow", help="Change to the long-range and slow channel", action='store_true')
@@ -794,10 +825,10 @@ def initParser():
"--ch-longfast", help="Change to the long-range and fast channel", action='store_true')
parser.add_argument(
"--ch-mediumslow", help="Change to the medium-range and slow channel", action='store_true')
"--ch-midslow", help="Change to the mid-range and slow channel", action='store_true')
parser.add_argument(
"--ch-mediumfast", help="Change to the medium-range and fast channel", action='store_true')
"--ch-midfast", help="Change to the mid-range and fast channel", action='store_true')
parser.add_argument(
"--ch-shortslow", help="Change to the short-range and slow channel", action='store_true')
@@ -808,6 +839,9 @@ def initParser():
parser.add_argument(
"--set-owner", help="Set device owner name", action="store")
parser.add_argument(
"--set-canned-message", help="Set the canned messages plugin message (up to 1000 characters).", action="store")
parser.add_argument(
"--set-owner-short", help="Set device owner short name", action="store")

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: admin.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
@@ -12,17 +11,318 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default()
from . import cannedmessages_pb2 as cannedmessages__pb2
from . import channel_pb2 as channel__pb2
from . import mesh_pb2 as mesh__pb2
from . import radioconfig_pb2 as radioconfig__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61\x64min.proto\x1a\x14\x63\x61nnedmessages.proto\x1a\rchannel.proto\x1a\nmesh.proto\x1a\x11radioconfig.proto\"\x87\x0c\n\x0c\x41\x64minMessage\x12!\n\tset_radio\x18\x01 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1a\n\tset_owner\x18\x02 \x01(\x0b\x32\x05.UserH\x00\x12\x1f\n\x0bset_channel\x18\x03 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_radio_request\x18\x04 \x01(\x08H\x00\x12*\n\x12get_radio_response\x18\x05 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1d\n\x13get_channel_request\x18\x06 \x01(\rH\x00\x12(\n\x14get_channel_response\x18\x07 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x08 \x01(\x08H\x00\x12#\n\x12get_owner_response\x18\t \x01(\x0b\x32\x05.UserH\x00\x12\x1d\n\x13\x63onfirm_set_channel\x18 \x01(\x08H\x00\x12\x1b\n\x11\x63onfirm_set_radio\x18! \x01(\x08H\x00\x12\x18\n\x0e\x65xit_simulator\x18\" \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18# \x01(\x05H\x00\x12\x31\n\'get_canned_message_plugin_part1_request\x18$ \x01(\x08H\x00\x12T\n(get_canned_message_plugin_part1_response\x18% \x01(\x0b\x32 .CannedMessagePluginMessagePart1H\x00\x12\x31\n\'get_canned_message_plugin_part2_request\x18& \x01(\x08H\x00\x12T\n(get_canned_message_plugin_part2_response\x18\' \x01(\x0b\x32 .CannedMessagePluginMessagePart2H\x00\x12\x31\n\'get_canned_message_plugin_part3_request\x18( \x01(\x08H\x00\x12T\n(get_canned_message_plugin_part3_response\x18) \x01(\x0b\x32 .CannedMessagePluginMessagePart3H\x00\x12\x31\n\'get_canned_message_plugin_part4_request\x18* \x01(\x08H\x00\x12T\n(get_canned_message_plugin_part4_response\x18+ \x01(\x0b\x32 .CannedMessagePluginMessagePart4H\x00\x12\x31\n\'get_canned_message_plugin_part5_request\x18, \x01(\x08H\x00\x12T\n(get_canned_message_plugin_part5_response\x18- \x01(\x0b\x32 .CannedMessagePluginMessagePart5H\x00\x12K\n\x1fset_canned_message_plugin_part1\x18. \x01(\x0b\x32 .CannedMessagePluginMessagePart1H\x00\x12K\n\x1fset_canned_message_plugin_part2\x18/ \x01(\x0b\x32 .CannedMessagePluginMessagePart2H\x00\x12K\n\x1fset_canned_message_plugin_part3\x18\x30 \x01(\x0b\x32 .CannedMessagePluginMessagePart3H\x00\x12K\n\x1fset_canned_message_plugin_part4\x18\x31 \x01(\x0b\x32 .CannedMessagePluginMessagePart4H\x00\x12K\n\x1fset_canned_message_plugin_part5\x18\x32 \x01(\x0b\x32 .CannedMessagePluginMessagePart5H\x00\x12\x1a\n\x10shutdown_seconds\x18\x33 \x01(\x05H\x00\x42\t\n\x07variantBG\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
DESCRIPTOR = _descriptor.FileDescriptor(
name='admin.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\013AdminProtosH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=b'\n\x0b\x61\x64min.proto\x1a\rchannel.proto\x1a\nmesh.proto\x1a\x11radioconfig.proto\"\xa1\x08\n\x0c\x41\x64minMessage\x12!\n\tset_radio\x18\x01 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1a\n\tset_owner\x18\x02 \x01(\x0b\x32\x05.UserH\x00\x12\x1f\n\x0bset_channel\x18\x03 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_radio_request\x18\x04 \x01(\x08H\x00\x12*\n\x12get_radio_response\x18\x05 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1d\n\x13get_channel_request\x18\x06 \x01(\rH\x00\x12(\n\x14get_channel_response\x18\x07 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x08 \x01(\x08H\x00\x12#\n\x12get_owner_response\x18\t \x01(\x0b\x32\x05.UserH\x00\x12\x1d\n\x13\x63onfirm_set_channel\x18 \x01(\x08H\x00\x12\x1b\n\x11\x63onfirm_set_radio\x18! \x01(\x08H\x00\x12\x18\n\x0e\x65xit_simulator\x18\" \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18# \x01(\x05H\x00\x12\x31\n\'get_canned_message_module_part1_request\x18$ \x01(\x08H\x00\x12\x32\n(get_canned_message_module_part1_response\x18% \x01(\tH\x00\x12\x31\n\'get_canned_message_module_part2_request\x18& \x01(\x08H\x00\x12\x32\n(get_canned_message_module_part2_response\x18\' \x01(\tH\x00\x12\x31\n\'get_canned_message_module_part3_request\x18( \x01(\x08H\x00\x12\x32\n(get_canned_message_module_part3_response\x18) \x01(\tH\x00\x12\x31\n\'get_canned_message_module_part4_request\x18* \x01(\x08H\x00\x12\x32\n(get_canned_message_module_part4_response\x18+ \x01(\tH\x00\x12)\n\x1fset_canned_message_module_part1\x18, \x01(\tH\x00\x12)\n\x1fset_canned_message_module_part2\x18- \x01(\tH\x00\x12)\n\x1fset_canned_message_module_part3\x18. \x01(\tH\x00\x12)\n\x1fset_canned_message_module_part4\x18/ \x01(\tH\x00\x12\x1a\n\x10shutdown_seconds\x18\x33 \x01(\x05H\x00\x42\t\n\x07variantBG\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
,
dependencies=[channel__pb2.DESCRIPTOR,mesh__pb2.DESCRIPTOR,radioconfig__pb2.DESCRIPTOR,])
_ADMINMESSAGE = DESCRIPTOR.message_types_by_name['AdminMessage']
_ADMINMESSAGE = _descriptor.Descriptor(
name='AdminMessage',
full_name='AdminMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='set_radio', full_name='AdminMessage.set_radio', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='set_owner', full_name='AdminMessage.set_owner', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='set_channel', full_name='AdminMessage.set_channel', index=2,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_radio_request', full_name='AdminMessage.get_radio_request', index=3,
number=4, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_radio_response', full_name='AdminMessage.get_radio_response', index=4,
number=5, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_channel_request', full_name='AdminMessage.get_channel_request', index=5,
number=6, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_channel_response', full_name='AdminMessage.get_channel_response', index=6,
number=7, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_owner_request', full_name='AdminMessage.get_owner_request', index=7,
number=8, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_owner_response', full_name='AdminMessage.get_owner_response', index=8,
number=9, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='confirm_set_channel', full_name='AdminMessage.confirm_set_channel', index=9,
number=32, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='confirm_set_radio', full_name='AdminMessage.confirm_set_radio', index=10,
number=33, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='exit_simulator', full_name='AdminMessage.exit_simulator', index=11,
number=34, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='reboot_seconds', full_name='AdminMessage.reboot_seconds', index=12,
number=35, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_canned_message_module_part1_request', full_name='AdminMessage.get_canned_message_module_part1_request', index=13,
number=36, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_canned_message_module_part1_response', full_name='AdminMessage.get_canned_message_module_part1_response', index=14,
number=37, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_canned_message_module_part2_request', full_name='AdminMessage.get_canned_message_module_part2_request', index=15,
number=38, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_canned_message_module_part2_response', full_name='AdminMessage.get_canned_message_module_part2_response', index=16,
number=39, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_canned_message_module_part3_request', full_name='AdminMessage.get_canned_message_module_part3_request', index=17,
number=40, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_canned_message_module_part3_response', full_name='AdminMessage.get_canned_message_module_part3_response', index=18,
number=41, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_canned_message_module_part4_request', full_name='AdminMessage.get_canned_message_module_part4_request', index=19,
number=42, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='get_canned_message_module_part4_response', full_name='AdminMessage.get_canned_message_module_part4_response', index=20,
number=43, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='set_canned_message_module_part1', full_name='AdminMessage.set_canned_message_module_part1', index=21,
number=44, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='set_canned_message_module_part2', full_name='AdminMessage.set_canned_message_module_part2', index=22,
number=45, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='set_canned_message_module_part3', full_name='AdminMessage.set_canned_message_module_part3', index=23,
number=46, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='set_canned_message_module_part4', full_name='AdminMessage.set_canned_message_module_part4', index=24,
number=47, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='shutdown_seconds', full_name='AdminMessage.shutdown_seconds', index=25,
number=51, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
_descriptor.OneofDescriptor(
name='variant', full_name='AdminMessage.variant',
index=0, containing_type=None, fields=[]),
],
serialized_start=62,
serialized_end=1119,
)
_ADMINMESSAGE.fields_by_name['set_radio'].message_type = radioconfig__pb2._RADIOCONFIG
_ADMINMESSAGE.fields_by_name['set_owner'].message_type = mesh__pb2._USER
_ADMINMESSAGE.fields_by_name['set_channel'].message_type = channel__pb2._CHANNEL
_ADMINMESSAGE.fields_by_name['get_radio_response'].message_type = radioconfig__pb2._RADIOCONFIG
_ADMINMESSAGE.fields_by_name['get_channel_response'].message_type = channel__pb2._CHANNEL
_ADMINMESSAGE.fields_by_name['get_owner_response'].message_type = mesh__pb2._USER
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['set_radio'])
_ADMINMESSAGE.fields_by_name['set_radio'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['set_owner'])
_ADMINMESSAGE.fields_by_name['set_owner'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['set_channel'])
_ADMINMESSAGE.fields_by_name['set_channel'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_radio_request'])
_ADMINMESSAGE.fields_by_name['get_radio_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_radio_response'])
_ADMINMESSAGE.fields_by_name['get_radio_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_channel_request'])
_ADMINMESSAGE.fields_by_name['get_channel_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_channel_response'])
_ADMINMESSAGE.fields_by_name['get_channel_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_owner_request'])
_ADMINMESSAGE.fields_by_name['get_owner_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_owner_response'])
_ADMINMESSAGE.fields_by_name['get_owner_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['confirm_set_channel'])
_ADMINMESSAGE.fields_by_name['confirm_set_channel'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['confirm_set_radio'])
_ADMINMESSAGE.fields_by_name['confirm_set_radio'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['exit_simulator'])
_ADMINMESSAGE.fields_by_name['exit_simulator'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['reboot_seconds'])
_ADMINMESSAGE.fields_by_name['reboot_seconds'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part1_request'])
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part1_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part1_response'])
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part1_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part2_request'])
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part2_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part2_response'])
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part2_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part3_request'])
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part3_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part3_response'])
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part3_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part4_request'])
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part4_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part4_response'])
_ADMINMESSAGE.fields_by_name['get_canned_message_module_part4_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['set_canned_message_module_part1'])
_ADMINMESSAGE.fields_by_name['set_canned_message_module_part1'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['set_canned_message_module_part2'])
_ADMINMESSAGE.fields_by_name['set_canned_message_module_part2'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['set_canned_message_module_part3'])
_ADMINMESSAGE.fields_by_name['set_canned_message_module_part3'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['set_canned_message_module_part4'])
_ADMINMESSAGE.fields_by_name['set_canned_message_module_part4'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
_ADMINMESSAGE.fields_by_name['shutdown_seconds'])
_ADMINMESSAGE.fields_by_name['shutdown_seconds'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
DESCRIPTOR.message_types_by_name['AdminMessage'] = _ADMINMESSAGE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
AdminMessage = _reflection.GeneratedProtocolMessageType('AdminMessage', (_message.Message,), {
'DESCRIPTOR' : _ADMINMESSAGE,
'__module__' : 'admin_pb2'
@@ -30,10 +330,6 @@ AdminMessage = _reflection.GeneratedProtocolMessageType('AdminMessage', (_messag
})
_sym_db.RegisterMessage(AdminMessage)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\013AdminProtosH\003Z!github.com/meshtastic/gomeshproto'
_ADMINMESSAGE._serialized_start=84
_ADMINMESSAGE._serialized_end=1627
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: apponly.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
@@ -15,11 +14,52 @@ _sym_db = _symbol_database.Default()
from . import channel_pb2 as channel__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rapponly.proto\x1a\rchannel.proto\"0\n\nChannelSet\x12\"\n\x08settings\x18\x01 \x03(\x0b\x32\x10.ChannelSettingsBI\n\x13\x63om.geeksville.meshB\rAppOnlyProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
DESCRIPTOR = _descriptor.FileDescriptor(
name='apponly.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\rAppOnlyProtosH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=b'\n\rapponly.proto\x1a\rchannel.proto\"0\n\nChannelSet\x12\"\n\x08settings\x18\x01 \x03(\x0b\x32\x10.ChannelSettingsBI\n\x13\x63om.geeksville.meshB\rAppOnlyProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
,
dependencies=[channel__pb2.DESCRIPTOR,])
_CHANNELSET = DESCRIPTOR.message_types_by_name['ChannelSet']
_CHANNELSET = _descriptor.Descriptor(
name='ChannelSet',
full_name='ChannelSet',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='settings', full_name='ChannelSet.settings', index=0,
number=1, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=32,
serialized_end=80,
)
_CHANNELSET.fields_by_name['settings'].message_type = channel__pb2._CHANNELSETTINGS
DESCRIPTOR.message_types_by_name['ChannelSet'] = _CHANNELSET
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
ChannelSet = _reflection.GeneratedProtocolMessageType('ChannelSet', (_message.Message,), {
'DESCRIPTOR' : _CHANNELSET,
'__module__' : 'apponly_pb2'
@@ -27,10 +67,6 @@ ChannelSet = _reflection.GeneratedProtocolMessageType('ChannelSet', (_message.Me
})
_sym_db.RegisterMessage(ChannelSet)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rAppOnlyProtosH\003Z!github.com/meshtastic/gomeshproto'
_CHANNELSET._serialized_start=32
_CHANNELSET._serialized_end=80
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: cannedmessages.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
@@ -14,62 +13,78 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x63\x61nnedmessages.proto\"/\n\x1f\x43\x61nnedMessagePluginMessagePart1\x12\x0c\n\x04text\x18\x01 \x01(\t\"/\n\x1f\x43\x61nnedMessagePluginMessagePart2\x12\x0c\n\x04text\x18\x01 \x01(\t\"/\n\x1f\x43\x61nnedMessagePluginMessagePart3\x12\x0c\n\x04text\x18\x01 \x01(\t\"/\n\x1f\x43\x61nnedMessagePluginMessagePart4\x12\x0c\n\x04text\x18\x01 \x01(\t\"/\n\x1f\x43\x61nnedMessagePluginMessagePart5\x12\x0c\n\x04text\x18\x01 \x01(\tBU\n\x13\x63om.geeksville.meshB\x19\x43\x61nnedMessageConfigProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
DESCRIPTOR = _descriptor.FileDescriptor(
name='cannedmessages.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\031CannedMessageConfigProtosH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=b'\n\x14\x63\x61nnedmessages.proto\"w\n\x19\x43\x61nnedMessageModuleConfig\x12\x15\n\rmessagesPart1\x18\x0b \x01(\t\x12\x15\n\rmessagesPart2\x18\x0c \x01(\t\x12\x15\n\rmessagesPart3\x18\r \x01(\t\x12\x15\n\rmessagesPart4\x18\x0e \x01(\tBU\n\x13\x63om.geeksville.meshB\x19\x43\x61nnedMessageConfigProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
)
_CANNEDMESSAGEPLUGINMESSAGEPART1 = DESCRIPTOR.message_types_by_name['CannedMessagePluginMessagePart1']
_CANNEDMESSAGEPLUGINMESSAGEPART2 = DESCRIPTOR.message_types_by_name['CannedMessagePluginMessagePart2']
_CANNEDMESSAGEPLUGINMESSAGEPART3 = DESCRIPTOR.message_types_by_name['CannedMessagePluginMessagePart3']
_CANNEDMESSAGEPLUGINMESSAGEPART4 = DESCRIPTOR.message_types_by_name['CannedMessagePluginMessagePart4']
_CANNEDMESSAGEPLUGINMESSAGEPART5 = DESCRIPTOR.message_types_by_name['CannedMessagePluginMessagePart5']
CannedMessagePluginMessagePart1 = _reflection.GeneratedProtocolMessageType('CannedMessagePluginMessagePart1', (_message.Message,), {
'DESCRIPTOR' : _CANNEDMESSAGEPLUGINMESSAGEPART1,
_CANNEDMESSAGEMODULECONFIG = _descriptor.Descriptor(
name='CannedMessageModuleConfig',
full_name='CannedMessageModuleConfig',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='messagesPart1', full_name='CannedMessageModuleConfig.messagesPart1', index=0,
number=11, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='messagesPart2', full_name='CannedMessageModuleConfig.messagesPart2', index=1,
number=12, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='messagesPart3', full_name='CannedMessageModuleConfig.messagesPart3', index=2,
number=13, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='messagesPart4', full_name='CannedMessageModuleConfig.messagesPart4', index=3,
number=14, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=24,
serialized_end=143,
)
DESCRIPTOR.message_types_by_name['CannedMessageModuleConfig'] = _CANNEDMESSAGEMODULECONFIG
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
CannedMessageModuleConfig = _reflection.GeneratedProtocolMessageType('CannedMessageModuleConfig', (_message.Message,), {
'DESCRIPTOR' : _CANNEDMESSAGEMODULECONFIG,
'__module__' : 'cannedmessages_pb2'
# @@protoc_insertion_point(class_scope:CannedMessagePluginMessagePart1)
# @@protoc_insertion_point(class_scope:CannedMessageModuleConfig)
})
_sym_db.RegisterMessage(CannedMessagePluginMessagePart1)
_sym_db.RegisterMessage(CannedMessageModuleConfig)
CannedMessagePluginMessagePart2 = _reflection.GeneratedProtocolMessageType('CannedMessagePluginMessagePart2', (_message.Message,), {
'DESCRIPTOR' : _CANNEDMESSAGEPLUGINMESSAGEPART2,
'__module__' : 'cannedmessages_pb2'
# @@protoc_insertion_point(class_scope:CannedMessagePluginMessagePart2)
})
_sym_db.RegisterMessage(CannedMessagePluginMessagePart2)
CannedMessagePluginMessagePart3 = _reflection.GeneratedProtocolMessageType('CannedMessagePluginMessagePart3', (_message.Message,), {
'DESCRIPTOR' : _CANNEDMESSAGEPLUGINMESSAGEPART3,
'__module__' : 'cannedmessages_pb2'
# @@protoc_insertion_point(class_scope:CannedMessagePluginMessagePart3)
})
_sym_db.RegisterMessage(CannedMessagePluginMessagePart3)
CannedMessagePluginMessagePart4 = _reflection.GeneratedProtocolMessageType('CannedMessagePluginMessagePart4', (_message.Message,), {
'DESCRIPTOR' : _CANNEDMESSAGEPLUGINMESSAGEPART4,
'__module__' : 'cannedmessages_pb2'
# @@protoc_insertion_point(class_scope:CannedMessagePluginMessagePart4)
})
_sym_db.RegisterMessage(CannedMessagePluginMessagePart4)
CannedMessagePluginMessagePart5 = _reflection.GeneratedProtocolMessageType('CannedMessagePluginMessagePart5', (_message.Message,), {
'DESCRIPTOR' : _CANNEDMESSAGEPLUGINMESSAGEPART5,
'__module__' : 'cannedmessages_pb2'
# @@protoc_insertion_point(class_scope:CannedMessagePluginMessagePart5)
})
_sym_db.RegisterMessage(CannedMessagePluginMessagePart5)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\031CannedMessageConfigProtosH\003Z!github.com/meshtastic/gomeshproto'
_CANNEDMESSAGEPLUGINMESSAGEPART1._serialized_start=24
_CANNEDMESSAGEPLUGINMESSAGEPART1._serialized_end=71
_CANNEDMESSAGEPLUGINMESSAGEPART2._serialized_start=73
_CANNEDMESSAGEPLUGINMESSAGEPART2._serialized_end=120
_CANNEDMESSAGEPLUGINMESSAGEPART3._serialized_start=122
_CANNEDMESSAGEPLUGINMESSAGEPART3._serialized_end=169
_CANNEDMESSAGEPLUGINMESSAGEPART4._serialized_start=171
_CANNEDMESSAGEPLUGINMESSAGEPART4._serialized_end=218
_CANNEDMESSAGEPLUGINMESSAGEPART5._serialized_start=220
_CANNEDMESSAGEPLUGINMESSAGEPART5._serialized_end=267
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: channel.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
@@ -14,14 +13,241 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rchannel.proto\"\x91\x03\n\x0f\x43hannelSettings\x12\x10\n\x08tx_power\x18\x01 \x01(\x05\x12\x32\n\x0cmodem_config\x18\x03 \x01(\x0e\x32\x1c.ChannelSettings.ModemConfig\x12\x11\n\tbandwidth\x18\x06 \x01(\r\x12\x15\n\rspread_factor\x18\x07 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x08 \x01(\r\x12\x13\n\x0b\x63hannel_num\x18\t \x01(\r\x12\x0b\n\x03psk\x18\x04 \x01(\x0c\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\n\n\x02id\x18\n \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x10 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x11 \x01(\x08\"\x8a\x01\n\x0bModemConfig\x12\x12\n\x0e\x42w125Cr45Sf128\x10\x00\x12\x12\n\x0e\x42w500Cr45Sf128\x10\x01\x12\x14\n\x10\x42w31_25Cr48Sf512\x10\x02\x12\x13\n\x0f\x42w125Cr48Sf4096\x10\x03\x12\x13\n\x0f\x42w250Cr46Sf2048\x10\x04\x12\x13\n\x0f\x42w250Cr47Sf1024\x10\x05\"\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\x42I\n\x13\x63om.geeksville.meshB\rChannelProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
DESCRIPTOR = _descriptor.FileDescriptor(
name='channel.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\rChannelProtosH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=b'\n\rchannel.proto\"\xf6\x02\n\x0f\x43hannelSettings\x12\x10\n\x08tx_power\x18\x01 \x01(\x05\x12\x32\n\x0cmodem_config\x18\x03 \x01(\x0e\x32\x1c.ChannelSettings.ModemConfig\x12\x11\n\tbandwidth\x18\x06 \x01(\r\x12\x15\n\rspread_factor\x18\x07 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x08 \x01(\r\x12\x13\n\x0b\x63hannel_num\x18\t \x01(\r\x12\x0b\n\x03psk\x18\x04 \x01(\x0c\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\n\n\x02id\x18\n \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x10 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x11 \x01(\x08\"p\n\x0bModemConfig\x12\r\n\tVLongSlow\x10\x00\x12\x0c\n\x08LongSlow\x10\x01\x12\x0c\n\x08LongFast\x10\x02\x12\x0b\n\x07MidSlow\x10\x03\x12\x0b\n\x07MidFast\x10\x04\x12\r\n\tShortSlow\x10\x05\x12\r\n\tShortFast\x10\x06\"\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\x42I\n\x13\x63om.geeksville.meshB\rChannelProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
)
_CHANNELSETTINGS = DESCRIPTOR.message_types_by_name['ChannelSettings']
_CHANNEL = DESCRIPTOR.message_types_by_name['Channel']
_CHANNELSETTINGS_MODEMCONFIG = _CHANNELSETTINGS.enum_types_by_name['ModemConfig']
_CHANNEL_ROLE = _CHANNEL.enum_types_by_name['Role']
_CHANNELSETTINGS_MODEMCONFIG = _descriptor.EnumDescriptor(
name='ModemConfig',
full_name='ChannelSettings.ModemConfig',
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name='VLongSlow', index=0, number=0,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='LongSlow', index=1, number=1,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='LongFast', index=2, number=2,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='MidSlow', index=3, number=3,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='MidFast', index=4, number=4,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ShortSlow', index=5, number=5,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ShortFast', index=6, number=6,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=280,
serialized_end=392,
)
_sym_db.RegisterEnumDescriptor(_CHANNELSETTINGS_MODEMCONFIG)
_CHANNEL_ROLE = _descriptor.EnumDescriptor(
name='Role',
full_name='Channel.Role',
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name='DISABLED', index=0, number=0,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='PRIMARY', index=1, number=1,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='SECONDARY', index=2, number=2,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=486,
serialized_end=534,
)
_sym_db.RegisterEnumDescriptor(_CHANNEL_ROLE)
_CHANNELSETTINGS = _descriptor.Descriptor(
name='ChannelSettings',
full_name='ChannelSettings',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='tx_power', full_name='ChannelSettings.tx_power', index=0,
number=1, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='modem_config', full_name='ChannelSettings.modem_config', index=1,
number=3, type=14, cpp_type=8, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='bandwidth', full_name='ChannelSettings.bandwidth', index=2,
number=6, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='spread_factor', full_name='ChannelSettings.spread_factor', index=3,
number=7, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='coding_rate', full_name='ChannelSettings.coding_rate', index=4,
number=8, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='channel_num', full_name='ChannelSettings.channel_num', index=5,
number=9, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='psk', full_name='ChannelSettings.psk', index=6,
number=4, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=b"",
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='name', full_name='ChannelSettings.name', index=7,
number=5, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='id', full_name='ChannelSettings.id', index=8,
number=10, type=7, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='uplink_enabled', full_name='ChannelSettings.uplink_enabled', index=9,
number=16, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='downlink_enabled', full_name='ChannelSettings.downlink_enabled', index=10,
number=17, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
_CHANNELSETTINGS_MODEMCONFIG,
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=18,
serialized_end=392,
)
_CHANNEL = _descriptor.Descriptor(
name='Channel',
full_name='Channel',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='index', full_name='Channel.index', index=0,
number=1, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='settings', full_name='Channel.settings', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='role', full_name='Channel.role', index=2,
number=3, type=14, cpp_type=8, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
_CHANNEL_ROLE,
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=395,
serialized_end=534,
)
_CHANNELSETTINGS.fields_by_name['modem_config'].enum_type = _CHANNELSETTINGS_MODEMCONFIG
_CHANNELSETTINGS_MODEMCONFIG.containing_type = _CHANNELSETTINGS
_CHANNEL.fields_by_name['settings'].message_type = _CHANNELSETTINGS
_CHANNEL.fields_by_name['role'].enum_type = _CHANNEL_ROLE
_CHANNEL_ROLE.containing_type = _CHANNEL
DESCRIPTOR.message_types_by_name['ChannelSettings'] = _CHANNELSETTINGS
DESCRIPTOR.message_types_by_name['Channel'] = _CHANNEL
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
ChannelSettings = _reflection.GeneratedProtocolMessageType('ChannelSettings', (_message.Message,), {
'DESCRIPTOR' : _CHANNELSETTINGS,
'__module__' : 'channel_pb2'
@@ -36,16 +262,6 @@ Channel = _reflection.GeneratedProtocolMessageType('Channel', (_message.Message,
})
_sym_db.RegisterMessage(Channel)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rChannelProtosH\003Z!github.com/meshtastic/gomeshproto'
_CHANNELSETTINGS._serialized_start=18
_CHANNELSETTINGS._serialized_end=419
_CHANNELSETTINGS_MODEMCONFIG._serialized_start=281
_CHANNELSETTINGS_MODEMCONFIG._serialized_end=419
_CHANNEL._serialized_start=422
_CHANNEL._serialized_end=561
_CHANNEL_ROLE._serialized_start=513
_CHANNEL_ROLE._serialized_end=561
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: deviceonly.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
@@ -14,31 +13,139 @@ _sym_db = _symbol_database.Default()
from . import channel_pb2 as channel__pb2
from . import mesh_pb2 as mesh__pb2
from . import radioconfig_pb2 as radioconfig__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x64\x65viceonly.proto\x1a\rchannel.proto\x1a\nmesh.proto\x1a\x11radioconfig.proto\"\x80\x01\n\x11LegacyRadioConfig\x12\x39\n\x0bpreferences\x18\x01 \x01(\x0b\x32$.LegacyRadioConfig.LegacyPreferences\x1a\x30\n\x11LegacyPreferences\x12\x1b\n\x06region\x18\x0f \x01(\x0e\x32\x0b.RegionCode\"\xf0\x03\n\x0b\x44\x65viceState\x12\'\n\x0blegacyRadio\x18\x01 \x01(\x0b\x32\x12.LegacyRadioConfig\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\x12+\n#canned_message_plugin_message_part1\x18\r \x01(\t\x12+\n#canned_message_plugin_message_part2\x18\x0e \x01(\t\x12+\n#canned_message_plugin_message_part3\x18\x0f \x01(\t\x12+\n#canned_message_plugin_message_part4\x18\x10 \x01(\t\x12+\n#canned_message_plugin_message_part5\x18\x11 \x01(\tJ\x04\x08\x0c\x10\r\")\n\x0b\x43hannelFile\x12\x1a\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x08.ChannelBF\n\x13\x63om.geeksville.meshB\nDeviceOnlyH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
_LEGACYRADIOCONFIG = DESCRIPTOR.message_types_by_name['LegacyRadioConfig']
_LEGACYRADIOCONFIG_LEGACYPREFERENCES = _LEGACYRADIOCONFIG.nested_types_by_name['LegacyPreferences']
_DEVICESTATE = DESCRIPTOR.message_types_by_name['DeviceState']
_CHANNELFILE = DESCRIPTOR.message_types_by_name['ChannelFile']
LegacyRadioConfig = _reflection.GeneratedProtocolMessageType('LegacyRadioConfig', (_message.Message,), {
'LegacyPreferences' : _reflection.GeneratedProtocolMessageType('LegacyPreferences', (_message.Message,), {
'DESCRIPTOR' : _LEGACYRADIOCONFIG_LEGACYPREFERENCES,
'__module__' : 'deviceonly_pb2'
# @@protoc_insertion_point(class_scope:LegacyRadioConfig.LegacyPreferences)
})
DESCRIPTOR = _descriptor.FileDescriptor(
name='deviceonly.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\nDeviceOnlyH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=b'\n\x10\x64\x65viceonly.proto\x1a\rchannel.proto\x1a\nmesh.proto\"\xe6\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(\x08J\x04\x08\x0c\x10\r\")\n\x0b\x43hannelFile\x12\x1a\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x08.ChannelBF\n\x13\x63om.geeksville.meshB\nDeviceOnlyH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
,
'DESCRIPTOR' : _LEGACYRADIOCONFIG,
'__module__' : 'deviceonly_pb2'
# @@protoc_insertion_point(class_scope:LegacyRadioConfig)
})
_sym_db.RegisterMessage(LegacyRadioConfig)
_sym_db.RegisterMessage(LegacyRadioConfig.LegacyPreferences)
dependencies=[channel__pb2.DESCRIPTOR,mesh__pb2.DESCRIPTOR,])
_DEVICESTATE = _descriptor.Descriptor(
name='DeviceState',
full_name='DeviceState',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='my_node', full_name='DeviceState.my_node', index=0,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='owner', full_name='DeviceState.owner', index=1,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='node_db', full_name='DeviceState.node_db', index=2,
number=4, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='receive_queue', full_name='DeviceState.receive_queue', index=3,
number=5, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='version', full_name='DeviceState.version', index=4,
number=8, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='rx_text_message', full_name='DeviceState.rx_text_message', index=5,
number=7, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='no_save', full_name='DeviceState.no_save', index=6,
number=9, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='did_gps_reset', full_name='DeviceState.did_gps_reset', index=7,
number=11, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=48,
serialized_end=278,
)
_CHANNELFILE = _descriptor.Descriptor(
name='ChannelFile',
full_name='ChannelFile',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='channels', full_name='ChannelFile.channels', index=0,
number=1, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=280,
serialized_end=321,
)
_DEVICESTATE.fields_by_name['my_node'].message_type = mesh__pb2._MYNODEINFO
_DEVICESTATE.fields_by_name['owner'].message_type = mesh__pb2._USER
_DEVICESTATE.fields_by_name['node_db'].message_type = mesh__pb2._NODEINFO
_DEVICESTATE.fields_by_name['receive_queue'].message_type = mesh__pb2._MESHPACKET
_DEVICESTATE.fields_by_name['rx_text_message'].message_type = mesh__pb2._MESHPACKET
_CHANNELFILE.fields_by_name['channels'].message_type = channel__pb2._CHANNEL
DESCRIPTOR.message_types_by_name['DeviceState'] = _DEVICESTATE
DESCRIPTOR.message_types_by_name['ChannelFile'] = _CHANNELFILE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
DeviceState = _reflection.GeneratedProtocolMessageType('DeviceState', (_message.Message,), {
'DESCRIPTOR' : _DEVICESTATE,
@@ -54,16 +161,6 @@ ChannelFile = _reflection.GeneratedProtocolMessageType('ChannelFile', (_message.
})
_sym_db.RegisterMessage(ChannelFile)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nDeviceOnlyH\003Z!github.com/meshtastic/gomeshproto'
_LEGACYRADIOCONFIG._serialized_start=67
_LEGACYRADIOCONFIG._serialized_end=195
_LEGACYRADIOCONFIG_LEGACYPREFERENCES._serialized_start=147
_LEGACYRADIOCONFIG_LEGACYPREFERENCES._serialized_end=195
_DEVICESTATE._serialized_start=198
_DEVICESTATE._serialized_end=694
_CHANNELFILE._serialized_start=696
_CHANNELFILE._serialized_end=737
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: environmental_measurement.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\x1f\x65nvironmental_measurement.proto\"\xa1\x01\n\x18\x45nvironmentalMeasurement\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\x42#Z!github.com/meshtastic/gomeshprotob\x06proto3')
_ENVIRONMENTALMEASUREMENT = DESCRIPTOR.message_types_by_name['EnvironmentalMeasurement']
EnvironmentalMeasurement = _reflection.GeneratedProtocolMessageType('EnvironmentalMeasurement', (_message.Message,), {
'DESCRIPTOR' : _ENVIRONMENTALMEASUREMENT,
'__module__' : 'environmental_measurement_pb2'
# @@protoc_insertion_point(class_scope:EnvironmentalMeasurement)
})
_sym_db.RegisterMessage(EnvironmentalMeasurement)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'Z!github.com/meshtastic/gomeshproto'
_ENVIRONMENTALMEASUREMENT._serialized_start=36
_ENVIRONMENTALMEASUREMENT._serialized_end=197
# @@protoc_insertion_point(module_scope)

View File

@@ -254,11 +254,12 @@ class MeshInterface:
meshPacket.decoded.payload = data
meshPacket.decoded.portnum = portNum
meshPacket.decoded.want_response = wantResponse
meshPacket.id = self._generatePacketId()
if onResponse is not None:
self._addResponseHandler(meshPacket.id, onResponse)
p = self._sendPacket(meshPacket, destinationId,
wantAck=wantAck, hopLimit=hopLimit)
if onResponse is not None:
self._addResponseHandler(p.id, onResponse)
return p
def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
@@ -631,11 +632,13 @@ class MeshInterface:
# asObj = DotMap(asDict)
topic = "meshtastic.receive" # Generic unknown packet type
decoded = asDict["decoded"]
# The default MessageToDict converts byte arrays into base64 strings.
# We don't want that - it messes up data payload. So slam in the correct
# byte array.
decoded["payload"] = meshPacket.decoded.payload
decoded = None
if 'decoded' in asDict:
decoded = asDict["decoded"]
# The default MessageToDict converts byte arrays into base64 strings.
# We don't want that - it messes up data payload. So slam in the correct
# byte array.
decoded["payload"] = meshPacket.decoded.payload
# UNKNOWN_APP is the default protobuf portnum value, and therefore if not
# set it will not be populated at all to make API usage easier, set

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: mqtt.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
@@ -15,11 +14,66 @@ _sym_db = _symbol_database.Default()
from . import mesh_pb2 as mesh__pb2
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(\tBF\n\x13\x63om.geeksville.meshB\nMQTTProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
DESCRIPTOR = _descriptor.FileDescriptor(
name='mqtt.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\nMQTTProtosH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=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(\tBF\n\x13\x63om.geeksville.meshB\nMQTTProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
,
dependencies=[mesh__pb2.DESCRIPTOR,])
_SERVICEENVELOPE = DESCRIPTOR.message_types_by_name['ServiceEnvelope']
_SERVICEENVELOPE = _descriptor.Descriptor(
name='ServiceEnvelope',
full_name='ServiceEnvelope',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='packet', full_name='ServiceEnvelope.packet', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='channel_id', full_name='ServiceEnvelope.channel_id', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='gateway_id', full_name='ServiceEnvelope.gateway_id', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=26,
serialized_end=112,
)
_SERVICEENVELOPE.fields_by_name['packet'].message_type = mesh__pb2._MESHPACKET
DESCRIPTOR.message_types_by_name['ServiceEnvelope'] = _SERVICEENVELOPE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
ServiceEnvelope = _reflection.GeneratedProtocolMessageType('ServiceEnvelope', (_message.Message,), {
'DESCRIPTOR' : _SERVICEENVELOPE,
'__module__' : 'mqtt_pb2'
@@ -27,10 +81,6 @@ ServiceEnvelope = _reflection.GeneratedProtocolMessageType('ServiceEnvelope', (_
})
_sym_db.RegisterMessage(ServiceEnvelope)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nMQTTProtosH\003Z!github.com/meshtastic/gomeshproto'
_SERVICEENVELOPE._serialized_start=26
_SERVICEENVELOPE._serialized_end=112
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -3,6 +3,7 @@
import logging
import base64
import time
from google.protobuf.json_format import MessageToJson
from meshtastic import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2
from meshtastic.util import pskToString, stripnl, Timeout, our_exit, fromPSK
@@ -24,6 +25,15 @@ class Node:
self.partialChannels = None
self.noProto = noProto
self.cannedPluginMessage = None
self.cannedPluginMessagePart1 = None
self.cannedPluginMessagePart2 = None
self.cannedPluginMessagePart3 = None
self.cannedPluginMessagePart4 = None
self.gotResponse = None
def showChannels(self):
"""Show human readable description of our channels."""
print("Channels:")
@@ -56,6 +66,14 @@ class Node:
self.channels = None
self.partialChannels = [] # We keep our channels in a temp array until finished
# Note: We do not get the canned plugin message, unless get_canned_message() is called
self.cannedPluginMessage = None
self.cannedPluginMessagePart1 = None
self.cannedPluginMessagePart2 = None
self.cannedPluginMessagePart3 = None
self.cannedPluginMessagePart4 = None
self._requestSettings()
def turnOffEncryptionOnPrimaryChannel(self):
@@ -64,9 +82,9 @@ class Node:
print("Writing modified channels to device")
self.writeChannel(0)
def waitForConfig(self):
def waitForConfig(self, attribute='channels'):
"""Block until radio config is received. Returns True if config has been received."""
return self._timeout.waitForSet(self, attrs=('radioConfig', 'channels'))
return self._timeout.waitForSet(self, attrs=('radioConfig', attribute))
def writeConfig(self):
"""Write the current (edited) radioConfig to the device"""
@@ -237,7 +255,7 @@ class Node:
"""Handle the response packet for requesting settings _requestSettings()"""
logging.debug(f'onResponseRequestSetting() p:{p}')
errorFound = False
if 'routing' in p["decoded"]:
if "routing" in p["decoded"]:
if p["decoded"]["routing"]["errorReason"] != "NONE":
errorFound = True
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
@@ -268,6 +286,156 @@ class Node:
return self._sendAdmin(p, wantResponse=True, onResponse=self.onResponseRequestSettings)
def onResponseRequestCannedMessagePluginMessagePart1(self, p):
"""Handle the response packet for requesting canned message plugin message part 1"""
logging.debug(f'onResponseRequestCannedMessagePluginMessagePart1() 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.cannedPluginMessagePart1 = p["decoded"]["admin"]["raw"].get_canned_message_plugin_part1_response
logging.debug(f'self.cannedPluginMessagePart1:{self.cannedPluginMessagePart1}')
self.gotResponse = True
def onResponseRequestCannedMessagePluginMessagePart2(self, p):
"""Handle the response packet for requesting canned message plugin message part 2"""
logging.debug(f'onResponseRequestCannedMessagePluginMessagePart2() 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.cannedPluginMessagePart2 = p["decoded"]["admin"]["raw"].get_canned_message_plugin_part2_response
logging.debug(f'self.cannedPluginMessagePart2:{self.cannedPluginMessagePart2}')
self.gotResponse = True
def onResponseRequestCannedMessagePluginMessagePart3(self, p):
"""Handle the response packet for requesting canned message plugin message part 3"""
logging.debug(f'onResponseRequestCannedMessagePluginMessagePart3() 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.cannedPluginMessagePart3 = p["decoded"]["admin"]["raw"].get_canned_message_plugin_part3_response
logging.debug(f'self.cannedPluginMessagePart3:{self.cannedPluginMessagePart3}')
self.gotResponse = True
def onResponseRequestCannedMessagePluginMessagePart4(self, p):
"""Handle the response packet for requesting canned message plugin message part 4"""
logging.debug(f'onResponseRequestCannedMessagePluginMessagePart4() 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.cannedPluginMessagePart4 = p["decoded"]["admin"]["raw"].get_canned_message_plugin_part4_response
logging.debug(f'self.cannedPluginMessagePart4:{self.cannedPluginMessagePart4}')
self.gotResponse = True
def get_canned_message(self):
"""Get the canned message string. Concatenate all pieces together and return a single string."""
logging.debug(f'in get_canned_message()')
if not self.cannedPluginMessage:
p1 = admin_pb2.AdminMessage()
p1.get_canned_message_plugin_part1_request = True
self.gotResponse = False
self._sendAdmin(p1, wantResponse=True, onResponse=self.onResponseRequestCannedMessagePluginMessagePart1)
while self.gotResponse is False:
time.sleep(0.1)
p2 = admin_pb2.AdminMessage()
p2.get_canned_message_plugin_part2_request = True
self.gotResponse = False
self._sendAdmin(p2, wantResponse=True, onResponse=self.onResponseRequestCannedMessagePluginMessagePart2)
while self.gotResponse is False:
time.sleep(0.1)
p3 = admin_pb2.AdminMessage()
p3.get_canned_message_plugin_part3_request = True
self.gotResponse = False
self._sendAdmin(p3, wantResponse=True, onResponse=self.onResponseRequestCannedMessagePluginMessagePart3)
while self.gotResponse is False:
time.sleep(0.1)
p4 = admin_pb2.AdminMessage()
p4.get_canned_message_plugin_part4_request = True
self.gotResponse = False
self._sendAdmin(p4, wantResponse=True, onResponse=self.onResponseRequestCannedMessagePluginMessagePart4)
while self.gotResponse is False:
time.sleep(0.1)
# TODO: This feels wrong to have a sleep here. Is there a way to ensure that
# all requests are complete? Perhaps change to a while loop any parts are None... maybe?
time.sleep(3)
logging.debug(f'self.cannedPluginMessagePart1:{self.cannedPluginMessagePart1}')
logging.debug(f'self.cannedPluginMessagePart2:{self.cannedPluginMessagePart2}')
logging.debug(f'self.cannedPluginMessagePart3:{self.cannedPluginMessagePart3}')
logging.debug(f'self.cannedPluginMessagePart4:{self.cannedPluginMessagePart4}')
self.cannedPluginMessage = ""
if self.cannedPluginMessagePart1:
self.cannedPluginMessage += self.cannedPluginMessagePart1
if self.cannedPluginMessagePart2:
self.cannedPluginMessage += self.cannedPluginMessagePart2
if self.cannedPluginMessagePart3:
self.cannedPluginMessage += self.cannedPluginMessagePart3
if self.cannedPluginMessagePart4:
self.cannedPluginMessage += self.cannedPluginMessagePart4
print(f'canned_plugin_message:{self.cannedPluginMessage}')
logging.debug(f'canned_plugin_message:{self.cannedPluginMessage}')
return self.cannedPluginMessage
def set_canned_message(self, message):
"""Set the canned message. Split into parts of 200 chars each."""
if len(message) > 800:
our_exit("Warning: The canned message must be less than 800 characters.")
# split into chunks
chunks = []
chunks_size = 200
for i in range(0, len(message), chunks_size):
chunks.append(message[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_canned_message_plugin_part1 = chunk
elif i == 1:
p.set_canned_message_plugin_part2 = chunk
elif i == 2:
p.set_canned_message_plugin_part3 = chunk
elif i == 3:
p.set_canned_message_plugin_part4 = chunk
logging.debug(f"Setting canned message '{chunk}' part {i+1}")
self._sendAdmin(p)
def exitSimulator(self):
"""Tell a simulator node to exit (this message
is ignored for other nodes)"""

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: portnums.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import enum_type_wrapper
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
@@ -15,9 +14,96 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eportnums.proto*\xcb\x02\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\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!\n\x1d\x45NVIRONMENTAL_MEASUREMENT_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\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\x44\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
DESCRIPTOR = _descriptor.FileDescriptor(
name='portnums.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\010PortnumsH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=b'\n\x0eportnums.proto*\xbb\x02\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\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\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42\x44\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
)
_PORTNUM = _descriptor.EnumDescriptor(
name='PortNum',
full_name='PortNum',
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name='UNKNOWN_APP', index=0, number=0,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='TEXT_MESSAGE_APP', index=1, number=1,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='REMOTE_HARDWARE_APP', index=2, number=2,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='POSITION_APP', index=3, number=3,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='NODEINFO_APP', index=4, number=4,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ROUTING_APP', index=5, number=5,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ADMIN_APP', index=6, number=6,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='REPLY_APP', index=7, number=32,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='IP_TUNNEL_APP', index=8, number=33,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='SERIAL_APP', index=9, number=64,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='STORE_FORWARD_APP', index=10, number=65,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='RANGE_TEST_APP', index=11, number=66,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='TELEMETRY_APP', index=12, number=67,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ZPS_APP', index=13, number=68,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='PRIVATE_APP', index=14, number=256,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ATAK_FORWARDER', index=15, number=257,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='MAX', index=16, number=511,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=19,
serialized_end=334,
)
_sym_db.RegisterEnumDescriptor(_PORTNUM)
_PORTNUM = DESCRIPTOR.enum_types_by_name['PortNum']
PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM)
UNKNOWN_APP = 0
TEXT_MESSAGE_APP = 1
@@ -31,17 +117,16 @@ IP_TUNNEL_APP = 33
SERIAL_APP = 64
STORE_FORWARD_APP = 65
RANGE_TEST_APP = 66
ENVIRONMENTAL_MEASUREMENT_APP = 67
TELEMETRY_APP = 67
ZPS_APP = 68
PRIVATE_APP = 256
ATAK_FORWARDER = 257
MAX = 511
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR.enum_types_by_name['PortNum'] = _PORTNUM
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsH\003Z!github.com/meshtastic/gomeshproto'
_PORTNUM._serialized_start=19
_PORTNUM._serialized_end=350
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: remote_hardware.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
@@ -14,12 +13,105 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15remote_hardware.proto\"\xca\x01\n\x0fHardwareMessage\x12\"\n\x03typ\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\x42J\n\x13\x63om.geeksville.meshB\x0eRemoteHardwareH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
DESCRIPTOR = _descriptor.FileDescriptor(
name='remote_hardware.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\016RemoteHardwareH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=b'\n\x15remote_hardware.proto\"\xca\x01\n\x0fHardwareMessage\x12\"\n\x03typ\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\x42J\n\x13\x63om.geeksville.meshB\x0eRemoteHardwareH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
)
_HARDWAREMESSAGE = DESCRIPTOR.message_types_by_name['HardwareMessage']
_HARDWAREMESSAGE_TYPE = _HARDWAREMESSAGE.enum_types_by_name['Type']
_HARDWAREMESSAGE_TYPE = _descriptor.EnumDescriptor(
name='Type',
full_name='HardwareMessage.Type',
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name='UNSET', index=0, number=0,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='WRITE_GPIOS', index=1, number=1,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='WATCH_GPIOS', index=2, number=2,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='GPIOS_CHANGED', index=3, number=3,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='READ_GPIOS', index=4, number=4,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='READ_GPIOS_REPLY', index=5, number=5,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=120,
serialized_end=228,
)
_sym_db.RegisterEnumDescriptor(_HARDWAREMESSAGE_TYPE)
_HARDWAREMESSAGE = _descriptor.Descriptor(
name='HardwareMessage',
full_name='HardwareMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='typ', full_name='HardwareMessage.typ', index=0,
number=1, type=14, cpp_type=8, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='gpio_mask', full_name='HardwareMessage.gpio_mask', index=1,
number=2, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='gpio_value', full_name='HardwareMessage.gpio_value', index=2,
number=3, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
_HARDWAREMESSAGE_TYPE,
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=26,
serialized_end=228,
)
_HARDWAREMESSAGE.fields_by_name['typ'].enum_type = _HARDWAREMESSAGE_TYPE
_HARDWAREMESSAGE_TYPE.containing_type = _HARDWAREMESSAGE
DESCRIPTOR.message_types_by_name['HardwareMessage'] = _HARDWAREMESSAGE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
HardwareMessage = _reflection.GeneratedProtocolMessageType('HardwareMessage', (_message.Message,), {
'DESCRIPTOR' : _HARDWAREMESSAGE,
'__module__' : 'remote_hardware_pb2'
@@ -27,12 +119,6 @@ HardwareMessage = _reflection.GeneratedProtocolMessageType('HardwareMessage', (_
})
_sym_db.RegisterMessage(HardwareMessage)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016RemoteHardwareH\003Z!github.com/meshtastic/gomeshproto'
_HARDWAREMESSAGE._serialized_start=26
_HARDWAREMESSAGE._serialized_end=228
_HARDWAREMESSAGE_TYPE._serialized_start=120
_HARDWAREMESSAGE_TYPE._serialized_end=228
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -24,8 +24,10 @@ class SerialInterface(StreamInterface):
"""
self.noProto = noProto
if devPath is None:
ports = meshtastic.util.findPorts()
self.devPath = devPath
if self.devPath is None:
ports = meshtastic.util.findPorts(True)
logging.debug(f"ports:{ports}")
if len(ports) == 0:
meshtastic.util.our_exit("Warning: No Meshtastic devices detected.")
@@ -34,21 +36,21 @@ class SerialInterface(StreamInterface):
message += f" Ports detected:{ports}"
meshtastic.util.our_exit(message)
else:
devPath = ports[0]
self.devPath = ports[0]
logging.debug(f"Connecting to {devPath}")
logging.debug(f"Connecting to {self.devPath}")
# first we need to set the HUPCL so the device will not reboot based on RTS and/or DTR
# see https://github.com/pyserial/pyserial/issues/124
if platform.system() != 'Windows':
with open(devPath, encoding='utf8') as f:
with open(self.devPath, encoding='utf8') as f:
attrs = termios.tcgetattr(f)
attrs[2] = attrs[2] & ~termios.HUPCL
termios.tcsetattr(f, termios.TCSAFLUSH, attrs)
f.close()
time.sleep(0.1)
self.stream = serial.Serial(devPath, 921600, exclusive=True, timeout=0.5, write_timeout=0)
self.stream = serial.Serial(self.devPath, 921600, exclusive=True, timeout=0.5, write_timeout=0)
self.stream.flush()
time.sleep(0.1)

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: storeforward.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
@@ -14,15 +13,313 @@ _sym_db = _symbol_database.Default()
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\x10jBQ\n\x13\x63om.geeksville.meshB\x15StoreAndForwardProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
DESCRIPTOR = _descriptor.FileDescriptor(
name='storeforward.proto',
package='',
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\025StoreAndForwardProtosH\003Z!github.com/meshtastic/gomeshproto',
serialized_pb=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\x10jBQ\n\x13\x63om.geeksville.meshB\x15StoreAndForwardProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
)
_STOREANDFORWARD = DESCRIPTOR.message_types_by_name['StoreAndForward']
_STOREANDFORWARD_STATISTICS = _STOREANDFORWARD.nested_types_by_name['Statistics']
_STOREANDFORWARD_HISTORY = _STOREANDFORWARD.nested_types_by_name['History']
_STOREANDFORWARD_HEARTBEAT = _STOREANDFORWARD.nested_types_by_name['Heartbeat']
_STOREANDFORWARD_REQUESTRESPONSE = _STOREANDFORWARD.enum_types_by_name['RequestResponse']
_STOREANDFORWARD_REQUESTRESPONSE = _descriptor.EnumDescriptor(
name='RequestResponse',
full_name='StoreAndForward.RequestResponse',
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name='UNSET', index=0, number=0,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ROUTER_ERROR', index=1, number=1,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ROUTER_HEARTBEAT', index=2, number=2,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ROUTER_PING', index=3, number=3,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ROUTER_PONG', index=4, number=4,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ROUTER_BUSY', index=5, number=5,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ROUTER_HISTORY', index=6, number=6,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='CLIENT_ERROR', index=7, number=101,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='CLIENT_HISTORY', index=8, number=102,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='CLIENT_STATS', index=9, number=103,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='CLIENT_PING', index=10, number=104,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='CLIENT_PONG', index=11, number=105,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='CLIENT_ABORT', index=12, number=106,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=554,
serialized_end=801,
)
_sym_db.RegisterEnumDescriptor(_STOREANDFORWARD_REQUESTRESPONSE)
_STOREANDFORWARD_STATISTICS = _descriptor.Descriptor(
name='Statistics',
full_name='StoreAndForward.Statistics',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='messages_total', full_name='StoreAndForward.Statistics.messages_total', index=0,
number=1, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='messages_saved', full_name='StoreAndForward.Statistics.messages_saved', index=1,
number=2, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='messages_max', full_name='StoreAndForward.Statistics.messages_max', index=2,
number=3, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='up_time', full_name='StoreAndForward.Statistics.up_time', index=3,
number=4, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='requests', full_name='StoreAndForward.Statistics.requests', index=4,
number=5, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='requests_history', full_name='StoreAndForward.Statistics.requests_history', index=5,
number=6, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='heartbeat', full_name='StoreAndForward.Statistics.heartbeat', index=6,
number=7, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='return_max', full_name='StoreAndForward.Statistics.return_max', index=7,
number=8, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='return_window', full_name='StoreAndForward.Statistics.return_window', index=8,
number=9, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=223,
serialized_end=428,
)
_STOREANDFORWARD_HISTORY = _descriptor.Descriptor(
name='History',
full_name='StoreAndForward.History',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='history_messages', full_name='StoreAndForward.History.history_messages', index=0,
number=1, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='window', full_name='StoreAndForward.History.window', index=1,
number=2, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='last_request', full_name='StoreAndForward.History.last_request', index=2,
number=3, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=430,
serialized_end=503,
)
_STOREANDFORWARD_HEARTBEAT = _descriptor.Descriptor(
name='Heartbeat',
full_name='StoreAndForward.Heartbeat',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='period', full_name='StoreAndForward.Heartbeat.period', index=0,
number=1, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='secondary', full_name='StoreAndForward.Heartbeat.secondary', index=1,
number=2, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=505,
serialized_end=551,
)
_STOREANDFORWARD = _descriptor.Descriptor(
name='StoreAndForward',
full_name='StoreAndForward',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='rr', full_name='StoreAndForward.rr', index=0,
number=1, type=14, cpp_type=8, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='stats', full_name='StoreAndForward.stats', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='history', full_name='StoreAndForward.history', index=2,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='heartbeat', full_name='StoreAndForward.heartbeat', index=3,
number=4, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[_STOREANDFORWARD_STATISTICS, _STOREANDFORWARD_HISTORY, _STOREANDFORWARD_HEARTBEAT, ],
enum_types=[
_STOREANDFORWARD_REQUESTRESPONSE,
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=23,
serialized_end=801,
)
_STOREANDFORWARD_STATISTICS.containing_type = _STOREANDFORWARD
_STOREANDFORWARD_HISTORY.containing_type = _STOREANDFORWARD
_STOREANDFORWARD_HEARTBEAT.containing_type = _STOREANDFORWARD
_STOREANDFORWARD.fields_by_name['rr'].enum_type = _STOREANDFORWARD_REQUESTRESPONSE
_STOREANDFORWARD.fields_by_name['stats'].message_type = _STOREANDFORWARD_STATISTICS
_STOREANDFORWARD.fields_by_name['history'].message_type = _STOREANDFORWARD_HISTORY
_STOREANDFORWARD.fields_by_name['heartbeat'].message_type = _STOREANDFORWARD_HEARTBEAT
_STOREANDFORWARD_REQUESTRESPONSE.containing_type = _STOREANDFORWARD
DESCRIPTOR.message_types_by_name['StoreAndForward'] = _STOREANDFORWARD
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
StoreAndForward = _reflection.GeneratedProtocolMessageType('StoreAndForward', (_message.Message,), {
'Statistics' : _reflection.GeneratedProtocolMessageType('Statistics', (_message.Message,), {
@@ -54,18 +351,6 @@ _sym_db.RegisterMessage(StoreAndForward.Statistics)
_sym_db.RegisterMessage(StoreAndForward.History)
_sym_db.RegisterMessage(StoreAndForward.Heartbeat)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\025StoreAndForwardProtosH\003Z!github.com/meshtastic/gomeshproto'
_STOREANDFORWARD._serialized_start=23
_STOREANDFORWARD._serialized_end=801
_STOREANDFORWARD_STATISTICS._serialized_start=223
_STOREANDFORWARD_STATISTICS._serialized_end=428
_STOREANDFORWARD_HISTORY._serialized_start=430
_STOREANDFORWARD_HISTORY._serialized_end=503
_STOREANDFORWARD_HEARTBEAT._serialized_start=505
_STOREANDFORWARD_HEARTBEAT._serialized_end=551
_STOREANDFORWARD_REQUESTRESPONSE._serialized_start=554
_STOREANDFORWARD_REQUESTRESPONSE._serialized_end=801
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -8,7 +8,7 @@ import serial
from meshtastic.mesh_interface import MeshInterface
from meshtastic.util import stripnl
from meshtastic.util import stripnl, is_windows11
START1 = 0x94
@@ -38,6 +38,8 @@ class StreamInterface(MeshInterface):
self._rxBuf = bytes() # empty
self._wantExit = False
self.is_windows11 = is_windows11()
# FIXME, figure out why daemon=True causes reader thread to exit too early
self._rxThread = threading.Thread(target=self.__reader, args=(), daemon=True)
@@ -88,8 +90,12 @@ class StreamInterface(MeshInterface):
if self.stream: # ignore writes when stream is closed
self.stream.write(b)
self.stream.flush()
# we sleep here to give the TBeam a chance to work
time.sleep(0.1)
# win11 might need a bit more time, too
if self.is_windows11:
time.sleep(1.0)
else:
# we sleep here to give the TBeam a chance to work
time.sleep(0.1)
def _readBytes(self, length):
"""Read an array of bytes from our stream"""

View File

@@ -2,10 +2,6 @@
It is used for auto detection as to which device might be connected.
"""
import platform
import subprocess
import re
# Goal is to detect which device and port to use from the supported devices
# without installing any libraries that are not currently in the python meshtastic library
@@ -42,16 +38,13 @@ tbeam_M8N = SupportedDevice(name="T-Beam", version="M8N", for_firmware="tbeam",
tbeam_M8N_SX1262 = SupportedDevice(name="T-Beam", version="M8N_SX1262", for_firmware="tbeam",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v1_1 = SupportedDevice(name="T-Lora", version="1.1", for_firmware="tlora-v1",
tlora_v1 = SupportedDevice(name="T-Lora", version="1", for_firmware="tlora-v1",
baseport_on_linux="ttyUSB", baseport_on_mac="cu.usbserial",
usb_vendor_id_in_hex="10c4", usb_product_id_in_hex="ea60")
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v1_3 = SupportedDevice(name="T-Lora", version="1.3", for_firmware="tlora-v1-3",
baseport_on_linux="ttyUSB", baseport_on_mac="cu.usbserial",
usb_vendor_id_in_hex="10c4", usb_product_id_in_hex="ea60")
tlora_v2_0 = SupportedDevice(name="T-Lora", version="2.0", for_firmware="tlora-v2-1",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v2_1 = SupportedDevice(name="T-Lora", version="2.1", for_firmware="tlora-v2-1",
tlora_v2 = SupportedDevice(name="T-Lora", version="2", for_firmware="tlora-v2",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v2_1_1_6 = SupportedDevice(name="T-Lora", version="2.1-1.6", for_firmware="tlora-v2-1-1.6",
@@ -66,11 +59,16 @@ heltec_v2_0 = SupportedDevice(name="Heltec", version="2.0", for_firmware="heltec
heltec_v2_1 = SupportedDevice(name="Heltec", version="2.1", for_firmware="heltec-v2.1",
baseport_on_linux="ttyUSB", baseport_on_mac="cu.usbserial-",
usb_vendor_id_in_hex="10c4", usb_product_id_in_hex="ea60")
rak11200 = SupportedDevice(name="RAK 11200", version="", for_firmware="rak11200",
baseport_on_linux="ttyUSB", baseport_on_mac="cu.usbserial-",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="7523")
meshtastic_diy_v1 = SupportedDevice(name="Meshtastic DIY", version="1", for_firmware="meshtastic-diy-v1",
baseport_on_linux="ttyUSB", baseport_on_mac="cu.usbserial-",
usb_vendor_id_in_hex="10c4", usb_product_id_in_hex="ea60")
# TODO: get info on TEcho
techo_1 = SupportedDevice(name="T-Echo", version="1", for_firmware="t-echo-1", device_class="nrf52")
# Note: The T-Echo reports product id in boot mode
techo_1 = SupportedDevice(name="T-Echo", version="1", for_firmware="t-echo-1", device_class="nrf52",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="239a", usb_product_id_in_hex="0029")
rak4631_5005 = SupportedDevice(name="RAK 4631 5005", version="", for_firmware="rak4631_5005",
device_class="nrf52",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
@@ -82,109 +80,7 @@ rak4631_19003 = SupportedDevice(name="RAK 4631 19003", version="", for_firmware=
usb_vendor_id_in_hex="239a", usb_product_id_in_hex="8029")
supported_devices = [tbeam_v0_7, tbeam_v1_1, tbeam_M8N, tbeam_M8N_SX1262,
tlora_v1_1, tlora_v1_3, tlora_v2_0, tlora_v2_1, tlora_v2_1_1_6,
tlora_v1, tlora_v1_3, tlora_v2, tlora_v2_1_1_6,
heltec_v1, heltec_v2_0, heltec_v2_1,
meshtastic_diy_v1, techo_1, rak4631_5005, rak4631_19003]
def get_unique_vendor_ids():
"""Return a set of unique vendor ids"""
vids = set()
for d in supported_devices:
if d.usb_vendor_id_in_hex:
vids.add(d.usb_vendor_id_in_hex)
return vids
def get_devices_with_vendor_id(vid):
"""Return a set of unique devices with the vendor id"""
sd = set()
for d in supported_devices:
if d.usb_vendor_id_in_hex == vid:
sd.add(d)
return sd
def active_ports_on_supported_devices(sds):
"""Return a set of active ports based on the supplied supported devices"""
ports = set()
baseports = set()
system = platform.system()
# figure out what possible base ports there are
for d in sds:
if system == "Linux":
baseports.add(d.baseport_on_linux)
elif system == "Darwin":
baseports.add(d.baseport_on_mac)
elif system == "Windows":
baseports.add(d.baseport_on_windows)
for bp in baseports:
if system == "Linux":
# see if we have any devices (ignoring any stderr output)
command = f'ls -al /dev/{bp}* 2> /dev/null'
#print(f'command:{command}')
_, ls_output = subprocess.getstatusoutput(command)
#print(f'ls_output:{ls_output}')
# if we got output, there are ports
if len(ls_output) > 0:
#print('got output')
# for each line of output
lines = ls_output.split('\n')
#print(f'lines:{lines}')
for line in lines:
parts = line.split(' ')
#print(f'parts:{parts}')
port = parts[-1]
#print(f'port:{port}')
ports.add(port)
elif system == "Darwin":
# see if we have any devices (ignoring any stderr output)
command = f'ls -al /dev/{bp}* 2> /dev/null'
#print(f'command:{command}')
_, ls_output = subprocess.getstatusoutput(command)
#print(f'ls_output:{ls_output}')
# if we got output, there are ports
if len(ls_output) > 0:
#print('got output')
# for each line of output
lines = ls_output.split('\n')
#print(f'lines:{lines}')
for line in lines:
parts = line.split(' ')
#print(f'parts:{parts}')
port = parts[-1]
#print(f'port:{port}')
ports.add(port)
elif system == "Windows":
# for each device in supported devices found
for d in sds:
# find the port(s)
com_ports = detect_windows_port(d)
#print(f'com_ports:{com_ports}')
# add all ports
for com_port in com_ports:
ports.add(com_port)
return ports
def detect_windows_port(sd):
"""detect if Windows port"""
ports = set()
if sd:
system = platform.system()
if system == "Windows":
command = ('powershell.exe "[Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8;'
'Get-PnpDevice -PresentOnly | Where-Object{ ($_.DeviceId -like ')
command += f"'*{sd.usb_vendor_id_in_hex.upper()}*'"
command += ')} | Format-List"'
#print(f'command:{command}')
_, sp_output = subprocess.getstatusoutput(command)
#print(f'sp_output:{sp_output}')
p = re.compile(r'\(COM(.*)\)')
for x in p.findall(sp_output):
#print(f'x:{x}')
ports.add(f'COM{x}')
return ports
meshtastic_diy_v1, techo_1, rak4631_5005, rak4631_19003,
rak11200]

104
meshtastic/telemetry_pb2.py Normal file
View File

@@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: telemetry.proto
from google.protobuf import descriptor as _descriptor
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.FileDescriptor(
name='telemetry.proto',
package='',
syntax='proto3',
serialized_options=b'Z!github.com/meshtastic/gomeshproto',
serialized_pb=b'\n\x0ftelemetry.proto\"\x92\x01\n\tTelemetry\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\x42#Z!github.com/meshtastic/gomeshprotob\x06proto3'
)
_TELEMETRY = _descriptor.Descriptor(
name='Telemetry',
full_name='Telemetry',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='temperature', full_name='Telemetry.temperature', index=0,
number=1, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='relative_humidity', full_name='Telemetry.relative_humidity', index=1,
number=2, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='barometric_pressure', full_name='Telemetry.barometric_pressure', index=2,
number=3, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='gas_resistance', full_name='Telemetry.gas_resistance', index=3,
number=4, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='voltage', full_name='Telemetry.voltage', index=4,
number=5, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='current', full_name='Telemetry.current', index=5,
number=6, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=20,
serialized_end=166,
)
DESCRIPTOR.message_types_by_name['Telemetry'] = _TELEMETRY
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
Telemetry = _reflection.GeneratedProtocolMessageType('Telemetry', (_message.Message,), {
'DESCRIPTOR' : _TELEMETRY,
'__module__' : 'telemetry_pb2'
# @@protoc_insertion_point(class_scope:Telemetry)
})
_sym_db.RegisterMessage(Telemetry)
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)

View File

@@ -149,7 +149,7 @@ def testAll(numTests=5):
This is called from the cli with the "--test" option.
"""
ports = meshtastic.util.findPorts()
ports = meshtastic.util.findPorts(True)
if len(ports) < 2:
meshtastic.util.our_exit("Warning: Must have at least two devices connected to USB.")

View File

@@ -46,7 +46,7 @@ def test_main_init_parser_version(capsys):
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0
out, err = capsys.readouterr()
assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
assert re.match(r'[0-9]+\.[0-9]+[\.a][0-9]', out)
assert err == ''
@@ -62,7 +62,7 @@ def test_main_main_version(capsys):
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0
out, err = capsys.readouterr()
assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
assert re.match(r'[0-9]+\.[0-9]+[\.a][0-9]', out)
assert err == ''
@@ -442,6 +442,43 @@ def test_main_set_owner_short_to_bob(capsys):
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_set_canned_messages(capsys):
"""Test --set-canned-message """
sys.argv = ['', '--set-canned-message', 'foo']
Globals.getInstance().set_args(sys.argv)
iface = MagicMock(autospec=SerialInterface)
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'Setting canned plugin message to foo', out, re.MULTILINE)
assert err == ''
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_get_canned_messages(capsys, caplog, iface_with_nodes):
"""Test --get-canned-message """
sys.argv = ['', '--get-canned-message']
Globals.getInstance().set_args(sys.argv)
iface = iface_with_nodes
iface.localNode.cannedPluginMessage = 'foo'
with caplog.at_level(logging.DEBUG):
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'canned_plugin_message:foo', out, re.MULTILINE)
assert err == ''
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_set_ham_to_KI123(capsys):
@@ -1248,8 +1285,8 @@ def test_main_ch_enable_primary_channel(capsys):
@pytest.mark.usefixtures("reset_globals")
def test_main_ch_range_options(capsys):
"""Test changing the various range options."""
range_options = ['--ch-longslow', '--ch-longfast', '--ch-mediumslow',
'--ch-mediumfast', '--ch-shortslow', '--ch-shortfast']
range_options = ['--ch-vlongslow', '--ch-longslow', '--ch-longfast', '--ch-midslow',
'--ch-midfast', '--ch-shortslow', '--ch-shortfast']
for range_option in range_options:
sys.argv = ['', f"{range_option}" ]
Globals.getInstance().set_args(sys.argv)
@@ -2294,6 +2331,54 @@ def test_main_setPref_invalid_field_camel(capsys):
assert err == ''
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_setPref_ignore_incoming_123(capsys):
"""Test setPref() with ignore_incoming"""
class Field:
"""Simple class for testing."""
def __init__(self, name, enum_type):
"""constructor"""
self.name = name
self.enum_type = enum_type
ignore_incoming_field = Field('ignore_incoming', 'list')
prefs = MagicMock()
prefs.DESCRIPTOR.fields_by_name.get.return_value = ignore_incoming_field
setPref(prefs, 'ignore_incoming', '123')
out, err = capsys.readouterr()
assert re.search(r"Adding '123' to the ignore_incoming list", out, re.MULTILINE)
assert re.search(r'Set ignore_incoming to 123', out, re.MULTILINE)
assert err == ''
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_setPref_ignore_incoming_0(capsys):
"""Test setPref() with ignore_incoming"""
class Field:
"""Simple class for testing."""
def __init__(self, name, enum_type):
"""constructor"""
self.name = name
self.enum_type = enum_type
ignore_incoming_field = Field('ignore_incoming', 'list')
prefs = MagicMock()
prefs.DESCRIPTOR.fields_by_name.get.return_value = ignore_incoming_field
setPref(prefs, 'ignore_incoming', '0')
out, err = capsys.readouterr()
assert re.search(r'Clearing ignore_incoming list', out, re.MULTILINE)
assert re.search(r'Set ignore_incoming to 0', out, re.MULTILINE)
assert err == ''
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_ch_set_psk_no_ch_index(capsys):

View File

@@ -213,13 +213,13 @@ def test_handleFromRadio_with_my_info(caplog):
# It "translates" to this:
# my_info {
# my_node_num: 682584012
# num_bands: 13
# firmware_version: "1.2.49.5354c49"
# reboot_count: 13
# bitrate: 17.088470458984375
# message_timeout_msec: 300000
# min_app_version: 20200
# max_channels: 8
# has_wifi: true
# }
from_radio_bytes = b'\x1a,\x08\xcc\xcf\xbd\xc5\x02\x18\r2\x0e1.2.49.5354c49P\r]0\xb5\x88Ah\xe0\xa7\x12p\xe8\x9d\x01x\x08\x90\x01\x01'
iface = MeshInterface(noProto=True)
@@ -227,7 +227,6 @@ def test_handleFromRadio_with_my_info(caplog):
iface._handleFromRadio(from_radio_bytes)
iface.close()
assert re.search(r'Received myinfo', caplog.text, re.MULTILINE)
assert re.search(r'num_bands: 13', caplog.text, re.MULTILINE)
assert re.search(r'max_channels: 8', caplog.text, re.MULTILINE)

View File

@@ -11,6 +11,9 @@ from ..serial_interface import SerialInterface
from ..admin_pb2 import AdminMessage
from ..channel_pb2 import Channel
from ..radioconfig_pb2 import RadioConfig
#from ..cannedmessages_pb2 import (CannedMessagePluginMessagePart1, CannedMessagePluginMessagePart2,
# CannedMessagePluginMessagePart3, CannedMessagePluginMessagePart4,
# CannedMessagePluginMessagePart5)
from ..util import Timeout
@@ -43,6 +46,122 @@ def test_node_requestConfig(capsys):
assert err == ''
#@pytest.mark.unit
#def test_node_get_canned_message_with_all_parts(capsys):
# """Test run get_canned_message()"""
# iface = MagicMock(autospec=SerialInterface)
# amesg = MagicMock(autospec=AdminMessage)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# with patch('meshtastic.admin_pb2.AdminMessage', return_value=amesg):
# # we have a sleep in this method, so override it so it goes fast
# with patch('time.sleep'):
# anode = Node(mo, 'bar')
# anode.cannedPluginMessagePart1 = 'a'
# anode.cannedPluginMessagePart2 = 'b'
# anode.cannedPluginMessagePart3 = 'c'
# anode.cannedPluginMessagePart4 = 'd'
# anode.cannedPluginMessagePart5 = 'e'
# anode.get_canned_message()
# out, err = capsys.readouterr()
# assert re.search(r'canned_plugin_message:abcde', out, re.MULTILINE)
# assert err == ''
#
#
#@pytest.mark.unit
#def test_node_get_canned_message_with_some_parts(capsys):
# """Test run get_canned_message()"""
# iface = MagicMock(autospec=SerialInterface)
# amesg = MagicMock(autospec=AdminMessage)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# with patch('meshtastic.admin_pb2.AdminMessage', return_value=amesg):
# # we have a sleep in this method, so override it so it goes fast
# with patch('time.sleep'):
# anode = Node(mo, 'bar')
# anode.cannedPluginMessagePart1 = 'a'
# anode.get_canned_message()
# out, err = capsys.readouterr()
# assert re.search(r'canned_plugin_message:a', out, re.MULTILINE)
# assert err == ''
#
#
#@pytest.mark.unit
#def test_node_set_canned_message_one_part(caplog):
# """Test run set_canned_message()"""
# iface = MagicMock(autospec=SerialInterface)
# amesg = MagicMock(autospec=AdminMessage)
# with caplog.at_level(logging.DEBUG):
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# with patch('meshtastic.admin_pb2.AdminMessage', return_value=amesg):
# anode = Node(mo, 'bar')
# anode.set_canned_message('foo')
# assert re.search(r"Setting canned message 'foo' part 1", caplog.text, re.MULTILINE)
# assert not re.search(r"Setting canned message '' part 2", caplog.text, re.MULTILINE)
#
#
#@pytest.mark.unit
#def test_node_set_canned_message_200(caplog):
# """Test run set_canned_message() 200 characters long"""
# iface = MagicMock(autospec=SerialInterface)
# amesg = MagicMock(autospec=AdminMessage)
# with caplog.at_level(logging.DEBUG):
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# with patch('meshtastic.admin_pb2.AdminMessage', return_value=amesg):
# anode = Node(mo, 'bar')
# message_200_chars_long = 'a' * 200
# anode.set_canned_message(message_200_chars_long)
# assert re.search(r" part 1", caplog.text, re.MULTILINE)
# assert not re.search(r"Setting canned message '' part 2", caplog.text, re.MULTILINE)
#
#
#@pytest.mark.unit
#def test_node_set_canned_message_201(caplog):
# """Test run set_canned_message() 201 characters long"""
# iface = MagicMock(autospec=SerialInterface)
# amesg = MagicMock(autospec=AdminMessage)
# with caplog.at_level(logging.DEBUG):
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# with patch('meshtastic.admin_pb2.AdminMessage', return_value=amesg):
# anode = Node(mo, 'bar')
# message_201_chars_long = 'a' * 201
# anode.set_canned_message(message_201_chars_long)
# assert re.search(r" part 1", caplog.text, re.MULTILINE)
# assert re.search(r"Setting canned message 'a' part 2", caplog.text, re.MULTILINE)
#
#
#@pytest.mark.unit
#def test_node_set_canned_message_1000(caplog):
# """Test run set_canned_message() 1000 characters long"""
# iface = MagicMock(autospec=SerialInterface)
# amesg = MagicMock(autospec=AdminMessage)
# with caplog.at_level(logging.DEBUG):
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# with patch('meshtastic.admin_pb2.AdminMessage', return_value=amesg):
# anode = Node(mo, 'bar')
# message_1000_chars_long = 'a' * 1000
# anode.set_canned_message(message_1000_chars_long)
# assert re.search(r" part 1", caplog.text, re.MULTILINE)
# assert re.search(r" part 2", caplog.text, re.MULTILINE)
# assert re.search(r" part 3", caplog.text, re.MULTILINE)
# assert re.search(r" part 4", caplog.text, re.MULTILINE)
# assert re.search(r" part 5", caplog.text, re.MULTILINE)
#
#
#@pytest.mark.unit
#def test_node_set_canned_message_1001(capsys):
# """Test run set_canned_message() 1001 characters long"""
# iface = MagicMock(autospec=SerialInterface)
# with pytest.raises(SystemExit) as pytest_wrapped_e:
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar')
# message_1001_chars_long = 'a' * 1001
# anode.set_canned_message(message_1001_chars_long)
# assert pytest_wrapped_e.type == SystemExit
# assert pytest_wrapped_e.value.code == 1
# out, err = capsys.readouterr()
# assert re.search(r'Warning: The canned message', out, re.MULTILINE)
# assert err == ''
@pytest.mark.unit
def test_setOwner_and_team(caplog):
"""Test setOwner"""
@@ -162,7 +281,7 @@ def test_setURL_valid_URL(caplog):
anode.channels = channels
anode.setURL(url)
assert re.search(r'Channel i:0', caplog.text, re.MULTILINE)
assert re.search(r'modem_config: Bw125Cr48Sf4096', caplog.text, re.MULTILINE)
assert re.search(r'modem_config: MidSlow', caplog.text, re.MULTILINE)
assert re.search(r'psk: "\\001"', caplog.text, re.MULTILINE)
assert re.search(r'role: PRIMARY', caplog.text, re.MULTILINE)
@@ -216,7 +335,7 @@ def test_showChannels(capsys):
# primary channel
assert re.search(r'Primary channel URL', out, re.MULTILINE)
assert re.search(r'PRIMARY psk=default ', out, re.MULTILINE)
assert re.search(r'"modemConfig": "Bw125Cr48Sf4096"', out, re.MULTILINE)
assert re.search(r'"modemConfig": "MidSlow"', out, re.MULTILINE)
assert re.search(r'"psk": "AQ=="', out, re.MULTILINE)
# secondary channel
assert re.search(r'SECONDARY psk=secret ', out, re.MULTILINE)
@@ -694,6 +813,352 @@ def test_requestChannel_localNode(caplog):
assert not re.search(r'from remote node', caplog.text, re.MULTILINE)
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart1(caplog):
# """Test onResponseRequestCannedMessagePluginMessagePart1()"""
#
# part1 = CannedMessagePluginMessagePart1()
# part1.text = 'foo1'
#
# msg1 = MagicMock(autospec=AdminMessage)
# msg1.get_canned_message_plugin_part1_response = part1
#
# packet = {
# 'from': 682968612,
# 'to': 682968612,
# 'decoded': {
# 'portnum': 'ADMIN_APP',
# 'payload': 'faked',
# 'requestId': 927039000,
# 'admin': {
# 'getCannedMessagePluginPart1Response': {'text': 'foo1'},
# 'raw': msg1
# }
# },
# 'id': 589440320,
# 'rxTime': 1642710843,
# 'hopLimit': 3,
# 'priority': 'RELIABLE',
# 'raw': 'faked',
# 'fromId': '!28b54624',
# 'toId': '!28b54624'
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart1(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart1', caplog.text, re.MULTILINE)
# assert anode.cannedPluginMessagePart1 == 'foo1'
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart2(caplog):
# """Test onResponseRequestCannedMessagePluginMessagePart2()"""
#
# part2 = CannedMessagePluginMessagePart2()
# part2.text = 'foo2'
#
# msg2 = MagicMock(autospec=AdminMessage)
# msg2.get_canned_message_plugin_part2_response = part2
#
# packet = {
# 'from': 682968612,
# 'to': 682968612,
# 'decoded': {
# 'portnum': 'ADMIN_APP',
# 'payload': 'faked',
# 'requestId': 927039000,
# 'admin': {
# 'getCannedMessagePluginPart2Response': {'text': 'foo2'},
# 'raw': msg2
# }
# },
# 'id': 589440320,
# 'rxTime': 1642710843,
# 'hopLimit': 3,
# 'priority': 'RELIABLE',
# 'raw': 'faked',
# 'fromId': '!28b54624',
# 'toId': '!28b54624'
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart2(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart2', caplog.text, re.MULTILINE)
# assert anode.cannedPluginMessagePart2 == 'foo2'
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart3(caplog):
# """Test onResponseRequestCannedMessagePluginMessagePart3()"""
#
# part3 = CannedMessagePluginMessagePart3()
# part3.text = 'foo3'
#
# msg3 = MagicMock(autospec=AdminMessage)
# msg3.get_canned_message_plugin_part3_response = part3
#
# packet = {
# 'from': 682968612,
# 'to': 682968612,
# 'decoded': {
# 'portnum': 'ADMIN_APP',
# 'payload': 'faked',
# 'requestId': 927039000,
# 'admin': {
# 'getCannedMessagePluginPart3Response': {'text': 'foo3'},
# 'raw': msg3
# }
# },
# 'id': 589440320,
# 'rxTime': 1642710843,
# 'hopLimit': 3,
# 'priority': 'RELIABLE',
# 'raw': 'faked',
# 'fromId': '!28b54624',
# 'toId': '!28b54624'
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart3(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart3', caplog.text, re.MULTILINE)
# assert anode.cannedPluginMessagePart3 == 'foo3'
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart4(caplog):
# """Test onResponseRequestCannedMessagePluginMessagePart4()"""
#
# part4 = CannedMessagePluginMessagePart4()
# part4.text = 'foo4'
#
# msg4 = MagicMock(autospec=AdminMessage)
# msg4.get_canned_message_plugin_part4_response = part4
#
# packet = {
# 'from': 682968612,
# 'to': 682968612,
# 'decoded': {
# 'portnum': 'ADMIN_APP',
# 'payload': 'faked',
# 'requestId': 927039000,
# 'admin': {
# 'getCannedMessagePluginPart4Response': {'text': 'foo4'},
# 'raw': msg4
# }
# },
# 'id': 589440320,
# 'rxTime': 1642710843,
# 'hopLimit': 3,
# 'priority': 'RELIABLE',
# 'raw': 'faked',
# 'fromId': '!28b54624',
# 'toId': '!28b54624'
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart4(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart4', caplog.text, re.MULTILINE)
# assert anode.cannedPluginMessagePart4 == 'foo4'
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart5(caplog):
# """Test onResponseRequestCannedMessagePluginMessagePart5()"""
#
# part5 = CannedMessagePluginMessagePart5()
# part5.text = 'foo5'
#
# msg5 = MagicMock(autospec=AdminMessage)
# msg5.get_canned_message_plugin_part5_response = part5
#
#
# packet = {
# 'from': 682968612,
# 'to': 682968612,
# 'decoded': {
# 'portnum': 'ADMIN_APP',
# 'payload': 'faked',
# 'requestId': 927039000,
# 'admin': {
# 'getCannedMessagePluginPart5Response': {'text': 'foo5'},
# 'raw': msg5
# }
# },
# 'id': 589440320,
# 'rxTime': 1642710843,
# 'hopLimit': 3,
# 'priority': 'RELIABLE',
# 'raw': 'faked',
# 'fromId': '!28b54624',
# 'toId': '!28b54624'
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart5(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart5', caplog.text, re.MULTILINE)
# assert anode.cannedPluginMessagePart5 == 'foo5'
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart1_error(caplog, capsys):
# """Test onResponseRequestCannedMessagePluginMessagePart1() with error"""
#
# packet = {
# 'decoded': {
# 'routing': {
# 'errorReason': 'some made up error',
# },
# },
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart1(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart1', caplog.text, re.MULTILINE)
# out, err = capsys.readouterr()
# assert re.search(r'Error on response', out)
# assert err == ''
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart2_error(caplog, capsys):
# """Test onResponseRequestCannedMessagePluginMessagePart2() with error"""
#
# packet = {
# 'decoded': {
# 'routing': {
# 'errorReason': 'some made up error',
# },
# },
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart2(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart2', caplog.text, re.MULTILINE)
# out, err = capsys.readouterr()
# assert re.search(r'Error on response', out)
# assert err == ''
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart3_error(caplog, capsys):
# """Test onResponseRequestCannedMessagePluginMessagePart3() with error"""
#
# packet = {
# 'decoded': {
# 'routing': {
# 'errorReason': 'some made up error',
# },
# },
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart3(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart3', caplog.text, re.MULTILINE)
# out, err = capsys.readouterr()
# assert re.search(r'Error on response', out)
# assert err == ''
#
#
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart4_error(caplog, capsys):
# """Test onResponseRequestCannedMessagePluginMessagePart4() with error"""
#
# packet = {
# 'decoded': {
# 'routing': {
# 'errorReason': 'some made up error',
# },
# },
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart4(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart4', caplog.text, re.MULTILINE)
# out, err = capsys.readouterr()
# assert re.search(r'Error on response', out)
# assert err == ''
#
#
#@pytest.mark.unit
#def test_onResponseRequestCannedMessagePluginMesagePart5_error(caplog, capsys):
# """Test onResponseRequestCannedMessagePluginMessagePart5() with error"""
#
# packet = {
# 'decoded': {
# 'routing': {
# 'errorReason': 'some made up error',
# },
# },
# }
#
# iface = MagicMock(autospec=SerialInterface)
# with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
# anode = Node(mo, 'bar', noProto=True)
# # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
# mo.localNode = anode
#
# with caplog.at_level(logging.DEBUG):
# anode.onResponseRequestCannedMessagePluginMessagePart5(packet)
# assert re.search(r'onResponseRequestCannedMessagePluginMessagePart5', caplog.text, re.MULTILINE)
# out, err = capsys.readouterr()
# assert re.search(r'Error on response', out)
# assert err == ''
@pytest.mark.unit
def test_onResponseRequestChannel(caplog):
"""Test onResponseRequestChannel()"""

View File

@@ -160,7 +160,7 @@ def test_smoke1_send_hello():
def test_smoke1_port():
"""Test --port"""
# first, get the ports
ports = findPorts()
ports = findPorts(True)
# hopefully there is just one
assert len(ports) == 1
port = ports[0]

View File

@@ -21,7 +21,7 @@ from ..util import findPorts
# seconds to pause after running a meshtastic command
PAUSE_AFTER_COMMAND = 0.1
PAUSE_AFTER_REBOOT = 0.1
PAUSE_AFTER_REBOOT = 0.2
#TODO: need to fix the virtual device to have a reboot. When you issue the command
@@ -358,6 +358,11 @@ def test_smokevirt_ch_set_downlink_and_uplink():
@pytest.mark.smokevirt
def test_smokevirt_ch_add_and_ch_del():
"""Test --ch-add"""
return_value, out = subprocess.getstatusoutput('meshtastic --host localhost --ch-index 1 --ch-del')
assert re.search(r'Deleting channel 1', out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput('meshtastic --host localhost --ch-add testing')
assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
assert return_value == 0
@@ -375,7 +380,7 @@ def test_smokevirt_ch_add_and_ch_del():
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
# make sure the secondar channel is not there
# make sure the secondary channel is not there
return_value, out = subprocess.getstatusoutput('meshtastic --host localhost --info')
assert re.match(r'Connected to radio', out)
assert not re.search(r'SECONDARY', out, re.MULTILINE)
@@ -386,6 +391,11 @@ def test_smokevirt_ch_add_and_ch_del():
@pytest.mark.smokevirt
def test_smokevirt_ch_enable_and_disable():
"""Test --ch-enable and --ch-disable"""
return_value, out = subprocess.getstatusoutput('meshtastic --host localhost --ch-index 1 --ch-del')
assert re.search(r'Deleting channel 1', out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput('meshtastic --host localhost --ch-add testing')
assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
assert return_value == 0
@@ -434,6 +444,11 @@ def test_smokevirt_ch_enable_and_disable():
@pytest.mark.smokevirt
def test_smokevirt_ch_del_a_disabled_non_primary_channel():
"""Test --ch-del will work on a disabled non-primary channel."""
return_value, out = subprocess.getstatusoutput('meshtastic --host localhost --ch-index 1 --ch-del')
assert re.search(r'Deleting channel 1', out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput('meshtastic --host localhost --ch-add testing')
assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
assert return_value == 0

View File

@@ -11,7 +11,10 @@ from meshtastic.util import (fixme, stripnl, pskToString, our_exit,
quoteBooleans, catchAndIgnore,
remove_keys_from_dict, Timeout, hexstr,
ipstr, readnet_u16, findPorts, convert_mac_addr,
snake_to_camel, camel_to_snake)
snake_to_camel, camel_to_snake, eliminate_duplicate_port,
is_windows11, active_ports_on_supported_devices)
from meshtastic.supported_device import SupportedDevice
@pytest.mark.unit
@@ -247,6 +250,54 @@ def test_findPorts_when_none_found(patch_comports):
patch_comports.assert_called()
@pytest.mark.unitslow
@patch('serial.tools.list_ports.comports')
def test_findPorts_when_duplicate_found_and_duplicate_option_used(patch_comports):
"""Test findPorts()"""
class TempPort:
""" temp class for port"""
def __init__(self, device=None, vid=None):
self.device = device
self.vid = vid
fake1 = TempPort('/dev/cu.usbserial-1430', vid='fake1')
fake2 = TempPort('/dev/cu.wchusbserial1430', vid='fake2')
patch_comports.return_value = [fake1, fake2]
assert findPorts(eliminate_duplicates=True) == ['/dev/cu.wchusbserial1430']
patch_comports.assert_called()
@pytest.mark.unitslow
@patch('serial.tools.list_ports.comports')
def test_findPorts_when_duplicate_found_and_duplicate_option_used_ports_reversed(patch_comports):
"""Test findPorts()"""
class TempPort:
""" temp class for port"""
def __init__(self, device=None, vid=None):
self.device = device
self.vid = vid
fake1 = TempPort('/dev/cu.usbserial-1430', vid='fake1')
fake2 = TempPort('/dev/cu.wchusbserial1430', vid='fake2')
patch_comports.return_value = [fake2, fake1]
assert findPorts(eliminate_duplicates=True) == ['/dev/cu.wchusbserial1430']
patch_comports.assert_called()
@pytest.mark.unitslow
@patch('serial.tools.list_ports.comports')
def test_findPorts_when_duplicate_found_and_duplicate_option_not_used(patch_comports):
"""Test findPorts()"""
class TempPort:
""" temp class for port"""
def __init__(self, device=None, vid=None):
self.device = device
self.vid = vid
fake1 = TempPort('/dev/cu.usbserial-1430', vid='fake1')
fake2 = TempPort('/dev/cu.wchusbserial1430', vid='fake2')
patch_comports.return_value = [fake1, fake2]
assert findPorts() == ['/dev/cu.usbserial-1430', '/dev/cu.wchusbserial1430']
patch_comports.assert_called()
@pytest.mark.unitslow
def test_convert_mac_addr():
"""Test convert_mac_addr()"""
@@ -272,3 +323,136 @@ def test_camel_to_snake():
assert camel_to_snake('Foo') == 'foo'
assert camel_to_snake('fooBar') == 'foo_bar'
assert camel_to_snake('fooBarBaz') == 'foo_bar_baz'
@pytest.mark.unit
def test_eliminate_duplicate_port():
"""Test eliminate_duplicate_port()"""
assert not eliminate_duplicate_port([])
assert eliminate_duplicate_port(['/dev/fake']) == ['/dev/fake']
assert eliminate_duplicate_port(['/dev/fake', '/dev/fake1']) == ['/dev/fake', '/dev/fake1']
assert eliminate_duplicate_port(['/dev/fake', '/dev/fake1', '/dev/fake2']) == ['/dev/fake', '/dev/fake1', '/dev/fake2']
assert eliminate_duplicate_port(['/dev/cu.usbserial-1430', '/dev/cu.wchusbserial1430']) == ['/dev/cu.wchusbserial1430']
assert eliminate_duplicate_port(['/dev/cu.wchusbserial1430', '/dev/cu.usbserial-1430']) == ['/dev/cu.wchusbserial1430']
assert eliminate_duplicate_port(['/dev/cu.SLAB_USBtoUART', '/dev/cu.usbserial-0001']) == ['/dev/cu.usbserial-0001']
assert eliminate_duplicate_port(['/dev/cu.usbserial-0001', '/dev/cu.SLAB_USBtoUART']) == ['/dev/cu.usbserial-0001']
assert eliminate_duplicate_port(['/dev/cu.usbmodem11301', '/dev/cu.wchusbserial11301']) == ['/dev/cu.wchusbserial11301']
assert eliminate_duplicate_port(['/dev/cu.wchusbserial11301', '/dev/cu.usbmodem11301']) == ['/dev/cu.wchusbserial11301']
assert eliminate_duplicate_port(['/dev/cu.usbmodem53230051441', '/dev/cu.wchusbserial53230051441']) == ['/dev/cu.wchusbserial53230051441']
assert eliminate_duplicate_port(['/dev/cu.wchusbserial53230051441', '/dev/cu.usbmodem53230051441']) == ['/dev/cu.wchusbserial53230051441']
@patch('platform.version', return_value='10.0.22000.194')
@patch('platform.release', return_value='10')
@patch('platform.system', return_value='Windows')
def test_is_windows11_true(patched_platform, patched_release, patched_version):
"""Test is_windows11()"""
assert is_windows11() is True
patched_platform.assert_called()
patched_release.assert_called()
patched_version.assert_called()
@patch('platform.version', return_value='10.0.a2200.foo') # made up
@patch('platform.release', return_value='10')
@patch('platform.system', return_value='Windows')
def test_is_windows11_true2(patched_platform, patched_release, patched_version):
"""Test is_windows11()"""
assert is_windows11() is False
patched_platform.assert_called()
patched_release.assert_called()
patched_version.assert_called()
@patch('platform.version', return_value='10.0.17763') # windows 10 home
@patch('platform.release', return_value='10')
@patch('platform.system', return_value='Windows')
def test_is_windows11_false(patched_platform, patched_release, patched_version):
"""Test is_windows11()"""
assert is_windows11() is False
patched_platform.assert_called()
patched_release.assert_called()
patched_version.assert_called()
@patch('platform.release', return_value='8.1')
@patch('platform.system', return_value='Windows')
def test_is_windows11_false_win8_1(patched_platform, patched_release):
"""Test is_windows11()"""
assert is_windows11() is False
patched_platform.assert_called()
patched_release.assert_called()
@pytest.mark.unit
@patch('platform.system', return_value='Linux')
def test_active_ports_on_supported_devices_empty(mock_platform):
"""Test active_ports_on_supported_devices()"""
sds = set()
assert active_ports_on_supported_devices(sds) == set()
mock_platform.assert_called()
@pytest.mark.unit
@patch('subprocess.getstatusoutput')
@patch('platform.system', return_value='Linux')
def test_active_ports_on_supported_devices_linux(mock_platform, mock_sp):
"""Test active_ports_on_supported_devices()"""
mock_sp.return_value = (None, 'crw-rw-rw- 1 root wheel 0x9000000 Feb 8 22:22 /dev/ttyUSBfake')
fake_device = SupportedDevice(name='a', for_firmware='heltec-v2.1', baseport_on_linux='ttyUSB')
fake_supported_devices = [fake_device]
assert active_ports_on_supported_devices(fake_supported_devices) == {'/dev/ttyUSBfake'}
mock_platform.assert_called()
mock_sp.assert_called()
@pytest.mark.unit
@patch('subprocess.getstatusoutput')
@patch('platform.system', return_value='Darwin')
def test_active_ports_on_supported_devices_mac(mock_platform, mock_sp):
"""Test active_ports_on_supported_devices()"""
mock_sp.return_value = (None, 'crw-rw-rw- 1 root wheel 0x9000000 Feb 8 22:22 /dev/cu.usbserial-foo')
fake_device = SupportedDevice(name='a', for_firmware='heltec-v2.1', baseport_on_linux='cu.usbserial-')
fake_supported_devices = [fake_device]
assert active_ports_on_supported_devices(fake_supported_devices) == {'/dev/cu.usbserial-foo'}
mock_platform.assert_called()
mock_sp.assert_called()
@pytest.mark.unit
@patch('meshtastic.util.detect_windows_port', return_value={'COM2'})
@patch('platform.system', return_value='Windows')
def test_active_ports_on_supported_devices_win(mock_platform, mock_dwp):
"""Test active_ports_on_supported_devices()"""
fake_device = SupportedDevice(name='a', for_firmware='heltec-v2.1')
fake_supported_devices = [fake_device]
assert active_ports_on_supported_devices(fake_supported_devices) == {'COM2'}
mock_platform.assert_called()
mock_dwp.assert_called()
@pytest.mark.unit
@patch('subprocess.getstatusoutput')
@patch('platform.system', return_value='Darwin')
def test_active_ports_on_supported_devices_mac_no_duplicates_check(mock_platform, mock_sp):
"""Test active_ports_on_supported_devices()"""
mock_sp.return_value = (None, ('crw-rw-rw- 1 root wheel 0x9000005 Mar 8 10:05 /dev/cu.usbmodem53230051441\n'
'crw-rw-rw- 1 root wheel 0x9000003 Mar 8 10:06 /dev/cu.wchusbserial53230051441'))
fake_device = SupportedDevice(name='a', for_firmware='tbeam', baseport_on_mac='cu.usbmodem')
fake_supported_devices = [fake_device]
assert active_ports_on_supported_devices(fake_supported_devices, False) == {'/dev/cu.usbmodem53230051441', '/dev/cu.wchusbserial53230051441'}
mock_platform.assert_called()
mock_sp.assert_called()
@pytest.mark.unit
@patch('subprocess.getstatusoutput')
@patch('platform.system', return_value='Darwin')
def test_active_ports_on_supported_devices_mac_duplicates_check(mock_platform, mock_sp):
"""Test active_ports_on_supported_devices()"""
mock_sp.return_value = (None, ('crw-rw-rw- 1 root wheel 0x9000005 Mar 8 10:05 /dev/cu.usbmodem53230051441\n'
'crw-rw-rw- 1 root wheel 0x9000003 Mar 8 10:06 /dev/cu.wchusbserial53230051441'))
fake_device = SupportedDevice(name='a', for_firmware='tbeam', baseport_on_mac='cu.usbmodem')
fake_supported_devices = [fake_device]
assert active_ports_on_supported_devices(fake_supported_devices, True) == {'/dev/cu.wchusbserial53230051441'}
mock_platform.assert_called()
mock_sp.assert_called()

View File

@@ -14,7 +14,8 @@ import subprocess
import serial
import serial.tools.list_ports
import pkg_resources
from meshtastic.supported_device import get_unique_vendor_ids, get_devices_with_vendor_id
from meshtastic.supported_device import supported_devices
"""Some devices such as a seger jlink we never want to accidentally open"""
blacklistVids = dict.fromkeys([0x1366])
@@ -113,8 +114,9 @@ def catchAndIgnore(reason, closure):
logging.error(f"Exception thrown in {reason}: {ex}")
def findPorts():
def findPorts(eliminate_duplicates=False):
"""Find all ports that might have meshtastic devices
eliminate_duplicates will run the eliminate_duplicate_port() on the collection
Returns:
list -- a list of device paths
@@ -123,6 +125,8 @@ def findPorts():
filter(lambda port: port.vid is not None and port.vid not in blacklistVids,
serial.tools.list_ports.comports())))
l.sort()
if eliminate_duplicates:
l = eliminate_duplicate_port(l)
return l
@@ -381,3 +385,161 @@ def detect_windows_needs_driver(sd, print_reason=False):
if print_reason:
print(sp_output)
return need_to_install_driver
def eliminate_duplicate_port(ports):
"""Sometimes we detect 2 serial ports, but we really only need to use one of the ports.
ports is a list of ports
return a list with a single port to use, if it meets the duplicate port conditions
examples:
Ports: ['/dev/cu.usbserial-1430', '/dev/cu.wchusbserial1430'] => ['/dev/cu.wchusbserial1430']
Ports: ['/dev/cu.usbmodem11301', '/dev/cu.wchusbserial11301'] => ['/dev/cu.wchusbserial11301']
Ports: ['/dev/cu.SLAB_USBtoUART', '/dev/cu.usbserial-0001'] => ['/dev/cu.usbserial-0001']
"""
new_ports = []
if len(ports) != 2:
new_ports = ports
else:
ports.sort()
if 'usbserial' in ports[0] and 'wchusbserial' in ports[1]:
first = ports[0].replace("usbserial-", "")
second = ports[1].replace("wchusbserial", "")
if first == second:
new_ports.append(ports[1])
elif 'usbmodem' in ports[0] and 'wchusbserial' in ports[1]:
first = ports[0].replace("usbmodem", "")
second = ports[1].replace("wchusbserial", "")
if first == second:
new_ports.append(ports[1])
elif 'SLAB_USBtoUART' in ports[0] and 'usbserial' in ports[1]:
new_ports.append(ports[1])
else:
new_ports = ports
return new_ports
def is_windows11():
"""Detect if Windows 11"""
is_win11 = False
if platform.system() == "Windows":
if float(platform.release()) >= 10.0:
patch = platform.version().split('.')[2]
# in case they add some number suffix later, just get first 5 chars of patch
patch = patch[:5]
try:
if int(patch) >= 22000:
is_win11 = True
except Exception as e:
print(f'problem detecting win11 e:{e}')
return is_win11
def get_unique_vendor_ids():
"""Return a set of unique vendor ids"""
vids = set()
for d in supported_devices:
if d.usb_vendor_id_in_hex:
vids.add(d.usb_vendor_id_in_hex)
return vids
def get_devices_with_vendor_id(vid):
"""Return a set of unique devices with the vendor id"""
sd = set()
for d in supported_devices:
if d.usb_vendor_id_in_hex == vid:
sd.add(d)
return sd
def active_ports_on_supported_devices(sds, eliminate_duplicates=False):
"""Return a set of active ports based on the supplied supported devices"""
ports = set()
baseports = set()
system = platform.system()
# figure out what possible base ports there are
for d in sds:
if system == "Linux":
baseports.add(d.baseport_on_linux)
elif system == "Darwin":
baseports.add(d.baseport_on_mac)
elif system == "Windows":
baseports.add(d.baseport_on_windows)
for bp in baseports:
if system == "Linux":
# see if we have any devices (ignoring any stderr output)
command = f'ls -al /dev/{bp}* 2> /dev/null'
#print(f'command:{command}')
_, ls_output = subprocess.getstatusoutput(command)
#print(f'ls_output:{ls_output}')
# if we got output, there are ports
if len(ls_output) > 0:
#print('got output')
# for each line of output
lines = ls_output.split('\n')
#print(f'lines:{lines}')
for line in lines:
parts = line.split(' ')
#print(f'parts:{parts}')
port = parts[-1]
#print(f'port:{port}')
ports.add(port)
elif system == "Darwin":
# see if we have any devices (ignoring any stderr output)
command = f'ls -al /dev/{bp}* 2> /dev/null'
#print(f'command:{command}')
_, ls_output = subprocess.getstatusoutput(command)
#print(f'ls_output:{ls_output}')
# if we got output, there are ports
if len(ls_output) > 0:
#print('got output')
# for each line of output
lines = ls_output.split('\n')
#print(f'lines:{lines}')
for line in lines:
parts = line.split(' ')
#print(f'parts:{parts}')
port = parts[-1]
#print(f'port:{port}')
ports.add(port)
elif system == "Windows":
# for each device in supported devices found
for d in sds:
# find the port(s)
com_ports = detect_windows_port(d)
#print(f'com_ports:{com_ports}')
# add all ports
for com_port in com_ports:
ports.add(com_port)
if eliminate_duplicates:
ports = eliminate_duplicate_port(list(ports))
ports.sort()
ports = set(ports)
return ports
def detect_windows_port(sd):
"""detect if Windows port"""
ports = set()
if sd:
system = platform.system()
if system == "Windows":
command = ('powershell.exe "[Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8;'
'Get-PnpDevice -PresentOnly | Where-Object{ ($_.DeviceId -like ')
command += f"'*{sd.usb_vendor_id_in_hex.upper()}*'"
command += ')} | Format-List"'
#print(f'command:{command}')
_, sp_output = subprocess.getstatusoutput(command)
#print(f'sp_output:{sp_output}')
p = re.compile(r'\(COM(.*)\)')
for x in p.findall(sp_output):
#print(f'x:{x}')
ports.add(f'COM{x}')
return ports

2
proto

Submodule proto updated: 792027be93...441303d531

View File

@@ -12,7 +12,7 @@ with open("README.md", "r") as fh:
# This call to setup() does all the work
setup(
name="meshtastic",
version="1.2.79",
version="1.3alpha.6",
description="Python API & client shell for talking to Meshtastic devices",
long_description=long_description,
long_description_content_type="text/markdown",
@@ -22,8 +22,7 @@ setup(
license="MIT",
classifiers=[
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Development Status :: 4 - Beta",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
@@ -38,7 +37,7 @@ setup(
extras_require={
'tunnel': ["pytap2>=2.0.0"]
},
python_requires='>=3.6',
python_requires='>=3.7',
entry_points={
"console_scripts": [
"meshtastic=meshtastic.__main__:main",

View File

@@ -2,6 +2,6 @@ readme.txt for single standalone executable zip files that can be
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
zip 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.
See https://meshtastic.org/docs/software/python/python-standalone for more info.