Compare commits

...

189 Commits

Author SHA1 Message Date
Ben Meadors
c65a60d22d Update protos 2023-03-28 19:35:48 -05:00
github-actions
3a6475dc9d bump version 2023-03-26 20:30:40 +00:00
Ben Meadors
6f91479605 Re-cut protos for spelling fix 2023-03-26 15:29:14 -05:00
github-actions
bbebddea78 bump version 2023-03-26 19:45:12 +00:00
Ben Meadors
45be828183 Merge pull request #432 from mverch67/master
Fix remote_hardware configuration
2023-03-26 14:43:41 -05:00
Ben Meadors
e0753d4745 Added new smart broadcast properties 2023-03-26 14:43:07 -05:00
Manuel
21f2e185f2 Merge branch 'master' into master 2023-03-26 20:03:19 +02:00
Manuel Verch
4bfedf6aa9 added missing audio module remote config 2023-03-26 19:59:25 +02:00
Manuel Verch
193c3faca5 Fix remote_hardware configuration 2023-03-26 16:25:59 +02:00
Manuel Verch
1f47c225b3 Fix remote_hardware configuration 2023-03-25 21:37:10 +01:00
github-actions
1b372fca8d bump version 2023-03-19 18:38:37 +00:00
Ben Meadors
5e7b6027fa Bump to 2.1.x 2023-03-19 13:36:38 -05:00
Ben Meadors
64bd5deb4b Update protos to 2.1.3 2023-03-19 13:35:13 -05:00
Ben Meadors
d0fdb9b570 Merge pull request #428 from GUVWAF/remoteAdmin
Get and set methods for remote node using one admin message
2023-03-19 13:31:49 -05:00
Garth Vander Houwen
f37755209e Merge pull request #429 from GUVWAF/configSnake
Convert sections to snake_case when configuring
2023-03-19 09:17:30 -07:00
GUVWAF
297c0dbc0e Convert sections to snake_case when configuring 2023-03-19 15:25:08 +01:00
GUVWAF
7de17f7c94 Display that '--nodes' is not supported for a remote node 2023-03-19 14:42:44 +01:00
GUVWAF
55f6494681 Wait for ACK after setting remote config 2023-03-19 14:42:12 +01:00
GUVWAF
b2cfebc5a7 '--set' works as well, also chained commands 2023-03-18 21:12:05 +01:00
GUVWAF
802768e0cc Nicer printing 2023-03-18 16:40:27 +01:00
GUVWAF
f68e4112e1 Remote get method works 2023-03-18 15:20:00 +01:00
github-actions
19b4cd65ce bump version 2023-02-10 20:53:49 +00:00
Ben Meadors
ef12125785 Update protos 2023-02-10 13:26:29 -06:00
Garth Vander Houwen
014993f058 Merge pull request #417 from tobymurray/patch-2 2023-02-09 10:01:21 -08:00
github-actions
a10da7d3ed bump version 2023-01-31 16:54:53 +00:00
Ben Meadors
786dca9d13 Protos 2023-01-31 10:53:03 -06:00
github-actions
1cfd471abc bump version 2023-01-29 23:04:27 +00:00
Ben Meadors
9ff575c388 Hack to make python compile again 2023-01-29 15:19:03 -06:00
Toby Murray
b973e39ef7 Fix link to Getting Started Guide
Previous link (https://meshtastic.org/docs/software/python/python-installation) 404's
2023-01-16 13:53:31 -05:00
github-actions
75cdc5a36b bump version 2023-01-07 21:29:31 +00:00
Thomas Göttgens
93441a473f Merge pull request #414 from meshtastic/ringtone-support
get and set RTTTL ringtone
2023-01-04 20:23:28 +01:00
Thomas Göttgens
7b8a83ade7 get and set RTTTL ringtone 2023-01-04 19:52:24 +01:00
github-actions
2cf1ce2898 Update protobuf submodule 2023-01-04 17:19:27 +00:00
Sacha Weatherstone
e4890bfff2 Update README.md 2023-01-02 16:49:27 +11:00
github-actions
5c6ba26334 Update protobuf submodule 2022-12-29 16:18:30 +00:00
Thomas Göttgens
e6e3ad121d Merge pull request #413 from GUVWAF/metrics
Display battery level, channel and Tx air util. with --nodes
2022-12-29 17:13:00 +01:00
Thomas Göttgens
7133c859d6 Merge pull request #411 from mkinney/fix_pylint_warnings
fix pylint warnings
2022-12-29 17:12:00 +01:00
GUVWAF
8acf0b849a --nodes displays battery, channel and Tx air util. 2022-12-29 17:00:35 +01:00
github-actions
42f6818a02 bump version 2022-12-28 16:41:43 +00:00
github-actions
af043ef5c0 Update protobuf submodule 2022-12-28 16:37:24 +00:00
github-actions
4f46858643 bump version 2022-12-27 21:23:16 +00:00
Thomas Göttgens
ddc47fb8de Merge pull request #412 from meshtastic/remote-hardware
tryfix remote hardware
2022-12-27 22:16:57 +01:00
Thomas Göttgens
7ee134b819 tryfix remote hardware 2022-12-27 21:32:25 +01:00
Ben Meadors
254e9f4015 Typos 2022-12-22 14:35:48 -06:00
Mike Kinney
babd1242d5 fix pylint warnings 2022-12-20 11:18:40 -08:00
mkinney
cc99ea009e Update README.md
fix codecoverage link
2022-12-20 11:00:01 -08:00
github-actions
76407e11f8 bump version 2022-12-06 14:44:31 +00:00
Thomas Göttgens
57719ddd5e Merge pull request #407 from GUVWAF/traceRoute
Traceroute option
2022-12-06 15:36:49 +01:00
GUVWAF
d0b8b9ff1b Forgot to convert into TRACEROUTE_APP 2022-12-06 14:18:30 +01:00
github-actions
c5c9723208 Update protobuf submodule 2022-12-06 13:16:28 +00:00
Ben Meadors
9bceaafd9c Merge pull request #406 from GUVWAF/hopLimit
Set hopLimit to the config of the device
2022-12-05 20:10:27 -06:00
GUVWAF
7d3a9178ea Add traceroute option 2022-12-05 20:36:34 +01:00
GUVWAF
2c76c0cafa Remove setting hopLimit to default
Instead set is to config of device
2022-12-05 20:04:38 +01:00
GUVWAF
82977e9ef2 Fix --ch-set help message 2022-12-05 20:02:53 +01:00
Sacha Weatherstone
7a9c25da8e Merge pull request #404 from ahmedkadd/fix-script-typo
Rename protobufs shell script to fix typo
2022-12-02 14:39:18 +11:00
Ahmed Kaddoura
342c48fb16 Rename protobufs shell script to fix typo 2022-11-30 07:58:56 -08:00
github-actions
6bc955a403 bump version 2022-11-27 12:10:59 +00:00
Ben Meadors
741ba378ab Merge pull request #402 from GUVWAF/wantResponse
Only set wantResponse for admin packets
2022-11-27 06:10:01 -06:00
GUVWAF
c1054caf4a Only set wantResponse for admin packets 2022-11-27 12:44:58 +01:00
Ben Meadors
24b97d9277 Merge pull request #401 from GUVWAF/setowner
Remove automatic short owner naming and increase to 4 characters
2022-11-26 07:56:34 -06:00
GUVWAF
868fb64857 Only set is_licensed if long_name is set 2022-11-26 11:08:00 +01:00
GUVWAF
8729e97e1b Remove automatic short owner naming and increase to 4 characters 2022-11-26 10:52:20 +01:00
github-actions
aaed54393e bump version 2022-11-22 17:03:56 +00:00
Ben Meadors
d12776bb5f Merge pull request #400 from meshtastic/transaction-for-config
Transactions for editing settings
2022-11-21 15:27:31 -06:00
Ben Meadors
7829f6afca Args 2022-11-20 20:01:50 -06:00
Ben Meadors
4bd10bc102 Add begin / edit transactions for setting updates 2022-11-20 19:46:43 -06:00
Ben Meadors
3821e02f09 Update protos 2022-11-20 19:11:38 -06:00
Ben Meadors
97689da0b4 Merge pull request #395 from GUVWAF/master
Change how admin packets to remote nodes are handled
2022-11-19 15:36:33 -06:00
GUVWAF
5c75e74bf9 Don't request config and channels if not needed.
Instead, wait for an (implicit) ACK or NAK.
Applies to admin packets set-owner, reboot,
shutdown, factory-reset and reset-nodedb.
2022-11-19 21:19:06 +01:00
GUVWAF
388a46abf4 Merge branch 'meshtastic:master' into master 2022-11-15 13:26:30 +01:00
github-actions
6b89fc81a1 bump version 2022-11-10 03:23:52 +00:00
Ben Meadors
c9b5d5d697 Update protos and add audio 2022-11-09 21:20:38 -06:00
Ben Meadors
f16dd0e737 Update url 2022-11-08 18:25:49 -06:00
Ben Meadors
5ed19eff73 Create cleanup_artifacts.yml 2022-11-05 06:52:28 -05:00
github-actions
0b3605141d bump version 2022-11-03 13:02:34 +00:00
GUVWAF
f1df14ca92 lastTried channel should be its index 2022-11-03 09:28:15 +01:00
Ben Meadors
83776ceec5 Fix url 2022-11-02 21:20:25 -05:00
GUVWAF
7aff5e9ee5 Unset wantAck if you set wantResponse for Admin 2022-11-02 09:49:20 +01:00
github-actions
bf6be107d3 bump version 2022-11-01 12:26:50 +00:00
Ben Meadors
c24d1fe26b Missing a comma! 2022-11-01 07:26:04 -05:00
Ben Meadors
61f5468847 Update setup.py 2022-11-01 07:24:54 -05:00
github-actions
c713ce04b6 bump version 2022-11-01 12:17:41 +00:00
Ben Meadors
fe2b36e04b Merge pull request #392 from meshtastic/licence-change-&-2.0-prep
License change & 2.0 Prep
2022-11-01 07:08:09 -05:00
Ben Meadors
a720916df5 Update version in setup.py 2022-10-31 08:00:29 -05:00
Sacha Weatherstone
b2593e4bb1 Changes 2022-10-31 19:47:42 +10:00
github-actions
6e3c759e5c bump version 2022-10-30 01:08:22 +00:00
github-actions
a41f33e0bd bump version 2022-10-28 15:06:14 +00:00
Ben Meadors
111bf8dcbf Update protos 2022-10-28 10:03:26 -05:00
Ben Meadors
f18abb2fe6 Update protos 2022-10-26 08:53:32 -05:00
github-actions
b7093e176a bump version 2022-10-21 16:58:02 +00:00
Ben Meadors
cf7d37a454 Update __main__.py 2022-10-21 11:53:58 -05:00
github-actions
2af431e2eb bump version 2022-10-21 12:38:51 +00:00
Ben Meadors
3db64f7988 Merge pull request #387 from meshtastic/fun-fun
Print available options
2022-10-21 07:37:56 -05:00
Ben Meadors
7ef64d4250 Print options 2022-10-21 07:27:55 -05:00
Ben Meadors
363aa995a2 Push it real good 2022-10-20 17:13:26 -05:00
github-actions
696fa28e6f bump version 2022-10-16 13:46:40 +00:00
Ben Meadors
a908bdfc1c Protos 2022-10-16 08:44:30 -05:00
Ben Meadors
81b64ac908 Merge pull request #385 from GUVWAF/master
Use new config for pos-fields
2022-10-16 08:43:38 -05:00
GUVWAF
d5ccdc826f Use new config for pos-fields 2022-10-16 15:38:18 +02:00
Ben Meadors
fac4faaae8 Merge pull request #383 from meshtastic/reboot-ota
add reboot to ota command for testing purposes.
2022-10-10 10:28:59 -05:00
Thomas Göttgens
cfb8769746 add reeboot to ota command for testing purposes. This is a developer only command for now :-) 2022-10-10 16:59:01 +02:00
github-actions
c1b0e4e8d0 bump version 2022-10-09 15:10:27 +00:00
Ben Meadors
5683e31f6b Update protos 2022-10-09 10:00:51 -05:00
Ben Meadors
7909ad477b Merge pull request #380 from GUVWAF/master
Remove additional print statements
2022-10-09 09:59:51 -05:00
github-actions
f94dbf05ef bump version 2022-10-08 12:19:51 +00:00
Ben Meadors
a44b769390 Merge pull request #381 from meshtastic/config
Get export-configuration and configure working again
2022-10-08 07:19:03 -05:00
Ben Meadors
2a4816a9cd Get configuration yaml working again 2022-10-08 07:16:20 -05:00
GUVWAF
674fd92690 Merge branch 'master' of https://github.com/GUVWAF/Meshtastic-python 2022-10-08 13:21:02 +02:00
GUVWAF
cc29cab99a Remove additional print statements 2022-10-08 13:20:28 +02:00
Ben Meadors
bf803bb6e9 Merge pull request #379 from GUVWAF/master
Catch RoutingApp response for Admin packet
2022-10-08 05:57:56 -05:00
Ben Meadors
3c80fd0f02 Protos 2022-10-08 05:57:10 -05:00
GUVWAF
616a3ab706 Catch RoutingApp on requestGetMetadata 2022-10-08 12:47:48 +02:00
GUVWAF
8350cc611d Catch RoutingApp on requestChannel 2022-10-08 12:47:13 +02:00
github-actions
621feb749d bump version 2022-10-02 14:40:33 +00:00
Ben Meadors
f6731a435d Proto baggins 2022-10-01 08:36:43 -05:00
Ben Meadors
dcfe5fb558 Merge pull request #377 from GUVWAF/master
Add KnownProtocol for Simulator_App
2022-10-01 07:59:26 -05:00
GUVWAF
4fa80e9652 Add KnownProtocol for Simulator_App 2022-10-01 11:46:40 +02:00
github-actions
02851b6237 bump version 2022-09-25 18:52:40 +00:00
Ben Meadors
a74ec12445 Reset nodedb command 2022-09-25 13:46:11 -05:00
github-actions
262e921a81 bump version 2022-09-20 02:05:17 +00:00
Ben Meadors
0c7b9e10f4 Update setup.py 2022-09-19 21:04:22 -05:00
github-actions
ab8b930365 bump version 2022-09-18 13:07:41 +00:00
Ben Meadors
4ae49c68aa Add factory reset 2022-09-18 08:05:50 -05:00
github-actions
733f22d927 bump version 2022-09-18 01:00:31 +00:00
Ben Meadors
791131ea27 Version bump fix 2022-09-17 19:59:08 -05:00
github-actions
f17292221c bump version 2022-09-18 00:42:08 +00:00
Ben Meadors
b60a438c9d Update setup.py 2022-09-17 19:30:56 -05:00
github-actions
3b3a610375 bump version 2022-09-18 00:20:12 +00:00
Ben Meadors
38f928bdb7 Update setup.py 2022-09-17 19:19:23 -05:00
github-actions
6272e992a4 bump version 2022-09-18 00:09:40 +00:00
Ben Meadors
3263fbca28 Increment build number instead 2022-09-17 19:08:41 -05:00
Ben Meadors
f0e7af389c Update setup.py 2022-09-17 18:52:53 -05:00
github-actions
471dfc7a29 bump version 2022-09-13 01:19:06 +00:00
Ben Meadors
2a7c21c062 Protos sync 2022-09-12 20:16:14 -05:00
github-actions
03797e3336 bump version 2022-09-11 13:03:34 +00:00
Ben Meadors
dc1be12c86 Update protos 2022-09-11 08:01:55 -05:00
github-actions
4c83a43d64 bump version 2022-09-09 16:44:46 +00:00
Ben Meadors
e083cda3d9 Merge pull request #371 from meshtastic/big-proto-refactor
Update python to use reworked protos
2022-09-09 11:43:10 -05:00
Ben Meadors
c0006f888b Add alpha back for upcoming release 2022-09-09 11:05:10 -05:00
Ben Meadors
e2d2d3a347 Refactor 2022-09-09 11:02:58 -05:00
Ben Meadors
3fd50b0e44 Update python to use reworked protos 2022-09-09 09:49:04 -05:00
github-actions
4b0e3ae923 bump version 2022-09-08 21:43:54 +00:00
Ben Meadors
37f10cc0d4 Remove alpha 2022-09-08 15:55:19 -05:00
github-actions
998df265e6 bump version 2022-09-08 12:11:11 +00:00
Ben Meadors
d852981371 Med 2022-09-08 07:09:25 -05:00
Ben Meadors
afed5bd943 Fixed med preset names 2022-09-08 07:09:13 -05:00
Ben Meadors
97b9041b76 Merge pull request #368 from ghostop14/master
Fixes #367 MedFast Enum Not Defined
2022-09-08 06:58:18 -05:00
Ben Meadors
2dc14ef466 Merge pull request #369 from rohanki/master
Fix for --setalt --setlat --setlon
2022-09-05 20:30:29 -05:00
Rohan King
8e69c32a36 Fix for --setalt --setlat --setlon
fix for --setalt --setlat and --setlon
2022-09-06 10:23:19 +10:00
github-actions
42b33bea5b bump version 2022-09-03 14:03:36 +00:00
Ben Meadors
7fd101cbf8 Update protos and fix error 2022-09-03 09:02:36 -05:00
ghostop14
92ee9889b1 Fixes #367 MedFast Enum Not Defined 2022-09-02 10:44:59 -04:00
github-actions
b6e1610abe bump version 2022-08-27 13:37:05 +00:00
Ben Meadors
bde5db9c51 Fixed ch-set command in setPref 2022-08-27 08:14:48 -05:00
github-actions
148ae49ded bump version 2022-08-25 18:25:24 +00:00
Ben Meadors
d1f8365da1 Merge pull request #363 from meshtastic/channel-url
Channel setting fixed
2022-08-25 13:24:20 -05:00
Ben Meadors
59fc294d66 Channel setting fixed 2022-08-25 13:22:05 -05:00
github-actions
7473b4e18c bump version 2022-08-17 02:49:05 +00:00
Ben Meadors
58aafcf3f1 Merge pull request #361 from Douile/dev-change-channel
Fix changing modem_preset from CLI shortcuts
2022-08-16 08:58:56 -05:00
Douile
776fc57c35 Fix changing modem_preset from CLI shortcuts
Previously the channel shortcuts (e.g. --ch-shortfast) would overrwrite
the entire lora config, this meant you lost other configured things such
as region. This patch changes that so that just modem_preset is
overwritten, and also fixes the call to write config that was missing
an argument.
2022-08-16 14:55:17 +01:00
Ben Meadors
b3f752a3c4 Merge pull request #360 from meshtastic/bt-canned
Bluetooth and canned messages changes
2022-08-15 21:01:44 -05:00
Ben Meadors
4965ec7f1d Missed some spots 2022-08-15 20:54:11 -05:00
Ben Meadors
0746acd34f Canned messages and bluetooth sections 2022-08-15 19:01:37 -05:00
github-actions
49b1c4816e bump version 2022-08-11 17:46:19 +00:00
Ben Meadors
7c6e87e161 Merge pull request #356 from meshtastic/increase-timeouts
Only write single config
2022-08-11 12:45:12 -05:00
Ben Meadors
b548700c0b Only write single config 2022-08-11 12:43:41 -05:00
github-actions
f278a30003 bump version 2022-08-11 16:53:26 +00:00
Ben Meadors
22bbe67d24 Merge pull request #355 from meshtastic/increase-timeouts
Increase delay for reliability
2022-08-11 11:51:09 -05:00
Ben Meadors
a2861a133e Increase delay for reliability 2022-08-11 11:48:57 -05:00
github-actions
03aab10786 bump version 2022-08-09 11:29:44 +00:00
Ben Meadors
95e768efd5 Merge pull request #354 from meshtastic/device-metadata
Add get device metadata admin message
2022-08-08 07:07:47 -05:00
Ben Meadors
6644e86be9 Add get device metadata admin message 2022-08-08 07:04:29 -05:00
Ben Meadors
c8363cd476 Merge pull request #352 from Douile/dev-export-valid-yaml
Replace the primative print based config generator with proper yaml serialization
2022-08-05 10:14:42 -05:00
Ben Meadors
62efe1ab7f Merge pull request #353 from Douile/dev-fix-lint-errors-2
Fix lint errors
2022-08-05 10:13:58 -05:00
Douile
01e643ad2f Fix lint errors 2022-08-05 13:48:07 +01:00
Douile
e4078e84d7 Fix linting errors caused by this PR 2022-08-05 13:34:25 +01:00
Ben Meadors
abfcbe2a90 Merge pull request #350 from Douile/dev-base64-decode
Allow setting values from base64 values
2022-07-28 17:42:08 -05:00
Douile
e06d8bbc06 Use pyyaml to generate valid configuration output
The custom yaml generator made an invalid yaml file that needed to be
fixed, by using the already included pyyaml library we can make sure the
output is valid.
2022-07-28 15:11:35 +01:00
Ben Meadors
a78cdde86f Merge pull request #349 from Douile/dev-fix-errors
Fix crash when trying to set value that doesn't exist
2022-07-27 18:53:44 -05:00
Douile
10517ac94d Allow setting values from base64 values
By prefixing a value with "base64:" e.g. ("base64:AQ==") it will now be
decoded to raw bytes. This is useful when setting psk as that is often
shown as base64.
2022-07-27 15:12:23 +01:00
Douile
a572699588 Fix crash when trying to set value that doesn't exist 2022-07-27 15:09:58 +01:00
github-actions
d11fb47734 bump version 2022-07-02 19:52:35 +00:00
Ben Meadors
92c7b2db69 Merge pull request #348 from meshtastic/moduleconfg
100ms delays to prevent overloading the serial
2022-07-02 14:43:24 -05:00
Ben Meadors
ff94ad968c 100ms delays to prevent overloading the serial 2022-07-02 14:41:09 -05:00
github-actions
c6071c57ec bump version 2022-06-30 01:17:37 +00:00
Ben Meadors
e3e3562c2c Merge pull request #347 from meshtastic/moduleconfg
Module config progress
2022-06-29 20:16:37 -05:00
Ben Meadors
06b5b8fa83 It works, I think 2022-06-29 20:01:48 -05:00
Ben Meadors
4b95b0ff30 Module config progress 2022-06-29 18:35:06 -05:00
Thomas Göttgens
42f2ed571d Merge pull request #346 from meshtastic/patch-1
small issues corrected
2022-06-21 19:38:01 +02:00
41 changed files with 1656 additions and 687 deletions

