1
1
forked from iarv/meshview

740 Commits

Author SHA1 Message Date
pablorevilla-meshtastic
f87831c3a5 small map change 2026-02-18 16:17:18 -08:00
pablorevilla-meshtastic
9c40ce2d59 add world meshview tag 2026-02-18 15:32:16 -08:00
pablorevilla-meshtastic
f108197e5f Documentation update 2026-02-13 16:28:52 -08:00
pablorevilla-meshtastic
20c2a3dc62 Update to stats page 2026-02-13 15:48:40 -08:00
pablorevilla-meshtastic
4a7fa1df08 fix error for sqlite 2026-02-13 14:20:12 -08:00
pablorevilla-meshtastic
685dbc9505 Added the ability to track gateways and present them in varous pages 2026-02-13 14:14:46 -08:00
pablorevilla-meshtastic
9aacceda28 fix location of edges now that the node is in a different spot 2026-02-12 13:29:51 -08:00
pablorevilla-meshtastic
a7051e7d26 More fixes for maps overlay 2026-02-12 12:01:51 -08:00
pablorevilla-meshtastic
7926e81562 documents updte 2026-02-12 11:34:19 -08:00
pablorevilla-meshtastic
2002e093af Added visivility on maps of nodes that overlap 2026-02-12 11:33:24 -08:00
pablorevilla-meshtastic
fc44f49f2d Work on updating protobufs and .gitignore 2026-02-11 17:30:53 -08:00
pablorevilla-meshtastic
89fbc6aeca changes 2026-02-11 07:00:21 -08:00
pablorevilla-meshtastic
20e3f9c104 Added Observed coverage to the node.html page 2026-02-10 15:33:59 -08:00
pablorevilla-meshtastic
17fa92d4cf modified the colors 2026-02-10 12:23:17 -08:00
pablorevilla-meshtastic
a48a3a4141 Updating anb fixing errors 2026-02-10 11:07:22 -08:00
pablorevilla-meshtastic
7d5b638eac changes to coverage page 2026-02-10 10:27:07 -08:00
pablorevilla-meshtastic
5f5fe0da90 Merge branch 'pr-128' into 3.0.5 2026-02-10 10:04:40 -08:00
Amy Nagle
dd98814b2c Normalize port number lists 2026-02-10 10:33:54 -05:00
pablorevilla-meshtastic
4dd999178c more details 2026-02-09 21:31:34 -08:00
pablorevilla-meshtastic
01dce2a5e0 Update to check for new requirements 2026-02-09 21:29:53 -08:00
pablorevilla-meshtastic
9622092c17 Add basic coverege support. 2026-02-09 21:17:22 -08:00
pablorevilla-meshtastic
29da1487d4 Merge branch 'pr-127' into 3.0.5 2026-02-09 07:48:33 -08:00
Mike Weaver
357fb530e2 Add database health check to include last import time
Retrieve the last import time from the database during health check.

This is useful to setup monitoring for meshview instances that are no longer receiving messages.
2026-02-08 03:07:46 -07:00
pablorevilla-meshtastic
b43683a259 Added First Seen time to node.html and /api/nodes 2026-02-06 11:41:15 -08:00
pablorevilla-meshtastic
59379649e2 Add version number 2026-02-06 11:23:07 -08:00
pablorevilla-meshtastic
a62bc350c0 fix: update store.py 2026-02-05 18:25:23 -08:00
pablorevilla-meshtastic
82ff4bb0df Merge PR 124: QR/import, impersonation detection, node public keys 2026-02-05 18:02:49 -08:00
pablorevilla-meshtastic
c454f2ef3a started work on new traceroute template 2026-02-05 06:53:49 -08:00
pablorevilla-meshtastic
b93f640233 load language dictionaries into memory to reduce call to file system 2026-01-31 10:42:47 -08:00
pablorevilla-meshtastic
018e16e9fa updates to language dictionaries 2026-01-26 10:40:20 -08:00
pablorevilla-meshtastic
41397072af Added unmaped packets detials to map.htnl 2026-01-26 09:15:01 -08:00
pablorevilla-meshtastic
43be448100 fix typo in container workflow file 2026-01-25 21:06:46 -08:00
pablorevilla-meshtastic
8c7f181002 Merge branch 'master' of github.com:pablorevilla-meshtastic/meshview 2026-01-25 20:47:03 -08:00
pablorevilla-meshtastic
5195868719 Made latest to follow master 2026-01-25 20:43:43 -08:00
Pablo Revilla
a473e32c59 Add initial server and configuration settings 2026-01-25 13:39:14 -08:00
pablorevilla-meshtastic
be51dc9c55 working on container 2026-01-25 13:34:26 -08:00
pablorevilla-meshtastic
bea6c8cd8e Fix how we show the actual channel on the packet list. 2026-01-24 23:31:57 -08:00
pablorevilla-meshtastic
351c35ef42 Fix issues with decryption of secondary keys 2026-01-24 21:38:14 -08:00
pablorevilla-meshtastic
7f722b6f12 Updated Readme.md 2026-01-24 11:20:34 -08:00
pablorevilla-meshtastic
52f1a1e788 updated the version number and date 2026-01-24 11:14:06 -08:00
pablorevilla-meshtastic
f44a78730a Added the ablility to skip packets with specific from_id and have secondary enccryption key for mqtt_reader. 2026-01-23 21:49:03 -08:00
pablorevilla-meshtastic
a9a5e046ea more container test 2026-01-23 13:02:34 -08:00
pablorevilla-meshtastic
37386f9e28 change to container.yml 2026-01-23 11:58:48 -08:00
pablorevilla-meshtastic
b66bfb1ee9 Fix error on container build and update README 2026-01-23 11:42:03 -08:00
pablorevilla-meshtastic
caf9cd1596 Updated list of sites runing meshview 2026-01-22 07:42:24 -08:00
pablorevilla-meshtastic
a4ebd2b23c work on net.html to limit packets to last 12 hours instead of 48 hours. 2026-01-21 20:11:17 -08:00
pablorevilla-meshtastic
5676ade6b7 fix api query so that weekly mesh works. 2026-01-21 17:19:19 -08:00
pablorevilla-meshtastic
319f8eac06 optimization 2026-01-20 14:48:33 -08:00
pablorevilla-meshtastic
d85132133a fix bug 2026-01-20 11:27:42 -08:00
pablorevilla-meshtastic
b6d8af409c fix bug on backwards compatibility 2026-01-20 10:10:39 -08:00
pablorevilla-meshtastic
896a0980d5 Update Scripts for PortgreSQL 2026-01-15 16:24:42 -08:00
pablorevilla-meshtastic
7d395e5e27 Correct documentation error 2026-01-15 14:42:18 -08:00
pablorevilla-meshtastic
c3cc01d7e7 Docuement Update 2026-01-15 14:30:04 -08:00
pablorevilla-meshtastic
ecbadc6087 configure "Wal" for sqlite 2026-01-15 14:10:49 -08:00
pablorevilla-meshtastic
ff30623bdf Documentation updte 2026-01-15 11:55:07 -08:00
pablorevilla-meshtastic
a43433ccb4 Update documentation 2026-01-15 11:51:03 -08:00
pablorevilla-meshtastic
4d9db2a52c Update instructions 2026-01-15 11:49:25 -08:00
pablorevilla-meshtastic
e30b59851f Update to 2026-01-15 11:39:24 -08:00
pablorevilla-meshtastic
36dd91be63 Merge branch 'db_updates' 2026-01-15 09:04:09 -08:00
pablorevilla-meshtastic
c9639d851b Fix Time function on store.py 2026-01-15 08:48:22 -08:00
Pablo Revilla
4516c84128 Modify cleanup.sh to use import_time_us for queries
Updated cleanup script to use import_time_us for deletions.
2026-01-14 22:11:52 -08:00
pablorevilla-meshtastic
fa98f56318 Made a cople of changes to the time handling and database config. 2026-01-12 20:10:19 -08:00
pablorevilla-meshtastic
f85e783e8c Adding code to work with multiple databases types. 2026-01-12 14:18:51 -08:00
Pablo Revilla
a882bc22dd Update README with version 3.0.2 details
Added notes about database changes for version 3.0.2.
2026-01-12 10:38:55 -08:00
pablorevilla-meshtastic
e12e3a2a41 Database change to remove import time columns 2026-01-09 13:30:14 -08:00
pablorevilla-meshtastic
da31794d8d Bump version to 3.0.2 and update release date to 2026-1-9 2026-01-09 11:49:58 -08:00
pablorevilla-meshtastic
9912f6b181 testing commit message functionality 2026-01-08 18:39:01 -08:00
pablorevilla-meshtastic
cb4cc281c6 fix speed of node list rendering 2026-01-08 17:38:56 -08:00
pablorevilla-meshtastic
571559114d Add node status indicator and improve favorites handling in nodelist 2026-01-08 17:38:12 -08:00
pablorevilla-meshtastic
df26df07f1 Changes to node.html. fix some of the data 2026-01-08 14:59:45 -08:00
pablorevilla-meshtastic
ffc7340bc9 Changes to nodelist.html. fix some of the data 2026-01-07 17:19:32 -08:00
pablorevilla-meshtastic
1d58aaba83 Changes to nodelist.html. fix some of the data 2026-01-07 13:35:58 -08:00
pablorevilla-meshtastic
b2bb9345fe Changes to nodelist.html. fix some of the data 2026-01-07 13:29:56 -08:00
pablorevilla-meshtastic
9686622b56 Changes to node.html. fix some of the data 2026-01-07 10:01:02 -08:00
pablorevilla-meshtastic
f7644a9573 Changes to node.html. fix some of the data 2026-01-07 09:48:26 -08:00
Pablo Revilla
e48e9464d7 Modify packet.html to add distance 2026-01-03 21:48:19 -08:00
Pablo Revilla
b72bc5d52b Modify packet.html to add distance 2026-01-03 21:44:26 -08:00
Pablo Revilla
1220f0bcbd Modify node.html to add statistics 2026-01-03 21:28:33 -08:00
Pablo Revilla
539410d5bb Modify node.html to add statistics 2026-01-03 21:26:39 -08:00
Pablo Revilla
383b576d18 Modify node.html to add statistics 2026-01-03 21:12:24 -08:00
Pablo Revilla
64a55a3ef3 Modify node.html to add statistics 2026-01-03 20:51:17 -08:00
Pablo Revilla
9408201e57 Modify node.html to add statistics 2026-01-03 19:27:00 -08:00
Pablo Revilla
f75d6bf749 Modify node.html to add statistics 2026-01-03 19:00:39 -08:00
Pablo Revilla
924d223866 Modify node.html to add statistics 2026-01-03 18:13:57 -08:00
Pablo Revilla
e9dcca1f19 Modify node.html to add statistics 2025-12-31 11:58:45 -08:00
Pablo Revilla
00cc2abd23 Modify node.html to add statistics 2025-12-31 11:56:18 -08:00
Pablo Revilla
b76477167d Modify top.html to add paging 2025-12-31 11:13:52 -08:00
Pablo Revilla
b41b249a6d Modify top.html to add paging 2025-12-31 10:38:13 -08:00
Pablo Revilla
71fcda2dd6 Modify top.html to add paging 2025-12-30 09:27:51 -08:00
Pablo Revilla
c4453fbb31 Modify packet.html to sort by hop count. 2025-12-24 10:54:09 -08:00
Pablo Revilla
79fa3f66a8 Fix chart on node.html. 2025-12-24 10:06:17 -08:00
Pablo Revilla
0ce64ac975 Fix chart on node.html. 2025-12-10 09:56:30 -08:00
Pablo Revilla
350aa9e4a3 Fix chart on node.html. 2025-12-09 17:40:49 -08:00
Pablo Revilla
e5bbf972c7 Fix chart on node.html. 2025-12-09 17:35:52 -08:00
Pablo Revilla
4326e12e88 Fix chart on node.html. 2025-12-09 16:58:38 -08:00
Pablo Revilla
00aa3216ff Fix chart on node.html. 2025-12-09 16:19:55 -08:00
Pablo Revilla
3d6c01f020 minor fix on node.html table of tackets shows to and from not just from. 2025-12-08 10:45:33 -08:00
Pablo Revilla
d3bf0ede67 minor fix on node.html table of tackets shows to and from not just from. 2025-12-08 10:29:24 -08:00
Pablo Revilla
2b02166d82 minor fix on node.html table of tackets shows to and from not just from. 2025-12-07 20:02:33 -08:00
Pablo Revilla
2fd36b4b11 minor fix on node.html table of tackets shows to and from not just from. 2025-12-07 17:29:01 -08:00
Pablo Revilla
8aa1c59873 minor fix to langauge dictionary 2025-12-06 11:30:25 -08:00
Pablo Revilla
cd036b8004 efficiency improvement node.html now it only queries the needed node info rather than all the nodes. 2025-12-06 11:26:36 -08:00
Pablo Revilla
989da239fb efficiency improvement for map.html. Now it only download the edges that need to be drawn. 2025-12-04 14:15:46 -08:00
Pablo Revilla
31626494d3 Fix README.md details 2025-12-04 10:38:58 -08:00
Pablo Revilla
960a7ef075 Fix README.md details 2025-12-04 09:41:59 -08:00
Pablo Revilla
60c4d22d2d Update multi-language support. So far Spanish and english. 2025-12-04 09:39:27 -08:00
Pablo Revilla
13a094be00 Update multi-language support. So far Spanish and english. 2025-12-04 09:38:18 -08:00
Pablo Revilla
7744cedd8c Update multi-language support. So far Spanish and english. 2025-12-04 09:35:34 -08:00
Pablo Revilla
ad42c1aeaf Update multi-language support. So far Spanish and english. 2025-12-02 16:03:25 -08:00
Pablo Revilla
41f7bf42a3 Update multi-language support. So far Spanish and english. 2025-12-02 14:45:31 -08:00
Pablo Revilla
0543aeb650 Update multi-language support. So far Spanish and english. 2025-12-02 14:24:10 -08:00
Pablo Revilla
679071cc14 Update multi-language support. So far Spanish and english. 2025-12-02 13:54:39 -08:00
Pablo Revilla
198afcc7d8 Update multi-language support. So far Spanish and english. 2025-12-02 13:51:18 -08:00
Pablo Revilla
191a01a03c update version date 2025-12-01 09:48:51 -08:00
Pablo Revilla
fd653f8234 Fixed Sort nodes by firmware in nodelist.html 2025-12-01 09:38:08 -08:00
Pablo Revilla
2149fed8c5 Fixed Sort nodes by firmware in nodelist.html 2025-11-30 10:38:18 -08:00
Pablo Revilla
5609d18284 worked on making map and base all API driven 2025-11-29 19:27:57 -08:00
Pablo Revilla
705b0b79fc worked on making map and base all API driven 2025-11-29 19:12:53 -08:00
Joel Krauska
32ad8e3a9c Fix search 2 (#108)
Co-authored-by: Pablo Revilla <pablorevilla@gmail.com>
2025-11-29 19:07:58 -08:00
Joel Krauska
e77428661c Version 3.0.0 Feature Release - Target Before Thanksgiving! (#96)
* Add alembic DB schema management (#86)

* Use alembic
* add creation helper
* example migration tool

* Store UTC int time in DB (#81)

* use UTC int time

* Remove old index notes script -- no longer needed

* modify alembic to support cleaner migrations

* add /version json endpoint

* move technical docs

* remove old migrate script

* add readme in docs:

* more doc tidy

* rm

* update api docs

* ignore other database files

* health endpoint

* alembic log format

* break out api calls in to their own file to reduce footprint

* ruff and docs

* vuln

* Improves arguments in mvrun.py

* Set dbcleanup.log location configurable

* mvrun work

* fallback if missing config

* remove unused loop

* improve migrations and fix logging problem with mqtt

* Container using slim/uv

* auto build containers

* symlink

* fix symlink

* checkout and containerfile

* make /app owned by ap0p

* Traceroute Return Path logged and displayed (#97)


* traceroute returns are now logged and /packetlist now graphs the correct data for a return route
* now using alembic to update schema
* HOWTO - Alembic

---------

Co-authored-by: Joel Krauska <jkrauska@gmail.com>

* DB Backups

* backups and cleanups are different

* ruff

* Docker Docs

* setup-dev

* graphviz for dot in Container

* Summary of 3.0.0 stuff

* Alembic was blocking mqtt logs

* Add us first/last timestamps to node table too

* Worked on /api/packet. Needed to modify
- Store.py to read the new time data
- api.py to present the new time data
- firehose.html chat.html and map.html now use the new apis and the time is the browser local time

* Worked on /api/packet. Needed to modify
- Store.py to read the new time data
- api.py to present the new time data
- firehose.html chat.html and map.html now use the new apis and the time is the browser local time

* Improves container build (#94)

* Worked on /api/packet. Needed to modify
- Store.py to read the new time data
- api.py to present the new time data
- firehose.html chat.html and map.html now use the new apis and the time is the browser local time

* Worked on /api/packet. Needed to modify
- Store.py to read the new time data
- api.py to present the new time data
- firehose.html chat.html and map.html now use the new apis and the time is the browser local time

* Worked on /api/packet. Needed to modify
- Added new api endpoint /api/packets_seen
- Modified web.py and store.py to support changes to APIs.
- Started to work on new_node.html and new_packet.html for presentation of data.

* Worked on /api/packet. Needed to modify
- Added new api endpoint /api/packets_seen
- Modified web.py and store.py to support changes to APIs.
- Started to work on new_node.html and new_packet.html for presentation of data.

* Finishing up all the pages for the 3.0 release.

Now all pages are functional.

* Finishing up all the pages for the 3.0 release.

Now all pages are functional.

* fix ruff format

* more ruff

* Finishing up all the pages for the 3.0 release.

Now all pages are functional.

* Finishing up all the pages for the 3.0 release.

Now all pages are functional.

* pyproject.toml requirements

* use sys.executable

* fix 0 epoch dates in /chat

* Make the robots do our bidding

* another compatibility fix when _us is empty and we need to sort by BOTH old and new

* Finishing up all the pages for the 3.0 release.

Now all pages are functional.

* Finishing up all the pages for the 3.0 release.

Now all pages are functional.

* Remamed new_node to node. shorter and descriptive.

* Remamed new_node to node. shorter and descriptive.

* Remamed new_node to node. shorter and descriptive.

* Remamed new_node to node. shorter and descriptive.

* Remamed new_node to node. shorter and descriptive.

* Remamed new_node to node. shorter and descriptive.

* More changes... almost ready for release.

Ranamed 2 pages for easy or reading.

* Fix the net page as it was not showing the date information

* Fix the net page as it was not showing the date information

* Fix the net page as it was not showing the date information

* Fix the net page as it was not showing the date information

* ruff

---------

Co-authored-by: Óscar García Amor <ogarcia@connectical.com>
Co-authored-by: Jim Schrempp <jschrempp@users.noreply.github.com>
Co-authored-by: Pablo Revilla <pablorevilla@gmail.com>
2025-11-28 11:17:20 -08:00
Joel Krauska
e68cdf8cc1 test commit
Added information about the new statistic page and API.
2025-11-03 12:43:07 -08:00
Pablo Revilla
60ae77772d worked on making map and base all API driven 2025-11-02 11:41:15 -08:00
Pablo Revilla
ed33bfe540 worked on making map and base all API driven 2025-11-02 11:39:29 -08:00
Pablo Revilla
47a22911ca worked on making map and base all API driven 2025-11-01 18:30:26 -07:00
Pablo Revilla
d61427db8f worked on making map and base all API driven 2025-10-31 16:55:41 -07:00
Pablo Revilla
f11455eebc worked on making map and base all API driven 2025-10-31 16:55:05 -07:00
Pablo Revilla
0a548904c8 Merge remote-tracking branch 'origin/master' 2025-10-31 16:54:15 -07:00
Pablo Revilla
a0e5bb0747 worked on making map and base all API driven 2025-10-31 16:52:32 -07:00
Pablo Revilla
986ef8e4e5 Merge pull request #92 from io235/master
Add Salzburg/Austria to list of running instances
2025-10-31 11:07:59 -07:00
Pablo Revilla
54f7f1b1ce worked on making map and base all API driven 2025-10-31 07:45:48 -07:00
Io
6886a97874 Add Salzburg/Austria to list of running instances 2025-10-31 10:09:13 +00:00
Pablo Revilla
c4f2e3f24f Merge pull request #87 from jkrauska/traceLines
render traceroutes on top
2025-10-27 21:31:11 -07:00
Joel Krauska
8db8e90f80 use ruff format 2025-10-27 14:40:41 -07:00
Joel Krauska
3ea2809df0 render traceroutes on top 2025-10-27 14:38:35 -07:00
Pablo Revilla
f7f932d821 worked on making map and base all API driven 2025-10-23 13:53:41 -07:00
Pablo Revilla
ad8835a46b worked on making map and base all API driven 2025-10-22 15:57:34 -07:00
Pablo Revilla
cbe4895b2c worked on making map and base all API driven 2025-10-22 15:22:47 -07:00
Pablo Revilla
d9b1d5ac49 worked on making map and base all API driven 2025-10-22 14:31:07 -07:00
Pablo Revilla
13aa73e88f worked on making map and base all API driven 2025-10-22 09:20:08 -07:00
Pablo Revilla
58244bff09 worked on making map and base all API driven 2025-10-22 08:54:18 -07:00
Pablo Revilla
635353f3c8 worked on making map and base all API driven 2025-10-21 21:07:28 -07:00
Pablo Revilla
d5fb589665 worked on making map and base all API driven 2025-10-18 15:52:50 -07:00
Pablo Revilla
a4b51ace73 worked on making map and base all API driven 2025-10-18 15:27:13 -07:00
Pablo Revilla
75d0d9ea6a worked on making map and base all API driven 2025-10-18 15:13:08 -07:00
Pablo Revilla
c909ff58a5 Merge pull request #80 from pablorevilla-meshtastic/revert-78-10-15-25-bugs2
Revert "Add configurable channel filtering with allowlist and minimum packet threshold"
2025-10-17 18:40:48 -07:00
Pablo Revilla
a15b039a1f Revert "Add configurable channel filtering with allowlist and minimum packet threshold" 2025-10-17 18:40:22 -07:00
Pablo Revilla
d52b7d0929 Merge pull request #78 from nullrouten0/10-15-25-bugs2
Add configurable channel filtering with allowlist and minimum packet threshold
2025-10-17 16:54:06 -07:00
Nathan
d56ee8f4c5 ruff fixes 2025-10-17 15:36:36 -07:00
Pablo Revilla
52ca8a4060 Merge branch 'master' into 10-15-25-bugs2 2025-10-17 15:09:10 -07:00
Pablo Revilla
e4a6de3615 worked on making map and base all API driven 2025-10-17 14:26:08 -07:00
Pablo Revilla
3cca445cad worked on making map and base all API driven 2025-10-17 12:54:44 -07:00
Pablo Revilla
8b0c7a16e7 Start adding language support 2025-10-16 13:34:35 -07:00
Nathan
c5a1009877 added channel filtering min_packets, and allowlist, fixed javascript error, new sample.config.ini sections 2025-10-16 01:07:49 -07:00
Pablo Revilla
65ada1ba3e Merge pull request #77 from pablorevilla-meshtastic/revert-73-maphours-stacked
Revert "Maphours changes stacked with filtering additions"
2025-10-15 21:36:29 -07:00
Pablo Revilla
7f94bc0e39 Merge branch 'master' into revert-73-maphours-stacked 2025-10-15 21:36:06 -07:00
Pablo Revilla
5d687da598 Merge pull request #76 from pablorevilla-meshtastic/revert-75-10-15-25-bugs
Revert "fixed map to show only channels with locations"
2025-10-15 21:33:16 -07:00
Pablo Revilla
a002cde2d7 Revert "fixed map to show only channels with locations" 2025-10-15 21:32:50 -07:00
Nathan
954cd4653d fixing node graph selector 2025-10-15 18:02:52 -07:00
Pablo Revilla
454c8ff6e2 Start adding language support 2025-10-15 16:27:43 -07:00
Pablo Revilla
021bc54f9d Start adding language support 2025-10-15 16:25:34 -07:00
Pablo Revilla
155ef89724 Merge remote-tracking branch 'origin/master' 2025-10-15 16:24:07 -07:00
Pablo Revilla
084647eec1 Start adding language support 2025-10-15 16:23:59 -07:00
Pablo Revilla
c13a851145 Merge pull request #75 from nullrouten0/10-15-25-bugs
fixed map to show only channels with locations
2025-10-15 16:15:01 -07:00
Pablo Revilla
114cd980b9 Merge branch 'master' into 10-15-25-bugs 2025-10-15 16:14:47 -07:00
Nathan
c23a650c0d fixed map to show only channels with locations 2025-10-15 16:07:52 -07:00
Pablo Revilla
318bf83403 Revert "Maphours changes stacked with filtering additions" 2025-10-15 15:57:56 -07:00
Pablo Revilla
636ab3e976 Start adding language support 2025-10-15 15:57:39 -07:00
Pablo Revilla
ea10a656e7 Start adding language support 2025-10-15 15:31:04 -07:00
Pablo Revilla
bcd007e5e2 Merge pull request #73 from nullrouten0/maphours-stacked
Maphours changes stacked with filtering additions
2025-10-15 15:09:24 -07:00
Nathan
b35acde821 Add channel-aware activity filters and API-driven dashboards 2025-10-14 21:34:52 -07:00
Nathan
b7752bc315 Map: activity time filters 2025-10-11 21:21:10 -07:00
Nathan
257bf7ffac Add channel filters to stats, chat, and firehose views 2025-10-11 16:28:34 -07:00
Pablo Revilla
d561d1a8de Start adding language support 2025-10-10 21:37:45 -07:00
Pablo Revilla
60e7389d83 Start adding language support 2025-10-10 21:34:42 -07:00
Pablo Revilla
4ac3262544 Start adding language support 2025-10-10 21:34:36 -07:00
Pablo Revilla
87643e4bd2 Start adding language support 2025-10-10 21:32:36 -07:00
Pablo Revilla
29174a649c Start adding language support 2025-10-10 21:28:48 -07:00
Pablo Revilla
712aea5139 Start adding language support 2025-10-10 21:10:35 -07:00
Pablo Revilla
d6fadd99d0 Start adding language support 2025-10-10 21:01:43 -07:00
Pablo Revilla
ae0b0944f0 Merge pull request #68 from jkrauska/profileTop
Add database indexes for 10X improvement in page load for /top
2025-10-10 12:58:41 -07:00
Pablo Revilla
d7b830e2f7 Merge pull request #69 from jkrauska/lornet.pl
fix for loranet.pl missing gateway_id
2025-10-08 18:31:05 -07:00
Joel Krauska
4a1737ebd4 fix for loranet.pl 2025-10-07 20:13:00 -07:00
Joel Krauska
60131007df fix for ruff 2025-10-07 19:49:57 -07:00
Joel Krauska
23d66c0d67 add database indexes 2025-10-07 18:22:50 -07:00
Pablo Revilla
30ba603f66 Merge pull request #67 from jkrauska/nodeListFavorites
FEATURE: Add NodeList Favorites and Remember Map Filters
2025-10-07 16:08:52 -07:00
Pablo Revilla
9811102681 Merge pull request #66 from jkrauska/apiEdges
BUG: Fix for api/edges traceback
2025-10-07 15:54:04 -07:00
Joel Krauska
7c92b06bec use ruff format 2025-10-07 14:15:29 -07:00
Joel Krauska
adda666a39 Add Favorites and Remember Filters 2025-10-07 14:04:14 -07:00
Joel Krauska
3e673f30bc Fix for api/edges traceback 2025-10-07 13:59:20 -07:00
Pablo Revilla
beefb4c5df Merge pull request #64 from jkrauska/ruffVersionFix
Bump ruff version - fix open call from lang work
2025-10-03 21:56:19 -07:00
Joel Krauska
e1bada8378 Bump ruff version - fix open call from lang work 2025-10-03 21:34:13 -07:00
Pablo Revilla
fbd6fcb123 Merge pull request #62 from jkrauska/ruffAutomation
Automate ruff in github action
2025-10-03 21:03:53 -07:00
Pablo Revilla
5d267effa5 Remove unused code 2025-10-03 20:56:47 -07:00
Joel Krauska
e28d248cf9 Automate ruff in github action 2025-10-03 20:55:11 -07:00
Pablo Revilla
ab101dd461 Merge pull request #61 from jkrauska/jkrauska/ruffFormat
Add Ruff formatting and pre-commit hooks
2025-10-03 20:49:44 -07:00
Joel Krauska
35212d403e Merge branch 'master' into jkrauska/ruffFormat 2025-10-03 20:43:16 -07:00
Pablo Revilla
3603014fd2 Added maps coordinates to /api/config 2025-10-03 20:41:02 -07:00
Joel Krauska
e25ff22127 Add Ruff formatting and pre-commit hooks
Configure Ruff as the code formatter and linter with pre-commit hooks.
  Applied automatic formatting fixes across the entire codebase including:
  - Import sorting and organization
  - Code style consistency (spacing, line breaks, indentation)
  - String quote normalization
  - Removal of trailing whitespace and unnecessary blank lines
2025-10-03 20:38:37 -07:00
Pablo Revilla
aa9922e7fa work on error where packet ids could be duplicate and crash the loop 2025-10-03 12:54:00 -07:00
Pablo Revilla
a9b16d6c18 work on error where packet ids could be duplicate and crash the loop 2025-10-03 12:33:04 -07:00
Pablo Revilla
b4fda0bb01 Merge remote-tracking branch 'origin/master' 2025-10-03 11:59:35 -07:00
Pablo Revilla
215817abc7 Cleanup the install process 2025-10-03 11:59:21 -07:00
Pablo Revilla
f167e8780d Merge pull request #57 from jkrauska/jkrauska/startupLogging
Add structured logging and improved startup/shutdown handling
2025-10-03 08:58:31 -07:00
Joel Krauska
2723022dd5 Add structured logging and improved startup/shutdown handling
- Add consistent logging format across all modules (timestamp, file:line, PID, level)
- Add startup logging for MQTT connection, web server startup with URL display
- Add MQTT message processing metrics (count and rate logging every 10k messages)
- Add graceful shutdown handling with signal handlers and PID file cleanup
- Add configurable HTTP access log toggle via config.ini (default: disabled)
- Replace print() statements with proper logger calls throughout
- Update .gitignore to exclude PID files (meshview-db.pid, meshview-web.pid)
- Update documentation for new logging configuration options

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-01 17:49:01 -07:00
Pablo Revilla
d2d18746ef Fixed bug on edges API 2025-10-01 14:00:14 -07:00
Pablo Revilla
7146f69beb update protobuf 2025-10-01 12:07:43 -07:00
Pablo Revilla
db8703919d Merge pull request #53 from jkrauska/jkrauska/mapzoom
Add url parameters to /map to support zoomed view
2025-10-01 11:43:45 -07:00
Pablo Revilla
baeaf29df0 Merge pull request #51 from Cloud-121/master
Fix Client_BASE not showing in Mesh Graphs
2025-10-01 09:18:50 -07:00
Pablo Revilla
44ddfe7ed7 update protobuf 2025-10-01 08:08:50 -07:00
Pablo Revilla
fc28dcc53e Merge pull request #52 from jkrauska/master
Minor README Tweaks and gitignore add
2025-10-01 08:05:34 -07:00
Pablo Revilla
81a2c0c7ca update protobuf 2025-10-01 08:01:00 -07:00
Joel Krauska
c7f5467acb Add url parameters to /map to support zoomed view 2025-09-30 17:56:35 -07:00
Joel Krauska
396e5ccbf1 Minor README Tweaks and gitignore add 2025-09-30 17:17:55 -07:00
Cloud Hayes
0a522f9a19 Fix Client_BASE not showing in Mesh Graphs 2025-09-30 17:40:06 -05:00
Pablo Revilla
40c5d4e291 update protobuf 2025-09-25 13:37:55 -07:00
Pablo Revilla
550a266212 update protobuf 2025-09-24 20:28:33 -07:00
Pablo Revilla
238ac409f8 testing new integration 2025-09-24 20:16:10 -07:00
Pablo Revilla
ee640b2cec Update .gitmodules 2025-09-24 20:13:28 -07:00
Pablo Revilla
561d410e6a Updates stats with pie chart and report for channel 2025-09-24 19:55:41 -07:00
Pablo Revilla
a20dafe714 Updates stats with pie chart and report for channel 2025-09-24 19:54:33 -07:00
Pablo Revilla
3cd93c08a7 Updates stats with pie chart and report for channel 2025-09-24 19:39:06 -07:00
Pablo Revilla
11537fdef1 Merge remote-tracking branch 'origin/master' 2025-09-24 19:38:55 -07:00
Pablo Revilla
5068f7acb1 Updates stats with pie chart and report for channel 2025-09-24 17:23:12 -07:00
Pablo Revilla
85f04f485e Merge pull request #36 from madeofstown/master
New Install Procedure
2025-09-24 17:17:16 -07:00
Pablo Revilla
a094b3edd5 Merge branch 'master' into master 2025-09-24 17:17:01 -07:00
Pablo Revilla
8d7f72ac6e Updates stats with pie chart and report for channel 2025-09-22 10:25:24 -07:00
Pablo Revilla
03e198b80c Updates stats with pie chart and report for channel 2025-09-22 10:18:06 -07:00
Pablo Revilla
86b4fa6cbf Update README.md 2025-09-19 21:48:39 -07:00
Pablo Revilla
e6424e3c6d Update README.md 2025-09-19 21:48:13 -07:00
Pablo Revilla
e2c1e311b8 Update README.md 2025-09-19 11:11:25 -07:00
Pablo Revilla
02f63fca70 Work on DB cleanup tool 2025-09-19 10:50:15 -07:00
Pablo Revilla
f9a6f3dff2 Work on DB cleanup tool 2025-09-19 09:20:43 -07:00
Pablo Revilla
0da2ef841c Work on DB cleanup tool 2025-09-19 09:11:00 -07:00
Pablo Revilla
4ffd287c84 Work on DB cleanup tool 2025-09-19 08:50:10 -07:00
Pablo Revilla
ec0dd4ef03 Work on status page 2025-09-18 10:28:55 -07:00
Pablo Revilla
608fde9e9c Work on db cleanup tool 2025-09-18 10:25:27 -07:00
Pablo Revilla
7c40c64de8 Work on db cleanup tool 2025-09-18 09:45:01 -07:00
Pablo Revilla
4f4c18fa14 Work on db cleanup tool 2025-09-18 09:37:24 -07:00
Pablo Revilla
6eb1cdbd2d Work on db cleanup tool 2025-09-18 07:40:25 -07:00
Pablo Revilla
cad3051e7f Work on db cleanup tool 2025-09-18 07:38:58 -07:00
Pablo Revilla
2b9422efbc fixed spelling of variable firehouse_interval 2025-09-18 07:34:26 -07:00
Pablo Revilla
ddb691d4de fixed spelling of variable firehouse_interval 2025-09-17 23:05:05 -07:00
Pablo Revilla
bbab5fefd0 make the /api/config endpoint restrictive to what it provides. It will only show what is needed for the current code. 2025-09-17 23:01:29 -07:00
Pablo Revilla
6e223a066a make the /api/config endpoint restrictive to what it provides. It will only show what is needed for the current code. 2025-09-17 23:00:44 -07:00
Pablo Revilla
61b74473e3 make the /api/config endpoint restrictive to what it provides. It will only show what is needed for the current code. 2025-09-17 22:55:40 -07:00
Pablo Revilla
f06fa3a4a3 Added Database cleanup feature to startdb.py 2025-09-17 22:22:35 -07:00
Pablo Revilla
9d4ebc00f6 Added Database cleanup feature to startdb.py 2025-09-17 22:15:12 -07:00
Pablo Revilla
a69d1a5729 Added Database cleanup feature to startdb.py 2025-09-17 22:12:04 -07:00
Pablo Revilla
d5272c1aec added index to API list 2025-09-17 07:44:48 -07:00
Pablo Revilla
4201c5476b Fixed multiple responses for active map 2025-09-15 16:05:30 -07:00
Pablo Revilla
6b4a33aeb2 Fixed multiple responses for active map 2025-09-15 13:42:52 -07:00
Pablo Revilla
77cf3df06a Fixed multiple responses for active map 2025-09-15 12:29:50 -07:00
Pablo Revilla
a532fb0a16 Merge remote-tracking branch 'origin/master' 2025-09-15 09:59:52 -07:00
Pablo Revilla
48a4be887c New charts added to stats as we have access not to nodes via API 2025-09-15 09:59:19 -07:00
Pablo Revilla
8dec274045 New charts added to stats as we have access not to nodes via API 2025-09-12 17:42:19 -07:00
Pablo Revilla
b09ea7192c Update sample.config.ini
added:

# Updates intervals in seconds, zero or negative number means no updates
# defaults will be 3 seconds
map_interval=3
firehose_interal=3
2025-09-12 17:40:52 -07:00
Pablo Revilla
93bad96268 New charts added to stats as we have access not to nodes via API 2025-09-12 16:15:02 -07:00
Pablo Revilla
bb5dba23d0 New charts added to stats as we have access not to nodes via API 2025-09-12 12:15:10 -07:00
Pablo Revilla
fd57310b0e nodelist now also works with API 2025-09-12 11:46:20 -07:00
Pablo Revilla
168763357a nodelist now also works with API 2025-09-12 11:19:55 -07:00
Pablo Revilla
285db92a53 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	meshview/templates/map.html
2025-09-12 09:54:09 -07:00
Pablo Revilla
3897ce268e Merge pull request #47 from alecperkins/feature/graph-colors
Add colors and weighting to graph, condense labels
2025-09-12 09:42:27 -07:00
Pablo Revilla
aea81f77f8 nodelist now also works with API 2025-09-12 07:46:45 -07:00
Pablo Revilla
7e76424053 Merge pull request #46 from alecperkins/feature/map-fill-screen
Fill screen with map
2025-09-11 21:06:07 -07:00
Pablo Revilla
9c4171928a nodelist now also works with API 2025-09-11 07:54:00 -07:00
Pablo Revilla
d69a7959b8 Added API pages and moved chat to API/JS 2025-09-10 22:31:09 -07:00
Pablo Revilla
81fe8353c4 Added API pages and moved chat to API/JS 2025-09-10 22:25:22 -07:00
Pablo Revilla
868a1658ce Added API pages and moved chat to API/JS 2025-09-10 22:04:02 -07:00
Alec Perkins
a93f8d7212 feat: Add colors and weighting to graph, condense labels
The colors indicate the role, and the edges are weighted by how many traceroutes contributed to that edge. This helps to communicate the quality of the connection. The colors and node size based on role make it easier to see the composition of the graph. This also moves the look-and-feel pieces into the template only, and attempts to centralize the color definitions.
2025-09-10 18:04:12 -04:00
Alec Perkins
3eca96a01d feat: Fill screen with map
A naive approach. Ideally it would use flexbox but that would require more substantial changes.
2025-09-10 17:21:03 -04:00
Pablo Revilla
1e7fccae82 Added the traceroute and neighbours to the map 2025-09-08 09:35:18 -07:00
Pablo Revilla
5bef93b186 Merge pull request #40 from jschrempp/arrowheads
Add direction arrow heads to main map edges shown on node click
2025-09-08 09:33:46 -07:00
Pablo Revilla
8c01a7b4a0 Added the traceroute and neighbours to the map 2025-09-05 07:43:15 -07:00
Pablo Revilla
783972e4bd Added the traceroute and neighbours to the map 2025-09-04 09:05:37 -07:00
Pablo Revilla
c42173cdc8 Added the traceroute and neighbours to the map 2025-09-03 09:37:17 -07:00
Jim Schrempp
52dc78b8d0 added direction arrow heads to main map edges shown on node click 2025-08-31 07:00:10 -07:00
Pablo Revilla
ce8717b55a Added the traceroute and neighbours to the map 2025-08-29 09:42:56 -07:00
Pablo Revilla
6836d42fd6 Added the traceroute and neighbours to the map 2025-08-29 09:28:35 -07:00
Pablo Revilla
396d919df3 Added the traceroute and neighbours to the map 2025-08-29 09:19:56 -07:00
Pablo Revilla
c374167568 Added the traceroute and neighbours to the map 2025-08-29 09:06:04 -07:00
Pablo Revilla
1ccc3bfc7d Added the traceroute and neighbours to the map 2025-08-28 16:19:47 -07:00
Pablo Revilla
0500be4541 Added the traceroute and neighbours to the map 2025-08-28 16:08:38 -07:00
Pablo Revilla
a4533c33e5 Added the traceroute and neighbours to the map 2025-08-28 15:56:44 -07:00
Pablo Revilla
d0799f44ec Added the traceroute and neighbours to the map 2025-08-28 15:32:52 -07:00
Pablo Revilla
a022795251 Added the traceroute and neighbours to the map 2025-08-28 09:12:54 -07:00
Pablo Revilla
7b8f2e6678 Added the traceroute and neighbours to the map 2025-08-28 09:05:01 -07:00
Pablo Revilla
34cdb03791 Added the traceroute and neighbours to the map 2025-08-28 07:50:34 -07:00
Pablo Revilla
0629b7b1ef Added the traceroute and neighbours to the map 2025-08-27 16:27:24 -07:00
Pablo Revilla
749fc615a8 Added the traceroute and neighbours to the map 2025-08-27 16:12:04 -07:00
Pablo Revilla
9f93602b51 Added the traceroute and neighbours to the map 2025-08-27 14:51:08 -07:00
Pablo Revilla
2295751e18 Added the traceroute and neighbours to the map 2025-08-27 14:17:46 -07:00
Pablo Revilla
eccba20a13 Added the traceroute and neighbours to the map 2025-08-27 14:13:37 -07:00
Pablo Revilla
9eae03013d Added the traceroute and neighbours to the map 2025-08-27 14:08:11 -07:00
Pablo Revilla
d305ea424d Added the traceroute and neighbours to the map 2025-08-27 13:15:22 -07:00
Pablo Revilla
e40b96168a Added the traceroute and neighbours to the map 2025-08-27 12:35:49 -07:00
Pablo Revilla
d38c587a76 Added the traceroute and neighbours to the map 2025-08-27 12:28:19 -07:00
Pablo Revilla
ec02d72f89 Added the traceroute and neighbours to the map 2025-08-27 12:25:13 -07:00
Pablo Revilla
93b7276b9e Added the traceroute and neighbours to the map 2025-08-27 11:25:26 -07:00
Pablo Revilla
f72e5178b2 Added the traceroute and neighbours to the map 2025-08-27 09:54:55 -07:00
Pablo Revilla
21760552e4 Added the traceroute and neighbours to the map 2025-08-27 07:30:28 -07:00
Pablo Revilla
fdfbdd50ba Fixed bug with nodegraph.html it was not able to handle some characters on the name_long 2025-08-26 13:23:55 -07:00
Pablo Revilla
34fd41c10f Adding live-map and static pages for the apis 2025-08-25 20:32:24 -07:00
Pablo Revilla
7e80e83850 Adding live-map and static pages for the apis 2025-08-25 20:21:20 -07:00
Pablo Revilla
b8647ee993 Adding live-map and static pages for the apis 2025-08-25 20:13:52 -07:00
Pablo Revilla
de50e2bc7b Adding live-map and static pages for the apis 2025-08-25 20:01:33 -07:00
Pablo Revilla
ad93483cd0 Adding live-map and static pages for the apis 2025-08-25 17:08:49 -07:00
Pablo Revilla
75eb392182 Adding live-map and static pages for the apis 2025-08-25 16:57:55 -07:00
Pablo Revilla
94a03d7cbb Adding live-map and static pages for the apis 2025-08-25 16:29:45 -07:00
Pablo Revilla
e7963683f1 Adding live-map and static pages for the apis 2025-08-25 14:57:10 -07:00
Pablo Revilla
941de1c2fb Adding live-map and static pages for the apis 2025-08-25 14:27:19 -07:00
Pablo Revilla
0a2f7e50c9 Adding live-map and static pages for the apis 2025-08-25 14:07:47 -07:00
Pablo Revilla
0e548d4c03 Adding live-map and static pages for the apis 2025-08-25 14:04:59 -07:00
Pablo Revilla
dee948e26c Adding live-map and static pages for the apis 2025-08-25 14:03:47 -07:00
Pablo Revilla
4c815ec486 Changing the way we load protobuf definitions since meshtastic added a submodule that is not loading properly 2025-08-21 10:49:30 -07:00
Pablo Revilla
2cf2c32e31 Changing the way we load protobuf definitions since meshtastic added a submodule that is not loading properly 2025-08-21 10:30:04 -07:00
Pablo Revilla
2a55309bde Changing the way we load protobuf definitions since meshtastic added a submodule that is not loading properly 2025-08-20 08:31:52 -07:00
madeofstown
7e3076c0e2 Update README.md
symlink target is relative to link location
2025-08-19 19:24:58 -07:00
madeofstown
e3f5c0f006 Delete meshtastic/protobuf 2025-08-19 19:14:48 -07:00
madeofstown
572e79c9ac Update .gitmodules 2025-08-19 19:10:46 -07:00
madeofstown
fb70f644e5 Update README.md
Change install procedure to mitigate broken submodule
2025-08-19 19:08:38 -07:00
madeofstown
954d6300de Update .gitignore 2025-08-19 17:35:26 -07:00
madeofstown
9ceca0eea9 Update .gitmodules 2025-08-19 17:31:36 -07:00
madeofstown
24f768f725 Merge pull request #5 from madeofstown/testing
re-add meshtastic/python submodule
2025-08-19 17:14:35 -07:00
madeofstown
89f3eade15 re-add meshtastic/python submodule 2025-08-19 17:12:40 -07:00
Pablo Revilla
f147360bfc Delete .gitmodules 2025-08-19 16:20:09 -07:00
Pablo Revilla
a3186e6cca Update protobuf 2025-08-19 15:20:27 -07:00
Pablo Revilla
4e06b5b7cc Update .gitmodules 2025-08-19 15:19:15 -07:00
Pablo Revilla
40235c9c11 Updating the protobuf 2025-08-19 14:54:27 -07:00
Pablo Revilla
d025255748 Update .gitmodules 2025-08-19 14:52:26 -07:00
Pablo Revilla
333d538955 Update .gitmodules 2025-08-19 13:02:45 -07:00
Pablo Revilla
ed0c15a92e Delete .idea directory 2025-08-19 12:52:19 -07:00
Pablo Revilla
8b7de8d30b Update .gitmodules 2025-08-19 12:49:19 -07:00
Pablo Revilla
ee2a449c55 Update .gitmodules 2025-08-19 12:41:00 -07:00
Pablo Revilla
7bde05e6da Update .gitmodules 2025-08-19 12:22:36 -07:00
Pablo Revilla
9648b9a849 Update .gitmodules 2025-08-19 12:14:44 -07:00
Pablo Revilla
7d3b94f23c Update .gitmodules 2025-08-19 12:00:34 -07:00
Pablo Revilla
563e239ee9 test 2025-08-19 11:56:46 -07:00
Pablo Revilla
46142dcb7b Update .gitmodules 2025-08-19 11:41:12 -07:00
Pablo Revilla
501adc4519 Update .gitmodules 2025-08-19 11:22:25 -07:00
Pablo Revilla
3135ad00f1 Update .gitmodules 2025-08-19 11:14:13 -07:00
Pablo Revilla
6dd40bea29 Update .gitmodules 2025-08-19 11:06:31 -07:00
Pablo Revilla
722c404715 Update .gitmodules 2025-08-19 11:05:27 -07:00
Pablo Revilla
734162fb48 Update .gitmodules 2025-08-19 10:53:50 -07:00
Pablo Revilla
64c9d23de6 Update .gitmodules 2025-08-19 10:53:03 -07:00
Pablo Revilla
da92fd8155 Update .gitmodules 2025-08-19 10:46:42 -07:00
Pablo Revilla
a88db0cd92 Update .gitmodules 2025-08-19 10:41:24 -07:00
Pablo Revilla
1522bf1138 Update .gitmodules 2025-08-19 10:40:10 -07:00
Pablo Revilla
0ffdc60c62 Update .gitmodules 2025-08-19 10:29:28 -07:00
Pablo Revilla
efd3742f99 New updates to documentation 2025-08-19 10:13:51 -07:00
Pablo Revilla
078ace50aa New updates to documentation 2025-08-19 09:07:32 -07:00
Pablo Revilla
b53bcd2d7b New updates to documentation 2025-08-18 14:27:00 -07:00
Pablo Revilla
fedbd10bf8 Merge pull request #34 from jschrempp/patch-1
Update README.md
2025-08-15 08:33:24 -07:00
Pablo Revilla
9d3b2af087 Merge pull request #33 from SConaway/error-page
Use error template for more issues
2025-08-15 08:32:34 -07:00
Jim Schrempp
c6f91b4d4e Update README.md
added note on the bind = setting for OSX
2025-08-14 21:23:24 -07:00
Steven Conaway
e00c0a426a Show tracebacks on errors 2025-08-14 18:48:30 -07:00
Steven Conaway
82783b301f Use error template for issues with node info page 2025-08-14 11:27:25 -07:00
Pablo Revilla
59f7bc73e1 New updates to documentation 2025-08-12 15:26:12 -07:00
Pablo Revilla
ead29f1dbb New updates to documentation 2025-08-12 15:25:32 -07:00
Pablo Revilla
2cc913d133 Add the Replying to link to the chat page 2025-08-12 15:20:14 -07:00
Pablo Revilla
ef105a0928 Add the Replying to link to the chat page 2025-08-12 14:59:17 -07:00
Pablo Revilla
f2afd3d0ee Add the Replying to link to the chat page 2025-08-12 12:55:26 -07:00
Pablo Revilla
b163b773c8 Add the Replying to link to the chat page 2025-08-12 12:43:43 -07:00
Pablo Revilla
b9e0cd10bc Statistic page redo 2025-08-12 12:37:09 -07:00
Pablo Revilla
77f8746b4a Statistic page redo 2025-08-12 12:30:59 -07:00
Pablo Revilla
b212c57ad7 Statistic page redo 2025-08-11 17:04:24 -07:00
Pablo Revilla
8d0a13729c add API code for /api/packets 2025-08-11 16:07:56 -07:00
Pablo Revilla
573b1b1571 add API code for /api/packets 2025-08-11 15:57:45 -07:00
Pablo Revilla
32dd6b5c96 add API code for /api/packets 2025-08-11 15:50:47 -07:00
Pablo Revilla
a8313cd921 add API code for /api/packets 2025-08-11 14:26:40 -07:00
Pablo Revilla
edb0f7a23d add API code for /api/packets 2025-08-11 14:00:52 -07:00
Pablo Revilla
d8ceb19163 add API code for /api/packets 2025-08-11 13:57:30 -07:00
Pablo Revilla
635cb7bb41 add API code for /api/packets 2025-08-11 09:20:16 -07:00
Pablo Revilla
69c819ee22 add API code for /api/packets 2025-08-11 09:20:06 -07:00
Pablo Revilla
d405524ff5 add API code for /api/packets 2025-08-07 16:06:24 -07:00
Pablo Revilla
9065616347 add API code for /api/packets 2025-08-07 16:01:13 -07:00
Pablo Revilla
c77cbf70e8 add API code for /api/packets 2025-08-06 17:27:04 -07:00
Pablo Revilla
706c71ef39 add API code for /api/packets 2025-08-06 17:18:48 -07:00
Pablo Revilla
a9514a0238 add API code for /api/packets 2025-08-06 16:47:17 -07:00
Pablo Revilla
5671983ebd add API code for /api/packets 2025-08-06 16:46:08 -07:00
Pablo Revilla
fc8e63bdf7 add API code for /api/packets 2025-08-06 16:16:28 -07:00
Pablo Revilla
b2c307a392 add API code for /api/packets 2025-08-06 15:26:09 -07:00
Pablo Revilla
cb7df2c35a add API code for /api/packets 2025-08-06 15:18:49 -07:00
Pablo Revilla
781ae14fd7 add API code for /api/packets 2025-08-06 15:11:30 -07:00
Pablo Revilla
78f22603dd add API code for /api/packets 2025-08-06 13:30:41 -07:00
Pablo Revilla
1c49529846 add API code for /api/packets 2025-07-23 08:53:23 -07:00
Pablo Revilla
4b5c2891ba add API code for /api/packets 2025-07-23 08:53:06 -07:00
Pablo Revilla
75a2189862 add API code for /api/packets 2025-07-23 08:49:18 -07:00
Pablo Revilla
f3dfdf6f04 add API code 2025-07-22 15:12:03 -07:00
Pablo Revilla
d8ab614f79 add API code 2025-07-22 15:10:56 -07:00
Pablo Revilla
4a700700d2 added another running instance. 2025-07-22 14:58:14 -07:00
Pablo Revilla
8c99b63399 added another running instance. 2025-07-22 14:49:43 -07:00
Pablo Revilla
b47240fa06 added another running instance. 2025-07-21 13:12:52 -07:00
Pablo Revilla
2ff89a2041 added another running instance. 2025-07-02 16:55:01 -07:00
Pablo Revilla
9d918a28f9 added another running instance. 2025-07-02 16:50:02 -07:00
Pablo Revilla
6361961a20 changed the label for a node that does not report firmware from None to N/A 2025-06-30 14:00:59 -07:00
Pablo Revilla
2192fa02a4 clean up the map.html template 2025-06-27 10:17:29 -07:00
Pablo Revilla
a4aa61dca1 update version and fix bug introuced a few days back 2025-06-26 18:54:20 -07:00
Pablo Revilla
baf66487de update version 2025-06-26 18:45:30 -07:00
Pablo Revilla
621d347849 update version 2025-06-26 18:33:35 -07:00
Pablo Revilla
a58aa5b211 update version 2025-06-24 20:00:30 -07:00
Pablo Revilla
6b4b1b52ce update version 2025-06-24 16:26:27 -07:00
Pablo Revilla
1729b6556f update version 2025-06-24 15:09:04 -07:00
Pablo Revilla
f462889b62 update version 2025-06-24 13:46:23 -07:00
Pablo Revilla
7d8a757788 update version 2025-06-24 13:08:19 -07:00
Pablo Revilla
66a9dc510d Merge remote-tracking branch 'origin/master' 2025-06-24 12:31:40 -07:00
Pablo Revilla
33a0992c97 update version 2025-06-24 12:31:22 -07:00
Pablo Revilla
6370f694d6 Merge pull request #29 from skullydazed/pad_node_ids
Pad Node IDs so they can be copied and pasted successfully
2025-06-23 09:53:52 -07:00
Zach White
1888a70e35 pad nodeids 2025-06-14 20:23:46 -07:00
Pablo Revilla
b1106d8558 update version 2025-06-12 15:12:56 -07:00
Pablo Revilla
762a771876 Worked on README.md to add cleanup instructions 2025-06-12 11:31:53 -07:00
Pablo Revilla
a72dde6a58 Worked on README.md to add cleanup instructions 2025-06-09 13:03:50 -07:00
Pablo Revilla
000f5def04 Worked on README.md to add cleanup instructions 2025-06-09 09:55:41 -07:00
Pablo Revilla
08ccbc9a6c Worked on README.md to add cleanup instructions 2025-06-06 15:58:57 -07:00
Pablo Revilla
76a07535d4 Worked on README.md to add cleanup instructions 2025-06-06 15:53:29 -07:00
Pablo Revilla
2fe52b8744 Worked on README.md to add cleanup instructions 2025-06-06 15:51:27 -07:00
Pablo Revilla
064db62ce4 Worked on README.md to add cleanup instructions 2025-06-06 15:50:44 -07:00
Pablo Revilla
8ff88e390f Worked on README.md to add cleanup instructions 2025-06-06 15:49:25 -07:00
Pablo Revilla
cb1e4e066d Worked on README.md to add cleanup instructions 2025-06-06 15:46:55 -07:00
Pablo Revilla
8e30de71f2 Worked on README.md to add cleanup instructions 2025-06-06 15:45:40 -07:00
Pablo Revilla
98b21af26e Worked on README.md to add cleanup instructions 2025-06-06 15:44:07 -07:00
Pablo Revilla
6e7167bc89 Merge pull request #27 from kabili207/master
Thank you. I will merge it.
2025-06-06 11:10:48 -07:00
Pablo Revilla
55c13588bf Fixed fuzzy node logic and error 2025-06-06 10:55:11 -07:00
Pablo Revilla
894e96e5dd Fixed fuzzy node logic and error 2025-06-06 10:52:32 -07:00
Pablo Revilla
4af559646d Fixed fuzzy node logic and error 2025-06-06 08:07:58 -07:00
Pablo Revilla
e1e1a1a1cb Fixed fuzzy node logic and error 2025-06-06 08:07:01 -07:00
Pablo Revilla
3a9f2eb5ab Changed zoom factor on maps 2025-06-05 22:33:57 -07:00
Pablo Revilla
b49a8d61e8 Changed zoom factor on maps 2025-06-05 16:05:58 -07:00
Pablo Revilla
5fde038ddc added version to the footer. 2025-06-05 15:46:29 -07:00
Pablo Revilla
6766f49d6f get some new screenshots 2025-06-05 15:44:07 -07:00
Amy Nagle
6b946d1b9c Process all data in MapReport packet 2025-06-04 14:22:44 -04:00
Pablo Revilla
ab8f56a7ef get some new screenshots 2025-06-03 13:44:06 -07:00
Pablo Revilla
52e1da3d99 get some new screenshots 2025-06-03 13:42:08 -07:00
Pablo Revilla
11d8385d13 get some new screenshots 2025-06-03 10:37:26 -07:00
Pablo Revilla
df6d02ff59 get some new screenshots 2025-06-03 10:32:52 -07:00
Pablo Revilla
49743f72ae get some new screenshots 2025-06-03 10:32:01 -07:00
Pablo Revilla
ec83bc1822 fixed base.html so that if a value in the quick links is not set it will not report an error. 2025-06-03 08:28:27 -07:00
Pablo Revilla
44657a8947 Merge remote-tracking branch 'origin/master' 2025-06-03 08:26:37 -07:00
Pablo Revilla
07aafb87e1 fixed base.html so that if a value in the quick links is not set it will not report an error. 2025-06-03 08:26:30 -07:00
Pablo Revilla
ef9fb202a3 Update README.md 2025-06-03 08:25:03 -07:00
Pablo Revilla
35d68cd004 fixed base.html so that if a value in the quick links is not set it will not report an error. 2025-06-03 08:23:10 -07:00
Pablo Revilla
39724a99b4 fixed base.html so that if a value in the quick links is not set it will not report an error. 2025-06-03 08:16:39 -07:00
Pablo Revilla
5ba9b17f09 add timeout to 60 seconds 2025-06-02 17:16:36 -07:00
Pablo Revilla
ab1b9c53e2 add timeout to 60 seconds 2025-06-02 15:25:49 -07:00
Pablo Revilla
b2f1944105 Cleaned up some print statements 2025-06-02 13:37:05 -07:00
Pablo Revilla
fbd84f1fec Cleaned up some print statements 2025-06-02 13:35:32 -07:00
Pablo Revilla
5b0d07e2d1 Added Chicago to the list of sites. 2025-06-01 23:05:12 -07:00
Pablo Revilla
4d9d893868 Changed so that the Top page starts with long fast selected 2025-06-01 22:54:42 -07:00
Pablo Revilla
9bca3566f6 Changed so that the Top page starts with long fast selected 2025-06-01 22:31:21 -07:00
Pablo Revilla
586ecc5d69 Remove pagination from the node's page 2025-06-01 22:26:20 -07:00
Pablo Revilla
6b70c119c2 Removed extra button in the firehose.html file 2025-06-01 22:19:27 -07:00
Pablo Revilla
82ef3cde88 Merge remote-tracking branch 'origin/master' 2025-06-01 22:15:31 -07:00
Pablo Revilla
cfa4d4003f Removed extra button in the firehose.html file 2025-06-01 22:15:11 -07:00
Pablo Revilla
38b0d6f630 Merge pull request #26 from gsilvr/meshview-docker
Added a working dockerfile and readme
2025-06-01 21:56:10 -07:00
Pablo Revilla
e45be00784 Added pagination to the nodes list 2025-06-01 21:31:57 -07:00
George
f037eb27f9 Added a working dockerfile and readme 2025-06-01 12:38:49 -07:00
Pablo Revilla
124c5f2840 Added pagination to the nodes list 2025-05-27 09:28:09 -07:00
Pablo Revilla
5f8c78cf98 Fix UI bug with chat.html 2025-05-23 10:31:42 -07:00
Pablo Revilla
dadcad3af3 Added seach to all the pages by adding it to base.html 2025-05-23 10:23:54 -07:00
Pablo Revilla
eefa896780 Added seach to all the pages by adding it to base.html 2025-05-23 09:09:48 -07:00
Pablo Revilla
dc0b14006f Modified the power and battery graph to show both axis 2025-05-23 07:26:08 -07:00
Pablo Revilla
49922ac617 Modified the README.md 2025-05-22 18:28:06 -07:00
Pablo Revilla
2d7dbdff49 Readded node_graphs 2025-05-22 18:24:08 -07:00
Pablo Revilla
b1f1e7c6da Added self updating firehose.html and chat.html 2025-05-22 15:56:33 -07:00
Pablo Revilla
ada5c1e0a3 Merge remote-tracking branch 'origin/master' 2025-05-22 15:51:05 -07:00
Pablo Revilla
0c443dde25 Added self updating firehose.html and chat.html 2025-05-22 15:50:47 -07:00
Pablo Revilla
a203d5ee30 Update README.md 2025-05-22 14:20:49 -07:00
Pablo Revilla
1ddc3445c3 Update README.md 2025-05-22 14:14:41 -07:00
Pablo Revilla
960a18586d Added self updating firehose.html and chat.html 2025-05-22 10:29:10 -07:00
Pablo Revilla
f08f6f9b93 Added self updating firehose.html and chat.html 2025-05-22 10:19:50 -07:00
Pablo Revilla
56fef8312b Cleaned up the import section as we removed 4 packages 2025-05-21 12:17:19 -07:00
Pablo Revilla
85427fd2a8 Modified all graphs to eliminate the errors and use eCharts 2025-05-21 12:13:51 -07:00
Pablo Revilla
32437584a9 Modified all graphs to eliminate the errors and use eCharts 2025-05-21 11:56:17 -07:00
Pablo Revilla
33bdb9d668 Modified all graphs to eliminate the errors and use eCharts 2025-05-21 11:29:41 -07:00
Pablo Revilla
dfb4b72056 Modified all graphs to eliminate the errors and use eCharts 2025-05-21 11:18:36 -07:00
Pablo Revilla
2b3be8bf93 Modified the Neighbours graphs to eliminate the errors. 2025-05-21 09:37:23 -07:00
Pablo Revilla
a6c9970054 Modified the Neighbours graphs to eliminate the errors. 2025-05-21 09:14:17 -07:00
Pablo Revilla
f9319472b1 Added site in Spain 2025-05-20 22:09:55 -07:00
Pablo Revilla
404996716a Added site in Spain 2025-05-20 10:58:58 -07:00
Pablo Revilla
5631f84b1a Updates to README.md 2025-05-12 11:07:40 -07:00
Pablo Revilla
ae15f0f291 Updates to README.md 2025-05-12 11:02:49 -07:00
Pablo Revilla
6f13be8a58 Added the ability to show receiving node location on map even if the main node is does not have location 2025-05-08 11:09:22 -07:00
Pablo Revilla
295f7083d7 Added the ability to show receiving node location on map even if the main node is does not have location 2025-05-08 10:49:18 -07:00
Pablo Revilla
67f769ec8e Merge all Graphs into one section 2025-05-08 10:20:16 -07:00
Pablo Revilla
6a66e3e579 Merge all Graphs into one section 2025-05-08 10:19:05 -07:00
Pablo Revilla
20f3ec4fab Merge all Graphs into one section 2025-05-07 22:04:43 -07:00
Pablo Revilla
8ce672c5ab Merge all Graphs into one section 2025-05-07 21:43:01 -07:00
Pablo Revilla
c0d69f13de Update README.md 2025-05-07 09:12:41 -07:00
Pablo Revilla
a3e867fc10 Merge pull request #20 from PSandro/master
config: fix server->bind when more than 1 char
2025-05-07 08:58:51 -07:00
Pablo Revilla
91bb0e006f Merge pull request #21 from PSandro/config-add-net-tag
add net_tag to sample.config.ini
2025-05-07 08:56:24 -07:00
Sandro Pischinger
35f8b4d234 add net_tag to sample.config.ini
Not having set net_tag in the config file causes a KeyError when opening
Weekly Net as the net_tag configuration is expected. Thus setting a default value.

Signed-off-by: Sandro Pischinger <mail@sandropischinger.de>
2025-05-04 18:09:01 +02:00
Sandro Pischinger
67f7d13ef6 config: fix server->bind when more than 1 char
Currently the bind option in the configuration file defaults to '*' and
is read during startup in web.py. The value of the host variable  is
of type string, but the current code tries to iterate through it,
suppusedly to support multiple hosts.
This would work if the value was of type array, holding multiple strings
of hostnames (similar to [mqtt]->topics, which is currently not
possible.

When setting 'bind=localhost', the code iterates through 'localhost'
and tries to start a TCPSite with a host of 'l', then 'o', then 'c' and
so on but failes at the first 'l' already since it cannot be resolved.

This commit changes the behaviour of 'bind' to only expect one value,
namely a string of the host where to bind to.

This change does not require any config changes in current productions
setups: The default bind value of '*' is still handled correctly and any
other bind values with more than one character currently fail anyways.

Signed-off-by: Sandro Pischinger <mail@sandropischinger.de>
2025-05-04 17:27:10 +02:00
Pablo Revilla
d374de7bf3 Merge remote-tracking branch 'origin/master' 2025-05-02 11:24:50 -07:00
Pablo Revilla
deb5b25da1 added version visivility. 2025-05-02 11:24:40 -07:00
Pablo Revilla
090d11fe28 added version visivility. 2025-05-02 11:23:13 -07:00
Pablo Revilla
c5d2f42013 added version visivility. 2025-05-02 11:21:21 -07:00
Pablo Revilla
c171ec52ec added version visivility. 2025-05-02 11:18:42 -07:00
Pablo Revilla
16332f928a Merge pull request #19 from tb0hdan/master
Add Canadaverse to the list of running instances
2025-05-01 20:27:53 -07:00
Pablo Revilla
36ddc97ca6 Made the number of node to show on map to be configurable 2025-05-01 20:17:00 -07:00
Pablo Revilla
afd86cb214 Made the number of node to show on map to be configurable 2025-05-01 20:13:45 -07:00
Bohdan Turkynewych
df5aa89946 Add Canadaverse to the list of running instances 2025-04-29 21:53:11 -04:00
Pablo Revilla
8fc04a5f18 Added popup link to the maps 2025-04-28 22:19:21 -07:00
Pablo Revilla
7d04035c60 Added popup link to the maps 2025-04-28 22:17:37 -07:00
Pablo Revilla
60ea735e11 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	startdb.py
2025-04-28 22:11:26 -07:00
Pablo Revilla
f9e6765a68 Added popup link to the maps 2025-04-28 22:10:55 -07:00
Pablo Revilla
2851ee00bf Update startdb.py 2025-04-28 22:06:42 -07:00
Pablo Revilla
f9c874bcc1 Revert "Added popup link to the maps"
This reverts commit 48d5dcbf7d.
2025-04-28 21:58:06 -07:00
Pablo Revilla
b42630e6d0 Added popup link to the maps 2025-04-28 21:38:55 -07:00
Pablo Revilla
48d5dcbf7d Added popup link to the maps 2025-04-28 21:38:31 -07:00
Pablo Revilla
85c1e24b18 Added popup link to the maps 2025-04-28 21:37:11 -07:00
Pablo Revilla
94d23ed5a9 Added popup link to the maps 2025-04-28 21:36:20 -07:00
Pablo Revilla
36c754c49b Added popup link to the maps 2025-04-28 21:16:25 -07:00
Pablo Revilla
3663f8264e Trying to fix a bug that is reported by web.py when a packet id is requested and it does not exist. 2025-04-24 09:28:40 -07:00
Pablo Revilla
187284f5de Trying to fix a bug that is reported by web.py when a packet id is requested and it does not exist. 2025-04-24 09:17:47 -07:00
Pablo Revilla
422750599d Fix bug with time in map.html and web.py 2025-04-21 13:42:20 -07:00
Pablo Revilla
c3c59bda53 Fix bug with time in map.html and web.py 2025-04-21 13:41:50 -07:00
Pablo Revilla
9f40458597 Merge pull request #18 from prokrypt/patch-6
Update store.py: localtime again
2025-04-17 15:55:33 -07:00
Pablo Revilla
2b1380eed0 Added channel selection on Top users statistics 2025-04-17 14:47:43 -07:00
Pablo Revilla
94dba95489 Added channel selection on Top users statistics 2025-04-17 14:31:25 -07:00
prokrypt
3d7aeb5d4e Update store.py: localtime again
moar localtime, moaaaaar
2025-04-14 16:00:45 -07:00
Pablo Revilla
d1fb800534 Fixed the colors of the dots on the map. 2025-04-12 08:56:51 -07:00
Pablo Revilla
27f231deb2 Fixed the colors of the dots on the map. 2025-04-11 21:52:55 -07:00
Pablo Revilla
914910fe76 Adding new Top Users visualization 2025-04-11 09:18:56 -07:00
Pablo Revilla
a8b5f75942 Adding new Top Users visualization 2025-04-10 14:40:40 -07:00
Pablo Revilla
60a5d98555 Adding new Top Users visualization 2025-04-10 14:32:32 -07:00
Pablo Revilla
6b5bd26b54 Now the tag for the weekly mesh can be configurable 2025-04-07 09:38:41 -07:00
Pablo Revilla
b6af98925d Now the tag for the weekly mesh can be configurable 2025-04-07 09:36:53 -07:00
Pablo Revilla
1cbdb4fda6 Now the tag for the weekly mesh can be configurable 2025-04-07 09:08:28 -07:00
Pablo Revilla
0d536e2308 Now the tag for the weekly mesh can be configurable 2025-04-06 13:23:39 -07:00
Pablo Revilla
e65b1eaeb6 Now the tag for the weekly mesh can be configurable 2025-04-06 13:22:28 -07:00
Pablo Revilla
1bc7957c65 Now the tag for the weekly mesh can be configurable 2025-04-06 13:15:27 -07:00
Pablo Revilla
ad767ee457 Now the tag for the weekly mesh can be configurable 2025-04-06 11:56:02 -07:00
Pablo Revilla
2b39074e01 Updated Documentation 2025-04-06 10:52:55 -07:00
Pablo Revilla
5a39c166a7 Updated Documentation 2025-04-06 10:49:30 -07:00
Pablo Revilla
c49b600b11 Updated Documentation 2025-04-06 10:41:55 -07:00
Pablo Revilla
887084de0f Changes:
new config file changes
2025-04-01 22:22:53 -07:00
Pablo Revilla
77dd2d16ed Changes:
new node graph
2025-04-01 22:10:39 -07:00
Pablo Revilla
e0080ce811 Changes:
new node graph
2025-04-01 22:06:29 -07:00
Pablo Revilla
ada666da44 Merge remote-tracking branch 'origin/master' 2025-03-30 17:48:41 -07:00
Pablo Revilla
c916b91e18 Changes:
add a way to print out records
2025-03-30 17:48:25 -07:00
Pablo Revilla
d7526daf46 Merge pull request #16 from prokrypt/patch-5
node_traffic.html: add WAYPOINT_APP
2025-03-30 17:45:44 -07:00
prokrypt
d53eebbbeb node_traffic.html: add waypoint
because waypoints are fun and we need more.
2025-03-28 18:04:14 -07:00
Pablo Revilla
0ca730b67b Changes:
Modified the map to accept all kinds of channels
2025-03-28 14:34:34 -07:00
Pablo Revilla
91ff7edbf9 Changes:
- Added the link to another sample instance
2025-03-28 14:05:48 -07:00
Pablo Revilla
f5566ed435 Changes:
- Added the link to another sample instance
2025-03-28 09:08:21 -07:00
Pablo Revilla
3a29fe87cb Changes:
- Added the link to another sample instance
2025-03-28 09:07:19 -07:00
Pablo Revilla
ab1afec042 Changes:
- Added the link to another sample instance
2025-03-28 09:05:32 -07:00
Pablo Revilla
421cb802e4 Changes:
- Added the link to another sample instance
2025-03-28 09:04:09 -07:00
Pablo Revilla
4197d15bea Merge pull request #15 from prokrypt/patch-4
store.py: get_node_traffic should not count incoming traffic
2025-03-26 16:13:25 -07:00
prokrypt
12c29c3e49 store.py: get_node_traffic should not count incoming traffic
to match behavior of get_top_traffic_nodes
2025-03-26 14:30:20 -07:00
Pablo Revilla
fd99067ea5 Merge pull request #14 from prokrypt/patch-3
store.py: fix timezone derp
2025-03-24 09:07:38 -07:00
prokrypt
a37bbf136f store.py: missing some hours here too 2025-03-23 20:44:27 -07:00
prokrypt
6c21c1a05f store.py: fix timezone derp
... and gain 7 hours! yay
2025-03-23 20:37:35 -07:00
Pablo Revilla
682fdd8dd2 Changes:
- Added the ability to change the message on the weekly net
2025-03-20 13:27:32 -07:00
Pablo Revilla
45f650c0d8 try fixing any channel change 2025-03-18 07:44:54 -07:00
Pablo Revilla
124ea2bf30 Added numbers to the hop count 2025-03-17 21:51:55 -07:00
Pablo Revilla
52a6450076 Merge remote-tracking branch 'origin/master' 2025-03-17 21:45:02 -07:00
Pablo Revilla
1b0023485c Added numbers to the hop count 2025-03-17 21:44:46 -07:00
Pablo Revilla
69f1937b44 Merge pull request #13
mqtt_store.py: update channel on existing nodeinfo
2025-03-17 15:26:10 -07:00
Pablo Revilla
77db8e13f6 Added numbers to the hop count 2025-03-17 14:33:32 -07:00
Pablo Revilla
a15dcf624f Added numbers to the hop count 2025-03-17 13:29:10 -07:00
Pablo Revilla
0b8597c704 Fixed Date format to mm/dd/YYYY.
Added /api that dumps a json with all the nodes.
2025-03-17 13:25:36 -07:00
Pablo Revilla
18b4ed1e2a Merge pull request #12 from prokrypt/patch-1
fix error when viewing packetlist for node with no nodeinfo
2025-03-17 11:02:41 -07:00
prokrypt
196ca07dac mqtt_store.py: update channel on seen nodeinfo 2025-03-16 13:20:33 -07:00
prokrypt
c14fe63044 fix error when viewing packetlist for node with no nodeinfo 2025-03-15 15:29:37 -07:00
Pablo Revilla
4ef3c27937 Fixed Date format to mm/dd/YYYY.
Added /api that dumps a json with all the nodes.
2025-03-14 10:27:45 -07:00
Pablo Revilla
da8490f3b4 Create sample.config.ini 2025-03-14 09:57:51 -07:00
Pablo Revilla
63724becf2 Merge pull request #11 from madeofstown/dev
mvrun.py
2025-03-14 09:47:57 -07:00
Pablo Revilla
45c4a1b14c Update README.md 2025-03-10 14:05:36 -07:00
Pablo Revilla
8ffbc90c51 Update README.md 2025-03-10 14:04:09 -07:00
Pablo Revilla
937845e5a5 Update README.md 2025-03-10 14:00:30 -07:00
Pablo Revilla
28fa11030d update screenshot 2025-03-10 13:58:33 -07:00
Pablo Revilla
e6c41f72b5 Added coordinates customization to the config.ini file and map.
Added search capabilities to the mesh graphs.
2025-03-10 13:54:15 -07:00
madeofstown
68bd8e12e7 Merge branch 'pablorevilla-meshtastic:master' into dev 2025-03-10 06:40:25 -07:00
madeofstown
2ccdb53974 Update README.md
fix note
2025-03-09 21:21:52 -07:00
madeofstown
e262c6dff8 mvrun.py changes 2025-03-09 21:20:55 -07:00
Pablo Revilla
ccd91185ef Merge pull request #10 from madeofstown/dev
Website configuration in `config.ini`
2025-03-09 12:14:30 -07:00
madeofstown
83033a3a64 Website configuration in config.ini 2025-03-08 19:24:17 -08:00
Pablo Revilla
95abb79af4 config.py is in the wrong location 2025-03-08 15:42:32 -08:00
Pablo Revilla
b525e57e91 changed font size on chat 2025-03-08 15:34:30 -08:00
Pablo Revilla
d696f41d5f changed font size on chat 2025-03-08 10:45:23 -08:00
Pablo Revilla
4679d6ba55 changed font size on chat 2025-03-08 10:40:13 -08:00
Pablo Revilla
80b309e850 Merge pull request #9 from madeofstown/pablo-merge
Restoring what was lost
2025-03-08 09:58:51 -08:00
madeofstown
e1cb984358 update README.md 2025-03-07 22:24:41 -08:00
madeofstown
408cc5c52b update sample.config.ini 2025-03-07 22:12:33 -08:00
madeofstown
93c1185447 i think its working now 2025-03-07 22:06:16 -08:00
madeofstown
10c1bea76f First Attempt
Try merge. Will need testing and tweaking.
2025-03-07 19:40:46 -08:00
madeofstown
031d75eb33 Merge branch 'pablo-merge' into site_config 2025-03-07 19:39:39 -08:00
Pablo Revilla
a59787a010 Added more analytics by reporting on the number and kinds of packets each node sends in a 24 hour period. 2025-03-06 15:59:09 -08:00
Pablo Revilla
ab5b8a7012 Added more analytics by reporting on the number and kinds of packets each node sends in a 24 hour period. 2025-03-06 15:50:33 -08:00
Pablo Revilla
d910fadf24 Merge remote-tracking branch 'origin/master' 2025-03-05 16:53:14 -08:00
Pablo Revilla
9006444cf8 Major changes to the project
- Now the database process and the web process are separate.
- Added Map
- Added new graphing tools
2025-03-05 16:53:05 -08:00
Pablo Revilla
45ce4c17e5 Update README.md 2025-03-05 16:45:26 -08:00
Pablo Revilla
19aba18fcd Update README.md 2025-03-05 16:44:26 -08:00
Pablo Revilla
707426dfd6 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	meshview/store.py
#	meshview/templates/node.html
#	meshview/web.py
2025-03-05 16:12:59 -08:00
Pablo Revilla
5f97274e80 Major changes to the project
- Now the database process and the web process are separate.
- Added Map
- Added new graphing tools
2025-03-05 16:11:40 -08:00
madeofstown
ae0748d874 Merge pull request #3 from pablorevilla-meshtastic/master
Merge pull request #8 from madeofstown/net-graph
2025-03-02 17:49:03 -08:00
madeofstown
c8bc651970 upload local 2025-03-02 17:12:42 -08:00
Pablo Revilla
445ffbc1fb Merge pull request #8 from madeofstown/net-graph
Fix the Network Graph button
2025-02-26 20:40:43 -08:00
madeofstown
e879030d70 Update README.md
technically flags are boolean arguments
2025-02-23 14:41:27 -08:00
madeofstown
272476c700 Update README.md
A few more changes - including a screenshot!
2025-02-23 14:37:56 -08:00
madeofstown
d381f9c009 Add files via upload 2025-02-23 14:30:47 -08:00
madeofstown
518f7f0c2f Delete screenshots/image.png 2025-02-23 14:30:12 -08:00
madeofstown
a66b3aa4f8 Add files via upload 2025-02-23 14:28:44 -08:00
madeofstown
334ffb03fe Delete screenshots/image.png 2025-02-23 14:28:21 -08:00
madeofstown
5ebfb4bf67 Add files via upload 2025-02-23 14:26:46 -08:00
madeofstown
e6680ff486 Rename image.png to nodeinfo.png 2025-02-23 14:25:09 -08:00
madeofstown
65ae1bb204 Add files via upload 2025-02-23 14:24:27 -08:00
madeofstown
44c30433c7 Delete config.ini 2025-02-23 14:18:16 -08:00
madeofstown
bcc9c03459 a few more changes with the readme 2025-02-23 14:14:57 -08:00
madeofstown
f17a3d2786 ok, it's a little more than just a fix 2025-02-23 13:33:43 -08:00
Pablo Revilla
532fd7a56d Merge remote-tracking branch 'origin/master'
# Conflicts:
#	config.ini
#	meshview/templates/map.html
2025-02-21 11:58:01 -08:00
Pablo Revilla
1bd41ae82a Adding screenshots 2025-02-21 11:57:01 -08:00
Pablo Revilla
bcb04bcec5 Create map.html 2025-02-21 11:56:07 -08:00
Pablo Revilla
03183384c6 Adding screenshots 2025-02-21 11:24:15 -08:00
Pablo Revilla
1a7a8b31a7 Merge pull request #7 from madeofstown/master
Fix for the mqtt bugs
2025-02-21 11:00:50 -08:00
madeofstown
4799a97f59 user is string not list 2025-02-20 19:24:04 -08:00
madeofstown
2bfb53ba45 Merge branch 'pablorevilla-meshtastic:master' into master 2025-02-20 19:19:58 -08:00
madeofstown
342a92c40e fix? 2025-02-20 19:16:59 -08:00
Pablo Revilla
4585f50b08 Adding screenshots 2025-02-20 10:19:05 -08:00
Pablo Revilla
b616623898 Adding screenshots 2025-02-20 10:17:38 -08:00
Pablo Revilla
6ea5cf7eba Added Map capabilities 2025-02-20 09:02:51 -08:00
Pablo Revilla
1432cefb4b Removed comments 2025-02-20 08:52:34 -08:00
Pablo Revilla
0c0c41e157 Removed comments 2025-02-20 08:52:08 -08:00
Pablo Revilla
4fd167a226 Merge pull request #6 from madeofstown/patch-3
Fix Code Snippet
2025-02-19 10:39:16 -08:00
madeofstown
2cdd2a7048 Update README.md
Fix embedded code snippet in README
2025-02-19 06:09:45 -08:00
Pablo Revilla
20bc89a21f Update README.md 2025-02-18 17:11:46 -08:00
Pablo Revilla
551b9f52eb Merge pull request #5 from madeofstown/master
Fix overlapping legends
2025-02-18 13:49:25 -08:00
Pablo Revilla
615dd44b85 Merge pull request #4 from madeofstown/configini
Add config file
2025-02-18 09:57:38 -08:00
Pablo Revilla
cacf072a51 Merge pull request #3 from madeofstown/patch-2
Update and rename README to README.md
2025-02-18 08:48:34 -08:00
madeofstown
a67383ee68 oops, add it back 2025-02-17 15:35:16 -08:00
madeofstown
ab1f1a71ea Fix Legend Overlap 2025-02-17 15:29:28 -08:00
madeofstown
f20ca4a88e Merge pull request #2 from madeofstown/configini
Merge configini branch into master
2025-02-17 14:47:20 -08:00
madeofstown
6406efffe8 Update README.md
Make python and graphviz requirements more clear
2025-02-17 14:28:06 -08:00
madeofstown
c8567fec6e Update README.md
More changes to reflect the addition of `config.ini`
2025-02-17 14:24:51 -08:00
madeofstown
c9d65a078a changes after testing 2025-02-17 13:49:34 -08:00
madeofstown
076abb5811 First changes - pre test 2025-02-17 13:04:42 -08:00
madeofstown
0de71c9f13 Update README.md
first mention of config.ini
2025-02-16 17:37:34 -08:00
madeofstown
4c07dcd2e5 Merge pull request #1 from madeofstown/patch-2
Update and rename README to README.md
2025-02-16 17:17:16 -08:00
madeofstown
a808b47295 Merge branch 'pablorevilla-meshtastic:master' into master 2025-02-16 17:09:07 -08:00
madeofstown
44f31c5eb7 Update README.md
fixed a spelling error
2025-02-16 13:28:11 -08:00
madeofstown
e04c3aaa08 Update and rename README to README.md
Also add new info for correctly cloning to include submodules
2025-02-16 13:21:06 -08:00
Pablo Revilla
55031ad711 Made the conversation section a bit more modern looking 2025-02-13 22:57:48 -08:00
Pablo Revilla
85c708a5a6 Added Weekly Mesh reporting 2025-02-13 11:18:11 -08:00
Pablo Revilla
0556706a30 Added new searching capabilities to our node reports 2025-02-12 08:50:19 -08:00
Pablo Revilla
81703c9e49 Merge remote-tracking branch 'origin/master' 2025-02-11 23:01:36 -08:00
Pablo Revilla
9fbe3400ef Added new searching capabilities to our node reports 2025-02-11 23:01:15 -08:00
Pablo Revilla
9446c3532c Update README 2025-02-11 17:49:00 -08:00
Pablo Revilla
66a3780ff9 Update README 2025-02-11 17:46:50 -08:00
Pablo Revilla
0151bd9513 Update README 2025-02-11 17:43:05 -08:00
Pablo Revilla
94d803df66 added screenshot 2025-02-11 17:41:57 -08:00
Pablo Revilla
e17c288041 added screenshot 2025-02-11 17:40:38 -08:00
Pablo Revilla
052adb7791 added screenshot 2025-02-11 17:38:54 -08:00
Pablo Revilla
bdcf086939 Multiple changes to the code. Important to mentioned:
- Added ways to show the node data on the page with links to the nodes themselves.
- more work on the graphs.
2025-02-11 17:37:12 -08:00
Pablo Revilla
e1228fbb64 Multiple changes to the code. Important to mentioned:
- Added ways to show the node data on the page with links to the nodes themselves.
- more work on the graphs.
2025-02-11 17:35:21 -08:00
Pablo Revilla
33767dc595 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	README
2025-02-11 17:32:21 -08:00
Pablo Revilla
6b76908698 Multiple changes to the code. Important to mentioned:
- Added ways to show the node data on the page with links to the nodes themselves.
- more work on the graphs.
2025-02-11 17:31:45 -08:00
Pablo Revilla
365200dcb8 Update README 2025-02-11 12:53:37 -08:00
Pablo Revilla
0831301997 Multiple changes to the code. Important to mentioned:
- We added another column to the nodes table to report on firmware version

- Also changed the date and time format to be more readable.

- Added a node list report

- Modified the Mesh Graphs
2025-02-07 21:18:02 -08:00
Pablo Revilla
604fc5c284 Multile changes to the code. Important to mentioned that we added another column to the nodes table to report on last_update
This can give us when the node was last seen on the mesh and provide some understanding if it is active.
2025-01-31 14:19:28 -08:00
Pablo Revilla
45c26aa713 Basic documentation of the notify feature. This is still reporting the "Missing return Statement on request handler" 2025-01-26 18:31:16 -08:00
Pablo Revilla
6f0f65f2b1 Added the code and HTML syntax to saparate LF from MS on the graphs. 2025-01-26 18:30:12 -08:00
madeofstown
77d1f84456 Merge branch 'pablorevilla-meshtastic:master' into master 2025-01-26 17:45:44 -08:00
Pablo Revilla
cedc809928 Added links for LF and MS network Graphs. 2025-01-25 19:14:41 -08:00
Pablo Revilla
f1c7f98353 Update to the data models to show new fields on DB 2025-01-25 18:28:42 -08:00
Pablo Revilla
94bd8ba423 Update to the data models to show new fields on DB 2025-01-25 18:27:49 -08:00
Pablo Revilla
40310d782a Update to the data models to show new fields on DB 2025-01-25 18:27:11 -08:00
Pablo Revilla
37ed0369e4 Update to the data models to show new fields on DB 2025-01-25 18:21:26 -08:00
madeofstown
8b05e500b8 Use config.ini for settings (try 2) 2025-01-25 15:41:26 -08:00
Pablo Revilla
f72d7f70f1 Merge pull request #2 from madeofstown/master
Major Additions
2025-01-25 14:31:06 -08:00
Pablo Revilla
1cbe5effd2 Update store.py
Added Comments
2025-01-23 09:54:56 -08:00
Pablo Revilla
28092a510f Update web.py
Does it need a web.response>
2025-01-21 21:51:19 -08:00
madeofstown
0c46891f13 Graphs and Dark Mode 2025-01-20 20:23:27 -08:00
madeofstown
4c8a8245ca oops 2025-01-20 14:22:45 -08:00
madeofstown
796f572cef more meshtastic-python as submodule changes 2025-01-20 14:19:49 -08:00
madeofstown
57643b1a12 tryfix symlink origin 2025-01-20 13:54:22 -08:00
madeofstown
f898b4632f meshtastic/protobuf 2025-01-20 13:51:16 -08:00
madeofstown
f189147ab5 meshtastic python as submodule 2025-01-20 13:41:48 -08:00
madeofstown
fb66b74fe7 add symlink to submodule folder 2025-01-20 13:05:43 -08:00
madeofstown
5204851a6a Delete old pb2 files 2025-01-20 13:04:28 -08:00
madeofstown
e28dd0ce83 meshtastic-python as submodule 2025-01-20 12:41:47 -08:00
Pablo Revilla
ff4f3a3734 Added quick link for statistics on base.html 2025-01-17 13:40:32 -08:00
Pablo Revilla
fcfd7d6683 Fixed Typo 2025-01-17 13:37:31 -08:00
Pablo Revilla
5e7d94973e Providing /stats to give us basic reporting on number of nodes and packets seen by the tool 2025-01-17 12:52:11 -08:00
Pablo Revilla
58e700db2b Providing /stats to give us basic reporting on number of nodes and packets seen by the tool 2025-01-17 12:47:55 -08:00
Pablo Revilla
4bcc7b08d0 Providing /stats to give us basic reporting on number of nodes and packets seen by the tool 2025-01-17 12:46:26 -08:00
Pablo Revilla
63552b3d53 Update base.html
Added link to Meshview forks on Github
2025-01-14 14:22:47 -08:00
Pablo Revilla
ef725185b1 Update web.py 2025-01-13 15:50:27 -08:00
Pablo Revilla
35da39e079 UTC change made uplinked packets not work. reverted the changes. 2025-01-13 14:33:58 -08:00
Pablo Revilla
43418c1249 Changed the import time from UTC to the server's time 2025-01-13 13:03:15 -08:00
Pablo Revilla
4fa4e17f45 changes to README 2025-01-13 12:56:55 -08:00
Pablo Revilla
854f1c5555 changes to README 2025-01-11 14:39:54 -08:00
Pablo Revilla
f809bfc54f Modified read me to add the graphviz requirement 2025-01-11 14:38:59 -08:00
Pablo Revilla
1eff0e6d5c Modified read me to add the graphviz requirement 2025-01-11 11:01:47 -08:00
Pablo Revilla
aa90d23740 Changed html from <center> to a div with center 2025-01-11 10:59:19 -08:00
Pablo Revilla
8ec4ad2108 Changed html from <center> to a div with center 2025-01-09 17:42:13 -08:00
Pablo Revilla
e3768b81a9 Cleaned up Index page 2025-01-09 15:50:37 -08:00
Pablo Revilla
5882f79211 Added main menu and spacing 2025-01-09 15:45:50 -08:00
Pablo Revilla
a17db8ce93 Added main menu and spacing 2025-01-09 15:36:16 -08:00
pablorevilla-meshtastic
eebfdb84c3 Update README 2025-01-09 15:17:35 -08:00
Jason Michalski
c0641147cb Change the default topic.
There is no traffic on msh/US/bayarea/# now that we moved to a private
server.
2024-08-26 20:47:25 -07:00
Jason Michalski
9a2c76a0a3 Set an identifier when connecting to MQTT. 2024-08-26 20:46:14 -07:00
Jason Michalski
d4a174ebbf Fix packet details for missing nodes. 2024-08-25 20:06:11 -07:00
Jason Michalski
0838f385ff Do not set pool settings for sqlite. 2024-08-25 19:45:16 -07:00
Jason Michalski
15a6efd813 Update protos. 2024-08-21 20:51:25 -07:00
Jason Michalski
4127ef4951 Disable fitBounds animation. 2024-08-17 19:25:40 -07:00
Jason Michalski
20194265a4 Add popups on the packet details map. 2024-08-17 19:08:39 -07:00
Jason Michalski
33879f3eda Add more graphs. 2024-07-29 21:43:15 -07:00
Jason Michalski
ddfd2550ac Make the mobile layout less bad. 2024-07-29 18:59:42 -07:00
Jason Michalski
0d58967da2 Use my new found fitBounds powers on the node map. 2024-07-27 21:53:05 -07:00
Jason Michalski
5a23fb25bd Add a map to the packet details. 2024-07-27 21:50:24 -07:00
Jason Michalski
e3969e12d6 Add net view. 2024-07-27 20:33:36 -07:00
Jason Michalski
d01d442eb7 Show milliseconds in timestamp because Fnnc wants it. 2024-07-16 15:04:42 -07:00
Jason Michalski
4def7c47e9 Allow using freedom MQTT servers. 2024-07-15 20:12:12 -07:00
Jason Michalski
b7667485b3 404 on missing packets. 2024-07-15 14:37:51 -07:00
Jason Michalski
7fd735353d The position packet may not have a location. 2024-07-14 21:21:36 -07:00
Jason Michalski
f5966acb7f Link nodes in the traceroute graphs. 2024-07-14 19:59:57 -07:00
Jason Michalski
83547197df Use a smaller image static SNR graph. 2024-07-14 19:59:30 -07:00
Jason Michalski
df33c43d1c Stop trusting the client's clock. 2024-07-14 19:58:59 -07:00
Jason Michalski
06c16806f2 Add a single old location point to the trace if we have one. 2024-07-14 19:57:49 -07:00
Jason Michalski
64a2862e17 Add minutes support to the network graph. 2024-07-03 15:52:31 -07:00
Jason Michalski
4437aff938 Use plotly for detailed neighbors graphs. 2024-06-30 22:05:38 -07:00
Jason Michalski
c469cee12b Only show the past 24h of locations. 2024-06-29 18:08:37 -07:00
Jason Michalski
e937f63322 Fix crash on missing traceroute request packet. 2024-06-29 17:14:18 -07:00
Jason Michalski
c251a4dc78 Add role to traceroute graphs. 2024-06-29 15:58:42 -07:00
Jason Michalski
3f6397f31b Fix crash when payload can not be decoded. 2024-06-29 15:58:24 -07:00
Jason Michalski
b279ddd88e Increase database conection pool size. 2024-06-29 15:57:56 -07:00
Jason Michalski
d1c7984aea Update protos 2024-06-29 15:55:45 -07:00
Jason Michalski
a6d8212143 Add sserver generated neighbor info. 2024-06-18 00:34:40 -07:00
Jason Michalski
672563c9cd concentrate was to working so do it myself. 2024-06-16 20:13:56 -07:00
Jason Michalski
3f15c29683 Add graph link to traceroute results as well. 2024-06-16 16:43:37 -07:00
Jason Michalski
a4c18d8525 Add node zooming and time filters. 2024-06-16 16:41:37 -07:00
Jason Michalski
13eda803c9 Include the dest of TRs in the network. 2024-06-15 20:50:25 -07:00
Jason Michalski
aa7c108513 Link to the network graph and make TR win. 2024-06-15 19:56:43 -07:00
Jason Michalski
f372001703 Color ROUTER nodes in the network graph. 2024-06-15 19:46:52 -07:00
Jason Michalski
96db2e0970 Add node role to the info box. 2024-06-15 19:31:46 -07:00
Jason Michalski
b24b829fb1 Add edge color and change some dot settings. 2024-06-15 19:06:50 -07:00
Jason Michalski
ad004c399c Add a network graph based on the list day of traceroute traffic. 2024-06-15 11:40:01 -07:00
Jason Michalski
eeffc52932 Add link to the packet from the chat list. 2024-06-15 10:14:26 -07:00
Jason Michalski
aab74af21a Load packet details on the package index. 2024-06-12 20:20:56 -07:00
Jason Michalski
51c478d8fc Add traceroute times. 2024-06-11 22:34:17 -07:00
245 changed files with 30052 additions and 14360 deletions

10
.dockerignore Normal file
View File

@@ -0,0 +1,10 @@
# This keeps Docker from including hostOS virtual environment folders
env/
.venv/
# Database files and backups
*.db
*.db-shm
*.db-wal
backups/
*.db.gz

54
.github/workflows/container.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Build container
on:
push:
workflow_dispatch:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
# list of Docker images to use as base name for tags
images: |
ghcr.io/${{ github.repository }}
# generate Docker tags based on the following events/attributes
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
# publish :latest from the default branch
type=raw,value=latest,enable={{is_default_branch}}
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Containerfile
push: ${{ github.event_name != 'pull_request' }}
labels: ${{ steps.meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64
# optional cache (speeds up rebuilds)
cache-from: type=gha
cache-to: type=gha,mode=max

39
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Ruff
on:
pull_request:
paths:
- "**/*.py"
- "pyproject.toml"
- "ruff.toml"
- ".pre-commit-config.yaml"
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Cache Ruff
uses: actions/cache@v4
with:
path: ~/.cache/ruff
key: ruff-${{ runner.os }}-${{ hashFiles('**/pyproject.toml', '**/ruff.toml') }}
- name: Install Ruff
run: pip install "ruff==0.13.3"
# Lint (with GitHub annotation format for inline PR messages)
- name: Ruff check
run: ruff check --output-format=github .
# Fail PR if formatting is needed
- name: Ruff format (check-only)
run: ruff format --check .
# TODO: Investigate only applying to changed files and possibly apply fixes

44
.gitignore vendored
View File

@@ -1,3 +1,47 @@
env/*
__pycache__/*
meshview/__pycache__/*
alembic/__pycache__/*
# Database files
packets.db
packets*.db
*.db
*.db-shm
*.db-wal
# Database backups
backups/
*.db.gz
# Process files
meshview-db.pid
meshview-web.pid
# Config and logs
/table_details.py
config.ini
*.log
# Screenshots
screenshots/*
# Python
python/nanopb
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
packets.db-journal

1
.gitmodules vendored Normal file
View File

@@ -0,0 +1 @@

8
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,8 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.3 # pin the latest youre comfortable with
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix] # fail if it had to change files
- id: ruff-format

204
AGENTS.md Normal file
View File

@@ -0,0 +1,204 @@
# AI Agent Guidelines for Meshview
This document provides context and guidelines for AI coding assistants working on the Meshview project.
## Project Overview
Meshview is a real-time monitoring and diagnostic tool for Meshtastic mesh networks. It provides web-based visualization and analysis of network activity, including:
- Real-time packet monitoring from MQTT streams
- Interactive map visualization of node locations
- Network topology graphs showing connectivity
- Message traffic analysis and conversation tracking
- Node statistics and telemetry data
- Packet inspection and traceroute analysis
## Architecture
### Core Components
1. **MQTT Reader** (`meshview/mqtt_reader.py`) - Subscribes to MQTT topics and receives mesh packets
2. **Database Manager** (`meshview/database.py`, `startdb.py`) - Handles database initialization and migrations
3. **MQTT Store** (`meshview/mqtt_store.py`) - Processes and stores packets in the database
4. **Web Server** (`meshview/web.py`, `main.py`) - Serves the web interface and API endpoints
5. **API Layer** (`meshview/web_api/api.py`) - REST API endpoints for data access
6. **Models** (`meshview/models.py`) - SQLAlchemy database models
7. **Decode Payload** (`meshview/decode_payload.py`) - Protobuf message decoding
### Technology Stack
- **Python 3.13+** - Main language
- **aiohttp** - Async web framework
- **aiomqtt** - Async MQTT client
- **SQLAlchemy (async)** - ORM with async support
- **Alembic** - Database migrations
- **Jinja2** - Template engine
- **Protobuf** - Message serialization (Meshtastic protocol)
- **SQLite/PostgreSQL** - Database backends (SQLite default, PostgreSQL via asyncpg)
### Key Patterns
- **Async/Await** - All I/O operations are asynchronous
- **Database Migrations** - Use Alembic for schema changes (see `docs/Database-Changes-With-Alembic.md`)
- **Configuration** - INI file-based config (`config.ini`, see `sample.config.ini`)
- **Modular API** - API routes separated into `meshview/web_api/` module
## Project Structure
```
meshview/
├── alembic/ # Database migration scripts
├── docs/ # Technical documentation
├── meshview/ # Main application package
│ ├── static/ # Static web assets (HTML, JS, CSS)
│ ├── templates/ # Jinja2 HTML templates
│ ├── web_api/ # API route handlers
│ └── *.py # Core modules
├── main.py # Web server entry point
├── startdb.py # Database manager entry point
├── mvrun.py # Combined runner (starts both services)
├── config.ini # Runtime configuration
└── requirements.txt # Python dependencies
```
## Development Workflow
### Setup
1. Use Python 3.13+ virtual environment
### Running
- **Database**: `./env/bin/python startdb.py`
- **Web Server**: `./env/bin/python main.py`
- **Both**: `./env/bin/python mvrun.py`
## Code Style
- **Line length**: 100 characters (see `pyproject.toml`)
- **Linting**: Ruff (configured in `pyproject.toml`)
- **Formatting**: Ruff formatter
- **Type hints**: Preferred but not strictly required
- **Async**: Use `async def` and `await` for I/O operations
## Important Files
### Configuration
- `config.ini` - Runtime configuration (server, MQTT, database, cleanup)
- `sample.config.ini` - Template configuration file
- `alembic.ini` - Alembic migration configuration
### Database
- `meshview/models.py` - SQLAlchemy models (Packet, Node, Traceroute, etc.)
- `meshview/database.py` - Database initialization and session management
- `alembic/versions/` - Migration scripts
### Core Logic
- `meshview/mqtt_reader.py` - MQTT subscription and message reception
- `meshview/mqtt_store.py` - Packet processing and storage
- `meshview/decode_payload.py` - Protobuf decoding
- `meshview/web.py` - Web server routes and handlers
- `meshview/web_api/api.py` - REST API endpoints
### Templates
- `meshview/templates/` - Jinja2 HTML templates
- `meshview/static/` - Static files (HTML pages, JS, CSS)
## Common Tasks
### Adding a New API Endpoint
1. Add route handler in `meshview/web_api/api.py`
2. Register route in `meshview/web.py` (if needed)
3. Update `docs/API_Documentation.md` if public API
### Database Schema Changes
1. Modify models in `meshview/models.py`
2. Create migration: `alembic revision --autogenerate -m "description"`
3. Review generated migration in `alembic/versions/`
4. Test migration: `alembic upgrade head`
5. **Never** modify existing migration files after they've been applied
### Adding a New Web Page
1. Create template in `meshview/templates/`
2. Add route in `meshview/web.py`
3. Add navigation link if needed (check existing templates for pattern)
4. Add static assets if needed in `meshview/static/`
### Processing New Packet Types
1. Check `meshview/decode_payload.py` for existing decoders
2. Add decoder function if new type
3. Update `meshview/mqtt_store.py` to handle new packet type
4. Update database models if new data needs storage
## Key Concepts
### Meshtastic Protocol
- Uses Protobuf for message serialization
- Packets contain various message types (text, position, telemetry, etc.)
- MQTT topics follow pattern: `msh/{region}/{subregion}/#`
### Database Schema
- **packet** - Raw packet data
- **node** - Mesh node information
- **traceroute** - Network path information
- **packet_seen** - Packet observation records
### Real-time Updates
- Web pages use Server-Sent Events (SSE) for live updates
- Map and firehose pages auto-refresh based on config intervals
- API endpoints return JSON for programmatic access
## Best Practices
1. **Always use async/await** for database and network operations
2. **Use Alembic** for all database schema changes
3. **Follow existing patterns** - check similar code before adding new features
4. **Update documentation** - keep `docs/` and README current
5. **Test migrations** - verify migrations work both up and down
6. **Handle errors gracefully** - log errors, don't crash on bad packets
7. **Respect configuration** - use `config.ini` values, don't hardcode
## Common Pitfalls
- **Don't modify applied migrations** - create new ones instead
- **Don't block the event loop** - use async I/O, not sync
- **Don't forget timezone handling** - timestamps are stored in UTC
- **Don't hardcode paths** - use configuration values
- **Don't ignore MQTT reconnection** - handle connection failures gracefully
## Resources
- **Main README**: `README.md` - Installation and basic usage
- **Docker Guide**: `README-Docker.md` - Container deployment
- **API Docs**: `docs/API_Documentation.md` - API endpoint reference
- **Migration Guide**: `docs/Database-Changes-With-Alembic.md` - Database workflow
- **Contributing**: `CONTRIBUTING.md` - Contribution guidelines
## Version Information
- **Current Version**: 3.0.0 (November 2025)
- **Python Requirement**: 3.13+
- **Key Features**: Alembic migrations, automated backups, Docker support, traceroute return paths
## Rules for robots
- Always run ruff check and ruff format after making changes (only on python changes)
---
When working on this project, prioritize:
1. Maintaining async patterns
2. Following existing code structure
3. Using proper database migrations
4. Keeping documentation updated
5. Testing changes thoroughly

133
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,133 @@
# Contributing to Meshview
First off, thanks for taking the time to contribute! ❤️
All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for ways to help and details about how this project handles contributions. Please read the relevant section before getting started — it will make things smoother for both you and the maintainers.
The Meshview community looks forward to your contributions. 🎉
> And if you like the project but dont have time to contribute code, thats fine! You can still support Meshview by:
> - ⭐ Starring the repo on GitHub
> - Talking about Meshview on social media
> - Referencing Meshview in your own projects README
> - Mentioning Meshview at local meetups or to colleagues/friends
---
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [I Have a Question](#i-have-a-question)
- [I Want to Contribute](#i-want-to-contribute)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Your First Code Contribution](#your-first-code-contribution)
- [Improving the Documentation](#improving-the-documentation)
- [Styleguides](#styleguides)
- [Commit Messages](#commit-messages)
- [Join the Project Team](#join-the-project-team)
---
## Code of Conduct
Meshview is an open and welcoming community. We want everyone to feel safe, respected, and valued.
### Our Standards
- Be respectful and considerate in all interactions.
- Welcome new contributors and help them learn.
- Provide constructive feedback, not personal attacks.
- Focus on collaboration and what benefits the community.
Unacceptable behavior includes harassment, insults, hate speech, personal attacks, or publishing others private information without permission.
---
## I Have a Question
> Before asking, please read the [documentation](docs/README.md) if available.
1. Search the [issues list](../../issues) to see if your question has already been asked.
2. If not, open a [new issue](../../issues/new) with the **question** label.
3. Provide as much context as possible (OS, Python version, database type, etc.).
---
## I Want to Contribute
### Legal Notice
By contributing to Meshview, you agree that:
- You authored the content yourself.
- You have the necessary rights to the content.
- Your contribution can be provided under the projects license.
---
### Reporting Bugs
Before submitting a bug report:
- Make sure youre using the latest Meshview version.
- Verify the issue is not due to a misconfigured environment (SQLite/MySQL, Python version, etc.).
- Search existing [bug reports](../../issues?q=label%3Abug).
- Collect relevant information:
- Steps to reproduce
- Error messages / stack traces
- OS, Python version, and database backend
- Any logs (`meshview-db.service`, `mqtt_reader.py`, etc.)
How to report:
- Open a [new issue](../../issues/new).
- Use a **clear and descriptive title**.
- Include reproduction steps and expected vs. actual behavior.
⚠️ Security issues should **not** be reported in public issues. Instead, email us at **meshview-maintainers@proton.me**.
---
### Suggesting Enhancements
Enhancements are tracked as [issues](../../issues). Before suggesting:
- Make sure the feature doesnt already exist.
- Search for prior suggestions.
- Check that it fits Meshviews scope (mesh packet analysis, visualization, telemetry, etc.).
When submitting:
- Use a **clear and descriptive title**.
- Describe the current behavior and what youd like to see instead.
- Include examples, screenshots, or mockups if relevant.
- Explain why it would be useful to most Meshview users.
---
### Your First Code Contribution
We love first-time contributors! 🚀
If youd like to start coding:
1. Look for issues tagged with [good first issue](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22).
2. Fork the repository and clone it locally.
3. Set up the development environment:
4. Run the app locally
5. Create a new branch, make your changes, commit, and push.
6. Open a pull request!
---
### Improving the Documentation
Docs are just as important as code. You can help by:
- Fixing typos or broken links.
- Clarifying confusing instructions.
- Adding examples (e.g., setting up Nginx as a reverse proxy, SQLite vs. MySQL setup).
- Writing or updating tutorials.
---
## Join the Project Team
Meshview is a community-driven project. If you consistently contribute (code, documentation, or community help), wed love to invite you as a maintainer.
Start by contributing regularly, engaging in issues/PRs, and helping others.
---
✨ Thats it! Thanks again for being part of Meshview. Every contribution matters.

79
Containerfile Normal file
View File

@@ -0,0 +1,79 @@
# Build Image
# Uses python:3.13-slim because no native dependencies are needed for meshview itself
# (everything is available as a wheel)
FROM docker.io/python:3.13-slim AS meshview-build
RUN apt-get update && \
apt-get install -y --no-install-recommends curl patch && \
rm -rf /var/lib/apt/lists/*
# Add a non-root user/group
ARG APP_USER=app
RUN useradd -m -u 10001 -s /bin/bash ${APP_USER}
# Install uv and put it on PATH system-wide
RUN curl -LsSf https://astral.sh/uv/install.sh | sh \
&& install -m 0755 /root/.local/bin/uv /usr/local/bin/uv
WORKDIR /app
RUN chown -R ${APP_USER}:${APP_USER} /app
# Copy deps first for caching
COPY --chown=${APP_USER}:${APP_USER} pyproject.toml uv.lock* requirements*.txt ./
# Optional: wheels-only to avoid slow source builds
ENV UV_NO_BUILD=1
RUN uv venv /opt/venv
# RUN uv sync --frozen
ENV VIRTUAL_ENV=/opt/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN uv pip install --no-cache-dir --upgrade pip \
&& if [ -f requirements.txt ]; then uv pip install --only-binary=:all: -r requirements.txt; fi
# Copy app code
COPY --chown=${APP_USER}:${APP_USER} . .
# Patch config
COPY --chown=${APP_USER}:${APP_USER} container/config.ini /app/sample.config.ini
# Clean
RUN rm -rf /app/.git* && \
rm -rf /app/.pre-commit-config.yaml && \
rm -rf /app/*.md && \
rm -rf /app/COPYING && \
rm -rf /app/Containerfile && \
rm -rf /app/Dockerfile && \
rm -rf /app/container && \
rm -rf /app/docker && \
rm -rf /app/docs && \
rm -rf /app/pyproject.toml && \
rm -rf /app/requirements.txt && \
rm -rf /app/screenshots
# Prepare /app and /opt to copy
RUN mkdir -p /meshview && \
mv /app /opt /meshview
# Use a clean container for install
FROM docker.io/python:3.13-slim
ARG APP_USER=app
COPY --from=meshview-build /meshview /
RUN apt-get update && \
apt-get install -y --no-install-recommends graphviz && \
rm -rf /var/lib/apt/lists/* && \
useradd -m -u 10001 -s /bin/bash ${APP_USER} && \
mkdir -p /etc/meshview /var/lib/meshview /var/log/meshview && \
mv /app/sample.config.ini /etc/meshview/config.ini && \
chown -R ${APP_USER}:${APP_USER} /var/lib/meshview /var/log/meshview
# Drop privileges
USER ${APP_USER}
WORKDIR /app
ENTRYPOINT [ "/opt/venv/bin/python", "mvrun.py"]
CMD ["--pid_dir", "/tmp", "--py_exec", "/opt/venv/bin/python", "--config", "/etc/meshview/config.ini" ]
EXPOSE 8081
VOLUME [ "/etc/meshview", "/var/lib/meshview", "/var/log/meshview" ]

1
Dockerfile Symbolic link
View File

@@ -0,0 +1 @@
Containerfile

19
README
View File

@@ -1,19 +0,0 @@
Meshview
========
This project watches a MQTT topic for meshtastic messages, imports them to a
database and has a web UI to view them.
Example
-------
An example instance, https://meshview.armooo.net, is running with with data
from the MQTT topic msh/US/bayarea/#.
Running
-------
$ python3 -m venv env
$ ./env/bin/pip install -r requirements.txt
$ ./env/bin/python main.py
Now you can hit http://localhost:8080/

247
README-Docker.md Normal file
View File

@@ -0,0 +1,247 @@
# Running MeshView with Docker
MeshView container images are built automatically and published to GitHub Container Registry.
## Quick Start
Pull and run the latest image:
```bash
docker pull ghcr.io/pablorevilla-meshtastic/meshview:latest
docker run -d \
--name meshview \
-p 8081:8081 \
-v ./config:/etc/meshview \
-v ./data:/var/lib/meshview \
-v ./logs:/var/log/meshview \
ghcr.io/pablorevilla-meshtastic/meshview:latest
```
Access the web interface at: http://localhost:8081
## Volume Mounts
The container uses three volumes for persistent data:
| Volume | Purpose | Required |
|--------|---------|----------|
| `/etc/meshview` | Configuration files | Yes |
| `/var/lib/meshview` | Database storage | Recommended |
| `/var/log/meshview` | Log files | Optional |
### Configuration Volume
Mount a directory containing your `config.ini` file:
```bash
-v /path/to/your/config:/etc/meshview
```
If no config is provided, the container will use the default `sample.config.ini`.
### Database Volume
Mount a directory to persist the SQLite database:
```bash
-v /path/to/your/data:/var/lib/meshview
```
**Important:** Without this mount, your database will be lost when the container stops.
### Logs Volume
Mount a directory to access logs from the host:
```bash
-v /path/to/your/logs:/var/log/meshview
```
## Complete Example
Create a directory structure and run:
```bash
# Create directories
mkdir -p meshview/{config,data,logs,backups}
# Copy sample config (first time only)
docker run --rm ghcr.io/pablorevilla-meshtastic/meshview:latest \
cat /etc/meshview/config.ini > meshview/config/config.ini
# Edit config.ini with your MQTT settings
nano meshview/config/config.ini
# Run the container
docker run -d \
--name meshview \
--restart unless-stopped \
-p 8081:8081 \
-v $(pwd)/meshview/config:/etc/meshview \
-v $(pwd)/meshview/data:/var/lib/meshview \
-v $(pwd)/meshview/logs:/var/log/meshview \
ghcr.io/pablorevilla-meshtastic/meshview:latest
```
## Docker Compose
Create a `docker-compose.yml`:
```yaml
version: '3.8'
services:
meshview:
image: ghcr.io/pablorevilla-meshtastic/meshview:latest
container_name: meshview
restart: unless-stopped
ports:
- "8081:8081"
volumes:
- ./config:/etc/meshview
- ./data:/var/lib/meshview
- ./logs:/var/log/meshview
- ./backups:/var/lib/meshview/backups # For database backups
environment:
- TZ=America/Los_Angeles # Set your timezone
```
Run with:
```bash
docker-compose up -d
```
## Configuration
### Minimum Configuration
Edit your `config.ini` to configure MQTT connection:
```ini
[mqtt]
server = mqtt.meshtastic.org
topics = ["msh/US/#"]
port = 1883
username =
password =
[database]
# SQLAlchemy async connection string.
# Examples:
# sqlite+aiosqlite:///var/lib/meshview/packets.db
# postgresql+asyncpg://user:pass@host:5432/meshview
connection_string = sqlite+aiosqlite:////var/lib/meshview/packets.db
```
### Database Backups
To enable automatic daily backups inside the container:
```ini
[cleanup]
backup_enabled = True
backup_dir = /var/lib/meshview/backups
backup_hour = 2
backup_minute = 00
```
Then mount the backups directory:
```bash
-v $(pwd)/meshview/backups:/var/lib/meshview/backups
```
## Available Tags
| Tag | Description |
|-----|-------------|
| `latest` | Latest build from the main branch |
| `dev-v3` | Development branch |
| `v1.2.3` | Specific version tags |
## Updating
Pull the latest image and restart:
```bash
docker pull ghcr.io/pablorevilla-meshtastic/meshview:latest
docker restart meshview
```
Or with docker-compose:
```bash
docker-compose pull
docker-compose up -d
```
## Logs
View container logs:
```bash
docker logs meshview
# Follow logs
docker logs -f meshview
# Last 100 lines
docker logs --tail 100 meshview
```
## Troubleshooting
### Container won't start
Check logs:
```bash
docker logs meshview
```
### Database permission issues
Ensure the data directory is writable:
```bash
chmod -R 755 meshview/data
```
### Can't connect to MQTT
1. Check your MQTT configuration in `config.ini`
2. Verify network connectivity from the container:
```bash
docker exec meshview ping mqtt.meshtastic.org
```
### Port already in use
Change the host port (left side):
```bash
-p 8082:8081
```
Then access at: http://localhost:8082
## Building Your Own Image
If you want to build from source:
```bash
git clone https://github.com/pablorevilla-meshtastic/meshview.git
cd meshview
docker build -f Containerfile -t meshview:local .
```
## Security Notes
- The container runs as a non-root user (`app`, UID 10001)
- No privileged access required
- Only port 8081 is exposed
- All data stored in mounted volumes
## Support
- GitHub Issues: https://github.com/pablorevilla-meshtastic/meshview/issues
- Documentation: https://github.com/pablorevilla-meshtastic/meshview

667
README.md Normal file
View File

@@ -0,0 +1,667 @@
# Meshview
![Start Page](screenshots/animated.gif)
The project serves as a real-time monitoring and diagnostic tool for the Meshtastic mesh network. It provides detailed insights into network activity, including message traffic, node positions, and telemetry data.
### Version 3.0.5 — February 2026
- **IMPORTANT:** the predicted coverage feature requires the extra `pyitm` dependency. If it is not installed, the coverage API will return 503.
- Ubuntu install (inside the venv): `./env/bin/pip install pyitm`
- Coverage: predicted coverage overlay (LongleyRice area mode) with perimeter rendering and documentation.
- Gateways: persistent gateway tracking (`is_mqtt_gateway`) and UI indicators in nodes, map popups, and stats.
- Map UX: deterministic jitter for overlapping nodes; edges follow jittered positions.
- Tooling: Meshtastic protobuf updater script with `--check` and `UPSTREAM_REV.txt` tracking.
### Version 3.0.4 — Late January 2026
- Database: multiDB support, PostgreSQL scripts, WAL config for SQLite, cleanup query timing fixes, removal of import time columns, and various timehandling fixes.
- UI/UX: extensive updates to node.html, nodelist.html, top.html, and packet.html (paging, stats, distance, status/favorites), plus net view changes to 12hour window.
- API/logic: weekly mesh query fix, node list performance improvement, backwardscompatibility and other bug fixes.
- MQTT reader: configurable skipnode list and secondary decryption keys.
- Docs/ops: multiple documentation updates, updated site list, container workflow fixes/tests, README updates.
### Version 3.0.2 — January 2026
- Changes to the Database to will make it so that there is a need for space when updating to the latest. SQlite requires to rebuild the database when droping a column. ( we are droping some of the old columns) so make sure you have 1.2x the size of the db of space in your environment. Depending on how big your db is it would take a long time.
### Version 3.0.1 — December 2025
#### 🌐 Multi-Language Support (i18n)
- New `/api/lang` endpoint for serving translations
- Section-based translation loading (e.g., `?section=firehose`)
- Default language controlled via config file language section
- JSON-based translation files for easy expansion
- Core pages updated to support `data-translate-lang` attributes
### 🛠 Improvements
- Updated UI elements across multiple templates for localization readiness
- General cleanup to support future language additions
### Version 3.0.0 update - November 2025
**Major Infrastructure Improvements:**
* **Database Migrations**: Alembic integration for safe schema upgrades and database versioning
* **Automated Backups**: Independent database backup system with gzip compression (separate from cleanup)
* **Development Tools**: Quick setup script (`setup-dev.sh`) with pre-commit hooks for code quality
* **Docker Support**: Pre-built containers now available on GitHub Container Registry with automatic builds - ogarcia
**New Features:**
* **Traceroute Return Path**: Log and display return path data for traceroute packets - jschrempp
* **Microsecond Timestamps**: Added `import_time_us` columns for higher precision time tracking
**Technical Improvements:**
* Migration from manual SQL to Alembic-managed schema
* Container images use `uv` for faster dependency installation
* Python 3.13 support with slim Debian-based images
* Documentation collection in `docs/` directory
* API routes moved to separate modules for better organization
* /version and /health endpoints added for monitoring
See [README-Docker.md](README-Docker.md) for container deployment and [docs/](docs/) for technical documentation.
### Version 2.0.7 update - September 2025
* New database maintenance capability to automatically keep a specific number of days of data.
* Added configuration for update intervals for both the Live Map and the Firehose pages.
### Version 2.0.6 update - August 2025
* New Live Map (Shows packet feed live)
* New API /api/config (See API documentation)
* New API /api/edges (See API documentation)
* Adds edges to the map (click to see traceroute and neighbours)
### Version 2.0.4 update - August 2025
* New statistic page with more data.
* New API /api/stats (See API documentation).
* Inprovement on "See Everything" and "Conversation" pages.
* Tracking of replies with links to original message.
### Version 2.0.3 update - June 2025
* Moved more graphs to eCharts.
* Addedd smooth updating for "Conversations" and "See everything" sections.
* Now you can turn on and off "Quick Links".
* Network graphs are now dynamically generated depending on your mesh and the presets in use.
* Download node's packet information for the last 3 days to .csv file.
* Display distance traveled by packet.
### Key Features
* **Live Data Visualization**: Users can view real-time data from the mesh network, including text messages, GPS positions, and node information.
* **Interactive Map**: The site offers an interactive map displaying the locations of active nodes, helping users identify network coverage areas.
* **Mesh Graphs**: Visual representations of the network's structure and connectivity are available, illustrating how nodes are interconnected.
* **Packet Analysis**: Detailed information on individual data packets transmitted within the network can be accessed, including payload content and transmission paths.
* **Node Statistics**: Users can explore statistics related to network traffic, such as top contributors and message volumes.
Samples of currently running instances:
- https://meshview.bayme.sh (SF Bay Area - USA)
- https://www.svme.sh (Sacramento Valley - USA)
- https://meshview.nyme.sh (New York - USA)
- https://meshview.socalmesh.org (Los Angenles - USA)
- https://map.wpamesh.net (Western Pennsylvania - USA)
- https://meshview.chicagolandmesh.org (Chicago - USA)
- https://meshview.freq51.net/ (Salt Lake City - USA)
- https://meshview.mt.gt (Canada)
- https://canadaverse.org (Canada)
- https://meshview.meshtastic.es (Spain)
- https://view.mtnme.sh (North Georgia / East Tennessee - USA)
- https://meshview.lsinfra.de (Hessen - Germany)
- https://meshview.pvmesh.org (Pioneer Valley, Massachusetts - USA)
- https://meshview.louisianamesh.org (Louisiana - USA)
- https://www.swlamesh.com (Southwest Louisiana- USA)
- https://meshview.meshcolombia.co (Colombia)
- https://meshview-salzburg.jmt.gr (Salzburg / Austria)
- https://map.cromesh.eu (Coatia)
- https://view.meshdresden.eu (Dresden / Germany)
- https://meshview.meshoregon.com (Oregon - USA)
- https://meshview.gamesh.net (Georgia - USA)
---
### Updating from 2.x to 3.x
We are adding the use of Alembic. If using GitHub
Update your codebase by running the pull command
```bash
cd meshview
git pull origin master
```
Install Alembic in your environment
```bash
./env/bin/pip install alembic
```
Start your scripts or services. This process will update your database with the latest schema.
## Installing
### Using Docker (Recommended)
The easiest way to run MeshView is using Docker. Pre-built images are available from GitHub Container Registry.
See **[README-Docker.md](README-Docker.md)** for complete Docker installation and usage instructions.
### Manual Installation
Requires **`python3.13`** or above.
Clone the repo from GitHub:
```bash
git clone https://github.com/pablorevilla-meshtastic/meshview.git
cd meshview
```
#### Quick Setup (Recommended)
Run the development setup script:
```bash
./setup-dev.sh
```
This will:
- Create Python virtual environment
- Install all requirements
- Install development tools (pre-commit, pytest)
- Set up pre-commit hooks for code formatting
- Create config.ini from sample
#### Manual Setup
Create a Python virtual environment:
```bash
python3 -m venv env
```
Install the environment requirements:
```bash
./env/bin/pip install -r requirements.txt
```
Install `graphviz` on MacOS or Debian/Ubuntu Linux:
```bash
sudo apt-get install graphviz
```
Copy `sample.config.ini` to `config.ini`:
```bash
cp sample.config.ini config.ini
```
Edit `config.ini` to match your MQTT and web server settings:
```bash
nano config.ini
```
> **NOTE**
> On MacOS set the bind configuration line to
> ```
> bind = 127.0.0.1
> ```
Example:
```ini
# -------------------------
# Server Configuration
# -------------------------
[server]
# The address to bind the server to. Use * to listen on all interfaces.
bind = *
# Port to run the web server on.
port = 8081
# Path to TLS certificate (leave blank to disable HTTPS).
tls_cert =
# Path for the ACME challenge if using Let's Encrypt.
acme_challenge =
# -------------------------
# Site Appearance & Behavior
# -------------------------
[site]
# The domain name of your site.
domain =
# Select language (this represents the name of the json file in the /lang directory)
language = es
# Site title to show in the browser title bar and headers.
title = Bay Area Mesh
# A brief message shown on the homepage.
message = Real time data from around the bay area and beyond.
# Starting URL when loading the index page.
starting = /chat
# Enable or disable site features (as strings: "True" or "False").
nodes = True
conversations = True
everything = True
graphs = True
stats = True
net = True
map = True
top = True
# Map boundaries (used for the map view).
# Defaults will show the San Francisco Bay Area
map_top_left_lat = 39
map_top_left_lon = -123
map_bottom_right_lat = 36
map_bottom_right_lon = -121
# Updates intervals in seconds, zero or negative number means no updates
# defaults will be 3 seconds
map_interval=3
firehose_interval=3
# Weekly net details
weekly_net_message = Weekly Mesh check-in. We will keep it open on every Wednesday from 5:00pm for checkins. The message format should be (LONG NAME) - (CITY YOU ARE IN) #BayMeshNet.
net_tag = #BayMeshNet
# -------------------------
# MQTT Broker Configuration
# -------------------------
[mqtt]
# MQTT server hostname or IP.
server = mqtt.bayme.sh
# Topics to subscribe to (as JSON-like list, but still a string).
topics = ["msh/US/bayarea/#", "msh/US/CA/mrymesh/#", "msh/US/CA/sacvalley"]
# Port used by MQTT (typically 1883 for unencrypted).
port = 1883
# MQTT username and password.
username = meshdev
password = large4cats
# -------------------------
# Database Configuration
# -------------------------
[database]
# SQLAlchemy async connection string.
# Examples:
# sqlite+aiosqlite:///packets.db
# postgresql+asyncpg://user:pass@host:5432/meshview
connection_string = sqlite+aiosqlite:///packets.db
# -------------------------
# Database Cleanup Configuration
# -------------------------
[cleanup]
# Enable or disable daily cleanup
enabled = False
# Number of days to keep records in the database
days_to_keep = 14
# Time to run daily cleanup (24-hour format)
hour = 2
minute = 00
# Run VACUUM after cleanup
vacuum = False
# -------------------------
# Logging Configuration
# -------------------------
[logging]
# Enable or disable HTTP access logs from the web server
# When disabled, request logs like "GET /api/chat" will not appear
# Application logs (errors, startup messages, etc.) are unaffected
# Set to True to enable, False to disable (default: False)
access_log = False
# Database cleanup logfile location
db_cleanup_logfile = dbcleanup.log
```
---
## NOTE (PostgreSQL setup)**
If you want to use PostgreSQL instead of SQLite:
Install PostgreSQL for your OS.
Create a user and database:
```
`CREATE USER meshview WITH PASSWORD 'change_me';`
`CREATE DATABASE meshview OWNER meshview;`
```
Update `config.ini` example:
```
`connection_string = postgresql+asyncpg://meshview:change_me@localhost:5432/meshview`
```
## Running Meshview
Start the database manager:
```bash
./env/bin/python startdb.py
```
Start the web server:
```bash
./env/bin/python main.py
```
> **NOTE**
> You can specify a custom config file with the `--config` flag:
>
> ```bash
> ./env/bin/python startdb.py --config /path/to/config.ini
> ./env/bin/python main.py --config /path/to/config.ini
> ```
Open in your browser: http://localhost:8081/
---
## Running Meshview with `mvrun.py`
- `mvrun.py` starts both `startdb.py` and `main.py` in separate threads and merges the output.
- It accepts several command-line arguments for flexible deployment.
```bash
./env/bin/python mvrun.py
```
**Command-line options:**
- `--config CONFIG` - Path to the configuration file (default: `config.ini`)
- `--pid_dir PID_DIR` - Directory for PID files (default: `.`)
- `--py_exec PY_EXEC` - Path to the Python executable (default: `./env/bin/python`)
**Examples:**
```bash
# Use a specific config file
./env/bin/python mvrun.py --config /etc/meshview/config.ini
# Store PID files in a specific directory
./env/bin/python mvrun.py --pid_dir /var/run/meshview
# Use a different Python executable
./env/bin/python mvrun.py --py_exec /usr/bin/python3
```
---
## Setting Up Systemd Services (Ubuntu)
To run Meshview automatically on boot, create systemd services for `startdb.py` and `main.py`.
> **NOTE**
> You need to change the "User" and "/path/to/meshview" for your instance of the code on each service.
### 1. Service for `startdb.py`
Create:
```bash
sudo nano /etc/systemd/system/meshview-db.service
```
Paste:
```ini
[Unit]
Description=Meshview Database Initializer
After=network.target
[Service]
Type=simple
WorkingDirectory=/path/to/meshview
ExecStart=/path/to/meshview/env/bin/python /path/to/meshview/startdb.py --config /path/to/meshview/config.ini
Restart=always
RestartSec=5
User=yourusername
[Install]
WantedBy=multi-user.target
```
### 2. Service for `main.py`
Create:
```bash
sudo nano /etc/systemd/system/meshview-web.service
```
Paste:
```ini
[Unit]
Description=Meshview Web Server
After=network.target meshview-db.service
[Service]
Type=simple
WorkingDirectory=/path/to/meshview
ExecStart=/path/to/meshview/env/bin/python /path/to/meshview/main.py --config /path/to/meshview/config.ini
Restart=always
RestartSec=5
User=yourusername
[Install]
WantedBy=multi-user.target
```
### 3. Enable and start the services
```bash
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable meshview-db
sudo systemctl enable meshview-web
sudo systemctl start meshview-db
sudo systemctl start meshview-web
```
### 4. Check status
```bash
systemctl status meshview-db
systemctl status meshview-web
```
**TIP**
After editing `.service` files, always run:
```bash
sudo systemctl daemon-reload
```
## 5. Database Maintenance
### Database maintnance can now be done via the script itself here is the section from the configuration file.
- Simple to setup
- It will not drop any packets
```
# -------------------------
# Database Cleanup Configuration
# -------------------------
[cleanup]
# Enable or disable daily cleanup
enabled = False
# Number of days to keep records in the database
days_to_keep = 14
# Time to run daily cleanup (24-hour format)
hour = 2
minute = 00
# Run VACUUM after cleanup
vacuum = False
# -------------------------
# Logging Configuration
# -------------------------
[logging]
# Enable or disable HTTP access logs from the web server
access_log = False
# Database cleanup logfile location
db_cleanup_logfile = dbcleanup.log
```
Once changes are done you need to restart the script for changes to load.
### Alternatively we can do it via your OS (This example is Ubuntu like OS)
- Create and save bash script below. (Modify /path/to/file/ to the correct path)
- Name it cleanup.sh
- Make it executable.
```bash
#!/bin/bash
DB_FILE="/path/to/file/packets.db"
# Stop DB service
sudo systemctl stop meshview-db.service
sudo systemctl stop meshview-web.service
sleep 5
echo "Run cleanup..."
# Run cleanup queries
sqlite3 "$DB_FILE" <<EOF
DELETE FROM packet
WHERE import_time_us IS NOT NULL
AND import_time_us < (strftime('%s','now','-14 days') * 1000000);
SELECT 'packet deleted: ' || changes();
DELETE FROM packet_seen
WHERE import_time_us IS NOT NULL
AND import_time_us < (strftime('%s','now','-14 days') * 1000000);
SELECT 'packet_seen deleted: ' || changes();
DELETE FROM traceroute
WHERE import_time_us IS NOT NULL
AND import_time_us < (strftime('%s','now','-14 days') * 1000000);
SELECT 'traceroute deleted: ' || changes();
DELETE FROM node
WHERE last_seen_us IS NULL
OR last_seen_us < (strftime('%s','now','-14 days') * 1000000);
SELECT 'node deleted: ' || changes();
VACUUM;
EOF
# Start DB service
sudo systemctl start meshview-db.service
sudo systemctl start meshview-web.service
echo "Database cleanup completed on $(date)"
```
- If you are using PostgreSQL, use this version instead (adjust credentials/DB name):
```bash
#!/bin/bash
set -euo pipefail
DB="postgresql://meshview@localhost:5432/meshview"
RETENTION_DAYS=14
BATCH_SIZE=100
PSQL="/usr/bin/psql"
echo "[$(date)] Starting batched cleanup..."
while true; do
DELETED=$(
$PSQL "$DB" -At -v ON_ERROR_STOP=1 <<EOF
WITH cutoff AS (
SELECT (EXTRACT(EPOCH FROM (NOW() - INTERVAL '${RETENTION_DAYS} days')) * 1000000)::bigint AS ts
),
old_packets AS (
SELECT id
FROM packet, cutoff
WHERE import_time_us IS NOT NULL
AND import_time_us < cutoff.ts
ORDER BY id
LIMIT ${BATCH_SIZE}
),
ps_del AS (
DELETE FROM packet_seen
WHERE packet_id IN (SELECT id FROM old_packets)
RETURNING 1
),
tr_del AS (
DELETE FROM traceroute
WHERE packet_id IN (SELECT id FROM old_packets)
RETURNING 1
),
p_del AS (
DELETE FROM packet
WHERE id IN (SELECT id FROM old_packets)
RETURNING 1
)
SELECT COUNT(*) FROM p_del;
EOF
)
if [[ "$DELETED" -eq 0 ]]; then
break
fi
sleep 0.1
done
echo "[$(date)] Packet cleanup complete"
echo "[$(date)] Cleaning old nodes..."
$PSQL "$DB" -v ON_ERROR_STOP=1 <<EOF
DELETE FROM node
WHERE last_seen_us IS NOT NULL
AND last_seen_us < (
EXTRACT(EPOCH FROM (NOW() - INTERVAL '${RETENTION_DAYS} days')) * 1000000
);
EOF
echo "[$(date)] Node cleanup complete"
$PSQL "$DB" -c "VACUUM (ANALYZE) packet_seen;"
$PSQL "$DB" -c "VACUUM (ANALYZE) traceroute;"
$PSQL "$DB" -c "VACUUM (ANALYZE) packet;"
$PSQL "$DB" -c "VACUUM (ANALYZE) node;"
echo "[$(date)] Cleanup finished"
```
- Schedule running the script on a regular basis.
- In this example it runs every night at 2:00am.
Open scheduler:
```bash
sudo crontab -e
```
Add schedule to the bottom of the file (modify /path/to/file/ to the correct path):
```bash
0 2 * * * /path/to/file/cleanup.sh >> /path/to/file/cleanup.log 2>&1
```
Check the log file to see it the script run at the specific time.
---
## Testing
MeshView includes a test suite using pytest. For detailed testing documentation, see [README-testing.md](README-testing.md).
Quick start:
```bash
./env/bin/pytest tests/test_api_simple.py -v
```
---
## Technical Documentation
For more detailed technical documentation including database migrations, architecture details, and advanced topics, see the [docs/](docs/) directory.

120
alembic.ini Normal file
View File

@@ -0,0 +1,120 @@
# A generic, single database configuration.
[alembic]
# path to migration scripts
# Use forward slashes (/) also on windows to provide an os agnostic path
script_location = alembic
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# Uncomment the line below if you want the files to be prepended with date and time
# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
# for all available tokens
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
# sys.path path, will be prepended to sys.path if present.
# defaults to the current working directory.
prepend_sys_path = .
# timezone to use when rendering the date within the migration file
# as well as the filename.
# If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library.
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
# string value is passed to ZoneInfo()
# leave blank for localtime
# timezone =
# max length of characters to apply to the "slug" field
# truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false
# version location specification; This defaults
# to alembic/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
# The path separator used here should be the separator specified by "version_path_separator" below.
# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions
# version path separator; As mentioned above, this is the character used to split
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
# Valid values for version_path_separator are:
#
# version_path_separator = :
# version_path_separator = ;
# version_path_separator = space
# version_path_separator = newline
#
# Use os.pathsep. Default configuration used for new projects.
version_path_separator = os
# set to 'true' to search source files recursively
# in each "version_locations" directory
# new in Alembic version 1.10
# recursive_version_locations = false
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
# sqlalchemy.url will be set programmatically from meshview config
# sqlalchemy.url = driver://user:pass@localhost/dbname
[post_write_hooks]
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples
# format using "black" - use the console_scripts runner, against the "black" entrypoint
# hooks = black
# black.type = console_scripts
# black.entrypoint = black
# black.options = -l 79 REVISION_SCRIPT_FILENAME
# lint with attempts to fix using "ruff" - use the exec runner, execute a binary
# hooks = ruff
# ruff.type = exec
# ruff.executable = %(here)s/.venv/bin/ruff
# ruff.options = --fix REVISION_SCRIPT_FILENAME
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
qualname =
[logger_sqlalchemy]
level = WARNING
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s %(filename)s:%(lineno)d [pid:%(process)d] %(levelname)s - %(message)s
datefmt = %Y-%m-%d %H:%M:%S

1
alembic/README Normal file
View File

@@ -0,0 +1 @@
Generic single-database configuration.

102
alembic/env.py Normal file
View File

@@ -0,0 +1,102 @@
import asyncio
from logging.config import fileConfig
from sqlalchemy import pool
from sqlalchemy.engine import Connection
from sqlalchemy.ext.asyncio import async_engine_from_config
from alembic import context
# Import models metadata for autogenerate support
from meshview.models import Base
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
# Use disable_existing_loggers=False to preserve app logging configuration
if config.config_file_name is not None:
fileConfig(config.config_file_name, disable_existing_loggers=False)
# Add your model's MetaData object here for 'autogenerate' support
target_metadata = Base.metadata
def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def do_run_migrations(connection: Connection) -> None:
"""Run migrations with the given connection."""
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
async def run_async_migrations() -> None:
"""Run migrations in async mode."""
# Get configuration section
configuration = config.get_section(config.config_ini_section, {})
# If sqlalchemy.url is not set in alembic.ini, try to get it from meshview config
if "sqlalchemy.url" not in configuration:
try:
from meshview.config import CONFIG
configuration["sqlalchemy.url"] = CONFIG["database"]["connection_string"]
except Exception:
# Fallback to a default for initial migration creation
configuration["sqlalchemy.url"] = "sqlite+aiosqlite:///packets.db"
connectable = async_engine_from_config(
configuration,
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
await connectable.dispose()
def run_migrations_online() -> None:
"""Run migrations in 'online' mode with async support."""
try:
# Event loop is already running, schedule and run the coroutine
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor() as pool:
pool.submit(lambda: asyncio.run(run_async_migrations())).result()
except RuntimeError:
# No event loop running, create one
asyncio.run(run_async_migrations())
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()

26
alembic/script.py.mako Normal file
View File

@@ -0,0 +1,26 @@
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
${imports if imports else ""}
# revision identifiers, used by Alembic.
revision: str = ${repr(up_revision)}
down_revision: Union[str, None] = ${repr(down_revision)}
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
def upgrade() -> None:
${upgrades if upgrades else "pass"}
def downgrade() -> None:
${downgrades if downgrades else "pass"}

View File

@@ -0,0 +1,45 @@
"""Add example table
Revision ID: 1717fa5c6545
Revises: c88468b7ab0b
Create Date: 2025-10-26 20:59:04.347066
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = '1717fa5c6545'
down_revision: str | None = 'add_time_us_cols'
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
"""Create example table with sample columns."""
op.create_table(
'example',
sa.Column('id', sa.Integer(), nullable=False, primary_key=True, autoincrement=True),
sa.Column('name', sa.String(length=100), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('value', sa.Float(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=False, server_default='1'),
sa.Column(
'created_at', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')
),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id'),
)
# Create an index on the name column for faster lookups
op.create_index('idx_example_name', 'example', ['name'])
def downgrade() -> None:
"""Remove example table."""
op.drop_index('idx_example_name', table_name='example')
op.drop_table('example')

View File

@@ -0,0 +1,27 @@
"""Add is_mqtt_gateway to node
Revision ID: 23dad03d2e42
Revises: a0c9c13e118f
Create Date: 2026-02-13 00:00:00.000000
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "23dad03d2e42"
down_revision: str | None = "a0c9c13e118f"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
op.add_column("node", sa.Column("is_mqtt_gateway", sa.Boolean(), nullable=True))
def downgrade() -> None:
op.drop_column("node", "is_mqtt_gateway")

View File

@@ -0,0 +1,35 @@
"""Add first_seen_us and last_seen_us to node table
Revision ID: 2b5a61bb2b75
Revises: ac311b3782a1
Create Date: 2025-11-05 15:19:13.446724
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = '2b5a61bb2b75'
down_revision: str | None = 'ac311b3782a1'
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
# Add microsecond epoch timestamp columns for first and last seen times
op.add_column('node', sa.Column('first_seen_us', sa.BigInteger(), nullable=True))
op.add_column('node', sa.Column('last_seen_us', sa.BigInteger(), nullable=True))
op.create_index('idx_node_first_seen_us', 'node', ['first_seen_us'], unique=False)
op.create_index('idx_node_last_seen_us', 'node', ['last_seen_us'], unique=False)
def downgrade() -> None:
# Remove the microsecond epoch timestamp columns and their indexes
op.drop_index('idx_node_last_seen_us', table_name='node')
op.drop_index('idx_node_first_seen_us', table_name='node')
op.drop_column('node', 'last_seen_us')
op.drop_column('node', 'first_seen_us')

View File

@@ -0,0 +1,65 @@
"""Drop import_time columns.
Revision ID: 9f3b1a8d2c4f
Revises: 2b5a61bb2b75
Create Date: 2026-01-09 09:55:00.000000
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "9f3b1a8d2c4f"
down_revision: str | None = "2b5a61bb2b75"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
conn = op.get_bind()
inspector = sa.inspect(conn)
packet_indexes = {idx["name"] for idx in inspector.get_indexes("packet")}
packet_columns = {col["name"] for col in inspector.get_columns("packet")}
with op.batch_alter_table("packet", schema=None) as batch_op:
if "idx_packet_import_time" in packet_indexes:
batch_op.drop_index("idx_packet_import_time")
if "idx_packet_from_node_time" in packet_indexes:
batch_op.drop_index("idx_packet_from_node_time")
if "import_time" in packet_columns:
batch_op.drop_column("import_time")
packet_seen_columns = {col["name"] for col in inspector.get_columns("packet_seen")}
with op.batch_alter_table("packet_seen", schema=None) as batch_op:
if "import_time" in packet_seen_columns:
batch_op.drop_column("import_time")
traceroute_indexes = {idx["name"] for idx in inspector.get_indexes("traceroute")}
traceroute_columns = {col["name"] for col in inspector.get_columns("traceroute")}
with op.batch_alter_table("traceroute", schema=None) as batch_op:
if "idx_traceroute_import_time" in traceroute_indexes:
batch_op.drop_index("idx_traceroute_import_time")
if "import_time" in traceroute_columns:
batch_op.drop_column("import_time")
def downgrade() -> None:
with op.batch_alter_table("traceroute", schema=None) as batch_op:
batch_op.add_column(sa.Column("import_time", sa.DateTime(), nullable=True))
batch_op.create_index("idx_traceroute_import_time", ["import_time"], unique=False)
with op.batch_alter_table("packet_seen", schema=None) as batch_op:
batch_op.add_column(sa.Column("import_time", sa.DateTime(), nullable=True))
with op.batch_alter_table("packet", schema=None) as batch_op:
batch_op.add_column(sa.Column("import_time", sa.DateTime(), nullable=True))
batch_op.create_index("idx_packet_import_time", [sa.text("import_time DESC")], unique=False)
batch_op.create_index(
"idx_packet_from_node_time",
["from_node_id", sa.text("import_time DESC")],
unique=False,
)

View File

@@ -0,0 +1,43 @@
"""Add node_public_key table
Revision ID: a0c9c13e118f
Revises: d4d7b0c2e1a4
Create Date: 2026-02-06 00:00:00.000000
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "a0c9c13e118f"
down_revision: str | None = "d4d7b0c2e1a4"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
op.create_table(
"node_public_key",
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
sa.Column("node_id", sa.BigInteger(), nullable=False),
sa.Column("public_key", sa.String(), nullable=False),
sa.Column("first_seen_us", sa.BigInteger(), nullable=True),
sa.Column("last_seen_us", sa.BigInteger(), nullable=True),
)
op.create_index("idx_node_public_key_node_id", "node_public_key", ["node_id"], unique=False)
op.create_index(
"idx_node_public_key_public_key",
"node_public_key",
["public_key"],
unique=False,
)
def downgrade() -> None:
op.drop_index("idx_node_public_key_public_key", table_name="node_public_key")
op.drop_index("idx_node_public_key_node_id", table_name="node_public_key")
op.drop_table("node_public_key")

View File

@@ -0,0 +1,31 @@
"""add route_return to traceroute
Revision ID: ac311b3782a1
Revises: 1717fa5c6545
Create Date: 2025-11-04 20:28:33.174137
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = 'ac311b3782a1'
down_revision: str | None = '1717fa5c6545'
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
# Add route_return column to traceroute table
with op.batch_alter_table('traceroute', schema=None) as batch_op:
batch_op.add_column(sa.Column('route_return', sa.LargeBinary(), nullable=True))
def downgrade() -> None:
# Remove route_return column from traceroute table
with op.batch_alter_table('traceroute', schema=None) as batch_op:
batch_op.drop_column('route_return')

View File

@@ -0,0 +1,74 @@
"""add import_time_us columns
Revision ID: add_time_us_cols
Revises: c88468b7ab0b
Create Date: 2025-11-03 14:10:00.000000
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = 'add_time_us_cols'
down_revision: str | None = 'c88468b7ab0b'
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
# Check if columns already exist, add them if they don't
conn = op.get_bind()
inspector = sa.inspect(conn)
# Add import_time_us to packet table
packet_columns = [col['name'] for col in inspector.get_columns('packet')]
if 'import_time_us' not in packet_columns:
with op.batch_alter_table('packet', schema=None) as batch_op:
batch_op.add_column(sa.Column('import_time_us', sa.BigInteger(), nullable=True))
op.create_index(
'idx_packet_import_time_us', 'packet', [sa.text('import_time_us DESC')], unique=False
)
op.create_index(
'idx_packet_from_node_time_us',
'packet',
['from_node_id', sa.text('import_time_us DESC')],
unique=False,
)
# Add import_time_us to packet_seen table
packet_seen_columns = [col['name'] for col in inspector.get_columns('packet_seen')]
if 'import_time_us' not in packet_seen_columns:
with op.batch_alter_table('packet_seen', schema=None) as batch_op:
batch_op.add_column(sa.Column('import_time_us', sa.BigInteger(), nullable=True))
op.create_index(
'idx_packet_seen_import_time_us', 'packet_seen', ['import_time_us'], unique=False
)
# Add import_time_us to traceroute table
traceroute_columns = [col['name'] for col in inspector.get_columns('traceroute')]
if 'import_time_us' not in traceroute_columns:
with op.batch_alter_table('traceroute', schema=None) as batch_op:
batch_op.add_column(sa.Column('import_time_us', sa.BigInteger(), nullable=True))
op.create_index(
'idx_traceroute_import_time_us', 'traceroute', ['import_time_us'], unique=False
)
def downgrade() -> None:
# Drop indexes and columns
op.drop_index('idx_traceroute_import_time_us', table_name='traceroute')
with op.batch_alter_table('traceroute', schema=None) as batch_op:
batch_op.drop_column('import_time_us')
op.drop_index('idx_packet_seen_import_time_us', table_name='packet_seen')
with op.batch_alter_table('packet_seen', schema=None) as batch_op:
batch_op.drop_column('import_time_us')
op.drop_index('idx_packet_from_node_time_us', table_name='packet')
op.drop_index('idx_packet_import_time_us', table_name='packet')
with op.batch_alter_table('packet', schema=None) as batch_op:
batch_op.drop_column('import_time_us')

View File

@@ -0,0 +1,94 @@
"""Add last_update_us to node and migrate data.
Revision ID: b7c3c2e3a1f0
Revises: 9f3b1a8d2c4f
Create Date: 2026-01-12 10:12:00.000000
"""
from collections.abc import Sequence
from datetime import UTC, datetime
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "b7c3c2e3a1f0"
down_revision: str | None = "9f3b1a8d2c4f"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def _parse_datetime(value):
if value is None:
return None
if isinstance(value, datetime):
dt = value
elif isinstance(value, str):
text = value.replace("Z", "+00:00")
try:
dt = datetime.fromisoformat(text)
except ValueError:
return None
else:
return None
if dt.tzinfo is None:
return dt.replace(tzinfo=UTC)
return dt.astimezone(UTC)
def upgrade() -> None:
conn = op.get_bind()
op.add_column("node", sa.Column("last_update_us", sa.BigInteger(), nullable=True))
op.create_index("idx_node_last_update_us", "node", ["last_update_us"], unique=False)
node = sa.table(
"node",
sa.column("id", sa.String()),
sa.column("last_update", sa.DateTime()),
sa.column("last_update_us", sa.BigInteger()),
)
rows = conn.execute(sa.select(node.c.id, node.c.last_update)).all()
for node_id, last_update in rows:
dt = _parse_datetime(last_update)
if dt is None:
continue
last_update_us = int(dt.timestamp() * 1_000_000)
conn.execute(
sa.update(node).where(node.c.id == node_id).values(last_update_us=last_update_us)
)
if conn.dialect.name == "sqlite":
with op.batch_alter_table("node", schema=None) as batch_op:
batch_op.drop_column("last_update")
else:
op.drop_column("node", "last_update")
def downgrade() -> None:
conn = op.get_bind()
op.add_column("node", sa.Column("last_update", sa.DateTime(), nullable=True))
node = sa.table(
"node",
sa.column("id", sa.String()),
sa.column("last_update", sa.DateTime()),
sa.column("last_update_us", sa.BigInteger()),
)
rows = conn.execute(sa.select(node.c.id, node.c.last_update_us)).all()
for node_id, last_update_us in rows:
if last_update_us is None:
continue
dt = datetime.fromtimestamp(last_update_us / 1_000_000, tz=UTC).replace(tzinfo=None)
conn.execute(sa.update(node).where(node.c.id == node_id).values(last_update=dt))
if conn.dialect.name == "sqlite":
with op.batch_alter_table("node", schema=None) as batch_op:
batch_op.drop_index("idx_node_last_update_us")
batch_op.drop_column("last_update_us")
else:
op.drop_index("idx_node_last_update_us", table_name="node")
op.drop_column("node", "last_update_us")

View File

@@ -0,0 +1,160 @@
"""Initial migration
Revision ID: c88468b7ab0b
Revises:
Create Date: 2025-10-26 20:56:50.285200
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = 'c88468b7ab0b'
down_revision: str | None = None
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
# Get connection and inspector to check what exists
conn = op.get_bind()
inspector = sa.inspect(conn)
existing_tables = inspector.get_table_names()
# Create node table if it doesn't exist
if 'node' not in existing_tables:
op.create_table(
'node',
sa.Column('id', sa.String(), nullable=False),
sa.Column('node_id', sa.BigInteger(), nullable=True),
sa.Column('long_name', sa.String(), nullable=True),
sa.Column('short_name', sa.String(), nullable=True),
sa.Column('hw_model', sa.String(), nullable=True),
sa.Column('firmware', sa.String(), nullable=True),
sa.Column('role', sa.String(), nullable=True),
sa.Column('last_lat', sa.BigInteger(), nullable=True),
sa.Column('last_long', sa.BigInteger(), nullable=True),
sa.Column('channel', sa.String(), nullable=True),
sa.Column('last_update', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('node_id'),
)
op.create_index('idx_node_node_id', 'node', ['node_id'], unique=False)
# Create packet table if it doesn't exist
if 'packet' not in existing_tables:
op.create_table(
'packet',
sa.Column('id', sa.BigInteger(), nullable=False),
sa.Column('portnum', sa.Integer(), nullable=True),
sa.Column('from_node_id', sa.BigInteger(), nullable=True),
sa.Column('to_node_id', sa.BigInteger(), nullable=True),
sa.Column('payload', sa.LargeBinary(), nullable=True),
sa.Column('import_time', sa.DateTime(), nullable=True),
sa.Column('import_time_us', sa.BigInteger(), nullable=True),
sa.Column('channel', sa.String(), nullable=True),
sa.PrimaryKeyConstraint('id'),
)
op.create_index('idx_packet_from_node_id', 'packet', ['from_node_id'], unique=False)
op.create_index('idx_packet_to_node_id', 'packet', ['to_node_id'], unique=False)
op.create_index(
'idx_packet_import_time', 'packet', [sa.text('import_time DESC')], unique=False
)
op.create_index(
'idx_packet_import_time_us', 'packet', [sa.text('import_time_us DESC')], unique=False
)
op.create_index(
'idx_packet_from_node_time',
'packet',
['from_node_id', sa.text('import_time DESC')],
unique=False,
)
op.create_index(
'idx_packet_from_node_time_us',
'packet',
['from_node_id', sa.text('import_time_us DESC')],
unique=False,
)
# Create packet_seen table if it doesn't exist
if 'packet_seen' not in existing_tables:
op.create_table(
'packet_seen',
sa.Column('packet_id', sa.BigInteger(), nullable=False),
sa.Column('node_id', sa.BigInteger(), nullable=False),
sa.Column('rx_time', sa.BigInteger(), nullable=False),
sa.Column('hop_limit', sa.Integer(), nullable=True),
sa.Column('hop_start', sa.Integer(), nullable=True),
sa.Column('channel', sa.String(), nullable=True),
sa.Column('rx_snr', sa.Float(), nullable=True),
sa.Column('rx_rssi', sa.Integer(), nullable=True),
sa.Column('topic', sa.String(), nullable=True),
sa.Column('import_time', sa.DateTime(), nullable=True),
sa.Column('import_time_us', sa.BigInteger(), nullable=True),
sa.ForeignKeyConstraint(
['packet_id'],
['packet.id'],
),
sa.PrimaryKeyConstraint('packet_id', 'node_id', 'rx_time'),
)
op.create_index('idx_packet_seen_node_id', 'packet_seen', ['node_id'], unique=False)
op.create_index('idx_packet_seen_packet_id', 'packet_seen', ['packet_id'], unique=False)
op.create_index(
'idx_packet_seen_import_time_us', 'packet_seen', ['import_time_us'], unique=False
)
# Create traceroute table if it doesn't exist
if 'traceroute' not in existing_tables:
op.create_table(
'traceroute',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('packet_id', sa.BigInteger(), nullable=True),
sa.Column('gateway_node_id', sa.BigInteger(), nullable=True),
sa.Column('done', sa.Boolean(), nullable=True),
sa.Column('route', sa.LargeBinary(), nullable=True),
sa.Column('import_time', sa.DateTime(), nullable=True),
sa.Column('import_time_us', sa.BigInteger(), nullable=True),
sa.ForeignKeyConstraint(
['packet_id'],
['packet.id'],
),
sa.PrimaryKeyConstraint('id'),
)
op.create_index('idx_traceroute_import_time', 'traceroute', ['import_time'], unique=False)
op.create_index(
'idx_traceroute_import_time_us', 'traceroute', ['import_time_us'], unique=False
)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
# Drop traceroute table and indexes
op.drop_index('idx_traceroute_import_time_us', table_name='traceroute')
op.drop_index('idx_traceroute_import_time', table_name='traceroute')
op.drop_table('traceroute')
# Drop packet_seen table and indexes
op.drop_index('idx_packet_seen_import_time_us', table_name='packet_seen')
op.drop_index('idx_packet_seen_packet_id', table_name='packet_seen')
op.drop_index('idx_packet_seen_node_id', table_name='packet_seen')
op.drop_table('packet_seen')
# Drop packet table and indexes
op.drop_index('idx_packet_from_node_time_us', table_name='packet')
op.drop_index('idx_packet_from_node_time', table_name='packet')
op.drop_index('idx_packet_import_time_us', table_name='packet')
op.drop_index('idx_packet_import_time', table_name='packet')
op.drop_index('idx_packet_to_node_id', table_name='packet')
op.drop_index('idx_packet_from_node_id', table_name='packet')
op.drop_table('packet')
# Drop node table and indexes
op.drop_index('idx_node_node_id', table_name='node')
op.drop_table('node')
# ### end Alembic commands ###

View File

@@ -0,0 +1,34 @@
"""Drop last_update_us from node.
Revision ID: d4d7b0c2e1a4
Revises: b7c3c2e3a1f0
Create Date: 2026-01-12 10:20:00.000000
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "d4d7b0c2e1a4"
down_revision: str | None = "b7c3c2e3a1f0"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
conn = op.get_bind()
if conn.dialect.name == "sqlite":
with op.batch_alter_table("node", schema=None) as batch_op:
batch_op.drop_index("idx_node_last_update_us")
batch_op.drop_column("last_update_us")
else:
op.drop_index("idx_node_last_update_us", table_name="node")
op.drop_column("node", "last_update_us")
def downgrade() -> None:
op.add_column("node", sa.Column("last_update_us", sa.BigInteger(), nullable=True))
op.create_index("idx_node_last_update_us", "node", ["last_update_us"], unique=False)

57
container/build-container.sh Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/sh
#
# build-container.sh
#
# Script to build MeshView container images
set -e
# Default values
IMAGE_NAME="meshview"
TAG="latest"
CONTAINERFILE="Containerfile"
# Parse arguments
while [ $# -gt 0 ]; do
case "$1" in
--tag|-t)
TAG="$2"
shift 2
;;
--name|-n)
IMAGE_NAME="$2"
shift 2
;;
--file|-f)
CONTAINERFILE="$2"
shift 2
;;
--help|-h)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -t, --tag TAG Tag for the image (default: latest)"
echo " -n, --name NAME Image name (default: meshview)"
echo " -f, --file FILE Containerfile path (default: Containerfile)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
echo "Building MeshView container image..."
echo " Image: ${IMAGE_NAME}:${TAG}"
echo " Containerfile: ${CONTAINERFILE}"
echo ""
# Build the container
docker build -f "${CONTAINERFILE}" -t "${IMAGE_NAME}:${TAG}" .
echo ""
echo "Build complete!"
echo "Run with: docker run --rm -p 8081:8081 ${IMAGE_NAME}:${TAG}"

90
container/config.ini Normal file
View File

@@ -0,0 +1,90 @@
# -------------------------
# Server Configuration
# -------------------------
[server]
# The address to bind the server to. Use * to listen on all interfaces.
bind = 0.0.0.0
# Port to run the web server on.
port = 8081
# Path to TLS certificate (leave blank to disable HTTPS).
tls_cert =
# Path for the ACME challenge if using Let's Encrypt.
acme_challenge =
# -------------------------
# Site Appearance & Behavior
# -------------------------
[site]
domain =
language = en
title = Bay Area Mesh
message = Real time data from around the bay area and beyond.
starting = /chat
nodes = True
conversations = True
everything = True
graphs = True
stats = True
net = True
map = True
top = True
map_top_left_lat = 39
map_top_left_lon = -123
map_bottom_right_lat = 36
map_bottom_right_lon = -121
map_interval = 3
firehose_interal = 3
weekly_net_message = Weekly Mesh check-in. We will keep it open on every Wednesday from 5:00pm for checkins. The message format should be (LONG NAME) - (CITY YOU ARE IN) #BayMeshNet.
net_tag = #BayMeshNet
# -------------------------
# MQTT Broker Configuration
# -------------------------
[mqtt]
server = mqtt.meshtastic.org
topics = ["msh/US/bayarea/#", "msh/US/CA/mrymesh/#", "msh/US/CA/sacvalley"]
port = 1883
username = meshdev
password = large4cats
skip_node_ids =
secondary_keys =
# -------------------------
# Database Configuration
# -------------------------
[database]
connection_string = sqlite+aiosqlite:////var/lib/meshview/packets.db
# -------------------------
# Database Cleanup Configuration
# -------------------------
[cleanup]
enabled = False
days_to_keep = 14
hour = 2
minute = 00
vacuum = False
backup_enabled = False
backup_dir = ./backups
backup_hour = 2
backup_minute = 00
# -------------------------
# Logging Configuration
# -------------------------
[logging]
access_log = False
db_cleanup_logfile = /var/log/meshview/dbcleanup.log

37
container/config.patch Normal file
View File

@@ -0,0 +1,37 @@
diff --git a/sample.config.ini b/sample.config.ini
index 0e64980..494685c 100644
--- a/sample.config.ini
+++ b/sample.config.ini
@@ -3,7 +3,7 @@
# -------------------------
[server]
# The address to bind the server to. Use * to listen on all interfaces.
-bind = *
+bind = 0.0.0.0
# Port to run the web server on.
port = 8081
@@ -64,7 +64,7 @@ net_tag = #BayMeshNet
# -------------------------
[mqtt]
# MQTT server hostname or IP.
-server = mqtt.bayme.sh
+server = mqtt.meshtastic.org
# Topics to subscribe to (as JSON-like list, but still a string).
topics = ["msh/US/bayarea/#", "msh/US/CA/mrymesh/#", "msh/US/CA/sacvalley"]
@@ -82,7 +82,7 @@ password = large4cats
# -------------------------
[database]
# SQLAlchemy connection string. This one uses SQLite with asyncio support.
-connection_string = sqlite+aiosqlite:///packets.db
+connection_string = sqlite+aiosqlite:////var/lib/meshview/packets.db
# -------------------------
@@ -110,4 +110,4 @@ vacuum = False
# Set to True to enable, False to disable (default: False)
access_log = False
# Database cleanup logfile
-db_cleanup_logfile = dbcleanup.log
+db_cleanup_logfile = /var/log/meshview/dbcleanup.log

52
create_example_migration.py Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""
Script to create a blank migration for manual editing.
Usage:
./env/bin/python create_example_migration.py
This creates an empty migration file that you can manually edit to add
custom migration logic (data migrations, complex schema changes, etc.)
Unlike create_migration.py which auto-generates from model changes,
this creates a blank template for you to fill in.
"""
import os
import sys
# Add current directory to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from alembic.config import Config
from alembic import command
# Create Alembic config
alembic_cfg = Config("alembic.ini")
# Set database URL from meshview config
try:
from meshview.config import CONFIG
database_url = CONFIG["database"]["connection_string"]
alembic_cfg.set_main_option("sqlalchemy.url", database_url)
print(f"Using database URL from config: {database_url}")
except Exception as e:
print(f"Warning: Could not load meshview config: {e}")
print("Using default database URL")
alembic_cfg.set_main_option("sqlalchemy.url", "sqlite+aiosqlite:///packets.db")
# Generate blank migration
try:
print("Creating blank migration for manual editing...")
command.revision(alembic_cfg, autogenerate=False, message="Manual migration")
print("✓ Successfully created blank migration!")
print("\nNow edit the generated file in alembic/versions/")
print("Add your custom upgrade() and downgrade() logic")
except Exception as e:
print(f"✗ Error creating migration: {e}")
import traceback
traceback.print_exc()
sys.exit(1)

58
create_migration.py Executable file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""
Helper script to create Alembic migrations from SQLAlchemy model changes.
Usage:
./env/bin/python create_migration.py
This will:
1. Load your current models from meshview/models.py
2. Compare them to the current database schema
3. Auto-generate a migration with the detected changes
4. Save the migration to alembic/versions/
After running this, review the generated migration file before committing!
"""
import os
import sys
# Add current directory to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from alembic.config import Config
from alembic import command
# Create Alembic config
alembic_cfg = Config("alembic.ini")
# Set database URL from meshview config
try:
from meshview.config import CONFIG
database_url = CONFIG["database"]["connection_string"]
alembic_cfg.set_main_option("sqlalchemy.url", database_url)
print(f"Using database URL from config: {database_url}")
except Exception as e:
print(f"Warning: Could not load meshview config: {e}")
print("Using default database URL")
alembic_cfg.set_main_option("sqlalchemy.url", "sqlite+aiosqlite:///packets.db")
# Generate migration
try:
print("\nComparing models to current database schema...")
print("Generating migration...\n")
command.revision(alembic_cfg, autogenerate=True, message="Auto-generated migration")
print("\n✓ Successfully created migration!")
print("\nNext steps:")
print("1. Review the generated file in alembic/versions/")
print("2. Edit the migration message/logic if needed")
print("3. Test the migration: ./env/bin/alembic upgrade head")
print("4. Commit the migration file to version control")
except Exception as e:
print(f"\n✗ Error creating migration: {e}")
import traceback
traceback.print_exc()
sys.exit(1)

361
docs/ALEMBIC_SETUP.md Normal file
View File

@@ -0,0 +1,361 @@
# Alembic Database Migration Setup
This document describes the automatic database migration system implemented for MeshView using Alembic.
## Overview
The system provides automatic database schema migrations with coordination between the writer app (startdb.py) and reader app (web.py):
- **Writer App**: Automatically runs pending migrations on startup
- **Reader App**: Waits for migrations to complete before starting
## Architecture
### Key Components
1. **`meshview/migrations.py`** - Migration management utilities
- `run_migrations()` - Runs pending migrations (writer app)
- `wait_for_migrations()` - Waits for schema to be current (reader app)
- `is_database_up_to_date()` - Checks schema version
- Migration status tracking table
2. **`alembic/`** - Alembic migration directory
- `env.py` - Configured for async SQLAlchemy support
- `versions/` - Migration scripts directory
- `alembic.ini` - Alembic configuration
3. **Modified Apps**:
- `startdb.py` - Writer app that runs migrations before MQTT ingestion
- `meshview/web.py` - Reader app that waits for schema updates
## How It Works - Automatic In-Place Updates
### ✨ Fully Automatic Operation
**No manual migration commands needed!** The database schema updates automatically when you:
1. Deploy new code with migration files
2. Restart the applications
### Writer App (startdb.py) Startup Sequence
1. Initialize database connection
2. Create migration status tracking table
3. Set "migration in progress" flag
4. **🔄 Automatically run any pending Alembic migrations** (synchronously)
- Detects current schema version
- Compares to latest available migration
- Runs all pending migrations in sequence
- Updates database schema in place
5. Clear "migration in progress" flag
6. Start MQTT ingestion and other tasks
### Reader App (web.py) Startup Sequence
1. Initialize database connection
2. **Check database schema version**
3. If not up to date:
- Wait up to 60 seconds (30 retries × 2 seconds)
- Check every 2 seconds for schema updates
- Automatically proceeds once writer completes migrations
4. Once schema is current, start web server
### 🎯 Key Point: Zero Manual Steps
When you deploy new code with migrations:
```bash
# Just start the apps - migrations happen automatically!
./env/bin/python startdb.py # Migrations run here automatically
./env/bin/python main.py # Waits for migrations, then starts
```
**The database updates itself!** No need to run `alembic upgrade` manually.
### Coordination
The apps coordinate using:
- **Alembic version table** (`alembic_version`) - Tracks current schema version
- **Migration status table** (`migration_status`) - Optional flag for "in progress" state
## Creating New Migrations
### Using the helper script:
```bash
./env/bin/python create_migration.py
```
### Manual creation:
```bash
./env/bin/alembic revision --autogenerate -m "Description of changes"
```
This will:
1. Compare current database schema with SQLAlchemy models
2. Generate a migration script in `alembic/versions/`
3. Automatically detect most schema changes
### Manual migration (advanced):
```bash
./env/bin/alembic revision -m "Manual migration"
```
Then edit the generated file to add custom migration logic.
## Running Migrations
### Automatic (Recommended)
Migrations run automatically when the writer app starts:
```bash
./env/bin/python startdb.py
```
### Manual
To run migrations manually:
```bash
./env/bin/alembic upgrade head
```
To downgrade:
```bash
./env/bin/alembic downgrade -1 # Go back one version
./env/bin/alembic downgrade base # Go back to beginning
```
## Checking Migration Status
Check current database version:
```bash
./env/bin/alembic current
```
View migration history:
```bash
./env/bin/alembic history
```
## Benefits
1. **Zero Manual Intervention**: Migrations run automatically on startup
2. **Safe Coordination**: Reader won't connect to incompatible schema
3. **Version Control**: All schema changes tracked in git
4. **Rollback Capability**: Can downgrade if needed
5. **Auto-generation**: Most migrations created automatically from model changes
## Migration Workflow
### Development Process
1. **Modify SQLAlchemy models** in `meshview/models.py`
2. **Create migration**:
```bash
./env/bin/python create_migration.py
```
3. **Review generated migration** in `alembic/versions/`
4. **Test migration**:
- Stop all apps
- Start writer app (migrations run automatically)
- Start reader app (waits for schema to be current)
5. **Commit migration** to version control
### Production Deployment
1. **Deploy new code** with migration scripts
2. **Start writer app** - Migrations run automatically
3. **Start reader app** - Waits for migrations, then starts
4. **Monitor logs** for migration success
## Troubleshooting
### Migration fails
Check logs in writer app for error details. To manually fix:
```bash
./env/bin/alembic current # Check current version
./env/bin/alembic history # View available versions
./env/bin/alembic upgrade head # Try manual upgrade
```
### Reader app won't start (timeout)
Check if writer app is running and has completed migrations:
```bash
./env/bin/alembic current
```
### Reset to clean state
⚠️ **Warning: This will lose all data**
```bash
rm packets.db # Or your database file
./env/bin/alembic upgrade head # Create fresh schema
```
## File Structure
```
meshview/
├── alembic.ini # Alembic configuration
├── alembic/
│ ├── env.py # Async-enabled migration runner
│ ├── script.py.mako # Migration template
│ └── versions/ # Migration scripts
│ └── c88468b7ab0b_initial_migration.py
├── meshview/
│ ├── models.py # SQLAlchemy models (source of truth)
│ ├── migrations.py # Migration utilities
│ ├── mqtt_database.py # Writer database connection
│ └── database.py # Reader database connection
├── startdb.py # Writer app (runs migrations)
├── main.py # Entry point for reader app
└── create_migration.py # Helper script for creating migrations
```
## Configuration
Database URL is read from `config.ini`:
```ini
[database]
connection_string = sqlite+aiosqlite:///packets.db
```
Alembic automatically uses this configuration through `meshview/migrations.py`.
## Important Notes
1. **Always test migrations** in development before deploying to production
2. **Backup database** before running migrations in production
3. **Check for data loss** - Some migrations may require data migration logic
4. **Coordinate deployments** - Start writer before readers in multi-instance setups
5. **Monitor logs** during first startup after deployment
## Example Migrations
### Example 1: Generated Initial Migration
Here's what an auto-generated migration looks like (from comparing models to database):
```python
"""Initial migration
Revision ID: c88468b7ab0b
Revises:
Create Date: 2025-01-26 20:56:50.123456
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers
revision = 'c88468b7ab0b'
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
# Upgrade operations
op.create_table('node',
sa.Column('id', sa.String(), nullable=False),
sa.Column('node_id', sa.BigInteger(), nullable=True),
# ... more columns
sa.PrimaryKeyConstraint('id')
)
def downgrade() -> None:
# Downgrade operations
op.drop_table('node')
```
### Example 2: Manual Migration Adding a New Table
We've included an example migration (`1717fa5c6545_add_example_table.py`) that demonstrates how to manually create a new table:
```python
"""Add example table
Revision ID: 1717fa5c6545
Revises: c88468b7ab0b
Create Date: 2025-10-26 20:59:04.347066
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
def upgrade() -> None:
"""Create example table with sample columns."""
op.create_table(
'example',
sa.Column('id', sa.Integer(), nullable=False, primary_key=True, autoincrement=True),
sa.Column('name', sa.String(length=100), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('value', sa.Float(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=False, server_default='1'),
sa.Column('created_at', sa.DateTime(), nullable=False,
server_default=sa.text('CURRENT_TIMESTAMP')),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
# Create an index on the name column for faster lookups
op.create_index('idx_example_name', 'example', ['name'])
def downgrade() -> None:
"""Remove example table."""
op.drop_index('idx_example_name', table_name='example')
op.drop_table('example')
```
**Key features demonstrated:**
- Various column types (Integer, String, Text, Float, Boolean, DateTime)
- Primary key with autoincrement
- Nullable and non-nullable columns
- Server defaults (for timestamps and booleans)
- Creating indexes
- Proper downgrade that reverses all changes
**To test this migration:**
```bash
# Apply the migration
./env/bin/alembic upgrade head
# Check it was applied
./env/bin/alembic current
# Verify table was created
sqlite3 packetsPL.db "SELECT sql FROM sqlite_master WHERE type='table' AND name='example';"
# Roll back the migration
./env/bin/alembic downgrade -1
# Verify table was removed
sqlite3 packetsPL.db "SELECT name FROM sqlite_master WHERE type='table' AND name='example';"
```
**To remove this example migration** (after testing):
```bash
# First make sure you're not on this revision
./env/bin/alembic downgrade c88468b7ab0b
# Then delete the migration file
rm alembic/versions/1717fa5c6545_add_example_table.py
```
## References
- [Alembic Documentation](https://alembic.sqlalchemy.org/)
- [SQLAlchemy Documentation](https://docs.sqlalchemy.org/)
- [Async SQLAlchemy](https://docs.sqlalchemy.org/en/20/orm/extensions/asyncio.html)

392
docs/API_Documentation.md Normal file
View File

@@ -0,0 +1,392 @@
# API Documentation
Base URL: `http(s)://<host>`
All endpoints return JSON. Timestamps are either ISO 8601 strings or `*_us` values in
microseconds since epoch.
## 1. Nodes API
### GET `/api/nodes`
Returns a list of nodes, with optional filtering.
Query Parameters
- `node_id` (optional, int): Exact node ID.
- `role` (optional, string): Node role.
- `channel` (optional, string): Channel name.
- `hw_model` (optional, string): Hardware model.
- `days_active` (optional, int): Nodes seen within the last N days.
Response Example
```json
{
"nodes": [
{
"id": 42,
"node_id": 1234,
"long_name": "Alice",
"short_name": "A",
"hw_model": "T-Beam",
"firmware": "1.2.3",
"role": "client",
"last_lat": 377749000,
"last_long": -1224194000,
"channel": "main",
"last_seen_us": 1736370123456789
}
]
}
```
---
## 2. Packets API
### GET `/api/packets`
Returns packets with optional filters.
Query Parameters
- `packet_id` (optional, int): Return exactly one packet (overrides other filters).
- `limit` (optional, int): Max packets to return, clamped 1-1000. Default: `50`.
- `since` (optional, int): Only packets imported after this microsecond timestamp.
- `portnum` (optional, int): Filter by port number.
- `contains` (optional, string): Payload substring filter.
- `from_node_id` (optional, int): Filter by sender node ID.
- `to_node_id` (optional, int): Filter by recipient node ID.
- `node_id` (optional, int): Legacy filter matching either from or to node ID.
Response Example
```json
{
"packets": [
{
"id": 123,
"import_time_us": 1736370123456789,
"channel": "main",
"from_node_id": 5678,
"to_node_id": 91011,
"portnum": 1,
"long_name": "Alice",
"payload": "Hello, Bob!",
"to_long_name": "Bob",
"reply_id": 122
}
],
"latest_import_time": 1736370123456789
}
```
Notes
- For `portnum=1` (text messages), packets are filtered to remove sequence-only payloads.
- `latest_import_time` is returned when available for incremental polling (microseconds).
---
## 3. Channels API
### GET `/api/channels`
Returns channels seen in a time period.
Query Parameters
- `period_type` (optional, string): `hour` or `day`. Default: `hour`.
- `length` (optional, int): Number of periods to look back. Default: `24`.
Response Example
```json
{
"channels": ["LongFast", "MediumFast", "ShortFast"]
}
```
---
## 4. Stats API
### GET `/api/stats`
Returns packet statistics aggregated by time periods, with optional filtering.
Query Parameters
- `period_type` (optional, string): `hour` or `day`. Default: `hour`.
- `length` (optional, int): Number of periods to include. Default: `24`.
- `channel` (optional, string): Filter by channel (case-insensitive).
- `portnum` (optional, int): Filter by port number.
- `to_node` (optional, int): Filter by destination node ID.
- `from_node` (optional, int): Filter by source node ID.
- `node` (optional, int): If provided, return combined `sent` and `seen` totals for that node.
Response Example (series)
```json
{
"period_type": "hour",
"length": 24,
"channel": "LongFast",
"portnum": 1,
"to_node": 12345678,
"from_node": 87654321,
"data": [
{ "period": "2025-08-08 14:00", "count": 10 },
{ "period": "2025-08-08 15:00", "count": 7 }
]
}
```
Response Example (`node` totals)
```json
{
"node_id": 12345678,
"period_type": "hour",
"length": 24,
"sent": 42,
"seen": 58
}
```
---
### GET `/api/stats/count`
Returns total packet counts, optionally filtered.
Query Parameters
- `packet_id` (optional, int): Filter packet_seen by packet ID.
- `period_type` (optional, string): `hour` or `day`.
- `length` (optional, int): Number of periods to include.
- `channel` (optional, string): Filter by channel.
- `from_node` (optional, int): Filter by source node ID.
- `to_node` (optional, int): Filter by destination node ID.
Response Example
```json
{
"total_packets": 12345,
"total_seen": 67890
}
```
---
### GET `/api/stats/top`
Returns nodes sorted by packets seen, with pagination.
Query Parameters
- `period_type` (optional, string): `hour` or `day`. Default: `day`.
- `length` (optional, int): Number of periods to include. Default: `1`.
- `channel` (optional, string): Filter by channel.
- `limit` (optional, int): Max nodes to return. Default: `20`, max `100`.
- `offset` (optional, int): Pagination offset. Default: `0`.
Response Example
```json
{
"total": 250,
"limit": 20,
"offset": 0,
"nodes": [
{
"node_id": 1234,
"long_name": "Alice",
"short_name": "A",
"channel": "main",
"sent": 100,
"seen": 240,
"avg": 2.4
}
]
}
```
---
## 5. Edges API
### GET `/api/edges`
Returns network edges (connections between nodes) based on traceroutes and neighbor info.
Traceroute edges are collected over the last 12 hours. Neighbor edges are based on
port 71 packets.
Query Parameters
- `type` (optional, string): `traceroute` or `neighbor`. If omitted, returns both.
- `node_id` (optional, int): Filter edges to only those touching a node.
Response Example
```json
{
"edges": [
{ "from": 12345678, "to": 87654321, "type": "traceroute" },
{ "from": 11111111, "to": 22222222, "type": "neighbor" }
]
}
```
---
## 6. Config API
### GET `/api/config`
Returns a safe subset of server configuration.
Response Example
```json
{
"site": {
"domain": "example.com",
"language": "en",
"title": "Meshview",
"message": "",
"starting": "/chat",
"nodes": "true",
"chat": "true",
"everything": "true",
"graphs": "true",
"stats": "true",
"net": "true",
"map": "true",
"top": "true",
"map_top_left_lat": 39.0,
"map_top_left_lon": -123.0,
"map_bottom_right_lat": 36.0,
"map_bottom_right_lon": -121.0,
"map_interval": 3,
"firehose_interval": 3,
"weekly_net_message": "Weekly Mesh check-in message.",
"net_tag": "#BayMeshNet",
"version": "3.0.0"
},
"mqtt": {
"server": "mqtt.example.com",
"topics": ["msh/region/#"]
},
"cleanup": {
"enabled": "false",
"days_to_keep": "14",
"hour": "2",
"minute": "0",
"vacuum": "false"
}
}
```
---
## 7. Language API
### GET `/api/lang`
Returns translation strings.
Query Parameters
- `lang` (optional, string): Language code (e.g., `en`, `es`). Default from config or `en`.
- `section` (optional, string): Return only one section (e.g., `nodelist`, `firehose`).
Response Example
```json
{
"title": "Meshview",
"search_placeholder": "Search..."
}
```
---
## 8. Packets Seen API
### GET `/api/packets_seen/{packet_id}`
Returns packet_seen entries for a packet.
Path Parameters
- `packet_id` (required, int): Packet ID.
Response Example
```json
{
"seen": [
{
"packet_id": 123,
"node_id": 456,
"rx_time": "2025-07-22T12:45:00",
"hop_limit": 7,
"hop_start": 0,
"channel": "main",
"rx_snr": 5.0,
"rx_rssi": -90,
"topic": "msh/region/#",
"import_time_us": 1736370123456789
}
]
}
```
---
## 9. Traceroute API
### GET `/api/traceroute/{packet_id}`
Returns traceroute details and derived paths for a packet.
Path Parameters
- `packet_id` (required, int): Packet ID.
Response Example
```json
{
"packet": {
"id": 123,
"from": 111,
"to": 222,
"channel": "main"
},
"traceroute_packets": [
{
"index": 0,
"gateway_node_id": 333,
"done": true,
"forward_hops": [111, 444, 222],
"reverse_hops": [222, 444, 111]
}
],
"unique_forward_paths": [
{ "path": [111, 444, 222], "count": 2 }
],
"unique_reverse_paths": [
[222, 444, 111]
],
"winning_paths": [
[111, 444, 222]
]
}
```
---
## 10. Health API
### GET `/health`
Returns service health and database status.
Response Example
```json
{
"status": "healthy",
"timestamp": "2025-07-22T12:45:00+00:00",
"version": "3.0.3",
"git_revision": "abc1234",
"database": "connected",
"database_size": "12.34 MB",
"database_size_bytes": 12939444
}
```
---
## 11. Version API
### GET `/version`
Returns version metadata.
Response Example
```json
{
"version": "3.0.3",
"release_date": "2026-1-15",
"git_revision": "abc1234",
"git_revision_short": "abc1234"
}
```

37
docs/COVERAGE.md Normal file
View File

@@ -0,0 +1,37 @@
# Coverage
## Predicted coverage
Meshview can display a predicted coverage boundary for a node. This is a **model**
estimate, not a guarantee of real-world performance.
### How it works
The coverage boundary is computed using the Longley-Rice / ITM **area mode**
propagation model. Area mode estimates average path loss over generic terrain
and does not use a terrain profile. This means it captures general distance
effects, but **does not** account for terrain shadows, buildings, or foliage.
### What you are seeing
The UI draws a **perimeter** (not a heatmap) that represents the furthest
distance where predicted signal strength is above a threshold (default
`-120 dBm`). The model is run radially from the node in multiple directions,
and the last point above the threshold forms the outline.
### Key parameters
- **Frequency**: default `907 MHz`
- **Transmit power**: default `20 dBm`
- **Antenna heights**: default `5 m` (TX) and `1.5 m` (RX)
- **Reliability**: default `0.5` (median)
- **Terrain irregularity**: default `90 m` (average terrain)
### Limitations
- No terrain or building data is used (area mode only).
- Results are sensitive to power, height, and threshold.
- Environmental factors can cause large real-world deviations.

View File

@@ -0,0 +1,146 @@
# Database Changes With Alembic
This guide explains how to make database schema changes in MeshView using Alembic migrations.
## Overview
When you need to add, modify, or remove columns from database tables, you must:
1. Update the SQLAlchemy model
2. Create an Alembic migration
3. Let the system automatically apply the migration
## Step-by-Step Process
### 1. Update the Model
Edit `meshview/models.py` to add/modify the column in the appropriate model class:
```python
class Traceroute(Base):
__tablename__ = "traceroute"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
# ... existing columns ...
route_return: Mapped[bytes] = mapped_column(nullable=True) # New column
```
### 2. Create an Alembic Migration
Generate a new migration file with a descriptive message:
```bash
./env/bin/alembic revision -m "add route_return to traceroute"
```
This creates a new file in `alembic/versions/` with a unique revision ID.
### 3. Fill in the Migration
Edit the generated migration file to implement the actual database changes:
```python
def upgrade() -> None:
# Add route_return column to traceroute table
with op.batch_alter_table('traceroute', schema=None) as batch_op:
batch_op.add_column(sa.Column('route_return', sa.LargeBinary(), nullable=True))
def downgrade() -> None:
# Remove route_return column from traceroute table
with op.batch_alter_table('traceroute', schema=None) as batch_op:
batch_op.drop_column('route_return')
```
### 4. Migration Runs Automatically
When you restart the application with `mvrun.py`:
1. The writer process (`startdb.py`) starts up
2. It checks if the database schema is up to date
3. If new migrations are pending, it runs them automatically
4. The reader process (web server) waits for migrations to complete before starting
**No manual migration command is needed** - the application handles this automatically on startup.
### 5. Commit Both Files
Add both files to git:
```bash
git add meshview/models.py
git add alembic/versions/ac311b3782a1_add_route_return_to_traceroute.py
git commit -m "Add route_return column to traceroute table"
```
## Important Notes
### SQLite Compatibility
Always use `batch_alter_table` for SQLite compatibility:
```python
with op.batch_alter_table('table_name', schema=None) as batch_op:
batch_op.add_column(...)
```
SQLite has limited ALTER TABLE support, and `batch_alter_table` works around these limitations.
### Migration Process
- **Writer process** (`startdb.py`): Runs migrations on startup
- **Reader process** (web server in `main.py`): Waits for migrations to complete
- Migrations are checked and applied every time the application starts
- The system uses a migration status table to coordinate between processes
### Common Column Types
```python
# Integer
column: Mapped[int] = mapped_column(BigInteger, nullable=True)
# String
column: Mapped[str] = mapped_column(nullable=True)
# Bytes/Binary
column: Mapped[bytes] = mapped_column(nullable=True)
# DateTime
column: Mapped[datetime] = mapped_column(nullable=True)
# Boolean
column: Mapped[bool] = mapped_column(nullable=True)
# Float
column: Mapped[float] = mapped_column(nullable=True)
```
### Migration File Location
Migrations are stored in: `alembic/versions/`
Each migration file includes:
- Revision ID (unique identifier)
- Down revision (previous migration in chain)
- Create date
- `upgrade()` function (applies changes)
- `downgrade()` function (reverts changes)
## Troubleshooting
### Migration Not Running
If migrations don't run automatically:
1. Check that the database is writable
2. Look for errors in the startup logs
3. Verify the migration chain is correct (each migration references the previous one)
### Manual Migration (Not Recommended)
If you need to manually run migrations for debugging:
```bash
./env/bin/alembic upgrade head
```
However, the application normally handles this automatically.

14
docs/README.md Normal file
View File

@@ -0,0 +1,14 @@
# Technical Documentation
This directory contains technical documentation for MeshView that goes beyond initial setup and basic usage.
These documents are intended for developers, contributors, and advanced users who need deeper insight into the system's architecture, database migrations, API endpoints, and internal workings.
## Contents
- [ALEMBIC_SETUP.md](ALEMBIC_SETUP.md) - Database migration setup and management
- [TIMESTAMP_MIGRATION.md](TIMESTAMP_MIGRATION.md) - Details on timestamp schema changes
- [API_Documentation.md](API_Documentation.md) - REST API endpoints and usage
- [CODE_IMPROVEMENTS.md](CODE_IMPROVEMENTS.md) - Suggested code improvements and refactoring ideas
For initial setup and basic usage instructions, please see the main [README.md](../README.md) in the root directory.

193
docs/TIMESTAMP_MIGRATION.md Normal file
View File

@@ -0,0 +1,193 @@
# High-Resolution Timestamp Migration
This document describes the implementation of GitHub issue #55: storing high-resolution timestamps as integers in the database for improved performance and query efficiency.
## Overview
The meshview database now stores timestamps in two formats:
1. **TEXT format** (`import_time`): Human-readable ISO8601 format with microseconds (e.g., `2025-03-12 04:15:56.058038`)
2. **INTEGER format** (`import_time_us`): Microseconds since Unix epoch (1970-01-01 00:00:00 UTC)
The dual format approach provides:
- **Backward compatibility**: Existing `import_time` TEXT columns remain unchanged
- **Performance**: Fast integer comparisons and math operations
- **Precision**: Microsecond resolution for accurate timing
- **Efficiency**: Compact storage and fast indexed lookups
## Database Changes
### New Columns Added
Three tables have new `import_time_us` columns:
1. **packet.import_time_us** (INTEGER)
- Stores when the packet was imported into the database
- Indexed for fast queries
2. **packet_seen.import_time_us** (INTEGER)
- Stores when the packet_seen record was imported
- Indexed for performance
3. **traceroute.import_time_us** (INTEGER)
- Stores when the traceroute was imported
- Indexed for fast lookups
### New Indexes
The following indexes were created for optimal query performance:
```sql
CREATE INDEX idx_packet_import_time_us ON packet(import_time_us DESC);
CREATE INDEX idx_packet_from_node_time_us ON packet(from_node_id, import_time_us DESC);
CREATE INDEX idx_packet_seen_import_time_us ON packet_seen(import_time_us);
CREATE INDEX idx_traceroute_import_time_us ON traceroute(import_time_us);
```
## Migration Process
### For Existing Databases
Run the migration script to add the new columns and populate them from existing data:
```bash
python migrate_add_timestamp_us.py [database_path]
```
If no path is provided, it defaults to `packets.db` in the current directory.
The migration script:
1. Checks if migration is needed (idempotent)
2. Adds `import_time_us` columns to the three tables
3. Populates the new columns from existing `import_time` values
4. Creates indexes for optimal performance
5. Verifies the migration completed successfully
### For New Databases
New databases created with the updated schema will automatically include the `import_time_us` columns. The MQTT store module populates both columns when inserting new records.
## Code Changes
### Models (meshview/models.py)
The ORM models now include the new `import_time_us` fields:
```python
class Packet(Base):
import_time: Mapped[datetime] = mapped_column(nullable=True)
import_time_us: Mapped[int] = mapped_column(BigInteger, nullable=True)
```
### MQTT Store (meshview/mqtt_store.py)
The data ingestion logic now populates both timestamp columns using UTC time:
```python
now = datetime.datetime.now(datetime.timezone.utc)
now_us = int(now.timestamp() * 1_000_000)
# Both columns are populated
import_time=now,
import_time_us=now_us,
```
**Important**: All new timestamps use UTC (Coordinated Universal Time) for consistency across time zones.
## Using the New Timestamps
### Example Queries
**Query packets from the last 7 days:**
```sql
-- Old way (slower)
SELECT * FROM packet
WHERE import_time >= datetime('now', '-7 days');
-- New way (faster)
SELECT * FROM packet
WHERE import_time_us >= (strftime('%s', 'now', '-7 days') * 1000000);
```
**Query packets in a specific time range:**
```sql
SELECT * FROM packet
WHERE import_time_us BETWEEN 1759254380000000 AND 1759254390000000;
```
**Calculate time differences (in microseconds):**
```sql
SELECT
id,
(import_time_us - LAG(import_time_us) OVER (ORDER BY import_time_us)) / 1000000.0 as seconds_since_last
FROM packet
LIMIT 10;
```
### Converting Timestamps
**From datetime to microseconds (UTC):**
```python
import datetime
now = datetime.datetime.now(datetime.timezone.utc)
now_us = int(now.timestamp() * 1_000_000)
```
**From microseconds to datetime:**
```python
import datetime
timestamp_us = 1759254380813451
dt = datetime.datetime.fromtimestamp(timestamp_us / 1_000_000)
```
**In SQL queries:**
```sql
-- Datetime to microseconds
SELECT CAST((strftime('%s', import_time) || substr(import_time, 21, 6)) AS INTEGER);
-- Microseconds to datetime (approximate)
SELECT datetime(import_time_us / 1000000, 'unixepoch');
```
## Performance Benefits
The integer timestamp columns provide significant performance improvements:
1. **Faster comparisons**: Integer comparisons are much faster than string/datetime comparisons
2. **Smaller index size**: Integer indexes are more compact than datetime indexes
3. **Range queries**: BETWEEN operations on integers are highly optimized
4. **Math operations**: Easy to calculate time differences, averages, etc.
5. **Sorting**: Integer sorting is faster than datetime sorting
## Backward Compatibility
The original `import_time` TEXT columns remain unchanged:
- Existing code continues to work
- Human-readable timestamps still available
- Gradual migration to new columns possible
- No breaking changes for existing queries
## Future Work
Future improvements could include:
- Migrating queries to use `import_time_us` columns
- Deprecating the TEXT `import_time` columns (after transition period)
- Adding helper functions for timestamp conversion
- Creating views that expose both formats
## Testing
The migration was tested on a production database with:
- 132,466 packet records
- 1,385,659 packet_seen records
- 28,414 traceroute records
All records were successfully migrated with microsecond precision preserved.
## References
- GitHub Issue: #55 - Storing High-Resolution Timestamps in SQLite
- SQLite datetime functions: https://www.sqlite.org/lang_datefunc.html
- Python datetime module: https://docs.python.org/3/library/datetime.html

View File

@@ -1,23 +0,0 @@
#!/bin/sh
protoc \
-Iproto_def \
--python_out=. \
proto_def/meshtastic/admin.proto \
proto_def/meshtastic/apponly.proto \
proto_def/meshtastic/atak.proto \
proto_def/meshtastic/cannedmessages.proto \
proto_def/meshtastic/channel.proto \
proto_def/meshtastic/clientonly.proto \
proto_def/meshtastic/config.proto \
proto_def/meshtastic/connection_status.proto \
proto_def/meshtastic/localonly.proto \
proto_def/meshtastic/mesh.proto \
proto_def/meshtastic/module_config.proto \
proto_def/meshtastic/mqtt.proto \
proto_def/meshtastic/paxcount.proto \
proto_def/meshtastic/portnums.proto \
proto_def/meshtastic/remote_hardware.proto \
proto_def/meshtastic/rtttl.proto \
proto_def/meshtastic/storeforward.proto \
proto_def/meshtastic/telemetry.proto \
proto_def/meshtastic/xmodem.proto

34
main.py
View File

@@ -1,40 +1,12 @@
import asyncio
import argparse
from meshview import mqtt_reader
from meshview import database
from meshview import store
from meshview import web
from meshview import http
async def load_database_from_mqtt(topic):
async for topic, env in mqtt_reader.get_topic_envelopes(topic):
await store.process_envelope(topic, env)
async def main(args):
database.init_database(args.database)
await database.create_tables()
async def main():
async with asyncio.TaskGroup() as tg:
tg.create_task(load_database_from_mqtt(args.topic))
tg.create_task(web.run_server(args.bind, args.port, args.tls_cert))
if args.acme_challenge:
tg.create_task(http.run_server(args.bind, args.acme_challenge))
tg.create_task(web.run_server())
if __name__ == '__main__':
parser = argparse.ArgumentParser('meshview')
parser.add_argument('--bind', nargs='*', default=['::1'])
parser.add_argument('--acme-challenge')
parser.add_argument('--port', default=8080, type=int)
parser.add_argument('--tls-cert')
parser.add_argument('--topic', nargs='*', default=['msh/US/bayarea/#'])
parser.add_argument('--database', default='sqlite+aiosqlite:///packets.db')
args = parser.parse_args()
asyncio.run(main(args))
asyncio.run(main())

View File

@@ -1,39 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/admin.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic import channel_pb2 as meshtastic_dot_channel__pb2
from meshtastic import config_pb2 as meshtastic_dot_config__pb2
from meshtastic import connection_status_pb2 as meshtastic_dot_connection__status__pb2
from meshtastic import mesh_pb2 as meshtastic_dot_mesh__pb2
from meshtastic import module_config_pb2 as meshtastic_dot_module__config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16meshtastic/admin.proto\x12\nmeshtastic\x1a\x18meshtastic/channel.proto\x1a\x17meshtastic/config.proto\x1a\"meshtastic/connection_status.proto\x1a\x15meshtastic/mesh.proto\x1a\x1emeshtastic/module_config.proto\"\xce\x11\n\x0c\x41\x64minMessage\x12\x1d\n\x13get_channel_request\x18\x01 \x01(\rH\x00\x12\x33\n\x14get_channel_response\x18\x02 \x01(\x0b\x32\x13.meshtastic.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x03 \x01(\x08H\x00\x12.\n\x12get_owner_response\x18\x04 \x01(\x0b\x32\x10.meshtastic.UserH\x00\x12\x41\n\x12get_config_request\x18\x05 \x01(\x0e\x32#.meshtastic.AdminMessage.ConfigTypeH\x00\x12\x31\n\x13get_config_response\x18\x06 \x01(\x0b\x32\x12.meshtastic.ConfigH\x00\x12N\n\x19get_module_config_request\x18\x07 \x01(\x0e\x32).meshtastic.AdminMessage.ModuleConfigTypeH\x00\x12>\n\x1aget_module_config_response\x18\x08 \x01(\x0b\x32\x18.meshtastic.ModuleConfigH\x00\x12\x34\n*get_canned_message_module_messages_request\x18\n \x01(\x08H\x00\x12\x35\n+get_canned_message_module_messages_response\x18\x0b \x01(\tH\x00\x12%\n\x1bget_device_metadata_request\x18\x0c \x01(\x08H\x00\x12\x42\n\x1cget_device_metadata_response\x18\r \x01(\x0b\x32\x1a.meshtastic.DeviceMetadataH\x00\x12\x1e\n\x14get_ringtone_request\x18\x0e \x01(\x08H\x00\x12\x1f\n\x15get_ringtone_response\x18\x0f \x01(\tH\x00\x12.\n$get_device_connection_status_request\x18\x10 \x01(\x08H\x00\x12S\n%get_device_connection_status_response\x18\x11 \x01(\x0b\x32\".meshtastic.DeviceConnectionStatusH\x00\x12\x31\n\x0cset_ham_mode\x18\x12 \x01(\x0b\x32\x19.meshtastic.HamParametersH\x00\x12/\n%get_node_remote_hardware_pins_request\x18\x13 \x01(\x08H\x00\x12\\\n&get_node_remote_hardware_pins_response\x18\x14 \x01(\x0b\x32*.meshtastic.NodeRemoteHardwarePinsResponseH\x00\x12 \n\x16\x65nter_dfu_mode_request\x18\x15 \x01(\x08H\x00\x12\x1d\n\x13\x64\x65lete_file_request\x18\x16 \x01(\tH\x00\x12%\n\tset_owner\x18 \x01(\x0b\x32\x10.meshtastic.UserH\x00\x12*\n\x0bset_channel\x18! \x01(\x0b\x32\x13.meshtastic.ChannelH\x00\x12(\n\nset_config\x18\" \x01(\x0b\x32\x12.meshtastic.ConfigH\x00\x12\x35\n\x11set_module_config\x18# \x01(\x0b\x32\x18.meshtastic.ModuleConfigH\x00\x12,\n\"set_canned_message_module_messages\x18$ \x01(\tH\x00\x12\x1e\n\x14set_ringtone_message\x18% \x01(\tH\x00\x12\x1b\n\x11remove_by_nodenum\x18& \x01(\rH\x00\x12\x1b\n\x11set_favorite_node\x18\' \x01(\rH\x00\x12\x1e\n\x14remove_favorite_node\x18( \x01(\rH\x00\x12\x32\n\x12set_fixed_position\x18) \x01(\x0b\x32\x14.meshtastic.PositionH\x00\x12\x1f\n\x15remove_fixed_position\x18* \x01(\x08H\x00\x12\x1d\n\x13\x62\x65gin_edit_settings\x18@ \x01(\x08H\x00\x12\x1e\n\x14\x63ommit_edit_settings\x18\x41 \x01(\x08H\x00\x12\x1c\n\x12reboot_ota_seconds\x18_ \x01(\x05H\x00\x12\x18\n\x0e\x65xit_simulator\x18` \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18\x61 \x01(\x05H\x00\x12\x1a\n\x10shutdown_seconds\x18\x62 \x01(\x05H\x00\x12\x17\n\rfactory_reset\x18\x63 \x01(\x05H\x00\x12\x16\n\x0cnodedb_reset\x18\x64 \x01(\x05H\x00\"\x95\x01\n\nConfigType\x12\x11\n\rDEVICE_CONFIG\x10\x00\x12\x13\n\x0fPOSITION_CONFIG\x10\x01\x12\x10\n\x0cPOWER_CONFIG\x10\x02\x12\x12\n\x0eNETWORK_CONFIG\x10\x03\x12\x12\n\x0e\x44ISPLAY_CONFIG\x10\x04\x12\x0f\n\x0bLORA_CONFIG\x10\x05\x12\x14\n\x10\x42LUETOOTH_CONFIG\x10\x06\"\xbb\x02\n\x10ModuleConfigType\x12\x0f\n\x0bMQTT_CONFIG\x10\x00\x12\x11\n\rSERIAL_CONFIG\x10\x01\x12\x13\n\x0f\x45XTNOTIF_CONFIG\x10\x02\x12\x17\n\x13STOREFORWARD_CONFIG\x10\x03\x12\x14\n\x10RANGETEST_CONFIG\x10\x04\x12\x14\n\x10TELEMETRY_CONFIG\x10\x05\x12\x14\n\x10\x43\x41NNEDMSG_CONFIG\x10\x06\x12\x10\n\x0c\x41UDIO_CONFIG\x10\x07\x12\x19\n\x15REMOTEHARDWARE_CONFIG\x10\x08\x12\x17\n\x13NEIGHBORINFO_CONFIG\x10\t\x12\x1a\n\x16\x41MBIENTLIGHTING_CONFIG\x10\n\x12\x1a\n\x16\x44\x45TECTIONSENSOR_CONFIG\x10\x0b\x12\x15\n\x11PAXCOUNTER_CONFIG\x10\x0c\x42\x11\n\x0fpayload_variant\"[\n\rHamParameters\x12\x11\n\tcall_sign\x18\x01 \x01(\t\x12\x10\n\x08tx_power\x18\x02 \x01(\x05\x12\x11\n\tfrequency\x18\x03 \x01(\x02\x12\x12\n\nshort_name\x18\x04 \x01(\t\"f\n\x1eNodeRemoteHardwarePinsResponse\x12\x44\n\x19node_remote_hardware_pins\x18\x01 \x03(\x0b\x32!.meshtastic.NodeRemoteHardwarePinB`\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.admin_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\013AdminProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_ADMINMESSAGE._serialized_start=181
_ADMINMESSAGE._serialized_end=2435
_ADMINMESSAGE_CONFIGTYPE._serialized_start=1949
_ADMINMESSAGE_CONFIGTYPE._serialized_end=2098
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_start=2101
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_end=2416
_HAMPARAMETERS._serialized_start=2437
_HAMPARAMETERS._serialized_end=2528
_NODEREMOTEHARDWAREPINSRESPONSE._serialized_start=2530
_NODEREMOTEHARDWAREPINSRESPONSE._serialized_end=2632
# @@protoc_insertion_point(module_scope)

View File

@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/apponly.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic import channel_pb2 as meshtastic_dot_channel__pb2
from meshtastic import config_pb2 as meshtastic_dot_config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18meshtastic/apponly.proto\x12\nmeshtastic\x1a\x18meshtastic/channel.proto\x1a\x17meshtastic/config.proto\"o\n\nChannelSet\x12-\n\x08settings\x18\x01 \x03(\x0b\x32\x1b.meshtastic.ChannelSettings\x12\x32\n\x0blora_config\x18\x02 \x01(\x0b\x32\x1d.meshtastic.Config.LoRaConfigBb\n\x13\x63om.geeksville.meshB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.apponly_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_CHANNELSET._serialized_start=91
_CHANNELSET._serialized_end=202
# @@protoc_insertion_point(module_scope)

View File

@@ -1,40 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/atak.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15meshtastic/atak.proto\x12\nmeshtastic\"\xe6\x01\n\tTAKPacket\x12\x15\n\ris_compressed\x18\x01 \x01(\x08\x12$\n\x07\x63ontact\x18\x02 \x01(\x0b\x32\x13.meshtastic.Contact\x12 \n\x05group\x18\x03 \x01(\x0b\x32\x11.meshtastic.Group\x12\"\n\x06status\x18\x04 \x01(\x0b\x32\x12.meshtastic.Status\x12\x1e\n\x03pli\x18\x05 \x01(\x0b\x32\x0f.meshtastic.PLIH\x00\x12#\n\x04\x63hat\x18\x06 \x01(\x0b\x32\x13.meshtastic.GeoChatH\x00\x42\x11\n\x0fpayload_variant\"2\n\x07GeoChat\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0f\n\x02to\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x05\n\x03_to\"M\n\x05Group\x12$\n\x04role\x18\x01 \x01(\x0e\x32\x16.meshtastic.MemberRole\x12\x1e\n\x04team\x18\x02 \x01(\x0e\x32\x10.meshtastic.Team\"\x19\n\x06Status\x12\x0f\n\x07\x62\x61ttery\x18\x01 \x01(\r\"4\n\x07\x43ontact\x12\x10\n\x08\x63\x61llsign\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65vice_callsign\x18\x02 \x01(\t\"_\n\x03PLI\x12\x12\n\nlatitude_i\x18\x01 \x01(\x0f\x12\x13\n\x0blongitude_i\x18\x02 \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\r\n\x05speed\x18\x04 \x01(\r\x12\x0e\n\x06\x63ourse\x18\x05 \x01(\r*\xc0\x01\n\x04Team\x12\x14\n\x10Unspecifed_Color\x10\x00\x12\t\n\x05White\x10\x01\x12\n\n\x06Yellow\x10\x02\x12\n\n\x06Orange\x10\x03\x12\x0b\n\x07Magenta\x10\x04\x12\x07\n\x03Red\x10\x05\x12\n\n\x06Maroon\x10\x06\x12\n\n\x06Purple\x10\x07\x12\r\n\tDark_Blue\x10\x08\x12\x08\n\x04\x42lue\x10\t\x12\x08\n\x04\x43yan\x10\n\x12\x08\n\x04Teal\x10\x0b\x12\t\n\x05Green\x10\x0c\x12\x0e\n\nDark_Green\x10\r\x12\t\n\x05\x42rown\x10\x0e*\x7f\n\nMemberRole\x12\x0e\n\nUnspecifed\x10\x00\x12\x0e\n\nTeamMember\x10\x01\x12\x0c\n\x08TeamLead\x10\x02\x12\x06\n\x02HQ\x10\x03\x12\n\n\x06Sniper\x10\x04\x12\t\n\x05Medic\x10\x05\x12\x13\n\x0f\x46orwardObserver\x10\x06\x12\x07\n\x03RTO\x10\x07\x12\x06\n\x02K9\x10\x08\x42_\n\x13\x63om.geeksville.meshB\nATAKProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.atak_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nATAKProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_TEAM._serialized_start=580
_TEAM._serialized_end=772
_MEMBERROLE._serialized_start=774
_MEMBERROLE._serialized_end=901
_TAKPACKET._serialized_start=38
_TAKPACKET._serialized_end=268
_GEOCHAT._serialized_start=270
_GEOCHAT._serialized_end=320
_GROUP._serialized_start=322
_GROUP._serialized_end=399
_STATUS._serialized_start=401
_STATUS._serialized_end=426
_CONTACT._serialized_start=428
_CONTACT._serialized_end=480
_PLI._serialized_start=482
_PLI._serialized_end=577
# @@protoc_insertion_point(module_scope)

View File

@@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/cannedmessages.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/cannedmessages.proto\x12\nmeshtastic\"-\n\x19\x43\x61nnedMessageModuleConfig\x12\x10\n\x08messages\x18\x01 \x01(\tBn\n\x13\x63om.geeksville.meshB\x19\x43\x61nnedMessageConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.cannedmessages_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\031CannedMessageConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_CANNEDMESSAGEMODULECONFIG._serialized_start=47
_CANNEDMESSAGEMODULECONFIG._serialized_end=92
# @@protoc_insertion_point(module_scope)

View File

@@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/channel.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18meshtastic/channel.proto\x12\nmeshtastic\"\xb8\x01\n\x0f\x43hannelSettings\x12\x17\n\x0b\x63hannel_num\x18\x01 \x01(\rB\x02\x18\x01\x12\x0b\n\x03psk\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\n\n\x02id\x18\x04 \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x05 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x06 \x01(\x08\x12\x33\n\x0fmodule_settings\x18\x07 \x01(\x0b\x32\x1a.meshtastic.ModuleSettings\"E\n\x0eModuleSettings\x12\x1a\n\x12position_precision\x18\x01 \x01(\r\x12\x17\n\x0fis_client_muted\x18\x02 \x01(\x08\"\xa1\x01\n\x07\x43hannel\x12\r\n\x05index\x18\x01 \x01(\x05\x12-\n\x08settings\x18\x02 \x01(\x0b\x32\x1b.meshtastic.ChannelSettings\x12&\n\x04role\x18\x03 \x01(\x0e\x32\x18.meshtastic.Channel.Role\"0\n\x04Role\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07PRIMARY\x10\x01\x12\r\n\tSECONDARY\x10\x02\x42\x62\n\x13\x63om.geeksville.meshB\rChannelProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.channel_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\rChannelProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_CHANNELSETTINGS.fields_by_name['channel_num']._options = None
_CHANNELSETTINGS.fields_by_name['channel_num']._serialized_options = b'\030\001'
_CHANNELSETTINGS._serialized_start=41
_CHANNELSETTINGS._serialized_end=225
_MODULESETTINGS._serialized_start=227
_MODULESETTINGS._serialized_end=296
_CHANNEL._serialized_start=299
_CHANNEL._serialized_end=460
_CHANNEL_ROLE._serialized_start=412
_CHANNEL_ROLE._serialized_end=460
# @@protoc_insertion_point(module_scope)

View File

@@ -1,27 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/clientonly.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic import localonly_pb2 as meshtastic_dot_localonly__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bmeshtastic/clientonly.proto\x12\nmeshtastic\x1a\x1ameshtastic/localonly.proto\"\x8d\x02\n\rDeviceProfile\x12\x16\n\tlong_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nshort_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x63hannel_url\x18\x03 \x01(\tH\x02\x88\x01\x01\x12,\n\x06\x63onfig\x18\x04 \x01(\x0b\x32\x17.meshtastic.LocalConfigH\x03\x88\x01\x01\x12\x39\n\rmodule_config\x18\x05 \x01(\x0b\x32\x1d.meshtastic.LocalModuleConfigH\x04\x88\x01\x01\x42\x0c\n\n_long_nameB\r\n\x0b_short_nameB\x0e\n\x0c_channel_urlB\t\n\x07_configB\x10\n\x0e_module_configBe\n\x13\x63om.geeksville.meshB\x10\x43lientOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.clientonly_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\020ClientOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_DEVICEPROFILE._serialized_start=72
_DEVICEPROFILE._serialized_end=341
# @@protoc_insertion_point(module_scope)

File diff suppressed because one or more lines are too long

View File

@@ -1,36 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/connection_status.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/connection_status.proto\x12\nmeshtastic\"\xb1\x02\n\x16\x44\x65viceConnectionStatus\x12\x33\n\x04wifi\x18\x01 \x01(\x0b\x32 .meshtastic.WifiConnectionStatusH\x00\x88\x01\x01\x12;\n\x08\x65thernet\x18\x02 \x01(\x0b\x32$.meshtastic.EthernetConnectionStatusH\x01\x88\x01\x01\x12=\n\tbluetooth\x18\x03 \x01(\x0b\x32%.meshtastic.BluetoothConnectionStatusH\x02\x88\x01\x01\x12\x37\n\x06serial\x18\x04 \x01(\x0b\x32\".meshtastic.SerialConnectionStatusH\x03\x88\x01\x01\x42\x07\n\x05_wifiB\x0b\n\t_ethernetB\x0c\n\n_bluetoothB\t\n\x07_serial\"g\n\x14WifiConnectionStatus\x12\x33\n\x06status\x18\x01 \x01(\x0b\x32#.meshtastic.NetworkConnectionStatus\x12\x0c\n\x04ssid\x18\x02 \x01(\t\x12\x0c\n\x04rssi\x18\x03 \x01(\x05\"O\n\x18\x45thernetConnectionStatus\x12\x33\n\x06status\x18\x01 \x01(\x0b\x32#.meshtastic.NetworkConnectionStatus\"{\n\x17NetworkConnectionStatus\x12\x12\n\nip_address\x18\x01 \x01(\x07\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x12\x19\n\x11is_mqtt_connected\x18\x03 \x01(\x08\x12\x1b\n\x13is_syslog_connected\x18\x04 \x01(\x08\"L\n\x19\x42luetoothConnectionStatus\x12\x0b\n\x03pin\x18\x01 \x01(\r\x12\x0c\n\x04rssi\x18\x02 \x01(\x05\x12\x14\n\x0cis_connected\x18\x03 \x01(\x08\"<\n\x16SerialConnectionStatus\x12\x0c\n\x04\x62\x61ud\x18\x01 \x01(\r\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x42\x65\n\x13\x63om.geeksville.meshB\x10\x43onnStatusProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.connection_status_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\020ConnStatusProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_DEVICECONNECTIONSTATUS._serialized_start=51
_DEVICECONNECTIONSTATUS._serialized_end=356
_WIFICONNECTIONSTATUS._serialized_start=358
_WIFICONNECTIONSTATUS._serialized_end=461
_ETHERNETCONNECTIONSTATUS._serialized_start=463
_ETHERNETCONNECTIONSTATUS._serialized_end=542
_NETWORKCONNECTIONSTATUS._serialized_start=544
_NETWORKCONNECTIONSTATUS._serialized_end=667
_BLUETOOTHCONNECTIONSTATUS._serialized_start=669
_BLUETOOTHCONNECTIONSTATUS._serialized_end=745
_SERIALCONNECTIONSTATUS._serialized_start=747
_SERIALCONNECTIONSTATUS._serialized_end=807
# @@protoc_insertion_point(module_scope)

View File

@@ -1,30 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/localonly.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic import config_pb2 as meshtastic_dot_config__pb2
from meshtastic import module_config_pb2 as meshtastic_dot_module__config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1ameshtastic/localonly.proto\x12\nmeshtastic\x1a\x17meshtastic/config.proto\x1a\x1emeshtastic/module_config.proto\"\xfd\x02\n\x0bLocalConfig\x12/\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32\x1f.meshtastic.Config.DeviceConfig\x12\x33\n\x08position\x18\x02 \x01(\x0b\x32!.meshtastic.Config.PositionConfig\x12-\n\x05power\x18\x03 \x01(\x0b\x32\x1e.meshtastic.Config.PowerConfig\x12\x31\n\x07network\x18\x04 \x01(\x0b\x32 .meshtastic.Config.NetworkConfig\x12\x31\n\x07\x64isplay\x18\x05 \x01(\x0b\x32 .meshtastic.Config.DisplayConfig\x12+\n\x04lora\x18\x06 \x01(\x0b\x32\x1d.meshtastic.Config.LoRaConfig\x12\x35\n\tbluetooth\x18\x07 \x01(\x0b\x32\".meshtastic.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\"\xfb\x06\n\x11LocalModuleConfig\x12\x31\n\x04mqtt\x18\x01 \x01(\x0b\x32#.meshtastic.ModuleConfig.MQTTConfig\x12\x35\n\x06serial\x18\x02 \x01(\x0b\x32%.meshtastic.ModuleConfig.SerialConfig\x12R\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32\x33.meshtastic.ModuleConfig.ExternalNotificationConfig\x12\x42\n\rstore_forward\x18\x04 \x01(\x0b\x32+.meshtastic.ModuleConfig.StoreForwardConfig\x12<\n\nrange_test\x18\x05 \x01(\x0b\x32(.meshtastic.ModuleConfig.RangeTestConfig\x12;\n\ttelemetry\x18\x06 \x01(\x0b\x32(.meshtastic.ModuleConfig.TelemetryConfig\x12\x44\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32,.meshtastic.ModuleConfig.CannedMessageConfig\x12\x33\n\x05\x61udio\x18\t \x01(\x0b\x32$.meshtastic.ModuleConfig.AudioConfig\x12\x46\n\x0fremote_hardware\x18\n \x01(\x0b\x32-.meshtastic.ModuleConfig.RemoteHardwareConfig\x12\x42\n\rneighbor_info\x18\x0b \x01(\x0b\x32+.meshtastic.ModuleConfig.NeighborInfoConfig\x12H\n\x10\x61mbient_lighting\x18\x0c \x01(\x0b\x32..meshtastic.ModuleConfig.AmbientLightingConfig\x12H\n\x10\x64\x65tection_sensor\x18\r \x01(\x0b\x32..meshtastic.ModuleConfig.DetectionSensorConfig\x12=\n\npaxcounter\x18\x0e \x01(\x0b\x32).meshtastic.ModuleConfig.PaxcounterConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBd\n\x13\x63om.geeksville.meshB\x0fLocalOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.localonly_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017LocalOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_LOCALCONFIG._serialized_start=100
_LOCALCONFIG._serialized_end=481
_LOCALMODULECONFIG._serialized_start=484
_LOCALMODULECONFIG._serialized_end=1375
# @@protoc_insertion_point(module_scope)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,30 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/mqtt.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic import config_pb2 as meshtastic_dot_config__pb2
from meshtastic import mesh_pb2 as meshtastic_dot_mesh__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15meshtastic/mqtt.proto\x12\nmeshtastic\x1a\x17meshtastic/config.proto\x1a\x15meshtastic/mesh.proto\"a\n\x0fServiceEnvelope\x12&\n\x06packet\x18\x01 \x01(\x0b\x32\x16.meshtastic.MeshPacket\x12\x12\n\nchannel_id\x18\x02 \x01(\t\x12\x12\n\ngateway_id\x18\x03 \x01(\t\"\xbc\x03\n\tMapReport\x12\x11\n\tlong_name\x18\x01 \x01(\t\x12\x12\n\nshort_name\x18\x02 \x01(\t\x12\x32\n\x04role\x18\x03 \x01(\x0e\x32$.meshtastic.Config.DeviceConfig.Role\x12+\n\x08hw_model\x18\x04 \x01(\x0e\x32\x19.meshtastic.HardwareModel\x12\x18\n\x10\x66irmware_version\x18\x05 \x01(\t\x12\x38\n\x06region\x18\x06 \x01(\x0e\x32(.meshtastic.Config.LoRaConfig.RegionCode\x12?\n\x0cmodem_preset\x18\x07 \x01(\x0e\x32).meshtastic.Config.LoRaConfig.ModemPreset\x12\x1b\n\x13has_default_channel\x18\x08 \x01(\x08\x12\x12\n\nlatitude_i\x18\t \x01(\x0f\x12\x13\n\x0blongitude_i\x18\n \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x0b \x01(\x05\x12\x1a\n\x12position_precision\x18\x0c \x01(\r\x12\x1e\n\x16num_online_local_nodes\x18\r \x01(\rB_\n\x13\x63om.geeksville.meshB\nMQTTProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.mqtt_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nMQTTProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_SERVICEENVELOPE._serialized_start=85
_SERVICEENVELOPE._serialized_end=182
_MAPREPORT._serialized_start=185
_MAPREPORT._serialized_end=629
# @@protoc_insertion_point(module_scope)

View File

@@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/paxcount.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19meshtastic/paxcount.proto\x12\nmeshtastic\"5\n\x08Paxcount\x12\x0c\n\x04wifi\x18\x01 \x01(\r\x12\x0b\n\x03\x62le\x18\x02 \x01(\r\x12\x0e\n\x06uptime\x18\x03 \x01(\rBc\n\x13\x63om.geeksville.meshB\x0ePaxcountProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.paxcount_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016PaxcountProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_PAXCOUNT._serialized_start=41
_PAXCOUNT._serialized_end=94
# @@protoc_insertion_point(module_scope)

View File

@@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/portnums.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19meshtastic/portnums.proto\x12\nmeshtastic*\x8d\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.portnums_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_PORTNUM._serialized_start=42
_PORTNUM._serialized_end=567
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1 @@
e1a6b3a868d735da72cd6c94c574d655129d390a

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,889 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import collections.abc
import google.protobuf.descriptor
import google.protobuf.internal.containers
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import meshtastic.protobuf.channel_pb2
import meshtastic.protobuf.config_pb2
import meshtastic.protobuf.connection_status_pb2
import meshtastic.protobuf.device_ui_pb2
import meshtastic.protobuf.mesh_pb2
import meshtastic.protobuf.module_config_pb2
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class AdminMessage(google.protobuf.message.Message):
"""
This message is handled by the Admin module and is responsible for all settings/channel read/write operations.
This message is used to do settings operations to both remote AND local nodes.
(Prior to 1.2 these operations were done via special ToRadio operations)
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _ConfigType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _ConfigTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[AdminMessage._ConfigType.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
DEVICE_CONFIG: AdminMessage._ConfigType.ValueType # 0
"""
TODO: REPLACE
"""
POSITION_CONFIG: AdminMessage._ConfigType.ValueType # 1
"""
TODO: REPLACE
"""
POWER_CONFIG: AdminMessage._ConfigType.ValueType # 2
"""
TODO: REPLACE
"""
NETWORK_CONFIG: AdminMessage._ConfigType.ValueType # 3
"""
TODO: REPLACE
"""
DISPLAY_CONFIG: AdminMessage._ConfigType.ValueType # 4
"""
TODO: REPLACE
"""
LORA_CONFIG: AdminMessage._ConfigType.ValueType # 5
"""
TODO: REPLACE
"""
BLUETOOTH_CONFIG: AdminMessage._ConfigType.ValueType # 6
"""
TODO: REPLACE
"""
SECURITY_CONFIG: AdminMessage._ConfigType.ValueType # 7
"""
TODO: REPLACE
"""
SESSIONKEY_CONFIG: AdminMessage._ConfigType.ValueType # 8
"""
Session key config
"""
DEVICEUI_CONFIG: AdminMessage._ConfigType.ValueType # 9
"""
device-ui config
"""
class ConfigType(_ConfigType, metaclass=_ConfigTypeEnumTypeWrapper):
"""
TODO: REPLACE
"""
DEVICE_CONFIG: AdminMessage.ConfigType.ValueType # 0
"""
TODO: REPLACE
"""
POSITION_CONFIG: AdminMessage.ConfigType.ValueType # 1
"""
TODO: REPLACE
"""
POWER_CONFIG: AdminMessage.ConfigType.ValueType # 2
"""
TODO: REPLACE
"""
NETWORK_CONFIG: AdminMessage.ConfigType.ValueType # 3
"""
TODO: REPLACE
"""
DISPLAY_CONFIG: AdminMessage.ConfigType.ValueType # 4
"""
TODO: REPLACE
"""
LORA_CONFIG: AdminMessage.ConfigType.ValueType # 5
"""
TODO: REPLACE
"""
BLUETOOTH_CONFIG: AdminMessage.ConfigType.ValueType # 6
"""
TODO: REPLACE
"""
SECURITY_CONFIG: AdminMessage.ConfigType.ValueType # 7
"""
TODO: REPLACE
"""
SESSIONKEY_CONFIG: AdminMessage.ConfigType.ValueType # 8
"""
Session key config
"""
DEVICEUI_CONFIG: AdminMessage.ConfigType.ValueType # 9
"""
device-ui config
"""
class _ModuleConfigType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _ModuleConfigTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[AdminMessage._ModuleConfigType.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
MQTT_CONFIG: AdminMessage._ModuleConfigType.ValueType # 0
"""
TODO: REPLACE
"""
SERIAL_CONFIG: AdminMessage._ModuleConfigType.ValueType # 1
"""
TODO: REPLACE
"""
EXTNOTIF_CONFIG: AdminMessage._ModuleConfigType.ValueType # 2
"""
TODO: REPLACE
"""
STOREFORWARD_CONFIG: AdminMessage._ModuleConfigType.ValueType # 3
"""
TODO: REPLACE
"""
RANGETEST_CONFIG: AdminMessage._ModuleConfigType.ValueType # 4
"""
TODO: REPLACE
"""
TELEMETRY_CONFIG: AdminMessage._ModuleConfigType.ValueType # 5
"""
TODO: REPLACE
"""
CANNEDMSG_CONFIG: AdminMessage._ModuleConfigType.ValueType # 6
"""
TODO: REPLACE
"""
AUDIO_CONFIG: AdminMessage._ModuleConfigType.ValueType # 7
"""
TODO: REPLACE
"""
REMOTEHARDWARE_CONFIG: AdminMessage._ModuleConfigType.ValueType # 8
"""
TODO: REPLACE
"""
NEIGHBORINFO_CONFIG: AdminMessage._ModuleConfigType.ValueType # 9
"""
TODO: REPLACE
"""
AMBIENTLIGHTING_CONFIG: AdminMessage._ModuleConfigType.ValueType # 10
"""
TODO: REPLACE
"""
DETECTIONSENSOR_CONFIG: AdminMessage._ModuleConfigType.ValueType # 11
"""
TODO: REPLACE
"""
PAXCOUNTER_CONFIG: AdminMessage._ModuleConfigType.ValueType # 12
"""
TODO: REPLACE
"""
class ModuleConfigType(_ModuleConfigType, metaclass=_ModuleConfigTypeEnumTypeWrapper):
"""
TODO: REPLACE
"""
MQTT_CONFIG: AdminMessage.ModuleConfigType.ValueType # 0
"""
TODO: REPLACE
"""
SERIAL_CONFIG: AdminMessage.ModuleConfigType.ValueType # 1
"""
TODO: REPLACE
"""
EXTNOTIF_CONFIG: AdminMessage.ModuleConfigType.ValueType # 2
"""
TODO: REPLACE
"""
STOREFORWARD_CONFIG: AdminMessage.ModuleConfigType.ValueType # 3
"""
TODO: REPLACE
"""
RANGETEST_CONFIG: AdminMessage.ModuleConfigType.ValueType # 4
"""
TODO: REPLACE
"""
TELEMETRY_CONFIG: AdminMessage.ModuleConfigType.ValueType # 5
"""
TODO: REPLACE
"""
CANNEDMSG_CONFIG: AdminMessage.ModuleConfigType.ValueType # 6
"""
TODO: REPLACE
"""
AUDIO_CONFIG: AdminMessage.ModuleConfigType.ValueType # 7
"""
TODO: REPLACE
"""
REMOTEHARDWARE_CONFIG: AdminMessage.ModuleConfigType.ValueType # 8
"""
TODO: REPLACE
"""
NEIGHBORINFO_CONFIG: AdminMessage.ModuleConfigType.ValueType # 9
"""
TODO: REPLACE
"""
AMBIENTLIGHTING_CONFIG: AdminMessage.ModuleConfigType.ValueType # 10
"""
TODO: REPLACE
"""
DETECTIONSENSOR_CONFIG: AdminMessage.ModuleConfigType.ValueType # 11
"""
TODO: REPLACE
"""
PAXCOUNTER_CONFIG: AdminMessage.ModuleConfigType.ValueType # 12
"""
TODO: REPLACE
"""
class _BackupLocation:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _BackupLocationEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[AdminMessage._BackupLocation.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
FLASH: AdminMessage._BackupLocation.ValueType # 0
"""
Backup to the internal flash
"""
SD: AdminMessage._BackupLocation.ValueType # 1
"""
Backup to the SD card
"""
class BackupLocation(_BackupLocation, metaclass=_BackupLocationEnumTypeWrapper): ...
FLASH: AdminMessage.BackupLocation.ValueType # 0
"""
Backup to the internal flash
"""
SD: AdminMessage.BackupLocation.ValueType # 1
"""
Backup to the SD card
"""
@typing.final
class InputEvent(google.protobuf.message.Message):
"""
Input event message to be sent to the node.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
EVENT_CODE_FIELD_NUMBER: builtins.int
KB_CHAR_FIELD_NUMBER: builtins.int
TOUCH_X_FIELD_NUMBER: builtins.int
TOUCH_Y_FIELD_NUMBER: builtins.int
event_code: builtins.int
"""
The input event code
"""
kb_char: builtins.int
"""
Keyboard character code
"""
touch_x: builtins.int
"""
The touch X coordinate
"""
touch_y: builtins.int
"""
The touch Y coordinate
"""
def __init__(
self,
*,
event_code: builtins.int = ...,
kb_char: builtins.int = ...,
touch_x: builtins.int = ...,
touch_y: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["event_code", b"event_code", "kb_char", b"kb_char", "touch_x", b"touch_x", "touch_y", b"touch_y"]) -> None: ...
SESSION_PASSKEY_FIELD_NUMBER: builtins.int
GET_CHANNEL_REQUEST_FIELD_NUMBER: builtins.int
GET_CHANNEL_RESPONSE_FIELD_NUMBER: builtins.int
GET_OWNER_REQUEST_FIELD_NUMBER: builtins.int
GET_OWNER_RESPONSE_FIELD_NUMBER: builtins.int
GET_CONFIG_REQUEST_FIELD_NUMBER: builtins.int
GET_CONFIG_RESPONSE_FIELD_NUMBER: builtins.int
GET_MODULE_CONFIG_REQUEST_FIELD_NUMBER: builtins.int
GET_MODULE_CONFIG_RESPONSE_FIELD_NUMBER: builtins.int
GET_CANNED_MESSAGE_MODULE_MESSAGES_REQUEST_FIELD_NUMBER: builtins.int
GET_CANNED_MESSAGE_MODULE_MESSAGES_RESPONSE_FIELD_NUMBER: builtins.int
GET_DEVICE_METADATA_REQUEST_FIELD_NUMBER: builtins.int
GET_DEVICE_METADATA_RESPONSE_FIELD_NUMBER: builtins.int
GET_RINGTONE_REQUEST_FIELD_NUMBER: builtins.int
GET_RINGTONE_RESPONSE_FIELD_NUMBER: builtins.int
GET_DEVICE_CONNECTION_STATUS_REQUEST_FIELD_NUMBER: builtins.int
GET_DEVICE_CONNECTION_STATUS_RESPONSE_FIELD_NUMBER: builtins.int
SET_HAM_MODE_FIELD_NUMBER: builtins.int
GET_NODE_REMOTE_HARDWARE_PINS_REQUEST_FIELD_NUMBER: builtins.int
GET_NODE_REMOTE_HARDWARE_PINS_RESPONSE_FIELD_NUMBER: builtins.int
ENTER_DFU_MODE_REQUEST_FIELD_NUMBER: builtins.int
DELETE_FILE_REQUEST_FIELD_NUMBER: builtins.int
SET_SCALE_FIELD_NUMBER: builtins.int
BACKUP_PREFERENCES_FIELD_NUMBER: builtins.int
RESTORE_PREFERENCES_FIELD_NUMBER: builtins.int
REMOVE_BACKUP_PREFERENCES_FIELD_NUMBER: builtins.int
SEND_INPUT_EVENT_FIELD_NUMBER: builtins.int
SET_OWNER_FIELD_NUMBER: builtins.int
SET_CHANNEL_FIELD_NUMBER: builtins.int
SET_CONFIG_FIELD_NUMBER: builtins.int
SET_MODULE_CONFIG_FIELD_NUMBER: builtins.int
SET_CANNED_MESSAGE_MODULE_MESSAGES_FIELD_NUMBER: builtins.int
SET_RINGTONE_MESSAGE_FIELD_NUMBER: builtins.int
REMOVE_BY_NODENUM_FIELD_NUMBER: builtins.int
SET_FAVORITE_NODE_FIELD_NUMBER: builtins.int
REMOVE_FAVORITE_NODE_FIELD_NUMBER: builtins.int
SET_FIXED_POSITION_FIELD_NUMBER: builtins.int
REMOVE_FIXED_POSITION_FIELD_NUMBER: builtins.int
SET_TIME_ONLY_FIELD_NUMBER: builtins.int
GET_UI_CONFIG_REQUEST_FIELD_NUMBER: builtins.int
GET_UI_CONFIG_RESPONSE_FIELD_NUMBER: builtins.int
STORE_UI_CONFIG_FIELD_NUMBER: builtins.int
SET_IGNORED_NODE_FIELD_NUMBER: builtins.int
REMOVE_IGNORED_NODE_FIELD_NUMBER: builtins.int
BEGIN_EDIT_SETTINGS_FIELD_NUMBER: builtins.int
COMMIT_EDIT_SETTINGS_FIELD_NUMBER: builtins.int
ADD_CONTACT_FIELD_NUMBER: builtins.int
KEY_VERIFICATION_FIELD_NUMBER: builtins.int
FACTORY_RESET_DEVICE_FIELD_NUMBER: builtins.int
REBOOT_OTA_SECONDS_FIELD_NUMBER: builtins.int
EXIT_SIMULATOR_FIELD_NUMBER: builtins.int
REBOOT_SECONDS_FIELD_NUMBER: builtins.int
SHUTDOWN_SECONDS_FIELD_NUMBER: builtins.int
FACTORY_RESET_CONFIG_FIELD_NUMBER: builtins.int
NODEDB_RESET_FIELD_NUMBER: builtins.int
session_passkey: builtins.bytes
"""
The node generates this key and sends it with any get_x_response packets.
The client MUST include the same key with any set_x commands. Key expires after 300 seconds.
Prevents replay attacks for admin messages.
"""
get_channel_request: builtins.int
"""
Send the specified channel in the response to this message
NOTE: This field is sent with the channel index + 1 (to ensure we never try to send 'zero' - which protobufs treats as not present)
"""
get_owner_request: builtins.bool
"""
Send the current owner data in the response to this message.
"""
get_config_request: global___AdminMessage.ConfigType.ValueType
"""
Ask for the following config data to be sent
"""
get_module_config_request: global___AdminMessage.ModuleConfigType.ValueType
"""
Ask for the following config data to be sent
"""
get_canned_message_module_messages_request: builtins.bool
"""
Get the Canned Message Module messages in the response to this message.
"""
get_canned_message_module_messages_response: builtins.str
"""
Get the Canned Message Module messages in the response to this message.
"""
get_device_metadata_request: builtins.bool
"""
Request the node to send device metadata (firmware, protobuf version, etc)
"""
get_ringtone_request: builtins.bool
"""
Get the Ringtone in the response to this message.
"""
get_ringtone_response: builtins.str
"""
Get the Ringtone in the response to this message.
"""
get_device_connection_status_request: builtins.bool
"""
Request the node to send it's connection status
"""
get_node_remote_hardware_pins_request: builtins.bool
"""
Get the mesh's nodes with their available gpio pins for RemoteHardware module use
"""
enter_dfu_mode_request: builtins.bool
"""
Enter (UF2) DFU mode
Only implemented on NRF52 currently
"""
delete_file_request: builtins.str
"""
Delete the file by the specified path from the device
"""
set_scale: builtins.int
"""
Set zero and offset for scale chips
"""
backup_preferences: global___AdminMessage.BackupLocation.ValueType
"""
Backup the node's preferences
"""
restore_preferences: global___AdminMessage.BackupLocation.ValueType
"""
Restore the node's preferences
"""
remove_backup_preferences: global___AdminMessage.BackupLocation.ValueType
"""
Remove backups of the node's preferences
"""
set_canned_message_module_messages: builtins.str
"""
Set the Canned Message Module messages text.
"""
set_ringtone_message: builtins.str
"""
Set the ringtone for ExternalNotification.
"""
remove_by_nodenum: builtins.int
"""
Remove the node by the specified node-num from the NodeDB on the device
"""
set_favorite_node: builtins.int
"""
Set specified node-num to be favorited on the NodeDB on the device
"""
remove_favorite_node: builtins.int
"""
Set specified node-num to be un-favorited on the NodeDB on the device
"""
remove_fixed_position: builtins.bool
"""
Clear fixed position coordinates and then set position.fixed_position = false
"""
set_time_only: builtins.int
"""
Set time only on the node
Convenience method to set the time on the node (as Net quality) without any other position data
"""
get_ui_config_request: builtins.bool
"""
Tell the node to send the stored ui data.
"""
set_ignored_node: builtins.int
"""
Set specified node-num to be ignored on the NodeDB on the device
"""
remove_ignored_node: builtins.int
"""
Set specified node-num to be un-ignored on the NodeDB on the device
"""
begin_edit_settings: builtins.bool
"""
Begins an edit transaction for config, module config, owner, and channel settings changes
This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings)
"""
commit_edit_settings: builtins.bool
"""
Commits an open transaction for any edits made to config, module config, owner, and channel settings
"""
factory_reset_device: builtins.int
"""
Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared.
"""
reboot_ota_seconds: builtins.int
"""
Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth.
"""
exit_simulator: builtins.bool
"""
This message is only supported for the simulator Portduino build.
If received the simulator will exit successfully.
"""
reboot_seconds: builtins.int
"""
Tell the node to reboot in this many seconds (or <0 to cancel reboot)
"""
shutdown_seconds: builtins.int
"""
Tell the node to shutdown in this many seconds (or <0 to cancel shutdown)
"""
factory_reset_config: builtins.int
"""
Tell the node to factory reset config; all device state and configuration will be returned to factory defaults; BLE bonds will be preserved.
"""
nodedb_reset: builtins.int
"""
Tell the node to reset the nodedb.
"""
@property
def get_channel_response(self) -> meshtastic.protobuf.channel_pb2.Channel:
"""
TODO: REPLACE
"""
@property
def get_owner_response(self) -> meshtastic.protobuf.mesh_pb2.User:
"""
TODO: REPLACE
"""
@property
def get_config_response(self) -> meshtastic.protobuf.config_pb2.Config:
"""
Send the current Config in the response to this message.
"""
@property
def get_module_config_response(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig:
"""
Send the current Config in the response to this message.
"""
@property
def get_device_metadata_response(self) -> meshtastic.protobuf.mesh_pb2.DeviceMetadata:
"""
Device metadata response
"""
@property
def get_device_connection_status_response(self) -> meshtastic.protobuf.connection_status_pb2.DeviceConnectionStatus:
"""
Device connection status response
"""
@property
def set_ham_mode(self) -> global___HamParameters:
"""
Setup a node for licensed amateur (ham) radio operation
"""
@property
def get_node_remote_hardware_pins_response(self) -> global___NodeRemoteHardwarePinsResponse:
"""
Respond with the mesh's nodes with their available gpio pins for RemoteHardware module use
"""
@property
def send_input_event(self) -> global___AdminMessage.InputEvent:
"""
Send an input event to the node.
This is used to trigger physical input events like button presses, touch events, etc.
"""
@property
def set_owner(self) -> meshtastic.protobuf.mesh_pb2.User:
"""
Set the owner for this node
"""
@property
def set_channel(self) -> meshtastic.protobuf.channel_pb2.Channel:
"""
Set channels (using the new API).
A special channel is the "primary channel".
The other records are secondary channels.
Note: only one channel can be marked as primary.
If the client sets a particular channel to be primary, the previous channel will be set to SECONDARY automatically.
"""
@property
def set_config(self) -> meshtastic.protobuf.config_pb2.Config:
"""
Set the current Config
"""
@property
def set_module_config(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig:
"""
Set the current Config
"""
@property
def set_fixed_position(self) -> meshtastic.protobuf.mesh_pb2.Position:
"""
Set fixed position data on the node and then set the position.fixed_position = true
"""
@property
def get_ui_config_response(self) -> meshtastic.protobuf.device_ui_pb2.DeviceUIConfig:
"""
Reply stored device ui data.
"""
@property
def store_ui_config(self) -> meshtastic.protobuf.device_ui_pb2.DeviceUIConfig:
"""
Tell the node to store UI data persistently.
"""
@property
def add_contact(self) -> global___SharedContact:
"""
Add a contact (User) to the nodedb
"""
@property
def key_verification(self) -> global___KeyVerificationAdmin:
"""
Initiate or respond to a key verification request
"""
def __init__(
self,
*,
session_passkey: builtins.bytes = ...,
get_channel_request: builtins.int = ...,
get_channel_response: meshtastic.protobuf.channel_pb2.Channel | None = ...,
get_owner_request: builtins.bool = ...,
get_owner_response: meshtastic.protobuf.mesh_pb2.User | None = ...,
get_config_request: global___AdminMessage.ConfigType.ValueType = ...,
get_config_response: meshtastic.protobuf.config_pb2.Config | None = ...,
get_module_config_request: global___AdminMessage.ModuleConfigType.ValueType = ...,
get_module_config_response: meshtastic.protobuf.module_config_pb2.ModuleConfig | None = ...,
get_canned_message_module_messages_request: builtins.bool = ...,
get_canned_message_module_messages_response: builtins.str = ...,
get_device_metadata_request: builtins.bool = ...,
get_device_metadata_response: meshtastic.protobuf.mesh_pb2.DeviceMetadata | None = ...,
get_ringtone_request: builtins.bool = ...,
get_ringtone_response: builtins.str = ...,
get_device_connection_status_request: builtins.bool = ...,
get_device_connection_status_response: meshtastic.protobuf.connection_status_pb2.DeviceConnectionStatus | None = ...,
set_ham_mode: global___HamParameters | None = ...,
get_node_remote_hardware_pins_request: builtins.bool = ...,
get_node_remote_hardware_pins_response: global___NodeRemoteHardwarePinsResponse | None = ...,
enter_dfu_mode_request: builtins.bool = ...,
delete_file_request: builtins.str = ...,
set_scale: builtins.int = ...,
backup_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
restore_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
remove_backup_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
send_input_event: global___AdminMessage.InputEvent | None = ...,
set_owner: meshtastic.protobuf.mesh_pb2.User | None = ...,
set_channel: meshtastic.protobuf.channel_pb2.Channel | None = ...,
set_config: meshtastic.protobuf.config_pb2.Config | None = ...,
set_module_config: meshtastic.protobuf.module_config_pb2.ModuleConfig | None = ...,
set_canned_message_module_messages: builtins.str = ...,
set_ringtone_message: builtins.str = ...,
remove_by_nodenum: builtins.int = ...,
set_favorite_node: builtins.int = ...,
remove_favorite_node: builtins.int = ...,
set_fixed_position: meshtastic.protobuf.mesh_pb2.Position | None = ...,
remove_fixed_position: builtins.bool = ...,
set_time_only: builtins.int = ...,
get_ui_config_request: builtins.bool = ...,
get_ui_config_response: meshtastic.protobuf.device_ui_pb2.DeviceUIConfig | None = ...,
store_ui_config: meshtastic.protobuf.device_ui_pb2.DeviceUIConfig | None = ...,
set_ignored_node: builtins.int = ...,
remove_ignored_node: builtins.int = ...,
begin_edit_settings: builtins.bool = ...,
commit_edit_settings: builtins.bool = ...,
add_contact: global___SharedContact | None = ...,
key_verification: global___KeyVerificationAdmin | None = ...,
factory_reset_device: builtins.int = ...,
reboot_ota_seconds: builtins.int = ...,
exit_simulator: builtins.bool = ...,
reboot_seconds: builtins.int = ...,
shutdown_seconds: builtins.int = ...,
factory_reset_config: builtins.int = ...,
nodedb_reset: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["add_contact", b"add_contact", "backup_preferences", b"backup_preferences", "begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "get_ui_config_request", b"get_ui_config_request", "get_ui_config_response", b"get_ui_config_response", "key_verification", b"key_verification", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_backup_preferences", b"remove_backup_preferences", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "remove_ignored_node", b"remove_ignored_node", "restore_preferences", b"restore_preferences", "send_input_event", b"send_input_event", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_ignored_node", b"set_ignored_node", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "set_time_only", b"set_time_only", "shutdown_seconds", b"shutdown_seconds", "store_ui_config", b"store_ui_config"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["add_contact", b"add_contact", "backup_preferences", b"backup_preferences", "begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "get_ui_config_request", b"get_ui_config_request", "get_ui_config_response", b"get_ui_config_response", "key_verification", b"key_verification", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_backup_preferences", b"remove_backup_preferences", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "remove_ignored_node", b"remove_ignored_node", "restore_preferences", b"restore_preferences", "send_input_event", b"send_input_event", "session_passkey", b"session_passkey", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_ignored_node", b"set_ignored_node", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "set_time_only", b"set_time_only", "shutdown_seconds", b"shutdown_seconds", "store_ui_config", b"store_ui_config"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["get_channel_request", "get_channel_response", "get_owner_request", "get_owner_response", "get_config_request", "get_config_response", "get_module_config_request", "get_module_config_response", "get_canned_message_module_messages_request", "get_canned_message_module_messages_response", "get_device_metadata_request", "get_device_metadata_response", "get_ringtone_request", "get_ringtone_response", "get_device_connection_status_request", "get_device_connection_status_response", "set_ham_mode", "get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", "enter_dfu_mode_request", "delete_file_request", "set_scale", "backup_preferences", "restore_preferences", "remove_backup_preferences", "send_input_event", "set_owner", "set_channel", "set_config", "set_module_config", "set_canned_message_module_messages", "set_ringtone_message", "remove_by_nodenum", "set_favorite_node", "remove_favorite_node", "set_fixed_position", "remove_fixed_position", "set_time_only", "get_ui_config_request", "get_ui_config_response", "store_ui_config", "set_ignored_node", "remove_ignored_node", "begin_edit_settings", "commit_edit_settings", "add_contact", "key_verification", "factory_reset_device", "reboot_ota_seconds", "exit_simulator", "reboot_seconds", "shutdown_seconds", "factory_reset_config", "nodedb_reset"] | None: ...
global___AdminMessage = AdminMessage
@typing.final
class HamParameters(google.protobuf.message.Message):
"""
Parameters for setting up Meshtastic for ameteur radio usage
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
CALL_SIGN_FIELD_NUMBER: builtins.int
TX_POWER_FIELD_NUMBER: builtins.int
FREQUENCY_FIELD_NUMBER: builtins.int
SHORT_NAME_FIELD_NUMBER: builtins.int
call_sign: builtins.str
"""
Amateur radio call sign, eg. KD2ABC
"""
tx_power: builtins.int
"""
Transmit power in dBm at the LoRA transceiver, not including any amplification
"""
frequency: builtins.float
"""
The selected frequency of LoRA operation
Please respect your local laws, regulations, and band plans.
Ensure your radio is capable of operating of the selected frequency before setting this.
"""
short_name: builtins.str
"""
Optional short name of user
"""
def __init__(
self,
*,
call_sign: builtins.str = ...,
tx_power: builtins.int = ...,
frequency: builtins.float = ...,
short_name: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["call_sign", b"call_sign", "frequency", b"frequency", "short_name", b"short_name", "tx_power", b"tx_power"]) -> None: ...
global___HamParameters = HamParameters
@typing.final
class NodeRemoteHardwarePinsResponse(google.protobuf.message.Message):
"""
Response envelope for node_remote_hardware_pins
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NODE_REMOTE_HARDWARE_PINS_FIELD_NUMBER: builtins.int
@property
def node_remote_hardware_pins(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[meshtastic.protobuf.mesh_pb2.NodeRemoteHardwarePin]:
"""
Nodes and their respective remote hardware GPIO pins
"""
def __init__(
self,
*,
node_remote_hardware_pins: collections.abc.Iterable[meshtastic.protobuf.mesh_pb2.NodeRemoteHardwarePin] | None = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["node_remote_hardware_pins", b"node_remote_hardware_pins"]) -> None: ...
global___NodeRemoteHardwarePinsResponse = NodeRemoteHardwarePinsResponse
@typing.final
class SharedContact(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NODE_NUM_FIELD_NUMBER: builtins.int
USER_FIELD_NUMBER: builtins.int
SHOULD_IGNORE_FIELD_NUMBER: builtins.int
MANUALLY_VERIFIED_FIELD_NUMBER: builtins.int
node_num: builtins.int
"""
The node number of the contact
"""
should_ignore: builtins.bool
"""
Add this contact to the blocked / ignored list
"""
manually_verified: builtins.bool
"""
Set the IS_KEY_MANUALLY_VERIFIED bit
"""
@property
def user(self) -> meshtastic.protobuf.mesh_pb2.User:
"""
The User of the contact
"""
def __init__(
self,
*,
node_num: builtins.int = ...,
user: meshtastic.protobuf.mesh_pb2.User | None = ...,
should_ignore: builtins.bool = ...,
manually_verified: builtins.bool = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["user", b"user"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["manually_verified", b"manually_verified", "node_num", b"node_num", "should_ignore", b"should_ignore", "user", b"user"]) -> None: ...
global___SharedContact = SharedContact
@typing.final
class KeyVerificationAdmin(google.protobuf.message.Message):
"""
This message is used by a client to initiate or complete a key verification
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _MessageType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _MessageTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[KeyVerificationAdmin._MessageType.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
INITIATE_VERIFICATION: KeyVerificationAdmin._MessageType.ValueType # 0
"""
This is the first stage, where a client initiates
"""
PROVIDE_SECURITY_NUMBER: KeyVerificationAdmin._MessageType.ValueType # 1
"""
After the nonce has been returned over the mesh, the client prompts for the security number
And uses this message to provide it to the node.
"""
DO_VERIFY: KeyVerificationAdmin._MessageType.ValueType # 2
"""
Once the user has compared the verification message, this message notifies the node.
"""
DO_NOT_VERIFY: KeyVerificationAdmin._MessageType.ValueType # 3
"""
This is the cancel path, can be taken at any point
"""
class MessageType(_MessageType, metaclass=_MessageTypeEnumTypeWrapper):
"""
Three stages of this request.
"""
INITIATE_VERIFICATION: KeyVerificationAdmin.MessageType.ValueType # 0
"""
This is the first stage, where a client initiates
"""
PROVIDE_SECURITY_NUMBER: KeyVerificationAdmin.MessageType.ValueType # 1
"""
After the nonce has been returned over the mesh, the client prompts for the security number
And uses this message to provide it to the node.
"""
DO_VERIFY: KeyVerificationAdmin.MessageType.ValueType # 2
"""
Once the user has compared the verification message, this message notifies the node.
"""
DO_NOT_VERIFY: KeyVerificationAdmin.MessageType.ValueType # 3
"""
This is the cancel path, can be taken at any point
"""
MESSAGE_TYPE_FIELD_NUMBER: builtins.int
REMOTE_NODENUM_FIELD_NUMBER: builtins.int
NONCE_FIELD_NUMBER: builtins.int
SECURITY_NUMBER_FIELD_NUMBER: builtins.int
message_type: global___KeyVerificationAdmin.MessageType.ValueType
remote_nodenum: builtins.int
"""
The nodenum we're requesting
"""
nonce: builtins.int
"""
The nonce is used to track the connection
"""
security_number: builtins.int
"""
The 4 digit code generated by the remote node, and communicated outside the mesh
"""
def __init__(
self,
*,
message_type: global___KeyVerificationAdmin.MessageType.ValueType = ...,
remote_nodenum: builtins.int = ...,
nonce: builtins.int = ...,
security_number: builtins.int | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_security_number", b"_security_number", "security_number", b"security_number"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_security_number", b"_security_number", "message_type", b"message_type", "nonce", b"nonce", "remote_nodenum", b"remote_nodenum", "security_number", b"security_number"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["_security_number", b"_security_number"]) -> typing.Literal["security_number"] | None: ...
global___KeyVerificationAdmin = KeyVerificationAdmin

View File

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/apponly.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import channel_pb2 as meshtastic_dot_protobuf_dot_channel__pb2
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!meshtastic/protobuf/apponly.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\"\x81\x01\n\nChannelSet\x12\x36\n\x08settings\x18\x01 \x03(\x0b\x32$.meshtastic.protobuf.ChannelSettings\x12;\n\x0blora_config\x18\x02 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfigBc\n\x14org.meshtastic.protoB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.apponly_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_CHANNELSET']._serialized_start=128
_globals['_CHANNELSET']._serialized_end=257
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,52 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import collections.abc
import google.protobuf.descriptor
import google.protobuf.internal.containers
import google.protobuf.message
import meshtastic.protobuf.channel_pb2
import meshtastic.protobuf.config_pb2
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class ChannelSet(google.protobuf.message.Message):
"""
This is the most compact possible representation for a set of channels.
It includes only one PRIMARY channel (which must be first) and
any SECONDARY channels.
No DISABLED channels are included.
This abstraction is used only on the the 'app side' of the world (ie python, javascript and android etc) to show a group of Channels as a (long) URL
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
SETTINGS_FIELD_NUMBER: builtins.int
LORA_CONFIG_FIELD_NUMBER: builtins.int
@property
def settings(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[meshtastic.protobuf.channel_pb2.ChannelSettings]:
"""
Channel list with settings
"""
@property
def lora_config(self) -> meshtastic.protobuf.config_pb2.Config.LoRaConfig:
"""
LoRa config
"""
def __init__(
self,
*,
settings: collections.abc.Iterable[meshtastic.protobuf.channel_pb2.ChannelSettings] | None = ...,
lora_config: meshtastic.protobuf.config_pb2.Config.LoRaConfig | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["lora_config", b"lora_config"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["lora_config", b"lora_config", "settings", b"settings"]) -> None: ...
global___ChannelSet = ChannelSet

View File

@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/atak.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/atak.proto\x12\x13meshtastic.protobuf\"\xa5\x02\n\tTAKPacket\x12\x15\n\ris_compressed\x18\x01 \x01(\x08\x12-\n\x07\x63ontact\x18\x02 \x01(\x0b\x32\x1c.meshtastic.protobuf.Contact\x12)\n\x05group\x18\x03 \x01(\x0b\x32\x1a.meshtastic.protobuf.Group\x12+\n\x06status\x18\x04 \x01(\x0b\x32\x1b.meshtastic.protobuf.Status\x12\'\n\x03pli\x18\x05 \x01(\x0b\x32\x18.meshtastic.protobuf.PLIH\x00\x12,\n\x04\x63hat\x18\x06 \x01(\x0b\x32\x1c.meshtastic.protobuf.GeoChatH\x00\x12\x10\n\x06\x64\x65tail\x18\x07 \x01(\x0cH\x00\x42\x11\n\x0fpayload_variant\"\\\n\x07GeoChat\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0f\n\x02to\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0bto_callsign\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x05\n\x03_toB\x0e\n\x0c_to_callsign\"_\n\x05Group\x12-\n\x04role\x18\x01 \x01(\x0e\x32\x1f.meshtastic.protobuf.MemberRole\x12\'\n\x04team\x18\x02 \x01(\x0e\x32\x19.meshtastic.protobuf.Team\"\x19\n\x06Status\x12\x0f\n\x07\x62\x61ttery\x18\x01 \x01(\r\"4\n\x07\x43ontact\x12\x10\n\x08\x63\x61llsign\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65vice_callsign\x18\x02 \x01(\t\"_\n\x03PLI\x12\x12\n\nlatitude_i\x18\x01 \x01(\x0f\x12\x13\n\x0blongitude_i\x18\x02 \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\r\n\x05speed\x18\x04 \x01(\r\x12\x0e\n\x06\x63ourse\x18\x05 \x01(\r*\xc0\x01\n\x04Team\x12\x14\n\x10Unspecifed_Color\x10\x00\x12\t\n\x05White\x10\x01\x12\n\n\x06Yellow\x10\x02\x12\n\n\x06Orange\x10\x03\x12\x0b\n\x07Magenta\x10\x04\x12\x07\n\x03Red\x10\x05\x12\n\n\x06Maroon\x10\x06\x12\n\n\x06Purple\x10\x07\x12\r\n\tDark_Blue\x10\x08\x12\x08\n\x04\x42lue\x10\t\x12\x08\n\x04\x43yan\x10\n\x12\x08\n\x04Teal\x10\x0b\x12\t\n\x05Green\x10\x0c\x12\x0e\n\nDark_Green\x10\r\x12\t\n\x05\x42rown\x10\x0e*\x7f\n\nMemberRole\x12\x0e\n\nUnspecifed\x10\x00\x12\x0e\n\nTeamMember\x10\x01\x12\x0c\n\x08TeamLead\x10\x02\x12\x06\n\x02HQ\x10\x03\x12\n\n\x06Sniper\x10\x04\x12\t\n\x05Medic\x10\x05\x12\x13\n\x0f\x46orwardObserver\x10\x06\x12\x07\n\x03RTO\x10\x07\x12\x06\n\x02K9\x10\x08\x42`\n\x14org.meshtastic.protoB\nATAKProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.atak_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\nATAKProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_TEAM']._serialized_start=721
_globals['_TEAM']._serialized_end=913
_globals['_MEMBERROLE']._serialized_start=915
_globals['_MEMBERROLE']._serialized_end=1042
_globals['_TAKPACKET']._serialized_start=56
_globals['_TAKPACKET']._serialized_end=349
_globals['_GEOCHAT']._serialized_start=351
_globals['_GEOCHAT']._serialized_end=443
_globals['_GROUP']._serialized_start=445
_globals['_GROUP']._serialized_end=540
_globals['_STATUS']._serialized_start=542
_globals['_STATUS']._serialized_end=567
_globals['_CONTACT']._serialized_start=569
_globals['_CONTACT']._serialized_end=621
_globals['_PLI']._serialized_start=623
_globals['_PLI']._serialized_end=718
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,477 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _Team:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _TeamEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_Team.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
Unspecifed_Color: _Team.ValueType # 0
"""
Unspecifed
"""
White: _Team.ValueType # 1
"""
White
"""
Yellow: _Team.ValueType # 2
"""
Yellow
"""
Orange: _Team.ValueType # 3
"""
Orange
"""
Magenta: _Team.ValueType # 4
"""
Magenta
"""
Red: _Team.ValueType # 5
"""
Red
"""
Maroon: _Team.ValueType # 6
"""
Maroon
"""
Purple: _Team.ValueType # 7
"""
Purple
"""
Dark_Blue: _Team.ValueType # 8
"""
Dark Blue
"""
Blue: _Team.ValueType # 9
"""
Blue
"""
Cyan: _Team.ValueType # 10
"""
Cyan
"""
Teal: _Team.ValueType # 11
"""
Teal
"""
Green: _Team.ValueType # 12
"""
Green
"""
Dark_Green: _Team.ValueType # 13
"""
Dark Green
"""
Brown: _Team.ValueType # 14
"""
Brown
"""
class Team(_Team, metaclass=_TeamEnumTypeWrapper): ...
Unspecifed_Color: Team.ValueType # 0
"""
Unspecifed
"""
White: Team.ValueType # 1
"""
White
"""
Yellow: Team.ValueType # 2
"""
Yellow
"""
Orange: Team.ValueType # 3
"""
Orange
"""
Magenta: Team.ValueType # 4
"""
Magenta
"""
Red: Team.ValueType # 5
"""
Red
"""
Maroon: Team.ValueType # 6
"""
Maroon
"""
Purple: Team.ValueType # 7
"""
Purple
"""
Dark_Blue: Team.ValueType # 8
"""
Dark Blue
"""
Blue: Team.ValueType # 9
"""
Blue
"""
Cyan: Team.ValueType # 10
"""
Cyan
"""
Teal: Team.ValueType # 11
"""
Teal
"""
Green: Team.ValueType # 12
"""
Green
"""
Dark_Green: Team.ValueType # 13
"""
Dark Green
"""
Brown: Team.ValueType # 14
"""
Brown
"""
global___Team = Team
class _MemberRole:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _MemberRoleEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_MemberRole.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
Unspecifed: _MemberRole.ValueType # 0
"""
Unspecifed
"""
TeamMember: _MemberRole.ValueType # 1
"""
Team Member
"""
TeamLead: _MemberRole.ValueType # 2
"""
Team Lead
"""
HQ: _MemberRole.ValueType # 3
"""
Headquarters
"""
Sniper: _MemberRole.ValueType # 4
"""
Airsoft enthusiast
"""
Medic: _MemberRole.ValueType # 5
"""
Medic
"""
ForwardObserver: _MemberRole.ValueType # 6
"""
ForwardObserver
"""
RTO: _MemberRole.ValueType # 7
"""
Radio Telephone Operator
"""
K9: _MemberRole.ValueType # 8
"""
Doggo
"""
class MemberRole(_MemberRole, metaclass=_MemberRoleEnumTypeWrapper):
"""
Role of the group member
"""
Unspecifed: MemberRole.ValueType # 0
"""
Unspecifed
"""
TeamMember: MemberRole.ValueType # 1
"""
Team Member
"""
TeamLead: MemberRole.ValueType # 2
"""
Team Lead
"""
HQ: MemberRole.ValueType # 3
"""
Headquarters
"""
Sniper: MemberRole.ValueType # 4
"""
Airsoft enthusiast
"""
Medic: MemberRole.ValueType # 5
"""
Medic
"""
ForwardObserver: MemberRole.ValueType # 6
"""
ForwardObserver
"""
RTO: MemberRole.ValueType # 7
"""
Radio Telephone Operator
"""
K9: MemberRole.ValueType # 8
"""
Doggo
"""
global___MemberRole = MemberRole
@typing.final
class TAKPacket(google.protobuf.message.Message):
"""
Packets for the official ATAK Plugin
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
IS_COMPRESSED_FIELD_NUMBER: builtins.int
CONTACT_FIELD_NUMBER: builtins.int
GROUP_FIELD_NUMBER: builtins.int
STATUS_FIELD_NUMBER: builtins.int
PLI_FIELD_NUMBER: builtins.int
CHAT_FIELD_NUMBER: builtins.int
DETAIL_FIELD_NUMBER: builtins.int
is_compressed: builtins.bool
"""
Are the payloads strings compressed for LoRA transport?
"""
detail: builtins.bytes
"""
Generic CoT detail XML
May be compressed / truncated by the sender (EUD)
"""
@property
def contact(self) -> global___Contact:
"""
The contact / callsign for ATAK user
"""
@property
def group(self) -> global___Group:
"""
The group for ATAK user
"""
@property
def status(self) -> global___Status:
"""
The status of the ATAK EUD
"""
@property
def pli(self) -> global___PLI:
"""
TAK position report
"""
@property
def chat(self) -> global___GeoChat:
"""
ATAK GeoChat message
"""
def __init__(
self,
*,
is_compressed: builtins.bool = ...,
contact: global___Contact | None = ...,
group: global___Group | None = ...,
status: global___Status | None = ...,
pli: global___PLI | None = ...,
chat: global___GeoChat | None = ...,
detail: builtins.bytes = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["chat", b"chat", "contact", b"contact", "detail", b"detail", "group", b"group", "payload_variant", b"payload_variant", "pli", b"pli", "status", b"status"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["chat", b"chat", "contact", b"contact", "detail", b"detail", "group", b"group", "is_compressed", b"is_compressed", "payload_variant", b"payload_variant", "pli", b"pli", "status", b"status"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["pli", "chat", "detail"] | None: ...
global___TAKPacket = TAKPacket
@typing.final
class GeoChat(google.protobuf.message.Message):
"""
ATAK GeoChat message
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MESSAGE_FIELD_NUMBER: builtins.int
TO_FIELD_NUMBER: builtins.int
TO_CALLSIGN_FIELD_NUMBER: builtins.int
message: builtins.str
"""
The text message
"""
to: builtins.str
"""
Uid recipient of the message
"""
to_callsign: builtins.str
"""
Callsign of the recipient for the message
"""
def __init__(
self,
*,
message: builtins.str = ...,
to: builtins.str | None = ...,
to_callsign: builtins.str | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_to", b"_to", "_to_callsign", b"_to_callsign", "to", b"to", "to_callsign", b"to_callsign"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_to", b"_to", "_to_callsign", b"_to_callsign", "message", b"message", "to", b"to", "to_callsign", b"to_callsign"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_to", b"_to"]) -> typing.Literal["to"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_to_callsign", b"_to_callsign"]) -> typing.Literal["to_callsign"] | None: ...
global___GeoChat = GeoChat
@typing.final
class Group(google.protobuf.message.Message):
"""
ATAK Group
<__group role='Team Member' name='Cyan'/>
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
ROLE_FIELD_NUMBER: builtins.int
TEAM_FIELD_NUMBER: builtins.int
role: global___MemberRole.ValueType
"""
Role of the group member
"""
team: global___Team.ValueType
"""
Team (color)
Default Cyan
"""
def __init__(
self,
*,
role: global___MemberRole.ValueType = ...,
team: global___Team.ValueType = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["role", b"role", "team", b"team"]) -> None: ...
global___Group = Group
@typing.final
class Status(google.protobuf.message.Message):
"""
ATAK EUD Status
<status battery='100' />
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
BATTERY_FIELD_NUMBER: builtins.int
battery: builtins.int
"""
Battery level
"""
def __init__(
self,
*,
battery: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["battery", b"battery"]) -> None: ...
global___Status = Status
@typing.final
class Contact(google.protobuf.message.Message):
"""
ATAK Contact
<contact endpoint='0.0.0.0:4242:tcp' phone='+12345678' callsign='FALKE'/>
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
CALLSIGN_FIELD_NUMBER: builtins.int
DEVICE_CALLSIGN_FIELD_NUMBER: builtins.int
callsign: builtins.str
"""
Callsign
"""
device_callsign: builtins.str
"""
Device callsign
IP address of endpoint in integer form (0.0.0.0 default)
"""
def __init__(
self,
*,
callsign: builtins.str = ...,
device_callsign: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["callsign", b"callsign", "device_callsign", b"device_callsign"]) -> None: ...
global___Contact = Contact
@typing.final
class PLI(google.protobuf.message.Message):
"""
Position Location Information from ATAK
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
LATITUDE_I_FIELD_NUMBER: builtins.int
LONGITUDE_I_FIELD_NUMBER: builtins.int
ALTITUDE_FIELD_NUMBER: builtins.int
SPEED_FIELD_NUMBER: builtins.int
COURSE_FIELD_NUMBER: builtins.int
latitude_i: builtins.int
"""
The new preferred location encoding, multiply by 1e-7 to get degrees
in floating point
"""
longitude_i: builtins.int
"""
The new preferred location encoding, multiply by 1e-7 to get degrees
in floating point
"""
altitude: builtins.int
"""
Altitude (ATAK prefers HAE)
"""
speed: builtins.int
"""
Speed
"""
course: builtins.int
"""
Course in degrees
"""
def __init__(
self,
*,
latitude_i: builtins.int = ...,
longitude_i: builtins.int = ...,
altitude: builtins.int = ...,
speed: builtins.int = ...,
course: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["altitude", b"altitude", "course", b"course", "latitude_i", b"latitude_i", "longitude_i", b"longitude_i", "speed", b"speed"]) -> None: ...
global___PLI = PLI

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/cannedmessages.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(meshtastic/protobuf/cannedmessages.proto\x12\x13meshtastic.protobuf\"-\n\x19\x43\x61nnedMessageModuleConfig\x12\x10\n\x08messages\x18\x01 \x01(\tBo\n\x14org.meshtastic.protoB\x19\x43\x61nnedMessageConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.cannedmessages_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\031CannedMessageConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_CANNEDMESSAGEMODULECONFIG']._serialized_start=65
_globals['_CANNEDMESSAGEMODULECONFIG']._serialized_end=110
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,33 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.message
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class CannedMessageModuleConfig(google.protobuf.message.Message):
"""
Canned message module configuration.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MESSAGES_FIELD_NUMBER: builtins.int
messages: builtins.str
"""
Predefined messages for canned message module separated by '|' characters.
"""
def __init__(
self,
*,
messages: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["messages", b"messages"]) -> None: ...
global___CannedMessageModuleConfig = CannedMessageModuleConfig

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/channel.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!meshtastic/protobuf/channel.proto\x12\x13meshtastic.protobuf\"\xc1\x01\n\x0f\x43hannelSettings\x12\x17\n\x0b\x63hannel_num\x18\x01 \x01(\rB\x02\x18\x01\x12\x0b\n\x03psk\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\n\n\x02id\x18\x04 \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x05 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x06 \x01(\x08\x12<\n\x0fmodule_settings\x18\x07 \x01(\x0b\x32#.meshtastic.protobuf.ModuleSettings\">\n\x0eModuleSettings\x12\x1a\n\x12position_precision\x18\x01 \x01(\r\x12\x10\n\x08is_muted\x18\x02 \x01(\x08\"\xb3\x01\n\x07\x43hannel\x12\r\n\x05index\x18\x01 \x01(\x05\x12\x36\n\x08settings\x18\x02 \x01(\x0b\x32$.meshtastic.protobuf.ChannelSettings\x12/\n\x04role\x18\x03 \x01(\x0e\x32!.meshtastic.protobuf.Channel.Role\"0\n\x04Role\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07PRIMARY\x10\x01\x12\r\n\tSECONDARY\x10\x02\x42\x63\n\x14org.meshtastic.protoB\rChannelProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.channel_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\rChannelProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_CHANNELSETTINGS.fields_by_name['channel_num']._options = None
_CHANNELSETTINGS.fields_by_name['channel_num']._serialized_options = b'\030\001'
_globals['_CHANNELSETTINGS']._serialized_start=59
_globals['_CHANNELSETTINGS']._serialized_end=252
_globals['_MODULESETTINGS']._serialized_start=254
_globals['_MODULESETTINGS']._serialized_end=316
_globals['_CHANNEL']._serialized_start=319
_globals['_CHANNEL']._serialized_end=498
_globals['_CHANNEL_ROLE']._serialized_start=450
_globals['_CHANNEL_ROLE']._serialized_end=498
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,234 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class ChannelSettings(google.protobuf.message.Message):
"""
This information can be encoded as a QRcode/url so that other users can configure
their radio to join the same channel.
A note about how channel names are shown to users: channelname-X
poundsymbol is a prefix used to indicate this is a channel name (idea from @professr).
Where X is a letter from A-Z (base 26) representing a hash of the PSK for this
channel - so that if the user changes anything about the channel (which does
force a new PSK) this letter will also change. Thus preventing user confusion if
two friends try to type in a channel name of "BobsChan" and then can't talk
because their PSKs will be different.
The PSK is hashed into this letter by "0x41 + [xor all bytes of the psk ] modulo 26"
This also allows the option of someday if people have the PSK off (zero), the
users COULD type in a channel name and be able to talk.
FIXME: Add description of multi-channel support and how primary vs secondary channels are used.
FIXME: explain how apps use channels for security.
explain how remote settings and remote gpio are managed as an example
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
CHANNEL_NUM_FIELD_NUMBER: builtins.int
PSK_FIELD_NUMBER: builtins.int
NAME_FIELD_NUMBER: builtins.int
ID_FIELD_NUMBER: builtins.int
UPLINK_ENABLED_FIELD_NUMBER: builtins.int
DOWNLINK_ENABLED_FIELD_NUMBER: builtins.int
MODULE_SETTINGS_FIELD_NUMBER: builtins.int
channel_num: builtins.int
"""
Deprecated in favor of LoraConfig.channel_num
"""
psk: builtins.bytes
"""
A simple pre-shared key for now for crypto.
Must be either 0 bytes (no crypto), 16 bytes (AES128), or 32 bytes (AES256).
A special shorthand is used for 1 byte long psks.
These psks should be treated as only minimally secure,
because they are listed in this source code.
Those bytes are mapped using the following scheme:
`0` = No crypto
`1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01}
`2` through 10 = The default channel key, except with 1 through 9 added to the last byte.
Shown to user as simple1 through 10
"""
name: builtins.str
"""
A SHORT name that will be packed into the URL.
Less than 12 bytes.
Something for end users to call the channel
If this is the empty string it is assumed that this channel
is the special (minimally secure) "Default"channel.
In user interfaces it should be rendered as a local language translation of "X".
For channel_num hashing empty string will be treated as "X".
Where "X" is selected based on the English words listed above for ModemPreset
"""
id: builtins.int
"""
Used to construct a globally unique channel ID.
The full globally unique ID will be: "name.id" where ID is shown as base36.
Assuming that the number of meshtastic users is below 20K (true for a long time)
the chance of this 64 bit random number colliding with anyone else is super low.
And the penalty for collision is low as well, it just means that anyone trying to decrypt channel messages might need to
try multiple candidate channels.
Any time a non wire compatible change is made to a channel, this field should be regenerated.
There are a small number of 'special' globally known (and fairly) insecure standard channels.
Those channels do not have a numeric id included in the settings, but instead it is pulled from
a table of well known IDs.
(see Well Known Channels FIXME)
"""
uplink_enabled: builtins.bool
"""
If true, messages on the mesh will be sent to the *public* internet by any gateway ndoe
"""
downlink_enabled: builtins.bool
"""
If true, messages seen on the internet will be forwarded to the local mesh.
"""
@property
def module_settings(self) -> global___ModuleSettings:
"""
Per-channel module settings.
"""
def __init__(
self,
*,
channel_num: builtins.int = ...,
psk: builtins.bytes = ...,
name: builtins.str = ...,
id: builtins.int = ...,
uplink_enabled: builtins.bool = ...,
downlink_enabled: builtins.bool = ...,
module_settings: global___ModuleSettings | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["module_settings", b"module_settings"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["channel_num", b"channel_num", "downlink_enabled", b"downlink_enabled", "id", b"id", "module_settings", b"module_settings", "name", b"name", "psk", b"psk", "uplink_enabled", b"uplink_enabled"]) -> None: ...
global___ChannelSettings = ChannelSettings
@typing.final
class ModuleSettings(google.protobuf.message.Message):
"""
This message is specifically for modules to store per-channel configuration data.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
POSITION_PRECISION_FIELD_NUMBER: builtins.int
IS_MUTED_FIELD_NUMBER: builtins.int
position_precision: builtins.int
"""
Bits of precision for the location sent in position packets.
"""
is_muted: builtins.bool
"""
Controls whether or not the client / device should mute the current channel
Useful for noisy public channels you don't necessarily want to disable
"""
def __init__(
self,
*,
position_precision: builtins.int = ...,
is_muted: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["is_muted", b"is_muted", "position_precision", b"position_precision"]) -> None: ...
global___ModuleSettings = ModuleSettings
@typing.final
class Channel(google.protobuf.message.Message):
"""
A pair of a channel number, mode and the (sharable) settings for that channel
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _Role:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _RoleEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Channel._Role.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
DISABLED: Channel._Role.ValueType # 0
"""
This channel is not in use right now
"""
PRIMARY: Channel._Role.ValueType # 1
"""
This channel is used to set the frequency for the radio - all other enabled channels must be SECONDARY
"""
SECONDARY: Channel._Role.ValueType # 2
"""
Secondary channels are only used for encryption/decryption/authentication purposes.
Their radio settings (freq etc) are ignored, only psk is used.
"""
class Role(_Role, metaclass=_RoleEnumTypeWrapper):
"""
How this channel is being used (or not).
Note: this field is an enum to give us options for the future.
In particular, someday we might make a 'SCANNING' option.
SCANNING channels could have different frequencies and the radio would
occasionally check that freq to see if anything is being transmitted.
For devices that have multiple physical radios attached, we could keep multiple PRIMARY/SCANNING channels active at once to allow
cross band routing as needed.
If a device has only a single radio (the common case) only one channel can be PRIMARY at a time
(but any number of SECONDARY channels can't be sent received on that common frequency)
"""
DISABLED: Channel.Role.ValueType # 0
"""
This channel is not in use right now
"""
PRIMARY: Channel.Role.ValueType # 1
"""
This channel is used to set the frequency for the radio - all other enabled channels must be SECONDARY
"""
SECONDARY: Channel.Role.ValueType # 2
"""
Secondary channels are only used for encryption/decryption/authentication purposes.
Their radio settings (freq etc) are ignored, only psk is used.
"""
INDEX_FIELD_NUMBER: builtins.int
SETTINGS_FIELD_NUMBER: builtins.int
ROLE_FIELD_NUMBER: builtins.int
index: builtins.int
"""
The index of this channel in the channel table (from 0 to MAX_NUM_CHANNELS-1)
(Someday - not currently implemented) An index of -1 could be used to mean "set by name",
in which case the target node will find and set the channel by settings.name.
"""
role: global___Channel.Role.ValueType
"""
TODO: REPLACE
"""
@property
def settings(self) -> global___ChannelSettings:
"""
The new settings, or NULL to disable that channel
"""
def __init__(
self,
*,
index: builtins.int = ...,
settings: global___ChannelSettings | None = ...,
role: global___Channel.Role.ValueType = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["settings", b"settings"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["index", b"index", "role", b"role", "settings", b"settings"]) -> None: ...
global___Channel = Channel

View File

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/clientonly.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_localonly__pb2
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/clientonly.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/localonly.proto\x1a\x1emeshtastic/protobuf/mesh.proto\"\xc4\x03\n\rDeviceProfile\x12\x16\n\tlong_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nshort_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x63hannel_url\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x35\n\x06\x63onfig\x18\x04 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfigH\x03\x88\x01\x01\x12\x42\n\rmodule_config\x18\x05 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfigH\x04\x88\x01\x01\x12:\n\x0e\x66ixed_position\x18\x06 \x01(\x0b\x32\x1d.meshtastic.protobuf.PositionH\x05\x88\x01\x01\x12\x15\n\x08ringtone\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x1c\n\x0f\x63\x61nned_messages\x18\x08 \x01(\tH\x07\x88\x01\x01\x42\x0c\n\n_long_nameB\r\n\x0b_short_nameB\x0e\n\x0c_channel_urlB\t\n\x07_configB\x10\n\x0e_module_configB\x11\n\x0f_fixed_positionB\x0b\n\t_ringtoneB\x12\n\x10_canned_messagesBf\n\x14org.meshtastic.protoB\x10\x43lientOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.clientonly_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\020ClientOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_DEVICEPROFILE']._serialized_start=131
_globals['_DEVICEPROFILE']._serialized_end=583
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,101 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.message
import meshtastic.protobuf.localonly_pb2
import meshtastic.protobuf.mesh_pb2
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class DeviceProfile(google.protobuf.message.Message):
"""
This abstraction is used to contain any configuration for provisioning a node on any client.
It is useful for importing and exporting configurations.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
LONG_NAME_FIELD_NUMBER: builtins.int
SHORT_NAME_FIELD_NUMBER: builtins.int
CHANNEL_URL_FIELD_NUMBER: builtins.int
CONFIG_FIELD_NUMBER: builtins.int
MODULE_CONFIG_FIELD_NUMBER: builtins.int
FIXED_POSITION_FIELD_NUMBER: builtins.int
RINGTONE_FIELD_NUMBER: builtins.int
CANNED_MESSAGES_FIELD_NUMBER: builtins.int
long_name: builtins.str
"""
Long name for the node
"""
short_name: builtins.str
"""
Short name of the node
"""
channel_url: builtins.str
"""
The url of the channels from our node
"""
ringtone: builtins.str
"""
Ringtone for ExternalNotification
"""
canned_messages: builtins.str
"""
Predefined messages for CannedMessage
"""
@property
def config(self) -> meshtastic.protobuf.localonly_pb2.LocalConfig:
"""
The Config of the node
"""
@property
def module_config(self) -> meshtastic.protobuf.localonly_pb2.LocalModuleConfig:
"""
The ModuleConfig of the node
"""
@property
def fixed_position(self) -> meshtastic.protobuf.mesh_pb2.Position:
"""
Fixed position data
"""
def __init__(
self,
*,
long_name: builtins.str | None = ...,
short_name: builtins.str | None = ...,
channel_url: builtins.str | None = ...,
config: meshtastic.protobuf.localonly_pb2.LocalConfig | None = ...,
module_config: meshtastic.protobuf.localonly_pb2.LocalModuleConfig | None = ...,
fixed_position: meshtastic.protobuf.mesh_pb2.Position | None = ...,
ringtone: builtins.str | None = ...,
canned_messages: builtins.str | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_canned_messages", b"_canned_messages", "_channel_url", b"_channel_url", "_config", b"_config", "_fixed_position", b"_fixed_position", "_long_name", b"_long_name", "_module_config", b"_module_config", "_ringtone", b"_ringtone", "_short_name", b"_short_name", "canned_messages", b"canned_messages", "channel_url", b"channel_url", "config", b"config", "fixed_position", b"fixed_position", "long_name", b"long_name", "module_config", b"module_config", "ringtone", b"ringtone", "short_name", b"short_name"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_canned_messages", b"_canned_messages", "_channel_url", b"_channel_url", "_config", b"_config", "_fixed_position", b"_fixed_position", "_long_name", b"_long_name", "_module_config", b"_module_config", "_ringtone", b"_ringtone", "_short_name", b"_short_name", "canned_messages", b"canned_messages", "channel_url", b"channel_url", "config", b"config", "fixed_position", b"fixed_position", "long_name", b"long_name", "module_config", b"module_config", "ringtone", b"ringtone", "short_name", b"short_name"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_canned_messages", b"_canned_messages"]) -> typing.Literal["canned_messages"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_channel_url", b"_channel_url"]) -> typing.Literal["channel_url"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_config", b"_config"]) -> typing.Literal["config"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_fixed_position", b"_fixed_position"]) -> typing.Literal["fixed_position"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_long_name", b"_long_name"]) -> typing.Literal["long_name"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_module_config", b"_module_config"]) -> typing.Literal["module_config"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ringtone", b"_ringtone"]) -> typing.Literal["ringtone"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_short_name", b"_short_name"]) -> typing.Literal["short_name"] | None: ...
global___DeviceProfile = DeviceProfile

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/connection_status.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n+meshtastic/protobuf/connection_status.proto\x12\x13meshtastic.protobuf\"\xd5\x02\n\x16\x44\x65viceConnectionStatus\x12<\n\x04wifi\x18\x01 \x01(\x0b\x32).meshtastic.protobuf.WifiConnectionStatusH\x00\x88\x01\x01\x12\x44\n\x08\x65thernet\x18\x02 \x01(\x0b\x32-.meshtastic.protobuf.EthernetConnectionStatusH\x01\x88\x01\x01\x12\x46\n\tbluetooth\x18\x03 \x01(\x0b\x32..meshtastic.protobuf.BluetoothConnectionStatusH\x02\x88\x01\x01\x12@\n\x06serial\x18\x04 \x01(\x0b\x32+.meshtastic.protobuf.SerialConnectionStatusH\x03\x88\x01\x01\x42\x07\n\x05_wifiB\x0b\n\t_ethernetB\x0c\n\n_bluetoothB\t\n\x07_serial\"p\n\x14WifiConnectionStatus\x12<\n\x06status\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.NetworkConnectionStatus\x12\x0c\n\x04ssid\x18\x02 \x01(\t\x12\x0c\n\x04rssi\x18\x03 \x01(\x05\"X\n\x18\x45thernetConnectionStatus\x12<\n\x06status\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.NetworkConnectionStatus\"{\n\x17NetworkConnectionStatus\x12\x12\n\nip_address\x18\x01 \x01(\x07\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x12\x19\n\x11is_mqtt_connected\x18\x03 \x01(\x08\x12\x1b\n\x13is_syslog_connected\x18\x04 \x01(\x08\"L\n\x19\x42luetoothConnectionStatus\x12\x0b\n\x03pin\x18\x01 \x01(\r\x12\x0c\n\x04rssi\x18\x02 \x01(\x05\x12\x14\n\x0cis_connected\x18\x03 \x01(\x08\"<\n\x16SerialConnectionStatus\x12\x0c\n\x04\x62\x61ud\x18\x01 \x01(\r\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x42\x66\n\x14org.meshtastic.protoB\x10\x43onnStatusProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.connection_status_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\020ConnStatusProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_DEVICECONNECTIONSTATUS']._serialized_start=69
_globals['_DEVICECONNECTIONSTATUS']._serialized_end=410
_globals['_WIFICONNECTIONSTATUS']._serialized_start=412
_globals['_WIFICONNECTIONSTATUS']._serialized_end=524
_globals['_ETHERNETCONNECTIONSTATUS']._serialized_start=526
_globals['_ETHERNETCONNECTIONSTATUS']._serialized_end=614
_globals['_NETWORKCONNECTIONSTATUS']._serialized_start=616
_globals['_NETWORKCONNECTIONSTATUS']._serialized_end=739
_globals['_BLUETOOTHCONNECTIONSTATUS']._serialized_start=741
_globals['_BLUETOOTHCONNECTIONSTATUS']._serialized_end=817
_globals['_SERIALCONNECTIONSTATUS']._serialized_start=819
_globals['_SERIALCONNECTIONSTATUS']._serialized_end=879
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,228 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.message
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class DeviceConnectionStatus(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
WIFI_FIELD_NUMBER: builtins.int
ETHERNET_FIELD_NUMBER: builtins.int
BLUETOOTH_FIELD_NUMBER: builtins.int
SERIAL_FIELD_NUMBER: builtins.int
@property
def wifi(self) -> global___WifiConnectionStatus:
"""
WiFi Status
"""
@property
def ethernet(self) -> global___EthernetConnectionStatus:
"""
WiFi Status
"""
@property
def bluetooth(self) -> global___BluetoothConnectionStatus:
"""
Bluetooth Status
"""
@property
def serial(self) -> global___SerialConnectionStatus:
"""
Serial Status
"""
def __init__(
self,
*,
wifi: global___WifiConnectionStatus | None = ...,
ethernet: global___EthernetConnectionStatus | None = ...,
bluetooth: global___BluetoothConnectionStatus | None = ...,
serial: global___SerialConnectionStatus | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_bluetooth", b"_bluetooth", "_ethernet", b"_ethernet", "_serial", b"_serial", "_wifi", b"_wifi", "bluetooth", b"bluetooth", "ethernet", b"ethernet", "serial", b"serial", "wifi", b"wifi"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_bluetooth", b"_bluetooth", "_ethernet", b"_ethernet", "_serial", b"_serial", "_wifi", b"_wifi", "bluetooth", b"bluetooth", "ethernet", b"ethernet", "serial", b"serial", "wifi", b"wifi"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_bluetooth", b"_bluetooth"]) -> typing.Literal["bluetooth"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ethernet", b"_ethernet"]) -> typing.Literal["ethernet"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_serial", b"_serial"]) -> typing.Literal["serial"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_wifi", b"_wifi"]) -> typing.Literal["wifi"] | None: ...
global___DeviceConnectionStatus = DeviceConnectionStatus
@typing.final
class WifiConnectionStatus(google.protobuf.message.Message):
"""
WiFi connection status
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
STATUS_FIELD_NUMBER: builtins.int
SSID_FIELD_NUMBER: builtins.int
RSSI_FIELD_NUMBER: builtins.int
ssid: builtins.str
"""
WiFi access point SSID
"""
rssi: builtins.int
"""
RSSI of wireless connection
"""
@property
def status(self) -> global___NetworkConnectionStatus:
"""
Connection status
"""
def __init__(
self,
*,
status: global___NetworkConnectionStatus | None = ...,
ssid: builtins.str = ...,
rssi: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["status", b"status"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["rssi", b"rssi", "ssid", b"ssid", "status", b"status"]) -> None: ...
global___WifiConnectionStatus = WifiConnectionStatus
@typing.final
class EthernetConnectionStatus(google.protobuf.message.Message):
"""
Ethernet connection status
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
STATUS_FIELD_NUMBER: builtins.int
@property
def status(self) -> global___NetworkConnectionStatus:
"""
Connection status
"""
def __init__(
self,
*,
status: global___NetworkConnectionStatus | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["status", b"status"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["status", b"status"]) -> None: ...
global___EthernetConnectionStatus = EthernetConnectionStatus
@typing.final
class NetworkConnectionStatus(google.protobuf.message.Message):
"""
Ethernet or WiFi connection status
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
IP_ADDRESS_FIELD_NUMBER: builtins.int
IS_CONNECTED_FIELD_NUMBER: builtins.int
IS_MQTT_CONNECTED_FIELD_NUMBER: builtins.int
IS_SYSLOG_CONNECTED_FIELD_NUMBER: builtins.int
ip_address: builtins.int
"""
IP address of device
"""
is_connected: builtins.bool
"""
Whether the device has an active connection or not
"""
is_mqtt_connected: builtins.bool
"""
Whether the device has an active connection to an MQTT broker or not
"""
is_syslog_connected: builtins.bool
"""
Whether the device is actively remote syslogging or not
"""
def __init__(
self,
*,
ip_address: builtins.int = ...,
is_connected: builtins.bool = ...,
is_mqtt_connected: builtins.bool = ...,
is_syslog_connected: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["ip_address", b"ip_address", "is_connected", b"is_connected", "is_mqtt_connected", b"is_mqtt_connected", "is_syslog_connected", b"is_syslog_connected"]) -> None: ...
global___NetworkConnectionStatus = NetworkConnectionStatus
@typing.final
class BluetoothConnectionStatus(google.protobuf.message.Message):
"""
Bluetooth connection status
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
PIN_FIELD_NUMBER: builtins.int
RSSI_FIELD_NUMBER: builtins.int
IS_CONNECTED_FIELD_NUMBER: builtins.int
pin: builtins.int
"""
The pairing PIN for bluetooth
"""
rssi: builtins.int
"""
RSSI of bluetooth connection
"""
is_connected: builtins.bool
"""
Whether the device has an active connection or not
"""
def __init__(
self,
*,
pin: builtins.int = ...,
rssi: builtins.int = ...,
is_connected: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["is_connected", b"is_connected", "pin", b"pin", "rssi", b"rssi"]) -> None: ...
global___BluetoothConnectionStatus = BluetoothConnectionStatus
@typing.final
class SerialConnectionStatus(google.protobuf.message.Message):
"""
Serial connection status
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
BAUD_FIELD_NUMBER: builtins.int
IS_CONNECTED_FIELD_NUMBER: builtins.int
baud: builtins.int
"""
Serial baud rate
"""
is_connected: builtins.bool
"""
Whether the device has an active connection or not
"""
def __init__(
self,
*,
baud: builtins.int = ...,
is_connected: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["baud", b"baud", "is_connected", b"is_connected"]) -> None: ...
global___SerialConnectionStatus = SerialConnectionStatus

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/device_ui.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/device_ui.proto\x12\x13meshtastic.protobuf\"\xff\x05\n\x0e\x44\x65viceUIConfig\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x19\n\x11screen_brightness\x18\x02 \x01(\r\x12\x16\n\x0escreen_timeout\x18\x03 \x01(\r\x12\x13\n\x0bscreen_lock\x18\x04 \x01(\x08\x12\x15\n\rsettings_lock\x18\x05 \x01(\x08\x12\x10\n\x08pin_code\x18\x06 \x01(\r\x12)\n\x05theme\x18\x07 \x01(\x0e\x32\x1a.meshtastic.protobuf.Theme\x12\x15\n\ralert_enabled\x18\x08 \x01(\x08\x12\x16\n\x0e\x62\x61nner_enabled\x18\t \x01(\x08\x12\x14\n\x0cring_tone_id\x18\n \x01(\r\x12/\n\x08language\x18\x0b \x01(\x0e\x32\x1d.meshtastic.protobuf.Language\x12\x34\n\x0bnode_filter\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.NodeFilter\x12:\n\x0enode_highlight\x18\r \x01(\x0b\x32\".meshtastic.protobuf.NodeHighlight\x12\x18\n\x10\x63\x61libration_data\x18\x0e \x01(\x0c\x12*\n\x08map_data\x18\x0f \x01(\x0b\x32\x18.meshtastic.protobuf.Map\x12\x36\n\x0c\x63ompass_mode\x18\x10 \x01(\x0e\x32 .meshtastic.protobuf.CompassMode\x12\x18\n\x10screen_rgb_color\x18\x11 \x01(\r\x12\x1b\n\x13is_clockface_analog\x18\x12 \x01(\x08\x12K\n\ngps_format\x18\x13 \x01(\x0e\x32\x37.meshtastic.protobuf.DeviceUIConfig.GpsCoordinateFormat\"V\n\x13GpsCoordinateFormat\x12\x07\n\x03\x44\x45\x43\x10\x00\x12\x07\n\x03\x44MS\x10\x01\x12\x07\n\x03UTM\x10\x02\x12\x08\n\x04MGRS\x10\x03\x12\x07\n\x03OLC\x10\x04\x12\x08\n\x04OSGR\x10\x05\x12\x07\n\x03MLS\x10\x06\"\xa7\x01\n\nNodeFilter\x12\x16\n\x0eunknown_switch\x18\x01 \x01(\x08\x12\x16\n\x0eoffline_switch\x18\x02 \x01(\x08\x12\x19\n\x11public_key_switch\x18\x03 \x01(\x08\x12\x11\n\thops_away\x18\x04 \x01(\x05\x12\x17\n\x0fposition_switch\x18\x05 \x01(\x08\x12\x11\n\tnode_name\x18\x06 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\x05\"~\n\rNodeHighlight\x12\x13\n\x0b\x63hat_switch\x18\x01 \x01(\x08\x12\x17\n\x0fposition_switch\x18\x02 \x01(\x08\x12\x18\n\x10telemetry_switch\x18\x03 \x01(\x08\x12\x12\n\niaq_switch\x18\x04 \x01(\x08\x12\x11\n\tnode_name\x18\x05 \x01(\t\"=\n\x08GeoPoint\x12\x0c\n\x04zoom\x18\x01 \x01(\x05\x12\x10\n\x08latitude\x18\x02 \x01(\x05\x12\x11\n\tlongitude\x18\x03 \x01(\x05\"U\n\x03Map\x12+\n\x04home\x18\x01 \x01(\x0b\x32\x1d.meshtastic.protobuf.GeoPoint\x12\r\n\x05style\x18\x02 \x01(\t\x12\x12\n\nfollow_gps\x18\x03 \x01(\x08*>\n\x0b\x43ompassMode\x12\x0b\n\x07\x44YNAMIC\x10\x00\x12\x0e\n\nFIXED_RING\x10\x01\x12\x12\n\x0e\x46REEZE_HEADING\x10\x02*%\n\x05Theme\x12\x08\n\x04\x44\x41RK\x10\x00\x12\t\n\x05LIGHT\x10\x01\x12\x07\n\x03RED\x10\x02*\xc0\x02\n\x08Language\x12\x0b\n\x07\x45NGLISH\x10\x00\x12\n\n\x06\x46RENCH\x10\x01\x12\n\n\x06GERMAN\x10\x02\x12\x0b\n\x07ITALIAN\x10\x03\x12\x0e\n\nPORTUGUESE\x10\x04\x12\x0b\n\x07SPANISH\x10\x05\x12\x0b\n\x07SWEDISH\x10\x06\x12\x0b\n\x07\x46INNISH\x10\x07\x12\n\n\x06POLISH\x10\x08\x12\x0b\n\x07TURKISH\x10\t\x12\x0b\n\x07SERBIAN\x10\n\x12\x0b\n\x07RUSSIAN\x10\x0b\x12\t\n\x05\x44UTCH\x10\x0c\x12\t\n\x05GREEK\x10\r\x12\r\n\tNORWEGIAN\x10\x0e\x12\r\n\tSLOVENIAN\x10\x0f\x12\r\n\tUKRAINIAN\x10\x10\x12\r\n\tBULGARIAN\x10\x11\x12\t\n\x05\x43ZECH\x10\x12\x12\n\n\x06\x44\x41NISH\x10\x13\x12\x16\n\x12SIMPLIFIED_CHINESE\x10\x1e\x12\x17\n\x13TRADITIONAL_CHINESE\x10\x1f\x42\x64\n\x14org.meshtastic.protoB\x0e\x44\x65viceUIProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.device_ui_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\016DeviceUIProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_COMPASSMODE']._serialized_start=1278
_globals['_COMPASSMODE']._serialized_end=1340
_globals['_THEME']._serialized_start=1342
_globals['_THEME']._serialized_end=1379
_globals['_LANGUAGE']._serialized_start=1382
_globals['_LANGUAGE']._serialized_end=1702
_globals['_DEVICEUICONFIG']._serialized_start=61
_globals['_DEVICEUICONFIG']._serialized_end=828
_globals['_DEVICEUICONFIG_GPSCOORDINATEFORMAT']._serialized_start=742
_globals['_DEVICEUICONFIG_GPSCOORDINATEFORMAT']._serialized_end=828
_globals['_NODEFILTER']._serialized_start=831
_globals['_NODEFILTER']._serialized_end=998
_globals['_NODEHIGHLIGHT']._serialized_start=1000
_globals['_NODEHIGHLIGHT']._serialized_end=1126
_globals['_GEOPOINT']._serialized_start=1128
_globals['_GEOPOINT']._serialized_end=1189
_globals['_MAP']._serialized_start=1191
_globals['_MAP']._serialized_end=1276
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,649 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _CompassMode:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _CompassModeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_CompassMode.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
DYNAMIC: _CompassMode.ValueType # 0
"""
Compass with dynamic ring and heading
"""
FIXED_RING: _CompassMode.ValueType # 1
"""
Compass with fixed ring and heading
"""
FREEZE_HEADING: _CompassMode.ValueType # 2
"""
Compass with heading and freeze option
"""
class CompassMode(_CompassMode, metaclass=_CompassModeEnumTypeWrapper): ...
DYNAMIC: CompassMode.ValueType # 0
"""
Compass with dynamic ring and heading
"""
FIXED_RING: CompassMode.ValueType # 1
"""
Compass with fixed ring and heading
"""
FREEZE_HEADING: CompassMode.ValueType # 2
"""
Compass with heading and freeze option
"""
global___CompassMode = CompassMode
class _Theme:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _ThemeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_Theme.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
DARK: _Theme.ValueType # 0
"""
Dark
"""
LIGHT: _Theme.ValueType # 1
"""
Light
"""
RED: _Theme.ValueType # 2
"""
Red
"""
class Theme(_Theme, metaclass=_ThemeEnumTypeWrapper): ...
DARK: Theme.ValueType # 0
"""
Dark
"""
LIGHT: Theme.ValueType # 1
"""
Light
"""
RED: Theme.ValueType # 2
"""
Red
"""
global___Theme = Theme
class _Language:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _LanguageEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_Language.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
ENGLISH: _Language.ValueType # 0
"""
English
"""
FRENCH: _Language.ValueType # 1
"""
French
"""
GERMAN: _Language.ValueType # 2
"""
German
"""
ITALIAN: _Language.ValueType # 3
"""
Italian
"""
PORTUGUESE: _Language.ValueType # 4
"""
Portuguese
"""
SPANISH: _Language.ValueType # 5
"""
Spanish
"""
SWEDISH: _Language.ValueType # 6
"""
Swedish
"""
FINNISH: _Language.ValueType # 7
"""
Finnish
"""
POLISH: _Language.ValueType # 8
"""
Polish
"""
TURKISH: _Language.ValueType # 9
"""
Turkish
"""
SERBIAN: _Language.ValueType # 10
"""
Serbian
"""
RUSSIAN: _Language.ValueType # 11
"""
Russian
"""
DUTCH: _Language.ValueType # 12
"""
Dutch
"""
GREEK: _Language.ValueType # 13
"""
Greek
"""
NORWEGIAN: _Language.ValueType # 14
"""
Norwegian
"""
SLOVENIAN: _Language.ValueType # 15
"""
Slovenian
"""
UKRAINIAN: _Language.ValueType # 16
"""
Ukrainian
"""
BULGARIAN: _Language.ValueType # 17
"""
Bulgarian
"""
CZECH: _Language.ValueType # 18
"""
Czech
"""
DANISH: _Language.ValueType # 19
"""
Danish
"""
SIMPLIFIED_CHINESE: _Language.ValueType # 30
"""
Simplified Chinese (experimental)
"""
TRADITIONAL_CHINESE: _Language.ValueType # 31
"""
Traditional Chinese (experimental)
"""
class Language(_Language, metaclass=_LanguageEnumTypeWrapper):
"""
Localization
"""
ENGLISH: Language.ValueType # 0
"""
English
"""
FRENCH: Language.ValueType # 1
"""
French
"""
GERMAN: Language.ValueType # 2
"""
German
"""
ITALIAN: Language.ValueType # 3
"""
Italian
"""
PORTUGUESE: Language.ValueType # 4
"""
Portuguese
"""
SPANISH: Language.ValueType # 5
"""
Spanish
"""
SWEDISH: Language.ValueType # 6
"""
Swedish
"""
FINNISH: Language.ValueType # 7
"""
Finnish
"""
POLISH: Language.ValueType # 8
"""
Polish
"""
TURKISH: Language.ValueType # 9
"""
Turkish
"""
SERBIAN: Language.ValueType # 10
"""
Serbian
"""
RUSSIAN: Language.ValueType # 11
"""
Russian
"""
DUTCH: Language.ValueType # 12
"""
Dutch
"""
GREEK: Language.ValueType # 13
"""
Greek
"""
NORWEGIAN: Language.ValueType # 14
"""
Norwegian
"""
SLOVENIAN: Language.ValueType # 15
"""
Slovenian
"""
UKRAINIAN: Language.ValueType # 16
"""
Ukrainian
"""
BULGARIAN: Language.ValueType # 17
"""
Bulgarian
"""
CZECH: Language.ValueType # 18
"""
Czech
"""
DANISH: Language.ValueType # 19
"""
Danish
"""
SIMPLIFIED_CHINESE: Language.ValueType # 30
"""
Simplified Chinese (experimental)
"""
TRADITIONAL_CHINESE: Language.ValueType # 31
"""
Traditional Chinese (experimental)
"""
global___Language = Language
@typing.final
class DeviceUIConfig(google.protobuf.message.Message):
"""
Protobuf structures for device-ui persistency
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _GpsCoordinateFormat:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _GpsCoordinateFormatEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[DeviceUIConfig._GpsCoordinateFormat.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
DEC: DeviceUIConfig._GpsCoordinateFormat.ValueType # 0
"""
GPS coordinates are displayed in the normal decimal degrees format:
DD.DDDDDD DDD.DDDDDD
"""
DMS: DeviceUIConfig._GpsCoordinateFormat.ValueType # 1
"""
GPS coordinates are displayed in the degrees minutes seconds format:
DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant
"""
UTM: DeviceUIConfig._GpsCoordinateFormat.ValueType # 2
"""
Universal Transverse Mercator format:
ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing
"""
MGRS: DeviceUIConfig._GpsCoordinateFormat.ValueType # 3
"""
Military Grid Reference System format:
ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square,
E is easting, N is northing
"""
OLC: DeviceUIConfig._GpsCoordinateFormat.ValueType # 4
"""
Open Location Code (aka Plus Codes).
"""
OSGR: DeviceUIConfig._GpsCoordinateFormat.ValueType # 5
"""
Ordnance Survey Grid Reference (the National Grid System of the UK).
Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square,
E is the easting, N is the northing
"""
MLS: DeviceUIConfig._GpsCoordinateFormat.ValueType # 6
"""
Maidenhead Locator System
Described here: https://en.wikipedia.org/wiki/Maidenhead_Locator_System
"""
class GpsCoordinateFormat(_GpsCoordinateFormat, metaclass=_GpsCoordinateFormatEnumTypeWrapper):
"""
How the GPS coordinates are displayed on the OLED screen.
"""
DEC: DeviceUIConfig.GpsCoordinateFormat.ValueType # 0
"""
GPS coordinates are displayed in the normal decimal degrees format:
DD.DDDDDD DDD.DDDDDD
"""
DMS: DeviceUIConfig.GpsCoordinateFormat.ValueType # 1
"""
GPS coordinates are displayed in the degrees minutes seconds format:
DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant
"""
UTM: DeviceUIConfig.GpsCoordinateFormat.ValueType # 2
"""
Universal Transverse Mercator format:
ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing
"""
MGRS: DeviceUIConfig.GpsCoordinateFormat.ValueType # 3
"""
Military Grid Reference System format:
ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square,
E is easting, N is northing
"""
OLC: DeviceUIConfig.GpsCoordinateFormat.ValueType # 4
"""
Open Location Code (aka Plus Codes).
"""
OSGR: DeviceUIConfig.GpsCoordinateFormat.ValueType # 5
"""
Ordnance Survey Grid Reference (the National Grid System of the UK).
Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square,
E is the easting, N is the northing
"""
MLS: DeviceUIConfig.GpsCoordinateFormat.ValueType # 6
"""
Maidenhead Locator System
Described here: https://en.wikipedia.org/wiki/Maidenhead_Locator_System
"""
VERSION_FIELD_NUMBER: builtins.int
SCREEN_BRIGHTNESS_FIELD_NUMBER: builtins.int
SCREEN_TIMEOUT_FIELD_NUMBER: builtins.int
SCREEN_LOCK_FIELD_NUMBER: builtins.int
SETTINGS_LOCK_FIELD_NUMBER: builtins.int
PIN_CODE_FIELD_NUMBER: builtins.int
THEME_FIELD_NUMBER: builtins.int
ALERT_ENABLED_FIELD_NUMBER: builtins.int
BANNER_ENABLED_FIELD_NUMBER: builtins.int
RING_TONE_ID_FIELD_NUMBER: builtins.int
LANGUAGE_FIELD_NUMBER: builtins.int
NODE_FILTER_FIELD_NUMBER: builtins.int
NODE_HIGHLIGHT_FIELD_NUMBER: builtins.int
CALIBRATION_DATA_FIELD_NUMBER: builtins.int
MAP_DATA_FIELD_NUMBER: builtins.int
COMPASS_MODE_FIELD_NUMBER: builtins.int
SCREEN_RGB_COLOR_FIELD_NUMBER: builtins.int
IS_CLOCKFACE_ANALOG_FIELD_NUMBER: builtins.int
GPS_FORMAT_FIELD_NUMBER: builtins.int
version: builtins.int
"""
A version integer used to invalidate saved files when we make incompatible changes.
"""
screen_brightness: builtins.int
"""
TFT display brightness 1..255
"""
screen_timeout: builtins.int
"""
Screen timeout 0..900
"""
screen_lock: builtins.bool
"""
Screen/Settings lock enabled
"""
settings_lock: builtins.bool
pin_code: builtins.int
theme: global___Theme.ValueType
"""
Color theme
"""
alert_enabled: builtins.bool
"""
Audible message, banner and ring tone
"""
banner_enabled: builtins.bool
ring_tone_id: builtins.int
language: global___Language.ValueType
"""
Localization
"""
calibration_data: builtins.bytes
"""
8 integers for screen calibration data
"""
compass_mode: global___CompassMode.ValueType
"""
Compass mode
"""
screen_rgb_color: builtins.int
"""
RGB color for BaseUI
0xRRGGBB format, e.g. 0xFF0000 for red
"""
is_clockface_analog: builtins.bool
"""
Clockface analog style
true for analog clockface, false for digital clockface
"""
gps_format: global___DeviceUIConfig.GpsCoordinateFormat.ValueType
"""
How the GPS coordinates are formatted on the OLED screen.
"""
@property
def node_filter(self) -> global___NodeFilter:
"""
Node list filter
"""
@property
def node_highlight(self) -> global___NodeHighlight:
"""
Node list highlightening
"""
@property
def map_data(self) -> global___Map:
"""
Map related data
"""
def __init__(
self,
*,
version: builtins.int = ...,
screen_brightness: builtins.int = ...,
screen_timeout: builtins.int = ...,
screen_lock: builtins.bool = ...,
settings_lock: builtins.bool = ...,
pin_code: builtins.int = ...,
theme: global___Theme.ValueType = ...,
alert_enabled: builtins.bool = ...,
banner_enabled: builtins.bool = ...,
ring_tone_id: builtins.int = ...,
language: global___Language.ValueType = ...,
node_filter: global___NodeFilter | None = ...,
node_highlight: global___NodeHighlight | None = ...,
calibration_data: builtins.bytes = ...,
map_data: global___Map | None = ...,
compass_mode: global___CompassMode.ValueType = ...,
screen_rgb_color: builtins.int = ...,
is_clockface_analog: builtins.bool = ...,
gps_format: global___DeviceUIConfig.GpsCoordinateFormat.ValueType = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["map_data", b"map_data", "node_filter", b"node_filter", "node_highlight", b"node_highlight"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["alert_enabled", b"alert_enabled", "banner_enabled", b"banner_enabled", "calibration_data", b"calibration_data", "compass_mode", b"compass_mode", "gps_format", b"gps_format", "is_clockface_analog", b"is_clockface_analog", "language", b"language", "map_data", b"map_data", "node_filter", b"node_filter", "node_highlight", b"node_highlight", "pin_code", b"pin_code", "ring_tone_id", b"ring_tone_id", "screen_brightness", b"screen_brightness", "screen_lock", b"screen_lock", "screen_rgb_color", b"screen_rgb_color", "screen_timeout", b"screen_timeout", "settings_lock", b"settings_lock", "theme", b"theme", "version", b"version"]) -> None: ...
global___DeviceUIConfig = DeviceUIConfig
@typing.final
class NodeFilter(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
UNKNOWN_SWITCH_FIELD_NUMBER: builtins.int
OFFLINE_SWITCH_FIELD_NUMBER: builtins.int
PUBLIC_KEY_SWITCH_FIELD_NUMBER: builtins.int
HOPS_AWAY_FIELD_NUMBER: builtins.int
POSITION_SWITCH_FIELD_NUMBER: builtins.int
NODE_NAME_FIELD_NUMBER: builtins.int
CHANNEL_FIELD_NUMBER: builtins.int
unknown_switch: builtins.bool
"""
Filter unknown nodes
"""
offline_switch: builtins.bool
"""
Filter offline nodes
"""
public_key_switch: builtins.bool
"""
Filter nodes w/o public key
"""
hops_away: builtins.int
"""
Filter based on hops away
"""
position_switch: builtins.bool
"""
Filter nodes w/o position
"""
node_name: builtins.str
"""
Filter nodes by matching name string
"""
channel: builtins.int
"""
Filter based on channel
"""
def __init__(
self,
*,
unknown_switch: builtins.bool = ...,
offline_switch: builtins.bool = ...,
public_key_switch: builtins.bool = ...,
hops_away: builtins.int = ...,
position_switch: builtins.bool = ...,
node_name: builtins.str = ...,
channel: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["channel", b"channel", "hops_away", b"hops_away", "node_name", b"node_name", "offline_switch", b"offline_switch", "position_switch", b"position_switch", "public_key_switch", b"public_key_switch", "unknown_switch", b"unknown_switch"]) -> None: ...
global___NodeFilter = NodeFilter
@typing.final
class NodeHighlight(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
CHAT_SWITCH_FIELD_NUMBER: builtins.int
POSITION_SWITCH_FIELD_NUMBER: builtins.int
TELEMETRY_SWITCH_FIELD_NUMBER: builtins.int
IAQ_SWITCH_FIELD_NUMBER: builtins.int
NODE_NAME_FIELD_NUMBER: builtins.int
chat_switch: builtins.bool
"""
Hightlight nodes w/ active chat
"""
position_switch: builtins.bool
"""
Highlight nodes w/ position
"""
telemetry_switch: builtins.bool
"""
Highlight nodes w/ telemetry data
"""
iaq_switch: builtins.bool
"""
Highlight nodes w/ iaq data
"""
node_name: builtins.str
"""
Highlight nodes by matching name string
"""
def __init__(
self,
*,
chat_switch: builtins.bool = ...,
position_switch: builtins.bool = ...,
telemetry_switch: builtins.bool = ...,
iaq_switch: builtins.bool = ...,
node_name: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["chat_switch", b"chat_switch", "iaq_switch", b"iaq_switch", "node_name", b"node_name", "position_switch", b"position_switch", "telemetry_switch", b"telemetry_switch"]) -> None: ...
global___NodeHighlight = NodeHighlight
@typing.final
class GeoPoint(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
ZOOM_FIELD_NUMBER: builtins.int
LATITUDE_FIELD_NUMBER: builtins.int
LONGITUDE_FIELD_NUMBER: builtins.int
zoom: builtins.int
"""
Zoom level
"""
latitude: builtins.int
"""
Coordinate: latitude
"""
longitude: builtins.int
"""
Coordinate: longitude
"""
def __init__(
self,
*,
zoom: builtins.int = ...,
latitude: builtins.int = ...,
longitude: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["latitude", b"latitude", "longitude", b"longitude", "zoom", b"zoom"]) -> None: ...
global___GeoPoint = GeoPoint
@typing.final
class Map(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
HOME_FIELD_NUMBER: builtins.int
STYLE_FIELD_NUMBER: builtins.int
FOLLOW_GPS_FIELD_NUMBER: builtins.int
style: builtins.str
"""
Map tile style
"""
follow_gps: builtins.bool
"""
Map scroll follows GPS
"""
@property
def home(self) -> global___GeoPoint:
"""
Home coordinates
"""
def __init__(
self,
*,
home: global___GeoPoint | None = ...,
style: builtins.str = ...,
follow_gps: builtins.bool = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["home", b"home"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["follow_gps", b"follow_gps", "home", b"home", "style", b"style"]) -> None: ...
global___Map = Map

View File

@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/deviceonly.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import channel_pb2 as meshtastic_dot_protobuf_dot_channel__pb2
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_localonly__pb2
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
from meshtastic.protobuf import telemetry_pb2 as meshtastic_dot_protobuf_dot_telemetry__pb2
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/deviceonly.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a#meshtastic/protobuf/localonly.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a meshtastic/protobuf/nanopb.proto\"\x99\x01\n\x0cPositionLite\x12\x12\n\nlatitude_i\x18\x01 \x01(\x0f\x12\x13\n\x0blongitude_i\x18\x02 \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\x0c\n\x04time\x18\x04 \x01(\x07\x12@\n\x0flocation_source\x18\x05 \x01(\x0e\x32\'.meshtastic.protobuf.Position.LocSource\"\x94\x02\n\x08UserLite\x12\x13\n\x07macaddr\x18\x01 \x01(\x0c\x42\x02\x18\x01\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x34\n\x08hw_model\x18\x04 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12\x13\n\x0bis_licensed\x18\x05 \x01(\x08\x12;\n\x04role\x18\x06 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x12\n\npublic_key\x18\x07 \x01(\x0c\x12\x1c\n\x0fis_unmessagable\x18\t \x01(\x08H\x00\x88\x01\x01\x42\x12\n\x10_is_unmessagable\"\xf0\x02\n\x0cNodeInfoLite\x12\x0b\n\x03num\x18\x01 \x01(\r\x12+\n\x04user\x18\x02 \x01(\x0b\x32\x1d.meshtastic.protobuf.UserLite\x12\x33\n\x08position\x18\x03 \x01(\x0b\x32!.meshtastic.protobuf.PositionLite\x12\x0b\n\x03snr\x18\x04 \x01(\x02\x12\x12\n\nlast_heard\x18\x05 \x01(\x07\x12:\n\x0e\x64\x65vice_metrics\x18\x06 \x01(\x0b\x32\".meshtastic.protobuf.DeviceMetrics\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\r\x12\x10\n\x08via_mqtt\x18\x08 \x01(\x08\x12\x16\n\thops_away\x18\t \x01(\rH\x00\x88\x01\x01\x12\x13\n\x0bis_favorite\x18\n \x01(\x08\x12\x12\n\nis_ignored\x18\x0b \x01(\x08\x12\x10\n\x08next_hop\x18\x0c \x01(\r\x12\x10\n\x08\x62itfield\x18\r \x01(\rB\x0c\n\n_hops_away\"\xa1\x03\n\x0b\x44\x65viceState\x12\x30\n\x07my_node\x18\x02 \x01(\x0b\x32\x1f.meshtastic.protobuf.MyNodeInfo\x12(\n\x05owner\x18\x03 \x01(\x0b\x32\x19.meshtastic.protobuf.User\x12\x36\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12\x38\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x13\n\x07no_save\x18\t \x01(\x08\x42\x02\x18\x01\x12\x19\n\rdid_gps_reset\x18\x0b \x01(\x08\x42\x02\x18\x01\x12\x34\n\x0brx_waypoint\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12M\n\x19node_remote_hardware_pins\x18\r \x03(\x0b\x32*.meshtastic.protobuf.NodeRemoteHardwarePin\"}\n\x0cNodeDatabase\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\\\n\x05nodes\x18\x02 \x03(\x0b\x32!.meshtastic.protobuf.NodeInfoLiteB*\x92?\'\x92\x01$std::vector<meshtastic_NodeInfoLite>\"N\n\x0b\x43hannelFile\x12.\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x1c.meshtastic.protobuf.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\x86\x02\n\x11\x42\x61\x63kupPreferences\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\x07\x12\x30\n\x06\x63onfig\x18\x03 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfig\x12=\n\rmodule_config\x18\x04 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfig\x12\x32\n\x08\x63hannels\x18\x05 \x01(\x0b\x32 .meshtastic.protobuf.ChannelFile\x12(\n\x05owner\x18\x06 \x01(\x0b\x32\x19.meshtastic.protobuf.UserBn\n\x14org.meshtastic.protoB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x92?\x0b\xc2\x01\x08<vector>b\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.deviceonly_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000\222?\013\302\001\010<vector>'
_USERLITE.fields_by_name['macaddr']._options = None
_USERLITE.fields_by_name['macaddr']._serialized_options = b'\030\001'
_DEVICESTATE.fields_by_name['no_save']._options = None
_DEVICESTATE.fields_by_name['no_save']._serialized_options = b'\030\001'
_DEVICESTATE.fields_by_name['did_gps_reset']._options = None
_DEVICESTATE.fields_by_name['did_gps_reset']._serialized_options = b'\030\001'
_NODEDATABASE.fields_by_name['nodes']._options = None
_NODEDATABASE.fields_by_name['nodes']._serialized_options = b'\222?\'\222\001$std::vector<meshtastic_NodeInfoLite>'
_globals['_POSITIONLITE']._serialized_start=271
_globals['_POSITIONLITE']._serialized_end=424
_globals['_USERLITE']._serialized_start=427
_globals['_USERLITE']._serialized_end=703
_globals['_NODEINFOLITE']._serialized_start=706
_globals['_NODEINFOLITE']._serialized_end=1074
_globals['_DEVICESTATE']._serialized_start=1077
_globals['_DEVICESTATE']._serialized_end=1494
_globals['_NODEDATABASE']._serialized_start=1496
_globals['_NODEDATABASE']._serialized_end=1621
_globals['_CHANNELFILE']._serialized_start=1623
_globals['_CHANNELFILE']._serialized_end=1701
_globals['_BACKUPPREFERENCES']._serialized_start=1704
_globals['_BACKUPPREFERENCES']._serialized_end=1966
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,458 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import collections.abc
import google.protobuf.descriptor
import google.protobuf.internal.containers
import google.protobuf.message
import meshtastic.protobuf.channel_pb2
import meshtastic.protobuf.config_pb2
import meshtastic.protobuf.localonly_pb2
import meshtastic.protobuf.mesh_pb2
import meshtastic.protobuf.telemetry_pb2
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class PositionLite(google.protobuf.message.Message):
"""
Position with static location information only for NodeDBLite
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
LATITUDE_I_FIELD_NUMBER: builtins.int
LONGITUDE_I_FIELD_NUMBER: builtins.int
ALTITUDE_FIELD_NUMBER: builtins.int
TIME_FIELD_NUMBER: builtins.int
LOCATION_SOURCE_FIELD_NUMBER: builtins.int
latitude_i: builtins.int
"""
The new preferred location encoding, multiply by 1e-7 to get degrees
in floating point
"""
longitude_i: builtins.int
"""
TODO: REPLACE
"""
altitude: builtins.int
"""
In meters above MSL (but see issue #359)
"""
time: builtins.int
"""
This is usually not sent over the mesh (to save space), but it is sent
from the phone so that the local device can set its RTC If it is sent over
the mesh (because there are devices on the mesh without GPS), it will only
be sent by devices which has a hardware GPS clock.
seconds since 1970
"""
location_source: meshtastic.protobuf.mesh_pb2.Position.LocSource.ValueType
"""
TODO: REPLACE
"""
def __init__(
self,
*,
latitude_i: builtins.int = ...,
longitude_i: builtins.int = ...,
altitude: builtins.int = ...,
time: builtins.int = ...,
location_source: meshtastic.protobuf.mesh_pb2.Position.LocSource.ValueType = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["altitude", b"altitude", "latitude_i", b"latitude_i", "location_source", b"location_source", "longitude_i", b"longitude_i", "time", b"time"]) -> None: ...
global___PositionLite = PositionLite
@typing.final
class UserLite(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MACADDR_FIELD_NUMBER: builtins.int
LONG_NAME_FIELD_NUMBER: builtins.int
SHORT_NAME_FIELD_NUMBER: builtins.int
HW_MODEL_FIELD_NUMBER: builtins.int
IS_LICENSED_FIELD_NUMBER: builtins.int
ROLE_FIELD_NUMBER: builtins.int
PUBLIC_KEY_FIELD_NUMBER: builtins.int
IS_UNMESSAGABLE_FIELD_NUMBER: builtins.int
macaddr: builtins.bytes
"""
This is the addr of the radio.
"""
long_name: builtins.str
"""
A full name for this user, i.e. "Kevin Hester"
"""
short_name: builtins.str
"""
A VERY short name, ideally two characters.
Suitable for a tiny OLED screen
"""
hw_model: meshtastic.protobuf.mesh_pb2.HardwareModel.ValueType
"""
TBEAM, HELTEC, etc...
Starting in 1.2.11 moved to hw_model enum in the NodeInfo object.
Apps will still need the string here for older builds
(so OTA update can find the right image), but if the enum is available it will be used instead.
"""
is_licensed: builtins.bool
"""
In some regions Ham radio operators have different bandwidth limitations than others.
If this user is a licensed operator, set this flag.
Also, "long_name" should be their licence number.
"""
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType
"""
Indicates that the user's role in the mesh
"""
public_key: builtins.bytes
"""
The public key of the user's device.
This is sent out to other nodes on the mesh to allow them to compute a shared secret key.
"""
is_unmessagable: builtins.bool
"""
Whether or not the node can be messaged
"""
def __init__(
self,
*,
macaddr: builtins.bytes = ...,
long_name: builtins.str = ...,
short_name: builtins.str = ...,
hw_model: meshtastic.protobuf.mesh_pb2.HardwareModel.ValueType = ...,
is_licensed: builtins.bool = ...,
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType = ...,
public_key: builtins.bytes = ...,
is_unmessagable: builtins.bool | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_is_unmessagable", b"_is_unmessagable", "is_unmessagable", b"is_unmessagable"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_is_unmessagable", b"_is_unmessagable", "hw_model", b"hw_model", "is_licensed", b"is_licensed", "is_unmessagable", b"is_unmessagable", "long_name", b"long_name", "macaddr", b"macaddr", "public_key", b"public_key", "role", b"role", "short_name", b"short_name"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["_is_unmessagable", b"_is_unmessagable"]) -> typing.Literal["is_unmessagable"] | None: ...
global___UserLite = UserLite
@typing.final
class NodeInfoLite(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NUM_FIELD_NUMBER: builtins.int
USER_FIELD_NUMBER: builtins.int
POSITION_FIELD_NUMBER: builtins.int
SNR_FIELD_NUMBER: builtins.int
LAST_HEARD_FIELD_NUMBER: builtins.int
DEVICE_METRICS_FIELD_NUMBER: builtins.int
CHANNEL_FIELD_NUMBER: builtins.int
VIA_MQTT_FIELD_NUMBER: builtins.int
HOPS_AWAY_FIELD_NUMBER: builtins.int
IS_FAVORITE_FIELD_NUMBER: builtins.int
IS_IGNORED_FIELD_NUMBER: builtins.int
NEXT_HOP_FIELD_NUMBER: builtins.int
BITFIELD_FIELD_NUMBER: builtins.int
num: builtins.int
"""
The node number
"""
snr: builtins.float
"""
Returns the Signal-to-noise ratio (SNR) of the last received message,
as measured by the receiver. Return SNR of the last received message in dB
"""
last_heard: builtins.int
"""
Set to indicate the last time we received a packet from this node
"""
channel: builtins.int
"""
local channel index we heard that node on. Only populated if its not the default channel.
"""
via_mqtt: builtins.bool
"""
True if we witnessed the node over MQTT instead of LoRA transport
"""
hops_away: builtins.int
"""
Number of hops away from us this node is (0 if direct neighbor)
"""
is_favorite: builtins.bool
"""
True if node is in our favorites list
Persists between NodeDB internal clean ups
"""
is_ignored: builtins.bool
"""
True if node is in our ignored list
Persists between NodeDB internal clean ups
"""
next_hop: builtins.int
"""
Last byte of the node number of the node that should be used as the next hop to reach this node.
"""
bitfield: builtins.int
"""
Bitfield for storing booleans.
LSB 0 is_key_manually_verified
"""
@property
def user(self) -> global___UserLite:
"""
The user info for this node
"""
@property
def position(self) -> global___PositionLite:
"""
This position data. Note: before 1.2.14 we would also store the last time we've heard from this node in position.time, that is no longer true.
Position.time now indicates the last time we received a POSITION from that node.
"""
@property
def device_metrics(self) -> meshtastic.protobuf.telemetry_pb2.DeviceMetrics:
"""
The latest device metrics for the node.
"""
def __init__(
self,
*,
num: builtins.int = ...,
user: global___UserLite | None = ...,
position: global___PositionLite | None = ...,
snr: builtins.float = ...,
last_heard: builtins.int = ...,
device_metrics: meshtastic.protobuf.telemetry_pb2.DeviceMetrics | None = ...,
channel: builtins.int = ...,
via_mqtt: builtins.bool = ...,
hops_away: builtins.int | None = ...,
is_favorite: builtins.bool = ...,
is_ignored: builtins.bool = ...,
next_hop: builtins.int = ...,
bitfield: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "position", b"position", "user", b"user"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "bitfield", b"bitfield", "channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "is_ignored", b"is_ignored", "last_heard", b"last_heard", "next_hop", b"next_hop", "num", b"num", "position", b"position", "snr", b"snr", "user", b"user", "via_mqtt", b"via_mqtt"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["_hops_away", b"_hops_away"]) -> typing.Literal["hops_away"] | None: ...
global___NodeInfoLite = NodeInfoLite
@typing.final
class DeviceState(google.protobuf.message.Message):
"""
This message is never sent over the wire, but it is used for serializing DB
state to flash in the device code
FIXME, since we write this each time we enter deep sleep (and have infinite
flash) it would be better to use some sort of append only data structure for
the receive queue and use the preferences store for the other stuff
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MY_NODE_FIELD_NUMBER: builtins.int
OWNER_FIELD_NUMBER: builtins.int
RECEIVE_QUEUE_FIELD_NUMBER: builtins.int
VERSION_FIELD_NUMBER: builtins.int
RX_TEXT_MESSAGE_FIELD_NUMBER: builtins.int
NO_SAVE_FIELD_NUMBER: builtins.int
DID_GPS_RESET_FIELD_NUMBER: builtins.int
RX_WAYPOINT_FIELD_NUMBER: builtins.int
NODE_REMOTE_HARDWARE_PINS_FIELD_NUMBER: builtins.int
version: builtins.int
"""
A version integer used to invalidate old save files when we make
incompatible changes This integer is set at build time and is private to
NodeDB.cpp in the device code.
"""
no_save: builtins.bool
"""
Used only during development.
Indicates developer is testing and changes should never be saved to flash.
Deprecated in 2.3.1
"""
did_gps_reset: builtins.bool
"""
Previously used to manage GPS factory resets.
Deprecated in 2.5.23
"""
@property
def my_node(self) -> meshtastic.protobuf.mesh_pb2.MyNodeInfo:
"""
Read only settings/info about this node
"""
@property
def owner(self) -> meshtastic.protobuf.mesh_pb2.User:
"""
My owner info
"""
@property
def receive_queue(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[meshtastic.protobuf.mesh_pb2.MeshPacket]:
"""
Received packets saved for delivery to the phone
"""
@property
def rx_text_message(self) -> meshtastic.protobuf.mesh_pb2.MeshPacket:
"""
We keep the last received text message (only) stored in the device flash,
so we can show it on the screen.
Might be null
"""
@property
def rx_waypoint(self) -> meshtastic.protobuf.mesh_pb2.MeshPacket:
"""
We keep the last received waypoint stored in the device flash,
so we can show it on the screen.
Might be null
"""
@property
def node_remote_hardware_pins(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[meshtastic.protobuf.mesh_pb2.NodeRemoteHardwarePin]:
"""
The mesh's nodes with their available gpio pins for RemoteHardware module
"""
def __init__(
self,
*,
my_node: meshtastic.protobuf.mesh_pb2.MyNodeInfo | None = ...,
owner: meshtastic.protobuf.mesh_pb2.User | None = ...,
receive_queue: collections.abc.Iterable[meshtastic.protobuf.mesh_pb2.MeshPacket] | None = ...,
version: builtins.int = ...,
rx_text_message: meshtastic.protobuf.mesh_pb2.MeshPacket | None = ...,
no_save: builtins.bool = ...,
did_gps_reset: builtins.bool = ...,
rx_waypoint: meshtastic.protobuf.mesh_pb2.MeshPacket | None = ...,
node_remote_hardware_pins: collections.abc.Iterable[meshtastic.protobuf.mesh_pb2.NodeRemoteHardwarePin] | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["my_node", b"my_node", "owner", b"owner", "rx_text_message", b"rx_text_message", "rx_waypoint", b"rx_waypoint"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["did_gps_reset", b"did_gps_reset", "my_node", b"my_node", "no_save", b"no_save", "node_remote_hardware_pins", b"node_remote_hardware_pins", "owner", b"owner", "receive_queue", b"receive_queue", "rx_text_message", b"rx_text_message", "rx_waypoint", b"rx_waypoint", "version", b"version"]) -> None: ...
global___DeviceState = DeviceState
@typing.final
class NodeDatabase(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
VERSION_FIELD_NUMBER: builtins.int
NODES_FIELD_NUMBER: builtins.int
version: builtins.int
"""
A version integer used to invalidate old save files when we make
incompatible changes This integer is set at build time and is private to
NodeDB.cpp in the device code.
"""
@property
def nodes(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___NodeInfoLite]:
"""
New lite version of NodeDB to decrease memory footprint
"""
def __init__(
self,
*,
version: builtins.int = ...,
nodes: collections.abc.Iterable[global___NodeInfoLite] | None = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["nodes", b"nodes", "version", b"version"]) -> None: ...
global___NodeDatabase = NodeDatabase
@typing.final
class ChannelFile(google.protobuf.message.Message):
"""
The on-disk saved channels
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
CHANNELS_FIELD_NUMBER: builtins.int
VERSION_FIELD_NUMBER: builtins.int
version: builtins.int
"""
A version integer used to invalidate old save files when we make
incompatible changes This integer is set at build time and is private to
NodeDB.cpp in the device code.
"""
@property
def channels(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[meshtastic.protobuf.channel_pb2.Channel]:
"""
The channels our node knows about
"""
def __init__(
self,
*,
channels: collections.abc.Iterable[meshtastic.protobuf.channel_pb2.Channel] | None = ...,
version: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["channels", b"channels", "version", b"version"]) -> None: ...
global___ChannelFile = ChannelFile
@typing.final
class BackupPreferences(google.protobuf.message.Message):
"""
The on-disk backup of the node's preferences
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
VERSION_FIELD_NUMBER: builtins.int
TIMESTAMP_FIELD_NUMBER: builtins.int
CONFIG_FIELD_NUMBER: builtins.int
MODULE_CONFIG_FIELD_NUMBER: builtins.int
CHANNELS_FIELD_NUMBER: builtins.int
OWNER_FIELD_NUMBER: builtins.int
version: builtins.int
"""
The version of the backup
"""
timestamp: builtins.int
"""
The timestamp of the backup (if node has time)
"""
@property
def config(self) -> meshtastic.protobuf.localonly_pb2.LocalConfig:
"""
The node's configuration
"""
@property
def module_config(self) -> meshtastic.protobuf.localonly_pb2.LocalModuleConfig:
"""
The node's module configuration
"""
@property
def channels(self) -> global___ChannelFile:
"""
The node's channels
"""
@property
def owner(self) -> meshtastic.protobuf.mesh_pb2.User:
"""
The node's user (owner) information
"""
def __init__(
self,
*,
version: builtins.int = ...,
timestamp: builtins.int = ...,
config: meshtastic.protobuf.localonly_pb2.LocalConfig | None = ...,
module_config: meshtastic.protobuf.localonly_pb2.LocalModuleConfig | None = ...,
channels: global___ChannelFile | None = ...,
owner: meshtastic.protobuf.mesh_pb2.User | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["channels", b"channels", "config", b"config", "module_config", b"module_config", "owner", b"owner"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["channels", b"channels", "config", b"config", "module_config", b"module_config", "owner", b"owner", "timestamp", b"timestamp", "version", b"version"]) -> None: ...
global___BackupPreferences = BackupPreferences

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/interdevice.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%meshtastic/protobuf/interdevice.proto\x12\x13meshtastic.protobuf\"s\n\nSensorData\x12.\n\x04type\x18\x01 \x01(\x0e\x32 .meshtastic.protobuf.MessageType\x12\x15\n\x0b\x66loat_value\x18\x02 \x01(\x02H\x00\x12\x16\n\x0cuint32_value\x18\x03 \x01(\rH\x00\x42\x06\n\x04\x64\x61ta\"_\n\x12InterdeviceMessage\x12\x0e\n\x04nmea\x18\x01 \x01(\tH\x00\x12\x31\n\x06sensor\x18\x02 \x01(\x0b\x32\x1f.meshtastic.protobuf.SensorDataH\x00\x42\x06\n\x04\x64\x61ta*\xd5\x01\n\x0bMessageType\x12\x07\n\x03\x41\x43K\x10\x00\x12\x15\n\x10\x43OLLECT_INTERVAL\x10\xa0\x01\x12\x0c\n\x07\x42\x45\x45P_ON\x10\xa1\x01\x12\r\n\x08\x42\x45\x45P_OFF\x10\xa2\x01\x12\r\n\x08SHUTDOWN\x10\xa3\x01\x12\r\n\x08POWER_ON\x10\xa4\x01\x12\x0f\n\nSCD41_TEMP\x10\xb0\x01\x12\x13\n\x0eSCD41_HUMIDITY\x10\xb1\x01\x12\x0e\n\tSCD41_CO2\x10\xb2\x01\x12\x0f\n\nAHT20_TEMP\x10\xb3\x01\x12\x13\n\x0e\x41HT20_HUMIDITY\x10\xb4\x01\x12\x0f\n\nTVOC_INDEX\x10\xb5\x01\x42g\n\x14org.meshtastic.protoB\x11InterdeviceProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.interdevice_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\021InterdeviceProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_MESSAGETYPE']._serialized_start=277
_globals['_MESSAGETYPE']._serialized_end=490
_globals['_SENSORDATA']._serialized_start=62
_globals['_SENSORDATA']._serialized_end=177
_globals['_INTERDEVICEMESSAGE']._serialized_start=179
_globals['_INTERDEVICEMESSAGE']._serialized_end=274
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,105 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _MessageType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _MessageTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_MessageType.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
ACK: _MessageType.ValueType # 0
COLLECT_INTERVAL: _MessageType.ValueType # 160
"""in ms"""
BEEP_ON: _MessageType.ValueType # 161
"""duration ms"""
BEEP_OFF: _MessageType.ValueType # 162
"""cancel prematurely"""
SHUTDOWN: _MessageType.ValueType # 163
POWER_ON: _MessageType.ValueType # 164
SCD41_TEMP: _MessageType.ValueType # 176
SCD41_HUMIDITY: _MessageType.ValueType # 177
SCD41_CO2: _MessageType.ValueType # 178
AHT20_TEMP: _MessageType.ValueType # 179
AHT20_HUMIDITY: _MessageType.ValueType # 180
TVOC_INDEX: _MessageType.ValueType # 181
class MessageType(_MessageType, metaclass=_MessageTypeEnumTypeWrapper):
"""encapsulate up to 1k of NMEA string data"""
ACK: MessageType.ValueType # 0
COLLECT_INTERVAL: MessageType.ValueType # 160
"""in ms"""
BEEP_ON: MessageType.ValueType # 161
"""duration ms"""
BEEP_OFF: MessageType.ValueType # 162
"""cancel prematurely"""
SHUTDOWN: MessageType.ValueType # 163
POWER_ON: MessageType.ValueType # 164
SCD41_TEMP: MessageType.ValueType # 176
SCD41_HUMIDITY: MessageType.ValueType # 177
SCD41_CO2: MessageType.ValueType # 178
AHT20_TEMP: MessageType.ValueType # 179
AHT20_HUMIDITY: MessageType.ValueType # 180
TVOC_INDEX: MessageType.ValueType # 181
global___MessageType = MessageType
@typing.final
class SensorData(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
TYPE_FIELD_NUMBER: builtins.int
FLOAT_VALUE_FIELD_NUMBER: builtins.int
UINT32_VALUE_FIELD_NUMBER: builtins.int
type: global___MessageType.ValueType
"""The message type"""
float_value: builtins.float
uint32_value: builtins.int
def __init__(
self,
*,
type: global___MessageType.ValueType = ...,
float_value: builtins.float = ...,
uint32_value: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["data", b"data", "float_value", b"float_value", "uint32_value", b"uint32_value"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["data", b"data", "float_value", b"float_value", "type", b"type", "uint32_value", b"uint32_value"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["data", b"data"]) -> typing.Literal["float_value", "uint32_value"] | None: ...
global___SensorData = SensorData
@typing.final
class InterdeviceMessage(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NMEA_FIELD_NUMBER: builtins.int
SENSOR_FIELD_NUMBER: builtins.int
nmea: builtins.str
@property
def sensor(self) -> global___SensorData: ...
def __init__(
self,
*,
nmea: builtins.str = ...,
sensor: global___SensorData | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["data", b"data", "nmea", b"nmea", "sensor", b"sensor"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["data", b"data", "nmea", b"nmea", "sensor", b"sensor"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["data", b"data"]) -> typing.Literal["nmea", "sensor"] | None: ...
global___InterdeviceMessage = InterdeviceMessage

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/localonly.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
from meshtastic.protobuf import module_config_pb2 as meshtastic_dot_protobuf_dot_module__config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/localonly.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/config.proto\x1a\'meshtastic/protobuf/module_config.proto\"\xfa\x03\n\x0bLocalConfig\x12\x38\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfig\x12<\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfig\x12\x36\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfig\x12:\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfig\x12:\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfig\x12\x34\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfig\x12>\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\x12<\n\x08security\x18\t \x01(\x0b\x32*.meshtastic.protobuf.Config.SecurityConfig\"\xf0\x07\n\x11LocalModuleConfig\x12:\n\x04mqtt\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.ModuleConfig.MQTTConfig\x12>\n\x06serial\x18\x02 \x01(\x0b\x32..meshtastic.protobuf.ModuleConfig.SerialConfig\x12[\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32<.meshtastic.protobuf.ModuleConfig.ExternalNotificationConfig\x12K\n\rstore_forward\x18\x04 \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.StoreForwardConfig\x12\x45\n\nrange_test\x18\x05 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.RangeTestConfig\x12\x44\n\ttelemetry\x18\x06 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.TelemetryConfig\x12M\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.CannedMessageConfig\x12<\n\x05\x61udio\x18\t \x01(\x0b\x32-.meshtastic.protobuf.ModuleConfig.AudioConfig\x12O\n\x0fremote_hardware\x18\n \x01(\x0b\x32\x36.meshtastic.protobuf.ModuleConfig.RemoteHardwareConfig\x12K\n\rneighbor_info\x18\x0b \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.NeighborInfoConfig\x12Q\n\x10\x61mbient_lighting\x18\x0c \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.AmbientLightingConfig\x12Q\n\x10\x64\x65tection_sensor\x18\r \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.DetectionSensorConfig\x12\x46\n\npaxcounter\x18\x0e \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.PaxcounterConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBe\n\x14org.meshtastic.protoB\x0fLocalOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.localonly_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\017LocalOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_LOCALCONFIG']._serialized_start=136
_globals['_LOCALCONFIG']._serialized_end=642
_globals['_LOCALMODULECONFIG']._serialized_start=645
_globals['_LOCALMODULECONFIG']._serialized_end=1653
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,228 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.message
import meshtastic.protobuf.config_pb2
import meshtastic.protobuf.module_config_pb2
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class LocalConfig(google.protobuf.message.Message):
"""
Protobuf structures common to apponly.proto and deviceonly.proto
This is never sent over the wire, only for local use
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
DEVICE_FIELD_NUMBER: builtins.int
POSITION_FIELD_NUMBER: builtins.int
POWER_FIELD_NUMBER: builtins.int
NETWORK_FIELD_NUMBER: builtins.int
DISPLAY_FIELD_NUMBER: builtins.int
LORA_FIELD_NUMBER: builtins.int
BLUETOOTH_FIELD_NUMBER: builtins.int
VERSION_FIELD_NUMBER: builtins.int
SECURITY_FIELD_NUMBER: builtins.int
version: builtins.int
"""
A version integer used to invalidate old save files when we make
incompatible changes This integer is set at build time and is private to
NodeDB.cpp in the device code.
"""
@property
def device(self) -> meshtastic.protobuf.config_pb2.Config.DeviceConfig:
"""
The part of the config that is specific to the Device
"""
@property
def position(self) -> meshtastic.protobuf.config_pb2.Config.PositionConfig:
"""
The part of the config that is specific to the GPS Position
"""
@property
def power(self) -> meshtastic.protobuf.config_pb2.Config.PowerConfig:
"""
The part of the config that is specific to the Power settings
"""
@property
def network(self) -> meshtastic.protobuf.config_pb2.Config.NetworkConfig:
"""
The part of the config that is specific to the Wifi Settings
"""
@property
def display(self) -> meshtastic.protobuf.config_pb2.Config.DisplayConfig:
"""
The part of the config that is specific to the Display
"""
@property
def lora(self) -> meshtastic.protobuf.config_pb2.Config.LoRaConfig:
"""
The part of the config that is specific to the Lora Radio
"""
@property
def bluetooth(self) -> meshtastic.protobuf.config_pb2.Config.BluetoothConfig:
"""
The part of the config that is specific to the Bluetooth settings
"""
@property
def security(self) -> meshtastic.protobuf.config_pb2.Config.SecurityConfig:
"""
The part of the config that is specific to Security settings
"""
def __init__(
self,
*,
device: meshtastic.protobuf.config_pb2.Config.DeviceConfig | None = ...,
position: meshtastic.protobuf.config_pb2.Config.PositionConfig | None = ...,
power: meshtastic.protobuf.config_pb2.Config.PowerConfig | None = ...,
network: meshtastic.protobuf.config_pb2.Config.NetworkConfig | None = ...,
display: meshtastic.protobuf.config_pb2.Config.DisplayConfig | None = ...,
lora: meshtastic.protobuf.config_pb2.Config.LoRaConfig | None = ...,
bluetooth: meshtastic.protobuf.config_pb2.Config.BluetoothConfig | None = ...,
version: builtins.int = ...,
security: meshtastic.protobuf.config_pb2.Config.SecurityConfig | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "display", b"display", "lora", b"lora", "network", b"network", "position", b"position", "power", b"power", "security", b"security"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "display", b"display", "lora", b"lora", "network", b"network", "position", b"position", "power", b"power", "security", b"security", "version", b"version"]) -> None: ...
global___LocalConfig = LocalConfig
@typing.final
class LocalModuleConfig(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MQTT_FIELD_NUMBER: builtins.int
SERIAL_FIELD_NUMBER: builtins.int
EXTERNAL_NOTIFICATION_FIELD_NUMBER: builtins.int
STORE_FORWARD_FIELD_NUMBER: builtins.int
RANGE_TEST_FIELD_NUMBER: builtins.int
TELEMETRY_FIELD_NUMBER: builtins.int
CANNED_MESSAGE_FIELD_NUMBER: builtins.int
AUDIO_FIELD_NUMBER: builtins.int
REMOTE_HARDWARE_FIELD_NUMBER: builtins.int
NEIGHBOR_INFO_FIELD_NUMBER: builtins.int
AMBIENT_LIGHTING_FIELD_NUMBER: builtins.int
DETECTION_SENSOR_FIELD_NUMBER: builtins.int
PAXCOUNTER_FIELD_NUMBER: builtins.int
VERSION_FIELD_NUMBER: builtins.int
version: builtins.int
"""
A version integer used to invalidate old save files when we make
incompatible changes This integer is set at build time and is private to
NodeDB.cpp in the device code.
"""
@property
def mqtt(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.MQTTConfig:
"""
The part of the config that is specific to the MQTT module
"""
@property
def serial(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.SerialConfig:
"""
The part of the config that is specific to the Serial module
"""
@property
def external_notification(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.ExternalNotificationConfig:
"""
The part of the config that is specific to the ExternalNotification module
"""
@property
def store_forward(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.StoreForwardConfig:
"""
The part of the config that is specific to the Store & Forward module
"""
@property
def range_test(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.RangeTestConfig:
"""
The part of the config that is specific to the RangeTest module
"""
@property
def telemetry(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.TelemetryConfig:
"""
The part of the config that is specific to the Telemetry module
"""
@property
def canned_message(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.CannedMessageConfig:
"""
The part of the config that is specific to the Canned Message module
"""
@property
def audio(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.AudioConfig:
"""
The part of the config that is specific to the Audio module
"""
@property
def remote_hardware(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.RemoteHardwareConfig:
"""
The part of the config that is specific to the Remote Hardware module
"""
@property
def neighbor_info(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.NeighborInfoConfig:
"""
The part of the config that is specific to the Neighbor Info module
"""
@property
def ambient_lighting(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.AmbientLightingConfig:
"""
The part of the config that is specific to the Ambient Lighting module
"""
@property
def detection_sensor(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.DetectionSensorConfig:
"""
The part of the config that is specific to the Detection Sensor module
"""
@property
def paxcounter(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.PaxcounterConfig:
"""
Paxcounter Config
"""
def __init__(
self,
*,
mqtt: meshtastic.protobuf.module_config_pb2.ModuleConfig.MQTTConfig | None = ...,
serial: meshtastic.protobuf.module_config_pb2.ModuleConfig.SerialConfig | None = ...,
external_notification: meshtastic.protobuf.module_config_pb2.ModuleConfig.ExternalNotificationConfig | None = ...,
store_forward: meshtastic.protobuf.module_config_pb2.ModuleConfig.StoreForwardConfig | None = ...,
range_test: meshtastic.protobuf.module_config_pb2.ModuleConfig.RangeTestConfig | None = ...,
telemetry: meshtastic.protobuf.module_config_pb2.ModuleConfig.TelemetryConfig | None = ...,
canned_message: meshtastic.protobuf.module_config_pb2.ModuleConfig.CannedMessageConfig | None = ...,
audio: meshtastic.protobuf.module_config_pb2.ModuleConfig.AudioConfig | None = ...,
remote_hardware: meshtastic.protobuf.module_config_pb2.ModuleConfig.RemoteHardwareConfig | None = ...,
neighbor_info: meshtastic.protobuf.module_config_pb2.ModuleConfig.NeighborInfoConfig | None = ...,
ambient_lighting: meshtastic.protobuf.module_config_pb2.ModuleConfig.AmbientLightingConfig | None = ...,
detection_sensor: meshtastic.protobuf.module_config_pb2.ModuleConfig.DetectionSensorConfig | None = ...,
paxcounter: meshtastic.protobuf.module_config_pb2.ModuleConfig.PaxcounterConfig | None = ...,
version: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "store_forward", b"store_forward", "telemetry", b"telemetry"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "store_forward", b"store_forward", "telemetry", b"telemetry", "version", b"version"]) -> None: ...
global___LocalModuleConfig = LocalModuleConfig

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/mqtt.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/mqtt.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/config.proto\x1a\x1emeshtastic/protobuf/mesh.proto\"j\n\x0fServiceEnvelope\x12/\n\x06packet\x18\x01 \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x12\n\nchannel_id\x18\x02 \x01(\t\x12\x12\n\ngateway_id\x18\x03 \x01(\t\"\x83\x04\n\tMapReport\x12\x11\n\tlong_name\x18\x01 \x01(\t\x12\x12\n\nshort_name\x18\x02 \x01(\t\x12;\n\x04role\x18\x03 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x34\n\x08hw_model\x18\x04 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12\x18\n\x10\x66irmware_version\x18\x05 \x01(\t\x12\x41\n\x06region\x18\x06 \x01(\x0e\x32\x31.meshtastic.protobuf.Config.LoRaConfig.RegionCode\x12H\n\x0cmodem_preset\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.Config.LoRaConfig.ModemPreset\x12\x1b\n\x13has_default_channel\x18\x08 \x01(\x08\x12\x12\n\nlatitude_i\x18\t \x01(\x0f\x12\x13\n\x0blongitude_i\x18\n \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x0b \x01(\x05\x12\x1a\n\x12position_precision\x18\x0c \x01(\r\x12\x1e\n\x16num_online_local_nodes\x18\r \x01(\r\x12!\n\x19has_opted_report_location\x18\x0e \x01(\x08\x42`\n\x14org.meshtastic.protoB\nMQTTProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.mqtt_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\nMQTTProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_SERVICEENVELOPE']._serialized_start=121
_globals['_SERVICEENVELOPE']._serialized_end=227
_globals['_MAPREPORT']._serialized_start=230
_globals['_MAPREPORT']._serialized_end=745
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,155 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.message
import meshtastic.protobuf.config_pb2
import meshtastic.protobuf.mesh_pb2
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class ServiceEnvelope(google.protobuf.message.Message):
"""
This message wraps a MeshPacket with extra metadata about the sender and how it arrived.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
PACKET_FIELD_NUMBER: builtins.int
CHANNEL_ID_FIELD_NUMBER: builtins.int
GATEWAY_ID_FIELD_NUMBER: builtins.int
channel_id: builtins.str
"""
The global channel ID it was sent on
"""
gateway_id: builtins.str
"""
The sending gateway node ID. Can we use this to authenticate/prevent fake
nodeid impersonation for senders? - i.e. use gateway/mesh id (which is authenticated) + local node id as
the globally trusted nodenum
"""
@property
def packet(self) -> meshtastic.protobuf.mesh_pb2.MeshPacket:
"""
The (probably encrypted) packet
"""
def __init__(
self,
*,
packet: meshtastic.protobuf.mesh_pb2.MeshPacket | None = ...,
channel_id: builtins.str = ...,
gateway_id: builtins.str = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["packet", b"packet"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["channel_id", b"channel_id", "gateway_id", b"gateway_id", "packet", b"packet"]) -> None: ...
global___ServiceEnvelope = ServiceEnvelope
@typing.final
class MapReport(google.protobuf.message.Message):
"""
Information about a node intended to be reported unencrypted to a map using MQTT.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
LONG_NAME_FIELD_NUMBER: builtins.int
SHORT_NAME_FIELD_NUMBER: builtins.int
ROLE_FIELD_NUMBER: builtins.int
HW_MODEL_FIELD_NUMBER: builtins.int
FIRMWARE_VERSION_FIELD_NUMBER: builtins.int
REGION_FIELD_NUMBER: builtins.int
MODEM_PRESET_FIELD_NUMBER: builtins.int
HAS_DEFAULT_CHANNEL_FIELD_NUMBER: builtins.int
LATITUDE_I_FIELD_NUMBER: builtins.int
LONGITUDE_I_FIELD_NUMBER: builtins.int
ALTITUDE_FIELD_NUMBER: builtins.int
POSITION_PRECISION_FIELD_NUMBER: builtins.int
NUM_ONLINE_LOCAL_NODES_FIELD_NUMBER: builtins.int
HAS_OPTED_REPORT_LOCATION_FIELD_NUMBER: builtins.int
long_name: builtins.str
"""
A full name for this user, i.e. "Kevin Hester"
"""
short_name: builtins.str
"""
A VERY short name, ideally two characters.
Suitable for a tiny OLED screen
"""
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType
"""
Role of the node that applies specific settings for a particular use-case
"""
hw_model: meshtastic.protobuf.mesh_pb2.HardwareModel.ValueType
"""
Hardware model of the node, i.e. T-Beam, Heltec V3, etc...
"""
firmware_version: builtins.str
"""
Device firmware version string
"""
region: meshtastic.protobuf.config_pb2.Config.LoRaConfig.RegionCode.ValueType
"""
The region code for the radio (US, CN, EU433, etc...)
"""
modem_preset: meshtastic.protobuf.config_pb2.Config.LoRaConfig.ModemPreset.ValueType
"""
Modem preset used by the radio (LongFast, MediumSlow, etc...)
"""
has_default_channel: builtins.bool
"""
Whether the node has a channel with default PSK and name (LongFast, MediumSlow, etc...)
and it uses the default frequency slot given the region and modem preset.
"""
latitude_i: builtins.int
"""
Latitude: multiply by 1e-7 to get degrees in floating point
"""
longitude_i: builtins.int
"""
Longitude: multiply by 1e-7 to get degrees in floating point
"""
altitude: builtins.int
"""
Altitude in meters above MSL
"""
position_precision: builtins.int
"""
Indicates the bits of precision for latitude and longitude set by the sending node
"""
num_online_local_nodes: builtins.int
"""
Number of online nodes (heard in the last 2 hours) this node has in its list that were received locally (not via MQTT)
"""
has_opted_report_location: builtins.bool
"""
User has opted in to share their location (map report) with the mqtt server
Controlled by map_report.should_report_location
"""
def __init__(
self,
*,
long_name: builtins.str = ...,
short_name: builtins.str = ...,
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType = ...,
hw_model: meshtastic.protobuf.mesh_pb2.HardwareModel.ValueType = ...,
firmware_version: builtins.str = ...,
region: meshtastic.protobuf.config_pb2.Config.LoRaConfig.RegionCode.ValueType = ...,
modem_preset: meshtastic.protobuf.config_pb2.Config.LoRaConfig.ModemPreset.ValueType = ...,
has_default_channel: builtins.bool = ...,
latitude_i: builtins.int = ...,
longitude_i: builtins.int = ...,
altitude: builtins.int = ...,
position_precision: builtins.int = ...,
num_online_local_nodes: builtins.int = ...,
has_opted_report_location: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["altitude", b"altitude", "firmware_version", b"firmware_version", "has_default_channel", b"has_default_channel", "has_opted_report_location", b"has_opted_report_location", "hw_model", b"hw_model", "latitude_i", b"latitude_i", "long_name", b"long_name", "longitude_i", b"longitude_i", "modem_preset", b"modem_preset", "num_online_local_nodes", b"num_online_local_nodes", "position_precision", b"position_precision", "region", b"region", "role", b"role", "short_name", b"short_name"]) -> None: ...
global___MapReport = MapReport

View File

@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/nanopb.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/protobuf/nanopb.proto\x1a google/protobuf/descriptor.proto\"\xa4\x07\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x12\n\nmax_length\x18\x0e \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12&\n\x08int_size\x18\x07 \x01(\x0e\x32\x08.IntSize:\nIS_DEFAULT\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bpacked_enum\x18\n \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0cskip_message\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x18\n\tno_unions\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05msgid\x18\t \x01(\r\x12\x1e\n\x0f\x61nonymous_oneof\x18\x0b \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06proto3\x18\x0c \x01(\x08:\x05\x66\x61lse\x12#\n\x14proto3_singular_msgs\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0e\x65num_to_string\x18\r \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0c\x66ixed_length\x18\x0f \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0b\x66ixed_count\x18\x10 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0fsubmsg_callback\x18\x16 \x01(\x08:\x05\x66\x61lse\x12/\n\x0cmangle_names\x18\x11 \x01(\x0e\x32\x11.TypenameMangling:\x06M_NONE\x12(\n\x11\x63\x61llback_datatype\x18\x12 \x01(\t:\rpb_callback_t\x12\x34\n\x11\x63\x61llback_function\x18\x13 \x01(\t:\x19pb_default_field_callback\x12\x30\n\x0e\x64\x65scriptorsize\x18\x14 \x01(\x0e\x32\x0f.DescriptorSize:\x07\x44S_AUTO\x12\x1a\n\x0b\x64\x65\x66\x61ult_has\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07include\x18\x18 \x03(\t\x12\x0f\n\x07\x65xclude\x18\x1a \x03(\t\x12\x0f\n\x07package\x18\x19 \x01(\t\x12\x41\n\rtype_override\x18\x1b \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x19\n\x0bsort_by_tag\x18\x1c \x01(\x08:\x04true\x12.\n\rfallback_type\x18\x1d \x01(\x0e\x32\n.FieldType:\x0b\x46T_CALLBACK*i\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03\x12\r\n\tFT_INLINE\x10\x05*D\n\x07IntSize\x12\x0e\n\nIS_DEFAULT\x10\x00\x12\x08\n\x04IS_8\x10\x08\x12\t\n\x05IS_16\x10\x10\x12\t\n\x05IS_32\x10 \x12\t\n\x05IS_64\x10@*Z\n\x10TypenameMangling\x12\n\n\x06M_NONE\x10\x00\x12\x13\n\x0fM_STRIP_PACKAGE\x10\x01\x12\r\n\tM_FLATTEN\x10\x02\x12\x16\n\x12M_PACKAGE_INITIALS\x10\x03*E\n\x0e\x44\x65scriptorSize\x12\x0b\n\x07\x44S_AUTO\x10\x00\x12\x08\n\x04\x44S_1\x10\x01\x12\x08\n\x04\x44S_2\x10\x02\x12\x08\n\x04\x44S_4\x10\x04\x12\x08\n\x04\x44S_8\x10\x08:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB>\n\x18\x66i.kapsi.koti.jpa.nanopbZ\"github.com/meshtastic/go/generated')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.nanopb_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\030fi.kapsi.koti.jpa.nanopbZ\"github.com/meshtastic/go/generated'
_globals['_FIELDTYPE']._serialized_start=1005
_globals['_FIELDTYPE']._serialized_end=1110
_globals['_INTSIZE']._serialized_start=1112
_globals['_INTSIZE']._serialized_end=1180
_globals['_TYPENAMEMANGLING']._serialized_start=1182
_globals['_TYPENAMEMANGLING']._serialized_end=1272
_globals['_DESCRIPTORSIZE']._serialized_start=1274
_globals['_DESCRIPTORSIZE']._serialized_end=1343
_globals['_NANOPBOPTIONS']._serialized_start=71
_globals['_NANOPBOPTIONS']._serialized_end=1003
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,324 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
Custom options for defining:
- Maximum size of string/bytes
- Maximum number of elements in array
These are used by nanopb to generate statically allocable structures
for memory-limited environments.
"""
import builtins
import collections.abc
import google.protobuf.descriptor
import google.protobuf.descriptor_pb2
import google.protobuf.internal.containers
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.internal.extension_dict
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _FieldType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _FieldTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_FieldType.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
FT_DEFAULT: _FieldType.ValueType # 0
"""Automatically decide field type, generate static field if possible."""
FT_CALLBACK: _FieldType.ValueType # 1
"""Always generate a callback field."""
FT_POINTER: _FieldType.ValueType # 4
"""Always generate a dynamically allocated field."""
FT_STATIC: _FieldType.ValueType # 2
"""Generate a static field or raise an exception if not possible."""
FT_IGNORE: _FieldType.ValueType # 3
"""Ignore the field completely."""
FT_INLINE: _FieldType.ValueType # 5
"""Legacy option, use the separate 'fixed_length' option instead"""
class FieldType(_FieldType, metaclass=_FieldTypeEnumTypeWrapper): ...
FT_DEFAULT: FieldType.ValueType # 0
"""Automatically decide field type, generate static field if possible."""
FT_CALLBACK: FieldType.ValueType # 1
"""Always generate a callback field."""
FT_POINTER: FieldType.ValueType # 4
"""Always generate a dynamically allocated field."""
FT_STATIC: FieldType.ValueType # 2
"""Generate a static field or raise an exception if not possible."""
FT_IGNORE: FieldType.ValueType # 3
"""Ignore the field completely."""
FT_INLINE: FieldType.ValueType # 5
"""Legacy option, use the separate 'fixed_length' option instead"""
global___FieldType = FieldType
class _IntSize:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _IntSizeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_IntSize.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
IS_DEFAULT: _IntSize.ValueType # 0
"""Default, 32/64bit based on type in .proto"""
IS_8: _IntSize.ValueType # 8
IS_16: _IntSize.ValueType # 16
IS_32: _IntSize.ValueType # 32
IS_64: _IntSize.ValueType # 64
class IntSize(_IntSize, metaclass=_IntSizeEnumTypeWrapper): ...
IS_DEFAULT: IntSize.ValueType # 0
"""Default, 32/64bit based on type in .proto"""
IS_8: IntSize.ValueType # 8
IS_16: IntSize.ValueType # 16
IS_32: IntSize.ValueType # 32
IS_64: IntSize.ValueType # 64
global___IntSize = IntSize
class _TypenameMangling:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _TypenameManglingEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_TypenameMangling.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
M_NONE: _TypenameMangling.ValueType # 0
"""Default, no typename mangling"""
M_STRIP_PACKAGE: _TypenameMangling.ValueType # 1
"""Strip current package name"""
M_FLATTEN: _TypenameMangling.ValueType # 2
"""Only use last path component"""
M_PACKAGE_INITIALS: _TypenameMangling.ValueType # 3
"""Replace the package name by the initials"""
class TypenameMangling(_TypenameMangling, metaclass=_TypenameManglingEnumTypeWrapper): ...
M_NONE: TypenameMangling.ValueType # 0
"""Default, no typename mangling"""
M_STRIP_PACKAGE: TypenameMangling.ValueType # 1
"""Strip current package name"""
M_FLATTEN: TypenameMangling.ValueType # 2
"""Only use last path component"""
M_PACKAGE_INITIALS: TypenameMangling.ValueType # 3
"""Replace the package name by the initials"""
global___TypenameMangling = TypenameMangling
class _DescriptorSize:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _DescriptorSizeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_DescriptorSize.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
DS_AUTO: _DescriptorSize.ValueType # 0
"""Select minimal size based on field type"""
DS_1: _DescriptorSize.ValueType # 1
"""1 word; up to 15 byte fields, no arrays"""
DS_2: _DescriptorSize.ValueType # 2
"""2 words; up to 4095 byte fields, 4095 entry arrays"""
DS_4: _DescriptorSize.ValueType # 4
"""4 words; up to 2^32-1 byte fields, 2^16-1 entry arrays"""
DS_8: _DescriptorSize.ValueType # 8
"""8 words; up to 2^32-1 entry arrays"""
class DescriptorSize(_DescriptorSize, metaclass=_DescriptorSizeEnumTypeWrapper): ...
DS_AUTO: DescriptorSize.ValueType # 0
"""Select minimal size based on field type"""
DS_1: DescriptorSize.ValueType # 1
"""1 word; up to 15 byte fields, no arrays"""
DS_2: DescriptorSize.ValueType # 2
"""2 words; up to 4095 byte fields, 4095 entry arrays"""
DS_4: DescriptorSize.ValueType # 4
"""4 words; up to 2^32-1 byte fields, 2^16-1 entry arrays"""
DS_8: DescriptorSize.ValueType # 8
"""8 words; up to 2^32-1 entry arrays"""
global___DescriptorSize = DescriptorSize
@typing.final
class NanoPBOptions(google.protobuf.message.Message):
"""This is the inner options message, which basically defines options for
a field. When it is used in message or file scope, it applies to all
fields.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MAX_SIZE_FIELD_NUMBER: builtins.int
MAX_LENGTH_FIELD_NUMBER: builtins.int
MAX_COUNT_FIELD_NUMBER: builtins.int
INT_SIZE_FIELD_NUMBER: builtins.int
TYPE_FIELD_NUMBER: builtins.int
LONG_NAMES_FIELD_NUMBER: builtins.int
PACKED_STRUCT_FIELD_NUMBER: builtins.int
PACKED_ENUM_FIELD_NUMBER: builtins.int
SKIP_MESSAGE_FIELD_NUMBER: builtins.int
NO_UNIONS_FIELD_NUMBER: builtins.int
MSGID_FIELD_NUMBER: builtins.int
ANONYMOUS_ONEOF_FIELD_NUMBER: builtins.int
PROTO3_FIELD_NUMBER: builtins.int
PROTO3_SINGULAR_MSGS_FIELD_NUMBER: builtins.int
ENUM_TO_STRING_FIELD_NUMBER: builtins.int
FIXED_LENGTH_FIELD_NUMBER: builtins.int
FIXED_COUNT_FIELD_NUMBER: builtins.int
SUBMSG_CALLBACK_FIELD_NUMBER: builtins.int
MANGLE_NAMES_FIELD_NUMBER: builtins.int
CALLBACK_DATATYPE_FIELD_NUMBER: builtins.int
CALLBACK_FUNCTION_FIELD_NUMBER: builtins.int
DESCRIPTORSIZE_FIELD_NUMBER: builtins.int
DEFAULT_HAS_FIELD_NUMBER: builtins.int
INCLUDE_FIELD_NUMBER: builtins.int
EXCLUDE_FIELD_NUMBER: builtins.int
PACKAGE_FIELD_NUMBER: builtins.int
TYPE_OVERRIDE_FIELD_NUMBER: builtins.int
SORT_BY_TAG_FIELD_NUMBER: builtins.int
FALLBACK_TYPE_FIELD_NUMBER: builtins.int
max_size: builtins.int
"""Allocated size for 'bytes' and 'string' fields.
For string fields, this should include the space for null terminator.
"""
max_length: builtins.int
"""Maximum length for 'string' fields. Setting this is equivalent
to setting max_size to a value of length+1.
"""
max_count: builtins.int
"""Allocated number of entries in arrays ('repeated' fields)"""
int_size: global___IntSize.ValueType
"""Size of integer fields. Can save some memory if you don't need
full 32 bits for the value.
"""
type: global___FieldType.ValueType
"""Force type of field (callback or static allocation)"""
long_names: builtins.bool
"""Use long names for enums, i.e. EnumName_EnumValue."""
packed_struct: builtins.bool
"""Add 'packed' attribute to generated structs.
Note: this cannot be used on CPUs that break on unaligned
accesses to variables.
"""
packed_enum: builtins.bool
"""Add 'packed' attribute to generated enums."""
skip_message: builtins.bool
"""Skip this message"""
no_unions: builtins.bool
"""Generate oneof fields as normal optional fields instead of union."""
msgid: builtins.int
"""integer type tag for a message"""
anonymous_oneof: builtins.bool
"""decode oneof as anonymous union"""
proto3: builtins.bool
"""Proto3 singular field does not generate a "has_" flag"""
proto3_singular_msgs: builtins.bool
"""Force proto3 messages to have no "has_" flag.
This was default behavior until nanopb-0.4.0.
"""
enum_to_string: builtins.bool
"""Generate an enum->string mapping function (can take up lots of space)."""
fixed_length: builtins.bool
"""Generate bytes arrays with fixed length"""
fixed_count: builtins.bool
"""Generate repeated field with fixed count"""
submsg_callback: builtins.bool
"""Generate message-level callback that is called before decoding submessages.
This can be used to set callback fields for submsgs inside oneofs.
"""
mangle_names: global___TypenameMangling.ValueType
"""Shorten or remove package names from type names.
This option applies only on the file level.
"""
callback_datatype: builtins.str
"""Data type for storage associated with callback fields."""
callback_function: builtins.str
"""Callback function used for encoding and decoding.
Prior to nanopb-0.4.0, the callback was specified in per-field pb_callback_t
structure. This is still supported, but does not work inside e.g. oneof or pointer
fields. Instead, a new method allows specifying a per-message callback that
will be called for all callback fields in a message type.
"""
descriptorsize: global___DescriptorSize.ValueType
"""Select the size of field descriptors. This option has to be defined
for the whole message, not per-field. Usually automatic selection is
ok, but if it results in compilation errors you can increase the field
size here.
"""
default_has: builtins.bool
"""Set default value for has_ fields."""
package: builtins.str
"""Package name that applies only for nanopb."""
type_override: google.protobuf.descriptor_pb2.FieldDescriptorProto.Type.ValueType
"""Override type of the field in generated C code. Only to be used with related field types"""
sort_by_tag: builtins.bool
"""Due to historical reasons, nanopb orders fields in structs by their tag number
instead of the order in .proto. Set this to false to keep the .proto order.
The default value will probably change to false in nanopb-0.5.0.
"""
fallback_type: global___FieldType.ValueType
"""Set the FT_DEFAULT field conversion strategy.
A field that can become a static member of a c struct (e.g. int, bool, etc)
will be a a static field.
Fields with dynamic length are converted to either a pointer or a callback.
"""
@property
def include(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]:
"""Extra files to include in generated `.pb.h`"""
@property
def exclude(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]:
"""Automatic includes to exclude from generated `.pb.h`
Same as nanopb_generator.py command line flag -x.
"""
def __init__(
self,
*,
max_size: builtins.int | None = ...,
max_length: builtins.int | None = ...,
max_count: builtins.int | None = ...,
int_size: global___IntSize.ValueType | None = ...,
type: global___FieldType.ValueType | None = ...,
long_names: builtins.bool | None = ...,
packed_struct: builtins.bool | None = ...,
packed_enum: builtins.bool | None = ...,
skip_message: builtins.bool | None = ...,
no_unions: builtins.bool | None = ...,
msgid: builtins.int | None = ...,
anonymous_oneof: builtins.bool | None = ...,
proto3: builtins.bool | None = ...,
proto3_singular_msgs: builtins.bool | None = ...,
enum_to_string: builtins.bool | None = ...,
fixed_length: builtins.bool | None = ...,
fixed_count: builtins.bool | None = ...,
submsg_callback: builtins.bool | None = ...,
mangle_names: global___TypenameMangling.ValueType | None = ...,
callback_datatype: builtins.str | None = ...,
callback_function: builtins.str | None = ...,
descriptorsize: global___DescriptorSize.ValueType | None = ...,
default_has: builtins.bool | None = ...,
include: collections.abc.Iterable[builtins.str] | None = ...,
exclude: collections.abc.Iterable[builtins.str] | None = ...,
package: builtins.str | None = ...,
type_override: google.protobuf.descriptor_pb2.FieldDescriptorProto.Type.ValueType | None = ...,
sort_by_tag: builtins.bool | None = ...,
fallback_type: global___FieldType.ValueType | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["anonymous_oneof", b"anonymous_oneof", "callback_datatype", b"callback_datatype", "callback_function", b"callback_function", "default_has", b"default_has", "descriptorsize", b"descriptorsize", "enum_to_string", b"enum_to_string", "fallback_type", b"fallback_type", "fixed_count", b"fixed_count", "fixed_length", b"fixed_length", "int_size", b"int_size", "long_names", b"long_names", "mangle_names", b"mangle_names", "max_count", b"max_count", "max_length", b"max_length", "max_size", b"max_size", "msgid", b"msgid", "no_unions", b"no_unions", "package", b"package", "packed_enum", b"packed_enum", "packed_struct", b"packed_struct", "proto3", b"proto3", "proto3_singular_msgs", b"proto3_singular_msgs", "skip_message", b"skip_message", "sort_by_tag", b"sort_by_tag", "submsg_callback", b"submsg_callback", "type", b"type", "type_override", b"type_override"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["anonymous_oneof", b"anonymous_oneof", "callback_datatype", b"callback_datatype", "callback_function", b"callback_function", "default_has", b"default_has", "descriptorsize", b"descriptorsize", "enum_to_string", b"enum_to_string", "exclude", b"exclude", "fallback_type", b"fallback_type", "fixed_count", b"fixed_count", "fixed_length", b"fixed_length", "include", b"include", "int_size", b"int_size", "long_names", b"long_names", "mangle_names", b"mangle_names", "max_count", b"max_count", "max_length", b"max_length", "max_size", b"max_size", "msgid", b"msgid", "no_unions", b"no_unions", "package", b"package", "packed_enum", b"packed_enum", "packed_struct", b"packed_struct", "proto3", b"proto3", "proto3_singular_msgs", b"proto3_singular_msgs", "skip_message", b"skip_message", "sort_by_tag", b"sort_by_tag", "submsg_callback", b"submsg_callback", "type", b"type", "type_override", b"type_override"]) -> None: ...
global___NanoPBOptions = NanoPBOptions
NANOPB_FILEOPT_FIELD_NUMBER: builtins.int
NANOPB_MSGOPT_FIELD_NUMBER: builtins.int
NANOPB_ENUMOPT_FIELD_NUMBER: builtins.int
NANOPB_FIELD_NUMBER: builtins.int
nanopb_fileopt: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FileOptions, global___NanoPBOptions]
nanopb_msgopt: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MessageOptions, global___NanoPBOptions]
nanopb_enumopt: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.EnumOptions, global___NanoPBOptions]
nanopb: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FieldOptions, global___NanoPBOptions]

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/paxcount.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/paxcount.proto\x12\x13meshtastic.protobuf\"5\n\x08Paxcount\x12\x0c\n\x04wifi\x18\x01 \x01(\r\x12\x0b\n\x03\x62le\x18\x02 \x01(\r\x12\x0e\n\x06uptime\x18\x03 \x01(\rBd\n\x14org.meshtastic.protoB\x0ePaxcountProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.paxcount_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\016PaxcountProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_PAXCOUNT']._serialized_start=59
_globals['_PAXCOUNT']._serialized_end=112
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,45 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.message
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class Paxcount(google.protobuf.message.Message):
"""
TODO: REPLACE
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
WIFI_FIELD_NUMBER: builtins.int
BLE_FIELD_NUMBER: builtins.int
UPTIME_FIELD_NUMBER: builtins.int
wifi: builtins.int
"""
seen Wifi devices
"""
ble: builtins.int
"""
Seen BLE devices
"""
uptime: builtins.int
"""
Uptime in seconds
"""
def __init__(
self,
*,
wifi: builtins.int = ...,
ble: builtins.int = ...,
uptime: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["ble", b"ble", "uptime", b"uptime", "wifi", b"wifi"]) -> None: ...
global___Paxcount = Paxcount

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/portnums.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\xf6\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tALERT_APP\x10\x0b\x12\x18\n\x14KEY_VERIFICATION_APP\x10\x0c\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x13\n\x0fPOWERSTRESS_APP\x10J\x12\x18\n\x14RETICULUM_TUNNEL_APP\x10L\x12\x0f\n\x0b\x43\x41YENNE_APP\x10M\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42^\n\x14org.meshtastic.protoB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.portnums_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\010PortnumsZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_PORTNUM']._serialized_start=60
_globals['_PORTNUM']._serialized_end=690
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,416 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _PortNum:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _PortNumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_PortNum.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
UNKNOWN_APP: _PortNum.ValueType # 0
"""
Deprecated: do not use in new code (formerly called OPAQUE)
A message sent from a device outside of the mesh, in a form the mesh does not understand
NOTE: This must be 0, because it is documented in IMeshService.aidl to be so
ENCODING: binary undefined
"""
TEXT_MESSAGE_APP: _PortNum.ValueType # 1
"""
A simple UTF-8 text message, which even the little micros in the mesh
can understand and show on their screen eventually in some circumstances
even signal might send messages in this form (see below)
ENCODING: UTF-8 Plaintext (?)
"""
REMOTE_HARDWARE_APP: _PortNum.ValueType # 2
"""
Reserved for built-in GPIO/example app.
See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number
ENCODING: Protobuf
"""
POSITION_APP: _PortNum.ValueType # 3
"""
The built-in position messaging app.
Payload is a Position message.
ENCODING: Protobuf
"""
NODEINFO_APP: _PortNum.ValueType # 4
"""
The built-in user info app.
Payload is a User message.
ENCODING: Protobuf
"""
ROUTING_APP: _PortNum.ValueType # 5
"""
Protocol control packets for mesh protocol use.
Payload is a Routing message.
ENCODING: Protobuf
"""
ADMIN_APP: _PortNum.ValueType # 6
"""
Admin control packets.
Payload is a AdminMessage message.
ENCODING: Protobuf
"""
TEXT_MESSAGE_COMPRESSED_APP: _PortNum.ValueType # 7
"""
Compressed TEXT_MESSAGE payloads.
ENCODING: UTF-8 Plaintext (?) with Unishox2 Compression
NOTE: The Device Firmware converts a TEXT_MESSAGE_APP to TEXT_MESSAGE_COMPRESSED_APP if the compressed
payload is shorter. There's no need for app developers to do this themselves. Also the firmware will decompress
any incoming TEXT_MESSAGE_COMPRESSED_APP payload and convert to TEXT_MESSAGE_APP.
"""
WAYPOINT_APP: _PortNum.ValueType # 8
"""
Waypoint payloads.
Payload is a Waypoint message.
ENCODING: Protobuf
"""
AUDIO_APP: _PortNum.ValueType # 9
"""
Audio Payloads.
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now
ENCODING: codec2 audio frames
NOTE: audio frames contain a 3 byte header (0xc0 0xde 0xc2) and a one byte marker for the decompressed bitrate.
This marker comes from the 'moduleConfig.audio.bitrate' enum minus one.
"""
DETECTION_SENSOR_APP: _PortNum.ValueType # 10
"""
Same as Text Message but originating from Detection Sensor Module.
NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9
"""
ALERT_APP: _PortNum.ValueType # 11
"""
Same as Text Message but used for critical alerts.
"""
KEY_VERIFICATION_APP: _PortNum.ValueType # 12
"""
Module/port for handling key verification requests.
"""
REPLY_APP: _PortNum.ValueType # 32
"""
Provides a 'ping' service that replies to any packet it receives.
Also serves as a small example module.
ENCODING: ASCII Plaintext
"""
IP_TUNNEL_APP: _PortNum.ValueType # 33
"""
Used for the python IP tunnel feature
ENCODING: IP Packet. Handled by the python API, firmware ignores this one and pases on.
"""
PAXCOUNTER_APP: _PortNum.ValueType # 34
"""
Paxcounter lib included in the firmware
ENCODING: protobuf
"""
SERIAL_APP: _PortNum.ValueType # 64
"""
Provides a hardware serial interface to send and receive from the Meshtastic network.
Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic
network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network.
Maximum packet size of 240 bytes.
Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp.
ENCODING: binary undefined
"""
STORE_FORWARD_APP: _PortNum.ValueType # 65
"""
STORE_FORWARD_APP (Work in Progress)
Maintained by Jm Casler (MC Hamster) : jm@casler.org
ENCODING: Protobuf
"""
RANGE_TEST_APP: _PortNum.ValueType # 66
"""
Optional port for messages for the range test module.
ENCODING: ASCII Plaintext
NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9
"""
TELEMETRY_APP: _PortNum.ValueType # 67
"""
Provides a format to send and receive telemetry data from the Meshtastic network.
Maintained by Charles Crossan (crossan007) : crossan007@gmail.com
ENCODING: Protobuf
"""
ZPS_APP: _PortNum.ValueType # 68
"""
Experimental tools for estimating node position without a GPS
Maintained by Github user a-f-G-U-C (a Meshtastic contributor)
Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS
ENCODING: arrays of int64 fields
"""
SIMULATOR_APP: _PortNum.ValueType # 69
"""
Used to let multiple instances of Linux native applications communicate
as if they did using their LoRa chip.
Maintained by GitHub user GUVWAF.
Project files at https://github.com/GUVWAF/Meshtasticator
ENCODING: Protobuf (?)
"""
TRACEROUTE_APP: _PortNum.ValueType # 70
"""
Provides a traceroute functionality to show the route a packet towards
a certain destination would take on the mesh. Contains a RouteDiscovery message as payload.
ENCODING: Protobuf
"""
NEIGHBORINFO_APP: _PortNum.ValueType # 71
"""
Aggregates edge info for the network by sending out a list of each node's neighbors
ENCODING: Protobuf
"""
ATAK_PLUGIN: _PortNum.ValueType # 72
"""
ATAK Plugin
Portnum for payloads from the official Meshtastic ATAK plugin
"""
MAP_REPORT_APP: _PortNum.ValueType # 73
"""
Provides unencrypted information about a node for consumption by a map via MQTT
"""
POWERSTRESS_APP: _PortNum.ValueType # 74
"""
PowerStress based monitoring support (for automated power consumption testing)
"""
RETICULUM_TUNNEL_APP: _PortNum.ValueType # 76
"""
Reticulum Network Stack Tunnel App
ENCODING: Fragmented RNS Packet. Handled by Meshtastic RNS interface
"""
CAYENNE_APP: _PortNum.ValueType # 77
"""
App for transporting Cayenne Low Power Payload, popular for LoRaWAN sensor nodes. Offers ability to send
arbitrary telemetry over meshtastic that is not covered by telemetry.proto
ENCODING: CayenneLLP
"""
PRIVATE_APP: _PortNum.ValueType # 256
"""
Private applications should use portnums >= 256.
To simplify initial development and testing you can use "PRIVATE_APP"
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh))
"""
ATAK_FORWARDER: _PortNum.ValueType # 257
"""
ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder
ENCODING: libcotshrink
"""
MAX: _PortNum.ValueType # 511
"""
Currently we limit port nums to no higher than this value
"""
class PortNum(_PortNum, metaclass=_PortNumEnumTypeWrapper):
"""
For any new 'apps' that run on the device or via sister apps on phones/PCs they should pick and use a
unique 'portnum' for their application.
If you are making a new app using meshtastic, please send in a pull request to add your 'portnum' to this
master table.
PortNums should be assigned in the following range:
0-63 Core Meshtastic use, do not use for third party apps
64-127 Registered 3rd party apps, send in a pull request that adds a new entry to portnums.proto to register your application
256-511 Use one of these portnums for your private applications that you don't want to register publically
All other values are reserved.
Note: This was formerly a Type enum named 'typ' with the same id #
We have change to this 'portnum' based scheme for specifying app handlers for particular payloads.
This change is backwards compatible by treating the legacy OPAQUE/CLEAR_TEXT values identically.
"""
UNKNOWN_APP: PortNum.ValueType # 0
"""
Deprecated: do not use in new code (formerly called OPAQUE)
A message sent from a device outside of the mesh, in a form the mesh does not understand
NOTE: This must be 0, because it is documented in IMeshService.aidl to be so
ENCODING: binary undefined
"""
TEXT_MESSAGE_APP: PortNum.ValueType # 1
"""
A simple UTF-8 text message, which even the little micros in the mesh
can understand and show on their screen eventually in some circumstances
even signal might send messages in this form (see below)
ENCODING: UTF-8 Plaintext (?)
"""
REMOTE_HARDWARE_APP: PortNum.ValueType # 2
"""
Reserved for built-in GPIO/example app.
See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number
ENCODING: Protobuf
"""
POSITION_APP: PortNum.ValueType # 3
"""
The built-in position messaging app.
Payload is a Position message.
ENCODING: Protobuf
"""
NODEINFO_APP: PortNum.ValueType # 4
"""
The built-in user info app.
Payload is a User message.
ENCODING: Protobuf
"""
ROUTING_APP: PortNum.ValueType # 5
"""
Protocol control packets for mesh protocol use.
Payload is a Routing message.
ENCODING: Protobuf
"""
ADMIN_APP: PortNum.ValueType # 6
"""
Admin control packets.
Payload is a AdminMessage message.
ENCODING: Protobuf
"""
TEXT_MESSAGE_COMPRESSED_APP: PortNum.ValueType # 7
"""
Compressed TEXT_MESSAGE payloads.
ENCODING: UTF-8 Plaintext (?) with Unishox2 Compression
NOTE: The Device Firmware converts a TEXT_MESSAGE_APP to TEXT_MESSAGE_COMPRESSED_APP if the compressed
payload is shorter. There's no need for app developers to do this themselves. Also the firmware will decompress
any incoming TEXT_MESSAGE_COMPRESSED_APP payload and convert to TEXT_MESSAGE_APP.
"""
WAYPOINT_APP: PortNum.ValueType # 8
"""
Waypoint payloads.
Payload is a Waypoint message.
ENCODING: Protobuf
"""
AUDIO_APP: PortNum.ValueType # 9
"""
Audio Payloads.
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now
ENCODING: codec2 audio frames
NOTE: audio frames contain a 3 byte header (0xc0 0xde 0xc2) and a one byte marker for the decompressed bitrate.
This marker comes from the 'moduleConfig.audio.bitrate' enum minus one.
"""
DETECTION_SENSOR_APP: PortNum.ValueType # 10
"""
Same as Text Message but originating from Detection Sensor Module.
NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9
"""
ALERT_APP: PortNum.ValueType # 11
"""
Same as Text Message but used for critical alerts.
"""
KEY_VERIFICATION_APP: PortNum.ValueType # 12
"""
Module/port for handling key verification requests.
"""
REPLY_APP: PortNum.ValueType # 32
"""
Provides a 'ping' service that replies to any packet it receives.
Also serves as a small example module.
ENCODING: ASCII Plaintext
"""
IP_TUNNEL_APP: PortNum.ValueType # 33
"""
Used for the python IP tunnel feature
ENCODING: IP Packet. Handled by the python API, firmware ignores this one and pases on.
"""
PAXCOUNTER_APP: PortNum.ValueType # 34
"""
Paxcounter lib included in the firmware
ENCODING: protobuf
"""
SERIAL_APP: PortNum.ValueType # 64
"""
Provides a hardware serial interface to send and receive from the Meshtastic network.
Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic
network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network.
Maximum packet size of 240 bytes.
Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp.
ENCODING: binary undefined
"""
STORE_FORWARD_APP: PortNum.ValueType # 65
"""
STORE_FORWARD_APP (Work in Progress)
Maintained by Jm Casler (MC Hamster) : jm@casler.org
ENCODING: Protobuf
"""
RANGE_TEST_APP: PortNum.ValueType # 66
"""
Optional port for messages for the range test module.
ENCODING: ASCII Plaintext
NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9
"""
TELEMETRY_APP: PortNum.ValueType # 67
"""
Provides a format to send and receive telemetry data from the Meshtastic network.
Maintained by Charles Crossan (crossan007) : crossan007@gmail.com
ENCODING: Protobuf
"""
ZPS_APP: PortNum.ValueType # 68
"""
Experimental tools for estimating node position without a GPS
Maintained by Github user a-f-G-U-C (a Meshtastic contributor)
Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS
ENCODING: arrays of int64 fields
"""
SIMULATOR_APP: PortNum.ValueType # 69
"""
Used to let multiple instances of Linux native applications communicate
as if they did using their LoRa chip.
Maintained by GitHub user GUVWAF.
Project files at https://github.com/GUVWAF/Meshtasticator
ENCODING: Protobuf (?)
"""
TRACEROUTE_APP: PortNum.ValueType # 70
"""
Provides a traceroute functionality to show the route a packet towards
a certain destination would take on the mesh. Contains a RouteDiscovery message as payload.
ENCODING: Protobuf
"""
NEIGHBORINFO_APP: PortNum.ValueType # 71
"""
Aggregates edge info for the network by sending out a list of each node's neighbors
ENCODING: Protobuf
"""
ATAK_PLUGIN: PortNum.ValueType # 72
"""
ATAK Plugin
Portnum for payloads from the official Meshtastic ATAK plugin
"""
MAP_REPORT_APP: PortNum.ValueType # 73
"""
Provides unencrypted information about a node for consumption by a map via MQTT
"""
POWERSTRESS_APP: PortNum.ValueType # 74
"""
PowerStress based monitoring support (for automated power consumption testing)
"""
RETICULUM_TUNNEL_APP: PortNum.ValueType # 76
"""
Reticulum Network Stack Tunnel App
ENCODING: Fragmented RNS Packet. Handled by Meshtastic RNS interface
"""
CAYENNE_APP: PortNum.ValueType # 77
"""
App for transporting Cayenne Low Power Payload, popular for LoRaWAN sensor nodes. Offers ability to send
arbitrary telemetry over meshtastic that is not covered by telemetry.proto
ENCODING: CayenneLLP
"""
PRIVATE_APP: PortNum.ValueType # 256
"""
Private applications should use portnums >= 256.
To simplify initial development and testing you can use "PRIVATE_APP"
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh))
"""
ATAK_FORWARDER: PortNum.ValueType # 257
"""
ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder
ENCODING: libcotshrink
"""
MAX: PortNum.ValueType # 511
"""
Currently we limit port nums to no higher than this value
"""
global___PortNum = PortNum

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/powermon.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/powermon.proto\x12\x13meshtastic.protobuf\"\xe0\x01\n\x08PowerMon\"\xd3\x01\n\x05State\x12\x08\n\x04None\x10\x00\x12\x11\n\rCPU_DeepSleep\x10\x01\x12\x12\n\x0e\x43PU_LightSleep\x10\x02\x12\x0c\n\x08Vext1_On\x10\x04\x12\r\n\tLora_RXOn\x10\x08\x12\r\n\tLora_TXOn\x10\x10\x12\x11\n\rLora_RXActive\x10 \x12\t\n\x05\x42T_On\x10@\x12\x0b\n\x06LED_On\x10\x80\x01\x12\x0e\n\tScreen_On\x10\x80\x02\x12\x13\n\x0eScreen_Drawing\x10\x80\x04\x12\x0c\n\x07Wifi_On\x10\x80\x08\x12\x0f\n\nGPS_Active\x10\x80\x10\"\x88\x03\n\x12PowerStressMessage\x12;\n\x03\x63md\x18\x01 \x01(\x0e\x32..meshtastic.protobuf.PowerStressMessage.Opcode\x12\x13\n\x0bnum_seconds\x18\x02 \x01(\x02\"\x9f\x02\n\x06Opcode\x12\t\n\x05UNSET\x10\x00\x12\x0e\n\nPRINT_INFO\x10\x01\x12\x0f\n\x0b\x46ORCE_QUIET\x10\x02\x12\r\n\tEND_QUIET\x10\x03\x12\r\n\tSCREEN_ON\x10\x10\x12\x0e\n\nSCREEN_OFF\x10\x11\x12\x0c\n\x08\x43PU_IDLE\x10 \x12\x11\n\rCPU_DEEPSLEEP\x10!\x12\x0e\n\nCPU_FULLON\x10\"\x12\n\n\x06LED_ON\x10\x30\x12\x0b\n\x07LED_OFF\x10\x31\x12\x0c\n\x08LORA_OFF\x10@\x12\x0b\n\x07LORA_TX\x10\x41\x12\x0b\n\x07LORA_RX\x10\x42\x12\n\n\x06\x42T_OFF\x10P\x12\t\n\x05\x42T_ON\x10Q\x12\x0c\n\x08WIFI_OFF\x10`\x12\x0b\n\x07WIFI_ON\x10\x61\x12\x0b\n\x07GPS_OFF\x10p\x12\n\n\x06GPS_ON\x10qBd\n\x14org.meshtastic.protoB\x0ePowerMonProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.powermon_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\016PowerMonProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_POWERMON']._serialized_start=60
_globals['_POWERMON']._serialized_end=284
_globals['_POWERMON_STATE']._serialized_start=73
_globals['_POWERMON_STATE']._serialized_end=284
_globals['_POWERSTRESSMESSAGE']._serialized_start=287
_globals['_POWERSTRESSMESSAGE']._serialized_end=679
_globals['_POWERSTRESSMESSAGE_OPCODE']._serialized_start=392
_globals['_POWERSTRESSMESSAGE_OPCODE']._serialized_end=679
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,221 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class PowerMon(google.protobuf.message.Message):
"""Note: There are no 'PowerMon' messages normally in use (PowerMons are sent only as structured logs - slogs).
But we wrap our State enum in this message to effectively nest a namespace (without our linter yelling at us)
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _State:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _StateEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[PowerMon._State.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
CPU_DeepSleep: PowerMon._State.ValueType # 1
CPU_LightSleep: PowerMon._State.ValueType # 2
Vext1_On: PowerMon._State.ValueType # 4
"""
The external Vext1 power is on. Many boards have auxillary power rails that the CPU turns on only
occasionally. In cases where that rail has multiple devices on it we usually want to have logging on
the state of that rail as an independent record.
For instance on the Heltec Tracker 1.1 board, this rail is the power source for the GPS and screen.
The log messages will be short and complete (see PowerMon.Event in the protobufs for details).
something like "S:PM:C,0x00001234,REASON" where the hex number is the bitmask of all current states.
(We use a bitmask for states so that if a log message gets lost it won't be fatal)
"""
Lora_RXOn: PowerMon._State.ValueType # 8
Lora_TXOn: PowerMon._State.ValueType # 16
Lora_RXActive: PowerMon._State.ValueType # 32
BT_On: PowerMon._State.ValueType # 64
LED_On: PowerMon._State.ValueType # 128
Screen_On: PowerMon._State.ValueType # 256
Screen_Drawing: PowerMon._State.ValueType # 512
Wifi_On: PowerMon._State.ValueType # 1024
GPS_Active: PowerMon._State.ValueType # 2048
"""
GPS is actively trying to find our location
See GPSPowerState for more details
"""
class State(_State, metaclass=_StateEnumTypeWrapper):
"""Any significant power changing event in meshtastic should be tagged with a powermon state transition.
If you are making new meshtastic features feel free to add new entries at the end of this definition.
"""
CPU_DeepSleep: PowerMon.State.ValueType # 1
CPU_LightSleep: PowerMon.State.ValueType # 2
Vext1_On: PowerMon.State.ValueType # 4
"""
The external Vext1 power is on. Many boards have auxillary power rails that the CPU turns on only
occasionally. In cases where that rail has multiple devices on it we usually want to have logging on
the state of that rail as an independent record.
For instance on the Heltec Tracker 1.1 board, this rail is the power source for the GPS and screen.
The log messages will be short and complete (see PowerMon.Event in the protobufs for details).
something like "S:PM:C,0x00001234,REASON" where the hex number is the bitmask of all current states.
(We use a bitmask for states so that if a log message gets lost it won't be fatal)
"""
Lora_RXOn: PowerMon.State.ValueType # 8
Lora_TXOn: PowerMon.State.ValueType # 16
Lora_RXActive: PowerMon.State.ValueType # 32
BT_On: PowerMon.State.ValueType # 64
LED_On: PowerMon.State.ValueType # 128
Screen_On: PowerMon.State.ValueType # 256
Screen_Drawing: PowerMon.State.ValueType # 512
Wifi_On: PowerMon.State.ValueType # 1024
GPS_Active: PowerMon.State.ValueType # 2048
"""
GPS is actively trying to find our location
See GPSPowerState for more details
"""
def __init__(
self,
) -> None: ...
global___PowerMon = PowerMon
@typing.final
class PowerStressMessage(google.protobuf.message.Message):
"""
PowerStress testing support via the C++ PowerStress module
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _Opcode:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _OpcodeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[PowerStressMessage._Opcode.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
UNSET: PowerStressMessage._Opcode.ValueType # 0
"""
Unset/unused
"""
PRINT_INFO: PowerStressMessage._Opcode.ValueType # 1
"""Print board version slog and send an ack that we are alive and ready to process commands"""
FORCE_QUIET: PowerStressMessage._Opcode.ValueType # 2
"""Try to turn off all automatic processing of packets, screen, sleeping, etc (to make it easier to measure in isolation)"""
END_QUIET: PowerStressMessage._Opcode.ValueType # 3
"""Stop powerstress processing - probably by just rebooting the board"""
SCREEN_ON: PowerStressMessage._Opcode.ValueType # 16
"""Turn the screen on"""
SCREEN_OFF: PowerStressMessage._Opcode.ValueType # 17
"""Turn the screen off"""
CPU_IDLE: PowerStressMessage._Opcode.ValueType # 32
"""Let the CPU run but we assume mostly idling for num_seconds"""
CPU_DEEPSLEEP: PowerStressMessage._Opcode.ValueType # 33
"""Force deep sleep for FIXME seconds"""
CPU_FULLON: PowerStressMessage._Opcode.ValueType # 34
"""Spin the CPU as fast as possible for num_seconds"""
LED_ON: PowerStressMessage._Opcode.ValueType # 48
"""Turn the LED on for num_seconds (and leave it on - for baseline power measurement purposes)"""
LED_OFF: PowerStressMessage._Opcode.ValueType # 49
"""Force the LED off for num_seconds"""
LORA_OFF: PowerStressMessage._Opcode.ValueType # 64
"""Completely turn off the LORA radio for num_seconds"""
LORA_TX: PowerStressMessage._Opcode.ValueType # 65
"""Send Lora packets for num_seconds"""
LORA_RX: PowerStressMessage._Opcode.ValueType # 66
"""Receive Lora packets for num_seconds (node will be mostly just listening, unless an external agent is helping stress this by sending packets on the current channel)"""
BT_OFF: PowerStressMessage._Opcode.ValueType # 80
"""Turn off the BT radio for num_seconds"""
BT_ON: PowerStressMessage._Opcode.ValueType # 81
"""Turn on the BT radio for num_seconds"""
WIFI_OFF: PowerStressMessage._Opcode.ValueType # 96
"""Turn off the WIFI radio for num_seconds"""
WIFI_ON: PowerStressMessage._Opcode.ValueType # 97
"""Turn on the WIFI radio for num_seconds"""
GPS_OFF: PowerStressMessage._Opcode.ValueType # 112
"""Turn off the GPS radio for num_seconds"""
GPS_ON: PowerStressMessage._Opcode.ValueType # 113
"""Turn on the GPS radio for num_seconds"""
class Opcode(_Opcode, metaclass=_OpcodeEnumTypeWrapper):
"""
What operation would we like the UUT to perform.
note: senders should probably set want_response in their request packets, so that they can know when the state
machine has started processing their request
"""
UNSET: PowerStressMessage.Opcode.ValueType # 0
"""
Unset/unused
"""
PRINT_INFO: PowerStressMessage.Opcode.ValueType # 1
"""Print board version slog and send an ack that we are alive and ready to process commands"""
FORCE_QUIET: PowerStressMessage.Opcode.ValueType # 2
"""Try to turn off all automatic processing of packets, screen, sleeping, etc (to make it easier to measure in isolation)"""
END_QUIET: PowerStressMessage.Opcode.ValueType # 3
"""Stop powerstress processing - probably by just rebooting the board"""
SCREEN_ON: PowerStressMessage.Opcode.ValueType # 16
"""Turn the screen on"""
SCREEN_OFF: PowerStressMessage.Opcode.ValueType # 17
"""Turn the screen off"""
CPU_IDLE: PowerStressMessage.Opcode.ValueType # 32
"""Let the CPU run but we assume mostly idling for num_seconds"""
CPU_DEEPSLEEP: PowerStressMessage.Opcode.ValueType # 33
"""Force deep sleep for FIXME seconds"""
CPU_FULLON: PowerStressMessage.Opcode.ValueType # 34
"""Spin the CPU as fast as possible for num_seconds"""
LED_ON: PowerStressMessage.Opcode.ValueType # 48
"""Turn the LED on for num_seconds (and leave it on - for baseline power measurement purposes)"""
LED_OFF: PowerStressMessage.Opcode.ValueType # 49
"""Force the LED off for num_seconds"""
LORA_OFF: PowerStressMessage.Opcode.ValueType # 64
"""Completely turn off the LORA radio for num_seconds"""
LORA_TX: PowerStressMessage.Opcode.ValueType # 65
"""Send Lora packets for num_seconds"""
LORA_RX: PowerStressMessage.Opcode.ValueType # 66
"""Receive Lora packets for num_seconds (node will be mostly just listening, unless an external agent is helping stress this by sending packets on the current channel)"""
BT_OFF: PowerStressMessage.Opcode.ValueType # 80
"""Turn off the BT radio for num_seconds"""
BT_ON: PowerStressMessage.Opcode.ValueType # 81
"""Turn on the BT radio for num_seconds"""
WIFI_OFF: PowerStressMessage.Opcode.ValueType # 96
"""Turn off the WIFI radio for num_seconds"""
WIFI_ON: PowerStressMessage.Opcode.ValueType # 97
"""Turn on the WIFI radio for num_seconds"""
GPS_OFF: PowerStressMessage.Opcode.ValueType # 112
"""Turn off the GPS radio for num_seconds"""
GPS_ON: PowerStressMessage.Opcode.ValueType # 113
"""Turn on the GPS radio for num_seconds"""
CMD_FIELD_NUMBER: builtins.int
NUM_SECONDS_FIELD_NUMBER: builtins.int
cmd: global___PowerStressMessage.Opcode.ValueType
"""
What type of HardwareMessage is this?
"""
num_seconds: builtins.float
def __init__(
self,
*,
cmd: global___PowerStressMessage.Opcode.ValueType = ...,
num_seconds: builtins.float = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["cmd", b"cmd", "num_seconds", b"num_seconds"]) -> None: ...
global___PowerStressMessage = PowerStressMessage

View File

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/remote_hardware.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n)meshtastic/protobuf/remote_hardware.proto\x12\x13meshtastic.protobuf\"\xdf\x01\n\x0fHardwareMessage\x12\x37\n\x04type\x18\x01 \x01(\x0e\x32).meshtastic.protobuf.HardwareMessage.Type\x12\x11\n\tgpio_mask\x18\x02 \x01(\x04\x12\x12\n\ngpio_value\x18\x03 \x01(\x04\"l\n\x04Type\x12\t\n\x05UNSET\x10\x00\x12\x0f\n\x0bWRITE_GPIOS\x10\x01\x12\x0f\n\x0bWATCH_GPIOS\x10\x02\x12\x11\n\rGPIOS_CHANGED\x10\x03\x12\x0e\n\nREAD_GPIOS\x10\x04\x12\x14\n\x10READ_GPIOS_REPLY\x10\x05\x42\x64\n\x14org.meshtastic.protoB\x0eRemoteHardwareZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.remote_hardware_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\016RemoteHardwareZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_HARDWAREMESSAGE']._serialized_start=67
_globals['_HARDWAREMESSAGE']._serialized_end=290
_globals['_HARDWAREMESSAGE_TYPE']._serialized_start=182
_globals['_HARDWAREMESSAGE_TYPE']._serialized_end=290
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,126 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class HardwareMessage(google.protobuf.message.Message):
"""
An example app to show off the module system. This message is used for
REMOTE_HARDWARE_APP PortNums.
Also provides easy remote access to any GPIO.
In the future other remote hardware operations can be added based on user interest
(i.e. serial output, spi/i2c input/output).
FIXME - currently this feature is turned on by default which is dangerous
because no security yet (beyond the channel mechanism).
It should be off by default and then protected based on some TBD mechanism
(a special channel once multichannel support is included?)
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _Type:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[HardwareMessage._Type.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
UNSET: HardwareMessage._Type.ValueType # 0
"""
Unset/unused
"""
WRITE_GPIOS: HardwareMessage._Type.ValueType # 1
"""
Set gpio gpios based on gpio_mask/gpio_value
"""
WATCH_GPIOS: HardwareMessage._Type.ValueType # 2
"""
We are now interested in watching the gpio_mask gpios.
If the selected gpios change, please broadcast GPIOS_CHANGED.
Will implicitly change the gpios requested to be INPUT gpios.
"""
GPIOS_CHANGED: HardwareMessage._Type.ValueType # 3
"""
The gpios listed in gpio_mask have changed, the new values are listed in gpio_value
"""
READ_GPIOS: HardwareMessage._Type.ValueType # 4
"""
Read the gpios specified in gpio_mask, send back a READ_GPIOS_REPLY reply with gpio_value populated
"""
READ_GPIOS_REPLY: HardwareMessage._Type.ValueType # 5
"""
A reply to READ_GPIOS. gpio_mask and gpio_value will be populated
"""
class Type(_Type, metaclass=_TypeEnumTypeWrapper):
"""
TODO: REPLACE
"""
UNSET: HardwareMessage.Type.ValueType # 0
"""
Unset/unused
"""
WRITE_GPIOS: HardwareMessage.Type.ValueType # 1
"""
Set gpio gpios based on gpio_mask/gpio_value
"""
WATCH_GPIOS: HardwareMessage.Type.ValueType # 2
"""
We are now interested in watching the gpio_mask gpios.
If the selected gpios change, please broadcast GPIOS_CHANGED.
Will implicitly change the gpios requested to be INPUT gpios.
"""
GPIOS_CHANGED: HardwareMessage.Type.ValueType # 3
"""
The gpios listed in gpio_mask have changed, the new values are listed in gpio_value
"""
READ_GPIOS: HardwareMessage.Type.ValueType # 4
"""
Read the gpios specified in gpio_mask, send back a READ_GPIOS_REPLY reply with gpio_value populated
"""
READ_GPIOS_REPLY: HardwareMessage.Type.ValueType # 5
"""
A reply to READ_GPIOS. gpio_mask and gpio_value will be populated
"""
TYPE_FIELD_NUMBER: builtins.int
GPIO_MASK_FIELD_NUMBER: builtins.int
GPIO_VALUE_FIELD_NUMBER: builtins.int
type: global___HardwareMessage.Type.ValueType
"""
What type of HardwareMessage is this?
"""
gpio_mask: builtins.int
"""
What gpios are we changing. Not used for all MessageTypes, see MessageType for details
"""
gpio_value: builtins.int
"""
For gpios that were listed in gpio_mask as valid, what are the signal levels for those gpios.
Not used for all MessageTypes, see MessageType for details
"""
def __init__(
self,
*,
type: global___HardwareMessage.Type.ValueType = ...,
gpio_mask: builtins.int = ...,
gpio_value: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["gpio_mask", b"gpio_mask", "gpio_value", b"gpio_value", "type", b"type"]) -> None: ...
global___HardwareMessage = HardwareMessage

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/rtttl.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/protobuf/rtttl.proto\x12\x13meshtastic.protobuf\"\x1f\n\x0bRTTTLConfig\x12\x10\n\x08ringtone\x18\x01 \x01(\tBg\n\x14org.meshtastic.protoB\x11RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.rtttl_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\021RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_RTTTLCONFIG']._serialized_start=56
_globals['_RTTTLCONFIG']._serialized_end=87
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,33 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.message
import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class RTTTLConfig(google.protobuf.message.Message):
"""
Canned message module configuration.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
RINGTONE_FIELD_NUMBER: builtins.int
ringtone: builtins.str
"""
Ringtone for PWM Buzzer in RTTTL Format.
"""
def __init__(
self,
*,
ringtone: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["ringtone", b"ringtone"]) -> None: ...
global___RTTTLConfig = RTTTLConfig

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/storeforward.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&meshtastic/protobuf/storeforward.proto\x12\x13meshtastic.protobuf\"\xc0\x07\n\x0fStoreAndForward\x12@\n\x02rr\x18\x01 \x01(\x0e\x32\x34.meshtastic.protobuf.StoreAndForward.RequestResponse\x12@\n\x05stats\x18\x02 \x01(\x0b\x32/.meshtastic.protobuf.StoreAndForward.StatisticsH\x00\x12?\n\x07history\x18\x03 \x01(\x0b\x32,.meshtastic.protobuf.StoreAndForward.HistoryH\x00\x12\x43\n\theartbeat\x18\x04 \x01(\x0b\x32..meshtastic.protobuf.StoreAndForward.HeartbeatH\x00\x12\x0e\n\x04text\x18\x05 \x01(\x0cH\x00\x1a\xcd\x01\n\nStatistics\x12\x16\n\x0emessages_total\x18\x01 \x01(\r\x12\x16\n\x0emessages_saved\x18\x02 \x01(\r\x12\x14\n\x0cmessages_max\x18\x03 \x01(\r\x12\x0f\n\x07up_time\x18\x04 \x01(\r\x12\x10\n\x08requests\x18\x05 \x01(\r\x12\x18\n\x10requests_history\x18\x06 \x01(\r\x12\x11\n\theartbeat\x18\x07 \x01(\x08\x12\x12\n\nreturn_max\x18\x08 \x01(\r\x12\x15\n\rreturn_window\x18\t \x01(\r\x1aI\n\x07History\x12\x18\n\x10history_messages\x18\x01 \x01(\r\x12\x0e\n\x06window\x18\x02 \x01(\r\x12\x14\n\x0clast_request\x18\x03 \x01(\r\x1a.\n\tHeartbeat\x12\x0e\n\x06period\x18\x01 \x01(\r\x12\x11\n\tsecondary\x18\x02 \x01(\r\"\xbc\x02\n\x0fRequestResponse\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0cROUTER_ERROR\x10\x01\x12\x14\n\x10ROUTER_HEARTBEAT\x10\x02\x12\x0f\n\x0bROUTER_PING\x10\x03\x12\x0f\n\x0bROUTER_PONG\x10\x04\x12\x0f\n\x0bROUTER_BUSY\x10\x05\x12\x12\n\x0eROUTER_HISTORY\x10\x06\x12\x10\n\x0cROUTER_STATS\x10\x07\x12\x16\n\x12ROUTER_TEXT_DIRECT\x10\x08\x12\x19\n\x15ROUTER_TEXT_BROADCAST\x10\t\x12\x10\n\x0c\x43LIENT_ERROR\x10@\x12\x12\n\x0e\x43LIENT_HISTORY\x10\x41\x12\x10\n\x0c\x43LIENT_STATS\x10\x42\x12\x0f\n\x0b\x43LIENT_PING\x10\x43\x12\x0f\n\x0b\x43LIENT_PONG\x10\x44\x12\x10\n\x0c\x43LIENT_ABORT\x10jB\t\n\x07variantBk\n\x14org.meshtastic.protoB\x15StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.storeforward_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\025StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_STOREANDFORWARD']._serialized_start=64
_globals['_STOREANDFORWARD']._serialized_end=1024
_globals['_STOREANDFORWARD_STATISTICS']._serialized_start=366
_globals['_STOREANDFORWARD_STATISTICS']._serialized_end=571
_globals['_STOREANDFORWARD_HISTORY']._serialized_start=573
_globals['_STOREANDFORWARD_HISTORY']._serialized_end=646
_globals['_STOREANDFORWARD_HEARTBEAT']._serialized_start=648
_globals['_STOREANDFORWARD_HEARTBEAT']._serialized_end=694
_globals['_STOREANDFORWARD_REQUESTRESPONSE']._serialized_start=697
_globals['_STOREANDFORWARD_REQUESTRESPONSE']._serialized_end=1013
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,345 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@typing.final
class StoreAndForward(google.protobuf.message.Message):
"""
TODO: REPLACE
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _RequestResponse:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _RequestResponseEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[StoreAndForward._RequestResponse.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
UNSET: StoreAndForward._RequestResponse.ValueType # 0
"""
Unset/unused
"""
ROUTER_ERROR: StoreAndForward._RequestResponse.ValueType # 1
"""
Router is an in error state.
"""
ROUTER_HEARTBEAT: StoreAndForward._RequestResponse.ValueType # 2
"""
Router heartbeat
"""
ROUTER_PING: StoreAndForward._RequestResponse.ValueType # 3
"""
Router has requested the client respond. This can work as a
"are you there" message.
"""
ROUTER_PONG: StoreAndForward._RequestResponse.ValueType # 4
"""
The response to a "Ping"
"""
ROUTER_BUSY: StoreAndForward._RequestResponse.ValueType # 5
"""
Router is currently busy. Please try again later.
"""
ROUTER_HISTORY: StoreAndForward._RequestResponse.ValueType # 6
"""
Router is responding to a request for history.
"""
ROUTER_STATS: StoreAndForward._RequestResponse.ValueType # 7
"""
Router is responding to a request for stats.
"""
ROUTER_TEXT_DIRECT: StoreAndForward._RequestResponse.ValueType # 8
"""
Router sends a text message from its history that was a direct message.
"""
ROUTER_TEXT_BROADCAST: StoreAndForward._RequestResponse.ValueType # 9
"""
Router sends a text message from its history that was a broadcast.
"""
CLIENT_ERROR: StoreAndForward._RequestResponse.ValueType # 64
"""
Client is an in error state.
"""
CLIENT_HISTORY: StoreAndForward._RequestResponse.ValueType # 65
"""
Client has requested a replay from the router.
"""
CLIENT_STATS: StoreAndForward._RequestResponse.ValueType # 66
"""
Client has requested stats from the router.
"""
CLIENT_PING: StoreAndForward._RequestResponse.ValueType # 67
"""
Client has requested the router respond. This can work as a
"are you there" message.
"""
CLIENT_PONG: StoreAndForward._RequestResponse.ValueType # 68
"""
The response to a "Ping"
"""
CLIENT_ABORT: StoreAndForward._RequestResponse.ValueType # 106
"""
Client has requested that the router abort processing the client's request
"""
class RequestResponse(_RequestResponse, metaclass=_RequestResponseEnumTypeWrapper):
"""
001 - 063 = From Router
064 - 127 = From Client
"""
UNSET: StoreAndForward.RequestResponse.ValueType # 0
"""
Unset/unused
"""
ROUTER_ERROR: StoreAndForward.RequestResponse.ValueType # 1
"""
Router is an in error state.
"""
ROUTER_HEARTBEAT: StoreAndForward.RequestResponse.ValueType # 2
"""
Router heartbeat
"""
ROUTER_PING: StoreAndForward.RequestResponse.ValueType # 3
"""
Router has requested the client respond. This can work as a
"are you there" message.
"""
ROUTER_PONG: StoreAndForward.RequestResponse.ValueType # 4
"""
The response to a "Ping"
"""
ROUTER_BUSY: StoreAndForward.RequestResponse.ValueType # 5
"""
Router is currently busy. Please try again later.
"""
ROUTER_HISTORY: StoreAndForward.RequestResponse.ValueType # 6
"""
Router is responding to a request for history.
"""
ROUTER_STATS: StoreAndForward.RequestResponse.ValueType # 7
"""
Router is responding to a request for stats.
"""
ROUTER_TEXT_DIRECT: StoreAndForward.RequestResponse.ValueType # 8
"""
Router sends a text message from its history that was a direct message.
"""
ROUTER_TEXT_BROADCAST: StoreAndForward.RequestResponse.ValueType # 9
"""
Router sends a text message from its history that was a broadcast.
"""
CLIENT_ERROR: StoreAndForward.RequestResponse.ValueType # 64
"""
Client is an in error state.
"""
CLIENT_HISTORY: StoreAndForward.RequestResponse.ValueType # 65
"""
Client has requested a replay from the router.
"""
CLIENT_STATS: StoreAndForward.RequestResponse.ValueType # 66
"""
Client has requested stats from the router.
"""
CLIENT_PING: StoreAndForward.RequestResponse.ValueType # 67
"""
Client has requested the router respond. This can work as a
"are you there" message.
"""
CLIENT_PONG: StoreAndForward.RequestResponse.ValueType # 68
"""
The response to a "Ping"
"""
CLIENT_ABORT: StoreAndForward.RequestResponse.ValueType # 106
"""
Client has requested that the router abort processing the client's request
"""
@typing.final
class Statistics(google.protobuf.message.Message):
"""
TODO: REPLACE
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MESSAGES_TOTAL_FIELD_NUMBER: builtins.int
MESSAGES_SAVED_FIELD_NUMBER: builtins.int
MESSAGES_MAX_FIELD_NUMBER: builtins.int
UP_TIME_FIELD_NUMBER: builtins.int
REQUESTS_FIELD_NUMBER: builtins.int
REQUESTS_HISTORY_FIELD_NUMBER: builtins.int
HEARTBEAT_FIELD_NUMBER: builtins.int
RETURN_MAX_FIELD_NUMBER: builtins.int
RETURN_WINDOW_FIELD_NUMBER: builtins.int
messages_total: builtins.int
"""
Number of messages we have ever seen
"""
messages_saved: builtins.int
"""
Number of messages we have currently saved our history.
"""
messages_max: builtins.int
"""
Maximum number of messages we will save
"""
up_time: builtins.int
"""
Router uptime in seconds
"""
requests: builtins.int
"""
Number of times any client sent a request to the S&F.
"""
requests_history: builtins.int
"""
Number of times the history was requested.
"""
heartbeat: builtins.bool
"""
Is the heartbeat enabled on the server?
"""
return_max: builtins.int
"""
Maximum number of messages the server will return.
"""
return_window: builtins.int
"""
Maximum history window in minutes the server will return messages from.
"""
def __init__(
self,
*,
messages_total: builtins.int = ...,
messages_saved: builtins.int = ...,
messages_max: builtins.int = ...,
up_time: builtins.int = ...,
requests: builtins.int = ...,
requests_history: builtins.int = ...,
heartbeat: builtins.bool = ...,
return_max: builtins.int = ...,
return_window: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["heartbeat", b"heartbeat", "messages_max", b"messages_max", "messages_saved", b"messages_saved", "messages_total", b"messages_total", "requests", b"requests", "requests_history", b"requests_history", "return_max", b"return_max", "return_window", b"return_window", "up_time", b"up_time"]) -> None: ...
@typing.final
class History(google.protobuf.message.Message):
"""
TODO: REPLACE
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
HISTORY_MESSAGES_FIELD_NUMBER: builtins.int
WINDOW_FIELD_NUMBER: builtins.int
LAST_REQUEST_FIELD_NUMBER: builtins.int
history_messages: builtins.int
"""
Number of that will be sent to the client
"""
window: builtins.int
"""
The window of messages that was used to filter the history client requested
"""
last_request: builtins.int
"""
Index in the packet history of the last message sent in a previous request to the server.
Will be sent to the client before sending the history and can be set in a subsequent request to avoid getting packets the server already sent to the client.
"""
def __init__(
self,
*,
history_messages: builtins.int = ...,
window: builtins.int = ...,
last_request: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["history_messages", b"history_messages", "last_request", b"last_request", "window", b"window"]) -> None: ...
@typing.final
class Heartbeat(google.protobuf.message.Message):
"""
TODO: REPLACE
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
PERIOD_FIELD_NUMBER: builtins.int
SECONDARY_FIELD_NUMBER: builtins.int
period: builtins.int
"""
Period in seconds that the heartbeat is sent out that will be sent to the client
"""
secondary: builtins.int
"""
If set, this is not the primary Store & Forward router on the mesh
"""
def __init__(
self,
*,
period: builtins.int = ...,
secondary: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["period", b"period", "secondary", b"secondary"]) -> None: ...
RR_FIELD_NUMBER: builtins.int
STATS_FIELD_NUMBER: builtins.int
HISTORY_FIELD_NUMBER: builtins.int
HEARTBEAT_FIELD_NUMBER: builtins.int
TEXT_FIELD_NUMBER: builtins.int
rr: global___StoreAndForward.RequestResponse.ValueType
"""
TODO: REPLACE
"""
text: builtins.bytes
"""
Text from history message.
"""
@property
def stats(self) -> global___StoreAndForward.Statistics:
"""
TODO: REPLACE
"""
@property
def history(self) -> global___StoreAndForward.History:
"""
TODO: REPLACE
"""
@property
def heartbeat(self) -> global___StoreAndForward.Heartbeat:
"""
TODO: REPLACE
"""
def __init__(
self,
*,
rr: global___StoreAndForward.RequestResponse.ValueType = ...,
stats: global___StoreAndForward.Statistics | None = ...,
history: global___StoreAndForward.History | None = ...,
heartbeat: global___StoreAndForward.Heartbeat | None = ...,
text: builtins.bytes = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["heartbeat", b"heartbeat", "history", b"history", "stats", b"stats", "text", b"text", "variant", b"variant"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["heartbeat", b"heartbeat", "history", b"history", "rr", b"rr", "stats", b"stats", "text", b"text", "variant", b"variant"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["variant", b"variant"]) -> typing.Literal["stats", "history", "heartbeat", "text"] | None: ...
global___StoreAndForward = StoreAndForward

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