mirror of
https://github.com/meshtastic/python.git
synced 2025-12-26 09:27:52 -05:00
Compare commits
142 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57719ddd5e | ||
|
|
d0b8b9ff1b | ||
|
|
c5c9723208 | ||
|
|
9bceaafd9c | ||
|
|
7d3a9178ea | ||
|
|
2c76c0cafa | ||
|
|
82977e9ef2 | ||
|
|
7a9c25da8e | ||
|
|
342c48fb16 | ||
|
|
6bc955a403 | ||
|
|
741ba378ab | ||
|
|
c1054caf4a | ||
|
|
24b97d9277 | ||
|
|
868fb64857 | ||
|
|
8729e97e1b | ||
|
|
aaed54393e | ||
|
|
d12776bb5f | ||
|
|
7829f6afca | ||
|
|
4bd10bc102 | ||
|
|
3821e02f09 | ||
|
|
97689da0b4 | ||
|
|
5c75e74bf9 | ||
|
|
388a46abf4 | ||
|
|
6b89fc81a1 | ||
|
|
c9b5d5d697 | ||
|
|
f16dd0e737 | ||
|
|
5ed19eff73 | ||
|
|
0b3605141d | ||
|
|
f1df14ca92 | ||
|
|
83776ceec5 | ||
|
|
7aff5e9ee5 | ||
|
|
bf6be107d3 | ||
|
|
c24d1fe26b | ||
|
|
61f5468847 | ||
|
|
c713ce04b6 | ||
|
|
fe2b36e04b | ||
|
|
a720916df5 | ||
|
|
b2593e4bb1 | ||
|
|
6e3c759e5c | ||
|
|
a41f33e0bd | ||
|
|
111bf8dcbf | ||
|
|
f18abb2fe6 | ||
|
|
b7093e176a | ||
|
|
cf7d37a454 | ||
|
|
2af431e2eb | ||
|
|
3db64f7988 | ||
|
|
7ef64d4250 | ||
|
|
363aa995a2 | ||
|
|
696fa28e6f | ||
|
|
a908bdfc1c | ||
|
|
81b64ac908 | ||
|
|
d5ccdc826f | ||
|
|
fac4faaae8 | ||
|
|
cfb8769746 | ||
|
|
c1b0e4e8d0 | ||
|
|
5683e31f6b | ||
|
|
7909ad477b | ||
|
|
f94dbf05ef | ||
|
|
a44b769390 | ||
|
|
2a4816a9cd | ||
|
|
674fd92690 | ||
|
|
cc29cab99a | ||
|
|
bf803bb6e9 | ||
|
|
3c80fd0f02 | ||
|
|
616a3ab706 | ||
|
|
8350cc611d | ||
|
|
621feb749d | ||
|
|
f6731a435d | ||
|
|
dcfe5fb558 | ||
|
|
4fa80e9652 | ||
|
|
02851b6237 | ||
|
|
a74ec12445 | ||
|
|
262e921a81 | ||
|
|
0c7b9e10f4 | ||
|
|
ab8b930365 | ||
|
|
4ae49c68aa | ||
|
|
733f22d927 | ||
|
|
791131ea27 | ||
|
|
f17292221c | ||
|
|
b60a438c9d | ||
|
|
3b3a610375 | ||
|
|
38f928bdb7 | ||
|
|
6272e992a4 | ||
|
|
3263fbca28 | ||
|
|
f0e7af389c | ||
|
|
471dfc7a29 | ||
|
|
2a7c21c062 | ||
|
|
03797e3336 | ||
|
|
dc1be12c86 | ||
|
|
4c83a43d64 | ||
|
|
e083cda3d9 | ||
|
|
c0006f888b | ||
|
|
e2d2d3a347 | ||
|
|
3fd50b0e44 | ||
|
|
4b0e3ae923 | ||
|
|
37f10cc0d4 | ||
|
|
998df265e6 | ||
|
|
d852981371 | ||
|
|
afed5bd943 | ||
|
|
97b9041b76 | ||
|
|
2dc14ef466 | ||
|
|
8e69c32a36 | ||
|
|
42b33bea5b | ||
|
|
7fd101cbf8 | ||
|
|
92ee9889b1 | ||
|
|
b6e1610abe | ||
|
|
bde5db9c51 | ||
|
|
148ae49ded | ||
|
|
d1f8365da1 | ||
|
|
59fc294d66 | ||
|
|
7473b4e18c | ||
|
|
58aafcf3f1 | ||
|
|
776fc57c35 | ||
|
|
b3f752a3c4 | ||
|
|
4965ec7f1d | ||
|
|
0746acd34f | ||
|
|
49b1c4816e | ||
|
|
7c6e87e161 | ||
|
|
b548700c0b | ||
|
|
f278a30003 | ||
|
|
22bbe67d24 | ||
|
|
a2861a133e | ||
|
|
03aab10786 | ||
|
|
95e768efd5 | ||
|
|
6644e86be9 | ||
|
|
c8363cd476 | ||
|
|
62efe1ab7f | ||
|
|
01e643ad2f | ||
|
|
e4078e84d7 | ||
|
|
abfcbe2a90 | ||
|
|
e06d8bbc06 | ||
|
|
a78cdde86f | ||
|
|
10517ac94d | ||
|
|
a572699588 | ||
|
|
d11fb47734 | ||
|
|
92c7b2db69 | ||
|
|
ff94ad968c | ||
|
|
c6071c57ec | ||
|
|
e3e3562c2c | ||
|
|
06b5b8fa83 | ||
|
|
4b95b0ff30 | ||
|
|
42f2ed571d |
20
.github/workflows/cleanup_artifacts.yml
vendored
Normal file
20
.github/workflows/cleanup_artifacts.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
name: Remove old artifacts
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# Every day at 1am
|
||||||
|
- cron: '0 1 * * *'
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
remove-old-artifacts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Remove old artifacts
|
||||||
|
uses: c-hive/gha-remove-artifacts@v1
|
||||||
|
with:
|
||||||
|
age: '1 month'
|
||||||
|
skip-tags: true
|
||||||
10
.github/workflows/update_protobufs.yml
vendored
10
.github/workflows/update_protobufs.yml
vendored
@@ -15,22 +15,22 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git pull --recurse-submodules
|
git pull --recurse-submodules
|
||||||
git submodule update --remote --recursive
|
git submodule update --remote --recursive
|
||||||
|
|
||||||
- name: Download nanopb
|
- name: Download nanopb
|
||||||
run: |
|
run: |
|
||||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz
|
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz
|
||||||
tar xvzf nanopb-0.4.6-linux-x86.tar.gz
|
tar xvzf nanopb-0.4.6-linux-x86.tar.gz
|
||||||
mv nanopb-0.4.6-linux-x86 nanopb-0.4.6
|
mv nanopb-0.4.6-linux-x86 nanopb-0.4.6
|
||||||
|
|
||||||
- name: Re-generate protocol buffers
|
- name: Re-generate protocol buffers
|
||||||
run: |
|
run: |
|
||||||
./bin/regen-protos.sh
|
./bin/regen-protobufs.sh
|
||||||
|
|
||||||
- name: Commit update
|
- name: Commit update
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name 'github-actions'
|
git config --global user.name 'github-actions'
|
||||||
git config --global user.email 'bot@noreply.github.com'
|
git config --global user.email 'bot@noreply.github.com'
|
||||||
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
||||||
git add proto
|
git add protobufs
|
||||||
git add meshtastic
|
git add meshtastic
|
||||||
git commit -m "Update protobuf submodule" && git push || echo "No changes to commit"
|
git commit -m "Update protobuf submodule" && git push || echo "No changes to commit"
|
||||||
|
|||||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
|||||||
[submodule "proto"]
|
[submodule "protobufs"]
|
||||||
path = proto
|
path = protobufs
|
||||||
url = https://github.com/meshtastic/Meshtastic-protobufs.git
|
url = http://github.com/meshtastic/protobufs
|
||||||
|
|||||||
73
.vscode/launch.json
vendored
73
.vscode/launch.json
vendored
@@ -52,6 +52,46 @@
|
|||||||
"justMyCode": true,
|
"justMyCode": true,
|
||||||
"args": ["--debug", "--get", "power.is_power_saving"]
|
"args": ["--debug", "--get", "power.is_power_saving"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic debug getPref telemetry",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--get", "telemetry.environment_update_interval"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic debug info",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--info"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic debug set region",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--set", "lora.region", "TW"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic debug set bluetooth fixed pin",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--set", "bluetooth.fixed_pin", "555555"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic debug get bluetooth fixed pin",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--get", "bluetooth.fixed_pin"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "meshtastic debug setPref",
|
"name": "meshtastic debug setPref",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
@@ -60,6 +100,30 @@
|
|||||||
"justMyCode": true,
|
"justMyCode": true,
|
||||||
"args": ["--debug", "--set", "power.is_power_saving", "1"]
|
"args": ["--debug", "--set", "power.is_power_saving", "1"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic debug setPref telemetry.environment_measurement_enabled",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--set", "telemetry.environment_measurement_enabled", "1"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic debug setPref telemetry.environment_screen_enabled",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--set", "telemetry.environment_screen_enabled", "1"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic debug setPref telemetry",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--set", "telemetry.environment_measurement_enabled", "1"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "meshtastic setpref",
|
"name": "meshtastic setpref",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
@@ -68,6 +132,15 @@
|
|||||||
"justMyCode": true,
|
"justMyCode": true,
|
||||||
"args": ["--debug", "--setchan", "psk", ""]
|
"args": ["--debug", "--setchan", "psk", ""]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "meshtastic --ch-set",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "meshtastic",
|
||||||
|
"justMyCode": true,
|
||||||
|
"args": ["--debug", "--ch-set", "channel_num", "0", "--ch-index", "0"]
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "meshtastic seturl",
|
"name": "meshtastic seturl",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -26,11 +26,11 @@ lint:
|
|||||||
slow:
|
slow:
|
||||||
pytest -m unit --durations=5
|
pytest -m unit --durations=5
|
||||||
|
|
||||||
proto: FORCE
|
protobufs: FORCE
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
git pull --rebase
|
git pull --rebase
|
||||||
git submodule update --remote --merge
|
git submodule update --remote --merge
|
||||||
./bin/regen-protos.sh
|
./bin/regen-protobufs.sh
|
||||||
|
|
||||||
# run the coverage report and open results in a browser
|
# run the coverage report and open results in a browser
|
||||||
cov:
|
cov:
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -1,9 +1,9 @@
|
|||||||
# Meshtastic Python
|
# Meshtastic Python
|
||||||
|
|
||||||
[](https://codecov.io/gh/meshtastic/Meshtastic-python)
|
[](https://codecov.io/gh/meshtastic/python)
|
||||||

|

|
||||||
[](https://github.com/meshtastic/Meshtastic-python/actions/workflows/ci.yml)
|
[](https://github.com/meshtastic/python/actions/workflows/ci.yml)
|
||||||
[](https://cla-assistant.io/meshtastic/Meshtastic-python)
|
[](https://cla-assistant.io/meshtastic/python)
|
||||||
[](https://opencollective.com/meshtastic/)
|
[](https://opencollective.com/meshtastic/)
|
||||||
[](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
|
[](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
|
||||||
|
|
||||||
@@ -14,12 +14,10 @@ This small library (and example application) provides an easy API for sending an
|
|||||||
It also provides access to any of the operations/data available in the device user interface or the Android application.
|
It also provides access to any of the operations/data available in the device user interface or the Android application.
|
||||||
Events are delivered using a publish-subscribe model, and you can subscribe to only the message types you are interested in.
|
Events are delivered using a publish-subscribe model, and you can subscribe to only the message types you are interested in.
|
||||||
|
|
||||||
|
|
||||||
**[Getting Started Guide](https://meshtastic.org/docs/software/python/python-installation)**
|
**[Getting Started Guide](https://meshtastic.org/docs/software/python/python-installation)**
|
||||||
|
|
||||||
**[Documentation/API Reference](https://python.meshtastic.org/)**
|
**[Documentation/API Reference](https://python.meshtastic.org/)**
|
||||||
|
|
||||||
|
|
||||||
## Stats
|
## Stats
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""Bump the version number"""
|
"""Bump the version number"""
|
||||||
|
import re
|
||||||
|
|
||||||
version_filename = "setup.py"
|
version_filename = "setup.py"
|
||||||
|
|
||||||
@@ -19,7 +20,9 @@ with open(version_filename, 'w', encoding='utf-8') as f:
|
|||||||
words = line.split("=")
|
words = line.split("=")
|
||||||
# split the version into parts (by period)
|
# split the version into parts (by period)
|
||||||
v = words[1].split(".")
|
v = words[1].split(".")
|
||||||
ver = f'{v[0]}.{v[1]}.{int(v[2]) + 1}'
|
build_num = re.findall(r"\d+", v[2])[0]
|
||||||
|
new_build_num = str(int(build_num)+1)
|
||||||
|
ver = f'{v[0]}.{v[1]}.{v[2].replace(build_num, new_build_num)}'.replace('\n', '')
|
||||||
f.write(f' version="{ver}",\n')
|
f.write(f' version="{ver}",\n')
|
||||||
else:
|
else:
|
||||||
f.write(line)
|
f.write(line)
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
./nanopb-0.4.6/generator-bin/protoc -I=proto --python_out meshtastic `ls proto/*.proto`
|
./nanopb-0.4.6/generator-bin/protoc -I=protobufs --python_out meshtastic `ls protobufs/*.proto`
|
||||||
|
|
||||||
# workaround for import bug in protoc https://github.com/protocolbuffers/protobuf/issues/1491#issuecomment-690618628
|
# workaround for import bug in protoc https://github.com/protocolbuffers/protobuf/issues/1491#issuecomment-690618628
|
||||||
|
|
||||||
if [[ $OSTYPE == 'darwin'* ]]; then
|
if [[ $OSTYPE == 'darwin'* ]]; then
|
||||||
sed -i '' -E 's/^(import.*_pb2)/from . \1/' meshtastic/*.py
|
sed -i '' -E 's/^(import.*_pb2)/from . \1/' meshtastic/*.py
|
||||||
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/Meshtastic-protobufs/issues/27)
|
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/protobufs/issues/27)
|
||||||
sed -i '' -E "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py
|
sed -i '' -E "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py
|
||||||
else
|
else
|
||||||
sed -i -e 's/^import.*_pb2/from . \0/' meshtastic/*.py
|
sed -i -e 's/^import.*_pb2/from . \0/' meshtastic/*.py
|
||||||
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/Meshtastic-protobufs/issues/27)
|
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/protobufs/issues/27)
|
||||||
sed -i -e "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py
|
sed -i -e "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py
|
||||||
fi
|
fi
|
||||||
@@ -2,16 +2,42 @@
|
|||||||
owner: Bob TBeam
|
owner: Bob TBeam
|
||||||
owner_short: BOB
|
owner_short: BOB
|
||||||
|
|
||||||
channel_url: https://www.meshtastic.org/d/#CgUYAyIBAQ
|
channel_url: https://www.meshtastic.org/e/#CgMSAQESCDgBQANIAVAe
|
||||||
|
|
||||||
location:
|
location:
|
||||||
lat: 35.88888
|
lat: 35.88888
|
||||||
lon: -93.88888
|
lon: -93.88888
|
||||||
alt: 304
|
alt: 304
|
||||||
|
|
||||||
user_prefs:
|
config:
|
||||||
region: 1
|
bluetooth:
|
||||||
is_always_powered: 'true'
|
enabled: true
|
||||||
screen_on_secs: 31536000
|
fixedPin: 123456
|
||||||
wait_bluetooth_secs: 31536000
|
device:
|
||||||
location_share: 'LocEnabled'
|
serialEnabled: true
|
||||||
|
display:
|
||||||
|
screenOnSecs: 600
|
||||||
|
lora:
|
||||||
|
region: US
|
||||||
|
hopLimit: 3
|
||||||
|
txEnabled: true
|
||||||
|
txPower: 30
|
||||||
|
network:
|
||||||
|
ntpServer: 0.pool.ntp.org
|
||||||
|
position:
|
||||||
|
gpsAttemptTime: 900
|
||||||
|
gpsEnabled: true
|
||||||
|
gpsUpdateInterval: 120
|
||||||
|
positionBroadcastSecs: 900
|
||||||
|
positionBroadcastSmartEnabled: true
|
||||||
|
positionFlags: 3
|
||||||
|
power:
|
||||||
|
lsSecs: 300
|
||||||
|
meshSdsTimeoutSecs: 7200
|
||||||
|
minWakeSecs: 10
|
||||||
|
sdsSecs: 4294967295
|
||||||
|
|
||||||
|
module_config:
|
||||||
|
telemetry:
|
||||||
|
deviceUpdateInterval: 900
|
||||||
|
environmentUpdateInterval: 900
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Primary class: SerialInterface
|
Primary class: SerialInterface
|
||||||
Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)"
|
Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)"
|
||||||
Source code on [github](https://github.com/meshtastic/Meshtastic-python)
|
Source code on [github](https://github.com/meshtastic/python)
|
||||||
|
|
||||||
properties of SerialInterface:
|
properties of SerialInterface:
|
||||||
|
|
||||||
@@ -182,5 +182,7 @@ protocols = {
|
|||||||
portnums_pb2.PortNum.ADMIN_APP: KnownProtocol("admin", admin_pb2.AdminMessage),
|
portnums_pb2.PortNum.ADMIN_APP: KnownProtocol("admin", admin_pb2.AdminMessage),
|
||||||
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
|
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
|
||||||
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol("telemetry", telemetry_pb2.Telemetry),
|
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol("telemetry", telemetry_pb2.Telemetry),
|
||||||
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol("remotehw", remote_hardware_pb2.HardwareMessage)
|
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol("remotehw", remote_hardware_pb2.HardwareMessage),
|
||||||
|
portnums_pb2.PortNum.SIMULATOR_APP: KnownProtocol("simulator", mesh_pb2.Compressed),
|
||||||
|
portnums_pb2.PortNum.TRACEROUTE_APP: KnownProtocol("traceroute", mesh_pb2.RouteDiscovery)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import yaml
|
|||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
import pyqrcode
|
import pyqrcode
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
from google.protobuf.json_format import MessageToDict
|
||||||
import meshtastic.util
|
import meshtastic.util
|
||||||
import meshtastic.test
|
import meshtastic.test
|
||||||
from meshtastic import remote_hardware
|
from meshtastic import remote_hardware
|
||||||
@@ -52,13 +53,10 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # pylint: disable=W0613
|
|||||||
print(f"Connection changed: {topic.getName()}")
|
print(f"Connection changed: {topic.getName()}")
|
||||||
|
|
||||||
|
|
||||||
def getPref(attributes, comp_name):
|
def getPref(config, comp_name):
|
||||||
"""Get a channel or preferences value"""
|
"""Get a channel or preferences value"""
|
||||||
|
|
||||||
name = comp_name.split(".",1)
|
name = splitCompoundName(comp_name)
|
||||||
if len(name) != 2:
|
|
||||||
name[0]=comp_name
|
|
||||||
name.append(comp_name)
|
|
||||||
|
|
||||||
camel_name = meshtastic.util.snake_to_camel(name[1])
|
camel_name = meshtastic.util.snake_to_camel(name[1])
|
||||||
# Note: protobufs has the keys in snake_case, so snake internally
|
# Note: protobufs has the keys in snake_case, so snake internally
|
||||||
@@ -66,33 +64,18 @@ def getPref(attributes, comp_name):
|
|||||||
logging.debug(f'snake_name:{snake_name} camel_name:{camel_name}')
|
logging.debug(f'snake_name:{snake_name} camel_name:{camel_name}')
|
||||||
logging.debug(f'use camel:{Globals.getInstance().get_camel_case()}')
|
logging.debug(f'use camel:{Globals.getInstance().get_camel_case()}')
|
||||||
|
|
||||||
objDesc = attributes.DESCRIPTOR
|
objDesc = config.DESCRIPTOR
|
||||||
|
print()
|
||||||
config_type = objDesc.fields_by_name.get(name[0])
|
config_type = objDesc.fields_by_name.get(name[0])
|
||||||
pref = False
|
pref = False
|
||||||
if config_type:
|
if config_type:
|
||||||
pref = config_type.message_type.fields_by_name.get(snake_name)
|
pref = config_type.message_type.fields_by_name.get(snake_name)
|
||||||
|
|
||||||
if (not pref) or (not config_type):
|
if (not pref) or (not config_type):
|
||||||
if Globals.getInstance().get_camel_case():
|
return False
|
||||||
print(f"{attributes.__class__.__name__} does not have an attribute called {name[0]}.{camel_name}, so you can not get it.")
|
|
||||||
else:
|
|
||||||
print(f"{attributes.__class__.__name__} does not have an attribute called {name[0]}.{snake_name}, so you can not get it.")
|
|
||||||
print(f"Choices in sorted order are:")
|
|
||||||
names = []
|
|
||||||
for f in objDesc.fields:
|
|
||||||
tmp_path = f'{f.name}'
|
|
||||||
if(f.message_type):
|
|
||||||
for ff in f.message_type.fields:
|
|
||||||
tmp_name = f'{ff.name}'
|
|
||||||
if Globals.getInstance().get_camel_case():
|
|
||||||
tmp_name = meshtastic.util.snake_to_camel(tmp_name)
|
|
||||||
names.append(tmp_path + "." +tmp_name)
|
|
||||||
for temp_name in sorted(names):
|
|
||||||
print(f" {temp_name}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# read the value
|
# read the value
|
||||||
config_values = getattr(attributes, config_type.name)
|
config_values = getattr(config, config_type.name)
|
||||||
pref_value = getattr(config_values, pref.name)
|
pref_value = getattr(config_values, pref.name)
|
||||||
|
|
||||||
if Globals.getInstance().get_camel_case():
|
if Globals.getInstance().get_camel_case():
|
||||||
@@ -101,52 +84,44 @@ def getPref(attributes, comp_name):
|
|||||||
else:
|
else:
|
||||||
print(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
|
print(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
|
||||||
logging.debug(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
|
logging.debug(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def splitCompoundName(comp_name):
|
||||||
def setPref(attributes, comp_name, valStr):
|
"""Split compound (dot separated) preference name into parts"""
|
||||||
"""Set a channel or preferences value"""
|
|
||||||
|
|
||||||
name = comp_name.split(".",1)
|
name = comp_name.split(".",1)
|
||||||
if len(name) != 2:
|
if len(name) != 2:
|
||||||
name[0]=comp_name
|
name[0]=comp_name
|
||||||
name.append(comp_name)
|
name.append(comp_name)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def setPref(config, comp_name, valStr):
|
||||||
|
"""Set a channel or preferences value"""
|
||||||
|
|
||||||
|
name = splitCompoundName(comp_name)
|
||||||
|
|
||||||
snake_name = meshtastic.util.camel_to_snake(name[1])
|
snake_name = meshtastic.util.camel_to_snake(name[1])
|
||||||
camel_name = meshtastic.util.snake_to_camel(name[1])
|
camel_name = meshtastic.util.snake_to_camel(name[1])
|
||||||
logging.debug(f'snake_name:{snake_name}')
|
logging.debug(f'snake_name:{snake_name}')
|
||||||
logging.debug(f'camel_name:{camel_name}')
|
logging.debug(f'camel_name:{camel_name}')
|
||||||
|
|
||||||
objDesc = attributes.DESCRIPTOR
|
objDesc = config.DESCRIPTOR
|
||||||
config_type = objDesc.fields_by_name.get(name[0])
|
config_type = objDesc.fields_by_name.get(name[0])
|
||||||
pref = False
|
pref = False
|
||||||
if config_type:
|
if config_type and config_type.message_type is not None:
|
||||||
pref = config_type.message_type.fields_by_name.get(snake_name)
|
pref = config_type.message_type.fields_by_name.get(snake_name)
|
||||||
|
# Others like ChannelSettings are standalone
|
||||||
|
elif config_type:
|
||||||
|
pref = config_type
|
||||||
|
|
||||||
if (not pref) or (not config_type):
|
if (not pref) or (not config_type):
|
||||||
if Globals.getInstance().get_camel_case():
|
return False
|
||||||
print(f"{attributes.__class__.__name__} does not have an attribute called {name[0]}.{camel_name}, so you can not set it.")
|
|
||||||
else:
|
|
||||||
print(f"{attributes.__class__.__name__} does not have an attribute called {name[0]}.{snake_name}, so you can not set it.")
|
|
||||||
print(f"Choices in sorted order are:")
|
|
||||||
names = []
|
|
||||||
for f in objDesc.fields:
|
|
||||||
tmp_path = f'{f.name}'
|
|
||||||
if(f.message_type):
|
|
||||||
for ff in f.message_type.fields:
|
|
||||||
tmp_name = f'{ff.name}'
|
|
||||||
if Globals.getInstance().get_camel_case():
|
|
||||||
tmp_name = meshtastic.util.snake_to_camel(tmp_name)
|
|
||||||
names.append(tmp_path + "." + tmp_name)
|
|
||||||
for temp_name in sorted(names):
|
|
||||||
print(f" {temp_name}")
|
|
||||||
return
|
|
||||||
|
|
||||||
val = meshtastic.util.fromStr(valStr)
|
val = meshtastic.util.fromStr(valStr)
|
||||||
logging.debug(f'valStr:{valStr} val:{val}')
|
logging.debug(f'valStr:{valStr} val:{val}')
|
||||||
|
|
||||||
if snake_name == 'psk' and len(valStr) < 8:
|
if snake_name == 'psk' and len(valStr) < 8:
|
||||||
print(f"Warning: wifi.psk must be 8 or more characters.")
|
print(f"Warning: wifi.psk must be 8 or more characters.")
|
||||||
return
|
return False
|
||||||
|
|
||||||
enumType = pref.enum_type
|
enumType = pref.enum_type
|
||||||
# pylint: disable=C0123
|
# pylint: disable=C0123
|
||||||
@@ -167,16 +142,19 @@ def setPref(attributes, comp_name, valStr):
|
|||||||
names.append(f'{f.name}')
|
names.append(f'{f.name}')
|
||||||
for temp_name in sorted(names):
|
for temp_name in sorted(names):
|
||||||
print(f" {temp_name}")
|
print(f" {temp_name}")
|
||||||
return
|
return False
|
||||||
|
|
||||||
# note: 'ignore_incoming' is a repeating field
|
# note: 'ignore_incoming' is a repeating field
|
||||||
if snake_name != 'ignore_incoming':
|
if snake_name != 'ignore_incoming':
|
||||||
try:
|
try:
|
||||||
config_values = getattr(attributes, config_type.name)
|
if config_type.message_type is not None:
|
||||||
setattr(config_values, pref.name, val)
|
config_values = getattr(config, config_type.name)
|
||||||
|
setattr(config_values, pref.name, val)
|
||||||
|
else:
|
||||||
|
setattr(config, snake_name, val)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# The setter didn't like our arg type guess try again as a string
|
# The setter didn't like our arg type guess try again as a string
|
||||||
config_values = getattr(attributes, config_type.name)
|
config_values = getattr(config, config_type.name)
|
||||||
setattr(config_values, pref.name, valStr)
|
setattr(config_values, pref.name, valStr)
|
||||||
else:
|
else:
|
||||||
if val == 0:
|
if val == 0:
|
||||||
@@ -187,15 +165,19 @@ def setPref(attributes, comp_name, valStr):
|
|||||||
print(f"Adding '{val}' to the ignore_incoming list")
|
print(f"Adding '{val}' to the ignore_incoming list")
|
||||||
config_type.message_type.ignore_incoming.extend([val])
|
config_type.message_type.ignore_incoming.extend([val])
|
||||||
|
|
||||||
|
prefix = f"{name[0]}." if config_type.message_type is not None else ""
|
||||||
if Globals.getInstance().get_camel_case():
|
if Globals.getInstance().get_camel_case():
|
||||||
print(f"Set {name[0]}.{camel_name} to {valStr}")
|
print(f"Set {prefix}{camel_name} to {valStr}")
|
||||||
else:
|
else:
|
||||||
print(f"Set {name[0]}.{snake_name} to {valStr}")
|
print(f"Set {prefix}{snake_name} to {valStr}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def onConnected(interface):
|
def onConnected(interface):
|
||||||
"""Callback invoked when we connect to a radio"""
|
"""Callback invoked when we connect to a radio"""
|
||||||
closeNow = False # Should we drop the connection after we finish?
|
closeNow = False # Should we drop the connection after we finish?
|
||||||
|
waitForAckNak = False # Should we wait for an acknowledgment if we send to a remote node?
|
||||||
try:
|
try:
|
||||||
our_globals = Globals.getInstance()
|
our_globals = Globals.getInstance()
|
||||||
args = our_globals.get_args()
|
args = our_globals.get_args()
|
||||||
@@ -210,75 +192,79 @@ def onConnected(interface):
|
|||||||
alt = 0
|
alt = 0
|
||||||
lat = 0.0
|
lat = 0.0
|
||||||
lon = 0.0
|
lon = 0.0
|
||||||
prefs = interface.localNode.localConfig
|
# TODO: use getNode(args.dest) to be able to set it for a remote node
|
||||||
|
localConfig = interface.localNode.localConfig
|
||||||
if args.setalt:
|
if args.setalt:
|
||||||
alt = int(args.setalt)
|
alt = int(args.setalt)
|
||||||
prefs.fixed_position = True
|
localConfig.position.fixed_position = True
|
||||||
print(f"Fixing altitude at {alt} meters")
|
print(f"Fixing altitude at {alt} meters")
|
||||||
if args.setlat:
|
if args.setlat:
|
||||||
lat = float(args.setlat)
|
lat = float(args.setlat)
|
||||||
prefs.fixed_position = True
|
localConfig.position.fixed_position = True
|
||||||
print(f"Fixing latitude at {lat} degrees")
|
print(f"Fixing latitude at {lat} degrees")
|
||||||
if args.setlon:
|
if args.setlon:
|
||||||
lon = float(args.setlon)
|
lon = float(args.setlon)
|
||||||
prefs.fixed_position = True
|
localConfig.position.fixed_position = True
|
||||||
print(f"Fixing longitude at {lon} degrees")
|
print(f"Fixing longitude at {lon} degrees")
|
||||||
|
|
||||||
print("Setting device position")
|
print("Setting device position")
|
||||||
# can include lat/long/alt etc: latitude = 37.5, longitude = -122.1
|
# can include lat/long/alt etc: latitude = 37.5, longitude = -122.1
|
||||||
interface.sendPosition(lat, lon, alt)
|
interface.sendPosition(lat, lon, alt)
|
||||||
interface.localNode.writeConfig()
|
interface.localNode.writeConfig('position')
|
||||||
elif not args.no_time:
|
elif not args.no_time:
|
||||||
# We normally provide a current time to the mesh when we connect
|
# We normally provide a current time to the mesh when we connect
|
||||||
interface.sendPosition()
|
interface.sendPosition()
|
||||||
|
|
||||||
if args.set_owner:
|
if args.set_owner:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
|
waitForAckNak = True
|
||||||
print(f"Setting device owner to {args.set_owner}")
|
print(f"Setting device owner to {args.set_owner}")
|
||||||
interface.getNode(args.dest).setOwner(args.set_owner)
|
interface.getNode(args.dest, False).setOwner(args.set_owner)
|
||||||
|
|
||||||
if args.set_owner_short:
|
if args.set_owner_short:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
|
waitForAckNak = True
|
||||||
print(f"Setting device owner short to {args.set_owner_short}")
|
print(f"Setting device owner short to {args.set_owner_short}")
|
||||||
interface.getNode(args.dest).setOwner(long_name=None, short_name=args.set_owner_short)
|
interface.getNode(args.dest, False).setOwner(long_name=None, short_name=args.set_owner_short)
|
||||||
|
|
||||||
# TODO: add to export-config and configure
|
# TODO: add to export-config and configure
|
||||||
if args.set_canned_message:
|
if args.set_canned_message:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
|
waitForAckNak = True
|
||||||
print(f"Setting canned plugin message to {args.set_canned_message}")
|
print(f"Setting canned plugin message to {args.set_canned_message}")
|
||||||
interface.getNode(args.dest).set_canned_message(args.set_canned_message)
|
interface.getNode(args.dest, False).set_canned_message(args.set_canned_message)
|
||||||
|
|
||||||
if args.pos_fields:
|
if args.pos_fields:
|
||||||
# If --pos-fields invoked with args, set position fields
|
# If --pos-fields invoked with args, set position fields
|
||||||
closeNow = True
|
closeNow = True
|
||||||
prefs = interface.getNode(args.dest).localConfig
|
positionConfig = interface.getNode(args.dest).localConfig.position
|
||||||
allFields = 0
|
allFields = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for field in args.pos_fields:
|
for field in args.pos_fields:
|
||||||
v_field = config_pb2.PositionFlags.Value(field)
|
v_field = positionConfig.PositionFlags.Value(field)
|
||||||
allFields |= v_field
|
allFields |= v_field
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("ERROR: supported position fields are:")
|
print("ERROR: supported position fields are:")
|
||||||
print(config_pb2.PositionFlags.keys())
|
print(positionConfig.PositionFlags.keys())
|
||||||
print("If no fields are specified, will read and display current value.")
|
print("If no fields are specified, will read and display current value.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f"Setting position fields to {allFields}")
|
print(f"Setting position fields to {allFields}")
|
||||||
setPref(prefs, 'position_flags', f'{allFields:d}')
|
setPref(positionConfig, 'position_flags', f'{allFields:d}')
|
||||||
print("Writing modified preferences to device")
|
print("Writing modified preferences to device")
|
||||||
interface.getNode(args.dest).writeConfig()
|
interface.getNode(args.dest).writeConfig('position')
|
||||||
|
|
||||||
elif args.pos_fields is not None:
|
elif args.pos_fields is not None:
|
||||||
# If --pos-fields invoked without args, read and display current value
|
# If --pos-fields invoked without args, read and display current value
|
||||||
closeNow = True
|
closeNow = True
|
||||||
prefs = interface.getNode(args.dest).localConfig
|
positionConfig = interface.getNode(args.dest).localConfig.position
|
||||||
|
|
||||||
fieldNames = []
|
fieldNames = []
|
||||||
for bit in config_pb2.PositionFlags.values():
|
for bit in positionConfig.PositionFlags.values():
|
||||||
if prefs.position_flags & bit:
|
if positionConfig.position_flags & bit:
|
||||||
fieldNames.append(config_pb2.PositionFlags.Name(bit))
|
fieldNames.append(positionConfig.PositionFlags.Name(bit))
|
||||||
print(' '.join(fieldNames))
|
print(' '.join(fieldNames))
|
||||||
|
|
||||||
if args.set_ham:
|
if args.set_ham:
|
||||||
@@ -290,11 +276,40 @@ def onConnected(interface):
|
|||||||
|
|
||||||
if args.reboot:
|
if args.reboot:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
interface.getNode(args.dest).reboot()
|
waitForAckNak = True
|
||||||
|
interface.getNode(args.dest, False).reboot()
|
||||||
|
|
||||||
|
if args.reboot_ota:
|
||||||
|
closeNow = True
|
||||||
|
waitForAckNak = True
|
||||||
|
interface.getNode(args.dest, False).rebootOTA();
|
||||||
|
|
||||||
if args.shutdown:
|
if args.shutdown:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
interface.getNode(args.dest).shutdown()
|
waitForAckNak = True
|
||||||
|
interface.getNode(args.dest, False).shutdown()
|
||||||
|
|
||||||
|
if args.device_metadata:
|
||||||
|
closeNow = True
|
||||||
|
interface.getNode(args.dest).getMetadata()
|
||||||
|
|
||||||
|
if args.begin_edit:
|
||||||
|
closeNow = True
|
||||||
|
interface.getNode(args.dest, False).beginSettingsTransaction()
|
||||||
|
|
||||||
|
if args.commit_edit:
|
||||||
|
closeNow = True
|
||||||
|
interface.getNode(args.dest, False).commitSettingsTransaction()
|
||||||
|
|
||||||
|
if args.factory_reset:
|
||||||
|
closeNow = True
|
||||||
|
waitForAckNak = True
|
||||||
|
interface.getNode(args.dest, False).factoryReset()
|
||||||
|
|
||||||
|
if args.reset_nodedb:
|
||||||
|
closeNow = True
|
||||||
|
waitForAckNak = True
|
||||||
|
interface.getNode(args.dest, False).resetNodeDb()
|
||||||
|
|
||||||
if args.sendtext:
|
if args.sendtext:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
@@ -315,6 +330,13 @@ def onConnected(interface):
|
|||||||
interface.sendData(payload, args.dest, portNum=portnums_pb2.PortNum.REPLY_APP,
|
interface.sendData(payload, args.dest, portNum=portnums_pb2.PortNum.REPLY_APP,
|
||||||
wantAck=True, wantResponse=True)
|
wantAck=True, wantResponse=True)
|
||||||
|
|
||||||
|
if args.traceroute:
|
||||||
|
loraConfig = getattr(interface.localNode.localConfig, 'lora')
|
||||||
|
hopLimit = getattr(loraConfig, 'hop_limit')
|
||||||
|
dest = str(args.traceroute)
|
||||||
|
print(f"Sending traceroute request to {dest} (this could take a while)")
|
||||||
|
interface.sendTraceRoute(dest, hopLimit)
|
||||||
|
|
||||||
if args.gpio_wrb or args.gpio_rd or args.gpio_watch:
|
if args.gpio_wrb or args.gpio_rd or args.gpio_watch:
|
||||||
if args.dest == BROADCAST_ADDR:
|
if args.dest == BROADCAST_ADDR:
|
||||||
meshtastic.util.our_exit("Warning: Must use a destination node ID.")
|
meshtastic.util.our_exit("Warning: Must use a destination node ID.")
|
||||||
@@ -353,31 +375,48 @@ def onConnected(interface):
|
|||||||
# handle settings
|
# handle settings
|
||||||
if args.set:
|
if args.set:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
prefs = interface.getNode(args.dest).localConfig
|
node = interface.getNode(args.dest)
|
||||||
|
|
||||||
# Handle the int/float/bool arguments
|
# Handle the int/float/bool arguments
|
||||||
|
pref = None
|
||||||
for pref in args.set:
|
for pref in args.set:
|
||||||
setPref(prefs, pref[0], pref[1])
|
found = setPref(node.localConfig, pref[0], pref[1])
|
||||||
|
if not found:
|
||||||
|
found = setPref(node.moduleConfig, pref[0], pref[1])
|
||||||
|
|
||||||
print("Writing modified preferences to device")
|
if found:
|
||||||
interface.getNode(args.dest).writeConfig()
|
print("Writing modified preferences to device")
|
||||||
|
interface.getNode(args.dest).writeConfig(splitCompoundName(pref[0].lower())[0])
|
||||||
|
else:
|
||||||
|
if Globals.getInstance().get_camel_case():
|
||||||
|
print(f"{node.localConfig.__class__.__name__} and {node.moduleConfig.__class__.__name__} do not have an attribute {pref[0]}.")
|
||||||
|
else:
|
||||||
|
print(f"{node.localConfig.__class__.__name__} and {node.moduleConfig.__class__.__name__} do not have attribute {pref[0]}.")
|
||||||
|
print("Choices are...")
|
||||||
|
printConfig(node.localConfig)
|
||||||
|
printConfig(node.moduleConfig)
|
||||||
|
|
||||||
if args.configure:
|
if args.configure:
|
||||||
with open(args.configure[0], encoding='utf8') as file:
|
with open(args.configure[0], encoding='utf8') as file:
|
||||||
configuration = yaml.safe_load(file)
|
configuration = yaml.safe_load(file)
|
||||||
closeNow = True
|
closeNow = True
|
||||||
|
|
||||||
|
interface.getNode(args.dest, False).beginSettingsTransaction()
|
||||||
|
|
||||||
if 'owner' in configuration:
|
if 'owner' in configuration:
|
||||||
print(f"Setting device owner to {configuration['owner']}")
|
print(f"Setting device owner to {configuration['owner']}")
|
||||||
interface.getNode(args.dest).setOwner(configuration['owner'])
|
waitForAckNak = True
|
||||||
|
interface.getNode(args.dest, False).setOwner(configuration['owner'])
|
||||||
|
|
||||||
if 'owner_short' in configuration:
|
if 'owner_short' in configuration:
|
||||||
print(f"Setting device owner short to {configuration['owner_short']}")
|
print(f"Setting device owner short to {configuration['owner_short']}")
|
||||||
interface.getNode(args.dest).setOwner(long_name=None, short_name=configuration['owner_short'])
|
waitForAckNak = True
|
||||||
|
interface.getNode(args.dest, False).setOwner(long_name=None, short_name=configuration['owner_short'])
|
||||||
|
|
||||||
if 'ownerShort' in configuration:
|
if 'ownerShort' in configuration:
|
||||||
print(f"Setting device owner short to {configuration['ownerShort']}")
|
print(f"Setting device owner short to {configuration['ownerShort']}")
|
||||||
interface.getNode(args.dest).setOwner(long_name=None, short_name=configuration['ownerShort'])
|
waitForAckNak = True
|
||||||
|
interface.getNode(args.dest, False).setOwner(long_name=None, short_name=configuration['ownerShort'])
|
||||||
|
|
||||||
if 'channel_url' in configuration:
|
if 'channel_url' in configuration:
|
||||||
print("Setting channel url to", configuration['channel_url'])
|
print("Setting channel url to", configuration['channel_url'])
|
||||||
@@ -391,37 +430,40 @@ def onConnected(interface):
|
|||||||
alt = 0
|
alt = 0
|
||||||
lat = 0.0
|
lat = 0.0
|
||||||
lon = 0.0
|
lon = 0.0
|
||||||
prefs = interface.localNode.localConfig
|
localConfig = interface.localNode.localConfig
|
||||||
|
|
||||||
if 'alt' in configuration['location']:
|
if 'alt' in configuration['location']:
|
||||||
alt = int(configuration['location']['alt'])
|
alt = int(configuration['location']['alt'])
|
||||||
prefs.fixed_position = True
|
localConfig.position.fixed_position = True
|
||||||
print(f"Fixing altitude at {alt} meters")
|
print(f"Fixing altitude at {alt} meters")
|
||||||
if 'lat' in configuration['location']:
|
if 'lat' in configuration['location']:
|
||||||
lat = float(configuration['location']['lat'])
|
lat = float(configuration['location']['lat'])
|
||||||
prefs.fixed_position = True
|
localConfig.position.fixed_position = True
|
||||||
print(f"Fixing latitude at {lat} degrees")
|
print(f"Fixing latitude at {lat} degrees")
|
||||||
if 'lon' in configuration['location']:
|
if 'lon' in configuration['location']:
|
||||||
lon = float(configuration['location']['lon'])
|
lon = float(configuration['location']['lon'])
|
||||||
prefs.fixed_position = True
|
localConfig.position.fixed_position = True
|
||||||
print(f"Fixing longitude at {lon} degrees")
|
print(f"Fixing longitude at {lon} degrees")
|
||||||
print("Setting device position")
|
print("Setting device position")
|
||||||
interface.sendPosition(lat, lon, alt)
|
interface.sendPosition(lat, lon, alt)
|
||||||
interface.localNode.writeConfig()
|
interface.localNode.writeConfig('position')
|
||||||
|
|
||||||
if 'user_prefs' in configuration:
|
if 'config' in configuration:
|
||||||
prefs = interface.getNode(args.dest).localConfig
|
localConfig = interface.getNode(args.dest).localConfig
|
||||||
for pref in configuration['user_prefs']:
|
for section in configuration['config']:
|
||||||
setPref(prefs, pref, str(configuration['user_prefs'][pref]))
|
for pref in configuration['config'][section]:
|
||||||
print("Writing modified preferences to device")
|
setPref(localConfig, f"{section}.{pref}", str(configuration['config'][section][pref]))
|
||||||
interface.getNode(args.dest).writeConfig()
|
interface.getNode(args.dest).writeConfig(section)
|
||||||
|
|
||||||
|
if 'module_config' in configuration:
|
||||||
|
moduleConfig = interface.getNode(args.dest).moduleConfig
|
||||||
|
for section in configuration['module_config']:
|
||||||
|
for pref in configuration['module_config'][section]:
|
||||||
|
setPref(moduleConfig, f"{section}.{pref}", str(configuration['module_config'][section][pref]))
|
||||||
|
interface.getNode(args.dest).writeConfig(section)
|
||||||
|
|
||||||
if 'userPrefs' in configuration:
|
interface.getNode(args.dest, False).commitSettingsTransaction()
|
||||||
prefs = interface.getNode(args.dest).localConfig
|
print("Writing modified configuration to device")
|
||||||
for pref in configuration['userPrefs']:
|
|
||||||
setPref(prefs, pref, str(configuration['userPrefs'][pref]))
|
|
||||||
print("Writing modified preferences to device")
|
|
||||||
interface.getNode(args.dest).writeConfig()
|
|
||||||
|
|
||||||
if args.export_config:
|
if args.export_config:
|
||||||
# export the configuration (the opposite of '--configure')
|
# export the configuration (the opposite of '--configure')
|
||||||
@@ -470,34 +512,32 @@ def onConnected(interface):
|
|||||||
|
|
||||||
def setSimpleConfig(modem_preset):
|
def setSimpleConfig(modem_preset):
|
||||||
"""Set one of the simple modem_config"""
|
"""Set one of the simple modem_config"""
|
||||||
# Completely new radio settings
|
# Overwrite modem_preset
|
||||||
chs = config_pb2.Config.LoRaConfig()
|
|
||||||
chs.modem_preset = modem_preset
|
|
||||||
prefs = interface.getNode(args.dest).localConfig
|
prefs = interface.getNode(args.dest).localConfig
|
||||||
prefs.lora.CopyFrom(chs)
|
prefs.lora.modem_preset = modem_preset
|
||||||
interface.getNode(args.dest).writeConfig()
|
interface.getNode(args.dest).writeConfig('lora')
|
||||||
|
|
||||||
# handle the simple radio set commands
|
# handle the simple radio set commands
|
||||||
if args.ch_vlongslow:
|
if args.ch_vlongslow:
|
||||||
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.VLongSlow)
|
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.VERY_LONG_SLOW)
|
||||||
|
|
||||||
if args.ch_longslow:
|
if args.ch_longslow:
|
||||||
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.LongSlow)
|
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.LONG_SLOW)
|
||||||
|
|
||||||
if args.ch_longfast:
|
if args.ch_longfast:
|
||||||
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.LongFast)
|
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.LONG_FAST)
|
||||||
|
|
||||||
if args.ch_midslow:
|
if args.ch_medslow:
|
||||||
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.MidSlow)
|
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.MEDIUM_SLOW)
|
||||||
|
|
||||||
if args.ch_midfast:
|
if args.ch_medfast:
|
||||||
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.MidFast)
|
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.MEDIUM_FAST)
|
||||||
|
|
||||||
if args.ch_shortslow:
|
if args.ch_shortslow:
|
||||||
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.ShortSlow)
|
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.SHORT_SLOW)
|
||||||
|
|
||||||
if args.ch_shortfast:
|
if args.ch_shortfast:
|
||||||
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.ShortFast)
|
setSimpleConfig(config_pb2.Config.LoRaConfig.ModemPreset.SHORT_FAST)
|
||||||
|
|
||||||
if args.ch_set or args.ch_enable or args.ch_disable:
|
if args.ch_set or args.ch_enable or args.ch_disable:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
@@ -553,13 +593,25 @@ def onConnected(interface):
|
|||||||
|
|
||||||
if args.get:
|
if args.get:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
prefs = interface.getNode(args.dest).localConfig
|
localConfig = interface.getNode(args.dest).localConfig
|
||||||
|
moduleConfig = interface.getNode(args.dest).moduleConfig
|
||||||
|
|
||||||
# Handle the int/float/bool arguments
|
# Handle the int/float/bool arguments
|
||||||
for pref in args.get:
|
for pref in args.get:
|
||||||
getPref(prefs, pref[0])
|
found = getPref(localConfig, pref[0])
|
||||||
|
if not found:
|
||||||
|
found = getPref(moduleConfig, pref[0])
|
||||||
|
|
||||||
print("Completed getting preferences")
|
if not found:
|
||||||
|
if Globals.getInstance().get_camel_case():
|
||||||
|
print(f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have an attribute {pref[0]}.")
|
||||||
|
else:
|
||||||
|
print(f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have attribute {pref[0]}.")
|
||||||
|
print("Choices are...")
|
||||||
|
printConfig(localConfig)
|
||||||
|
printConfig(moduleConfig)
|
||||||
|
else:
|
||||||
|
print("Completed getting preferences")
|
||||||
|
|
||||||
if args.nodes:
|
if args.nodes:
|
||||||
closeNow = True
|
closeNow = True
|
||||||
@@ -583,6 +635,10 @@ def onConnected(interface):
|
|||||||
else:
|
else:
|
||||||
tunnel.Tunnel(interface, subnet=args.tunnel_net)
|
tunnel.Tunnel(interface, subnet=args.tunnel_net)
|
||||||
|
|
||||||
|
if args.dest != BROADCAST_ADDR and waitForAckNak:
|
||||||
|
print(f"Waiting for an acknowledgment from remote node (this could take a while)")
|
||||||
|
interface.getNode(args.dest, False).iface.waitForAckNak()
|
||||||
|
|
||||||
# if the user didn't ask for serial debugging output, we might want to exit after we've done our operation
|
# if the user didn't ask for serial debugging output, we might want to exit after we've done our operation
|
||||||
if (not args.seriallog) and closeNow:
|
if (not args.seriallog) and closeNow:
|
||||||
interface.close() # after running command then exit
|
interface.close() # after running command then exit
|
||||||
@@ -591,6 +647,20 @@ def onConnected(interface):
|
|||||||
print(f"Aborting due to: {ex}")
|
print(f"Aborting due to: {ex}")
|
||||||
interface.close() # close the connection now, so that our app exits
|
interface.close() # close the connection now, so that our app exits
|
||||||
|
|
||||||
|
def printConfig(config):
|
||||||
|
objDesc = config.DESCRIPTOR
|
||||||
|
for config_section in objDesc.fields:
|
||||||
|
if config_section.name != "version":
|
||||||
|
config = objDesc.fields_by_name.get(config_section.name)
|
||||||
|
print(f"{config_section.name}:")
|
||||||
|
names = []
|
||||||
|
for field in config.message_type.fields:
|
||||||
|
tmp_name = f'{config_section.name}.{field.name}'
|
||||||
|
if Globals.getInstance().get_camel_case():
|
||||||
|
tmp_name = meshtastic.util.snake_to_camel(tmp_name)
|
||||||
|
names.append(tmp_name)
|
||||||
|
for temp_name in sorted(names):
|
||||||
|
print(f" {temp_name}")
|
||||||
|
|
||||||
def onNode(node):
|
def onNode(node):
|
||||||
"""Callback invoked when the node DB changes"""
|
"""Callback invoked when the node DB changes"""
|
||||||
@@ -610,6 +680,8 @@ def subscribe():
|
|||||||
|
|
||||||
def export_config(interface):
|
def export_config(interface):
|
||||||
"""used in--export-config"""
|
"""used in--export-config"""
|
||||||
|
configObj = {}
|
||||||
|
|
||||||
owner = interface.getLongName()
|
owner = interface.getLongName()
|
||||||
owner_short = interface.getShortName()
|
owner_short = interface.getShortName()
|
||||||
channel_url = interface.localNode.getURL()
|
channel_url = interface.localNode.getURL()
|
||||||
@@ -623,38 +695,46 @@ def export_config(interface):
|
|||||||
lon = pos.get('longitude')
|
lon = pos.get('longitude')
|
||||||
alt = pos.get('altitude')
|
alt = pos.get('altitude')
|
||||||
|
|
||||||
config = "# start of Meshtastic configure yaml\n"
|
|
||||||
if owner:
|
if owner:
|
||||||
config += f"owner: {owner}\n\n"
|
configObj["owner"] = owner
|
||||||
if owner_short:
|
if owner_short:
|
||||||
config += f"owner_short: {owner_short}\n\n"
|
configObj["owner_short"] = owner_short
|
||||||
if channel_url:
|
if channel_url:
|
||||||
if Globals.getInstance().get_camel_case():
|
if Globals.getInstance().get_camel_case():
|
||||||
config += f"channelUrl: {channel_url}\n\n"
|
configObj["channelUrl"] = channel_url
|
||||||
else:
|
else:
|
||||||
config += f"channel_url: {channel_url}\n\n"
|
configObj["channel_url"] = channel_url
|
||||||
if lat or lon or alt:
|
if lat or lon or alt:
|
||||||
config += "location:\n"
|
configObj["location"] = { "lat": lat, "lon": lon, "alt": alt }
|
||||||
if lat:
|
|
||||||
config += f" lat: {lat}\n"
|
config = MessageToDict(interface.localNode.localConfig)
|
||||||
if lon:
|
if config:
|
||||||
config += f" lon: {lon}\n"
|
# Convert inner keys to correct snake/camelCase
|
||||||
if alt:
|
prefs = {}
|
||||||
config += f" alt: {alt}\n"
|
for pref in config:
|
||||||
config += "\n"
|
|
||||||
preferences = f'{interface.localNode.localConfig}'
|
|
||||||
prefs = preferences.splitlines()
|
|
||||||
if prefs:
|
|
||||||
if Globals.getInstance().get_camel_case():
|
|
||||||
config += "userPrefs:\n"
|
|
||||||
else:
|
|
||||||
config += "user_prefs:\n"
|
|
||||||
for pref in prefs:
|
|
||||||
if Globals.getInstance().get_camel_case():
|
if Globals.getInstance().get_camel_case():
|
||||||
# Note: This may not work if the value has '_'
|
prefs[meshtastic.util.snake_to_camel(pref)] = config[pref]
|
||||||
config += f" {meshtastic.util.snake_to_camel(meshtastic.util.quoteBooleans(pref))}\n"
|
|
||||||
else:
|
else:
|
||||||
config += f" {meshtastic.util.quoteBooleans(pref)}\n"
|
prefs[pref] = config[pref]
|
||||||
|
if Globals.getInstance().get_camel_case():
|
||||||
|
configObj["config"] = config
|
||||||
|
else:
|
||||||
|
configObj["config"] = config
|
||||||
|
|
||||||
|
module_config = MessageToDict(interface.localNode.moduleConfig)
|
||||||
|
if module_config:
|
||||||
|
# Convert inner keys to correct snake/camelCase
|
||||||
|
prefs = {}
|
||||||
|
for pref in module_config:
|
||||||
|
if len(module_config[pref]) > 0:
|
||||||
|
prefs[pref] = module_config[pref]
|
||||||
|
if Globals.getInstance().get_camel_case():
|
||||||
|
configObj["module_config"] = prefs
|
||||||
|
else:
|
||||||
|
configObj["module_config"] = prefs
|
||||||
|
|
||||||
|
config = "# start of Meshtastic configure yaml\n"
|
||||||
|
config += yaml.dump(configObj)
|
||||||
print(config)
|
print(config)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
@@ -816,7 +896,7 @@ def initParser():
|
|||||||
"--ch-set", help=("Set a channel parameter. To see channel settings available:'--ch-set all all --ch-index 0'. "
|
"--ch-set", help=("Set a channel parameter. To see channel settings available:'--ch-set all all --ch-index 0'. "
|
||||||
"Can set the 'psk' using this command. To disable encryption on primary channel:'--ch-set psk none --ch-index 0'. "
|
"Can set the 'psk' using this command. To disable encryption on primary channel:'--ch-set psk none --ch-index 0'. "
|
||||||
"To set encryption with a new random key on second channel:'--ch-set psk random --ch-index 1'. "
|
"To set encryption with a new random key on second channel:'--ch-set psk random --ch-index 1'. "
|
||||||
"To set encryption back to the default:'--ch-set default --ch-index 0'. To set encryption with your "
|
"To set encryption back to the default:'--ch-set psk default --ch-index 0'. To set encryption with your "
|
||||||
"own key: '--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --ch-index 0'."),
|
"own key: '--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --ch-index 0'."),
|
||||||
nargs=2, action='append')
|
nargs=2, action='append')
|
||||||
|
|
||||||
@@ -830,10 +910,10 @@ def initParser():
|
|||||||
"--ch-longfast", help="Change to the long-range and fast channel", action='store_true')
|
"--ch-longfast", help="Change to the long-range and fast channel", action='store_true')
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--ch-midslow", help="Change to the mid-range and slow channel", action='store_true')
|
"--ch-medslow", help="Change to the med-range and slow channel", action='store_true')
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--ch-midfast", help="Change to the mid-range and fast channel", action='store_true')
|
"--ch-medfast", help="Change to the med-range and fast channel", action='store_true')
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--ch-shortslow", help="Change to the short-range and slow channel", action='store_true')
|
"--ch-shortslow", help="Change to the short-range and slow channel", action='store_true')
|
||||||
@@ -862,12 +942,36 @@ def initParser():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--sendping", help="Send a ping message (which requests a reply)", action="store_true")
|
"--sendping", help="Send a ping message (which requests a reply)", action="store_true")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--traceroute", help="Traceroute from connected node to a destination. " \
|
||||||
|
"You need pass the destination ID as argument, like " \
|
||||||
|
"this: '--traceroute !ba4bf9d0' " \
|
||||||
|
"Only nodes that have the encryption key can be traced.")
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--reboot", help="Tell the destination node to reboot", action="store_true")
|
"--reboot", help="Tell the destination node to reboot", action="store_true")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--reboot-ota", help="Tell the destination node to reboot into factory firmware", action="store_true")
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--shutdown", help="Tell the destination node to shutdown", action="store_true")
|
"--shutdown", help="Tell the destination node to shutdown", action="store_true")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--device-metadata", help="Get the device metadata from the node", action="store_true")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--begin-edit", help="Tell the node to open a transaction to edit settings", action="store_true")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--commit-edit", help="Tell the node to commit open settings transaction", action="store_true")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--factory-reset", help="Tell the destination node to install the default config", action="store_true")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--reset-nodedb", help="Tell the destination node clear its list of nodes", action="store_true")
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--reply", help="Reply to received messages",
|
"--reply", help="Reply to received messages",
|
||||||
action="store_true")
|
action="store_true")
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ _sym_db = _symbol_database.Default()
|
|||||||
|
|
||||||
from . import channel_pb2 as channel__pb2
|
from . import channel_pb2 as channel__pb2
|
||||||
from . import config_pb2 as config__pb2
|
from . import config_pb2 as config__pb2
|
||||||
|
from . import device_metadata_pb2 as device__metadata__pb2
|
||||||
from . import mesh_pb2 as mesh__pb2
|
from . import mesh_pb2 as mesh__pb2
|
||||||
from . import module_config_pb2 as module__config__pb2
|
from . import module_config_pb2 as module__config__pb2
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61\x64min.proto\x1a\rchannel.proto\x1a\x0c\x63onfig.proto\x1a\nmesh.proto\x1a\x13module_config.proto\"\xc4\x0c\n\x0c\x41\x64minMessage\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\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\x36\n\x12get_config_request\x18\n \x01(\x0e\x32\x18.AdminMessage.ConfigTypeH\x00\x12&\n\x13get_config_response\x18\x0b \x01(\x0b\x32\x07.ConfigH\x00\x12\x1d\n\nset_config\x18\x0c \x01(\x0b\x32\x07.ConfigH\x00\x12\x1c\n\x12\x63onfirm_set_config\x18\r \x01(\x08H\x00\x12\x43\n\x19get_module_config_request\x18\x0e \x01(\x0e\x32\x1e.AdminMessage.ModuleConfigTypeH\x00\x12\x33\n\x1aget_module_config_response\x18\x0f \x01(\x0b\x32\r.ModuleConfigH\x00\x12*\n\x11set_module_config\x18\x10 \x01(\x0b\x32\r.ModuleConfigH\x00\x12#\n\x19\x63onfirm_set_module_config\x18\x11 \x01(\x08H\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\"|\n\nConfigType\x12\x11\n\rDEVICE_CONFIG\x10\x00\x12\x13\n\x0fPOSITION_CONFIG\x10\x01\x12\x10\n\x0cPOWER_CONFIG\x10\x02\x12\x0f\n\x0bWIFI_CONFIG\x10\x03\x12\x12\n\x0e\x44ISPLAY_CONFIG\x10\x04\x12\x0f\n\x0bLORA_CONFIG\x10\x05\"\xa6\x01\n\x10ModuleConfigType\x12\x0f\n\x0bMQTT_CONFIG\x10\x00\x12\x11\n\rSERIAL_CONFIG\x10\x01\x12\x13\n\x0f\x45XTNOTIF_CONFIG\x10\x02\x12\x17\n\x13STOREFORWARD_CONFIG\x10\x03\x12\x14\n\x10RANGETEST_CONFIG\x10\x04\x12\x14\n\x10TELEMETRY_CONFIG\x10\x05\x12\x14\n\x10\x43\x41NNEDMSG_CONFIG\x10\x06\x42\t\n\x07variantBG\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61\x64min.proto\x1a\rchannel.proto\x1a\x0c\x63onfig.proto\x1a\x15\x64\x65vice_metadata.proto\x1a\nmesh.proto\x1a\x13module_config.proto\"\xf6\n\n\x0c\x41\x64minMessage\x12\x1d\n\x13get_channel_request\x18\x01 \x01(\rH\x00\x12(\n\x14get_channel_response\x18\x02 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x03 \x01(\x08H\x00\x12#\n\x12get_owner_response\x18\x04 \x01(\x0b\x32\x05.UserH\x00\x12\x36\n\x12get_config_request\x18\x05 \x01(\x0e\x32\x18.AdminMessage.ConfigTypeH\x00\x12&\n\x13get_config_response\x18\x06 \x01(\x0b\x32\x07.ConfigH\x00\x12\x43\n\x19get_module_config_request\x18\x07 \x01(\x0e\x32\x1e.AdminMessage.ModuleConfigTypeH\x00\x12\x33\n\x1aget_module_config_response\x18\x08 \x01(\x0b\x32\r.ModuleConfigH\x00\x12\x34\n*get_canned_message_module_messages_request\x18\n \x01(\x08H\x00\x12\x35\n+get_canned_message_module_messages_response\x18\x0b \x01(\tH\x00\x12%\n\x1bget_device_metadata_request\x18\x0c \x01(\x08H\x00\x12\x37\n\x1cget_device_metadata_response\x18\r \x01(\x0b\x32\x0f.DeviceMetadataH\x00\x12\x1a\n\tset_owner\x18 \x01(\x0b\x32\x05.UserH\x00\x12\x1f\n\x0bset_channel\x18! \x01(\x0b\x32\x08.ChannelH\x00\x12\x1d\n\nset_config\x18\" \x01(\x0b\x32\x07.ConfigH\x00\x12*\n\x11set_module_config\x18# \x01(\x0b\x32\r.ModuleConfigH\x00\x12,\n\"set_canned_message_module_messages\x18$ \x01(\tH\x00\x12\x1d\n\x13\x62\x65gin_edit_settings\x18@ \x01(\x08H\x00\x12\x1e\n\x14\x63ommit_edit_settings\x18\x41 \x01(\x08H\x00\x12\x1d\n\x13\x63onfirm_set_channel\x18\x42 \x01(\x08H\x00\x12\x1b\n\x11\x63onfirm_set_radio\x18\x43 \x01(\x08H\x00\x12\x1c\n\x12reboot_ota_seconds\x18_ \x01(\x05H\x00\x12\x18\n\x0e\x65xit_simulator\x18` \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18\x61 \x01(\x05H\x00\x12\x1a\n\x10shutdown_seconds\x18\x62 \x01(\x05H\x00\x12\x17\n\rfactory_reset\x18\x63 \x01(\x05H\x00\x12\x16\n\x0cnodedb_reset\x18\x64 \x01(\x05H\x00\"\x95\x01\n\nConfigType\x12\x11\n\rDEVICE_CONFIG\x10\x00\x12\x13\n\x0fPOSITION_CONFIG\x10\x01\x12\x10\n\x0cPOWER_CONFIG\x10\x02\x12\x12\n\x0eNETWORK_CONFIG\x10\x03\x12\x12\n\x0e\x44ISPLAY_CONFIG\x10\x04\x12\x0f\n\x0bLORA_CONFIG\x10\x05\x12\x14\n\x10\x42LUETOOTH_CONFIG\x10\x06\"\xb8\x01\n\x10ModuleConfigType\x12\x0f\n\x0bMQTT_CONFIG\x10\x00\x12\x11\n\rSERIAL_CONFIG\x10\x01\x12\x13\n\x0f\x45XTNOTIF_CONFIG\x10\x02\x12\x17\n\x13STOREFORWARD_CONFIG\x10\x03\x12\x14\n\x10RANGETEST_CONFIG\x10\x04\x12\x14\n\x10TELEMETRY_CONFIG\x10\x05\x12\x14\n\x10\x43\x41NNEDMSG_CONFIG\x10\x06\x12\x10\n\x0c\x41UDIO_CONFIG\x10\x07\x42\x11\n\x0fpayload_variantBH\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -35,11 +36,11 @@ _sym_db.RegisterMessage(AdminMessage)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\013AdminProtosH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\013AdminProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_ADMINMESSAGE._serialized_start=78
|
_ADMINMESSAGE._serialized_start=101
|
||||||
_ADMINMESSAGE._serialized_end=1682
|
_ADMINMESSAGE._serialized_end=1499
|
||||||
_ADMINMESSAGE_CONFIGTYPE._serialized_start=1378
|
_ADMINMESSAGE_CONFIGTYPE._serialized_start=1144
|
||||||
_ADMINMESSAGE_CONFIGTYPE._serialized_end=1502
|
_ADMINMESSAGE_CONFIGTYPE._serialized_end=1293
|
||||||
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_start=1505
|
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_start=1296
|
||||||
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_end=1671
|
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_end=1480
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from . import channel_pb2 as channel__pb2
|
|||||||
from . import config_pb2 as config__pb2
|
from . import config_pb2 as config__pb2
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rapponly.proto\x1a\rchannel.proto\x1a\x0c\x63onfig.proto\"Y\n\nChannelSet\x12\"\n\x08settings\x18\x01 \x03(\x0b\x32\x10.ChannelSettings\x12\'\n\x0blora_config\x18\x02 \x01(\x0b\x32\x12.Config.LoRaConfigBI\n\x13\x63om.geeksville.meshB\rAppOnlyProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rapponly.proto\x1a\rchannel.proto\x1a\x0c\x63onfig.proto\"Y\n\nChannelSet\x12\"\n\x08settings\x18\x01 \x03(\x0b\x32\x10.ChannelSettings\x12\'\n\x0blora_config\x18\x02 \x01(\x0b\x32\x12.Config.LoRaConfigBJ\n\x13\x63om.geeksville.meshB\rAppOnlyProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ _sym_db.RegisterMessage(ChannelSet)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rAppOnlyProtosH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rAppOnlyProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_CHANNELSET._serialized_start=46
|
_CHANNELSET._serialized_start=46
|
||||||
_CHANNELSET._serialized_end=135
|
_CHANNELSET._serialized_end=135
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(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')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x63\x61nnedmessages.proto\"-\n\x19\x43\x61nnedMessageModuleConfig\x12\x10\n\x08messages\x18\x01 \x01(\tBV\n\x13\x63om.geeksville.meshB\x19\x43\x61nnedMessageConfigProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ _sym_db.RegisterMessage(CannedMessageModuleConfig)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\031CannedMessageConfigProtosH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\031CannedMessageConfigProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_CANNEDMESSAGEMODULECONFIG._serialized_start=24
|
_CANNEDMESSAGEMODULECONFIG._serialized_start=24
|
||||||
_CANNEDMESSAGEMODULECONFIG._serialized_end=143
|
_CANNEDMESSAGEMODULECONFIG._serialized_end=69
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rchannel.proto\"\x7f\n\x0f\x43hannelSettings\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\"\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_pool.Default().AddSerializedFile(b'\n\rchannel.proto\"\x83\x01\n\x0f\x43hannelSettings\x12\x17\n\x0b\x63hannel_num\x18\x01 \x01(\rB\x02\x18\x01\x12\x0b\n\x03psk\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\n\n\x02id\x18\x04 \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x05 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x06 \x01(\x08\"\x8b\x01\n\x07\x43hannel\x12\r\n\x05index\x18\x01 \x01(\x05\x12\"\n\x08settings\x18\x02 \x01(\x0b\x32\x10.ChannelSettings\x12\x1b\n\x04role\x18\x03 \x01(\x0e\x32\r.Channel.Role\"0\n\x04Role\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07PRIMARY\x10\x01\x12\r\n\tSECONDARY\x10\x02\x42J\n\x13\x63om.geeksville.meshB\rChannelProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -38,11 +38,13 @@ _sym_db.RegisterMessage(Channel)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rChannelProtosH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rChannelProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_CHANNELSETTINGS._serialized_start=17
|
_CHANNELSETTINGS.fields_by_name['channel_num']._options = None
|
||||||
_CHANNELSETTINGS._serialized_end=144
|
_CHANNELSETTINGS.fields_by_name['channel_num']._serialized_options = b'\030\001'
|
||||||
_CHANNEL._serialized_start=147
|
_CHANNELSETTINGS._serialized_start=18
|
||||||
_CHANNEL._serialized_end=286
|
_CHANNELSETTINGS._serialized_end=149
|
||||||
_CHANNEL_ROLE._serialized_start=238
|
_CHANNEL._serialized_start=152
|
||||||
_CHANNEL_ROLE._serialized_end=286
|
_CHANNEL._serialized_end=291
|
||||||
|
_CHANNEL_ROLE._serialized_start=243
|
||||||
|
_CHANNEL_ROLE._serialized_end=291
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
35
meshtastic/device_metadata_pb2.py
Normal file
35
meshtastic/device_metadata_pb2.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
# source: device_metadata.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\x15\x64\x65vice_metadata.proto\"\x99\x01\n\x0e\x44\x65viceMetadata\x12\x18\n\x10\x66irmware_version\x18\x01 \x01(\t\x12\x1c\n\x14\x64\x65vice_state_version\x18\x02 \x01(\r\x12\x13\n\x0b\x63\x61nShutdown\x18\x03 \x01(\x08\x12\x0f\n\x07hasWifi\x18\x04 \x01(\x08\x12\x14\n\x0chasBluetooth\x18\x05 \x01(\x08\x12\x13\n\x0bhasEthernet\x18\x06 \x01(\x08\x42Q\n\x13\x63om.geeksville.meshB\x14\x44\x65viceMetadataProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_DEVICEMETADATA = DESCRIPTOR.message_types_by_name['DeviceMetadata']
|
||||||
|
DeviceMetadata = _reflection.GeneratedProtocolMessageType('DeviceMetadata', (_message.Message,), {
|
||||||
|
'DESCRIPTOR' : _DEVICEMETADATA,
|
||||||
|
'__module__' : 'device_metadata_pb2'
|
||||||
|
# @@protoc_insertion_point(class_scope:DeviceMetadata)
|
||||||
|
})
|
||||||
|
_sym_db.RegisterMessage(DeviceMetadata)
|
||||||
|
|
||||||
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
|
DESCRIPTOR._options = None
|
||||||
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\024DeviceMetadataProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
|
_DEVICEMETADATA._serialized_start=26
|
||||||
|
_DEVICEMETADATA._serialized_end=179
|
||||||
|
# @@protoc_insertion_point(module_scope)
|
||||||
@@ -17,7 +17,7 @@ from . import channel_pb2 as channel__pb2
|
|||||||
from . import mesh_pb2 as mesh__pb2
|
from . import mesh_pb2 as mesh__pb2
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(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.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\x84\x01\n\x08OEMStore\x12\x16\n\x0eoem_icon_width\x18\x01 \x01(\r\x12\x17\n\x0foem_icon_height\x18\x02 \x01(\r\x12\x15\n\roem_icon_bits\x18\x03 \x01(\x0c\x12\x1e\n\x08oem_font\x18\x04 \x01(\x0e\x32\x0c.ScreenFonts\x12\x10\n\x08oem_text\x18\x05 \x01(\t*>\n\x0bScreenFonts\x12\x0e\n\nFONT_SMALL\x10\x00\x12\x0f\n\x0b\x46ONT_MEDIUM\x10\x01\x12\x0e\n\nFONT_LARGE\x10\x02\x42\x46\n\x13\x63om.geeksville.meshB\nDeviceOnlyH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x64\x65viceonly.proto\x1a\rchannel.proto\x1a\nmesh.proto\"\xe0\x01\n\x0b\x44\x65viceState\x12\x1c\n\x07my_node\x18\x02 \x01(\x0b\x32\x0b.MyNodeInfo\x12\x14\n\x05owner\x18\x03 \x01(\x0b\x32\x05.User\x12\x1a\n\x07node_db\x18\x04 \x03(\x0b\x32\t.NodeInfo\x12\"\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12$\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07no_save\x18\t \x01(\x08\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08\":\n\x0b\x43hannelFile\x12\x1a\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x08.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\x99\x01\n\x08OEMStore\x12\x16\n\x0eoem_icon_width\x18\x01 \x01(\r\x12\x17\n\x0foem_icon_height\x18\x02 \x01(\r\x12\x15\n\roem_icon_bits\x18\x03 \x01(\x0c\x12\x1e\n\x08oem_font\x18\x04 \x01(\x0e\x32\x0c.ScreenFonts\x12\x10\n\x08oem_text\x18\x05 \x01(\t\x12\x13\n\x0boem_aes_key\x18\x06 \x01(\x0c*>\n\x0bScreenFonts\x12\x0e\n\nFONT_SMALL\x10\x00\x12\x0f\n\x0b\x46ONT_MEDIUM\x10\x01\x12\x0e\n\nFONT_LARGE\x10\x02\x42G\n\x13\x63om.geeksville.meshB\nDeviceOnlyH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
_SCREENFONTS = DESCRIPTOR.enum_types_by_name['ScreenFonts']
|
_SCREENFONTS = DESCRIPTOR.enum_types_by_name['ScreenFonts']
|
||||||
ScreenFonts = enum_type_wrapper.EnumTypeWrapper(_SCREENFONTS)
|
ScreenFonts = enum_type_wrapper.EnumTypeWrapper(_SCREENFONTS)
|
||||||
@@ -53,13 +53,13 @@ _sym_db.RegisterMessage(OEMStore)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nDeviceOnlyH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nDeviceOnlyH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_SCREENFONTS._serialized_start=475
|
_SCREENFONTS._serialized_start=490
|
||||||
_SCREENFONTS._serialized_end=537
|
_SCREENFONTS._serialized_end=552
|
||||||
_DEVICESTATE._serialized_start=48
|
_DEVICESTATE._serialized_start=48
|
||||||
_DEVICESTATE._serialized_end=278
|
_DEVICESTATE._serialized_end=272
|
||||||
_CHANNELFILE._serialized_start=280
|
_CHANNELFILE._serialized_start=274
|
||||||
_CHANNELFILE._serialized_end=338
|
_CHANNELFILE._serialized_end=332
|
||||||
_OEMSTORE._serialized_start=341
|
_OEMSTORE._serialized_start=335
|
||||||
_OEMSTORE._serialized_end=473
|
_OEMSTORE._serialized_end=488
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from . import config_pb2 as config__pb2
|
|||||||
from . import module_config_pb2 as module__config__pb2
|
from . import module_config_pb2 as module__config__pb2
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0flocalonly.proto\x1a\x0c\x63onfig.proto\x1a\x13module_config.proto\"\xfe\x01\n\x0bLocalConfig\x12$\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32\x14.Config.DeviceConfig\x12(\n\x08position\x18\x02 \x01(\x0b\x32\x16.Config.PositionConfig\x12\"\n\x05power\x18\x03 \x01(\x0b\x32\x13.Config.PowerConfig\x12 \n\x04wifi\x18\x04 \x01(\x0b\x32\x12.Config.WiFiConfig\x12&\n\x07\x64isplay\x18\x05 \x01(\x0b\x32\x15.Config.DisplayConfig\x12 \n\x04lora\x18\x06 \x01(\x0b\x32\x12.Config.LoRaConfig\x12\x0f\n\x07version\x18\x07 \x01(\r\"\x9a\x03\n\x11LocalModuleConfig\x12&\n\x04mqtt\x18\x01 \x01(\x0b\x32\x18.ModuleConfig.MQTTConfig\x12*\n\x06serial\x18\x02 \x01(\x0b\x32\x1a.ModuleConfig.SerialConfig\x12G\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32(.ModuleConfig.ExternalNotificationConfig\x12\x37\n\rstore_forward\x18\x04 \x01(\x0b\x32 .ModuleConfig.StoreForwardConfig\x12\x31\n\nrange_test\x18\x05 \x01(\x0b\x32\x1d.ModuleConfig.RangeTestConfig\x12\x30\n\ttelemetry\x18\x06 \x01(\x0b\x32\x1d.ModuleConfig.TelemetryConfig\x12\x39\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32!.ModuleConfig.CannedMessageConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBK\n\x13\x63om.geeksville.meshB\x0fLocalOnlyProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0flocalonly.proto\x1a\x0c\x63onfig.proto\x1a\x13module_config.proto\"\xb0\x02\n\x0bLocalConfig\x12$\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32\x14.Config.DeviceConfig\x12(\n\x08position\x18\x02 \x01(\x0b\x32\x16.Config.PositionConfig\x12\"\n\x05power\x18\x03 \x01(\x0b\x32\x13.Config.PowerConfig\x12&\n\x07network\x18\x04 \x01(\x0b\x32\x15.Config.NetworkConfig\x12&\n\x07\x64isplay\x18\x05 \x01(\x0b\x32\x15.Config.DisplayConfig\x12 \n\x04lora\x18\x06 \x01(\x0b\x32\x12.Config.LoRaConfig\x12*\n\tbluetooth\x18\x07 \x01(\x0b\x32\x17.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\"\xc4\x03\n\x11LocalModuleConfig\x12&\n\x04mqtt\x18\x01 \x01(\x0b\x32\x18.ModuleConfig.MQTTConfig\x12*\n\x06serial\x18\x02 \x01(\x0b\x32\x1a.ModuleConfig.SerialConfig\x12G\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32(.ModuleConfig.ExternalNotificationConfig\x12\x37\n\rstore_forward\x18\x04 \x01(\x0b\x32 .ModuleConfig.StoreForwardConfig\x12\x31\n\nrange_test\x18\x05 \x01(\x0b\x32\x1d.ModuleConfig.RangeTestConfig\x12\x30\n\ttelemetry\x18\x06 \x01(\x0b\x32\x1d.ModuleConfig.TelemetryConfig\x12\x39\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32!.ModuleConfig.CannedMessageConfig\x12(\n\x05\x61udio\x18\t \x01(\x0b\x32\x19.ModuleConfig.AudioConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBL\n\x13\x63om.geeksville.meshB\x0fLocalOnlyProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -39,9 +39,9 @@ _sym_db.RegisterMessage(LocalModuleConfig)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017LocalOnlyProtosH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017LocalOnlyProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_LOCALCONFIG._serialized_start=55
|
_LOCALCONFIG._serialized_start=55
|
||||||
_LOCALCONFIG._serialized_end=309
|
_LOCALCONFIG._serialized_end=359
|
||||||
_LOCALMODULECONFIG._serialized_start=312
|
_LOCALMODULECONFIG._serialized_start=362
|
||||||
_LOCALMODULECONFIG._serialized_end=722
|
_LOCALMODULECONFIG._serialized_end=814
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from google.protobuf.json_format import MessageToJson
|
|||||||
|
|
||||||
import meshtastic.node
|
import meshtastic.node
|
||||||
from meshtastic import portnums_pb2, mesh_pb2
|
from meshtastic import portnums_pb2, mesh_pb2
|
||||||
from meshtastic.util import stripnl, Timeout, our_exit, remove_keys_from_dict, convert_mac_addr
|
from meshtastic.util import stripnl, Timeout, Acknowledgment, our_exit, remove_keys_from_dict, convert_mac_addr
|
||||||
from meshtastic.__init__ import LOCAL_ADDR, BROADCAST_NUM, BROADCAST_ADDR, ResponseHandler, publishingThread, OUR_APP_VERSION, protocols
|
from meshtastic.__init__ import LOCAL_ADDR, BROADCAST_NUM, BROADCAST_ADDR, ResponseHandler, publishingThread, OUR_APP_VERSION, protocols
|
||||||
|
|
||||||
class MeshInterface:
|
class MeshInterface:
|
||||||
@@ -47,12 +47,12 @@ class MeshInterface:
|
|||||||
self.responseHandlers = {} # A map from request ID to the handler
|
self.responseHandlers = {} # A map from request ID to the handler
|
||||||
self.failure = None # If we've encountered a fatal exception it will be kept here
|
self.failure = None # If we've encountered a fatal exception it will be kept here
|
||||||
self._timeout = Timeout()
|
self._timeout = Timeout()
|
||||||
|
self._acknowledgment = Acknowledgment()
|
||||||
self.heartbeatTimer = None
|
self.heartbeatTimer = None
|
||||||
random.seed() # FIXME, we should not clobber the random seedval here, instead tell user they must call it
|
random.seed() # FIXME, we should not clobber the random seedval here, instead tell user they must call it
|
||||||
self.currentPacketId = random.randint(0, 0xffffffff)
|
self.currentPacketId = random.randint(0, 0xffffffff)
|
||||||
self.nodesByNum = None
|
self.nodesByNum = None
|
||||||
self.configId = None
|
self.configId = None
|
||||||
self.defaultHopLimit = 3
|
|
||||||
self.gotResponse = False # used in gpio read
|
self.gotResponse = False # used in gpio read
|
||||||
self.mask = None # used in gpio read and gpio watch
|
self.mask = None # used in gpio read and gpio watch
|
||||||
|
|
||||||
@@ -157,23 +157,24 @@ class MeshInterface:
|
|||||||
return table
|
return table
|
||||||
|
|
||||||
|
|
||||||
def getNode(self, nodeId):
|
def getNode(self, nodeId, requestConfig=True):
|
||||||
"""Return a node object which contains device settings and channel info"""
|
"""Return a node object which contains device settings and channel info"""
|
||||||
if nodeId in (LOCAL_ADDR, BROADCAST_ADDR):
|
if nodeId in (LOCAL_ADDR, BROADCAST_ADDR):
|
||||||
return self.localNode
|
return self.localNode
|
||||||
else:
|
else:
|
||||||
n = meshtastic.node.Node(self, nodeId)
|
n = meshtastic.node.Node(self, nodeId)
|
||||||
logging.debug("About to requestConfig")
|
# Only request device settings and channel info when necessary
|
||||||
n.requestConfig()
|
if requestConfig:
|
||||||
if not n.waitForConfig():
|
logging.debug("About to requestConfig")
|
||||||
our_exit("Error: Timed out waiting for node config")
|
n.requestConfig()
|
||||||
|
if not n.waitForConfig():
|
||||||
|
our_exit("Error: Timed out waiting for node config")
|
||||||
return n
|
return n
|
||||||
|
|
||||||
def sendText(self, text: AnyStr,
|
def sendText(self, text: AnyStr,
|
||||||
destinationId=BROADCAST_ADDR,
|
destinationId=BROADCAST_ADDR,
|
||||||
wantAck=False,
|
wantAck=False,
|
||||||
wantResponse=False,
|
wantResponse=False,
|
||||||
hopLimit=None,
|
|
||||||
onResponse=None,
|
onResponse=None,
|
||||||
channelIndex=0):
|
channelIndex=0):
|
||||||
"""Send a utf8 string to some other node, if the node has a display it
|
"""Send a utf8 string to some other node, if the node has a display it
|
||||||
@@ -195,21 +196,17 @@ class MeshInterface:
|
|||||||
Returns the sent packet. The id field will be populated in this packet
|
Returns the sent packet. The id field will be populated in this packet
|
||||||
and can be used to track future message acks/naks.
|
and can be used to track future message acks/naks.
|
||||||
"""
|
"""
|
||||||
if hopLimit is None:
|
|
||||||
hopLimit = self.defaultHopLimit
|
|
||||||
|
|
||||||
return self.sendData(text.encode("utf-8"), destinationId,
|
return self.sendData(text.encode("utf-8"), destinationId,
|
||||||
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
|
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
|
||||||
wantAck=wantAck,
|
wantAck=wantAck,
|
||||||
wantResponse=wantResponse,
|
wantResponse=wantResponse,
|
||||||
hopLimit=hopLimit,
|
|
||||||
onResponse=onResponse,
|
onResponse=onResponse,
|
||||||
channelIndex=channelIndex)
|
channelIndex=channelIndex)
|
||||||
|
|
||||||
def sendData(self, data, destinationId=BROADCAST_ADDR,
|
def sendData(self, data, destinationId=BROADCAST_ADDR,
|
||||||
portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
|
portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
|
||||||
wantResponse=False,
|
wantResponse=False,
|
||||||
hopLimit=None,
|
|
||||||
onResponse=None,
|
onResponse=None,
|
||||||
channelIndex=0):
|
channelIndex=0):
|
||||||
"""Send a data packet to some other node
|
"""Send a data packet to some other node
|
||||||
@@ -234,8 +231,6 @@ class MeshInterface:
|
|||||||
Returns the sent packet. The id field will be populated in this packet
|
Returns the sent packet. The id field will be populated in this packet
|
||||||
and can be used to track future message acks/naks.
|
and can be used to track future message acks/naks.
|
||||||
"""
|
"""
|
||||||
if hopLimit is None:
|
|
||||||
hopLimit = self.defaultHopLimit
|
|
||||||
|
|
||||||
if getattr(data, "SerializeToString", None):
|
if getattr(data, "SerializeToString", None):
|
||||||
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
||||||
@@ -258,8 +253,7 @@ class MeshInterface:
|
|||||||
|
|
||||||
if onResponse is not None:
|
if onResponse is not None:
|
||||||
self._addResponseHandler(meshPacket.id, onResponse)
|
self._addResponseHandler(meshPacket.id, onResponse)
|
||||||
p = self._sendPacket(meshPacket, destinationId,
|
p = self._sendPacket(meshPacket, destinationId, wantAck=wantAck)
|
||||||
wantAck=wantAck, hopLimit=hopLimit)
|
|
||||||
return p
|
return p
|
||||||
|
|
||||||
def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
|
def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
|
||||||
@@ -297,21 +291,42 @@ class MeshInterface:
|
|||||||
portNum=portnums_pb2.PortNum.POSITION_APP,
|
portNum=portnums_pb2.PortNum.POSITION_APP,
|
||||||
wantAck=wantAck,
|
wantAck=wantAck,
|
||||||
wantResponse=wantResponse)
|
wantResponse=wantResponse)
|
||||||
|
|
||||||
|
def sendTraceRoute(self, dest, hopLimit):
|
||||||
|
r = mesh_pb2.RouteDiscovery()
|
||||||
|
self.sendData(r, destinationId=dest, portNum=portnums_pb2.PortNum.TRACEROUTE_APP,
|
||||||
|
wantResponse=True, onResponse=self.onResponseTraceRoute)
|
||||||
|
# extend timeout based on number of nodes, limit by configured hopLimit
|
||||||
|
waitFactor = min(len(self.nodes)-1, hopLimit)
|
||||||
|
self.waitForTraceRoute(waitFactor)
|
||||||
|
|
||||||
|
def onResponseTraceRoute(self, p):
|
||||||
|
routeDiscovery = mesh_pb2.RouteDiscovery()
|
||||||
|
routeDiscovery.ParseFromString(p["decoded"]["payload"])
|
||||||
|
asDict = google.protobuf.json_format.MessageToDict(routeDiscovery)
|
||||||
|
|
||||||
|
print("Route traced:")
|
||||||
|
routeStr = self._nodeNumToId(p["to"])
|
||||||
|
if "route" in asDict:
|
||||||
|
for nodeNum in asDict["route"]:
|
||||||
|
routeStr += " --> " + self._nodeNumToId(nodeNum)
|
||||||
|
routeStr += " --> " + self._nodeNumToId(p["from"])
|
||||||
|
print(routeStr)
|
||||||
|
|
||||||
|
self._acknowledgment.receivedTraceRoute = True
|
||||||
|
|
||||||
def _addResponseHandler(self, requestId, callback):
|
def _addResponseHandler(self, requestId, callback):
|
||||||
self.responseHandlers[requestId] = ResponseHandler(callback)
|
self.responseHandlers[requestId] = ResponseHandler(callback)
|
||||||
|
|
||||||
def _sendPacket(self, meshPacket,
|
def _sendPacket(self, meshPacket,
|
||||||
destinationId=BROADCAST_ADDR,
|
destinationId=BROADCAST_ADDR,
|
||||||
wantAck=False, hopLimit=None):
|
wantAck=False):
|
||||||
"""Send a MeshPacket to the specified node (or if unspecified, broadcast).
|
"""Send a MeshPacket to the specified node (or if unspecified, broadcast).
|
||||||
You probably don't want this - use sendData instead.
|
You probably don't want this - use sendData instead.
|
||||||
|
|
||||||
Returns the sent packet. The id field will be populated in this packet and
|
Returns the sent packet. The id field will be populated in this packet and
|
||||||
can be used to track future message acks/naks.
|
can be used to track future message acks/naks.
|
||||||
"""
|
"""
|
||||||
if hopLimit is None:
|
|
||||||
hopLimit = self.defaultHopLimit
|
|
||||||
|
|
||||||
# We allow users to talk to the local node before we've completed the full connection flow...
|
# We allow users to talk to the local node before we've completed the full connection flow...
|
||||||
if(self.myInfo is not None and destinationId != self.myInfo.my_node_num):
|
if(self.myInfo is not None and destinationId != self.myInfo.my_node_num):
|
||||||
@@ -345,6 +360,8 @@ class MeshInterface:
|
|||||||
|
|
||||||
meshPacket.to = nodeNum
|
meshPacket.to = nodeNum
|
||||||
meshPacket.want_ack = wantAck
|
meshPacket.want_ack = wantAck
|
||||||
|
loraConfig = getattr(self.localNode.localConfig, 'lora')
|
||||||
|
hopLimit = getattr(loraConfig, 'hop_limit')
|
||||||
meshPacket.hop_limit = hopLimit
|
meshPacket.hop_limit = hopLimit
|
||||||
|
|
||||||
# if the user hasn't set an ID for this packet (likely and recommended),
|
# if the user hasn't set an ID for this packet (likely and recommended),
|
||||||
@@ -366,6 +383,16 @@ class MeshInterface:
|
|||||||
if not success:
|
if not success:
|
||||||
raise Exception("Timed out waiting for interface config")
|
raise Exception("Timed out waiting for interface config")
|
||||||
|
|
||||||
|
def waitForAckNak(self):
|
||||||
|
success = self._timeout.waitForAckNak(self._acknowledgment)
|
||||||
|
if not success:
|
||||||
|
raise Exception("Timed out waiting for an acknowledgment")
|
||||||
|
|
||||||
|
def waitForTraceRoute(self, waitFactor):
|
||||||
|
success = self._timeout.waitForTraceRoute(waitFactor, self._acknowledgment)
|
||||||
|
if not success:
|
||||||
|
raise Exception("Timed out waiting for traceroute")
|
||||||
|
|
||||||
def getMyNodeInfo(self):
|
def getMyNodeInfo(self):
|
||||||
"""Get info about my node."""
|
"""Get info about my node."""
|
||||||
if self.myInfo is None:
|
if self.myInfo is None:
|
||||||
@@ -532,27 +559,46 @@ class MeshInterface:
|
|||||||
# stream API fromRadio.config_complete_id
|
# stream API fromRadio.config_complete_id
|
||||||
logging.debug(f"Config complete ID {self.configId}")
|
logging.debug(f"Config complete ID {self.configId}")
|
||||||
self._handleConfigComplete()
|
self._handleConfigComplete()
|
||||||
|
|
||||||
elif fromRadio.HasField("packet"):
|
elif fromRadio.HasField("packet"):
|
||||||
self._handlePacketFromRadio(fromRadio.packet)
|
self._handlePacketFromRadio(fromRadio.packet)
|
||||||
|
|
||||||
elif fromRadio.rebooted:
|
elif fromRadio.rebooted:
|
||||||
# Tell clients the device went away. Careful not to call the overridden
|
# Tell clients the device went away. Careful not to call the overridden
|
||||||
# subclass version that closes the serial port
|
# subclass version that closes the serial port
|
||||||
MeshInterface._disconnected(self)
|
MeshInterface._disconnected(self)
|
||||||
|
|
||||||
self._startConfig() # redownload the node db etc...
|
self._startConfig() # redownload the node db etc...
|
||||||
elif fromRadio.config:
|
|
||||||
|
elif fromRadio.config or fromRadio.moduleConfig:
|
||||||
if fromRadio.config.HasField("device"):
|
if fromRadio.config.HasField("device"):
|
||||||
self.localNode.localConfig.device.CopyFrom(fromRadio.config.device)
|
self.localNode.localConfig.device.CopyFrom(fromRadio.config.device)
|
||||||
elif fromRadio.config.HasField("position"):
|
elif fromRadio.config.HasField("position"):
|
||||||
self.localNode.localConfig.position.CopyFrom(fromRadio.config.position)
|
self.localNode.localConfig.position.CopyFrom(fromRadio.config.position)
|
||||||
elif fromRadio.config.HasField("power"):
|
elif fromRadio.config.HasField("power"):
|
||||||
self.localNode.localConfig.power.CopyFrom(fromRadio.config.power)
|
self.localNode.localConfig.power.CopyFrom(fromRadio.config.power)
|
||||||
elif fromRadio.config.HasField("wifi"):
|
elif fromRadio.config.HasField("network"):
|
||||||
self.localNode.localConfig.wifi.CopyFrom(fromRadio.config.wifi)
|
self.localNode.localConfig.network.CopyFrom(fromRadio.config.network)
|
||||||
elif fromRadio.config.HasField("display"):
|
elif fromRadio.config.HasField("display"):
|
||||||
self.localNode.localConfig.display.CopyFrom(fromRadio.config.display)
|
self.localNode.localConfig.display.CopyFrom(fromRadio.config.display)
|
||||||
elif fromRadio.config.HasField("lora"):
|
elif fromRadio.config.HasField("lora"):
|
||||||
self.localNode.localConfig.lora.CopyFrom(fromRadio.config.lora)
|
self.localNode.localConfig.lora.CopyFrom(fromRadio.config.lora)
|
||||||
|
elif fromRadio.config.HasField("bluetooth"):
|
||||||
|
self.localNode.localConfig.bluetooth.CopyFrom(fromRadio.config.bluetooth)
|
||||||
|
|
||||||
|
elif fromRadio.moduleConfig.HasField("mqtt"):
|
||||||
|
self.localNode.moduleConfig.mqtt.CopyFrom(fromRadio.moduleConfig.mqtt)
|
||||||
|
elif fromRadio.moduleConfig.HasField("serial"):
|
||||||
|
self.localNode.moduleConfig.serial.CopyFrom(fromRadio.moduleConfig.serial)
|
||||||
|
elif fromRadio.moduleConfig.HasField("external_notification"):
|
||||||
|
self.localNode.moduleConfig.external_notification.CopyFrom(fromRadio.moduleConfig.external_notification)
|
||||||
|
elif fromRadio.moduleConfig.HasField("range_test"):
|
||||||
|
self.localNode.moduleConfig.range_test.CopyFrom(fromRadio.moduleConfig.range_test)
|
||||||
|
elif fromRadio.moduleConfig.HasField("telemetry"):
|
||||||
|
self.localNode.moduleConfig.telemetry.CopyFrom(fromRadio.moduleConfig.telemetry)
|
||||||
|
elif fromRadio.moduleConfig.HasField("canned_message"):
|
||||||
|
self.localNode.moduleConfig.canned_message.CopyFrom(fromRadio.moduleConfig.canned_message)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.debug("Unexpected FromRadio payload")
|
logging.debug("Unexpected FromRadio payload")
|
||||||
|
|
||||||
@@ -656,7 +702,7 @@ class MeshInterface:
|
|||||||
# UNKNOWN_APP is the default protobuf portnum value, and therefore if not
|
# 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
|
# set it will not be populated at all to make API usage easier, set
|
||||||
# it to prevent confusion
|
# it to prevent confusion
|
||||||
if "portnum" not in decoded:
|
if decoded and "portnum" not in decoded:
|
||||||
new_portnum = portnums_pb2.PortNum.Name(portnums_pb2.PortNum.UNKNOWN_APP)
|
new_portnum = portnums_pb2.PortNum.Name(portnums_pb2.PortNum.UNKNOWN_APP)
|
||||||
decoded["portnum"] = new_portnum
|
decoded["portnum"] = new_portnum
|
||||||
logging.warning(f"portnum was not in decoded. Setting to:{new_portnum}")
|
logging.warning(f"portnum was not in decoded. Setting to:{new_portnum}")
|
||||||
@@ -698,7 +744,8 @@ class MeshInterface:
|
|||||||
# we keep the responseHandler in dict until we get a non ack
|
# we keep the responseHandler in dict until we get a non ack
|
||||||
handler = self.responseHandlers.pop(requestId, None)
|
handler = self.responseHandlers.pop(requestId, None)
|
||||||
if handler is not None:
|
if handler is not None:
|
||||||
handler.callback(asDict)
|
if not isAck or (isAck and handler.__name__ == "onAckNak"):
|
||||||
|
handler.callback(asDict)
|
||||||
|
|
||||||
logging.debug(f"Publishing {topic}: packet={stripnl(asDict)} ")
|
logging.debug(f"Publishing {topic}: packet={stripnl(asDict)} ")
|
||||||
publishingThread.queueWork(lambda: pub.sendMessage(
|
publishingThread.queueWork(lambda: pub.sendMessage(
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -15,7 +15,7 @@ _sym_db = _symbol_database.Default()
|
|||||||
from . import mesh_pb2 as mesh__pb2
|
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_pool.Default().AddSerializedFile(b'\n\nmqtt.proto\x1a\nmesh.proto\"V\n\x0fServiceEnvelope\x12\x1b\n\x06packet\x18\x01 \x01(\x0b\x32\x0b.MeshPacket\x12\x12\n\nchannel_id\x18\x02 \x01(\t\x12\x12\n\ngateway_id\x18\x03 \x01(\tBG\n\x13\x63om.geeksville.meshB\nMQTTProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ _sym_db.RegisterMessage(ServiceEnvelope)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nMQTTProtosH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nMQTTProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_SERVICEENVELOPE._serialized_start=26
|
_SERVICEENVELOPE._serialized_start=26
|
||||||
_SERVICEENVELOPE._serialized_end=112
|
_SERVICEENVELOPE._serialized_end=112
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from meshtastic.util import pskToString, stripnl, Timeout, our_exit, fromPSK
|
|||||||
class Node:
|
class Node:
|
||||||
"""A model of a (local or remote) node in the mesh
|
"""A model of a (local or remote) node in the mesh
|
||||||
|
|
||||||
Includes methods for localConfig and channels
|
Includes methods for localConfig, moduleConfig and channels
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, iface, nodeNum, noProto=False):
|
def __init__(self, iface, nodeNum, noProto=False):
|
||||||
@@ -20,17 +20,14 @@ class Node:
|
|||||||
self.iface = iface
|
self.iface = iface
|
||||||
self.nodeNum = nodeNum
|
self.nodeNum = nodeNum
|
||||||
self.localConfig = localonly_pb2.LocalConfig()
|
self.localConfig = localonly_pb2.LocalConfig()
|
||||||
|
self.moduleConfig = localonly_pb2.LocalModuleConfig()
|
||||||
self.channels = None
|
self.channels = None
|
||||||
self._timeout = Timeout(maxSecs=300)
|
self._timeout = Timeout(maxSecs=300)
|
||||||
self.partialChannels = None
|
self.partialChannels = None
|
||||||
self.noProto = noProto
|
self.noProto = noProto
|
||||||
|
|
||||||
self.cannedPluginMessage = None
|
self.cannedPluginMessage = None
|
||||||
|
|
||||||
self.cannedPluginMessagePart1 = None
|
self.cannedPluginMessageMessages = None
|
||||||
self.cannedPluginMessagePart2 = None
|
|
||||||
self.cannedPluginMessagePart3 = None
|
|
||||||
self.cannedPluginMessagePart4 = None
|
|
||||||
|
|
||||||
self.gotResponse = None
|
self.gotResponse = None
|
||||||
|
|
||||||
@@ -57,6 +54,10 @@ class Node:
|
|||||||
if self.localConfig:
|
if self.localConfig:
|
||||||
prefs = stripnl(MessageToJson(self.localConfig))
|
prefs = stripnl(MessageToJson(self.localConfig))
|
||||||
print(f"Preferences: {prefs}\n")
|
print(f"Preferences: {prefs}\n")
|
||||||
|
prefs = ""
|
||||||
|
if self.moduleConfig:
|
||||||
|
prefs = stripnl(MessageToJson(self.moduleConfig))
|
||||||
|
print(f"Module preferences: {prefs}\n")
|
||||||
self.showChannels()
|
self.showChannels()
|
||||||
|
|
||||||
def requestConfig(self):
|
def requestConfig(self):
|
||||||
@@ -87,43 +88,154 @@ class Node:
|
|||||||
p.set_config.device.CopyFrom(self.localConfig.device)
|
p.set_config.device.CopyFrom(self.localConfig.device)
|
||||||
self._sendAdmin(p)
|
self._sendAdmin(p)
|
||||||
logging.debug("Wrote device")
|
logging.debug("Wrote device")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
if self.localConfig.position:
|
if self.localConfig.position:
|
||||||
p = admin_pb2.AdminMessage()
|
p = admin_pb2.AdminMessage()
|
||||||
p.set_config.position.CopyFrom(self.localConfig.position)
|
p.set_config.position.CopyFrom(self.localConfig.position)
|
||||||
self._sendAdmin(p)
|
self._sendAdmin(p)
|
||||||
logging.debug("Wrote position")
|
logging.debug("Wrote position")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
if self.localConfig.power:
|
if self.localConfig.power:
|
||||||
p = admin_pb2.AdminMessage()
|
p = admin_pb2.AdminMessage()
|
||||||
p.set_config.power.CopyFrom(self.localConfig.power)
|
p.set_config.power.CopyFrom(self.localConfig.power)
|
||||||
self._sendAdmin(p)
|
self._sendAdmin(p)
|
||||||
logging.debug("Wrote power")
|
logging.debug("Wrote power")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
if self.localConfig.wifi:
|
if self.localConfig.network:
|
||||||
p = admin_pb2.AdminMessage()
|
p = admin_pb2.AdminMessage()
|
||||||
p.set_config.wifi.CopyFrom(self.localConfig.wifi)
|
p.set_config.network.CopyFrom(self.localConfig.network)
|
||||||
self._sendAdmin(p)
|
self._sendAdmin(p)
|
||||||
logging.debug("Wrote wifi")
|
logging.debug("Wrote network")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
if self.localConfig.display:
|
if self.localConfig.display:
|
||||||
p = admin_pb2.AdminMessage()
|
p = admin_pb2.AdminMessage()
|
||||||
p.set_config.display.CopyFrom(self.localConfig.display)
|
p.set_config.display.CopyFrom(self.localConfig.display)
|
||||||
self._sendAdmin(p)
|
self._sendAdmin(p)
|
||||||
logging.debug("Wrote display")
|
logging.debug("Wrote display")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
if self.localConfig.lora:
|
if self.localConfig.lora:
|
||||||
p = admin_pb2.AdminMessage()
|
p = admin_pb2.AdminMessage()
|
||||||
p.set_config.lora.CopyFrom(self.localConfig.lora)
|
p.set_config.lora.CopyFrom(self.localConfig.lora)
|
||||||
self._sendAdmin(p)
|
self._sendAdmin(p)
|
||||||
logging.debug("Wrote lora")
|
logging.debug("Wrote lora")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.localConfig.bluetooth:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_config.bluetooth.CopyFrom(self.localConfig.bluetooth)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote bluetooth")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.moduleConfig.mqtt:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_module_config.mqtt.CopyFrom(self.moduleConfig.mqtt)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote module: mqtt")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.moduleConfig.serial:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_module_config.serial.CopyFrom(self.moduleConfig.serial)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote module: serial")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.moduleConfig.external_notification:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_module_config.external_notification.CopyFrom(self.moduleConfig.external_notification)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote module: external_notification")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.moduleConfig.store_forward:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_module_config.store_forward.CopyFrom(self.moduleConfig.store_forward)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote module: store_forward")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.moduleConfig.range_test:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_module_config.range_test.CopyFrom(self.moduleConfig.range_test)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote module: range_test")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.moduleConfig.telemetry:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_module_config.telemetry.CopyFrom(self.moduleConfig.telemetry)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote module: telemetry")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.moduleConfig.canned_message:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_module_config.canned_message.CopyFrom(self.moduleConfig.canned_message)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote module: canned_message")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if self.moduleConfig.audio:
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_module_config.audio.CopyFrom(self.moduleConfig.audio)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
logging.debug("Wrote module: audo")
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
def writeConfig(self, config_name):
|
||||||
|
"""Write the current (edited) localConfig to the device"""
|
||||||
|
if self.localConfig is None:
|
||||||
|
our_exit("Error: No localConfig has been read")
|
||||||
|
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
|
||||||
|
if config_name == 'device':
|
||||||
|
p.set_config.device.CopyFrom(self.localConfig.device)
|
||||||
|
elif config_name == 'position':
|
||||||
|
p.set_config.position.CopyFrom(self.localConfig.position)
|
||||||
|
elif config_name == 'power':
|
||||||
|
p.set_config.power.CopyFrom(self.localConfig.power)
|
||||||
|
elif config_name == 'network':
|
||||||
|
p.set_config.network.CopyFrom(self.localConfig.network)
|
||||||
|
elif config_name == 'display':
|
||||||
|
p.set_config.display.CopyFrom(self.localConfig.display)
|
||||||
|
elif config_name == 'lora':
|
||||||
|
p.set_config.lora.CopyFrom(self.localConfig.lora)
|
||||||
|
elif config_name == 'bluetooth':
|
||||||
|
p.set_config.bluetooth.CopyFrom(self.localConfig.bluetooth)
|
||||||
|
elif config_name == 'mqtt':
|
||||||
|
p.set_module_config.mqtt.CopyFrom(self.moduleConfig.mqtt)
|
||||||
|
elif config_name == 'serial':
|
||||||
|
p.set_module_config.serial.CopyFrom(self.moduleConfig.serial)
|
||||||
|
elif config_name == 'external_notification':
|
||||||
|
p.set_module_config.external_notification.CopyFrom(self.moduleConfig.external_notification)
|
||||||
|
elif config_name == 'store_forward':
|
||||||
|
p.set_module_config.store_forward.CopyFrom(self.moduleConfig.store_forward)
|
||||||
|
elif config_name == 'range_test':
|
||||||
|
p.set_module_config.range_test.CopyFrom(self.moduleConfig.range_test)
|
||||||
|
elif config_name == 'telemetry':
|
||||||
|
p.set_module_config.telemetry.CopyFrom(self.moduleConfig.telemetry)
|
||||||
|
elif config_name == 'canned_message':
|
||||||
|
p.set_module_config.canned_message.CopyFrom(self.moduleConfig.canned_message)
|
||||||
|
elif config_name == 'audio':
|
||||||
|
p.set_module_config.audio.CopyFrom(self.moduleConfig.audio)
|
||||||
|
else:
|
||||||
|
our_exit(f"Error: No valid config with name {config_name}")
|
||||||
|
|
||||||
|
logging.debug(f"Wrote: {config_name}")
|
||||||
|
self._sendAdmin(p)
|
||||||
|
|
||||||
def writeChannel(self, channelIndex, adminIndex=0):
|
def writeChannel(self, channelIndex, adminIndex=0):
|
||||||
"""Write the current (edited) channel to the device"""
|
"""Write the current (edited) channel to the device"""
|
||||||
|
|
||||||
p = admin_pb2.AdminMessage()
|
p = admin_pb2.AdminMessage()
|
||||||
p.set_channel.CopyFrom(self.channels[channelIndex])
|
p.set_channel.CopyFrom(self.channels[channelIndex])
|
||||||
|
|
||||||
self._sendAdmin(p, adminIndex=adminIndex)
|
self._sendAdmin(p, adminIndex=adminIndex)
|
||||||
logging.debug(f"Wrote channel {channelIndex}")
|
logging.debug(f"Wrote channel {channelIndex}")
|
||||||
|
|
||||||
@@ -187,38 +299,30 @@ class Node:
|
|||||||
def setOwner(self, long_name=None, short_name=None, is_licensed=False):
|
def setOwner(self, long_name=None, short_name=None, is_licensed=False):
|
||||||
"""Set device owner name"""
|
"""Set device owner name"""
|
||||||
logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
|
logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
|
||||||
nChars = 3
|
|
||||||
minChars = 2
|
|
||||||
if long_name is not None:
|
|
||||||
long_name = long_name.strip()
|
|
||||||
if short_name is None:
|
|
||||||
words = long_name.split()
|
|
||||||
if len(long_name) <= nChars:
|
|
||||||
short_name = long_name
|
|
||||||
elif len(words) >= minChars:
|
|
||||||
short_name = ''.join(map(lambda word: word[0], words))
|
|
||||||
else:
|
|
||||||
trans = str.maketrans(dict.fromkeys('aeiouAEIOU'))
|
|
||||||
short_name = long_name[0] + long_name[1:].translate(trans)
|
|
||||||
if len(short_name) < nChars:
|
|
||||||
short_name = long_name[:nChars]
|
|
||||||
|
|
||||||
p = admin_pb2.AdminMessage()
|
p = admin_pb2.AdminMessage()
|
||||||
|
|
||||||
|
nChars = 4
|
||||||
if long_name is not None:
|
if long_name is not None:
|
||||||
|
long_name = long_name.strip()
|
||||||
p.set_owner.long_name = long_name
|
p.set_owner.long_name = long_name
|
||||||
|
p.set_owner.is_licensed = is_licensed
|
||||||
if short_name is not None:
|
if short_name is not None:
|
||||||
short_name = short_name.strip()
|
short_name = short_name.strip()
|
||||||
if len(short_name) > nChars:
|
if len(short_name) > nChars:
|
||||||
short_name = short_name[:nChars]
|
short_name = short_name[:nChars]
|
||||||
|
print(f"Maximum is 4 characters, truncated to {short_name}")
|
||||||
p.set_owner.short_name = short_name
|
p.set_owner.short_name = short_name
|
||||||
p.set_owner.is_licensed = is_licensed
|
|
||||||
|
|
||||||
# Note: These debug lines are used in unit tests
|
# Note: These debug lines are used in unit tests
|
||||||
logging.debug(f'p.set_owner.long_name:{p.set_owner.long_name}:')
|
logging.debug(f'p.set_owner.long_name:{p.set_owner.long_name}:')
|
||||||
logging.debug(f'p.set_owner.short_name:{p.set_owner.short_name}:')
|
logging.debug(f'p.set_owner.short_name:{p.set_owner.short_name}:')
|
||||||
logging.debug(f'p.set_owner.is_licensed:{p.set_owner.is_licensed}')
|
logging.debug(f'p.set_owner.is_licensed:{p.set_owner.is_licensed}')
|
||||||
return self._sendAdmin(p)
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
def getURL(self, includeAll: bool = True):
|
def getURL(self, includeAll: bool = True):
|
||||||
"""The sharable URL that describes the current channel"""
|
"""The sharable URL that describes the current channel"""
|
||||||
@@ -228,16 +332,19 @@ class Node:
|
|||||||
for c in self.channels:
|
for c in self.channels:
|
||||||
if c.role == channel_pb2.Channel.Role.PRIMARY or (includeAll and c.role == channel_pb2.Channel.Role.SECONDARY):
|
if c.role == channel_pb2.Channel.Role.PRIMARY or (includeAll and c.role == channel_pb2.Channel.Role.SECONDARY):
|
||||||
channelSet.settings.append(c.settings)
|
channelSet.settings.append(c.settings)
|
||||||
|
|
||||||
|
channelSet.lora_config.CopyFrom(self.localConfig.lora)
|
||||||
some_bytes = channelSet.SerializeToString()
|
some_bytes = channelSet.SerializeToString()
|
||||||
s = base64.urlsafe_b64encode(some_bytes).decode('ascii')
|
s = base64.urlsafe_b64encode(some_bytes).decode('ascii')
|
||||||
return f"https://www.meshtastic.org/e/#{s}".replace("=", "")
|
s = s.replace("=", "").replace("+", "-").replace("/", "_")
|
||||||
|
return f"https://meshtastic.org/e/#{s}"
|
||||||
|
|
||||||
def setURL(self, url):
|
def setURL(self, url):
|
||||||
"""Set mesh network URL"""
|
"""Set mesh network URL"""
|
||||||
if self.localConfig is None:
|
if self.localConfig is None:
|
||||||
our_exit("Warning: No Config has been read")
|
our_exit("Warning: No Config has been read")
|
||||||
|
|
||||||
# URLs are of the form https://www.meshtastic.org/d/#{base64_channel_set}
|
# URLs are of the form https://meshtastic.org/d/#{base64_channel_set}
|
||||||
# Split on '/#' to find the base64 encoded channel settings
|
# Split on '/#' to find the base64 encoded channel settings
|
||||||
splitURL = url.split("/#")
|
splitURL = url.split("/#")
|
||||||
b64 = splitURL[-1]
|
b64 = splitURL[-1]
|
||||||
@@ -268,9 +375,13 @@ class Node:
|
|||||||
self.writeChannel(ch.index)
|
self.writeChannel(ch.index)
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
|
||||||
def onResponseRequestCannedMessagePluginMessagePart1(self, p):
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.set_config.lora.CopyFrom(channelSet.lora_config)
|
||||||
|
self._sendAdmin(p)
|
||||||
|
|
||||||
|
def onResponseRequestCannedMessagePluginMessageMessages(self, p):
|
||||||
"""Handle the response packet for requesting canned message plugin message part 1"""
|
"""Handle the response packet for requesting canned message plugin message part 1"""
|
||||||
logging.debug(f'onResponseRequestCannedMessagePluginMessagePart1() p:{p}')
|
logging.debug(f'onResponseRequestCannedMessagePluginMessageMessages() p:{p}')
|
||||||
errorFound = False
|
errorFound = False
|
||||||
if "routing" in p["decoded"]:
|
if "routing" in p["decoded"]:
|
||||||
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||||
@@ -280,57 +391,10 @@ class Node:
|
|||||||
if "decoded" in p:
|
if "decoded" in p:
|
||||||
if "admin" in p["decoded"]:
|
if "admin" in p["decoded"]:
|
||||||
if "raw" in p["decoded"]["admin"]:
|
if "raw" in p["decoded"]["admin"]:
|
||||||
self.cannedPluginMessagePart1 = p["decoded"]["admin"]["raw"].get_canned_message_module_part1_response
|
self.cannedPluginMessageMessages = p["decoded"]["admin"]["raw"].get_canned_message_module_messages_response
|
||||||
logging.debug(f'self.cannedPluginMessagePart1:{self.cannedPluginMessagePart1}')
|
logging.debug(f'self.cannedPluginMessageMessages:{self.cannedPluginMessageMessages}')
|
||||||
self.gotResponse = True
|
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_module_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_module_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_module_part4_response
|
|
||||||
logging.debug(f'self.cannedPluginMessagePart4:{self.cannedPluginMessagePart4}')
|
|
||||||
self.gotResponse = True
|
|
||||||
|
|
||||||
def get_canned_message(self):
|
def get_canned_message(self):
|
||||||
"""Get the canned message string. Concatenate all pieces together and return a single string."""
|
"""Get the canned message string. Concatenate all pieces together and return a single string."""
|
||||||
@@ -338,61 +402,27 @@ class Node:
|
|||||||
if not self.cannedPluginMessage:
|
if not self.cannedPluginMessage:
|
||||||
|
|
||||||
p1 = admin_pb2.AdminMessage()
|
p1 = admin_pb2.AdminMessage()
|
||||||
p1.get_canned_message_module_part1_request = True
|
p1.get_canned_message_module_messages_request = True
|
||||||
self.gotResponse = False
|
self.gotResponse = False
|
||||||
self._sendAdmin(p1, wantResponse=True, onResponse=self.onResponseRequestCannedMessagePluginMessagePart1)
|
self._sendAdmin(p1, wantResponse=True, onResponse=self.onResponseRequestCannedMessagePluginMessageMessages)
|
||||||
while self.gotResponse is False:
|
while self.gotResponse is False:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
p2 = admin_pb2.AdminMessage()
|
logging.debug(f'self.cannedPluginMessageMessages:{self.cannedPluginMessageMessages}')
|
||||||
p2.get_canned_message_module_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_module_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_module_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 = ""
|
self.cannedPluginMessage = ""
|
||||||
if self.cannedPluginMessagePart1:
|
if self.cannedPluginMessageMessages:
|
||||||
self.cannedPluginMessage += self.cannedPluginMessagePart1
|
self.cannedPluginMessage += self.cannedPluginMessageMessages
|
||||||
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}')
|
print(f'canned_plugin_message:{self.cannedPluginMessage}')
|
||||||
logging.debug(f'canned_plugin_message:{self.cannedPluginMessage}')
|
logging.debug(f'canned_plugin_message:{self.cannedPluginMessage}')
|
||||||
return self.cannedPluginMessage
|
return self.cannedPluginMessage
|
||||||
|
|
||||||
def set_canned_message(self, message):
|
def set_canned_message(self, message):
|
||||||
"""Set the canned message. Split into parts of 200 chars each."""
|
"""Set the canned message. The canned messages length must be less than 200 character."""
|
||||||
|
|
||||||
if len(message) > 800:
|
if len(message) > 200:
|
||||||
our_exit("Warning: The canned message must be less than 800 characters.")
|
our_exit("Warning: The canned message must be less than 200 characters.")
|
||||||
|
|
||||||
# split into chunks
|
# split into chunks
|
||||||
chunks = []
|
chunks = []
|
||||||
@@ -407,16 +437,15 @@ class Node:
|
|||||||
|
|
||||||
# TODO: should be a way to improve this
|
# TODO: should be a way to improve this
|
||||||
if i == 0:
|
if i == 0:
|
||||||
p.set_canned_message_module_part1 = chunk
|
p.set_canned_message_module_messages = chunk
|
||||||
elif i == 1:
|
|
||||||
p.set_canned_message_module_part2 = chunk
|
|
||||||
elif i == 2:
|
|
||||||
p.set_canned_message_module_part3 = chunk
|
|
||||||
elif i == 3:
|
|
||||||
p.set_canned_message_module_part4 = chunk
|
|
||||||
|
|
||||||
logging.debug(f"Setting canned message '{chunk}' part {i+1}")
|
logging.debug(f"Setting canned message '{chunk}' part {i+1}")
|
||||||
self._sendAdmin(p)
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
def exitSimulator(self):
|
def exitSimulator(self):
|
||||||
"""Tell a simulator node to exit (this message
|
"""Tell a simulator node to exit (this message
|
||||||
@@ -433,7 +462,51 @@ class Node:
|
|||||||
p.reboot_seconds = secs
|
p.reboot_seconds = secs
|
||||||
logging.info(f"Telling node to reboot in {secs} seconds")
|
logging.info(f"Telling node to reboot in {secs} seconds")
|
||||||
|
|
||||||
return self._sendAdmin(p)
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
|
def beginSettingsTransaction(self):
|
||||||
|
"""Tell the node to open a transaction to edit settings."""
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.begin_edit_settings = True
|
||||||
|
logging.info(f"Telling open a transaction to edit settings")
|
||||||
|
|
||||||
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
|
def commitSettingsTransaction(self):
|
||||||
|
"""Tell the node to commit the open transaction for editing settings."""
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.commit_edit_settings = True
|
||||||
|
logging.info(f"Telling node to commit open transaction for editing settings")
|
||||||
|
|
||||||
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
|
def rebootOTA(self, secs: int = 10):
|
||||||
|
"""Tell the node to reboot into factory firmware."""
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.reboot_ota_seconds = secs
|
||||||
|
logging.info(f"Telling node to reboot to OTA in {secs} seconds")
|
||||||
|
|
||||||
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
def shutdown(self, secs: int = 10):
|
def shutdown(self, secs: int = 10):
|
||||||
"""Tell the node to shutdown."""
|
"""Tell the node to shutdown."""
|
||||||
@@ -441,7 +514,46 @@ class Node:
|
|||||||
p.shutdown_seconds = secs
|
p.shutdown_seconds = secs
|
||||||
logging.info(f"Telling node to shutdown in {secs} seconds")
|
logging.info(f"Telling node to shutdown in {secs} seconds")
|
||||||
|
|
||||||
return self._sendAdmin(p)
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
|
def getMetadata(self, secs: int = 10):
|
||||||
|
"""Tell the node to shutdown."""
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.get_device_metadata_request = True
|
||||||
|
logging.info(f"Requesting device metadata")
|
||||||
|
|
||||||
|
return self._sendAdmin(p, wantResponse=True, onResponse=self.onRequestGetMetadata)
|
||||||
|
|
||||||
|
def factoryReset(self):
|
||||||
|
"""Tell the node to factory reset."""
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.factory_reset = True
|
||||||
|
logging.info(f"Telling node to factory reset")
|
||||||
|
|
||||||
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
|
def resetNodeDb(self):
|
||||||
|
"""Tell the node to reset its list of nodes."""
|
||||||
|
p = admin_pb2.AdminMessage()
|
||||||
|
p.nodedb_reset = True
|
||||||
|
logging.info(f"Telling node to reset the NodeDB")
|
||||||
|
|
||||||
|
# If sending to a remote node, wait for ACK/NAK
|
||||||
|
if self == self.iface.localNode:
|
||||||
|
onResponse = None
|
||||||
|
else:
|
||||||
|
onResponse = self.onAckNak
|
||||||
|
return self._sendAdmin(p, onResponse=onResponse)
|
||||||
|
|
||||||
def _fixupChannels(self):
|
def _fixupChannels(self):
|
||||||
"""Fixup indexes and add disabled channels as needed"""
|
"""Fixup indexes and add disabled channels as needed"""
|
||||||
@@ -466,9 +578,41 @@ class Node:
|
|||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
|
|
||||||
|
def onRequestGetMetadata(self, p):
|
||||||
|
"""Handle the response packet for requesting device metadata getMetadata()"""
|
||||||
|
logging.debug(f'onRequestGetMetadata() p:{p}')
|
||||||
|
|
||||||
|
if p["decoded"]["portnum"] == portnums_pb2.PortNum.Name(portnums_pb2.PortNum.ROUTING_APP):
|
||||||
|
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||||
|
logging.warning(f'Metadata request failed, error reason: {p["decoded"]["routing"]["errorReason"]}')
|
||||||
|
self._timeout.expireTime = time.time() # Do not wait any longer
|
||||||
|
return # Don't try to parse this routing message
|
||||||
|
logging.debug(f"Retrying metadata request.")
|
||||||
|
self.getMetadata()
|
||||||
|
return
|
||||||
|
|
||||||
|
c = p["decoded"]["admin"]["raw"].get_device_metadata_response
|
||||||
|
self._timeout.reset() # We made foreward progress
|
||||||
|
logging.debug(f"Received metadata {stripnl(c)}")
|
||||||
|
print(f"\nfirmware_version: {c.firmware_version}")
|
||||||
|
print(f"device_state_version: {c.device_state_version}")
|
||||||
|
|
||||||
def onResponseRequestChannel(self, p):
|
def onResponseRequestChannel(self, p):
|
||||||
"""Handle the response packet for requesting a channel _requestChannel()"""
|
"""Handle the response packet for requesting a channel _requestChannel()"""
|
||||||
logging.debug(f'onResponseRequestChannel() p:{p}')
|
logging.debug(f'onResponseRequestChannel() p:{p}')
|
||||||
|
|
||||||
|
if p["decoded"]["portnum"] == portnums_pb2.PortNum.Name(portnums_pb2.PortNum.ROUTING_APP):
|
||||||
|
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||||
|
logging.warning(f'Channel request failed, error reason: {p["decoded"]["routing"]["errorReason"]}')
|
||||||
|
self._timeout.expireTime = time.time() # Do not wait any longer
|
||||||
|
return # Don't try to parse this routing message
|
||||||
|
lastTried = 0
|
||||||
|
if len(self.partialChannels) > 0:
|
||||||
|
lastTried = self.partialChannels[-1].index
|
||||||
|
logging.debug(f"Retrying previous channel request.")
|
||||||
|
self._requestChannel(lastTried)
|
||||||
|
return
|
||||||
|
|
||||||
c = p["decoded"]["admin"]["raw"].get_channel_response
|
c = p["decoded"]["admin"]["raw"].get_channel_response
|
||||||
self.partialChannels.append(c)
|
self.partialChannels.append(c)
|
||||||
self._timeout.reset() # We made foreward progress
|
self._timeout.reset() # We made foreward progress
|
||||||
@@ -493,6 +637,18 @@ class Node:
|
|||||||
else:
|
else:
|
||||||
self._requestChannel(index + 1)
|
self._requestChannel(index + 1)
|
||||||
|
|
||||||
|
def onAckNak(self, p):
|
||||||
|
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||||
|
print(f'Received a NAK, error reason: {p["decoded"]["routing"]["errorReason"]}')
|
||||||
|
self.iface._acknowledgment.receivedNak = True
|
||||||
|
else:
|
||||||
|
if int(p["from"]) == self.iface.localNode.nodeNum:
|
||||||
|
print(f'Received an implicit ACK. Packet will likely arrive, but cannot be guaranteed.')
|
||||||
|
self.iface._acknowledgment.receivedImplAck = True
|
||||||
|
else:
|
||||||
|
print(f'Received an ACK.')
|
||||||
|
self.iface._acknowledgment.receivedAck = True
|
||||||
|
|
||||||
def _requestChannel(self, channelNum: int):
|
def _requestChannel(self, channelNum: int):
|
||||||
"""Done with initial config messages, now send regular
|
"""Done with initial config messages, now send regular
|
||||||
MeshPackets to ask for settings"""
|
MeshPackets to ask for settings"""
|
||||||
@@ -510,7 +666,7 @@ class Node:
|
|||||||
|
|
||||||
|
|
||||||
# pylint: disable=R1710
|
# pylint: disable=R1710
|
||||||
def _sendAdmin(self, p: admin_pb2.AdminMessage, wantResponse=False,
|
def _sendAdmin(self, p: admin_pb2.AdminMessage, wantResponse=True,
|
||||||
onResponse=None, adminIndex=0):
|
onResponse=None, adminIndex=0):
|
||||||
"""Send an admin message to the specified node (or the local node if destNodeNum is zero)"""
|
"""Send an admin message to the specified node (or the local node if destNodeNum is zero)"""
|
||||||
|
|
||||||
@@ -520,10 +676,10 @@ class Node:
|
|||||||
if adminIndex == 0: # unless a special channel index was used, we want to use the admin index
|
if adminIndex == 0: # unless a special channel index was used, we want to use the admin index
|
||||||
adminIndex = self.iface.localNode._getAdminChannelIndex()
|
adminIndex = self.iface.localNode._getAdminChannelIndex()
|
||||||
logging.debug(f'adminIndex:{adminIndex}')
|
logging.debug(f'adminIndex:{adminIndex}')
|
||||||
|
|
||||||
return self.iface.sendData(p, self.nodeNum,
|
return self.iface.sendData(p, self.nodeNum,
|
||||||
portNum=portnums_pb2.PortNum.ADMIN_APP,
|
portNum=portnums_pb2.PortNum.ADMIN_APP,
|
||||||
wantAck=True,
|
wantAck=False,
|
||||||
wantResponse=wantResponse,
|
wantResponse=wantResponse,
|
||||||
onResponse=onResponse,
|
onResponse=onResponse,
|
||||||
channelIndex=adminIndex)
|
channelIndex=adminIndex)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ _sym_db = _symbol_database.Default()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eportnums.proto*\xee\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\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\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_pool.Default().AddSerializedFile(b'\n\x0eportnums.proto*\xa4\x03\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42\x45\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
_PORTNUM = DESCRIPTOR.enum_types_by_name['PortNum']
|
_PORTNUM = DESCRIPTOR.enum_types_by_name['PortNum']
|
||||||
PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM)
|
PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM)
|
||||||
@@ -28,6 +28,7 @@ ROUTING_APP = 5
|
|||||||
ADMIN_APP = 6
|
ADMIN_APP = 6
|
||||||
TEXT_MESSAGE_COMPRESSED_APP = 7
|
TEXT_MESSAGE_COMPRESSED_APP = 7
|
||||||
WAYPOINT_APP = 8
|
WAYPOINT_APP = 8
|
||||||
|
AUDIO_APP = 9
|
||||||
REPLY_APP = 32
|
REPLY_APP = 32
|
||||||
IP_TUNNEL_APP = 33
|
IP_TUNNEL_APP = 33
|
||||||
SERIAL_APP = 64
|
SERIAL_APP = 64
|
||||||
@@ -35,6 +36,8 @@ STORE_FORWARD_APP = 65
|
|||||||
RANGE_TEST_APP = 66
|
RANGE_TEST_APP = 66
|
||||||
TELEMETRY_APP = 67
|
TELEMETRY_APP = 67
|
||||||
ZPS_APP = 68
|
ZPS_APP = 68
|
||||||
|
SIMULATOR_APP = 69
|
||||||
|
TRACEROUTE_APP = 70
|
||||||
PRIVATE_APP = 256
|
PRIVATE_APP = 256
|
||||||
ATAK_FORWARDER = 257
|
ATAK_FORWARDER = 257
|
||||||
MAX = 511
|
MAX = 511
|
||||||
@@ -43,7 +46,7 @@ MAX = 511
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_PORTNUM._serialized_start=19
|
_PORTNUM._serialized_start=19
|
||||||
_PORTNUM._serialized_end=385
|
_PORTNUM._serialized_end=439
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ _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_pool.Default().AddSerializedFile(b'\n\x15remote_hardware.proto\"\xcb\x01\n\x0fHardwareMessage\x12#\n\x04type\x18\x01 \x01(\x0e\x32\x15.HardwareMessage.Type\x12\x11\n\tgpio_mask\x18\x02 \x01(\x04\x12\x12\n\ngpio_value\x18\x03 \x01(\x04\"l\n\x04Type\x12\t\n\x05UNSET\x10\x00\x12\x0f\n\x0bWRITE_GPIOS\x10\x01\x12\x0f\n\x0bWATCH_GPIOS\x10\x02\x12\x11\n\rGPIOS_CHANGED\x10\x03\x12\x0e\n\nREAD_GPIOS\x10\x04\x12\x14\n\x10READ_GPIOS_REPLY\x10\x05\x42K\n\x13\x63om.geeksville.meshB\x0eRemoteHardwareH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -30,9 +30,9 @@ _sym_db.RegisterMessage(HardwareMessage)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016RemoteHardwareH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016RemoteHardwareH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_HARDWAREMESSAGE._serialized_start=26
|
_HARDWAREMESSAGE._serialized_start=26
|
||||||
_HARDWAREMESSAGE._serialized_end=228
|
_HARDWAREMESSAGE._serialized_end=229
|
||||||
_HARDWAREMESSAGE_TYPE._serialized_start=120
|
_HARDWAREMESSAGE_TYPE._serialized_start=121
|
||||||
_HARDWAREMESSAGE_TYPE._serialized_end=228
|
_HARDWAREMESSAGE_TYPE._serialized_end=229
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ _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_pool.Default().AddSerializedFile(b'\n\x12storeforward.proto\"\x8a\x06\n\x0fStoreAndForward\x12,\n\x02rr\x18\x01 \x01(\x0e\x32 .StoreAndForward.RequestResponse\x12*\n\x05stats\x18\x02 \x01(\x0b\x32\x1b.StoreAndForward.Statistics\x12)\n\x07history\x18\x03 \x01(\x0b\x32\x18.StoreAndForward.History\x12-\n\theartbeat\x18\x04 \x01(\x0b\x32\x1a.StoreAndForward.Heartbeat\x1a\xcd\x01\n\nStatistics\x12\x16\n\x0emessages_total\x18\x01 \x01(\r\x12\x16\n\x0emessages_saved\x18\x02 \x01(\r\x12\x14\n\x0cmessages_max\x18\x03 \x01(\r\x12\x0f\n\x07up_time\x18\x04 \x01(\r\x12\x10\n\x08requests\x18\x05 \x01(\r\x12\x18\n\x10requests_history\x18\x06 \x01(\r\x12\x11\n\theartbeat\x18\x07 \x01(\x08\x12\x12\n\nreturn_max\x18\x08 \x01(\r\x12\x15\n\rreturn_window\x18\t \x01(\r\x1aI\n\x07History\x12\x18\n\x10history_messages\x18\x01 \x01(\r\x12\x0e\n\x06window\x18\x02 \x01(\r\x12\x14\n\x0clast_request\x18\x03 \x01(\r\x1a.\n\tHeartbeat\x12\x0e\n\x06period\x18\x01 \x01(\r\x12\x11\n\tsecondary\x18\x02 \x01(\r\"\xf7\x01\n\x0fRequestResponse\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0cROUTER_ERROR\x10\x01\x12\x14\n\x10ROUTER_HEARTBEAT\x10\x02\x12\x0f\n\x0bROUTER_PING\x10\x03\x12\x0f\n\x0bROUTER_PONG\x10\x04\x12\x0f\n\x0bROUTER_BUSY\x10\x05\x12\x12\n\x0eROUTER_HISTORY\x10\x06\x12\x10\n\x0c\x43LIENT_ERROR\x10\x65\x12\x12\n\x0e\x43LIENT_HISTORY\x10\x66\x12\x10\n\x0c\x43LIENT_STATS\x10g\x12\x0f\n\x0b\x43LIENT_PING\x10h\x12\x0f\n\x0b\x43LIENT_PONG\x10i\x12\x10\n\x0c\x43LIENT_ABORT\x10jBR\n\x13\x63om.geeksville.meshB\x15StoreAndForwardProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ _sym_db.RegisterMessage(StoreAndForward.Heartbeat)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\025StoreAndForwardProtosH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\025StoreAndForwardProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_STOREANDFORWARD._serialized_start=23
|
_STOREANDFORWARD._serialized_start=23
|
||||||
_STOREANDFORWARD._serialized_end=801
|
_STOREANDFORWARD._serialized_end=801
|
||||||
_STOREANDFORWARD_STATISTICS._serialized_start=223
|
_STOREANDFORWARD_STATISTICS._serialized_start=223
|
||||||
|
|||||||
@@ -15,22 +15,22 @@ _sym_db = _symbol_database.Default()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0ftelemetry.proto\"i\n\rDeviceMetrics\x12\x15\n\rbattery_level\x18\x01 \x01(\r\x12\x0f\n\x07voltage\x18\x02 \x01(\x02\x12\x1b\n\x13\x63hannel_utilization\x18\x03 \x01(\x02\x12\x13\n\x0b\x61ir_util_tx\x18\x04 \x01(\x02\"\x9b\x01\n\x12\x45nvironmentMetrics\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\x19\n\x11relative_humidity\x18\x02 \x01(\x02\x12\x1b\n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02\x12\x16\n\x0egas_resistance\x18\x04 \x01(\x02\x12\x0f\n\x07voltage\x18\x05 \x01(\x02\x12\x0f\n\x07\x63urrent\x18\x06 \x01(\x02\"\x82\x01\n\tTelemetry\x12\x0c\n\x04time\x18\x01 \x01(\x07\x12(\n\x0e\x64\x65vice_metrics\x18\x02 \x01(\x0b\x32\x0e.DeviceMetricsH\x00\x12\x32\n\x13\x65nvironment_metrics\x18\x03 \x01(\x0b\x32\x13.EnvironmentMetricsH\x00\x42\t\n\x07variant*\xa2\x01\n\x13TelemetrySensorType\x12\n\n\x06NotSet\x10\x00\x12\t\n\x05\x44HT11\x10\x01\x12\x0b\n\x07\x44S18B20\x10\x02\x12\t\n\x05\x44HT12\x10\x03\x12\t\n\x05\x44HT21\x10\x04\x12\t\n\x05\x44HT22\x10\x05\x12\n\n\x06\x42ME280\x10\x06\x12\n\n\x06\x42ME680\x10\x07\x12\x0b\n\x07MCP9808\x10\x08\x12\t\n\x05SHTC3\x10\t\x12\n\n\x06INA260\x10\n\x12\n\n\x06INA219\x10\x0b\x42K\n\x13\x63om.geeksville.meshB\x0fTelemetryProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0ftelemetry.proto\"i\n\rDeviceMetrics\x12\x15\n\rbattery_level\x18\x01 \x01(\r\x12\x0f\n\x07voltage\x18\x02 \x01(\x02\x12\x1b\n\x13\x63hannel_utilization\x18\x03 \x01(\x02\x12\x13\n\x0b\x61ir_util_tx\x18\x04 \x01(\x02\"\x9b\x01\n\x12\x45nvironmentMetrics\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\x19\n\x11relative_humidity\x18\x02 \x01(\x02\x12\x1b\n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02\x12\x16\n\x0egas_resistance\x18\x04 \x01(\x02\x12\x0f\n\x07voltage\x18\x05 \x01(\x02\x12\x0f\n\x07\x63urrent\x18\x06 \x01(\x02\"\x82\x01\n\tTelemetry\x12\x0c\n\x04time\x18\x01 \x01(\x07\x12(\n\x0e\x64\x65vice_metrics\x18\x02 \x01(\x0b\x32\x0e.DeviceMetricsH\x00\x12\x32\n\x13\x65nvironment_metrics\x18\x03 \x01(\x0b\x32\x13.EnvironmentMetricsH\x00\x42\t\n\x07variant*\xae\x01\n\x13TelemetrySensorType\x12\x10\n\x0cSENSOR_UNSET\x10\x00\x12\n\n\x06\x42ME280\x10\x01\x12\n\n\x06\x42ME680\x10\x02\x12\x0b\n\x07MCP9808\x10\x03\x12\n\n\x06INA260\x10\x04\x12\n\n\x06INA219\x10\x05\x12\n\n\x06\x42MP280\x10\x06\x12\t\n\x05SHTC3\x10\x07\x12\t\n\x05LPS22\x10\x08\x12\x0b\n\x07QMC6310\x10\t\x12\x0b\n\x07QMI8658\x10\n\x12\x0c\n\x08QMC5883L\x10\x0b\x42L\n\x13\x63om.geeksville.meshB\x0fTelemetryProtosH\x03Z\"github.com/meshtastic/go/generatedb\x06proto3')
|
||||||
|
|
||||||
_TELEMETRYSENSORTYPE = DESCRIPTOR.enum_types_by_name['TelemetrySensorType']
|
_TELEMETRYSENSORTYPE = DESCRIPTOR.enum_types_by_name['TelemetrySensorType']
|
||||||
TelemetrySensorType = enum_type_wrapper.EnumTypeWrapper(_TELEMETRYSENSORTYPE)
|
TelemetrySensorType = enum_type_wrapper.EnumTypeWrapper(_TELEMETRYSENSORTYPE)
|
||||||
NotSet = 0
|
SENSOR_UNSET = 0
|
||||||
DHT11 = 1
|
BME280 = 1
|
||||||
DS18B20 = 2
|
BME680 = 2
|
||||||
DHT12 = 3
|
MCP9808 = 3
|
||||||
DHT21 = 4
|
INA260 = 4
|
||||||
DHT22 = 5
|
INA219 = 5
|
||||||
BME280 = 6
|
BMP280 = 6
|
||||||
BME680 = 7
|
SHTC3 = 7
|
||||||
MCP9808 = 8
|
LPS22 = 8
|
||||||
SHTC3 = 9
|
QMC6310 = 9
|
||||||
INA260 = 10
|
QMI8658 = 10
|
||||||
INA219 = 11
|
QMC5883L = 11
|
||||||
|
|
||||||
|
|
||||||
_DEVICEMETRICS = DESCRIPTOR.message_types_by_name['DeviceMetrics']
|
_DEVICEMETRICS = DESCRIPTOR.message_types_by_name['DeviceMetrics']
|
||||||
@@ -60,9 +60,9 @@ _sym_db.RegisterMessage(Telemetry)
|
|||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017TelemetryProtosH\003Z!github.com/meshtastic/gomeshproto'
|
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017TelemetryProtosH\003Z\"github.com/meshtastic/go/generated'
|
||||||
_TELEMETRYSENSORTYPE._serialized_start=418
|
_TELEMETRYSENSORTYPE._serialized_start=418
|
||||||
_TELEMETRYSENSORTYPE._serialized_end=580
|
_TELEMETRYSENSORTYPE._serialized_end=592
|
||||||
_DEVICEMETRICS._serialized_start=19
|
_DEVICEMETRICS._serialized_start=19
|
||||||
_DEVICEMETRICS._serialized_end=124
|
_DEVICEMETRICS._serialized_end=124
|
||||||
_ENVIRONMENTMETRICS._serialized_start=127
|
_ENVIRONMENTMETRICS._serialized_start=127
|
||||||
|
|||||||
@@ -217,24 +217,24 @@ def test_smoke1_set_owner():
|
|||||||
@pytest.mark.smoke1
|
@pytest.mark.smoke1
|
||||||
def test_smoke1_ch_set_modem_config():
|
def test_smoke1_ch_set_modem_config():
|
||||||
"""Test --ch-set modem_config"""
|
"""Test --ch-set modem_config"""
|
||||||
return_value, out = subprocess.getstatusoutput('meshtastic --ch-set modem_config MidFast')
|
return_value, out = subprocess.getstatusoutput('meshtastic --ch-set modem_config MedFast')
|
||||||
assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
|
assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
|
||||||
assert return_value == 1
|
assert return_value == 1
|
||||||
# pause for the radio
|
# pause for the radio
|
||||||
time.sleep(PAUSE_AFTER_COMMAND)
|
time.sleep(PAUSE_AFTER_COMMAND)
|
||||||
return_value, out = subprocess.getstatusoutput('meshtastic --info')
|
return_value, out = subprocess.getstatusoutput('meshtastic --info')
|
||||||
assert not re.search(r'MidFast', out, re.MULTILINE)
|
assert not re.search(r'MedFast', out, re.MULTILINE)
|
||||||
assert return_value == 0
|
assert return_value == 0
|
||||||
# pause for the radio
|
# pause for the radio
|
||||||
time.sleep(PAUSE_AFTER_COMMAND)
|
time.sleep(PAUSE_AFTER_COMMAND)
|
||||||
return_value, out = subprocess.getstatusoutput('meshtastic --ch-set modem_config MidFast --ch-index 0')
|
return_value, out = subprocess.getstatusoutput('meshtastic --ch-set modem_config MedFast --ch-index 0')
|
||||||
assert re.match(r'Connected to radio', out)
|
assert re.match(r'Connected to radio', out)
|
||||||
assert re.search(r'^Set modem_config to MidFast', out, re.MULTILINE)
|
assert re.search(r'^Set modem_config to MedFast', out, re.MULTILINE)
|
||||||
assert return_value == 0
|
assert return_value == 0
|
||||||
# pause for the radio
|
# pause for the radio
|
||||||
time.sleep(PAUSE_AFTER_REBOOT)
|
time.sleep(PAUSE_AFTER_REBOOT)
|
||||||
return_value, out = subprocess.getstatusoutput('meshtastic --info')
|
return_value, out = subprocess.getstatusoutput('meshtastic --info')
|
||||||
assert re.search(r'MidFast', out, re.MULTILINE)
|
assert re.search(r'MedFast', out, re.MULTILINE)
|
||||||
assert return_value == 0
|
assert return_value == 0
|
||||||
|
|
||||||
|
|
||||||
@@ -247,8 +247,8 @@ def test_smoke1_ch_values():
|
|||||||
'--ch-vlongslow': '{ "psk": "AQ==" }',
|
'--ch-vlongslow': '{ "psk": "AQ==" }',
|
||||||
'--ch-longslow': 'LongSlow',
|
'--ch-longslow': 'LongSlow',
|
||||||
'--ch-longfast': 'LongFast',
|
'--ch-longfast': 'LongFast',
|
||||||
'--ch-midslow': 'MidSlow',
|
'--ch-medslow': 'MedSlow',
|
||||||
'--ch-midfast': 'MidFast',
|
'--ch-medfast': 'MedFast',
|
||||||
'--ch-shortslow': 'ShortSlow',
|
'--ch-shortslow': 'ShortSlow',
|
||||||
'--ch-shortfast': 'ShortFast'
|
'--ch-shortfast': 'ShortFast'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,8 +227,8 @@ def test_smokevirt_ch_values():
|
|||||||
exp = {
|
exp = {
|
||||||
'--ch-longslow': 'LongSlow',
|
'--ch-longslow': 'LongSlow',
|
||||||
'--ch-longfast': 'LongFast',
|
'--ch-longfast': 'LongFast',
|
||||||
'--ch-midslow': 'MidSlow',
|
'--ch-medslow': 'MedSlow',
|
||||||
'--ch-midfast': 'MidFast',
|
'--ch-medfast': 'MedFast',
|
||||||
'--ch-shortslow': 'ShortSlow',
|
'--ch-shortslow': 'ShortSlow',
|
||||||
'--ch-shortfast': 'ShortFast'
|
'--ch-shortfast': 'ShortFast'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ def fromStr(valstr):
|
|||||||
elif valstr.startswith('0x'):
|
elif valstr.startswith('0x'):
|
||||||
# if needed convert to string with asBytes.decode('utf-8')
|
# if needed convert to string with asBytes.decode('utf-8')
|
||||||
val = bytes.fromhex(valstr[2:])
|
val = bytes.fromhex(valstr[2:])
|
||||||
|
elif valstr.startswith('base64:'):
|
||||||
|
val = base64.b64decode(valstr[7:])
|
||||||
elif valstr.lower() in {"t", "true", "yes"}:
|
elif valstr.lower() in {"t", "true", "yes"}:
|
||||||
val = True
|
val = True
|
||||||
elif valstr.lower() in {"f", "false", "no"}:
|
elif valstr.lower() in {"f", "false", "no"}:
|
||||||
@@ -157,6 +159,40 @@ class Timeout:
|
|||||||
time.sleep(self.sleepInterval)
|
time.sleep(self.sleepInterval)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def waitForAckNak(self, acknowledgment, attrs=('receivedAck', 'receivedNak', 'receivedImplAck')):
|
||||||
|
"""Block until an ACK or NAK has been received. Returns True if ACK or NAK has been received."""
|
||||||
|
self.reset()
|
||||||
|
while time.time() < self.expireTime:
|
||||||
|
if any(map(lambda a: getattr(acknowledgment, a, None), attrs)):
|
||||||
|
acknowledgment.reset()
|
||||||
|
return True
|
||||||
|
time.sleep(self.sleepInterval)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def waitForTraceRoute(self, waitFactor, acknowledgment, attr='receivedTraceRoute'):
|
||||||
|
"""Block until traceroute response is received. Returns True if traceroute response has been received."""
|
||||||
|
self.expireTimeout *= waitFactor
|
||||||
|
self.reset()
|
||||||
|
while time.time() < self.expireTime:
|
||||||
|
if getattr(acknowledgment, attr, None):
|
||||||
|
acknowledgment.reset()
|
||||||
|
return True
|
||||||
|
time.sleep(self.sleepInterval)
|
||||||
|
return False
|
||||||
|
|
||||||
|
class Acknowledgment:
|
||||||
|
"A class that records which type of acknowledgment was just received, if any."
|
||||||
|
def __init__(self):
|
||||||
|
self.receivedAck = False
|
||||||
|
self.receivedNak = False
|
||||||
|
self.receivedImplAck = False
|
||||||
|
self.receivedTraceRoute = False
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.receivedAck = False
|
||||||
|
self.receivedNak = False
|
||||||
|
self.receivedImplAck = False
|
||||||
|
self.receivedTraceRoute = False
|
||||||
|
|
||||||
class DeferredExecution():
|
class DeferredExecution():
|
||||||
"""A thread that accepts closures to run, and runs them as they are received"""
|
"""A thread that accepts closures to run, and runs them as they are received"""
|
||||||
@@ -194,7 +230,7 @@ def support_info():
|
|||||||
print('')
|
print('')
|
||||||
print('If having issues with meshtastic cli or python library')
|
print('If having issues with meshtastic cli or python library')
|
||||||
print('or wish to make feature requests, visit:')
|
print('or wish to make feature requests, visit:')
|
||||||
print('https://github.com/meshtastic/Meshtastic-python/issues')
|
print('https://github.com/meshtastic/python/issues')
|
||||||
print('When adding an issue, be sure to include the following info:')
|
print('When adding an issue, be sure to include the following info:')
|
||||||
print(f' System: {platform.system()}')
|
print(f' System: {platform.system()}')
|
||||||
print(f' Platform: {platform.platform()}')
|
print(f' Platform: {platform.platform()}')
|
||||||
|
|||||||
1
proto
1
proto
Submodule proto deleted from 274aa01a38
1
protobufs
Submodule
1
protobufs
Submodule
Submodule protobufs added at c4c484d9a3
12
setup.py
12
setup.py
@@ -12,16 +12,16 @@ with open("README.md", "r") as fh:
|
|||||||
# This call to setup() does all the work
|
# This call to setup() does all the work
|
||||||
setup(
|
setup(
|
||||||
name="meshtastic",
|
name="meshtastic",
|
||||||
version="1.3alpha.18",
|
version="2.0.5",
|
||||||
description="Python API & client shell for talking to Meshtastic devices",
|
description="Python API & client shell for talking to Meshtastic devices",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
url="https://github.com/meshtastic/Meshtastic-python",
|
url="https://github.com/meshtastic/python",
|
||||||
author="Kevin Hester",
|
author="Meshtastic Developers",
|
||||||
author_email="kevinh@geeksville.com",
|
author_email="contact@meshtastic.org",
|
||||||
license="MIT",
|
license="GPL-3.0-only",
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"License :: OSI Approved :: MIT License",
|
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||||
"Development Status :: 4 - Beta",
|
"Development Status :: 4 - Beta",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.7",
|
||||||
"Programming Language :: Python :: 3.8",
|
"Programming Language :: Python :: 3.8",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
readme.txt for single standalone executable zip files that can be
|
readme.txt for single standalone executable zip files that can be
|
||||||
downloaded from https://github.com/meshtastic/Meshtastic-python/releases
|
downloaded from https://github.com/meshtastic/python/releases
|
||||||
|
|
||||||
If you do not want to install python and/or the python libraries, you can download one of these
|
If you do not want to install python and/or the python libraries, you can download one of these
|
||||||
files to run the Meshtastic command line interface (CLI) as a standalone executable.
|
files to run the Meshtastic command line interface (CLI) as a standalone executable.
|
||||||
|
|||||||
Reference in New Issue
Block a user