20
.github/workflows/cleanup_artifacts.yml vendored Normal file
View 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

View File

@@ -15,22 +15,22 @@ jobs:
run: | run: |
git pull --recurse-submodules git pull --recurse-submodules
git submodule update --remote --recursive git submodule update --remote --recursive
- name: Download nanopb - name: Download nanopb
run: | run: |
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz
tar xvzf nanopb-0.4.6-linux-x86.tar.gz tar xvzf nanopb-0.4.6-linux-x86.tar.gz
mv nanopb-0.4.6-linux-x86 nanopb-0.4.6 mv nanopb-0.4.6-linux-x86 nanopb-0.4.6
- name: Re-generate protocol buffers - name: Re-generate protocol buffers
run: | run: |
./bin/regen-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
View File

@@ -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

View File

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

73
.vscode/launch.json vendored
View File

@@ -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",

View File

@@ -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:

View File

@@ -2,8 +2,8 @@
[![codecov](https://codecov.io/gh/meshtastic/Meshtastic-python/branch/master/graph/badge.svg?token=TIWPJL73KV)](https://codecov.io/gh/meshtastic/Meshtastic-python) [![codecov](https://codecov.io/gh/meshtastic/Meshtastic-python/branch/master/graph/badge.svg?token=TIWPJL73KV)](https://codecov.io/gh/meshtastic/Meshtastic-python)
![PyPI - Downloads](https://img.shields.io/pypi/dm/meshtastic) ![PyPI - Downloads](https://img.shields.io/pypi/dm/meshtastic)
[![CI](https://img.shields.io/github/workflow/status/meshtastic/Meshtastic-python/CI?label=actions&logo=github&color=yellow)](https://github.com/meshtastic/Meshtastic-python/actions/workflows/ci.yml) [![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/python/ci.yml?branch=master&label=actions&logo=github&color=yellow)](https://github.com/meshtastic/python/actions/workflows/ci.yml)
[![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/Meshtastic-python)](https://cla-assistant.io/meshtastic/Meshtastic-python) [![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/python)](https://cla-assistant.io/meshtastic/python)
[![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/) [![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/)
[![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss) [![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
@@ -14,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/cli/installation)**
**[Getting Started Guide](https://meshtastic.org/docs/software/python/python-installation)**
**[Documentation/API Reference](https://python.meshtastic.org/)** **[Documentation/API Reference](https://python.meshtastic.org/)**
## Stats ## Stats
![Alt](https://repobeats.axiom.co/api/embed/3d64492daee3a603497071b45e6cdb81d9b2d421.svg "Repobeats analytics image") ![Alt](https://repobeats.axiom.co/api/embed/c71ee8fc4a79690402e5d2807a41eec5e96d9039.svg "Repobeats analytics image")

View File

@@ -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)

View File

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

View File

@@ -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

View File

@@ -3,7 +3,7 @@
Primary class: SerialInterface Primary class: SerialInterface
Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)" Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)"
Source code on [github](https://github.com/meshtastic/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)
} }

View File

@@ -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,11 @@ 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(node, 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: wholeField = name[0] == name[1] # We want the whole field
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,87 +65,87 @@ 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 # First validate the input
config_type = objDesc.fields_by_name.get(name[0]) localConfig = node.localConfig
pref = False moduleConfig = node.moduleConfig
if config_type: found = False
pref = config_type.message_type.fields_by_name.get(snake_name) for config in [localConfig, moduleConfig]:
objDesc = config.DESCRIPTOR
config_type = objDesc.fields_by_name.get(name[0])
pref = False
if config_type:
pref = config_type.message_type.fields_by_name.get(snake_name)
if pref or wholeField:
found = True
break
if (not pref) or (not config_type): if not found:
if Globals.getInstance().get_camel_case(): if Globals.getInstance().get_camel_case():
print(f"{attributes.__class__.__name__} does not have an attribute called {name[0]}.{camel_name}, so you can not get it.") print(f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have an attribute {snake_name}.")
else: else:
print(f"{attributes.__class__.__name__} does not have an attribute called {name[0]}.{snake_name}, so you can not get it.") print(f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have attribute {snake_name}.")
print(f"Choices in sorted order are:") print("Choices are...")
names = [] printConfig(localConfig)
for f in objDesc.fields: printConfig(moduleConfig)
tmp_path = f'{f.name}' return False
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 # Check if we need to request the config
config_values = getattr(attributes, config_type.name) if len(config.ListFields()) != 0:
pref_value = getattr(config_values, pref.name) # read the value
config_values = getattr(config, config_type.name)
if Globals.getInstance().get_camel_case(): if not wholeField:
print(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}") pref_value = getattr(config_values, pref.name)
logging.debug(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}") if Globals.getInstance().get_camel_case():
else: print(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}")
print(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}") logging.debug(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}")
logging.debug(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}") else:
print(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
logging.debug(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
def setPref(attributes, comp_name, valStr): else:
"""Set a channel or preferences value""" print(f"{str(config_type.name)}:\n{str(config_values)}")
logging.debug(f"{str(config_type.name)}: {str(config_values)}")
else:
# Always show whole field for remote node
node.requestConfig(config_type)
return True
def splitCompoundName(comp_name):
"""Split compound (dot separated) preference name into parts"""
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 +166,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 +189,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 +216,86 @@ 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)
# TODO: add to export-config and configure
if args.set_ringtone:
closeNow = True
waitForAckNak = True
print(f"Setting ringtone to {args.set_ringtone}")
interface.getNode(args.dest, False).set_ringtone(args.set_ringtone)
if args.pos_fields: if args.pos_fields:
# If --pos-fields invoked with args, set position fields # If --pos-fields invoked with args, set position fields
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 +307,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, False).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 +361,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 +406,56 @@ def onConnected(interface):
# handle settings # handle settings
if args.set: if args.set:
closeNow = True closeNow = True
prefs = interface.getNode(args.dest).localConfig waitForAckNak = True
node = interface.getNode(args.dest, False)
# 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 = False
field = splitCompoundName(pref[0].lower())[0]
for config in [node.localConfig, node.moduleConfig]:
config_type = config.DESCRIPTOR.fields_by_name.get(field)
if config_type:
if len(config.ListFields()) == 0:
node.requestConfig(config.DESCRIPTOR.fields_by_name.get(field))
found = setPref(config, pref[0], pref[1])
if found:
break
print("Writing modified preferences to device") if found:
interface.getNode(args.dest).writeConfig() print("Writing modified preferences to device")
node.writeConfig(field)
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 +469,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"{meshtastic.util.camel_to_snake(section)}.{pref}", str(configuration['config'][section][pref]))
interface.getNode(args.dest).writeConfig() interface.getNode(args.dest).writeConfig(meshtastic.util.camel_to_snake(section))
if 'userPrefs' in configuration: if 'module_config' in configuration:
prefs = interface.getNode(args.dest).localConfig moduleConfig = interface.getNode(args.dest).moduleConfig
for pref in configuration['userPrefs']: for section in configuration['module_config']:
setPref(prefs, pref, str(configuration['userPrefs'][pref])) for pref in configuration['module_config'][section]:
print("Writing modified preferences to device") setPref(moduleConfig, f"{meshtastic.util.camel_to_snake(section)}.{pref}", str(configuration['module_config'][section][pref]))
interface.getNode(args.dest).writeConfig() interface.getNode(args.dest).writeConfig(meshtastic.util.camel_to_snake(section))
interface.getNode(args.dest, False).commitSettingsTransaction()
print("Writing modified configuration to device")
if args.export_config: if args.export_config:
# export the configuration (the opposite of '--configure') # export the configuration (the opposite of '--configure')
@@ -470,34 +551,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
@@ -540,29 +619,38 @@ def onConnected(interface):
print("") print("")
interface.getNode(args.dest).get_canned_message() interface.getNode(args.dest).get_canned_message()
if args.get_ringtone:
closeNow = True
print("")
interface.getNode(args.dest).get_ringtone()
if args.info: if args.info:
print("") print("")
# If we aren't trying to talk to our local node, don't show it # If we aren't trying to talk to our local node, don't show it
if args.dest == BROADCAST_ADDR: if args.dest == BROADCAST_ADDR:
interface.showInfo() interface.showInfo()
print("")
print("") interface.getNode(args.dest).showInfo()
interface.getNode(args.dest).showInfo() closeNow = True
closeNow = True # FIXME, for now we leave the link up while talking to remote nodes print("")
print("") else:
print("Showing info of remote node is not supported.")
print("Use the '--get' command for a specific configuration (e.g. 'lora') instead.")
if args.get: if args.get:
closeNow = True closeNow = True
prefs = interface.getNode(args.dest).localConfig node = interface.getNode(args.dest, False)
# Handle the int/float/bool arguments
for pref in args.get: for pref in args.get:
getPref(prefs, pref[0]) found = getPref(node, pref[0])
print("Completed getting preferences") if found:
print("Completed getting preferences")
if args.nodes: if args.nodes:
closeNow = True closeNow = True
if args.dest != BROADCAST_ADDR:
print("Showing node list of a remote node is not supported.")
return
interface.showNodes() interface.showNodes()
if args.qr: if args.qr:
@@ -583,6 +671,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 +683,21 @@ 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):
"""print configuration"""
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 +717,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 +732,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
@@ -779,6 +896,9 @@ def initParser():
parser.add_argument("--get-canned-message", help="Show the canned message plugin message", parser.add_argument("--get-canned-message", help="Show the canned message plugin message",
action="store_true") action="store_true")
parser.add_argument("--get-ringtone", help="Show the stored ringtone",
action="store_true")
parser.add_argument("--nodes", help="Print Node List in a pretty formatted table", parser.add_argument("--nodes", help="Print Node List in a pretty formatted table",
action="store_true") action="store_true")
@@ -816,7 +936,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 +950,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')
@@ -845,7 +965,10 @@ def initParser():
"--set-owner", help="Set device owner name", action="store") "--set-owner", help="Set device owner name", action="store")
parser.add_argument( parser.add_argument(
"--set-canned-message", help="Set the canned messages plugin message (up to 1000 characters).", action="store") "--set-canned-message", help="Set the canned messages plugin message (up to 200 characters).", action="store")
parser.add_argument(
"--set-ringtone", help="Set the Notification Ringtone (up to 230 characters).", action="store")
parser.add_argument( parser.add_argument(
"--set-owner-short", help="Set device owner short name", action="store") "--set-owner-short", help="Set device owner short name", action="store")
@@ -862,12 +985,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")

View File

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

View File

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

View File

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

View File

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

View File

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/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()
from meshtastic import config_pb2 as meshtastic_dot_config__pb2
from meshtastic import mesh_pb2 as meshtastic_dot_mesh__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/device_metadata.proto\x1a\x17meshtastic/config.proto\x1a\x15meshtastic/mesh.proto\"\xfc\x01\n\x0e\x44\x65viceMetadata\x12\x18\n\x10\x66irmware_version\x18\x01 \x01(\t\x12\x1c\n\x14\x64\x65vice_state_version\x18\x02 \x01(\r\x12\x13\n\x0b\x63\x61nShutdown\x18\x03 \x01(\x08\x12\x0f\n\x07hasWifi\x18\x04 \x01(\x08\x12\x14\n\x0chasBluetooth\x18\x05 \x01(\x08\x12\x13\n\x0bhasEthernet\x18\x06 \x01(\x08\x12\'\n\x04role\x18\x07 \x01(\x0e\x32\x19.Config.DeviceConfig.Role\x12\x16\n\x0eposition_flags\x18\x08 \x01(\r\x12 \n\x08hw_model\x18\t \x01(\x0e\x32\x0e.HardwareModelBi\n\x13\x63om.geeksville.meshB\x14\x44\x65viceMetadataProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_DEVICEMETADATA = DESCRIPTOR.message_types_by_name['DeviceMetadata']
DeviceMetadata = _reflection.GeneratedProtocolMessageType('DeviceMetadata', (_message.Message,), {
'DESCRIPTOR' : _DEVICEMETADATA,
'__module__' : 'meshtastic.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\024DeviceMetadataProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_DEVICEMETADATA._serialized_start=85
_DEVICEMETADATA._serialized_end=337
# @@protoc_insertion_point(module_scope)

View File

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

View File

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

View File

@@ -18,7 +18,7 @@ from google.protobuf.json_format import MessageToJson
import meshtastic.node import meshtastic.node
from meshtastic import portnums_pb2, mesh_pb2 from meshtastic import portnums_pb2, mesh_pb2
from meshtastic.util import stripnl, Timeout, 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
@@ -137,7 +137,20 @@ class MeshInterface:
"Latitude": formatFloat(pos.get("latitude"), 4, "°"), "Latitude": formatFloat(pos.get("latitude"), 4, "°"),
"Longitude": formatFloat(pos.get("longitude"), 4, "°"), "Longitude": formatFloat(pos.get("longitude"), 4, "°"),
"Altitude": formatFloat(pos.get("altitude"), 0, " m"), "Altitude": formatFloat(pos.get("altitude"), 0, " m"),
"Battery": formatFloat(pos.get("batteryLevel"), 2, "%"), })
metrics = node.get('deviceMetrics')
if metrics:
batteryLevel = metrics.get('batteryLevel')
if batteryLevel is not None:
if batteryLevel == 0:
batteryString = "Powered"
else:
batteryString = str(batteryLevel)+"%"
row.update({"Battery": batteryString})
row.update({
"Channel util.": formatFloat(metrics.get('channelUtilization'), 2, "%"),
"Tx air util.": formatFloat(metrics.get('airUtilTx'), 2, "%"),
}) })
row.update({ row.update({
@@ -157,23 +170,24 @@ class MeshInterface:
return table return table
def getNode(self, nodeId): def getNode(self, nodeId, requestChannels=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 requestChannels:
if not n.waitForConfig(): logging.debug("About to requestChannels")
our_exit("Error: Timed out waiting for node config") n.requestChannels()
if not n.waitForConfig():
our_exit("Error: Timed out waiting for channels")
return n return n
def sendText(self, text: AnyStr, def sendText(self, text: AnyStr,
destinationId=BROADCAST_ADDR, destinationId=BROADCAST_ADDR,
wantAck=False, wantAck=False,
wantResponse=False, wantResponse=False,
hopLimit=None,
onResponse=None, onResponse=None,
channelIndex=0): channelIndex=0):
"""Send a utf8 string to some other node, if the node has a display it """Send a utf8 string to some other node, if the node has a display it
@@ -195,21 +209,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 +244,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 +266,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,
@@ -298,20 +305,43 @@ class MeshInterface:
wantAck=wantAck, wantAck=wantAck,
wantResponse=wantResponse) wantResponse=wantResponse)
def sendTraceRoute(self, dest, hopLimit):
"""Send the trace route"""
r = mesh_pb2.RouteDiscovery()
self.sendData(r, destinationId=dest, portNum=portnums_pb2.PortNum.TRACEROUTE_APP,
wantResponse=True, onResponse=self.onResponseTraceRoute)
# extend timeout based on number of nodes, limit by configured hopLimit
waitFactor = min(len(self.nodes)-1, hopLimit)
self.waitForTraceRoute(waitFactor)
def onResponseTraceRoute(self, p):
"""on response for trace route"""
routeDiscovery = mesh_pb2.RouteDiscovery()
routeDiscovery.ParseFromString(p["decoded"]["payload"])
asDict = google.protobuf.json_format.MessageToDict(routeDiscovery)
print("Route traced:")
routeStr = self._nodeNumToId(p["to"])
if "route" in asDict:
for nodeNum in asDict["route"]:
routeStr += " --> " + self._nodeNumToId(nodeNum)
routeStr += " --> " + self._nodeNumToId(p["from"])
print(routeStr)
self._acknowledgment.receivedTraceRoute = True
def _addResponseHandler(self, requestId, callback): def _addResponseHandler(self, requestId, callback):
self.responseHandlers[requestId] = ResponseHandler(callback) self.responseHandlers[requestId] = ResponseHandler(callback)
def _sendPacket(self, meshPacket, def _sendPacket(self, meshPacket,
destinationId=BROADCAST_ADDR, destinationId=BROADCAST_ADDR,
wantAck=False, 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 +375,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 +398,18 @@ class MeshInterface:
if not success: if not success:
raise Exception("Timed out waiting for interface config") raise Exception("Timed out waiting for interface config")
def waitForAckNak(self):
"""Wait for the ack/nak"""
success = self._timeout.waitForAckNak(self._acknowledgment)
if not success:
raise Exception("Timed out waiting for an acknowledgment")
def waitForTraceRoute(self, waitFactor):
"""Wait for trace route"""
success = self._timeout.waitForTraceRoute(waitFactor, self._acknowledgment)
if not success:
raise Exception("Timed out waiting for traceroute")
def getMyNodeInfo(self): def getMyNodeInfo(self):
"""Get info about my node.""" """Get info about my node."""
if self.myInfo is None: if self.myInfo is None:
@@ -478,7 +522,7 @@ class MeshInterface:
Done with initial config messages, now send regular MeshPackets Done with initial config messages, now send regular MeshPackets
to ask for settings and channels to ask for settings and channels
""" """
self.localNode.requestConfig() self.localNode.requestChannels()
def _handleFromRadio(self, fromRadioBytes): def _handleFromRadio(self, fromRadioBytes):
""" """
@@ -532,27 +576,50 @@ 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)
elif fromRadio.moduleConfig.HasField("audio"):
self.localNode.moduleConfig.audio.CopyFrom(fromRadio.moduleConfig.audio)
elif fromRadio.moduleConfig.HasField("remote_hardware"):
self.localNode.moduleConfig.remote_hardware.CopyFrom(fromRadio.moduleConfig.remote_hardware)
else: else:
logging.debug("Unexpected FromRadio payload") logging.debug("Unexpected FromRadio payload")
@@ -656,7 +723,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 +765,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(

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -6,13 +6,13 @@ import base64
import time import time
from google.protobuf.json_format import MessageToJson from google.protobuf.json_format import MessageToJson
from meshtastic import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2, localonly_pb2 from meshtastic import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2, localonly_pb2
from meshtastic.util import pskToString, stripnl, Timeout, our_exit, fromPSK from meshtastic.util import pskToString, stripnl, Timeout, our_exit, fromPSK, camel_to_snake
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,15 @@ 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.cannedPluginMessageMessages = None
self.cannedPluginMessagePart1 = None self.ringtone = None
self.cannedPluginMessagePart2 = None self.ringtonePart = None
self.cannedPluginMessagePart3 = None
self.cannedPluginMessagePart4 = None
self.gotResponse = None self.gotResponse = None
@@ -57,15 +55,66 @@ 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 requestChannels(self):
"""Send regular MeshPackets to ask for settings and channels.""" """Send regular MeshPackets to ask channels."""
logging.debug(f"requestConfig for nodeNum:{self.nodeNum}") logging.debug(f"requestChannels for nodeNum:{self.nodeNum}")
self.channels = None self.channels = None
self.partialChannels = [] # We keep our channels in a temp array until finished self.partialChannels = [] # We keep our channels in a temp array until finished
self._requestChannel(0) self._requestChannel(0)
def onResponseRequestSettings(self, p):
"""Handle the response packets for requesting settings _requestSettings()"""
logging.debug(f'onResponseRequestSetting() p:{p}')
if "routing" in p["decoded"]:
if p["decoded"]["routing"]["errorReason"] != "NONE":
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
self.iface._acknowledgment.receivedNak = True
else:
self.iface._acknowledgment.receivedAck = True
print("")
adminMessage = p["decoded"]["admin"]
if "getConfigResponse" in adminMessage:
resp = adminMessage["getConfigResponse"]
field = list(resp.keys())[0]
config_type = self.localConfig.DESCRIPTOR.fields_by_name.get(camel_to_snake(field))
config_values = getattr(self.localConfig, config_type.name)
elif "getModuleConfigResponse" in adminMessage:
resp = adminMessage["getModuleConfigResponse"]
field = list(resp.keys())[0]
config_type = self.moduleConfig.DESCRIPTOR.fields_by_name.get(camel_to_snake(field))
config_values = getattr(self.moduleConfig, config_type.name)
else:
print("Did not receive a valid response. Make sure to have a shared channel named 'admin'.")
return
for key, value in resp[field].items():
setattr(config_values, camel_to_snake(key), value)
print(f"{str(camel_to_snake(field))}:\n{str(config_values)}")
def requestConfig(self, configType):
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onResponseRequestSettings
print("Requesting current config from remote node (this can take a while).")
msgIndex = configType.index
if configType.containing_type.full_name == "LocalConfig":
p = admin_pb2.AdminMessage()
p.get_config_request = msgIndex
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
else:
p = admin_pb2.AdminMessage()
p.get_module_config_request = msgIndex
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
if onResponse:
self.iface.waitForAckNak()
def turnOffEncryptionOnPrimaryChannel(self): def turnOffEncryptionOnPrimaryChannel(self):
"""Turn off encryption on primary channel.""" """Turn off encryption on primary channel."""
@@ -87,43 +136,167 @@ 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: audio")
time.sleep(0.3)
if self.moduleConfig.remote_hardware:
p = admin_pb2.AdminMessage()
p.set_module_config.remote_hardware.CopyFrom(self.moduleConfig.remote_hardware)
self._sendAdmin(p)
logging.debug("Wrote module: remote_hardware")
time.sleep(0.3)
def writeConfig(self, config_name):
"""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)
elif config_name == 'remote_hardware':
p.set_module_config.remote_hardware.CopyFrom(self.moduleConfig.remote_hardware)
else:
our_exit(f"Error: No valid config with name {config_name}")
logging.debug(f"Wrote: {config_name}")
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
self._sendAdmin(p, onResponse=onResponse)
def writeChannel(self, channelIndex, adminIndex=0): def writeChannel(self, channelIndex, adminIndex=0):
"""Write the current (edited) channel to the device""" """Write the current (edited) channel to the device"""
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 +360,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 +393,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 +436,80 @@ 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 onResponseRequestRingtone(self, p):
"""Handle the response packet for requesting ringtone part 1"""
logging.debug(f'onResponseRequestRingtone() p:{p}')
errorFound = False
if "routing" in p["decoded"]:
if p["decoded"]["routing"]["errorReason"] != "NONE":
errorFound = True
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
if errorFound is False:
if "decoded" in p:
if "admin" in p["decoded"]:
if "raw" in p["decoded"]["admin"]:
self.ringtonePart = p["decoded"]["admin"]["raw"].get_ringtone_response
logging.debug(f'self.ringtonePart:{self.ringtonePart}')
self.gotResponse = True
def get_ringtone(self):
"""Get the ringtone. Concatenate all pieces together and return a single string."""
logging.debug(f'in get_ringtone()')
if not self.ringtone:
p1 = admin_pb2.AdminMessage()
p1.get_ringtone_request = True
self.gotResponse = False
self._sendAdmin(p1, wantResponse=True, onResponse=self.onResponseRequestRingtone)
while self.gotResponse is False:
time.sleep(0.1)
logging.debug(f'self.ringtone:{self.ringtone}')
self.ringtone = ""
if self.ringtonePart:
self.ringtone += self.ringtonePart
print(f'ringtone:{self.ringtone}')
logging.debug(f'ringtone:{self.ringtone}')
return self.ringtone
def set_ringtone(self, ringtone):
"""Set the ringtone. The ringtone length must be less than 230 character."""
if len(ringtone) > 230:
our_exit("Warning: The ringtone must be less than 230 characters.")
# split into chunks
chunks = []
chunks_size = 230
for i in range(0, len(ringtone), chunks_size):
chunks.append(ringtone[i: i + chunks_size])
# for each chunk, send a message to set the values
#for i in range(0, len(chunks)):
for i, chunk in enumerate(chunks):
p = admin_pb2.AdminMessage()
# TODO: should be a way to improve this
if i == 0:
p.set_ringtone_message = chunk
logging.debug(f"Setting ringtone '{chunk}' part {i+1}")
# If sending to a remote node, wait for ACK/NAK
if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)
def onResponseRequestCannedMessagePluginMessageMessages(self, p):
"""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 +519,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 +530,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 +565,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 +590,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 +642,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):
"""Get the node's metadata."""
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 +706,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 +765,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 +794,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 +804,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)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT! # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: portnums.proto # source: meshtastic/portnums.proto
"""Generated protocol buffer code.""" """Generated protocol buffer code."""
from google.protobuf.internal import enum_type_wrapper from google.protobuf.internal import enum_type_wrapper
from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor as _descriptor
@@ -15,7 +15,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\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\x19meshtastic/portnums.proto*\xa4\x03\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_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\010PortnumsZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_PORTNUM._serialized_start=19 _PORTNUM._serialized_start=30
_PORTNUM._serialized_end=385 _PORTNUM._serialized_end=450
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

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

View File

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

35
meshtastic/rtttl_pb2.py Normal file
View File

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

View File

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

View File

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

View File

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

View File

@@ -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'
} }

View File

@@ -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'
} }

View File

@@ -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,42 @@ class Timeout:
time.sleep(self.sleepInterval) time.sleep(self.sleepInterval)
return False return False
def waitForAckNak(self, acknowledgment, attrs=('receivedAck', 'receivedNak', 'receivedImplAck')):
"""Block until an ACK or NAK has been received. Returns True if ACK or NAK has been received."""
self.reset()
while time.time() < self.expireTime:
if any(map(lambda a: getattr(acknowledgment, a, None), attrs)):
acknowledgment.reset()
return True
time.sleep(self.sleepInterval)
return False
def waitForTraceRoute(self, waitFactor, acknowledgment, attr='receivedTraceRoute'):
"""Block until traceroute response is received. Returns True if traceroute response has been received."""
self.expireTimeout *= waitFactor
self.reset()
while time.time() < self.expireTime:
if getattr(acknowledgment, attr, None):
acknowledgment.reset()
return True
time.sleep(self.sleepInterval)
return False
class Acknowledgment:
"A class that records which type of acknowledgment was just received, if any."
def __init__(self):
"""initialize"""
self.receivedAck = False
self.receivedNak = False
self.receivedImplAck = False
self.receivedTraceRoute = False
def reset(self):
"""reset"""
self.receivedAck = False
self.receivedNak = False
self.receivedImplAck = False
self.receivedTraceRoute = False
class DeferredExecution(): class DeferredExecution():
"""A thread that accepts closures to run, and runs them as they are received""" """A thread that accepts closures to run, and runs them as they are received"""
@@ -194,7 +232,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()}')

38
meshtastic/xmodem_pb2.py Normal file
View File

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

1
proto

Submodule proto deleted from 274aa01a38

1
protobufs Submodule

Submodule protobufs added at ef83ba1d91

View File

@@ -12,16 +12,16 @@ with open("README.md", "r") as fh:
# This call to setup() does all the work # This call to setup() does all the work
setup( setup(
name="meshtastic", name="meshtastic",
version="1.3alpha.18", version="2.1.3",
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",

View File

@@ -1,5 +1,5 @@
readme.txt for single standalone executable zip files that can be readme.txt for single standalone executable zip files that can be
downloaded from https://github.com/meshtastic/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.