Compare commits

...

1635 Commits

Author SHA1 Message Date
github-actions
3c6dba78a3 bump version to 2.7.4 2025-11-06 22:50:41 +00:00
Ian McEwen
8a3b114153 protobufs: v2.7.13 2025-11-06 15:37:32 -07:00
Ian McEwen
0bb04100e1 Merge pull request #843 from SpudGunMan/channel-hash-info
Add Channel Hash Utility to Node class
2025-11-06 15:35:36 -07:00
Ian McEwen
ad04c26d13 split out constant, improve logic some, add tests for channel_hash and generate_channel_hash 2025-11-06 15:19:12 -07:00
Ian McEwen
0e67ef37aa Return hash from channel_hash function 2025-11-06 14:55:41 -07:00
Ian McEwen
e924afd140 Merge branch 'master' into channel-hash-info 2025-11-06 14:51:32 -07:00
Ian McEwen
87682c153b Merge pull request #834 from NillRudd/feat/cli-ignore-formats
CLI: normalize lora.ignore_incoming IDs (dec/!hex/0x), dedupe, YAML [] clear, fix bytes→int crash
2025-11-06 14:19:57 -07:00
Ian McEwen
e6c276fe96 Fix trailing whitespace 2025-11-06 14:17:07 -07:00
Ian McEwen
b4662251ed Merge pull request #841 from SpudGunMan/master
refactor close()
2025-11-06 13:24:59 -07:00
SpudGunMan
a17cfe9d2b rename to generate_channel_hash 2025-11-06 12:01:53 -08:00
SpudGunMan
471e3ce145 generate_hash to util 2025-11-06 12:00:16 -08:00
SpudGunMan
39c9864682 move and rename hash function
this function, xor_hash, and a variable for the default key (as bytes, I think, rather than the base64 version) really all belong in meshtastic.util rather than here.
There's multiple forms of hashing in firmware so this should be named to denote that, perhaps channel_hash. If we later want to add the frequency-slot-style hash, better if it's distinguished better from the start.
2025-11-06 11:49:57 -08:00
Niklas Roslund
1d3a7d39f7 Move to_node_num to util and updated function calls 2025-11-06 19:05:34 +01:00
Ian McEwen
2065598754 Merge pull request #825 from trose/feature/tdeck-support
Add T-Deck device support
2025-11-06 11:00:56 -07:00
Ian McEwen
4cac15686b Merge pull request #851 from pdxlocations/waypoint-icon
add icon parameter to sendWaypoint()
2025-11-06 10:28:00 -07:00
pdxlocations
9285f7d13f add waypoint parameter 2025-10-29 08:58:25 -07:00
SpudGunMan
f6f1b748dc hashGen fix
using from https://raw.githubusercontent.com/pdxlocations/mudp/refs/heads/main/mudp/encryption.py

@pdxlocations
2025-10-22 14:21:46 -07:00
SpudGunMan
d2d9c03bc8 tidy up the autobot 2025-10-22 14:19:52 -07:00
SpudGunMan
c44f9b1bb4 Add Channel Hash Utility to Node class
### Summary

- Added a new method `get_channels_with_hash()` to the `Node` class.
- This method returns a list of dictionaries, each containing the channel index, role, name, and a hash value derived from the channel name and PSK.
- The hash is calculated using the existing `generate_hash` utility, ensuring consistency with other parts of the codebase.
- This utility makes it easier to programmatically access channel metadata, including a unique hash, for scripting, debugging, or integration purposes.

### Motivation

- The protobuf `Channel` objects do not include a hash value by default.
- This addition provides a Pythonic, easy-to-use way to access channel info and a unique hash for each channel, which can be useful for diagnostics, scripting, or UI display.

### Example Usage

```python
channels = node.get_channels_with_hash()
for ch in channels:
    print(f"Index {ch['index']}: {ch['role']} name='{ch['name']}' hash={ch['hash']}")
```

### Impact

- No breaking changes; existing APIs and CLI output remain unchanged.
- The new method is additive and can be used where needed for enhanced channel introspection.
2025-10-22 10:42:54 -07:00
Kelly
6f35eb3923 Merge branch 'meshtastic:master' into master 2025-10-22 09:40:37 -07:00
Ian McEwen
dcd077d85e Merge pull request #839 from horrible-knots/master
Plumb timeout from --timeout through MeshInterface
2025-10-17 08:47:42 -07:00
SpudGunMan
da416fcd20 refactor flush
The double flush() is not the root cause; the real issue is that code is trying to use the serial port after it has been closed.
The error occurs both in close() (during flush()) and later in _writeBytes() (during write()), indicating the port is closed or invalid at those times.
2025-10-14 07:54:37 -07:00
SpudGunMan
93da1da386 flush() is only called if the stream is open
This ensures flush() is only called if the stream is open, and logs (but ignores) any exceptions during flush. This should prevent the "Bad file descriptor" error.

I see this error a lot on a rak unit, I dont know this is the way but .. you be the judge.
2025-10-14 07:42:27 -07:00
horrible-knots
2de7c30a27 Plumb timeout from --timeout through MeshInterface
Fix C0301: Line too long

Ignore the pylint for 6 positional arguments
2025-10-13 17:35:30 -04:00
Niklas Roslund
43a685f012 cli: notmalize ignore IDs for dec, hex and 0x. support YAML [] clear
Signed-off-by: Niklas Roslund <nroslund@kth.se>
2025-10-05 12:55:59 +02:00
Ian McEwen
7554c03a26 protobufs: v2.7.10 2025-09-24 21:20:49 -07:00
Taylor Rose
49783d9108 Add T-Deck device support to Meshtastic CLI
- Add T-Deck device definition with verified USB IDs (303a:1001)
- Add T-Deck to supported_devices list
- Uses t-deck firmware identifier and ESP32 device class
- Supports Linux (ttyACM), macOS (cu.usbmodem), and Windows (COM) ports
- Update .gitignore to exclude virtual environment files

T-Deck is now fully supported and automatically detected by the CLI.
2025-09-18 14:39:46 -06:00
github-actions
3615135e97 bump version to 2.7.3 2025-09-18 16:42:32 +00:00
Ian McEwen
cfb23788e1 Merge pull request #812 from shukari/loggingHandler2
Added Logging Handler Names & windows pytest support
2025-09-18 09:26:55 -07:00
Ian McEwen
14ff3eb9c4 Merge branch 'master' into loggingHandler2 2025-09-18 09:26:32 -07:00
Ian McEwen
47e5b04d3b protobufs: v2.7.9 2025-09-18 09:24:33 -07:00
github-actions
e5159f1156 bump version to 2.7.2 2025-09-12 16:49:34 +00:00
Ian McEwen
593b05dbcd protobufs: v2.7.8 2025-09-12 09:46:52 -07:00
Ian McEwen
f519d1f2d2 Merge pull request #818 from pdxlocations/check-module-bitmask
Fix Getting and Setting Excluded Modules: Ringtone and Canned Messages
2025-09-12 09:44:29 -07:00
Ian McEwen
8b36561406 Merge pull request #821 from shukari/contributionHelp
Added Github CONTRIBUTING.md file
2025-09-12 09:43:30 -07:00
shukari
e2b4948d45 Github CONTRIBUTING.md file 2025-09-09 18:17:29 +02:00
pdxlocations
7e3d347b63 remove trailing whitespaces 2025-08-29 23:19:22 -07:00
pdxlocations
c6efccdbd2 init 2025-08-29 23:11:26 -07:00
shukari
fe093ac34b fix errors and better linux/windows handling in tests 2025-08-21 15:56:10 +02:00
Ian McEwen
2b10459db0 remove dangling submodule 2025-08-20 10:13:27 -07:00
shukari
dd238dcbe3 ignore pathlib import 2025-08-19 22:03:37 +02:00
shukari
e330afc899 more paths to os.path.join 2025-08-19 13:38:59 +02:00
shukari
a63f3f6e94 use os.path.join for path 2025-08-19 11:23:22 +02:00
shukari
52eb112b95 new Parameter --debuglib for only meshtastic debug, more termios fixes for windows tests
(cherry picked from commit 4fc4d41d3d29998bb7b697bf412be5c1449ea950)
2025-08-19 11:14:38 +02:00
github-actions
d53ced216c bump version to 2.7.1 2025-08-18 19:40:36 +00:00
Ian McEwen
f5ecd28705 protobufs: v2.7.5 2025-08-18 09:52:48 -07:00
Ian McEwen
82ad9b2f51 Merge pull request #813 from pdxlocations/unmess-unmessageable
Fix --set-owner by calling setOwner!
2025-08-18 09:50:28 -07:00
shukari
cbf7b9befe pylint: test_mesh_interface.py line too long 2025-08-09 16:58:48 +02:00
shukari
f3ba660cf4 fix: lint error 2025-08-07 13:30:47 +02:00
shukari
4b143030d3 system independent path separators; pytest for windows fixes 2025-08-07 12:05:43 +02:00
pdxlocations
03aaa4c98e always call setOwner 2025-08-06 21:58:42 -07:00
shukari
a79e17a575 fix test_exit_with_exception test, pytest for windows
- test are now runable on windows, some are ignored and a fake termios for the decorators
- test_exit_with_exception with a true exception
2025-08-06 23:01:40 +02:00
shukari
38b163fa89 move logger init to the end of the import block for mesh_interface 2025-08-06 20:00:42 +02:00
shukari
af4947d020 move logger init to the end of the import block 2025-08-06 19:54:08 +02:00
shukari
db1891b651 Added Logging Handler Names 2025-08-06 18:21:32 +02:00
github-actions
d7d9c7219a bump version to 2.7.0 2025-08-01 22:56:21 +00:00
Ian McEwen
c60b5d4b05 Add some extra fields that now appear in MyNodeInfo to tests 2025-08-01 15:53:13 -07:00
Ian McEwen
83d82c518a Merge pull request #807 from pdxlocations/export-true-defaults
Export missing defaults when set False
2025-08-01 15:51:05 -07:00
Ian McEwen
8a95ce4636 protobufs: v2.7.4 2025-08-01 15:48:32 -07:00
pdxlocations
0261313fc5 add test 2025-07-27 12:10:05 -07:00
pdxlocations
c1a6234694 make tuple type hint explicit 2025-07-26 23:16:50 -07:00
pdxlocations
66e32f812a fix launch.json punctuation 2025-07-26 22:35:18 -07:00
pdxlocations
eb85439000 rename function 2025-07-26 22:27:10 -07:00
pdxlocations
885eb4898d init 2025-07-26 22:20:19 -07:00
Ian McEwen
172c123990 protobufs: v2.7.3 2025-07-22 17:26:15 -07:00
Ian McEwen
fcdd83838b Merge pull request #795 from pdxlocations/canned-config
Add Ringtone and Canned Messages to --export-config and --configure
2025-07-22 17:22:11 -07:00
Ian McEwen
58967e1d91 Merge pull request #794 from pdxlocations/is-unmessageable
add --set-is-unmessageable to CLI commands
2025-07-22 17:07:50 -07:00
pdxlocations
17f7e8e20e don't check for typoed keyword 2025-07-22 11:23:45 -07:00
pdxlocations
9b5a889676 combine arguments 2025-07-22 10:17:40 -07:00
pdxlocations
ce7c61861f Merge branch 'master' into is-unmessageable 2025-07-22 10:15:19 -07:00
Ian McEwen
4adcbb6787 Merge pull request #743 from ianmcorvidae/client-notifications
Add handling of clientNotification on FromRadio
2025-07-22 09:55:19 -07:00
Ian McEwen
125f63419e Merge branch 'master' into client-notifications 2025-07-22 09:54:17 -07:00
Ian McEwen
cad5d18aff Merge pull request #798 from pdxlocations/export-utf8
Allow forced UTF-8 encoding for --export-config
2025-07-22 09:28:14 -07:00
Ian McEwen
706d0649c1 Merge pull request #801 from Cyclic3/master
Plumb reply_id into sendText and sendData
2025-07-22 09:23:02 -07:00
Ian McEwen
167044907d for some reason pylint likes this better 2025-07-16 19:16:16 -07:00
Ian McEwen
ab1669994f Merge pull request #804 from dangerdyke/fix-vids
Add seeed xiao esp32s3 support
2025-07-16 18:44:16 -07:00
Tom Fifield
6f67f33378 Merge pull request #806 from meshtastic/fifieldt-patch-1
Add check for poetry install to regen-protobufs.sh
2025-07-17 09:05:17 +08:00
Tom Fifield
e60c8ea105 Add check for poetry install to regen-protobufs.sh
This was failing in the CI because the poetry was not initialized.
2025-07-17 10:49:23 +10:00
flockofsparrows
d633f8c895 Add seeed xiao esp32s3 to supported devices 2025-07-09 16:23:21 -04:00
Cyclic3
ca82e1ce2b plumb reply_id into sendText and sendData 2025-07-08 23:38:02 +01:00
pdxlocations
0ae23eec7e don't think i needed that 2025-06-30 00:34:44 -07:00
pdxlocations
2fa85bac1f typo 2025-06-30 00:21:15 -07:00
pdxlocations
58fc614fb7 fix test 2025-06-30 00:12:42 -07:00
pdxlocations
795b652069 export utf-8 2025-06-30 00:03:11 -07:00
rcarteraz
213faa0cae rename and move license file 2025-06-25 12:23:00 -07:00
pdxlocations
68a2009e0e add more tests 2025-06-24 11:47:33 -07:00
pdxlocations
c76e4dac87 undo comment 2025-06-24 11:17:01 -07:00
pdxlocations
428be9fbce add mesh_interface tests 2025-06-24 11:16:23 -07:00
pdxlocations
d83f7b2307 add to example config 2025-06-24 10:12:12 -07:00
pdxlocations
eb453a2e8a add to tests 2025-06-24 08:16:45 -07:00
pdxlocations
308ac93399 add to configure 2025-06-24 07:40:11 -07:00
pdxlocations
84417f0bb1 working export-config 2025-06-23 22:39:24 -07:00
pdxlocations
0bb3389b3b init 2025-06-23 22:11:50 -07:00
pdxlocations
22b3062151 remove whitespace 2025-06-23 16:37:49 -07:00
pdxlocations
373b8a3139 combine with set_owner handling 2025-06-23 16:14:59 -07:00
github-actions
db21942244 bump version to 2.6.4 2025-06-23 22:15:45 +00:00
Ian McEwen
c55f1ef610 Merge pull request #782 from Crank-Git/validate-short-and-long-names
Add validation/prevent --set-owner, --set-owner-short, and --set-ham from accepting empty or whitespace-only names
2025-06-23 09:15:47 -07:00
pdxlocations
51b543ff40 add tests 2025-06-21 18:16:24 -07:00
pdxlocations
8752a0de6e remove whitespace 2025-06-21 16:25:48 -07:00
pdxlocations
7160e79fbf more not incorrect spelling 2025-06-21 13:51:58 -07:00
pdxlocations
b73fcbff88 didn't spell it wrong 2025-06-21 13:50:30 -07:00
pdxlocations
1b5b07e752 add --set-is-unmessageable 2025-06-21 13:44:25 -07:00
Ian McEwen
ab997aac84 Merge pull request #790 from ianmcorvidae/sendMqttClientProxyMessage
Add a sendMqttClientProxyMessage helper for client proxy implementation
2025-06-16 12:48:47 -07:00
Ian McEwen
a097161dbc Add a sendMqttClientProxyMessage helper for client proxy implementation 2025-06-16 12:45:25 -07:00
Ian McEwen
e6750507c8 protobufs: v2.6.12 2025-06-16 12:22:31 -07:00
Ian McEwen
0deb98b4c6 Merge pull request #785 from grleblanc/master
fix(util): update waitForTraceRoute reset logic
2025-06-09 16:22:45 -07:00
grleblanc
04a0ff6322 fix(util): fix typo 2025-06-09 15:50:21 -04:00
grleblanc
b4764d3bc3 fix(util): update waitForTraceRoute reset logic 2025-06-09 15:05:53 -04:00
Ian McEwen
9281c4a335 Correctly call self.close() in disconnected_callback for bleak (fixes #770) 2025-06-09 11:52:23 -07:00
Ben Meadors
3c2dd6f4ff Merge pull request #783 from pdxlocations/config-work
Fix --configure by adding delays after sections
2025-06-09 05:37:25 -05:00
pdxlocations
8e48d141c8 add sleeps 2025-06-08 23:32:32 -07:00
Crank-Git
8a6ee5fb35 fixed assertion errors by replace ham id with ham radio callsign, fixed _sendAdmin assertion 2025-06-08 20:39:26 -04:00
Crank-Git
aa786c7ebd Fix linting errors and duplicate function 2025-06-08 19:51:21 -04:00
Crank-Git
23be2d2189 Add validation/prevent --set-owner, --set-owner-short, and --set-ham from accepting empty or whitespace-only names. This is in relation to meshtastic#6867 firmware feature request https://github.com/meshtastic/firmware/issues/6867 2025-06-08 18:16:49 -04:00
Ian McEwen
622a435465 Add __repr__ methods to interface types and Node, for nicer printing/logging 2025-05-08 21:23:00 -07:00
github-actions
56680f8da6 bump version to 2.6.3 2025-05-08 22:27:56 +00:00
Ian McEwen
321a960c13 protobufs: v2.6.7 2025-05-08 15:26:47 -07:00
Ian McEwen
4668852b0b Admin messages should be requesting acknowledgements 2025-05-08 15:22:27 -07:00
github-actions
c3973117c8 bump version to 2.6.2 2025-04-23 16:49:59 +00:00
Ian McEwen
d456e4ce30 protobufs: v2.6.6 2025-04-23 09:47:13 -07:00
Ben Meadors
ec78f62992 Merge pull request #763 from meshtastic/revert-753-fix-rtsdtr-windows
Revert "Work around RTS/DTR serial reset issues on Windows"
2025-04-15 16:37:23 -05:00
Ben Meadors
dfc9547ffc Revert "Work around RTS/DTR serial reset issues on Windows" 2025-04-15 16:03:33 -05:00
Ian McEwen
ee0f73a20e Merge pull request #761 from derekn/master
fixing tcp_interface 100% cpu usage bug (#709)
2025-04-15 13:56:28 -07:00
Derek Nicol
2e73fe310c fixing tcp_interface 100% cpu usage bug (#709) 2025-04-15 15:23:09 -05:00
Ian McEwen
d4bc39153a bump to 2.6.2a0 2025-04-05 23:01:43 -07:00
github-actions
2e8f823431 bump version to 2.6.1 2025-04-06 05:56:17 +00:00
Ian McEwen
675169167c protobufs: v2.6.4 2025-04-05 22:53:02 -07:00
Ian McEwen
75f8e27799 Merge pull request #749 from cdanis/fix-default-pytest
Fix pytest test collection on default install
2025-03-30 22:28:28 -07:00
Ian McEwen
f426699d2b Merge pull request #753 from dwhinham/fix-rtsdtr-windows
Work around RTS/DTR serial reset issues on Windows
2025-03-30 22:27:34 -07:00
Dale Whinham
bc1664dade Work around RTS/DTR serial reset issues on Windows
Some devices (e.g. Heltec V3.1) are reset when the RTS or DTR pins are
messed with, which means that without workarounds, Meshtastic CLI will
cause a reset with any operation that opens the serial port.

This behavior is documented in this PySerial issue:
https://github.com/pyserial/pyserial/issues/124

On Linux, we already handle this by disabling the HUPCL termios flag,
which has the effect of preventing the offending lines being toggled. On
Windows, setting the initial state of RTS and DTR before opening the
port has a similar effect.

Implement this workaround so that Meshtastic CLI can be used on Windows
with these devices.
2025-03-20 13:47:25 +00:00
Ian McEwen
32a61b0209 Make nanopb.proto stuff work right again, hopefully 2025-03-12 14:13:43 -07:00
github-actions
0c38a9eb0b bump version to 2.6.0 2025-03-10 23:18:47 +00:00
Ian McEwen
e591cc184f set 2.6 version num 2025-03-10 16:17:40 -07:00
Chris Danis
b42d33824a Fix pytest test collection on default install
As is, with a default `poetry install`, a simple `poetry pytest run`
will encouter import errors while reading the test files themselves --
which causes pytest to fatally error during test collection, meaning no
tests are run.
2025-03-07 13:16:20 -05:00
rcarteraz
ed908fc4b6 Merge pull request #748 from rcarteraz/master
update README
2025-03-03 11:44:08 -07:00
rcarteraz
3710e6e909 update README 2025-03-03 11:42:15 -07:00
Ian McEwen
faa8064ccc protobufs: v2.6.0 2025-03-02 12:14:20 -07:00
Ian McEwen
2f44351945 Merge pull request #742 from ianmcorvidae/multiset
Enable setting things from more than one configuration section with `--set`, using a configuration transaction.
2025-02-21 10:08:15 -07:00
Ian McEwen
f5fa30cb22 try to get pylint happier 2025-02-20 12:40:39 -07:00
Ian McEwen
46a8db286c Add handling of clientNotification on FromRadio, sending a pubsub message 2025-02-20 12:36:21 -07:00
Ian McEwen
852949575b Enable setting things from more than one configuration section with --set, using a configuration transaction. 2025-02-20 11:39:16 -07:00
github-actions
e2c9c1315e bump version to 2.5.12 2025-02-19 17:21:25 +00:00
Ian McEwen
f41ef042a9 Merge pull request #708 from mikeymakesit/add-channel
Add new channels from an add URL with the new --ch-add-url option
2025-02-19 10:18:09 -07:00
Ian McEwen
84bec5a7c4 fix up misc. lint/type/test issues, streamline, align argument names and groupings 2025-02-19 10:15:27 -07:00
Ian McEwen
985366c812 Merge pull request #710 from digitaldisarray/master
Add text message port cli option
2025-02-19 09:55:01 -07:00
Ian McEwen
3954fbd404 fix misc lint, test, type complaints from CI 2025-02-19 09:52:16 -07:00
Ian McEwen
5f174b2850 Merge pull request #731 from migillett/464/0x-prefix
464: allow for 0x node prefix values
2025-02-19 09:30:15 -07:00
Michael Gillett
23ea19c00b linter fixes following failed build 2025-02-19 11:26:49 -05:00
Ian McEwen
acc47146c9 Merge pull request #736 from dandrzejewski/master
Add optional CLI parameter to specify node info fields to show with --nodes parameter.
2025-02-19 09:26:17 -07:00
Ian McEwen
dd8803793d fix test mock 2025-02-19 09:21:51 -07:00
Ian McEwen
68ec588804 remove trailing whitespace 2025-02-19 09:15:45 -07:00
David Andrzejewski
2f48594dc3 Fix a pylint error regarding typing. 2025-02-18 22:09:37 -05:00
David Andrzejewski
c7c3c69fc3 Fix a pylint error regarding typing. 2025-02-18 22:08:26 -05:00
David Andrzejewski
53e40d5aab Fix a pylint error 2025-02-18 22:05:46 -05:00
David Andrzejewski
dd3da6a670 Merge remote-tracking branch 'origin/master' 2025-02-18 21:18:59 -05:00
David Andrzejewski
e500b399f4 Merge branch 'meshtastic:master' into master 2025-02-18 21:18:48 -05:00
David Andrzejewski
27ac28e300 Fixing indentation per project coding standards. 2025-02-18 21:18:22 -05:00
David Andrzejewski
6bc5f5e305 Fix count vs len on a list (https://github.com/meshtastic/python/pull/736#discussion_r1960099918) 2025-02-18 21:15:31 -05:00
Michael Gillett
c844e4e0fe help details for new prefix values 2025-02-18 15:25:24 -05:00
Michael Gillett
060df86bb6 Update __main__.py 2025-02-18 15:10:55 -05:00
Michael Gillett
7d87d5037e Update __main__.py 2025-02-18 15:10:26 -05:00
Michael Gillett
4ec7698d94 metavars being a PAIN 2025-02-18 15:09:59 -05:00
Michael Gillett
7cc65aa08a missed one 2025-02-18 15:06:20 -05:00
Michael Gillett
cc411ce0bb remove nargs and unneeded fstrings 2025-02-18 15:05:31 -05:00
Michael Gillett
edff956f9d specify nargs 2025-02-18 14:53:01 -05:00
Michael Gillett
bd68739158 >= 8 instead of > 8 2025-02-18 14:30:28 -05:00
Michael Gillett
530d92ead2 remove redundant f string 2025-02-18 14:24:04 -05:00
Michael Gillett
60f9dc6266 new implementation 2025-02-18 14:23:55 -05:00
Michael Gillett
f9ae021e43 remove old implementation 2025-02-18 14:23:40 -05:00
Michael Gillett
317d81c983 list -> tuple fix for pytest 2025-02-18 14:02:48 -05:00
Ian McEwen
5837bd0172 Merge pull request #734 from dudash/master
catch unhandled OSError when serial port in use
2025-02-18 09:52:03 -07:00
Ian McEwen
5487f7a791 Merge pull request #735 from tache/master
Added descriptive FileNotFoundError handler for serial device connection
2025-02-18 09:51:17 -07:00
Ian McEwen
c6d8a540eb Bump to 2.5.12a0 2025-02-18 09:43:55 -07:00
Ian McEwen
0962c9b058 protobufs: v2.5.22 2025-02-18 09:43:32 -07:00
Ian McEwen
4f98602ac2 ignore argcomplete import in main 2025-02-18 09:41:54 -07:00
David Andrzejewski
6ebddb67c0 Refactored showNodes. It now uses a lookup table to determine the human-readable names of the fields. 2025-02-15 17:18:14 -05:00
David Andrzejewski
82554a1f18 Add optional parameter to specify what fields to show with --nodes 2025-02-15 02:23:13 -05:00
tache
8c115dc636 Added descriptive FileNotFoundError handler for serial device connection
- Added a detailed error message for FileNotFoundError when the serial device is not found.
- Included troubleshooting steps for common issues.
2025-02-09 14:23:31 -05:00
dudash
e2fe359527 catch unhandled OSError when serial port in use 2025-02-08 14:51:53 -05:00
Michael Gillett
5600ce92b0 update to comments 2025-01-26 13:10:56 -05:00
Michael Gillett
efb848adf9 comments explaining logic 2025-01-26 12:58:18 -05:00
Michael Gillett
0d8646189f remove logging.info used for local debugging 2025-01-26 12:56:17 -05:00
Michael Gillett
d0023df8ca slight logic rework 2025-01-26 12:55:03 -05:00
Michael Gillett
b522abf33e update docs 2025-01-26 12:06:31 -05:00
Michael Gillett
c086b6372e Update mesh_interface.py 2025-01-26 11:58:48 -05:00
github-actions
6ec506fe3b bump version to 2.5.11 2025-01-24 17:22:13 +00:00
Ian McEwen
fc3b81dfde protobufs: v2.5.20 2025-01-24 10:19:13 -07:00
Ben Meadors
9c53ea017c Merge pull request #730 from migillett/feature/nodes-add-role
#692 feature/nodes-add-role
2025-01-23 19:07:46 -06:00
Michael Gillett
1e6625d062 feature/nodes-add-role 2025-01-21 22:31:33 -05:00
github-actions
0487ce5e1a bump version to 2.5.10 2025-01-10 17:10:16 +00:00
Ian McEwen
aac19b2ecc protobufs: v2.5.19 2025-01-10 10:06:40 -07:00
digitaldisarray
0fb72b8ad1 Only allow PRIVATE_APP custom port 2024-12-31 15:15:18 -08:00
github-actions
872fbef5d6 bump version to 2.5.9 2024-12-29 03:22:52 +00:00
Ian McEwen
ec4fbe3a59 protobufs: v2.5.18 2024-12-28 20:18:13 -07:00
Ian McEwen
6bab385380 Tweak error messaging in the onReceive function for sendtext packets 2024-12-27 10:04:36 -07:00
Ian McEwen
b8178d513a bump alpha version 2024-12-27 09:54:15 -07:00
Ian McEwen
f4c085fc50 Merge pull request #714 from loic-fejoz/feature/waypoint
Waypoint creation/move/deletion
2024-12-27 09:46:45 -07:00
Ian McEwen
57f0598082 Fix some pylint complaints 2024-12-27 09:40:17 -07:00
github-actions
55d3188408 bump version to 2.5.8 2024-12-27 12:06:45 +00:00
Ben Meadors
7b64fbb71b Merge pull request #725 from meshtastic/dependabot/pip/jinja2-3.1.5
Bump jinja2 from 3.1.4 to 3.1.5
2024-12-25 08:42:58 -06:00
dependabot[bot]
7f85eb0285 Bump jinja2 from 3.1.4 to 3.1.5
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.4...3.1.5)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-24 00:32:14 +00:00
Ben Meadors
d05ef17ab3 Merge pull request #724 from meshtastic/send-alert
Add sendAlert method on mesh interface
2024-12-23 10:48:49 -06:00
Ben Meadors
d161291ca4 Add sendAlert method on mesh interface 2024-12-22 09:09:54 -06:00
Ian McEwen
4e267c75b0 bump to 2.5.8a0 2024-12-21 20:49:32 -07:00
github-actions
f56b9eefa6 bump version to 2.5.7 2024-12-22 03:46:10 +00:00
Ian McEwen
2de1f1921c Merge pull request #723 from ianmcorvidae/add-wcwidth-optional
Add 'wcwidth' as an optional cli dependency
2024-12-21 20:32:47 -07:00
Ian McEwen
227507780e Add 'wcwidth' as an optional cli dependency
Fixes #598 when installed as meshtastic[cli], as should now be
recommended by documentation.
2024-12-21 20:29:07 -07:00
Ian McEwen
9f286c9023 Merge pull request #721 from ianmcorvidae/shell-completion
Add very simple shell completion using argcomplete
2024-12-21 20:26:06 -07:00
Ian McEwen
0b1545393e Make mypy happy with the optional import of argcomplete 2024-12-21 20:23:35 -07:00
Ian McEwen
245a9e40b1 Add very simple shell completion using argcomplete 2024-12-21 20:12:26 -07:00
Ian McEwen
749c6a70bc Merge pull request #720 from ianmcorvidae/winserver-fix
Fix windows-11 detection for non-float platform.release() values
2024-12-21 14:22:55 -07:00
Ian McEwen
afd071c24e Fix windows-11 detection for non-float platform.release() values (fixes #639) 2024-12-21 14:17:41 -07:00
Ian McEwen
29f355bd61 Merge pull request #719 from ianmcorvidae/ignore-nodes
Support setting nodes ignored in nodedb (with 2.5.13+ firmware)
2024-12-21 13:50:44 -07:00
Ian McEwen
4b6d7a8587 Support setting nodes ignored in nodedb (with 2.5.13+ firmware) 2024-12-21 13:46:17 -07:00
Loïc Fejoz
7cc18e9df6 fix(waypoint): Missing methods
Add missing methods callbacks regarding waypoints.
2024-12-21 10:36:36 +01:00
Ian McEwen
a765bccf4d Merge pull request #718 from ianmcorvidae/show-unknown-more-nicely
Display unknown hop count as '?', and header as just 'Hops'
2024-12-20 23:08:19 -07:00
Ian McEwen
f950ecae2d Display unknown hop count as '?', and header as just 'Hops' 2024-12-20 23:04:36 -07:00
Ian McEwen
7c7170a5dd Merge pull request #706 from meshtastic/dependabot/pip/tornado-6.4.2
Bump tornado from 6.4.1 to 6.4.2
2024-12-20 22:50:01 -07:00
Ian McEwen
df191e149b Merge pull request #713 from esev/favorite
Support setting/removing nodes as favorites
2024-12-20 22:36:23 -07:00
Ian McEwen
843abe587f Back out release workflow changes from hotfix 2024-12-20 14:59:26 -07:00
Ian McEwen
ff7dcc3afb Merge branch '2.5.6-hotfix' 2024-12-20 14:47:52 -07:00
Ian McEwen
d66b8fa9dd fix import-related errors 2024-12-20 14:45:54 -07:00
Ian McEwen
f6f8ccfcbc Fix message_to_json_shows_all test for added MyNodeInfo fields 2024-12-20 13:51:27 -07:00
Ian McEwen
cace959ca4 Update protobufs (to 2.5.17) and main python version (to 2.5.7) 2024-12-20 13:45:58 -07:00
github-actions
01ffd83d64 bump version to 2.5.6 2024-12-20 20:42:21 +00:00
Loïc Fejoz
9284a848f2 feat(waypoint): Waypoint creation/deletion
Add methods to send (create or move), delete waypoint.
Add an example script to create, move, delete waypoint.
2024-12-18 17:36:58 +01:00
Eric Severance
18ac0d6d5c Support setting/removing nodes as favorites 2024-12-17 17:38:51 -08:00
Ian McEwen
7c89e231bd Merge pull request #711 from ianmcorvidae/optionalize-deps
Make several dependencies optional (dotmap, print_color, and pyqrcode)
2024-12-12 21:19:15 -07:00
Ian McEwen
4673824236 Add the newly optional dependencies to an extras group 2024-12-12 21:14:58 -07:00
Ian McEwen
d87eddfd33 Make pyqrcode optional 2024-12-12 21:01:38 -07:00
Ian McEwen
31f322f1c2 Make dotmap (via meshtastic.test) and print_color optional 2024-12-12 20:59:22 -07:00
Ian McEwen
89b41c1a19 Remove pexpect too 2024-12-12 20:40:59 -07:00
Ian McEwen
1a5ca789c2 Remove pyparsing and webencodings dependencies, unsure why they're here at all 2024-12-12 19:48:29 -07:00
digitaldisarray
74c911cb75 Add text message port cli option 2024-12-06 17:54:08 -08:00
Mike Hornung
579383cd5a Add new channels from an add URL with the new --ch-add-url option 2024-12-01 23:33:47 -08:00
Ian McEwen
03ac322583 reset mypy-protobuf to non-optional, hopefully without breaking stuff 2024-11-26 14:35:48 -07:00
Ian McEwen
c63814358a prep 2.5.6a0 & protobufs 2024-11-26 14:31:33 -07:00
github-actions
663fabce74 bump version to 2.5.5 2024-11-26 21:22:11 +00:00
Ian McEwen
6243965044 Merge pull request #707 from meshtastic/request-localstats
Allow request-telemetry to elicit LocalStats response
2024-11-24 11:31:01 -07:00
Ben Meadors
b180b6fb15 Allow request-telemetry to illicit LocalStats response 2024-11-24 08:19:40 -06:00
dependabot[bot]
7bb8e4e9dd Bump tornado from 6.4.1 to 6.4.2
Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.4.1 to 6.4.2.
- [Changelog](https://github.com/tornadoweb/tornado/blob/v6.4.2/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.4.1...v6.4.2)

---
updated-dependencies:
- dependency-name: tornado
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-22 22:17:33 +00:00
Ian McEwen
4c7ac60be6 appease mypy too 2024-11-15 11:55:25 -07:00
Ian McEwen
0b086d10f8 appease pylint 2024-11-15 11:50:35 -07:00
Ian McEwen
426795fccd semi-experimentally, add fallback code for message_to_json, allowing older protobuf library versions 2024-11-15 11:47:17 -07:00
Ian McEwen
fb88ee114c bump protobufs to 2.5.5 2024-11-01 09:06:02 -07:00
github-actions
a4630b53eb bump version to 2.5.4 2024-11-01 16:03:00 +00:00
Ian McEwen
646aa981d5 update readme to link to docs again 2024-10-29 14:22:09 -07:00
Ian McEwen
9381acd6ac Merge pull request #681 from william-stearns/wls_add_types2
Wls add types2
2024-10-29 06:50:52 -07:00
Ian McEwen
384063db19 Fix some remaining mypy complaints 2024-10-29 06:47:16 -07:00
Ian McEwen
20d75d9023 Merge branch 'master' into wls_add_types2 2024-10-29 06:19:16 -07:00
Ian McEwen
0deb1d788f Merge pull request #702 from meshtastic/dependabot/pip/werkzeug-3.0.6
Bump werkzeug from 3.0.4 to 3.0.6
2024-10-28 20:36:24 -07:00
Ian McEwen
1070d9202b Merge pull request #698 from lachesis/lachesis/fix-remote-module-cfg-get
Add missing camel to snake conversion
2024-10-28 20:35:10 -07:00
Ian McEwen
b90de8b73b Merge pull request #701 from fmoessbauer/master
A lot of fixes around setting / retrieving base64 encoded values
2024-10-28 20:29:05 -07:00
dependabot[bot]
2e79ecf759 Bump werkzeug from 3.0.4 to 3.0.6
Bumps [werkzeug](https://github.com/pallets/werkzeug) from 3.0.4 to 3.0.6.
- [Release notes](https://github.com/pallets/werkzeug/releases)
- [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/werkzeug/compare/3.0.4...3.0.6)

---
updated-dependencies:
- dependency-name: werkzeug
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-26 00:29:31 +00:00
Felix Moessbauer
578d3e4b24 do not double-print value when setting a repeated value
When clearning or appending to a repeated value, both the "Clearing..."
/ "Adding..." line and the "Set..." line were shown. However, this is
misleading as the only performed operation is the clearing / appending.

We fix this by directly returning from the function in case of clearing
/ appending.
2024-10-25 17:11:06 +02:00
Felix Moessbauer
4ca13bcede fix setting of list item on configure
When setting the whole configuration via --configure, list types like
adminKey need special handling. Previously this failed as a list cannot
be appended to a list. The new code adds dedicated logic to replace the
repeated value when passing a list. Also, all items of that list are
converted into the correct (typed) form before setting them.
2024-10-25 17:11:06 +02:00
Felix Moessbauer
6ceae7c72f setPref: pass typed value instead of string
By passing a typed value we can conserve the type information to later
use that to convert it back into the correct protobuf type. The type
conversion is now done inside setPref.
2024-10-25 17:11:06 +02:00
Felix Moessbauer
4c29d7dd0f refactor camel and snake naming in setPref
Same change as done in getPerf to have less branches (simplifies the
code).
2024-10-25 17:11:06 +02:00
Felix Moessbauer
839bbbcad2 config: correctly print byte and array types on get
When getting config values of type bytes or list (technically a protobuf
repeated container type), these were directly printed on the output.
However, the retrieved values could not be set by --set again, as the
format was different (e.g. python string representation of bytes vs.
base64 prefixed and encoded as expected by --set).

We fix this by adding a toStr utility function (similar to the fromStr)
function to convert byte types correctly to the base64 representation.
Further, we check if the type is repeated and apply this operation to
all values.
2024-10-25 17:11:06 +02:00
Felix Moessbauer
1abb9fb213 refactor getPref to use uniform printing logic
We add a local helper function to print a single setting. This is a
preparation to correctly print non-trivial types. The existing code
in getPref is ported over to use that function. By that, the output
of "wholeField" is changed slightly to always print the full path for
each setting (e.g. "security.serialEnabled" instead of
"security:\nserialEnabled"). This improves support for grepping on the
output.
2024-10-25 17:11:06 +02:00
Felix Moessbauer
7fcbbe9b80 refactor camel and snake naming in getPref
We have a lot of code duplication by checkin over and over again if
field should be named in camel or snake notation. We simplify this by
writing the choosen variant into a variable and just use that name
across the code.

No functional change.
2024-10-25 14:13:50 +02:00
Eric Swanson
073274cb00 Add missing camel to snake conversion 2024-10-21 22:06:43 -04:00
Ian McEwen
92a3986a8f Improve comments for pdoc 2024-10-21 16:39:47 -07:00
github-actions
f08ec1885b bump version to 2.5.3 2024-10-18 17:02:53 +00:00
Ian McEwen
feca49faed Merge pull request #696 from fmoessbauer/master
fix base64 encoding of key field in config
2024-10-18 09:57:13 -07:00
Felix Moessbauer
dfaf1a275d fix base64 encoding of key field in config
The security.privateKey and security.publicKey fields are of type bytes,
but the protobuf MessageToDict converts them to base64 encoded strings.
When importing the config again, this is read as a string, which breaks
the import. Instead, the value needs to be prefixed with "base64:", so
the type handling logic on import kicks in and decodes the value to a
bytes array again.

Fixes: #678
2024-10-18 16:13:25 +02:00
Ian McEwen
da7fa31805 tweak documentation formatting 2024-10-16 20:52:10 -07:00
Ian McEwen
12fd29b203 Merge pull request #694 from ianmcorvidae/configure-fixed-position
Use dedicated fixed position admin message for --configure
2024-10-16 16:01:06 -07:00
Ian McEwen
a43dd201ba Merge pull request #695 from ianmcorvidae/ble-disconnect
Send the meshtastic.connection.lost message from BLEInterface's close method
2024-10-16 16:00:49 -07:00
Ian McEwen
a64a9d203a Send the meshtastic.connection.lost message from BLEInterface's close method 2024-10-16 12:13:30 -07:00
Ian McEwen
10136962d7 Use dedicated fixed position admin message for --configure 2024-10-15 07:28:55 -07:00
Ian McEwen
3afb294f9b Merge pull request #691 from logikal/telemetry_output
autoprint other types of telemetry when returned from --request-telemetry
2024-10-14 17:11:00 -07:00
Sean Kilgore
ee405fec41 autoprint other types of telemetry when returned from --request-telemetry 2024-10-14 16:58:52 -07:00
Ian McEwen
3eabaf91d0 Merge pull request #687 from ianmcorvidae/telemetry-types
Support requesting different telemetry types
2024-10-13 21:50:04 -07:00
Ian McEwen
78b92cecc9 fix type check 2024-10-13 20:40:22 -07:00
Ian McEwen
7088b90514 Support requesting different telemetry types 2024-10-13 20:35:11 -07:00
Ian McEwen
2ae81f8602 Merge pull request #686 from jose1711/typofix
Fix typo.
2024-10-13 18:00:16 -07:00
Jose Riha
923f5e82d0 Fix typo. 2024-10-14 02:48:41 +02:00
Ian McEwen
05731128fa missed a spot 2024-10-12 12:52:36 -07:00
Ian McEwen
0523d4c94f disable R0917 pylint failures 2024-10-12 12:49:14 -07:00
Ian McEwen
90e901de79 Upgrade bleak and therefore also the supported python versions 2024-10-12 12:32:43 -07:00
Ian McEwen
6606851135 Merge pull request #685 from ianmcorvidae/more-telemetry
Add other telemetry variants to automatic handling/adding to node information
2024-10-12 11:59:45 -07:00
Ian McEwen
33fecbd74d Add other telemetry variants to automatic handling/adding to node information 2024-10-12 11:56:55 -07:00
Ian McEwen
6b9db7abd9 2.5.3 setup 2024-10-12 09:33:28 -07:00
github-actions
ece6286d82 bump version to 2.5.2 2024-10-12 16:31:48 +00:00
William Stearns
e335f12a3b attempts to fix mypy issues 2024-10-11 00:59:02 -04:00
William Stearns
0da405168f pylint cleanups 2024-10-10 23:49:20 -04:00
William Stearns
58d9039a04 another missing import 2024-10-10 16:49:06 -04:00
William Stearns
f77e788aa8 fix missing import 2024-10-10 16:33:07 -04:00
William Stearns
aba381fb54 Merge branch 'master' into wls_add_types 2024-10-08 23:28:25 -04:00
Ian McEwen
0bb4b31b6a Merge pull request #679 from ianmcorvidae/argument-groups
Add a number of argument groups to organize the help output
2024-10-03 19:45:13 -07:00
Ian McEwen
915066e0af add metavars for a bunch of arguments for nicer docs 2024-10-03 19:45:03 -07:00
Ian McEwen
6be3969577 Add a number of argument groups to organize the help output 2024-10-01 18:10:14 -07:00
Ian McEwen
b73cc1f499 Make it so wantconfig isn't a 1 in 4294967296 lottery for getting no nodes 2024-10-01 14:00:06 -07:00
Ian McEwen
65305af184 protobufs/alpha version: 2.5.2 2024-09-29 14:34:53 -07:00
github-actions
3fb1e67357 bump version to 2.5.1 2024-09-29 21:30:36 +00:00
Ian McEwen
cbd3c119fe Fix pylint errors 2024-09-28 20:15:08 -07:00
Ian McEwen
bbd6d6a541 Change order of logging and parsing fromRadioBytes, and add a bit more traceback logging at that point 2024-09-28 20:11:52 -07:00
Ian McEwen
6e1217c7ca Merge pull request #677 from ianmcorvidae/pkiencrypted_admin
Default to pkiEncrypted always on for admin messages
2024-09-28 18:40:31 -07:00
Ian McEwen
81db38956b Silence pylint 2024-09-28 18:37:05 -07:00
Ian McEwen
27729995d2 Default to pkiEncrypted always on for admin messages 2024-09-28 11:13:04 -07:00
Ian McEwen
d875a574b6 Merge pull request #676 from ianmcorvidae/set-time
Add a --set-time command that set's the node time using a provided timestamp or the host system clock
2024-09-22 10:06:09 -07:00
Ian McEwen
40019a9712 Add a --set-time command that set's the node time using a provided timestamp or the host system clock. 2024-09-22 09:32:04 -07:00
Ian McEwen
de657bab24 Merge pull request #675 from djholt/feature/remote-config-position
Enable setting and removing fixed position via remote admin
2024-09-19 11:24:23 -07:00
DJ Holt
40353a387e Fix tests for remote position configs 2024-09-19 03:31:01 -06:00
DJ Holt
9949d144a1 Enable setting and removing fixed position via remote admin 2024-09-19 02:39:49 -06:00
Ian McEwen
48a06c6e1e protobufs & alpha version number: v2.5.1 2024-09-18 14:58:05 -07:00
Ian McEwen
c696d59b90 Set list-type keys differently, excluding 0-like values and resetting whole list 2024-09-17 21:52:57 -07:00
Ian McEwen
4fdbcb9679 Fix test_fuzz_fromStr for floats 2024-09-17 21:10:57 -07:00
Ian McEwen
5d6dfb877b Merge pull request #673 from djholt/feature/tcp-port
Allow port number to be specified with tcp hostname
2024-09-17 21:08:03 -07:00
Ian McEwen
951edfe27b Merge pull request #665 from lysol/remote-admin-retry
Retry admin channel setting retrieval and add configurable timeout
2024-09-17 21:06:38 -07:00
DJ Holt
5cc9627e21 Refactor default port number to variable 2024-09-16 23:41:44 -06:00
DJ Holt
bf904c6906 Allow port number to be specified with tcp hostname 2024-09-16 23:24:03 -06:00
Derek Arnold
2026212a00 please pylint with a docstring and newline 2024-09-15 16:27:40 -05:00
Derek Arnold
34f9be255e fix unrelated bug when fromStr input is short hex
For example, 0x0 will generate an unhandled ValueError. This was caught
during a random unit test run for 3.9, so I figure I'd fix it.

This is unrelated to the PR otherwise.
2024-09-15 16:20:50 -05:00
Derek Arnold
e561222ea7 add docstrings 2024-09-15 16:06:44 -05:00
Derek Arnold
73a1bbc7d5 add test coverage for changes to requestChannels 2024-09-15 16:02:59 -05:00
Derek Arnold
8f2c397fbf missed one reference for requestChannelRetries 🤡 2024-09-15 14:01:41 -05:00
Derek Arnold
62f5201a38 Add test covering retry logic 2024-09-15 12:04:22 -05:00
Derek Arnold
9e7d5e96ab Rename "retries" to "attempts"
Otherwise, semantically, it's off-by-one.
2024-09-15 12:03:51 -05:00
Derek Arnold
aa74db46cb update message check in test to reflect new message 2024-09-15 11:59:03 -05:00
Derek Arnold
1967519deb correct type issue during initial assignment 2024-09-15 11:52:27 -05:00
Derek Arnold
662aea049a Merge branch 'master' into remote-admin-retry 2024-09-15 11:46:32 -05:00
Derek Arnold
44cfd72a80 make sure new_index is always an int 2024-09-15 11:39:10 -05:00
Derek Arnold
abe1dd47ca add type to argument 2024-09-15 11:36:23 -05:00
Ian McEwen
584a14f578 Merge pull request #668 from ianmcorvidae/channel-preset-optimize
Change modem preset shortcuts to not request channels, and to request remote config when needed
2024-09-12 16:20:59 -07:00
github-actions
f7724295f9 bump version to 2.5.0 2024-09-12 16:27:45 +00:00
Ian McEwen
cc2067b729 clean up settings response to use CopyFrom to be better at repeated and nested fields 2024-09-11 17:10:04 -07:00
Ian McEwen
180ddbcd1a Merge pull request #672 from ianmcorvidae/detect-repeating
Detect repeating fields using field labels, enabling admin key to be set
2024-09-11 16:36:29 -07:00
Ian McEwen
3bbd02c915 Detect repeating fields using field labels, enabling admin key to be set 2024-09-11 16:34:03 -07:00
Ian McEwen
23e6eca056 Merge pull request #671 from ianmcorvidae/factory-reset-update
Split factory reset into two variants
2024-09-11 09:43:16 -07:00
Ian McEwen
21ff4a1a4a Split factory reset into two variants 2024-09-11 09:40:26 -07:00
Ian McEwen
ef6db0e48c Merge branch 'master' into 2.5 2024-09-11 09:21:01 -07:00
Ian McEwen
43b0993aaa Merge branch 'master' into 2.5 2024-09-11 09:19:43 -07:00
github-actions
9423a8a8b9 bump version to 2.4.3 2024-09-11 16:16:12 +00:00
Ian McEwen
33a13f715e 2.4.3 prep (protobufs, alpha version) 2024-09-11 09:12:41 -07:00
github-actions
0aac077ce7 bump version to 2.4.2 2024-09-11 16:05:25 +00:00
Ian McEwen
8ba92da7cf Change modem preset shortcuts to not request channels, and to request remote config when needed 2024-09-06 23:38:52 -07:00
Ian McEwen
0d26c26f7e update protobufs to master 2024-09-06 23:13:31 -07:00
Ian McEwen
aa6f09635a Merge pull request #661 from meshtastic/dependabot/pip/jupyterlab-4.2.5
Bump jupyterlab from 4.2.3 to 4.2.5
2024-09-06 11:30:17 -07:00
Ian McEwen
83b0dcad56 Merge pull request #667 from ianmcorvidae/telemetry-updating
Update telemetry in interface.nodes on receiving device metrics packets
2024-09-06 11:10:17 -07:00
Ian McEwen
78d8403bbd Update telemetry in interface.nodes on receiving device metrics packets 2024-09-06 00:08:20 -07:00
Ian McEwen
0813e8dba6 protobufs: v2.4.2; bump to alpha version 2024-09-05 14:27:38 -07:00
github-actions
23bb2e26f9 bump version to 2.4.1 2024-09-05 21:22:03 +00:00
Ian McEwen
399dd477b8 Merge branch 'master' into 2.5 2024-09-05 14:00:35 -07:00
Ian McEwen
b59ecff272 Merge pull request #666 from ianmcorvidae/fix-set-owner
Ensure set-owner combined with set-owner-short sets both values
2024-09-05 13:58:36 -07:00
Ian McEwen
17f3605736 Ensure set-owner combined with set-owner-short sets both values 2024-09-05 13:58:02 -07:00
Ian McEwen
a689fd73a2 Deprecate --no-time and remove behavior, followup to #663 2024-09-05 13:49:28 -07:00
Ian McEwen
da30e1141a Merge pull request #663 from meshtastic/outtatime
Don't automatically set the time from Python
2024-09-05 13:47:36 -07:00
Derek Arnold
3811226a61 add a configurable timeout 2024-09-03 22:12:03 -05:00
Derek Arnold
b6547c9737 actually link up the retry args from the commandline to getNode 2024-09-03 22:11:52 -05:00
Derek Arnold
9612aea9b9 Add in a retry mechanism for channel settings
Attempts multiple times to fetch things over the admin channel
before giving up.
2024-09-03 21:58:16 -05:00
Ian McEwen
b4bd9568e4 Merge pull request #664 from lysol/master
Reuse node to prevent overwriting channel settings
2024-09-03 16:12:13 -07:00
Derek Arnold
aed4f25cf5 Reuse node to prevent overwriting channel settings to be sent out over the admin channel 2024-09-03 17:41:05 -05:00
Jonathan Bennett
5c312bedc1 Remove assert from test, due to removed position time 2024-08-30 01:15:40 -05:00
Jonathan Bennett
428e9a228c Remove unused time variable 2024-08-29 23:09:04 -05:00
Jonathan Bennett
4500850063 Don't automatically set the time from Python
The Python MO is to do as little as possible beyond what the user has intentionally instructed. So don't try to set the time automatically.
2024-08-29 22:29:20 -05:00
dependabot[bot]
aedaa3748d Bump jupyterlab from 4.2.3 to 4.2.5
Bumps [jupyterlab](https://github.com/jupyterlab/jupyterlab) from 4.2.3 to 4.2.5.
- [Release notes](https://github.com/jupyterlab/jupyterlab/releases)
- [Changelog](https://github.com/jupyterlab/jupyterlab/blob/@jupyterlab/lsp@4.2.5/CHANGELOG.md)
- [Commits](https://github.com/jupyterlab/jupyterlab/compare/@jupyterlab/lsp@4.2.3...@jupyterlab/lsp@4.2.5)

---
updated-dependencies:
- dependency-name: jupyterlab
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-29 18:23:54 +00:00
Ian McEwen
4b60c5b457 Merge pull request #660 from GUVWAF/2way_traceroute
HopStart should be set for route back to be valid
2024-08-26 11:40:08 -07:00
GUVWAF
c92474cf36 HopStart should be set for route back to be valid 2024-08-26 20:32:51 +02:00
Ian McEwen
b2acc84717 remove trailing whitespace 2024-08-25 18:27:34 -07:00
Ian McEwen
1981f0e899 Merge pull request #654 from GUVWAF/2way_traceroute
Show two-way traceroute result with SNR if available
2024-08-25 16:54:36 -07:00
Ian McEwen
bcce5687c5 Merge pull request #659 from wnagele/unreachable_code
Code block unreachable
2024-08-25 13:18:06 -07:00
Ian McEwen
b9d805057f Merge pull request #658 from wnagele/master
Add method to be able to send heartbeat
2024-08-25 13:17:51 -07:00
Wolfgang Nagele
d77335caa7 Add sendHeartbeat doc-string 2024-08-25 22:13:08 +02:00
Wolfgang Nagele
b692ef4cfb Add method to be able to send heartbeat 2024-08-25 14:47:41 +02:00
Wolfgang Nagele
e725292ee0 Code block unreachable 2024-08-25 14:39:37 +02:00
Ian McEwen
84dff75399 allow for underscore-only stuff in camel_to_snake, silly as that is 2024-08-24 23:38:48 -07:00
Ian McEwen
df12b8a659 appease the pylint beast 2024-08-24 23:34:28 -07:00
Ian McEwen
eedf42b904 add more fuzzing tests for utility functions 2024-08-24 22:25:18 -07:00
Ian McEwen
e7ed254d9d appease pylint, tests, mypy 2024-08-24 22:00:29 -07:00
Ian McEwen
dfa29bbb7c Add ensureSessionKey to setURL and setFixedPosition calls 2024-08-24 21:50:44 -07:00
Ian McEwen
5a06888cc7 Merge pull request #656 from meshtastic/more-admin
More admin
2024-08-24 21:48:19 -07:00
Jonathan Bennett
a9e2168f1d Refactor to add ensureSessionKey function 2024-08-24 20:18:57 -05:00
Jonathan Bennett
eec745c861 Add missed colon in if statement 2024-08-24 19:29:18 -05:00
Jonathan Bennett
4cc283d004 Add the admin sessionkey_only request 2024-08-24 17:27:42 -05:00
Ian McEwen
bc508ff9e6 cleanup admin stuff a little 2024-08-24 14:15:37 -07:00
Ian McEwen
ff72fc4804 Merge pull request #655 from meshtastic/show-pubkey
Adds admin session_passkey handling for 2.5 remote admin
2024-08-24 14:12:41 -07:00
Jonathan Bennett
78399503c5 Adds handlers to get and set admin session_key for remote admin 2024-08-24 15:32:44 -05:00
GUVWAF
216fd7ddc4 Show two-way traceroute result with SNR if available 2024-08-24 10:07:48 +02:00
Ian McEwen
688693d2fb Merge pull request #653 from meshtastic/show-pubkey
Adds handler function for public key, and adds to nodedb display
2024-08-23 20:41:40 -07:00
Jonathan Bennett
15b5e93563 Correctly format public key and add to node list 2024-08-23 22:21:54 -05:00
Ian McEwen
1bbcc452ae precalculate bit-shifts and don't generate too-large random numbers for packet ID generation 2024-08-23 15:34:25 -07:00
Ben Meadors
1abe00d0b2 Merge pull request #652 from ianmcorvidae/randomized-packet-ids
randomize packet IDs as firmware does
2024-08-23 17:30:07 -05:00
Ian McEwen
c8cf8094c3 randomize packet IDs as firmware does 2024-08-23 13:18:23 -07:00
Ian McEwen
477690edde mark protobufs folder as generated code for github 2024-08-21 22:27:18 -07:00
Ian McEwen
58466f2ab7 Add wiring for security config in node.py 2024-08-21 22:11:45 -07:00
Ian McEwen
bb6f51eb43 protobufs: 2.5 (in progress, untagged) 2024-08-21 21:58:56 -07:00
Ian McEwen
48987c38e2 set alpha version 2024-08-21 21:55:43 -07:00
Ian McEwen
abf9e96d3d Set release tag to the version update commit sha, not the pre-update one 2024-08-21 20:07:12 -07:00
Ian McEwen
740f0f0961 set prerelease version to match protobufs 2024-08-21 19:53:23 -07:00
Ian McEwen
abb00251c0 protobufs: v2.4.1 2024-08-21 19:52:56 -07:00
github-actions
3335b3d651 bump version to 2.4.0 2024-08-22 02:23:53 +00:00
Ian McEwen
4ad776f219 revert poetry version minor change -- with alpha version set, it's unnecessary 2024-08-21 19:20:10 -07:00
Ian McEwen
d5f732263a set alpha 2.4.0a0 version 2024-08-21 19:18:48 -07:00
Ian McEwen
c59583e4bd Make version-bump commit include the version being bumped to 2024-08-21 19:17:58 -07:00
Ian McEwen
28d8355547 Use poetry version minor, to revert after 2.4.0 release 2024-08-21 19:11:12 -07:00
Ian McEwen
d57186d1e4 protobufs: v2.4.0 2024-08-21 19:07:35 -07:00
github-actions
a8d86dee2d bump version 2024-08-11 17:22:31 +00:00
Ian McEwen
40d03a6ea1 mess with more stuff to try to make powermon optional 2024-08-11 10:19:38 -07:00
Ian McEwen
6757f5cdb5 slog depends on powermon, so move it within the optional block as well 2024-08-11 10:16:22 -07:00
Ian McEwen
b8c0a62b27 Add powermon group to ci install 2024-08-11 10:11:35 -07:00
Ian McEwen
72de803195 Attempt to make powermon stuff optional, hopefully allowing pypi release 2024-08-11 10:08:40 -07:00
Ian McEwen
84ffdcdb8c Merge pull request #647 from ianmcorvidae/improve-mypy
Add/update some types to be at least as backwards-compatible as we can be
2024-08-08 09:47:02 -07:00
Ian McEwen
5366ddf770 Add/update some types to be at least as backwards-compatible as we can be 2024-08-08 09:43:43 -07:00
Ian McEwen
fd4282b401 Merge pull request #636 from geeksville/pr-powermon2
final powermon / power analysis reporting changes
2024-08-08 09:36:16 -07:00
Ian McEwen
e84a3cb468 appease pylint 2024-08-04 12:26:20 -07:00
Ian McEwen
2ae18c1903 Clarify documentation of position options slightly 2024-08-04 12:22:57 -07:00
Kevin Hester
8096d10276 Do code coverage testing on analysis (using stored device data) 2024-08-01 10:07:48 -07:00
Kevin Hester
b0e1d961fd add vscode config for auto running python tests 2024-08-01 09:50:41 -07:00
Kevin Hester
dfa3d46a34 add pandas as an optional dependancy (for analytics only) 2024-07-31 17:03:44 -07:00
Kevin Hester
de29bf34ef install all extras when running poetry inside of CI 2024-07-31 16:03:22 -07:00
Kevin Hester
bf71e09091 get test coverage on powermon and slog stuff 2024-07-31 15:46:37 -07:00
Kevin Hester
4906f79be5 fix linter warnings (and alas: reformat __main__.py)
main.py's only real change is
        log_set: Optional[LogSet] = None  # type: ignore[annotation-unchecked]
Everything else is the automated reformatting to match our trunk formatting
rules.
2024-07-31 15:19:16 -07:00
Kevin Hester
a4715171e4 Add basic arg parsing to the meshtastic analysis stuff 2024-07-31 14:41:47 -07:00
Kevin Hester
c8eb202c15 cleanup and document analysis stuff 2024-07-31 13:40:29 -07:00
Kevin Hester
ea0c7abc3d Merge remote-tracking branch 'root/master' into pr-powermon2
# Conflicts:
#	meshtastic/mesh_interface.py
2024-07-23 16:57:08 -07:00
Kevin Hester
66f83835d9 use bootstrap for layout 2024-07-11 16:56:01 -07:00
Kevin Hester
39e03dbad8 add beginnings of analysis viewer (and fix poetry extras usage for tunnel) 2024-07-11 16:39:05 -07:00
Kevin Hester
4dbf9b94e9 do a new power measurement every 2ms(ish) 2024-07-11 12:27:16 -07:00
Kevin Hester
b464e90368 make ppk2 power meter threadsafe 2024-07-11 12:19:16 -07:00
Kevin Hester
3c76e19c33 poll for power readings much more rapidly - traces now look great 2024-07-11 11:49:12 -07:00
Kevin Hester
7e007e7e24 make ArrowWriter thread safe 2024-07-11 11:48:53 -07:00
Ian McEwen
d996965f0f Merge pull request #638 from ianmcorvidae/request-telemetry-uptime
Include uptime_seconds in sendTelemetry and print upon response
2024-07-10 17:31:45 -07:00
Ian McEwen
fd9b691b74 Include uptime_seconds in sendTelemetry and print upon response 2024-07-10 17:29:42 -07:00
Kevin Hester
628a4cb9be Always use IDENTICAL timestamps so the power and slog reports can match 2024-07-10 16:44:56 -07:00
Kevin Hester
d0db5cae13 Store much higher (time) res power readings any time we've just fetched
new readings.  This allows for better plotting/analysis but still keeping
runtime polling low.
2024-07-10 16:44:27 -07:00
Kevin Hester
0bc608d8cf fix analysis imports to import less 2024-07-10 16:43:24 -07:00
William Stearns
60de9dddb1 Remove references to BLEClient breaking CI checks 2024-07-09 19:54:01 -04:00
Kevin Hester
043530afca fix linter warnings 2024-07-08 09:17:52 -07:00
Kevin Hester
eb45c16f89 Merge remote-tracking branch 'root/master' into pr-powermon2
# Conflicts:
#	meshtastic/mesh_interface.py
2024-07-08 08:53:45 -07:00
Ian McEwen
3c772b5a31 Attempt adding python 3.12 to CI 2024-07-07 21:15:29 -07:00
Ian McEwen
865bb6a497 Remove python 3.8 warning. protobufs: v2.3.15 (brought in by merge) 2024-07-07 21:00:26 -07:00
Ian McEwen
c04943308a Merge pull request #607 from geeksville/pr-powermon
PowerMon/StructuredLogging support
2024-07-07 20:56:28 -07:00
github-actions
62cfe2d7fe bump version 2024-07-08 03:52:47 +00:00
Ian McEwen
ec4e521001 Add a warning about this being the last version supporting python 3.8 2024-07-07 20:49:38 -07:00
Ian McEwen
19d7e914bc Merge pull request #629 from ppicazo/trace_route_hop_fix
Fix for hopLimit param on sendTraceRoute not being respected
2024-07-07 20:43:22 -07:00
Paul Picazo
64bb668251 Fix line too long 2024-07-07 20:30:19 -07:00
Kevin Hester
8c63f4dec6 always write using correct schema for the file 2024-07-07 15:17:26 -07:00
Kevin Hester
9297732806 fix possible race with thread shutdown. somehow receiveThread can be null 2024-07-07 15:17:09 -07:00
Kevin Hester
a6c3e5cba8 properly parse all structured log messages 2024-07-07 14:58:30 -07:00
Kevin Hester
d35423a816 strip \n if it was incorrectly added by the device
+        # Devices should _not_ be including a newline at the end of each log-line str (especially when
+        # encapsulated as a LogRecord).  But to cope with old device loads, we check for that and fix it here:
+        if line.endswith("\n"):
+            line = line[:-1]

Also: auto reformatting per our trunk formatting rules.
2024-07-07 14:57:44 -07:00
Kevin Hester
84b4188211 Gracefully cope with exceptions during power-stress test 2024-07-07 14:07:27 -07:00
Kevin Hester
72e0f2a92b Don't silently ingnore malformed protobufs (the \0 in the device side
was at fault)
2024-07-07 13:47:02 -07:00
Kevin Hester
ecbda74bd6 make PPK2 power supply monitor work in supply-mode 2024-07-06 16:41:33 -07:00
Kevin Hester
fb191092fb gracefully shutdown when BLE device connect fails 2024-07-06 16:27:20 -07:00
Kevin Hester
1e447cb52a also store raw log messages in the slog file. 2024-07-06 15:26:15 -07:00
Kevin Hester
462d9a83df Automatically extract and store all known structured-logs 2024-07-06 15:07:13 -07:00
Kevin Hester
4c02114b75 fix null pointer if closing an interface which was already shutting down 2024-07-06 13:43:19 -07:00
Kevin Hester
42e069455e transition through power stress states and capture data
meshtastic-py3.12kevinh@kdesktop:~/development/meshtastic/meshtastic-python$  cd /home/kevinh/development/meshtastic/meshtastic-python ; /usr/bin/env /home/kevinh/.cache/pypoetry/virtualenvs/meshtastic-l6tP90xw-py3.12/bin/python /home/kevinh/.vscode/extensions/ms-python.debugpy-2024.6.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher 52521 -- -m meshtastic --slog --power-ppk2-meter --power-stress --power-voltage 3.3
INFO file:ppk2.py __init__ line:52 Connected to Power Profiler Kit II (PPK2)
INFO file:__main__.py create_power_meter line:1022 Setting power supply to 3.3 volts
Connected to radio
INFO file:slog.py __init__ line:183 Writing slogs to /home/kevinh/.local/share/meshtastic/slogs/20240706-123803
INFO file:stress.py syncPowerStress line:68 Sending power stress command PRINT_INFO
INFO file:stress.py run line:105 Running power stress test 48 for 5.0 seconds
INFO file:stress.py syncPowerStress line:68 Sending power stress command LED_ON
INFO file:stress.py run line:105 Running power stress test 80 for 5.0 seconds
INFO file:stress.py syncPowerStress line:68 Sending power stress command BT_OFF
INFO file:stress.py run line:105 Running power stress test 81 for 5.0 seconds
INFO file:stress.py syncPowerStress line:68 Sending power stress command BT_ON
INFO file:stress.py run line:105 Running power stress test 34 for 5.0 seconds
INFO file:stress.py syncPowerStress line:68 Sending power stress command CPU_FULLON
INFO file:stress.py run line:105 Running power stress test 32 for 5.0 seconds
INFO file:stress.py syncPowerStress line:68 Sending power stress command CPU_IDLE
INFO file:stress.py run line:105 Running power stress test 33 for 5.0 seconds
INFO file:stress.py syncPowerStress line:68 Sending power stress command CPU_DEEPSLEEP
INFO file:stress.py run line:108 Power stress test complete.
INFO file:slog.py close line:201 Closing slogs in /home/kevinh/.local/share/meshtastic/slogs/20240706-123803
WARNING file:arrow.py close line:67 Discarding empty file: /home/kevinh/.local/share/meshtastic/slogs/20240706-123803/slog.arrow
INFO file:arrow.py close line:70 Compressing log data into /home/kevinh/.local/share/meshtastic/slogs/20240706-123803/power.feather
meshtastic-py3.12kevinh@kdesktop:~/development/meshtastic/meshtastic-python$
2024-07-06 12:43:34 -07:00
Ian McEwen
1511d4ea99 Merge pull request #633 from meshtastic/dependabot/pip/certifi-2024.7.4
Bump certifi from 2024.6.2 to 2024.7.4
2024-07-05 21:37:17 -07:00
dependabot[bot]
b59aee91f2 Bump certifi from 2024.6.2 to 2024.7.4
Bumps [certifi](https://github.com/certifi/python-certifi) from 2024.6.2 to 2024.7.4.
- [Commits](https://github.com/certifi/python-certifi/compare/2024.06.02...2024.07.04)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-06 02:31:50 +00:00
Ian McEwen
2c8fd8b606 Merge pull request #632 from ianmcorvidae/remote-config-wrongtype-again
Correctly detect LocalConfig vs. LocalModuleConfig, again. fixes #630
2024-07-03 20:36:21 -07:00
Ian McEwen
15b03b704c Correctly detect LocalConfig vs. LocalModuleConfig, again. fixes #630 2024-07-03 20:35:58 -07:00
Kevin Hester
63327986b4 fix incorrect Vid - thanks @ianmcorvidae for notixing.
0x04b4 is cypress semi but commonly used in Chinese oscopes (like mine).
So it was supposed to be a blacklist not a whitelist!
2024-07-03 20:11:59 -07:00
Kevin Hester
5695ec7102 change --slog to use nargs 2024-07-03 11:00:42 -07:00
Kevin Hester
ae2ef78560 fix linter warnings
(note: the linter test for min/max is buggy so disabled)
2024-07-03 09:57:24 -07:00
Kevin Hester
2f5a736e1f Merge remote-tracking branch 'root/master' into pr-powermon
# Conflicts:
#	meshtastic/ble_interface.py
#	meshtastic/protobuf/mesh_pb2.py
#	meshtastic/protobuf/powermon_pb2.py
#	meshtastic/protobuf/powermon_pb2.pyi
2024-07-03 09:22:45 -07:00
Paul Picazo
775108b47b Hop limit param on sendTraceRoute fix 2024-07-02 10:09:58 -07:00
Ian McEwen
ae904f6dbe Merge pull request #628 from meshtastic/update-heartbeat
Update heartbeat interval to a fixed 300 seconds
2024-07-02 10:01:32 -07:00
Ian McEwen
a14cc4f573 Update heartbeat interval to a fixed 300 seconds 2024-07-02 09:58:45 -07:00
Ian McEwen
dc5f59260f protobufs: v2.3.14 2024-07-02 09:52:47 -07:00
github-actions
91c42d598e bump version 2024-07-02 16:46:09 +00:00
Ian McEwen
22bf34ee35 Merge pull request #627 from meshtastic/protobuf-ble-logging
New LogRecord protobuf BLE logging
2024-07-02 09:44:49 -07:00
Ian McEwen
32b4575262 Reorganize imports for pylint 2024-07-02 09:43:49 -07:00
Ben Meadors
5eafc2c866 Remove newline handling 2024-07-02 07:30:27 -05:00
Ben Meadors
19363967f3 Shut up linter 2024-07-01 21:11:35 -05:00
Ben Meadors
ce6c096c3e Fix 2024-07-01 21:05:27 -05:00
Ben Meadors
bef9b480f0 Log Recod logging with new characterstic 2024-07-01 18:05:15 -05:00
Ben Meadors
d5a4d86c21 Merge remote-tracking branch 'origin/master' into protobuf-ble-logging 2024-07-01 06:18:32 -05:00
Ben Meadors
188f9d593c Add handler for new log-record BLE characteristic 2024-07-01 06:16:49 -05:00
Ben Meadors
0e6a0eb1d0 Merge pull request #626 from ianmcorvidae/ble-older-firmware
Support --ble on older firmwares that don't have the log-radio characteristic yet
2024-07-01 06:16:04 -05:00
Ian McEwen
3b4690e932 appease the linter 2024-07-01 00:00:59 -07:00
Ian McEwen
49bd9cb515 Support --ble on older firmwares that don't have the log-radio characteristic yet. 2024-06-30 23:40:11 -07:00
Ian McEwen
33c5be5219 Update doc string for --pos-fields to use valid values 2024-06-30 23:25:57 -07:00
Ian McEwen
9ffdc30c1f Make remote hardware args live in their own little box 2024-06-30 23:25:07 -07:00
Ian McEwen
98b7a7d0df Merge pull request #625 from ianmcorvidae/nargs2
Allow connection args without an argument, add argument aliases
2024-06-30 16:54:52 -07:00
Ian McEwen
abdfbc673e Allow connection args without an argument, add argument aliases 2024-06-30 16:52:31 -07:00
Ian McEwen
42ea29be8f Merge pull request #624 from geeksville/pr-bletweak
bleak reads can hang if a device walks out of range, cope with that.
2024-06-30 15:59:24 -07:00
Kevin Hester
6da04f7a15 Merge branch 'pr-bletweak' into pr-powermon
# Conflicts:
#	.vscode/launch.json
2024-06-30 13:03:33 -07:00
Kevin Hester
111d61ea0a bleak reads can hang if a device walks out of range, cope with that. 2024-06-30 13:00:12 -07:00
Ian McEwen
9e71e85c9f Merge pull request #621 from ianmcorvidae/str-concat-trace
Properly handle missing nodes in traceroute response
2024-06-30 10:05:50 -07:00
Ian McEwen
93fbc78492 Properly handle missing nodes in traceroute response (fixes #612) 2024-06-30 10:04:54 -07:00
Ian McEwen
e331bea4ea make typing a little more 3.8-approved 2024-06-30 09:58:32 -07:00
Ian McEwen
7788271278 Merge pull request #582 from FedericoCeratto/clarify-licensing
Clarify licensing
2024-06-30 09:45:41 -07:00
Ian McEwen
01674b9803 Merge pull request #619 from geeksville/pr-poelock
Add bin/git-resolve-poetry-lock.sh to resolve merge conficts
2024-06-30 09:33:51 -07:00
Ian McEwen
4f1ea5b7da Merge pull request #616 from meshtastic/ble-logging
Adds support for ble logging characteristic
2024-06-30 09:33:05 -07:00
Ian McEwen
18883b977b Merge pull request #618 from geeksville/pr-fixstdout
make specifying an argument to --seriallog optional
2024-06-30 09:31:41 -07:00
Kevin Hester
a68a9f8517 Add bin/git-resolve-poetry-lock.sh to resolve merge conficts
Previously I was just doing poetry update to resolve such conflicts,
but that's not really ideal because it updates all libs.
poetry lock --no-update is better, but even better to base the changes
from their version of poetry-lock and then add only my changes as required
by pyproject.yaml.

You can use this script if you get a merge conflict with poetry.lock
and it will just do the right thing.

btw: in my powermon/structuredlogging branch I have a commit to add
support for the "poe" tool which will provide a shortcut for this script.
2024-06-30 07:25:11 -07:00
Kevin Hester
8f98878cac Merge branch 'ble-logging' into pr-powermon
# Conflicts:
#	.vscode/launch.json
#	meshtastic/protobuf/config_pb2.py
#	meshtastic/protobuf/mesh_pb2.py
#	meshtastic/protobuf/mesh_pb2.pyi
2024-06-30 07:06:32 -07:00
Kevin Hester
a04b3498b3 make specifying an argument to --seriallog optional
thanks @ianmcorvidae for telling me about the cool nargs='?' option!
2024-06-30 06:54:29 -07:00
Kevin Hester
5c2851db85 nargs='?' is awesome! get rid of ble_dest. 2024-06-30 06:46:39 -07:00
Kevin Hester
7e440693a3 Merge remote-tracking branch 'root/master' into ble-logging
# Conflicts:
#	poetry.lock
2024-06-30 06:36:11 -07:00
Kevin Hester
13ca8fd681 debug launch configs 2024-06-30 06:31:09 -07:00
Ian McEwen
18c2d08bf0 protobufs: v2.3.13 2024-06-29 17:36:22 -07:00
Ian McEwen
a3afc2ae0a Ensure regen-protobufs works if there's no pre-existing directory to remove 2024-06-29 17:34:02 -07:00
Ian McEwen
f6d1b4bc39 Merge pull request #613 from geeksville/pr-moveproto
Move protobuf python glue from meshtastic to meshtastic.protobuf
2024-06-29 17:12:32 -07:00
Kevin Hester
1da687cf2d move @thebentern spiffy logging so it is shared with !ble log sources 2024-06-29 16:15:32 -07:00
Kevin Hester
42236f2de8 Merge branch 'ble-logging' into pr-powermon
# Conflicts:
#	poetry.lock
#	pyproject.toml
2024-06-29 15:59:03 -07:00
Kevin Hester
9004f1ed57 fixes for type checker 2024-06-29 15:18:22 -07:00
Kevin Hester
bd767af485 A better way to ensure BLE disconnects:
It turns out that Bleak is kinda racey.  If we call disconnect()
and then immediately close() the disconnect may or may not actually happen
(probably because it was merely queued for dbus).
So instead: When we want to close the BLEInterface we call disconnect()
and then in a preregistered 'on disconnect' handler we actually close
down our interface/datastructures.
2024-06-29 15:08:50 -07:00
Kevin Hester
6194e41baf fix linter warnings 2024-06-29 14:37:50 -07:00
Kevin Hester
532ca54ba4 fix bug: we were never calling BLE.disconnect() which...
on linux breaks all but the first connection attempts.
Also remove unneeded event stuff and arbitrary timeouts, better just to
use thread.join()
2024-06-29 14:25:01 -07:00
Kevin Hester
898018ebf3 yay Bleak works again on Linux! 2024-06-29 13:52:46 -07:00
Kevin Hester
9f015f499a wow Bleak now seems pretty buggy to me (compared to 2 yrs ago) 2024-06-29 10:18:37 -07:00
Kevin Hester
dc50a60b01 BLE debugging 2024-06-29 09:35:42 -07:00
Kevin Hester
a24384cbe2 Merge remote-tracking branch 'root/ble-logging' into pr-fixbluetooth 2024-06-29 09:31:28 -07:00
Kevin Hester
adbfb328b2 threads should aways be named (for debugability) 2024-06-29 09:29:29 -07:00
Kevin Hester
6df89f54a7 fix BLE scan with latest Bleak 2024-06-29 09:10:20 -07:00
Kevin Hester
821d3e95f1 remvoe unneeded paren 2024-06-29 08:40:16 -07:00
Ben Meadors
897adfb8c2 Adds support for ble logging characteristic 2024-06-29 09:41:06 -05:00
Kevin Hester
542f99b28f handle the new LogRecord protobufs
(backwards/forwards compatible) with old firmware
2024-06-28 09:41:17 -07:00
Kevin Hester
dabb4ea44c PowerStress client approximately works 2024-06-28 09:40:33 -07:00
Kevin Hester
119be81000 PowerStress WIP 2024-06-27 16:37:58 -07:00
Federico Ceratto
5b55e3b877 Fix typo 2024-06-27 19:35:43 +02:00
Federico Ceratto
960e32fa4b Clarify licensing in compliance with https://reuse.software/
The license was changed on 1 Nov 2022 in
https://github.com/meshtastic/python/pull/392
2024-06-27 19:30:52 +02:00
Kevin Hester
c9351236e6 blacklist hantek oscilliscope 2024-06-26 17:28:55 -07:00
Kevin Hester
2294546560 fix bogus high current reading on first ppk2 read 2024-06-26 16:43:14 -07:00
Kevin Hester
67bb6665f2 the stock PPK2 API is super inefficient, remove lots of buffering 2024-06-26 15:29:18 -07:00
Kevin Hester
62ce8eaa77 fix code coverage CI false alarm? 2024-06-26 13:52:54 -07:00
Kevin Hester
1587c31d18 Merge remote-tracking branch 'root/master' into pr-powermon 2024-06-26 13:33:34 -07:00
Kevin Hester
715a085183 add more dataviz tooling 2024-06-26 12:59:52 -07:00
Kevin Hester
047a56d554 speed up file writing 2024-06-26 12:59:28 -07:00
Kevin Hester
320bb30d29 Use .feather files as our long-term representation 2024-06-26 11:12:02 -07:00
Kevin Hester
f2c427430c Update protobufs to master (required for powermon stuff) 2024-06-26 10:21:47 -07:00
Kevin Hester
ef4b534396 Merge branch 'pr-moveproto' into pr-powermon 2024-06-26 10:19:04 -07:00
Kevin Hester
3e8a807868 Update all libs to latest (in particular the mypy-protobuf tool) 2024-06-26 10:17:37 -07:00
Kevin Hester
6d846c3a63 manually rebuild the protobuf glue files for now... (see PR for info) 2024-06-26 10:12:24 -07:00
Kevin Hester
88b73611f0 Move protobufs to meshtastic.protobuf python namespace 2024-06-26 10:05:59 -07:00
Ian McEwen
f5febc566f comment out windows build for next release, we've been deleting it out of the releases anyway 2024-06-25 19:13:23 -07:00
github-actions
c3dcafb5ef bump version 2024-06-26 02:08:30 +00:00
Ian McEwen
96afa703ba output version number in correct format for github actions, hopefully 2024-06-25 19:07:35 -07:00
Kevin Hester
0b9af0dcba remove old protobufs (moving to meshtastic.protobuf) 2024-06-25 19:05:46 -07:00
Kevin Hester
b063d33d77 don't git jupyter temp directories 2024-06-25 18:58:32 -07:00
Ian McEwen
1b14b1ef20 Use poetry version --short for a valid tag name 2024-06-25 18:58:27 -07:00
Kevin Hester
8761b3270a Merge remote-tracking branch 'root/master' into pr-powermon
# Conflicts:
#	meshtastic/mesh_interface.py
#	poetry.lock
#	pyproject.toml
2024-06-25 18:54:38 -07:00
Kevin Hester
4ca9aa29c2 beginnings of meshtastic.analysis 2024-06-25 18:49:48 -07:00
Ian McEwen
68836b1af1 Merge pull request #606 from geeksville/pr-poetry
Change build to use poetry
2024-06-25 18:24:27 -07:00
Ian McEwen
195f0c9d90 drop timeago dep, concurrent PR 2024-06-25 18:24:04 -07:00
Ian McEwen
1ff7334385 Merge branch 'master' into pr-poetry 2024-06-25 18:22:02 -07:00
Ian McEwen
b15e27c7b6 Merge pull request #587 from FedericoCeratto/drop-timeago 2024-06-25 18:14:27 -07:00
Ian McEwen
267923fdc5 Add hypothesis fuzzing test for _timeago 2024-06-25 18:14:07 -07:00
Ian McEwen
9ab1b32bdb make pylint happy with a docstring 2024-06-25 18:09:20 -07:00
Kevin Hester
231bc25255 PPK2 based power measurements seem to approximately work 2024-06-25 15:19:21 -07:00
Kevin Hester
ff20ad5d05 group power options in --help. add --power-wait to support some boards 2024-06-25 13:48:14 -07:00
Ian McEwen
3a4795d3b8 Merge pull request #605 from geeksville/pr-whitelist
Add a whitelist of known meshtastic USB VIDs to use a default serial …
2024-06-25 12:53:39 -07:00
Ian McEwen
c2a2d5a77c Merge pull request #611 from geeksville/pr-fixbitrot
fix bitrot in an old sanity test - use correct namespace
2024-06-25 12:52:21 -07:00
Kevin Hester
f8ad4fef7c deferred execution thread should be named and marked as daemon 2024-06-25 12:23:38 -07:00
Kevin Hester
d1aadf0c8e close power meter gracefully 2024-06-25 12:22:47 -07:00
Kevin Hester
d448ea5767 keep a symbolic link "latest" that points to the latest slog dir 2024-06-25 12:03:35 -07:00
Kevin Hester
b30cde979c fix bitrot in an old sanity test - use correct namespace 2024-06-25 11:31:02 -07:00
Kevin Hester
402622f427 fix type warnings 2024-06-25 11:25:07 -07:00
Kevin Hester
220241448f more fighting with trunk 2024-06-25 11:08:47 -07:00
Kevin Hester
9b61f11c88 temporarily suppress warning about main.py being too long 2024-06-25 11:08:35 -07:00
Kevin Hester
8d94458e55 flake8 has different settings than trunk, don't confict in vscode 2024-06-25 11:02:58 -07:00
Kevin Hester
1b045bec88 fix linter warnings 2024-06-25 11:02:24 -07:00
Kevin Hester
07fc991f4e clean up slog closing 2024-06-25 10:39:44 -07:00
Kevin Hester
c6561713db don't let daemon keep process alive 2024-06-25 10:27:36 -07:00
Kevin Hester
9cdfde47ec store slogs in correct default directory (OS dependent) 2024-06-25 10:27:35 -07:00
Kevin Hester
91066f6aed add powermon_sim support 2024-06-25 10:26:45 -07:00
Kevin Hester
7ce7d73e89 Switch from pandas to apache arrow for live data logging (better streaming) 2024-06-25 10:26:45 -07:00
Kevin Hester
43e1f65a75 "python" is deprecated vscode now wants "pydebug" 2024-06-25 10:26:45 -07:00
Kevin Hester
dc8348b99e add (optional) poe tool config for easy running of external commands 2024-06-25 10:26:45 -07:00
Kevin Hester
26a672ed58 ppk2 tweaks 2024-06-25 10:26:45 -07:00
Kevin Hester
ea18057c1f Add support for NRF PPK2 power testing board. 2024-06-25 10:26:44 -07:00
Kevin Hester
5ff4025ed6 add NordicSemi Power Profiler Kit 2 device to the USB blacklist 2024-06-25 10:25:58 -07:00
geeksville
1add293414 Add a whitelist of known meshtastic USB VIDs to use a default serial ports.
Initially only RAK4631 and heltec tracker are listed
2024-06-25 10:25:58 -07:00
Kevin Hester
8b781d3245 fix #610: bump nanopb to 0.4.8
Including in the Poetry changes because it touches the same lines
and I want to avoid hand merging ;-)
2024-06-25 10:25:58 -07:00
Kevin Hester
6c0e978470 debugging config tweaks 2024-06-25 10:25:58 -07:00
Kevin Hester
b7f7a40192 document why using python 3.9 2024-06-25 10:25:58 -07:00
Kevin Hester
7b18fd599c remove observable - switch because we are already using pubsub elsewhere 2024-06-25 10:25:58 -07:00
Kevin Hester
46edd78f92 For poetry change: need to put venv in our path so mypy protobuf plugin works
# Conflicts:
#	bin/regen-protobufs.sh
2024-06-25 10:25:52 -07:00
Kevin Hester
67e1e7c318 move mypy and type info into dev-time only dependencies thx @njh
# Conflicts:
#	poetry.lock
#	pyproject.toml
2024-06-25 10:23:34 -07:00
Kevin Hester
51c6c2cae1 The github action for building protobufs is using 0.4.6 so we should match 2024-06-25 10:21:11 -07:00
Kevin Hester
9c657c6c8a switch to latest protobufs 2024-06-25 10:21:11 -07:00
Kevin Hester
79c65c1706 make slog nicely add new rows 2024-06-25 10:21:11 -07:00
Kevin Hester
0e45637f2c generalize the powermon stuff to become structured logging 2024-06-25 10:21:11 -07:00
Kevin Hester
be74c3eea0 fix linter warnings 2024-06-25 10:21:11 -07:00
Kevin Hester
362c1f3d2a remove python 3.8 2024-06-25 10:21:11 -07:00
Kevin Hester
cc60f3ebc0 begin support for multiple power meter types 2024-06-25 10:21:11 -07:00
Kevin Hester
a1f86a351a add typing hints 2024-06-25 10:21:11 -07:00
Kevin Hester
21e5601b23 run linter as part of prerelease tests 2024-06-25 10:21:11 -07:00
Kevin Hester
338f00a64a minor cleanup on observable 2024-06-25 10:21:11 -07:00
Kevin Hester
a3462e0209 didn't mean to check in built protobufs 2024-06-25 10:21:02 -07:00
Kevin Hester
8456f36c6b add NordicSemi Power Profiler Kit 2 device to the USB blacklist 2024-06-23 17:18:04 -07:00
Kevin Hester
81266e756b fixes to make Bleak (BLE) work better 2024-06-23 13:52:32 -07:00
Kevin Hester
62f16d34d4 fix BLE scan and connect to work with latest bleak 2024-06-23 11:56:44 -07:00
Kevin Hester
e6a88e055f fix #610: bump nanopb to 0.4.8
Including in the Poetry changes because it touches the same lines
and I want to avoid hand merging ;-)
2024-06-23 08:26:20 -07:00
Kevin Hester
7bea6f6120 For poetry change: need to put venv in our path so mypy protobuf plugin works 2024-06-22 23:25:42 -07:00
Kevin Hester
725de4c2f9 move mypy and type info into dev-time only dependencies thx @njh 2024-06-22 16:43:56 -07:00
Kevin Hester
b41cb7d8df Merge branch 'pr-poetry' into powermon 2024-06-22 10:49:42 -07:00
geeksville
4203553a44 changes to (hopefully) make release CI actions work
add pyinstaller as a dev dep.  Use it to make "bin/build-bin.sh"
remove old version scripts (no longer needed with poetry)
2024-06-22 09:34:24 -07:00
geeksville
9e319f3c52 update CI scripts to allow running CI on the desktop (see below)
* add script to run 'act' local github actions tool (lets devs check github
actions on their local machine)
* Update various github actions to latest (so they can work with the 'act'
tool)
* change a few places where python version was not properly quoted as a
string (act yaml parser is more strict than the github version)
* update pylint min-version to work with recent github actions
* remove pandas/riden requirement (that's in my other branch for now)
2024-06-22 08:02:33 -07:00
geeksville
cd5913ae6d WIP switch to using Poetry for builds/dev usage. Looks pretty good
still need to update readme and pypi upload
2024-06-22 08:01:54 -07:00
geeksville
ccfb04720f Add a whitelist of known meshtastic USB VIDs to use a default serial ports.
Initially only RAK4631 and heltec tracker are listed
2024-06-21 14:42:29 -07:00
Federico Ceratto
c34d08b0e5 Refactor timeago and add tests
_timeago is not specialized for mesh interfaces so it is factored
out into a private function
2024-06-21 10:28:45 +02:00
Federico Ceratto
b5d1b7612f Replace timeago
Replace the timeago library with a simple function
2024-06-21 09:25:39 +02:00
Ian McEwen
b58094b9ce Merge pull request #602 from ianmcorvidae/improve-acks
Improve ACK handling: pass to `onAckNak` and on request in sendData
2024-06-20 17:16:36 -07:00
Ian McEwen
23f41bff0a Improve ACK handling: correctly pass them to onAckNak handlers, and add a mechanism for other handlers to request acks as well. 2024-06-20 16:52:01 -07:00
Ian McEwen
a1021c4f78 add dotmap back, that test file isn't in tests, it's in meshtastic.test, oops 2024-06-20 16:45:22 -07:00
Ian McEwen
b06329f47e Remove dotmap and pexpect from setup.py, they shouldn't be required 2024-06-20 16:40:46 -07:00
William Stearns
a29ee840f2 Adding mypy typing 2024-06-15 23:22:43 -04:00
Ian McEwen
53b0e35b0c protobufs: v2.3.12 2024-06-09 19:30:11 -07:00
github-actions
9ac5aeeaf0 bump version 2024-06-08 15:10:49 +00:00
Ian McEwen
5c703aff1d Merge pull request #591 from ianmcorvidae/device-metadata-resp
Wait for response with --device-metadata. Fixes #527
2024-06-08 07:29:45 -07:00
Ian McEwen
5441266565 Wait for response with --device-metadata. Fixes #527 2024-06-08 07:26:20 -07:00
Ian McEwen
890557fa5d Merge branch 'more-tests' 2024-06-05 19:58:03 -07:00
Ian McEwen
e27d210a71 Test with --dest on setlat/remove-position for the error/exit case 2024-06-05 19:57:40 -07:00
Ian McEwen
16c08b8b47 Add simple --remove-position test 2024-06-05 19:54:12 -07:00
Ian McEwen
ebd3c7f5e8 Add test for fromStr base64 branch 2024-06-05 19:48:58 -07:00
Ian McEwen
da0312a5b0 more miscellaneous types 2024-06-05 19:44:18 -07:00
Ian McEwen
919ae8c40f make pylint happy, again 2024-06-05 19:32:45 -07:00
Ian McEwen
dd4fccbc77 Add a fairly simple property-based test as a starting point 2024-06-05 19:29:55 -07:00
Ian McEwen
32682b5230 Merge pull request #589 from ianmcorvidae/nodeless-startup
Allow a faster nodedb-less startup on 2.3.11+ with `--no-nodes`
2024-06-05 18:59:18 -07:00
Ian McEwen
9dab76bb64 quell pylint 2024-06-05 18:56:19 -07:00
Ian McEwen
e6d61c6603 Allow a faster nodedb-less startup on 2.3.11+ with --no-nodes and the magic value from meshtastic/firmware#3949 2024-06-05 18:52:35 -07:00
Ian McEwen
ee857c5128 Merge pull request #588 from nerdenator/quick-coverage
quick-coverage: simple test case just to cover uncovered code.
2024-06-03 23:22:33 -07:00
Nerdenator
87a4bb0888 quick-coverage: fixing linting issues. 2024-06-04 01:15:10 -05:00
Nerdenator
d72cc0e201 quick-coverage: simple test case just to cover uncovered code. 2024-06-04 01:01:32 -05:00
Ian McEwen
b350b9eab9 Update the main module docstring to be a bit more accurate, at least 2024-06-01 23:03:56 -07:00
Ian McEwen
dc112f2f3a protobufs: v2.3.11 2024-06-01 12:04:01 -07:00
github-actions
14ae4eeac1 bump version 2024-06-01 18:47:51 +00:00
Ian McEwen
bbc526d0a8 Merge pull request #584 from ianmcorvidae/improve-fixed-position
Use new fixed position admin messages and add `--remove-position` argument
2024-06-01 00:44:17 -07:00
Ian McEwen
abe98f5079 Merge pull request #585 from ianmcorvidae/position-rounding
Fix rounding of position values when converting from integer to float in _fixupPosition
2024-06-01 00:42:58 -07:00
Ian McEwen
e8dfee8454 Fix rounding of position values when converting from integer to float in _fixupPosition. Fixes #572 2024-05-31 18:57:30 -07:00
Ian McEwen
1746ad15d7 Use new fixed position admin messages and add --remove-position argument. Fixes #525 2024-05-31 18:44:33 -07:00
Ian McEwen
4d67e7fc76 Fix up/add some more types 2024-05-30 17:51:42 -07:00
Ian McEwen
3b112d2f49 Merge pull request #583 from ianmcorvidae/update-unknown-node-setup
Initialize unknown nodes more in line with meshtastic/design#16; show hardware in --nodes
2024-05-30 15:52:16 -07:00
Ian McEwen
93e9c1c66c Initialize unknown nodes more in line with meshtastic/design#16 2024-05-30 13:50:52 -07:00
Ian McEwen
8e641b3186 Merge pull request #581 from 868meshbot/868meshbot-fix-ignore-incoming
Fix the ignore_incoming management BUG 568
2024-05-26 00:03:11 -07:00
Ian McEwen
ed545cd9b4 Merge pull request #580 from todd-herbert/wait-to-disconnect
Add "wait to disconnect" argument
2024-05-26 00:02:08 -07:00
868meshbot
bcd60c9ef7 Update __main__.py
Simple patch to fix the ignore_incoming management aka
https://github.com/meshtastic/python/issues/568
2024-05-25 16:28:16 +01:00
Todd Herbert
c3d044e3f2 Optional pause before disconnecting 2024-05-24 17:10:07 +12:00
Ian McEwen
8d538e8f24 protobufs: v2.3.10 2024-05-18 12:56:41 -07:00
github-actions
fa1a3d7901 bump version 2024-05-18 00:15:11 +00:00
Ian McEwen
3adeb925dd tweak the roadmap in README a little 2024-05-14 16:05:21 -07:00
Ian McEwen
9de04a12e1 Merge pull request #574 from ianmcorvidae/warn-enable-disable
add a warning on --ch-enable and --ch-disable, which should usually be avoided
2024-05-13 21:30:01 -07:00
Ian McEwen
e01a1bb6e0 add a warning on --ch-enable and --ch-disable, which should usually be avoided 2024-05-13 21:27:53 -07:00
Ian McEwen
1ebea53703 make pylint happy with import order 2024-05-11 22:28:50 -07:00
Ian McEwen
ba2d6c9d93 continue progressively typing things (SerialInterface/BLEInterface initializations) 2024-05-11 22:27:31 -07:00
Ian McEwen
fef0e1b77f Remove an unuseful/inaccurate comment 2024-05-10 20:17:48 -07:00
Ian McEwen
dc1dec17b5 protobufs: v2.3.9 2024-05-10 14:56:07 -07:00
Ian McEwen
02ed17837b Improve FromRadio handling, publish messages for client proxy/xmodem stuff tentatively 2024-05-10 14:54:32 -07:00
Ian McEwen
8cf996a242 Merge pull request #564 from jhollowe-forks/fix-help-typo
Fix typo in __main__.py
2024-05-02 19:04:08 -07:00
John Hollowell
02189aae07 Fix typo in __main__.py 2024-05-02 21:51:09 -04:00
Ian McEwen
894581ce00 Merge pull request #563 from ianmcorvidae/show-channel-0
Print 0 for channel rather than N/A, since we should probably always have a channel
2024-05-02 18:29:00 -07:00
Ian McEwen
fb8db01427 Print 0 for channel rather than N/A, since we should probably always have a channel. Fixes #562 2024-05-02 18:22:39 -07:00
github-actions
fa5ede93ed bump version 2024-05-01 16:42:38 +00:00
Ian McEwen
022a8a1017 protobufs: v2.3.8 2024-05-01 09:40:04 -07:00
Ian McEwen
21f6e25ab0 Merge pull request #561 from ianmcorvidae/use-heartbeat
Use the new Heartbeat payload variant for the heartbeat instead of an empty ToRadio packet
2024-04-29 15:18:23 -07:00
Ian McEwen
243e297505 Use the new Heartbeat payload variant for the heartbeat instead of an empty ToRadio packet 2024-04-29 15:16:04 -07:00
Ian McEwen
9fc86f9450 Merge pull request #558 from geeksville/pr-fixjson
Pretty indent --info JSON output (see below for details)
2024-04-28 21:40:43 -07:00
Ian McEwen
e5999f5be6 Merge pull request #560 from geeksville/pr-fixchannel
(high-pri fix) Update python client to use the 'modern' meshtastic protocol init flow
2024-04-28 19:53:04 -07:00
geeksville
3886bc16d7 Update python client to use the 'modern' meshtastic protocol init flow
Some time ago I updated the protocol so that after sending NODEINFOs to
client devices (via fromRadio protobufs), it would proactively send the
channel definitions.  Prior to this the client had to ask for each channel
by sending an admin request.  This handshaking was really slow for mobile/
bluetooth clients.  So in the current device code (last couple of years)
the device automatically sends this info to the client during initial config
download.

Unfortunately I never updated the python client to expect this.  I assumed
(incorrectly) that it would just cope and keep sending the channel requests
the old way it always had (which is still supported by devices - and
required for remote administration of nodes).

This change removes sending channel requests (for the local node only)
from the python startup code.  It also now understands (no longer ignoring)
the channels which were sent proactively by the local device.

This makes connection/config/api operations from the python client 100%
reliable again.  Previously it would only work sometimes depending on how
quickly it was able to get the local node db downloaded.

Also this flow is much faster - which should help all users of the python
api.
2024-04-27 11:59:17 -07:00
geeksville
7fe98bc266 Pretty indent --info JSON output (see below for details)
Changes to make --info much more human readable (while still keeping
machine readabilty for anyone foolish enough to be parsing the existing
output as text)

* change message_to_json to optionally not strip the multiline JSON
* use multiline=True for the two places we are printing to the console
* make the node list JSON indented
2024-04-26 15:15:57 -07:00
github-actions
2f9307fd99 bump version 2024-04-25 18:33:55 +00:00
Ian McEwen
3d6fa369e8 Merge pull request #556 from ianmcorvidae/enter-dfu
Add --enter-dfu for entering DFU mode on NRF52 devices via admin message
2024-04-25 11:29:09 -07:00
Ian McEwen
6812f508bc Add --enter-dfu for entering DFU mode on NRF52 devices via admin message 2024-04-25 11:21:27 -07:00
Ian McEwen
158cac6b0b Merge pull request #555 from ianmcorvidae/channel-indices
Better support --ch-index for other commands (traceroute, telemetry, position)
2024-04-24 19:35:44 -07:00
Ian McEwen
4d10b6e1bd Better support --ch-index for other commands (traceroute, telemetry, position) 2024-04-24 17:18:17 -07:00
Ian McEwen
bb6e3b7a49 protobufs: v2.3.7 2024-04-23 21:35:15 -07:00
Ian McEwen
8b29dc683a Merge pull request #554 from GUVWAF/storeForward
Add missing StoreForward config from radio
2024-04-22 11:14:21 -07:00
GUVWAF
d4156d78c6 Add missing StoreForward config from radio 2024-04-22 20:09:30 +02:00
Ian McEwen
c52977781e Merge pull request #553 from ianmcorvidae/more-dest-not-allowed
Disallow --dest in remaining spots that don't actually use/allow it
2024-04-21 13:03:58 -07:00
Ian McEwen
5ebc8e6f95 Don't allow --dest with --tunnel either 2024-04-21 10:38:01 -07:00
Ian McEwen
56d1dcafe5 --dest doesn't work with --export-config 2024-04-21 10:35:59 -07:00
Ian McEwen
393c765557 Fix up tests 2024-04-21 10:32:07 -07:00
Ian McEwen
243b310eb2 Allow generating QR codes for remote nodes and for all channels 2024-04-21 09:41:07 -07:00
Ian McEwen
cd1ecab4e0 Don't allow --dest with --setlat/lon/alt. Fixes #545 2024-04-21 09:38:32 -07:00
github-actions
c710953b85 bump version 2024-04-20 17:50:14 +00:00
Ian McEwen
70c5a30b77 protobufs: v2.3.6 2024-04-18 14:08:40 -07:00
Ian McEwen
9f0ba7aeae Merge pull request #549 from ianmcorvidae/export-import-config-altitude
Don't export null altitude, but support importing null lat/lon/alt as 0s
2024-04-18 12:32:04 -07:00
Ian McEwen
4226201423 Don't export null altitude, but support importing null lat/lon/alt as 0s. Fixes #548 2024-04-18 12:15:58 -07:00
Ian McEwen
bdf3a24be1 Merge pull request #546 from ianmcorvidae/request-position
Add a `--request-position` argument to request positions from nodes
2024-04-16 15:45:50 -07:00
Ian McEwen
e8ba5581f6 Add a --request-position argument to request positions from nodes 2024-04-16 15:43:24 -07:00
Ian McEwen
948846e0f1 Send the position the node already thinks it's at when --no-time is absent, rather than an empty position 2024-04-16 15:13:53 -07:00
Ian McEwen
6c4dbb6fe6 Fix quotes 2024-04-16 14:58:50 -07:00
Ian McEwen
afbabf9538 Merge branch 'bugfix-466-yaml-import' 2024-04-16 13:56:00 -07:00
Ian McEwen
d8107122a2 Merge remote-tracking branch 'danwelch3/bugfix-466-yaml-import' into bugfix-466-yaml-import 2024-04-16 13:53:54 -07:00
Dan Welch
03c1f08e45 Fix Lint Error
- add docstring to traverseConfig function
2024-04-16 14:46:35 -06:00
Ian McEwen
760fcfcea7 Merge pull request #544 from holdenweb/new-globals
Refactor to avoid the use of a special global object.
2024-04-16 13:17:16 -07:00
Ian McEwen
a4830f5f62 Treat a message as an ack if there is an errorReason but it's set to NONE, not just if the errorReason is absent 2024-04-16 13:10:18 -07:00
github-actions
2b1f337a41 bump version 2024-04-15 06:47:12 +00:00
Ian McEwen
ddad5f08b3 protobufs: v2.3.5 2024-04-14 12:30:14 -07:00
Ian McEwen
6e7933a3ce Fix my own pylint mistakes 2024-04-11 18:40:10 -07:00
Ian McEwen
f449ff9506 Add a variety of type annotations, primarily in mesh_interface 2024-04-11 18:28:01 -07:00
Steve Holden
a07e853f69 Refactor to remove pylint issues.
Since one of pylint's complains was that the globals module was
shadowing the built-in, and since the name `config` was already
is use in several modules, globals.py was renamed as mt_config.py.
All tests now pass, and the only remaining local pylint errors
relate to the protobuf code, I'm hoping this will make the PR
valid.
2024-04-10 17:42:44 +01:00
Steve Holden
0d57449030 Begin to rationalise test data.
Also refactor to silence some CI issues.
2024-04-10 14:25:17 +01:00
Steve Holden
067cddd354 Refactor to avoid the use of a special global object.
The global object formerly used is now replaced by direct use
of the namespace opf the globals module. This eliminates the
redundant getters and setters and simplifies the code for
future maintainers.

Note that the globals module name conflicts (harmlessly at
present) with a Python built-in function. A future commit
should rename it `config` to remove this clash and better
represent its intended purpose.
2024-04-10 10:03:12 +01:00
AeroXuk
4af1b322da Also accept nested settings in module_config.
Show full config path in output when nested.
2024-04-09 12:27:08 +01:00
AeroXuk
c580df15e1 Merge 'master' into 'bugfix-466-yaml-import'. 2024-04-09 12:20:04 +01:00
Ian McEwen
b280d0ba23 Merge pull request #541 from ianmcorvidae/removenode
Add --remove-node (fixes #514)
2024-04-08 15:05:11 -07:00
Ian McEwen
439b1ade2e Add --remove-node (fixes #514) 2024-04-08 14:58:15 -07:00
Ian McEwen
9f2b54eb98 Merge pull request #540 from ianmcorvidae/hopsaway
Show hops away when present in nodeDB (fixes #539)
2024-04-08 11:28:39 -07:00
Ian McEwen
278ca74a70 Show hops away when present in nodeDB (fixes #539) 2024-04-08 11:24:21 -07:00
Ian McEwen
1c93b7bd52 Revert "disable bump for post1 version"
This reverts commit 2d4be347e9.
2024-04-08 10:54:10 -07:00
Ian McEwen
2d4be347e9 disable bump for post1 version 2024-04-08 10:49:13 -07:00
Ian McEwen
26f024dc11 Set minimum version for protobuf to ensure presence of always_print_fields_with_no_presence 2024-04-08 10:47:01 -07:00
github-actions
2b8348ea05 bump version 2024-04-08 17:14:00 +00:00
Ian McEwen
7cea3cefc8 protobufs: v2.3.4 2024-04-08 10:12:50 -07:00
Ian McEwen
693533aba2 Merge pull request #538 from ianmcorvidae/organize-args
refactoring: Start adding some more structure to the arguments for the CLI
2024-04-07 23:33:21 -07:00
Ian McEwen
157f9cd276 Group and organize arguments a bit more 2024-04-07 23:20:02 -07:00
Ian McEwen
e742b5c0b8 Split out connection-related args into their own function & group 2024-04-05 15:22:26 -07:00
Ian McEwen
b57d1d81ff Fix up pylint from merged PR 2024-04-02 15:15:22 -07:00
Ian McEwen
4c97866875 Merge pull request #511 from flavoromission/506-show-all-module-settings
feat:506 show all module settings
2024-04-02 13:11:35 -07:00
Ian McEwen
8bb0cdf21b Merge pull request #528 from ianmcorvidae/protobufs-mypy
Protobuf type interfaces for type-checking & undoing protobufs hack
2024-04-01 10:50:24 -07:00
Ian McEwen
218e9b969a Merge pull request #532 from ianmcorvidae/listen-enables-debug
When `--listen` is set, turn on debug-level logging
2024-03-30 11:08:22 -07:00
Ian McEwen
917d6b2214 update docs for --listen too 2024-03-30 11:06:01 -07:00
Ian McEwen
523a855238 When --listen is set, turn on debug-level logging as though --debug was, even if it wasn't explicitly provided
Fixes #513
2024-03-30 11:04:33 -07:00
Ian McEwen
7a1b4b0d8b Attempt to add mypy to CI 2024-03-30 10:46:42 -07:00
Ian McEwen
896eeff1a4 Update codecov link, remove current docs link, update standalone installation docs link
fixes #529, fixes #531
2024-03-30 10:17:02 -07:00
Ian McEwen
9f0d223b81 Merge pull request #530 from Jorropo/meters
in --help indicate --setalt takes meters
2024-03-30 10:13:27 -07:00
Jorropo
5f92ac3995 in --help indicate --setalt takes meters 2024-03-30 10:36:56 +01:00
Ian McEwen
1b08aa4852 Attempt upgrading codecov action to see if tokenless uploads can be made to work 2024-03-29 19:58:24 -07:00
Ian McEwen
ffa2de5385 Attempt upgrading codecov action to see if tokenless uploads can be made to work 2024-03-29 19:54:51 -07:00
Ian McEwen
03ceb9bcab Ignore generated interfaces for pylint 2024-03-29 18:56:19 -07:00
Ian McEwen
59091664db Check against proper full name for moved protobufs 2024-03-29 18:38:26 -07:00
Ian McEwen
4baef92523 Fix assorted mypy-detected errors 2024-03-29 18:38:25 -07:00
Ian McEwen
4528cbf407 Update dependencies, regen-protobufs, protobufs, etc. to support types & mypy 2024-03-29 18:38:25 -07:00
Ian McEwen
ad8dbeab14 List unknown node IDs always with 8 hex digits, padded with 0s 2024-03-29 16:15:57 -07:00
github-actions
2746a8ebb6 bump version 2024-03-29 16:26:33 +00:00
Ian McEwen
5a277ab4bd Guard against lack of decoded message in --reply 2024-03-29 09:23:06 -07:00
Ian McEwen
1a278db65e protobufs: v2.3.3 2024-03-29 09:20:39 -07:00
Ben Meadors
276e99ad75 Remove vercel 2024-03-27 11:29:15 -05:00
Ben Meadors
f51bc8b9d7 Merge pull request #526 from ianmcorvidae/missing-portnums-knownprotocol
Add missing portnums to the dict for automatic decoding as protocol buffers/text
2024-03-26 07:39:51 -05:00
Ian McEwen
f3f6a6327d fixing copypaste error 2024-03-25 22:36:33 -07:00
Ian McEwen
d03c78518d Add missing portnums to the dict for automatic decoding as protocol buffers/text 2024-03-25 19:54:53 -07:00
Ian McEwen
54303b5e02 reset version bumping and setup.py 2024-03-25 14:16:42 -07:00
Ian McEwen
49a5f6a63a set to .post1 version number 2024-03-25 14:10:37 -07:00
Ian McEwen
934491dbd3 disable bump_version for now 2024-03-25 14:06:46 -07:00
Ian McEwen
f4120102b3 Fix things for nanopb.proto 2024-03-25 14:03:58 -07:00
github-actions
3839c75c82 bump version 2024-03-25 20:19:17 +00:00
Ian McEwen
05e181dece protobufs: v2.3.2 2024-03-25 13:17:23 -07:00
Ben Meadors
ad02ce172d Merge pull request #524 from ianmcorvidae/make-tests-happy
Fix up or comment out broken tests, to get CI (hopefully) happy
2024-03-24 20:25:15 -05:00
Ian McEwen
daa5587443 re-fix pylint 2024-03-23 22:17:49 -07:00
Ian McEwen
a139d180b8 Fix up or comment out broken tests, to get CI (hopefully) happy 2024-03-23 22:07:17 -07:00
Ian McEwen
09f8405422 Remove --sendping as REPLY_APP portnum is disabled in firmware now 2024-03-23 21:25:38 -07:00
Ben Meadors
107629e581 Merge pull request #523 from ianmcorvidae/readme-roadmap
Add a rudimentary call for contributors & roadmap to README.md
2024-03-22 14:28:38 -05:00
Ian McEwen
39a2ecb439 improve README wording 2024-03-22 12:27:05 -07:00
Ian McEwen
1318225e27 Add a rudimentary call for contributors & roadmap to README.md 2024-03-22 12:05:40 -07:00
Ian McEwen
85a6d4c21b Remove stale device_metadata_pb2 whose .proto file no longer exists 2024-03-22 11:46:29 -07:00
github-actions
1088880f04 bump version 2024-03-21 12:47:22 +00:00
Ben Meadors
0738e5ec6d Remove publish mac (for now) 2024-03-21 07:35:55 -05:00
Ben Meadors
5537778b64 2.3.1 protobufs 2024-03-20 10:27:19 -05:00
Ben Meadors
341d8e0cec Merge pull request #517 from ianmcorvidae/pylint-wrangling
Pylint wrangling
2024-03-19 17:51:14 -05:00
Ian McEwen
9b5943192d Make pylint happy with ble_interface.py 2024-03-19 13:18:15 -07:00
Ian McEwen
bf56521a53 Create Tunnel.TunnelError for specialized errors in that file 2024-03-19 13:00:06 -07:00
Ian McEwen
16a1af6a13 Create MeshInterface.MeshInterfaceError to specialize errors in that file 2024-03-19 12:58:44 -07:00
Ian McEwen
b8640666d7 Fix some outstanding pylint issues (or disable the checks) 2024-03-19 12:47:08 -07:00
Ben Meadors
0528a6fb3b Merge pull request #516 from ianmcorvidae/pkgversions-ci
use importlib.metadata and packaging.version instead of pkg_resources
2024-03-19 14:24:23 -05:00
Ian McEwen
5511871442 Add packaging to setup.py. hopefully. 2024-03-19 12:20:35 -07:00
Ian McEwen
486e13a93b Add 'packaging' to requirements.txt 2024-03-19 12:17:24 -07:00
Ian McEwen
759cafb817 use importlib.metadata and packaging.version instead of pkg_resources 2024-03-19 12:02:40 -07:00
flavor omission
27be73c707 feat:506 show all module settings
Problem:
Missing fields are omitted.

Solution:
This fix sets the flag `always_print_fields_with_no_presence`
in the invocation of the protobuff method
`MessageToJson` will display the missing fields.

see: MessageToJson 6b36eb633c/python/google/protobuf/json_format.py (L82)
see: issue #506 https://github.com/meshtastic/python/issues/506
2024-03-18 00:01:47 -04:00
Ben Meadors
bd788ae303 Merge pull request #508 from ianmcorvidae/set-ch-index-on-add
Set --ch-index to a newly added channel when --ch-add is set, to allow further modification
2024-03-17 07:45:29 -05:00
Ben Meadors
bb8a0d987f Merge pull request #509 from ianmcorvidae/fix-chset-options-list
Make --ch-set with invalid options print out the available options
2024-03-17 07:44:30 -05:00
Ian McEwen
92cc84e692 Make --ch-set with invalid options print out the available options as the documentation says it does 2024-03-16 11:58:38 -07:00
Ian McEwen
03abaf6059 Set --ch-index to a newly added channel when --ch-add is set, to allow further modification 2024-03-16 11:06:32 -07:00
Ben Meadors
6bed30e175 Merge pull request #505 from ianmcorvidae/unknown-nodes
Show unknown nodes in a fashion similar to the web UI. Fixes #504
2024-03-14 07:38:23 -05:00
Ian McEwen
9f2cc28fef Show unknown nodes in a fashion similar to the web UI. Fixes #504 2024-03-13 21:15:00 -07:00
Ben Meadors
fdd5b866b5 Merge pull request #503 from wnagele/ble_improvements
Make BLE connections a bit more resilient
2024-03-13 08:20:55 -05:00
Wolfgang Nagele
4ebb928400 Make BLE connections a bit more resilient 2024-03-13 14:08:32 +01:00
Jonathan Bennett
4522a8a7b0 Document automatic device search 2024-03-11 18:41:20 -05:00
Jonathan Bennett
14813e5c76 Attempt TCP connection to localhost if serial detect fails 2024-03-11 18:41:20 -05:00
Ben Meadors
c67d299984 Put bump version back 2024-03-11 12:45:32 -05:00
Ben Meadors
d1efe39c59 Temporarily remove bump_version 2024-03-11 12:38:21 -05:00
Ben Meadors
079c8c6a24 Version 2024-03-11 12:21:00 -05:00
Ben Meadors
fbcdab37ed Protobufs 2024-03-11 12:20:08 -05:00
Ben Meadors
83359a9cae Merge pull request #497 from meshtastic/revert-490-master
Revert "Move pb2 Files to Own Folder"
2024-03-11 12:18:53 -05:00
Ben Meadors
67636c4ce2 Revert "Move pb2 Files to Own Folder" 2024-03-11 12:18:25 -05:00
Ben Meadors
fdf594492c Merge pull request #496 from meshtastic/listen-command
Added command to listen to protobuf stream
2024-03-09 15:51:33 -06:00
Ben Meadors
8d6827dd23 Merge pull request #490 from rc14193/master
Move pb2 Files to Own Folder
2024-03-08 14:19:22 -06:00
Ben Meadors
a1ffb459f8 Added command to listen to protobuf stream 2024-03-08 14:16:02 -06:00
foglet15
df8ea85873 change to PbDefinitions for clearer naming 2024-02-25 14:22:15 -05:00
foglet15
10c2e753f5 fix tests imports, add sed for fixing pb2 imports 2024-02-25 14:16:31 -05:00
foglet15
769c99ec7d reset regen bash again 2024-02-25 14:02:45 -05:00
foglet15
1a8778022f use the move command instead 2024-02-25 13:53:10 -05:00
foglet15
b7e23ab762 use mv command instead, run regen test 2024-02-25 13:48:10 -05:00
foglet15
9fbde7b85a change regen to unmodified 2024-02-25 13:40:28 -05:00
foglet15
17ab557f81 change back to previous path 2024-02-25 13:32:25 -05:00
foglet15
8271997279 fix sed commands and dir path 2024-02-25 13:28:28 -05:00
foglet15
1c9af1f002 modify dir path 2024-02-25 13:26:01 -05:00
foglet15
9a4feecea8 move pb2 to own folder, regen script writes to new folder, update imports 2024-02-25 13:11:36 -05:00
Ben Meadors
90c218daa7 Merge pull request #489 from meshtastic/precision-try-2
Fixup handling for radio configs with disabled channel
2024-02-22 07:14:41 -06:00
Jonathan Bennett
a067c9295e Fixup handling for radio configs with disabled channel 2024-02-22 00:44:25 -06:00
github-actions
48fe844e12 bump version 2024-02-17 02:02:53 +00:00
Ben Meadors
1a9e728dee v2.2.23 protobufs 2024-02-16 20:02:10 -06:00
github-actions
34736bd246 bump version 2024-02-12 17:02:47 +00:00
Ben Meadors
193b8bcfb5 Merge pull request #486 from thoherr/add-paxcounter-config
add paxcounter moduleConfig (fixes Bug #485)
2024-02-12 11:01:58 -06:00
Ben Meadors
3321d8454a v.2.2.22 protos 2024-02-12 11:00:28 -06:00
Thomas Herrmann
22f2168bfd add paxcounter moduleConfig
(fixes Bug #485 "No valid config with name paxcounter" for me)
2024-02-10 14:06:02 +01:00
github-actions
2bf72523e9 bump version 2024-02-01 14:23:53 +00:00
Ben Meadors
658ecb60dc v2.2.21 protos 2024-02-01 08:23:02 -06:00
Ben Meadors
129f68ec14 Merge pull request #483 from bmidgley/brad/longer-timeout
Extend timeout for slow devices like pi zero
2024-01-28 07:51:46 -06:00
Brad Midgley
281ff788f3 Extend timeout for slow devices like pi zero 2024-01-28 06:35:15 -07:00
github-actions
70069323fc bump version 2024-01-16 17:12:28 +00:00
Ben Meadors
4721bc5adf Merge pull request #473 from wnagele/BLE_support
BLE Support
2024-01-16 11:11:50 -06:00
Ben Meadors
bc67546019 V2.2.18 protos 2024-01-16 10:39:50 -06:00
github-actions
dc35ffa12e bump version 2024-01-16 16:38:56 +00:00
Ben Meadors
b41baeac98 Merge pull request #477 from TimothyHarder/hardertimothy/issue-366
Issue #366 TCP connection error handling
2024-01-16 10:37:43 -06:00
Ben Meadors
bbc458954d Merge pull request #478 from TimothyHarder/hardertimothy/issue-424
Issue #424 Admin channel case sensitivity
2024-01-16 10:37:22 -06:00
Ben Meadors
2f59028df3 v2.2.17 2024-01-16 10:36:43 -06:00
Wolfgang Nagele
0a8a193081 BLE Support 2024-01-15 21:33:53 +01:00
github-actions
2eda2e56d5 Update protobuf submodule 2024-01-14 14:47:08 +00:00
Timothy Harder
52f8e82ea1 _getAdminChannelIndex can get the index of the admin channel regardless of case. 2024-01-07 14:02:44 -06:00
Timothy Harder
b11edacee0 Added except block to args.host to handle connection errors for the CLI. 2024-01-07 12:37:13 -06:00
github-actions
6dcdf7fc19 bump version 2024-01-06 12:24:57 +00:00
Ben Meadors
fe8ae6237e Merge pull request #469 from marek22k/improve-argument-handling
Improve argument handling
2024-01-04 20:30:36 -06:00
github-actions
7908fda1cf bump version 2023-12-17 17:43:05 +00:00
github-actions
fe9a367553 Update protobuf submodule 2023-12-17 17:41:45 +00:00
github-actions
79d7dcc199 bump version 2023-12-13 01:04:29 +00:00
Ben Meadors
ddf2221797 2.2.16 Protos 2023-12-12 19:03:23 -06:00
github-actions
a6f9100520 bump version 2023-12-13 01:01:38 +00:00
Ben Meadors
36011da918 2.2.15 protos 2023-12-12 19:00:48 -06:00
Ben Meadors
882e160a32 Merge pull request #471 from marek22k/cjdns-beacon
Tunnel: Add overlay peer discovery to blocklist
2023-12-12 18:58:37 -06:00
github-actions
958edbfdb2 bump version 2023-12-13 00:58:02 +00:00
Ben Meadors
484dc8007c 2.2.14 protos 2023-12-12 18:56:33 -06:00
Marek Küthe
2464bcf414 Tunnel: Add overlay peer discovery to blocklist 2023-12-09 11:50:47 +00:00
Dan Welch
590b60fefb Allow 'configure' to import yaml settings nested deepr than 2 levels
Resolves meshtastic/python#466
2023-12-06 11:52:22 -07:00
Marek Küthe
b468a0c908 Tunnel: Check other arguments 2023-12-04 12:55:36 +00:00
Marek Küthe
de154e50ca Tunnel: Pass variable only if it has content.
Closes https://github.com/meshtastic/python/issues/468
2023-12-04 12:55:06 +00:00
github-actions
70bb58b8ce bump version 2023-11-05 00:25:17 +00:00
Ben Meadors
dae63d4176 Protos 2023-11-04 19:24:27 -05:00
github-actions
9aef3b11f1 bump version 2023-11-03 21:41:23 +00:00
Ben Meadors
eebaa10d13 Regen protos 2023-11-03 07:50:30 -05:00
Ben Meadors
5076119b4f Merge pull request #463 from GUVWAF/AmbientLighting 2023-11-02 14:46:49 -05:00
GUVWAF
e25b183c23 Add getter/setter for AmbientLighting Module 2023-11-02 20:35:57 +01:00
github-actions
236d30f7c1 bump version 2023-10-11 14:59:14 +00:00
Ben Meadors
1f054abe47 Update protobufs 2023-10-11 09:58:07 -05:00
github-actions
d793ae431c bump version 2023-10-08 11:55:02 +00:00
Garth Vander Houwen
d02c4af995 Merge pull request #461 from sbias/add-channel-info
add channel info
2023-10-07 10:25:14 -07:00
Sascha Bias
7123a095dc add channel info 2023-10-07 19:01:01 +02:00
github-actions
abbe9ba10e bump version 2023-09-30 11:00:34 +00:00
Ben Meadors
6fe40e22b6 Update protos 2023-09-30 05:59:39 -05:00
Ben Meadors
ae648e7a82 Update protos 2023-09-26 06:09:43 -05:00
github-actions
550a5fe49a bump version 2023-09-26 11:06:05 +00:00
github-actions
20bb1ebdfa bump version 2023-09-20 12:01:35 +00:00
Ben Meadors
a6d20abcdf Protobufs 2023-09-20 07:00:21 -05:00
github-actions
7d9e75cf3f bump version 2023-09-14 12:02:11 +00:00
Ben Meadors
7c3df00b46 Protos 2023-09-14 07:01:02 -05:00
github-actions
28e848ace6 bump version 2023-09-12 20:53:06 +00:00
Ben Meadors
849724a129 Protobufs 2023-09-12 15:51:52 -05:00
Ben Meadors
309b069558 Protos 2023-09-07 07:23:15 -05:00
github-actions
cbedc982b6 bump version 2023-09-07 12:17:06 +00:00
Ben Meadors
dd482f2f89 Merge pull request #458 from EliSchleifer/master
Upgrade trunk to 1.15.0; enable new security linters
2023-09-07 06:30:33 -05:00
Eli Schleifer
29331cc3d2 sort linters 2023-09-06 13:16:27 -07:00
Eli Schleifer
4f2fbe39c0 Upgrade trunk to 1.15.0; enable new security linters 2023-09-06 13:11:47 -07:00
github-actions
b2f3ba11ae bump version 2023-08-26 00:28:47 +00:00
Ben Meadors
08c0b0e940 Protos 2023-08-25 19:28:06 -05:00
github-actions
775cb4d650 bump version 2023-08-21 20:32:45 +00:00
Ben Meadors
52cc825b3e Update protobufs 2023-08-21 14:56:26 -05:00
Ben Meadors
ce3065b37d Merge pull request #457 from GUVWAF/reqTelemetry
Add `request-telemetry` option
2023-08-21 14:50:27 -05:00
GUVWAF
d6ee815183 Only wait if response is wanted 2023-08-21 21:09:12 +02:00
GUVWAF
0192eed76e Spacing 2023-08-21 21:04:30 +02:00
GUVWAF
9858fa1976 Add request-telemetry option 2023-08-21 20:58:27 +02:00
Ben Meadors
95bfc0b428 Merge pull request #455 from bmidgley/brad/error-exit
Exit with an error code on failure
2023-08-11 06:21:36 -05:00
Brad Midgley
130c82ae4f Exit with an error code on failure 2023-08-10 22:18:08 -06:00
Ben Meadors
3698f2e4fb Add bump_version back 2023-08-08 19:09:54 -05:00
Ben Meadors
f58f8bdb1d Comment bump version for now 2023-08-08 16:50:09 -05:00
Ben Meadors
e76c9852d6 2.2 changes and added device_metadata 2023-08-08 16:40:15 -05:00
Ben Meadors
0788c1fadc Update protos to 2.2 and add neighbor_info 2023-08-08 13:48:51 -05:00
github-actions
a8057ac670 bump version 2023-08-08 17:49:28 +00:00
Ben Meadors
bb067e0e1e Remove min app version check 2023-08-08 12:48:03 -05:00
github-actions
755e68040f bump version 2023-08-06 20:54:23 +00:00
Ben Meadors
1687a4cb90 Update protos 2023-08-06 15:53:37 -05:00
github-actions
03398c7e3b bump version 2023-08-01 01:45:41 +00:00
Ben Meadors
d27be003c7 Update protos 2023-07-31 20:12:28 -05:00
github-actions
8e39a00c30 bump version 2023-07-26 00:47:11 +00:00
Ben Meadors
055da95b8a Update protos and remove old max_channels check 2023-07-25 19:46:17 -05:00
Ben Meadors
0c2ad5c77c Merge pull request #453 from luzpaz/typos
Fix various source comment typos
2023-07-25 19:42:44 -05:00
luzpaz
0a88ca6a5c Fix various source comment typos
Found via `codespell -q 3`
2023-07-15 01:04:47 +00:00
github-actions
51079d4f25 bump version 2023-07-09 11:26:51 +00:00
Ben Meadors
4ca3b4bf58 Update protobufs 2023-07-09 06:25:24 -05:00
Ben Meadors
25d42d3361 Merge pull request #451 from hhartzer/python-3.11
Update Github CI removing end-of-lifed Python 3.6 and 3.7, add 3.11
2023-07-07 19:43:51 -05:00
Henrich Hartzer
a1bffe4f26 Update Github CI removing end-of-lifed Python 3.6 and 3.7, add 3.11 2023-07-07 15:44:19 +00:00
github-actions
b87630803f bump version 2023-06-28 01:16:18 +00:00
Ben Meadors
e2c7a2c32c Update protobufs 2023-06-27 20:14:40 -05:00
Ben Meadors
9dda5d6d2d Merge pull request #449 from pdxlocations/no-psk
Show Channels with No PSK on --info
2023-06-25 14:48:04 -05:00
Ben Meadors
c3be392533 Merge pull request #450 from GUVWAF/NeighborInfo
Setter for NeighborInfo Module
2023-06-25 14:47:22 -05:00
GUVWAF
f63f2e3e39 Merge remote-tracking branch 'origin/master' into NeighborInfo 2023-06-25 15:55:38 +02:00
github-actions
c8dbac7770 Update protobuf submodule 2023-06-25 13:53:04 +00:00
GUVWAF
959c597e33 Setter for NeighborInfo 2023-06-25 15:50:59 +02:00
pdxlocations
4b0ca13ad1 list channels with no psk 2023-06-15 21:29:46 -07:00
github-actions
811bfdcb8c bump version 2023-05-30 12:46:45 +00:00
Ben Meadors
79095dc243 Update protos 2023-05-30 07:38:53 -05:00
github-actions
ff9ab44796 bump version 2023-05-28 14:33:46 +00:00
Ben Meadors
77dea8ee67 Update protos 2023-05-28 09:32:34 -05:00
Ben Meadors
c2eb466792 Merge pull request #445 from mverch67/fix-444
Fix TypeError: 'NoneType'
2023-05-26 05:49:51 -05:00
Manuel Verch
b4405dc60e Fix TypeError: 'NoneType' 2023-04-11 17:24:45 +02:00
github-actions
dc3d43c57c bump version 2023-04-11 15:06:05 +00:00
Ben Meadors
be91e923ab Merge pull request #443 from GUVWAF/master
Option to wait for ACK after --sendtext
2023-04-11 10:05:02 -05:00
Ben Meadors
6408d65ae7 2.1.8 protos 2023-04-11 10:04:29 -05:00
GUVWAF
6506a1be1a Option to wait for ACK after --sendtext 2023-04-10 11:26:50 +02:00
github-actions
fc768fa3ea bump version 2023-04-06 14:20:28 +00:00
Ben Meadors
8012f979cb Update protos 2023-04-06 09:15:45 -05:00
Manuel Verch
06b87b376c Fix: showNodes crash #439 2023-04-06 13:13:47 +02:00
Thomas Göttgens
1a97dc6982 Merge pull request #433 from mverch67/master
Output  of --info "Nodes in mesh" to JSON Format - YOLO
2023-03-31 20:11:55 +02:00
Thomas Göttgens
6a181ae025 Merge branch 'master' into master 2023-03-31 20:10:56 +02:00
Thomas Göttgens
97aa8a8d74 fixing a few linter errors. 2023-03-31 20:09:59 +02:00
Thomas Göttgens
7e6f13f0a2 establish trunk format 2023-03-31 20:09:59 +02:00
Manuel
f0723ffbc0 Merge branch 'meshtastic:master' into master 2023-03-31 10:41:10 +02:00
Manuel Verch
78f85efe56 Added install_requires requests 2023-03-31 10:08:36 +02:00
Manuel Verch
72510088c9 reverted file belonging to another PR 2023-03-31 10:08:36 +02:00
Manuel Verch
edb537947a Add module "requests" as requirement 2023-03-31 10:08:36 +02:00
Manuel Verch
b8b268feac Check most current meshtastic version 2023-03-31 10:08:36 +02:00
Manuel Verch
c28b61fbb1 Output of --info "Nodes in mesh" to JSON Format 2023-03-31 10:08:36 +02:00
Thomas Göttgens
62843ea39c Ignore the generated files 2023-03-31 10:04:42 +02:00
Pavel Boldin
cb93669740 python: add QueueStatus support
This makes Python API parse QueueStatus packages returned by
the firmware allowing for TX Queue status control from the phone
or PC. This makes it easier to not overwhelm device with packages
that are going to be ignored anyways.

Signed-off-by: Pavel Boldin <pavel.b@techspark.engineering>
2023-03-31 08:55:58 +02:00
Manuel Verch
f154d223bf Output of --info "Nodes in mesh" to JSON Format 2023-03-30 14:37:01 +02:00
github-actions
4980a02ef6 bump version 2023-03-29 00:36:41 +00:00
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
Thomas Göttgens
f3791c5c6d - make segemented config print entire name on screen
- rename wifi password to psk
2022-06-21 19:29:54 +02:00
github-actions
4cff344971 bump version 2022-06-21 16:18:33 +00:00
Ben Meadors
594b307e94 Merge pull request #344 from meshtastic/patch-1
Get and Set general attributes working.
2022-06-21 08:23:58 -05:00
Ben Meadors
8a5fd16469 Don't blow away config please 2022-06-21 08:05:15 -05:00
Ben Meadors
4fa93989fa Don't need to pass interface down 2022-06-19 15:41:21 -05:00
Ben Meadors
032072d2f3 Started on set 2022-06-19 09:55:09 -05:00
Ben Meadors
ce7b1d9916 Get preferences now working 2022-06-19 08:17:28 -05:00
Thomas Göttgens
d015da3ca1 Get and Set general attributes almost working. 2022-06-18 14:53:04 +02:00
Thomas Göttgens
a956c8068c Merge pull request #343 from meshtastic/patch-1
Untangle Modem Presets from Channels
2022-06-18 13:41:38 +02:00
Thomas Göttgens
2124e292f1 Untangle Modem Presets from Channels 2022-06-18 13:38:08 +02:00
Ben Meadors
115739a9bb Merge pull request #342 from meshtastic/nanopb-upgrade
Github action protos version
2022-06-17 08:39:00 -05:00
Ben Meadors
cc2c16b957 Github action protos version 2022-06-17 08:33:13 -05:00
Thomas Göttgens
b9245c6c1f Merge pull request #341 from meshtastic/patch-1
almost working
2022-06-17 12:40:06 +02:00
Thomas Göttgens
d21f7811fa where did that came from? 2022-06-17 12:37:50 +02:00
Thomas Göttgens
8dbd6431f7 almost working 2022-06-17 12:31:18 +02:00
Thomas Göttgens
c7b2bbf700 Merge pull request #340 from meshtastic/patch-1
remove "Request Settings" during init, team settings and deprecated settings.
2022-06-17 10:59:54 +02:00
Thomas Göttgens
682fdb7ef4 Remove test for deprecated option 2022-06-17 10:57:39 +02:00
Thomas Göttgens
9c79f9d80e Wait again, since we don't request config manually 2022-06-17 10:54:31 +02:00
Thomas Göttgens
c55b1188e8 remove "Request Settings" during init, team settings and deprecated settings. 2022-06-17 10:40:40 +02:00
github-actions
d5e4eaf2d8 bump version 2022-06-17 05:53:24 +00:00
mkinney
d49cc74828 Merge pull request #339 from mkinney/hack_13
Hack 13
2022-06-16 22:49:22 -07:00
Mike Kinney
47781fa1e0 remove unused import 2022-06-16 22:46:04 -07:00
Mike Kinney
cc98ed1084 comment yet another test 2022-06-16 22:43:42 -07:00
Mike Kinney
bec8cf2b13 change the d to an e 2022-06-16 22:40:48 -07:00
Mike Kinney
5bfebbe436 comment out code until it does not complain 2022-06-16 22:38:23 -07:00
Mike Kinney
c02a4d8138 Merge remote-tracking branch 'upstream/master' 2022-06-16 19:35:58 -07:00
mkinney
15aae34d65 Merge pull request #338 from mkinney/bump_nanopb
Bump nanopb
2022-06-16 19:30:46 -07:00
Mike Kinney
89b0426a2b fix warnings now that tests have been commented out 2022-06-16 19:26:52 -07:00
Mike Kinney
e1f1cab5a5 comment out failing tests (for now) 2022-06-16 19:22:13 -07:00
Mike Kinney
132fb4fe5f get pylint to pass 2022-06-16 19:13:18 -07:00
Mike Kinney
f1843649ba bump nanopb 2022-06-16 18:57:40 -07:00
Mike Kinney
43b7bbb5b3 Merge remote-tracking branch 'upstream/master' 2022-06-16 18:37:40 -07:00
Ben Meadors
b79b7ceb40 Correct config 2022-06-16 20:31:14 -05:00
Ben Meadors
2a546f8899 Merge master 2022-06-16 16:57:31 -05:00
Ben Meadors
a4a0740903 Regen protos 2022-06-16 16:57:05 -05:00
Ben Meadors
075ad01e46 Merge pull request #336 from meshtastic/change-default-baud
Changed baud to 115200
2022-06-15 11:46:31 -05:00
Ben Meadors
1296a1ce28 Changed baud to 115200 2022-06-15 10:58:55 -05:00
Thomas Göttgens
d510ba15c5 Trunk Protos 2022-06-09 12:20:13 +02:00
Jm Casler
decc887cb5 updating proto submodule to latest 2022-05-21 17:10:27 -07:00
Mike Kinney
163f7eeaaa update proto 2022-05-19 10:09:25 -07:00
Ben Meadors
d15667d5ce Regened new protos 2022-05-19 07:24:39 -05:00
Sacha Weatherstone
39a7869524 Update README.md 2022-05-12 21:52:04 +10:00
Sacha Weatherstone
c9464d2595 Update README.md 2022-05-12 21:28:38 +10:00
Sacha Weatherstone
717de611b9 Update ci.yml 2022-05-12 21:28:09 +10:00
Jm Casler
85869cf595 updating proto submodule to latest 2022-05-01 18:33:44 -07:00
Jm Casler
03ca28e0d2 updating proto submodule to latest 2022-05-01 08:42:04 -07:00
github-actions
a3bdf976bb bump version 2022-04-27 18:40:29 +00:00
mkinney
bf6eec626c Merge pull request #328 from mkinney/master
add nano_g1
2022-04-27 11:35:44 -07:00
Mike Kinney
cd0bdbbd9c add nano_g1 2022-04-27 11:29:05 -07:00
github-actions
e7faa85476 bump version 2022-04-27 12:33:09 +00:00
Ben Meadors
e419f95910 Merge pull request #327 from meshtastic/device-updates-release
Updated protos
2022-04-27 07:21:56 -05:00
Ben Meadors
ee613104f1 Updated protos 2022-04-27 07:19:08 -05:00
github-actions
93a8722b22 bump version 2022-04-25 07:20:32 +00:00
Thomas Göttgens
73b06248aa Update __init__.py
Device firmware requires 20300 now - change coming from android.
2022-04-25 09:15:33 +02:00
Jm Casler
82169f9d58 updating proto submodule to latest 2022-04-20 18:01:40 -07:00
github-actions
1fa71f2e2d bump version 2022-04-18 23:38:33 +00:00
mkinney
af599ab320 Merge pull request #326 from mkinney/master
update protos
2022-04-18 16:37:41 -07:00
Mike Kinney
99eed4bb5c remove send_owner_interval 2022-04-18 16:35:06 -07:00
Jm Casler
d8deb90527 updating proto submodule to latest 2022-04-18 12:29:23 -07:00
Mike Kinney
37a0010714 Merge remote-tracking branch 'upstream/master' 2022-04-18 11:53:16 -07:00
Mike Kinney
3c298df5ce update protos 2022-04-18 11:49:43 -07:00
Jm Casler
c6a8618d33 updating proto submodule to latest 2022-04-15 22:30:23 -07:00
Jm Casler
f19ddf66b8 updating proto submodule to latest 2022-04-12 21:10:46 -07:00
github-actions
203d5246eb bump version 2022-04-11 21:27:30 +00:00
mkinney
b78276e49a Merge pull request #323 from mkinney/master
fix smoke1 tests; regen protobufs
2022-04-11 14:26:00 -07:00
Mike Kinney
bd4d309d89 update codecov 2022-04-11 14:23:49 -07:00
Mike Kinney
804c09b6c5 bump to v2 of codecov 2022-04-11 14:18:38 -07:00
Mike Kinney
92202807f7 update/regen protobufs 2022-04-11 14:07:04 -07:00
Mike Kinney
0c92460163 got smoke1 tests to pass 2022-04-11 13:58:56 -07:00
Mike Kinney
8bb570d222 fix smoke1 tests 2022-04-11 13:17:39 -07:00
mkinney
f1abce9eff Merge pull request #322 from amerinoj/master
fixed set and get canned message
2022-04-11 12:48:50 -07:00
chst
1fc46a3c02 fixed set and get canned message
replacement the entries "get canned_message plugin" to get_canned_message_module_" in node.py
2022-04-10 19:21:57 +02:00
Jm Casler
1d45adfb27 Update README.md 2022-04-07 16:31:27 -07:00
mkinney
8365ad5d1b Merge pull request #316 from mkinney/master
fix tests for 1.3
2022-03-31 14:22:41 -07:00
Mike Kinney
00346ea441 fix tests for 1.3 2022-03-31 14:18:53 -07:00
github-actions
ae70d34dd6 bump version 2022-03-31 17:29:03 +00:00
mkinney
e0ef62d1b3 Merge pull request #315 from mkinney/master
detect devices only using vendor id
2022-03-31 10:28:04 -07:00
Mike Kinney
02e8467fdd detect devices only using vendor id 2022-03-31 10:24:17 -07:00
github-actions
48e7f8c755 bump version 2022-03-30 21:00:08 +00:00
mkinney
19b607b3f2 Merge pull request #314 from mkinney/master
add epaper; fix product id on 5005/4631
2022-03-30 13:59:15 -07:00
Mike Kinney
1d827ab2bf add epaper; fix product id on 5005/4631 2022-03-30 13:56:19 -07:00
github-actions
7af886cf07 bump version 2022-03-30 18:48:11 +00:00
mkinney
a76ad6c686 Merge pull request #313 from mkinney/master
regen code from latest protobufs
2022-03-30 11:36:33 -07:00
Mike Kinney
3d9a55add3 regen code from updated protobufs 2022-03-30 11:32:47 -07:00
Mike Kinney
4ceac5e847 Merge remote-tracking branch 'upstream/master' 2022-03-30 11:25:45 -07:00
Jm Casler
0939022cb4 updating proto submodule to latest 2022-03-29 21:44:51 -07:00
Jm Casler
f7afb9ff15 updating proto submodule to latest 2022-03-29 20:04:43 -07:00
Jm Casler
13fd4ba614 updating proto submodule to latest 2022-03-26 09:32:15 -07:00
Jm Casler
2f80c9866a updating proto submodule to latest 2022-03-25 22:30:43 -07:00
Jm Casler
e2bca647ae updating proto submodule to latest 2022-03-25 22:23:58 -07:00
mkinney
ec2467486c Merge pull request #302 from raldi/master
Added examples/tcp_gps_example.py
2022-03-22 15:10:25 -07:00
Mike Schiraldi
3332271a97 lint 2022-03-22 12:41:50 -07:00
github-actions
7fdfd782d8 bump version 2022-03-21 17:50:05 +00:00
Mike Kinney
af7bf7ff7f add wifi min length check 2022-03-21 10:48:27 -07:00
github-actions
b6dc4d0bd2 bump version 2022-03-16 03:26:41 +00:00
mkinney
8ec5dbbf38 Merge pull request #307 from mkinney/master
there is no tlora_v2.1
2022-03-15 20:13:51 -07:00
Mike Kinney
0c760f3721 there is no tlora_v2.1 2022-03-15 20:11:14 -07:00
mkinney
c45568731f Merge pull request #306 from mkinney/master
regen protobuf code; tlora v1 vendor/product id fix
2022-03-15 19:57:45 -07:00
Mike Kinney
ef4c9dc338 fix the vendor and product id for tlora v1 2022-03-15 19:54:18 -07:00
Mike Kinney
89de553aba regen python based on updated protobufs 2022-03-15 19:30:54 -07:00
mkinney
247e7b2605 Merge pull request #303 from mkinney/supported_devices_fixes
fix some tlora entries
2022-03-15 19:27:42 -07:00
Mike Kinney
f81ba64b91 fix some tlora entries 2022-03-15 19:25:04 -07:00
Jm Casler
d6fbca1bf1 updating proto submodule to latest 2022-03-15 15:46:02 -07:00
Mike Schiraldi
ef9441e7d2 Added examples/tcp_gps_example.py 2022-03-14 23:32:42 -07:00
Jm Casler
6fbf78fa19 updating proto submodule to latest 2022-03-14 18:05:28 -07:00
github-actions
e38a614c37 bump version 2022-03-11 23:08:22 +00:00
mkinney
d8b9665946 Merge pull request #299 from mkinney/master
update to latest protobufs
2022-03-11 15:07:34 -08:00
Mike Kinney
e655beb01c update to latest protobufs 2022-03-11 15:04:09 -08:00
mkinney
aa1dcb7f99 Merge pull request #298 from mkinney/master
refactor code to util; add duplicate check
2022-03-08 10:53:33 -08:00
Mike Kinney
1a2519d647 refactor code to util 2022-03-08 10:45:11 -08:00
Mike Kinney
a3572efaa6 add duplicate check 2022-03-08 10:44:14 -08:00
github-actions
e28f0d5509 bump version 2022-03-08 06:16:57 +00:00
mkinney
789a14054f Update release.yml 2022-03-07 22:16:03 -08:00
github-actions
4655b5c732 bump version 2022-03-08 06:04:02 +00:00
mkinney
81ebd8c8e7 Merge pull request #296 from mkinney/fix_release_version
keep sha ref and use it for subsequent checkouts
2022-03-07 22:02:28 -08:00
Mike Kinney
7998520e4a keep sha ref and use it for subsequent checkouts 2022-03-07 21:59:46 -08:00
mkinney
460196a62b Merge pull request #295 from mkinney/bug_when_ports_not_sorted
do not checkout the code again
2022-03-07 21:48:28 -08:00
Mike Kinney
22f43851bd do not checkout the code again 2022-03-07 21:44:11 -08:00
mkinney
91bb63eb97 Merge pull request #294 from mkinney/bug_when_ports_not_sorted
fix when ports are not sorted
2022-03-07 21:25:42 -08:00
Mike Kinney
ede1b5f08b fix when ports are not sorted 2022-03-07 21:21:41 -08:00
mkinney
a26c157c65 Merge pull request #292 from mkinney/handle_ignore_incoming
handle ignore_incoming repeated field
2022-03-03 17:14:09 -08:00
Mike Kinney
bcf00a1f8d handle ignore_incoming repeated field 2022-03-03 17:11:22 -08:00
Jm Casler
749a94e6e4 updating proto submodule to latest 2022-03-02 18:49:49 -08:00
github-actions
fc9d1e077c bump version 2022-03-02 21:56:05 +00:00
mkinney
a40f0b4038 Merge pull request #291 from mkinney/1_3_python
min req of python is 3.7 now; bump nanopb version
2022-03-02 13:55:09 -08:00
Mike Kinney
dbf54396f3 min req of python is 3.7 now; bump nanopb version 2022-03-02 13:29:19 -08:00
github-actions
3fe881e45a bump version 2022-03-02 19:43:05 +00:00
mkinney
af03c5163c Merge pull request #290 from mkinney/master
change version per pypi reqs
2022-03-02 11:42:09 -08:00
Mike Kinney
58de84945f change version per pypi reqs 2022-03-02 11:39:07 -08:00
github-actions
a2d4252002 bump version 2022-03-02 19:32:52 +00:00
mkinney
0689fc19a9 Merge pull request #289 from mkinney/1_3_initial
got lint and pytest working
2022-03-02 11:31:49 -08:00
Mike Kinney
68530f6e11 change medium to mid 2022-03-02 11:29:38 -08:00
Mike Kinney
fd752bedc5 change version format 2022-03-02 11:24:13 -08:00
Mike Kinney
cac880eb1a change to alpha 2022-03-02 11:15:47 -08:00
Mike Kinney
2c66cd4a95 change the name not the package 2022-03-02 10:50:08 -08:00
Mike Kinney
64e428f182 change package name and version 2022-03-02 10:44:35 -08:00
Mike Kinney
6f2efdcefe got lint and pytest working 2022-03-02 10:28:07 -08:00
github-actions
9214b2ffcc bump version 2022-03-02 00:20:31 +00:00
mkinney
cfb14d4b77 Merge pull request #287 from mkinney/changes_to_smokevirt
increase timeout; ensure secondary channel is deleted before trying t…
2022-03-01 16:19:14 -08:00
Mike Kinney
5965615e17 increase timeout; ensure secondary channel is deleted before trying to add it 2022-03-02 00:04:21 +00:00
Jm Casler
40eb7d8515 updating proto submodule to latest 2022-02-28 22:03:42 -08:00
Jm Casler
e2f36a9bea updating proto submodule to latest 2022-02-28 19:36:02 -08:00
Jm Casler
a0ba644488 updating proto submodule to latest 2022-02-27 10:01:44 -08:00
Jm Casler
2f67f344b7 updating proto submodule to latest 2022-02-27 09:57:16 -08:00
Jm Casler
8bb208aed1 updating proto submodule to latest 2022-02-27 09:52:34 -08:00
Jm Casler
48b145a592 updating proto submodule to latest 2022-02-27 01:00:38 -08:00
Jm Casler
65de9200fb updating proto submodule to latest 2022-02-27 00:48:57 -08:00
Jm Casler
e51d7a7a18 updating proto submodule to latest 2022-02-27 00:38:09 -08:00
Jm Casler
c4af50d63a updating proto submodule to latest 2022-02-26 21:22:33 -08:00
Jm Casler
933fe8953a updating proto submodule to latest 2022-02-26 21:09:20 -08:00
mkinney
66aa492d50 Merge pull request #283 from mkinney/add_cm
add cm
2022-02-25 23:44:13 -08:00
Mike Kinney
730934f520 add cm 2022-02-25 23:36:05 -08:00
mkinney
d2ec09eaf8 Merge pull request #281 from prampec/extend_canned_message_length
Canned message - Extend messages length
2022-02-25 22:58:57 -08:00
mkinney
7fd3b313b2 Update release.yml 2022-02-25 22:15:36 -08:00
github-actions
89f1549741 bump version 2022-02-26 06:11:26 +00:00
github-actions
e91015f5c8 bump version 2022-02-26 06:07:50 +00:00
mkinney
d9c3edfb12 Update release.yml 2022-02-25 22:06:27 -08:00
mkinney
cbf9696f47 Merge pull request #282 from mkinney/master
improve the release process
2022-02-25 22:04:48 -08:00
Mike Kinney
24e556b9a7 improve the release process 2022-02-25 22:01:21 -08:00
mkinney
eaf29512b6 Update standalone_readme.txt 2022-02-25 21:38:23 -08:00
Jm Casler
0c1e0ec375 updating proto submodule to latest 2022-02-22 17:10:04 -08:00
Balazs Kelemen
b56a054f50 Canned message - Extend messages length 2022-02-21 22:06:03 +01:00
Jm Casler
33ff4e36de updating proto submodule to latest 2022-02-20 01:32:53 -08:00
Jm Casler
bf879934e6 updating proto submodule to latest 2022-02-19 23:48:24 -08:00
Jm Casler
b878fa3a80 updating proto submodule to latest 2022-02-19 23:17:50 -08:00
Jm Casler
901849f176 updating proto submodule to latest 2022-02-19 23:10:53 -08:00
Jm Casler
371c0d22c2 updating proto submodule to latest 2022-02-19 22:55:38 -08:00
mkinney
4f7f38e0a7 Update setup.py 2022-02-18 11:16:49 -08:00
mkinney
85dca2e14e Merge pull request #278 from mkinney/fix_smoke1
add detection of duplicate ports to findPorts; fix smoke1 test
2022-02-18 11:16:25 -08:00
Mike Kinney
e53a5023f1 add detection of duplicate ports to findPorts; fix smoke1 test 2022-02-18 11:13:48 -08:00
mkinney
ce8b75d96d Merge pull request #277 from mkinney/win11_delay_only
only delay on win11
2022-02-18 10:12:16 -08:00
Mike Kinney
26f65c4fee only delay on win11 2022-02-18 10:08:53 -08:00
mkinney
1ba1e51ca4 Merge pull request #276 from mkinney/keep_devpath_on_serial
keep the devPath used on serial connections
2022-02-18 10:03:43 -08:00
Mike Kinney
f674afc412 keep the devPath used on serial connections 2022-02-18 09:59:09 -08:00
mkinney
db90b898e1 Update setup.py 2022-02-16 10:16:10 -08:00
mkinney
71621c2225 Merge pull request #269 from mkinney/two_serials
if we have a duplicate serial port use the appropriate one
2022-02-16 10:12:57 -08:00
Mike Kinney
ed36fca4a2 remove testing prints 2022-02-16 10:10:32 -08:00
Mike Kinney
fdd3699ba5 if we have a duplicate serial port use the appropriate one 2022-02-16 10:08:57 -08:00
Jm Casler
7d4b39643b updating proto submodule to latest 2022-02-14 20:35:46 -08:00
Jm Casler
7698cd2c7d updating proto submodule to latest 2022-02-14 20:08:31 -08:00
Jm Casler
03c744df54 updating proto submodule to latest 2022-02-14 19:55:21 -08:00
Jm Casler
90978d1f35 updating proto submodule to latest 2022-02-14 19:42:06 -08:00
Jm Casler
68a2bf271a updating proto submodule to latest 2022-02-14 17:59:45 -08:00
Jm Casler
8301384c53 updating proto submodule to latest 2022-02-14 16:59:26 -08:00
Jm Casler
045592212a updating proto submodule to latest 2022-02-14 16:56:59 -08:00
mkinney
45d879e607 Update setup.py 2022-02-12 21:19:20 -08:00
mkinney
3e44ee1eba Merge pull request #266 from mkinney/increase_sleep_for_win11
increase sleep for win11
2022-02-12 21:18:53 -08:00
Mike Kinney
36c5fc8d3c increase sleep for win11 2022-02-12 21:16:11 -08:00
mkinney
38ceb85ad9 Update setup.py 2022-02-10 15:15:46 -08:00
mkinney
6d18d9226d Merge pull request #263 from mkinney/add_rak11200
Add rak11200
2022-02-10 15:15:15 -08:00
Mike Kinney
6d5ed2129a add rak11200 2022-02-10 15:12:28 -08:00
Mike Kinney
5cfb6ffa11 add examples to lint and fix warnings 2022-02-10 14:51:22 -08:00
mkinney
363b268ccf Update setup.py 2022-02-03 10:03:31 -08:00
mkinney
e6cddb0084 Merge pull request #260 from mkinney/update_protobufs
update protobufs to latest
2022-02-03 10:01:31 -08:00
Mike Kinney
5e77bf62b9 update protobufs to latest 2022-02-03 09:59:03 -08:00
github-actions
4905c0b179 Update protobuf submodule 2022-02-03 15:00:36 +00:00
Ben Meadors
43ab3be804 Update update_protobufs.yml 2022-02-03 08:59:32 -06:00
github-actions
14a6e581bc Update protobuf submodule 2022-02-03 14:38:02 +00:00
mkinney
cadad32bdb Update setup.py 2022-02-01 17:44:37 -08:00
mkinney
71c6411d1a Merge pull request #257 from mkinney/add_techo_info
add T-Echo info
2022-02-01 17:41:19 -08:00
Mike Kinney
85e8fad16f add T-Echo info 2022-02-01 17:18:05 -08:00
mkinney
67398222d4 Update setup.py 2022-02-01 13:56:03 -08:00
mkinney
1a82bdee75 Merge pull request #256 from mkinney/update_proto2
fix regen-protos script
2022-02-01 13:55:42 -08:00
Mike Kinney
9fff26c3db fix regen-protos script 2022-02-01 13:53:14 -08:00
mkinney
172f6c577d Merge pull request #254 from mkinney/force_win_encoding
specify a code page on windows
2022-02-01 12:03:08 -08:00
Mike Kinney
ff5652058d fix lint complaining about long lines 2022-02-01 12:00:58 -08:00
Mike Kinney
5241fabb33 change encoding to utf8 for windows 2022-02-01 11:56:07 -08:00
Mike Kinney
6c9aa5794f specify a code page on windows 2022-02-01 11:44:02 -08:00
mkinney
7c8cb375a3 Merge pull request #252 from mkinney/update_sd_info
add info about 19003
2022-01-30 23:11:22 -08:00
Mike Kinney
a6e770f548 add info about 19003 2022-01-30 22:38:35 -08:00
mkinney
eb7683450f Merge pull request #251 from mkinney/update_sd
add more info about some devices; fix tlora info
2022-01-30 21:15:40 -08:00
Mike Kinney
ee739d3414 add more info about some devices; fix tlora info 2022-01-30 17:36:15 -08:00
mkinney
b864bbdd5f Update setup.py 2022-01-29 21:48:57 -08:00
mkinney
5a740eddc3 Merge pull request #250 from mkinney/bugfix_for_owner_short
fix bug
2022-01-29 21:48:17 -08:00
Mike Kinney
fdced6f225 fix bug 2022-01-29 21:37:34 -08:00
mkinney
3d772845f9 Merge pull request #249 from mkinney/device_detection
Device detection
2022-01-29 21:11:40 -08:00
Mike Kinney
72326d467e only show active windows ports 2022-01-29 20:53:09 -08:00
Mike Kinney
a0944961b5 fix lint warnings 2022-01-29 20:47:58 -08:00
Mike Kinney
1fa61ece93 add windows device and port detection 2022-01-29 20:45:29 -08:00
Mike Kinney
288d0bb884 add detection on mac 2022-01-29 17:12:36 -08:00
Mike Kinney
28a2aa47e8 add device and port detection on linux 2022-01-30 00:57:56 +00:00
mkinney
069056edad Update setup.py 2022-01-27 17:12:50 -08:00
github-actions
19bd510975 Update protobuf submodule 2022-01-28 01:12:41 +00:00
mkinney
7979efc0a1 Merge pull request #247 from mkinney/remote_hardware
remote hardware tests
2022-01-27 17:11:37 -08:00
Mike Kinney
66866a4c65 fix logic 2022-01-27 17:09:13 -08:00
Mike Kinney
e6fb066fe5 get last couple of lines covered in remote_hardware 2022-01-27 17:05:16 -08:00
Mike Kinney
5841979566 remove line 2022-01-27 17:00:53 -08:00
Mike Kinney
529f50edc6 remote hardware tests 2022-01-27 16:54:47 -08:00
github-actions
5895e8fb4d Update protobuf submodule 2022-01-27 14:21:10 +00:00
mkinney
49dcf71116 Update setup.py 2022-01-26 20:32:45 -08:00
Jm Casler
5778552380 updating proto submodule to latest 2022-01-26 13:35:48 -08:00
Jm Casler
592ecc9997 updating proto submodule to latest 2022-01-26 12:27:52 -08:00
mkinney
1aaa205cc9 Merge pull request #246 from mkinney/update_help
add more info on --ch-set help
2022-01-26 11:22:05 -08:00
Mike Kinney
ff5a0927fa add more info on --ch-set help 2022-01-26 11:16:01 -08:00
mkinney
607127d46e Update regen-protos.sh 2022-01-23 15:15:14 -08:00
mkinney
cf61a5d39d Update update_protobufs.yml 2022-01-23 15:09:44 -08:00
mkinney
69b2599abb Update setup.py 2022-01-23 14:51:38 -08:00
mkinney
533e50de9d Update release.yml 2022-01-23 14:51:21 -08:00
mkinney
12b99f80dc Update release.yml 2022-01-23 14:48:59 -08:00
mkinney
0193ca052f Update setup.py 2022-01-23 14:47:26 -08:00
mkinney
e0af620cbe Merge pull request #245 from mkinney/standalone_readme
add readme.txt to release for standalone zip files
2022-01-23 14:47:06 -08:00
Mike Kinney
80367232ae add readme.txt to release for standalone zip files 2022-01-23 14:44:59 -08:00
mkinney
1c480bd74f Update setup.py 2022-01-23 14:25:01 -08:00
mkinney
ba05de263c Update release.yml 2022-01-23 14:24:48 -08:00
mkinney
f045c3bc2b Update setup.py 2022-01-23 14:17:05 -08:00
mkinney
9ec5f33a85 Update release.yml 2022-01-23 14:16:50 -08:00
mkinney
e1cc657059 Update setup.py 2022-01-23 14:10:58 -08:00
mkinney
9c3dce4bbb Update release.yml 2022-01-23 14:10:43 -08:00
mkinney
5418539275 Update setup.py 2022-01-23 14:04:51 -08:00
mkinney
3103640688 Update release.yml 2022-01-23 14:04:36 -08:00
mkinney
86beb2f212 Update setup.py 2022-01-23 14:03:05 -08:00
mkinney
dd1c96fcba Update release.yml 2022-01-23 14:02:48 -08:00
mkinney
b282baadb7 Update setup.py 2022-01-23 13:55:08 -08:00
mkinney
fccb38fced Update release.yml 2022-01-23 13:54:53 -08:00
mkinney
700a7e27d3 Update setup.py 2022-01-23 13:51:06 -08:00
mkinney
bb1c40c7f8 Update release.yml 2022-01-23 13:50:49 -08:00
mkinney
407490c654 Update setup.py 2022-01-23 13:38:54 -08:00
mkinney
dfd61af346 Update release.yml 2022-01-23 13:38:36 -08:00
mkinney
a85b4ad985 Update setup.py 2022-01-23 13:35:02 -08:00
mkinney
eacffa79fa Update release.yml 2022-01-23 13:34:47 -08:00
mkinney
ca5449f1b8 Update release.yml 2022-01-23 13:21:50 -08:00
mkinney
6751f5bd53 Update release.yml 2022-01-23 13:12:17 -08:00
mkinney
c5c70fe83e Update setup.py 2022-01-23 13:10:06 -08:00
mkinney
0c0cd81253 Update release.yml 2022-01-23 13:09:40 -08:00
mkinney
553a03e40f Update setup.py 2022-01-23 12:53:51 -08:00
mkinney
b50190aeb0 Update release.yml 2022-01-23 12:53:32 -08:00
mkinney
bc231a8a9d Update setup.py 2022-01-23 12:34:36 -08:00
mkinney
c1c9cb8139 Update release.yml 2022-01-23 12:34:12 -08:00
mkinney
0a915e305d Update setup.py 2022-01-23 12:09:55 -08:00
mkinney
308eb1f321 Update release.yml 2022-01-23 12:09:36 -08:00
mkinney
d576c0e30b Update setup.py 2022-01-23 12:01:41 -08:00
mkinney
e63d4c3a30 Update release.yml 2022-01-23 12:01:17 -08:00
mkinney
2041e81101 Update setup.py 2022-01-23 11:49:04 -08:00
mkinney
f396374fa8 Update release.yml 2022-01-23 11:48:13 -08:00
mkinney
1a0db63f32 Merge pull request #244 from mkinney/release_improvements
improve the release process
2022-01-23 11:44:33 -08:00
Mike Kinney
0d32a83e66 improve the release process 2022-01-23 11:41:49 -08:00
mkinney
7ac3328db8 Merge pull request #243 from mkinney/short_name
Short name
2022-01-23 11:25:06 -08:00
Mike Kinney
4f72987a29 add some config tests 2022-01-23 11:22:05 -08:00
Mike Kinney
aa5af53348 add option to configure just the owner short name 2022-01-23 11:17:41 -08:00
Jm Casler
030ee8554c updating proto submodule to latest 2022-01-23 09:10:37 -08:00
mkinney
80d447d64b Update setup.py 2022-01-21 17:15:26 -08:00
mkinney
bfac5a418c Merge pull request #239 from meshtastic/update-protos-for-shutdown
Shutdown command (should mirror reboot)
2022-01-21 17:05:26 -08:00
mkinney
a3b09f028a Merge pull request #242 from mkinney/help_update_protos_for_shutdown
ignore new pb file
2022-01-21 17:00:19 -08:00
Mike Kinney
930292aaad ignore new pb file 2022-01-21 16:59:17 -08:00
mkinney
1d3b59a7e0 Merge pull request #240 from mkinney/help_update_protos_for_shutdown
update protos
2022-01-21 16:56:59 -08:00
Mike Kinney
d54b518bfd update protos 2022-01-21 16:55:09 -08:00
Ben Meadors
ccb8bb83a6 Consistent spacing 2022-01-21 18:33:09 -06:00
Ben Meadors
076e865f77 Node level test 2022-01-21 18:20:50 -06:00
Ben Meadors
8ceb9faf2d Shutdown command 2022-01-21 18:11:26 -06:00
github-actions
b15e5f516a Update protobuf submodule 2022-01-21 23:58:36 +00:00
github-actions
e161d75986 Update protobuf submodule 2022-01-20 22:18:17 +00:00
mkinney
084473a340 Update README.md
add pypi downloads
2022-01-20 10:10:42 -08:00
Jm Casler
74d6d4d634 updating proto submodule to latest 2022-01-19 18:18:59 -08:00
github-actions
38ac4298a0 Update protobuf submodule 2022-01-19 23:56:04 +00:00
mkinney
9b2c0e7954 Merge pull request #237 from mkinney/master
regen proto from updated protobufs
2022-01-16 17:06:35 -08:00
Mike Kinney
62472034f1 regen proto from updated protobufs 2022-01-17 00:26:31 +00:00
github-actions
13cfc19841 Update protobuf submodule 2022-01-17 00:21:35 +00:00
mkinney
4955ab8df2 Update setup.py 2022-01-16 12:48:35 -08:00
mkinney
de39c98e50 Merge pull request #236 from mkinney/fix_enum_listing
fix enum listing; add tests for pref values
2022-01-16 12:47:49 -08:00
Mike Kinney
51378bb0eb fix enum listing; add tests for pref values 2022-01-16 12:45:28 -08:00
mkinney
aff3bdd78e Update setup.py 2022-01-15 14:19:36 -08:00
mkinney
e9a8e26e76 Merge pull request #235 from mkinney/fix_for_setPref
looks like we needed some of that dead code after all
2022-01-15 14:19:07 -08:00
Mike Kinney
83439679c1 looks like we needed some of that dead code after all 2022-01-15 14:15:55 -08:00
mkinney
968027a439 Update setup.py 2022-01-15 10:38:40 -08:00
mkinney
cc24b6ebc5 Merge pull request #231 from mkinney/camelCase
handle snake_case or camelCase
2022-01-15 10:32:08 -08:00
Mike Kinney
db09b4718d add two more lines to code coverage 2022-01-15 10:21:24 -08:00
Jm Casler
e0edbc6288 updating proto submodule to latest 2022-01-15 09:34:14 -08:00
Mike Kinney
ae9ae91af5 remove dead code 2022-01-15 00:24:41 -08:00
Mike Kinney
7921db007b add some coverage to getPref() and setPref() 2022-01-15 00:01:44 -08:00
Mike Kinney
e85af2f9e9 Merge branch 'camelCase' of github.com:mkinney/Meshtastic-python into camelCase 2022-01-14 20:16:26 -08:00
Mike Kinney
8ccc64f92e Merge remote-tracking branch 'upstream/master' into camelCase 2022-01-14 20:16:10 -08:00
Mike Kinney
afb21c6dc3 remove code not needed 2022-01-14 20:15:25 -08:00
mkinney
3291bc7097 Merge branch 'meshtastic:master' into camelCase 2022-01-14 20:06:40 -08:00
Mike Kinney
a7d56504be handle snake_case or camelCase 2022-01-14 16:36:53 -08:00
Jm Casler
90e5b473d9 updating proto submodule to latest 2022-01-13 16:55:22 -08:00
mkinney
52834e9966 Update setup.py 2022-01-12 17:25:00 -08:00
mkinney
63c60d4cea Merge pull request #229 from mkinney/check_for_multiple_mac_conversions
suggested fix from MitchConner912 for not converting mac address more…
2022-01-12 17:13:14 -08:00
Mike Kinney
6a2a9d2093 suggested fix from MitchConner912 for not converting mac address more than once 2022-01-12 17:10:51 -08:00
mkinney
1410448808 Merge pull request #228 from mkinney/more_unit_tests
add more unit tests
2022-01-12 17:06:24 -08:00
Mike Kinney
ad8f2222db cover a few more lines 2022-01-12 16:50:29 -08:00
Mike Kinney
48265e73b1 no need to import pygatt here 2022-01-12 15:54:07 -08:00
Mike Kinney
f3139a8aa0 add more unit tests 2022-01-12 15:50:16 -08:00
mkinney
8d68e36703 Merge pull request #227 from mkinney/pylint_fixes
fix the consider-using-f-string warnings
2022-01-12 14:57:50 -08:00
Mike Kinney
d2d93fbe80 no longer need to disable this pylint warning 2022-01-12 14:50:10 -08:00
Mike Kinney
ed8510468d no need to disable these pylint warnings anymore 2022-01-12 14:47:49 -08:00
Mike Kinney
e7680e07c2 fix pylint global-statement warnings 2022-01-12 14:46:21 -08:00
Mike Kinney
0f89baa36e fix the pylint unused-argument warnings 2022-01-12 14:41:49 -08:00
Mike Kinney
48ed7690af fix the consider-using-f-string warnings 2022-01-12 13:46:01 -08:00
mkinney
59b94ea650 Merge pull request #226 from mkinney/add_get_hw_example
add example how you can get the hwModel using api
2022-01-12 10:59:43 -08:00
Mike Kinney
5b992734fb add example how you can get the hwModel using api 2022-01-12 10:57:03 -08:00
mkinney
3b74b911f8 Merge pull request #224 from mkinney/add_set_owner_example
simple example showing how you can set the long and short name
2022-01-12 10:26:22 -08:00
Mike Kinney
b6570e3c27 simple example showing how you can set the long and short name 2022-01-12 10:23:51 -08:00
mkinney
e1e1664b96 Merge pull request #223 from mkinney/make_pygatt_linux_only
make pygatt linux only in requirements.txt
2022-01-12 10:23:06 -08:00
Mike Kinney
cb1913dfc3 make pygatt linux only in requirements.txt 2022-01-12 10:15:06 -08:00
Sacha Weatherstone
b813a6f8c5 Update requirements.txt 2022-01-12 14:39:20 +11:00
mkinney
0b662318e1 Merge pull request #222 from mkinney/testing_on_mac_air
fixes for working on mac air
2022-01-11 16:48:01 -08:00
Mike Kinney
a6ccc1a246 add conditional lib if linux 2022-01-11 16:42:25 -08:00
Mike Kinney
bc17e9b389 fixes for working on mac air 2022-01-11 16:36:39 -08:00
mkinney
b08e96b66a Update setup.py
bump version for release
2022-01-11 11:02:26 -08:00
mkinney
9e74ead54e Merge pull request #219 from mkinney/smoke_virt
add smoke test for virtual device
2022-01-11 10:56:33 -08:00
Mike Kinney
2cf52f3df6 add a convenience target in Makefile for running the smokevirt test 2022-01-11 18:50:18 +00:00
Mike Kinney
50e9a0a9f7 exclude smokevirt from ci 2022-01-11 18:44:39 +00:00
Mike Kinney
841c44e05c add smoke test for virtual device 2022-01-11 18:39:49 +00:00
mkinney
465bafeb30 Merge pull request #218 from mkinney/fix_remote_admin_message
refactor code to only call local node when necessary; fix tests
2022-01-10 16:51:04 -08:00
Mike Kinney
cb8dafbd31 add more coverage 2022-01-10 16:40:47 -08:00
Mike Kinney
52db617b06 refactor code to only call local node when necessary; fix tests 2022-01-10 16:20:11 -08:00
Jm Casler
ec622590da updating proto submodule to latest 2022-01-09 22:23:07 -08:00
mkinney
345cb1bdc4 Merge pull request #217 from mkinney/fix_remote_admin_message
Fix remote admin message
2022-01-06 12:36:03 -08:00
Mike Kinney
8ca692a26e cannot call os.getlogin() on github instances 2022-01-06 12:33:30 -08:00
Mike Kinney
d1ea68d7dc add code coverage to recently added code 2022-01-06 12:17:42 -08:00
Mike Kinney
b56440a4e8 should not need to talk with remote node if just doing sendtext 2022-01-06 11:55:36 -08:00
github-actions
1401b949a3 Update protobuf submodule 2022-01-06 17:09:45 +00:00
mkinney
97f3ce6198 Merge pull request #215 from mkinney/combine_build_single_executables
combine the building of single executables into one action
2022-01-06 00:25:46 -08:00
Mike Kinney
8019391914 combine the building of single executables into one action 2022-01-06 00:24:59 -08:00
mkinney
8d10010ab1 Merge pull request #214 from mkinney/more_testing_stuff
move slower unit tests to unitslow
2022-01-06 00:00:42 -08:00
mkinney
a2b4d2a96a Update build_mac.yml 2022-01-05 23:47:02 -08:00
mkinney
4de558bdf6 Update build_mac.yml 2022-01-05 23:40:49 -08:00
mkinney
8ff06a0de1 Update build_mac.yml 2022-01-05 23:37:35 -08:00
mkinney
f8ad6061c1 Update build_mac.yml
revert
2022-01-05 23:06:49 -08:00
mkinney
aa4cdb6aea Update build_mac.yml 2022-01-05 23:01:13 -08:00
Mike Kinney
cba424fde0 move slower unit tests to unitslow 2022-01-05 21:12:50 -08:00
mkinney
6c7a870645 Merge pull request #213 from mkinney/add_python_310
check python v3.10 as well
2022-01-05 18:20:55 -08:00
Mike Kinney
f42b1ad4e0 check python v3.10 as well 2022-01-05 18:18:31 -08:00
mkinney
30a51952e0 Merge pull request #212 from mkinney/serial_perms
improve the permission error on linux
2022-01-05 15:08:24 -08:00
Mike Kinney
5de754c5ab improve the permission error on linux 2022-01-05 23:03:06 +00:00
mkinney
bda446c7b5 Update build_mac.yml 2022-01-05 14:13:42 -08:00
mkinney
f79540f197 Update build_mac.yml 2022-01-05 14:09:17 -08:00
mkinney
d507697e56 Merge pull request #210 from mkinney/work_on_single_executable
install meshtastic before building single executable
2022-01-05 13:58:47 -08:00
Mike Kinney
acbc1f2e30 install meshtastic before building single executable 2022-01-05 13:56:07 -08:00
mkinney
7b3c68119c Merge pull request #209 from mkinney/add_modules_for_building_single_executables
collect the meshtastic libs
2022-01-05 13:36:25 -08:00
Mike Kinney
39f97166b0 collect the meshtastic libs 2022-01-05 13:34:28 -08:00
mkinney
541d19cafb Merge pull request #208 from mkinney/create_actions_for_building_single_executables
Create actions for building single executables
2022-01-05 13:26:47 -08:00
Mike Kinney
969a81b779 Merge remote-tracking branch 'upstream/master' into create_actions_for_building_single_executables 2022-01-05 13:24:33 -08:00
Mike Kinney
3f76c1efb0 refactor version info so pyinstaller will work; add build mac and ubuntu standalone executables 2022-01-05 13:22:37 -08:00
mkinney
774849189f Merge pull request #207 from mkinney/create_build_windows_action
add a build windows action
2022-01-05 12:46:10 -08:00
Mike Kinney
53d626aa72 add a build windows action 2022-01-05 12:44:05 -08:00
mkinney
1a3a840269 Merge pull request #206 from mkinney/fully_qualify_imports
need to fully qualify imports so projects consuming the library will …
2022-01-05 11:24:13 -08:00
Mike Kinney
fe69f05e75 add python 3.6, 3.7, 3.8, and 3.9 for ci and validation 2022-01-05 11:20:04 -08:00
Mike Kinney
5c662822b9 need to fully qualify imports so projects consuming the library will work 2022-01-05 11:16:08 -08:00
mkinney
c049d3424a Merge pull request #205 from mkinney/remove_nested_keys
remove nested keys from nodes so we do not display garbage
2022-01-02 11:28:07 -08:00
Mike Kinney
471535853b bump version 2022-01-02 11:20:15 -08:00
Mike Kinney
676148cc14 meant to use decoded not decode 2022-01-02 11:19:17 -08:00
Mike Kinney
a915b05240 remove nested keys from nodes so we do not display garbage 2022-01-02 11:15:19 -08:00
Jm Casler
a1668e8c66 updating proto submodule to latest 2022-01-01 23:25:22 -08:00
mkinney
e7664cb40b Merge pull request #204 from mkinney/add_more_unit_tests
get last two lines covered in node
2022-01-01 15:51:21 -08:00
Mike Kinney
83c18f4008 working on more unit tests 2022-01-01 15:48:33 -08:00
Mike Kinney
8b6321ce7f add a few more tests 2022-01-01 15:21:53 -08:00
Mike Kinney
9fac981ba6 test heartbeatTimer 2022-01-01 14:53:57 -08:00
Mike Kinney
ccc71930f7 get last two lines covered in node 2022-01-01 13:25:36 -08:00
mkinney
9380f048fa Update setup.py
bump version
2022-01-01 11:11:54 -08:00
mkinney
0a655ac8df Merge pull request #203 from mkinney/minor_changes
do not print line for export; comment out ble test; do not send decoded
2022-01-01 09:51:34 -08:00
Mike Kinney
0b6676c5b3 do not print line for export; comment out ble test; do not send decoded 2022-01-01 09:49:21 -08:00
mkinney
e5ecba7ec0 Merge pull request #202 from mkinney/format_mac_address
if mac address is in nodes, format it like a valid mac address
2021-12-31 20:04:19 -08:00
Mike Kinney
a1809f5b84 if mac address is in nodes, format it like a valid mac address 2021-12-31 20:01:14 -08:00
mkinney
9c66447913 Merge pull request #201 from mkinney/more_testing
added tests for _getOrCreateByNum(), nodeNumToId(), and _fixupPositio…
2021-12-31 14:26:37 -08:00
Mike Kinney
65960fb982 added tests for _getOrCreateByNum(), nodeNumToId(), and _fixupPosition(); found/fixed bug on _fixupPosition 2021-12-31 13:43:37 -08:00
mkinney
9d0bc09e0f Merge pull request #200 from mkinney/tuning_tests
Tuning tests
2021-12-31 12:30:00 -08:00
Mike Kinney
475ddcc8dd add tests for _ipToNodeId() 2021-12-31 12:28:14 -08:00
Mike Kinney
105276f98e add unit tests for _shouldFilterPacket() 2021-12-31 12:17:04 -08:00
Mike Kinney
4ee647403b fix output on tests using pytest -s option; fixed some tests 2021-12-31 10:55:13 -08:00
Mike Kinney
10f48f130f move some unit tests to unitslow 2021-12-31 09:59:22 -08:00
mkinney
bd697864e4 Merge pull request #199 from mkinney/unit_testing_continues
revert the stream interface change; fix tunnel tests
2021-12-31 09:40:58 -08:00
Mike Kinney
ab876c9efd add unit test for findPorts() 2021-12-31 09:38:44 -08:00
Mike Kinney
aba303c677 figured out issue; had device connected to serial port; needed to patch; fixed tunnel test in main 2021-12-31 09:28:17 -08:00
Mike Kinney
43d59ca8d8 temp comment out tests that pass locally but not when run from CI 2021-12-31 08:53:17 -08:00
Mike Kinney
177705aeff revert the stream interface change; fix tunnel tests 2021-12-31 08:49:13 -08:00
Sacha Weatherstone
b92fff0da6 Create vercel.json 2021-12-31 20:46:21 +11:00
mkinney
6a6b72a2ae Merge pull request #198 from mkinney/keep_working_on_unit_tests
start to add unit tests for tunnel
2021-12-30 23:01:05 -08:00
Mike Kinney
614a90c0eb unit test a few more lines 2021-12-30 22:59:01 -08:00
Mike Kinney
9adbed4be6 add unit tests for onTunnelReceive() 2021-12-30 22:52:49 -08:00
Mike Kinney
809f005f61 add unit tests for ipstr(), hexstr(), and readnet_u16() 2021-12-30 22:26:26 -08:00
Mike Kinney
d366e74e86 refactor of Tunnel() for unit testing; create unit tests for Tunnel() 2021-12-30 21:24:32 -08:00
Mike Kinney
3f307880f9 add unit tests for tunnel and subnet 2021-12-30 20:04:32 -08:00
Mike Kinney
50523ec1b1 start to add unit tests for tunnel 2021-12-30 19:37:38 -08:00
mkinney
684b2885aa Merge pull request #197 from mkinney/work_on_unit_tests
add more tests; do not need the old --reply test
2021-12-30 12:28:36 -08:00
Mike Kinney
f5eb8738fb added unit tests for --ch-set and onNode() 2021-12-30 12:20:24 -08:00
Mike Kinney
14941c742a add more tests; do not need the old --reply test 2021-12-30 11:28:03 -08:00
mkinney
217add3b00 Update README.md
add code coverage badge
2021-12-30 09:32:18 -08:00
mkinney
4bac85b6a9 Update ci.yml 2021-12-30 09:21:17 -08:00
mkinney
36bed11959 Update publish_to_pypi.yml 2021-12-30 09:12:53 -08:00
mkinney
6f9bcfaaff Merge pull request #196 from mkinney/bump_version
bump version for testing pub to pypi
2021-12-30 09:06:54 -08:00
Mike Kinney
f17b66c872 bump version for testing pub to pypi 2021-12-30 09:05:26 -08:00
Sacha Weatherstone
040cb9bf34 Update and rename publish_to_pypi.py to publish_to_pypi.yml 2021-12-31 04:00:03 +11:00
mkinney
3269b3018f Merge pull request #195 from mkinney/publish_to_pypi
add workflow to publish to pypi
2021-12-30 08:49:26 -08:00
Mike Kinney
aab10b0912 add workflow to publish to pypi 2021-12-30 08:46:34 -08:00
mkinney
e2e9b7d55e Merge pull request #194 from mkinney/remove_raw_from_nodes_display
remove the raw key from the nodes dict
2021-12-30 08:28:36 -08:00
Mike Kinney
cecc5c3b25 remove the raw key from the nodes dict 2021-12-30 08:26:13 -08:00
mkinney
54bb846d00 Merge pull request #193 from mkinney/temp_disable_reply_unittest
need to comment out unittest with change to --reply
2021-12-30 07:51:15 -08:00
Mike Kinney
1a5f525632 need to comment out unittest with change to --reply 2021-12-30 07:49:34 -08:00
mkinney
8ba3d26d63 Merge pull request #191 from Beiri22/patch-1
Update __main__.py
2021-12-30 07:46:40 -08:00
Beiri22
b341b6cfdb Update __main__.py
Main loop also in reply mode.
2021-12-30 10:31:27 +01:00
mkinney
38e7972191 Merge pull request #189 from mkinney/master
bump version; remove docs dir; no need to regen docs on release
2021-12-29 22:02:01 -08:00
mkinney
5be70328fe Merge branch 'meshtastic:master' into master 2021-12-29 21:58:15 -08:00
Mike Kinney
dfe798dbdf no longer gen docs 2021-12-29 21:57:16 -08:00
Mike Kinney
d98b23dba0 remove docs dir 2021-12-29 21:56:03 -08:00
Mike Kinney
4fbe5c7863 bump version 2021-12-29 21:55:41 -08:00
Sacha Weatherstone
69bb8bcca2 Fx protobuf path 2021-12-30 16:52:25 +11:00
Sacha Weatherstone
bb2ea17371 Fix action name 2021-12-30 16:49:55 +11:00
Sacha Weatherstone
b51af8a070 Create update_protobufs 2021-12-30 16:48:20 +11:00
mkinney
aede26694c Merge pull request #188 from mkinney/work_on_serial_issue
revamp the serial connection to avoid Tbeam reboots
2021-12-29 21:41:59 -08:00
Mike Kinney
8e1010e9f2 ignore two checks for Windows smoke1 testing 2021-12-29 21:21:24 -08:00
Mike Kinney
ce2d9f5728 yet another attempt 2021-12-29 21:13:20 -08:00
Mike Kinney
9879e9f2df try yet another way 2021-12-29 21:00:22 -08:00
Mike Kinney
e79faf93d0 try a different way 2021-12-29 20:57:57 -08:00
Mike Kinney
181c04716a accidentally dropped an arg 2021-12-29 20:55:31 -08:00
Mike Kinney
c7d981ec35 fix typo 2021-12-29 20:51:46 -08:00
Mike Kinney
75fe7622a4 deal with windows on the serial issue 2021-12-29 20:49:19 -08:00
Mike Kinney
5dc800f9a3 deal with windows on smoke1 test 2021-12-29 20:39:34 -08:00
Mike Kinney
c7d3f9f787 close seriallog if we have one 2021-12-29 20:35:50 -08:00
Mike Kinney
c70d36d2cd revamp the serial connection to avoid Tbeam reboots 2021-12-29 19:24:26 -08:00
Jm Casler
f239c23d9a Merge branch 'master' of https://github.com/meshtastic/Meshtastic-python 2021-12-29 14:18:35 -08:00
Jm Casler
ac5d729cdf Bumped to 1.2.47. 2021-12-29 14:18:34 -08:00
mkinney
047f43534f Merge pull request #187 from mkinney/bump_version
bump version
2021-12-29 13:29:28 -08:00
Mike Kinney
c26e030f1f bump version 2021-12-29 13:28:08 -08:00
mkinney
1a61a5ccdc Update README.md 2021-12-29 11:01:13 -08:00
mkinney
eec3f722dc Merge pull request #186 from mkinney/docs
migrate docs to main project docs
2021-12-29 10:55:12 -08:00
Mike Kinney
adb797d453 migrate docs to main project docs 2021-12-29 10:53:41 -08:00
Jm Casler
7d75fd61d1 updating proto submodule to latest 2021-12-29 09:22:50 -08:00
Jm Casler
3abf82fc0a updating proto submodule to latest 2021-12-28 23:33:14 -08:00
Jm Casler
f56c7a0ef1 updating proto submodule to latest 2021-12-28 23:29:32 -08:00
Sacha Weatherstone
e1941bc6f5 Remove old docs & add vercel badge to readme 2021-12-29 18:15:38 +11:00
Sacha Weatherstone
7bd0565e21 Fix pypubsub in requirements.txt 2021-12-29 17:48:36 +11:00
Sacha Weatherstone
3f1165adc3 Add pubsub to requirements.txt 2021-12-29 17:42:57 +11:00
Sacha Weatherstone
e611a89392 Add pdoc3 to requirements.txt 2021-12-29 17:38:14 +11:00
mkinney
209a0669de Merge pull request #183 from mkinney/more_doc
regen doc with overriding the pdoc _is_public()
2021-12-28 22:12:04 -08:00
Mike Kinney
b6a9dec824 regen doc with overriding the pdoc _is_public() 2021-12-28 22:10:11 -08:00
mkinney
40afc56b2e Merge pull request #182 from mkinney/update_doc
fix some comments for doc
2021-12-28 21:15:02 -08:00
Mike Kinney
ecf68d5544 fix some comments for doc 2021-12-28 21:08:28 -08:00
mkinney
fc88d2bff3 Merge pull request #181 from linagee/master
Ham, not HAM
2021-12-28 12:41:53 -08:00
linagee
06d37914c3 Merge pull request #1 from linagee/Ham-not-HAM
Ham, not HAM
2021-12-27 21:10:06 -07:00
linagee
4575c58b97 Ham, not HAM
Discovered in 1ffa55d39a
2021-12-27 21:07:17 -07:00
mkinney
f8dfa3f0fd Merge pull request #180 from mkinney/oops_need_this_for_smoke1
meant to add this change to the last PR
2021-12-25 23:28:01 -08:00
Mike Kinney
dda4d4b653 meant to add this change to the last PR 2021-12-25 23:24:28 -08:00
mkinney
4a864d2b0e Merge pull request #179 from mkinney/more_boring_unit_testing
add more unit tests for onReceive in main
2021-12-25 22:26:18 -08:00
Mike Kinney
580c081303 captured packets and simulate what server would send 2021-12-25 16:19:13 -08:00
Mike Kinney
988540c77d move the slow unit tests into own group 2021-12-25 13:09:23 -08:00
Mike Kinney
a243fab9af figured out how to unit test __reader() 2021-12-25 11:39:04 -08:00
Mike Kinney
9fea479af4 do not add the test.py to the code coverage 2021-12-24 15:08:56 -08:00
Mike Kinney
e1f0c7f154 add tests for setPref() 2021-12-24 14:56:15 -08:00
Mike Kinney
7ef6465b5f add some tests for getPref() 2021-12-24 14:42:39 -08:00
Mike Kinney
87b95c5893 add more unit tests for onReceive in main 2021-12-24 13:48:10 -08:00
mkinney
3d00d05a89 Merge pull request #178 from mkinney/add_gpio_tests
Add gpio tests
2021-12-24 13:10:43 -08:00
Mike Kinney
c9ff1d9ad0 remove extraneous print 2021-12-24 13:02:49 -08:00
Mike Kinney
901be0ae04 wip; testing gpio read not working for me on real device; worked on gpio watch 2021-12-24 10:17:45 -08:00
Mike Kinney
fee052892b got gpio read to work and one unit test 2021-12-23 14:35:48 -08:00
mkinney
942600f399 Merge pull request #177 from mkinney/fix_channel_change
needed to do some actual testing to see error in code
2021-12-23 09:34:06 -08:00
Mike Kinney
a56a92b166 needed to do some actual testing to see error in code 2021-12-23 09:30:23 -08:00
mkinney
01ac345cf9 Merge pull request #176 from mkinney/yet_more_testing
add more info/checking on --sendtext and --ch-index; wrote helper met…
2021-12-23 09:20:37 -08:00
Mike Kinney
cbd41efb19 add unit test for catchAndIgnore() 2021-12-23 00:40:21 -08:00
Mike Kinney
276b2762c8 add more info/checking on --sendtext and --ch-index; wrote helper method and tests 2021-12-23 00:03:32 -08:00
mkinney
d21eaf9392 Merge pull request #175 from mkinney/continue_working_on_unit_tests
add unit tests for toRadio, sendData() and sendPosition(); found and …
2021-12-22 16:29:45 -08:00
Mike Kinney
0f0a978692 minor refactor now that there is a fixture 2021-12-22 16:20:09 -08:00
Mike Kinney
4428ccfe59 add unit tests for getMyUser(), getLongName(), getShortName(), and sendPacket() 2021-12-22 16:15:16 -08:00
Mike Kinney
dbb5af1f35 added unit test for test_onResponseRequestChannel() 2021-12-22 12:11:27 -08:00
Mike Kinney
586a3eb463 wip extracting onResponse() closures to class methods so they can be tested 2021-12-22 11:11:17 -08:00
Mike Kinney
2eeffdcd49 add unit tests for _requestChannel() 2021-12-22 09:21:47 -08:00
Mike Kinney
002a7caf38 add more unit tests to deleteChannel() and writeConfig() 2021-12-22 09:10:39 -08:00
Mike Kinney
8bf1dd6dcb add unit tests for showChannels(), deleteChannel(), getChannelByName(), getDisabledChannel(), getAdminChannelIndex(), turnOffEncryptionOnPrimaryChannel(), and writeConfig() 2021-12-21 22:13:02 -08:00
Mike Kinney
8e578c3b24 add unit test for getMyNodeInfo() 2021-12-21 16:27:43 -08:00
Mike Kinney
2919930473 unit tests for sendPacket() 2021-12-21 15:21:30 -08:00
Mike Kinney
302f52469a add unit tests for toRadio, sendData() and sendPosition(); found and fixed Exception without raise 2021-12-21 14:47:05 -08:00
mkinney
71c8ca5381 Merge pull request #174 from mkinney/import_issues
add examples; add Makefile
2021-12-21 11:33:53 -08:00
Mike Kinney
0701d400ff add examples; add Makefile 2021-12-21 11:21:37 -08:00
mkinney
1acc193248 Merge pull request #171 from mkinney/more_testing
add unit tests for RemoteHardwareClient()
2021-12-20 23:27:45 -08:00
Mike Kinney
d82f197c06 remove the message from the sendping option 2021-12-20 23:23:27 -08:00
Mike Kinney
a35f3a4e7b revert changes to onResponse() methods 2021-12-20 23:19:38 -08:00
Mike Kinney
036ce8258f ignore long binary line 2021-12-20 22:25:19 -08:00
Mike Kinney
1c8a5d8c5b work around for issue 172 2021-12-20 22:11:52 -08:00
Mike Kinney
266ed868d2 Merge remote-tracking branch 'upstream/master' into more_testing 2021-12-20 21:22:01 -08:00
Mike Kinney
29d3723094 not sure what happened to example_config.yaml file 2021-12-20 21:21:20 -08:00
Mike Kinney
4597ea1898 add channel index to send text 2021-12-20 14:00:56 -08:00
Mike Kinney
23d946baaa wip on validating --set-owner on remote node 2021-12-19 17:34:39 -08:00
Jm Casler
900ce6ab5e updating proto submodule to latest 2021-12-19 13:54:53 -05:00
Jm Casler
19e5ecb86d updating proto submodule to latest 2021-12-18 15:51:46 -05:00
Mike Kinney
c1cab5e62f add unit tests for RemoteHardwareClient() 2021-12-17 14:37:30 -08:00
mkinney
35f10f1490 Merge pull request #170 from mkinney/add_configure_dump
Add configure dump
2021-12-17 13:01:52 -08:00
Mike Kinney
c63dc09e5d rename to --export-config 2021-12-17 12:47:27 -08:00
Mike Kinney
b47393d62d refactor and write unit test 2021-12-17 10:55:51 -08:00
Mike Kinney
8fd00efe8b working initial 2021-12-17 10:19:48 -08:00
mkinney
0410a427b6 Merge pull request #169 from mkinney/fix_smoke_tests
now that the firmware is updated, can fix smoke test
2021-12-17 09:10:17 -08:00
Mike Kinney
e869e3c72e now that the firmware is updated, can fix smoke test 2021-12-17 09:08:09 -08:00
mkinney
0987db3d1d Merge pull request #167 from mkinney/work_on_unit_tests
Work on unit tests
2021-12-17 08:03:10 -08:00
Mike Kinney
95f7f560ba add unit tests for reboot(), exitSimulator(), and setURL() 2021-12-16 23:23:43 -08:00
Mike Kinney
fd6deedd8d add unit tests for setOwner() 2021-12-16 22:47:10 -08:00
Mike Kinney
fc637ee6ae add to test for showNodes() 2021-12-16 22:17:08 -08:00
Mike Kinney
e43d9f5318 add unit tests for _handleFromRadio() and sendPosition() 2021-12-16 19:12:55 -08:00
Mike Kinney
2a0c9f0669 add mesh_interface unit tests for handlePacketFromRadio and getNode 2021-12-16 17:02:40 -08:00
Mike Kinney
f7753b2ce8 Merge branch 'master' into work_on_unit_tests 2021-12-16 12:33:43 -08:00
mkinney
ca032e485c Merge pull request #166 from mkinney/validate_cli
see if we can validate if we can run the cli from just the build
2021-12-16 12:28:14 -08:00
Mike Kinney
df194389e1 add lib back in now that validation worked 2021-12-16 12:26:24 -08:00
Mike Kinney
1b60676365 temp remove a lib to see if the validation fails 2021-12-16 12:24:40 -08:00
Mike Kinney
8aa165ec93 see if we can validate if we can run the cli from just the build 2021-12-16 12:21:49 -08:00
Jm Casler
28a72218fc bump to 1.2.46 2021-12-16 15:00:46 -05:00
mkinney
03374eb62b Merge pull request #165 from mkinney/fix_pyyaml_import
adding pyyaml to setup
2021-12-16 11:57:17 -08:00
Mike Kinney
95cd5f92c7 adding pyyaml to setup 2021-12-16 11:54:50 -08:00
Mike Kinney
6b0521003c wip on adding unit tests to mesh_interface 2021-12-16 11:51:25 -08:00
245 changed files with 36979 additions and 45164 deletions

View File

@@ -1,2 +1,6 @@
[run]
omit = meshtastic/*_pb2.py,meshtastic/tests/*.py
omit = meshtastic/protobuf/*_pb2.py,meshtastic/tests/*.py,meshtastic/test.py
[report]
exclude_lines =
if __name__ == .__main__.:

5
.gitattributes vendored Normal file
View File

@@ -0,0 +1,5 @@
* text=auto eol=lf
*.{cmd,[cC][mM][dD]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf
*.{sh,[sS][hH]} text eol=lf
meshtastic/protobuf/* linguist-generated=true

22
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,22 @@
# Contributing to Meshtastic Python
## Development resources
- [API Documentation](https://python.meshtastic.org/)
- [Meshtastic Python Development](https://meshtastic.org/docs/development/python/)
- [Building Meshtastic Python](https://meshtastic.org/docs/development/python/building/)
- [Using the Meshtastic Python Library](https://meshtastic.org/docs/development/python/library/)
## How to check your code (pytest/pylint) before a PR
- [Pre-requisites](https://meshtastic.org/docs/development/python/building/#pre-requisites)
- also execute `poetry install --all-extras --with dev,powermon` for all optional dependencies
- check your code with github ci actions locally
- You need to have act installed. You can get it at https://nektosact.com/
- on linux: `act -P ubuntu-latest=-self-hosted --matrix "python-version:3.12"`
- on windows:
- linux checks (linux docker): `act --matrix "python-version:3.12"`
- windows checks (windows host): `act -P ubuntu-latest=-self-hosted --matrix "python-version:3.12"`
- or run all locally:
- run `poetry run pylint meshtastic examples/ --ignore-patterns ".*_pb2.pyi?$"`
- run `poetry run mypy meshtastic/`
- run `poetry run pytest`
- more commands see [CI workflow](https://github.com/meshtastic/python/blob/master/.github/workflows/ci.yml)

BIN
.github/meshtastic_logo.png vendored Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@@ -1,4 +1,4 @@
name: Linting and Tests
name: CI
on:
push:
branches:
@@ -10,25 +10,63 @@ on:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install Python 3
uses: actions/setup-python@v1
with:
python-version: 3.9
uses: actions/setup-python@v5
- name: Uninstall meshtastic
run: |
pip3 uninstall meshtastic
pip3 uninstall -y meshtastic
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip3 install -r requirements.txt
pip3 install poetry
- name: Install meshtastic from local
run: |
pip3 install .
which meshtastic
meshtastic --version
poetry install --all-extras --with dev,powermon
poetry run meshtastic --version
- name: Run pylint
run: pylint meshtastic
run: poetry run pylint meshtastic examples/ --ignore-patterns ".*_pb2.pyi?$"
- name: Check types with mypy
run: poetry run mypy meshtastic/
- name: Run tests with pytest
run: pytest --cov=meshtastic
run: poetry run pytest --cov=meshtastic
- name: Generate coverage report
run: |
poetry run pytest --cov=meshtastic --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
env_vars: OS, PYTHON
files: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: true
verbose: true
validate:
runs-on: ubuntu-latest
strategy:
matrix:
python-version:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
steps:
- uses: actions/checkout@v4
- name: Install Python 3
uses: actions/setup-python@v5
- name: Install meshtastic from local
run: |
python -m pip install --upgrade pip
pip3 install poetry
poetry install
poetry run meshtastic --version

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

183
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,183 @@
name: Make Release
on: workflow_dispatch
jobs:
release_create:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
upload_url: ${{ steps.create_release.outputs.upload_url }}
new_sha: ${{ steps.commit_updated.outputs.sha }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip3 install poetry
- name: Bump version
run: >-
poetry version patch
- name: Get version
id: get_version
run: >-
poetry version --short | sed 's/^/::set-output name=version::/'
- name: Commit updated version.
id: commit_updated
run: |
git config --global user.name 'github-actions'
git config --global user.email 'bot@noreply.github.com'
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
git add pyproject.toml
git commit -m "bump version to ${{ steps.get_version.outputs.version }}" && git push || echo "No changes to commit"
git log -n 1 --pretty=format:"%H" | tail -n 1 | awk '{print "::set-output name=sha::"$0}'
- name: Create GitHub release
uses: actions/create-release@v1
id: create_release
with:
draft: true
prerelease: true
release_name: Meshtastic Python ${{ steps.get_version.outputs.version }}
tag_name: ${{ steps.get_version.outputs.version }}
commitish: ${{ steps.commit_updated.outputs.sha }}
body: |
Autogenerated by github action, developer should edit as required before publishing...
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build a binary wheel and a source tarball
run: >-
poetry build
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
# build-and-publish-mac:
# runs-on: macos-latest
# needs: release_create
# steps:
# - name: Checkout
# uses: actions/checkout@v4
# with:
# ref: ${{ needs.release_create.outputs.new_sha }}
# - name: Set up Python 3.9
# uses: actions/setup-python@v5
# with:
# python-version: "3.9"
# - name: Setup code signing
# env:
# MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
# MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
# MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
# run: |
# echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
# security create-keychain -p "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
# security default-keychain -s meshtastic.keychain
# security unlock-keychain -p "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
# security import certificate.p12 -k meshtastic.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
# security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
# - name: Build
# env:
# MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
# run: |
# pip install pyinstaller
# pip install -r requirements.txt
# pip install .
# pyinstaller -F -n meshtastic --collect-all meshtastic --codesign-identity "$MACOS_SIGNING_IDENTITY" meshtastic/__main__.py
# - name: Add mac to release
# uses: actions/upload-release-asset@v1
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# upload_url: ${{ needs.release_create.outputs.upload_url }}
# asset_path: dist/meshtastic
# asset_name: meshtastic_mac
# asset_content_type: application/zip
build-and-publish-ubuntu:
runs-on: ubuntu-latest
needs: release_create
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.release_create.outputs.new_sha }}
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Build
run: |
pip install poetry
bin/build-bin.sh
- name: Add ubuntu to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release_create.outputs.upload_url }}
asset_path: dist/meshtastic
asset_name: meshtastic_ubuntu
asset_content_type: application/zip
- name: Add readme.txt to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release_create.outputs.upload_url }}
asset_path: standalone_readme.txt
asset_name: readme.txt
asset_content_type: text/plain
# build-and-publish-windows:
# runs-on: windows-latest
# needs: release_create
# steps:
# - name: Checkout
# uses: actions/checkout@v4
# with:
# ref: ${{ needs.release_create.outputs.new_sha }}
# - name: Set up Python 3.9
# uses: actions/setup-python@v5
# with:
# python-version: "3.9"
# - name: Build
# run: |
# pip install poetry
# bin/build-bin.sh
# - name: Add windows to release
# uses: actions/upload-release-asset@v1
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# upload_url: ${{ needs.release_create.outputs.upload_url }}
# asset_path: dist/meshtastic.exe
# asset_name: meshtastic_windows
# asset_content_type: application/zip

41
.github/workflows/update_protobufs.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: "Update protobufs"
on: workflow_dispatch
jobs:
update-protobufs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: true
- name: Update Submodule
run: |
git pull --recurse-submodules
git submodule update --remote --recursive
- name: Download nanopb
run: |
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.8-linux-x86.tar.gz
tar xvzf nanopb-0.4.8-linux-x86.tar.gz
mv nanopb-0.4.8-linux-x86 nanopb-0.4.8
- name: Install poetry (needed by regen-protobufs.sh)
run: |
python -m pip install --upgrade pip
pip3 install poetry
- name: Re-generate protocol buffers
run: |
./bin/regen-protobufs.sh
- name: Commit update
run: |
git config --global user.name 'github-actions'
git config --global user.email 'bot@noreply.github.com'
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
git add protobufs
git add meshtastic/protobuf
git commit -m "Update protobuf submodule" && git push || echo "No changes to commit"

12
.gitignore vendored
View File

@@ -1,11 +1,21 @@
README
docs/
build
dist
*.egg-info
log_*
.eggs
nanopb-0.4.4
nanopb-*
.*swp
.coverage
*.py-E
venv/
*pyc
.DS_Store
__pycache__
examples/__pycache__
meshtastic.spec
.hypothesis/
coverage.xml
.ipynb_checkpoints
.cursor/

6
.gitmodules vendored
View File

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

View File

@@ -7,7 +7,7 @@
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=mqtt_pb2.py,channel_pb2.py,environmental_measurement_pb2.py,admin_pb2.py,radioconfig_pb2.py,deviceonly_pb2.py,apponly_pb2.py,remote_hardware_pb2.py,portnums_pb2.py,mesh_pb2.py,storeforward_pb2.py
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,nanopb_pb2.py
@@ -23,8 +23,7 @@ ignore-patterns=mqtt_pb2.py,channel_pb2.py,environmental_measurement_pb2.py,admi
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
#
disable=invalid-name,fixme,logging-fstring-interpolation,too-many-statements,too-many-branches,too-many-locals,no-member,f-string-without-interpolation,protected-access,no-self-use,pointless-string-statement,too-few-public-methods,consider-using-f-string,broad-except,no-else-return,unused-argument,global-statement,global-variable-not-assigned,too-many-boolean-expressions,no-else-raise,bare-except
disable=invalid-name,fixme,logging-fstring-interpolation,too-many-statements,too-many-branches,too-many-locals,no-member,f-string-without-interpolation,protected-access,pointless-string-statement,too-few-public-methods,broad-except,no-else-return,no-else-raise,bare-except,too-many-public-methods,nested-min-max
[BASIC]
@@ -41,7 +40,7 @@ bad-names=foo,bar,baz,toto,tutu,tata
max-line-length=150
# Maximum number of lines in a module
max-module-lines=1200
max-module-lines=1600

64
.reuse/dep5 Normal file
View File

@@ -0,0 +1,64 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Meshtastic Python
Upstream-Contact: Various Authors
Source: https://github.com/meshtastic/python
Files: *
Copyright:
2020-2020 Nils Werner <nils@hey.com>
2020-2020 Paul Vivier <github@vivier.net>
2020-2020 Tim Gunter <tgunter+github@gmail.com>
2020-2021 Charles Crossan <crossan007@gmail.com>
2020-2021 IZ1IVA
2020-2022 Jm Casler <jm@casler.org>
2020-2024 geeksville <kevinh@geeksville.com>
2021-2021 Andrew Cabey <me@acabey.xyz>
2021-2021 dylan <eris.has.a.dad+github@gmail.com>
2021-2021 Fabian Affolter <mail@fabian-affolter.ch>
2021-2021 Foster Irwin <foster@jfirwin.com>
2021-2021 Manuel Giolo <iz1kga@gmail.com>
2021-2021 meehow <michal@ert.pl>
2021-2021 srichs
2021-2021 ChuckNorrison
2021-2021 Aivaras-s
2021-2021 a-f-G-U-C
2021-2021 <Beiri22ny@googlemail.com>
2021-2021 jdstroy
2021-2021 linagee
2021-2021 Simonas <simonas@5grupe.lt>
2021-2022 <mike.kinney@gmail.com>
2021-2023 Sacha Weatherstone <sachaw100@hotmail.com>
2021-2024 Ben Meadors <benmmeadors@gmail.com>
2022-2022 Balázs Kelemen <10376327+prampec
2022-2022 <akadd8@gmail.com>
2022-2022 <a.merino.jimenez@gmail.com>
2022-2022 <ghostop14@gmail.com>
2022-2022 <git@schiraldi.org>
2022-2022 <pavel.b@techspark.engineering>
2022-2022 Rohan King <king.rohan.ja@gmail.com>
2022-2022 Tom Douile
2022-2023 Thomas Göttgens <tgoettgens@gmail.com>
2022-2024 thijs@havinga.eu>
2023-2023 Eli Schleifer <eli@trunk.io>
2023-2023 Manuel <manuel.verch@gmx.de>
2023-2023 Marek Küthe <m.k@mk16.de>
2023-2023 <benlipsey@gmail.com>
2023-2023 <dwelch@structuralcomponents.net>
2023-2023 <henrichhartzer@tuta.io>
2023-2023 luzpaz
2023-2023 <sb@liztv.net>
2023-2023 Toby Murray <toby.murray@protonmail.com>
2023-2024 Brad Midgley <bmidgley@gmail.com>
2024-2024 Ian McEwen <ianmcorvidae@ianmcorvidae.net>
2024-2024 John Hollowell <jhollowe@johnhollowell.com>
2024-2024 Jonathan Bennett <jbennett@incomsystems.biz>
2024-2024 <danwelch3@gmail.com>
2024-2024 <god@yahoo.com>
2024-2024 <herbert.todd@gmail.com>
2024-2024 <jorropo.pgm@gmail.com>
2024-2024 rc14193 <emdort@gmail.com>
2024-2024 Steve Holden <steve@holdenweb.com>
2024-2024 Thomas Herrmann <mail@thoherr.de>
2024-2024 Timothy Harder <harder.timothy.j@gmail.com>
2024-2024 Wolfgang Nagele <mail@wnagele.com>
License: GPL-3.0-only

8
.trunk/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
*out
*logs
*actions
*notifications
*tools
plugins
user_trunk.yaml
user.yaml

View File

@@ -0,0 +1,2 @@
[settings]
profile=black

View File

@@ -0,0 +1,10 @@
# Autoformatter friendly markdownlint config (all formatting rules disabled)
default: true
blank_lines: false
bullet: false
html: false
indentation: false
line_length: false
spaces: false
url: false
whitespace: false

View File

@@ -0,0 +1,7 @@
enable=all
source-path=SCRIPTDIR
disable=SC2154
# If you're having issues with shellcheck following source, disable the errors via:
# disable=SC1090
# disable=SC1091

View File

@@ -0,0 +1,10 @@
rules:
quoted-strings:
required: only-when-needed
extra-allowed: ["{|}"]
empty-values:
forbid-in-block-mappings: true
forbid-in-flow-mappings: true
key-duplicates: {}
octal-values:
forbid-implicit-octal: true

5
.trunk/configs/ruff.toml Normal file
View File

@@ -0,0 +1,5 @@
# Generic, formatter-friendly config.
select = ["B", "D3", "D4", "E", "F"]
# Never enforce `E501` (line length violations). This should be handled by formatters.
ignore = ["E501"]

46
.trunk/trunk.yaml Normal file
View File

@@ -0,0 +1,46 @@
version: 0.1
cli:
version: 1.15.0
plugins:
sources:
- id: trunk
ref: v1.2.2
uri: https://github.com/trunk-io/plugins
lint:
disabled:
- bandit
ignore:
- linters: [ALL]
paths:
# Ignore generated files
- meshtastic/*_pb2.py
enabled:
- actionlint@1.6.25
- black@23.7.0
- checkov@2.4.9
- git-diff-check
- gitleaks@8.18.0
- isort@5.12.0
- markdownlint@0.36.0
- osv-scanner@1.3.6
- prettier@3.0.3
- pylint@2.17.5
- ruff@0.0.287
- shellcheck@0.9.0
- shfmt@3.6.0
- taplo@0.8.1
- trivy@0.44.1
- trufflehog@3.54.3
- yamllint@1.32.0
runtimes:
enabled:
- go@1.21.0
- node@18.12.1
- python@3.10.8
actions:
disabled:
- trunk-announce
- trunk-check-pre-push
- trunk-fmt-pre-commit
enabled:
- trunk-upgrade-available

202
.vscode/launch.json vendored
View File

@@ -4,17 +4,26 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "meshtastic BLE",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": false,
"args": ["--ble", "--info", "--seriallog", "stdout"]
},
{
"name": "meshtastic BLE scan",
"type": "python",
"request": "launch",
"module": "meshtastic",
"justMyCode": false,
"args": ["--debug", "--ble", "--device", "24:62:AB:DD:DF:3A"]
"args": ["--debug", "--ble-scan"]
},
{
"name": "meshtastic admin",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
@@ -22,15 +31,23 @@
},
{
"name": "meshtastic tunnel",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--tunnel", "--debug"]
},
{
"name": "meshtastic analysis",
"type": "debugpy",
"request": "launch",
"module": "meshtastic.analysis",
"justMyCode": false,
"args": []
},
{
"name": "meshtastic set chan",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
@@ -38,23 +55,128 @@
},
{
"name": "meshtastic debug",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug"]
},
{
"name": "meshtastic listen",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--listen", "--debug"]
},
{
"name": "meshtastic debug getPref",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--get", "power.is_power_saving"]
},
{
"name": "meshtastic debug getPref telemetry",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--get", "telemetry.environment_update_interval"]
},
{
"name": "meshtastic debug info",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--info"]
},
{
"name": "meshtastic debug BLE",
"type": "python",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug" ]
"args": ["--debug", "--ble", "--info"]
},
{
"name": "meshtastic debug set region",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--set", "lora.region", "TW"]
},
{
"name": "meshtastic debug set bluetooth fixed pin",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--set", "bluetooth.fixed_pin", "555555"]
},
{
"name": "meshtastic debug get bluetooth fixed pin",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--get", "bluetooth.fixed_pin"]
},
{
"name": "meshtastic debug setPref",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--set", "power.powermon_enables", "65527"]
},
{
"name": "meshtastic debug setPref telemetry.environment_measurement_enabled",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--set", "telemetry.environment_measurement_enabled", "1"]
},
{
"name": "meshtastic debug setPref telemetry.environment_screen_enabled",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--set", "telemetry.environment_screen_enabled", "1"]
},
{
"name": "meshtastic debug setPref telemetry",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--set", "telemetry.environment_measurement_enabled", "1"]
},
{
"name": "meshtastic setpref",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--setchan", "psk", ""]
},
{
"name": "meshtastic --ch-set",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--ch-set", "channel_num", "0", "--ch-index", "0"]
},
{
"name": "meshtastic seturl",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
@@ -63,15 +185,39 @@
},
{
"name": "meshtastic shell",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--seriallog", "stdout"]
"justMyCode": false,
"args": ["--noproto", "--seriallog", "stdout"]
},
{
"name": "meshtastic powermon sim",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": false,
"args": ["--slog-out", "default", "--power-sim", "--power-voltage", "3.3", "--port", "/dev/ttyUSB0", "--noproto", "--seriallog", "stdout"]
},
{
"name": "meshtastic powermon ppk2",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": false,
"args": ["--slog-out", "default", "--power-ppk2-meter", "--power-wait", "--power-voltage", "3.3", "--noproto", "--seriallog", "stdout"]
},
{
"name": "meshtastic stress ppk2",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": false,
"args": ["--slog", "--power-ppk2-supply", "--power-stress", "--power-voltage", "3.3", "--ble"]
},
{
"name": "meshtastic test",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
@@ -79,7 +225,7 @@
},
{
"name": "meshtastic settime",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
@@ -87,19 +233,43 @@
},
{
"name": "meshtastic sendtext",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--sendtext", "pytest"]
}
},
{
"name": "meshtastic showNodes",
"type": "python",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--debug", "--nodes"]
}
},
{
"name": "meshtastic nodes table",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--nodes"]
},
{
"name": "meshtastic nodes table with show-fields",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--nodes", "--show-fields", "AKA,Pubkey,Role,Role,Role,Latitude,Latitude,deviceMetrics.voltage"]
},
{
"name": "meshtastic --export-config",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--export-config", "config.json"]
},
]
}

16
.vscode/settings.json vendored
View File

@@ -1,8 +1,22 @@
{
"cSpell.words": [
"bitmask",
"boardid",
"DEEPSLEEP",
"Meshtastic",
"milliwatt",
"portnums",
"powermon",
"POWERSTRESS",
"pyarrow",
"TORADIO",
"Vids"
],
"python.pythonPath": "/usr/bin/python3"
"python.pythonPath": "/usr/bin/python3",
"flake8.enabled": false,
"python.testing.pytestArgs": [
"meshtastic/tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true // we are using trunk for formatting/linting rules, don't yell at us about line length
}

232
LICENSE.md Normal file
View File

@@ -0,0 +1,232 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for software and other kinds of works.
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS
0. Definitions.
“This License” refers to version 3 of the GNU General Public License.
“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
A “covered work” means either the unmodified Program or a work based on the Program.
To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
1. Source Code.
The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
7. Additional Terms.
“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
11. Patents.
A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <https://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

46
Makefile Normal file
View File

@@ -0,0 +1,46 @@
# only run the fast unit tests
test:
pytest -m unit
# only run the smoke tests against the virtual device
virt:
pytest -m smokevirt
# run the smoke1 test (after doing a factory reset and unplugging/replugging in device)
smoke1:
pytest -m smoke1 -s -vv
# local install
install:
pip install .
# generate the docs (for local use)
docs:
pdoc3 --html -f --output-dir docs meshtastic
# lint the codebase
lint:
pylint meshtastic examples
# show the slowest unit tests
slow:
pytest -m unit --durations=5
protobufs: FORCE
git submodule update --init --recursive
git pull --rebase
git submodule update --remote --merge
./bin/regen-protobufs.sh
# run the coverage report and open results in a browser
cov:
pytest --cov-report html --cov=meshtastic
# on mac, this will open the coverage report in a browser
open htmlcov/index.html
# run cli examples
examples: FORCE
pytest -mexamples
# Makefile hack to get the examples to always run
FORCE: ;

279
README.md
View File

@@ -1,249 +1,60 @@
# Meshtastic-python
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/meshtastic/Meshtastic-python)
![Unit Tests](https://github.com/meshtastic/Meshtastic-python/actions/workflows/ci.yml/badge.svg)
<div align="center" markdown="1">
<img src=".github/meshtastic_logo.png" alt="Meshtastic Logo" width="80"/>
A python client for using [Meshtastic](https://www.meshtastic.org) devices. This small library (and example application) provides an easy API for sending and receiving messages over mesh radios. 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.
<h1 align="center"> Meshtastic Python
</h1>
<p style="font-size:15px;" align="center">A Python library and client for use with Meshtastic devices. </p>
Full documentation including examples [here](https://meshtastic.github.io/Meshtastic-python/meshtastic/index.html).
[![codecov](https://codecov.io/gh/meshtastic/python/branch/master/graph/badge.svg?token=TIWPJL73KV)](https://codecov.io/gh/meshtastic/python)
![PyPI - Downloads](https://img.shields.io/pypi/dm/meshtastic)
[![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/python/ci.yml?branch=master&label=actions&logo=github&color=yellow)](https://github.com/meshtastic/python/actions/workflows/ci.yml)
[![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/)
![GPL-3.0](https://img.shields.io/badge/License-GPL%20v3-blue.svg)
Installation is easily done through the Python package installer pip (note, you must use pip version 20 or later):
</div>
- check that your computer has the required serial drivers installed, if not download them from [here](https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers).
- check that your computer has Python 3 installed.
- check that your computer has "pip3" installed, if not follow [this guide](https://www.makeuseof.com/tag/install-pip-for-python/).
- check that pytap2 is installed by pip3. If not, install it:
<div align="center">
<a href="https://meshtastic.org/docs/software/python/cli/installation">Getting Started Guide</a>
-
<a href="https://python.meshtastic.org">API Documentation</a>
</div>
```
sudo pip3 install --upgrade pytap2
```
## Overview
- install meshtastic:
This small library (and example application) provides an easy API for sending and receiving messages over mesh radios.
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.
```
sudo pip3 install --upgrade meshtastic
```
## Call for Contributors
An example using Python 3 code to send a message to the mesh:
This library and CLI has gone without a consistent maintainer for a while, and there's many improvements that could be made. We're all volunteers here and help is extremely appreciated, whether in implementing your own needs or helping maintain the library and CLI in general.
```
import meshtastic
interface = meshtastic.SerialInterface() # By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0
interface.sendText("hello mesh") # or sendData to send binary data, see documentations for other options.
interface.close()
```
If you're interested in contributing but don't have specific things you'd like to work on, look at the roadmap below!
For the rough notes/implementation plan see [TODO](https://github.com/meshtastic/Meshtastic-python/blob/master/TODO.md).
## Roadmap
## Command line tool
This should always be considered a list in progress and flux -- inclusion doesn't guarantee implementation, and exclusion doesn't mean something's not wanted. GitHub issues are a great place to discuss ideas.
This pip package will also install a "meshtastic" command line executable, which displays packets sent over the network as JSON and lets you see serial debugging information from the meshtastic devices. The source code for this tool is also a good [example](https://github.com/meshtastic/Meshtastic-python/blob/master/meshtastic/__main__.py) of a 'complete' application that uses the meshtastic python API.
* Types
* type annotations throughout the codebase, and upgrading mypy running in CI to `--strict`
* async-friendliness
* CLI completeness & consistency
* the CLI should support all features of the firmware
* there should be a consistent output format available for shell scripting
* CLI input validation & documentation
* what arguments and options are compatible & incompatible with one another?
* can the options be restructured in a way that is more self-documenting?
* pubsub events should be documented clearly
* helpers for third-party code
* it should be easy to write a script that supports similar options to the CLI so many tools support the same ways of connecting to nodes
* data storage & processing
* there should be a standardized way of recording packets for later use, debugging, etc.
* a persistence layer could also keep track of nodes beyond nodedb, as the apps do
* a sqlite database schema and tools for writing to it may be a good starting point
* enable maps, charts, visualizations
NOTE: This command is not run inside of python; you run it from your operating system shell prompt directly. If when you type "meshtastic" it doesn't find the command and you are using Windows: Check that the python "scripts" directory [is in your path](https://datatofish.com/add-python-to-windows-path/).
## Stats
To display a (partial) list of the available commands:
```
meshtastic -h
```
### Changing device settings
You can also use this tool to set any of the device parameters which are stored in persistent storage. For instance, here's how to set the device
to keep the bluetooth link alive for eight hours (any usage of the bluetooth protcol from your phone will reset this timer)
```
meshtastic --set wait_bluetooth_secs 28800
Connected to radio...
Setting preference wait_bluetooth_secs to 28800
Writing modified preferences to device...
```
Or to set a node at a fixed position and never power up the GPS.
```
meshtastic --setlat 25.2 --setlon -16.8 --setalt 120
```
Or to configure an ESP32 based board to join a wifi network as a station (wifi support in the device code is coming soon):
```
meshtastic --set wifi_ap_mode false --set wifi_ssid mywifissid --set wifi_password mywifipsw
```
Or to configure an ESP32 to run as a Wifi access point:
```
meshtastic --set wifi_ap_mode true --set wifi_ssid mywifissid --set wifi_password mywifipsw
```
Once an a node is connected to a Wi-Fi network, you can use the `--host` option to access it instead of using the USB serial bridge:
```
meshtastic --host Meshtastic-0123.lan --info --nodes
```
For a full list of preferences which can be set (and their documentation) see [here](https://meshtastic.org/docs/developers/protobufs/api#radioconfiguserpreferences).
### Changing channel settings
The channel settings can be changed similiarly. Either by using a standard (sharable) meshtastic URL or you can set partiular channel parameters (for advanced users).
The URL is constructed automatically based off of the current channel settings. So if you want to customize a channel you could do something like:
```
meshtastic --ch-set name mychan --ch-set channel_num 4 --info
```
This will change some channel params and then show device info (which will include the current channel URL)
You can even set the channel preshared key to a particular AES128 or AES256 sequence.
```
meshtastic --ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --info
```
Use "--ch-set psk none" to turn off encryption.
Use "--ch-set psk random" will assign a new (high quality) random AES256 key to the primary channel (similar to what the Android app does when making new channels).
Use "--ch-set psk default" to restore the standard 'default' (minimally secure, because it is in the source code for anyone to read) AES128 key.
All "ch-set" commands will default to the primary channel at index 0, but can be applied to other channels with the "ch-index" parameter:
```
meshtastic --ch-index 1 --ch-set name mychan --ch-set channel_num 4 --info
```
## Ham radio support
Meshtastic is designed to be used without a radio operator license. If you do have a license you can set your operator ID and turn off encryption with:
```
meshtastic --port /dev/ttyUSB1 --set-ham KI1345
Connected to radio
Setting HAM ID to KI1345 and turning off encryption
Writing modified channels to device
```
## Changing multiple settings from a yaml file
You can put parameters into a yaml file to update multiple values. See the [example_config.yaml](example_config.yaml).
This is how you might call it:
```
meshtastic --configure example_config.yaml
```
## FAQ/common problems
This is a collection of common questions and answers from our friendly forum.
### [Permission denied: /dev/ttyUSB0](https://meshtastic.discourse.group/t/question-on-permission-denied-dev-ttyusb0/590/3?u=geeksville)
This indicates an OS permission problem for access by your user to the USB serial port. Typically this is fixed by the following.
```
sudo usermod -a -G dialout $USER
```
This adds the "dialout" group to your user. You'll need to obtain a new login session (for example, by logging out and logging back in) for the group change (and thus permission change) to take effect.
## Mac OS Big Sur
There is a problem with Big Sur and pyserial. The workaround is to install a newer version of pyserial:
```
pip3 install -U --pre pyserial
```
Afterwards you can use the Meshtastic python client again on MacOS.
## A note to developers of this lib
We use the visual-studio-code default python formatting conventions (autopep8). So if you use that IDE you should be able to use "Format Document" and not generate unrelated diffs. If you use some other editor, please don't change formatting on lines you haven't changed.
If you need to build a new release you'll need:
```
apt install pandoc
sudo pip3 install markdown pdoc3 webencodings pyparsing twine autopep8 pylint pytest pytest-cov
```
For development, you will probably want to run:
```
pip3 install -r requirements.txt
```
To lint, run:
```
pylint meshtastic
```
To test, first install this code locally, then run pytest:
```
pip3 install .
pytest
```
Possible options for testing:
* For more verbosity, add "-v" or even "-vv" like this:
```
pytest -vv
```
* To run just unit tests:
```
pytest
# or (more verbosely)
pytest -m unit
```
* To run just integration tests:
```
pytest -m int
```
* To run the smoke test with only one device connected serially (aka smoke1):
```
pytest -m smoke1
```
CAUTION: Running smoke1 will reset values on the device, including the region to 1 (US).
Be sure to hit the reset button on the device after the test is completed.
* To run the smoke test with only two device connected serially (aka smoke2):
```
pytest -m smoke2
```
* To run the wifi smoke test:
```
pytest -m smokewifi
```
* To run a specific test:
```
pytest -msmoke1 meshtastic/tests/test_smoke1.py::test_smoke1_info
# or to run a specific smoke2 test
pytest -m smoke2 meshtastic/tests/test_smoke2.py::test_smoke2_info
# or to run a specific smoke_wifi test
pytest -m smokewifi meshtastic/tests/test_smoke_wifi.py::test_smokewifi_info
```
* To add another classification of tests such as "unit" or "smoke1", see [pytest.ini](pytest.ini).
* To see the unit test code coverage:
```
pytest --cov=meshtastic
# or if want html coverage report
pytest --cov-report html --cov=meshtastic
```
![Alt](https://repobeats.axiom.co/api/embed/c71ee8fc4a79690402e5d2807a41eec5e96d9039.svg "Repobeats analytics image")

10
TODO.md
View File

@@ -5,7 +5,6 @@ Basic functionality is complete now.
## Eventual tasks
- Improve documentation on properties/fields
- change back to Bleak for BLE support - now that they fixed https://github.com/hbldh/bleak/issues/139#event-3499535304
- include more examples: textchat.py, replymessage.py all as one little demo
- possibly use tk to make a multiwindow test console: https://stackoverflow.com/questions/12351786/how-to-redirect-print-statements-to-tkinter-text-widget
@@ -17,11 +16,8 @@ Basic functionality is complete now.
## Bluetooth support
(Pre-alpha level feature - you probably don't want this one yet)
- This library supports connecting to Meshtastic devices over either USB (serial) or Bluetooth. Before connecting to the device you must [pair](https://docs.ubuntu.com/core/en/stacks/bluetooth/bluez/docs/reference/pairing/outbound.html) your PC with it.
- We use the pip3 install "pygatt[GATTTOOL]"
- ./bin/run.sh --debug --ble --device 24:62:AB:DD:DF:3A
- ./bin/run.sh --ble-scan # To look for Meshtastic devices
- ./bin/run.sh --ble 24:62:AB:DD:DF:3A --info
## Done
@@ -34,7 +30,7 @@ Basic functionality is complete now.
- DONE add fromId and toId to received messages dictionaries
- make command line options for displaying/changing config
- update nodedb as nodes change
- radioConfig - getter/setter syntax: https://www.python-course.eu/python3_properties.php
- localConfig - getter/setter syntax: https://www.python-course.eu/python3_properties.php
- let user change radio params via commandline options
- keep nodedb up-to-date based on received MeshPackets
- handle radio reboots and redownload db when that happens. Look for a special FromRadio.rebooted packet

9
bin/build-bin.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
set -e
echo Building ubuntu binary
poetry install
source $(poetry env info --path)/bin/activate
pyinstaller -F -n meshtastic --collect-all meshtastic meshtastic/__main__.py

19
bin/git-resolve-poetry-lock.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -e
# This is a little helper you can use to resolve git merge conflicts in poetry.lock
# with minimal changes vs the requested lib versions
# Based on this article with a good description of best practices:
# https://www.peterbe.com/plog/how-to-resolve-a-git-conflict-in-poetry.lock
echo "Resolving poetry.lock merge conflicts, you'll need to run git commit yourself..."
# Get poetry.lock to look like it does in master
git checkout --theirs poetry.lock
# Rewrite the lock file
poetry lock --no-update
git add poetry.lock
# Update your poetry env to match the new merged lock file
poetry install

View File

@@ -2,21 +2,31 @@ set -e
# You may consider running: "pytest -m smoke1" instead of this test.
echo "Linting"
poetry run pylint meshtastic examples/ --ignore-patterns ".*_pb2.pyi?$"
echo "Checking types"
poetry run mypy meshtastic/
echo "Running (crude) prerelease tests to verify sanity"
# Use the python environment created by poetry
source $(poetry env info --path)/bin/activate
echo running hello
python3 tests/hello_world.py
# bin/run.sh --help
# meshtastic --help
echo toggling router
bin/run.sh --set is_router true
bin/run.sh --set is_router false
meshtastic --set is_router true
meshtastic --set is_router false
# TODO: This does not seem to work.
echo setting channel
bin/run.sh --seturl "https://www.meshtastic.org/c/#GAMiENTxuzogKQdZ8Lz_q89Oab8qB0RlZmF1bHQ="
meshtastic --seturl "https://www.meshtastic.org/c/#GAMiENTxuzogKQdZ8Lz_q89Oab8qB0RlZmF1bHQ="
echo setting owner
bin/run.sh --set-owner "Test Build"
meshtastic --set-owner "Test Build"
echo setting position
bin/run.sh --setlat 32.7767 --setlon -96.7970 --setalt 1337
meshtastic --setlat 32.7767 --setlon -96.7970 --setalt 1337
echo dumping info
bin/run.sh --info
meshtastic run meshtastic --info
echo sending closing message
bin/run.sh --sendtext "Sanity complete"
meshtastic --sendtext "Sanity complete"

View File

@@ -1 +1,4 @@
pdoc3 --html -f --output-dir docs meshtastic
# Note: Docs are generated from this command below, albeit from Vercel.
# The docs/ dir is not used and is no longer committed.
# see sachaw if you have questions
pdoc3 --html -f --output-dir docs meshtastic

62
bin/regen-protobufs.sh Executable file
View File

@@ -0,0 +1,62 @@
#!/bin/bash
set -e
#Uncomment to run hack
#gsed -i 's/import "\//import ".\//g' ./protobufs/meshtastic/*
#gsed -i 's/package meshtastic;//g' ./protobufs/meshtastic/*
POETRYDIR=$(poetry env info --path)
if [[ -z "${POETRYDIR}" ]]; then
poetry install
fi
# protoc looks for mypy plugin in the python path
source $(poetry env info --path)/bin/activate
# Put our temp files in the poetry build directory
TMPDIR=./build/meshtastic/protofixup
echo "Fixing up protobuf paths in ${TMPDIR} temp directory"
# Ensure a clean build
[ -e "${TMPDIR}" ] && rm -r "${TMPDIR}"
INDIR=${TMPDIR}/in/meshtastic/protobuf
OUTDIR=${TMPDIR}/out
PYIDIR=${TMPDIR}/out
mkdir -p "${OUTDIR}" "${INDIR}" "${PYIDIR}"
cp ./protobufs/meshtastic/*.proto "${INDIR}"
cp ./protobufs/nanopb.proto "${INDIR}"
# OS-X sed is apparently a little different and expects an arg for -i
if [[ $OSTYPE == 'darwin'* ]]; then
SEDCMD="sed -i '' -E"
else
SEDCMD="sed -i -E"
fi
# change the package names to meshtastic.protobuf
$SEDCMD 's/^package meshtastic;/package meshtastic.protobuf;/' "${INDIR}/"*.proto
# fix the imports to match
$SEDCMD 's/^import "meshtastic\//import "meshtastic\/protobuf\//' "${INDIR}/"*.proto
$SEDCMD 's/^import "nanopb.proto"/import "meshtastic\/protobuf\/nanopb.proto"/' "${INDIR}/"*.proto
# Generate the python files
./nanopb-0.4.8/generator-bin/protoc -I=$TMPDIR/in --python_out "${OUTDIR}" "--mypy_out=${PYIDIR}" $INDIR/*.proto
# Change "from meshtastic.protobuf import" to "from . import"
$SEDCMD 's/^from meshtastic.protobuf import/from . import/' "${OUTDIR}"/meshtastic/protobuf/*pb2*.py[i]
# Create a __init__.py in the out directory
touch "${OUTDIR}/meshtastic/protobuf/__init__.py"
# Copy to the source controlled tree
mkdir -p meshtastic/protobuf
rm -rf meshtastic/protobuf/*pb2*.py
cp "${OUTDIR}/meshtastic/protobuf"/* meshtastic/protobuf
exit 0

View File

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

11
bin/run-ci-local.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
# This script lets you run github ci actions locally
# You need to have act installed. You can get it at https://nektosact.com/
# by default it simulates a push event
# other useful options
# -j build-and-publish-ubuntu
# also: we only run one of the 4 matrix tests, because otherwise it absolutely hammers the CPU (so many containers and threads)
act -P ubuntu-latest=-self-hosted --matrix "python-version:3.8" "$@"

View File

@@ -1,2 +0,0 @@
rm log_*
python3 -m meshtastic "$@"

View File

@@ -3,8 +3,6 @@ set -e
bin/regen-docs.sh
pandoc --from=markdown --to=rst --output=README README.md
python3 setup.py sdist bdist_wheel
python3 -m twine check dist/*
# test the upload
python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*
echo "view the upload at https://test.pypi.org/ it it looks good upload for real"
poetry publish -r test-pypi --build
echo "view the upload at https://test.pypi.org/ it it looks good upload for real"

View File

@@ -1,7 +1,8 @@
rm dist/*
set -e
bin/regen-docs.sh
pandoc --from=markdown --to=rst --output=README README.md
python3 setup.py sdist bdist_wheel
python3 -m twine upload dist/*
poetry build
poetry run pytest
poetry publish
#python3 setup.py sdist bdist_wheel
#python3 -m twine upload dist/*

View File

@@ -1 +0,0 @@
<meta http-equiv="refresh" content="0; url=./meshtastic/index.html" />

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,707 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.apponly_pb2 API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.apponly_pb2</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"># -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: apponly.proto
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from . import channel_pb2 as channel__pb2
DESCRIPTOR = _descriptor.FileDescriptor(
name=&#39;apponly.proto&#39;,
package=&#39;&#39;,
syntax=&#39;proto3&#39;,
serialized_options=b&#39;\n\023com.geeksville.meshB\rAppOnlyProtosH\003Z!github.com/meshtastic/gomeshproto&#39;,
serialized_pb=b&#39;\n\rapponly.proto\x1a\rchannel.proto\&#34;0\n\nChannelSet\x12\&#34;\n\x08settings\x18\x01 \x03(\x0b\x32\x10.ChannelSettingsBI\n\x13\x63om.geeksville.meshB\rAppOnlyProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3&#39;
,
dependencies=[channel__pb2.DESCRIPTOR,])
_CHANNELSET = _descriptor.Descriptor(
name=&#39;ChannelSet&#39;,
full_name=&#39;ChannelSet&#39;,
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name=&#39;settings&#39;, full_name=&#39;ChannelSet.settings&#39;, index=0,
number=1, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax=&#39;proto3&#39;,
extension_ranges=[],
oneofs=[
],
serialized_start=32,
serialized_end=80,
)
_CHANNELSET.fields_by_name[&#39;settings&#39;].message_type = channel__pb2._CHANNELSETTINGS
DESCRIPTOR.message_types_by_name[&#39;ChannelSet&#39;] = _CHANNELSET
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
ChannelSet = _reflection.GeneratedProtocolMessageType(&#39;ChannelSet&#39;, (_message.Message,), {
&#39;DESCRIPTOR&#39; : _CHANNELSET,
&#39;__module__&#39; : &#39;apponly_pb2&#39;
# @@protoc_insertion_point(class_scope:ChannelSet)
})
_sym_db.RegisterMessage(ChannelSet)
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.apponly_pb2.ChannelSet"><code class="flex name class">
<span>class <span class="ident">ChannelSet</span></span>
<span>(</span><span>**kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Abstract base class for protocol messages.</p>
<p>Protocol message classes are almost always generated by the protocol
compiler.
These generated types subclass Message and implement the methods
shown below.</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="meshtastic.apponly_pb2.ChannelSet.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.SETTINGS_FIELD_NUMBER"><code class="name">var <span class="ident">SETTINGS_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Static methods</h3>
<dl>
<dt id="meshtastic.apponly_pb2.ChannelSet.FromString"><code class="name flex">
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FromString(s):
message = cls()
message.MergeFromString(s)
return message</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.RegisterExtension"><code class="name flex">
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def RegisterExtension(extension_handle):
extension_handle.containing_type = cls.DESCRIPTOR
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
# pylint: disable=protected-access
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
_AttachFieldHelpers(cls, extension_handle)</code></pre>
</details>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.apponly_pb2.ChannelSet.settings"><code class="name">var <span class="ident">settings</span></code></dt>
<dd>
<div class="desc"><p>Getter for settings.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
# take that object and discard ours.
# WARNING: We are relying on setdefault() being atomic. This is true
# in CPython but we haven&#39;t investigated others. This warning appears
# in several other locations in this file.
field_value = self._fields.setdefault(field, field_value)
return field_value</code></pre>
</details>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.apponly_pb2.ChannelSet.ByteSize"><code class="name flex">
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ByteSize(self):
if not self._cached_byte_size_dirty:
return self._cached_byte_size
size = 0
descriptor = self.DESCRIPTOR
if descriptor.GetOptions().map_entry:
# Fields of map entry should always be serialized.
size = descriptor.fields_by_name[&#39;key&#39;]._sizer(self.key)
size += descriptor.fields_by_name[&#39;value&#39;]._sizer(self.value)
else:
for field_descriptor, field_value in self.ListFields():
size += field_descriptor._sizer(field_value)
for tag_bytes, value_bytes in self._unknown_fields:
size += len(tag_bytes) + len(value_bytes)
self._cached_byte_size = size
self._cached_byte_size_dirty = False
self._listener_for_children.dirty = False
return size</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.Clear"><code class="name flex">
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _Clear(self):
# Clear fields.
self._fields = {}
self._unknown_fields = ()
# pylint: disable=protected-access
if self._unknown_field_set is not None:
self._unknown_field_set._clear()
self._unknown_field_set = None
self._oneofs = {}
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.ClearField"><code class="name flex">
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ClearField(self, field_name):
try:
field = message_descriptor.fields_by_name[field_name]
except KeyError:
try:
field = message_descriptor.oneofs_by_name[field_name]
if field in self._oneofs:
field = self._oneofs[field]
else:
return
except KeyError:
raise ValueError(&#39;Protocol message %s has no &#34;%s&#34; field.&#39; %
(message_descriptor.name, field_name))
if field in self._fields:
# To match the C++ implementation, we need to invalidate iterators
# for map fields when ClearField() happens.
if hasattr(self._fields[field], &#39;InvalidateIterators&#39;):
self._fields[field].InvalidateIterators()
# Note: If the field is a sub-message, its listener will still point
# at us. That&#39;s fine, because the worst than can happen is that it
# will call _Modified() and invalidate our byte size. Big deal.
del self._fields[field]
if self._oneofs.get(field.containing_oneof, None) is field:
del self._oneofs[field.containing_oneof]
# Always call _Modified() -- even if nothing was changed, this is
# a mutating method, and thus calling it should cause the field to become
# present in the parent message.
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.DiscardUnknownFields"><code class="name flex">
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _DiscardUnknownFields(self):
self._unknown_fields = []
self._unknown_field_set = None # pylint: disable=protected-access
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
value[key].DiscardUnknownFields()
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for sub_message in value:
sub_message.DiscardUnknownFields()
else:
value.DiscardUnknownFields()</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.FindInitializationErrors"><code class="name flex">
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Finds required fields which are not initialized.</p>
<h2 id="returns">Returns</h2>
<p>A list of strings.
Each string is a path to an uninitialized field from
the top-level message, e.g. "foo.bar[5].baz".</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FindInitializationErrors(self):
&#34;&#34;&#34;Finds required fields which are not initialized.
Returns:
A list of strings. Each string is a path to an uninitialized field from
the top-level message, e.g. &#34;foo.bar[5].baz&#34;.
&#34;&#34;&#34;
errors = [] # simplify things
for field in required_fields:
if not self.HasField(field.name):
errors.append(field.name)
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.is_extension:
name = &#39;(%s)&#39; % field.full_name
else:
name = field.name
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
element = value[key]
prefix = &#39;%s[%s].&#39; % (name, key)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
# ScalarMaps can&#39;t have any initialization errors.
pass
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for i in range(len(value)):
element = value[i]
prefix = &#39;%s[%d].&#39; % (name, i)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
prefix = name + &#39;.&#39;
sub_errors = value.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
return errors</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.HasField"><code class="name flex">
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def HasField(self, field_name):
try:
field = hassable_fields[field_name]
except KeyError:
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
if isinstance(field, descriptor_mod.OneofDescriptor):
try:
return HasField(self, self._oneofs[field].name)
except KeyError:
return False
else:
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
value = self._fields.get(field)
return value is not None and value._is_present_in_parent
else:
return field in self._fields</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.IsInitialized"><code class="name flex">
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
</code></dt>
<dd>
<div class="desc"><p>Checks if all required fields of a message are set.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>errors</code></strong></dt>
<dd>A list which, if provided, will be populated with the field
paths of all missing required fields.</dd>
</dl>
<h2 id="returns">Returns</h2>
<p>True iff the specified message has all required fields set.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def IsInitialized(self, errors=None):
&#34;&#34;&#34;Checks if all required fields of a message are set.
Args:
errors: A list which, if provided, will be populated with the field
paths of all missing required fields.
Returns:
True iff the specified message has all required fields set.
&#34;&#34;&#34;
# Performance is critical so we avoid HasField() and ListFields().
for field in required_fields:
if (field not in self._fields or
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
not self._fields[field]._is_present_in_parent)):
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
for field, value in list(self._fields.items()): # dict can change size!
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.label == _FieldDescriptor.LABEL_REPEATED:
if (field.message_type.has_options and
field.message_type.GetOptions().map_entry):
continue
for element in value:
if not element.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
elif value._is_present_in_parent and not value.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
return True</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.ListFields"><code class="name flex">
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ListFields(self):
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
all_fields.sort(key = lambda item: item[0].number)
return all_fields</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.MergeFrom"><code class="name flex">
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFrom(self, msg):
if not isinstance(msg, cls):
raise TypeError(
&#39;Parameter to MergeFrom() must be instance of same class: &#39;
&#39;expected %s got %s.&#39; % (_FullyQualifiedClassName(cls),
_FullyQualifiedClassName(msg.__class__)))
assert msg is not self
self._Modified()
fields = self._fields
for field, value in msg._fields.items():
if field.label == LABEL_REPEATED:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
elif field.cpp_type == CPPTYPE_MESSAGE:
if value._is_present_in_parent:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
else:
self._fields[field] = value
if field.containing_oneof:
self._UpdateOneofState(field)
if msg._unknown_fields:
if not self._unknown_fields:
self._unknown_fields = []
self._unknown_fields.extend(msg._unknown_fields)
# pylint: disable=protected-access
if self._unknown_field_set is None:
self._unknown_field_set = containers.UnknownFieldSet()
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.MergeFromString"><code class="name flex">
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFromString(self, serialized):
serialized = memoryview(serialized)
length = len(serialized)
try:
if self._InternalParse(serialized, 0, length) != length:
# The only reason _InternalParse would return early is if it
# encountered an end-group tag.
raise message_mod.DecodeError(&#39;Unexpected end-group tag.&#39;)
except (IndexError, TypeError):
# Now ord(buf[p:p+1]) == ord(&#39;&#39;) gets TypeError.
raise message_mod.DecodeError(&#39;Truncated message.&#39;)
except struct.error as e:
raise message_mod.DecodeError(e)
return length # Return this for legacy reasons.</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.SerializePartialToString"><code class="name flex">
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializePartialToString(self, **kwargs):
out = BytesIO()
self._InternalSerialize(out.write, **kwargs)
return out.getvalue()</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.SerializeToString"><code class="name flex">
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializeToString(self, **kwargs):
# Check if the message has all of its required fields set.
if not self.IsInitialized():
raise message_mod.EncodeError(
&#39;Message %s is missing required fields: %s&#39; % (
self.DESCRIPTOR.full_name, &#39;,&#39;.join(self.FindInitializationErrors())))
return self.SerializePartialToString(**kwargs)</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.SetInParent"><code class="name flex">
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def Modified(self):
&#34;&#34;&#34;Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.
&#34;&#34;&#34;
# Note: Some callers check _cached_byte_size_dirty before calling
# _Modified() as an extra optimization. So, if this method is ever
# changed such that it does stuff even when _cached_byte_size_dirty is
# already true, the callers need to be updated.
if not self._cached_byte_size_dirty:
self._cached_byte_size_dirty = True
self._listener_for_children.dirty = True
self._is_present_in_parent = True
self._listener.Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.UnknownFields"><code class="name flex">
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _UnknownFields(self):
if self._unknown_field_set is None: # pylint: disable=protected-access
# pylint: disable=protected-access
self._unknown_field_set = containers.UnknownFieldSet()
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
</details>
</dd>
<dt id="meshtastic.apponly_pb2.ChannelSet.WhichOneof"><code class="name flex">
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
</code></dt>
<dd>
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def WhichOneof(self, oneof_name):
&#34;&#34;&#34;Returns the name of the currently set field inside a oneof, or None.&#34;&#34;&#34;
try:
field = message_descriptor.oneofs_by_name[oneof_name]
except KeyError:
raise ValueError(
&#39;Protocol message has no oneof &#34;%s&#34; field.&#39; % oneof_name)
nested_field = self._oneofs.get(field, None)
if nested_field is not None and self.HasField(nested_field.name):
return nested_field.name
else:
return None</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.apponly_pb2.ChannelSet" href="#meshtastic.apponly_pb2.ChannelSet">ChannelSet</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.ByteSize" href="#meshtastic.apponly_pb2.ChannelSet.ByteSize">ByteSize</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.Clear" href="#meshtastic.apponly_pb2.ChannelSet.Clear">Clear</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.ClearField" href="#meshtastic.apponly_pb2.ChannelSet.ClearField">ClearField</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.DESCRIPTOR" href="#meshtastic.apponly_pb2.ChannelSet.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.DiscardUnknownFields" href="#meshtastic.apponly_pb2.ChannelSet.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.FindInitializationErrors" href="#meshtastic.apponly_pb2.ChannelSet.FindInitializationErrors">FindInitializationErrors</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.FromString" href="#meshtastic.apponly_pb2.ChannelSet.FromString">FromString</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.HasField" href="#meshtastic.apponly_pb2.ChannelSet.HasField">HasField</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.IsInitialized" href="#meshtastic.apponly_pb2.ChannelSet.IsInitialized">IsInitialized</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.ListFields" href="#meshtastic.apponly_pb2.ChannelSet.ListFields">ListFields</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.MergeFrom" href="#meshtastic.apponly_pb2.ChannelSet.MergeFrom">MergeFrom</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.MergeFromString" href="#meshtastic.apponly_pb2.ChannelSet.MergeFromString">MergeFromString</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.RegisterExtension" href="#meshtastic.apponly_pb2.ChannelSet.RegisterExtension">RegisterExtension</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.SETTINGS_FIELD_NUMBER" href="#meshtastic.apponly_pb2.ChannelSet.SETTINGS_FIELD_NUMBER">SETTINGS_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.SerializePartialToString" href="#meshtastic.apponly_pb2.ChannelSet.SerializePartialToString">SerializePartialToString</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.SerializeToString" href="#meshtastic.apponly_pb2.ChannelSet.SerializeToString">SerializeToString</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.SetInParent" href="#meshtastic.apponly_pb2.ChannelSet.SetInParent">SetInParent</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.UnknownFields" href="#meshtastic.apponly_pb2.ChannelSet.UnknownFields">UnknownFields</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.WhichOneof" href="#meshtastic.apponly_pb2.ChannelSet.WhichOneof">WhichOneof</a></code></li>
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.settings" href="#meshtastic.apponly_pb2.ChannelSet.settings">settings</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,53 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.ble API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.ble</code></h1>
</header>
<section id="section-intro">
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,212 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.ble_interface API documentation</title>
<meta name="description" content="Bluetooth interface" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.ble_interface</code></h1>
</header>
<section id="section-intro">
<p>Bluetooth interface</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Bluetooth interface
&#34;&#34;&#34;
import logging
import pygatt
from .mesh_interface import MeshInterface
# Our standard BLE characteristics
TORADIO_UUID = &#34;f75c76d2-129e-4dad-a1dd-7866124401e7&#34;
FROMRADIO_UUID = &#34;8ba2bcc2-ee02-4a55-a531-c525c5e454d5&#34;
FROMNUM_UUID = &#34;ed9da18c-a800-4f66-a670-aa7547e34453&#34;
class BLEInterface(MeshInterface):
&#34;&#34;&#34;A not quite ready - FIXME - BLE interface to devices&#34;&#34;&#34;
def __init__(self, address, noProto=False, debugOut=None):
self.address = address
if not noProto:
self.adapter = pygatt.GATTToolBackend() # BGAPIBackend()
self.adapter.start()
logging.debug(f&#34;Connecting to {self.address}&#34;)
self.device = self.adapter.connect(address)
else:
self.adapter = None
self.device = None
logging.debug(&#34;Connected to device&#34;)
# fromradio = self.device.char_read(FROMRADIO_UUID)
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
self._readFromRadio() # read the initial responses
def handle_data(handle, data):
self._handleFromRadio(data)
if self.device:
self.device.subscribe(FROMNUM_UUID, callback=handle_data)
def _sendToRadioImpl(self, toRadio):
&#34;&#34;&#34;Send a ToRadio protobuf to the device&#34;&#34;&#34;
#logging.debug(f&#34;Sending: {stripnl(toRadio)}&#34;)
b = toRadio.SerializeToString()
self.device.char_write(TORADIO_UUID, b)
def close(self):
MeshInterface.close(self)
if self.adapter:
self.adapter.stop()
def _readFromRadio(self):
if not self.noProto:
wasEmpty = False
while not wasEmpty:
if self.device:
b = self.device.char_read(FROMRADIO_UUID)
wasEmpty = len(b) == 0
if not wasEmpty:
self._handleFromRadio(b)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.ble_interface.BLEInterface"><code class="flex name class">
<span>class <span class="ident">BLEInterface</span></span>
<span>(</span><span>address, noProto=False, debugOut=None)</span>
</code></dt>
<dd>
<div class="desc"><p>A not quite ready - FIXME - BLE interface to devices</p>
<p>Constructor</p>
<p>Keyword Arguments:
noProto &ndash; If True, don't try to run our protocol on the
link - just be a dumb serial client.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class BLEInterface(MeshInterface):
&#34;&#34;&#34;A not quite ready - FIXME - BLE interface to devices&#34;&#34;&#34;
def __init__(self, address, noProto=False, debugOut=None):
self.address = address
if not noProto:
self.adapter = pygatt.GATTToolBackend() # BGAPIBackend()
self.adapter.start()
logging.debug(f&#34;Connecting to {self.address}&#34;)
self.device = self.adapter.connect(address)
else:
self.adapter = None
self.device = None
logging.debug(&#34;Connected to device&#34;)
# fromradio = self.device.char_read(FROMRADIO_UUID)
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
self._readFromRadio() # read the initial responses
def handle_data(handle, data):
self._handleFromRadio(data)
if self.device:
self.device.subscribe(FROMNUM_UUID, callback=handle_data)
def _sendToRadioImpl(self, toRadio):
&#34;&#34;&#34;Send a ToRadio protobuf to the device&#34;&#34;&#34;
#logging.debug(f&#34;Sending: {stripnl(toRadio)}&#34;)
b = toRadio.SerializeToString()
self.device.char_write(TORADIO_UUID, b)
def close(self):
MeshInterface.close(self)
if self.adapter:
self.adapter.stop()
def _readFromRadio(self):
if not self.noProto:
wasEmpty = False
while not wasEmpty:
if self.device:
b = self.device.char_read(FROMRADIO_UUID)
wasEmpty = len(b) == 0
if not wasEmpty:
self._handleFromRadio(b)</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="meshtastic.mesh_interface.MeshInterface" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface">MeshInterface</a></li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="meshtastic.mesh_interface.MeshInterface" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface">MeshInterface</a></b></code>:
<ul class="hlist">
<li><code><a title="meshtastic.mesh_interface.MeshInterface.close" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.close">close</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getLongName" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getLongName">getLongName</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getMyNodeInfo" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getMyNodeInfo">getMyNodeInfo</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getMyUser" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getMyUser">getMyUser</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getNode" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getNode">getNode</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getShortName" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getShortName">getShortName</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.sendData" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendData">sendData</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.sendPosition" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendPosition">sendPosition</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.sendText" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendText">sendText</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.showInfo" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.showInfo">showInfo</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.showNodes" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.showNodes">showNodes</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.waitForConfig" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.waitForConfig">waitForConfig</a></code></li>
</ul>
</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.ble_interface.BLEInterface" href="#meshtastic.ble_interface.BLEInterface">BLEInterface</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,746 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.environmental_measurement_pb2 API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.environmental_measurement_pb2</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"># -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: environmental_measurement.proto
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name=&#39;environmental_measurement.proto&#39;,
package=&#39;&#39;,
syntax=&#39;proto3&#39;,
serialized_options=b&#39;Z!github.com/meshtastic/gomeshproto&#39;,
serialized_pb=b&#39;\n\x1f\x65nvironmental_measurement.proto\&#34;g\n\x18\x45nvironmentalMeasurement\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\x19\n\x11relative_humidity\x18\x02 \x01(\x02\x12\x1b\n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02\x42#Z!github.com/meshtastic/gomeshprotob\x06proto3&#39;
)
_ENVIRONMENTALMEASUREMENT = _descriptor.Descriptor(
name=&#39;EnvironmentalMeasurement&#39;,
full_name=&#39;EnvironmentalMeasurement&#39;,
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name=&#39;temperature&#39;, full_name=&#39;EnvironmentalMeasurement.temperature&#39;, index=0,
number=1, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name=&#39;relative_humidity&#39;, full_name=&#39;EnvironmentalMeasurement.relative_humidity&#39;, index=1,
number=2, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name=&#39;barometric_pressure&#39;, full_name=&#39;EnvironmentalMeasurement.barometric_pressure&#39;, index=2,
number=3, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax=&#39;proto3&#39;,
extension_ranges=[],
oneofs=[
],
serialized_start=35,
serialized_end=138,
)
DESCRIPTOR.message_types_by_name[&#39;EnvironmentalMeasurement&#39;] = _ENVIRONMENTALMEASUREMENT
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
EnvironmentalMeasurement = _reflection.GeneratedProtocolMessageType(&#39;EnvironmentalMeasurement&#39;, (_message.Message,), {
&#39;DESCRIPTOR&#39; : _ENVIRONMENTALMEASUREMENT,
&#39;__module__&#39; : &#39;environmental_measurement_pb2&#39;
# @@protoc_insertion_point(class_scope:EnvironmentalMeasurement)
})
_sym_db.RegisterMessage(EnvironmentalMeasurement)
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement"><code class="flex name class">
<span>class <span class="ident">EnvironmentalMeasurement</span></span>
<span>(</span><span>**kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Abstract base class for protocol messages.</p>
<p>Protocol message classes are almost always generated by the protocol
compiler.
These generated types subclass Message and implement the methods
shown below.</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.BAROMETRIC_PRESSURE_FIELD_NUMBER"><code class="name">var <span class="ident">BAROMETRIC_PRESSURE_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RELATIVE_HUMIDITY_FIELD_NUMBER"><code class="name">var <span class="ident">RELATIVE_HUMIDITY_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.TEMPERATURE_FIELD_NUMBER"><code class="name">var <span class="ident">TEMPERATURE_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Static methods</h3>
<dl>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FromString"><code class="name flex">
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FromString(s):
message = cls()
message.MergeFromString(s)
return message</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RegisterExtension"><code class="name flex">
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def RegisterExtension(extension_handle):
extension_handle.containing_type = cls.DESCRIPTOR
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
# pylint: disable=protected-access
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
_AttachFieldHelpers(cls, extension_handle)</code></pre>
</details>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.barometric_pressure"><code class="name">var <span class="ident">barometric_pressure</span></code></dt>
<dd>
<div class="desc"><p>Getter for barometric_pressure.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.relative_humidity"><code class="name">var <span class="ident">relative_humidity</span></code></dt>
<dd>
<div class="desc"><p>Getter for relative_humidity.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.temperature"><code class="name">var <span class="ident">temperature</span></code></dt>
<dd>
<div class="desc"><p>Getter for temperature.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ByteSize"><code class="name flex">
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ByteSize(self):
if not self._cached_byte_size_dirty:
return self._cached_byte_size
size = 0
descriptor = self.DESCRIPTOR
if descriptor.GetOptions().map_entry:
# Fields of map entry should always be serialized.
size = descriptor.fields_by_name[&#39;key&#39;]._sizer(self.key)
size += descriptor.fields_by_name[&#39;value&#39;]._sizer(self.value)
else:
for field_descriptor, field_value in self.ListFields():
size += field_descriptor._sizer(field_value)
for tag_bytes, value_bytes in self._unknown_fields:
size += len(tag_bytes) + len(value_bytes)
self._cached_byte_size = size
self._cached_byte_size_dirty = False
self._listener_for_children.dirty = False
return size</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.Clear"><code class="name flex">
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _Clear(self):
# Clear fields.
self._fields = {}
self._unknown_fields = ()
# pylint: disable=protected-access
if self._unknown_field_set is not None:
self._unknown_field_set._clear()
self._unknown_field_set = None
self._oneofs = {}
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ClearField"><code class="name flex">
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ClearField(self, field_name):
try:
field = message_descriptor.fields_by_name[field_name]
except KeyError:
try:
field = message_descriptor.oneofs_by_name[field_name]
if field in self._oneofs:
field = self._oneofs[field]
else:
return
except KeyError:
raise ValueError(&#39;Protocol message %s has no &#34;%s&#34; field.&#39; %
(message_descriptor.name, field_name))
if field in self._fields:
# To match the C++ implementation, we need to invalidate iterators
# for map fields when ClearField() happens.
if hasattr(self._fields[field], &#39;InvalidateIterators&#39;):
self._fields[field].InvalidateIterators()
# Note: If the field is a sub-message, its listener will still point
# at us. That&#39;s fine, because the worst than can happen is that it
# will call _Modified() and invalidate our byte size. Big deal.
del self._fields[field]
if self._oneofs.get(field.containing_oneof, None) is field:
del self._oneofs[field.containing_oneof]
# Always call _Modified() -- even if nothing was changed, this is
# a mutating method, and thus calling it should cause the field to become
# present in the parent message.
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DiscardUnknownFields"><code class="name flex">
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _DiscardUnknownFields(self):
self._unknown_fields = []
self._unknown_field_set = None # pylint: disable=protected-access
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
value[key].DiscardUnknownFields()
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for sub_message in value:
sub_message.DiscardUnknownFields()
else:
value.DiscardUnknownFields()</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FindInitializationErrors"><code class="name flex">
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Finds required fields which are not initialized.</p>
<h2 id="returns">Returns</h2>
<p>A list of strings.
Each string is a path to an uninitialized field from
the top-level message, e.g. "foo.bar[5].baz".</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FindInitializationErrors(self):
&#34;&#34;&#34;Finds required fields which are not initialized.
Returns:
A list of strings. Each string is a path to an uninitialized field from
the top-level message, e.g. &#34;foo.bar[5].baz&#34;.
&#34;&#34;&#34;
errors = [] # simplify things
for field in required_fields:
if not self.HasField(field.name):
errors.append(field.name)
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.is_extension:
name = &#39;(%s)&#39; % field.full_name
else:
name = field.name
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
element = value[key]
prefix = &#39;%s[%s].&#39; % (name, key)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
# ScalarMaps can&#39;t have any initialization errors.
pass
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for i in range(len(value)):
element = value[i]
prefix = &#39;%s[%d].&#39; % (name, i)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
prefix = name + &#39;.&#39;
sub_errors = value.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
return errors</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.HasField"><code class="name flex">
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def HasField(self, field_name):
try:
field = hassable_fields[field_name]
except KeyError:
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
if isinstance(field, descriptor_mod.OneofDescriptor):
try:
return HasField(self, self._oneofs[field].name)
except KeyError:
return False
else:
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
value = self._fields.get(field)
return value is not None and value._is_present_in_parent
else:
return field in self._fields</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.IsInitialized"><code class="name flex">
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
</code></dt>
<dd>
<div class="desc"><p>Checks if all required fields of a message are set.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>errors</code></strong></dt>
<dd>A list which, if provided, will be populated with the field
paths of all missing required fields.</dd>
</dl>
<h2 id="returns">Returns</h2>
<p>True iff the specified message has all required fields set.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def IsInitialized(self, errors=None):
&#34;&#34;&#34;Checks if all required fields of a message are set.
Args:
errors: A list which, if provided, will be populated with the field
paths of all missing required fields.
Returns:
True iff the specified message has all required fields set.
&#34;&#34;&#34;
# Performance is critical so we avoid HasField() and ListFields().
for field in required_fields:
if (field not in self._fields or
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
not self._fields[field]._is_present_in_parent)):
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
for field, value in list(self._fields.items()): # dict can change size!
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.label == _FieldDescriptor.LABEL_REPEATED:
if (field.message_type.has_options and
field.message_type.GetOptions().map_entry):
continue
for element in value:
if not element.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
elif value._is_present_in_parent and not value.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
return True</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ListFields"><code class="name flex">
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ListFields(self):
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
all_fields.sort(key = lambda item: item[0].number)
return all_fields</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFrom"><code class="name flex">
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFrom(self, msg):
if not isinstance(msg, cls):
raise TypeError(
&#39;Parameter to MergeFrom() must be instance of same class: &#39;
&#39;expected %s got %s.&#39; % (_FullyQualifiedClassName(cls),
_FullyQualifiedClassName(msg.__class__)))
assert msg is not self
self._Modified()
fields = self._fields
for field, value in msg._fields.items():
if field.label == LABEL_REPEATED:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
elif field.cpp_type == CPPTYPE_MESSAGE:
if value._is_present_in_parent:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
else:
self._fields[field] = value
if field.containing_oneof:
self._UpdateOneofState(field)
if msg._unknown_fields:
if not self._unknown_fields:
self._unknown_fields = []
self._unknown_fields.extend(msg._unknown_fields)
# pylint: disable=protected-access
if self._unknown_field_set is None:
self._unknown_field_set = containers.UnknownFieldSet()
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFromString"><code class="name flex">
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFromString(self, serialized):
serialized = memoryview(serialized)
length = len(serialized)
try:
if self._InternalParse(serialized, 0, length) != length:
# The only reason _InternalParse would return early is if it
# encountered an end-group tag.
raise message_mod.DecodeError(&#39;Unexpected end-group tag.&#39;)
except (IndexError, TypeError):
# Now ord(buf[p:p+1]) == ord(&#39;&#39;) gets TypeError.
raise message_mod.DecodeError(&#39;Truncated message.&#39;)
except struct.error as e:
raise message_mod.DecodeError(e)
return length # Return this for legacy reasons.</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializePartialToString"><code class="name flex">
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializePartialToString(self, **kwargs):
out = BytesIO()
self._InternalSerialize(out.write, **kwargs)
return out.getvalue()</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializeToString"><code class="name flex">
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializeToString(self, **kwargs):
# Check if the message has all of its required fields set.
if not self.IsInitialized():
raise message_mod.EncodeError(
&#39;Message %s is missing required fields: %s&#39; % (
self.DESCRIPTOR.full_name, &#39;,&#39;.join(self.FindInitializationErrors())))
return self.SerializePartialToString(**kwargs)</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SetInParent"><code class="name flex">
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def Modified(self):
&#34;&#34;&#34;Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.
&#34;&#34;&#34;
# Note: Some callers check _cached_byte_size_dirty before calling
# _Modified() as an extra optimization. So, if this method is ever
# changed such that it does stuff even when _cached_byte_size_dirty is
# already true, the callers need to be updated.
if not self._cached_byte_size_dirty:
self._cached_byte_size_dirty = True
self._listener_for_children.dirty = True
self._is_present_in_parent = True
self._listener.Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.UnknownFields"><code class="name flex">
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _UnknownFields(self):
if self._unknown_field_set is None: # pylint: disable=protected-access
# pylint: disable=protected-access
self._unknown_field_set = containers.UnknownFieldSet()
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
</details>
</dd>
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.WhichOneof"><code class="name flex">
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
</code></dt>
<dd>
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def WhichOneof(self, oneof_name):
&#34;&#34;&#34;Returns the name of the currently set field inside a oneof, or None.&#34;&#34;&#34;
try:
field = message_descriptor.oneofs_by_name[oneof_name]
except KeyError:
raise ValueError(
&#39;Protocol message has no oneof &#34;%s&#34; field.&#39; % oneof_name)
nested_field = self._oneofs.get(field, None)
if nested_field is not None and self.HasField(nested_field.name):
return nested_field.name
else:
return None</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement">EnvironmentalMeasurement</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.BAROMETRIC_PRESSURE_FIELD_NUMBER" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.BAROMETRIC_PRESSURE_FIELD_NUMBER">BAROMETRIC_PRESSURE_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ByteSize" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ByteSize">ByteSize</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.Clear" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.Clear">Clear</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ClearField" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ClearField">ClearField</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DESCRIPTOR" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DiscardUnknownFields" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FindInitializationErrors" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FindInitializationErrors">FindInitializationErrors</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FromString" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FromString">FromString</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.HasField" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.HasField">HasField</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.IsInitialized" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.IsInitialized">IsInitialized</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ListFields" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ListFields">ListFields</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFrom" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFrom">MergeFrom</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFromString" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFromString">MergeFromString</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RELATIVE_HUMIDITY_FIELD_NUMBER" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RELATIVE_HUMIDITY_FIELD_NUMBER">RELATIVE_HUMIDITY_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RegisterExtension" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RegisterExtension">RegisterExtension</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializePartialToString" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializePartialToString">SerializePartialToString</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializeToString" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializeToString">SerializeToString</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SetInParent" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SetInParent">SetInParent</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.TEMPERATURE_FIELD_NUMBER" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.TEMPERATURE_FIELD_NUMBER">TEMPERATURE_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.UnknownFields" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.UnknownFields">UnknownFields</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.WhichOneof" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.WhichOneof">WhichOneof</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.barometric_pressure" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.barometric_pressure">barometric_pressure</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.relative_humidity" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.relative_humidity">relative_humidity</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.temperature" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.temperature">temperature</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,380 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.globals API documentation</title>
<meta name="description" content="Globals singleton class …" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.globals</code></h1>
</header>
<section id="section-intro">
<p>Globals singleton class.</p>
<p>Instead of using a global, stuff your variables in this "trash can".
This is not much better than using python's globals, but it allows
us to better test meshtastic. Plus, there are some weird python
global issues/gotcha that we can hopefully avoid by using this
class instead.</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Globals singleton class.
Instead of using a global, stuff your variables in this &#34;trash can&#34;.
This is not much better than using python&#39;s globals, but it allows
us to better test meshtastic. Plus, there are some weird python
global issues/gotcha that we can hopefully avoid by using this
class instead.
&#34;&#34;&#34;
class Globals:
&#34;&#34;&#34;Globals class is a Singleton.&#34;&#34;&#34;
__instance = None
@staticmethod
def getInstance():
&#34;&#34;&#34;Get an instance of the Globals class.&#34;&#34;&#34;
if Globals.__instance is None:
Globals()
return Globals.__instance
def __init__(self):
&#34;&#34;&#34;Constructor for the Globals CLass&#34;&#34;&#34;
if Globals.__instance is not None:
raise Exception(&#34;This class is a singleton&#34;)
else:
Globals.__instance = self
self.args = None
self.parser = None
self.target_node = None
self.channel_index = None
def reset(self):
&#34;&#34;&#34;Reset all of our globals. If you add a member, add it to this method, too.&#34;&#34;&#34;
self.args = None
self.parser = None
self.target_node = None
self.channel_index = None
def set_args(self, args):
&#34;&#34;&#34;Set the args&#34;&#34;&#34;
self.args = args
def set_parser(self, parser):
&#34;&#34;&#34;Set the parser&#34;&#34;&#34;
self.parser = parser
def set_target_node(self, target_node):
&#34;&#34;&#34;Set the target_node&#34;&#34;&#34;
self.target_node = target_node
def set_channel_index(self, channel_index):
&#34;&#34;&#34;Set the channel_index&#34;&#34;&#34;
self.channel_index = channel_index
def get_args(self):
&#34;&#34;&#34;Get args&#34;&#34;&#34;
return self.args
def get_parser(self):
&#34;&#34;&#34;Get parser&#34;&#34;&#34;
return self.parser
def get_target_node(self):
&#34;&#34;&#34;Get target_node&#34;&#34;&#34;
return self.target_node
def get_channel_index(self):
&#34;&#34;&#34;Get channel_index&#34;&#34;&#34;
return self.channel_index</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.globals.Globals"><code class="flex name class">
<span>class <span class="ident">Globals</span></span>
</code></dt>
<dd>
<div class="desc"><p>Globals class is a Singleton.</p>
<p>Constructor for the Globals CLass</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class Globals:
&#34;&#34;&#34;Globals class is a Singleton.&#34;&#34;&#34;
__instance = None
@staticmethod
def getInstance():
&#34;&#34;&#34;Get an instance of the Globals class.&#34;&#34;&#34;
if Globals.__instance is None:
Globals()
return Globals.__instance
def __init__(self):
&#34;&#34;&#34;Constructor for the Globals CLass&#34;&#34;&#34;
if Globals.__instance is not None:
raise Exception(&#34;This class is a singleton&#34;)
else:
Globals.__instance = self
self.args = None
self.parser = None
self.target_node = None
self.channel_index = None
def reset(self):
&#34;&#34;&#34;Reset all of our globals. If you add a member, add it to this method, too.&#34;&#34;&#34;
self.args = None
self.parser = None
self.target_node = None
self.channel_index = None
def set_args(self, args):
&#34;&#34;&#34;Set the args&#34;&#34;&#34;
self.args = args
def set_parser(self, parser):
&#34;&#34;&#34;Set the parser&#34;&#34;&#34;
self.parser = parser
def set_target_node(self, target_node):
&#34;&#34;&#34;Set the target_node&#34;&#34;&#34;
self.target_node = target_node
def set_channel_index(self, channel_index):
&#34;&#34;&#34;Set the channel_index&#34;&#34;&#34;
self.channel_index = channel_index
def get_args(self):
&#34;&#34;&#34;Get args&#34;&#34;&#34;
return self.args
def get_parser(self):
&#34;&#34;&#34;Get parser&#34;&#34;&#34;
return self.parser
def get_target_node(self):
&#34;&#34;&#34;Get target_node&#34;&#34;&#34;
return self.target_node
def get_channel_index(self):
&#34;&#34;&#34;Get channel_index&#34;&#34;&#34;
return self.channel_index</code></pre>
</details>
<h3>Static methods</h3>
<dl>
<dt id="meshtastic.globals.Globals.getInstance"><code class="name flex">
<span>def <span class="ident">getInstance</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Get an instance of the Globals class.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@staticmethod
def getInstance():
&#34;&#34;&#34;Get an instance of the Globals class.&#34;&#34;&#34;
if Globals.__instance is None:
Globals()
return Globals.__instance</code></pre>
</details>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.globals.Globals.get_args"><code class="name flex">
<span>def <span class="ident">get_args</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Get args</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def get_args(self):
&#34;&#34;&#34;Get args&#34;&#34;&#34;
return self.args</code></pre>
</details>
</dd>
<dt id="meshtastic.globals.Globals.get_channel_index"><code class="name flex">
<span>def <span class="ident">get_channel_index</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Get channel_index</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def get_channel_index(self):
&#34;&#34;&#34;Get channel_index&#34;&#34;&#34;
return self.channel_index</code></pre>
</details>
</dd>
<dt id="meshtastic.globals.Globals.get_parser"><code class="name flex">
<span>def <span class="ident">get_parser</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Get parser</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def get_parser(self):
&#34;&#34;&#34;Get parser&#34;&#34;&#34;
return self.parser</code></pre>
</details>
</dd>
<dt id="meshtastic.globals.Globals.get_target_node"><code class="name flex">
<span>def <span class="ident">get_target_node</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Get target_node</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def get_target_node(self):
&#34;&#34;&#34;Get target_node&#34;&#34;&#34;
return self.target_node</code></pre>
</details>
</dd>
<dt id="meshtastic.globals.Globals.reset"><code class="name flex">
<span>def <span class="ident">reset</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Reset all of our globals. If you add a member, add it to this method, too.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def reset(self):
&#34;&#34;&#34;Reset all of our globals. If you add a member, add it to this method, too.&#34;&#34;&#34;
self.args = None
self.parser = None
self.target_node = None
self.channel_index = None</code></pre>
</details>
</dd>
<dt id="meshtastic.globals.Globals.set_args"><code class="name flex">
<span>def <span class="ident">set_args</span></span>(<span>self, args)</span>
</code></dt>
<dd>
<div class="desc"><p>Set the args</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def set_args(self, args):
&#34;&#34;&#34;Set the args&#34;&#34;&#34;
self.args = args</code></pre>
</details>
</dd>
<dt id="meshtastic.globals.Globals.set_channel_index"><code class="name flex">
<span>def <span class="ident">set_channel_index</span></span>(<span>self, channel_index)</span>
</code></dt>
<dd>
<div class="desc"><p>Set the channel_index</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def set_channel_index(self, channel_index):
&#34;&#34;&#34;Set the channel_index&#34;&#34;&#34;
self.channel_index = channel_index</code></pre>
</details>
</dd>
<dt id="meshtastic.globals.Globals.set_parser"><code class="name flex">
<span>def <span class="ident">set_parser</span></span>(<span>self, parser)</span>
</code></dt>
<dd>
<div class="desc"><p>Set the parser</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def set_parser(self, parser):
&#34;&#34;&#34;Set the parser&#34;&#34;&#34;
self.parser = parser</code></pre>
</details>
</dd>
<dt id="meshtastic.globals.Globals.set_target_node"><code class="name flex">
<span>def <span class="ident">set_target_node</span></span>(<span>self, target_node)</span>
</code></dt>
<dd>
<div class="desc"><p>Set the target_node</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def set_target_node(self, target_node):
&#34;&#34;&#34;Set the target_node&#34;&#34;&#34;
self.target_node = target_node</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.globals.Globals" href="#meshtastic.globals.Globals">Globals</a></code></h4>
<ul class="two-column">
<li><code><a title="meshtastic.globals.Globals.getInstance" href="#meshtastic.globals.Globals.getInstance">getInstance</a></code></li>
<li><code><a title="meshtastic.globals.Globals.get_args" href="#meshtastic.globals.Globals.get_args">get_args</a></code></li>
<li><code><a title="meshtastic.globals.Globals.get_channel_index" href="#meshtastic.globals.Globals.get_channel_index">get_channel_index</a></code></li>
<li><code><a title="meshtastic.globals.Globals.get_parser" href="#meshtastic.globals.Globals.get_parser">get_parser</a></code></li>
<li><code><a title="meshtastic.globals.Globals.get_target_node" href="#meshtastic.globals.Globals.get_target_node">get_target_node</a></code></li>
<li><code><a title="meshtastic.globals.Globals.reset" href="#meshtastic.globals.Globals.reset">reset</a></code></li>
<li><code><a title="meshtastic.globals.Globals.set_args" href="#meshtastic.globals.Globals.set_args">set_args</a></code></li>
<li><code><a title="meshtastic.globals.Globals.set_channel_index" href="#meshtastic.globals.Globals.set_channel_index">set_channel_index</a></code></li>
<li><code><a title="meshtastic.globals.Globals.set_parser" href="#meshtastic.globals.Globals.set_parser">set_parser</a></code></li>
<li><code><a title="meshtastic.globals.Globals.set_target_node" href="#meshtastic.globals.Globals.set_target_node">set_target_node</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,525 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic API documentation</title>
<meta name="description" content="an API for Meshtastic devices …" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Package <code>meshtastic</code></h1>
</header>
<section id="section-intro">
<h1 id="an-api-for-meshtastic-devices">an API for Meshtastic devices</h1>
<p>Primary class: SerialInterface
Install with pip: "<a href="https://pypi.org/project/meshtastic/">pip3 install meshtastic</a>"
Source code on <a href="https://github.com/meshtastic/Meshtastic-python">github</a></p>
<p>properties of SerialInterface:</p>
<ul>
<li>radioConfig - Current radio configuration and device settings, if you write to this the new settings will be applied to
the device.</li>
<li>nodes - The database of received nodes.
Includes always up-to-date location and username information for each
node in the mesh.
This is a read-only datastructure.</li>
<li>nodesByNum - like "nodes" but keyed by nodeNum instead of nodeId</li>
<li>myInfo - Contains read-only information about the local radio device (software version, hardware version, etc)</li>
</ul>
<h1 id="published-pubsub-topics">Published PubSub topics</h1>
<p>We use a <a href="https://pypubsub.readthedocs.io/en/v4.0.3/">publish-subscribe</a> model to communicate asynchronous events.
Available
topics:</p>
<ul>
<li>meshtastic.connection.established - published once we've successfully connected to the radio and downloaded the node DB</li>
<li>meshtastic.connection.lost - published once we've lost our link to the radio</li>
<li>meshtastic.receive.text(packet) - delivers a received packet as a dictionary, if you only care about a particular
type of packet, you should subscribe to the full topic name.
If you want to see all packets, simply subscribe to "meshtastic.receive".</li>
<li>meshtastic.receive.position(packet)</li>
<li>meshtastic.receive.user(packet)</li>
<li>meshtastic.receive.data.portnum(packet) (where portnum is an integer or well known PortNum enum)</li>
<li>meshtastic.node.updated(node = NodeInfo) - published when a node in the DB changes (appears, location changed, username changed, etc&hellip;)</li>
</ul>
<p>We receive position, user, or data packets from the mesh.
You probably only care about meshtastic.receive.data.
The first argument for
that publish will be the packet.
Text or binary data packets (from sendData or sendText) will both arrive this way.
If you print packet
you'll see the fields in the dictionary.
decoded.data.payload will contain the raw bytes that were sent.
If the packet was sent with
sendText, decoded.data.text will <strong>also</strong> be populated with the decoded string.
For ASCII these two strings will be the same, but for
unicode scripts they can be different.</p>
<h1 id="example-usage">Example Usage</h1>
<pre><code>import meshtastic
from pubsub import pub
def onReceive(packet, interface): # called when a packet arrives
print(f&quot;Received: {packet}&quot;)
def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect to the radio
# defaults to broadcast, specify a destination ID if you wish
interface.sendText(&quot;hello mesh&quot;)
pub.subscribe(onReceive, &quot;meshtastic.receive&quot;)
pub.subscribe(onConnection, &quot;meshtastic.connection.established&quot;)
# By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0
interface = meshtastic.SerialInterface()
</code></pre>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;
# an API for Meshtastic devices
Primary class: SerialInterface
Install with pip: &#34;[pip3 install meshtastic](https://pypi.org/project/meshtastic/)&#34;
Source code on [github](https://github.com/meshtastic/Meshtastic-python)
properties of SerialInterface:
- radioConfig - Current radio configuration and device settings, if you write to this the new settings will be applied to
the device.
- nodes - The database of received nodes. Includes always up-to-date location and username information for each
node in the mesh. This is a read-only datastructure.
- nodesByNum - like &#34;nodes&#34; but keyed by nodeNum instead of nodeId
- myInfo - Contains read-only information about the local radio device (software version, hardware version, etc)
# Published PubSub topics
We use a [publish-subscribe](https://pypubsub.readthedocs.io/en/v4.0.3/) model to communicate asynchronous events. Available
topics:
- meshtastic.connection.established - published once we&#39;ve successfully connected to the radio and downloaded the node DB
- meshtastic.connection.lost - published once we&#39;ve lost our link to the radio
- meshtastic.receive.text(packet) - delivers a received packet as a dictionary, if you only care about a particular
type of packet, you should subscribe to the full topic name. If you want to see all packets, simply subscribe to &#34;meshtastic.receive&#34;.
- meshtastic.receive.position(packet)
- meshtastic.receive.user(packet)
- meshtastic.receive.data.portnum(packet) (where portnum is an integer or well known PortNum enum)
- meshtastic.node.updated(node = NodeInfo) - published when a node in the DB changes (appears, location changed, username changed, etc...)
We receive position, user, or data packets from the mesh. You probably only care about meshtastic.receive.data. The first argument for
that publish will be the packet. Text or binary data packets (from sendData or sendText) will both arrive this way. If you print packet
you&#39;ll see the fields in the dictionary. decoded.data.payload will contain the raw bytes that were sent. If the packet was sent with
sendText, decoded.data.text will **also** be populated with the decoded string. For ASCII these two strings will be the same, but for
unicode scripts they can be different.
# Example Usage
```
import meshtastic
from pubsub import pub
def onReceive(packet, interface): # called when a packet arrives
print(f&#34;Received: {packet}&#34;)
def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect to the radio
# defaults to broadcast, specify a destination ID if you wish
interface.sendText(&#34;hello mesh&#34;)
pub.subscribe(onReceive, &#34;meshtastic.receive&#34;)
pub.subscribe(onConnection, &#34;meshtastic.connection.established&#34;)
# By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0
interface = meshtastic.SerialInterface()
```
&#34;&#34;&#34;
import base64
import logging
import os
import platform
import random
import socket
import sys
import stat
import threading
import traceback
import time
from datetime import datetime
from typing import *
import serial
import timeago
import google.protobuf.json_format
import pygatt
from pubsub import pub
from dotmap import DotMap
from tabulate import tabulate
from google.protobuf.json_format import MessageToJson
from .util import fixme, catchAndIgnore, stripnl, DeferredExecution, Timeout
from .node import Node
from . import mesh_pb2, portnums_pb2, apponly_pb2, admin_pb2, environmental_measurement_pb2, remote_hardware_pb2, channel_pb2, radioconfig_pb2, util
&#34;&#34;&#34;A special ID that means the local node&#34;&#34;&#34;
LOCAL_ADDR = &#34;^local&#34;
# if using 8 bit nodenums this will be shortend on the target
BROADCAST_NUM = 0xffffffff
&#34;&#34;&#34;A special ID that means broadcast&#34;&#34;&#34;
BROADCAST_ADDR = &#34;^all&#34;
&#34;&#34;&#34;The numeric buildnumber (shared with android apps) specifying the
level of device code we are guaranteed to understand
format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
&#34;&#34;&#34;
OUR_APP_VERSION = 20200
publishingThread = DeferredExecution(&#34;publishing&#34;)
class ResponseHandler(NamedTuple):
&#34;&#34;&#34;A pending response callback, waiting for a response to one of our messages&#34;&#34;&#34;
# requestId: int - used only as a key
callback: Callable
# FIXME, add timestamp and age out old requests
class KnownProtocol(NamedTuple):
&#34;&#34;&#34;Used to automatically decode known protocol payloads&#34;&#34;&#34;
name: str
# portnum: int, now a key
# If set, will be called to prase as a protocol buffer
protobufFactory: Callable = None
# If set, invoked as onReceive(interface, packet)
onReceive: Callable = None
def _onTextReceive(iface, asDict):
&#34;&#34;&#34;Special text auto parsing for received messages&#34;&#34;&#34;
# We don&#39;t throw if the utf8 is invalid in the text message. Instead we just don&#39;t populate
# the decoded.data.text and we log an error message. This at least allows some delivery to
# the app and the app can deal with the missing decoded representation.
#
# Usually btw this problem is caused by apps sending binary data but setting the payload type to
# text.
try:
asBytes = asDict[&#34;decoded&#34;][&#34;payload&#34;]
asDict[&#34;decoded&#34;][&#34;text&#34;] = asBytes.decode(&#34;utf-8&#34;)
except Exception as ex:
logging.error(f&#34;Malformatted utf8 in text message: {ex}&#34;)
_receiveInfoUpdate(iface, asDict)
def _onPositionReceive(iface, asDict):
&#34;&#34;&#34;Special auto parsing for received messages&#34;&#34;&#34;
p = asDict[&#34;decoded&#34;][&#34;position&#34;]
iface._fixupPosition(p)
# update node DB as needed
iface._getOrCreateByNum(asDict[&#34;from&#34;])[&#34;position&#34;] = p
def _onNodeInfoReceive(iface, asDict):
&#34;&#34;&#34;Special auto parsing for received messages&#34;&#34;&#34;
p = asDict[&#34;decoded&#34;][&#34;user&#34;]
# decode user protobufs and update nodedb, provide decoded version as &#34;position&#34; in the published msg
# update node DB as needed
n = iface._getOrCreateByNum(asDict[&#34;from&#34;])
n[&#34;user&#34;] = p
# We now have a node ID, make sure it is uptodate in that table
iface.nodes[p[&#34;id&#34;]] = n
_receiveInfoUpdate(iface, asDict)
def _receiveInfoUpdate(iface, asDict):
iface._getOrCreateByNum(asDict[&#34;from&#34;])[&#34;lastReceived&#34;] = asDict
iface._getOrCreateByNum(asDict[&#34;from&#34;])[&#34;lastHeard&#34;] = asDict.get(&#34;rxTime&#34;)
iface._getOrCreateByNum(asDict[&#34;from&#34;])[&#34;snr&#34;] = asDict.get(&#34;rxSnr&#34;)
iface._getOrCreateByNum(asDict[&#34;from&#34;])[&#34;hopLimit&#34;] = asDict.get(&#34;hopLimit&#34;)
&#34;&#34;&#34;Well known message payloads can register decoders for automatic protobuf parsing&#34;&#34;&#34;
protocols = {
portnums_pb2.PortNum.TEXT_MESSAGE_APP: KnownProtocol(&#34;text&#34;, onReceive=_onTextReceive),
portnums_pb2.PortNum.POSITION_APP: KnownProtocol(&#34;position&#34;, mesh_pb2.Position, _onPositionReceive),
portnums_pb2.PortNum.NODEINFO_APP: KnownProtocol(&#34;user&#34;, mesh_pb2.User, _onNodeInfoReceive),
portnums_pb2.PortNum.ADMIN_APP: KnownProtocol(&#34;admin&#34;, admin_pb2.AdminMessage),
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol(&#34;routing&#34;, mesh_pb2.Routing),
portnums_pb2.PortNum.ENVIRONMENTAL_MEASUREMENT_APP: KnownProtocol(&#34;environmental&#34;, environmental_measurement_pb2.EnvironmentalMeasurement),
portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol(
&#34;remotehw&#34;, remote_hardware_pb2.HardwareMessage)
}</code></pre>
</details>
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="meshtastic.admin_pb2" href="admin_pb2.html">meshtastic.admin_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.apponly_pb2" href="apponly_pb2.html">meshtastic.apponly_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.ble" href="ble.html">meshtastic.ble</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.ble_interface" href="ble_interface.html">meshtastic.ble_interface</a></code></dt>
<dd>
<div class="desc"><p>Bluetooth interface</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.channel_pb2" href="channel_pb2.html">meshtastic.channel_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.deviceonly_pb2" href="deviceonly_pb2.html">meshtastic.deviceonly_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.environmental_measurement_pb2" href="environmental_measurement_pb2.html">meshtastic.environmental_measurement_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.globals" href="globals.html">meshtastic.globals</a></code></dt>
<dd>
<div class="desc"><p>Globals singleton class …</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.mesh_interface" href="mesh_interface.html">meshtastic.mesh_interface</a></code></dt>
<dd>
<div class="desc"><p>Mesh Interface class</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.mesh_pb2" href="mesh_pb2.html">meshtastic.mesh_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.mqtt_pb2" href="mqtt_pb2.html">meshtastic.mqtt_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.node" href="node.html">meshtastic.node</a></code></dt>
<dd>
<div class="desc"><p>Node class</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.portnums_pb2" href="portnums_pb2.html">meshtastic.portnums_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.radioconfig_pb2" href="radioconfig_pb2.html">meshtastic.radioconfig_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.remote_hardware" href="remote_hardware.html">meshtastic.remote_hardware</a></code></dt>
<dd>
<div class="desc"><p>Remote hardware</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.remote_hardware_pb2" href="remote_hardware_pb2.html">meshtastic.remote_hardware_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.serial_interface" href="serial_interface.html">meshtastic.serial_interface</a></code></dt>
<dd>
<div class="desc"><p>Serial interface class</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.storeforward_pb2" href="storeforward_pb2.html">meshtastic.storeforward_pb2</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.stream_interface" href="stream_interface.html">meshtastic.stream_interface</a></code></dt>
<dd>
<div class="desc"><p>Stream Interface base class</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tcp_interface" href="tcp_interface.html">meshtastic.tcp_interface</a></code></dt>
<dd>
<div class="desc"><p>TCPInterface class for interfacing with http endpoint</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.test" href="test.html">meshtastic.test</a></code></dt>
<dd>
<div class="desc"><p>With two radios connected serially, send and receive test
messages and report back if successful.</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests" href="tests/index.html">meshtastic.tests</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="meshtastic.tunnel" href="tunnel.html">meshtastic.tunnel</a></code></dt>
<dd>
<div class="desc"><p>Code for IP tunnel over a mesh …</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.util" href="util.html">meshtastic.util</a></code></dt>
<dd>
<div class="desc"><p>Utility functions.</p></div>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-variables">Global variables</h2>
<dl>
<dt id="meshtastic.BROADCAST_ADDR"><code class="name">var <span class="ident">BROADCAST_ADDR</span></code></dt>
<dd>
<div class="desc"><p>The numeric buildnumber (shared with android apps) specifying the
level of device code we are guaranteed to understand</p>
<p>format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20</p></div>
</dd>
<dt id="meshtastic.BROADCAST_NUM"><code class="name">var <span class="ident">BROADCAST_NUM</span></code></dt>
<dd>
<div class="desc"><p>A special ID that means broadcast</p></div>
</dd>
</dl>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.KnownProtocol"><code class="flex name class">
<span>class <span class="ident">KnownProtocol</span></span>
<span>(</span><span>name: str, protobufFactory: Callable = None, onReceive: Callable = None)</span>
</code></dt>
<dd>
<div class="desc"><p>Used to automatically decode known protocol payloads</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class KnownProtocol(NamedTuple):
&#34;&#34;&#34;Used to automatically decode known protocol payloads&#34;&#34;&#34;
name: str
# portnum: int, now a key
# If set, will be called to prase as a protocol buffer
protobufFactory: Callable = None
# If set, invoked as onReceive(interface, packet)
onReceive: Callable = None</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li>builtins.tuple</li>
</ul>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.KnownProtocol.name"><code class="name">var <span class="ident">name</span> : str</code></dt>
<dd>
<div class="desc"><p>Alias for field number 0</p></div>
</dd>
<dt id="meshtastic.KnownProtocol.onReceive"><code class="name">var <span class="ident">onReceive</span> : Callable</code></dt>
<dd>
<div class="desc"><p>Alias for field number 2</p></div>
</dd>
<dt id="meshtastic.KnownProtocol.protobufFactory"><code class="name">var <span class="ident">protobufFactory</span> : Callable</code></dt>
<dd>
<div class="desc"><p>Alias for field number 1</p></div>
</dd>
</dl>
</dd>
<dt id="meshtastic.ResponseHandler"><code class="flex name class">
<span>class <span class="ident">ResponseHandler</span></span>
<span>(</span><span>callback: Callable)</span>
</code></dt>
<dd>
<div class="desc"><p>A pending response callback, waiting for a response to one of our messages</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class ResponseHandler(NamedTuple):
&#34;&#34;&#34;A pending response callback, waiting for a response to one of our messages&#34;&#34;&#34;
# requestId: int - used only as a key
callback: Callable
# FIXME, add timestamp and age out old requests</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li>builtins.tuple</li>
</ul>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.ResponseHandler.callback"><code class="name">var <span class="ident">callback</span> : Callable</code></dt>
<dd>
<div class="desc"><p>Alias for field number 0</p></div>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul>
<li><a href="#an-api-for-meshtastic-devices">an API for Meshtastic devices</a></li>
<li><a href="#published-pubsub-topics">Published PubSub topics</a></li>
<li><a href="#example-usage">Example Usage</a></li>
</ul>
</div>
<ul id="index">
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="meshtastic.admin_pb2" href="admin_pb2.html">meshtastic.admin_pb2</a></code></li>
<li><code><a title="meshtastic.apponly_pb2" href="apponly_pb2.html">meshtastic.apponly_pb2</a></code></li>
<li><code><a title="meshtastic.ble" href="ble.html">meshtastic.ble</a></code></li>
<li><code><a title="meshtastic.ble_interface" href="ble_interface.html">meshtastic.ble_interface</a></code></li>
<li><code><a title="meshtastic.channel_pb2" href="channel_pb2.html">meshtastic.channel_pb2</a></code></li>
<li><code><a title="meshtastic.deviceonly_pb2" href="deviceonly_pb2.html">meshtastic.deviceonly_pb2</a></code></li>
<li><code><a title="meshtastic.environmental_measurement_pb2" href="environmental_measurement_pb2.html">meshtastic.environmental_measurement_pb2</a></code></li>
<li><code><a title="meshtastic.globals" href="globals.html">meshtastic.globals</a></code></li>
<li><code><a title="meshtastic.mesh_interface" href="mesh_interface.html">meshtastic.mesh_interface</a></code></li>
<li><code><a title="meshtastic.mesh_pb2" href="mesh_pb2.html">meshtastic.mesh_pb2</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2" href="mqtt_pb2.html">meshtastic.mqtt_pb2</a></code></li>
<li><code><a title="meshtastic.node" href="node.html">meshtastic.node</a></code></li>
<li><code><a title="meshtastic.portnums_pb2" href="portnums_pb2.html">meshtastic.portnums_pb2</a></code></li>
<li><code><a title="meshtastic.radioconfig_pb2" href="radioconfig_pb2.html">meshtastic.radioconfig_pb2</a></code></li>
<li><code><a title="meshtastic.remote_hardware" href="remote_hardware.html">meshtastic.remote_hardware</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2" href="remote_hardware_pb2.html">meshtastic.remote_hardware_pb2</a></code></li>
<li><code><a title="meshtastic.serial_interface" href="serial_interface.html">meshtastic.serial_interface</a></code></li>
<li><code><a title="meshtastic.storeforward_pb2" href="storeforward_pb2.html">meshtastic.storeforward_pb2</a></code></li>
<li><code><a title="meshtastic.stream_interface" href="stream_interface.html">meshtastic.stream_interface</a></code></li>
<li><code><a title="meshtastic.tcp_interface" href="tcp_interface.html">meshtastic.tcp_interface</a></code></li>
<li><code><a title="meshtastic.test" href="test.html">meshtastic.test</a></code></li>
<li><code><a title="meshtastic.tests" href="tests/index.html">meshtastic.tests</a></code></li>
<li><code><a title="meshtastic.tunnel" href="tunnel.html">meshtastic.tunnel</a></code></li>
<li><code><a title="meshtastic.util" href="util.html">meshtastic.util</a></code></li>
</ul>
</li>
<li><h3><a href="#header-variables">Global variables</a></h3>
<ul class="">
<li><code><a title="meshtastic.BROADCAST_ADDR" href="#meshtastic.BROADCAST_ADDR">BROADCAST_ADDR</a></code></li>
<li><code><a title="meshtastic.BROADCAST_NUM" href="#meshtastic.BROADCAST_NUM">BROADCAST_NUM</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.KnownProtocol" href="#meshtastic.KnownProtocol">KnownProtocol</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.KnownProtocol.name" href="#meshtastic.KnownProtocol.name">name</a></code></li>
<li><code><a title="meshtastic.KnownProtocol.onReceive" href="#meshtastic.KnownProtocol.onReceive">onReceive</a></code></li>
<li><code><a title="meshtastic.KnownProtocol.protobufFactory" href="#meshtastic.KnownProtocol.protobufFactory">protobufFactory</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="meshtastic.ResponseHandler" href="#meshtastic.ResponseHandler">ResponseHandler</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.ResponseHandler.callback" href="#meshtastic.ResponseHandler.callback">callback</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,759 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.mqtt_pb2 API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.mqtt_pb2</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"># -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: mqtt.proto
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from . import mesh_pb2 as mesh__pb2
DESCRIPTOR = _descriptor.FileDescriptor(
name=&#39;mqtt.proto&#39;,
package=&#39;&#39;,
syntax=&#39;proto3&#39;,
serialized_options=b&#39;\n\023com.geeksville.meshB\nMQTTProtosH\003Z!github.com/meshtastic/gomeshproto&#39;,
serialized_pb=b&#39;\n\nmqtt.proto\x1a\nmesh.proto\&#34;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&#39;
,
dependencies=[mesh__pb2.DESCRIPTOR,])
_SERVICEENVELOPE = _descriptor.Descriptor(
name=&#39;ServiceEnvelope&#39;,
full_name=&#39;ServiceEnvelope&#39;,
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name=&#39;packet&#39;, full_name=&#39;ServiceEnvelope.packet&#39;, index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name=&#39;channel_id&#39;, full_name=&#39;ServiceEnvelope.channel_id&#39;, index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b&#34;&#34;.decode(&#39;utf-8&#39;),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name=&#39;gateway_id&#39;, full_name=&#39;ServiceEnvelope.gateway_id&#39;, index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b&#34;&#34;.decode(&#39;utf-8&#39;),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax=&#39;proto3&#39;,
extension_ranges=[],
oneofs=[
],
serialized_start=26,
serialized_end=112,
)
_SERVICEENVELOPE.fields_by_name[&#39;packet&#39;].message_type = mesh__pb2._MESHPACKET
DESCRIPTOR.message_types_by_name[&#39;ServiceEnvelope&#39;] = _SERVICEENVELOPE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
ServiceEnvelope = _reflection.GeneratedProtocolMessageType(&#39;ServiceEnvelope&#39;, (_message.Message,), {
&#39;DESCRIPTOR&#39; : _SERVICEENVELOPE,
&#39;__module__&#39; : &#39;mqtt_pb2&#39;
# @@protoc_insertion_point(class_scope:ServiceEnvelope)
})
_sym_db.RegisterMessage(ServiceEnvelope)
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope"><code class="flex name class">
<span>class <span class="ident">ServiceEnvelope</span></span>
<span>(</span><span>**kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Abstract base class for protocol messages.</p>
<p>Protocol message classes are almost always generated by the protocol
compiler.
These generated types subclass Message and implement the methods
shown below.</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.CHANNEL_ID_FIELD_NUMBER"><code class="name">var <span class="ident">CHANNEL_ID_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.GATEWAY_ID_FIELD_NUMBER"><code class="name">var <span class="ident">GATEWAY_ID_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.PACKET_FIELD_NUMBER"><code class="name">var <span class="ident">PACKET_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Static methods</h3>
<dl>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.FromString"><code class="name flex">
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FromString(s):
message = cls()
message.MergeFromString(s)
return message</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.RegisterExtension"><code class="name flex">
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def RegisterExtension(extension_handle):
extension_handle.containing_type = cls.DESCRIPTOR
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
# pylint: disable=protected-access
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
_AttachFieldHelpers(cls, extension_handle)</code></pre>
</details>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.channel_id"><code class="name">var <span class="ident">channel_id</span></code></dt>
<dd>
<div class="desc"><p>Getter for channel_id.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.gateway_id"><code class="name">var <span class="ident">gateway_id</span></code></dt>
<dd>
<div class="desc"><p>Getter for gateway_id.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.packet"><code class="name">var <span class="ident">packet</span></code></dt>
<dd>
<div class="desc"><p>Getter for packet.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
# take that object and discard ours.
# WARNING: We are relying on setdefault() being atomic. This is true
# in CPython but we haven&#39;t investigated others. This warning appears
# in several other locations in this file.
field_value = self._fields.setdefault(field, field_value)
return field_value</code></pre>
</details>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.ByteSize"><code class="name flex">
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ByteSize(self):
if not self._cached_byte_size_dirty:
return self._cached_byte_size
size = 0
descriptor = self.DESCRIPTOR
if descriptor.GetOptions().map_entry:
# Fields of map entry should always be serialized.
size = descriptor.fields_by_name[&#39;key&#39;]._sizer(self.key)
size += descriptor.fields_by_name[&#39;value&#39;]._sizer(self.value)
else:
for field_descriptor, field_value in self.ListFields():
size += field_descriptor._sizer(field_value)
for tag_bytes, value_bytes in self._unknown_fields:
size += len(tag_bytes) + len(value_bytes)
self._cached_byte_size = size
self._cached_byte_size_dirty = False
self._listener_for_children.dirty = False
return size</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.Clear"><code class="name flex">
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _Clear(self):
# Clear fields.
self._fields = {}
self._unknown_fields = ()
# pylint: disable=protected-access
if self._unknown_field_set is not None:
self._unknown_field_set._clear()
self._unknown_field_set = None
self._oneofs = {}
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.ClearField"><code class="name flex">
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ClearField(self, field_name):
try:
field = message_descriptor.fields_by_name[field_name]
except KeyError:
try:
field = message_descriptor.oneofs_by_name[field_name]
if field in self._oneofs:
field = self._oneofs[field]
else:
return
except KeyError:
raise ValueError(&#39;Protocol message %s has no &#34;%s&#34; field.&#39; %
(message_descriptor.name, field_name))
if field in self._fields:
# To match the C++ implementation, we need to invalidate iterators
# for map fields when ClearField() happens.
if hasattr(self._fields[field], &#39;InvalidateIterators&#39;):
self._fields[field].InvalidateIterators()
# Note: If the field is a sub-message, its listener will still point
# at us. That&#39;s fine, because the worst than can happen is that it
# will call _Modified() and invalidate our byte size. Big deal.
del self._fields[field]
if self._oneofs.get(field.containing_oneof, None) is field:
del self._oneofs[field.containing_oneof]
# Always call _Modified() -- even if nothing was changed, this is
# a mutating method, and thus calling it should cause the field to become
# present in the parent message.
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.DiscardUnknownFields"><code class="name flex">
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _DiscardUnknownFields(self):
self._unknown_fields = []
self._unknown_field_set = None # pylint: disable=protected-access
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
value[key].DiscardUnknownFields()
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for sub_message in value:
sub_message.DiscardUnknownFields()
else:
value.DiscardUnknownFields()</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.FindInitializationErrors"><code class="name flex">
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Finds required fields which are not initialized.</p>
<h2 id="returns">Returns</h2>
<p>A list of strings.
Each string is a path to an uninitialized field from
the top-level message, e.g. "foo.bar[5].baz".</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FindInitializationErrors(self):
&#34;&#34;&#34;Finds required fields which are not initialized.
Returns:
A list of strings. Each string is a path to an uninitialized field from
the top-level message, e.g. &#34;foo.bar[5].baz&#34;.
&#34;&#34;&#34;
errors = [] # simplify things
for field in required_fields:
if not self.HasField(field.name):
errors.append(field.name)
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.is_extension:
name = &#39;(%s)&#39; % field.full_name
else:
name = field.name
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
element = value[key]
prefix = &#39;%s[%s].&#39; % (name, key)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
# ScalarMaps can&#39;t have any initialization errors.
pass
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for i in range(len(value)):
element = value[i]
prefix = &#39;%s[%d].&#39; % (name, i)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
prefix = name + &#39;.&#39;
sub_errors = value.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
return errors</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.HasField"><code class="name flex">
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def HasField(self, field_name):
try:
field = hassable_fields[field_name]
except KeyError:
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
if isinstance(field, descriptor_mod.OneofDescriptor):
try:
return HasField(self, self._oneofs[field].name)
except KeyError:
return False
else:
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
value = self._fields.get(field)
return value is not None and value._is_present_in_parent
else:
return field in self._fields</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.IsInitialized"><code class="name flex">
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
</code></dt>
<dd>
<div class="desc"><p>Checks if all required fields of a message are set.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>errors</code></strong></dt>
<dd>A list which, if provided, will be populated with the field
paths of all missing required fields.</dd>
</dl>
<h2 id="returns">Returns</h2>
<p>True iff the specified message has all required fields set.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def IsInitialized(self, errors=None):
&#34;&#34;&#34;Checks if all required fields of a message are set.
Args:
errors: A list which, if provided, will be populated with the field
paths of all missing required fields.
Returns:
True iff the specified message has all required fields set.
&#34;&#34;&#34;
# Performance is critical so we avoid HasField() and ListFields().
for field in required_fields:
if (field not in self._fields or
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
not self._fields[field]._is_present_in_parent)):
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
for field, value in list(self._fields.items()): # dict can change size!
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.label == _FieldDescriptor.LABEL_REPEATED:
if (field.message_type.has_options and
field.message_type.GetOptions().map_entry):
continue
for element in value:
if not element.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
elif value._is_present_in_parent and not value.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
return True</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.ListFields"><code class="name flex">
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ListFields(self):
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
all_fields.sort(key = lambda item: item[0].number)
return all_fields</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.MergeFrom"><code class="name flex">
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFrom(self, msg):
if not isinstance(msg, cls):
raise TypeError(
&#39;Parameter to MergeFrom() must be instance of same class: &#39;
&#39;expected %s got %s.&#39; % (_FullyQualifiedClassName(cls),
_FullyQualifiedClassName(msg.__class__)))
assert msg is not self
self._Modified()
fields = self._fields
for field, value in msg._fields.items():
if field.label == LABEL_REPEATED:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
elif field.cpp_type == CPPTYPE_MESSAGE:
if value._is_present_in_parent:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
else:
self._fields[field] = value
if field.containing_oneof:
self._UpdateOneofState(field)
if msg._unknown_fields:
if not self._unknown_fields:
self._unknown_fields = []
self._unknown_fields.extend(msg._unknown_fields)
# pylint: disable=protected-access
if self._unknown_field_set is None:
self._unknown_field_set = containers.UnknownFieldSet()
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.MergeFromString"><code class="name flex">
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFromString(self, serialized):
serialized = memoryview(serialized)
length = len(serialized)
try:
if self._InternalParse(serialized, 0, length) != length:
# The only reason _InternalParse would return early is if it
# encountered an end-group tag.
raise message_mod.DecodeError(&#39;Unexpected end-group tag.&#39;)
except (IndexError, TypeError):
# Now ord(buf[p:p+1]) == ord(&#39;&#39;) gets TypeError.
raise message_mod.DecodeError(&#39;Truncated message.&#39;)
except struct.error as e:
raise message_mod.DecodeError(e)
return length # Return this for legacy reasons.</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.SerializePartialToString"><code class="name flex">
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializePartialToString(self, **kwargs):
out = BytesIO()
self._InternalSerialize(out.write, **kwargs)
return out.getvalue()</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.SerializeToString"><code class="name flex">
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializeToString(self, **kwargs):
# Check if the message has all of its required fields set.
if not self.IsInitialized():
raise message_mod.EncodeError(
&#39;Message %s is missing required fields: %s&#39; % (
self.DESCRIPTOR.full_name, &#39;,&#39;.join(self.FindInitializationErrors())))
return self.SerializePartialToString(**kwargs)</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.SetInParent"><code class="name flex">
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def Modified(self):
&#34;&#34;&#34;Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.
&#34;&#34;&#34;
# Note: Some callers check _cached_byte_size_dirty before calling
# _Modified() as an extra optimization. So, if this method is ever
# changed such that it does stuff even when _cached_byte_size_dirty is
# already true, the callers need to be updated.
if not self._cached_byte_size_dirty:
self._cached_byte_size_dirty = True
self._listener_for_children.dirty = True
self._is_present_in_parent = True
self._listener.Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.UnknownFields"><code class="name flex">
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _UnknownFields(self):
if self._unknown_field_set is None: # pylint: disable=protected-access
# pylint: disable=protected-access
self._unknown_field_set = containers.UnknownFieldSet()
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
</details>
</dd>
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.WhichOneof"><code class="name flex">
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
</code></dt>
<dd>
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def WhichOneof(self, oneof_name):
&#34;&#34;&#34;Returns the name of the currently set field inside a oneof, or None.&#34;&#34;&#34;
try:
field = message_descriptor.oneofs_by_name[oneof_name]
except KeyError:
raise ValueError(
&#39;Protocol message has no oneof &#34;%s&#34; field.&#39; % oneof_name)
nested_field = self._oneofs.get(field, None)
if nested_field is not None and self.HasField(nested_field.name):
return nested_field.name
else:
return None</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope" href="#meshtastic.mqtt_pb2.ServiceEnvelope">ServiceEnvelope</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.ByteSize" href="#meshtastic.mqtt_pb2.ServiceEnvelope.ByteSize">ByteSize</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.CHANNEL_ID_FIELD_NUMBER" href="#meshtastic.mqtt_pb2.ServiceEnvelope.CHANNEL_ID_FIELD_NUMBER">CHANNEL_ID_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.Clear" href="#meshtastic.mqtt_pb2.ServiceEnvelope.Clear">Clear</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.ClearField" href="#meshtastic.mqtt_pb2.ServiceEnvelope.ClearField">ClearField</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.DESCRIPTOR" href="#meshtastic.mqtt_pb2.ServiceEnvelope.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.DiscardUnknownFields" href="#meshtastic.mqtt_pb2.ServiceEnvelope.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.FindInitializationErrors" href="#meshtastic.mqtt_pb2.ServiceEnvelope.FindInitializationErrors">FindInitializationErrors</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.FromString" href="#meshtastic.mqtt_pb2.ServiceEnvelope.FromString">FromString</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.GATEWAY_ID_FIELD_NUMBER" href="#meshtastic.mqtt_pb2.ServiceEnvelope.GATEWAY_ID_FIELD_NUMBER">GATEWAY_ID_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.HasField" href="#meshtastic.mqtt_pb2.ServiceEnvelope.HasField">HasField</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.IsInitialized" href="#meshtastic.mqtt_pb2.ServiceEnvelope.IsInitialized">IsInitialized</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.ListFields" href="#meshtastic.mqtt_pb2.ServiceEnvelope.ListFields">ListFields</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.MergeFrom" href="#meshtastic.mqtt_pb2.ServiceEnvelope.MergeFrom">MergeFrom</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.MergeFromString" href="#meshtastic.mqtt_pb2.ServiceEnvelope.MergeFromString">MergeFromString</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.PACKET_FIELD_NUMBER" href="#meshtastic.mqtt_pb2.ServiceEnvelope.PACKET_FIELD_NUMBER">PACKET_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.RegisterExtension" href="#meshtastic.mqtt_pb2.ServiceEnvelope.RegisterExtension">RegisterExtension</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.SerializePartialToString" href="#meshtastic.mqtt_pb2.ServiceEnvelope.SerializePartialToString">SerializePartialToString</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.SerializeToString" href="#meshtastic.mqtt_pb2.ServiceEnvelope.SerializeToString">SerializeToString</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.SetInParent" href="#meshtastic.mqtt_pb2.ServiceEnvelope.SetInParent">SetInParent</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.UnknownFields" href="#meshtastic.mqtt_pb2.ServiceEnvelope.UnknownFields">UnknownFields</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.WhichOneof" href="#meshtastic.mqtt_pb2.ServiceEnvelope.WhichOneof">WhichOneof</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.channel_id" href="#meshtastic.mqtt_pb2.ServiceEnvelope.channel_id">channel_id</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.gateway_id" href="#meshtastic.mqtt_pb2.ServiceEnvelope.gateway_id">gateway_id</a></code></li>
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.packet" href="#meshtastic.mqtt_pb2.ServiceEnvelope.packet">packet</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,190 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.portnums_pb2 API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.portnums_pb2</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"># -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: portnums.proto
from google.protobuf.internal import enum_type_wrapper
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name=&#39;portnums.proto&#39;,
package=&#39;&#39;,
syntax=&#39;proto3&#39;,
serialized_options=b&#39;\n\023com.geeksville.meshB\010PortnumsH\003Z!github.com/meshtastic/gomeshproto&#39;,
serialized_pb=b&#39;\n\x0eportnums.proto*\xcb\x02\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12!\n\x1d\x45NVIRONMENTAL_MEASUREMENT_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42\x44\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3&#39;
)
_PORTNUM = _descriptor.EnumDescriptor(
name=&#39;PortNum&#39;,
full_name=&#39;PortNum&#39;,
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name=&#39;UNKNOWN_APP&#39;, index=0, number=0,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;TEXT_MESSAGE_APP&#39;, index=1, number=1,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;REMOTE_HARDWARE_APP&#39;, index=2, number=2,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;POSITION_APP&#39;, index=3, number=3,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;NODEINFO_APP&#39;, index=4, number=4,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;ROUTING_APP&#39;, index=5, number=5,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;ADMIN_APP&#39;, index=6, number=6,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;REPLY_APP&#39;, index=7, number=32,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;IP_TUNNEL_APP&#39;, index=8, number=33,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;SERIAL_APP&#39;, index=9, number=64,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;STORE_FORWARD_APP&#39;, index=10, number=65,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;RANGE_TEST_APP&#39;, index=11, number=66,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;ENVIRONMENTAL_MEASUREMENT_APP&#39;, index=12, number=67,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;ZPS_APP&#39;, index=13, number=68,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;PRIVATE_APP&#39;, index=14, number=256,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;ATAK_FORWARDER&#39;, index=15, number=257,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;MAX&#39;, index=16, number=511,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=19,
serialized_end=350,
)
_sym_db.RegisterEnumDescriptor(_PORTNUM)
PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM)
UNKNOWN_APP = 0
TEXT_MESSAGE_APP = 1
REMOTE_HARDWARE_APP = 2
POSITION_APP = 3
NODEINFO_APP = 4
ROUTING_APP = 5
ADMIN_APP = 6
REPLY_APP = 32
IP_TUNNEL_APP = 33
SERIAL_APP = 64
STORE_FORWARD_APP = 65
RANGE_TEST_APP = 66
ENVIRONMENTAL_MEASUREMENT_APP = 67
ZPS_APP = 68
PRIVATE_APP = 256
ATAK_FORWARDER = 257
MAX = 511
DESCRIPTOR.enum_types_by_name[&#39;PortNum&#39;] = _PORTNUM
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,301 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.remote_hardware API documentation</title>
<meta name="description" content="Remote hardware" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.remote_hardware</code></h1>
</header>
<section id="section-intro">
<p>Remote hardware</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34; Remote hardware
&#34;&#34;&#34;
from pubsub import pub
from . import portnums_pb2, remote_hardware_pb2
def onGPIOreceive(packet, interface):
&#34;&#34;&#34;Callback for received GPIO responses
FIXME figure out how to do closures with methods in python&#34;&#34;&#34;
hw = packet[&#34;decoded&#34;][&#34;remotehw&#34;]
print(f&#39;Received RemoteHardware typ={hw[&#34;typ&#34;]}, gpio_value={hw[&#34;gpioValue&#34;]}&#39;)
class RemoteHardwareClient:
&#34;&#34;&#34;
This is the client code to control/monitor simple hardware built into the
meshtastic devices. It is intended to be both a useful API/service and example
code for how you can connect to your own custom meshtastic services
&#34;&#34;&#34;
def __init__(self, iface):
&#34;&#34;&#34;
Constructor
iface is the already open MeshInterface instance
&#34;&#34;&#34;
self.iface = iface
ch = iface.localNode.getChannelByName(&#34;gpio&#34;)
if not ch:
raise Exception(
&#34;No gpio channel found, please create on the sending and receive nodes &#34;\
&#34;to use this (secured) service (--ch-add gpio --info then --seturl)&#34;)
self.channelIndex = ch.index
pub.subscribe(
onGPIOreceive, &#34;meshtastic.receive.remotehw&#34;)
def _sendHardware(self, nodeid, r, wantResponse=False, onResponse=None):
if not nodeid:
raise Exception(
r&#34;You must set a destination node ID for this operation (use --dest \!xxxxxxxxx)&#34;)
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP,
wantAck=True, channelIndex=self.channelIndex, wantResponse=wantResponse, onResponse=onResponse)
def writeGPIOs(self, nodeid, mask, vals):
&#34;&#34;&#34;
Write the specified vals bits to the device GPIOs. Only bits in mask that
are 1 will be changed
&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
r.gpio_mask = mask
r.gpio_value = vals
return self._sendHardware(nodeid, r)
def readGPIOs(self, nodeid, mask, onResponse = None):
&#34;&#34;&#34;Read the specified bits from GPIO inputs on the device&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
r.gpio_mask = mask
return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)
def watchGPIOs(self, nodeid, mask):
&#34;&#34;&#34;Watch the specified bits from GPIO inputs on the device for changes&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
r.gpio_mask = mask
return self._sendHardware(nodeid, r)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.remote_hardware.onGPIOreceive"><code class="name flex">
<span>def <span class="ident">onGPIOreceive</span></span>(<span>packet, interface)</span>
</code></dt>
<dd>
<div class="desc"><p>Callback for received GPIO responses</p>
<p>FIXME figure out how to do closures with methods in python</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def onGPIOreceive(packet, interface):
&#34;&#34;&#34;Callback for received GPIO responses
FIXME figure out how to do closures with methods in python&#34;&#34;&#34;
hw = packet[&#34;decoded&#34;][&#34;remotehw&#34;]
print(f&#39;Received RemoteHardware typ={hw[&#34;typ&#34;]}, gpio_value={hw[&#34;gpioValue&#34;]}&#39;)</code></pre>
</details>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.remote_hardware.RemoteHardwareClient"><code class="flex name class">
<span>class <span class="ident">RemoteHardwareClient</span></span>
<span>(</span><span>iface)</span>
</code></dt>
<dd>
<div class="desc"><p>This is the client code to control/monitor simple hardware built into the
meshtastic devices.
It is intended to be both a useful API/service and example
code for how you can connect to your own custom meshtastic services</p>
<p>Constructor</p>
<p>iface is the already open MeshInterface instance</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class RemoteHardwareClient:
&#34;&#34;&#34;
This is the client code to control/monitor simple hardware built into the
meshtastic devices. It is intended to be both a useful API/service and example
code for how you can connect to your own custom meshtastic services
&#34;&#34;&#34;
def __init__(self, iface):
&#34;&#34;&#34;
Constructor
iface is the already open MeshInterface instance
&#34;&#34;&#34;
self.iface = iface
ch = iface.localNode.getChannelByName(&#34;gpio&#34;)
if not ch:
raise Exception(
&#34;No gpio channel found, please create on the sending and receive nodes &#34;\
&#34;to use this (secured) service (--ch-add gpio --info then --seturl)&#34;)
self.channelIndex = ch.index
pub.subscribe(
onGPIOreceive, &#34;meshtastic.receive.remotehw&#34;)
def _sendHardware(self, nodeid, r, wantResponse=False, onResponse=None):
if not nodeid:
raise Exception(
r&#34;You must set a destination node ID for this operation (use --dest \!xxxxxxxxx)&#34;)
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP,
wantAck=True, channelIndex=self.channelIndex, wantResponse=wantResponse, onResponse=onResponse)
def writeGPIOs(self, nodeid, mask, vals):
&#34;&#34;&#34;
Write the specified vals bits to the device GPIOs. Only bits in mask that
are 1 will be changed
&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
r.gpio_mask = mask
r.gpio_value = vals
return self._sendHardware(nodeid, r)
def readGPIOs(self, nodeid, mask, onResponse = None):
&#34;&#34;&#34;Read the specified bits from GPIO inputs on the device&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
r.gpio_mask = mask
return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)
def watchGPIOs(self, nodeid, mask):
&#34;&#34;&#34;Watch the specified bits from GPIO inputs on the device for changes&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
r.gpio_mask = mask
return self._sendHardware(nodeid, r)</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.remote_hardware.RemoteHardwareClient.readGPIOs"><code class="name flex">
<span>def <span class="ident">readGPIOs</span></span>(<span>self, nodeid, mask, onResponse=None)</span>
</code></dt>
<dd>
<div class="desc"><p>Read the specified bits from GPIO inputs on the device</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def readGPIOs(self, nodeid, mask, onResponse = None):
&#34;&#34;&#34;Read the specified bits from GPIO inputs on the device&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
r.gpio_mask = mask
return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware.RemoteHardwareClient.watchGPIOs"><code class="name flex">
<span>def <span class="ident">watchGPIOs</span></span>(<span>self, nodeid, mask)</span>
</code></dt>
<dd>
<div class="desc"><p>Watch the specified bits from GPIO inputs on the device for changes</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def watchGPIOs(self, nodeid, mask):
&#34;&#34;&#34;Watch the specified bits from GPIO inputs on the device for changes&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
r.gpio_mask = mask
return self._sendHardware(nodeid, r)</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware.RemoteHardwareClient.writeGPIOs"><code class="name flex">
<span>def <span class="ident">writeGPIOs</span></span>(<span>self, nodeid, mask, vals)</span>
</code></dt>
<dd>
<div class="desc"><p>Write the specified vals bits to the device GPIOs.
Only bits in mask that
are 1 will be changed</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def writeGPIOs(self, nodeid, mask, vals):
&#34;&#34;&#34;
Write the specified vals bits to the device GPIOs. Only bits in mask that
are 1 will be changed
&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
r.gpio_mask = mask
r.gpio_value = vals
return self._sendHardware(nodeid, r)</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.remote_hardware.onGPIOreceive" href="#meshtastic.remote_hardware.onGPIOreceive">onGPIOreceive</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.remote_hardware.RemoteHardwareClient" href="#meshtastic.remote_hardware.RemoteHardwareClient">RemoteHardwareClient</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.remote_hardware.RemoteHardwareClient.readGPIOs" href="#meshtastic.remote_hardware.RemoteHardwareClient.readGPIOs">readGPIOs</a></code></li>
<li><code><a title="meshtastic.remote_hardware.RemoteHardwareClient.watchGPIOs" href="#meshtastic.remote_hardware.RemoteHardwareClient.watchGPIOs">watchGPIOs</a></code></li>
<li><code><a title="meshtastic.remote_hardware.RemoteHardwareClient.writeGPIOs" href="#meshtastic.remote_hardware.RemoteHardwareClient.writeGPIOs">writeGPIOs</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,822 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.remote_hardware_pb2 API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.remote_hardware_pb2</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"># -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: remote_hardware.proto
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name=&#39;remote_hardware.proto&#39;,
package=&#39;&#39;,
syntax=&#39;proto3&#39;,
serialized_options=b&#39;\n\023com.geeksville.meshB\016RemoteHardwareH\003Z!github.com/meshtastic/gomeshproto&#39;,
serialized_pb=b&#39;\n\x15remote_hardware.proto\&#34;\xca\x01\n\x0fHardwareMessage\x12\&#34;\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\&#34;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&#39;
)
_HARDWAREMESSAGE_TYPE = _descriptor.EnumDescriptor(
name=&#39;Type&#39;,
full_name=&#39;HardwareMessage.Type&#39;,
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name=&#39;UNSET&#39;, index=0, number=0,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;WRITE_GPIOS&#39;, index=1, number=1,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;WATCH_GPIOS&#39;, index=2, number=2,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;GPIOS_CHANGED&#39;, index=3, number=3,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;READ_GPIOS&#39;, index=4, number=4,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name=&#39;READ_GPIOS_REPLY&#39;, index=5, number=5,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=120,
serialized_end=228,
)
_sym_db.RegisterEnumDescriptor(_HARDWAREMESSAGE_TYPE)
_HARDWAREMESSAGE = _descriptor.Descriptor(
name=&#39;HardwareMessage&#39;,
full_name=&#39;HardwareMessage&#39;,
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name=&#39;typ&#39;, full_name=&#39;HardwareMessage.typ&#39;, index=0,
number=1, type=14, cpp_type=8, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name=&#39;gpio_mask&#39;, full_name=&#39;HardwareMessage.gpio_mask&#39;, index=1,
number=2, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name=&#39;gpio_value&#39;, full_name=&#39;HardwareMessage.gpio_value&#39;, index=2,
number=3, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
_HARDWAREMESSAGE_TYPE,
],
serialized_options=None,
is_extendable=False,
syntax=&#39;proto3&#39;,
extension_ranges=[],
oneofs=[
],
serialized_start=26,
serialized_end=228,
)
_HARDWAREMESSAGE.fields_by_name[&#39;typ&#39;].enum_type = _HARDWAREMESSAGE_TYPE
_HARDWAREMESSAGE_TYPE.containing_type = _HARDWAREMESSAGE
DESCRIPTOR.message_types_by_name[&#39;HardwareMessage&#39;] = _HARDWAREMESSAGE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
HardwareMessage = _reflection.GeneratedProtocolMessageType(&#39;HardwareMessage&#39;, (_message.Message,), {
&#39;DESCRIPTOR&#39; : _HARDWAREMESSAGE,
&#39;__module__&#39; : &#39;remote_hardware_pb2&#39;
# @@protoc_insertion_point(class_scope:HardwareMessage)
})
_sym_db.RegisterMessage(HardwareMessage)
DESCRIPTOR._options = None
# @@protoc_insertion_point(module_scope)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage"><code class="flex name class">
<span>class <span class="ident">HardwareMessage</span></span>
<span>(</span><span>**kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Abstract base class for protocol messages.</p>
<p>Protocol message classes are almost always generated by the protocol
compiler.
These generated types subclass Message and implement the methods
shown below.</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.GPIOS_CHANGED"><code class="name">var <span class="ident">GPIOS_CHANGED</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_MASK_FIELD_NUMBER"><code class="name">var <span class="ident">GPIO_MASK_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_VALUE_FIELD_NUMBER"><code class="name">var <span class="ident">GPIO_VALUE_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS"><code class="name">var <span class="ident">READ_GPIOS</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS_REPLY"><code class="name">var <span class="ident">READ_GPIOS_REPLY</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.TYP_FIELD_NUMBER"><code class="name">var <span class="ident">TYP_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.Type"><code class="name">var <span class="ident">Type</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.UNSET"><code class="name">var <span class="ident">UNSET</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.WATCH_GPIOS"><code class="name">var <span class="ident">WATCH_GPIOS</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.WRITE_GPIOS"><code class="name">var <span class="ident">WRITE_GPIOS</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Static methods</h3>
<dl>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.FromString"><code class="name flex">
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FromString(s):
message = cls()
message.MergeFromString(s)
return message</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.RegisterExtension"><code class="name flex">
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def RegisterExtension(extension_handle):
extension_handle.containing_type = cls.DESCRIPTOR
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
# pylint: disable=protected-access
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
_AttachFieldHelpers(cls, extension_handle)</code></pre>
</details>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.gpio_mask"><code class="name">var <span class="ident">gpio_mask</span></code></dt>
<dd>
<div class="desc"><p>Getter for gpio_mask.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.gpio_value"><code class="name">var <span class="ident">gpio_value</span></code></dt>
<dd>
<div class="desc"><p>Getter for gpio_value.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.typ"><code class="name">var <span class="ident">typ</span></code></dt>
<dd>
<div class="desc"><p>Getter for typ.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.ByteSize"><code class="name flex">
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ByteSize(self):
if not self._cached_byte_size_dirty:
return self._cached_byte_size
size = 0
descriptor = self.DESCRIPTOR
if descriptor.GetOptions().map_entry:
# Fields of map entry should always be serialized.
size = descriptor.fields_by_name[&#39;key&#39;]._sizer(self.key)
size += descriptor.fields_by_name[&#39;value&#39;]._sizer(self.value)
else:
for field_descriptor, field_value in self.ListFields():
size += field_descriptor._sizer(field_value)
for tag_bytes, value_bytes in self._unknown_fields:
size += len(tag_bytes) + len(value_bytes)
self._cached_byte_size = size
self._cached_byte_size_dirty = False
self._listener_for_children.dirty = False
return size</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.Clear"><code class="name flex">
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _Clear(self):
# Clear fields.
self._fields = {}
self._unknown_fields = ()
# pylint: disable=protected-access
if self._unknown_field_set is not None:
self._unknown_field_set._clear()
self._unknown_field_set = None
self._oneofs = {}
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.ClearField"><code class="name flex">
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ClearField(self, field_name):
try:
field = message_descriptor.fields_by_name[field_name]
except KeyError:
try:
field = message_descriptor.oneofs_by_name[field_name]
if field in self._oneofs:
field = self._oneofs[field]
else:
return
except KeyError:
raise ValueError(&#39;Protocol message %s has no &#34;%s&#34; field.&#39; %
(message_descriptor.name, field_name))
if field in self._fields:
# To match the C++ implementation, we need to invalidate iterators
# for map fields when ClearField() happens.
if hasattr(self._fields[field], &#39;InvalidateIterators&#39;):
self._fields[field].InvalidateIterators()
# Note: If the field is a sub-message, its listener will still point
# at us. That&#39;s fine, because the worst than can happen is that it
# will call _Modified() and invalidate our byte size. Big deal.
del self._fields[field]
if self._oneofs.get(field.containing_oneof, None) is field:
del self._oneofs[field.containing_oneof]
# Always call _Modified() -- even if nothing was changed, this is
# a mutating method, and thus calling it should cause the field to become
# present in the parent message.
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.DiscardUnknownFields"><code class="name flex">
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _DiscardUnknownFields(self):
self._unknown_fields = []
self._unknown_field_set = None # pylint: disable=protected-access
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
value[key].DiscardUnknownFields()
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for sub_message in value:
sub_message.DiscardUnknownFields()
else:
value.DiscardUnknownFields()</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.FindInitializationErrors"><code class="name flex">
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Finds required fields which are not initialized.</p>
<h2 id="returns">Returns</h2>
<p>A list of strings.
Each string is a path to an uninitialized field from
the top-level message, e.g. "foo.bar[5].baz".</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FindInitializationErrors(self):
&#34;&#34;&#34;Finds required fields which are not initialized.
Returns:
A list of strings. Each string is a path to an uninitialized field from
the top-level message, e.g. &#34;foo.bar[5].baz&#34;.
&#34;&#34;&#34;
errors = [] # simplify things
for field in required_fields:
if not self.HasField(field.name):
errors.append(field.name)
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.is_extension:
name = &#39;(%s)&#39; % field.full_name
else:
name = field.name
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
element = value[key]
prefix = &#39;%s[%s].&#39; % (name, key)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
# ScalarMaps can&#39;t have any initialization errors.
pass
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for i in range(len(value)):
element = value[i]
prefix = &#39;%s[%d].&#39; % (name, i)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
prefix = name + &#39;.&#39;
sub_errors = value.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
return errors</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.HasField"><code class="name flex">
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def HasField(self, field_name):
try:
field = hassable_fields[field_name]
except KeyError:
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
if isinstance(field, descriptor_mod.OneofDescriptor):
try:
return HasField(self, self._oneofs[field].name)
except KeyError:
return False
else:
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
value = self._fields.get(field)
return value is not None and value._is_present_in_parent
else:
return field in self._fields</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.IsInitialized"><code class="name flex">
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
</code></dt>
<dd>
<div class="desc"><p>Checks if all required fields of a message are set.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>errors</code></strong></dt>
<dd>A list which, if provided, will be populated with the field
paths of all missing required fields.</dd>
</dl>
<h2 id="returns">Returns</h2>
<p>True iff the specified message has all required fields set.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def IsInitialized(self, errors=None):
&#34;&#34;&#34;Checks if all required fields of a message are set.
Args:
errors: A list which, if provided, will be populated with the field
paths of all missing required fields.
Returns:
True iff the specified message has all required fields set.
&#34;&#34;&#34;
# Performance is critical so we avoid HasField() and ListFields().
for field in required_fields:
if (field not in self._fields or
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
not self._fields[field]._is_present_in_parent)):
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
for field, value in list(self._fields.items()): # dict can change size!
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.label == _FieldDescriptor.LABEL_REPEATED:
if (field.message_type.has_options and
field.message_type.GetOptions().map_entry):
continue
for element in value:
if not element.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
elif value._is_present_in_parent and not value.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
return True</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.ListFields"><code class="name flex">
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ListFields(self):
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
all_fields.sort(key = lambda item: item[0].number)
return all_fields</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.MergeFrom"><code class="name flex">
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFrom(self, msg):
if not isinstance(msg, cls):
raise TypeError(
&#39;Parameter to MergeFrom() must be instance of same class: &#39;
&#39;expected %s got %s.&#39; % (_FullyQualifiedClassName(cls),
_FullyQualifiedClassName(msg.__class__)))
assert msg is not self
self._Modified()
fields = self._fields
for field, value in msg._fields.items():
if field.label == LABEL_REPEATED:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
elif field.cpp_type == CPPTYPE_MESSAGE:
if value._is_present_in_parent:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
else:
self._fields[field] = value
if field.containing_oneof:
self._UpdateOneofState(field)
if msg._unknown_fields:
if not self._unknown_fields:
self._unknown_fields = []
self._unknown_fields.extend(msg._unknown_fields)
# pylint: disable=protected-access
if self._unknown_field_set is None:
self._unknown_field_set = containers.UnknownFieldSet()
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.MergeFromString"><code class="name flex">
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFromString(self, serialized):
serialized = memoryview(serialized)
length = len(serialized)
try:
if self._InternalParse(serialized, 0, length) != length:
# The only reason _InternalParse would return early is if it
# encountered an end-group tag.
raise message_mod.DecodeError(&#39;Unexpected end-group tag.&#39;)
except (IndexError, TypeError):
# Now ord(buf[p:p+1]) == ord(&#39;&#39;) gets TypeError.
raise message_mod.DecodeError(&#39;Truncated message.&#39;)
except struct.error as e:
raise message_mod.DecodeError(e)
return length # Return this for legacy reasons.</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.SerializePartialToString"><code class="name flex">
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializePartialToString(self, **kwargs):
out = BytesIO()
self._InternalSerialize(out.write, **kwargs)
return out.getvalue()</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.SerializeToString"><code class="name flex">
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializeToString(self, **kwargs):
# Check if the message has all of its required fields set.
if not self.IsInitialized():
raise message_mod.EncodeError(
&#39;Message %s is missing required fields: %s&#39; % (
self.DESCRIPTOR.full_name, &#39;,&#39;.join(self.FindInitializationErrors())))
return self.SerializePartialToString(**kwargs)</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.SetInParent"><code class="name flex">
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def Modified(self):
&#34;&#34;&#34;Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.
&#34;&#34;&#34;
# Note: Some callers check _cached_byte_size_dirty before calling
# _Modified() as an extra optimization. So, if this method is ever
# changed such that it does stuff even when _cached_byte_size_dirty is
# already true, the callers need to be updated.
if not self._cached_byte_size_dirty:
self._cached_byte_size_dirty = True
self._listener_for_children.dirty = True
self._is_present_in_parent = True
self._listener.Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.UnknownFields"><code class="name flex">
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _UnknownFields(self):
if self._unknown_field_set is None: # pylint: disable=protected-access
# pylint: disable=protected-access
self._unknown_field_set = containers.UnknownFieldSet()
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.WhichOneof"><code class="name flex">
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
</code></dt>
<dd>
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def WhichOneof(self, oneof_name):
&#34;&#34;&#34;Returns the name of the currently set field inside a oneof, or None.&#34;&#34;&#34;
try:
field = message_descriptor.oneofs_by_name[oneof_name]
except KeyError:
raise ValueError(
&#39;Protocol message has no oneof &#34;%s&#34; field.&#39; % oneof_name)
nested_field = self._oneofs.get(field, None)
if nested_field is not None and self.HasField(nested_field.name):
return nested_field.name
else:
return None</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage" href="#meshtastic.remote_hardware_pb2.HardwareMessage">HardwareMessage</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.ByteSize" href="#meshtastic.remote_hardware_pb2.HardwareMessage.ByteSize">ByteSize</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.Clear" href="#meshtastic.remote_hardware_pb2.HardwareMessage.Clear">Clear</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.ClearField" href="#meshtastic.remote_hardware_pb2.HardwareMessage.ClearField">ClearField</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.DESCRIPTOR" href="#meshtastic.remote_hardware_pb2.HardwareMessage.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.DiscardUnknownFields" href="#meshtastic.remote_hardware_pb2.HardwareMessage.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.FindInitializationErrors" href="#meshtastic.remote_hardware_pb2.HardwareMessage.FindInitializationErrors">FindInitializationErrors</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.FromString" href="#meshtastic.remote_hardware_pb2.HardwareMessage.FromString">FromString</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.GPIOS_CHANGED" href="#meshtastic.remote_hardware_pb2.HardwareMessage.GPIOS_CHANGED">GPIOS_CHANGED</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_MASK_FIELD_NUMBER" href="#meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_MASK_FIELD_NUMBER">GPIO_MASK_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_VALUE_FIELD_NUMBER" href="#meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_VALUE_FIELD_NUMBER">GPIO_VALUE_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.HasField" href="#meshtastic.remote_hardware_pb2.HardwareMessage.HasField">HasField</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.IsInitialized" href="#meshtastic.remote_hardware_pb2.HardwareMessage.IsInitialized">IsInitialized</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.ListFields" href="#meshtastic.remote_hardware_pb2.HardwareMessage.ListFields">ListFields</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.MergeFrom" href="#meshtastic.remote_hardware_pb2.HardwareMessage.MergeFrom">MergeFrom</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.MergeFromString" href="#meshtastic.remote_hardware_pb2.HardwareMessage.MergeFromString">MergeFromString</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS" href="#meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS">READ_GPIOS</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS_REPLY" href="#meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS_REPLY">READ_GPIOS_REPLY</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.RegisterExtension" href="#meshtastic.remote_hardware_pb2.HardwareMessage.RegisterExtension">RegisterExtension</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.SerializePartialToString" href="#meshtastic.remote_hardware_pb2.HardwareMessage.SerializePartialToString">SerializePartialToString</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.SerializeToString" href="#meshtastic.remote_hardware_pb2.HardwareMessage.SerializeToString">SerializeToString</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.SetInParent" href="#meshtastic.remote_hardware_pb2.HardwareMessage.SetInParent">SetInParent</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.TYP_FIELD_NUMBER" href="#meshtastic.remote_hardware_pb2.HardwareMessage.TYP_FIELD_NUMBER">TYP_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.Type" href="#meshtastic.remote_hardware_pb2.HardwareMessage.Type">Type</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.UNSET" href="#meshtastic.remote_hardware_pb2.HardwareMessage.UNSET">UNSET</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.UnknownFields" href="#meshtastic.remote_hardware_pb2.HardwareMessage.UnknownFields">UnknownFields</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.WATCH_GPIOS" href="#meshtastic.remote_hardware_pb2.HardwareMessage.WATCH_GPIOS">WATCH_GPIOS</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.WRITE_GPIOS" href="#meshtastic.remote_hardware_pb2.HardwareMessage.WRITE_GPIOS">WRITE_GPIOS</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.WhichOneof" href="#meshtastic.remote_hardware_pb2.HardwareMessage.WhichOneof">WhichOneof</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.gpio_mask" href="#meshtastic.remote_hardware_pb2.HardwareMessage.gpio_mask">gpio_mask</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.gpio_value" href="#meshtastic.remote_hardware_pb2.HardwareMessage.gpio_value">gpio_value</a></code></li>
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.typ" href="#meshtastic.remote_hardware_pb2.HardwareMessage.typ">typ</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,254 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.serial_interface API documentation</title>
<meta name="description" content="Serial interface class" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.serial_interface</code></h1>
</header>
<section id="section-intro">
<p>Serial interface class</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34; Serial interface class
&#34;&#34;&#34;
import logging
import platform
import os
import stat
import serial
import meshtastic.util
from .stream_interface import StreamInterface
class SerialInterface(StreamInterface):
&#34;&#34;&#34;Interface class for meshtastic devices over a serial link&#34;&#34;&#34;
def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True):
&#34;&#34;&#34;Constructor, opens a connection to a specified serial port, or if unspecified try to
find one Meshtastic device by probing
Keyword Arguments:
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
debugOut {stream} -- If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})
&#34;&#34;&#34;
if devPath is None:
ports = meshtastic.util.findPorts()
logging.debug(f&#34;ports:{ports}&#34;)
if len(ports) == 0:
meshtastic.util.our_exit(&#34;Warning: No Meshtastic devices detected.&#34;)
elif len(ports) &gt; 1:
message = &#34;Warning: Multiple serial ports were detected so one serial port must be specified with the &#39;--port&#39;.\n&#34;
message += f&#34; Ports detected:{ports}&#34;
meshtastic.util.our_exit(message)
else:
devPath = ports[0]
logging.debug(f&#34;Connecting to {devPath}&#34;)
# Note: we provide None for port here, because we will be opening it later
self.stream = serial.Serial(
None, 921600, exclusive=True, timeout=0.5, write_timeout=0)
# rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
self.stream.port = devPath
# HACK: If the platform driving the serial port is unable to leave the RTS pin in high-impedance
# mode, set RTS to false so that the device platform won&#39;t be reset spuriously.
# Linux does this properly, so don&#39;t apply this hack on Linux (because it makes the reset button not work).
if self._hostPlatformAlwaysDrivesUartRts():
self.stream.rts = False
self.stream.open()
StreamInterface.__init__(
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
&#34;&#34;&#34;true if platform driving the serial port is Windows Subsystem for Linux 1.&#34;&#34;&#34;
def _isWsl1(self):
# WSL1 identifies itself as Linux, but has a special char device at /dev/lxss for use with session control,
# e.g. /init. We should treat WSL1 as Windows for the RTS-driving hack because the underlying platfrom
# serial driver for the CP21xx still exhibits the buggy behavior.
# WSL2 is not covered here, as it does not (as of 2021-May-25) support the appropriate functionality to
# share or pass-through serial ports.
try:
# Claims to be Linux, but has /dev/lxss; must be WSL 1
return platform.system() == &#39;Linux&#39; and stat.S_ISCHR(os.stat(&#39;/dev/lxss&#39;).st_mode)
except:
# Couldn&#39;t stat /dev/lxss special device; not WSL1
return False
def _hostPlatformAlwaysDrivesUartRts(self):
# OS-X/Windows seems to have a bug in its CP21xx serial drivers. It ignores that we asked for no RTSCTS
# control and will always drive RTS either high or low (rather than letting the CP102 leave
# it as an open-collector floating pin).
# TODO: When WSL2 supports USB passthrough, this will get messier. If/when WSL2 gets virtual serial
# ports that &#34;share&#34; the Windows serial port (and thus the Windows drivers), this code will need to be
# updated to reflect that as well -- or if T-Beams get made with an alternate USB to UART bridge that has
# a less buggy driver.
return platform.system() != &#39;Linux&#39; or self._isWsl1()</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.serial_interface.SerialInterface"><code class="flex name class">
<span>class <span class="ident">SerialInterface</span></span>
<span>(</span><span>devPath=None, debugOut=None, noProto=False, connectNow=True)</span>
</code></dt>
<dd>
<div class="desc"><p>Interface class for meshtastic devices over a serial link</p>
<p>Constructor, opens a connection to a specified serial port, or if unspecified try to
find one Meshtastic device by probing</p>
<p>Keyword Arguments:
devPath {string} &ndash; A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
debugOut {stream} &ndash; If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class SerialInterface(StreamInterface):
&#34;&#34;&#34;Interface class for meshtastic devices over a serial link&#34;&#34;&#34;
def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True):
&#34;&#34;&#34;Constructor, opens a connection to a specified serial port, or if unspecified try to
find one Meshtastic device by probing
Keyword Arguments:
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
debugOut {stream} -- If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})
&#34;&#34;&#34;
if devPath is None:
ports = meshtastic.util.findPorts()
logging.debug(f&#34;ports:{ports}&#34;)
if len(ports) == 0:
meshtastic.util.our_exit(&#34;Warning: No Meshtastic devices detected.&#34;)
elif len(ports) &gt; 1:
message = &#34;Warning: Multiple serial ports were detected so one serial port must be specified with the &#39;--port&#39;.\n&#34;
message += f&#34; Ports detected:{ports}&#34;
meshtastic.util.our_exit(message)
else:
devPath = ports[0]
logging.debug(f&#34;Connecting to {devPath}&#34;)
# Note: we provide None for port here, because we will be opening it later
self.stream = serial.Serial(
None, 921600, exclusive=True, timeout=0.5, write_timeout=0)
# rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
self.stream.port = devPath
# HACK: If the platform driving the serial port is unable to leave the RTS pin in high-impedance
# mode, set RTS to false so that the device platform won&#39;t be reset spuriously.
# Linux does this properly, so don&#39;t apply this hack on Linux (because it makes the reset button not work).
if self._hostPlatformAlwaysDrivesUartRts():
self.stream.rts = False
self.stream.open()
StreamInterface.__init__(
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
&#34;&#34;&#34;true if platform driving the serial port is Windows Subsystem for Linux 1.&#34;&#34;&#34;
def _isWsl1(self):
# WSL1 identifies itself as Linux, but has a special char device at /dev/lxss for use with session control,
# e.g. /init. We should treat WSL1 as Windows for the RTS-driving hack because the underlying platfrom
# serial driver for the CP21xx still exhibits the buggy behavior.
# WSL2 is not covered here, as it does not (as of 2021-May-25) support the appropriate functionality to
# share or pass-through serial ports.
try:
# Claims to be Linux, but has /dev/lxss; must be WSL 1
return platform.system() == &#39;Linux&#39; and stat.S_ISCHR(os.stat(&#39;/dev/lxss&#39;).st_mode)
except:
# Couldn&#39;t stat /dev/lxss special device; not WSL1
return False
def _hostPlatformAlwaysDrivesUartRts(self):
# OS-X/Windows seems to have a bug in its CP21xx serial drivers. It ignores that we asked for no RTSCTS
# control and will always drive RTS either high or low (rather than letting the CP102 leave
# it as an open-collector floating pin).
# TODO: When WSL2 supports USB passthrough, this will get messier. If/when WSL2 gets virtual serial
# ports that &#34;share&#34; the Windows serial port (and thus the Windows drivers), this code will need to be
# updated to reflect that as well -- or if T-Beams get made with an alternate USB to UART bridge that has
# a less buggy driver.
return platform.system() != &#39;Linux&#39; or self._isWsl1()</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="meshtastic.stream_interface.StreamInterface" href="stream_interface.html#meshtastic.stream_interface.StreamInterface">StreamInterface</a></li>
<li><a title="meshtastic.mesh_interface.MeshInterface" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface">MeshInterface</a></li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="meshtastic.stream_interface.StreamInterface" href="stream_interface.html#meshtastic.stream_interface.StreamInterface">StreamInterface</a></b></code>:
<ul class="hlist">
<li><code><a title="meshtastic.stream_interface.StreamInterface.close" href="stream_interface.html#meshtastic.stream_interface.StreamInterface.close">close</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.connect" href="stream_interface.html#meshtastic.stream_interface.StreamInterface.connect">connect</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getLongName" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getLongName">getLongName</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getMyNodeInfo" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getMyNodeInfo">getMyNodeInfo</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getMyUser" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getMyUser">getMyUser</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getNode" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getNode">getNode</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getShortName" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getShortName">getShortName</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.sendData" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendData">sendData</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.sendPosition" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendPosition">sendPosition</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.sendText" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendText">sendText</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.showInfo" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.showInfo">showInfo</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.showNodes" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.showNodes">showNodes</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.waitForConfig" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.waitForConfig">waitForConfig</a></code></li>
</ul>
</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.serial_interface.SerialInterface" href="#meshtastic.serial_interface.SerialInterface">SerialInterface</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,510 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.stream_interface API documentation</title>
<meta name="description" content="Stream Interface base class" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.stream_interface</code></h1>
</header>
<section id="section-intro">
<p>Stream Interface base class</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Stream Interface base class
&#34;&#34;&#34;
import logging
import threading
import time
import traceback
import serial
from .mesh_interface import MeshInterface
from .util import stripnl
START1 = 0x94
START2 = 0xc3
HEADER_LEN = 4
MAX_TO_FROM_RADIO_SIZE = 512
class StreamInterface(MeshInterface):
&#34;&#34;&#34;Interface class for meshtastic devices over a stream link (serial, TCP, etc)&#34;&#34;&#34;
def __init__(self, debugOut=None, noProto=False, connectNow=True):
&#34;&#34;&#34;Constructor, opens a connection to self.stream
Keyword Arguments:
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
debugOut {stream} -- If a stream is provided, any debug serial output from the
device will be emitted to that stream. (default: {None})
Raises:
Exception: [description]
Exception: [description]
&#34;&#34;&#34;
if not hasattr(self, &#39;stream&#39;):
raise Exception(
&#34;StreamInterface is now abstract (to update existing code create SerialInterface instead)&#34;)
self._rxBuf = bytes() # empty
self._wantExit = False
# FIXME, figure out why daemon=True causes reader thread to exit too early
self._rxThread = threading.Thread(
target=self.__reader, args=(), daemon=True)
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
# Start the reader thread after superclass constructor completes init
if connectNow:
self.connect()
if not noProto:
self.waitForConfig()
def connect(self):
&#34;&#34;&#34;Connect to our radio
Normally this is called automatically by the constructor, but if you
passed in connectNow=False you can manually start the reading thread later.
&#34;&#34;&#34;
# Send some bogus UART characters to force a sleeping device to wake, and
# if the reading statemachine was parsing a bad packet make sure
# we write enought start bytes to force it to resync (we don&#39;t use START1
# because we want to ensure it is looking for START1)
p = bytearray([START2] * 32)
self._writeBytes(p)
time.sleep(0.1) # wait 100ms to give device time to start running
self._rxThread.start()
self._startConfig()
if not self.noProto: # Wait for the db download if using the protocol
self._waitConnected()
def _disconnected(self):
&#34;&#34;&#34;We override the superclass implementation to close our port&#34;&#34;&#34;
MeshInterface._disconnected(self)
logging.debug(&#34;Closing our port&#34;)
# pylint: disable=E0203
if not self.stream is None:
# pylint: disable=E0203
self.stream.close()
# pylint: disable=W0201
self.stream = None
def _writeBytes(self, b):
&#34;&#34;&#34;Write an array of bytes to our stream and flush&#34;&#34;&#34;
if self.stream: # ignore writes when stream is closed
self.stream.write(b)
self.stream.flush()
def _readBytes(self, length):
&#34;&#34;&#34;Read an array of bytes from our stream&#34;&#34;&#34;
return self.stream.read(length)
def _sendToRadioImpl(self, toRadio):
&#34;&#34;&#34;Send a ToRadio protobuf to the device&#34;&#34;&#34;
logging.debug(f&#34;Sending: {stripnl(toRadio)}&#34;)
b = toRadio.SerializeToString()
bufLen = len(b)
# We convert into a string, because the TCP code doesn&#39;t work with byte arrays
header = bytes([START1, START2, (bufLen &gt;&gt; 8) &amp; 0xff, bufLen &amp; 0xff])
self._writeBytes(header + b)
def close(self):
&#34;&#34;&#34;Close a connection to the device&#34;&#34;&#34;
logging.debug(&#34;Closing stream&#34;)
MeshInterface.close(self)
# pyserial cancel_read doesn&#39;t seem to work, therefore we ask the
# reader thread to close things for us
self._wantExit = True
if self._rxThread != threading.current_thread():
self._rxThread.join() # wait for it to exit
def __reader(self):
&#34;&#34;&#34;The reader thread that reads bytes from our stream&#34;&#34;&#34;
empty = bytes()
try:
while not self._wantExit:
# logging.debug(&#34;reading character&#34;)
b = self._readBytes(1)
# logging.debug(&#34;In reader loop&#34;)
# logging.debug(f&#34;read returned {b}&#34;)
if len(b) &gt; 0:
c = b[0]
ptr = len(self._rxBuf)
# Assume we want to append this byte, fixme use bytearray instead
self._rxBuf = self._rxBuf + b
if ptr == 0: # looking for START1
if c != START1:
self._rxBuf = empty # failed to find start
if self.debugOut is not None:
try:
self.debugOut.write(b.decode(&#34;utf-8&#34;))
except:
self.debugOut.write(&#39;?&#39;)
elif ptr == 1: # looking for START2
if c != START2:
self._rxBuf = empty # failed to find start2
elif ptr &gt;= HEADER_LEN - 1: # we&#39;ve at least got a header
# big endian length follos header
packetlen = (self._rxBuf[2] &lt;&lt; 8) + self._rxBuf[3]
if ptr == HEADER_LEN - 1: # we _just_ finished reading the header, validate length
if packetlen &gt; MAX_TO_FROM_RADIO_SIZE:
self._rxBuf = empty # length ws out out bounds, restart
if len(self._rxBuf) != 0 and ptr + 1 &gt;= packetlen + HEADER_LEN:
try:
self._handleFromRadio(self._rxBuf[HEADER_LEN:])
except Exception as ex:
logging.error(f&#34;Error while handling message from radio {ex}&#34;)
traceback.print_exc()
self._rxBuf = empty
else:
# logging.debug(f&#34;timeout&#34;)
pass
except serial.SerialException as ex:
if not self._wantExit: # We might intentionally get an exception during shutdown
logging.warning(f&#34;Meshtastic serial port disconnected, disconnecting... {ex}&#34;)
except OSError as ex:
if not self._wantExit: # We might intentionally get an exception during shutdown
logging.error(f&#34;Unexpected OSError, terminating meshtastic reader... {ex}&#34;)
except Exception as ex:
logging.error(f&#34;Unexpected exception, terminating meshtastic reader... {ex}&#34;)
finally:
logging.debug(&#34;reader is exiting&#34;)
self._disconnected()</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.stream_interface.StreamInterface"><code class="flex name class">
<span>class <span class="ident">StreamInterface</span></span>
<span>(</span><span>debugOut=None, noProto=False, connectNow=True)</span>
</code></dt>
<dd>
<div class="desc"><p>Interface class for meshtastic devices over a stream link (serial, TCP, etc)</p>
<p>Constructor, opens a connection to self.stream</p>
<p>Keyword Arguments:
devPath {string} &ndash; A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
debugOut {stream} &ndash; If a stream is provided, any debug serial output from the
device will be emitted to that stream. (default: {None})</p>
<h2 id="raises">Raises</h2>
<dl>
<dt><code>Exception</code></dt>
<dd>[description]</dd>
<dt><code>Exception</code></dt>
<dd>[description]</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class StreamInterface(MeshInterface):
&#34;&#34;&#34;Interface class for meshtastic devices over a stream link (serial, TCP, etc)&#34;&#34;&#34;
def __init__(self, debugOut=None, noProto=False, connectNow=True):
&#34;&#34;&#34;Constructor, opens a connection to self.stream
Keyword Arguments:
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
debugOut {stream} -- If a stream is provided, any debug serial output from the
device will be emitted to that stream. (default: {None})
Raises:
Exception: [description]
Exception: [description]
&#34;&#34;&#34;
if not hasattr(self, &#39;stream&#39;):
raise Exception(
&#34;StreamInterface is now abstract (to update existing code create SerialInterface instead)&#34;)
self._rxBuf = bytes() # empty
self._wantExit = False
# FIXME, figure out why daemon=True causes reader thread to exit too early
self._rxThread = threading.Thread(
target=self.__reader, args=(), daemon=True)
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
# Start the reader thread after superclass constructor completes init
if connectNow:
self.connect()
if not noProto:
self.waitForConfig()
def connect(self):
&#34;&#34;&#34;Connect to our radio
Normally this is called automatically by the constructor, but if you
passed in connectNow=False you can manually start the reading thread later.
&#34;&#34;&#34;
# Send some bogus UART characters to force a sleeping device to wake, and
# if the reading statemachine was parsing a bad packet make sure
# we write enought start bytes to force it to resync (we don&#39;t use START1
# because we want to ensure it is looking for START1)
p = bytearray([START2] * 32)
self._writeBytes(p)
time.sleep(0.1) # wait 100ms to give device time to start running
self._rxThread.start()
self._startConfig()
if not self.noProto: # Wait for the db download if using the protocol
self._waitConnected()
def _disconnected(self):
&#34;&#34;&#34;We override the superclass implementation to close our port&#34;&#34;&#34;
MeshInterface._disconnected(self)
logging.debug(&#34;Closing our port&#34;)
# pylint: disable=E0203
if not self.stream is None:
# pylint: disable=E0203
self.stream.close()
# pylint: disable=W0201
self.stream = None
def _writeBytes(self, b):
&#34;&#34;&#34;Write an array of bytes to our stream and flush&#34;&#34;&#34;
if self.stream: # ignore writes when stream is closed
self.stream.write(b)
self.stream.flush()
def _readBytes(self, length):
&#34;&#34;&#34;Read an array of bytes from our stream&#34;&#34;&#34;
return self.stream.read(length)
def _sendToRadioImpl(self, toRadio):
&#34;&#34;&#34;Send a ToRadio protobuf to the device&#34;&#34;&#34;
logging.debug(f&#34;Sending: {stripnl(toRadio)}&#34;)
b = toRadio.SerializeToString()
bufLen = len(b)
# We convert into a string, because the TCP code doesn&#39;t work with byte arrays
header = bytes([START1, START2, (bufLen &gt;&gt; 8) &amp; 0xff, bufLen &amp; 0xff])
self._writeBytes(header + b)
def close(self):
&#34;&#34;&#34;Close a connection to the device&#34;&#34;&#34;
logging.debug(&#34;Closing stream&#34;)
MeshInterface.close(self)
# pyserial cancel_read doesn&#39;t seem to work, therefore we ask the
# reader thread to close things for us
self._wantExit = True
if self._rxThread != threading.current_thread():
self._rxThread.join() # wait for it to exit
def __reader(self):
&#34;&#34;&#34;The reader thread that reads bytes from our stream&#34;&#34;&#34;
empty = bytes()
try:
while not self._wantExit:
# logging.debug(&#34;reading character&#34;)
b = self._readBytes(1)
# logging.debug(&#34;In reader loop&#34;)
# logging.debug(f&#34;read returned {b}&#34;)
if len(b) &gt; 0:
c = b[0]
ptr = len(self._rxBuf)
# Assume we want to append this byte, fixme use bytearray instead
self._rxBuf = self._rxBuf + b
if ptr == 0: # looking for START1
if c != START1:
self._rxBuf = empty # failed to find start
if self.debugOut is not None:
try:
self.debugOut.write(b.decode(&#34;utf-8&#34;))
except:
self.debugOut.write(&#39;?&#39;)
elif ptr == 1: # looking for START2
if c != START2:
self._rxBuf = empty # failed to find start2
elif ptr &gt;= HEADER_LEN - 1: # we&#39;ve at least got a header
# big endian length follos header
packetlen = (self._rxBuf[2] &lt;&lt; 8) + self._rxBuf[3]
if ptr == HEADER_LEN - 1: # we _just_ finished reading the header, validate length
if packetlen &gt; MAX_TO_FROM_RADIO_SIZE:
self._rxBuf = empty # length ws out out bounds, restart
if len(self._rxBuf) != 0 and ptr + 1 &gt;= packetlen + HEADER_LEN:
try:
self._handleFromRadio(self._rxBuf[HEADER_LEN:])
except Exception as ex:
logging.error(f&#34;Error while handling message from radio {ex}&#34;)
traceback.print_exc()
self._rxBuf = empty
else:
# logging.debug(f&#34;timeout&#34;)
pass
except serial.SerialException as ex:
if not self._wantExit: # We might intentionally get an exception during shutdown
logging.warning(f&#34;Meshtastic serial port disconnected, disconnecting... {ex}&#34;)
except OSError as ex:
if not self._wantExit: # We might intentionally get an exception during shutdown
logging.error(f&#34;Unexpected OSError, terminating meshtastic reader... {ex}&#34;)
except Exception as ex:
logging.error(f&#34;Unexpected exception, terminating meshtastic reader... {ex}&#34;)
finally:
logging.debug(&#34;reader is exiting&#34;)
self._disconnected()</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="meshtastic.mesh_interface.MeshInterface" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface">MeshInterface</a></li>
</ul>
<h3>Subclasses</h3>
<ul class="hlist">
<li><a title="meshtastic.serial_interface.SerialInterface" href="serial_interface.html#meshtastic.serial_interface.SerialInterface">SerialInterface</a></li>
<li><a title="meshtastic.tcp_interface.TCPInterface" href="tcp_interface.html#meshtastic.tcp_interface.TCPInterface">TCPInterface</a></li>
</ul>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.stream_interface.StreamInterface.close"><code class="name flex">
<span>def <span class="ident">close</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Close a connection to the device</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def close(self):
&#34;&#34;&#34;Close a connection to the device&#34;&#34;&#34;
logging.debug(&#34;Closing stream&#34;)
MeshInterface.close(self)
# pyserial cancel_read doesn&#39;t seem to work, therefore we ask the
# reader thread to close things for us
self._wantExit = True
if self._rxThread != threading.current_thread():
self._rxThread.join() # wait for it to exit</code></pre>
</details>
</dd>
<dt id="meshtastic.stream_interface.StreamInterface.connect"><code class="name flex">
<span>def <span class="ident">connect</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Connect to our radio</p>
<p>Normally this is called automatically by the constructor, but if you
passed in connectNow=False you can manually start the reading thread later.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def connect(self):
&#34;&#34;&#34;Connect to our radio
Normally this is called automatically by the constructor, but if you
passed in connectNow=False you can manually start the reading thread later.
&#34;&#34;&#34;
# Send some bogus UART characters to force a sleeping device to wake, and
# if the reading statemachine was parsing a bad packet make sure
# we write enought start bytes to force it to resync (we don&#39;t use START1
# because we want to ensure it is looking for START1)
p = bytearray([START2] * 32)
self._writeBytes(p)
time.sleep(0.1) # wait 100ms to give device time to start running
self._rxThread.start()
self._startConfig()
if not self.noProto: # Wait for the db download if using the protocol
self._waitConnected()</code></pre>
</details>
</dd>
</dl>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="meshtastic.mesh_interface.MeshInterface" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface">MeshInterface</a></b></code>:
<ul class="hlist">
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getLongName" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getLongName">getLongName</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getMyNodeInfo" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getMyNodeInfo">getMyNodeInfo</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getMyUser" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getMyUser">getMyUser</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getNode" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getNode">getNode</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.getShortName" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getShortName">getShortName</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.sendData" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendData">sendData</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.sendPosition" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendPosition">sendPosition</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.sendText" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendText">sendText</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.showInfo" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.showInfo">showInfo</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.showNodes" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.showNodes">showNodes</a></code></li>
<li><code><a title="meshtastic.mesh_interface.MeshInterface.waitForConfig" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.waitForConfig">waitForConfig</a></code></li>
</ul>
</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.stream_interface.StreamInterface" href="#meshtastic.stream_interface.StreamInterface">StreamInterface</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.stream_interface.StreamInterface.close" href="#meshtastic.stream_interface.StreamInterface.close">close</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.connect" href="#meshtastic.stream_interface.StreamInterface.connect">connect</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,207 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tcp_interface API documentation</title>
<meta name="description" content="TCPInterface class for interfacing with http endpoint" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tcp_interface</code></h1>
</header>
<section id="section-intro">
<p>TCPInterface class for interfacing with http endpoint</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;TCPInterface class for interfacing with http endpoint
&#34;&#34;&#34;
import logging
import socket
from typing import AnyStr
from .stream_interface import StreamInterface
class TCPInterface(StreamInterface):
&#34;&#34;&#34;Interface class for meshtastic devices over a TCP link&#34;&#34;&#34;
def __init__(self, hostname: AnyStr, debugOut=None, noProto=False,
connectNow=True, portNumber=4403):
&#34;&#34;&#34;Constructor, opens a connection to a specified IP address/hostname
Keyword Arguments:
hostname {string} -- Hostname/IP address of the device to connect to
&#34;&#34;&#34;
logging.debug(f&#34;Connecting to {hostname}&#34;)
server_address = (hostname, portNumber)
sock = socket.create_connection(server_address)
# Instead of wrapping as a stream, we use the native socket API
# self.stream = sock.makefile(&#39;rw&#39;)
self.stream = None
self.socket = sock
StreamInterface.__init__(
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
def close(self):
&#34;&#34;&#34;Close a connection to the device&#34;&#34;&#34;
logging.debug(&#34;Closing TCP stream&#34;)
StreamInterface.close(self)
# Sometimes the socket read might be blocked in the reader thread.
# Therefore we force the shutdown by closing the socket here
self._wantExit = True
if not self.socket is None:
try:
self.socket.shutdown(socket.SHUT_RDWR)
except:
pass # Ignore errors in shutdown, because we might have a race with the server
self.socket.close()
def _writeBytes(self, b):
&#34;&#34;&#34;Write an array of bytes to our stream and flush&#34;&#34;&#34;
self.socket.send(b)
def _readBytes(self, length):
&#34;&#34;&#34;Read an array of bytes from our stream&#34;&#34;&#34;
return self.socket.recv(length)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.tcp_interface.TCPInterface"><code class="flex name class">
<span>class <span class="ident">TCPInterface</span></span>
<span>(</span><span>hostname: ~AnyStr, debugOut=None, noProto=False, connectNow=True, portNumber=4403)</span>
</code></dt>
<dd>
<div class="desc"><p>Interface class for meshtastic devices over a TCP link</p>
<p>Constructor, opens a connection to a specified IP address/hostname</p>
<p>Keyword Arguments:
hostname {string} &ndash; Hostname/IP address of the device to connect to</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class TCPInterface(StreamInterface):
&#34;&#34;&#34;Interface class for meshtastic devices over a TCP link&#34;&#34;&#34;
def __init__(self, hostname: AnyStr, debugOut=None, noProto=False,
connectNow=True, portNumber=4403):
&#34;&#34;&#34;Constructor, opens a connection to a specified IP address/hostname
Keyword Arguments:
hostname {string} -- Hostname/IP address of the device to connect to
&#34;&#34;&#34;
logging.debug(f&#34;Connecting to {hostname}&#34;)
server_address = (hostname, portNumber)
sock = socket.create_connection(server_address)
# Instead of wrapping as a stream, we use the native socket API
# self.stream = sock.makefile(&#39;rw&#39;)
self.stream = None
self.socket = sock
StreamInterface.__init__(
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
def close(self):
&#34;&#34;&#34;Close a connection to the device&#34;&#34;&#34;
logging.debug(&#34;Closing TCP stream&#34;)
StreamInterface.close(self)
# Sometimes the socket read might be blocked in the reader thread.
# Therefore we force the shutdown by closing the socket here
self._wantExit = True
if not self.socket is None:
try:
self.socket.shutdown(socket.SHUT_RDWR)
except:
pass # Ignore errors in shutdown, because we might have a race with the server
self.socket.close()
def _writeBytes(self, b):
&#34;&#34;&#34;Write an array of bytes to our stream and flush&#34;&#34;&#34;
self.socket.send(b)
def _readBytes(self, length):
&#34;&#34;&#34;Read an array of bytes from our stream&#34;&#34;&#34;
return self.socket.recv(length)</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="meshtastic.stream_interface.StreamInterface" href="stream_interface.html#meshtastic.stream_interface.StreamInterface">StreamInterface</a></li>
<li><a title="meshtastic.mesh_interface.MeshInterface" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface">MeshInterface</a></li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="meshtastic.stream_interface.StreamInterface" href="stream_interface.html#meshtastic.stream_interface.StreamInterface">StreamInterface</a></b></code>:
<ul class="hlist">
<li><code><a title="meshtastic.stream_interface.StreamInterface.close" href="stream_interface.html#meshtastic.stream_interface.StreamInterface.close">close</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.connect" href="stream_interface.html#meshtastic.stream_interface.StreamInterface.connect">connect</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getLongName" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getLongName">getLongName</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getMyNodeInfo" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getMyNodeInfo">getMyNodeInfo</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getMyUser" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getMyUser">getMyUser</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getNode" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getNode">getNode</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.getShortName" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.getShortName">getShortName</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.sendData" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendData">sendData</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.sendPosition" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendPosition">sendPosition</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.sendText" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.sendText">sendText</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.showInfo" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.showInfo">showInfo</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.showNodes" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.showNodes">showNodes</a></code></li>
<li><code><a title="meshtastic.stream_interface.StreamInterface.waitForConfig" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface.waitForConfig">waitForConfig</a></code></li>
</ul>
</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.tcp_interface.TCPInterface" href="#meshtastic.tcp_interface.TCPInterface">TCPInterface</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,544 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.test API documentation</title>
<meta name="description" content="With two radios connected serially, send and receive test
messages and report back if successful." />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.test</code></h1>
</header>
<section id="section-intro">
<p>With two radios connected serially, send and receive test
messages and report back if successful.</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;With two radios connected serially, send and receive test
messages and report back if successful.
&#34;&#34;&#34;
import logging
import time
import sys
import traceback
from dotmap import DotMap
from pubsub import pub
import meshtastic.util
from .__init__ import BROADCAST_NUM
from .serial_interface import SerialInterface
from .tcp_interface import TCPInterface
&#34;&#34;&#34;The interfaces we are using for our tests&#34;&#34;&#34;
interfaces = None
&#34;&#34;&#34;A list of all packets we received while the current test was running&#34;&#34;&#34;
receivedPackets = None
testsRunning = False
testNumber = 0
sendingInterface = None
def onReceive(packet, interface):
&#34;&#34;&#34;Callback invoked when a packet arrives&#34;&#34;&#34;
if sendingInterface == interface:
pass
# print(&#34;Ignoring sending interface&#34;)
else:
# print(f&#34;From {interface.stream.port}: {packet}&#34;)
p = DotMap(packet)
if p.decoded.portnum == &#34;TEXT_MESSAGE_APP&#34;:
# We only care a about clear text packets
if receivedPackets is not None:
receivedPackets.append(p)
def onNode(node):
&#34;&#34;&#34;Callback invoked when the node DB changes&#34;&#34;&#34;
print(f&#34;Node changed: {node}&#34;)
def subscribe():
&#34;&#34;&#34;Subscribe to the topics the user probably wants to see, prints output to stdout&#34;&#34;&#34;
pub.subscribe(onNode, &#34;meshtastic.node&#34;)
def testSend(fromInterface, toInterface, isBroadcast=False, asBinary=False, wantAck=False):
&#34;&#34;&#34;
Sends one test packet between two nodes and then returns success or failure
Arguments:
fromInterface {[type]} -- [description]
toInterface {[type]} -- [description]
Returns:
boolean -- True for success
&#34;&#34;&#34;
global receivedPackets
receivedPackets = []
fromNode = fromInterface.myInfo.my_node_num
if isBroadcast:
toNode = BROADCAST_NUM
else:
toNode = toInterface.myInfo.my_node_num
logging.debug(
f&#34;Sending test wantAck={wantAck} packet from {fromNode} to {toNode}&#34;)
global sendingInterface
sendingInterface = fromInterface
if not asBinary:
fromInterface.sendText(f&#34;Test {testNumber}&#34;, toNode, wantAck=wantAck)
else:
fromInterface.sendData((f&#34;Binary {testNumber}&#34;).encode(
&#34;utf-8&#34;), toNode, wantAck=wantAck)
for _ in range(60): # max of 60 secs before we timeout
time.sleep(1)
if len(receivedPackets) &gt;= 1:
return True
return False # Failed to send
def runTests(numTests=50, wantAck=False, maxFailures=0):
&#34;&#34;&#34;Run the tests.&#34;&#34;&#34;
logging.info(f&#34;Running {numTests} tests with wantAck={wantAck}&#34;)
numFail = 0
numSuccess = 0
for _ in range(numTests):
global testNumber
testNumber = testNumber + 1
isBroadcast = True
# asBinary=(i % 2 == 0)
success = testSend(
interfaces[0], interfaces[1], isBroadcast, asBinary=False, wantAck=wantAck)
if not success:
numFail = numFail + 1
logging.error(
f&#34;Test {testNumber} failed, expected packet not received ({numFail} failures so far)&#34;)
else:
numSuccess = numSuccess + 1
logging.info(
f&#34;Test {testNumber} succeeded {numSuccess} successes {numFail} failures so far&#34;)
time.sleep(1)
if numFail &gt; maxFailures:
logging.error(&#34;Too many failures! Test failed!&#34;)
return False
return True
def testThread(numTests=50):
&#34;&#34;&#34;Test thread&#34;&#34;&#34;
logging.info(&#34;Found devices, starting tests...&#34;)
result = runTests(numTests, wantAck=True)
if result:
# Run another test
# Allow a few dropped packets
result = runTests(numTests, wantAck=False, maxFailures=1)
return result
def onConnection(topic=pub.AUTO_TOPIC):
&#34;&#34;&#34;Callback invoked when we connect/disconnect from a radio&#34;&#34;&#34;
print(f&#34;Connection changed: {topic.getName()}&#34;)
def openDebugLog(portName):
&#34;&#34;&#34;Open the debug log file&#34;&#34;&#34;
debugname = &#34;log&#34; + portName.replace(&#34;/&#34;, &#34;_&#34;)
logging.info(f&#34;Writing serial debugging to {debugname}&#34;)
return open(debugname, &#39;w+&#39;, buffering=1, encoding=&#39;utf8&#39;)
def testAll(numTests=5):
&#34;&#34;&#34;
Run a series of tests using devices we can find.
This is called from the cli with the &#34;--test&#34; option.
&#34;&#34;&#34;
ports = meshtastic.util.findPorts()
if len(ports) &lt; 2:
meshtastic.util.our_exit(&#34;Warning: Must have at least two devices connected to USB.&#34;)
pub.subscribe(onConnection, &#34;meshtastic.connection&#34;)
pub.subscribe(onReceive, &#34;meshtastic.receive&#34;)
global interfaces
interfaces = list(map(lambda port: SerialInterface(
port, debugOut=openDebugLog(port), connectNow=True), ports))
logging.info(&#34;Ports opened, starting test&#34;)
result = testThread(numTests)
for i in interfaces:
i.close()
return result
def testSimulator():
&#34;&#34;&#34;
Assume that someone has launched meshtastic-native as a simulated node.
Talk to that node over TCP, do some operations and if they are successful
exit the process with a success code, else exit with a non zero exit code.
Run with
python3 -c &#39;from meshtastic.test import testSimulator; testSimulator()&#39;
&#34;&#34;&#34;
logging.basicConfig(level=logging.DEBUG)
logging.info(&#34;Connecting to simulator on localhost!&#34;)
try:
iface = TCPInterface(&#34;localhost&#34;)
iface.showInfo()
iface.localNode.showInfo()
iface.localNode.exitSimulator()
iface.close()
logging.info(&#34;Integration test successful!&#34;)
except:
print(&#34;Error while testing simulator:&#34;, sys.exc_info()[0])
traceback.print_exc()
sys.exit(1)
sys.exit(0)</code></pre>
</details>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-variables">Global variables</h2>
<dl>
<dt id="meshtastic.test.interfaces"><code class="name">var <span class="ident">interfaces</span></code></dt>
<dd>
<div class="desc"><p>A list of all packets we received while the current test was running</p></div>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.test.onConnection"><code class="name flex">
<span>def <span class="ident">onConnection</span></span>(<span>topic=pubsub.core.callables.AUTO_TOPIC)</span>
</code></dt>
<dd>
<div class="desc"><p>Callback invoked when we connect/disconnect from a radio</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def onConnection(topic=pub.AUTO_TOPIC):
&#34;&#34;&#34;Callback invoked when we connect/disconnect from a radio&#34;&#34;&#34;
print(f&#34;Connection changed: {topic.getName()}&#34;)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.onNode"><code class="name flex">
<span>def <span class="ident">onNode</span></span>(<span>node)</span>
</code></dt>
<dd>
<div class="desc"><p>Callback invoked when the node DB changes</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def onNode(node):
&#34;&#34;&#34;Callback invoked when the node DB changes&#34;&#34;&#34;
print(f&#34;Node changed: {node}&#34;)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.onReceive"><code class="name flex">
<span>def <span class="ident">onReceive</span></span>(<span>packet, interface)</span>
</code></dt>
<dd>
<div class="desc"><p>Callback invoked when a packet arrives</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def onReceive(packet, interface):
&#34;&#34;&#34;Callback invoked when a packet arrives&#34;&#34;&#34;
if sendingInterface == interface:
pass
# print(&#34;Ignoring sending interface&#34;)
else:
# print(f&#34;From {interface.stream.port}: {packet}&#34;)
p = DotMap(packet)
if p.decoded.portnum == &#34;TEXT_MESSAGE_APP&#34;:
# We only care a about clear text packets
if receivedPackets is not None:
receivedPackets.append(p)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.openDebugLog"><code class="name flex">
<span>def <span class="ident">openDebugLog</span></span>(<span>portName)</span>
</code></dt>
<dd>
<div class="desc"><p>Open the debug log file</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def openDebugLog(portName):
&#34;&#34;&#34;Open the debug log file&#34;&#34;&#34;
debugname = &#34;log&#34; + portName.replace(&#34;/&#34;, &#34;_&#34;)
logging.info(f&#34;Writing serial debugging to {debugname}&#34;)
return open(debugname, &#39;w+&#39;, buffering=1, encoding=&#39;utf8&#39;)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.runTests"><code class="name flex">
<span>def <span class="ident">runTests</span></span>(<span>numTests=50, wantAck=False, maxFailures=0)</span>
</code></dt>
<dd>
<div class="desc"><p>Run the tests.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def runTests(numTests=50, wantAck=False, maxFailures=0):
&#34;&#34;&#34;Run the tests.&#34;&#34;&#34;
logging.info(f&#34;Running {numTests} tests with wantAck={wantAck}&#34;)
numFail = 0
numSuccess = 0
for _ in range(numTests):
global testNumber
testNumber = testNumber + 1
isBroadcast = True
# asBinary=(i % 2 == 0)
success = testSend(
interfaces[0], interfaces[1], isBroadcast, asBinary=False, wantAck=wantAck)
if not success:
numFail = numFail + 1
logging.error(
f&#34;Test {testNumber} failed, expected packet not received ({numFail} failures so far)&#34;)
else:
numSuccess = numSuccess + 1
logging.info(
f&#34;Test {testNumber} succeeded {numSuccess} successes {numFail} failures so far&#34;)
time.sleep(1)
if numFail &gt; maxFailures:
logging.error(&#34;Too many failures! Test failed!&#34;)
return False
return True</code></pre>
</details>
</dd>
<dt id="meshtastic.test.subscribe"><code class="name flex">
<span>def <span class="ident">subscribe</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Subscribe to the topics the user probably wants to see, prints output to stdout</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def subscribe():
&#34;&#34;&#34;Subscribe to the topics the user probably wants to see, prints output to stdout&#34;&#34;&#34;
pub.subscribe(onNode, &#34;meshtastic.node&#34;)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.testAll"><code class="name flex">
<span>def <span class="ident">testAll</span></span>(<span>numTests=5)</span>
</code></dt>
<dd>
<div class="desc"><p>Run a series of tests using devices we can find.
This is called from the cli with the "&ndash;test" option.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def testAll(numTests=5):
&#34;&#34;&#34;
Run a series of tests using devices we can find.
This is called from the cli with the &#34;--test&#34; option.
&#34;&#34;&#34;
ports = meshtastic.util.findPorts()
if len(ports) &lt; 2:
meshtastic.util.our_exit(&#34;Warning: Must have at least two devices connected to USB.&#34;)
pub.subscribe(onConnection, &#34;meshtastic.connection&#34;)
pub.subscribe(onReceive, &#34;meshtastic.receive&#34;)
global interfaces
interfaces = list(map(lambda port: SerialInterface(
port, debugOut=openDebugLog(port), connectNow=True), ports))
logging.info(&#34;Ports opened, starting test&#34;)
result = testThread(numTests)
for i in interfaces:
i.close()
return result</code></pre>
</details>
</dd>
<dt id="meshtastic.test.testSend"><code class="name flex">
<span>def <span class="ident">testSend</span></span>(<span>fromInterface, toInterface, isBroadcast=False, asBinary=False, wantAck=False)</span>
</code></dt>
<dd>
<div class="desc"><p>Sends one test packet between two nodes and then returns success or failure</p>
<h2 id="arguments">Arguments</h2>
<p>fromInterface {[type]} &ndash; [description]
toInterface {[type]} &ndash; [description]</p>
<h2 id="returns">Returns</h2>
<p>boolean &ndash; True for success</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def testSend(fromInterface, toInterface, isBroadcast=False, asBinary=False, wantAck=False):
&#34;&#34;&#34;
Sends one test packet between two nodes and then returns success or failure
Arguments:
fromInterface {[type]} -- [description]
toInterface {[type]} -- [description]
Returns:
boolean -- True for success
&#34;&#34;&#34;
global receivedPackets
receivedPackets = []
fromNode = fromInterface.myInfo.my_node_num
if isBroadcast:
toNode = BROADCAST_NUM
else:
toNode = toInterface.myInfo.my_node_num
logging.debug(
f&#34;Sending test wantAck={wantAck} packet from {fromNode} to {toNode}&#34;)
global sendingInterface
sendingInterface = fromInterface
if not asBinary:
fromInterface.sendText(f&#34;Test {testNumber}&#34;, toNode, wantAck=wantAck)
else:
fromInterface.sendData((f&#34;Binary {testNumber}&#34;).encode(
&#34;utf-8&#34;), toNode, wantAck=wantAck)
for _ in range(60): # max of 60 secs before we timeout
time.sleep(1)
if len(receivedPackets) &gt;= 1:
return True
return False # Failed to send</code></pre>
</details>
</dd>
<dt id="meshtastic.test.testSimulator"><code class="name flex">
<span>def <span class="ident">testSimulator</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Assume that someone has launched meshtastic-native as a simulated node.
Talk to that node over TCP, do some operations and if they are successful
exit the process with a success code, else exit with a non zero exit code.</p>
<p>Run with
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def testSimulator():
&#34;&#34;&#34;
Assume that someone has launched meshtastic-native as a simulated node.
Talk to that node over TCP, do some operations and if they are successful
exit the process with a success code, else exit with a non zero exit code.
Run with
python3 -c &#39;from meshtastic.test import testSimulator; testSimulator()&#39;
&#34;&#34;&#34;
logging.basicConfig(level=logging.DEBUG)
logging.info(&#34;Connecting to simulator on localhost!&#34;)
try:
iface = TCPInterface(&#34;localhost&#34;)
iface.showInfo()
iface.localNode.showInfo()
iface.localNode.exitSimulator()
iface.close()
logging.info(&#34;Integration test successful!&#34;)
except:
print(&#34;Error while testing simulator:&#34;, sys.exc_info()[0])
traceback.print_exc()
sys.exit(1)
sys.exit(0)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.testThread"><code class="name flex">
<span>def <span class="ident">testThread</span></span>(<span>numTests=50)</span>
</code></dt>
<dd>
<div class="desc"><p>Test thread</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def testThread(numTests=50):
&#34;&#34;&#34;Test thread&#34;&#34;&#34;
logging.info(&#34;Found devices, starting tests...&#34;)
result = runTests(numTests, wantAck=True)
if result:
# Run another test
# Allow a few dropped packets
result = runTests(numTests, wantAck=False, maxFailures=1)
return result</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-variables">Global variables</a></h3>
<ul class="">
<li><code><a title="meshtastic.test.interfaces" href="#meshtastic.test.interfaces">interfaces</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="two-column">
<li><code><a title="meshtastic.test.onConnection" href="#meshtastic.test.onConnection">onConnection</a></code></li>
<li><code><a title="meshtastic.test.onNode" href="#meshtastic.test.onNode">onNode</a></code></li>
<li><code><a title="meshtastic.test.onReceive" href="#meshtastic.test.onReceive">onReceive</a></code></li>
<li><code><a title="meshtastic.test.openDebugLog" href="#meshtastic.test.openDebugLog">openDebugLog</a></code></li>
<li><code><a title="meshtastic.test.runTests" href="#meshtastic.test.runTests">runTests</a></code></li>
<li><code><a title="meshtastic.test.subscribe" href="#meshtastic.test.subscribe">subscribe</a></code></li>
<li><code><a title="meshtastic.test.testAll" href="#meshtastic.test.testAll">testAll</a></code></li>
<li><code><a title="meshtastic.test.testSend" href="#meshtastic.test.testSend">testSend</a></code></li>
<li><code><a title="meshtastic.test.testSimulator" href="#meshtastic.test.testSimulator">testSimulator</a></code></li>
<li><code><a title="meshtastic.test.testThread" href="#meshtastic.test.testThread">testThread</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,80 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.test API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.test</code></h1>
</header>
<section id="section-intro">
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="meshtastic.test.test_int" href="test_int.html">meshtastic.test.test_int</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic integration tests</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.test.test_mesh_interface" href="test_mesh_interface.html">meshtastic.test.test_mesh_interface</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for node.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.test.test_smoke1" href="test_smoke1.html">meshtastic.test.test_smoke1</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic smoke tests with a single device</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.test.test_util" href="test_util.html">meshtastic.test.test_util</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for node.py</p></div>
</dd>
</dl>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="../index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="meshtastic.test.test_int" href="test_int.html">meshtastic.test.test_int</a></code></li>
<li><code><a title="meshtastic.test.test_mesh_interface" href="test_mesh_interface.html">meshtastic.test.test_mesh_interface</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1" href="test_smoke1.html">meshtastic.test.test_smoke1</a></code></li>
<li><code><a title="meshtastic.test.test_util" href="test_util.html">meshtastic.test.test_util</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,177 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.test.test_int API documentation</title>
<meta name="description" content="Meshtastic integration tests" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.test.test_int</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic integration tests</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic integration tests&#34;&#34;&#34;
import re
import subprocess
import pytest
@pytest.mark.int
def test_int_no_args():
&#34;&#34;&#34;Test without any args&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic&#39;)
assert re.match(r&#39;usage: meshtastic&#39;, out)
assert return_value == 1
@pytest.mark.int
def test_int_version():
&#34;&#34;&#34;Test &#39;--version&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --version&#39;)
assert re.match(r&#39;[0-9]+\.[0-9]+\.[0-9]&#39;, out)
assert return_value == 0
@pytest.mark.int
def test_int_help():
&#34;&#34;&#34;Test &#39;--help&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --help&#39;)
assert re.match(r&#39;usage: meshtastic &#39;, out)
assert return_value == 0
@pytest.mark.int
def test_int_support():
&#34;&#34;&#34;Test &#39;--support&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --support&#39;)
assert re.search(r&#39;System&#39;, out)
assert re.search(r&#39;Python&#39;, out)
assert return_value == 0</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.test.test_int.test_int_help"><code class="name flex">
<span>def <span class="ident">test_int_help</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test '&ndash;help'.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.int
def test_int_help():
&#34;&#34;&#34;Test &#39;--help&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --help&#39;)
assert re.match(r&#39;usage: meshtastic &#39;, out)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_int.test_int_no_args"><code class="name flex">
<span>def <span class="ident">test_int_no_args</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test without any args</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.int
def test_int_no_args():
&#34;&#34;&#34;Test without any args&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic&#39;)
assert re.match(r&#39;usage: meshtastic&#39;, out)
assert return_value == 1</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_int.test_int_support"><code class="name flex">
<span>def <span class="ident">test_int_support</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test '&ndash;support'.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.int
def test_int_support():
&#34;&#34;&#34;Test &#39;--support&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --support&#39;)
assert re.search(r&#39;System&#39;, out)
assert re.search(r&#39;Python&#39;, out)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_int.test_int_version"><code class="name flex">
<span>def <span class="ident">test_int_version</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test '&ndash;version'.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.int
def test_int_version():
&#34;&#34;&#34;Test &#39;--version&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --version&#39;)
assert re.match(r&#39;[0-9]+\.[0-9]+\.[0-9]&#39;, out)
assert return_value == 0</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.test" href="index.html">meshtastic.test</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.test.test_int.test_int_help" href="#meshtastic.test.test_int.test_int_help">test_int_help</a></code></li>
<li><code><a title="meshtastic.test.test_int.test_int_no_args" href="#meshtastic.test.test_int.test_int_no_args">test_int_no_args</a></code></li>
<li><code><a title="meshtastic.test.test_int.test_int_support" href="#meshtastic.test.test_int.test_int_support">test_int_support</a></code></li>
<li><code><a title="meshtastic.test.test_int.test_int_version" href="#meshtastic.test.test_int.test_int_version">test_int_version</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,99 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.test.test_mesh_interface API documentation</title>
<meta name="description" content="Meshtastic unit tests for node.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.test.test_mesh_interface</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for node.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for node.py&#34;&#34;&#34;
import pytest
from meshtastic.mesh_interface import MeshInterface
@pytest.mark.unit
def test_MeshInterface():
&#34;&#34;&#34;Test that we instantiate a MeshInterface&#34;&#34;&#34;
iface = MeshInterface(noProto=True)
iface.showInfo()
iface.localNode.showInfo()
iface.close()</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.test.test_mesh_interface.test_MeshInterface"><code class="name flex">
<span>def <span class="ident">test_MeshInterface</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we instantiate a MeshInterface</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_MeshInterface():
&#34;&#34;&#34;Test that we instantiate a MeshInterface&#34;&#34;&#34;
iface = MeshInterface(noProto=True)
iface.showInfo()
iface.localNode.showInfo()
iface.close()</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.test" href="index.html">meshtastic.test</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.test.test_mesh_interface.test_MeshInterface" href="#meshtastic.test.test_mesh_interface.test_MeshInterface">test_MeshInterface</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,982 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.test.test_smoke1 API documentation</title>
<meta name="description" content="Meshtastic smoke tests with a single device" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.test.test_smoke1</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic smoke tests with a single device</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic smoke tests with a single device&#34;&#34;&#34;
import re
import subprocess
import time
import os
# Do not like using hard coded sleeps, but it probably makes
# sense to pause for the radio at apprpriate times
import pytest
import meshtastic
# seconds to pause after running a meshtastic command
PAUSE_AFTER_COMMAND = 2
PAUSE_AFTER_REBOOT = 7
@pytest.mark.smoke1
def test_smoke1_reboot():
&#34;&#34;&#34;Test reboot&#34;&#34;&#34;
return_value, _ = subprocess.getstatusoutput(&#39;meshtastic --reboot&#39;)
assert return_value == 0
# pause for the radio to reset (10 seconds for the pause, and a few more seconds to be back up)
time.sleep(18)
@pytest.mark.smoke1
def test_smoke1_info():
&#34;&#34;&#34;Test --info&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Owner&#39;, out, re.MULTILINE)
assert re.search(r&#39;^My info&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Nodes in mesh&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Preferences&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Channels&#39;, out, re.MULTILINE)
assert re.search(r&#39;^ PRIMARY&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Primary channel URL&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_debug():
&#34;&#34;&#34;Test --debug&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info --debug&#39;)
assert re.search(r&#39;^Owner&#39;, out, re.MULTILINE)
assert re.search(r&#39;^DEBUG:root&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_seriallog_to_file():
&#34;&#34;&#34;Test --seriallog to a file creates a file&#34;&#34;&#34;
filename = &#39;tmpoutput.txt&#39;
if os.path.exists(f&#34;{filename}&#34;):
os.remove(f&#34;{filename}&#34;)
return_value, _ = subprocess.getstatusoutput(f&#39;meshtastic --info --seriallog {filename}&#39;)
assert os.path.exists(f&#34;{filename}&#34;)
assert return_value == 0
os.remove(f&#34;{filename}&#34;)
@pytest.mark.smoke1
def test_smoke1_qr():
&#34;&#34;&#34;Test --qr&#34;&#34;&#34;
filename = &#39;tmpqr&#39;
if os.path.exists(f&#34;{filename}&#34;):
os.remove(f&#34;{filename}&#34;)
return_value, _ = subprocess.getstatusoutput(f&#39;meshtastic --qr &gt; {filename}&#39;)
assert os.path.exists(f&#34;{filename}&#34;)
# not really testing that a valid qr code is created, just that the file size
# is reasonably big enough for a qr code
assert os.stat(f&#34;{filename}&#34;).st_size &gt; 20000
assert return_value == 0
os.remove(f&#34;{filename}&#34;)
@pytest.mark.smoke1
def test_smoke1_nodes():
&#34;&#34;&#34;Test --nodes&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --nodes&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^│ N │ User&#39;, out, re.MULTILINE)
assert re.search(r&#39;^│ 1 │&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_send_hello():
&#34;&#34;&#34;Test --sendtext hello&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --sendtext hello&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Sending text message hello to \^all&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_port():
&#34;&#34;&#34;Test --port&#34;&#34;&#34;
# first, get the ports
ports = meshtastic.util.findPorts()
# hopefully there is just one
assert len(ports) == 1
port = ports[0]
return_value, out = subprocess.getstatusoutput(f&#39;meshtastic --port {port} --info&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Owner&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_set_is_router_true():
&#34;&#34;&#34;Test --set is_router true&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set is_router true&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set is_router to true&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --get is_router&#39;)
assert re.search(r&#39;^is_router: True&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_set_location_info():
&#34;&#34;&#34;Test --setlat, --setlon and --setalt &#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --setlat 32.7767 --setlon -96.7970 --setalt 1337&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Fixing altitude&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Fixing latitude&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Fixing longitude&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out2 = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;1337&#39;, out2, re.MULTILINE)
assert re.search(r&#39;32.7767&#39;, out2, re.MULTILINE)
assert re.search(r&#39;-96.797&#39;, out2, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_set_is_router_false():
&#34;&#34;&#34;Test --set is_router false&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set is_router false&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set is_router to false&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --get is_router&#39;)
assert re.search(r&#39;^is_router: False&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_set_owner():
&#34;&#34;&#34;Test --set-owner name&#34;&#34;&#34;
# make sure the owner is not Joe
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set-owner Bob&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Setting device owner to Bob&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert not re.search(r&#39;Owner: Joe&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set-owner Joe&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Setting device owner to Joe&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;Owner: Joe&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_set_team():
&#34;&#34;&#34;Test --set-team &#34;&#34;&#34;
# unset the team
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set-team CLEAR&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Setting team to CLEAR&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set-team CYAN&#39;)
assert re.search(r&#39;Setting team to CYAN&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;CYAN&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_ch_values():
&#34;&#34;&#34;Test --ch-longslow, --ch-longfast, --ch-mediumslow, --ch-mediumsfast,
--ch-shortslow, and --ch-shortfast arguments
&#34;&#34;&#34;
exp = {
&#39;--ch-longslow&#39;: &#39;Bw125Cr48Sf4096&#39;,
# TODO: not sure why these fail thru tests, but ok manually
#&#39;--ch-longfast&#39;: &#39;Bw31_25Cr48Sf512&#39;,
#&#39;--ch-mediumslow&#39;: &#39;Bw250Cr46Sf2048&#39;,
#&#39;--ch-mediumfast&#39;: &#39;Bw250Cr47Sf1024&#39;,
# TODO &#39;--ch-shortslow&#39;: &#39;?&#39;,
&#39;--ch-shortfast&#39;: &#39;Bw500Cr45Sf128&#39;
}
for key, val in exp.items():
print(key, val)
return_value, out = subprocess.getstatusoutput(f&#39;meshtastic {key}&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;Writing modified channels to device&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio (might reboot)
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(val, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
@pytest.mark.smoke1
def test_smoke1_ch_set_name():
&#34;&#34;&#34;Test --ch-set name&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert not re.search(r&#39;MyChannel&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-set name MyChannel&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set name to MyChannel&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;MyChannel&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_ch_add_and_ch_del():
&#34;&#34;&#34;Test --ch-add&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-add testing&#39;)
assert re.search(r&#39;Writing modified channels to device&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;SECONDARY&#39;, out, re.MULTILINE)
assert re.search(r&#39;testing&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-index 1 --ch-del&#39;)
assert re.search(r&#39;Deleting channel 1&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
# make sure the secondar channel is not there
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert not re.search(r&#39;SECONDARY&#39;, out, re.MULTILINE)
assert not re.search(r&#39;testing&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_ch_set_modem_config():
&#34;&#34;&#34;Test --ch-set modem_config&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert not re.search(r&#39;Bw31_25Cr48Sf512&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-set modem_config Bw31_25Cr48Sf512&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set modem_config to Bw31_25Cr48Sf512&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;Bw31_25Cr48Sf512&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_seturl_default():
&#34;&#34;&#34;Test --seturl with default value&#34;&#34;&#34;
# set some channel value so we no longer have a default channel
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-set name foo&#39;)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
# ensure we no longer have a default primary channel
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert not re.search(&#39;CgUYAyIBAQ&#39;, out, re.MULTILINE)
assert return_value == 0
url = &#34;https://www.meshtastic.org/d/#CgUYAyIBAQ&#34;
return_value, out = subprocess.getstatusoutput(f&#34;meshtastic --seturl {url}&#34;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(&#39;CgUYAyIBAQ&#39;, out, re.MULTILINE)
assert return_value == 0
@pytest.mark.smoke1
def test_smoke1_seturl_invalid_url():
&#34;&#34;&#34;Test --seturl with invalid url&#34;&#34;&#34;
# Note: This url is no longer a valid url.
url = &#34;https://www.meshtastic.org/c/#GAMiENTxuzogKQdZ8Lz_q89Oab8qB0RlZmF1bHQ=&#34;
return_value, out = subprocess.getstatusoutput(f&#34;meshtastic --seturl {url}&#34;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(&#39;Warning: There were no settings&#39;, out, re.MULTILINE)
assert return_value == 1
@pytest.mark.smoke1
def test_smoke1_configure():
&#34;&#34;&#34;Test --configure&#34;&#34;&#34;
_ , out = subprocess.getstatusoutput(f&#34;meshtastic --configure example_config.yaml&#34;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(&#39;^Setting device owner to Bob TBeam&#39;, out, re.MULTILINE)
assert re.search(&#39;^Fixing altitude at 304 meters&#39;, out, re.MULTILINE)
assert re.search(&#39;^Fixing latitude at 35.8&#39;, out, re.MULTILINE)
assert re.search(&#39;^Fixing longitude at -93.8&#39;, out, re.MULTILINE)
assert re.search(&#39;^Setting device position&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set region to 1&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set is_always_powered to true&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set send_owner_interval to 2&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set screen_on_secs to 31536000&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set wait_bluetooth_secs to 31536000&#39;, out, re.MULTILINE)
assert re.search(&#39;^Writing modified preferences to device&#39;, out, re.MULTILINE)
@pytest.mark.smoke1
def test_smoke1_factory_reset():
&#34;&#34;&#34;Test factory reset&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set factory_reset true&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set factory_reset to true&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Writing modified preferences to device&#39;, out, re.MULTILINE)
assert return_value == 0
# NOTE: The radio may not be responsive after this, may need to do a manual reboot
# by pressing the button</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.test.test_smoke1.test_smoke1_ch_add_and_ch_del"><code class="name flex">
<span>def <span class="ident">test_smoke1_ch_add_and_ch_del</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;ch-add</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_ch_add_and_ch_del():
&#34;&#34;&#34;Test --ch-add&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-add testing&#39;)
assert re.search(r&#39;Writing modified channels to device&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;SECONDARY&#39;, out, re.MULTILINE)
assert re.search(r&#39;testing&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-index 1 --ch-del&#39;)
assert re.search(r&#39;Deleting channel 1&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
# make sure the secondar channel is not there
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert not re.search(r&#39;SECONDARY&#39;, out, re.MULTILINE)
assert not re.search(r&#39;testing&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_ch_set_modem_config"><code class="name flex">
<span>def <span class="ident">test_smoke1_ch_set_modem_config</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;ch-set modem_config</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_ch_set_modem_config():
&#34;&#34;&#34;Test --ch-set modem_config&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert not re.search(r&#39;Bw31_25Cr48Sf512&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-set modem_config Bw31_25Cr48Sf512&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set modem_config to Bw31_25Cr48Sf512&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;Bw31_25Cr48Sf512&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_ch_set_name"><code class="name flex">
<span>def <span class="ident">test_smoke1_ch_set_name</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;ch-set name</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_ch_set_name():
&#34;&#34;&#34;Test --ch-set name&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert not re.search(r&#39;MyChannel&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-set name MyChannel&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set name to MyChannel&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;MyChannel&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_ch_values"><code class="name flex">
<span>def <span class="ident">test_smoke1_ch_values</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;ch-longslow, &ndash;ch-longfast, &ndash;ch-mediumslow, &ndash;ch-mediumsfast,
&ndash;ch-shortslow, and &ndash;ch-shortfast arguments</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_ch_values():
&#34;&#34;&#34;Test --ch-longslow, --ch-longfast, --ch-mediumslow, --ch-mediumsfast,
--ch-shortslow, and --ch-shortfast arguments
&#34;&#34;&#34;
exp = {
&#39;--ch-longslow&#39;: &#39;Bw125Cr48Sf4096&#39;,
# TODO: not sure why these fail thru tests, but ok manually
#&#39;--ch-longfast&#39;: &#39;Bw31_25Cr48Sf512&#39;,
#&#39;--ch-mediumslow&#39;: &#39;Bw250Cr46Sf2048&#39;,
#&#39;--ch-mediumfast&#39;: &#39;Bw250Cr47Sf1024&#39;,
# TODO &#39;--ch-shortslow&#39;: &#39;?&#39;,
&#39;--ch-shortfast&#39;: &#39;Bw500Cr45Sf128&#39;
}
for key, val in exp.items():
print(key, val)
return_value, out = subprocess.getstatusoutput(f&#39;meshtastic {key}&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;Writing modified channels to device&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio (might reboot)
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(val, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_configure"><code class="name flex">
<span>def <span class="ident">test_smoke1_configure</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;configure</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_configure():
&#34;&#34;&#34;Test --configure&#34;&#34;&#34;
_ , out = subprocess.getstatusoutput(f&#34;meshtastic --configure example_config.yaml&#34;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(&#39;^Setting device owner to Bob TBeam&#39;, out, re.MULTILINE)
assert re.search(&#39;^Fixing altitude at 304 meters&#39;, out, re.MULTILINE)
assert re.search(&#39;^Fixing latitude at 35.8&#39;, out, re.MULTILINE)
assert re.search(&#39;^Fixing longitude at -93.8&#39;, out, re.MULTILINE)
assert re.search(&#39;^Setting device position&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set region to 1&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set is_always_powered to true&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set send_owner_interval to 2&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set screen_on_secs to 31536000&#39;, out, re.MULTILINE)
assert re.search(&#39;^Set wait_bluetooth_secs to 31536000&#39;, out, re.MULTILINE)
assert re.search(&#39;^Writing modified preferences to device&#39;, out, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_debug"><code class="name flex">
<span>def <span class="ident">test_smoke1_debug</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;debug</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_debug():
&#34;&#34;&#34;Test --debug&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info --debug&#39;)
assert re.search(r&#39;^Owner&#39;, out, re.MULTILINE)
assert re.search(r&#39;^DEBUG:root&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_factory_reset"><code class="name flex">
<span>def <span class="ident">test_smoke1_factory_reset</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test factory reset</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_factory_reset():
&#34;&#34;&#34;Test factory reset&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set factory_reset true&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set factory_reset to true&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Writing modified preferences to device&#39;, out, re.MULTILINE)
assert return_value == 0
# NOTE: The radio may not be responsive after this, may need to do a manual reboot
# by pressing the button</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_info"><code class="name flex">
<span>def <span class="ident">test_smoke1_info</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;info</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_info():
&#34;&#34;&#34;Test --info&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Owner&#39;, out, re.MULTILINE)
assert re.search(r&#39;^My info&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Nodes in mesh&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Preferences&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Channels&#39;, out, re.MULTILINE)
assert re.search(r&#39;^ PRIMARY&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Primary channel URL&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_nodes"><code class="name flex">
<span>def <span class="ident">test_smoke1_nodes</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;nodes</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_nodes():
&#34;&#34;&#34;Test --nodes&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --nodes&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^│ N │ User&#39;, out, re.MULTILINE)
assert re.search(r&#39;^│ 1 │&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_port"><code class="name flex">
<span>def <span class="ident">test_smoke1_port</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;port</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_port():
&#34;&#34;&#34;Test --port&#34;&#34;&#34;
# first, get the ports
ports = meshtastic.util.findPorts()
# hopefully there is just one
assert len(ports) == 1
port = ports[0]
return_value, out = subprocess.getstatusoutput(f&#39;meshtastic --port {port} --info&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Owner&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_qr"><code class="name flex">
<span>def <span class="ident">test_smoke1_qr</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;qr</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_qr():
&#34;&#34;&#34;Test --qr&#34;&#34;&#34;
filename = &#39;tmpqr&#39;
if os.path.exists(f&#34;{filename}&#34;):
os.remove(f&#34;{filename}&#34;)
return_value, _ = subprocess.getstatusoutput(f&#39;meshtastic --qr &gt; {filename}&#39;)
assert os.path.exists(f&#34;{filename}&#34;)
# not really testing that a valid qr code is created, just that the file size
# is reasonably big enough for a qr code
assert os.stat(f&#34;{filename}&#34;).st_size &gt; 20000
assert return_value == 0
os.remove(f&#34;{filename}&#34;)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_reboot"><code class="name flex">
<span>def <span class="ident">test_smoke1_reboot</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test reboot</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_reboot():
&#34;&#34;&#34;Test reboot&#34;&#34;&#34;
return_value, _ = subprocess.getstatusoutput(&#39;meshtastic --reboot&#39;)
assert return_value == 0
# pause for the radio to reset (10 seconds for the pause, and a few more seconds to be back up)
time.sleep(18)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_send_hello"><code class="name flex">
<span>def <span class="ident">test_smoke1_send_hello</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;sendtext hello</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_send_hello():
&#34;&#34;&#34;Test --sendtext hello&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --sendtext hello&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Sending text message hello to \^all&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_seriallog_to_file"><code class="name flex">
<span>def <span class="ident">test_smoke1_seriallog_to_file</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;seriallog to a file creates a file</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_seriallog_to_file():
&#34;&#34;&#34;Test --seriallog to a file creates a file&#34;&#34;&#34;
filename = &#39;tmpoutput.txt&#39;
if os.path.exists(f&#34;{filename}&#34;):
os.remove(f&#34;{filename}&#34;)
return_value, _ = subprocess.getstatusoutput(f&#39;meshtastic --info --seriallog {filename}&#39;)
assert os.path.exists(f&#34;{filename}&#34;)
assert return_value == 0
os.remove(f&#34;{filename}&#34;)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_set_is_router_false"><code class="name flex">
<span>def <span class="ident">test_smoke1_set_is_router_false</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;set is_router false</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_set_is_router_false():
&#34;&#34;&#34;Test --set is_router false&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set is_router false&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set is_router to false&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --get is_router&#39;)
assert re.search(r&#39;^is_router: False&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_set_is_router_true"><code class="name flex">
<span>def <span class="ident">test_smoke1_set_is_router_true</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;set is_router true</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_set_is_router_true():
&#34;&#34;&#34;Test --set is_router true&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set is_router true&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Set is_router to true&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --get is_router&#39;)
assert re.search(r&#39;^is_router: True&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_set_location_info"><code class="name flex">
<span>def <span class="ident">test_smoke1_set_location_info</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;setlat, &ndash;setlon and &ndash;setalt</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_set_location_info():
&#34;&#34;&#34;Test --setlat, --setlon and --setalt &#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --setlat 32.7767 --setlon -96.7970 --setalt 1337&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Fixing altitude&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Fixing latitude&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Fixing longitude&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out2 = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;1337&#39;, out2, re.MULTILINE)
assert re.search(r&#39;32.7767&#39;, out2, re.MULTILINE)
assert re.search(r&#39;-96.797&#39;, out2, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_set_owner"><code class="name flex">
<span>def <span class="ident">test_smoke1_set_owner</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;set-owner name</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_set_owner():
&#34;&#34;&#34;Test --set-owner name&#34;&#34;&#34;
# make sure the owner is not Joe
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set-owner Bob&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Setting device owner to Bob&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert not re.search(r&#39;Owner: Joe&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set-owner Joe&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Setting device owner to Joe&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;Owner: Joe&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_set_team"><code class="name flex">
<span>def <span class="ident">test_smoke1_set_team</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;set-team</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_set_team():
&#34;&#34;&#34;Test --set-team &#34;&#34;&#34;
# unset the team
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set-team CLEAR&#39;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(r&#39;^Setting team to CLEAR&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --set-team CYAN&#39;)
assert re.search(r&#39;Setting team to CYAN&#39;, out, re.MULTILINE)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_REBOOT)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;CYAN&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_seturl_default"><code class="name flex">
<span>def <span class="ident">test_smoke1_seturl_default</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;seturl with default value</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_seturl_default():
&#34;&#34;&#34;Test --seturl with default value&#34;&#34;&#34;
# set some channel value so we no longer have a default channel
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --ch-set name foo&#39;)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
# ensure we no longer have a default primary channel
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert not re.search(&#39;CgUYAyIBAQ&#39;, out, re.MULTILINE)
assert return_value == 0
url = &#34;https://www.meshtastic.org/d/#CgUYAyIBAQ&#34;
return_value, out = subprocess.getstatusoutput(f&#34;meshtastic --seturl {url}&#34;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert return_value == 0
# pause for the radio
time.sleep(PAUSE_AFTER_COMMAND)
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(&#39;CgUYAyIBAQ&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_smoke1.test_smoke1_seturl_invalid_url"><code class="name flex">
<span>def <span class="ident">test_smoke1_seturl_invalid_url</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;seturl with invalid url</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke1
def test_smoke1_seturl_invalid_url():
&#34;&#34;&#34;Test --seturl with invalid url&#34;&#34;&#34;
# Note: This url is no longer a valid url.
url = &#34;https://www.meshtastic.org/c/#GAMiENTxuzogKQdZ8Lz_q89Oab8qB0RlZmF1bHQ=&#34;
return_value, out = subprocess.getstatusoutput(f&#34;meshtastic --seturl {url}&#34;)
assert re.match(r&#39;Connected to radio&#39;, out)
assert re.search(&#39;Warning: There were no settings&#39;, out, re.MULTILINE)
assert return_value == 1</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.test" href="index.html">meshtastic.test</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_ch_add_and_ch_del" href="#meshtastic.test.test_smoke1.test_smoke1_ch_add_and_ch_del">test_smoke1_ch_add_and_ch_del</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_ch_set_modem_config" href="#meshtastic.test.test_smoke1.test_smoke1_ch_set_modem_config">test_smoke1_ch_set_modem_config</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_ch_set_name" href="#meshtastic.test.test_smoke1.test_smoke1_ch_set_name">test_smoke1_ch_set_name</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_ch_values" href="#meshtastic.test.test_smoke1.test_smoke1_ch_values">test_smoke1_ch_values</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_configure" href="#meshtastic.test.test_smoke1.test_smoke1_configure">test_smoke1_configure</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_debug" href="#meshtastic.test.test_smoke1.test_smoke1_debug">test_smoke1_debug</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_factory_reset" href="#meshtastic.test.test_smoke1.test_smoke1_factory_reset">test_smoke1_factory_reset</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_info" href="#meshtastic.test.test_smoke1.test_smoke1_info">test_smoke1_info</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_nodes" href="#meshtastic.test.test_smoke1.test_smoke1_nodes">test_smoke1_nodes</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_port" href="#meshtastic.test.test_smoke1.test_smoke1_port">test_smoke1_port</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_qr" href="#meshtastic.test.test_smoke1.test_smoke1_qr">test_smoke1_qr</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_reboot" href="#meshtastic.test.test_smoke1.test_smoke1_reboot">test_smoke1_reboot</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_send_hello" href="#meshtastic.test.test_smoke1.test_smoke1_send_hello">test_smoke1_send_hello</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_seriallog_to_file" href="#meshtastic.test.test_smoke1.test_smoke1_seriallog_to_file">test_smoke1_seriallog_to_file</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_set_is_router_false" href="#meshtastic.test.test_smoke1.test_smoke1_set_is_router_false">test_smoke1_set_is_router_false</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_set_is_router_true" href="#meshtastic.test.test_smoke1.test_smoke1_set_is_router_true">test_smoke1_set_is_router_true</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_set_location_info" href="#meshtastic.test.test_smoke1.test_smoke1_set_location_info">test_smoke1_set_location_info</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_set_owner" href="#meshtastic.test.test_smoke1.test_smoke1_set_owner">test_smoke1_set_owner</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_set_team" href="#meshtastic.test.test_smoke1.test_smoke1_set_team">test_smoke1_set_team</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_seturl_default" href="#meshtastic.test.test_smoke1.test_smoke1_seturl_default">test_smoke1_seturl_default</a></code></li>
<li><code><a title="meshtastic.test.test_smoke1.test_smoke1_seturl_invalid_url" href="#meshtastic.test.test_smoke1.test_smoke1_seturl_invalid_url">test_smoke1_seturl_invalid_url</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,236 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.test.test_util API documentation</title>
<meta name="description" content="Meshtastic unit tests for node.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.test.test_util</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for node.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for node.py&#34;&#34;&#34;
import pytest
from meshtastic.util import pskToString, our_exit
@pytest.mark.unit
def test_pskToString_empty_string():
&#34;&#34;&#34;Test pskToString empty string&#34;&#34;&#34;
assert pskToString(&#39;&#39;) == &#39;unencrypted&#39;
@pytest.mark.unit
def test_pskToString_string():
&#34;&#34;&#34;Test pskToString string&#34;&#34;&#34;
assert pskToString(&#39;hunter123&#39;) == &#39;secret&#39;
@pytest.mark.unit
def test_pskToString_one_byte_zero_value():
&#34;&#34;&#34;Test pskToString one byte that is value of 0&#34;&#34;&#34;
assert pskToString(bytes([0x00])) == &#39;unencrypted&#39;
@pytest.mark.unit
def test_pskToString_one_byte_non_zero_value():
&#34;&#34;&#34;Test pskToString one byte that is non-zero&#34;&#34;&#34;
assert pskToString(bytes([0x01])) == &#39;default&#39;
@pytest.mark.unit
def test_pskToString_many_bytes():
&#34;&#34;&#34;Test pskToString many bytes&#34;&#34;&#34;
assert pskToString(bytes([0x02, 0x01])) == &#39;secret&#39;
@pytest.mark.unit
def test_our_exit_zero_return_value():
&#34;&#34;&#34;Test our_exit with a zero return value&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
our_exit(&#34;Warning: Some message&#34;, 0)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0
@pytest.mark.unit
def test_our_exit_non_zero_return_value():
&#34;&#34;&#34;Test our_exit with a non-zero return value&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
our_exit(&#34;Error: Some message&#34;, 1)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.test.test_util.test_our_exit_non_zero_return_value"><code class="name flex">
<span>def <span class="ident">test_our_exit_non_zero_return_value</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test our_exit with a non-zero return value</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_our_exit_non_zero_return_value():
&#34;&#34;&#34;Test our_exit with a non-zero return value&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
our_exit(&#34;Error: Some message&#34;, 1)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_util.test_our_exit_zero_return_value"><code class="name flex">
<span>def <span class="ident">test_our_exit_zero_return_value</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test our_exit with a zero return value</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_our_exit_zero_return_value():
&#34;&#34;&#34;Test our_exit with a zero return value&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
our_exit(&#34;Warning: Some message&#34;, 0)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_util.test_pskToString_empty_string"><code class="name flex">
<span>def <span class="ident">test_pskToString_empty_string</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString empty string</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_empty_string():
&#34;&#34;&#34;Test pskToString empty string&#34;&#34;&#34;
assert pskToString(&#39;&#39;) == &#39;unencrypted&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_util.test_pskToString_many_bytes"><code class="name flex">
<span>def <span class="ident">test_pskToString_many_bytes</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString many bytes</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_many_bytes():
&#34;&#34;&#34;Test pskToString many bytes&#34;&#34;&#34;
assert pskToString(bytes([0x02, 0x01])) == &#39;secret&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_util.test_pskToString_one_byte_non_zero_value"><code class="name flex">
<span>def <span class="ident">test_pskToString_one_byte_non_zero_value</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString one byte that is non-zero</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_one_byte_non_zero_value():
&#34;&#34;&#34;Test pskToString one byte that is non-zero&#34;&#34;&#34;
assert pskToString(bytes([0x01])) == &#39;default&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_util.test_pskToString_one_byte_zero_value"><code class="name flex">
<span>def <span class="ident">test_pskToString_one_byte_zero_value</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString one byte that is value of 0</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_one_byte_zero_value():
&#34;&#34;&#34;Test pskToString one byte that is value of 0&#34;&#34;&#34;
assert pskToString(bytes([0x00])) == &#39;unencrypted&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.test.test_util.test_pskToString_string"><code class="name flex">
<span>def <span class="ident">test_pskToString_string</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString string</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_string():
&#34;&#34;&#34;Test pskToString string&#34;&#34;&#34;
assert pskToString(&#39;hunter123&#39;) == &#39;secret&#39;</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.test" href="index.html">meshtastic.test</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.test.test_util.test_our_exit_non_zero_return_value" href="#meshtastic.test.test_util.test_our_exit_non_zero_return_value">test_our_exit_non_zero_return_value</a></code></li>
<li><code><a title="meshtastic.test.test_util.test_our_exit_zero_return_value" href="#meshtastic.test.test_util.test_our_exit_zero_return_value">test_our_exit_zero_return_value</a></code></li>
<li><code><a title="meshtastic.test.test_util.test_pskToString_empty_string" href="#meshtastic.test.test_util.test_pskToString_empty_string">test_pskToString_empty_string</a></code></li>
<li><code><a title="meshtastic.test.test_util.test_pskToString_many_bytes" href="#meshtastic.test.test_util.test_pskToString_many_bytes">test_pskToString_many_bytes</a></code></li>
<li><code><a title="meshtastic.test.test_util.test_pskToString_one_byte_non_zero_value" href="#meshtastic.test.test_util.test_pskToString_one_byte_non_zero_value">test_pskToString_one_byte_non_zero_value</a></code></li>
<li><code><a title="meshtastic.test.test_util.test_pskToString_one_byte_zero_value" href="#meshtastic.test.test_util.test_pskToString_one_byte_zero_value">test_pskToString_one_byte_zero_value</a></code></li>
<li><code><a title="meshtastic.test.test_util.test_pskToString_string" href="#meshtastic.test.test_util.test_pskToString_string">test_pskToString_string</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,100 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.conftest API documentation</title>
<meta name="description" content="Common pytest code (place for fixtures)." />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.conftest</code></h1>
</header>
<section id="section-intro">
<p>Common pytest code (place for fixtures).</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Common pytest code (place for fixtures).&#34;&#34;&#34;
import argparse
import pytest
from meshtastic.__main__ import Globals
@pytest.fixture
def reset_globals():
&#34;&#34;&#34;Fixture to reset globals.&#34;&#34;&#34;
parser = None
parser = argparse.ArgumentParser()
Globals.getInstance().reset()
Globals.getInstance().set_parser(parser)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.conftest.reset_globals"><code class="name flex">
<span>def <span class="ident">reset_globals</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Fixture to reset globals.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.fixture
def reset_globals():
&#34;&#34;&#34;Fixture to reset globals.&#34;&#34;&#34;
parser = None
parser = argparse.ArgumentParser()
Globals.getInstance().reset()
Globals.getInstance().set_parser(parser)</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.conftest.reset_globals" href="#meshtastic.tests.conftest.reset_globals">reset_globals</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,130 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests</code></h1>
</header>
<section id="section-intro">
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="meshtastic.tests.conftest" href="conftest.html">meshtastic.tests.conftest</a></code></dt>
<dd>
<div class="desc"><p>Common pytest code (place for fixtures).</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_ble_interface" href="test_ble_interface.html">meshtastic.tests.test_ble_interface</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for ble_interface.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_globals" href="test_globals.html">meshtastic.tests.test_globals</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for globals.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_int" href="test_int.html">meshtastic.tests.test_int</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic integration tests</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_main" href="test_main.html">meshtastic.tests.test_main</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for <strong>main</strong>.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_mesh_interface" href="test_mesh_interface.html">meshtastic.tests.test_mesh_interface</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for mesh_interface.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_node" href="test_node.html">meshtastic.tests.test_node</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for node.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_serial_interface" href="test_serial_interface.html">meshtastic.tests.test_serial_interface</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for serial_interface.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_smoke1" href="test_smoke1.html">meshtastic.tests.test_smoke1</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic smoke tests with a single device via USB</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_smoke2" href="test_smoke2.html">meshtastic.tests.test_smoke2</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic smoke tests with 2 devices connected via USB</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_smoke_wifi" href="test_smoke_wifi.html">meshtastic.tests.test_smoke_wifi</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic smoke tests a device setup with wifi …</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_stream_interface" href="test_stream_interface.html">meshtastic.tests.test_stream_interface</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for stream_interface.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_tcp_interface" href="test_tcp_interface.html">meshtastic.tests.test_tcp_interface</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for tcp_interface.py</p></div>
</dd>
<dt><code class="name"><a title="meshtastic.tests.test_util" href="test_util.html">meshtastic.tests.test_util</a></code></dt>
<dd>
<div class="desc"><p>Meshtastic unit tests for util.py</p></div>
</dd>
</dl>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="../index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="meshtastic.tests.conftest" href="conftest.html">meshtastic.tests.conftest</a></code></li>
<li><code><a title="meshtastic.tests.test_ble_interface" href="test_ble_interface.html">meshtastic.tests.test_ble_interface</a></code></li>
<li><code><a title="meshtastic.tests.test_globals" href="test_globals.html">meshtastic.tests.test_globals</a></code></li>
<li><code><a title="meshtastic.tests.test_int" href="test_int.html">meshtastic.tests.test_int</a></code></li>
<li><code><a title="meshtastic.tests.test_main" href="test_main.html">meshtastic.tests.test_main</a></code></li>
<li><code><a title="meshtastic.tests.test_mesh_interface" href="test_mesh_interface.html">meshtastic.tests.test_mesh_interface</a></code></li>
<li><code><a title="meshtastic.tests.test_node" href="test_node.html">meshtastic.tests.test_node</a></code></li>
<li><code><a title="meshtastic.tests.test_serial_interface" href="test_serial_interface.html">meshtastic.tests.test_serial_interface</a></code></li>
<li><code><a title="meshtastic.tests.test_smoke1" href="test_smoke1.html">meshtastic.tests.test_smoke1</a></code></li>
<li><code><a title="meshtastic.tests.test_smoke2" href="test_smoke2.html">meshtastic.tests.test_smoke2</a></code></li>
<li><code><a title="meshtastic.tests.test_smoke_wifi" href="test_smoke_wifi.html">meshtastic.tests.test_smoke_wifi</a></code></li>
<li><code><a title="meshtastic.tests.test_stream_interface" href="test_stream_interface.html">meshtastic.tests.test_stream_interface</a></code></li>
<li><code><a title="meshtastic.tests.test_tcp_interface" href="test_tcp_interface.html">meshtastic.tests.test_tcp_interface</a></code></li>
<li><code><a title="meshtastic.tests.test_util" href="test_util.html">meshtastic.tests.test_util</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,95 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_ble_interface API documentation</title>
<meta name="description" content="Meshtastic unit tests for ble_interface.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_ble_interface</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for ble_interface.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for ble_interface.py&#34;&#34;&#34;
import pytest
from ..ble_interface import BLEInterface
@pytest.mark.unit
def test_BLEInterface():
&#34;&#34;&#34;Test that we can instantiate a BLEInterface&#34;&#34;&#34;
iface = BLEInterface(&#39;foo&#39;, debugOut=True, noProto=True)
iface.close()</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_ble_interface.test_BLEInterface"><code class="name flex">
<span>def <span class="ident">test_BLEInterface</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a BLEInterface</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_BLEInterface():
&#34;&#34;&#34;Test that we can instantiate a BLEInterface&#34;&#34;&#34;
iface = BLEInterface(&#39;foo&#39;, debugOut=True, noProto=True)
iface.close()</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_ble_interface.test_BLEInterface" href="#meshtastic.tests.test_ble_interface.test_BLEInterface">test_BLEInterface</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,130 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_globals API documentation</title>
<meta name="description" content="Meshtastic unit tests for globals.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_globals</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for globals.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for globals.py
&#34;&#34;&#34;
import pytest
from ..globals import Globals
@pytest.mark.unit
def test_globals_get_instaance():
&#34;&#34;&#34;Test that we can instantiate a Globals instance&#34;&#34;&#34;
ourglobals = Globals.getInstance()
ourglobals2 = Globals.getInstance()
assert ourglobals == ourglobals2
@pytest.mark.unit
def test_globals_there_can_be_only_one():
&#34;&#34;&#34;Test that we can cannot create two Globals instances&#34;&#34;&#34;
# if we have an instance, delete it
Globals.getInstance()
with pytest.raises(Exception) as pytest_wrapped_e:
# try to create another instance
Globals()
assert pytest_wrapped_e.type == Exception</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_globals.test_globals_get_instaance"><code class="name flex">
<span>def <span class="ident">test_globals_get_instaance</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a Globals instance</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_globals_get_instaance():
&#34;&#34;&#34;Test that we can instantiate a Globals instance&#34;&#34;&#34;
ourglobals = Globals.getInstance()
ourglobals2 = Globals.getInstance()
assert ourglobals == ourglobals2</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_globals.test_globals_there_can_be_only_one"><code class="name flex">
<span>def <span class="ident">test_globals_there_can_be_only_one</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can cannot create two Globals instances</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_globals_there_can_be_only_one():
&#34;&#34;&#34;Test that we can cannot create two Globals instances&#34;&#34;&#34;
# if we have an instance, delete it
Globals.getInstance()
with pytest.raises(Exception) as pytest_wrapped_e:
# try to create another instance
Globals()
assert pytest_wrapped_e.type == Exception</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_globals.test_globals_get_instaance" href="#meshtastic.tests.test_globals.test_globals_get_instaance">test_globals_get_instaance</a></code></li>
<li><code><a title="meshtastic.tests.test_globals.test_globals_there_can_be_only_one" href="#meshtastic.tests.test_globals.test_globals_there_can_be_only_one">test_globals_there_can_be_only_one</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,177 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_int API documentation</title>
<meta name="description" content="Meshtastic integration tests" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_int</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic integration tests</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic integration tests&#34;&#34;&#34;
import re
import subprocess
import pytest
@pytest.mark.int
def test_int_no_args():
&#34;&#34;&#34;Test without any args&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic&#39;)
assert re.match(r&#39;usage: meshtastic&#39;, out)
assert return_value == 1
@pytest.mark.int
def test_int_version():
&#34;&#34;&#34;Test &#39;--version&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --version&#39;)
assert re.match(r&#39;[0-9]+\.[0-9]+\.[0-9]&#39;, out)
assert return_value == 0
@pytest.mark.int
def test_int_help():
&#34;&#34;&#34;Test &#39;--help&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --help&#39;)
assert re.match(r&#39;usage: meshtastic &#39;, out)
assert return_value == 0
@pytest.mark.int
def test_int_support():
&#34;&#34;&#34;Test &#39;--support&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --support&#39;)
assert re.search(r&#39;System&#39;, out)
assert re.search(r&#39;Python&#39;, out)
assert return_value == 0</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_int.test_int_help"><code class="name flex">
<span>def <span class="ident">test_int_help</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test '&ndash;help'.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.int
def test_int_help():
&#34;&#34;&#34;Test &#39;--help&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --help&#39;)
assert re.match(r&#39;usage: meshtastic &#39;, out)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_int.test_int_no_args"><code class="name flex">
<span>def <span class="ident">test_int_no_args</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test without any args</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.int
def test_int_no_args():
&#34;&#34;&#34;Test without any args&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic&#39;)
assert re.match(r&#39;usage: meshtastic&#39;, out)
assert return_value == 1</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_int.test_int_support"><code class="name flex">
<span>def <span class="ident">test_int_support</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test '&ndash;support'.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.int
def test_int_support():
&#34;&#34;&#34;Test &#39;--support&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --support&#39;)
assert re.search(r&#39;System&#39;, out)
assert re.search(r&#39;Python&#39;, out)
assert return_value == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_int.test_int_version"><code class="name flex">
<span>def <span class="ident">test_int_version</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test '&ndash;version'.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.int
def test_int_version():
&#34;&#34;&#34;Test &#39;--version&#39;.&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --version&#39;)
assert re.match(r&#39;[0-9]+\.[0-9]+\.[0-9]&#39;, out)
assert return_value == 0</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_int.test_int_help" href="#meshtastic.tests.test_int.test_int_help">test_int_help</a></code></li>
<li><code><a title="meshtastic.tests.test_int.test_int_no_args" href="#meshtastic.tests.test_int.test_int_no_args">test_int_no_args</a></code></li>
<li><code><a title="meshtastic.tests.test_int.test_int_support" href="#meshtastic.tests.test_int.test_int_support">test_int_support</a></code></li>
<li><code><a title="meshtastic.tests.test_int.test_int_version" href="#meshtastic.tests.test_int.test_int_version">test_int_version</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,117 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_mesh_interface API documentation</title>
<meta name="description" content="Meshtastic unit tests for mesh_interface.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_mesh_interface</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for mesh_interface.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for mesh_interface.py&#34;&#34;&#34;
import re
import pytest
from ..mesh_interface import MeshInterface
@pytest.mark.unit
def test_MeshInterface(capsys):
&#34;&#34;&#34;Test that we can instantiate a MeshInterface&#34;&#34;&#34;
iface = MeshInterface(noProto=True)
iface.showInfo()
iface.localNode.showInfo()
iface.showNodes()
iface.close()
out, err = capsys.readouterr()
assert re.search(r&#39;Owner: None \(None\)&#39;, out, re.MULTILINE)
assert re.search(r&#39;Nodes&#39;, out, re.MULTILINE)
assert re.search(r&#39;Preferences&#39;, out, re.MULTILINE)
assert re.search(r&#39;Channels&#39;, out, re.MULTILINE)
assert re.search(r&#39;Primary channel URL&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_mesh_interface.test_MeshInterface"><code class="name flex">
<span>def <span class="ident">test_MeshInterface</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a MeshInterface</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_MeshInterface(capsys):
&#34;&#34;&#34;Test that we can instantiate a MeshInterface&#34;&#34;&#34;
iface = MeshInterface(noProto=True)
iface.showInfo()
iface.localNode.showInfo()
iface.showNodes()
iface.close()
out, err = capsys.readouterr()
assert re.search(r&#39;Owner: None \(None\)&#39;, out, re.MULTILINE)
assert re.search(r&#39;Nodes&#39;, out, re.MULTILINE)
assert re.search(r&#39;Preferences&#39;, out, re.MULTILINE)
assert re.search(r&#39;Channels&#39;, out, re.MULTILINE)
assert re.search(r&#39;Primary channel URL&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_mesh_interface.test_MeshInterface" href="#meshtastic.tests.test_mesh_interface.test_MeshInterface">test_MeshInterface</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,951 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_node API documentation</title>
<meta name="description" content="Meshtastic unit tests for node.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_node</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for node.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for node.py&#34;&#34;&#34;
import re
from unittest.mock import patch, MagicMock
import pytest
from ..node import Node
from ..serial_interface import SerialInterface
from ..admin_pb2 import AdminMessage
@pytest.mark.unit
def test_node(capsys):
&#34;&#34;&#34;Test that we can instantiate a Node&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
anode.showChannels()
anode.showInfo()
out, err = capsys.readouterr()
assert re.search(r&#39;Preferences&#39;, out)
assert re.search(r&#39;Channels&#39;, out)
assert re.search(r&#39;Primary channel URL&#39;, out)
assert err == &#39;&#39;
@pytest.mark.unit
def test_node_reqquestConfig():
&#34;&#34;&#34;Test run requestConfig&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
amesg = MagicMock(autospec=AdminMessage)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
with patch(&#39;meshtastic.admin_pb2.AdminMessage&#39;, return_value=amesg):
anode = Node(mo, &#39;bar&#39;)
anode.requestConfig()</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_node.test_node"><code class="name flex">
<span>def <span class="ident">test_node</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a Node</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_node(capsys):
&#34;&#34;&#34;Test that we can instantiate a Node&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
anode.showChannels()
anode.showInfo()
out, err = capsys.readouterr()
assert re.search(r&#39;Preferences&#39;, out)
assert re.search(r&#39;Channels&#39;, out)
assert re.search(r&#39;Primary channel URL&#39;, out)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_node_reqquestConfig"><code class="name flex">
<span>def <span class="ident">test_node_reqquestConfig</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test run requestConfig</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_node_reqquestConfig():
&#34;&#34;&#34;Test run requestConfig&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
amesg = MagicMock(autospec=AdminMessage)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
with patch(&#39;meshtastic.admin_pb2.AdminMessage&#39;, return_value=amesg):
anode = Node(mo, &#39;bar&#39;)
anode.requestConfig()</code></pre>
</details>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.tests.test_node.AdminMessage"><code class="flex name class">
<span>class <span class="ident">AdminMessage</span></span>
<span>(</span><span>**kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Abstract base class for protocol messages.</p>
<p>Protocol message classes are almost always generated by the protocol
compiler.
These generated types subclass Message and implement the methods
shown below.</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="meshtastic.tests.test_node.AdminMessage.CONFIRM_SET_CHANNEL_FIELD_NUMBER"><code class="name">var <span class="ident">CONFIRM_SET_CHANNEL_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.CONFIRM_SET_RADIO_FIELD_NUMBER"><code class="name">var <span class="ident">CONFIRM_SET_RADIO_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.EXIT_SIMULATOR_FIELD_NUMBER"><code class="name">var <span class="ident">EXIT_SIMULATOR_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.GET_CHANNEL_REQUEST_FIELD_NUMBER"><code class="name">var <span class="ident">GET_CHANNEL_REQUEST_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.GET_CHANNEL_RESPONSE_FIELD_NUMBER"><code class="name">var <span class="ident">GET_CHANNEL_RESPONSE_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.GET_RADIO_REQUEST_FIELD_NUMBER"><code class="name">var <span class="ident">GET_RADIO_REQUEST_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.GET_RADIO_RESPONSE_FIELD_NUMBER"><code class="name">var <span class="ident">GET_RADIO_RESPONSE_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.REBOOT_SECONDS_FIELD_NUMBER"><code class="name">var <span class="ident">REBOOT_SECONDS_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.SET_CHANNEL_FIELD_NUMBER"><code class="name">var <span class="ident">SET_CHANNEL_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.SET_OWNER_FIELD_NUMBER"><code class="name">var <span class="ident">SET_OWNER_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.SET_RADIO_FIELD_NUMBER"><code class="name">var <span class="ident">SET_RADIO_FIELD_NUMBER</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Static methods</h3>
<dl>
<dt id="meshtastic.tests.test_node.AdminMessage.FromString"><code class="name flex">
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FromString(s):
message = cls()
message.MergeFromString(s)
return message</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.RegisterExtension"><code class="name flex">
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def RegisterExtension(extension_handle):
extension_handle.containing_type = cls.DESCRIPTOR
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
# pylint: disable=protected-access
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
_AttachFieldHelpers(cls, extension_handle)</code></pre>
</details>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.tests.test_node.AdminMessage.confirm_set_channel"><code class="name">var <span class="ident">confirm_set_channel</span></code></dt>
<dd>
<div class="desc"><p>Getter for confirm_set_channel.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.confirm_set_radio"><code class="name">var <span class="ident">confirm_set_radio</span></code></dt>
<dd>
<div class="desc"><p>Getter for confirm_set_radio.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.exit_simulator"><code class="name">var <span class="ident">exit_simulator</span></code></dt>
<dd>
<div class="desc"><p>Getter for exit_simulator.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.get_channel_request"><code class="name">var <span class="ident">get_channel_request</span></code></dt>
<dd>
<div class="desc"><p>Getter for get_channel_request.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.get_channel_response"><code class="name">var <span class="ident">get_channel_response</span></code></dt>
<dd>
<div class="desc"><p>Getter for get_channel_response.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
# take that object and discard ours.
# WARNING: We are relying on setdefault() being atomic. This is true
# in CPython but we haven&#39;t investigated others. This warning appears
# in several other locations in this file.
field_value = self._fields.setdefault(field, field_value)
return field_value</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.get_radio_request"><code class="name">var <span class="ident">get_radio_request</span></code></dt>
<dd>
<div class="desc"><p>Getter for get_radio_request.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.get_radio_response"><code class="name">var <span class="ident">get_radio_response</span></code></dt>
<dd>
<div class="desc"><p>Getter for get_radio_response.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
# take that object and discard ours.
# WARNING: We are relying on setdefault() being atomic. This is true
# in CPython but we haven&#39;t investigated others. This warning appears
# in several other locations in this file.
field_value = self._fields.setdefault(field, field_value)
return field_value</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.reboot_seconds"><code class="name">var <span class="ident">reboot_seconds</span></code></dt>
<dd>
<div class="desc"><p>Getter for reboot_seconds.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
# default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.set_channel"><code class="name">var <span class="ident">set_channel</span></code></dt>
<dd>
<div class="desc"><p>Getter for set_channel.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
# take that object and discard ours.
# WARNING: We are relying on setdefault() being atomic. This is true
# in CPython but we haven&#39;t investigated others. This warning appears
# in several other locations in this file.
field_value = self._fields.setdefault(field, field_value)
return field_value</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.set_owner"><code class="name">var <span class="ident">set_owner</span></code></dt>
<dd>
<div class="desc"><p>Getter for set_owner.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
# take that object and discard ours.
# WARNING: We are relying on setdefault() being atomic. This is true
# in CPython but we haven&#39;t investigated others. This warning appears
# in several other locations in this file.
field_value = self._fields.setdefault(field, field_value)
return field_value</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.set_radio"><code class="name">var <span class="ident">set_radio</span></code></dt>
<dd>
<div class="desc"><p>Getter for set_radio.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
# take that object and discard ours.
# WARNING: We are relying on setdefault() being atomic. This is true
# in CPython but we haven&#39;t investigated others. This warning appears
# in several other locations in this file.
field_value = self._fields.setdefault(field, field_value)
return field_value</code></pre>
</details>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.tests.test_node.AdminMessage.ByteSize"><code class="name flex">
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ByteSize(self):
if not self._cached_byte_size_dirty:
return self._cached_byte_size
size = 0
descriptor = self.DESCRIPTOR
if descriptor.GetOptions().map_entry:
# Fields of map entry should always be serialized.
size = descriptor.fields_by_name[&#39;key&#39;]._sizer(self.key)
size += descriptor.fields_by_name[&#39;value&#39;]._sizer(self.value)
else:
for field_descriptor, field_value in self.ListFields():
size += field_descriptor._sizer(field_value)
for tag_bytes, value_bytes in self._unknown_fields:
size += len(tag_bytes) + len(value_bytes)
self._cached_byte_size = size
self._cached_byte_size_dirty = False
self._listener_for_children.dirty = False
return size</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.Clear"><code class="name flex">
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _Clear(self):
# Clear fields.
self._fields = {}
self._unknown_fields = ()
# pylint: disable=protected-access
if self._unknown_field_set is not None:
self._unknown_field_set._clear()
self._unknown_field_set = None
self._oneofs = {}
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.ClearField"><code class="name flex">
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ClearField(self, field_name):
try:
field = message_descriptor.fields_by_name[field_name]
except KeyError:
try:
field = message_descriptor.oneofs_by_name[field_name]
if field in self._oneofs:
field = self._oneofs[field]
else:
return
except KeyError:
raise ValueError(&#39;Protocol message %s has no &#34;%s&#34; field.&#39; %
(message_descriptor.name, field_name))
if field in self._fields:
# To match the C++ implementation, we need to invalidate iterators
# for map fields when ClearField() happens.
if hasattr(self._fields[field], &#39;InvalidateIterators&#39;):
self._fields[field].InvalidateIterators()
# Note: If the field is a sub-message, its listener will still point
# at us. That&#39;s fine, because the worst than can happen is that it
# will call _Modified() and invalidate our byte size. Big deal.
del self._fields[field]
if self._oneofs.get(field.containing_oneof, None) is field:
del self._oneofs[field.containing_oneof]
# Always call _Modified() -- even if nothing was changed, this is
# a mutating method, and thus calling it should cause the field to become
# present in the parent message.
self._Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.DiscardUnknownFields"><code class="name flex">
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _DiscardUnknownFields(self):
self._unknown_fields = []
self._unknown_field_set = None # pylint: disable=protected-access
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
value[key].DiscardUnknownFields()
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for sub_message in value:
sub_message.DiscardUnknownFields()
else:
value.DiscardUnknownFields()</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.FindInitializationErrors"><code class="name flex">
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Finds required fields which are not initialized.</p>
<h2 id="returns">Returns</h2>
<p>A list of strings.
Each string is a path to an uninitialized field from
the top-level message, e.g. "foo.bar[5].baz".</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def FindInitializationErrors(self):
&#34;&#34;&#34;Finds required fields which are not initialized.
Returns:
A list of strings. Each string is a path to an uninitialized field from
the top-level message, e.g. &#34;foo.bar[5].baz&#34;.
&#34;&#34;&#34;
errors = [] # simplify things
for field in required_fields:
if not self.HasField(field.name):
errors.append(field.name)
for field, value in self.ListFields():
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.is_extension:
name = &#39;(%s)&#39; % field.full_name
else:
name = field.name
if _IsMapField(field):
if _IsMessageMapField(field):
for key in value:
element = value[key]
prefix = &#39;%s[%s].&#39; % (name, key)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
# ScalarMaps can&#39;t have any initialization errors.
pass
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for i in range(len(value)):
element = value[i]
prefix = &#39;%s[%d].&#39; % (name, i)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
prefix = name + &#39;.&#39;
sub_errors = value.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
return errors</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.HasField"><code class="name flex">
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def HasField(self, field_name):
try:
field = hassable_fields[field_name]
except KeyError:
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
if isinstance(field, descriptor_mod.OneofDescriptor):
try:
return HasField(self, self._oneofs[field].name)
except KeyError:
return False
else:
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
value = self._fields.get(field)
return value is not None and value._is_present_in_parent
else:
return field in self._fields</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.IsInitialized"><code class="name flex">
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
</code></dt>
<dd>
<div class="desc"><p>Checks if all required fields of a message are set.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>errors</code></strong></dt>
<dd>A list which, if provided, will be populated with the field
paths of all missing required fields.</dd>
</dl>
<h2 id="returns">Returns</h2>
<p>True iff the specified message has all required fields set.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def IsInitialized(self, errors=None):
&#34;&#34;&#34;Checks if all required fields of a message are set.
Args:
errors: A list which, if provided, will be populated with the field
paths of all missing required fields.
Returns:
True iff the specified message has all required fields set.
&#34;&#34;&#34;
# Performance is critical so we avoid HasField() and ListFields().
for field in required_fields:
if (field not in self._fields or
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
not self._fields[field]._is_present_in_parent)):
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
for field, value in list(self._fields.items()): # dict can change size!
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.label == _FieldDescriptor.LABEL_REPEATED:
if (field.message_type.has_options and
field.message_type.GetOptions().map_entry):
continue
for element in value:
if not element.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
elif value._is_present_in_parent and not value.IsInitialized():
if errors is not None:
errors.extend(self.FindInitializationErrors())
return False
return True</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.ListFields"><code class="name flex">
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ListFields(self):
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
all_fields.sort(key = lambda item: item[0].number)
return all_fields</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.MergeFrom"><code class="name flex">
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFrom(self, msg):
if not isinstance(msg, cls):
raise TypeError(
&#39;Parameter to MergeFrom() must be instance of same class: &#39;
&#39;expected %s got %s.&#39; % (_FullyQualifiedClassName(cls),
_FullyQualifiedClassName(msg.__class__)))
assert msg is not self
self._Modified()
fields = self._fields
for field, value in msg._fields.items():
if field.label == LABEL_REPEATED:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
elif field.cpp_type == CPPTYPE_MESSAGE:
if value._is_present_in_parent:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
field_value.MergeFrom(value)
else:
self._fields[field] = value
if field.containing_oneof:
self._UpdateOneofState(field)
if msg._unknown_fields:
if not self._unknown_fields:
self._unknown_fields = []
self._unknown_fields.extend(msg._unknown_fields)
# pylint: disable=protected-access
if self._unknown_field_set is None:
self._unknown_field_set = containers.UnknownFieldSet()
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.MergeFromString"><code class="name flex">
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def MergeFromString(self, serialized):
serialized = memoryview(serialized)
length = len(serialized)
try:
if self._InternalParse(serialized, 0, length) != length:
# The only reason _InternalParse would return early is if it
# encountered an end-group tag.
raise message_mod.DecodeError(&#39;Unexpected end-group tag.&#39;)
except (IndexError, TypeError):
# Now ord(buf[p:p+1]) == ord(&#39;&#39;) gets TypeError.
raise message_mod.DecodeError(&#39;Truncated message.&#39;)
except struct.error as e:
raise message_mod.DecodeError(e)
return length # Return this for legacy reasons.</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.SerializePartialToString"><code class="name flex">
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializePartialToString(self, **kwargs):
out = BytesIO()
self._InternalSerialize(out.write, **kwargs)
return out.getvalue()</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.SerializeToString"><code class="name flex">
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def SerializeToString(self, **kwargs):
# Check if the message has all of its required fields set.
if not self.IsInitialized():
raise message_mod.EncodeError(
&#39;Message %s is missing required fields: %s&#39; % (
self.DESCRIPTOR.full_name, &#39;,&#39;.join(self.FindInitializationErrors())))
return self.SerializePartialToString(**kwargs)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.SetInParent"><code class="name flex">
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def Modified(self):
&#34;&#34;&#34;Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.
&#34;&#34;&#34;
# Note: Some callers check _cached_byte_size_dirty before calling
# _Modified() as an extra optimization. So, if this method is ever
# changed such that it does stuff even when _cached_byte_size_dirty is
# already true, the callers need to be updated.
if not self._cached_byte_size_dirty:
self._cached_byte_size_dirty = True
self._listener_for_children.dirty = True
self._is_present_in_parent = True
self._listener.Modified()</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.UnknownFields"><code class="name flex">
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def _UnknownFields(self):
if self._unknown_field_set is None: # pylint: disable=protected-access
# pylint: disable=protected-access
self._unknown_field_set = containers.UnknownFieldSet()
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.WhichOneof"><code class="name flex">
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
</code></dt>
<dd>
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def WhichOneof(self, oneof_name):
&#34;&#34;&#34;Returns the name of the currently set field inside a oneof, or None.&#34;&#34;&#34;
try:
field = message_descriptor.oneofs_by_name[oneof_name]
except KeyError:
raise ValueError(
&#39;Protocol message has no oneof &#34;%s&#34; field.&#39; % oneof_name)
nested_field = self._oneofs.get(field, None)
if nested_field is not None and self.HasField(nested_field.name):
return nested_field.name
else:
return None</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_node.test_node" href="#meshtastic.tests.test_node.test_node">test_node</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_node_reqquestConfig" href="#meshtastic.tests.test_node.test_node_reqquestConfig">test_node_reqquestConfig</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.tests.test_node.AdminMessage" href="#meshtastic.tests.test_node.AdminMessage">AdminMessage</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.tests.test_node.AdminMessage.ByteSize" href="#meshtastic.tests.test_node.AdminMessage.ByteSize">ByteSize</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.CONFIRM_SET_CHANNEL_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.CONFIRM_SET_CHANNEL_FIELD_NUMBER">CONFIRM_SET_CHANNEL_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.CONFIRM_SET_RADIO_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.CONFIRM_SET_RADIO_FIELD_NUMBER">CONFIRM_SET_RADIO_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.Clear" href="#meshtastic.tests.test_node.AdminMessage.Clear">Clear</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.ClearField" href="#meshtastic.tests.test_node.AdminMessage.ClearField">ClearField</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.DESCRIPTOR" href="#meshtastic.tests.test_node.AdminMessage.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.DiscardUnknownFields" href="#meshtastic.tests.test_node.AdminMessage.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.EXIT_SIMULATOR_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.EXIT_SIMULATOR_FIELD_NUMBER">EXIT_SIMULATOR_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.FindInitializationErrors" href="#meshtastic.tests.test_node.AdminMessage.FindInitializationErrors">FindInitializationErrors</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.FromString" href="#meshtastic.tests.test_node.AdminMessage.FromString">FromString</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.GET_CHANNEL_REQUEST_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.GET_CHANNEL_REQUEST_FIELD_NUMBER">GET_CHANNEL_REQUEST_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.GET_CHANNEL_RESPONSE_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.GET_CHANNEL_RESPONSE_FIELD_NUMBER">GET_CHANNEL_RESPONSE_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.GET_RADIO_REQUEST_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.GET_RADIO_REQUEST_FIELD_NUMBER">GET_RADIO_REQUEST_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.GET_RADIO_RESPONSE_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.GET_RADIO_RESPONSE_FIELD_NUMBER">GET_RADIO_RESPONSE_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.HasField" href="#meshtastic.tests.test_node.AdminMessage.HasField">HasField</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.IsInitialized" href="#meshtastic.tests.test_node.AdminMessage.IsInitialized">IsInitialized</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.ListFields" href="#meshtastic.tests.test_node.AdminMessage.ListFields">ListFields</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.MergeFrom" href="#meshtastic.tests.test_node.AdminMessage.MergeFrom">MergeFrom</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.MergeFromString" href="#meshtastic.tests.test_node.AdminMessage.MergeFromString">MergeFromString</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.REBOOT_SECONDS_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.REBOOT_SECONDS_FIELD_NUMBER">REBOOT_SECONDS_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.RegisterExtension" href="#meshtastic.tests.test_node.AdminMessage.RegisterExtension">RegisterExtension</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.SET_CHANNEL_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.SET_CHANNEL_FIELD_NUMBER">SET_CHANNEL_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.SET_OWNER_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.SET_OWNER_FIELD_NUMBER">SET_OWNER_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.SET_RADIO_FIELD_NUMBER" href="#meshtastic.tests.test_node.AdminMessage.SET_RADIO_FIELD_NUMBER">SET_RADIO_FIELD_NUMBER</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.SerializePartialToString" href="#meshtastic.tests.test_node.AdminMessage.SerializePartialToString">SerializePartialToString</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.SerializeToString" href="#meshtastic.tests.test_node.AdminMessage.SerializeToString">SerializeToString</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.SetInParent" href="#meshtastic.tests.test_node.AdminMessage.SetInParent">SetInParent</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.UnknownFields" href="#meshtastic.tests.test_node.AdminMessage.UnknownFields">UnknownFields</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.WhichOneof" href="#meshtastic.tests.test_node.AdminMessage.WhichOneof">WhichOneof</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.confirm_set_channel" href="#meshtastic.tests.test_node.AdminMessage.confirm_set_channel">confirm_set_channel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.confirm_set_radio" href="#meshtastic.tests.test_node.AdminMessage.confirm_set_radio">confirm_set_radio</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.exit_simulator" href="#meshtastic.tests.test_node.AdminMessage.exit_simulator">exit_simulator</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.get_channel_request" href="#meshtastic.tests.test_node.AdminMessage.get_channel_request">get_channel_request</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.get_channel_response" href="#meshtastic.tests.test_node.AdminMessage.get_channel_response">get_channel_response</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.get_radio_request" href="#meshtastic.tests.test_node.AdminMessage.get_radio_request">get_radio_request</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.get_radio_response" href="#meshtastic.tests.test_node.AdminMessage.get_radio_response">get_radio_response</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.reboot_seconds" href="#meshtastic.tests.test_node.AdminMessage.reboot_seconds">reboot_seconds</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.set_channel" href="#meshtastic.tests.test_node.AdminMessage.set_channel">set_channel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.set_owner" href="#meshtastic.tests.test_node.AdminMessage.set_owner">set_owner</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.set_radio" href="#meshtastic.tests.test_node.AdminMessage.set_radio">set_radio</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,186 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_serial_interface API documentation</title>
<meta name="description" content="Meshtastic unit tests for serial_interface.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_serial_interface</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for serial_interface.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for serial_interface.py&#34;&#34;&#34;
import re
from unittest.mock import patch
import pytest
from ..serial_interface import SerialInterface
@pytest.mark.unit
@patch(&#39;serial.Serial&#39;)
@patch(&#39;meshtastic.util.findPorts&#39;, return_value=[&#39;/dev/ttyUSBfake&#39;])
def test_SerialInterface_single_port(mocked_findPorts, mocked_serial):
&#34;&#34;&#34;Test that we can instantiate a SerialInterface with a single port&#34;&#34;&#34;
iface = SerialInterface(noProto=True)
iface.showInfo()
iface.localNode.showInfo()
iface.close()
mocked_findPorts.assert_called()
mocked_serial.assert_called()
@pytest.mark.unit
@patch(&#39;meshtastic.util.findPorts&#39;, return_value=[])
def test_SerialInterface_no_ports(mocked_findPorts, capsys):
&#34;&#34;&#34;Test that we can instantiate a SerialInterface with no ports&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
SerialInterface(noProto=True)
mocked_findPorts.assert_called()
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1
out, err = capsys.readouterr()
assert re.search(r&#39;Warning: No Meshtastic devices detected&#39;, out, re.MULTILINE)
assert err == &#39;&#39;
@pytest.mark.unit
@patch(&#39;meshtastic.util.findPorts&#39;, return_value=[&#39;/dev/ttyUSBfake1&#39;, &#39;/dev/ttyUSBfake2&#39;])
def test_SerialInterface_multiple_ports(mocked_findPorts, capsys):
&#34;&#34;&#34;Test that we can instantiate a SerialInterface with two ports&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
SerialInterface(noProto=True)
mocked_findPorts.assert_called()
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1
out, err = capsys.readouterr()
assert re.search(r&#39;Warning: Multiple serial ports were detected&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_serial_interface.test_SerialInterface_multiple_ports"><code class="name flex">
<span>def <span class="ident">test_SerialInterface_multiple_ports</span></span>(<span>mocked_findPorts, capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a SerialInterface with two ports</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
@patch(&#39;meshtastic.util.findPorts&#39;, return_value=[&#39;/dev/ttyUSBfake1&#39;, &#39;/dev/ttyUSBfake2&#39;])
def test_SerialInterface_multiple_ports(mocked_findPorts, capsys):
&#34;&#34;&#34;Test that we can instantiate a SerialInterface with two ports&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
SerialInterface(noProto=True)
mocked_findPorts.assert_called()
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1
out, err = capsys.readouterr()
assert re.search(r&#39;Warning: Multiple serial ports were detected&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_serial_interface.test_SerialInterface_no_ports"><code class="name flex">
<span>def <span class="ident">test_SerialInterface_no_ports</span></span>(<span>mocked_findPorts, capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a SerialInterface with no ports</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
@patch(&#39;meshtastic.util.findPorts&#39;, return_value=[])
def test_SerialInterface_no_ports(mocked_findPorts, capsys):
&#34;&#34;&#34;Test that we can instantiate a SerialInterface with no ports&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
SerialInterface(noProto=True)
mocked_findPorts.assert_called()
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1
out, err = capsys.readouterr()
assert re.search(r&#39;Warning: No Meshtastic devices detected&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_serial_interface.test_SerialInterface_single_port"><code class="name flex">
<span>def <span class="ident">test_SerialInterface_single_port</span></span>(<span>mocked_findPorts, mocked_serial)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a SerialInterface with a single port</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
@patch(&#39;serial.Serial&#39;)
@patch(&#39;meshtastic.util.findPorts&#39;, return_value=[&#39;/dev/ttyUSBfake&#39;])
def test_SerialInterface_single_port(mocked_findPorts, mocked_serial):
&#34;&#34;&#34;Test that we can instantiate a SerialInterface with a single port&#34;&#34;&#34;
iface = SerialInterface(noProto=True)
iface.showInfo()
iface.localNode.showInfo()
iface.close()
mocked_findPorts.assert_called()
mocked_serial.assert_called()</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_serial_interface.test_SerialInterface_multiple_ports" href="#meshtastic.tests.test_serial_interface.test_SerialInterface_multiple_ports">test_SerialInterface_multiple_ports</a></code></li>
<li><code><a title="meshtastic.tests.test_serial_interface.test_SerialInterface_no_ports" href="#meshtastic.tests.test_serial_interface.test_SerialInterface_no_ports">test_SerialInterface_no_ports</a></code></li>
<li><code><a title="meshtastic.tests.test_serial_interface.test_SerialInterface_single_port" href="#meshtastic.tests.test_serial_interface.test_SerialInterface_single_port">test_SerialInterface_single_port</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,127 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_smoke2 API documentation</title>
<meta name="description" content="Meshtastic smoke tests with 2 devices connected via USB" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_smoke2</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic smoke tests with 2 devices connected via USB</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic smoke tests with 2 devices connected via USB&#34;&#34;&#34;
import re
import subprocess
import pytest
@pytest.mark.smoke2
def test_smoke2_info():
&#34;&#34;&#34;Test --info with 2 devices connected serially&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;Warning: Multiple&#39;, out, re.MULTILINE)
assert return_value == 1
@pytest.mark.smoke2
def test_smoke2_test():
&#34;&#34;&#34;Test --test&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --test&#39;)
assert re.search(r&#39;Writing serial debugging&#39;, out, re.MULTILINE)
assert re.search(r&#39;Ports opened&#39;, out, re.MULTILINE)
assert re.search(r&#39;Running 5 tests&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_smoke2.test_smoke2_info"><code class="name flex">
<span>def <span class="ident">test_smoke2_info</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;info with 2 devices connected serially</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke2
def test_smoke2_info():
&#34;&#34;&#34;Test --info with 2 devices connected serially&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info&#39;)
assert re.search(r&#39;Warning: Multiple&#39;, out, re.MULTILINE)
assert return_value == 1</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_smoke2.test_smoke2_test"><code class="name flex">
<span>def <span class="ident">test_smoke2_test</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;test</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smoke2
def test_smoke2_test():
&#34;&#34;&#34;Test --test&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --test&#39;)
assert re.search(r&#39;Writing serial debugging&#39;, out, re.MULTILINE)
assert re.search(r&#39;Ports opened&#39;, out, re.MULTILINE)
assert re.search(r&#39;Running 5 tests&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_smoke2.test_smoke2_info" href="#meshtastic.tests.test_smoke2.test_smoke2_info">test_smoke2_info</a></code></li>
<li><code><a title="meshtastic.tests.test_smoke2.test_smoke2_test" href="#meshtastic.tests.test_smoke2.test_smoke2_test">test_smoke2_test</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,115 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_smoke_wifi API documentation</title>
<meta name="description" content="Meshtastic smoke tests a device setup with wifi …" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_smoke_wifi</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic smoke tests a device setup with wifi.</p>
<p>Need to have run the following on an esp32 device:
meshtastic &ndash;set wifi_ssid 'foo' &ndash;set wifi_password 'sekret'</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic smoke tests a device setup with wifi.
Need to have run the following on an esp32 device:
meshtastic --set wifi_ssid &#39;foo&#39; --set wifi_password &#39;sekret&#39;
&#34;&#34;&#34;
import re
import subprocess
import pytest
@pytest.mark.smokewifi
def test_smokewifi_info():
&#34;&#34;&#34;Test --info&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info --host meshtastic.local&#39;)
assert re.search(r&#39;^Owner&#39;, out, re.MULTILINE)
assert re.search(r&#39;^My info&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Nodes in mesh&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Preferences&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Channels&#39;, out, re.MULTILINE)
assert re.search(r&#39;^ PRIMARY&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Primary channel URL&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_smoke_wifi.test_smokewifi_info"><code class="name flex">
<span>def <span class="ident">test_smokewifi_info</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test &ndash;info</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.smokewifi
def test_smokewifi_info():
&#34;&#34;&#34;Test --info&#34;&#34;&#34;
return_value, out = subprocess.getstatusoutput(&#39;meshtastic --info --host meshtastic.local&#39;)
assert re.search(r&#39;^Owner&#39;, out, re.MULTILINE)
assert re.search(r&#39;^My info&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Nodes in mesh&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Preferences&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Channels&#39;, out, re.MULTILINE)
assert re.search(r&#39;^ PRIMARY&#39;, out, re.MULTILINE)
assert re.search(r&#39;^Primary channel URL&#39;, out, re.MULTILINE)
assert return_value == 0</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_smoke_wifi.test_smokewifi_info" href="#meshtastic.tests.test_smoke_wifi.test_smokewifi_info">test_smokewifi_info</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,98 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_stream_interface API documentation</title>
<meta name="description" content="Meshtastic unit tests for stream_interface.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_stream_interface</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for stream_interface.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for stream_interface.py&#34;&#34;&#34;
import pytest
from ..stream_interface import StreamInterface
@pytest.mark.unit
def test_StreamInterface():
&#34;&#34;&#34;Test that we can instantiate a StreamInterface&#34;&#34;&#34;
with pytest.raises(Exception) as pytest_wrapped_e:
StreamInterface(noProto=True)
assert pytest_wrapped_e.type == Exception</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_stream_interface.test_StreamInterface"><code class="name flex">
<span>def <span class="ident">test_StreamInterface</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a StreamInterface</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_StreamInterface():
&#34;&#34;&#34;Test that we can instantiate a StreamInterface&#34;&#34;&#34;
with pytest.raises(Exception) as pytest_wrapped_e:
StreamInterface(noProto=True)
assert pytest_wrapped_e.type == Exception</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_stream_interface.test_StreamInterface" href="#meshtastic.tests.test_stream_interface.test_StreamInterface">test_StreamInterface</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,120 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_tcp_interface API documentation</title>
<meta name="description" content="Meshtastic unit tests for tcp_interface.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_tcp_interface</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for tcp_interface.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for tcp_interface.py&#34;&#34;&#34;
import re
from unittest.mock import patch
import pytest
from ..tcp_interface import TCPInterface
@pytest.mark.unit
def test_TCPInterface(capsys):
&#34;&#34;&#34;Test that we can instantiate a TCPInterface&#34;&#34;&#34;
with patch(&#39;socket.socket&#39;) as mock_socket:
iface = TCPInterface(hostname=&#39;localhost&#39;, noProto=True)
iface.showInfo()
iface.localNode.showInfo()
out, err = capsys.readouterr()
assert re.search(r&#39;Owner: None \(None\)&#39;, out, re.MULTILINE)
assert re.search(r&#39;Nodes&#39;, out, re.MULTILINE)
assert re.search(r&#39;Preferences&#39;, out, re.MULTILINE)
assert re.search(r&#39;Channels&#39;, out, re.MULTILINE)
assert re.search(r&#39;Primary channel URL&#39;, out, re.MULTILINE)
assert err == &#39;&#39;
assert mock_socket.called
iface.close()</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_tcp_interface.test_TCPInterface"><code class="name flex">
<span>def <span class="ident">test_TCPInterface</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a TCPInterface</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_TCPInterface(capsys):
&#34;&#34;&#34;Test that we can instantiate a TCPInterface&#34;&#34;&#34;
with patch(&#39;socket.socket&#39;) as mock_socket:
iface = TCPInterface(hostname=&#39;localhost&#39;, noProto=True)
iface.showInfo()
iface.localNode.showInfo()
out, err = capsys.readouterr()
assert re.search(r&#39;Owner: None \(None\)&#39;, out, re.MULTILINE)
assert re.search(r&#39;Nodes&#39;, out, re.MULTILINE)
assert re.search(r&#39;Preferences&#39;, out, re.MULTILINE)
assert re.search(r&#39;Channels&#39;, out, re.MULTILINE)
assert re.search(r&#39;Primary channel URL&#39;, out, re.MULTILINE)
assert err == &#39;&#39;
assert mock_socket.called
iface.close()</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_tcp_interface.test_TCPInterface" href="#meshtastic.tests.test_tcp_interface.test_TCPInterface">test_TCPInterface</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,455 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tests.test_util API documentation</title>
<meta name="description" content="Meshtastic unit tests for util.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_util</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for util.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for util.py&#34;&#34;&#34;
import re
import pytest
from meshtastic.util import fixme, stripnl, pskToString, our_exit, support_info, genPSK256, fromStr, fromPSK
@pytest.mark.unit
def test_genPSK256():
&#34;&#34;&#34;Test genPSK256&#34;&#34;&#34;
assert genPSK256() != &#39;&#39;
@pytest.mark.unit
def test_fromStr():
&#34;&#34;&#34;Test fromStr&#34;&#34;&#34;
assert fromStr(&#39;&#39;) == b&#39;&#39;
assert fromStr(&#39;0x12&#39;) == b&#39;\x12&#39;
assert fromStr(&#39;t&#39;)
assert fromStr(&#39;T&#39;)
assert fromStr(&#39;true&#39;)
assert fromStr(&#39;True&#39;)
assert fromStr(&#39;yes&#39;)
assert fromStr(&#39;Yes&#39;)
assert fromStr(&#39;f&#39;) is False
assert fromStr(&#39;F&#39;) is False
assert fromStr(&#39;false&#39;) is False
assert fromStr(&#39;False&#39;) is False
assert fromStr(&#39;no&#39;) is False
assert fromStr(&#39;No&#39;) is False
assert fromStr(&#39;100.01&#39;) == 100.01
assert fromStr(&#39;123&#39;) == 123
assert fromStr(&#39;abc&#39;) == &#39;abc&#39;
@pytest.mark.unit
def test_fromPSK():
&#34;&#34;&#34;Test fromPSK&#34;&#34;&#34;
assert fromPSK(&#39;random&#39;) != &#39;&#39;
assert fromPSK(&#39;none&#39;) == b&#39;\x00&#39;
assert fromPSK(&#39;default&#39;) == b&#39;\x01&#39;
assert fromPSK(&#39;simple22&#39;) == b&#39;\x17&#39;
assert fromPSK(&#39;trash&#39;) == &#39;trash&#39;
@pytest.mark.unit
def test_stripnl():
&#34;&#34;&#34;Test stripnl&#34;&#34;&#34;
assert stripnl(&#39;&#39;) == &#39;&#39;
assert stripnl(&#39;a\n&#39;) == &#39;a&#39;
assert stripnl(&#39; a \n &#39;) == &#39;a&#39;
assert stripnl(&#39;a\nb&#39;) == &#39;a b&#39;
@pytest.mark.unit
def test_pskToString_empty_string():
&#34;&#34;&#34;Test pskToString empty string&#34;&#34;&#34;
assert pskToString(&#39;&#39;) == &#39;unencrypted&#39;
@pytest.mark.unit
def test_pskToString_string():
&#34;&#34;&#34;Test pskToString string&#34;&#34;&#34;
assert pskToString(&#39;hunter123&#39;) == &#39;secret&#39;
@pytest.mark.unit
def test_pskToString_one_byte_zero_value():
&#34;&#34;&#34;Test pskToString one byte that is value of 0&#34;&#34;&#34;
assert pskToString(bytes([0x00])) == &#39;unencrypted&#39;
@pytest.mark.unit
def test_pskToString_one_byte_non_zero_value():
&#34;&#34;&#34;Test pskToString one byte that is non-zero&#34;&#34;&#34;
assert pskToString(bytes([0x01])) == &#39;default&#39;
@pytest.mark.unit
def test_pskToString_many_bytes():
&#34;&#34;&#34;Test pskToString many bytes&#34;&#34;&#34;
assert pskToString(bytes([0x02, 0x01])) == &#39;secret&#39;
@pytest.mark.unit
def test_pskToString_simple():
&#34;&#34;&#34;Test pskToString simple&#34;&#34;&#34;
assert pskToString(bytes([0x03])) == &#39;simple2&#39;
@pytest.mark.unit
def test_our_exit_zero_return_value():
&#34;&#34;&#34;Test our_exit with a zero return value&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
our_exit(&#34;Warning: Some message&#34;, 0)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0
@pytest.mark.unit
def test_our_exit_non_zero_return_value():
&#34;&#34;&#34;Test our_exit with a non-zero return value&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
our_exit(&#34;Error: Some message&#34;, 1)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1
@pytest.mark.unit
def test_fixme():
&#34;&#34;&#34;Test fixme&#34;&#34;&#34;
with pytest.raises(Exception) as pytest_wrapped_e:
fixme(&#34;some exception&#34;)
assert pytest_wrapped_e.type == Exception
@pytest.mark.unit
def test_support_info(capsys):
&#34;&#34;&#34;Test support_info&#34;&#34;&#34;
support_info()
out, err = capsys.readouterr()
assert re.search(r&#39;System&#39;, out, re.MULTILINE)
assert re.search(r&#39;Platform&#39;, out, re.MULTILINE)
assert re.search(r&#39;Machine&#39;, out, re.MULTILINE)
assert re.search(r&#39;Executable&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_util.test_fixme"><code class="name flex">
<span>def <span class="ident">test_fixme</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test fixme</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_fixme():
&#34;&#34;&#34;Test fixme&#34;&#34;&#34;
with pytest.raises(Exception) as pytest_wrapped_e:
fixme(&#34;some exception&#34;)
assert pytest_wrapped_e.type == Exception</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_fromPSK"><code class="name flex">
<span>def <span class="ident">test_fromPSK</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test fromPSK</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_fromPSK():
&#34;&#34;&#34;Test fromPSK&#34;&#34;&#34;
assert fromPSK(&#39;random&#39;) != &#39;&#39;
assert fromPSK(&#39;none&#39;) == b&#39;\x00&#39;
assert fromPSK(&#39;default&#39;) == b&#39;\x01&#39;
assert fromPSK(&#39;simple22&#39;) == b&#39;\x17&#39;
assert fromPSK(&#39;trash&#39;) == &#39;trash&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_fromStr"><code class="name flex">
<span>def <span class="ident">test_fromStr</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test fromStr</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_fromStr():
&#34;&#34;&#34;Test fromStr&#34;&#34;&#34;
assert fromStr(&#39;&#39;) == b&#39;&#39;
assert fromStr(&#39;0x12&#39;) == b&#39;\x12&#39;
assert fromStr(&#39;t&#39;)
assert fromStr(&#39;T&#39;)
assert fromStr(&#39;true&#39;)
assert fromStr(&#39;True&#39;)
assert fromStr(&#39;yes&#39;)
assert fromStr(&#39;Yes&#39;)
assert fromStr(&#39;f&#39;) is False
assert fromStr(&#39;F&#39;) is False
assert fromStr(&#39;false&#39;) is False
assert fromStr(&#39;False&#39;) is False
assert fromStr(&#39;no&#39;) is False
assert fromStr(&#39;No&#39;) is False
assert fromStr(&#39;100.01&#39;) == 100.01
assert fromStr(&#39;123&#39;) == 123
assert fromStr(&#39;abc&#39;) == &#39;abc&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_genPSK256"><code class="name flex">
<span>def <span class="ident">test_genPSK256</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test genPSK256</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_genPSK256():
&#34;&#34;&#34;Test genPSK256&#34;&#34;&#34;
assert genPSK256() != &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_our_exit_non_zero_return_value"><code class="name flex">
<span>def <span class="ident">test_our_exit_non_zero_return_value</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test our_exit with a non-zero return value</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_our_exit_non_zero_return_value():
&#34;&#34;&#34;Test our_exit with a non-zero return value&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
our_exit(&#34;Error: Some message&#34;, 1)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_our_exit_zero_return_value"><code class="name flex">
<span>def <span class="ident">test_our_exit_zero_return_value</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test our_exit with a zero return value</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_our_exit_zero_return_value():
&#34;&#34;&#34;Test our_exit with a zero return value&#34;&#34;&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
our_exit(&#34;Warning: Some message&#34;, 0)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_pskToString_empty_string"><code class="name flex">
<span>def <span class="ident">test_pskToString_empty_string</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString empty string</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_empty_string():
&#34;&#34;&#34;Test pskToString empty string&#34;&#34;&#34;
assert pskToString(&#39;&#39;) == &#39;unencrypted&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_pskToString_many_bytes"><code class="name flex">
<span>def <span class="ident">test_pskToString_many_bytes</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString many bytes</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_many_bytes():
&#34;&#34;&#34;Test pskToString many bytes&#34;&#34;&#34;
assert pskToString(bytes([0x02, 0x01])) == &#39;secret&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_pskToString_one_byte_non_zero_value"><code class="name flex">
<span>def <span class="ident">test_pskToString_one_byte_non_zero_value</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString one byte that is non-zero</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_one_byte_non_zero_value():
&#34;&#34;&#34;Test pskToString one byte that is non-zero&#34;&#34;&#34;
assert pskToString(bytes([0x01])) == &#39;default&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_pskToString_one_byte_zero_value"><code class="name flex">
<span>def <span class="ident">test_pskToString_one_byte_zero_value</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString one byte that is value of 0</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_one_byte_zero_value():
&#34;&#34;&#34;Test pskToString one byte that is value of 0&#34;&#34;&#34;
assert pskToString(bytes([0x00])) == &#39;unencrypted&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_pskToString_simple"><code class="name flex">
<span>def <span class="ident">test_pskToString_simple</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString simple</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_simple():
&#34;&#34;&#34;Test pskToString simple&#34;&#34;&#34;
assert pskToString(bytes([0x03])) == &#39;simple2&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_pskToString_string"><code class="name flex">
<span>def <span class="ident">test_pskToString_string</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test pskToString string</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_pskToString_string():
&#34;&#34;&#34;Test pskToString string&#34;&#34;&#34;
assert pskToString(&#39;hunter123&#39;) == &#39;secret&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_stripnl"><code class="name flex">
<span>def <span class="ident">test_stripnl</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test stripnl</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_stripnl():
&#34;&#34;&#34;Test stripnl&#34;&#34;&#34;
assert stripnl(&#39;&#39;) == &#39;&#39;
assert stripnl(&#39;a\n&#39;) == &#39;a&#39;
assert stripnl(&#39; a \n &#39;) == &#39;a&#39;
assert stripnl(&#39;a\nb&#39;) == &#39;a b&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_util.test_support_info"><code class="name flex">
<span>def <span class="ident">test_support_info</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test support_info</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_support_info(capsys):
&#34;&#34;&#34;Test support_info&#34;&#34;&#34;
support_info()
out, err = capsys.readouterr()
assert re.search(r&#39;System&#39;, out, re.MULTILINE)
assert re.search(r&#39;Platform&#39;, out, re.MULTILINE)
assert re.search(r&#39;Machine&#39;, out, re.MULTILINE)
assert re.search(r&#39;Executable&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_util.test_fixme" href="#meshtastic.tests.test_util.test_fixme">test_fixme</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_fromPSK" href="#meshtastic.tests.test_util.test_fromPSK">test_fromPSK</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_fromStr" href="#meshtastic.tests.test_util.test_fromStr">test_fromStr</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_genPSK256" href="#meshtastic.tests.test_util.test_genPSK256">test_genPSK256</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_our_exit_non_zero_return_value" href="#meshtastic.tests.test_util.test_our_exit_non_zero_return_value">test_our_exit_non_zero_return_value</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_our_exit_zero_return_value" href="#meshtastic.tests.test_util.test_our_exit_zero_return_value">test_our_exit_zero_return_value</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_pskToString_empty_string" href="#meshtastic.tests.test_util.test_pskToString_empty_string">test_pskToString_empty_string</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_pskToString_many_bytes" href="#meshtastic.tests.test_util.test_pskToString_many_bytes">test_pskToString_many_bytes</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_pskToString_one_byte_non_zero_value" href="#meshtastic.tests.test_util.test_pskToString_one_byte_non_zero_value">test_pskToString_one_byte_non_zero_value</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_pskToString_one_byte_zero_value" href="#meshtastic.tests.test_util.test_pskToString_one_byte_zero_value">test_pskToString_one_byte_zero_value</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_pskToString_simple" href="#meshtastic.tests.test_util.test_pskToString_simple">test_pskToString_simple</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_pskToString_string" href="#meshtastic.tests.test_util.test_pskToString_string">test_pskToString_string</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_stripnl" href="#meshtastic.tests.test_util.test_stripnl">test_stripnl</a></code></li>
<li><code><a title="meshtastic.tests.test_util.test_support_info" href="#meshtastic.tests.test_util.test_support_info">test_support_info</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,615 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.tunnel API documentation</title>
<meta name="description" content="Code for IP tunnel over a mesh …" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tunnel</code></h1>
</header>
<section id="section-intro">
<p>Code for IP tunnel over a mesh</p>
<h1 id="note-python-pytuntap-was-too-buggy">Note python-pytuntap was too buggy</h1>
<h1 id="using-pip3-install-pytap2">using pip3 install pytap2</h1>
<h1 id="make-sure-to-sudo-setcap-cap_net_admineip-usrbinpython38-so-python-can-access-tun-device-without-being-root">make sure to "sudo setcap cap_net_admin+eip /usr/bin/python3.8" so python can access tun device without being root</h1>
<h1 id="sudo-ip-tuntap-del-mode-tun-tun0">sudo ip tuntap del mode tun tun0</h1>
<h1 id="sudo-binrunsh-port-devttyusb0-setch-shortfast">sudo bin/run.sh &ndash;port /dev/ttyUSB0 &ndash;setch-shortfast</h1>
<h1 id="sudo-binrunsh-port-devttyusb0-tunnel-debug">sudo bin/run.sh &ndash;port /dev/ttyUSB0 &ndash;tunnel &ndash;debug</h1>
<h1 id="ssh-y-root19216810151-or-dietpi-default-password-p">ssh -Y root@192.168.10.151 (or dietpi), default password p</h1>
<h1 id="ncat-e-bincat-k-u-l-1235">ncat -e /bin/cat -k -u -l 1235</h1>
<h1 id="ncat-u-1011564152-1235">ncat -u 10.115.64.152 1235</h1>
<h1 id="ping-c-1-w-20-1011564152">ping -c 1 -W 20 10.115.64.152</h1>
<h1 id="ping-i-30-w-30-1011564152">ping -i 30 -W 30 10.115.64.152</h1>
<h1 id="fixme-use-a-more-optimal-mtu">FIXME: use a more optimal MTU</h1>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Code for IP tunnel over a mesh
# Note python-pytuntap was too buggy
# using pip3 install pytap2
# make sure to &#34;sudo setcap cap_net_admin+eip /usr/bin/python3.8&#34; so python can access tun device without being root
# sudo ip tuntap del mode tun tun0
# sudo bin/run.sh --port /dev/ttyUSB0 --setch-shortfast
# sudo bin/run.sh --port /dev/ttyUSB0 --tunnel --debug
# ssh -Y root@192.168.10.151 (or dietpi), default password p
# ncat -e /bin/cat -k -u -l 1235
# ncat -u 10.115.64.152 1235
# ping -c 1 -W 20 10.115.64.152
# ping -i 30 -W 30 10.115.64.152
# FIXME: use a more optimal MTU
&#34;&#34;&#34;
import logging
import threading
from pubsub import pub
from pytap2 import TapDevice
from . import portnums_pb2
# A new non standard log level that is lower level than DEBUG
LOG_TRACE = 5
# fixme - find a way to move onTunnelReceive inside of the class
tunnelInstance = None
&#34;&#34;&#34;A list of chatty UDP services we should never accidentally
forward to our slow network&#34;&#34;&#34;
udpBlacklist = {
1900, # SSDP
5353, # multicast DNS
}
&#34;&#34;&#34;A list of TCP services to block&#34;&#34;&#34;
tcpBlacklist = {}
&#34;&#34;&#34;A list of protocols we ignore&#34;&#34;&#34;
protocolBlacklist = {
0x02, # IGMP
0x80, # Service-Specific Connection-Oriented Protocol in a Multilink and Connectionless Environment
}
def hexstr(barray):
&#34;&#34;&#34;Print a string of hex digits&#34;&#34;&#34;
return &#34;:&#34;.join(&#39;{:02x}&#39;.format(x) for x in barray)
def ipstr(barray):
&#34;&#34;&#34;Print a string of ip digits&#34;&#34;&#34;
return &#34;.&#34;.join(&#39;{}&#39;.format(x) for x in barray)
def readnet_u16(p, offset):
&#34;&#34;&#34;Read big endian u16 (network byte order)&#34;&#34;&#34;
return p[offset] * 256 + p[offset + 1]
def onTunnelReceive(packet, interface):
&#34;&#34;&#34;Callback for received tunneled messages from mesh
FIXME figure out how to do closures with methods in python&#34;&#34;&#34;
tunnelInstance.onReceive(packet)
class Tunnel:
&#34;&#34;&#34;A TUN based IP tunnel over meshtastic&#34;&#34;&#34;
def __init__(self, iface, subnet=None, netmask=&#34;255.255.0.0&#34;):
&#34;&#34;&#34;
Constructor
iface is the already open MeshInterface instance
subnet is used to construct our network number (normally 10.115.x.x)
&#34;&#34;&#34;
if subnet is None:
subnet = &#34;10.115&#34;
self.iface = iface
self.subnetPrefix = subnet
global tunnelInstance
tunnelInstance = self
logging.info(&#34;Starting IP to mesh tunnel (you must be root for this *pre-alpha* &#34;\
&#34;feature to work). Mesh members:&#34;)
pub.subscribe(onTunnelReceive, &#34;meshtastic.receive.data.IP_TUNNEL_APP&#34;)
myAddr = self._nodeNumToIp(self.iface.myInfo.my_node_num)
for node in self.iface.nodes.values():
nodeId = node[&#34;user&#34;][&#34;id&#34;]
ip = self._nodeNumToIp(node[&#34;num&#34;])
logging.info(f&#34;Node { nodeId } has IP address { ip }&#34;)
logging.debug(&#34;creating TUN device with MTU=200&#34;)
# FIXME - figure out real max MTU, it should be 240 - the overhead bytes for SubPacket and Data
self.tun = TapDevice(name=&#34;mesh&#34;)
self.tun.up()
self.tun.ifconfig(address=myAddr, netmask=netmask, mtu=200)
logging.debug(f&#34;starting TUN reader, our IP address is {myAddr}&#34;)
self._rxThread = threading.Thread(
target=self.__tunReader, args=(), daemon=True)
self._rxThread.start()
def onReceive(self, packet):
&#34;&#34;&#34;onReceive&#34;&#34;&#34;
p = packet[&#34;decoded&#34;][&#34;payload&#34;]
if packet[&#34;from&#34;] == self.iface.myInfo.my_node_num:
logging.debug(&#34;Ignoring message we sent&#34;)
else:
logging.debug(
f&#34;Received mesh tunnel message type={type(p)} len={len(p)}&#34;)
# we don&#39;t really need to check for filtering here (sender should have checked),
# but this provides useful debug printing on types of packets received
if not self._shouldFilterPacket(p):
self.tun.write(p)
def _shouldFilterPacket(self, p):
&#34;&#34;&#34;Given a packet, decode it and return true if it should be ignored&#34;&#34;&#34;
protocol = p[8 + 1]
srcaddr = p[12:16]
destAddr = p[16:20]
subheader = 20
ignore = False # Assume we will be forwarding the packet
if protocol in protocolBlacklist:
ignore = True
logging.log(
LOG_TRACE, f&#34;Ignoring blacklisted protocol 0x{protocol:02x}&#34;)
elif protocol == 0x01: # ICMP
icmpType = p[20]
icmpCode = p[21]
checksum = p[22:24]
# pylint: disable=line-too-long
logging.debug(f&#34;forwarding ICMP message src={ipstr(srcaddr)}, dest={ipstr(destAddr)}, type={icmpType}, code={icmpCode}, checksum={checksum}&#34;)
# reply to pings (swap src and dest but keep rest of packet unchanged)
#pingback = p[:12]+p[16:20]+p[12:16]+p[20:]
# tap.write(pingback)
elif protocol == 0x11: # UDP
srcport = readnet_u16(p, subheader)
destport = readnet_u16(p, subheader + 2)
if destport in udpBlacklist:
ignore = True
logging.log(
LOG_TRACE, f&#34;ignoring blacklisted UDP port {destport}&#34;)
else:
logging.debug(
f&#34;forwarding udp srcport={srcport}, destport={destport}&#34;)
elif protocol == 0x06: # TCP
srcport = readnet_u16(p, subheader)
destport = readnet_u16(p, subheader + 2)
if destport in tcpBlacklist:
ignore = True
logging.log(LOG_TRACE, f&#34;ignoring blacklisted TCP port {destport}&#34;)
else:
logging.debug(f&#34;forwarding tcp srcport={srcport}, destport={destport}&#34;)
else:
logging.warning(f&#34;forwarding unexpected protocol 0x{protocol:02x}, &#34;\
&#34;src={ipstr(srcaddr)}, dest={ipstr(destAddr)}&#34;)
return ignore
def __tunReader(self):
tap = self.tun
logging.debug(&#34;TUN reader running&#34;)
while True:
p = tap.read()
#logging.debug(f&#34;IP packet received on TUN interface, type={type(p)}&#34;)
destAddr = p[16:20]
if not self._shouldFilterPacket(p):
self.sendPacket(destAddr, p)
def _ipToNodeId(self, ipAddr):
# We only consider the last 16 bits of the nodenum for IP address matching
ipBits = ipAddr[2] * 256 + ipAddr[3]
if ipBits == 0xffff:
return &#34;^all&#34;
for node in self.iface.nodes.values():
nodeNum = node[&#34;num&#34;] &amp; 0xffff
# logging.debug(f&#34;Considering nodenum 0x{nodeNum:x} for ipBits 0x{ipBits:x}&#34;)
if (nodeNum) == ipBits:
return node[&#34;user&#34;][&#34;id&#34;]
return None
def _nodeNumToIp(self, nodeNum):
return f&#34;{self.subnetPrefix}.{(nodeNum &gt;&gt; 8) &amp; 0xff}.{nodeNum &amp; 0xff}&#34;
def sendPacket(self, destAddr, p):
&#34;&#34;&#34;Forward the provided IP packet into the mesh&#34;&#34;&#34;
nodeId = self._ipToNodeId(destAddr)
if nodeId is not None:
logging.debug(f&#34;Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}&#34;)
self.iface.sendData(
p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck=False)
else:
logging.warning(f&#34;Dropping packet because no node found for destIP={ipstr(destAddr)}&#34;)
def close(self):
&#34;&#34;&#34;Close&#34;&#34;&#34;
self.tun.close()</code></pre>
</details>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-variables">Global variables</h2>
<dl>
<dt id="meshtastic.tunnel.tcpBlacklist"><code class="name">var <span class="ident">tcpBlacklist</span></code></dt>
<dd>
<div class="desc"><p>A list of protocols we ignore</p></div>
</dd>
<dt id="meshtastic.tunnel.tunnelInstance"><code class="name">var <span class="ident">tunnelInstance</span></code></dt>
<dd>
<div class="desc"><p>A list of chatty UDP services we should never accidentally
forward to our slow network</p></div>
</dd>
<dt id="meshtastic.tunnel.udpBlacklist"><code class="name">var <span class="ident">udpBlacklist</span></code></dt>
<dd>
<div class="desc"><p>A list of TCP services to block</p></div>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tunnel.hexstr"><code class="name flex">
<span>def <span class="ident">hexstr</span></span>(<span>barray)</span>
</code></dt>
<dd>
<div class="desc"><p>Print a string of hex digits</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def hexstr(barray):
&#34;&#34;&#34;Print a string of hex digits&#34;&#34;&#34;
return &#34;:&#34;.join(&#39;{:02x}&#39;.format(x) for x in barray)</code></pre>
</details>
</dd>
<dt id="meshtastic.tunnel.ipstr"><code class="name flex">
<span>def <span class="ident">ipstr</span></span>(<span>barray)</span>
</code></dt>
<dd>
<div class="desc"><p>Print a string of ip digits</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def ipstr(barray):
&#34;&#34;&#34;Print a string of ip digits&#34;&#34;&#34;
return &#34;.&#34;.join(&#39;{}&#39;.format(x) for x in barray)</code></pre>
</details>
</dd>
<dt id="meshtastic.tunnel.onTunnelReceive"><code class="name flex">
<span>def <span class="ident">onTunnelReceive</span></span>(<span>packet, interface)</span>
</code></dt>
<dd>
<div class="desc"><p>Callback for received tunneled messages from mesh</p>
<p>FIXME figure out how to do closures with methods in python</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def onTunnelReceive(packet, interface):
&#34;&#34;&#34;Callback for received tunneled messages from mesh
FIXME figure out how to do closures with methods in python&#34;&#34;&#34;
tunnelInstance.onReceive(packet)</code></pre>
</details>
</dd>
<dt id="meshtastic.tunnel.readnet_u16"><code class="name flex">
<span>def <span class="ident">readnet_u16</span></span>(<span>p, offset)</span>
</code></dt>
<dd>
<div class="desc"><p>Read big endian u16 (network byte order)</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def readnet_u16(p, offset):
&#34;&#34;&#34;Read big endian u16 (network byte order)&#34;&#34;&#34;
return p[offset] * 256 + p[offset + 1]</code></pre>
</details>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.tunnel.Tunnel"><code class="flex name class">
<span>class <span class="ident">Tunnel</span></span>
<span>(</span><span>iface, subnet=None, netmask='255.255.0.0')</span>
</code></dt>
<dd>
<div class="desc"><p>A TUN based IP tunnel over meshtastic</p>
<p>Constructor</p>
<p>iface is the already open MeshInterface instance
subnet is used to construct our network number (normally 10.115.x.x)</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class Tunnel:
&#34;&#34;&#34;A TUN based IP tunnel over meshtastic&#34;&#34;&#34;
def __init__(self, iface, subnet=None, netmask=&#34;255.255.0.0&#34;):
&#34;&#34;&#34;
Constructor
iface is the already open MeshInterface instance
subnet is used to construct our network number (normally 10.115.x.x)
&#34;&#34;&#34;
if subnet is None:
subnet = &#34;10.115&#34;
self.iface = iface
self.subnetPrefix = subnet
global tunnelInstance
tunnelInstance = self
logging.info(&#34;Starting IP to mesh tunnel (you must be root for this *pre-alpha* &#34;\
&#34;feature to work). Mesh members:&#34;)
pub.subscribe(onTunnelReceive, &#34;meshtastic.receive.data.IP_TUNNEL_APP&#34;)
myAddr = self._nodeNumToIp(self.iface.myInfo.my_node_num)
for node in self.iface.nodes.values():
nodeId = node[&#34;user&#34;][&#34;id&#34;]
ip = self._nodeNumToIp(node[&#34;num&#34;])
logging.info(f&#34;Node { nodeId } has IP address { ip }&#34;)
logging.debug(&#34;creating TUN device with MTU=200&#34;)
# FIXME - figure out real max MTU, it should be 240 - the overhead bytes for SubPacket and Data
self.tun = TapDevice(name=&#34;mesh&#34;)
self.tun.up()
self.tun.ifconfig(address=myAddr, netmask=netmask, mtu=200)
logging.debug(f&#34;starting TUN reader, our IP address is {myAddr}&#34;)
self._rxThread = threading.Thread(
target=self.__tunReader, args=(), daemon=True)
self._rxThread.start()
def onReceive(self, packet):
&#34;&#34;&#34;onReceive&#34;&#34;&#34;
p = packet[&#34;decoded&#34;][&#34;payload&#34;]
if packet[&#34;from&#34;] == self.iface.myInfo.my_node_num:
logging.debug(&#34;Ignoring message we sent&#34;)
else:
logging.debug(
f&#34;Received mesh tunnel message type={type(p)} len={len(p)}&#34;)
# we don&#39;t really need to check for filtering here (sender should have checked),
# but this provides useful debug printing on types of packets received
if not self._shouldFilterPacket(p):
self.tun.write(p)
def _shouldFilterPacket(self, p):
&#34;&#34;&#34;Given a packet, decode it and return true if it should be ignored&#34;&#34;&#34;
protocol = p[8 + 1]
srcaddr = p[12:16]
destAddr = p[16:20]
subheader = 20
ignore = False # Assume we will be forwarding the packet
if protocol in protocolBlacklist:
ignore = True
logging.log(
LOG_TRACE, f&#34;Ignoring blacklisted protocol 0x{protocol:02x}&#34;)
elif protocol == 0x01: # ICMP
icmpType = p[20]
icmpCode = p[21]
checksum = p[22:24]
# pylint: disable=line-too-long
logging.debug(f&#34;forwarding ICMP message src={ipstr(srcaddr)}, dest={ipstr(destAddr)}, type={icmpType}, code={icmpCode}, checksum={checksum}&#34;)
# reply to pings (swap src and dest but keep rest of packet unchanged)
#pingback = p[:12]+p[16:20]+p[12:16]+p[20:]
# tap.write(pingback)
elif protocol == 0x11: # UDP
srcport = readnet_u16(p, subheader)
destport = readnet_u16(p, subheader + 2)
if destport in udpBlacklist:
ignore = True
logging.log(
LOG_TRACE, f&#34;ignoring blacklisted UDP port {destport}&#34;)
else:
logging.debug(
f&#34;forwarding udp srcport={srcport}, destport={destport}&#34;)
elif protocol == 0x06: # TCP
srcport = readnet_u16(p, subheader)
destport = readnet_u16(p, subheader + 2)
if destport in tcpBlacklist:
ignore = True
logging.log(LOG_TRACE, f&#34;ignoring blacklisted TCP port {destport}&#34;)
else:
logging.debug(f&#34;forwarding tcp srcport={srcport}, destport={destport}&#34;)
else:
logging.warning(f&#34;forwarding unexpected protocol 0x{protocol:02x}, &#34;\
&#34;src={ipstr(srcaddr)}, dest={ipstr(destAddr)}&#34;)
return ignore
def __tunReader(self):
tap = self.tun
logging.debug(&#34;TUN reader running&#34;)
while True:
p = tap.read()
#logging.debug(f&#34;IP packet received on TUN interface, type={type(p)}&#34;)
destAddr = p[16:20]
if not self._shouldFilterPacket(p):
self.sendPacket(destAddr, p)
def _ipToNodeId(self, ipAddr):
# We only consider the last 16 bits of the nodenum for IP address matching
ipBits = ipAddr[2] * 256 + ipAddr[3]
if ipBits == 0xffff:
return &#34;^all&#34;
for node in self.iface.nodes.values():
nodeNum = node[&#34;num&#34;] &amp; 0xffff
# logging.debug(f&#34;Considering nodenum 0x{nodeNum:x} for ipBits 0x{ipBits:x}&#34;)
if (nodeNum) == ipBits:
return node[&#34;user&#34;][&#34;id&#34;]
return None
def _nodeNumToIp(self, nodeNum):
return f&#34;{self.subnetPrefix}.{(nodeNum &gt;&gt; 8) &amp; 0xff}.{nodeNum &amp; 0xff}&#34;
def sendPacket(self, destAddr, p):
&#34;&#34;&#34;Forward the provided IP packet into the mesh&#34;&#34;&#34;
nodeId = self._ipToNodeId(destAddr)
if nodeId is not None:
logging.debug(f&#34;Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}&#34;)
self.iface.sendData(
p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck=False)
else:
logging.warning(f&#34;Dropping packet because no node found for destIP={ipstr(destAddr)}&#34;)
def close(self):
&#34;&#34;&#34;Close&#34;&#34;&#34;
self.tun.close()</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.tunnel.Tunnel.close"><code class="name flex">
<span>def <span class="ident">close</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Close</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def close(self):
&#34;&#34;&#34;Close&#34;&#34;&#34;
self.tun.close()</code></pre>
</details>
</dd>
<dt id="meshtastic.tunnel.Tunnel.onReceive"><code class="name flex">
<span>def <span class="ident">onReceive</span></span>(<span>self, packet)</span>
</code></dt>
<dd>
<div class="desc"><p>onReceive</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def onReceive(self, packet):
&#34;&#34;&#34;onReceive&#34;&#34;&#34;
p = packet[&#34;decoded&#34;][&#34;payload&#34;]
if packet[&#34;from&#34;] == self.iface.myInfo.my_node_num:
logging.debug(&#34;Ignoring message we sent&#34;)
else:
logging.debug(
f&#34;Received mesh tunnel message type={type(p)} len={len(p)}&#34;)
# we don&#39;t really need to check for filtering here (sender should have checked),
# but this provides useful debug printing on types of packets received
if not self._shouldFilterPacket(p):
self.tun.write(p)</code></pre>
</details>
</dd>
<dt id="meshtastic.tunnel.Tunnel.sendPacket"><code class="name flex">
<span>def <span class="ident">sendPacket</span></span>(<span>self, destAddr, p)</span>
</code></dt>
<dd>
<div class="desc"><p>Forward the provided IP packet into the mesh</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def sendPacket(self, destAddr, p):
&#34;&#34;&#34;Forward the provided IP packet into the mesh&#34;&#34;&#34;
nodeId = self._ipToNodeId(destAddr)
if nodeId is not None:
logging.debug(f&#34;Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}&#34;)
self.iface.sendData(
p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck=False)
else:
logging.warning(f&#34;Dropping packet because no node found for destIP={ipstr(destAddr)}&#34;)</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul>
<li><a href="#note-python-pytuntap-was-too-buggy">Note python-pytuntap was too buggy</a></li>
<li><a href="#using-pip3-install-pytap2">using pip3 install pytap2</a></li>
<li><a href="#make-sure-to-sudo-setcap-cap_net_admineip-usrbinpython38-so-python-can-access-tun-device-without-being-root">make sure to "sudo setcap cap_net_admin+eip /usr/bin/python3.8" so python can access tun device without being root</a></li>
<li><a href="#sudo-ip-tuntap-del-mode-tun-tun0">sudo ip tuntap del mode tun tun0</a></li>
<li><a href="#sudo-binrunsh-port-devttyusb0-setch-shortfast">sudo bin/run.sh &ndash;port /dev/ttyUSB0 &ndash;setch-shortfast</a></li>
<li><a href="#sudo-binrunsh-port-devttyusb0-tunnel-debug">sudo bin/run.sh &ndash;port /dev/ttyUSB0 &ndash;tunnel &ndash;debug</a></li>
<li><a href="#ssh-y-root19216810151-or-dietpi-default-password-p">ssh -Y root@192.168.10.151 (or dietpi), default password p</a></li>
<li><a href="#ncat-e-bincat-k-u-l-1235">ncat -e /bin/cat -k -u -l 1235</a></li>
<li><a href="#ncat-u-1011564152-1235">ncat -u 10.115.64.152 1235</a></li>
<li><a href="#ping-c-1-w-20-1011564152">ping -c 1 -W 20 10.115.64.152</a></li>
<li><a href="#ping-i-30-w-30-1011564152">ping -i 30 -W 30 10.115.64.152</a></li>
<li><a href="#fixme-use-a-more-optimal-mtu">FIXME: use a more optimal MTU</a></li>
</ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-variables">Global variables</a></h3>
<ul class="">
<li><code><a title="meshtastic.tunnel.tcpBlacklist" href="#meshtastic.tunnel.tcpBlacklist">tcpBlacklist</a></code></li>
<li><code><a title="meshtastic.tunnel.tunnelInstance" href="#meshtastic.tunnel.tunnelInstance">tunnelInstance</a></code></li>
<li><code><a title="meshtastic.tunnel.udpBlacklist" href="#meshtastic.tunnel.udpBlacklist">udpBlacklist</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tunnel.hexstr" href="#meshtastic.tunnel.hexstr">hexstr</a></code></li>
<li><code><a title="meshtastic.tunnel.ipstr" href="#meshtastic.tunnel.ipstr">ipstr</a></code></li>
<li><code><a title="meshtastic.tunnel.onTunnelReceive" href="#meshtastic.tunnel.onTunnelReceive">onTunnelReceive</a></code></li>
<li><code><a title="meshtastic.tunnel.readnet_u16" href="#meshtastic.tunnel.readnet_u16">readnet_u16</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.tunnel.Tunnel" href="#meshtastic.tunnel.Tunnel">Tunnel</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.tunnel.Tunnel.close" href="#meshtastic.tunnel.Tunnel.close">close</a></code></li>
<li><code><a title="meshtastic.tunnel.Tunnel.onReceive" href="#meshtastic.tunnel.Tunnel.onReceive">onReceive</a></code></li>
<li><code><a title="meshtastic.tunnel.Tunnel.sendPacket" href="#meshtastic.tunnel.Tunnel.sendPacket">sendPacket</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,660 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>meshtastic.util API documentation</title>
<meta name="description" content="Utility functions." />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.util</code></h1>
</header>
<section id="section-intro">
<p>Utility functions.</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Utility functions.
&#34;&#34;&#34;
import traceback
from queue import Queue
import os
import sys
import time
import platform
import logging
import threading
import serial
import serial.tools.list_ports
import pkg_resources
&#34;&#34;&#34;Some devices such as a seger jlink we never want to accidentally open&#34;&#34;&#34;
blacklistVids = dict.fromkeys([0x1366])
def genPSK256():
&#34;&#34;&#34;Generate a random preshared key&#34;&#34;&#34;
return os.urandom(32)
def fromPSK(valstr):
&#34;&#34;&#34;A special version of fromStr that assumes the user is trying to set a PSK.
In that case we also allow &#34;none&#34;, &#34;default&#34; or &#34;random&#34; (to have python generate one), or simpleN
&#34;&#34;&#34;
if valstr == &#34;random&#34;:
return genPSK256()
elif valstr == &#34;none&#34;:
return bytes([0]) # Use the &#39;no encryption&#39; PSK
elif valstr == &#34;default&#34;:
return bytes([1]) # Use default channel psk
elif valstr.startswith(&#34;simple&#34;):
# Use one of the single byte encodings
return bytes([int(valstr[6:]) + 1])
else:
return fromStr(valstr)
def fromStr(valstr):
&#34;&#34;&#34;Try to parse as int, float or bool (and fallback to a string as last resort)
Returns: an int, bool, float, str or byte array (for strings of hex digits)
Args:
valstr (string): A user provided string
&#34;&#34;&#34;
if len(valstr) == 0: # Treat an emptystring as an empty bytes
val = bytes()
elif valstr.startswith(&#39;0x&#39;):
# if needed convert to string with asBytes.decode(&#39;utf-8&#39;)
val = bytes.fromhex(valstr[2:])
elif valstr.lower() in {&#34;t&#34;, &#34;true&#34;, &#34;yes&#34;}:
val = True
elif valstr.lower() in {&#34;f&#34;, &#34;false&#34;, &#34;no&#34;}:
val = False
else:
try:
val = int(valstr)
except ValueError:
try:
val = float(valstr)
except ValueError:
val = valstr # Not a float or an int, assume string
return val
def pskToString(psk: bytes):
&#34;&#34;&#34;Given an array of PSK bytes, decode them into a human readable (but privacy protecting) string&#34;&#34;&#34;
if len(psk) == 0:
return &#34;unencrypted&#34;
elif len(psk) == 1:
b = psk[0]
if b == 0:
return &#34;unencrypted&#34;
elif b == 1:
return &#34;default&#34;
else:
return f&#34;simple{b - 1}&#34;
else:
return &#34;secret&#34;
def stripnl(s):
&#34;&#34;&#34;Remove newlines from a string (and remove extra whitespace)&#34;&#34;&#34;
s = str(s).replace(&#34;\n&#34;, &#34; &#34;)
return &#39; &#39;.join(s.split())
def fixme(message):
&#34;&#34;&#34;Raise an exception for things that needs to be fixed&#34;&#34;&#34;
raise Exception(f&#34;FIXME: {message}&#34;)
def catchAndIgnore(reason, closure):
&#34;&#34;&#34;Call a closure but if it throws an excpetion print it and continue&#34;&#34;&#34;
try:
closure()
except BaseException as ex:
logging.error(f&#34;Exception thrown in {reason}: {ex}&#34;)
def findPorts():
&#34;&#34;&#34;Find all ports that might have meshtastic devices
Returns:
list -- a list of device paths
&#34;&#34;&#34;
l = list(map(lambda port: port.device,
filter(lambda port: port.vid is not None and port.vid not in blacklistVids,
serial.tools.list_ports.comports())))
l.sort()
return l
class dotdict(dict):
&#34;&#34;&#34;dot.notation access to dictionary attributes&#34;&#34;&#34;
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
class Timeout:
&#34;&#34;&#34;Timeout class&#34;&#34;&#34;
def __init__(self, maxSecs=20):
self.expireTime = 0
self.sleepInterval = 0.1
self.expireTimeout = maxSecs
def reset(self):
&#34;&#34;&#34;Restart the waitForSet timer&#34;&#34;&#34;
self.expireTime = time.time() + self.expireTimeout
def waitForSet(self, target, attrs=()):
&#34;&#34;&#34;Block until the specified attributes are set. Returns True if config has been received.&#34;&#34;&#34;
self.reset()
while time.time() &lt; self.expireTime:
if all(map(lambda a: getattr(target, a, None), attrs)):
return True
time.sleep(self.sleepInterval)
return False
class DeferredExecution():
&#34;&#34;&#34;A thread that accepts closures to run, and runs them as they are received&#34;&#34;&#34;
def __init__(self, name=None):
self.queue = Queue()
self.thread = threading.Thread(target=self._run, args=(), name=name)
self.thread.daemon = True
self.thread.start()
def queueWork(self, runnable):
&#34;&#34;&#34; Queue up the work&#34;&#34;&#34;
self.queue.put(runnable)
def _run(self):
while True:
try:
o = self.queue.get()
o()
except:
logging.error(
f&#34;Unexpected error in deferred execution {sys.exc_info()[0]}&#34;)
print(traceback.format_exc())
def our_exit(message, return_value = 1):
&#34;&#34;&#34;Print the message and return a value.
return_value defaults to 1 (non-successful)
&#34;&#34;&#34;
print(message)
sys.exit(return_value)
def support_info():
&#34;&#34;&#34;Print out info that helps troubleshooting of the cli.&#34;&#34;&#34;
print(&#39;&#39;)
print(&#39;If having issues with meshtastic cli or python library&#39;)
print(&#39;or wish to make feature requests, visit:&#39;)
print(&#39;https://github.com/meshtastic/Meshtastic-python/issues&#39;)
print(&#39;When adding an issue, be sure to include the following info:&#39;)
print(&#39; System: {0}&#39;.format(platform.system()))
print(&#39; Platform: {0}&#39;.format(platform.platform()))
print(&#39; Release: {0}&#39;.format(platform.uname().release))
print(&#39; Machine: {0}&#39;.format(platform.uname().machine))
print(&#39; Encoding (stdin): {0}&#39;.format(sys.stdin.encoding))
print(&#39; Encoding (stdout): {0}&#39;.format(sys.stdout.encoding))
print(&#39; meshtastic: v{0}&#39;.format(pkg_resources.require(&#39;meshtastic&#39;)[0].version))
print(&#39; Executable: {0}&#39;.format(sys.argv[0]))
print(&#39; Python: {0} {1} {2}&#39;.format(platform.python_version(),
platform.python_implementation(), platform.python_compiler()))
print(&#39;&#39;)
print(&#39;Please add the output from the command: meshtastic --info&#39;)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.util.catchAndIgnore"><code class="name flex">
<span>def <span class="ident">catchAndIgnore</span></span>(<span>reason, closure)</span>
</code></dt>
<dd>
<div class="desc"><p>Call a closure but if it throws an excpetion print it and continue</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def catchAndIgnore(reason, closure):
&#34;&#34;&#34;Call a closure but if it throws an excpetion print it and continue&#34;&#34;&#34;
try:
closure()
except BaseException as ex:
logging.error(f&#34;Exception thrown in {reason}: {ex}&#34;)</code></pre>
</details>
</dd>
<dt id="meshtastic.util.findPorts"><code class="name flex">
<span>def <span class="ident">findPorts</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Find all ports that might have meshtastic devices</p>
<h2 id="returns">Returns</h2>
<p>list &ndash; a list of device paths</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def findPorts():
&#34;&#34;&#34;Find all ports that might have meshtastic devices
Returns:
list -- a list of device paths
&#34;&#34;&#34;
l = list(map(lambda port: port.device,
filter(lambda port: port.vid is not None and port.vid not in blacklistVids,
serial.tools.list_ports.comports())))
l.sort()
return l</code></pre>
</details>
</dd>
<dt id="meshtastic.util.fixme"><code class="name flex">
<span>def <span class="ident">fixme</span></span>(<span>message)</span>
</code></dt>
<dd>
<div class="desc"><p>Raise an exception for things that needs to be fixed</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def fixme(message):
&#34;&#34;&#34;Raise an exception for things that needs to be fixed&#34;&#34;&#34;
raise Exception(f&#34;FIXME: {message}&#34;)</code></pre>
</details>
</dd>
<dt id="meshtastic.util.fromPSK"><code class="name flex">
<span>def <span class="ident">fromPSK</span></span>(<span>valstr)</span>
</code></dt>
<dd>
<div class="desc"><p>A special version of fromStr that assumes the user is trying to set a PSK.
In that case we also allow "none", "default" or "random" (to have python generate one), or simpleN</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def fromPSK(valstr):
&#34;&#34;&#34;A special version of fromStr that assumes the user is trying to set a PSK.
In that case we also allow &#34;none&#34;, &#34;default&#34; or &#34;random&#34; (to have python generate one), or simpleN
&#34;&#34;&#34;
if valstr == &#34;random&#34;:
return genPSK256()
elif valstr == &#34;none&#34;:
return bytes([0]) # Use the &#39;no encryption&#39; PSK
elif valstr == &#34;default&#34;:
return bytes([1]) # Use default channel psk
elif valstr.startswith(&#34;simple&#34;):
# Use one of the single byte encodings
return bytes([int(valstr[6:]) + 1])
else:
return fromStr(valstr)</code></pre>
</details>
</dd>
<dt id="meshtastic.util.fromStr"><code class="name flex">
<span>def <span class="ident">fromStr</span></span>(<span>valstr)</span>
</code></dt>
<dd>
<div class="desc"><p>Try to parse as int, float or bool (and fallback to a string as last resort)</p>
<p>Returns: an int, bool, float, str or byte array (for strings of hex digits)</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>valstr</code></strong> :&ensp;<code>string</code></dt>
<dd>A user provided string</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def fromStr(valstr):
&#34;&#34;&#34;Try to parse as int, float or bool (and fallback to a string as last resort)
Returns: an int, bool, float, str or byte array (for strings of hex digits)
Args:
valstr (string): A user provided string
&#34;&#34;&#34;
if len(valstr) == 0: # Treat an emptystring as an empty bytes
val = bytes()
elif valstr.startswith(&#39;0x&#39;):
# if needed convert to string with asBytes.decode(&#39;utf-8&#39;)
val = bytes.fromhex(valstr[2:])
elif valstr.lower() in {&#34;t&#34;, &#34;true&#34;, &#34;yes&#34;}:
val = True
elif valstr.lower() in {&#34;f&#34;, &#34;false&#34;, &#34;no&#34;}:
val = False
else:
try:
val = int(valstr)
except ValueError:
try:
val = float(valstr)
except ValueError:
val = valstr # Not a float or an int, assume string
return val</code></pre>
</details>
</dd>
<dt id="meshtastic.util.genPSK256"><code class="name flex">
<span>def <span class="ident">genPSK256</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Generate a random preshared key</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def genPSK256():
&#34;&#34;&#34;Generate a random preshared key&#34;&#34;&#34;
return os.urandom(32)</code></pre>
</details>
</dd>
<dt id="meshtastic.util.our_exit"><code class="name flex">
<span>def <span class="ident">our_exit</span></span>(<span>message, return_value=1)</span>
</code></dt>
<dd>
<div class="desc"><p>Print the message and return a value.
return_value defaults to 1 (non-successful)</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def our_exit(message, return_value = 1):
&#34;&#34;&#34;Print the message and return a value.
return_value defaults to 1 (non-successful)
&#34;&#34;&#34;
print(message)
sys.exit(return_value)</code></pre>
</details>
</dd>
<dt id="meshtastic.util.pskToString"><code class="name flex">
<span>def <span class="ident">pskToString</span></span>(<span>psk: bytes)</span>
</code></dt>
<dd>
<div class="desc"><p>Given an array of PSK bytes, decode them into a human readable (but privacy protecting) string</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def pskToString(psk: bytes):
&#34;&#34;&#34;Given an array of PSK bytes, decode them into a human readable (but privacy protecting) string&#34;&#34;&#34;
if len(psk) == 0:
return &#34;unencrypted&#34;
elif len(psk) == 1:
b = psk[0]
if b == 0:
return &#34;unencrypted&#34;
elif b == 1:
return &#34;default&#34;
else:
return f&#34;simple{b - 1}&#34;
else:
return &#34;secret&#34;</code></pre>
</details>
</dd>
<dt id="meshtastic.util.stripnl"><code class="name flex">
<span>def <span class="ident">stripnl</span></span>(<span>s)</span>
</code></dt>
<dd>
<div class="desc"><p>Remove newlines from a string (and remove extra whitespace)</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def stripnl(s):
&#34;&#34;&#34;Remove newlines from a string (and remove extra whitespace)&#34;&#34;&#34;
s = str(s).replace(&#34;\n&#34;, &#34; &#34;)
return &#39; &#39;.join(s.split())</code></pre>
</details>
</dd>
<dt id="meshtastic.util.support_info"><code class="name flex">
<span>def <span class="ident">support_info</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Print out info that helps troubleshooting of the cli.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def support_info():
&#34;&#34;&#34;Print out info that helps troubleshooting of the cli.&#34;&#34;&#34;
print(&#39;&#39;)
print(&#39;If having issues with meshtastic cli or python library&#39;)
print(&#39;or wish to make feature requests, visit:&#39;)
print(&#39;https://github.com/meshtastic/Meshtastic-python/issues&#39;)
print(&#39;When adding an issue, be sure to include the following info:&#39;)
print(&#39; System: {0}&#39;.format(platform.system()))
print(&#39; Platform: {0}&#39;.format(platform.platform()))
print(&#39; Release: {0}&#39;.format(platform.uname().release))
print(&#39; Machine: {0}&#39;.format(platform.uname().machine))
print(&#39; Encoding (stdin): {0}&#39;.format(sys.stdin.encoding))
print(&#39; Encoding (stdout): {0}&#39;.format(sys.stdout.encoding))
print(&#39; meshtastic: v{0}&#39;.format(pkg_resources.require(&#39;meshtastic&#39;)[0].version))
print(&#39; Executable: {0}&#39;.format(sys.argv[0]))
print(&#39; Python: {0} {1} {2}&#39;.format(platform.python_version(),
platform.python_implementation(), platform.python_compiler()))
print(&#39;&#39;)
print(&#39;Please add the output from the command: meshtastic --info&#39;)</code></pre>
</details>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.util.DeferredExecution"><code class="flex name class">
<span>class <span class="ident">DeferredExecution</span></span>
<span>(</span><span>name=None)</span>
</code></dt>
<dd>
<div class="desc"><p>A thread that accepts closures to run, and runs them as they are received</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class DeferredExecution():
&#34;&#34;&#34;A thread that accepts closures to run, and runs them as they are received&#34;&#34;&#34;
def __init__(self, name=None):
self.queue = Queue()
self.thread = threading.Thread(target=self._run, args=(), name=name)
self.thread.daemon = True
self.thread.start()
def queueWork(self, runnable):
&#34;&#34;&#34; Queue up the work&#34;&#34;&#34;
self.queue.put(runnable)
def _run(self):
while True:
try:
o = self.queue.get()
o()
except:
logging.error(
f&#34;Unexpected error in deferred execution {sys.exc_info()[0]}&#34;)
print(traceback.format_exc())</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.util.DeferredExecution.queueWork"><code class="name flex">
<span>def <span class="ident">queueWork</span></span>(<span>self, runnable)</span>
</code></dt>
<dd>
<div class="desc"><p>Queue up the work</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def queueWork(self, runnable):
&#34;&#34;&#34; Queue up the work&#34;&#34;&#34;
self.queue.put(runnable)</code></pre>
</details>
</dd>
</dl>
</dd>
<dt id="meshtastic.util.Timeout"><code class="flex name class">
<span>class <span class="ident">Timeout</span></span>
<span>(</span><span>maxSecs=20)</span>
</code></dt>
<dd>
<div class="desc"><p>Timeout class</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class Timeout:
&#34;&#34;&#34;Timeout class&#34;&#34;&#34;
def __init__(self, maxSecs=20):
self.expireTime = 0
self.sleepInterval = 0.1
self.expireTimeout = maxSecs
def reset(self):
&#34;&#34;&#34;Restart the waitForSet timer&#34;&#34;&#34;
self.expireTime = time.time() + self.expireTimeout
def waitForSet(self, target, attrs=()):
&#34;&#34;&#34;Block until the specified attributes are set. Returns True if config has been received.&#34;&#34;&#34;
self.reset()
while time.time() &lt; self.expireTime:
if all(map(lambda a: getattr(target, a, None), attrs)):
return True
time.sleep(self.sleepInterval)
return False</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.util.Timeout.reset"><code class="name flex">
<span>def <span class="ident">reset</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Restart the waitForSet timer</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def reset(self):
&#34;&#34;&#34;Restart the waitForSet timer&#34;&#34;&#34;
self.expireTime = time.time() + self.expireTimeout</code></pre>
</details>
</dd>
<dt id="meshtastic.util.Timeout.waitForSet"><code class="name flex">
<span>def <span class="ident">waitForSet</span></span>(<span>self, target, attrs=())</span>
</code></dt>
<dd>
<div class="desc"><p>Block until the specified attributes are set. Returns True if config has been received.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def waitForSet(self, target, attrs=()):
&#34;&#34;&#34;Block until the specified attributes are set. Returns True if config has been received.&#34;&#34;&#34;
self.reset()
while time.time() &lt; self.expireTime:
if all(map(lambda a: getattr(target, a, None), attrs)):
return True
time.sleep(self.sleepInterval)
return False</code></pre>
</details>
</dd>
</dl>
</dd>
<dt id="meshtastic.util.dotdict"><code class="flex name class">
<span>class <span class="ident">dotdict</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>dot.notation access to dictionary attributes</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class dotdict(dict):
&#34;&#34;&#34;dot.notation access to dictionary attributes&#34;&#34;&#34;
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li>builtins.dict</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic" href="index.html">meshtastic</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="two-column">
<li><code><a title="meshtastic.util.catchAndIgnore" href="#meshtastic.util.catchAndIgnore">catchAndIgnore</a></code></li>
<li><code><a title="meshtastic.util.findPorts" href="#meshtastic.util.findPorts">findPorts</a></code></li>
<li><code><a title="meshtastic.util.fixme" href="#meshtastic.util.fixme">fixme</a></code></li>
<li><code><a title="meshtastic.util.fromPSK" href="#meshtastic.util.fromPSK">fromPSK</a></code></li>
<li><code><a title="meshtastic.util.fromStr" href="#meshtastic.util.fromStr">fromStr</a></code></li>
<li><code><a title="meshtastic.util.genPSK256" href="#meshtastic.util.genPSK256">genPSK256</a></code></li>
<li><code><a title="meshtastic.util.our_exit" href="#meshtastic.util.our_exit">our_exit</a></code></li>
<li><code><a title="meshtastic.util.pskToString" href="#meshtastic.util.pskToString">pskToString</a></code></li>
<li><code><a title="meshtastic.util.stripnl" href="#meshtastic.util.stripnl">stripnl</a></code></li>
<li><code><a title="meshtastic.util.support_info" href="#meshtastic.util.support_info">support_info</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.util.DeferredExecution" href="#meshtastic.util.DeferredExecution">DeferredExecution</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.util.DeferredExecution.queueWork" href="#meshtastic.util.DeferredExecution.queueWork">queueWork</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="meshtastic.util.Timeout" href="#meshtastic.util.Timeout">Timeout</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.util.Timeout.reset" href="#meshtastic.util.Timeout.reset">reset</a></code></li>
<li><code><a title="meshtastic.util.Timeout.waitForSet" href="#meshtastic.util.Timeout.waitForSet">waitForSet</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="meshtastic.util.dotdict" href="#meshtastic.util.dotdict">dotdict</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

View File

@@ -1,389 +0,0 @@
# Python API Commands Guide
The python pip package installs a "meshtastic" command line executable, which displays packets sent over the network as JSON and lets you see serial debugging information from the meshtastic devices. This command is not run inside of python, you run it from your operating system shell prompt directly. If when you type "meshtastic" it doesn't find the command and you are using Windows: Check that the python "scripts" directory is in your path.
## Optional Arguments
### -h or --help
Shows a help message that describes the arguments.
**Usage**
``` shell
meshtastic -h
```
### --port PORT
The port the Meshtastic device is connected to, i.e. /dev/ttyUSB0 or COM4. if unspecified, meshtastic will try to find it. Important to use when multiple devices are connected to ensure you call the command for the correct device.
**Usage**
``` shell
meshtastic --port /dev/ttyUSB0 --info
meshtastic --port COM4 --info
```
### --host HOST
The hostname/ipaddr of the device to connect to (over TCP).
**Usage**
``` shell
meshtastic --host HOST
```
### --seriallog SERIALLOG
Logs device serial output to either 'stdout', 'none' or a filename to append to.
**Usage**
``` shell
meshtastic --port /dev/ttyUSB0 --seriallog
```
### --info
Read and display the radio config information.
**Usage**
``` shell
meshtastic --port /dev/ttyUSB0 --info
```
### --nodes
Prints a node list in a pretty, formatted table.
**Usage**
``` shell
meshtastic --nodes
```
### --qr
Displays the QR code that corresponds to the current channel.
**Usage**
``` shell
meshtastic --qr
```
### --get GET
Gets a preferences field.
**Usage**
``` shell
meshtastic --get modem_config
```
### --set SET SET
Sets a preferences field.
**Usage**
``` shell
meshtastic --set region Unset
```
### --seturl SETURL
Set a channel URL.
**Usage**
``` shell
meshtastic --seturl https://www.meshtastic.org/c/GAMiIE67C6zsNmlWQ-KE1tKt0fRKFciHka-DShI6G7ElvGOiKgZzaGFyZWQ=
```
### --ch-index CH_INDEX
Set the specified channel index
**Usage**
``` shell
meshtastic --ch-index 1 --ch-disable
```
### --ch-add CH_ADD
Add a secondary channel, you must specify a channel name.
**Usage**
``` shell
meshtastic --ch-add testing-channel
```
### --ch-del
Delete the ch-index channel.
**Usage**
``` shell
meshtastic --ch-index 1 --ch-del
```
### --ch-enable
Enable the specified channel.
**Usage**
``` shell
meshtastic --ch-index 1 --ch-enable
```
### --ch-disable
Disable the specified channel.
**Usage**
``` shell
meshtastic --ch-index 1 --ch-disable
```
### --ch-set CH_SET CH_SET
Set a channel parameter.
**Usage**
``` shell
meshtastic --ch-set id 1234
```
### --ch-longslow
Change to the standard long-range (but slow) channel.
**Usage**
``` shell
meshtastic --ch-longslow
```
### --ch-shortfast
Change to the standard fast (but short range) channel.
**Usage**
``` shell
meshtastic --ch-shortfast
```
### --set-owner SET_OWNER
Set device owner name.
**Usage**
``` shell
meshtastic --dest \!28979058 --set-owner "MeshyJohn"
```
### --set-ham SET_HAM
Set licensed HAM ID and turn off encryption.
**Usage**
``` shell
meshtastic --set-ham KI1345
```
### --dest DEST
The destination node id for any sent commands
**Usage**
``` shell
meshtastic --dest \!28979058 --set-owner "MeshyJohn"
```
### --sendtext SENDTEXT
Send a text message.
**Usage**
``` shell
meshtastic --sendtext "Hello Mesh!"
```
### --sendping
Send a ping message (which requests a reply).
**Usage**
``` shell
meshtastic --sendping
```
### --reboot
Tell the destination node to reboot.
**Usage**
``` shell
meshtastic --dest \!28979058 --reboot
```
### --reply
Reply to received messages.
**Usage**
``` shell
meshtastic --reply
```
### --gpio-wrb GPIO_WRB GPIO_WRB
Set a particular GPIO # to 1 or 0.
**Usage**
``` shell
meshtastic --port /dev/ttyUSB0 --gpio-wrb 4 1 --dest \!28979058
```
### --gpio-rd GPIO_RD
Read from a GPIO mask.
**Usage**
``` shell
meshtastic --port /dev/ttyUSB0 --gpio-rd 0x10 --dest \!28979058
```
### --gpio-watch GPIO_WATCH
Start watching a GPIO mask for changes.
**Usage**
``` shell
meshtastic --port /dev/ttyUSB0 --gpio-watch 0x10 --dest \!28979058
```
### --no-time
Suppress sending the current time to the mesh.
**Usage**
``` shell
meshtastic --port /dev/ttyUSB0 --no-time
```
### --setalt SETALT
Set device altitude (allows use without GPS).
**Usage**
``` shell
meshtastic --setalt 120
```
### --setlat SETLAT
Set device latitude (allows use without GPS).
**Usage**
``` shell
meshtastic --setlat 25.2
```
### --setlon SETLON
Set device longitude (allows use without GPS).
**Usage**
``` shell
meshtastic --setlon -16.8
```
### --debug
Show API library debug log messages.
**Usage**
``` shell
meshtastic --debug --info
```
### --test
Run stress test against all connected Meshtastic devices.
**Usage**
``` shell
meshtastic --test
```
### --ble BLE
BLE mac address to connect to (BLE is not yet supported for this tool).
**Usage**
``` shell
meshtastic --ble "83:38:92:32:37:48"
```
### --noproto
Don't start the API, just function as a dumb serial terminal.
**Usage**
``` shell
meshtastic --noproto
```
### --version
Show program's version number and exit.
**Usage**
``` shell
meshtastic --version
```
## Deprecated Arguments
### --setchan
Deprecated - use "--ch-set param value" instead.
### --set-router
Deprecated - use "--set is_router true" instead.
### --unset-router
Deprecated - use "--set is_router false" instead.

View File

@@ -1,17 +0,0 @@
# Stream protocol
Documentation on how out protobufs get encoded when placed onto any stream transport (i.e. TCP or serial, but not UDP or BLE)
## Wire encoding
When sending protobuf packets over serial or TCP each packet is preceded by uint32 sent in network byte order (big endian).
The upper 16 bits must be 0x94C3. The lower 16 bits are packet length (this encoding gives room to eventually allow quite large packets).
Implementations validate length against the maximum possible size of a BLE packet (our lowest common denominator) of 512 bytes. If the
length provided is larger than that we assume the packet is corrupted and begin again looking for 0x4403 framing.
The packets flowing towards the device are ToRadio protobufs, the packets flowing from the device are FromRadio protobufs.
The 0x94C3 marker can be used as framing to (eventually) resync if packets are corrupted over the wire.
Note: the 0x94C3 framing was chosen to prevent confusion with the 7 bit ascii character set. It also doesn't collide with any valid utf8 encoding. This makes it a bit easier to start a device outputting regular debug output on its serial port and then only after it has received a valid packet from the PC, turn off unencoded debug printing and switch to this
packet encoding.

16
exampleConfig.yaml Normal file
View File

@@ -0,0 +1,16 @@
# example config using camelCase keys
owner: Bob TBeam
ownerShort: BOB
channelUrl: https://www.meshtastic.org/d/#CgUYAyIBAQ
location:
lat: 35.88888
lon: -93.88888
alt: 304
userPrefs:
region: 1
isAlwaysPowered: "true"
screenOnSecs: 31536000
waitBluetoothSecs: 31536000

View File

@@ -1,15 +1,46 @@
# example configuration file with snake_case keys
owner: Bob TBeam
owner_short: BOB
channel_url: https://www.meshtastic.org/d/#CgUYAyIBAQ
channel_url: https://www.meshtastic.org/e/#CgMSAQESCDgBQANIAVAe
canned_messages: Hi|Bye|Yes|No|Ok
ringtone: 24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p
location:
lat: 35.88888
lon: -93.88888
alt: 304
user_prefs:
region: 1
is_always_powered: 'true'
send_owner_interval: 2
screen_on_secs: 31536000
wait_bluetooth_secs: 31536000
config:
bluetooth:
enabled: true
fixedPin: 123456
device:
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

21
examples/get_hw.py Normal file
View File

@@ -0,0 +1,21 @@
"""Simple program to demo how to use meshtastic library.
To run: python examples/get_hw.py
"""
import sys
import meshtastic
import meshtastic.serial_interface
# simple arg check
if len(sys.argv) != 1:
print(f"usage: {sys.argv[0]}")
print("Print the hardware model for the local node.")
sys.exit(3)
iface = meshtastic.serial_interface.SerialInterface()
if iface.nodes:
for n in iface.nodes.values():
if n["num"] == iface.myInfo.my_node_num:
print(n["user"]["hwModel"])
iface.close()

View File

@@ -0,0 +1,19 @@
"""Simple program to demo how to use meshtastic library.
To run: python examples/hello_world_serial.py
"""
import sys
import meshtastic
import meshtastic.serial_interface
# simple arg check
if len(sys.argv) < 2:
print(f"usage: {sys.argv[0]} message")
sys.exit(3)
# By default will try to find a meshtastic device,
# otherwise provide a device path like /dev/ttyUSB0
iface = meshtastic.serial_interface.SerialInterface()
iface.sendText(sys.argv[1])
iface.close()

20
examples/info_example.py Normal file
View File

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

View File

@@ -0,0 +1,30 @@
"""Simple program to demo how to use meshtastic library.
To run: python examples/pub_sub_example.py
"""
import sys
from pubsub import pub
import meshtastic
import meshtastic.tcp_interface
# simple arg check
if len(sys.argv) < 2:
print(f"usage: {sys.argv[0]} host")
sys.exit(1)
def onConnection(interface, topic=pub.AUTO_TOPIC): # pylint: disable=unused-argument
"""This is called when we (re)connect to the radio."""
print(interface.myInfo)
interface.close()
pub.subscribe(onConnection, "meshtastic.connection.established")
try:
iface = meshtastic.tcp_interface.TCPInterface(sys.argv[1])
except:
print(f"Error: Could not connect to {sys.argv[1]}")
sys.exit(1)

View File

@@ -0,0 +1,39 @@
"""Simple program to demo how to use meshtastic library.
To run: python examples/pub_sub_example2.py
"""
import sys
import time
from pubsub import pub
import meshtastic
import meshtastic.tcp_interface
# simple arg check
if len(sys.argv) < 2:
print(f"usage: {sys.argv[0]} host")
sys.exit(1)
def onReceive(packet, interface): # pylint: disable=unused-argument
"""called when a packet arrives"""
print(f"Received: {packet}")
def onConnection(interface, topic=pub.AUTO_TOPIC): # pylint: disable=unused-argument
"""called when we (re)connect to the radio"""
# defaults to broadcast, specify a destination ID if you wish
interface.sendText("hello mesh")
pub.subscribe(onReceive, "meshtastic.receive")
pub.subscribe(onConnection, "meshtastic.connection.established")
try:
iface = meshtastic.tcp_interface.TCPInterface(hostname=sys.argv[1])
while True:
time.sleep(1000)
iface.close()
except Exception as ex:
print(f"Error: Could not connect to {sys.argv[1]} {ex}")
sys.exit(1)

View File

@@ -0,0 +1,29 @@
"""Program to scan for hardware
To run: python examples/scan_for_devices.py
"""
import sys
from meshtastic.util import (
active_ports_on_supported_devices,
detect_supported_devices,
get_unique_vendor_ids,
)
# simple arg check
if len(sys.argv) != 1:
print(f"usage: {sys.argv[0]}")
print("Detect which device we might have.")
sys.exit(3)
vids = get_unique_vendor_ids()
print(f"Searching for all devices with these vendor ids {vids}")
sds = detect_supported_devices()
if len(sds) > 0:
print("Detected possible devices:")
for d in sds:
print(f" name:{d.name}{d.version} firmware:{d.for_firmware}")
ports = active_ports_on_supported_devices(sds)
print(f"ports:{ports}")

21
examples/set_owner.py Normal file
View File

@@ -0,0 +1,21 @@
"""Simple program to demo how to use meshtastic library.
To run: python examples/set_owner.py Bobby 333
"""
import sys
import meshtastic
import meshtastic.serial_interface
# simple arg check
if len(sys.argv) < 2:
print(f"usage: {sys.argv[0]} long_name [short_name]")
sys.exit(3)
iface = meshtastic.serial_interface.SerialInterface()
long_name = sys.argv[1]
short_name = None
if len(sys.argv) > 2:
short_name = sys.argv[2]
iface.localNode.setOwner(long_name, short_name)
iface.close()

6
examples/show_ports.py Normal file
View File

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

View File

@@ -0,0 +1,14 @@
"""Demonstration of how to look up a radio's location via its LAN connection.
Before running, connect your machine to the same WiFi network as the radio.
"""
import meshtastic
import meshtastic.tcp_interface
radio_hostname = "meshtastic.local" # Can also be an IP
iface = meshtastic.tcp_interface.TCPInterface(radio_hostname)
my_node_num = iface.myInfo.my_node_num
pos = iface.nodesByNum[my_node_num]["position"]
print(pos)
iface.close()

57
examples/waypoint.py Normal file
View File

@@ -0,0 +1,57 @@
"""Program to create and delete waypoint
To run:
python3 examples/waypoint.py --port /dev/ttyUSB0 create 45 test the_desc_2 '2024-12-18T23:05:23' 48.74 7.35
python3 examples/waypoint.py delete 45
"""
import argparse
import datetime
import sys
import meshtastic
import meshtastic.serial_interface
parser = argparse.ArgumentParser(
prog='waypoint',
description='Create and delete Meshtastic waypoint')
parser.add_argument('--port', default=None)
parser.add_argument('--debug', default=False, action='store_true')
subparsers = parser.add_subparsers(dest='cmd')
parser_delete = subparsers.add_parser('delete', help='Delete a waypoint')
parser_delete.add_argument('id', help="id of the waypoint")
parser_create = subparsers.add_parser('create', help='Create a new waypoint')
parser_create.add_argument('id', help="id of the waypoint")
parser_create.add_argument('name', help="name of the waypoint")
parser_create.add_argument('description', help="description of the waypoint")
parser_create.add_argument('icon', help="icon of the waypoint")
parser_create.add_argument('expire', help="expiration date of the waypoint as interpreted by datetime.fromisoformat")
parser_create.add_argument('latitude', help="latitude of the waypoint")
parser_create.add_argument('longitude', help="longitude of the waypoint")
args = parser.parse_args()
print(args)
# By default will try to find a meshtastic device,
# otherwise provide a device path like /dev/ttyUSB0
if args.debug:
d = sys.stderr
else:
d = None
with meshtastic.serial_interface.SerialInterface(args.port, debugOut=d) as iface:
if args.cmd == 'create':
p = iface.sendWaypoint(
waypoint_id=int(args.id),
name=args.name,
description=args.description,
icon=args.icon,
expire=int(datetime.datetime.fromisoformat(args.expire).timestamp()),
latitude=float(args.latitude),
longitude=float(args.longitude),
)
else:
p = iface.deleteWaypoint(int(args.id))
print(p)
# iface.close()

20
info/mac/heltec.txt Normal file
View File

@@ -0,0 +1,20 @@
ioreg -p IOUSB > /tmp/d
> | +-o CP2102 USB to UART Bridge Controller@14400000 <class AppleUSBDevice, id 0x10005c048, registered, matched, active, busy 0 (9 ms), retain 12>
system_profiler SPUSBDataType > /tmp/b
37a38,50
> CP2102 USB to UART Bridge Controller:
>
> Product ID: 0xea60
> Vendor ID: 0x10c4 (Silicon Laboratories, Inc.)
> Version: 1.00
> Serial Number: 0001
> Speed: Up to 12 Mb/s
> Manufacturer: Silicon Labs
> Location ID: 0x14400000 / 53
> Current Available (mA): 500
> Current Required (mA): 100
> Extra Operating Current (mA): 0

30
info/mac/nano_g1.txt Normal file
View File

@@ -0,0 +1,30 @@
meshtastic detected port: /dev/cu.wchusbserial53820208781
ioreg -p IOUSB
shows this:
| +-o USB Single Serial@14300000 <class AppleUSBDevice, id 0x1000407a5, registered, matched, active, busy 0 (18 ms), retain 14>
system_profiler SPUSBDataType > /tmp/a
with device plugged in
system_profiler SPUSBDataType > /tmp/b
with device not plugged in
diff /tmp/a /tmp/b
< USB Single Serial:
<
< Product ID: 0x55d4
< Vendor ID: 0x1a86
< Version: 4.43
< Serial Number: 5382020878
< Speed: Up to 12 Mb/s
< Location ID: 0x14300000 / 63
< Current Available (mA): 500
< Current Required (mA): 134
< Extra Operating Current (mA): 0

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

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

View File

@@ -0,0 +1,68 @@
> | +-o WisCore RAK4631 Board@14400000 <class AppleUSBDevice, id 0x10005c158, registered, matched, active, busy 0 (18 ms), retain 14>
/dev/cu.usbmodem14401
% ls -al /dev/*modem*
crw-rw-rw- 1 root wheel 0x9000005 Jan 29 15:32 /dev/cu.usbmodem14401
crw-rw-rw- 1 root wheel 0x9000004 Jan 29 15:31 /dev/tty.usbmodem14401
Note: On a Mac Air, output is:
% system_profiler SPUSBDataType
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8103USBXHCI
USB 3.1 Bus:
Host Controller Driver: AppleT8103USBXHCI
WisCore RAK4631 Board:
Product ID: 0x8029
Vendor ID: 0x239a
Version: 1.00
Serial Number: E6CF9502B1D410D8
Speed: Up to 12 Mb/s
Manufacturer: RAKwireless
Location ID: 0x01100000 / 2
Current Available (mA): 500
Current Required (mA): 100
Extra Operating Current (mA): 0
However, in FTHR840BOOT mode, it shows this:
% system_profiler SPUSBDataType
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8103USBXHCI
USB 3.1 Bus:
Host Controller Driver: AppleT8103USBXHCI
Feather nRF52840 Express:
Product ID: 0x0029
Vendor ID: 0x239a
Version: 1.00
Serial Number: E6CF9502B1D410D8
Speed: Up to 12 Mb/s
Manufacturer: Adafruit Industries
Location ID: 0x01100000 / 1
Current Available (mA): 500
Current Required (mA): 100
Extra Operating Current (mA): 0
Media:
nRF UF2:
Capacity: 33.7 MB (33,690,112 bytes)
Removable Media: Yes
BSD Name: disk4
Logical Unit: 0
Partition Map Type: Unknown
S.M.A.R.T. status: Verified
USB Interface: 2
$ cat /Volumes/FTHR840BOOT/INFO_UF2.TXT
UF2 Bootloader 0.3.2-109-gd6b28e6-dirty lib/nrfx (v2.0.0) lib/tinyusb (0.6.0-272-g4e6aa0d8) lib/uf2 (heads/master)
Model: Adafruit Feather nRF52840 Express
Board-ID: nRF52840-Feather-revD
SoftDevice: S140 version 6.1.1
Date: Jun 16 2020

18
info/mac/rak4631_5005.txt Normal file
View File

@@ -0,0 +1,18 @@
no device plugged in
% ioreg -p IOUSB > /tmp/a
device plugged in, in "boot" mode
% ioreg -p IOUSB > /tmp/b
device plugged in, botted to Meshtastic firmware
% ioreg -p IOUSB > /tmp/c
(venv) sweet Meshtastic-python % diff /tmp/a /tmp/b (with most info removed)
> | +-o Feather nRF52840 Express@14400000 <class AppleUSBDevice, id 0x10005c0ff, registered, matched, active, busy 0 (22 ms), retain 16>
diff /tmp/a /tmp/c (with most info removed)
> | +-o WisCore RAK4631 Board@14400000 <class AppleUSBDevice, id 0x10005c134, registered, matched, active, busy 0 (17 ms), retain 14>
Meshtastic detected port on /dev/cu.usbmodem14401

Some files were not shown because too many files have changed in this diff Show More