7 Commits
79 changed files with 3705 additions and 6007 deletions

No files matched your search

+27 -7
View File
@@ -6,7 +6,6 @@ The project serves as a real-time monitoring and diagnostic tool for the Meshtas
### Version 3.0.9 — October 2026
- Protobufs: refreshed Meshtastic schemas and Python type stubs to upstream commit `569a2b3ae7b6bda1a7ab177463a55d8ede3bef53`; updated the refresh script to handle custom metadata options.
- Live map: added animated packet traces from senders to reporting gateways and configurable channel colors through the optional `[map_channel_colors]` section in `config.ini`.
- Daily snapshots: new snapshots report activity for the previous complete UTC day, including newly imported packets, unique packet senders observed that day, and gateways that reported packets that day. Existing historical snapshots keep their original counts.
- Node tracking: record nodes from packet activity before their node information arrives, and preserve known positions when map reports have missing or invalid coordinates.
@@ -16,6 +15,29 @@ The project serves as a real-time monitoring and diagnostic tool for the Meshtas
- Coverage API: validate and bound request parameters, and run coverage calculations off the event loop to keep the web server responsive.
- Contributors: thanks to [nullrouten0](https://github.com/nullrouten0) and Nathan for the neighbor SNR chart, MQTT reliability, security, privacy, and coverage API fixes; Manuel Villaverde for improving map channel color visibility; and [Pablo Revilla](https://github.com/pablorevilla-meshtastic) for the live map, node tracking, and daily snapshot updates.
#### Updating your configuration for 3.0.9
Add the following section at the end of your existing `config.ini` to use these map channel colors.
If `[map_channel_colors]` already exists, update that section instead of adding a duplicate.
```ini
# Map channel color overrides. Use six-digit hex colors; other channels get generated colors.
# Names ignore case, spaces, hyphens, and underscores. Restart the web server after editing.
[map_channel_colors]
LongFast = #4363d8
LongSlow = #000075
VeryLongSlow = #808000
MediumSlow = #008080
MediumFast = #e6194b
ShortSlow = #911eb4
ShortFast = #f58231
LongModerate = #46f0f0
ShortTurbo = #f032e6
```
Restart the web server and reload the map after saving. This section is optional;
channels without an override use generated colors.
### Version 3.0.8 — September 2026
- Map updates: added OpenTopoMap as a selectable base map, improved map controls, and fixed several map/node display edge cases.
- Traceroute: added a dedicated traceroute page, corrected route path orientation in graph edges, and improved traceroute API/documentation support.
@@ -34,10 +56,7 @@ The project serves as a real-time monitoring and diagnostic tool for the Meshtas
- Tooling: improved the protobuf updater so it supports raw commit SHAs, the newer upstream `meshtastic/*.proto` layout, generated `.pyi` stubs, and the vendored `nanopb`/`serial_hal` outputs.
### Version 3.0.6 — March 2026
- Daily snapshots: added the `daily_snapshot` table, scheduled snapshot capture, and `/api/snapshots/daily` for historical node, packet, and gateway counts.
Each new snapshot stores packets imported during the previous complete UTC day,
labeled with that day's date. Node and gateway counts are database totals at capture
time. Existing historical snapshots retain their previously stored packet totals.
- Daily snapshots: added the `daily_snapshot` table, scheduled snapshot capture, and `/api/snapshots/daily` for historical node, packet, and gateway counts. These originally stored database totals; version 3.0.9 changes new snapshots to daily activity counts.
- Stats/UI: expanded stats views with snapshot data and added channel filters to Chat and Firehose.
- Map/node fixes: corrected node location handling, map popup behavior, packet page display, and node list sorting.
- Ingestion/API reliability: improved duplicate `PacketSeen` handling, guarded invalid node info packets, and made traceroute/edge APIs more tolerant of decode failures.
@@ -298,6 +317,9 @@ 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
@@ -307,8 +329,6 @@ stats = True
net = True
map = True
top = True
# Show the API documentation link in the navigation bar (default: True).
api = True
# Map boundaries (used for the map view).
# Defaults will show the San Francisco Bay Area
+14 -271
View File
@@ -2,43 +2,8 @@
Base URL: `http(s)://<host>`
This reference covers all 16 GET routes registered in `meshview/web_api/api.py`,
including `/health` and `/version`. The browser version is served at `/api.html`.
Responses below are illustrative examples; actual values depend on stored data.
Regenerate the browser reference after editing this file with
`node scripts/build-api-docs.mjs`.
## Conventions
- Successful API responses are JSON. Explicit validation errors usually return JSON
with an `error` field. Some unhandled errors return HTTP 500 with a plain-text
body; check HTTP status and Content-Type before parsing an error response.
- All routes are read-only. The application does not require an API token; a reverse
proxy may impose authentication. There are no application-level write endpoints.
- `*_us` timestamps and `since` use microseconds since the Unix epoch. Snapshot dates
and statistics buckets use UTC. Node latitude/longitude integers must be divided
by 10,000,000 to obtain degrees; coverage coordinates are already degrees.
- Packet `id` and `storage_id` are database row IDs. Use these for the `packet_id`
query/path parameters on packet, observation, count, and traceroute endpoints.
A response field named `packet_id` on a packet object is instead its over-the-air
Meshtastic ID. `reply_id`, when present, is also an over-the-air ID. These ID types
are not interchangeable. Node IDs are numeric Meshtastic node numbers; the node
object's `id` is a separate string identifier.
- Use decimal node IDs throughout. The packet sender/recipient filters and the QR
and coverage paths also accept Python-style `0x` hexadecimal numbers. This is
not supported consistently by the other routes.
- Public broadcast text is readable. Direct text messages on port 1 are returned as
`<redacted>`. Request chat with `/api/packets?portnum=1`; there is no `/api/chat`
route. Do not treat a decoded `payload` string as trusted HTML.
## Quick examples
```sh
curl 'http://localhost:8081/api/nodes?days_active=3'
curl 'http://localhost:8081/api/packets?portnum=1&limit=100'
curl 'http://localhost:8081/api/stats/count'
curl 'http://localhost:8081/api/coverage/1234?mode=perimeter&radius_km=20'
```
All endpoints return JSON. Timestamps are either ISO 8601 strings or `*_us` values in
microseconds since epoch.
## 1. Nodes API
@@ -50,21 +15,14 @@ Query Parameters
- `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. Omit for all
nodes with a non-null last-seen timestamp; invalid integers are ignored.
Nodes are sorted by `short_name` ascending. `role` is normalized to uppercase;
channel and hardware filters are exact matches. No pagination is implemented.
Errors: HTTP 500 with `{"error":"Failed to fetch nodes"}` for handler failures;
the storage helper may return an empty list for database failures.
- `days_active` (optional, int): Nodes seen within the last N days.
Response Example
```json
{
"nodes": [
{
"id": "!000004d2",
"id": 42,
"node_id": 1234,
"long_name": "Alice",
"short_name": "A",
@@ -74,8 +32,6 @@ Response Example
"last_lat": 377749000,
"last_long": -1224194000,
"channel": "main",
"is_mqtt_gateway": true,
"first_seen_us": 1736283723456789,
"last_seen_us": 1736370123456789
}
]
@@ -90,7 +46,7 @@ Response Example
Returns packets with optional filters.
Query Parameters
- `packet_id` (optional, decimal int): Return one packet by database row ID (overrides other filters).
- `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.
@@ -105,16 +61,14 @@ Response Example
"packets": [
{
"id": 123,
"storage_id": 123,
"packet_id": 3314808102,
"import_time_us": 1736370123456789,
"channel": "main",
"from_node_id": 5678,
"to_node_id": 4294967295,
"to_node_id": 91011,
"portnum": 1,
"long_name": "Alice",
"payload": "Hello, mesh!",
"to_long_name": null,
"payload": "Hello, Bob!",
"to_long_name": "Bob",
"reply_id": 122
}
],
@@ -124,21 +78,7 @@ Response Example
Notes
- For `portnum=1` (text messages), packets are filtered to remove sequence-only payloads.
- Results are newest first. `since` is strictly greater than the supplied timestamp.
Store `latest_import_time` for the next poll and deduplicate by `id`. A bounded
result can omit older records if more packets arrive than the requested limit;
this endpoint is not a durable cursor or backfill API.
- `latest_import_time` is returned only when the list response has a positive import
timestamp; it is absent for empty results and single-packet lookups.
- `packet_id` lookup returns `{"packets":[]}` with HTTP 200 when missing. Its objects
omit `to_long_name` and `reply_id`; nullable `portnum` is possible in this mode.
- `contains` is case-insensitive. With `portnum=1`, matching is performed on decoded
displayed payload text (including redaction placeholders) after the database limit is applied, so fewer than `limit` results
may be returned. For other requests, it searches stored payload bytes cast to text;
this is not a general search over decoded protobuf fields.
- Invalid `limit` falls back to 50. Invalid `since`, `portnum`, and node filters are
logged and ignored. Invalid single-packet IDs return HTTP 400; handler failures
return HTTP 500 with `{"error":"Failed to fetch packets"}`.
- `latest_import_time` is returned when available for incremental polling (microseconds).
---
@@ -160,10 +100,6 @@ Response Example
---
Errors: storage/period failures return HTTP 200 with `channels: []` and an `error`
field. Non-integer `length` is parsed outside that handler and can return HTTP 500.
Use a positive integer length and the literal `hour` or `day`.
## 4. Stats API
### GET `/api/stats`
@@ -200,26 +136,13 @@ Response Example (`node` totals)
"node_id": 12345678,
"period_type": "hour",
"length": 24,
"sent": 0,
"seen": 0
"sent": 42,
"seen": 58
}
```
---
The series response contains only buckets with records, ordered oldest first;
missing hours/days are not filled with zeroes. Periods are UTC strings.
Current `node`-mode limitation: the handler reads a `total` key that the statistics
helper does not provide, so `sent` and `seen` currently return zero. It also uses
recipient filtering for the second query, rather than gateway observations. This
mode ignores the other filters. For usable sent/observation totals, request
`/api/stats/count?from_node=1234&period_type=day&length=1` instead.
Errors: HTTP 400 for an unsupported `period_type`, non-integer `length`, `node`,
`portnum`, `from_node`, or `to_node`. Storage failures can return HTTP 500.
Use a positive `length`; the handler does not impose a positive lower bound.
### GET `/api/stats/count`
Returns total packet counts, optionally filtered.
@@ -241,18 +164,6 @@ Response Example
---
Without filters, counts cover the whole retained database. With time, channel,
or direction filters, omitted time settings default to `period_type=day&length=1`.
`total_seen` counts observation rows for packets matching the packet import-time
window, not distinct gateways. Channel matching is case-insensitive.
`packet_id` applies only to `total_seen` and overrides its other filters: it counts
all observations of that database packet ID. It does not narrow `total_packets`.
In particular, `packet_id` alone leaves `total_packets` as the global packet total.
Errors: HTTP 400 for non-integer ID/length filters. Unsupported `period_type` or
storage failures can return HTTP 500; use `hour` or `day` and a positive length.
### GET `/api/stats/top`
Returns nodes sorted by packets seen, with pagination.
@@ -285,16 +196,6 @@ Response Example
---
`sent` counts packet records from each node; `seen` counts observation records for
that sender's packets. `avg` is `round(seen / max(sent, 1), 2)`, not a distinct-gateway
count. Windows are anchored to the newest packet and newest observation in the
respective tables, not wall-clock time. Nodes with zero activity are included;
`total` counts nodes matching the channel filter, not just active nodes.
Channel matching is exact. Use positive `length` and `limit`, and a nonnegative
`offset`. Only the upper limit of 100 is enforced. Invalid numeric strings can
return HTTP 500; any `period_type` other than the literal `hour` is treated as days.
## 5. Edges API
### GET `/api/edges`
@@ -324,12 +225,7 @@ Response Example
---
Unknown `type` values return an empty edge list. Invalid `node_id` returns HTTP 400;
storage failures can return HTTP 500. A missing node is not an error and normally
returns an empty list. Neighbor edges come from the latest stored port-71 sample
(the storage helper defaults to 50 packets), not the traceroute 12-hour window.
## 6. Daily Snapshots and Configuration
## 6. Config API
### GET `/api/snapshots/daily`
@@ -345,22 +241,6 @@ import timestamps, not device timestamps. Older snapshots retain their originall
counts and are not automatically converted. Counts depend on the packet and observation
history still retained at capture time.
Query Parameters
- `length` (optional, int): Return the latest N snapshot records, clamped to 1-3650.
Omit for all stored snapshots. Results are always ordered by date ascending.
This is a record limit, not a guarantee of consecutive calendar dates.
Response Example
```json
{"data":[{"date":"2026-10-24","node_count":143,"packet_count":28465,"gateway_count":17,"captured_at_us":1792886400000000}]}
```
No stored snapshots returns `{"data":[]}`. Invalid `length` returns HTTP 400;
storage failures return HTTP 500. `captured_at_us` is the capture time, which may
be later than the day summarized by `date`.
### GET `/api/config`
Returns a safe subset of server configuration.
@@ -375,17 +255,6 @@ LongFast = #4363d8
LocalChat = #18aa18
```
No query parameters are supported. Only the `site`, MQTT server/topics, and cleanup
fields shown here are exposed; credentials and the database connection string are
not returned. Feature flags and cleanup booleans are lowercase strings (`"true"` /
`"false"`), not JSON booleans. Cleanup scheduling values are strings; map bounds are
numbers and refresh intervals are integers. The removed `starting` option is not
returned: `/` always serves the dashboard. `site.api` controls visibility of the API
documentation link in the navigation bar, defaults to `"true"`, and can be disabled
with `api = False` in `[site]`. This setting does not disable documentation or API
routes. Restart the web server and reload the page after changing it. Handler
failures return HTTP 500.
Restart the web server and reload the map after changing these settings. Omitting
the section uses generated colors for every channel.
@@ -397,6 +266,7 @@ Response Example
"language": "en",
"title": "Meshview",
"message": "",
"starting": "/chat",
"nodes": "true",
"chat": "true",
"everything": "true",
@@ -405,13 +275,11 @@ Response Example
"net": "true",
"map": "true",
"top": "true",
"api": "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,
"map_channel_colors": {"LongFast":"#4363d8"},
"firehose_interval": 3,
"weekly_net_message": "Weekly Mesh check-in message.",
"net_tag": "#BayMeshNet",
@@ -452,10 +320,6 @@ Response Example
---
Unknown or invalid language codes fall back to the English file. An unknown section
returns HTTP 404. The response has no wrapper: it is either the full translation
object or the requested section. Translation-file failures can return HTTP 500.
## 8. Packets Seen API
### GET `/api/packets_seen/{packet_id}`
@@ -471,7 +335,7 @@ Response Example
{
"packet_id": 123,
"node_id": 456,
"rx_time": 1753188300,
"rx_time": "2025-07-22T12:45:00",
"hop_limit": 7,
"hop_start": 0,
"channel": "main",
@@ -486,16 +350,6 @@ Response Example
---
`node_id` identifies the observing MQTT gateway. `rx_time` is the device-provided
receive time in Unix seconds, while `import_time_us` is local import time
in microseconds. Signal fields can be null. Multiple rows can describe the same
gateway; consumers wanting unique gateways must deduplicate them. Hop count is
usually `max(0, hop_start - hop_limit)` when both values are known. Observations
do not by themselves prove a direct radio link from the sender to that gateway.
No observations, including for an unknown packet, returns `{"seen":[]}` with HTTP
200. Invalid path IDs return HTTP 400; handler failures return HTTP 500.
## 9. Traceroute API
### GET `/api/traceroute/{packet_id}`
@@ -555,10 +409,6 @@ Response Example
---
`traceroute_packets` can be empty even when the packet exists. Unknown database
packet IDs return HTTP 404. Invalid integer IDs and storage failures can return
HTTP 500; this handler does not implement a separate HTTP 400 validation branch.
## 10. Health API
### GET `/health`
@@ -622,15 +472,6 @@ Response Example
---
No query parameters. HTTP 200 reports `status: "healthy"` with database connectivity.
A database failure returns HTTP 503 with `status: "unhealthy"` and
`database: "disconnected"`. `seconds_since_last_message` is included only when a
latest imported packet exists; SQLite size fields appear only when available.
Cleanup and backup reports include configured schedules and status-file contents
when present. Their status may be `disabled`, `unknown`, `error`, or the last job's
recorded status; a failed backup/cleanup does not itself change the top-level HTTP
status. The optional `last_run` objects depend on the job's stored report.
## 11. Version API
### GET `/version`
@@ -645,101 +486,3 @@ Response Example
"git_revision_short": "abc1234"
}
```
No query parameters. HTTP 500 with an `error` field if version metadata cannot be
retrieved. A revision may be `unknown` if Git metadata is unavailable.
## 12. Node Contact URL
### GET `/api/node/{node_id}/qr`
Returns a Meshtastic shared-contact URL as JSON, not a PNG or SVG image. The client
can encode `meshtastic_url` in a QR code. No query parameters are supported.
Path Parameters
- `node_id` (required, int): Node number in decimal or `0x` hexadecimal form.
Response Example
```json
{
"node_id":1234,
"long_name":"Alice",
"short_name":"A",
"role":"CLIENT",
"meshtastic_url":"https://meshtastic.org/v/#BASE64URL_CONTACT"
}
```
The example contact payload is a placeholder, not an importable contact. The URL
encodes node identity and available user metadata as a base64url SharedContact
protobuf, with `manually_verified` false. Metadata can be null.
Errors: HTTP 400 for invalid IDs; HTTP 404 when the node is absent; HTTP 500 for
contact serialization failures or unhandled storage errors.
## 13. Predicted Radio Coverage
### GET `/api/coverage/{node_id}`
Computes an ITM area-model prediction centered on the node's last stored position.
This is a model prediction, not a measured coverage boundary or terrain profile.
The optional `pyitm` dependency is required. Calculations run off the event loop
and reuse cached model results. All parameters are optional except the node ID.
Path Parameters
- `node_id` (required, int): Node number in decimal or `0x` hexadecimal form.
Query Parameters
- `mode` (string, default `perimeter`): `perimeter` or `heatmap`. Currently every
value other than the exact string `perimeter` selects the heatmap branch.
- `freq_mhz` (number, default `907`): Frequency in MHz; range 1-10000.
- `tx_dbm` (number, default `20`): Transmit power in dBm; range -50 to 60.
- `tx_height_m` (number, default `5`): Transmit antenna height in meters; range 0-1000.
- `rx_height_m` (number, default `1.5`): Receive antenna height in meters; range 0-1000.
- `radius_km` (number, default `40`): Maximum distance in kilometers; range 1-200.
- `step_km` (number, default `0.25`): Radial sample spacing in kilometers; range 0.05-50.
- `reliability` (number, default `0.5`): ITM time fraction; range 0.01-0.99.
- `threshold_dbm` (number, default `-120`): Perimeter received-power threshold in dBm;
range -200 to 0. Ignored by heatmap computation, although still validated.
Numeric bounds are inclusive, values must be finite, and `radius_km / step_km`
must not exceed 4000. Smaller steps increase computation cost.
Response Example (`mode=perimeter`)
```json
{
"mode":"perimeter",
"threshold_dbm":-120.0,
"perimeter":[[30.21,-93.20],[30.209,-93.198]]
}
```
`perimeter` contains `[latitude, longitude]` degree pairs for the furthest qualifying
sample on each modeled bearing. Bearings with no qualifying sample are omitted;
the list is not necessarily a closed GeoJSON polygon.
Response Example (`mode=heatmap`)
```json
{
"mode":"heatmap",
"min_dbm":-130.0,
"max_dbm":-80.0,
"points":[[30.21,-93.20,-110.5]]
}
```
`points` contains `[latitude, longitude, received_power_dbm]` triples. Min/max values
provide a color-scale range, extended from the defaults to include computed values.
An empty perimeter or point list is a valid result when no samples qualify.
Errors: HTTP 400 for invalid IDs, nonnumeric/nonfinite/out-of-range parameters, or
an excessive radius/step ratio; HTTP 404 for an unknown node or missing/zero-valued
stored coordinates; HTTP 503 when `pyitm` is unavailable. Dependency availability is checked
before numeric query validation and node lookup. Unexpected model/storage failures
can return HTTP 500.
+1 -1
View File
@@ -1 +1 @@
569a2b3ae7b6bda1a7ab177463a55d8ede3bef53
9ab4a1d08cb833d897aee2367013318718391f2f
+29 -35
View File
@@ -19,7 +19,7 @@ from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb
from meshtastic.protobuf import module_config_pb2 as meshtastic_dot_protobuf_dot_module__config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/protobuf/admin.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a+meshtastic/protobuf/connection_status.proto\x1a#meshtastic/protobuf/device_ui.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a\'meshtastic/protobuf/module_config.proto\"\xb5\x1d\n\x0c\x41\x64minMessage\x12\x17\n\x0fsession_passkey\x18\x65 \x01(\x0c\x12\x1d\n\x13get_channel_request\x18\x01 \x01(\rH\x00\x12<\n\x14get_channel_response\x18\x02 \x01(\x0b\x32\x1c.meshtastic.protobuf.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x03 \x01(\x08H\x00\x12\x37\n\x12get_owner_response\x18\x04 \x01(\x0b\x32\x19.meshtastic.protobuf.UserH\x00\x12J\n\x12get_config_request\x18\x05 \x01(\x0e\x32,.meshtastic.protobuf.AdminMessage.ConfigTypeH\x00\x12:\n\x13get_config_response\x18\x06 \x01(\x0b\x32\x1b.meshtastic.protobuf.ConfigH\x00\x12W\n\x19get_module_config_request\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.AdminMessage.ModuleConfigTypeH\x00\x12G\n\x1aget_module_config_response\x18\x08 \x01(\x0b\x32!.meshtastic.protobuf.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\x12K\n\x1cget_device_metadata_response\x18\r \x01(\x0b\x32#.meshtastic.protobuf.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\x12\\\n%get_device_connection_status_response\x18\x11 \x01(\x0b\x32+.meshtastic.protobuf.DeviceConnectionStatusH\x00\x12:\n\x0cset_ham_mode\x18\x12 \x01(\x0b\x32\".meshtastic.protobuf.HamParametersH\x00\x12/\n%get_node_remote_hardware_pins_request\x18\x13 \x01(\x08H\x00\x12\x65\n&get_node_remote_hardware_pins_response\x18\x14 \x01(\x0b\x32\x33.meshtastic.protobuf.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\x13\n\tset_scale\x18\x17 \x01(\rH\x00\x12N\n\x12\x62\x61\x63kup_preferences\x18\x18 \x01(\x0e\x32\x30.meshtastic.protobuf.AdminMessage.BackupLocationH\x00\x12O\n\x13restore_preferences\x18\x19 \x01(\x0e\x32\x30.meshtastic.protobuf.AdminMessage.BackupLocationH\x00\x12U\n\x19remove_backup_preferences\x18\x1a \x01(\x0e\x32\x30.meshtastic.protobuf.AdminMessage.BackupLocationH\x00\x12H\n\x10send_input_event\x18\x1b \x01(\x0b\x32,.meshtastic.protobuf.AdminMessage.InputEventH\x00\x12.\n\tset_owner\x18 \x01(\x0b\x32\x19.meshtastic.protobuf.UserH\x00\x12\x33\n\x0bset_channel\x18! \x01(\x0b\x32\x1c.meshtastic.protobuf.ChannelH\x00\x12\x31\n\nset_config\x18\" \x01(\x0b\x32\x1b.meshtastic.protobuf.ConfigH\x00\x12>\n\x11set_module_config\x18# \x01(\x0b\x32!.meshtastic.protobuf.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;\n\x12set_fixed_position\x18) \x01(\x0b\x32\x1d.meshtastic.protobuf.PositionH\x00\x12\x1f\n\x15remove_fixed_position\x18* \x01(\x08H\x00\x12\x17\n\rset_time_only\x18+ \x01(\x07H\x00\x12\x1f\n\x15get_ui_config_request\x18, \x01(\x08H\x00\x12\x45\n\x16get_ui_config_response\x18- \x01(\x0b\x32#.meshtastic.protobuf.DeviceUIConfigH\x00\x12>\n\x0fstore_ui_config\x18. \x01(\x0b\x32#.meshtastic.protobuf.DeviceUIConfigH\x00\x12\x1a\n\x10set_ignored_node\x18/ \x01(\rH\x00\x12\x1d\n\x13remove_ignored_node\x18\x30 \x01(\rH\x00\x12\x1b\n\x11toggle_muted_node\x18\x31 \x01(\rH\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\x39\n\x0b\x61\x64\x64_contact\x18\x42 \x01(\x0b\x32\".meshtastic.protobuf.SharedContactH\x00\x12\x45\n\x10key_verification\x18\x43 \x01(\x0b\x32).meshtastic.protobuf.KeyVerificationAdminH\x00\x12\x1e\n\x14\x66\x61\x63tory_reset_device\x18^ \x01(\x05H\x00\x12 \n\x12reboot_ota_seconds\x18_ \x01(\x05\x42\x02\x18\x01H\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\x1e\n\x14\x66\x61\x63tory_reset_config\x18\x63 \x01(\x05H\x00\x12\x16\n\x0cnodedb_reset\x18\x64 \x01(\x08H\x00\x12\x41\n\x0bota_request\x18\x66 \x01(\x0b\x32*.meshtastic.protobuf.AdminMessage.OTAEventH\x00\x12:\n\rsensor_config\x18g \x01(\x0b\x32!.meshtastic.protobuf.SensorConfigH\x00\x12:\n\rlockdown_auth\x18h \x01(\x0b\x32!.meshtastic.protobuf.LockdownAuthH\x00\x1aS\n\nInputEvent\x12\x12\n\nevent_code\x18\x01 \x01(\r\x12\x0f\n\x07kb_char\x18\x02 \x01(\r\x12\x0f\n\x07touch_x\x18\x03 \x01(\r\x12\x0f\n\x07touch_y\x18\x04 \x01(\r\x1aS\n\x08OTAEvent\x12\x35\n\x0freboot_ota_mode\x18\x01 \x01(\x0e\x32\xLine truncated
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/protobuf/admin.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a+meshtastic/protobuf/connection_status.proto\x1a#meshtastic/protobuf/device_ui.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a\'meshtastic/protobuf/module_config.proto\"\x9e\x1d\n\x0c\x41\x64minMessage\x12\x17\n\x0fsession_passkey\x18\x65 \x01(\x0c\x12\x1d\n\x13get_channel_request\x18\x01 \x01(\rH\x00\x12<\n\x14get_channel_response\x18\x02 \x01(\x0b\x32\x1c.meshtastic.protobuf.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x03 \x01(\x08H\x00\x12\x37\n\x12get_owner_response\x18\x04 \x01(\x0b\x32\x19.meshtastic.protobuf.UserH\x00\x12J\n\x12get_config_request\x18\x05 \x01(\x0e\x32,.meshtastic.protobuf.AdminMessage.ConfigTypeH\x00\x12:\n\x13get_config_response\x18\x06 \x01(\x0b\x32\x1b.meshtastic.protobuf.ConfigH\x00\x12W\n\x19get_module_config_request\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.AdminMessage.ModuleConfigTypeH\x00\x12G\n\x1aget_module_config_response\x18\x08 \x01(\x0b\x32!.meshtastic.protobuf.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\x12K\n\x1cget_device_metadata_response\x18\r \x01(\x0b\x32#.meshtastic.protobuf.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\x12\\\n%get_device_connection_status_response\x18\x11 \x01(\x0b\x32+.meshtastic.protobuf.DeviceConnectionStatusH\x00\x12:\n\x0cset_ham_mode\x18\x12 \x01(\x0b\x32\".meshtastic.protobuf.HamParametersH\x00\x12/\n%get_node_remote_hardware_pins_request\x18\x13 \x01(\x08H\x00\x12\x65\n&get_node_remote_hardware_pins_response\x18\x14 \x01(\x0b\x32\x33.meshtastic.protobuf.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\x13\n\tset_scale\x18\x17 \x01(\rH\x00\x12N\n\x12\x62\x61\x63kup_preferences\x18\x18 \x01(\x0e\x32\x30.meshtastic.protobuf.AdminMessage.BackupLocationH\x00\x12O\n\x13restore_preferences\x18\x19 \x01(\x0e\x32\x30.meshtastic.protobuf.AdminMessage.BackupLocationH\x00\x12U\n\x19remove_backup_preferences\x18\x1a \x01(\x0e\x32\x30.meshtastic.protobuf.AdminMessage.BackupLocationH\x00\x12H\n\x10send_input_event\x18\x1b \x01(\x0b\x32,.meshtastic.protobuf.AdminMessage.InputEventH\x00\x12.\n\tset_owner\x18 \x01(\x0b\x32\x19.meshtastic.protobuf.UserH\x00\x12\x33\n\x0bset_channel\x18! \x01(\x0b\x32\x1c.meshtastic.protobuf.ChannelH\x00\x12\x31\n\nset_config\x18\" \x01(\x0b\x32\x1b.meshtastic.protobuf.ConfigH\x00\x12>\n\x11set_module_config\x18# \x01(\x0b\x32!.meshtastic.protobuf.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;\n\x12set_fixed_position\x18) \x01(\x0b\x32\x1d.meshtastic.protobuf.PositionH\x00\x12\x1f\n\x15remove_fixed_position\x18* \x01(\x08H\x00\x12\x17\n\rset_time_only\x18+ \x01(\x07H\x00\x12\x1f\n\x15get_ui_config_request\x18, \x01(\x08H\x00\x12\x45\n\x16get_ui_config_response\x18- \x01(\x0b\x32#.meshtastic.protobuf.DeviceUIConfigH\x00\x12>\n\x0fstore_ui_config\x18. \x01(\x0b\x32#.meshtastic.protobuf.DeviceUIConfigH\x00\x12\x1a\n\x10set_ignored_node\x18/ \x01(\rH\x00\x12\x1d\n\x13remove_ignored_node\x18\x30 \x01(\rH\x00\x12\x1b\n\x11toggle_muted_node\x18\x31 \x01(\rH\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\x39\n\x0b\x61\x64\x64_contact\x18\x42 \x01(\x0b\x32\".meshtastic.protobuf.SharedContactH\x00\x12\x45\n\x10key_verification\x18\x43 \x01(\x0b\x32).meshtastic.protobuf.KeyVerificationAdminH\x00\x12\x1e\n\x14\x66\x61\x63tory_reset_device\x18^ \x01(\x05H\x00\x12 \n\x12reboot_ota_seconds\x18_ \x01(\x05\x42\x02\x18\x01H\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\x1e\n\x14\x66\x61\x63tory_reset_config\x18\x63 \x01(\x05H\x00\x12\x16\n\x0cnodedb_reset\x18\x64 \x01(\x08H\x00\x12\x41\n\x0bota_request\x18\x66 \x01(\x0b\x32*.meshtastic.protobuf.AdminMessage.OTAEventH\x00\x12:\n\rsensor_config\x18g \x01(\x0b\x32!.meshtastic.protobuf.SensorConfigH\x00\x12:\n\rlockdown_auth\x18h \x01(\x0b\x32!.meshtastic.protobuf.LockdownAuthH\x00\x1aS\n\nInputEvent\x12\x12\n\nevent_code\x18\x01 \x01(\r\x12\x0f\n\x07kb_char\x18\x02 \x01(\r\x12\x0f\n\x07touch_x\x18\x03 \x01(\r\x12\x0f\n\x07touch_y\x18\x04 \x01(\r\x1aS\n\x08OTAEvent\x12\x35\n\x0freboot_ota_mode\x18\x01 \x01(\x0e\x32\xLine truncated
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.admin_pb2', globals())
@@ -29,10 +29,10 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\013AdminProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_ADMINMESSAGE.fields_by_name['reboot_ota_seconds']._options = None
_ADMINMESSAGE.fields_by_name['reboot_ota_seconds']._serialized_options = b'\030\001'
_OTAMODE._serialized_start=6748
_OTAMODE._serialized_end=6803
_OTAMODE._serialized_start=5852
_OTAMODE._serialized_end=5907
_ADMINMESSAGE._serialized_start=281
_ADMINMESSAGE._serialized_end=4046
_ADMINMESSAGE._serialized_end=4023
_ADMINMESSAGE_INPUTEVENT._serialized_start=3192
_ADMINMESSAGE_INPUTEVENT._serialized_end=3275
_ADMINMESSAGE_OTAEVENT._serialized_start=3277
@@ -40,35 +40,29 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_ADMINMESSAGE_CONFIGTYPE._serialized_start=3363
_ADMINMESSAGE_CONFIGTYPE._serialized_end=3577
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_start=3580
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_end=3990
_ADMINMESSAGE_BACKUPLOCATION._serialized_start=3992
_ADMINMESSAGE_BACKUPLOCATION._serialized_end=4027
_LOCKDOWNAUTH._serialized_start=4049
_LOCKDOWNAUTH._serialized_end=4199
_HAMPARAMETERS._serialized_start=4201
_HAMPARAMETERS._serialized_end=4311
_NODEREMOTEHARDWAREPINSRESPONSE._serialized_start=4313
_NODEREMOTEHARDWAREPINSRESPONSE._serialized_end=4424
_SHAREDCONTACT._serialized_start=4426
_SHAREDCONTACT._serialized_end=4550
_KEYVERIFICATIONADMIN._serialized_start=4553
_KEYVERIFICATIONADMIN._serialized_end=4846
_KEYVERIFICATIONADMIN_MESSAGETYPE._serialized_start=4723
_KEYVERIFICATIONADMIN_MESSAGETYPE._serialized_end=4826
_SENSORCONFIG._serialized_start=4849
_SENSORCONFIG._serialized_end=5266
_SCD4X_CONFIG._serialized_start=5269
_SCD4X_CONFIG._serialized_end=5623
_SEN5X_CONFIG._serialized_start=5626
_SEN5X_CONFIG._serialized_end=5800
_SEN6X_CONFIG._serialized_start=5803
_SEN6X_CONFIG._serialized_end=6219
_SCD30_CONFIG._serialized_start=6222
_SCD30_CONFIG._serialized_end=6530
_SHTXX_CONFIG._serialized_start=6532
_SHTXX_CONFIG._serialized_end=6590
_DS248X_CONFIG._serialized_start=6592
_DS248X_CONFIG._serialized_end=6675
_AS3935_CONFIG._serialized_start=6677
_AS3935_CONFIG._serialized_end=6746
_ADMINMESSAGE_MODULECONFIGTYPE._serialized_end=3967
_ADMINMESSAGE_BACKUPLOCATION._serialized_start=3969
_ADMINMESSAGE_BACKUPLOCATION._serialized_end=4004
_LOCKDOWNAUTH._serialized_start=4025
_LOCKDOWNAUTH._serialized_end=4129
_HAMPARAMETERS._serialized_start=4131
_HAMPARAMETERS._serialized_end=4222
_NODEREMOTEHARDWAREPINSRESPONSE._serialized_start=4224
_NODEREMOTEHARDWAREPINSRESPONSE._serialized_end=4335
_SHAREDCONTACT._serialized_start=4337
_SHAREDCONTACT._serialized_end=4461
_KEYVERIFICATIONADMIN._serialized_start=4464
_KEYVERIFICATIONADMIN._serialized_end=4757
_KEYVERIFICATIONADMIN_MESSAGETYPE._serialized_start=4634
_KEYVERIFICATIONADMIN_MESSAGETYPE._serialized_end=4737
_SENSORCONFIG._serialized_start=4760
_SENSORCONFIG._serialized_end=5002
_SCD4X_CONFIG._serialized_start=5005
_SCD4X_CONFIG._serialized_end=5359
_SEN5X_CONFIG._serialized_start=5361
_SEN5X_CONFIG._serialized_end=5479
_SCD30_CONFIG._serialized_start=5482
_SCD30_CONFIG._serialized_end=5790
_SHTXX_CONFIG._serialized_start=5792
_SHTXX_CONFIG._serialized_end=5850
# @@protoc_insertion_point(module_scope)
+8 -55
View File
@@ -15,12 +15,6 @@ NO_REBOOT_OTA: OTAMode
OTA_BLE: OTAMode
OTA_WIFI: OTAMode
class AS3935_config(_message.Message):
__slots__ = ["set_tuning_cap_pf"]
SET_TUNING_CAP_PF_FIELD_NUMBER: _ClassVar[int]
set_tuning_cap_pf: int
def __init__(self, set_tuning_cap_pf: _Optional[int] = ...) -> None: ...
class AdminMessage(_message.Message):
__slots__ = ["add_contact", "backup_preferences", "begin_edit_settings", "commit_edit_settings", "delete_file_request", "enter_dfu_mode_request", "exit_simulator", "factory_reset_config", "factory_reset_device", "get_canned_message_module_messages_request", "get_canned_message_module_messages_response", "get_channel_request", "get_channel_response", "get_config_request", "get_config_response", "get_device_connection_status_request", "get_device_connection_status_response", "get_device_metadata_request", "get_device_metadata_response", "get_module_config_request", "get_module_config_response", "get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", "get_owner_request", "get_owner_response", "get_ringtone_request", "get_ringtone_response", "get_ui_config_request", "get_ui_config_response", "key_verification", "lockdown_auth", "nodedb_reset", "ota_request", "reboot_ota_seconds", "reboot_seconds", "remove_backup_preferences", "remove_by_nodenum", "remove_favorite_node", "remove_fixed_position", "remove_ignored_node", "restore_preferences", "send_input_event", "sensor_config", "session_passkey", "set_canned_message_module_messages", "set_channel", "set_config", "set_favorite_node", "set_fixed_position", "set_ham_mode", "set_ignored_node", "set_module_config", "set_owner", "set_ringtone_message", "set_scale", "set_time_only", "shutdown_seconds", "store_ui_config", "toggle_muted_node"]
class BackupLocation(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
@@ -89,7 +83,6 @@ class AdminMessage(_message.Message):
KEY_VERIFICATION_FIELD_NUMBER: _ClassVar[int]
LOCKDOWN_AUTH_FIELD_NUMBER: _ClassVar[int]
LORA_CONFIG: AdminMessage.ConfigType
MESHBEACON_CONFIG: AdminMessage.ModuleConfigType
MQTT_CONFIG: AdminMessage.ModuleConfigType
NEIGHBORINFO_CONFIG: AdminMessage.ModuleConfigType
NETWORK_CONFIG: AdminMessage.ConfigType
@@ -196,25 +189,17 @@ class AdminMessage(_message.Message):
toggle_muted_node: int
def __init__(self, session_passkey: _Optional[bytes] = ..., get_channel_request: _Optional[int] = ..., get_channel_response: _Optional[_Union[_channel_pb2.Channel, _Mapping]] = ..., get_owner_request: bool = ..., get_owner_response: _Optional[_Union[_mesh_pb2.User, _Mapping]] = ..., get_config_request: _Optional[_Union[AdminMessage.ConfigType, str]] = ..., get_config_response: _Optional[_Union[_config_pb2.Config, _Mapping]] = ..., get_module_config_request: _Optional[_Union[AdminMessage.ModuleConfigType, str]] = ..., get_module_config_response: _Optional[_Union[_module_config_pb2.ModuleConfig, _Mapping]] = ..., get_canned_message_module_messages_request: bool = ..., get_canned_message_module_messages_response: _Optional[str] = ..., get_device_metadata_request: bool = ..., get_device_metadata_response: _Optional[_Union[_mesh_pb2.DeviceMetadata, _Mapping]] = ..., get_ringtone_request: bool = ..., get_ringtone_response: _Optional[str] = ..., get_device_connection_status_request: bool = ..., get_device_connection_status_response: _Optional[_Union[_connection_status_pb2.DeviceConnectionStatus, _Mapping]] = ..., set_ham_mode: _Optional[_Union[HamParameters, _Mapping]] = ..., get_node_remote_hardware_pins_request: bool = ..., get_node_remote_hardware_pins_response: _Optional[_Union[NodeRemoteHardwarePinsResponse, _Mapping]] = ..., enter_dfu_mode_request: bool = ..., delete_file_request: _Optional[str] = ..., set_scale: _Optional[int] = ..., backup_preferences: _Optional[_Union[AdminMessage.BackupLocation, str]] = ..., restore_preferences: _Optional[_Union[AdminMessage.BackupLocation, str]] = ..., remove_backup_preferences: _Optional[_Union[AdminMessage.BackupLocation, str]] = ..., send_input_event: _Optional[_Union[AdminMessage.InputEvent, _Mapping]] = ..., set_owner: _Optional[_Union[_mesh_pb2.User, _Mapping]] = ..., set_channel: _Optional[_Union[_channel_pb2.Channel, _Mapping]] = ..., set_config: _Optional[_Union[_config_pb2.Config, _Mapping]] = ..., set_module_config: _Optional[_Union[_module_config_pb2.ModuleConfig, _Mapping]] = ..., set_canned_message_module_messages: _Optional[str] = ..., set_ringtone_message: _Optional[str] = ..., remove_by_nodenum: _Optional[int] = ..., set_favorite_node: _Optional[int] = ..., remove_favorite_node: _Optional[int] = ..., set_fixed_position: _Optional[_Union[_mesh_pb2.Position, _Mapping]] = ..., remove_fixed_position: bool = ..., set_time_only: _Optional[int] = ..., get_ui_config_request: bool = ..., get_ui_config_response: _Optional[_Union[_device_ui_pb2.DeviceUIConfig, _Mapping]] = ..., store_ui_config: _Optional[_Union[_device_ui_pb2.DeviceUIConfig, _Mapping]] = ..., set_ignored_node: _Optional[int] = ..., remove_ignored_node: _Optional[int] = ..., toggle_muted_node: _Optional[int] = ..., begin_edit_settings: bool = ..., commit_edit_settings: bool = ..., add_contact: _Optional[_Union[SharedContact, _Mapping]] = ..., key_verification: _Optional[_Union[KeyVerificationAdmin, _Mapping]] = ..., factory_reset_device: _Optional[int] = ..., reboot_ota_seconds: _Optional[int] = ..., exit_simulator: bool = ..., reboot_seconds: _Optional[int] = ..., shutdown_seconds: _Optional[int] = ..., factory_reset_config: _Optional[int] = ..., nodedb_reset: bool = ..., ota_request: _Optional[_Union[AdminMessage.OTAEvent, _Mapping]] = ..., sensor_config: _Optional[_Union[SensorConfig, _Mapping]] = ..., lockdown_auth: _Optional[_Union[LockdownAuth, _Mapping]] = ...) -> None: ...
class DS248X_config(_message.Message):
__slots__ = ["main_temperature_channel"]
MAIN_TEMPERATURE_CHANNEL_FIELD_NUMBER: _ClassVar[int]
main_temperature_channel: int
def __init__(self, main_temperature_channel: _Optional[int] = ...) -> None: ...
class HamParameters(_message.Message):
__slots__ = ["call_sign", "frequency", "long_name", "short_name", "tx_power"]
__slots__ = ["call_sign", "frequency", "short_name", "tx_power"]
CALL_SIGN_FIELD_NUMBER: _ClassVar[int]
FREQUENCY_FIELD_NUMBER: _ClassVar[int]
LONG_NAME_FIELD_NUMBER: _ClassVar[int]
SHORT_NAME_FIELD_NUMBER: _ClassVar[int]
TX_POWER_FIELD_NUMBER: _ClassVar[int]
call_sign: str
frequency: float
long_name: str
short_name: str
tx_power: int
def __init__(self, call_sign: _Optional[str] = ..., tx_power: _Optional[int] = ..., frequency: _Optional[float] = ..., short_name: _Optional[str] = ..., long_name: _Optional[str] = ...) -> None: ...
def __init__(self, call_sign: _Optional[str] = ..., tx_power: _Optional[int] = ..., frequency: _Optional[float] = ..., short_name: _Optional[str] = ...) -> None: ...
class KeyVerificationAdmin(_message.Message):
__slots__ = ["message_type", "nonce", "remote_nodenum", "security_number"]
@@ -235,20 +220,16 @@ class KeyVerificationAdmin(_message.Message):
def __init__(self, message_type: _Optional[_Union[KeyVerificationAdmin.MessageType, str]] = ..., remote_nodenum: _Optional[int] = ..., nonce: _Optional[int] = ..., security_number: _Optional[int] = ...) -> None: ...
class LockdownAuth(_message.Message):
__slots__ = ["boots_remaining", "disable", "lock_now", "max_session_seconds", "passphrase", "valid_until_epoch"]
__slots__ = ["boots_remaining", "lock_now", "passphrase", "valid_until_epoch"]
BOOTS_REMAINING_FIELD_NUMBER: _ClassVar[int]
DISABLE_FIELD_NUMBER: _ClassVar[int]
LOCK_NOW_FIELD_NUMBER: _ClassVar[int]
MAX_SESSION_SECONDS_FIELD_NUMBER: _ClassVar[int]
PASSPHRASE_FIELD_NUMBER: _ClassVar[int]
VALID_UNTIL_EPOCH_FIELD_NUMBER: _ClassVar[int]
boots_remaining: int
disable: bool
lock_now: bool
max_session_seconds: int
passphrase: bytes
valid_until_epoch: int
def __init__(self, passphrase: _Optional[bytes] = ..., boots_remaining: _Optional[int] = ..., valid_until_epoch: _Optional[int] = ..., lock_now: bool = ..., max_session_seconds: _Optional[int] = ..., disable: bool = ...) -> None: ...
def __init__(self, passphrase: _Optional[bytes] = ..., boots_remaining: _Optional[int] = ..., valid_until_epoch: _Optional[int] = ..., lock_now: bool = ...) -> None: ...
class NodeRemoteHardwarePinsResponse(_message.Message):
__slots__ = ["node_remote_hardware_pins"]
@@ -291,34 +272,12 @@ class SCD4X_config(_message.Message):
def __init__(self, set_asc: bool = ..., set_target_co2_conc: _Optional[int] = ..., set_temperature: _Optional[float] = ..., set_altitude: _Optional[int] = ..., set_ambient_pressure: _Optional[int] = ..., factory_reset: bool = ..., set_power_mode: bool = ...) -> None: ...
class SEN5X_config(_message.Message):
__slots__ = ["set_one_shot_mode", "set_temperature", "start_fan_cleaning"]
__slots__ = ["set_one_shot_mode", "set_temperature"]
SET_ONE_SHOT_MODE_FIELD_NUMBER: _ClassVar[int]
SET_TEMPERATURE_FIELD_NUMBER: _ClassVar[int]
START_FAN_CLEANING_FIELD_NUMBER: _ClassVar[int]
set_one_shot_mode: bool
set_temperature: float
start_fan_cleaning: bool
def __init__(self, set_temperature: _Optional[float] = ..., set_one_shot_mode: bool = ..., start_fan_cleaning: bool = ...) -> None: ...
class SEN6X_config(_message.Message):
__slots__ = ["factory_reset", "set_altitude", "set_ambient_pressure", "set_asc", "set_one_shot_mode", "set_target_co2_conc", "set_temperature", "start_fan_cleaning"]
FACTORY_RESET_FIELD_NUMBER: _ClassVar[int]
SET_ALTITUDE_FIELD_NUMBER: _ClassVar[int]
SET_AMBIENT_PRESSURE_FIELD_NUMBER: _ClassVar[int]
SET_ASC_FIELD_NUMBER: _ClassVar[int]
SET_ONE_SHOT_MODE_FIELD_NUMBER: _ClassVar[int]
SET_TARGET_CO2_CONC_FIELD_NUMBER: _ClassVar[int]
SET_TEMPERATURE_FIELD_NUMBER: _ClassVar[int]
START_FAN_CLEANING_FIELD_NUMBER: _ClassVar[int]
factory_reset: bool
set_altitude: int
set_ambient_pressure: int
set_asc: bool
set_one_shot_mode: bool
set_target_co2_conc: int
set_temperature: float
start_fan_cleaning: bool
def __init__(self, set_temperature: _Optional[float] = ..., set_one_shot_mode: bool = ..., start_fan_cleaning: bool = ..., set_asc: bool = ..., set_target_co2_conc: _Optional[int] = ..., set_altitude: _Optional[int] = ..., set_ambient_pressure: _Optional[int] = ..., factory_reset: bool = ...) -> None: ...
def __init__(self, set_temperature: _Optional[float] = ..., set_one_shot_mode: bool = ...) -> None: ...
class SHTXX_config(_message.Message):
__slots__ = ["set_accuracy"]
@@ -327,22 +286,16 @@ class SHTXX_config(_message.Message):
def __init__(self, set_accuracy: _Optional[int] = ...) -> None: ...
class SensorConfig(_message.Message):
__slots__ = ["as3935_config", "ds248x_config", "scd30_config", "scd4x_config", "sen5x_config", "sen6x_config", "shtxx_config"]
AS3935_CONFIG_FIELD_NUMBER: _ClassVar[int]
DS248X_CONFIG_FIELD_NUMBER: _ClassVar[int]
__slots__ = ["scd30_config", "scd4x_config", "sen5x_config", "shtxx_config"]
SCD30_CONFIG_FIELD_NUMBER: _ClassVar[int]
SCD4X_CONFIG_FIELD_NUMBER: _ClassVar[int]
SEN5X_CONFIG_FIELD_NUMBER: _ClassVar[int]
SEN6X_CONFIG_FIELD_NUMBER: _ClassVar[int]
SHTXX_CONFIG_FIELD_NUMBER: _ClassVar[int]
as3935_config: AS3935_config
ds248x_config: DS248X_config
scd30_config: SCD30_config
scd4x_config: SCD4X_config
sen5x_config: SEN5X_config
sen6x_config: SEN6X_config
shtxx_config: SHTXX_config
def __init__(self, scd4x_config: _Optional[_Union[SCD4X_config, _Mapping]] = ..., sen5x_config: _Optional[_Union[SEN5X_config, _Mapping]] = ..., scd30_config: _Optional[_Union[SCD30_config, _Mapping]] = ..., shtxx_config: _Optional[_Union[SHTXX_config, _Mapping]] = ..., ds248x_config: _Optional[_Union[DS248X_config, _Mapping]] = ..., sen6x_config: _Optional[_Union[SEN6X_config, _Mapping]] = ..., as3935_config: _Optional[_Union[AS3935_config, _Mapping]] = ...) -> None: ...
def __init__(self, scd4x_config: _Optional[_Union[SCD4X_config, _Mapping]] = ..., sen5x_config: _Optional[_Union[SEN5X_config, _Mapping]] = ..., scd30_config: _Optional[_Union[SCD30_config, _Mapping]] = ..., shtxx_config: _Optional[_Union[SHTXX_config, _Mapping]] = ...) -> None: ...
class SharedContact(_message.Message):
__slots__ = ["manually_verified", "node_num", "should_ignore", "user"]
+81 -134
View File
@@ -11,10 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import field_metadata_pb2 as meshtastic_dot_protobuf_dot_field__metadata__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/atak.proto\x12\x13meshtastic.protobuf\x1a(meshtastic/protobuf/field_metadata.proto\"\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\"\xfd\x02\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\x12\x17\n\x0freceipt_for_uid\x18\x04 \x01(\t\x12>\n\x0creceipt_type\x18\x05 \x01(\x0e\x32(.meshtastic.protobuf.GeoChat.ReceiptType\x12\x11\n\x04lang\x18\x06 \x01(\tH\x02\x88\x01\x01\x12\x14\n\x07room_id\x18\x07 \x01(\tH\x03\x88\x01\x01\x12\x1d\n\x10voice_profile_id\x18\x08 \x01(\tH\x04\x88\x01\x01\"T\n\x0bReceiptType\x12\x14\n\x10ReceiptType_None\x10\x00\x12\x19\n\x15ReceiptType_Delivered\x10\x01\x12\x14\n\x10ReceiptType_Read\x10\x02\x42\x05\n\x03_toB\x0e\n\x0c_to_callsignB\x07\n\x05_langB\n\n\x08_room_idB\x13\n\x11_voice_profile_id\"_\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\"\xb0\x01\n\rAircraftTrack\x12\x0c\n\x04icao\x18\x01 \x01(\t\x12\x14\n\x0cregistration\x18\x02 \x01(\t\x12\x0e\n\x06\x66light\x18\x03 \x01(\t\x12\x15\n\raircraft_type\x18\x04 \x01(\t\x12\x0e\n\x06squawk\x18\x05 \x01(\r\x12\x10\n\x08\x63\x61tegory\x18\x06 \x01(\t\x12\x10\n\x08rssi_x10\x18\x07 \x01(\x11\x12\x0b\n\x03gps\x18\x08 \x01(\x08\x12\x13\n\x0b\x63ot_host_id\x18\t \x01(\t\"7\n\x0b\x43otGeoPoint\x12\x13\n\x0blat_delta_i\x18\x01 \x01(\x11\x12\x13\n\x0blon_delta_i\x18\x02 \x01(\x11\"\x80\x07\n\nDrawnShape\x12\x32\n\x04kind\x18\x01 \x01(\x0e\x32$.meshtastic.protobuf.DrawnShape.Kind\x12\x38\n\x05style\x18\x02 \x01(\x0e\x32).meshtastic.protobuf.DrawnShape.StyleMode\x12\x10\n\x08major_cm\x18\x03 \x01(\r\x12\x10\n\x08minor_cm\x18\x04 \x01(\r\x12\x11\n\tangle_deg\x18\x05 \x01(\r\x12/\n\x0cstroke_color\x18\x06 \x01(\x0e\x32\x19.meshtastic.protobuf.Team\x12\x13\n\x0bstroke_argb\x18\x07 \x01(\x07\x12\x19\n\x11stroke_weight_x10\x18\x08 \x01(\r\x12-\n\nfill_color\x18\t \x01(\x0e\x32\x19.meshtastic.protobuf.Team\x12\x11\n\tfill_argb\x18\n \x01(\x07\x12\x11\n\tlabels_on\x18\x0b \x01(\x08\x12\x19\n\x11vertex_lat_deltas\x18\x12 \x03(\x11\x12\x19\n\x11vertex_lon_deltas\x18\x13 \x03(\x11\x12\x11\n\ttruncated\x18\r \x01(\x08\x12\x1c\n\x14\x62ullseye_distance_dm\x18\x0e \x01(\r\x12\x1c\n\x14\x62ullseye_bearing_ref\x18\x0f \x01(\r\x12\x16\n\x0e\x62ullseye_flags\x18\x10 \x01(\r\x12\x18\n\x10\x62ullseye_uid_ref\x18\x11 \x01(\t\"\xe2\x01\n\x04Kind\x12\x14\n\x10Kind_Unspecified\x10\x00\x12\x0f\n\x0bKind_Circle\x10\x01\x12\x12\n\x0eKind_Rectangle\x10\x02\x12\x11\n\rKind_Freeform\x10\x03\x12\x15\n\x11Kind_Telestration\x10\x04\x12\x10\n\x0cKind_Polygon\x10\x05\x12\x16\n\x12Kind_RangingCircle\x10\x06\x12\x11\n\rKind_Bullseye\x10\x07\x12\x10\n\x0cKind_Ellipse\x10\x08\x12\x12\n\x0eKind_Vehicle2D\x10\t\x12\x12\n\x0eKind_Vehicle3D\x10\n\"u\n\tStyleMode\x12\x19\n\x15StyleMode_Unspecified\x10\x00\x12\x18\n\x14StyleMode_StrokeOnly\x10\x01\x12\x16\n\x12StyleMode_FillOnly\x10\x02\x12\x1b\n\x17StyleMode_StrokeAndFill\x10\x03J\x04\x08\x0c\x10\r\"\xf7\x03\n\x06Marker\x12.\n\x04kind\x18\x01 \x01(\x0e\x32 .meshtastic.protobuf.Marker.Kind\x12(\n\x05\x63olor\x18\x02 \x01(\x0e\x32\x19.meshtastic.protobuf.Team\x12\x12\n\ncolor_argb\x18\x03 \x01(\x07\x12\x11\n\treadiness\x18\x04 \x01(\x08\x12\x12\n\nparent_uid\x18\x05 \x01(\t\x12\x13\n\x0bparent_type\x18\x06 \x01(\t\x12\x17\n\x0fparent_callsign\x18\x07 \x01(\t\x12\x0f\n\x07iconset\x18\x08 \x01(\t\"\x98\x02\n\x04Kind\x12\x14\n\x10Kind_Unspecified\x10\x00\x12\r\n\tKind_Spot\x10\x01\x12\x11\n\rKind_Waypoint\x10\x02\x12\x13\n\x0fKind_Checkpoint\x10\x03\x12\x15\n\x11Kind_SelfPosition\x10\x04\x12\x13\n\x0fKind_Symbol2525\x10\x05\x12\x10\n\x0cKind_SpotMap\x10\x06\x12\x13\n\x0fKind_CustomIcon\x10\x07\x12\x12\n\x0eKind_GoToPoint\x10\x08\x12\x15\n\x11Kind_InitialPoint\x10\t\x12\x15\n\x11Kind_ContactPoint\x10\n\x12\x18\n\x14Kind_ObservationPost\x10\x0b\x12\x14\n\x10Kind_ImageMarker\x10\x0c\"\xe0\x01\n\x0fRangeAndBearing\x12\x30\n\x06\x61nchor\x18\x01 \x01(\x0b\x32 .meshtastic.protobuf.CotGeoPoint\x12\x12\n\nanchor_uid\x18\x02 \x01(Line truncated
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\"\xfd\x02\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\x12\x17\n\x0freceipt_for_uid\x18\x04 \x01(\t\x12>\n\x0creceipt_type\x18\x05 \x01(\x0e\x32(.meshtastic.protobuf.GeoChat.ReceiptType\x12\x11\n\x04lang\x18\x06 \x01(\tH\x02\x88\x01\x01\x12\x14\n\x07room_id\x18\x07 \x01(\tH\x03\x88\x01\x01\x12\x1d\n\x10voice_profile_id\x18\x08 \x01(\tH\x04\x88\x01\x01\"T\n\x0bReceiptType\x12\x14\n\x10ReceiptType_None\x10\x00\x12\x19\n\x15ReceiptType_Delivered\x10\x01\x12\x14\n\x10ReceiptType_Read\x10\x02\x42\x05\n\x03_toB\x0e\n\x0c_to_callsignB\x07\n\x05_langB\n\n\x08_room_idB\x13\n\x11_voice_profile_id\"_\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\"\xb0\x01\n\rAircraftTrack\x12\x0c\n\x04icao\x18\x01 \x01(\t\x12\x14\n\x0cregistration\x18\x02 \x01(\t\x12\x0e\n\x06\x66light\x18\x03 \x01(\t\x12\x15\n\raircraft_type\x18\x04 \x01(\t\x12\x0e\n\x06squawk\x18\x05 \x01(\r\x12\x10\n\x08\x63\x61tegory\x18\x06 \x01(\t\x12\x10\n\x08rssi_x10\x18\x07 \x01(\x11\x12\x0b\n\x03gps\x18\x08 \x01(\x08\x12\x13\n\x0b\x63ot_host_id\x18\t \x01(\t\"7\n\x0b\x43otGeoPoint\x12\x13\n\x0blat_delta_i\x18\x01 \x01(\x11\x12\x13\n\x0blon_delta_i\x18\x02 \x01(\x11\"\xf8\x06\n\nDrawnShape\x12\x32\n\x04kind\x18\x01 \x01(\x0e\x32$.meshtastic.protobuf.DrawnShape.Kind\x12\x38\n\x05style\x18\x02 \x01(\x0e\x32).meshtastic.protobuf.DrawnShape.StyleMode\x12\x10\n\x08major_cm\x18\x03 \x01(\r\x12\x10\n\x08minor_cm\x18\x04 \x01(\r\x12\x11\n\tangle_deg\x18\x05 \x01(\r\x12/\n\x0cstroke_color\x18\x06 \x01(\x0e\x32\x19.meshtastic.protobuf.Team\x12\x13\n\x0bstroke_argb\x18\x07 \x01(\x07\x12\x19\n\x11stroke_weight_x10\x18\x08 \x01(\r\x12-\n\nfill_color\x18\t \x01(\x0e\x32\x19.meshtastic.protobuf.Team\x12\x11\n\tfill_argb\x18\n \x01(\x07\x12\x11\n\tlabels_on\x18\x0b \x01(\x08\x12\x32\n\x08vertices\x18\x0c \x03(\x0b\x32 .meshtastic.protobuf.CotGeoPoint\x12\x11\n\ttruncated\x18\r \x01(\x08\x12\x1c\n\x14\x62ullseye_distance_dm\x18\x0e \x01(\r\x12\x1c\n\x14\x62ullseye_bearing_ref\x18\x0f \x01(\r\x12\x16\n\x0e\x62ullseye_flags\x18\x10 \x01(\r\x12\x18\n\x10\x62ullseye_uid_ref\x18\x11 \x01(\t\"\xe2\x01\n\x04Kind\x12\x14\n\x10Kind_Unspecified\x10\x00\x12\x0f\n\x0bKind_Circle\x10\x01\x12\x12\n\x0eKind_Rectangle\x10\x02\x12\x11\n\rKind_Freeform\x10\x03\x12\x15\n\x11Kind_Telestration\x10\x04\x12\x10\n\x0cKind_Polygon\x10\x05\x12\x16\n\x12Kind_RangingCircle\x10\x06\x12\x11\n\rKind_Bullseye\x10\x07\x12\x10\n\x0cKind_Ellipse\x10\x08\x12\x12\n\x0eKind_Vehicle2D\x10\t\x12\x12\n\x0eKind_Vehicle3D\x10\n\"u\n\tStyleMode\x12\x19\n\x15StyleMode_Unspecified\x10\x00\x12\x18\n\x14StyleMode_StrokeOnly\x10\x01\x12\x16\n\x12StyleMode_FillOnly\x10\x02\x12\x1b\n\x17StyleMode_StrokeAndFill\x10\x03\"\xf7\x03\n\x06Marker\x12.\n\x04kind\x18\x01 \x01(\x0e\x32 .meshtastic.protobuf.Marker.Kind\x12(\n\x05\x63olor\x18\x02 \x01(\x0e\x32\x19.meshtastic.protobuf.Team\x12\x12\n\ncolor_argb\x18\x03 \x01(\x07\x12\x11\n\treadiness\x18\x04 \x01(\x08\x12\x12\n\nparent_uid\x18\x05 \x01(\t\x12\x13\n\x0bparent_type\x18\x06 \x01(\t\x12\x17\n\x0fparent_callsign\x18\x07 \x01(\t\x12\x0f\n\x07iconset\x18\x08 \x01(\t\"\x98\x02\n\x04Kind\x12\x14\n\x10Kind_Unspecified\x10\x00\x12\r\n\tKind_Spot\x10\x01\x12\x11\n\rKind_Waypoint\x10\x02\x12\x13\n\x0fKind_Checkpoint\x10\x03\x12\x15\n\x11Kind_SelfPosition\x10\x04\x12\x13\n\x0fKind_Symbol2525\x10\x05\x12\x10\n\x0cKind_SpotMap\x10\x06\x12\x13\n\x0fKind_CustomIcon\x10\x07\x12\x12\n\x0eKind_GoToPoint\x10\x08\x12\x15\n\x11Kind_InitialPoint\x10\t\x12\x15\n\x11Kind_ContactPoint\x10\n\x12\x18\n\x14Kind_ObservationPost\x10\x0b\x12\x14\n\x10Kind_ImageMarker\x10\x0c\"\xe0\x01\n\x0fRangeAndBearing\x12\x30\n\x06\x61nchor\x18\x01 \x01(\x0b\x32 .meshtastic.protobuf.CotGeoPoint\x12\x12\n\nanchor_uid\x18\x02 \x01(\t\x12\x10\n\x08range_cm\x18\x03 \x01(\r\x12\x14\n\x0c\x62\x65\x61ring_cdeg\x18\x04 \Line truncated
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.atak_pb2', globals())
@@ -22,136 +21,84 @@ 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'
_TEAM.values_by_name["Unspecifed_Color"]._options = None
_TEAM.values_by_name["Unspecifed_Color"]._serialized_options = b'\312\363\030\020:\016Default (Cyan)'
_TEAM.values_by_name["White"]._options = None
_TEAM.values_by_name["White"]._serialized_options = b'\312\363\030\007:\005White'
_TEAM.values_by_name["Yellow"]._options = None
_TEAM.values_by_name["Yellow"]._serialized_options = b'\312\363\030\010:\006Yellow'
_TEAM.values_by_name["Orange"]._options = None
_TEAM.values_by_name["Orange"]._serialized_options = b'\312\363\030\010:\006Orange'
_TEAM.values_by_name["Magenta"]._options = None
_TEAM.values_by_name["Magenta"]._serialized_options = b'\312\363\030\t:\007Magenta'
_TEAM.values_by_name["Red"]._options = None
_TEAM.values_by_name["Red"]._serialized_options = b'\312\363\030\005:\003Red'
_TEAM.values_by_name["Maroon"]._options = None
_TEAM.values_by_name["Maroon"]._serialized_options = b'\312\363\030\010:\006Maroon'
_TEAM.values_by_name["Purple"]._options = None
_TEAM.values_by_name["Purple"]._serialized_options = b'\312\363\030\010:\006Purple'
_TEAM.values_by_name["Dark_Blue"]._options = None
_TEAM.values_by_name["Dark_Blue"]._serialized_options = b'\312\363\030\013:\tDark Blue'
_TEAM.values_by_name["Blue"]._options = None
_TEAM.values_by_name["Blue"]._serialized_options = b'\312\363\030\006:\004Blue'
_TEAM.values_by_name["Cyan"]._options = None
_TEAM.values_by_name["Cyan"]._serialized_options = b'\312\363\030\006:\004Cyan'
_TEAM.values_by_name["Teal"]._options = None
_TEAM.values_by_name["Teal"]._serialized_options = b'\312\363\030\006:\004Teal'
_TEAM.values_by_name["Green"]._options = None
_TEAM.values_by_name["Green"]._serialized_options = b'\312\363\030\007:\005Green'
_TEAM.values_by_name["Dark_Green"]._options = None
_TEAM.values_by_name["Dark_Green"]._serialized_options = b'\312\363\030\014:\nDark Green'
_TEAM.values_by_name["Brown"]._options = None
_TEAM.values_by_name["Brown"]._serialized_options = b'\312\363\030\007:\005Brown'
_MEMBERROLE.values_by_name["Unspecifed"]._options = None
_MEMBERROLE.values_by_name["Unspecifed"]._serialized_options = b'\312\363\030\027:\025Default (Team Member)'
_MEMBERROLE.values_by_name["TeamMember"]._options = None
_MEMBERROLE.values_by_name["TeamMember"]._serialized_options = b'\312\363\030\r:\013Team Member'
_MEMBERROLE.values_by_name["TeamLead"]._options = None
_MEMBERROLE.values_by_name["TeamLead"]._serialized_options = b'\312\363\030\013:\tTeam Lead'
_MEMBERROLE.values_by_name["HQ"]._options = None
_MEMBERROLE.values_by_name["HQ"]._serialized_options = b'\312\363\030\004:\002HQ'
_MEMBERROLE.values_by_name["Sniper"]._options = None
_MEMBERROLE.values_by_name["Sniper"]._serialized_options = b'\312\363\030\010:\006Sniper'
_MEMBERROLE.values_by_name["Medic"]._options = None
_MEMBERROLE.values_by_name["Medic"]._serialized_options = b'\312\363\030\007:\005Medic'
_MEMBERROLE.values_by_name["ForwardObserver"]._options = None
_MEMBERROLE.values_by_name["ForwardObserver"]._serialized_options = b'\312\363\030\022:\020Forward Observer'
_MEMBERROLE.values_by_name["RTO"]._options = None
_MEMBERROLE.values_by_name["RTO"]._serialized_options = b'\312\363\030\005:\003RTO'
_MEMBERROLE.values_by_name["K9"]._options = None
_MEMBERROLE.values_by_name["K9"]._serialized_options = b'\312\363\030\004:\002K9'
_TAKTALKROOMDATA.fields_by_name['sender_callsign']._options = None
_TAKTALKROOMDATA.fields_by_name['sender_callsign']._serialized_options = b'\030\001'
_TEAM._serialized_start=7941
_TEAM._serialized_end=8347
_MEMBERROLE._serialized_start=8350
_MEMBERROLE._serialized_end=8624
_COTHOW._serialized_start=8627
_COTHOW._serialized_end=8777
_COTTYPE._serialized_start=8780
_COTTYPE._serialized_end=11727
_GEOPOINTSOURCE._serialized_start=11729
_GEOPOINTSOURCE._serialized_end=11854
_TAKPACKET._serialized_start=98
_TAKPACKET._serialized_end=391
_GEOCHAT._serialized_start=394
_GEOCHAT._serialized_end=775
_GEOCHAT_RECEIPTTYPE._serialized_start=626
_GEOCHAT_RECEIPTTYPE._serialized_end=710
_GROUP._serialized_start=777
_GROUP._serialized_end=872
_STATUS._serialized_start=874
_STATUS._serialized_end=899
_CONTACT._serialized_start=901
_CONTACT._serialized_end=953
_PLI._serialized_start=955
_PLI._serialized_end=1050
_AIRCRAFTTRACK._serialized_start=1053
_AIRCRAFTTRACK._serialized_end=1229
_COTGEOPOINT._serialized_start=1231
_COTGEOPOINT._serialized_end=1286
_DRAWNSHAPE._serialized_start=1289
_DRAWNSHAPE._serialized_end=2185
_DRAWNSHAPE_KIND._serialized_start=1834
_DRAWNSHAPE_KIND._serialized_end=2060
_DRAWNSHAPE_STYLEMODE._serialized_start=2062
_DRAWNSHAPE_STYLEMODE._serialized_end=2179
_MARKER._serialized_start=2188
_MARKER._serialized_end=2691
_MARKER_KIND._serialized_start=2411
_MARKER_KIND._serialized_end=2691
_RANGEANDBEARING._serialized_start=2694
_RANGEANDBEARING._serialized_end=2918
_ROUTE._serialized_start=2921
_ROUTE._serialized_end=3473
_ROUTE_LINK._serialized_start=3148
_ROUTE_LINK._serialized_end=3253
_ROUTE_METHOD._serialized_start=3256
_ROUTE_METHOD._serialized_end=3391
_ROUTE_DIRECTION._serialized_start=3393
_ROUTE_DIRECTION._serialized_end=3473
_CASEVACREPORT._serialized_start=3476
_CASEVACREPORT._serialized_end=4878
_CASEVACREPORT_PRECEDENCE._serialized_start=4400
_CASEVACREPORT_PRECEDENCE._serialized_end=4571
_CASEVACREPORT_HLZMARKING._serialized_start=4574
_CASEVACREPORT_HLZMARKING._serialized_end=4729
_CASEVACREPORT_SECURITY._serialized_start=4732
_CASEVACREPORT_SECURITY._serialized_end=4878
_ZMISTENTRY._serialized_start=4880
_ZMISTENTRY._serialized_end=4962
_EMERGENCYALERT._serialized_start=4965
_EMERGENCYALERT._serialized_end=5243
_EMERGENCYALERT_TYPE._serialized_start=5093
_EMERGENCYALERT_TYPE._serialized_end=5243
_TASKREQUEST._serialized_start=5246
_TASKREQUEST._serialized_end=5718
_TASKREQUEST_PRIORITY._serialized_start=5454
_TASKREQUEST_PRIORITY._serialized_end=5571
_TASKREQUEST_STATUS._serialized_start=5574
_TASKREQUEST_STATUS._serialized_end=5718
_TAKENVIRONMENT._serialized_start=5720
_TAKENVIRONMENT._serialized_end=5816
_SENSORFOV._serialized_start=5819
_SENSORFOV._serialized_end=6225
_SENSORFOV_SENSORTYPE._serialized_start=6043
_SENSORFOV_SENSORTYPE._serialized_end=6213
_TAKTALKMESSAGE._serialized_start=6227
_TAKTALKMESSAGE._serialized_end=6312
_TAKTALKROOMDATA._serialized_start=6314
_TAKTALKROOMDATA._serialized_end=6418
_MARTI._serialized_start=6420
_MARTI._serialized_end=6450
_TAKPACKETV2._serialized_start=6453
_TAKPACKETV2._serialized_end=7938
_TEAM._serialized_start=7812
_TEAM._serialized_end=8004
_MEMBERROLE._serialized_start=8006
_MEMBERROLE._serialized_end=8133
_COTHOW._serialized_start=8136
_COTHOW._serialized_end=8286
_COTTYPE._serialized_start=8289
_COTTYPE._serialized_end=11236
_GEOPOINTSOURCE._serialized_start=11238
_GEOPOINTSOURCE._serialized_end=11363
_TAKPACKET._serialized_start=56
_TAKPACKET._serialized_end=349
_GEOCHAT._serialized_start=352
_GEOCHAT._serialized_end=733
_GEOCHAT_RECEIPTTYPE._serialized_start=584
_GEOCHAT_RECEIPTTYPE._serialized_end=668
_GROUP._serialized_start=735
_GROUP._serialized_end=830
_STATUS._serialized_start=832
_STATUS._serialized_end=857
_CONTACT._serialized_start=859
_CONTACT._serialized_end=911
_PLI._serialized_start=913
_PLI._serialized_end=1008
_AIRCRAFTTRACK._serialized_start=1011
_AIRCRAFTTRACK._serialized_end=1187
_COTGEOPOINT._serialized_start=1189
_COTGEOPOINT._serialized_end=1244
_DRAWNSHAPE._serialized_start=1247
_DRAWNSHAPE._serialized_end=2135
_DRAWNSHAPE_KIND._serialized_start=1790
_DRAWNSHAPE_KIND._serialized_end=2016
_DRAWNSHAPE_STYLEMODE._serialized_start=2018
_DRAWNSHAPE_STYLEMODE._serialized_end=2135
_MARKER._serialized_start=2138
_MARKER._serialized_end=2641
_MARKER_KIND._serialized_start=2361
_MARKER_KIND._serialized_end=2641
_RANGEANDBEARING._serialized_start=2644
_RANGEANDBEARING._serialized_end=2868
_ROUTE._serialized_start=2871
_ROUTE._serialized_end=3423
_ROUTE_LINK._serialized_start=3098
_ROUTE_LINK._serialized_end=3203
_ROUTE_METHOD._serialized_start=3206
_ROUTE_METHOD._serialized_end=3341
_ROUTE_DIRECTION._serialized_start=3343
_ROUTE_DIRECTION._serialized_end=3423
_CASEVACREPORT._serialized_start=3426
_CASEVACREPORT._serialized_end=4828
_CASEVACREPORT_PRECEDENCE._serialized_start=4350
_CASEVACREPORT_PRECEDENCE._serialized_end=4521
_CASEVACREPORT_HLZMARKING._serialized_start=4524
_CASEVACREPORT_HLZMARKING._serialized_end=4679
_CASEVACREPORT_SECURITY._serialized_start=4682
_CASEVACREPORT_SECURITY._serialized_end=4828
_ZMISTENTRY._serialized_start=4830
_ZMISTENTRY._serialized_end=4912
_EMERGENCYALERT._serialized_start=4915
_EMERGENCYALERT._serialized_end=5193
_EMERGENCYALERT_TYPE._serialized_start=5043
_EMERGENCYALERT_TYPE._serialized_end=5193
_TASKREQUEST._serialized_start=5196
_TASKREQUEST._serialized_end=5668
_TASKREQUEST_PRIORITY._serialized_start=5404
_TASKREQUEST_PRIORITY._serialized_end=5521
_TASKREQUEST_STATUS._serialized_start=5524
_TASKREQUEST_STATUS._serialized_end=5668
_TAKENVIRONMENT._serialized_start=5670
_TAKENVIRONMENT._serialized_end=5766
_SENSORFOV._serialized_start=5769
_SENSORFOV._serialized_end=6175
_SENSORFOV_SENSORTYPE._serialized_start=5993
_SENSORFOV_SENSORTYPE._serialized_end=6163
_TAKTALKMESSAGE._serialized_start=6177
_TAKTALKMESSAGE._serialized_end=6262
_TAKTALKROOMDATA._serialized_start=6264
_TAKTALKROOMDATA._serialized_end=6364
_TAKPACKETV2._serialized_start=6367
_TAKPACKETV2._serialized_end=7809
# @@protoc_insertion_point(module_scope)
+8 -17
View File
@@ -1,4 +1,3 @@
from meshtastic.protobuf import field_metadata_pb2 as _field_metadata_pb2
from google.protobuf.internal import containers as _containers
from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
from google.protobuf import descriptor as _descriptor
@@ -302,7 +301,7 @@ class CotGeoPoint(_message.Message):
def __init__(self, lat_delta_i: _Optional[int] = ..., lon_delta_i: _Optional[int] = ...) -> None: ...
class DrawnShape(_message.Message):
__slots__ = ["angle_deg", "bullseye_bearing_ref", "bullseye_distance_dm", "bullseye_flags", "bullseye_uid_ref", "fill_argb", "fill_color", "kind", "labels_on", "major_cm", "minor_cm", "stroke_argb", "stroke_color", "stroke_weight_x10", "style", "truncated", "vertex_lat_deltas", "vertex_lon_deltas"]
__slots__ = ["angle_deg", "bullseye_bearing_ref", "bullseye_distance_dm", "bullseye_flags", "bullseye_uid_ref", "fill_argb", "fill_color", "kind", "labels_on", "major_cm", "minor_cm", "stroke_argb", "stroke_color", "stroke_weight_x10", "style", "truncated", "vertices"]
class Kind(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class StyleMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
@@ -338,8 +337,7 @@ class DrawnShape(_message.Message):
StyleMode_StrokeOnly: DrawnShape.StyleMode
StyleMode_Unspecified: DrawnShape.StyleMode
TRUNCATED_FIELD_NUMBER: _ClassVar[int]
VERTEX_LAT_DELTAS_FIELD_NUMBER: _ClassVar[int]
VERTEX_LON_DELTAS_FIELD_NUMBER: _ClassVar[int]
VERTICES_FIELD_NUMBER: _ClassVar[int]
angle_deg: int
bullseye_bearing_ref: int
bullseye_distance_dm: int
@@ -356,9 +354,8 @@ class DrawnShape(_message.Message):
stroke_weight_x10: int
style: DrawnShape.StyleMode
truncated: bool
vertex_lat_deltas: _containers.RepeatedScalarFieldContainer[int]
vertex_lon_deltas: _containers.RepeatedScalarFieldContainer[int]
def __init__(self, kind: _Optional[_Union[DrawnShape.Kind, str]] = ..., style: _Optional[_Union[DrawnShape.StyleMode, str]] = ..., major_cm: _Optional[int] = ..., minor_cm: _Optional[int] = ..., angle_deg: _Optional[int] = ..., stroke_color: _Optional[_Union[Team, str]] = ..., stroke_argb: _Optional[int] = ..., stroke_weight_x10: _Optional[int] = ..., fill_color: _Optional[_Union[Team, str]] = ..., fill_argb: _Optional[int] = ..., labels_on: bool = ..., vertex_lat_deltas: _Optional[_Iterable[int]] = ..., vertex_lon_deltas: _Optional[_Iterable[int]] = ..., truncated: bool = ..., bullseye_distance_dm: _Optional[int] = ..., bullseye_bearing_ref: _Optional[int] = ..., bullseye_flags: _Optional[int] = ..., bullseye_uid_ref: _Optional[str] = ...) -> None: ...
vertices: _containers.RepeatedCompositeFieldContainer[CotGeoPoint]
def __init__(self, kind: _Optional[_Union[DrawnShape.Kind, str]] = ..., style: _Optional[_Union[DrawnShape.StyleMode, str]] = ..., major_cm: _Optional[int] = ..., minor_cm: _Optional[int] = ..., angle_deg: _Optional[int] = ..., stroke_color: _Optional[_Union[Team, str]] = ..., stroke_argb: _Optional[int] = ..., stroke_weight_x10: _Optional[int] = ..., fill_color: _Optional[_Union[Team, str]] = ..., fill_argb: _Optional[int] = ..., labels_on: bool = ..., vertices: _Optional[_Iterable[_Union[CotGeoPoint, _Mapping]]] = ..., truncated: bool = ..., bullseye_distance_dm: _Optional[int] = ..., bullseye_bearing_ref: _Optional[int] = ..., bullseye_flags: _Optional[int] = ..., bullseye_uid_ref: _Optional[str] = ...) -> None: ...
class EmergencyAlert(_message.Message):
__slots__ = ["authoring_uid", "cancel_reference_uid", "type"]
@@ -447,12 +444,6 @@ class Marker(_message.Message):
readiness: bool
def __init__(self, kind: _Optional[_Union[Marker.Kind, str]] = ..., color: _Optional[_Union[Team, str]] = ..., color_argb: _Optional[int] = ..., readiness: bool = ..., parent_uid: _Optional[str] = ..., parent_type: _Optional[str] = ..., parent_callsign: _Optional[str] = ..., iconset: _Optional[str] = ...) -> None: ...
class Marti(_message.Message):
__slots__ = ["dest_callsign"]
DEST_CALLSIGN_FIELD_NUMBER: _ClassVar[int]
dest_callsign: _containers.RepeatedScalarFieldContainer[str]
def __init__(self, dest_callsign: _Optional[_Iterable[str]] = ...) -> None: ...
class PLI(_message.Message):
__slots__ = ["altitude", "course", "latitude_i", "longitude_i", "speed"]
ALTITUDE_FIELD_NUMBER: _ClassVar[int]
@@ -589,7 +580,7 @@ class TAKPacket(_message.Message):
def __init__(self, is_compressed: bool = ..., contact: _Optional[_Union[Contact, _Mapping]] = ..., group: _Optional[_Union[Group, _Mapping]] = ..., status: _Optional[_Union[Status, _Mapping]] = ..., pli: _Optional[_Union[PLI, _Mapping]] = ..., chat: _Optional[_Union[GeoChat, _Mapping]] = ..., detail: _Optional[bytes] = ...) -> None: ...
class TAKPacketV2(_message.Message):
__slots__ = ["aircraft", "alt_src", "altitude", "battery", "callsign", "casevac", "chat", "cot_type_id", "cot_type_str", "course", "device_callsign", "emergency", "endpoint", "environment", "geo_src", "how", "latitude_i", "longitude_i", "marker", "marti", "phone", "rab", "raw_detail", "remarks", "role", "route", "sensor_fov", "shape", "speed", "stale_seconds", "tak_device", "tak_os", "tak_platform", "tak_version", "taktalk", "taktalk_room", "task", "team", "uid"]
__slots__ = ["aircraft", "alt_src", "altitude", "battery", "callsign", "casevac", "chat", "cot_type_id", "cot_type_str", "course", "device_callsign", "emergency", "endpoint", "environment", "geo_src", "how", "latitude_i", "longitude_i", "marker", "phone", "pli", "rab", "raw_detail", "remarks", "role", "route", "sensor_fov", "shape", "speed", "stale_seconds", "tak_device", "tak_os", "tak_platform", "tak_version", "taktalk", "taktalk_room", "task", "team", "uid"]
AIRCRAFT_FIELD_NUMBER: _ClassVar[int]
ALTITUDE_FIELD_NUMBER: _ClassVar[int]
ALT_SRC_FIELD_NUMBER: _ClassVar[int]
@@ -609,8 +600,8 @@ class TAKPacketV2(_message.Message):
LATITUDE_I_FIELD_NUMBER: _ClassVar[int]
LONGITUDE_I_FIELD_NUMBER: _ClassVar[int]
MARKER_FIELD_NUMBER: _ClassVar[int]
MARTI_FIELD_NUMBER: _ClassVar[int]
PHONE_FIELD_NUMBER: _ClassVar[int]
PLI_FIELD_NUMBER: _ClassVar[int]
RAB_FIELD_NUMBER: _ClassVar[int]
RAW_DETAIL_FIELD_NUMBER: _ClassVar[int]
REMARKS_FIELD_NUMBER: _ClassVar[int]
@@ -648,8 +639,8 @@ class TAKPacketV2(_message.Message):
latitude_i: int
longitude_i: int
marker: Marker
marti: Marti
phone: str
pli: bool
rab: RangeAndBearing
raw_detail: bytes
remarks: str
@@ -668,7 +659,7 @@ class TAKPacketV2(_message.Message):
task: TaskRequest
team: Team
uid: str
def __init__(self, cot_type_id: _Optional[_Union[CotType, str]] = ..., how: _Optional[_Union[CotHow, str]] = ..., callsign: _Optional[str] = ..., team: _Optional[_Union[Team, str]] = ..., role: _Optional[_Union[MemberRole, str]] = ..., latitude_i: _Optional[int] = ..., longitude_i: _Optional[int] = ..., altitude: _Optional[int] = ..., speed: _Optional[int] = ..., course: _Optional[int] = ..., battery: _Optional[int] = ..., geo_src: _Optional[_Union[GeoPointSource, str]] = ..., alt_src: _Optional[_Union[GeoPointSource, str]] = ..., uid: _Optional[str] = ..., device_callsign: _Optional[str] = ..., stale_seconds: _Optional[int] = ..., tak_version: _Optional[str] = ..., tak_device: _Optional[str] = ..., tak_platform: _Optional[str] = ..., tak_os: _Optional[str] = ..., endpoint: _Optional[str] = ..., phone: _Optional[str] = ..., cot_type_str: _Optional[str] = ..., remarks: _Optional[str] = ..., environment: _Optional[_Union[TAKEnvironment, _Mapping]] = ..., sensor_fov: _Optional[_Union[SensorFov, _Mapping]] = ..., marti: _Optional[_Union[Marti, _Mapping]] = ..., chat: _Optional[_Union[GeoChat, _Mapping]] = ..., aircraft: _Optional[_Union[AircraftTrack, _Mapping]] = ..., raw_detail: _Optional[bytes] = ..., shape: _Optional[_Union[DrawnShape, _Mapping]] = ..., marker: _Optional[_Union[Marker, _Mapping]] = ..., rab: _Optional[_Union[RangeAndBearing, _Mapping]] = ..., route: _Optional[_Union[Route, _Mapping]] = ..., casevac: _Optional[_Union[CasevacReport, _Mapping]] = ..., emergency: _Optional[_Union[EmergencyAlert, _Mapping]] = ..., task: _Optional[_Union[TaskRequest, _Mapping]] = ..., taktalk: _Optional[_Union[TakTalkMessage, _Mapping]] = ..., taktalk_room: _Optional[_Union[TakTalkRoomData, _Mapping]] = ...) -> None: ...
def __init__(self, cot_type_id: _Optional[_Union[CotType, str]] = ..., how: _Optional[_Union[CotHow, str]] = ..., callsign: _Optional[str] = ..., team: _Optional[_Union[Team, str]] = ..., role: _Optional[_Union[MemberRole, str]] = ..., latitude_i: _Optional[int] = ..., longitude_i: _Optional[int] = ..., altitude: _Optional[int] = ..., speed: _Optional[int] = ..., course: _Optional[int] = ..., battery: _Optional[int] = ..., geo_src: _Optional[_Union[GeoPointSource, str]] = ..., alt_src: _Optional[_Union[GeoPointSource, str]] = ..., uid: _Optional[str] = ..., device_callsign: _Optional[str] = ..., stale_seconds: _Optional[int] = ..., tak_version: _Optional[str] = ..., tak_device: _Optional[str] = ..., tak_platform: _Optional[str] = ..., tak_os: _Optional[str] = ..., endpoint: _Optional[str] = ..., phone: _Optional[str] = ..., cot_type_str: _Optional[str] = ..., remarks: _Optional[str] = ..., environment: _Optional[_Union[TAKEnvironment, _Mapping]] = ..., sensor_fov: _Optional[_Union[SensorFov, _Mapping]] = ..., pli: bool = ..., chat: _Optional[_Union[GeoChat, _Mapping]] = ..., aircraft: _Optional[_Union[AircraftTrack, _Mapping]] = ..., raw_detail: _Optional[bytes] = ..., shape: _Optional[_Union[DrawnShape, _Mapping]] = ..., marker: _Optional[_Union[Marker, _Mapping]] = ..., rab: _Optional[_Union[RangeAndBearing, _Mapping]] = ..., route: _Optional[_Union[Route, _Mapping]] = ..., casevac: _Optional[_Union[CasevacReport, _Mapping]] = ..., emergency: _Optional[_Union[EmergencyAlert, _Mapping]] = ..., task: _Optional[_Union[TaskRequest, _Mapping]] = ..., taktalk: _Optional[_Union[TakTalkMessage, _Mapping]] = ..., taktalk_room: _Optional[_Union[TakTalkRoomData, _Mapping]] = ...) -> None: ...
class TakTalkMessage(_message.Message):
__slots__ = ["chatroom_id", "from_voice", "lang", "text"]
+8 -8
View File
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!meshtastic/protobuf/channel.proto\x12\x13meshtastic.protobuf\"\xd3\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\x12\x10\n\x08use_aead\x18\x08 \x01(\x08\">\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')
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')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.channel_pb2', globals())
@@ -24,11 +24,11 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_CHANNELSETTINGS.fields_by_name['channel_num']._options = None
_CHANNELSETTINGS.fields_by_name['channel_num']._serialized_options = b'\030\001'
_CHANNELSETTINGS._serialized_start=59
_CHANNELSETTINGS._serialized_end=270
_MODULESETTINGS._serialized_start=272
_MODULESETTINGS._serialized_end=334
_CHANNEL._serialized_start=337
_CHANNEL._serialized_end=516
_CHANNEL_ROLE._serialized_start=468
_CHANNEL_ROLE._serialized_end=516
_CHANNELSETTINGS._serialized_end=252
_MODULESETTINGS._serialized_start=254
_MODULESETTINGS._serialized_end=316
_CHANNEL._serialized_start=319
_CHANNEL._serialized_end=498
_CHANNEL_ROLE._serialized_start=450
_CHANNEL_ROLE._serialized_end=498
# @@protoc_insertion_point(module_scope)
+2 -4
View File
@@ -21,7 +21,7 @@ class Channel(_message.Message):
def __init__(self, index: _Optional[int] = ..., settings: _Optional[_Union[ChannelSettings, _Mapping]] = ..., role: _Optional[_Union[Channel.Role, str]] = ...) -> None: ...
class ChannelSettings(_message.Message):
__slots__ = ["channel_num", "downlink_enabled", "id", "module_settings", "name", "psk", "uplink_enabled", "use_aead"]
__slots__ = ["channel_num", "downlink_enabled", "id", "module_settings", "name", "psk", "uplink_enabled"]
CHANNEL_NUM_FIELD_NUMBER: _ClassVar[int]
DOWNLINK_ENABLED_FIELD_NUMBER: _ClassVar[int]
ID_FIELD_NUMBER: _ClassVar[int]
@@ -29,7 +29,6 @@ class ChannelSettings(_message.Message):
NAME_FIELD_NUMBER: _ClassVar[int]
PSK_FIELD_NUMBER: _ClassVar[int]
UPLINK_ENABLED_FIELD_NUMBER: _ClassVar[int]
USE_AEAD_FIELD_NUMBER: _ClassVar[int]
channel_num: int
downlink_enabled: bool
id: int
@@ -37,8 +36,7 @@ class ChannelSettings(_message.Message):
name: str
psk: bytes
uplink_enabled: bool
use_aead: bool
def __init__(self, channel_num: _Optional[int] = ..., psk: _Optional[bytes] = ..., name: _Optional[str] = ..., id: _Optional[int] = ..., uplink_enabled: bool = ..., downlink_enabled: bool = ..., module_settings: _Optional[_Union[ModuleSettings, _Mapping]] = ..., use_aead: bool = ...) -> None: ...
def __init__(self, channel_num: _Optional[int] = ..., psk: _Optional[bytes] = ..., name: _Optional[str] = ..., id: _Optional[int] = ..., uplink_enabled: bool = ..., downlink_enabled: bool = ..., module_settings: _Optional[_Union[ModuleSettings, _Mapping]] = ...) -> None: ...
class ModuleSettings(_message.Message):
__slots__ = ["is_muted", "position_precision"]
+2 -2
View File
@@ -15,7 +15,7 @@ from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_loc
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\"\xa0\x04\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\x12\x1c\n\x0fis_unmessagable\x18\t \x01(\x08H\x08\x88\x01\x01\x12\x18\n\x0bis_licensed\x18\n \x01(\x08H\t\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_messagesB\x12\n\x10_is_unmessagableB\x0e\n\x0c_is_licensedBf\n\x14org.meshtastic.protoB\x10\x43lientOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
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')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.clientonly_pb2', globals())
@@ -24,5 +24,5 @@ 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'
_DEVICEPROFILE._serialized_start=131
_DEVICEPROFILE._serialized_end=675
_DEVICEPROFILE._serialized_end=583
# @@protoc_insertion_point(module_scope)
+2 -6
View File
@@ -7,13 +7,11 @@ from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Opti
DESCRIPTOR: _descriptor.FileDescriptor
class DeviceProfile(_message.Message):
__slots__ = ["canned_messages", "channel_url", "config", "fixed_position", "is_licensed", "is_unmessagable", "long_name", "module_config", "ringtone", "short_name"]
__slots__ = ["canned_messages", "channel_url", "config", "fixed_position", "long_name", "module_config", "ringtone", "short_name"]
CANNED_MESSAGES_FIELD_NUMBER: _ClassVar[int]
CHANNEL_URL_FIELD_NUMBER: _ClassVar[int]
CONFIG_FIELD_NUMBER: _ClassVar[int]
FIXED_POSITION_FIELD_NUMBER: _ClassVar[int]
IS_LICENSED_FIELD_NUMBER: _ClassVar[int]
IS_UNMESSAGABLE_FIELD_NUMBER: _ClassVar[int]
LONG_NAME_FIELD_NUMBER: _ClassVar[int]
MODULE_CONFIG_FIELD_NUMBER: _ClassVar[int]
RINGTONE_FIELD_NUMBER: _ClassVar[int]
@@ -22,10 +20,8 @@ class DeviceProfile(_message.Message):
channel_url: str
config: _localonly_pb2.LocalConfig
fixed_position: _mesh_pb2.Position
is_licensed: bool
is_unmessagable: bool
long_name: str
module_config: _localonly_pb2.LocalModuleConfig
ringtone: str
short_name: str
def __init__(self, long_name: _Optional[str] = ..., short_name: _Optional[str] = ..., channel_url: _Optional[str] = ..., config: _Optional[_Union[_localonly_pb2.LocalConfig, _Mapping]] = ..., module_config: _Optional[_Union[_localonly_pb2.LocalModuleConfig, _Mapping]] = ..., fixed_position: _Optional[_Union[_mesh_pb2.Position, _Mapping]] = ..., ringtone: _Optional[str] = ..., canned_messages: _Optional[str] = ..., is_unmessagable: bool = ..., is_licensed: bool = ...) -> None: ...
def __init__(self, long_name: _Optional[str] = ..., short_name: _Optional[str] = ..., channel_url: _Optional[str] = ..., config: _Optional[_Union[_localonly_pb2.LocalConfig, _Mapping]] = ..., module_config: _Optional[_Union[_localonly_pb2.LocalModuleConfig, _Mapping]] = ..., fixed_position: _Optional[_Union[_mesh_pb2.Position, _Mapping]] = ..., ringtone: _Optional[str] = ..., canned_messages: _Optional[str] = ...) -> None: ...
+61 -446
View File
@@ -12,10 +12,9 @@ _sym_db = _symbol_database.Default()
from meshtastic.protobuf import device_ui_pb2 as meshtastic_dot_protobuf_dot_device__ui__pb2
from meshtastic.protobuf import field_metadata_pb2 as meshtastic_dot_protobuf_dot_field__metadata__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/protobuf/config.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/device_ui.proto\x1a(meshtastic/protobuf/field_metadata.proto\"\x93\x86\x01\n\x06\x43onfig\x12:\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfigH\x00\x12>\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfigH\x00\x12\x38\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfigH\x00\x12<\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfigH\x00\x12<\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfigH\x00\x12\x36\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfigH\x00\x12@\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfigH\x00\x12>\n\x08security\x18\x08 \x01(\x0b\x32*.meshtastic.protobuf.Config.SecurityConfigH\x00\x12\x42\n\nsessionkey\x18\t \x01(\x0b\x32,.meshtastic.protobuf.Config.SessionkeyConfigH\x00\x12\x38\n\tdevice_ui\x18\n \x01(\x0b\x32#.meshtastic.protobuf.DeviceUIConfigH\x00\x1a\x80\x1f\n\x0c\x44\x65viceConfig\x12N\n\x04role\x18\x01 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.RoleB\x11\xca\xf3\x18\r:\x0b\x44\x65vice Role\x12\x1a\n\x0eserial_enabled\x18\x02 \x01(\x08\x42\x02\x18\x01\x12u\n\x0b\x62utton_gpio\x18\x04 \x01(\rB`\xca\xf3\x18\\:\x0b\x42utton GPIOBMGPIO pin for the user button, can be remapped on boards with multiple buttons\x12\x43\n\x0b\x62uzzer_gpio\x18\x05 \x01(\rB.\xca\xf3\x18*:\x0b\x42uzzer GPIOB\x1bGPIO pin for the PWM buzzer\x12j\n\x10rebroadcast_mode\x18\x06 \x01(\x0e\x32\x38.meshtastic.protobuf.Config.DeviceConfig.RebroadcastModeB\x16\xca\xf3\x18\x12:\x10Rebroadcast Mode\x12\x9a\x01\n\x18node_info_broadcast_secs\x18\x07 \x01(\rBx\xca\xf3\x18t\x19\x00\x00\x00\x00\x00 \xac@*\x01s:\x1cNode Info Broadcast IntervalBHHow often node information is sent. Defaults to 3 hours, minimum 1 hour.\x12\x84\x01\n\x1a\x64ouble_tap_as_button_press\x18\x08 \x01(\x08\x42`\xca\xf3\x18\\:\x14\x44ouble Tap as ButtonBDTreat double tap on supported accelerometers as a user button press.\x12\x16\n\nis_managed\x18\t \x01(\x08\x42\x02\x18\x01\x12i\n\x14\x64isable_triple_click\x18\n \x01(\x08\x42K\xca\xf3\x18G:\x14\x44isable Triple ClickB/Disables the user button triple-press shortcut.\x12@\n\x05tzdef\x18\x0b \x01(\tB1\xca\xf3\x18-:\tTime ZoneB POSIX timezone definition string\x12\xc5\x01\n\x16led_heartbeat_disabled\x18\x0c \x01(\x08\x42\xa4\x01\xca\xf3\x18\x9f\x01:\x15\x44isable LED HeartbeatB\x85\x01Turns off the blinking LED on the device. On most devices this is one of up to 4 LEDs; the charger and GPS LEDs are not controllable.\x12U\n\x0b\x62uzzer_mode\x18\r \x01(\x0e\x32\x33.meshtastic.protobuf.Config.DeviceConfig.BuzzerModeB\x0b\xca\xf3\x18\x07R\x05\x32.7.0\"\xef\x0b\n\x04Role\x12G\n\x06\x43LIENT\x10\x00\x1a;\xca\xf3\x18\x37:\x06\x43lientB-App connected or standalone messaging device.\x12\\\n\x0b\x43LIENT_MUTE\x10\x01\x1aK\xca\xf3\x18G:\x0b\x43lient MuteB8Device that does not forward packets from other devices.\x12\xae\x01\n\x06ROUTER\x10\x02\x1a\xa1\x01\xca\xf3\x18\x9c\x01:\x06RouterB\x91\x01Infrastructure node on a tower or mountain top only. Not to be used for roofs or mobile nodes. Needs exceptional coverage. Visible in Nodes list.\x12(\n\rROUTER_CLIENT\x10\x03\x1a\x15\x08\x01\xca\xf3\x18\x0f:\rRouter Client\x12\xb3\x01\n\x08REPEATER\x10\x04\x1a\xa4\x01\x08\x01\xca\xf3\x18\x9d\x01:\x08RepeaterB\x90\x01\x44\x65precated infrastructure role that creates gaps in the mesh rebroadcast chain. Switch this node to a Router-based role (Router or Router Late).\x12H\n\x07TRACKER\x10\x05\x1a;\xca\xf3\x18\x37:\x07TrackerB,Broadcasts GPS position packets as priority.\x12\x43\n\x06SENSOR\x10\x06\x1a\x37\xca\xf3\x18\x33:\x06SensorB)Broadcasts telemetry packets as priority.\x12X\n\x03TAK\x10\x07\x1aO\xca\xf3\x18K:\x03TAKBDOptimized for ATAK system communication, reduces routine broadcasts.\x12k\n\rCLIENT_HIDDEN\x10\x08\x1aX\xca\xf3\x18T:\rClient HiddenBCDevice that only broadcasts as needed for stealth or power savings.\x12\x85\x01\n\x0eLOST_AND_FOUND\x10\t\x1aq\xca\xf3\x18m:\x0eLost and FoundB[Broadcasts location as message to default channel regularly to assist with device recovery.\x12h\n\x0bTAK_TRACKER\x10\n\x1aW\xca\xf3\x18S:\x0bTAK TrackerBDEnables automatic TAK PLI broadcasts and reduces routine broadcasts.\x12\xbc\x01\n\x0bROUTER_LATE\x10\x0b\x1a\xaa\x01\xca\xf3\x18\xa5\x01:\x0bRouter LateB\x95\x01Infrastructure node that always rebroadcasts packets once but only after all other modes. Visible in Nodes list. Not a good choice for rooftop nodes.\x12\xa7\x01\n\x0b\x43LIENT_BASE\x10\x0c\x1a\x95\x01\xca\xf3\x18\x90\x01:\x0b\x43lient BaseB\x80\x01Rooftop or attic node that rebroadcasts like Router Late for packets from or to favorited nodes, and like Client for all others.\"\xf6\x08\n\x0fRebroadcastMode\x12\x8c\x01\n\x03\x41LL\x10\x00\x1a\x82\x01\xca\xf3\x18~:\x03\x41llBwRebroadcast anLine truncated
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/protobuf/config.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/device_ui.proto\"\xeb-\n\x06\x43onfig\x12:\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfigH\x00\x12>\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfigH\x00\x12\x38\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfigH\x00\x12<\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfigH\x00\x12<\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfigH\x00\x12\x36\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfigH\x00\x12@\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfigH\x00\x12>\n\x08security\x18\x08 \x01(\x0b\x32*.meshtastic.protobuf.Config.SecurityConfigH\x00\x12\x42\n\nsessionkey\x18\t \x01(\x0b\x32,.meshtastic.protobuf.Config.SessionkeyConfigH\x00\x12\x38\n\tdevice_ui\x18\n \x01(\x0b\x32#.meshtastic.protobuf.DeviceUIConfigH\x00\x1a\x91\x07\n\x0c\x44\x65viceConfig\x12;\n\x04role\x18\x01 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x1a\n\x0eserial_enabled\x18\x02 \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0b\x62utton_gpio\x18\x04 \x01(\r\x12\x13\n\x0b\x62uzzer_gpio\x18\x05 \x01(\r\x12R\n\x10rebroadcast_mode\x18\x06 \x01(\x0e\x32\x38.meshtastic.protobuf.Config.DeviceConfig.RebroadcastMode\x12 \n\x18node_info_broadcast_secs\x18\x07 \x01(\r\x12\"\n\x1a\x64ouble_tap_as_button_press\x18\x08 \x01(\x08\x12\x16\n\nis_managed\x18\t \x01(\x08\x42\x02\x18\x01\x12\x1c\n\x14\x64isable_triple_click\x18\n \x01(\x08\x12\r\n\x05tzdef\x18\x0b \x01(\t\x12\x1e\n\x16led_heartbeat_disabled\x18\x0c \x01(\x08\x12H\n\x0b\x62uzzer_mode\x18\r \x01(\x0e\x32\x33.meshtastic.protobuf.Config.DeviceConfig.BuzzerMode\"\xd4\x01\n\x04Role\x12\n\n\x06\x43LIENT\x10\x00\x12\x0f\n\x0b\x43LIENT_MUTE\x10\x01\x12\n\n\x06ROUTER\x10\x02\x12\x15\n\rROUTER_CLIENT\x10\x03\x1a\x02\x08\x01\x12\x10\n\x08REPEATER\x10\x04\x1a\x02\x08\x01\x12\x0b\n\x07TRACKER\x10\x05\x12\n\n\x06SENSOR\x10\x06\x12\x07\n\x03TAK\x10\x07\x12\x11\n\rCLIENT_HIDDEN\x10\x08\x12\x12\n\x0eLOST_AND_FOUND\x10\t\x12\x0f\n\x0bTAK_TRACKER\x10\n\x12\x0f\n\x0bROUTER_LATE\x10\x0b\x12\x0f\n\x0b\x43LIENT_BASE\x10\x0c\"s\n\x0fRebroadcastMode\x12\x07\n\x03\x41LL\x10\x00\x12\x15\n\x11\x41LL_SKIP_DECODING\x10\x01\x12\x0e\n\nLOCAL_ONLY\x10\x02\x12\x0e\n\nKNOWN_ONLY\x10\x03\x12\x08\n\x04NONE\x10\x04\x12\x16\n\x12\x43ORE_PORTNUMS_ONLY\x10\x05\"i\n\nBuzzerMode\x12\x0f\n\x0b\x41LL_ENABLED\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01\x12\x16\n\x12NOTIFICATIONS_ONLY\x10\x02\x12\x0f\n\x0bSYSTEM_ONLY\x10\x03\x12\x13\n\x0f\x44IRECT_MSG_ONLY\x10\x04\x1a\x9a\x05\n\x0ePositionConfig\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12(\n position_broadcast_smart_enabled\x18\x02 \x01(\x08\x12\x16\n\x0e\x66ixed_position\x18\x03 \x01(\x08\x12\x17\n\x0bgps_enabled\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x1b\n\x13gps_update_interval\x18\x05 \x01(\r\x12\x1c\n\x10gps_attempt_time\x18\x06 \x01(\rB\x02\x18\x01\x12\x16\n\x0eposition_flags\x18\x07 \x01(\r\x12\x0f\n\x07rx_gpio\x18\x08 \x01(\r\x12\x0f\n\x07tx_gpio\x18\t \x01(\r\x12(\n broadcast_smart_minimum_distance\x18\n \x01(\r\x12-\n%broadcast_smart_minimum_interval_secs\x18\x0b \x01(\r\x12\x13\n\x0bgps_en_gpio\x18\x0c \x01(\r\x12\x44\n\x08gps_mode\x18\r \x01(\x0e\x32\x32.meshtastic.protobuf.Config.PositionConfig.GpsMode\"\xab\x01\n\rPositionFlags\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x41LTITUDE\x10\x01\x12\x10\n\x0c\x41LTITUDE_MSL\x10\x02\x12\x16\n\x12GEOIDAL_SEPARATION\x10\x04\x12\x07\n\x03\x44OP\x10\x08\x12\t\n\x05HVDOP\x10\x10\x12\r\n\tSATINVIEW\x10 \x12\n\n\x06SEQ_NO\x10@\x12\x0e\n\tTIMESTAMP\x10\x80\x01\x12\x0c\n\x07HEADING\x10\x80\x02\x12\n\n\x05SPEED\x10\x80\x04\"5\n\x07GpsMode\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x12\x0f\n\x0bNOT_PRESENT\x10\x02\x1a\x84\x02\n\x0bPowerConfig\x12\x17\n\x0fis_power_saving\x18\x01 \x01(\x08\x12&\n\x1eon_battery_shutdown_after_secs\x18\x02 \x01(\r\x12\x1f\n\x17\x61\x64\x63_multiplier_override\x18\x03 \x01(\x02\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x10\n\x08sds_secs\x18\x06 \x01(\r\x12\x0f\n\x07ls_secs\x18\x07 \x01(\r\x12\x15\n\rmin_wake_secs\x18\x08 \x01(\r\x12\"\n\x1a\x64\x65vice_battery_ina_address\x18\t \x01(\r\x12\x18\n\x10powermon_enables\x18 \x01(\x04\x1a\xf7\x03\n\rNetworkConfig\x12\x14\n\x0cwifi_enabled\x18\x01 \x01(\x08\x12\x11\n\twifi_ssid\x18\x03 \x01(\t\x12\x10\n\x08wifi_psk\x18\x04 \x01(\t\x12\x12\n\nntp_server\x18\x05 \x01(\t\x12\x13\n\x0b\x65th_enabled\x18\x06 \x01(\x08\x12K\n\x0c\x61\x64\x64ress_mode\x18\x07 \x01(\x0e\x32\x35.meshtastic.protobuf.Config.NetworkConfig.AddressMode\x12I\n\x0bipv4_config\x18\x08 \x01(\x0b\x32\x34.meshtastic.protobuf.Config.NetworkConfig.IpV4Config\x12\x16\n\x0ersyslog_server\x18\t \x01(\t\x12\x19\n\x11\x65nabled_protocols\x18\n \x01(\r\x12\x14\n\x0cipv6_enabled\x18\x0b \x01(\x08\x1a\x46\n\nIpV4Config\x12\n\n\x02ip\xLine truncated
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.config_pb2', globals())
@@ -23,462 +22,78 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\014ConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["CLIENT"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["CLIENT"]._serialized_options = b'\312\363\0307:\006ClientB-App connected or standalone messaging device.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["CLIENT_MUTE"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["CLIENT_MUTE"]._serialized_options = b'\312\363\030G:\013Client MuteB8Device that does not forward packets from other devices.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["ROUTER"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["ROUTER"]._serialized_options = b'\312\363\030\234\001:\006RouterB\221\001Infrastructure node on a tower or mountain top only. Not to be used for roofs or mobile nodes. Needs exceptional coverage. Visible in Nodes list.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["ROUTER_CLIENT"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["ROUTER_CLIENT"]._serialized_options = b'\010\001\312\363\030\017:\rRouter Client'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["ROUTER_CLIENT"]._serialized_options = b'\010\001'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["REPEATER"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["REPEATER"]._serialized_options = b'\010\001\312\363\030\235\001:\010RepeaterB\220\001Deprecated infrastructure role that creates gaps in the mesh rebroadcast chain. Switch this node to a Router-based role (Router or Router Late).'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["TRACKER"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["TRACKER"]._serialized_options = b'\312\363\0307:\007TrackerB,Broadcasts GPS position packets as priority.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["SENSOR"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["SENSOR"]._serialized_options = b'\312\363\0303:\006SensorB)Broadcasts telemetry packets as priority.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["TAK"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["TAK"]._serialized_options = b'\312\363\030K:\003TAKBDOptimized for ATAK system communication, reduces routine broadcasts.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["CLIENT_HIDDEN"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["CLIENT_HIDDEN"]._serialized_options = b'\312\363\030T:\rClient HiddenBCDevice that only broadcasts as needed for stealth or power savings.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["LOST_AND_FOUND"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["LOST_AND_FOUND"]._serialized_options = b'\312\363\030m:\016Lost and FoundB[Broadcasts location as message to default channel regularly to assist with device recovery.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["TAK_TRACKER"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["TAK_TRACKER"]._serialized_options = b'\312\363\030S:\013TAK TrackerBDEnables automatic TAK PLI broadcasts and reduces routine broadcasts.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["ROUTER_LATE"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["ROUTER_LATE"]._serialized_options = b'\312\363\030\245\001:\013Router LateB\225\001Infrastructure node that always rebroadcasts packets once but only after all other modes. Visible in Nodes list. Not a good choice for rooftop nodes.'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["CLIENT_BASE"]._options = None
_CONFIG_DEVICECONFIG_ROLE.values_by_name["CLIENT_BASE"]._serialized_options = b'\312\363\030\220\001:\013Client BaseB\200\001Rooftop or attic node that rebroadcasts like Router Late for packets from or to favorited nodes, and like Client for all others.'
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["ALL"]._options = None
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["ALL"]._serialized_options = b'\312\363\030~:\003AllBwRebroadcast any observed message, if it was on our private channel or from another channel with the same LoRa settings.'
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["ALL_SKIP_DECODING"]._options = None
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["ALL_SKIP_DECODING"]._serialized_options = b'\312\363\030~:\021All Skip DecodingBiBehaves as All. Skipping packet decoding applied only to the Repeater role, which is no longer supported.'
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["LOCAL_ONLY"]._options = None
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["LOCAL_ONLY"]._serialized_options = b'\312\363\030\271\001:\nLocal OnlyB\252\001Ignores observed messages from foreign meshes that are open or those which it cannot decrypt. Only rebroadcasts messages on the node\'s local primary / secondary channels.'
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["KNOWN_ONLY"]._options = None
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["KNOWN_ONLY"]._serialized_options = b'\312\363\030\264\001:\nKnown OnlyB\245\001Ignores observed messages from foreign meshes like Local Only, but takes it a step further by also ignoring messages from nodes not already in the node\'s known list.'
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["NONE"]._options = None
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["NONE"]._serialized_options = b'\312\363\030n:\004NoneBfInhibits all rebroadcasts, like the Client Mute role. Not allowed on the Router and Router Late roles.'
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["CORE_PORTNUMS_ONLY"]._options = None
_CONFIG_DEVICECONFIG_REBROADCASTMODE.values_by_name["CORE_PORTNUMS_ONLY"]._serialized_options = b'\312\363\030\373\001:\022Core Portnums OnlyB\344\001Ignores packets on non-core portnums such as Range Test, PAX Counter and ATAK, and does not rebroadcast them. Core portnums include Text, Position, NodeInfo, Telemetry, Routing, Admin, Waypoint, Traceroute and Store and Forward.'
_CONFIG_DEVICECONFIG.fields_by_name['role']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['role']._serialized_options = b'\312\363\030\r:\013Device Role'
_CONFIG_DEVICECONFIG_ROLE.values_by_name["REPEATER"]._serialized_options = b'\010\001'
_CONFIG_DEVICECONFIG.fields_by_name['serial_enabled']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['serial_enabled']._serialized_options = b'\030\001'
_CONFIG_DEVICECONFIG.fields_by_name['button_gpio']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['button_gpio']._serialized_options = b'\312\363\030\\:\013Button GPIOBMGPIO pin for the user button, can be remapped on boards with multiple buttons'
_CONFIG_DEVICECONFIG.fields_by_name['buzzer_gpio']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['buzzer_gpio']._serialized_options = b'\312\363\030*:\013Buzzer GPIOB\033GPIO pin for the PWM buzzer'
_CONFIG_DEVICECONFIG.fields_by_name['rebroadcast_mode']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['rebroadcast_mode']._serialized_options = b'\312\363\030\022:\020Rebroadcast Mode'
_CONFIG_DEVICECONFIG.fields_by_name['node_info_broadcast_secs']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['node_info_broadcast_secs']._serialized_options = b'\312\363\030t\031\000\000\000\000\000 \254@*\001s:\034Node Info Broadcast IntervalBHHow often node information is sent. Defaults to 3 hours, minimum 1 hour.'
_CONFIG_DEVICECONFIG.fields_by_name['double_tap_as_button_press']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['double_tap_as_button_press']._serialized_options = b'\312\363\030\\:\024Double Tap as ButtonBDTreat double tap on supported accelerometers as a user button press.'
_CONFIG_DEVICECONFIG.fields_by_name['is_managed']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['is_managed']._serialized_options = b'\030\001'
_CONFIG_DEVICECONFIG.fields_by_name['disable_triple_click']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['disable_triple_click']._serialized_options = b'\312\363\030G:\024Disable Triple ClickB/Disables the user button triple-press shortcut.'
_CONFIG_DEVICECONFIG.fields_by_name['tzdef']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['tzdef']._serialized_options = b'\312\363\030-:\tTime ZoneB POSIX timezone definition string'
_CONFIG_DEVICECONFIG.fields_by_name['led_heartbeat_disabled']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['led_heartbeat_disabled']._serialized_options = b'\312\363\030\237\001:\025Disable LED HeartbeatB\205\001Turns off the blinking LED on the device. On most devices this is one of up to 4 LEDs; the charger and GPS LEDs are not controllable.'
_CONFIG_DEVICECONFIG.fields_by_name['buzzer_mode']._options = None
_CONFIG_DEVICECONFIG.fields_by_name['buzzer_mode']._serialized_options = b'\312\363\030\007R\0052.7.0'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["ALTITUDE"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["ALTITUDE"]._serialized_options = b'\312\363\030Q:\010AltitudeBEInclude an altitude value in position reports, when one is available.'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["ALTITUDE_MSL"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["ALTITUDE_MSL"]._serialized_options = b'\312\363\030\034:\032Altitude is Mean Sea Level'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["GEOIDAL_SEPARATION"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["GEOIDAL_SEPARATION"]._serialized_options = b'\312\363\030\035:\033Altitude Geoidal Separation'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["DOP"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["DOP"]._serialized_options = b'\312\363\030H:\003DOPBAInclude the dilution of precision value. PDOP is used by default.'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["HVDOP"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["HVDOP"]._serialized_options = b'\312\363\030Q:\013HDOP / VDOPBBIf DOP is set, send separate HDOP and VDOP values instead of PDOP.'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["SATINVIEW"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["SATINVIEW"]._serialized_options = b'\312\363\030\026:\024Number of satellites'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["SEQ_NO"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["SEQ_NO"]._serialized_options = b'\312\363\030\021:\017Sequence number'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["TIMESTAMP"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["TIMESTAMP"]._serialized_options = b'\312\363\030\013:\tTimestamp'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["HEADING"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["HEADING"]._serialized_options = b'\312\363\030\021:\017Vehicle heading'
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["SPEED"]._options = None
_CONFIG_POSITIONCONFIG_POSITIONFLAGS.values_by_name["SPEED"]._serialized_options = b'\312\363\030\017:\rVehicle speed'
_CONFIG_POSITIONCONFIG_GPSMODE.values_by_name["DISABLED"]._options = None
_CONFIG_POSITIONCONFIG_GPSMODE.values_by_name["DISABLED"]._serialized_options = b'\312\363\030\n:\010Disabled'
_CONFIG_POSITIONCONFIG_GPSMODE.values_by_name["ENABLED"]._options = None
_CONFIG_POSITIONCONFIG_GPSMODE.values_by_name["ENABLED"]._serialized_options = b'\312\363\030\t:\007Enabled'
_CONFIG_POSITIONCONFIG_GPSMODE.values_by_name["NOT_PRESENT"]._options = None
_CONFIG_POSITIONCONFIG_GPSMODE.values_by_name["NOT_PRESENT"]._serialized_options = b'\312\363\030\r:\013Not Present'
_CONFIG_POSITIONCONFIG.fields_by_name['position_broadcast_secs']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['position_broadcast_secs']._serialized_options = b'\312\363\030T*\001s:\022Broadcast IntervalB;The longest a node will go without broadcasting a position.'
_CONFIG_POSITIONCONFIG.fields_by_name['position_broadcast_smart_enabled']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['position_broadcast_smart_enabled']._serialized_options = b'\312\363\030\020:\016Smart Position'
_CONFIG_POSITIONCONFIG.fields_by_name['fixed_position']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['fixed_position']._serialized_options = b'\312\363\030\224\001:\016Fixed PositionB\201\001The last known latitude, longitude and altitude are broadcast over the mesh on the position interval, rather than a live GPS fix.'
_CONFIG_POSITIONCONFIG.fields_by_name['gps_enabled']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['gps_enabled']._serialized_options = b'\030\001'
_CONFIG_POSITIONCONFIG.fields_by_name['gps_update_interval']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['gps_update_interval']._serialized_options = b'\312\363\030=*\001s:\017Update IntervalB\'How often to try to get a GPS position.'
_CONFIG_POSITIONCONFIG.fields_by_name['gps_attempt_time']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['gps_attempt_time']._serialized_options = b'\030\001'
_CONFIG_POSITIONCONFIG.fields_by_name['position_flags']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['position_flags']._serialized_options = b'\312\363\030N:\016Position FlagsB<Optional fields to include when assembling position messages'
_CONFIG_POSITIONCONFIG.fields_by_name['rx_gpio']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['rx_gpio']._serialized_options = b'\312\363\030)\010\001:\020GPS Receive GPIOB\023GPIO pin for GPS RX'
_CONFIG_POSITIONCONFIG.fields_by_name['tx_gpio']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['tx_gpio']._serialized_options = b'\312\363\030*\010\001:\021GPS Transmit GPIOB\023GPIO pin for GPS TX'
_CONFIG_POSITIONCONFIG.fields_by_name['broadcast_smart_minimum_distance']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['broadcast_smart_minimum_distance']._serialized_options = b'\312\363\030f*\001m:\020Minimum DistanceBOThe minimum change in distance before a smart position broadcast is considered.'
_CONFIG_POSITIONCONFIG.fields_by_name['broadcast_smart_minimum_interval_secs']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['broadcast_smart_minimum_interval_secs']._serialized_options = b'\312\363\030m*\001s:\020Minimum IntervalBVThe shortest interval between position updates once the minimum distance has been met.'
_CONFIG_POSITIONCONFIG.fields_by_name['gps_en_gpio']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['gps_en_gpio']._serialized_options = b'\312\363\030,\010\001:\017GPS Enable GPIOB\027GPIO pin for GPS enable'
_CONFIG_POSITIONCONFIG.fields_by_name['gps_mode']._options = None
_CONFIG_POSITIONCONFIG.fields_by_name['gps_mode']._serialized_options = b'\312\363\030\n:\010GPS Mode'
_CONFIG_POWERCONFIG.fields_by_name['is_power_saving']._options = None
_CONFIG_POWERCONFIG.fields_by_name['is_power_saving']._serialized_options = b'\312\363\030\366\001:\014Power SavingB\345\001Will sleep everything as much as possible, for the Tracker and Sensor roles this also includes the LoRa radio. Don\'t use this setting if you want to use your device with the phone apps or are using a device without a user button.'
_CONFIG_POWERCONFIG.fields_by_name['on_battery_shutdown_after_secs']._options = None
_CONFIG_POWERCONFIG.fields_by_name['on_battery_shutdown_after_secs']._serialized_options = b'\312\363\030\237\001*\001s:\026Shutdown on Power LossB\201\001How long after external power is removed before the device powers off. Zero to disable; values under 30 seconds are raised to 30.'
_CONFIG_POWERCONFIG.fields_by_name['adc_multiplier_override']._options = None
_CONFIG_POWERCONFIG.fields_by_name['adc_multiplier_override']._serialized_options = b'\312\363\030\016:\014ADC Override'
_CONFIG_POWERCONFIG.fields_by_name['wait_bluetooth_secs']._options = None
_CONFIG_POWERCONFIG.fields_by_name['wait_bluetooth_secs']._serialized_options = b'\312\363\030 *\001s:\033Wait for Bluetooth Duration'
_CONFIG_NETWORKCONFIG_IPV4CONFIG.fields_by_name['ip']._options = None
_CONFIG_NETWORKCONFIG_IPV4CONFIG.fields_by_name['ip']._serialized_options = b'\312\363\030\004:\002IP'
_CONFIG_NETWORKCONFIG_IPV4CONFIG.fields_by_name['gateway']._options = None
_CONFIG_NETWORKCONFIG_IPV4CONFIG.fields_by_name['gateway']._serialized_options = b'\312\363\030\t:\007Gateway'
_CONFIG_NETWORKCONFIG_IPV4CONFIG.fields_by_name['subnet']._options = None
_CONFIG_NETWORKCONFIG_IPV4CONFIG.fields_by_name['subnet']._serialized_options = b'\312\363\030\010:\006Subnet'
_CONFIG_NETWORKCONFIG_IPV4CONFIG.fields_by_name['dns']._options = None
_CONFIG_NETWORKCONFIG_IPV4CONFIG.fields_by_name['dns']._serialized_options = b'\312\363\030\005:\003DNS'
_CONFIG_NETWORKCONFIG_ADDRESSMODE.values_by_name["DHCP"]._options = None
_CONFIG_NETWORKCONFIG_ADDRESSMODE.values_by_name["DHCP"]._serialized_options = b'\312\363\030\006:\004DHCP'
_CONFIG_NETWORKCONFIG_ADDRESSMODE.values_by_name["STATIC"]._options = None
_CONFIG_NETWORKCONFIG_ADDRESSMODE.values_by_name["STATIC"]._serialized_options = b'\312\363\030\010:\006Static'
_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS.values_by_name["NO_BROADCAST"]._options = None
_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS.values_by_name["NO_BROADCAST"]._serialized_options = b'\312\363\030\006:\004None'
_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS.values_by_name["UDP_BROADCAST"]._options = None
_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS.values_by_name["UDP_BROADCAST"]._serialized_options = b'\312\363\030\017:\rUDP Broadcast'
_CONFIG_NETWORKCONFIG.fields_by_name['wifi_enabled']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['wifi_enabled']._serialized_options = b'\312\363\030O:\014WiFi EnabledB?Enabling WiFi will disable the Bluetooth connection to the app.'
_CONFIG_NETWORKCONFIG.fields_by_name['wifi_ssid']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['wifi_ssid']._serialized_options = b'\312\363\030\':\004SSIDB\037WiFi network name to connect to'
_CONFIG_NETWORKCONFIG.fields_by_name['wifi_psk']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['wifi_psk']._serialized_options = b'\312\363\030,:\010PasswordB WiFi password for authentication'
_CONFIG_NETWORKCONFIG.fields_by_name['ntp_server']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['ntp_server']._serialized_options = b'\312\363\030E:\nNTP ServerB7NTP server address. Defaults to meshtastic.pool.ntp.org'
_CONFIG_NETWORKCONFIG.fields_by_name['eth_enabled']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['eth_enabled']._serialized_options = b'\312\363\030h:\020Ethernet EnabledBTOn ESP32 boards, enabling Ethernet will disable the Bluetooth connection to the app.'
_CONFIG_NETWORKCONFIG.fields_by_name['address_mode']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['address_mode']._serialized_options = b'\312\363\030\016:\014Address Mode'
_CONFIG_NETWORKCONFIG.fields_by_name['rsyslog_server']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['rsyslog_server']._serialized_options = b'\312\363\030\020:\016Rsyslog Server'
_CONFIG_NETWORKCONFIG.fields_by_name['enabled_protocols']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['enabled_protocols']._serialized_options = b'\312\363\030W:\021Enabled ProtocolsB;Enable broadcasting packets via UDP over the local network.R\0052.6.0'
_CONFIG_NETWORKCONFIG.fields_by_name['ipv6_enabled']._options = None
_CONFIG_NETWORKCONFIG.fields_by_name['ipv6_enabled']._serialized_options = b'\312\363\030\010R\0062.7.16'
_CONFIG_DISPLAYCONFIG_DISPLAYUNITS.values_by_name["METRIC"]._options = None
_CONFIG_DISPLAYCONFIG_DISPLAYUNITS.values_by_name["METRIC"]._serialized_options = b'\312\363\030\010:\006Metric'
_CONFIG_DISPLAYCONFIG_DISPLAYUNITS.values_by_name["IMPERIAL"]._options = None
_CONFIG_DISPLAYCONFIG_DISPLAYUNITS.values_by_name["IMPERIAL"]._serialized_options = b'\312\363\030\n:\010Imperial'
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_AUTO"]._options = None
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_AUTO"]._serialized_options = b'\312\363\030\026:\024Detect Automatically'
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SSD1306"]._options = None
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SSD1306"]._serialized_options = b'\312\363\030\t:\007SSD1306'
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SH1106"]._options = None
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SH1106"]._serialized_options = b'\312\363\030\010:\006SH1106'
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SH1107"]._options = None
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SH1107"]._serialized_options = b'\312\363\030\010:\006SH1107'
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SH1107_128_128"]._options = None
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SH1107_128_128"]._serialized_options = b'\312\363\030\020:\016SH1107 128x128'
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SH1107_ROTATED"]._options = None
_CONFIG_DISPLAYCONFIG_OLEDTYPE.values_by_name["OLED_SH1107_ROTATED"]._serialized_options = b'\312\363\030\020:\016SH1107 Rotated'
_CONFIG_DISPLAYCONFIG_DISPLAYMODE.values_by_name["DEFAULT"]._options = None
_CONFIG_DISPLAYCONFIG_DISPLAYMODE.values_by_name["DEFAULT"]._serialized_options = b'\312\363\030\036:\034Default 128x64 screen layout'
_CONFIG_DISPLAYCONFIG_DISPLAYMODE.values_by_name["TWOCOLOR"]._options = None
_CONFIG_DISPLAYCONFIG_DISPLAYMODE.values_by_name["TWOCOLOR"]._serialized_options = b'\312\363\030 :\036Optimized for 2 color displays'
_CONFIG_DISPLAYCONFIG_DISPLAYMODE.values_by_name["INVERTED"]._options = None
_CONFIG_DISPLAYCONFIG_DISPLAYMODE.values_by_name["INVERTED"]._serialized_options = b'\312\363\030\':%Inverted top bar for 2 color displays'
_CONFIG_DISPLAYCONFIG_DISPLAYMODE.values_by_name["COLOR"]._options = None
_CONFIG_DISPLAYCONFIG_DISPLAYMODE.values_by_name["COLOR"]._serialized_options = b'\312\363\030\031:\027TFT Full Color Displays'
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_0"]._options = None
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_0"]._serialized_options = b'\312\363\030\005:\0030\302\260'
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_90"]._options = None
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_90"]._serialized_options = b'\312\363\030\006:\00490\302\260'
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_180"]._options = None
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_180"]._serialized_options = b'\312\363\030\007:\005180\302\260'
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_270"]._options = None
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_270"]._serialized_options = b'\312\363\030\007:\005270\302\260'
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_0_INVERTED"]._options = None
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_0_INVERTED"]._serialized_options = b'\312\363\030\016:\0140\302\260 Inverted'
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_90_INVERTED"]._options = None
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_90_INVERTED"]._serialized_options = b'\312\363\030\017:\r90\302\260 Inverted'
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_180_INVERTED"]._options = None
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_180_INVERTED"]._serialized_options = b'\312\363\030\020:\016180\302\260 Inverted'
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_270_INVERTED"]._options = None
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION.values_by_name["DEGREES_270_INVERTED"]._serialized_options = b'\312\363\030\020:\016270\302\260 Inverted'
_CONFIG_DISPLAYCONFIG.fields_by_name['screen_on_secs']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['screen_on_secs']._serialized_options = b'\312\363\030m*\001s:\rScreen on forBYHow long the screen remains on after the user button is pressed or messages are received.'
_CONFIG_DISPLAYCONFIG.fields_by_name['gps_format']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['gps_format']._serialized_options = b'\030\001\312\363\030\010Z\0062.7.10'
_CONFIG_DISPLAYCONFIG.fields_by_name['auto_screen_carousel_secs']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['auto_screen_carousel_secs']._serialized_options = b'\312\363\030g*\001s:\021Carousel IntervalBOAutomatically moves to the next screen page, like a carousel, on this interval.'
_CONFIG_DISPLAYCONFIG.fields_by_name['gps_format']._serialized_options = b'\030\001'
_CONFIG_DISPLAYCONFIG.fields_by_name['compass_north_top']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['compass_north_top']._serialized_options = b'\030\001\312\363\030m:\022Always point northBPThe compass heading on the screen outside of the circle will always point north.Z\0052.7.1'
_CONFIG_DISPLAYCONFIG.fields_by_name['flip_screen']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['flip_screen']._serialized_options = b'\312\363\030%:\013Flip ScreenB\026Flip screen vertically'
_CONFIG_DISPLAYCONFIG.fields_by_name['units']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['units']._serialized_options = b'\312\363\0302:\rDisplay UnitsB!Units shown on the device screen.'
_CONFIG_DISPLAYCONFIG.fields_by_name['oled']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['oled']._serialized_options = b'\312\363\0306:\tOLED TypeB)Override automatic OLED screen detection.'
_CONFIG_DISPLAYCONFIG.fields_by_name['displaymode']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['displaymode']._serialized_options = b'\312\363\030/:\014Display ModeB\037Override default screen layout.'
_CONFIG_DISPLAYCONFIG.fields_by_name['heading_bold']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['heading_bold']._serialized_options = b'\312\363\0304:\014Bold HeadingB$Bold the heading text on the screen.'
_CONFIG_DISPLAYCONFIG.fields_by_name['wake_on_tap_or_motion']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['wake_on_tap_or_motion']._serialized_options = b'\312\363\030W:\034Wake Screen on tap or motionB7Requires that there be an accelerometer on your device.'
_CONFIG_DISPLAYCONFIG.fields_by_name['compass_orientation']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['compass_orientation']._serialized_options = b'\312\363\030a:\023Compass OrientationBJIndicates how to rotate or invert the compass output for accurate display.'
_CONFIG_DISPLAYCONFIG.fields_by_name['use_12h_clock']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['use_12h_clock']._serialized_options = b'\312\363\030A:\r12 Hour ClockB(Sets the screen clock format to 12-hour.R\0062.5.22'
_CONFIG_DISPLAYCONFIG.fields_by_name['use_long_node_name']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['use_long_node_name']._serialized_options = b'\312\363\030\010R\0062.7.13'
_CONFIG_DISPLAYCONFIG.fields_by_name['enable_message_bubbles']._options = None
_CONFIG_DISPLAYCONFIG.fields_by_name['enable_message_bubbles']._serialized_options = b'\312\363\030\010R\0062.7.19'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["UNSET"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["UNSET"]._serialized_options = b'\312\363\030\025:\023Please set a region'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["US"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["US"]._serialized_options = b'\312\363\030\017:\rUnited States'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_433"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_433"]._serialized_options = b'\312\363\030\027:\025European Union 433MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_868"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_868"]._serialized_options = b'\312\363\030\027:\025European Union 868MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["CN"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["CN"]._serialized_options = b'\312\363\030\007:\005China'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["JP"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["JP"]._serialized_options = b'\312\363\030\007:\005Japan'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ANZ"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ANZ"]._serialized_options = b'\312\363\030\031:\027Australia / New Zealand'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["KR"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["KR"]._serialized_options = b'\312\363\030\007:\005Korea'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["TW"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["TW"]._serialized_options = b'\312\363\030\010:\006Taiwan'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["RU"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["RU"]._serialized_options = b'\312\363\030\010:\006Russia'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["IN"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["IN"]._serialized_options = b'\312\363\030\007:\005India'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["NZ_865"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["NZ_865"]._serialized_options = b'\312\363\030\024:\022New Zealand 865MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["TH"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["TH"]._serialized_options = b'\312\363\030\n:\010Thailand'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["LORA_24"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["LORA_24"]._serialized_options = b'\312\363\030\t:\0072.4 GHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["UA_433"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["UA_433"]._serialized_options = b'\312\363\030\020:\016Ukraine 433MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["UA_868"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["UA_868"]._serialized_options = b'\010\001\312\363\030\020:\016Ukraine 868MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["MY_433"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["MY_433"]._serialized_options = b'\312\363\030\021:\017Malaysia 433MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["MY_919"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["MY_919"]._serialized_options = b'\312\363\030\021:\017Malaysia 919MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["SG_923"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["SG_923"]._serialized_options = b'\312\363\030\022:\020Singapore 923MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["PH_433"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["PH_433"]._serialized_options = b'\312\363\030\024:\022Philippines 433MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["PH_868"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["PH_868"]._serialized_options = b'\312\363\030\024:\022Philippines 868MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["PH_915"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["PH_915"]._serialized_options = b'\312\363\030\024:\022Philippines 915MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ANZ_433"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ANZ_433"]._serialized_options = b'\312\363\030 :\036Australia / New Zealand 433MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["KZ_433"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["KZ_433"]._serialized_options = b'\312\363\030\023:\021Kazakhstan 433MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["KZ_863"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["KZ_863"]._serialized_options = b'\312\363\030\023:\021Kazakhstan 863MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["NP_865"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["NP_865"]._serialized_options = b'\312\363\030\016:\014Nepal 865MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["BR_902"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["BR_902"]._serialized_options = b'\312\363\030\017:\rBrazil 902MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU1_2M"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU1_2M"]._serialized_options = b'\312\363\030\033:\031ITU Region 1 / Amateur 2m'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU2_2M"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU2_2M"]._serialized_options = b'\312\363\030\033:\031ITU Region 2 / Amateur 2m'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_866"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_866"]._serialized_options = b'\312\363\030\027:\025European Union 866MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_874"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_874"]._serialized_options = b'\312\363\030\027:\025European Union 874MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_917"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_917"]._serialized_options = b'\312\363\030\027:\025European Union 917MHz'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_N_868"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["EU_N_868"]._serialized_options = b'\312\363\030 :\036European Union 868MHz (Narrow)'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU3_2M"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU3_2M"]._serialized_options = b'\312\363\030\033:\031ITU Region 3 / Amateur 2m'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU1_70CM"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU1_70CM"]._serialized_options = b'\312\363\030\035:\033ITU Region 1 / Amateur 70cm'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU2_70CM"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU2_70CM"]._serialized_options = b'\312\363\030\035:\033ITU Region 2 / Amateur 70cm'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU3_70CM"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU3_70CM"]._serialized_options = b'\312\363\030\035:\033ITU Region 3 / Amateur 70cm'
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU2_125CM"]._options = None
_CONFIG_LORACONFIG_REGIONCODE.values_by_name["ITU2_125CM"]._serialized_options = b'\312\363\030\036:\034ITU Region 2 / Amateur 1.25m'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_FAST"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_FAST"]._serialized_options = b'\312\363\030%:\021Long Range - FastJ\020longfast|default'
_CONFIG_DISPLAYCONFIG.fields_by_name['compass_north_top']._serialized_options = b'\030\001'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_SLOW"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_SLOW"]._serialized_options = b'\010\001\312\363\030\023:\021Long Range - Slow'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_SLOW"]._serialized_options = b'\010\001'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["VERY_LONG_SLOW"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["VERY_LONG_SLOW"]._serialized_options = b'\010\001\312\363\030\030:\026Very Long Range - Slow'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["MEDIUM_SLOW"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["MEDIUM_SLOW"]._serialized_options = b'\312\363\030\025:\023Medium Range - Slow'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["MEDIUM_FAST"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["MEDIUM_FAST"]._serialized_options = b'\312\363\030\025:\023Medium Range - Fast'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["SHORT_SLOW"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["SHORT_SLOW"]._serialized_options = b'\312\363\030\024:\022Short Range - Slow'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["SHORT_FAST"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["SHORT_FAST"]._serialized_options = b'\312\363\030\024:\022Short Range - Fast'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_MODERATE"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_MODERATE"]._serialized_options = b'\312\363\030\027:\025Long Range - Moderate'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["SHORT_TURBO"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["SHORT_TURBO"]._serialized_options = b'\312\363\030\025:\023Short Range - Turbo'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_TURBO"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LONG_TURBO"]._serialized_options = b'\312\363\030\024:\022Long Range - Turbo'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LITE_FAST"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LITE_FAST"]._serialized_options = b'\312\363\030\r:\013Lite - Fast'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LITE_SLOW"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["LITE_SLOW"]._serialized_options = b'\312\363\030\r:\013Lite - Slow'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["NARROW_FAST"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["NARROW_FAST"]._serialized_options = b'\312\363\030\017:\rNarrow - Fast'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["NARROW_SLOW"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["NARROW_SLOW"]._serialized_options = b'\312\363\030\017:\rNarrow - Slow'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["TINY_FAST"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["TINY_FAST"]._serialized_options = b'\312\363\030\r:\013Tiny - Fast'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["TINY_SLOW"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["TINY_SLOW"]._serialized_options = b'\312\363\030\r:\013Tiny - Slow'
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["MEDIUM_TURBO"]._options = None
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["MEDIUM_TURBO"]._serialized_options = b'\312\363\030\026:\024Medium Range - Turbo'
_CONFIG_LORACONFIG.fields_by_name['use_preset']._options = None
_CONFIG_LORACONFIG.fields_by_name['use_preset']._serialized_options = b'\312\363\030h:\nUse PresetBZUse the modem preset settings instead of a manual bandwidth, spread factor and coding rate'
_CONFIG_LORACONFIG.fields_by_name['modem_preset']._options = None
_CONFIG_LORACONFIG.fields_by_name['modem_preset']._serialized_options = b'\312\363\030\t:\007Presets'
_CONFIG_LORACONFIG.fields_by_name['bandwidth']._options = None
_CONFIG_LORACONFIG.fields_by_name['bandwidth']._serialized_options = b'\312\363\030\020*\003kHz:\tBandwidth'
_CONFIG_LORACONFIG.fields_by_name['spread_factor']._options = None
_CONFIG_LORACONFIG.fields_by_name['spread_factor']._serialized_options = b'\312\363\030Z\031\000\000\000\000\000\000\024@!\000\000\000\000\000\000(@:\rSpread FactorB7Number of chirps per symbol, as 2 raised to this value.'
_CONFIG_LORACONFIG.fields_by_name['coding_rate']._options = None
_CONFIG_LORACONFIG.fields_by_name['coding_rate']._serialized_options = b'\312\363\030\210\001:\013Coding RateByError-correction redundancy, as the denominator of 4/n. Higher values survive noisier links but make every packet longer.'
_CONFIG_LORACONFIG.fields_by_name['region']._options = None
_CONFIG_LORACONFIG.fields_by_name['region']._serialized_options = b'\312\363\0309:\006RegionB/The region where you will be using your radios.'
_CONFIG_LORACONFIG.fields_by_name['hop_limit']._options = None
_CONFIG_LORACONFIG.fields_by_name['hop_limit']._serialized_options = b'\312\363\030\204\001\031\000\000\000\000\000\000\000\000!\000\000\000\000\000\000\034@:\tHop LimitBIHow many times a message may be repeated before it stops being forwarded.J\032hops|ttl|range|rebroadcast'
_CONFIG_LORACONFIG.fields_by_name['tx_enabled']._options = None
_CONFIG_LORACONFIG.fields_by_name['tx_enabled']._serialized_options = b'\312\363\030l:\020Transmit EnabledBXAllow the LoRa radio to transmit. Turn off while hot-swapping antennas or bench testing.'
_CONFIG_LORACONFIG.fields_by_name['tx_power']._options = None
_CONFIG_LORACONFIG.fields_by_name['tx_power']._serialized_options = b'\312\363\030\266\001\031\000\000\000\000\000\000\000\000!\000\000\000\000\000\000B@*\003dBm:\016Transmit PowerBxRadio transmit power. Leave at zero to use the highest level legal for the region, which is what most radios should use.J\023tx|power|dbm|output'
_CONFIG_LORACONFIG.fields_by_name['channel_num']._options = None
_CONFIG_LORACONFIG.fields_by_name['channel_num']._serialized_options = b'\312\363\030\275\001:\016Frequency SlotB\252\001Your node\'s operating frequency is calculated based on the region, modem preset, and this field. When 0, the region picks the slot, usually from the primary channel name.'
_CONFIG_LORACONFIG.fields_by_name['override_duty_cycle']._options = None
_CONFIG_LORACONFIG.fields_by_name['override_duty_cycle']._serialized_options = b'\312\363\030\025:\023Override Duty Cycle'
_CONFIG_LORACONFIG.fields_by_name['sx126x_rx_boosted_gain']._options = None
_CONFIG_LORACONFIG.fields_by_name['sx126x_rx_boosted_gain']._serialized_options = b'\312\363\030F:\017RX Boosted GainB3Enable RX boosted gain mode on SX126x-based radios.'
_CONFIG_LORACONFIG.fields_by_name['override_frequency']._options = None
_CONFIG_LORACONFIG.fields_by_name['override_frequency']._serialized_options = b'\312\363\030\031*\003MHz:\022Frequency Override'
_CONFIG_LORACONFIG.fields_by_name['pa_fan_disabled']._options = None
_CONFIG_LORACONFIG.fields_by_name['pa_fan_disabled']._serialized_options = b'\312\363\030\021:\017PA Fan Disabled'
_CONFIG_LORACONFIG.fields_by_name['ignore_incoming']._options = None
_CONFIG_LORACONFIG.fields_by_name['ignore_incoming']._serialized_options = b'\312\363\030\021:\017Ignore Incoming'
_CONFIG_LORACONFIG.fields_by_name['ignore_mqtt']._options = None
_CONFIG_LORACONFIG.fields_by_name['ignore_mqtt']._serialized_options = b'\312\363\030`:\013Ignore MQTTBQIgnore packets received over LoRa that travelled via MQTT anywhere on their path.'
_CONFIG_LORACONFIG.fields_by_name['config_ok_to_mqtt']._options = None
_CONFIG_LORACONFIG.fields_by_name['config_ok_to_mqtt']._serialized_options = b'\312\363\030\014:\nOK to MQTT'
_CONFIG_LORACONFIG.fields_by_name['fem_lna_mode']._options = None
_CONFIG_LORACONFIG.fields_by_name['fem_lna_mode']._serialized_options = b'\312\363\030\010R\0062.7.20'
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE.values_by_name["RANDOM_PIN"]._options = None
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE.values_by_name["RANDOM_PIN"]._serialized_options = b'\312\363\030\014:\nRandom PIN'
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE.values_by_name["FIXED_PIN"]._options = None
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE.values_by_name["FIXED_PIN"]._serialized_options = b'\312\363\030\013:\tFixed PIN'
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE.values_by_name["NO_PIN"]._options = None
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE.values_by_name["NO_PIN"]._serialized_options = b'\312\363\030\025:\023No PIN (Just Works)'
_CONFIG_BLUETOOTHCONFIG.fields_by_name['enabled']._options = None
_CONFIG_BLUETOOTHCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\0303:\021Bluetooth EnabledB\036Enable Bluetooth on the device'
_CONFIG_BLUETOOTHCONFIG.fields_by_name['mode']._options = None
_CONFIG_BLUETOOTHCONFIG.fields_by_name['mode']._serialized_options = b'\312\363\030*:\014Pairing ModeB\032Bluetooth pairing strategy'
_CONFIG_BLUETOOTHCONFIG.fields_by_name['fixed_pin']._options = None
_CONFIG_BLUETOOTHCONFIG.fields_by_name['fixed_pin']._serialized_options = b'\312\363\030X:\tFixed PinBKFixed PIN for Bluetooth pairing. Used when pairing mode is set to fixed PIN'
_CONFIG_SECURITYCONFIG_PACKETSIGNATUREPOLICY.values_by_name["PACKET_SIGNATURE_POLICY_COMPATIBLE"]._options = None
_CONFIG_SECURITYCONFIG_PACKETSIGNATUREPOLICY.values_by_name["PACKET_SIGNATURE_POLICY_COMPATIBLE"]._serialized_options = b'\312\363\030\227\001:\034Compatible - Accept UnsignedBwAccept unsigned traffic for maximum compatibility. A signature that can be checked and is wrong still drops the packet.'
_CONFIG_SECURITYCONFIG_PACKETSIGNATUREPOLICY.values_by_name["PACKET_SIGNATURE_POLICY_BALANCED"]._options = None
_CONFIG_SECURITYCONFIG_PACKETSIGNATUREPOLICY.values_by_name["PACKET_SIGNATURE_POLICY_BALANCED"]._serialized_options = b'\312\363\030\200\001:\037Balanced - Prefer AuthenticatedB]Prefer authenticated packets, but still accept unsigned traffic from nodes not known to sign.'
_CONFIG_SECURITYCONFIG_PACKETSIGNATUREPOLICY.values_by_name["PACKET_SIGNATURE_POLICY_STRICT"]._options = None
_CONFIG_SECURITYCONFIG_PACKETSIGNATUREPOLICY.values_by_name["PACKET_SIGNATURE_POLICY_STRICT"]._serialized_options = b'\312\363\030\227\001:\037Strict - Require AuthenticationBtAccept only packets with a verified signature or successful PKI decryption. Packets from older nodes may be ignored.'
_CONFIG_SECURITYCONFIG.fields_by_name['public_key']._options = None
_CONFIG_SECURITYCONFIG.fields_by_name['public_key']._serialized_options = b'\312\363\030\202\001:\nPublic KeyBtGenerated from your private key and sent out to other nodes on the mesh to allow them to compute a shared secret key'
_CONFIG_SECURITYCONFIG.fields_by_name['private_key']._options = None
_CONFIG_SECURITYCONFIG.fields_by_name['private_key']._serialized_options = b'\312\363\030?:\013Private KeyB0Used to create a shared key with a remote device'
_CONFIG_SECURITYCONFIG.fields_by_name['admin_key']._options = None
_CONFIG_SECURITYCONFIG.fields_by_name['admin_key']._serialized_options = b'\312\363\030V:\tAdmin KeyBIPublic keys (up to three) authorized to send admin messages to this node.'
_CONFIG_SECURITYCONFIG.fields_by_name['is_managed']._options = None
_CONFIG_SECURITYCONFIG.fields_by_name['is_managed']._serialized_options = b'\312\363\030\210\001:\016Managed DeviceBvSettings are changed by a mesh administrator using an admin key, not from the local app. Needs at least one admin key.'
_CONFIG_SECURITYCONFIG.fields_by_name['serial_enabled']._options = None
_CONFIG_SECURITYCONFIG.fields_by_name['serial_enabled']._serialized_options = b'\312\363\0305:\016Serial ConsoleB#Serial Console over the Stream API.'
_CONFIG_SECURITYCONFIG.fields_by_name['debug_log_api_enabled']._options = None
_CONFIG_SECURITYCONFIG.fields_by_name['debug_log_api_enabled']._serialized_options = b'\312\363\030r:\nDebug LogsBdOutput live debug logging over serial, view and export position-redacted device logs over Bluetooth.'
_CONFIG_SECURITYCONFIG.fields_by_name['packet_signature_policy']._options = None
_CONFIG_SECURITYCONFIG.fields_by_name['packet_signature_policy']._serialized_options = b'\312\363\030\007R\0052.8.0'
_CONFIG._serialized_start=138
_CONFIG._serialized_end=17309
_CONFIG_DEVICECONFIG._serialized_start=767
_CONFIG_DEVICECONFIG._serialized_end=4735
_CONFIG_DEVICECONFIG_ROLE._serialized_start=1964
_CONFIG_DEVICECONFIG_ROLE._serialized_end=3483
_CONFIG_DEVICECONFIG_REBROADCASTMODE._serialized_start=3486
_CONFIG_DEVICECONFIG_REBROADCASTMODE._serialized_end=4628
_CONFIG_DEVICECONFIG_BUZZERMODE._serialized_start=4630
_CONFIG_DEVICECONFIG_BUZZERMODE._serialized_end=4735
_CONFIG_POSITIONCONFIG._serialized_start=4738
_CONFIG_POSITIONCONFIG._serialized_end=6693
_CONFIG_POSITIONCONFIG_POSITIONFLAGS._serialized_start=5984
_CONFIG_POSITIONCONFIG_POSITIONFLAGS._serialized_end=6588
_CONFIG_POSITIONCONFIG_GPSMODE._serialized_start=6590
_CONFIG_POSITIONCONFIG_GPSMODE._serialized_end=6693
_CONFIG_POWERCONFIG._serialized_start=6696
_CONFIG_POWERCONFIG._serialized_end=7437
_CONFIG_NETWORKCONFIG._serialized_start=7440
_CONFIG_NETWORKCONFIG._serialized_end=8567
_CONFIG_NETWORKCONFIG_IPV4CONFIG._serialized_start=8297
_CONFIG_NETWORKCONFIG_IPV4CONFIG._serialized_end=8417
_CONFIG_NETWORKCONFIG_ADDRESSMODE._serialized_start=8419
_CONFIG_NETWORKCONFIG_ADDRESSMODE._serialized_end=8480
_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS._serialized_start=8482
_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS._serialized_end=8567
_CONFIG_DISPLAYCONFIG._serialized_start=8570
_CONFIG_DISPLAYCONFIG._serialized_end=11054
_CONFIG_DISPLAYCONFIG_DEPRECATEDGPSCOORDINATEFORMAT._serialized_start=10153
_CONFIG_DISPLAYCONFIG_DEPRECATEDGPSCOORDINATEFORMAT._serialized_end=10196
_CONFIG_DISPLAYCONFIG_DISPLAYUNITS._serialized_start=10198
_CONFIG_DISPLAYCONFIG_DISPLAYUNITS._serialized_end=10268
_CONFIG_DISPLAYCONFIG_OLEDTYPE._serialized_start=10271
_CONFIG_DISPLAYCONFIG_OLEDTYPE._serialized_end=10513
_CONFIG_DISPLAYCONFIG_DISPLAYMODE._serialized_start=10516
_CONFIG_DISPLAYCONFIG_DISPLAYMODE._serialized_end=10731
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION._serialized_start=10734
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION._serialized_end=11054
_CONFIG_LORACONFIG._serialized_start=11057
_CONFIG_LORACONFIG._serialized_end=15305
_CONFIG_LORACONFIG_REGIONCODE._serialized_start=13099
_CONFIG_LORACONFIG_REGIONCODE._serialized_end=14513
_CONFIG_LORACONFIG_MODEMPRESET._serialized_start=14516
_CONFIG_LORACONFIG_MODEMPRESET._serialized_end=15245
_CONFIG_LORACONFIG_FEM_LNA_MODE._serialized_start=15247
_CONFIG_LORACONFIG_FEM_LNA_MODE._serialized_end=15305
_CONFIG_BLUETOOTHCONFIG._serialized_start=15308
_CONFIG_BLUETOOTHCONFIG._serialized_end=15751
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE._serialized_start=15633
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE._serialized_end=15751
_CONFIG_SECURITYCONFIG._serialized_start=15754
_CONFIG_SECURITYCONFIG._serialized_end=17270
_CONFIG_SECURITYCONFIG_PACKETSIGNATUREPOLICY._serialized_start=16676
_CONFIG_SECURITYCONFIG_PACKETSIGNATUREPOLICY._serialized_end=17270
_CONFIG_SESSIONKEYCONFIG._serialized_start=17272
_CONFIG_SESSIONKEYCONFIG._serialized_end=17290
_CONFIG_LORACONFIG_MODEMPRESET.values_by_name["VERY_LONG_SLOW"]._serialized_options = b'\010\001'
_CONFIG._serialized_start=95
_CONFIG._serialized_end=5962
_CONFIG_DEVICECONFIG._serialized_start=724
_CONFIG_DEVICECONFIG._serialized_end=1637
_CONFIG_DEVICECONFIG_ROLE._serialized_start=1201
_CONFIG_DEVICECONFIG_ROLE._serialized_end=1413
_CONFIG_DEVICECONFIG_REBROADCASTMODE._serialized_start=1415
_CONFIG_DEVICECONFIG_REBROADCASTMODE._serialized_end=1530
_CONFIG_DEVICECONFIG_BUZZERMODE._serialized_start=1532
_CONFIG_DEVICECONFIG_BUZZERMODE._serialized_end=1637
_CONFIG_POSITIONCONFIG._serialized_start=1640
_CONFIG_POSITIONCONFIG._serialized_end=2306
_CONFIG_POSITIONCONFIG_POSITIONFLAGS._serialized_start=2080
_CONFIG_POSITIONCONFIG_POSITIONFLAGS._serialized_end=2251
_CONFIG_POSITIONCONFIG_GPSMODE._serialized_start=2253
_CONFIG_POSITIONCONFIG_GPSMODE._serialized_end=2306
_CONFIG_POWERCONFIG._serialized_start=2309
_CONFIG_POWERCONFIG._serialized_end=2569
_CONFIG_NETWORKCONFIG._serialized_start=2572
_CONFIG_NETWORKCONFIG._serialized_end=3075
_CONFIG_NETWORKCONFIG_IPV4CONFIG._serialized_start=2914
_CONFIG_NETWORKCONFIG_IPV4CONFIG._serialized_end=2984
_CONFIG_NETWORKCONFIG_ADDRESSMODE._serialized_start=2986
_CONFIG_NETWORKCONFIG_ADDRESSMODE._serialized_end=3021
_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS._serialized_start=3023
_CONFIG_NETWORKCONFIG_PROTOCOLFLAGS._serialized_end=3075
_CONFIG_DISPLAYCONFIG._serialized_start=3078
_CONFIG_DISPLAYCONFIG._serialized_end=4213
_CONFIG_DISPLAYCONFIG_DEPRECATEDGPSCOORDINATEFORMAT._serialized_start=3743
_CONFIG_DISPLAYCONFIG_DEPRECATEDGPSCOORDINATEFORMAT._serialized_end=3786
_CONFIG_DISPLAYCONFIG_DISPLAYUNITS._serialized_start=3788
_CONFIG_DISPLAYCONFIG_DISPLAYUNITS._serialized_end=3828
_CONFIG_DISPLAYCONFIG_OLEDTYPE._serialized_start=3830
_CONFIG_DISPLAYCONFIG_OLEDTYPE._serialized_end=3957
_CONFIG_DISPLAYCONFIG_DISPLAYMODE._serialized_start=3959
_CONFIG_DISPLAYCONFIG_DISPLAYMODE._serialized_end=4024
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION._serialized_start=4027
_CONFIG_DISPLAYCONFIG_COMPASSORIENTATION._serialized_end=4213
_CONFIG_LORACONFIG._serialized_start=4216
_CONFIG_LORACONFIG._serialized_end=5553
_CONFIG_LORACONFIG_REGIONCODE._serialized_start=4846
_CONFIG_LORACONFIG_REGIONCODE._serialized_end=5237
_CONFIG_LORACONFIG_MODEMPRESET._serialized_start=5240
_CONFIG_LORACONFIG_MODEMPRESET._serialized_end=5493
_CONFIG_LORACONFIG_FEM_LNA_MODE._serialized_start=5495
_CONFIG_LORACONFIG_FEM_LNA_MODE._serialized_end=5553
_CONFIG_BLUETOOTHCONFIG._serialized_start=5556
_CONFIG_BLUETOOTHCONFIG._serialized_end=5738
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE._serialized_start=5682
_CONFIG_BLUETOOTHCONFIG_PAIRINGMODE._serialized_end=5738
_CONFIG_SECURITYCONFIG._serialized_start=5741
_CONFIG_SECURITYCONFIG._serialized_end=5923
_CONFIG_SESSIONKEYCONFIG._serialized_start=5925
_CONFIG_SESSIONKEYCONFIG._serialized_end=5943
# @@protoc_insertion_point(module_scope)
+2 -17
View File
@@ -1,5 +1,4 @@
from meshtastic.protobuf import device_ui_pb2 as _device_ui_pb2
from meshtastic.protobuf import field_metadata_pb2 as _field_metadata_pb2
from google.protobuf.internal import containers as _containers
from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
from google.protobuf import descriptor as _descriptor
@@ -174,12 +173,8 @@ class Config(_message.Message):
IGNORE_MQTT_FIELD_NUMBER: _ClassVar[int]
IN: Config.LoRaConfig.RegionCode
ITU1_2M: Config.LoRaConfig.RegionCode
ITU1_70CM: Config.LoRaConfig.RegionCode
ITU2_125CM: Config.LoRaConfig.RegionCode
ITU2_2M: Config.LoRaConfig.RegionCode
ITU2_70CM: Config.LoRaConfig.RegionCode
ITU3_2M: Config.LoRaConfig.RegionCode
ITU3_70CM: Config.LoRaConfig.RegionCode
JP: Config.LoRaConfig.RegionCode
KR: Config.LoRaConfig.RegionCode
KZ_433: Config.LoRaConfig.RegionCode
@@ -193,7 +188,6 @@ class Config(_message.Message):
LORA_24: Config.LoRaConfig.RegionCode
MEDIUM_FAST: Config.LoRaConfig.ModemPreset
MEDIUM_SLOW: Config.LoRaConfig.ModemPreset
MEDIUM_TURBO: Config.LoRaConfig.ModemPreset
MODEM_PRESET_FIELD_NUMBER: _ClassVar[int]
MY_433: Config.LoRaConfig.RegionCode
MY_919: Config.LoRaConfig.RegionCode
@@ -218,8 +212,6 @@ class Config(_message.Message):
SPREAD_FACTOR_FIELD_NUMBER: _ClassVar[int]
SX126X_RX_BOOSTED_GAIN_FIELD_NUMBER: _ClassVar[int]
TH: Config.LoRaConfig.RegionCode
TINY_FAST: Config.LoRaConfig.ModemPreset
TINY_SLOW: Config.LoRaConfig.ModemPreset
TW: Config.LoRaConfig.RegionCode
TX_ENABLED_FIELD_NUMBER: _ClassVar[int]
TX_POWER_FIELD_NUMBER: _ClassVar[int]
@@ -361,17 +353,11 @@ class Config(_message.Message):
wait_bluetooth_secs: int
def __init__(self, is_power_saving: bool = ..., on_battery_shutdown_after_secs: _Optional[int] = ..., adc_multiplier_override: _Optional[float] = ..., wait_bluetooth_secs: _Optional[int] = ..., sds_secs: _Optional[int] = ..., ls_secs: _Optional[int] = ..., min_wake_secs: _Optional[int] = ..., device_battery_ina_address: _Optional[int] = ..., powermon_enables: _Optional[int] = ...) -> None: ...
class SecurityConfig(_message.Message):
__slots__ = ["admin_channel_enabled", "admin_key", "debug_log_api_enabled", "is_managed", "packet_signature_policy", "private_key", "public_key", "serial_enabled"]
class PacketSignaturePolicy(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
__slots__ = ["admin_channel_enabled", "admin_key", "debug_log_api_enabled", "is_managed", "private_key", "public_key", "serial_enabled"]
ADMIN_CHANNEL_ENABLED_FIELD_NUMBER: _ClassVar[int]
ADMIN_KEY_FIELD_NUMBER: _ClassVar[int]
DEBUG_LOG_API_ENABLED_FIELD_NUMBER: _ClassVar[int]
IS_MANAGED_FIELD_NUMBER: _ClassVar[int]
PACKET_SIGNATURE_POLICY_BALANCED: Config.SecurityConfig.PacketSignaturePolicy
PACKET_SIGNATURE_POLICY_COMPATIBLE: Config.SecurityConfig.PacketSignaturePolicy
PACKET_SIGNATURE_POLICY_FIELD_NUMBER: _ClassVar[int]
PACKET_SIGNATURE_POLICY_STRICT: Config.SecurityConfig.PacketSignaturePolicy
PRIVATE_KEY_FIELD_NUMBER: _ClassVar[int]
PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int]
SERIAL_ENABLED_FIELD_NUMBER: _ClassVar[int]
@@ -379,11 +365,10 @@ class Config(_message.Message):
admin_key: _containers.RepeatedScalarFieldContainer[bytes]
debug_log_api_enabled: bool
is_managed: bool
packet_signature_policy: Config.SecurityConfig.PacketSignaturePolicy
private_key: bytes
public_key: bytes
serial_enabled: bool
def __init__(self, public_key: _Optional[bytes] = ..., private_key: _Optional[bytes] = ..., admin_key: _Optional[_Iterable[bytes]] = ..., is_managed: bool = ..., serial_enabled: bool = ..., debug_log_api_enabled: bool = ..., admin_channel_enabled: bool = ..., packet_signature_policy: _Optional[_Union[Config.SecurityConfig.PacketSignaturePolicy, str]] = ...) -> None: ...
def __init__(self, public_key: _Optional[bytes] = ..., private_key: _Optional[bytes] = ..., admin_key: _Optional[_Iterable[bytes]] = ..., is_managed: bool = ..., serial_enabled: bool = ..., debug_log_api_enabled: bool = ..., admin_channel_enabled: bool = ...) -> None: ...
class SessionkeyConfig(_message.Message):
__slots__ = []
def __init__(self) -> None: ...
+2 -2
View File
@@ -13,7 +13,7 @@ _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*\xe0\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\r\n\tHUNGARIAN\x10\x14\x12\x0f\n\x0b\x41ZERBAIJANI\x10\x15\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')
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')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.device_ui_pb2', globals())
@@ -26,7 +26,7 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_THEME._serialized_start=1342
_THEME._serialized_end=1379
_LANGUAGE._serialized_start=1382
_LANGUAGE._serialized_end=1734
_LANGUAGE._serialized_end=1702
_DEVICEUICONFIG._serialized_start=61
_DEVICEUICONFIG._serialized_end=828
_DEVICEUICONFIG_GPSCOORDINATEFORMAT._serialized_start=742
-2
View File
@@ -3,7 +3,6 @@ from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union
AZERBAIJANI: Language
BULGARIAN: Language
CZECH: Language
DANISH: Language
@@ -18,7 +17,6 @@ FREEZE_HEADING: CompassMode
FRENCH: Language
GERMAN: Language
GREEK: Language
HUNGARIAN: Language
ITALIAN: Language
LIGHT: Theme
NORWEGIAN: Language
@@ -1,33 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/deviceonly_legacy.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.protobuf import deviceonly_pb2 as meshtastic_dot_protobuf_dot_deviceonly__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_legacy.proto\x12\x13meshtastic.protobuf\x1a$meshtastic/protobuf/deviceonly.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a meshtastic/protobuf/nanopb.proto\"\xf7\x02\n\x13NodeInfoLite_Legacy\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\"\x92\x01\n\x13NodeDatabase_Legacy\x12\x0f\n\x07version\x18\x01 \x01(\r\x12j\n\x05nodes\x18\x02 \x03(\x0b\x32(.meshtastic.protobuf.NodeInfoLite_LegacyB1\x92?.\x92\x01+std::vector<meshtastic_NodeInfoLite_Legacy>Bt\n\x14org.meshtastic.protoB\x10\x44\x65viceOnlyLegacyZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x92?\x0b\xc2\x01\x08<vector>b\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.deviceonly_legacy_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\020DeviceOnlyLegacyZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000\222?\013\302\001\010<vector>'
_NODEDATABASE_LEGACY.fields_by_name['nodes']._options = None
_NODEDATABASE_LEGACY.fields_by_name['nodes']._serialized_options = b'\222?.\222\001+std::vector<meshtastic_NodeInfoLite_Legacy>'
_NODEINFOLITE_LEGACY._serialized_start=178
_NODEINFOLITE_LEGACY._serialized_end=553
_NODEDATABASE_LEGACY._serialized_start=556
_NODEDATABASE_LEGACY._serialized_end=702
# @@protoc_insertion_point(module_scope)
@@ -1,47 +0,0 @@
from meshtastic.protobuf import deviceonly_pb2 as _deviceonly_pb2
from meshtastic.protobuf import telemetry_pb2 as _telemetry_pb2
from meshtastic.protobuf import nanopb_pb2 as _nanopb_pb2
from google.protobuf.internal import containers as _containers
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
DESCRIPTOR: _descriptor.FileDescriptor
class NodeDatabase_Legacy(_message.Message):
__slots__ = ["nodes", "version"]
NODES_FIELD_NUMBER: _ClassVar[int]
VERSION_FIELD_NUMBER: _ClassVar[int]
nodes: _containers.RepeatedCompositeFieldContainer[NodeInfoLite_Legacy]
version: int
def __init__(self, version: _Optional[int] = ..., nodes: _Optional[_Iterable[_Union[NodeInfoLite_Legacy, _Mapping]]] = ...) -> None: ...
class NodeInfoLite_Legacy(_message.Message):
__slots__ = ["bitfield", "channel", "device_metrics", "hops_away", "is_favorite", "is_ignored", "last_heard", "next_hop", "num", "position", "snr", "user", "via_mqtt"]
BITFIELD_FIELD_NUMBER: _ClassVar[int]
CHANNEL_FIELD_NUMBER: _ClassVar[int]
DEVICE_METRICS_FIELD_NUMBER: _ClassVar[int]
HOPS_AWAY_FIELD_NUMBER: _ClassVar[int]
IS_FAVORITE_FIELD_NUMBER: _ClassVar[int]
IS_IGNORED_FIELD_NUMBER: _ClassVar[int]
LAST_HEARD_FIELD_NUMBER: _ClassVar[int]
NEXT_HOP_FIELD_NUMBER: _ClassVar[int]
NUM_FIELD_NUMBER: _ClassVar[int]
POSITION_FIELD_NUMBER: _ClassVar[int]
SNR_FIELD_NUMBER: _ClassVar[int]
USER_FIELD_NUMBER: _ClassVar[int]
VIA_MQTT_FIELD_NUMBER: _ClassVar[int]
bitfield: int
channel: int
device_metrics: _telemetry_pb2.DeviceMetrics
hops_away: int
is_favorite: bool
is_ignored: bool
last_heard: int
next_hop: int
num: int
position: _deviceonly_pb2.PositionLite
snr: float
user: _deviceonly_pb2.UserLite
via_mqtt: bool
def __init__(self, num: _Optional[int] = ..., user: _Optional[_Union[_deviceonly_pb2.UserLite, _Mapping]] = ..., position: _Optional[_Union[_deviceonly_pb2.PositionLite, _Mapping]] = ..., snr: _Optional[float] = ..., last_heard: _Optional[int] = ..., device_metrics: _Optional[_Union[_telemetry_pb2.DeviceMetrics, _Mapping]] = ..., channel: _Optional[int] = ..., via_mqtt: bool = ..., hops_away: _Optional[int] = ..., is_favorite: bool = ..., is_ignored: bool = ..., next_hop: _Optional[int] = ..., bitfield: _Optional[int] = ...) -> None: ...
+14 -30
View File
@@ -19,7 +19,7 @@ from meshtastic.protobuf import telemetry_pb2 as meshtastic_dot_protobuf_dot_tel
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\"\xb1\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\x12\x16\n\x0eprecision_bits\x18\x06 \x01(\r\"\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\"\xbc\x03\n\x0cNodeInfoLite\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x0b\n\x03snr\x18\x04 \x01(\x02\x12\x12\n\nlast_heard\x18\x05 \x01(\x07\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\r\x12\x16\n\thops_away\x18\t \x01(\rH\x00\x88\x01\x01\x12\x10\n\x08next_hop\x18\x0c \x01(\r\x12\x10\n\x08\x62itfield\x18\r \x01(\r\x12\x11\n\tlong_name\x18\x0e \x01(\t\x12\x12\n\nshort_name\x18\x0f \x01(\t\x12\x34\n\x08hw_model\x18\x10 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12;\n\x04role\x18\x11 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x12\n\npublic_key\x18\x12 \x01(\x0c\x12\x0e\n\x06snr_q4\x18\x13 \x01(\x11\x42\x0c\n\n_hops_awayJ\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x06\x10\x07J\x04\x08\x08\x10\tJ\x04\x08\n\x10\x0bJ\x04\x08\x0b\x10\x0cR\x04userR\x08positionR\x0e\x64\x65vice_metricsR\x08via_mqttR\x0bis_favoriteR\nis_ignored\"\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\"U\n\x11NodePositionEntry\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x33\n\x08position\x18\x02 \x01(\x0b\x32!.meshtastic.protobuf.PositionLite\"]\n\x12NodeTelemetryEntry\x12\x0b\n\x03num\x18\x01 \x01(\r\x12:\n\x0e\x64\x65vice_metrics\x18\x02 \x01(\x0b\x32\".meshtastic.protobuf.DeviceMetrics\"i\n\x14NodeEnvironmentEntry\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x44\n\x13\x65nvironment_metrics\x18\x02 \x01(\x0b\x32\'.meshtastic.protobuf.EnvironmentMetrics\"R\n\x0fNodeStatusEntry\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x32\n\x06status\x18\x02 \x01(\x0b\x32\".meshtastic.protobuf.StatusMessage\"\xb0\x04\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>\x12j\n\tpositions\x18\x03 \x03(\x0b\x32&.meshtastic.protobuf.NodePositionEntryB/\x92?,\x92\x01)std::vector<meshtastic_NodePositionEntry>\x12l\n\ttelemetry\x18\x04 \x03(\x0b\x32\'.meshtastic.protobuf.NodeTelemetryEntryB0\x92?-\x92\x01*std::vector<meshtastic_NodeTelemetryEntry>\x12\x63\n\x06status\x18\x05 \x03(\x0b\x32$.meshtastic.protobuf.NodeStatusEntryB-\x92?*\x92\x01\'std::vector<meshtastic_NodeStatusEntry>\x12r\n\x0b\x65nvironment\x18\x06 \x03(\x0b\x32).meshtastic.protobuf.NodeEnvironmentEntryB2\x92?/\x92\x01,std::vector<meshtastic_NodeEnvironmentEntry>\"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')
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')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.deviceonly_pb2', globals())
@@ -35,34 +35,18 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_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>'
_NODEDATABASE.fields_by_name['positions']._options = None
_NODEDATABASE.fields_by_name['positions']._serialized_options = b'\222?,\222\001)std::vector<meshtastic_NodePositionEntry>'
_NODEDATABASE.fields_by_name['telemetry']._options = None
_NODEDATABASE.fields_by_name['telemetry']._serialized_options = b'\222?-\222\001*std::vector<meshtastic_NodeTelemetryEntry>'
_NODEDATABASE.fields_by_name['status']._options = None
_NODEDATABASE.fields_by_name['status']._serialized_options = b'\222?*\222\001\'std::vector<meshtastic_NodeStatusEntry>'
_NODEDATABASE.fields_by_name['environment']._options = None
_NODEDATABASE.fields_by_name['environment']._serialized_options = b'\222?/\222\001,std::vector<meshtastic_NodeEnvironmentEntry>'
_POSITIONLITE._serialized_start=271
_POSITIONLITE._serialized_end=448
_USERLITE._serialized_start=451
_USERLITE._serialized_end=727
_NODEINFOLITE._serialized_start=730
_NODEINFOLITE._serialized_end=1174
_DEVICESTATE._serialized_start=1177
_DEVICESTATE._serialized_end=1594
_NODEPOSITIONENTRY._serialized_start=1596
_NODEPOSITIONENTRY._serialized_end=1681
_NODETELEMETRYENTRY._serialized_start=1683
_NODETELEMETRYENTRY._serialized_end=1776
_NODEENVIRONMENTENTRY._serialized_start=1778
_NODEENVIRONMENTENTRY._serialized_end=1883
_NODESTATUSENTRY._serialized_start=1885
_NODESTATUSENTRY._serialized_end=1967
_NODEDATABASE._serialized_start=1970
_NODEDATABASE._serialized_end=2530
_CHANNELFILE._serialized_start=2532
_CHANNELFILE._serialized_end=2610
_BACKUPPREFERENCES._serialized_start=2613
_BACKUPPREFERENCES._serialized_end=2875
_POSITIONLITE._serialized_end=424
_USERLITE._serialized_start=427
_USERLITE._serialized_end=703
_NODEINFOLITE._serialized_start=706
_NODEINFOLITE._serialized_end=1074
_DEVICESTATE._serialized_start=1077
_DEVICESTATE._serialized_end=1494
_NODEDATABASE._serialized_start=1496
_NODEDATABASE._serialized_end=1621
_CHANNELFILE._serialized_start=1623
_CHANNELFILE._serialized_end=1701
_BACKUPPREFERENCES._serialized_start=1704
_BACKUPPREFERENCES._serialized_end=1966
# @@protoc_insertion_point(module_scope)
+18 -60
View File
@@ -58,98 +58,56 @@ class DeviceState(_message.Message):
def __init__(self, my_node: _Optional[_Union[_mesh_pb2.MyNodeInfo, _Mapping]] = ..., owner: _Optional[_Union[_mesh_pb2.User, _Mapping]] = ..., receive_queue: _Optional[_Iterable[_Union[_mesh_pb2.MeshPacket, _Mapping]]] = ..., version: _Optional[int] = ..., rx_text_message: _Optional[_Union[_mesh_pb2.MeshPacket, _Mapping]] = ..., no_save: bool = ..., did_gps_reset: bool = ..., rx_waypoint: _Optional[_Union[_mesh_pb2.MeshPacket, _Mapping]] = ..., node_remote_hardware_pins: _Optional[_Iterable[_Union[_mesh_pb2.NodeRemoteHardwarePin, _Mapping]]] = ...) -> None: ...
class NodeDatabase(_message.Message):
__slots__ = ["environment", "nodes", "positions", "status", "telemetry", "version"]
ENVIRONMENT_FIELD_NUMBER: _ClassVar[int]
__slots__ = ["nodes", "version"]
NODES_FIELD_NUMBER: _ClassVar[int]
POSITIONS_FIELD_NUMBER: _ClassVar[int]
STATUS_FIELD_NUMBER: _ClassVar[int]
TELEMETRY_FIELD_NUMBER: _ClassVar[int]
VERSION_FIELD_NUMBER: _ClassVar[int]
environment: _containers.RepeatedCompositeFieldContainer[NodeEnvironmentEntry]
nodes: _containers.RepeatedCompositeFieldContainer[NodeInfoLite]
positions: _containers.RepeatedCompositeFieldContainer[NodePositionEntry]
status: _containers.RepeatedCompositeFieldContainer[NodeStatusEntry]
telemetry: _containers.RepeatedCompositeFieldContainer[NodeTelemetryEntry]
version: int
def __init__(self, version: _Optional[int] = ..., nodes: _Optional[_Iterable[_Union[NodeInfoLite, _Mapping]]] = ..., positions: _Optional[_Iterable[_Union[NodePositionEntry, _Mapping]]] = ..., telemetry: _Optional[_Iterable[_Union[NodeTelemetryEntry, _Mapping]]] = ..., status: _Optional[_Iterable[_Union[NodeStatusEntry, _Mapping]]] = ..., environment: _Optional[_Iterable[_Union[NodeEnvironmentEntry, _Mapping]]] = ...) -> None: ...
class NodeEnvironmentEntry(_message.Message):
__slots__ = ["environment_metrics", "num"]
ENVIRONMENT_METRICS_FIELD_NUMBER: _ClassVar[int]
NUM_FIELD_NUMBER: _ClassVar[int]
environment_metrics: _telemetry_pb2.EnvironmentMetrics
num: int
def __init__(self, num: _Optional[int] = ..., environment_metrics: _Optional[_Union[_telemetry_pb2.EnvironmentMetrics, _Mapping]] = ...) -> None: ...
def __init__(self, version: _Optional[int] = ..., nodes: _Optional[_Iterable[_Union[NodeInfoLite, _Mapping]]] = ...) -> None: ...
class NodeInfoLite(_message.Message):
__slots__ = ["bitfield", "channel", "hops_away", "hw_model", "last_heard", "long_name", "next_hop", "num", "public_key", "role", "short_name", "snr", "snr_q4"]
__slots__ = ["bitfield", "channel", "device_metrics", "hops_away", "is_favorite", "is_ignored", "last_heard", "next_hop", "num", "position", "snr", "user", "via_mqtt"]
BITFIELD_FIELD_NUMBER: _ClassVar[int]
CHANNEL_FIELD_NUMBER: _ClassVar[int]
DEVICE_METRICS_FIELD_NUMBER: _ClassVar[int]
HOPS_AWAY_FIELD_NUMBER: _ClassVar[int]
HW_MODEL_FIELD_NUMBER: _ClassVar[int]
IS_FAVORITE_FIELD_NUMBER: _ClassVar[int]
IS_IGNORED_FIELD_NUMBER: _ClassVar[int]
LAST_HEARD_FIELD_NUMBER: _ClassVar[int]
LONG_NAME_FIELD_NUMBER: _ClassVar[int]
NEXT_HOP_FIELD_NUMBER: _ClassVar[int]
NUM_FIELD_NUMBER: _ClassVar[int]
PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int]
ROLE_FIELD_NUMBER: _ClassVar[int]
SHORT_NAME_FIELD_NUMBER: _ClassVar[int]
POSITION_FIELD_NUMBER: _ClassVar[int]
SNR_FIELD_NUMBER: _ClassVar[int]
SNR_Q4_FIELD_NUMBER: _ClassVar[int]
USER_FIELD_NUMBER: _ClassVar[int]
VIA_MQTT_FIELD_NUMBER: _ClassVar[int]
bitfield: int
channel: int
device_metrics: _telemetry_pb2.DeviceMetrics
hops_away: int
hw_model: _mesh_pb2.HardwareModel
is_favorite: bool
is_ignored: bool
last_heard: int
long_name: str
next_hop: int
num: int
public_key: bytes
role: _config_pb2.Config.DeviceConfig.Role
short_name: str
snr: float
snr_q4: int
def __init__(self, num: _Optional[int] = ..., snr: _Optional[float] = ..., last_heard: _Optional[int] = ..., channel: _Optional[int] = ..., hops_away: _Optional[int] = ..., next_hop: _Optional[int] = ..., bitfield: _Optional[int] = ..., long_name: _Optional[str] = ..., short_name: _Optional[str] = ..., hw_model: _Optional[_Union[_mesh_pb2.HardwareModel, str]] = ..., role: _Optional[_Union[_config_pb2.Config.DeviceConfig.Role, str]] = ..., public_key: _Optional[bytes] = ..., snr_q4: _Optional[int] = ...) -> None: ...
class NodePositionEntry(_message.Message):
__slots__ = ["num", "position"]
NUM_FIELD_NUMBER: _ClassVar[int]
POSITION_FIELD_NUMBER: _ClassVar[int]
num: int
position: PositionLite
def __init__(self, num: _Optional[int] = ..., position: _Optional[_Union[PositionLite, _Mapping]] = ...) -> None: ...
class NodeStatusEntry(_message.Message):
__slots__ = ["num", "status"]
NUM_FIELD_NUMBER: _ClassVar[int]
STATUS_FIELD_NUMBER: _ClassVar[int]
num: int
status: _mesh_pb2.StatusMessage
def __init__(self, num: _Optional[int] = ..., status: _Optional[_Union[_mesh_pb2.StatusMessage, _Mapping]] = ...) -> None: ...
class NodeTelemetryEntry(_message.Message):
__slots__ = ["device_metrics", "num"]
DEVICE_METRICS_FIELD_NUMBER: _ClassVar[int]
NUM_FIELD_NUMBER: _ClassVar[int]
device_metrics: _telemetry_pb2.DeviceMetrics
num: int
def __init__(self, num: _Optional[int] = ..., device_metrics: _Optional[_Union[_telemetry_pb2.DeviceMetrics, _Mapping]] = ...) -> None: ...
snr: float
user: UserLite
via_mqtt: bool
def __init__(self, num: _Optional[int] = ..., user: _Optional[_Union[UserLite, _Mapping]] = ..., position: _Optional[_Union[PositionLite, _Mapping]] = ..., snr: _Optional[float] = ..., last_heard: _Optional[int] = ..., device_metrics: _Optional[_Union[_telemetry_pb2.DeviceMetrics, _Mapping]] = ..., channel: _Optional[int] = ..., via_mqtt: bool = ..., hops_away: _Optional[int] = ..., is_favorite: bool = ..., is_ignored: bool = ..., next_hop: _Optional[int] = ..., bitfield: _Optional[int] = ...) -> None: ...
class PositionLite(_message.Message):
__slots__ = ["altitude", "latitude_i", "location_source", "longitude_i", "precision_bits", "time"]
__slots__ = ["altitude", "latitude_i", "location_source", "longitude_i", "time"]
ALTITUDE_FIELD_NUMBER: _ClassVar[int]
LATITUDE_I_FIELD_NUMBER: _ClassVar[int]
LOCATION_SOURCE_FIELD_NUMBER: _ClassVar[int]
LONGITUDE_I_FIELD_NUMBER: _ClassVar[int]
PRECISION_BITS_FIELD_NUMBER: _ClassVar[int]
TIME_FIELD_NUMBER: _ClassVar[int]
altitude: int
latitude_i: int
location_source: _mesh_pb2.Position.LocSource
longitude_i: int
precision_bits: int
time: int
def __init__(self, latitude_i: _Optional[int] = ..., longitude_i: _Optional[int] = ..., altitude: _Optional[int] = ..., time: _Optional[int] = ..., location_source: _Optional[_Union[_mesh_pb2.Position.LocSource, str]] = ..., precision_bits: _Optional[int] = ...) -> None: ...
def __init__(self, latitude_i: _Optional[int] = ..., longitude_i: _Optional[int] = ..., altitude: _Optional[int] = ..., time: _Optional[int] = ..., location_source: _Optional[_Union[_mesh_pb2.Position.LocSource, str]] = ...) -> None: ...
class UserLite(_message.Message):
__slots__ = ["hw_model", "is_licensed", "is_unmessagable", "long_name", "macaddr", "public_key", "role", "short_name"]
-29
View File
@@ -1,29 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/field_metadata.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 google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(meshtastic/protobuf/field_metadata.proto\x12\x13meshtastic.protobuf\x1a google/protobuf/descriptor.proto\"\xfc\x01\n\rFieldMetadata\x12\x10\n\x08\x64iy_only\x18\x01 \x01(\x08\x12\x12\n\nadmin_only\x18\x02 \x01(\x08\x12\x11\n\tmin_value\x18\x03 \x01(\x01\x12\x11\n\tmax_value\x18\x04 \x01(\x01\x12\x0c\n\x04unit\x18\x05 \x01(\t\x12\x12\n\ndeprecated\x18\x06 \x01(\x08\x12\r\n\x05label\x18\x07 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x08 \x01(\t\x12\x10\n\x08keywords\x18\t \x01(\t\x12\x16\n\x0esince_firmware\x18\n \x01(\t\x12\x18\n\x10\x64\x65precated_since\x18\x0b \x01(\t\x12\x15\n\roem_fixed_gps\x18\x0c \x01(\x08:[\n\x0e\x66ield_metadata\x12\x1d.google.protobuf.FieldOptions\x18\xb9\x8e\x03 \x01(\x0b\x32\".meshtastic.protobuf.FieldMetadata:d\n\x13\x65num_value_metadata\x12!.google.protobuf.EnumValueOptions\x18\xb9\x8e\x03 \x01(\x0b\x32\".meshtastic.protobuf.FieldMetadataBi\n\x14org.meshtastic.protoB\x13\x46ieldMetadataProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.field_metadata_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(field_metadata)
google_dot_protobuf_dot_descriptor__pb2.EnumValueOptions.RegisterExtension(enum_value_metadata)
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\023FieldMetadataProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_FIELDMETADATA._serialized_start=100
_FIELDMETADATA._serialized_end=352
# @@protoc_insertion_point(module_scope)
@@ -1,38 +0,0 @@
from google.protobuf import descriptor_pb2 as _descriptor_pb2
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Optional as _Optional
DESCRIPTOR: _descriptor.FileDescriptor
ENUM_VALUE_METADATA_FIELD_NUMBER: _ClassVar[int]
FIELD_METADATA_FIELD_NUMBER: _ClassVar[int]
enum_value_metadata: _descriptor.FieldDescriptor
field_metadata: _descriptor.FieldDescriptor
class FieldMetadata(_message.Message):
__slots__ = ["admin_only", "deprecated", "deprecated_since", "description", "diy_only", "keywords", "label", "max_value", "min_value", "oem_fixed_gps", "since_firmware", "unit"]
ADMIN_ONLY_FIELD_NUMBER: _ClassVar[int]
DEPRECATED_FIELD_NUMBER: _ClassVar[int]
DEPRECATED_SINCE_FIELD_NUMBER: _ClassVar[int]
DESCRIPTION_FIELD_NUMBER: _ClassVar[int]
DIY_ONLY_FIELD_NUMBER: _ClassVar[int]
KEYWORDS_FIELD_NUMBER: _ClassVar[int]
LABEL_FIELD_NUMBER: _ClassVar[int]
MAX_VALUE_FIELD_NUMBER: _ClassVar[int]
MIN_VALUE_FIELD_NUMBER: _ClassVar[int]
OEM_FIXED_GPS_FIELD_NUMBER: _ClassVar[int]
SINCE_FIRMWARE_FIELD_NUMBER: _ClassVar[int]
UNIT_FIELD_NUMBER: _ClassVar[int]
admin_only: bool
deprecated: bool
deprecated_since: str
description: str
diy_only: bool
keywords: str
label: str
max_value: float
min_value: float
oem_fixed_gps: bool
since_firmware: str
unit: str
def __init__(self, diy_only: bool = ..., admin_only: bool = ..., min_value: _Optional[float] = ..., max_value: _Optional[float] = ..., unit: _Optional[str] = ..., deprecated: bool = ..., label: _Optional[str] = ..., description: _Optional[str] = ..., keywords: _Optional[str] = ..., since_firmware: _Optional[str] = ..., deprecated_since: _Optional[str] = ..., oem_fixed_gps: bool = ...) -> None: ...
+7 -27
View File
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%meshtastic/protobuf/interdevice.proto\x12\x13meshtastic.protobuf\"\xde\x01\n\x0c\x46ileTransfer\x12\x35\n\toperation\x18\x01 \x01(\x0e\x32\".meshtastic.protobuf.FileOperation\x12\x10\n\x08\x66ilepath\x18\x02 \x01(\t\x12\x10\n\x08\x66iledata\x18\x03 \x01(\x0c\x12/\n\x06status\x18\x04 \x01(\x0e\x32\x1f.meshtastic.protobuf.FileStatus\x12\x0f\n\x07message\x18\x05 \x01(\t\x12\x0e\n\x06offset\x18\x06 \x01(\x04\x12\x0e\n\x06length\x18\x07 \x01(\r\x12\x11\n\tfile_size\x18\x08 \x01(\x04\"\x9f\x01\n\x10\x44irectoryListing\x12\x11\n\tdirectory\x18\x01 \x01(\t\x12\x11\n\tfilenames\x18\x02 \x03(\t\x12/\n\x06status\x18\x03 \x01(\x0e\x32\x1f.meshtastic.protobuf.FileStatus\x12\x0f\n\x07message\x18\x04 \x01(\t\x12\x0e\n\x06offset\x18\x05 \x01(\r\x12\x13\n\x0btotal_count\x18\x06 \x01(\r\"G\n\x0eI2CTransaction\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\r\x12\x12\n\nwrite_data\x18\x02 \x01(\x0c\x12\x10\n\x08read_len\x18\x03 \x01(\r\"\x92\x03\n\nSdCardInfo\x12\x0f\n\x07present\x18\x01 \x01(\x08\x12;\n\tcard_type\x18\x02 \x01(\x0e\x32(.meshtastic.protobuf.SdCardInfo.CardType\x12\x39\n\x08\x66\x61t_type\x18\x03 \x01(\x0e\x32\'.meshtastic.protobuf.SdCardInfo.FatType\x12\x11\n\tcard_size\x18\x04 \x01(\x04\x12\x12\n\nused_bytes\x18\x05 \x01(\x04\x12\x12\n\nfree_bytes\x18\x06 \x01(\x04\x12\x13\n\x0bstats_valid\x18\x07 \x01(\x08\x12\x0c\n\x04\x62usy\x18\x08 \x01(\x08\x12\x13\n\x0bunformatted\x18\t \x01(\x08\"K\n\x08\x43\x61rdType\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03MMC\x10\x01\x12\x06\n\x02SD\x10\x02\x12\x08\n\x04SDHC\x10\x03\x12\x08\n\x04SDXC\x10\x04\x12\x10\n\x0cUNKNOWN_CARD\x10\x05\";\n\x07\x46\x61tType\x12\x0f\n\x0bUNKNOWN_FAT\x10\x00\x12\t\n\x05\x46\x41T16\x10\x01\x12\t\n\x05\x46\x41T32\x10\x02\x12\t\n\x05\x45XFAT\x10\x03\"\xa4\x01\n\tI2CResult\x12\x35\n\x06status\x18\x01 \x01(\x0e\x32%.meshtastic.protobuf.I2CResult.Status\x12\x11\n\tread_data\x18\x02 \x01(\x0c\"M\n\x06Status\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x06\n\x02OK\x10\x01\x12\x10\n\x0cNACK_ADDRESS\x10\x02\x12\r\n\tNACK_DATA\x10\x03\x12\t\n\x05\x45RROR\x10\x04\"\xf0\x04\n\x12InterdeviceMessage\x12\n\n\x02id\x18\x0f \x01(\r\x12\x0e\n\x04nmea\x18\x01 \x01(\tH\x00\x12\x0e\n\x04\x62\x65\x65p\x18\x02 \x01(\rH\x00\x12>\n\x0fi2c_transaction\x18\x03 \x01(\x0b\x32#.meshtastic.protobuf.I2CTransactionH\x00\x12\x34\n\ni2c_result\x18\x04 \x01(\x0b\x32\x1e.meshtastic.protobuf.I2CResultH\x00\x12\x12\n\x08i2c_scan\x18\x05 \x01(\x08H\x00\x12\x19\n\x0fi2c_scan_result\x18\x06 \x01(\x0cH\x00\x12:\n\rfile_transfer\x18\x07 \x01(\x0b\x32!.meshtastic.protobuf.FileTransferH\x00\x12\x42\n\x11\x64irectory_listing\x18\x08 \x01(\x0b\x32%.meshtastic.protobuf.DirectoryListingH\x00\x12\x15\n\x0bget_sd_info\x18\t \x01(\x08H\x00\x12\x32\n\x07sd_info\x18\n \x01(\x0b\x32\x1f.meshtastic.protobuf.SdCardInfoH\x00\x12\x37\n\x04ping\x18\x0b \x01(\x0e\x32\'.meshtastic.protobuf.InterdeviceVersionH\x00\x12\x37\n\x04pong\x18\x0c \x01(\x0e\x32\'.meshtastic.protobuf.InterdeviceVersionH\x00\x12\x0e\n\x04nack\x18\r \x01(\x08H\x00\x12\x34\n\nsd_command\x18\x0e \x01(\x0e\x32\x1e.meshtastic.protobuf.SdCommandH\x00\x42\x06\n\x04\x64\x61ta*Z\n\x12InterdeviceVersion\x12#\n\x1fINTERDEVICE_VERSION_UNSPECIFIED\x10\x00\x12\x1f\n\x1bINTERDEVICE_VERSION_CURRENT\x10\x02*7\n\rFileOperation\x12\x07\n\x03GET\x10\x00\x12\x08\n\x04POST\x10\x01\x12\x07\n\x03PUT\x10\x02\x12\n\n\x06\x44\x45LETE\x10\x03*\xa6\x01\n\nFileStatus\x12\x14\n\x10\x46ILE_UNSPECIFIED\x10\x00\x12\x0b\n\x07\x46ILE_OK\x10\x01\x12\r\n\tFILE_BUSY\x10\x02\x12\x10\n\x0c\x46ILE_NO_CARD\x10\x03\x12\x12\n\x0e\x46ILE_NOT_FOUND\x10\x04\x12\x18\n\x14\x46ILE_OFFSET_CONFLICT\x10\x05\x12\x11\n\rFILE_IO_ERROR\x10\x06\x12\x13\n\x0f\x46ILE_NOT_A_FILE\x10\x07*R\n\tSdCommand\x12\x1a\n\x16SD_COMMAND_UNSPECIFIED\x10\x00\x12\x0c\n\x08SD_MOUNT\x10\x01\x12\x0c\n\x08SD_EJECT\x10\x02\x12\r\n\tSD_FORMAT\x10\x03\x42g\n\x14org.meshtastic.protoB\x11InterdeviceProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
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')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.interdevice_pb2', globals())
@@ -21,30 +21,10 @@ 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'
_INTERDEVICEVERSION._serialized_start=1721
_INTERDEVICEVERSION._serialized_end=1811
_FILEOPERATION._serialized_start=1813
_FILEOPERATION._serialized_end=1868
_FILESTATUS._serialized_start=1871
_FILESTATUS._serialized_end=2037
_SDCOMMAND._serialized_start=2039
_SDCOMMAND._serialized_end=2121
_FILETRANSFER._serialized_start=63
_FILETRANSFER._serialized_end=285
_DIRECTORYLISTING._serialized_start=288
_DIRECTORYLISTING._serialized_end=447
_I2CTRANSACTION._serialized_start=449
_I2CTRANSACTION._serialized_end=520
_SDCARDINFO._serialized_start=523
_SDCARDINFO._serialized_end=925
_SDCARDINFO_CARDTYPE._serialized_start=789
_SDCARDINFO_CARDTYPE._serialized_end=864
_SDCARDINFO_FATTYPE._serialized_start=866
_SDCARDINFO_FATTYPE._serialized_end=925
_I2CRESULT._serialized_start=928
_I2CRESULT._serialized_end=1092
_I2CRESULT_STATUS._serialized_start=1015
_I2CRESULT_STATUS._serialized_end=1092
_INTERDEVICEMESSAGE._serialized_start=1095
_INTERDEVICEMESSAGE._serialized_end=1719
_MESSAGETYPE._serialized_start=277
_MESSAGETYPE._serialized_end=490
_SENSORDATA._serialized_start=62
_SENSORDATA._serialized_end=177
_INTERDEVICEMESSAGE._serialized_start=179
_INTERDEVICEMESSAGE._serialized_end=274
# @@protoc_insertion_point(module_scope)
+27 -156
View File
@@ -1,168 +1,39 @@
from google.protobuf.internal import containers as _containers
from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union
DELETE: FileOperation
ACK: MessageType
AHT20_HUMIDITY: MessageType
AHT20_TEMP: MessageType
BEEP_OFF: MessageType
BEEP_ON: MessageType
COLLECT_INTERVAL: MessageType
DESCRIPTOR: _descriptor.FileDescriptor
FILE_BUSY: FileStatus
FILE_IO_ERROR: FileStatus
FILE_NOT_A_FILE: FileStatus
FILE_NOT_FOUND: FileStatus
FILE_NO_CARD: FileStatus
FILE_OFFSET_CONFLICT: FileStatus
FILE_OK: FileStatus
FILE_UNSPECIFIED: FileStatus
GET: FileOperation
INTERDEVICE_VERSION_CURRENT: InterdeviceVersion
INTERDEVICE_VERSION_UNSPECIFIED: InterdeviceVersion
POST: FileOperation
PUT: FileOperation
SD_COMMAND_UNSPECIFIED: SdCommand
SD_EJECT: SdCommand
SD_FORMAT: SdCommand
SD_MOUNT: SdCommand
class DirectoryListing(_message.Message):
__slots__ = ["directory", "filenames", "message", "offset", "status", "total_count"]
DIRECTORY_FIELD_NUMBER: _ClassVar[int]
FILENAMES_FIELD_NUMBER: _ClassVar[int]
MESSAGE_FIELD_NUMBER: _ClassVar[int]
OFFSET_FIELD_NUMBER: _ClassVar[int]
STATUS_FIELD_NUMBER: _ClassVar[int]
TOTAL_COUNT_FIELD_NUMBER: _ClassVar[int]
directory: str
filenames: _containers.RepeatedScalarFieldContainer[str]
message: str
offset: int
status: FileStatus
total_count: int
def __init__(self, directory: _Optional[str] = ..., filenames: _Optional[_Iterable[str]] = ..., status: _Optional[_Union[FileStatus, str]] = ..., message: _Optional[str] = ..., offset: _Optional[int] = ..., total_count: _Optional[int] = ...) -> None: ...
class FileTransfer(_message.Message):
__slots__ = ["file_size", "filedata", "filepath", "length", "message", "offset", "operation", "status"]
FILEDATA_FIELD_NUMBER: _ClassVar[int]
FILEPATH_FIELD_NUMBER: _ClassVar[int]
FILE_SIZE_FIELD_NUMBER: _ClassVar[int]
LENGTH_FIELD_NUMBER: _ClassVar[int]
MESSAGE_FIELD_NUMBER: _ClassVar[int]
OFFSET_FIELD_NUMBER: _ClassVar[int]
OPERATION_FIELD_NUMBER: _ClassVar[int]
STATUS_FIELD_NUMBER: _ClassVar[int]
file_size: int
filedata: bytes
filepath: str
length: int
message: str
offset: int
operation: FileOperation
status: FileStatus
def __init__(self, operation: _Optional[_Union[FileOperation, str]] = ..., filepath: _Optional[str] = ..., filedata: _Optional[bytes] = ..., status: _Optional[_Union[FileStatus, str]] = ..., message: _Optional[str] = ..., offset: _Optional[int] = ..., length: _Optional[int] = ..., file_size: _Optional[int] = ...) -> None: ...
class I2CResult(_message.Message):
__slots__ = ["read_data", "status"]
class Status(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
ERROR: I2CResult.Status
NACK_ADDRESS: I2CResult.Status
NACK_DATA: I2CResult.Status
OK: I2CResult.Status
READ_DATA_FIELD_NUMBER: _ClassVar[int]
STATUS_FIELD_NUMBER: _ClassVar[int]
UNSPECIFIED: I2CResult.Status
read_data: bytes
status: I2CResult.Status
def __init__(self, status: _Optional[_Union[I2CResult.Status, str]] = ..., read_data: _Optional[bytes] = ...) -> None: ...
class I2CTransaction(_message.Message):
__slots__ = ["address", "read_len", "write_data"]
ADDRESS_FIELD_NUMBER: _ClassVar[int]
READ_LEN_FIELD_NUMBER: _ClassVar[int]
WRITE_DATA_FIELD_NUMBER: _ClassVar[int]
address: int
read_len: int
write_data: bytes
def __init__(self, address: _Optional[int] = ..., write_data: _Optional[bytes] = ..., read_len: _Optional[int] = ...) -> None: ...
POWER_ON: MessageType
SCD41_CO2: MessageType
SCD41_HUMIDITY: MessageType
SCD41_TEMP: MessageType
SHUTDOWN: MessageType
TVOC_INDEX: MessageType
class InterdeviceMessage(_message.Message):
__slots__ = ["beep", "directory_listing", "file_transfer", "get_sd_info", "i2c_result", "i2c_scan", "i2c_scan_result", "i2c_transaction", "id", "nack", "nmea", "ping", "pong", "sd_command", "sd_info"]
BEEP_FIELD_NUMBER: _ClassVar[int]
DIRECTORY_LISTING_FIELD_NUMBER: _ClassVar[int]
FILE_TRANSFER_FIELD_NUMBER: _ClassVar[int]
GET_SD_INFO_FIELD_NUMBER: _ClassVar[int]
I2C_RESULT_FIELD_NUMBER: _ClassVar[int]
I2C_SCAN_FIELD_NUMBER: _ClassVar[int]
I2C_SCAN_RESULT_FIELD_NUMBER: _ClassVar[int]
I2C_TRANSACTION_FIELD_NUMBER: _ClassVar[int]
ID_FIELD_NUMBER: _ClassVar[int]
NACK_FIELD_NUMBER: _ClassVar[int]
__slots__ = ["nmea", "sensor"]
NMEA_FIELD_NUMBER: _ClassVar[int]
PING_FIELD_NUMBER: _ClassVar[int]
PONG_FIELD_NUMBER: _ClassVar[int]
SD_COMMAND_FIELD_NUMBER: _ClassVar[int]
SD_INFO_FIELD_NUMBER: _ClassVar[int]
beep: int
directory_listing: DirectoryListing
file_transfer: FileTransfer
get_sd_info: bool
i2c_result: I2CResult
i2c_scan: bool
i2c_scan_result: bytes
i2c_transaction: I2CTransaction
id: int
nack: bool
SENSOR_FIELD_NUMBER: _ClassVar[int]
nmea: str
ping: InterdeviceVersion
pong: InterdeviceVersion
sd_command: SdCommand
sd_info: SdCardInfo
def __init__(self, id: _Optional[int] = ..., nmea: _Optional[str] = ..., beep: _Optional[int] = ..., i2c_transaction: _Optional[_Union[I2CTransaction, _Mapping]] = ..., i2c_result: _Optional[_Union[I2CResult, _Mapping]] = ..., i2c_scan: bool = ..., i2c_scan_result: _Optional[bytes] = ..., file_transfer: _Optional[_Union[FileTransfer, _Mapping]] = ..., directory_listing: _Optional[_Union[DirectoryListing, _Mapping]] = ..., get_sd_info: bool = ..., sd_info: _Optional[_Union[SdCardInfo, _Mapping]] = ..., ping: _Optional[_Union[InterdeviceVersion, str]] = ..., pong: _Optional[_Union[InterdeviceVersion, str]] = ..., nack: bool = ..., sd_command: _Optional[_Union[SdCommand, str]] = ...) -> None: ...
sensor: SensorData
def __init__(self, nmea: _Optional[str] = ..., sensor: _Optional[_Union[SensorData, _Mapping]] = ...) -> None: ...
class SdCardInfo(_message.Message):
__slots__ = ["busy", "card_size", "card_type", "fat_type", "free_bytes", "present", "stats_valid", "unformatted", "used_bytes"]
class CardType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class FatType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
BUSY_FIELD_NUMBER: _ClassVar[int]
CARD_SIZE_FIELD_NUMBER: _ClassVar[int]
CARD_TYPE_FIELD_NUMBER: _ClassVar[int]
EXFAT: SdCardInfo.FatType
FAT16: SdCardInfo.FatType
FAT32: SdCardInfo.FatType
FAT_TYPE_FIELD_NUMBER: _ClassVar[int]
FREE_BYTES_FIELD_NUMBER: _ClassVar[int]
MMC: SdCardInfo.CardType
NONE: SdCardInfo.CardType
PRESENT_FIELD_NUMBER: _ClassVar[int]
SD: SdCardInfo.CardType
SDHC: SdCardInfo.CardType
SDXC: SdCardInfo.CardType
STATS_VALID_FIELD_NUMBER: _ClassVar[int]
UNFORMATTED_FIELD_NUMBER: _ClassVar[int]
UNKNOWN_CARD: SdCardInfo.CardType
UNKNOWN_FAT: SdCardInfo.FatType
USED_BYTES_FIELD_NUMBER: _ClassVar[int]
busy: bool
card_size: int
card_type: SdCardInfo.CardType
fat_type: SdCardInfo.FatType
free_bytes: int
present: bool
stats_valid: bool
unformatted: bool
used_bytes: int
def __init__(self, present: bool = ..., card_type: _Optional[_Union[SdCardInfo.CardType, str]] = ..., fat_type: _Optional[_Union[SdCardInfo.FatType, str]] = ..., card_size: _Optional[int] = ..., used_bytes: _Optional[int] = ..., free_bytes: _Optional[int] = ..., stats_valid: bool = ..., busy: bool = ..., unformatted: bool = ...) -> None: ...
class SensorData(_message.Message):
__slots__ = ["float_value", "type", "uint32_value"]
FLOAT_VALUE_FIELD_NUMBER: _ClassVar[int]
TYPE_FIELD_NUMBER: _ClassVar[int]
UINT32_VALUE_FIELD_NUMBER: _ClassVar[int]
float_value: float
type: MessageType
uint32_value: int
def __init__(self, type: _Optional[_Union[MessageType, str]] = ..., float_value: _Optional[float] = ..., uint32_value: _Optional[int] = ...) -> None: ...
class InterdeviceVersion(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class FileOperation(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class FileStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class SdCommand(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
class MessageType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
+2 -2
View File
@@ -15,7 +15,7 @@ from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config
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\"\x98\n\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\x12L\n\rstatusmessage\x18\x0f \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.StatusMessageConfig\x12U\n\x12traffic_management\x18\x10 \x01(\x0b\x32\x39.meshtastic.protobuf.ModuleConfig.TrafficManagementConfig\x12\x38\n\x03tak\x18\x11 \x01(\x0b\x32+.meshtastic.protobuf.ModuleConfig.TAKConfig\x12G\n\x0bmesh_beacon\x18\x12 \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.MeshBeaconConfig\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')
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\"\xcf\t\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\x12L\n\rstatusmessage\x18\x0f \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.StatusMessageConfig\x12U\n\x12traffic_management\x18\x10 \x01(\x0b\x32\x39.meshtastic.protobuf.ModuleConfig.TrafficManagementConfig\x12\x38\n\x03tak\x18\x11 \x01(\x0b\x32+.meshtastic.protobuf.ModuleConfig.TAKConfig\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')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.localonly_pb2', globals())
@@ -26,5 +26,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_LOCALCONFIG._serialized_start=136
_LOCALCONFIG._serialized_end=642
_LOCALMODULECONFIG._serialized_start=645
_LOCALMODULECONFIG._serialized_end=1949
_LOCALMODULECONFIG._serialized_end=1876
# @@protoc_insertion_point(module_scope)
+2 -4
View File
@@ -29,13 +29,12 @@ class LocalConfig(_message.Message):
def __init__(self, device: _Optional[_Union[_config_pb2.Config.DeviceConfig, _Mapping]] = ..., position: _Optional[_Union[_config_pb2.Config.PositionConfig, _Mapping]] = ..., power: _Optional[_Union[_config_pb2.Config.PowerConfig, _Mapping]] = ..., network: _Optional[_Union[_config_pb2.Config.NetworkConfig, _Mapping]] = ..., display: _Optional[_Union[_config_pb2.Config.DisplayConfig, _Mapping]] = ..., lora: _Optional[_Union[_config_pb2.Config.LoRaConfig, _Mapping]] = ..., bluetooth: _Optional[_Union[_config_pb2.Config.BluetoothConfig, _Mapping]] = ..., version: _Optional[int] = ..., security: _Optional[_Union[_config_pb2.Config.SecurityConfig, _Mapping]] = ...) -> None: ...
class LocalModuleConfig(_message.Message):
__slots__ = ["ambient_lighting", "audio", "canned_message", "detection_sensor", "external_notification", "mesh_beacon", "mqtt", "neighbor_info", "paxcounter", "range_test", "remote_hardware", "serial", "statusmessage", "store_forward", "tak", "telemetry", "traffic_management", "version"]
__slots__ = ["ambient_lighting", "audio", "canned_message", "detection_sensor", "external_notification", "mqtt", "neighbor_info", "paxcounter", "range_test", "remote_hardware", "serial", "statusmessage", "store_forward", "tak", "telemetry", "traffic_management", "version"]
AMBIENT_LIGHTING_FIELD_NUMBER: _ClassVar[int]
AUDIO_FIELD_NUMBER: _ClassVar[int]
CANNED_MESSAGE_FIELD_NUMBER: _ClassVar[int]
DETECTION_SENSOR_FIELD_NUMBER: _ClassVar[int]
EXTERNAL_NOTIFICATION_FIELD_NUMBER: _ClassVar[int]
MESH_BEACON_FIELD_NUMBER: _ClassVar[int]
MQTT_FIELD_NUMBER: _ClassVar[int]
NEIGHBOR_INFO_FIELD_NUMBER: _ClassVar[int]
PAXCOUNTER_FIELD_NUMBER: _ClassVar[int]
@@ -53,7 +52,6 @@ class LocalModuleConfig(_message.Message):
canned_message: _module_config_pb2.ModuleConfig.CannedMessageConfig
detection_sensor: _module_config_pb2.ModuleConfig.DetectionSensorConfig
external_notification: _module_config_pb2.ModuleConfig.ExternalNotificationConfig
mesh_beacon: _module_config_pb2.ModuleConfig.MeshBeaconConfig
mqtt: _module_config_pb2.ModuleConfig.MQTTConfig
neighbor_info: _module_config_pb2.ModuleConfig.NeighborInfoConfig
paxcounter: _module_config_pb2.ModuleConfig.PaxcounterConfig
@@ -66,4 +64,4 @@ class LocalModuleConfig(_message.Message):
telemetry: _module_config_pb2.ModuleConfig.TelemetryConfig
traffic_management: _module_config_pb2.ModuleConfig.TrafficManagementConfig
version: int
def __init__(self, mqtt: _Optional[_Union[_module_config_pb2.ModuleConfig.MQTTConfig, _Mapping]] = ..., serial: _Optional[_Union[_module_config_pb2.ModuleConfig.SerialConfig, _Mapping]] = ..., external_notification: _Optional[_Union[_module_config_pb2.ModuleConfig.ExternalNotificationConfig, _Mapping]] = ..., store_forward: _Optional[_Union[_module_config_pb2.ModuleConfig.StoreForwardConfig, _Mapping]] = ..., range_test: _Optional[_Union[_module_config_pb2.ModuleConfig.RangeTestConfig, _Mapping]] = ..., telemetry: _Optional[_Union[_module_config_pb2.ModuleConfig.TelemetryConfig, _Mapping]] = ..., canned_message: _Optional[_Union[_module_config_pb2.ModuleConfig.CannedMessageConfig, _Mapping]] = ..., audio: _Optional[_Union[_module_config_pb2.ModuleConfig.AudioConfig, _Mapping]] = ..., remote_hardware: _Optional[_Union[_module_config_pb2.ModuleConfig.RemoteHardwareConfig, _Mapping]] = ..., neighbor_info: _Optional[_Union[_module_config_pb2.ModuleConfig.NeighborInfoConfig, _Mapping]] = ..., ambient_lighting: _Optional[_Union[_module_config_pb2.ModuleConfig.AmbientLightingConfig, _Mapping]] = ..., detection_sensor: _Optional[_Union[_module_config_pb2.ModuleConfig.DetectionSensorConfig, _Mapping]] = ..., paxcounter: _Optional[_Union[_module_config_pb2.ModuleConfig.PaxcounterConfig, _Mapping]] = ..., statusmessage: _Optional[_Union[_module_config_pb2.ModuleConfig.StatusMessageConfig, _Mapping]] = ..., traffic_management: _Optional[_Union[_module_config_pb2.ModuleConfig.TrafficManagementConfig, _Mapping]] = ..., tak: _Optional[_Union[_module_config_pb2.ModuleConfig.TAKConfig, _Mapping]] = ..., mesh_beacon: _Optional[_Union[_module_config_pb2.ModuleConfig.MeshBeaconConfig, _Mapping]] = ..., version: _Optional[int] = ...) -> None: ...
def __init__(self, mqtt: _Optional[_Union[_module_config_pb2.ModuleConfig.MQTTConfig, _Mapping]] = ..., serial: _Optional[_Union[_module_config_pb2.ModuleConfig.SerialConfig, _Mapping]] = ..., external_notification: _Optional[_Union[_module_config_pb2.ModuleConfig.ExternalNotificationConfig, _Mapping]] = ..., store_forward: _Optional[_Union[_module_config_pb2.ModuleConfig.StoreForwardConfig, _Mapping]] = ..., range_test: _Optional[_Union[_module_config_pb2.ModuleConfig.RangeTestConfig, _Mapping]] = ..., telemetry: _Optional[_Union[_module_config_pb2.ModuleConfig.TelemetryConfig, _Mapping]] = ..., canned_message: _Optional[_Union[_module_config_pb2.ModuleConfig.CannedMessageConfig, _Mapping]] = ..., audio: _Optional[_Union[_module_config_pb2.ModuleConfig.AudioConfig, _Mapping]] = ..., remote_hardware: _Optional[_Union[_module_config_pb2.ModuleConfig.RemoteHardwareConfig, _Mapping]] = ..., neighbor_info: _Optional[_Union[_module_config_pb2.ModuleConfig.NeighborInfoConfig, _Mapping]] = ..., ambient_lighting: _Optional[_Union[_module_config_pb2.ModuleConfig.AmbientLightingConfig, _Mapping]] = ..., detection_sensor: _Optional[_Union[_module_config_pb2.ModuleConfig.DetectionSensorConfig, _Mapping]] = ..., paxcounter: _Optional[_Union[_module_config_pb2.ModuleConfig.PaxcounterConfig, _Mapping]] = ..., statusmessage: _Optional[_Union[_module_config_pb2.ModuleConfig.StatusMessageConfig, _Mapping]] = ..., traffic_management: _Optional[_Union[_module_config_pb2.ModuleConfig.TrafficManagementConfig, _Mapping]] = ..., tak: _Optional[_Union[_module_config_pb2.ModuleConfig.TAKConfig, _Mapping]] = ..., version: _Optional[int] = ...) -> None: ...
-36
View File
@@ -1,36 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/lorawan_bridge.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/protobuf/lorawan_bridge.proto\x12\x13meshtastic.protobuf\"\xa9\x08\n\rLoRaWANBridge\x12;\n\x06uplink\x18\x01 \x01(\x0b\x32).meshtastic.protobuf.LoRaWANBridge.UplinkH\x00\x12?\n\x08\x64ownlink\x18\x02 \x01(\x0b\x32+.meshtastic.protobuf.LoRaWANBridge.DownlinkH\x00\x12@\n\ttx_result\x18\x03 \x01(\x0b\x32+.meshtastic.protobuf.LoRaWANBridge.TxResultH\x00\x12@\n\x05\x63hunk\x18\x04 \x01(\x0b\x32/.meshtastic.protobuf.LoRaWANBridge.PayloadChunkH\x00\x1a\xaf\x01\n\x06Uplink\x12\x0f\n\x07\x66req_hz\x18\x01 \x01(\x07\x12\x0c\n\x04tmst\x18\x02 \x01(\x07\x12\x10\n\x08rssi_x10\x18\x03 \x01(\x11\x12\x0f\n\x07snr_x10\x18\x04 \x01(\x11\x12\x14\n\x0cradio_params\x18\x05 \x01(\r\x12\x13\n\x0b\x66sk_bitrate\x18\t \x01(\r\x12\x0f\n\x07payload\x18\x06 \x01(\x0c\x12\x12\n\npayload_id\x18\x07 \x01(\r\x12\x13\n\x0b\x63hunk_count\x18\x08 \x01(\r\x1a\xef\x01\n\x08\x44ownlink\x12\x0f\n\x07\x66req_hz\x18\x01 \x01(\x07\x12\x0c\n\x04tmst\x18\x02 \x01(\x07\x12\x14\n\x0cradio_params\x18\x03 \x01(\r\x12\x11\n\tpower_dbm\x18\x04 \x01(\r\x12\x11\n\timmediate\x18\x05 \x01(\x08\x12\x17\n\x0finvert_polarity\x18\x06 \x01(\x08\x12\x0e\n\x06no_crc\x18\x07 \x01(\x08\x12\x11\n\tmay_defer\x18\x08 \x01(\x08\x12\x12\n\nrequest_id\x18\x0c \x01(\r\x12\x0f\n\x07payload\x18\t \x01(\x0c\x12\x12\n\npayload_id\x18\n \x01(\r\x12\x13\n\x0b\x63hunk_count\x18\x0b \x01(\r\x1aN\n\x0cPayloadChunk\x12\x12\n\npayload_id\x18\x01 \x01(\r\x12\x13\n\x0b\x63hunk_index\x18\x02 \x01(\r\x12\x15\n\rpayload_chunk\x18\x03 \x01(\x0c\x1a\x96\x02\n\x08TxResult\x12\x0c\n\x04tmst\x18\x01 \x01(\x07\x12\x42\n\x06status\x18\x02 \x01(\x0e\x32\x32.meshtastic.protobuf.LoRaWANBridge.TxResult.Status\x12\x12\n\nrequest_id\x18\x03 \x01(\r\"\xa3\x01\n\x06Status\x12\x08\n\x04NONE\x10\x00\x12\x0c\n\x08TOO_LATE\x10\x01\x12\r\n\tTOO_EARLY\x10\x02\x12\x14\n\x10\x43OLLISION_PACKET\x10\x03\x12\x14\n\x10\x43OLLISION_BEACON\x10\x04\x12\x0b\n\x07TX_FREQ\x10\x05\x12\x0c\n\x08TX_POWER\x10\x06\x12\x10\n\x0cGPS_UNLOCKED\x10\x07\x12\x0c\n\x08\x44\x45\x46\x45RRED\x10\x08\x12\x0b\n\x07\x44ROPPED\x10\tB\t\n\x07variantBi\n\x14org.meshtastic.protoB\x13LoRaWANBridgeProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.lorawan_bridge_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\023LoRaWANBridgeProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_LORAWANBRIDGE._serialized_start=66
_LORAWANBRIDGE._serialized_end=1131
_LORAWANBRIDGE_UPLINK._serialized_start=342
_LORAWANBRIDGE_UPLINK._serialized_end=517
_LORAWANBRIDGE_DOWNLINK._serialized_start=520
_LORAWANBRIDGE_DOWNLINK._serialized_end=759
_LORAWANBRIDGE_PAYLOADCHUNK._serialized_start=761
_LORAWANBRIDGE_PAYLOADCHUNK._serialized_end=839
_LORAWANBRIDGE_TXRESULT._serialized_start=842
_LORAWANBRIDGE_TXRESULT._serialized_end=1120
_LORAWANBRIDGE_TXRESULT_STATUS._serialized_start=957
_LORAWANBRIDGE_TXRESULT_STATUS._serialized_end=1120
# @@protoc_insertion_point(module_scope)
@@ -1,96 +0,0 @@
from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union
DESCRIPTOR: _descriptor.FileDescriptor
class LoRaWANBridge(_message.Message):
__slots__ = ["chunk", "downlink", "tx_result", "uplink"]
class Downlink(_message.Message):
__slots__ = ["chunk_count", "freq_hz", "immediate", "invert_polarity", "may_defer", "no_crc", "payload", "payload_id", "power_dbm", "radio_params", "request_id", "tmst"]
CHUNK_COUNT_FIELD_NUMBER: _ClassVar[int]
FREQ_HZ_FIELD_NUMBER: _ClassVar[int]
IMMEDIATE_FIELD_NUMBER: _ClassVar[int]
INVERT_POLARITY_FIELD_NUMBER: _ClassVar[int]
MAY_DEFER_FIELD_NUMBER: _ClassVar[int]
NO_CRC_FIELD_NUMBER: _ClassVar[int]
PAYLOAD_FIELD_NUMBER: _ClassVar[int]
PAYLOAD_ID_FIELD_NUMBER: _ClassVar[int]
POWER_DBM_FIELD_NUMBER: _ClassVar[int]
RADIO_PARAMS_FIELD_NUMBER: _ClassVar[int]
REQUEST_ID_FIELD_NUMBER: _ClassVar[int]
TMST_FIELD_NUMBER: _ClassVar[int]
chunk_count: int
freq_hz: int
immediate: bool
invert_polarity: bool
may_defer: bool
no_crc: bool
payload: bytes
payload_id: int
power_dbm: int
radio_params: int
request_id: int
tmst: int
def __init__(self, freq_hz: _Optional[int] = ..., tmst: _Optional[int] = ..., radio_params: _Optional[int] = ..., power_dbm: _Optional[int] = ..., immediate: bool = ..., invert_polarity: bool = ..., no_crc: bool = ..., may_defer: bool = ..., request_id: _Optional[int] = ..., payload: _Optional[bytes] = ..., payload_id: _Optional[int] = ..., chunk_count: _Optional[int] = ...) -> None: ...
class PayloadChunk(_message.Message):
__slots__ = ["chunk_index", "payload_chunk", "payload_id"]
CHUNK_INDEX_FIELD_NUMBER: _ClassVar[int]
PAYLOAD_CHUNK_FIELD_NUMBER: _ClassVar[int]
PAYLOAD_ID_FIELD_NUMBER: _ClassVar[int]
chunk_index: int
payload_chunk: bytes
payload_id: int
def __init__(self, payload_id: _Optional[int] = ..., chunk_index: _Optional[int] = ..., payload_chunk: _Optional[bytes] = ...) -> None: ...
class TxResult(_message.Message):
__slots__ = ["request_id", "status", "tmst"]
class Status(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
COLLISION_BEACON: LoRaWANBridge.TxResult.Status
COLLISION_PACKET: LoRaWANBridge.TxResult.Status
DEFERRED: LoRaWANBridge.TxResult.Status
DROPPED: LoRaWANBridge.TxResult.Status
GPS_UNLOCKED: LoRaWANBridge.TxResult.Status
NONE: LoRaWANBridge.TxResult.Status
REQUEST_ID_FIELD_NUMBER: _ClassVar[int]
STATUS_FIELD_NUMBER: _ClassVar[int]
TMST_FIELD_NUMBER: _ClassVar[int]
TOO_EARLY: LoRaWANBridge.TxResult.Status
TOO_LATE: LoRaWANBridge.TxResult.Status
TX_FREQ: LoRaWANBridge.TxResult.Status
TX_POWER: LoRaWANBridge.TxResult.Status
request_id: int
status: LoRaWANBridge.TxResult.Status
tmst: int
def __init__(self, tmst: _Optional[int] = ..., status: _Optional[_Union[LoRaWANBridge.TxResult.Status, str]] = ..., request_id: _Optional[int] = ...) -> None: ...
class Uplink(_message.Message):
__slots__ = ["chunk_count", "freq_hz", "fsk_bitrate", "payload", "payload_id", "radio_params", "rssi_x10", "snr_x10", "tmst"]
CHUNK_COUNT_FIELD_NUMBER: _ClassVar[int]
FREQ_HZ_FIELD_NUMBER: _ClassVar[int]
FSK_BITRATE_FIELD_NUMBER: _ClassVar[int]
PAYLOAD_FIELD_NUMBER: _ClassVar[int]
PAYLOAD_ID_FIELD_NUMBER: _ClassVar[int]
RADIO_PARAMS_FIELD_NUMBER: _ClassVar[int]
RSSI_X10_FIELD_NUMBER: _ClassVar[int]
SNR_X10_FIELD_NUMBER: _ClassVar[int]
TMST_FIELD_NUMBER: _ClassVar[int]
chunk_count: int
freq_hz: int
fsk_bitrate: int
payload: bytes
payload_id: int
radio_params: int
rssi_x10: int
snr_x10: int
tmst: int
def __init__(self, freq_hz: _Optional[int] = ..., tmst: _Optional[int] = ..., rssi_x10: _Optional[int] = ..., snr_x10: _Optional[int] = ..., radio_params: _Optional[int] = ..., fsk_bitrate: _Optional[int] = ..., payload: _Optional[bytes] = ..., payload_id: _Optional[int] = ..., chunk_count: _Optional[int] = ...) -> None: ...
CHUNK_FIELD_NUMBER: _ClassVar[int]
DOWNLINK_FIELD_NUMBER: _ClassVar[int]
TX_RESULT_FIELD_NUMBER: _ClassVar[int]
UPLINK_FIELD_NUMBER: _ClassVar[int]
chunk: LoRaWANBridge.PayloadChunk
downlink: LoRaWANBridge.Downlink
tx_result: LoRaWANBridge.TxResult
uplink: LoRaWANBridge.Uplink
def __init__(self, uplink: _Optional[_Union[LoRaWANBridge.Uplink, _Mapping]] = ..., downlink: _Optional[_Union[LoRaWANBridge.Downlink, _Mapping]] = ..., tx_result: _Optional[_Union[LoRaWANBridge.TxResult, _Mapping]] = ..., chunk: _Optional[_Union[LoRaWANBridge.PayloadChunk, _Mapping]] = ...) -> None: ...
-28
View File
@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/mesh_beacon.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.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/mesh_beacon.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\"\xbf\x02\n\nMeshBeacon\x12\x0f\n\x07message\x18\x01 \x01(\t\x12;\n\roffer_channel\x18\x02 \x01(\x0b\x32$.meshtastic.protobuf.ChannelSettings\x12G\n\x0coffer_region\x18\x03 \x01(\x0e\x32\x31.meshtastic.protobuf.Config.LoRaConfig.RegionCode\x12M\n\x0coffer_preset\x18\x04 \x01(\x0e\x32\x32.meshtastic.protobuf.Config.LoRaConfig.ModemPresetH\x00\x88\x01\x01\x12!\n\x14offer_frequency_slot\x18\x05 \x01(\rH\x01\x88\x01\x01\x42\x0f\n\r_offer_presetB\x17\n\x15_offer_frequency_slotBf\n\x14org.meshtastic.protoB\x10MeshBeaconProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.mesh_beacon_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\020MeshBeaconProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_MESHBEACON._serialized_start=132
_MESHBEACON._serialized_end=451
# @@protoc_insertion_point(module_scope)
-21
View File
@@ -1,21 +0,0 @@
from meshtastic.protobuf import channel_pb2 as _channel_pb2
from meshtastic.protobuf import config_pb2 as _config_pb2
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union
DESCRIPTOR: _descriptor.FileDescriptor
class MeshBeacon(_message.Message):
__slots__ = ["message", "offer_channel", "offer_frequency_slot", "offer_preset", "offer_region"]
MESSAGE_FIELD_NUMBER: _ClassVar[int]
OFFER_CHANNEL_FIELD_NUMBER: _ClassVar[int]
OFFER_FREQUENCY_SLOT_FIELD_NUMBER: _ClassVar[int]
OFFER_PRESET_FIELD_NUMBER: _ClassVar[int]
OFFER_REGION_FIELD_NUMBER: _ClassVar[int]
message: str
offer_channel: _channel_pb2.ChannelSettings
offer_frequency_slot: int
offer_preset: _config_pb2.Config.LoRaConfig.ModemPreset
offer_region: _config_pb2.Config.LoRaConfig.RegionCode
def __init__(self, message: _Optional[str] = ..., offer_channel: _Optional[_Union[_channel_pb2.ChannelSettings, _Mapping]] = ..., offer_region: _Optional[_Union[_config_pb2.Config.LoRaConfig.RegionCode, str]] = ..., offer_preset: _Optional[_Union[_config_pb2.Config.LoRaConfig.ModemPreset, str]] = ..., offer_frequency_slot: _Optional[int] = ...) -> None: ...
+101 -150
View File
@@ -14,14 +14,13 @@ _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 device_ui_pb2 as meshtastic_dot_protobuf_dot_device__ui__pb2
from meshtastic.protobuf import field_metadata_pb2 as meshtastic_dot_protobuf_dot_field__metadata__pb2
from meshtastic.protobuf import module_config_pb2 as meshtastic_dot_protobuf_dot_module__config__pb2
from meshtastic.protobuf import portnums_pb2 as meshtastic_dot_protobuf_dot_portnums__pb2
from meshtastic.protobuf import telemetry_pb2 as meshtastic_dot_protobuf_dot_telemetry__pb2
from meshtastic.protobuf import xmodem_pb2 as meshtastic_dot_protobuf_dot_xmodem__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/mesh.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a#meshtastic/protobuf/device_ui.proto\x1a(meshtastic/protobuf/field_metadata.proto\x1a\'meshtastic/protobuf/module_config.proto\x1a\"meshtastic/protobuf/portnums.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a meshtastic/protobuf/xmodem.proto\"\x99\x07\n\x08Position\x12\x17\n\nlatitude_i\x18\x01 \x01(\x0fH\x00\x88\x01\x01\x12\x18\n\x0blongitude_i\x18\x02 \x01(\x0fH\x01\x88\x01\x01\x12\x15\n\x08\x61ltitude\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x0c\n\x04time\x18\x04 \x01(\x07\x12@\n\x0flocation_source\x18\x05 \x01(\x0e\x32\'.meshtastic.protobuf.Position.LocSource\x12@\n\x0f\x61ltitude_source\x18\x06 \x01(\x0e\x32\'.meshtastic.protobuf.Position.AltSource\x12\x11\n\ttimestamp\x18\x07 \x01(\x07\x12\x1f\n\x17timestamp_millis_adjust\x18\x08 \x01(\x05\x12\x19\n\x0c\x61ltitude_hae\x18\t \x01(\x11H\x03\x88\x01\x01\x12(\n\x1b\x61ltitude_geoidal_separation\x18\n \x01(\x11H\x04\x88\x01\x01\x12\x0c\n\x04PDOP\x18\x0b \x01(\r\x12\x0c\n\x04HDOP\x18\x0c \x01(\r\x12\x0c\n\x04VDOP\x18\r \x01(\r\x12\x14\n\x0cgps_accuracy\x18\x0e \x01(\r\x12\x19\n\x0cground_speed\x18\x0f \x01(\rH\x05\x88\x01\x01\x12\x19\n\x0cground_track\x18\x10 \x01(\rH\x06\x88\x01\x01\x12\x13\n\x0b\x66ix_quality\x18\x11 \x01(\r\x12\x10\n\x08\x66ix_type\x18\x12 \x01(\r\x12\x14\n\x0csats_in_view\x18\x13 \x01(\r\x12\x11\n\tsensor_id\x18\x14 \x01(\r\x12\x13\n\x0bnext_update\x18\x15 \x01(\r\x12\x12\n\nseq_number\x18\x16 \x01(\r\x12\x16\n\x0eprecision_bits\x18\x17 \x01(\r\"N\n\tLocSource\x12\r\n\tLOC_UNSET\x10\x00\x12\x0e\n\nLOC_MANUAL\x10\x01\x12\x10\n\x0cLOC_INTERNAL\x10\x02\x12\x10\n\x0cLOC_EXTERNAL\x10\x03\"b\n\tAltSource\x12\r\n\tALT_UNSET\x10\x00\x12\x0e\n\nALT_MANUAL\x10\x01\x12\x10\n\x0c\x41LT_INTERNAL\x10\x02\x12\x10\n\x0c\x41LT_EXTERNAL\x10\x03\x12\x12\n\x0e\x41LT_BAROMETRIC\x10\x04\x42\r\n\x0b_latitude_iB\x0e\n\x0c_longitude_iB\x0b\n\t_altitudeB\x0f\n\r_altitude_haeB\x1e\n\x1c_altitude_geoidal_separationB\x0f\n\r_ground_speedB\x0f\n\r_ground_track\"\x9c\x02\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x13\n\x07macaddr\x18\x04 \x01(\x0c\x42\x02\x18\x01\x12\x34\n\x08hw_model\x18\x05 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12\x13\n\x0bis_licensed\x18\x06 \x01(\x08\x12;\n\x04role\x18\x07 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x12\n\npublic_key\x18\x08 \x01(\x0c\x12\x1c\n\x0fis_unmessagable\x18\t \x01(\x08H\x00\x88\x01\x01\x42\x12\n\x10_is_unmessagable\"Z\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x01 \x03(\x07\x12\x13\n\x0bsnr_towards\x18\x02 \x03(\x05\x12\x12\n\nroute_back\x18\x03 \x03(\x07\x12\x10\n\x08snr_back\x18\x04 \x03(\x05\"\xc7\x04\n\x07Routing\x12<\n\rroute_request\x18\x01 \x01(\x0b\x32#.meshtastic.protobuf.RouteDiscoveryH\x00\x12:\n\x0broute_reply\x18\x02 \x01(\x0b\x32#.meshtastic.protobuf.RouteDiscoveryH\x00\x12:\n\x0c\x65rror_reason\x18\x03 \x01(\x0e\x32\".meshtastic.protobuf.Routing.ErrorH\x00\x12\x11\n\tack_proof\x18\x04 \x01(\x0c\"\xe7\x02\n\x05\x45rror\x12\x08\n\x04NONE\x10\x00\x12\x0c\n\x08NO_ROUTE\x10\x01\x12\x0b\n\x07GOT_NAK\x10\x02\x12\x0b\n\x07TIMEOUT\x10\x03\x12\x10\n\x0cNO_INTERFACE\x10\x04\x12\x12\n\x0eMAX_RETRANSMIT\x10\x05\x12\x0e\n\nNO_CHANNEL\x10\x06\x12\r\n\tTOO_LARGE\x10\x07\x12\x0f\n\x0bNO_RESPONSE\x10\x08\x12\x14\n\x10\x44UTY_CYCLE_LIMIT\x10\t\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10 \x12\x12\n\x0eNOT_AUTHORIZED\x10!\x12\x0e\n\nPKI_FAILED\x10\"\x12\x16\n\x12PKI_UNKNOWN_PUBKEY\x10#\x12\x19\n\x15\x41\x44MIN_BAD_SESSION_KEY\x10$\x12!\n\x1d\x41\x44MIN_PUBLIC_KEY_UNAUTHORIZED\x10%\x12\x17\n\x13RATE_LIMIT_EXCEEDED\x10&\x12\x1c\n\x18PKI_SEND_FAIL_PUBLIC_KEY\x10\'B\t\n\x07variant\"\xee\x01\n\x04\x44\x61ta\x12-\n\x07portnum\x18\x01 \x01(\x0e\x32\x1c.meshtastic.protobuf.PortNum\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x12\x15\n\rwant_response\x18\x03 \x01(\x08\x12\x0c\n\x04\x64\x65st\x18\x04 \x01(\x07\x12\x0e\n\x06source\x18\x05 \x01(\x07\x12\x12\n\nrequest_id\x18\x06 \x01(\x07\x12\x10\n\x08reply_id\x18\x07 \x01(\x07\x12\r\n\x05\x65moji\x18\x08 \x01(\x07\x12\x15\n\x08\x62itfield\x18\t \x01(\rH\x00\x88\x01\x01\x12\x18\n\x10xeddsa_signature\x18\n \x01(\x0c\x42\x0b\n\t_bitfield\">\n\x0fKeyVerification\x12\r\n\x05nonce\x18\x01 \x01(\x04\x12\r\n\x05hash1\x18\x02 \x01(\x0c\x12\r\n\x05hash2\x18\x03 \x01(\x0c\"\xd4\x03\n\x14StoreForwardPlusPlus\x12V\n\x11sfpp_message_type\x18\x01 \x01(\x0e\x32;.meshtastic.protobuf.StoreForwardPlusPlus.SFPP_message_type\x12\x14\n\x0cmessage_hash\x18\x02 \x01(\x0c\x12\x13\n\x0b\x63ommit_hash\x18\x03 \x01(\x0c\x12\x11\n\troot_hash\x18\x04 \x01(\x0c\x12\x0f\n\x07message\x18\x05 \x01(\x0c\x12\x17\n\x0f\x65ncapsulated_id\x18\x06 \x01(\r\x12\x17\n\x0f\x65ncapsulated_to\x18\x07 \x01(\r\x12\x19\n\x11\x65ncapsulated_from\x18\x08 \x01(\r\x12\x1b\n\x13\x65ncapsulated_rxtime\x18\t \x01(\r\x12\x13\n\x0b\x63hain_count\x18\nLine truncated
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/mesh.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a#meshtastic/protobuf/device_ui.proto\x1a\'meshtastic/protobuf/module_config.proto\x1a\"meshtastic/protobuf/portnums.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a meshtastic/protobuf/xmodem.proto\"\x99\x07\n\x08Position\x12\x17\n\nlatitude_i\x18\x01 \x01(\x0fH\x00\x88\x01\x01\x12\x18\n\x0blongitude_i\x18\x02 \x01(\x0fH\x01\x88\x01\x01\x12\x15\n\x08\x61ltitude\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x0c\n\x04time\x18\x04 \x01(\x07\x12@\n\x0flocation_source\x18\x05 \x01(\x0e\x32\'.meshtastic.protobuf.Position.LocSource\x12@\n\x0f\x61ltitude_source\x18\x06 \x01(\x0e\x32\'.meshtastic.protobuf.Position.AltSource\x12\x11\n\ttimestamp\x18\x07 \x01(\x07\x12\x1f\n\x17timestamp_millis_adjust\x18\x08 \x01(\x05\x12\x19\n\x0c\x61ltitude_hae\x18\t \x01(\x11H\x03\x88\x01\x01\x12(\n\x1b\x61ltitude_geoidal_separation\x18\n \x01(\x11H\x04\x88\x01\x01\x12\x0c\n\x04PDOP\x18\x0b \x01(\r\x12\x0c\n\x04HDOP\x18\x0c \x01(\r\x12\x0c\n\x04VDOP\x18\r \x01(\r\x12\x14\n\x0cgps_accuracy\x18\x0e \x01(\r\x12\x19\n\x0cground_speed\x18\x0f \x01(\rH\x05\x88\x01\x01\x12\x19\n\x0cground_track\x18\x10 \x01(\rH\x06\x88\x01\x01\x12\x13\n\x0b\x66ix_quality\x18\x11 \x01(\r\x12\x10\n\x08\x66ix_type\x18\x12 \x01(\r\x12\x14\n\x0csats_in_view\x18\x13 \x01(\r\x12\x11\n\tsensor_id\x18\x14 \x01(\r\x12\x13\n\x0bnext_update\x18\x15 \x01(\r\x12\x12\n\nseq_number\x18\x16 \x01(\r\x12\x16\n\x0eprecision_bits\x18\x17 \x01(\r\"N\n\tLocSource\x12\r\n\tLOC_UNSET\x10\x00\x12\x0e\n\nLOC_MANUAL\x10\x01\x12\x10\n\x0cLOC_INTERNAL\x10\x02\x12\x10\n\x0cLOC_EXTERNAL\x10\x03\"b\n\tAltSource\x12\r\n\tALT_UNSET\x10\x00\x12\x0e\n\nALT_MANUAL\x10\x01\x12\x10\n\x0c\x41LT_INTERNAL\x10\x02\x12\x10\n\x0c\x41LT_EXTERNAL\x10\x03\x12\x12\n\x0e\x41LT_BAROMETRIC\x10\x04\x42\r\n\x0b_latitude_iB\x0e\n\x0c_longitude_iB\x0b\n\t_altitudeB\x0f\n\r_altitude_haeB\x1e\n\x1c_altitude_geoidal_separationB\x0f\n\r_ground_speedB\x0f\n\r_ground_track\"\x9c\x02\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x13\n\x07macaddr\x18\x04 \x01(\x0c\x42\x02\x18\x01\x12\x34\n\x08hw_model\x18\x05 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12\x13\n\x0bis_licensed\x18\x06 \x01(\x08\x12;\n\x04role\x18\x07 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x12\n\npublic_key\x18\x08 \x01(\x0c\x12\x1c\n\x0fis_unmessagable\x18\t \x01(\x08H\x00\x88\x01\x01\x42\x12\n\x10_is_unmessagable\"Z\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x01 \x03(\x07\x12\x13\n\x0bsnr_towards\x18\x02 \x03(\x05\x12\x12\n\nroute_back\x18\x03 \x03(\x07\x12\x10\n\x08snr_back\x18\x04 \x03(\x05\"\xb4\x04\n\x07Routing\x12<\n\rroute_request\x18\x01 \x01(\x0b\x32#.meshtastic.protobuf.RouteDiscoveryH\x00\x12:\n\x0broute_reply\x18\x02 \x01(\x0b\x32#.meshtastic.protobuf.RouteDiscoveryH\x00\x12:\n\x0c\x65rror_reason\x18\x03 \x01(\x0e\x32\".meshtastic.protobuf.Routing.ErrorH\x00\"\xe7\x02\n\x05\x45rror\x12\x08\n\x04NONE\x10\x00\x12\x0c\n\x08NO_ROUTE\x10\x01\x12\x0b\n\x07GOT_NAK\x10\x02\x12\x0b\n\x07TIMEOUT\x10\x03\x12\x10\n\x0cNO_INTERFACE\x10\x04\x12\x12\n\x0eMAX_RETRANSMIT\x10\x05\x12\x0e\n\nNO_CHANNEL\x10\x06\x12\r\n\tTOO_LARGE\x10\x07\x12\x0f\n\x0bNO_RESPONSE\x10\x08\x12\x14\n\x10\x44UTY_CYCLE_LIMIT\x10\t\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10 \x12\x12\n\x0eNOT_AUTHORIZED\x10!\x12\x0e\n\nPKI_FAILED\x10\"\x12\x16\n\x12PKI_UNKNOWN_PUBKEY\x10#\x12\x19\n\x15\x41\x44MIN_BAD_SESSION_KEY\x10$\x12!\n\x1d\x41\x44MIN_PUBLIC_KEY_UNAUTHORIZED\x10%\x12\x17\n\x13RATE_LIMIT_EXCEEDED\x10&\x12\x1c\n\x18PKI_SEND_FAIL_PUBLIC_KEY\x10\'B\t\n\x07variant\"\xd4\x01\n\x04\x44\x61ta\x12-\n\x07portnum\x18\x01 \x01(\x0e\x32\x1c.meshtastic.protobuf.PortNum\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x12\x15\n\rwant_response\x18\x03 \x01(\x08\x12\x0c\n\x04\x64\x65st\x18\x04 \x01(\x07\x12\x0e\n\x06source\x18\x05 \x01(\x07\x12\x12\n\nrequest_id\x18\x06 \x01(\x07\x12\x10\n\x08reply_id\x18\x07 \x01(\x07\x12\r\n\x05\x65moji\x18\x08 \x01(\x07\x12\x15\n\x08\x62itfield\x18\t \x01(\rH\x00\x88\x01\x01\x42\x0b\n\t_bitfield\">\n\x0fKeyVerification\x12\r\n\x05nonce\x18\x01 \x01(\x04\x12\r\n\x05hash1\x18\x02 \x01(\x0c\x12\r\n\x05hash2\x18\x03 \x01(\x0c\"\xd4\x03\n\x14StoreForwardPlusPlus\x12V\n\x11sfpp_message_type\x18\x01 \x01(\x0e\x32;.meshtastic.protobuf.StoreForwardPlusPlus.SFPP_message_type\x12\x14\n\x0cmessage_hash\x18\x02 \x01(\x0c\x12\x13\n\x0b\x63ommit_hash\x18\x03 \x01(\x0c\x12\x11\n\troot_hash\x18\x04 \x01(\x0c\x12\x0f\n\x07message\x18\x05 \x01(\x0c\x12\x17\n\x0f\x65ncapsulated_id\x18\x06 \x01(\r\x12\x17\n\x0f\x65ncapsulated_to\x18\x07 \x01(\r\x12\x19\n\x11\x65ncapsulated_from\x18\x08 \x01(\r\x12\x1b\n\x13\x65ncapsulated_rxtime\x18\t \x01(\r\x12\x13\n\x0b\x63hain_count\x18\n \x01(\r\"\x95\x01\n\x11SFPP_message_type\x12\x12\n\x0e\x43\x41NON_ANNOUNCE\x10\x00\x12\x0f\n\x0b\x43HAIN_QUERY\x10\x01\x12\x10\n\Line truncated
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.mesh_pb2', globals())
@@ -29,156 +28,108 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\nMeshProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_HARDWAREMODEL.values_by_name["TBEAM"]._options = None
_HARDWAREMODEL.values_by_name["TBEAM"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["T_ECHO"]._options = None
_HARDWAREMODEL.values_by_name["T_ECHO"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["LILYGO_TBEAM_S3_CORE"]._options = None
_HARDWAREMODEL.values_by_name["LILYGO_TBEAM_S3_CORE"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["WIO_WM1110"]._options = None
_HARDWAREMODEL.values_by_name["WIO_WM1110"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["CANARYONE"]._options = None
_HARDWAREMODEL.values_by_name["CANARYONE"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["T_ECHO_PLUS"]._options = None
_HARDWAREMODEL.values_by_name["T_ECHO_PLUS"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["HELTEC_WIRELESS_TRACKER"]._options = None
_HARDWAREMODEL.values_by_name["HELTEC_WIRELESS_TRACKER"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["TRACKER_T1000_E"]._options = None
_HARDWAREMODEL.values_by_name["TRACKER_T1000_E"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["THINKNODE_M1"]._options = None
_HARDWAREMODEL.values_by_name["THINKNODE_M1"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["SEEED_WIO_TRACKER_L1"]._options = None
_HARDWAREMODEL.values_by_name["SEEED_WIO_TRACKER_L1"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["SEEED_WIO_TRACKER_L1_EINK"]._options = None
_HARDWAREMODEL.values_by_name["SEEED_WIO_TRACKER_L1_EINK"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["T_DECK_PRO"]._options = None
_HARDWAREMODEL.values_by_name["T_DECK_PRO"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["T_LORA_PAGER"]._options = None
_HARDWAREMODEL.values_by_name["T_LORA_PAGER"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["WISMESH_TAG"]._options = None
_HARDWAREMODEL.values_by_name["WISMESH_TAG"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["HELTEC_WIRELESS_TRACKER_V2"]._options = None
_HARDWAREMODEL.values_by_name["HELTEC_WIRELESS_TRACKER_V2"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["TBEAM_1_WATT"]._options = None
_HARDWAREMODEL.values_by_name["TBEAM_1_WATT"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["TBEAM_BPF"]._options = None
_HARDWAREMODEL.values_by_name["TBEAM_BPF"]._serialized_options = b'\312\363\030\002`\001'
_HARDWAREMODEL.values_by_name["MESH_TRACKER_X1"]._options = None
_HARDWAREMODEL.values_by_name["MESH_TRACKER_X1"]._serialized_options = b'\312\363\030\002`\001'
_USER.fields_by_name['macaddr']._options = None
_USER.fields_by_name['macaddr']._serialized_options = b'\030\001'
_MESHPACKET.fields_by_name['delayed']._options = None
_MESHPACKET.fields_by_name['delayed']._serialized_options = b'\030\001'
_HARDWAREMODEL._serialized_start=10490
_HARDWAREMODEL._serialized_end=13636
_CONSTANTS._serialized_start=13638
_CONSTANTS._serialized_end=13682
_CRITICALERRORCODE._serialized_start=13685
_CRITICALERRORCODE._serialized_end=13993
_FIRMWAREEDITION._serialized_start=13996
_FIRMWAREEDITION._serialized_end=14157
_EXCLUDEDMODULES._serialized_start=14160
_EXCLUDEDMODULES._serialized_end=14647
_POSITION._serialized_start=352
_POSITION._serialized_end=1273
_POSITION_LOCSOURCE._serialized_start=968
_POSITION_LOCSOURCE._serialized_end=1046
_POSITION_ALTSOURCE._serialized_start=1048
_POSITION_ALTSOURCE._serialized_end=1146
_USER._serialized_start=1276
_USER._serialized_end=1560
_ROUTEDISCOVERY._serialized_start=1562
_ROUTEDISCOVERY._serialized_end=1652
_ROUTING._serialized_start=1655
_ROUTING._serialized_end=2238
_ROUTING_ERROR._serialized_start=1868
_ROUTING_ERROR._serialized_end=2227
_DATA._serialized_start=2241
_DATA._serialized_end=2479
_KEYVERIFICATION._serialized_start=2481
_KEYVERIFICATION._serialized_end=2543
_STOREFORWARDPLUSPLUS._serialized_start=2546
_STOREFORWARDPLUSPLUS._serialized_end=3014
_STOREFORWARDPLUSPLUS_SFPP_MESSAGE_TYPE._serialized_start=2865
_STOREFORWARDPLUSPLUS_SFPP_MESSAGE_TYPE._serialized_end=3014
_REMOTESHELL._serialized_start=3017
_REMOTESHELL._serialized_end=3381
_REMOTESHELL_OPCODE._serialized_start=3238
_REMOTESHELL_OPCODE._serialized_end=3381
_BOUNDINGBOX._serialized_start=3383
_BOUNDINGBOX._serialized_end=3500
_WAYPOINT._serialized_start=3503
_WAYPOINT._serialized_end=3874
_STATUSMESSAGE._serialized_start=3876
_STATUSMESSAGE._serialized_end=3907
_MQTTCLIENTPROXYMESSAGE._serialized_start=3909
_MQTTCLIENTPROXYMESSAGE._serialized_end=4017
_MESHPACKET._serialized_start=4020
_MESHPACKET._serialized_end=5414
_MESHPACKET_PRIORITY._serialized_start=4754
_MESHPACKET_PRIORITY._serialized_end=4880
_MESHPACKET_DELAYED._serialized_start=4882
_MESHPACKET_DELAYED._serialized_end=4948
_MESHPACKET_TRANSPORTMECHANISM._serialized_start=4951
_MESHPACKET_TRANSPORTMECHANISM._serialized_end=5185
_MESHPACKET_ACKPROOFSTATUS._serialized_start=5187
_MESHPACKET_ACKPROOFSTATUS._serialized_end=5291
_MESHPACKET_SLOTPARITY._serialized_start=5293
_MESHPACKET_SLOTPARITY._serialized_end=5371
_NODEINFO._serialized_start=5417
_NODEINFO._serialized_end=5847
_MYNODEINFO._serialized_start=5850
_MYNODEINFO._serialized_end=6052
_LOGRECORD._serialized_start=6055
_LOGRECORD._serialized_end=6256
_LOGRECORD_LEVEL._serialized_start=6168
_LOGRECORD_LEVEL._serialized_end=6256
_QUEUESTATUS._serialized_start=6258
_QUEUESTATUS._serialized_end=6338
_FROMRADIO._serialized_start=6341
_FROMRADIO._serialized_end=7360
_LOCKDOWNSTATUS._serialized_start=7363
_LOCKDOWNSTATUS._serialized_end=7647
_LOCKDOWNSTATUS_STATE._serialized_start=7537
_LOCKDOWNSTATUS_STATE._serialized_end=7647
_CLIENTNOTIFICATION._serialized_start=7650
_CLIENTNOTIFICATION._serialized_end=8210
_KEYVERIFICATIONNUMBERINFORM._serialized_start=8212
_KEYVERIFICATIONNUMBERINFORM._serialized_end=8306
_KEYVERIFICATIONNUMBERREQUEST._serialized_start=8308
_KEYVERIFICATIONNUMBERREQUEST._serialized_end=8378
_KEYVERIFICATIONFINAL._serialized_start=8380
_KEYVERIFICATIONFINAL._serialized_end=8493
_DUPLICATEDPUBLICKEY._serialized_start=8495
_DUPLICATEDPUBLICKEY._serialized_end=8516
_LOWENTROPYKEY._serialized_start=8518
_LOWENTROPYKEY._serialized_end=8533
_FILEINFO._serialized_start=8535
_FILEINFO._serialized_end=8584
_TORADIO._serialized_start=8587
_TORADIO._serialized_end=8899
_COMPRESSED._serialized_start=8901
_COMPRESSED._serialized_end=8974
_NEIGHBORINFO._serialized_start=8977
_NEIGHBORINFO._serialized_end=9121
_NEIGHBOR._serialized_start=9123
_NEIGHBOR._serialized_end=9223
_DEVICEMETADATA._serialized_start=9226
_DEVICEMETADATA._serialized_end=9607
_LORAPRESETGROUP._serialized_start=9610
_LORAPRESETGROUP._serialized_end=9795
_LORAREGIONPRESETS._serialized_start=9797
_LORAREGIONPRESETS._serialized_end=9904
_LORAREGIONPRESETMAP._serialized_start=9907
_LORAREGIONPRESETMAP._serialized_end=10045
_HEARTBEAT._serialized_start=10047
_HEARTBEAT._serialized_end=10073
_NODEREMOTEHARDWAREPIN._serialized_start=10075
_NODEREMOTEHARDWAREPIN._serialized_end=10169
_CHUNKEDPAYLOAD._serialized_start=10171
_CHUNKEDPAYLOAD._serialized_end=10272
_RESEND_CHUNKS._serialized_start=10274
_RESEND_CHUNKS._serialized_end=10305
_CHUNKEDPAYLOADRESPONSE._serialized_start=10308
_CHUNKEDPAYLOADRESPONSE._serialized_end=10487
_HARDWAREMODEL._serialized_start=9094
_HARDWAREMODEL._serialized_end=11732
_CONSTANTS._serialized_start=11734
_CONSTANTS._serialized_end=11778
_CRITICALERRORCODE._serialized_start=11781
_CRITICALERRORCODE._serialized_end=12089
_FIRMWAREEDITION._serialized_start=12091
_FIRMWAREEDITION._serialized_end=12218
_EXCLUDEDMODULES._serialized_start=12221
_EXCLUDEDMODULES._serialized_end=12605
_POSITION._serialized_start=310
_POSITION._serialized_end=1231
_POSITION_LOCSOURCE._serialized_start=926
_POSITION_LOCSOURCE._serialized_end=1004
_POSITION_ALTSOURCE._serialized_start=1006
_POSITION_ALTSOURCE._serialized_end=1104
_USER._serialized_start=1234
_USER._serialized_end=1518
_ROUTEDISCOVERY._serialized_start=1520
_ROUTEDISCOVERY._serialized_end=1610
_ROUTING._serialized_start=1613
_ROUTING._serialized_end=2177
_ROUTING_ERROR._serialized_start=1807
_ROUTING_ERROR._serialized_end=2166
_DATA._serialized_start=2180
_DATA._serialized_end=2392
_KEYVERIFICATION._serialized_start=2394
_KEYVERIFICATION._serialized_end=2456
_STOREFORWARDPLUSPLUS._serialized_start=2459
_STOREFORWARDPLUSPLUS._serialized_end=2927
_STOREFORWARDPLUSPLUS_SFPP_MESSAGE_TYPE._serialized_start=2778
_STOREFORWARDPLUSPLUS_SFPP_MESSAGE_TYPE._serialized_end=2927
_REMOTESHELL._serialized_start=2930
_REMOTESHELL._serialized_end=3294
_REMOTESHELL_OPCODE._serialized_start=3151
_REMOTESHELL_OPCODE._serialized_end=3294
_WAYPOINT._serialized_start=3297
_WAYPOINT._serialized_end=3485
_STATUSMESSAGE._serialized_start=3487
_STATUSMESSAGE._serialized_end=3518
_MQTTCLIENTPROXYMESSAGE._serialized_start=3520
_MQTTCLIENTPROXYMESSAGE._serialized_end=3628
_MESHPACKET._serialized_start=3631
_MESHPACKET._serialized_end=4616
_MESHPACKET_PRIORITY._serialized_start=4193
_MESHPACKET_PRIORITY._serialized_end=4319
_MESHPACKET_DELAYED._serialized_start=4321
_MESHPACKET_DELAYED._serialized_end=4387
_MESHPACKET_TRANSPORTMECHANISM._serialized_start=4390
_MESHPACKET_TRANSPORTMECHANISM._serialized_end=4597
_NODEINFO._serialized_start=4619
_NODEINFO._serialized_end=4991
_MYNODEINFO._serialized_start=4994
_MYNODEINFO._serialized_end=5196
_LOGRECORD._serialized_start=5199
_LOGRECORD._serialized_end=5400
_LOGRECORD_LEVEL._serialized_start=5312
_LOGRECORD_LEVEL._serialized_end=5400
_QUEUESTATUS._serialized_start=5402
_QUEUESTATUS._serialized_end=5482
_FROMRADIO._serialized_start=5485
_FROMRADIO._serialized_end=6436
_LOCKDOWNSTATUS._serialized_start=6439
_LOCKDOWNSTATUS._serialized_end=6709
_LOCKDOWNSTATUS_STATE._serialized_start=6613
_LOCKDOWNSTATUS_STATE._serialized_end=6709
_CLIENTNOTIFICATION._serialized_start=6712
_CLIENTNOTIFICATION._serialized_end=7272
_KEYVERIFICATIONNUMBERINFORM._serialized_start=7274
_KEYVERIFICATIONNUMBERINFORM._serialized_end=7368
_KEYVERIFICATIONNUMBERREQUEST._serialized_start=7370
_KEYVERIFICATIONNUMBERREQUEST._serialized_end=7440
_KEYVERIFICATIONFINAL._serialized_start=7442
_KEYVERIFICATIONFINAL._serialized_end=7555
_DUPLICATEDPUBLICKEY._serialized_start=7557
_DUPLICATEDPUBLICKEY._serialized_end=7578
_LOWENTROPYKEY._serialized_start=7580
_LOWENTROPYKEY._serialized_end=7595
_FILEINFO._serialized_start=7597
_FILEINFO._serialized_end=7646
_TORADIO._serialized_start=7649
_TORADIO._serialized_end=7961
_COMPRESSED._serialized_start=7963
_COMPRESSED._serialized_end=8036
_NEIGHBORINFO._serialized_start=8039
_NEIGHBORINFO._serialized_end=8183
_NEIGHBOR._serialized_start=8185
_NEIGHBOR._serialized_end=8285
_DEVICEMETADATA._serialized_start=8288
_DEVICEMETADATA._serialized_end=8649
_HEARTBEAT._serialized_start=8651
_HEARTBEAT._serialized_end=8677
_NODEREMOTEHARDWAREPIN._serialized_start=8679
_NODEREMOTEHARDWAREPIN._serialized_end=8773
_CHUNKEDPAYLOAD._serialized_start=8775
_CHUNKEDPAYLOAD._serialized_end=8876
_RESEND_CHUNKS._serialized_start=8878
_RESEND_CHUNKS._serialized_end=8909
_CHUNKEDPAYLOADRESPONSE._serialized_start=8912
_CHUNKEDPAYLOADRESPONSE._serialized_end=9091
# @@protoc_insertion_point(module_scope)
+17 -120
View File
@@ -1,7 +1,6 @@
from meshtastic.protobuf import channel_pb2 as _channel_pb2
from meshtastic.protobuf import config_pb2 as _config_pb2
from meshtastic.protobuf import device_ui_pb2 as _device_ui_pb2
from meshtastic.protobuf import field_metadata_pb2 as _field_metadata_pb2
from meshtastic.protobuf import module_config_pb2 as _module_config_pb2
from meshtastic.protobuf import portnums_pb2 as _portnums_pb2
from meshtastic.protobuf import telemetry_pb2 as _telemetry_pb2
@@ -15,7 +14,6 @@ from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Map
AMBIENTLIGHTING_CONFIG: ExcludedModules
ANDROID_SIM: HardwareModel
AUDIO_CONFIG: ExcludedModules
AXIOMETA_GENESIS_MINI: HardwareModel
BETAFPV_2400_TX: HardwareModel
BETAFPV_900_NANO_TX: HardwareModel
BLUETOOTH_CONFIG: ExcludedModules
@@ -23,24 +21,20 @@ BROWNOUT: CriticalErrorCode
BURNING_MAN: FirmwareEdition
CANARYONE: HardwareModel
CANNEDMSG_CONFIG: ExcludedModules
CCC: FirmwareEdition
CDEBYTE_EORA_S3: HardwareModel
CHATTER_2: HardwareModel
CROWPANEL: HardwareModel
CROWPANEL_P4: HardwareModel
DATA_PAYLOAD_LEN: Constants
DEFCON: FirmwareEdition
DESCRIPTOR: _descriptor.FileDescriptor
DETECTIONSENSOR_CONFIG: ExcludedModules
DIY_EDITION: FirmwareEdition
DIY_V1: HardwareModel
DRAGON_CON: FirmwareEdition
DR_DEV: HardwareModel
EBYTE_ESP32_S3: HardwareModel
ESP32_S3_PICO: HardwareModel
EXCLUDED_NONE: ExcludedModules
EXTNOTIF_CONFIG: ExcludedModules
FAB: FirmwareEdition
FLASH_CORRUPTION_RECOVERABLE: CriticalErrorCode
FLASH_CORRUPTION_UNRECOVERABLE: CriticalErrorCode
GENIEBLOCKS: HardwareModel
@@ -52,12 +46,7 @@ HELTEC_MESH_NODE_T096: HardwareModel
HELTEC_MESH_NODE_T1: HardwareModel
HELTEC_MESH_NODE_T114: HardwareModel
HELTEC_MESH_POCKET: HardwareModel
HELTEC_MESH_POCKET_V2: HardwareModel
HELTEC_MESH_SOLAR: HardwareModel
HELTEC_MESH_TOWER_V2: HardwareModel
HELTEC_RC32: HardwareModel
HELTEC_RC52: HardwareModel
HELTEC_RCC6: HardwareModel
HELTEC_SENSOR_HUB: HardwareModel
HELTEC_V1: HardwareModel
HELTEC_V2_0: HardwareModel
@@ -87,18 +76,10 @@ M5STACK_CORE2: HardwareModel
M5STACK_COREBASIC: HardwareModel
M5STACK_CORES3: HardwareModel
M5STACK_RESERVED: HardwareModel
MAKERFABS_NOMAD_TERMINAL: HardwareModel
MAKERFABS_RESERVED: HardwareModel
MAKERFABS_TRACKER: HardwareModel
ME25LS01_4Y10TD: HardwareModel
MESHBEACON_CONFIG: ExcludedModules
MESHLINK: HardwareModel
MESHNOLOGY_W10: HardwareModel
MESHNOLOGY_W12: HardwareModel
MESHPAGER_X2: HardwareModel
MESHSTICK_1262: HardwareModel
MESH_TAB: HardwareModel
MESH_TRACKER_X1: HardwareModel
MINI_EPAPER_S3: HardwareModel
MQTT_CONFIG: ExcludedModules
MS24SF1: HardwareModel
@@ -109,7 +90,6 @@ NANO_G1_EXPLORER: HardwareModel
NANO_G2_ULTRA: HardwareModel
NEIGHBORINFO_CONFIG: ExcludedModules
NETWORK_CONFIG: ExcludedModules
NODARA: HardwareModel
NOMADSTAR_METEOR_PRO: HardwareModel
NONE: CriticalErrorCode
NO_AXP192: CriticalErrorCode
@@ -144,21 +124,19 @@ RPI_PICO2: HardwareModel
SEEED_SOLAR_NODE: HardwareModel
SEEED_WIO_TRACKER_L1: HardwareModel
SEEED_WIO_TRACKER_L1_EINK: HardwareModel
SEEED_WIO_TRACKER_L1_PRO_1W: HardwareModel
SEEED_WIO_TRACKER_L2: HardwareModel
SEEED_XIAO_S3: HardwareModel
SENSECAP_INDICATOR: HardwareModel
SENSELORA_RP2040: HardwareModel
SENSELORA_S3: HardwareModel
SERIAL_CONFIG: ExcludedModules
SLEEP_ENTER_WAIT: CriticalErrorCode
SMART_CITIZEN: FirmwareEdition
STATION_G1: HardwareModel
STATION_G2: HardwareModel
STATION_G3: HardwareModel
STATUSMESSAGE_CONFIG: ExcludedModules
STOREFORWARD_CONFIG: ExcludedModules
SX1262_FAILURE: CriticalErrorCode
T5_S3_EPAPER_PRO: HardwareModel
TAK_CONFIG: ExcludedModules
TBEAM: HardwareModel
TBEAM_1_WATT: HardwareModel
TBEAM_BPF: HardwareModel
@@ -175,7 +153,6 @@ THINKNODE_M6: HardwareModel
THINKNODE_M7: HardwareModel
THINKNODE_M8: HardwareModel
THINKNODE_M9: HardwareModel
THINKNODE_MX: HardwareModel
TLORA_C6: HardwareModel
TLORA_T3_S3: HardwareModel
TLORA_V1: HardwareModel
@@ -184,11 +161,10 @@ TLORA_V2: HardwareModel
TLORA_V2_1_1P6: HardwareModel
TLORA_V2_1_1P8: HardwareModel
TRACKER_T1000_E: HardwareModel
TRAFFICMANAGEMENT_CONFIG: ExcludedModules
TRACKER_T1000_E_PRO: HardwareModel
TRANSMIT_FAILED: CriticalErrorCode
TWC_MESH_V4: HardwareModel
TX_WATCHDOG: CriticalErrorCode
T_CONNECT_PRO: HardwareModel
T_DECK: HardwareModel
T_DECK_PRO: HardwareModel
T_ECHO: HardwareModel
@@ -214,18 +190,6 @@ WISMESH_TAP_V2: HardwareModel
XIAO_NRF52_KIT: HardwareModel
ZERO: Constants
class BoundingBox(_message.Message):
__slots__ = ["latitude_north_i", "latitude_south_i", "longitude_east_i", "longitude_west_i"]
LATITUDE_NORTH_I_FIELD_NUMBER: _ClassVar[int]
LATITUDE_SOUTH_I_FIELD_NUMBER: _ClassVar[int]
LONGITUDE_EAST_I_FIELD_NUMBER: _ClassVar[int]
LONGITUDE_WEST_I_FIELD_NUMBER: _ClassVar[int]
latitude_north_i: int
latitude_south_i: int
longitude_east_i: int
longitude_west_i: int
def __init__(self, longitude_west_i: _Optional[int] = ..., latitude_south_i: _Optional[int] = ..., longitude_east_i: _Optional[int] = ..., latitude_north_i: _Optional[int] = ...) -> None: ...
class ChunkedPayload(_message.Message):
__slots__ = ["chunk_count", "chunk_index", "payload_chunk", "payload_id"]
CHUNK_COUNT_FIELD_NUMBER: _ClassVar[int]
@@ -281,7 +245,7 @@ class Compressed(_message.Message):
def __init__(self, portnum: _Optional[_Union[_portnums_pb2.PortNum, str]] = ..., data: _Optional[bytes] = ...) -> None: ...
class Data(_message.Message):
__slots__ = ["bitfield", "dest", "emoji", "payload", "portnum", "reply_id", "request_id", "source", "want_response", "xeddsa_signature"]
__slots__ = ["bitfield", "dest", "emoji", "payload", "portnum", "reply_id", "request_id", "source", "want_response"]
BITFIELD_FIELD_NUMBER: _ClassVar[int]
DEST_FIELD_NUMBER: _ClassVar[int]
EMOJI_FIELD_NUMBER: _ClassVar[int]
@@ -291,7 +255,6 @@ class Data(_message.Message):
REQUEST_ID_FIELD_NUMBER: _ClassVar[int]
SOURCE_FIELD_NUMBER: _ClassVar[int]
WANT_RESPONSE_FIELD_NUMBER: _ClassVar[int]
XEDDSA_SIGNATURE_FIELD_NUMBER: _ClassVar[int]
bitfield: int
dest: int
emoji: int
@@ -301,11 +264,10 @@ class Data(_message.Message):
request_id: int
source: int
want_response: bool
xeddsa_signature: bytes
def __init__(self, portnum: _Optional[_Union[_portnums_pb2.PortNum, str]] = ..., payload: _Optional[bytes] = ..., want_response: bool = ..., dest: _Optional[int] = ..., source: _Optional[int] = ..., request_id: _Optional[int] = ..., reply_id: _Optional[int] = ..., emoji: _Optional[int] = ..., bitfield: _Optional[int] = ..., xeddsa_signature: _Optional[bytes] = ...) -> None: ...
def __init__(self, portnum: _Optional[_Union[_portnums_pb2.PortNum, str]] = ..., payload: _Optional[bytes] = ..., want_response: bool = ..., dest: _Optional[int] = ..., source: _Optional[int] = ..., request_id: _Optional[int] = ..., reply_id: _Optional[int] = ..., emoji: _Optional[int] = ..., bitfield: _Optional[int] = ...) -> None: ...
class DeviceMetadata(_message.Message):
__slots__ = ["canShutdown", "device_state_version", "excluded_modules", "firmware_version", "hasBluetooth", "hasEthernet", "hasPKC", "hasRemoteHardware", "hasWifi", "has_xeddsa", "hw_model", "position_flags", "role"]
__slots__ = ["canShutdown", "device_state_version", "excluded_modules", "firmware_version", "hasBluetooth", "hasEthernet", "hasPKC", "hasRemoteHardware", "hasWifi", "hw_model", "position_flags", "role"]
CANSHUTDOWN_FIELD_NUMBER: _ClassVar[int]
DEVICE_STATE_VERSION_FIELD_NUMBER: _ClassVar[int]
EXCLUDED_MODULES_FIELD_NUMBER: _ClassVar[int]
@@ -315,7 +277,6 @@ class DeviceMetadata(_message.Message):
HASPKC_FIELD_NUMBER: _ClassVar[int]
HASREMOTEHARDWARE_FIELD_NUMBER: _ClassVar[int]
HASWIFI_FIELD_NUMBER: _ClassVar[int]
HAS_XEDDSA_FIELD_NUMBER: _ClassVar[int]
HW_MODEL_FIELD_NUMBER: _ClassVar[int]
POSITION_FLAGS_FIELD_NUMBER: _ClassVar[int]
ROLE_FIELD_NUMBER: _ClassVar[int]
@@ -328,11 +289,10 @@ class DeviceMetadata(_message.Message):
hasPKC: bool
hasRemoteHardware: bool
hasWifi: bool
has_xeddsa: bool
hw_model: HardwareModel
position_flags: int
role: _config_pb2.Config.DeviceConfig.Role
def __init__(self, firmware_version: _Optional[str] = ..., device_state_version: _Optional[int] = ..., canShutdown: bool = ..., hasWifi: bool = ..., hasBluetooth: bool = ..., hasEthernet: bool = ..., role: _Optional[_Union[_config_pb2.Config.DeviceConfig.Role, str]] = ..., position_flags: _Optional[int] = ..., hw_model: _Optional[_Union[HardwareModel, str]] = ..., hasRemoteHardware: bool = ..., hasPKC: bool = ..., excluded_modules: _Optional[int] = ..., has_xeddsa: bool = ...) -> None: ...
def __init__(self, firmware_version: _Optional[str] = ..., device_state_version: _Optional[int] = ..., canShutdown: bool = ..., hasWifi: bool = ..., hasBluetooth: bool = ..., hasEthernet: bool = ..., role: _Optional[_Union[_config_pb2.Config.DeviceConfig.Role, str]] = ..., position_flags: _Optional[int] = ..., hw_model: _Optional[_Union[HardwareModel, str]] = ..., hasRemoteHardware: bool = ..., hasPKC: bool = ..., excluded_modules: _Optional[int] = ...) -> None: ...
class DuplicatedPublicKey(_message.Message):
__slots__ = []
@@ -347,7 +307,7 @@ class FileInfo(_message.Message):
def __init__(self, file_name: _Optional[str] = ..., size_bytes: _Optional[int] = ...) -> None: ...
class FromRadio(_message.Message):
__slots__ = ["channel", "clientNotification", "config", "config_complete_id", "deviceuiConfig", "fileInfo", "id", "lockdown_status", "log_record", "metadata", "moduleConfig", "mqttClientProxyMessage", "my_info", "node_info", "packet", "queueStatus", "rebooted", "region_presets", "xmodemPacket"]
__slots__ = ["channel", "clientNotification", "config", "config_complete_id", "deviceuiConfig", "fileInfo", "id", "lockdown_status", "log_record", "metadata", "moduleConfig", "mqttClientProxyMessage", "my_info", "node_info", "packet", "queueStatus", "rebooted", "xmodemPacket"]
CHANNEL_FIELD_NUMBER: _ClassVar[int]
CLIENTNOTIFICATION_FIELD_NUMBER: _ClassVar[int]
CONFIG_COMPLETE_ID_FIELD_NUMBER: _ClassVar[int]
@@ -365,7 +325,6 @@ class FromRadio(_message.Message):
PACKET_FIELD_NUMBER: _ClassVar[int]
QUEUESTATUS_FIELD_NUMBER: _ClassVar[int]
REBOOTED_FIELD_NUMBER: _ClassVar[int]
REGION_PRESETS_FIELD_NUMBER: _ClassVar[int]
XMODEMPACKET_FIELD_NUMBER: _ClassVar[int]
channel: _channel_pb2.Channel
clientNotification: ClientNotification
@@ -384,9 +343,8 @@ class FromRadio(_message.Message):
packet: MeshPacket
queueStatus: QueueStatus
rebooted: bool
region_presets: LoRaRegionPresetMap
xmodemPacket: _xmodem_pb2.XModem
def __init__(self, id: _Optional[int] = ..., packet: _Optional[_Union[MeshPacket, _Mapping]] = ..., my_info: _Optional[_Union[MyNodeInfo, _Mapping]] = ..., node_info: _Optional[_Union[NodeInfo, _Mapping]] = ..., config: _Optional[_Union[_config_pb2.Config, _Mapping]] = ..., log_record: _Optional[_Union[LogRecord, _Mapping]] = ..., config_complete_id: _Optional[int] = ..., rebooted: bool = ..., moduleConfig: _Optional[_Union[_module_config_pb2.ModuleConfig, _Mapping]] = ..., channel: _Optional[_Union[_channel_pb2.Channel, _Mapping]] = ..., queueStatus: _Optional[_Union[QueueStatus, _Mapping]] = ..., xmodemPacket: _Optional[_Union[_xmodem_pb2.XModem, _Mapping]] = ..., metadata: _Optional[_Union[DeviceMetadata, _Mapping]] = ..., mqttClientProxyMessage: _Optional[_Union[MqttClientProxyMessage, _Mapping]] = ..., fileInfo: _Optional[_Union[FileInfo, _Mapping]] = ..., clientNotification: _Optional[_Union[ClientNotification, _Mapping]] = ..., deviceuiConfig: _Optional[_Union[_device_ui_pb2.DeviceUIConfig, _Mapping]] = ..., lockdown_status: _Optional[_Union[LockdownStatus, _Mapping]] = ..., region_presets: _Optional[_Union[LoRaRegionPresetMap, _Mapping]] = ...) -> None: ...
def __init__(self, id: _Optional[int] = ..., packet: _Optional[_Union[MeshPacket, _Mapping]] = ..., my_info: _Optional[_Union[MyNodeInfo, _Mapping]] = ..., node_info: _Optional[_Union[NodeInfo, _Mapping]] = ..., config: _Optional[_Union[_config_pb2.Config, _Mapping]] = ..., log_record: _Optional[_Union[LogRecord, _Mapping]] = ..., config_complete_id: _Optional[int] = ..., rebooted: bool = ..., moduleConfig: _Optional[_Union[_module_config_pb2.ModuleConfig, _Mapping]] = ..., channel: _Optional[_Union[_channel_pb2.Channel, _Mapping]] = ..., queueStatus: _Optional[_Union[QueueStatus, _Mapping]] = ..., xmodemPacket: _Optional[_Union[_xmodem_pb2.XModem, _Mapping]] = ..., metadata: _Optional[_Union[DeviceMetadata, _Mapping]] = ..., mqttClientProxyMessage: _Optional[_Union[MqttClientProxyMessage, _Mapping]] = ..., fileInfo: _Optional[_Union[FileInfo, _Mapping]] = ..., clientNotification: _Optional[_Union[ClientNotification, _Mapping]] = ..., deviceuiConfig: _Optional[_Union[_device_ui_pb2.DeviceUIConfig, _Mapping]] = ..., lockdown_status: _Optional[_Union[LockdownStatus, _Mapping]] = ...) -> None: ...
class Heartbeat(_message.Message):
__slots__ = ["nonce"]
@@ -434,39 +392,12 @@ class KeyVerificationNumberRequest(_message.Message):
remote_longname: str
def __init__(self, nonce: _Optional[int] = ..., remote_longname: _Optional[str] = ...) -> None: ...
class LoRaPresetGroup(_message.Message):
__slots__ = ["default_preset", "licensed_only", "presets"]
DEFAULT_PRESET_FIELD_NUMBER: _ClassVar[int]
LICENSED_ONLY_FIELD_NUMBER: _ClassVar[int]
PRESETS_FIELD_NUMBER: _ClassVar[int]
default_preset: _config_pb2.Config.LoRaConfig.ModemPreset
licensed_only: bool
presets: _containers.RepeatedScalarFieldContainer[_config_pb2.Config.LoRaConfig.ModemPreset]
def __init__(self, presets: _Optional[_Iterable[_Union[_config_pb2.Config.LoRaConfig.ModemPreset, str]]] = ..., default_preset: _Optional[_Union[_config_pb2.Config.LoRaConfig.ModemPreset, str]] = ..., licensed_only: bool = ...) -> None: ...
class LoRaRegionPresetMap(_message.Message):
__slots__ = ["groups", "region_groups"]
GROUPS_FIELD_NUMBER: _ClassVar[int]
REGION_GROUPS_FIELD_NUMBER: _ClassVar[int]
groups: _containers.RepeatedCompositeFieldContainer[LoRaPresetGroup]
region_groups: _containers.RepeatedCompositeFieldContainer[LoRaRegionPresets]
def __init__(self, groups: _Optional[_Iterable[_Union[LoRaPresetGroup, _Mapping]]] = ..., region_groups: _Optional[_Iterable[_Union[LoRaRegionPresets, _Mapping]]] = ...) -> None: ...
class LoRaRegionPresets(_message.Message):
__slots__ = ["group_index", "region"]
GROUP_INDEX_FIELD_NUMBER: _ClassVar[int]
REGION_FIELD_NUMBER: _ClassVar[int]
group_index: int
region: _config_pb2.Config.LoRaConfig.RegionCode
def __init__(self, region: _Optional[_Union[_config_pb2.Config.LoRaConfig.RegionCode, str]] = ..., group_index: _Optional[int] = ...) -> None: ...
class LockdownStatus(_message.Message):
__slots__ = ["backoff_seconds", "boots_remaining", "lock_reason", "state", "valid_until_epoch"]
class State(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
BACKOFF_SECONDS_FIELD_NUMBER: _ClassVar[int]
BOOTS_REMAINING_FIELD_NUMBER: _ClassVar[int]
DISABLED: LockdownStatus.State
LOCKED: LockdownStatus.State
LOCK_REASON_FIELD_NUMBER: _ClassVar[int]
NEEDS_PROVISION: LockdownStatus.State
@@ -508,23 +439,14 @@ class LowEntropyKey(_message.Message):
def __init__(self) -> None: ...
class MeshPacket(_message.Message):
__slots__ = ["ack_proof_status", "channel", "decoded", "delayed", "encrypted", "hop_limit", "hop_start", "id", "next_hop", "pki_encrypted", "priority", "public_key", "relay_node", "rx_rssi", "rx_snr", "rx_time", "slot_parity", "to", "transport_mechanism", "tx_after", "via_mqtt", "want_ack", "xeddsa_signed"]
class AckProofStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
__slots__ = ["channel", "decoded", "delayed", "encrypted", "hop_limit", "hop_start", "id", "next_hop", "pki_encrypted", "priority", "public_key", "relay_node", "rx_rssi", "rx_snr", "rx_time", "to", "transport_mechanism", "tx_after", "via_mqtt", "want_ack"]
class Delayed(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class Priority(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class SlotParity(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class TransportMechanism(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
ACK: MeshPacket.Priority
ACK_PROOF_ABSENT: MeshPacket.AckProofStatus
ACK_PROOF_INVALID: MeshPacket.AckProofStatus
ACK_PROOF_NO_KEY: MeshPacket.AckProofStatus
ACK_PROOF_STATUS_FIELD_NUMBER: _ClassVar[int]
ACK_PROOF_VALID: MeshPacket.AckProofStatus
ALERT: MeshPacket.Priority
BACKGROUND: MeshPacket.Priority
CHANNEL_FIELD_NUMBER: _ClassVar[int]
@@ -552,10 +474,6 @@ class MeshPacket(_message.Message):
RX_RSSI_FIELD_NUMBER: _ClassVar[int]
RX_SNR_FIELD_NUMBER: _ClassVar[int]
RX_TIME_FIELD_NUMBER: _ClassVar[int]
SLOT_PARITY_EVEN: MeshPacket.SlotParity
SLOT_PARITY_FIELD_NUMBER: _ClassVar[int]
SLOT_PARITY_ODD: MeshPacket.SlotParity
SLOT_PARITY_UNSET: MeshPacket.SlotParity
TO_FIELD_NUMBER: _ClassVar[int]
TRANSPORT_API: MeshPacket.TransportMechanism
TRANSPORT_INTERNAL: MeshPacket.TransportMechanism
@@ -566,13 +484,10 @@ class MeshPacket(_message.Message):
TRANSPORT_MECHANISM_FIELD_NUMBER: _ClassVar[int]
TRANSPORT_MQTT: MeshPacket.TransportMechanism
TRANSPORT_MULTICAST_UDP: MeshPacket.TransportMechanism
TRANSPORT_UNICAST_UDP: MeshPacket.TransportMechanism
TX_AFTER_FIELD_NUMBER: _ClassVar[int]
UNSET: MeshPacket.Priority
VIA_MQTT_FIELD_NUMBER: _ClassVar[int]
WANT_ACK_FIELD_NUMBER: _ClassVar[int]
XEDDSA_SIGNED_FIELD_NUMBER: _ClassVar[int]
ack_proof_status: MeshPacket.AckProofStatus
channel: int
decoded: Data
delayed: MeshPacket.Delayed
@@ -588,14 +503,12 @@ class MeshPacket(_message.Message):
rx_rssi: int
rx_snr: float
rx_time: int
slot_parity: MeshPacket.SlotParity
to: int
transport_mechanism: MeshPacket.TransportMechanism
tx_after: int
via_mqtt: bool
want_ack: bool
xeddsa_signed: bool
def __init__(self, to: _Optional[int] = ..., channel: _Optional[int] = ..., decoded: _Optional[_Union[Data, _Mapping]] = ..., encrypted: _Optional[bytes] = ..., id: _Optional[int] = ..., rx_time: _Optional[int] = ..., rx_snr: _Optional[float] = ..., hop_limit: _Optional[int] = ..., want_ack: bool = ..., priority: _Optional[_Union[MeshPacket.Priority, str]] = ..., rx_rssi: _Optional[int] = ..., delayed: _Optional[_Union[MeshPacket.Delayed, str]] = ..., via_mqtt: bool = ..., hop_start: _Optional[int] = ..., public_key: _Optional[bytes] = ..., pki_encrypted: bool = ..., next_hop: _Optional[int] = ..., relay_node: _Optional[int] = ..., tx_after: _Optional[int] = ..., transport_mechanism: _Optional[_Union[MeshPacket.TransportMechanism, str]] = ..., xeddsa_signed: bool = ..., ack_proof_status: _Optional[_Union[MeshPacket.AckProofStatus, str]] = ..., slot_parity: _Optional[_Union[MeshPacket.SlotParity, str]] = ..., **kwargs) -> None: ...
def __init__(self, to: _Optional[int] = ..., channel: _Optional[int] = ..., decoded: _Optional[_Union[Data, _Mapping]] = ..., encrypted: _Optional[bytes] = ..., id: _Optional[int] = ..., rx_time: _Optional[int] = ..., rx_snr: _Optional[float] = ..., hop_limit: _Optional[int] = ..., want_ack: bool = ..., priority: _Optional[_Union[MeshPacket.Priority, str]] = ..., rx_rssi: _Optional[int] = ..., delayed: _Optional[_Union[MeshPacket.Delayed, str]] = ..., via_mqtt: bool = ..., hop_start: _Optional[int] = ..., public_key: _Optional[bytes] = ..., pki_encrypted: bool = ..., next_hop: _Optional[int] = ..., relay_node: _Optional[int] = ..., tx_after: _Optional[int] = ..., transport_mechanism: _Optional[_Union[MeshPacket.TransportMechanism, str]] = ..., **kwargs) -> None: ...
class MqttClientProxyMessage(_message.Message):
__slots__ = ["data", "retained", "text", "topic"]
@@ -652,11 +565,9 @@ class NeighborInfo(_message.Message):
def __init__(self, node_id: _Optional[int] = ..., last_sent_by_id: _Optional[int] = ..., node_broadcast_interval_secs: _Optional[int] = ..., neighbors: _Optional[_Iterable[_Union[Neighbor, _Mapping]]] = ...) -> None: ...
class NodeInfo(_message.Message):
__slots__ = ["channel", "device_metrics", "has_xeddsa_signed", "heard_on_current_lora", "hops_away", "is_favorite", "is_ignored", "is_key_manually_verified", "is_muted", "last_heard", "num", "position", "snr", "user", "via_mqtt"]
__slots__ = ["channel", "device_metrics", "hops_away", "is_favorite", "is_ignored", "is_key_manually_verified", "is_muted", "last_heard", "num", "position", "snr", "user", "via_mqtt"]
CHANNEL_FIELD_NUMBER: _ClassVar[int]
DEVICE_METRICS_FIELD_NUMBER: _ClassVar[int]
HAS_XEDDSA_SIGNED_FIELD_NUMBER: _ClassVar[int]
HEARD_ON_CURRENT_LORA_FIELD_NUMBER: _ClassVar[int]
HOPS_AWAY_FIELD_NUMBER: _ClassVar[int]
IS_FAVORITE_FIELD_NUMBER: _ClassVar[int]
IS_IGNORED_FIELD_NUMBER: _ClassVar[int]
@@ -670,8 +581,6 @@ class NodeInfo(_message.Message):
VIA_MQTT_FIELD_NUMBER: _ClassVar[int]
channel: int
device_metrics: _telemetry_pb2.DeviceMetrics
has_xeddsa_signed: bool
heard_on_current_lora: bool
hops_away: int
is_favorite: bool
is_ignored: bool
@@ -683,7 +592,7 @@ class NodeInfo(_message.Message):
snr: float
user: User
via_mqtt: bool
def __init__(self, num: _Optional[int] = ..., user: _Optional[_Union[User, _Mapping]] = ..., position: _Optional[_Union[Position, _Mapping]] = ..., snr: _Optional[float] = ..., last_heard: _Optional[int] = ..., device_metrics: _Optional[_Union[_telemetry_pb2.DeviceMetrics, _Mapping]] = ..., channel: _Optional[int] = ..., via_mqtt: bool = ..., hops_away: _Optional[int] = ..., is_favorite: bool = ..., is_ignored: bool = ..., is_key_manually_verified: bool = ..., is_muted: bool = ..., has_xeddsa_signed: bool = ..., heard_on_current_lora: bool = ...) -> None: ...
def __init__(self, num: _Optional[int] = ..., user: _Optional[_Union[User, _Mapping]] = ..., position: _Optional[_Union[Position, _Mapping]] = ..., snr: _Optional[float] = ..., last_heard: _Optional[int] = ..., device_metrics: _Optional[_Union[_telemetry_pb2.DeviceMetrics, _Mapping]] = ..., channel: _Optional[int] = ..., via_mqtt: bool = ..., hops_away: _Optional[int] = ..., is_favorite: bool = ..., is_ignored: bool = ..., is_key_manually_verified: bool = ..., is_muted: bool = ...) -> None: ...
class NodeRemoteHardwarePin(_message.Message):
__slots__ = ["node_num", "pin"]
@@ -819,10 +728,9 @@ class RouteDiscovery(_message.Message):
def __init__(self, route: _Optional[_Iterable[int]] = ..., snr_towards: _Optional[_Iterable[int]] = ..., route_back: _Optional[_Iterable[int]] = ..., snr_back: _Optional[_Iterable[int]] = ...) -> None: ...
class Routing(_message.Message):
__slots__ = ["ack_proof", "error_reason", "route_reply", "route_request"]
__slots__ = ["error_reason", "route_reply", "route_request"]
class Error(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
ACK_PROOF_FIELD_NUMBER: _ClassVar[int]
ADMIN_BAD_SESSION_KEY: Routing.Error
ADMIN_PUBLIC_KEY_UNAUTHORIZED: Routing.Error
BAD_REQUEST: Routing.Error
@@ -844,11 +752,10 @@ class Routing(_message.Message):
ROUTE_REQUEST_FIELD_NUMBER: _ClassVar[int]
TIMEOUT: Routing.Error
TOO_LARGE: Routing.Error
ack_proof: bytes
error_reason: Routing.Error
route_reply: RouteDiscovery
route_request: RouteDiscovery
def __init__(self, route_request: _Optional[_Union[RouteDiscovery, _Mapping]] = ..., route_reply: _Optional[_Union[RouteDiscovery, _Mapping]] = ..., error_reason: _Optional[_Union[Routing.Error, str]] = ..., ack_proof: _Optional[bytes] = ...) -> None: ...
def __init__(self, route_request: _Optional[_Union[RouteDiscovery, _Mapping]] = ..., route_reply: _Optional[_Union[RouteDiscovery, _Mapping]] = ..., error_reason: _Optional[_Union[Routing.Error, str]] = ...) -> None: ...
class StatusMessage(_message.Message):
__slots__ = ["status"]
@@ -927,34 +834,24 @@ class User(_message.Message):
def __init__(self, id: _Optional[str] = ..., long_name: _Optional[str] = ..., short_name: _Optional[str] = ..., macaddr: _Optional[bytes] = ..., hw_model: _Optional[_Union[HardwareModel, str]] = ..., is_licensed: bool = ..., role: _Optional[_Union[_config_pb2.Config.DeviceConfig.Role, str]] = ..., public_key: _Optional[bytes] = ..., is_unmessagable: bool = ...) -> None: ...
class Waypoint(_message.Message):
__slots__ = ["bounding_box", "description", "expire", "geofence_radius", "icon", "id", "latitude_i", "locked_to", "longitude_i", "name", "notify_favorites_only", "notify_on_enter", "notify_on_exit"]
BOUNDING_BOX_FIELD_NUMBER: _ClassVar[int]
__slots__ = ["description", "expire", "icon", "id", "latitude_i", "locked_to", "longitude_i", "name"]
DESCRIPTION_FIELD_NUMBER: _ClassVar[int]
EXPIRE_FIELD_NUMBER: _ClassVar[int]
GEOFENCE_RADIUS_FIELD_NUMBER: _ClassVar[int]
ICON_FIELD_NUMBER: _ClassVar[int]
ID_FIELD_NUMBER: _ClassVar[int]
LATITUDE_I_FIELD_NUMBER: _ClassVar[int]
LOCKED_TO_FIELD_NUMBER: _ClassVar[int]
LONGITUDE_I_FIELD_NUMBER: _ClassVar[int]
NAME_FIELD_NUMBER: _ClassVar[int]
NOTIFY_FAVORITES_ONLY_FIELD_NUMBER: _ClassVar[int]
NOTIFY_ON_ENTER_FIELD_NUMBER: _ClassVar[int]
NOTIFY_ON_EXIT_FIELD_NUMBER: _ClassVar[int]
bounding_box: BoundingBox
description: str
expire: int
geofence_radius: int
icon: int
id: int
latitude_i: int
locked_to: int
longitude_i: int
name: str
notify_favorites_only: bool
notify_on_enter: bool
notify_on_exit: bool
def __init__(self, id: _Optional[int] = ..., latitude_i: _Optional[int] = ..., longitude_i: _Optional[int] = ..., expire: _Optional[int] = ..., locked_to: _Optional[int] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., icon: _Optional[int] = ..., geofence_radius: _Optional[int] = ..., bounding_box: _Optional[_Union[BoundingBox, _Mapping]] = ..., notify_on_enter: bool = ..., notify_on_exit: bool = ..., notify_favorites_only: bool = ...) -> None: ...
def __init__(self, id: _Optional[int] = ..., latitude_i: _Optional[int] = ..., longitude_i: _Optional[int] = ..., expire: _Optional[int] = ..., locked_to: _Optional[int] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., icon: _Optional[int] = ...) -> None: ...
class resend_chunks(_message.Message):
__slots__ = ["chunks"]
+54 -365
View File
@@ -12,12 +12,9 @@ _sym_db = _symbol_database.Default()
from meshtastic.protobuf import atak_pb2 as meshtastic_dot_protobuf_dot_atak__pb2
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 field_metadata_pb2 as meshtastic_dot_protobuf_dot_field__metadata__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'meshtastic/protobuf/module_config.proto\x12\x13meshtastic.protobuf\x1a\x1emeshtastic/protobuf/atak.proto\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a(meshtastic/protobuf/field_metadata.proto\"\xfd~\n\x0cModuleConfig\x12<\n\x04mqtt\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.ModuleConfig.MQTTConfigH\x00\x12@\n\x06serial\x18\x02 \x01(\x0b\x32..meshtastic.protobuf.ModuleConfig.SerialConfigH\x00\x12]\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32<.meshtastic.protobuf.ModuleConfig.ExternalNotificationConfigH\x00\x12M\n\rstore_forward\x18\x04 \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.StoreForwardConfigH\x00\x12G\n\nrange_test\x18\x05 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.RangeTestConfigH\x00\x12\x46\n\ttelemetry\x18\x06 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.TelemetryConfigH\x00\x12O\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.CannedMessageConfigH\x00\x12>\n\x05\x61udio\x18\x08 \x01(\x0b\x32-.meshtastic.protobuf.ModuleConfig.AudioConfigH\x00\x12Q\n\x0fremote_hardware\x18\t \x01(\x0b\x32\x36.meshtastic.protobuf.ModuleConfig.RemoteHardwareConfigH\x00\x12M\n\rneighbor_info\x18\n \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.NeighborInfoConfigH\x00\x12S\n\x10\x61mbient_lighting\x18\x0b \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.AmbientLightingConfigH\x00\x12S\n\x10\x64\x65tection_sensor\x18\x0c \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.DetectionSensorConfigH\x00\x12H\n\npaxcounter\x18\r \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.PaxcounterConfigH\x00\x12\\\n\rstatusmessage\x18\x0e \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.StatusMessageConfigB\x0c\xca\xf3\x18\x08R\x06\x32.7.20H\x00\x12\x64\n\x12traffic_management\x18\x0f \x01(\x0b\x32\x39.meshtastic.protobuf.ModuleConfig.TrafficManagementConfigB\x0b\xca\xf3\x18\x07R\x05\x32.8.0H\x00\x12G\n\x03tak\x18\x10 \x01(\x0b\x32+.meshtastic.protobuf.ModuleConfig.TAKConfigB\x0b\xca\xf3\x18\x07R\x05\x32.8.0H\x00\x12V\n\x0bmesh_beacon\x18\x11 \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.MeshBeaconConfigB\x0b\xca\xf3\x18\x07R\x05\x32.8.0H\x00\x1a\xd9\x07\n\nMQTTConfig\x12\x38\n\x07\x65nabled\x18\x01 \x01(\x08\x42\'\xca\xf3\x18#:\x0cMQTT EnabledB\x13\x45nable MQTT gateway\x12\x33\n\x07\x61\x64\x64ress\x18\x02 \x01(\tB\"\xca\xf3\x18\x1e:\x07\x41\x64\x64ressB\x13MQTT server address\x12/\n\x08username\x18\x03 \x01(\tB\x1d\xca\xf3\x18\x19:\x08UsernameB\rMQTT username\x12/\n\x08password\x18\x04 \x01(\tB\x1d\xca\xf3\x18\x19:\x08PasswordB\rMQTT password\x12T\n\x12\x65ncryption_enabled\x18\x05 \x01(\x08\x42\x38\xca\xf3\x18\x34:\x12\x45ncryption EnabledB\x1eSend encrypted packets to MQTT\x12#\n\x0cjson_enabled\x18\x06 \x01(\x08\x42\r\x18\x01\xca\xf3\x18\x07Z\x05\x32.8.0\x12L\n\x0btls_enabled\x18\x07 \x01(\x08\x42\x37\xca\xf3\x18\x33:\x0bTLS EnabledB$Connect to the MQTT server over TLS.\x12/\n\x04root\x18\x08 \x01(\tB!\xca\xf3\x18\x1d:\nRoot TopicB\x0fMQTT root topic\x12{\n\x17proxy_to_client_enabled\x18\t \x01(\x08\x42Z\xca\xf3\x18V:\x11MQTT Client ProxyBAUtilizes the network connection on your phone to connect to MQTT.\x12\xb0\x02\n\x15map_reporting_enabled\x18\n \x01(\x08\x42\x90\x02\xca\xf3\x18\x8b\x02:\rMap ReportingB\xf9\x01Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name.\x12P\n\x13map_report_settings\x18\x0b \x01(\x0b\x32\x33.meshtastic.protobuf.ModuleConfig.MapReportSettings\x1a\xea\x02\n\x11MapReportSettings\x12{\n\x15publish_interval_secs\x18\x01 \x01(\rB\\\xca\xf3\x18X\x19\x00\x00\x00\x00\x00 \xac@*\x01s:\x14Map Publish IntervalB4How often a map report is published. Minimum 1 hour.\x12\x1a\n\x12position_precision\x18\x02 \x01(\r\x12\xbb\x01\n\x16should_report_location\x18\x03 \x01(\x08\x42\x9a\x01\xca\xf3\x18\x95\x01:\x0cShare on MapB~Consent to publish this node\'s details and approximate location unencrypted to the MQTT map. No map report is sent without it.R\x05\x32.6.8\x1a\x8b\x01\n\x14RemoteHardwareConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\"\n\x1a\x61llow_undefined_pin_access\x18\x02 \x01(\x08\x12>\n\x0e\x61vailable_pins\x18\x03 \x03(\x0b\x32&.meshtastic.protobuf.RemoteHardwarePin\x1a\x84\x04\n\x12NeighborInfoConfig\x12\xb2\x01\n\x07\x65nabled\x18\x01 \x01(\x08\x42\xa0\x01\xca\xf3\x18\x9b\x01:\x15Neighbor Info EnabledB\x81\x01\x45nable neighbor info broadcasting. Periodically sends information about directly-heard neighbors to help visualize mesh topology.\x12r\n\x0fupdate_interval\x18\x02 \x01(\rBY\xca\xf3\x18U\x19\x00\x00\x00\x00\x00 \xcc@*\x01s:\x0fUpdate IntervalB6How often to broadcast neighbor info. Minimum 4 hours.\x12\xc4\x01\n\x12transmit_over_lora\x18\x03 \x01(\x08\x42\xa7\x01\xca\xf3\x18\xa2\x01:\x12Transmit over LoRaB\x8b\x01Whether to traLine truncated
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'meshtastic/protobuf/module_config.proto\x12\x13meshtastic.protobuf\x1a\x1emeshtastic/protobuf/atak.proto\"\x86/\n\x0cModuleConfig\x12<\n\x04mqtt\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.ModuleConfig.MQTTConfigH\x00\x12@\n\x06serial\x18\x02 \x01(\x0b\x32..meshtastic.protobuf.ModuleConfig.SerialConfigH\x00\x12]\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32<.meshtastic.protobuf.ModuleConfig.ExternalNotificationConfigH\x00\x12M\n\rstore_forward\x18\x04 \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.StoreForwardConfigH\x00\x12G\n\nrange_test\x18\x05 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.RangeTestConfigH\x00\x12\x46\n\ttelemetry\x18\x06 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.TelemetryConfigH\x00\x12O\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.CannedMessageConfigH\x00\x12>\n\x05\x61udio\x18\x08 \x01(\x0b\x32-.meshtastic.protobuf.ModuleConfig.AudioConfigH\x00\x12Q\n\x0fremote_hardware\x18\t \x01(\x0b\x32\x36.meshtastic.protobuf.ModuleConfig.RemoteHardwareConfigH\x00\x12M\n\rneighbor_info\x18\n \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.NeighborInfoConfigH\x00\x12S\n\x10\x61mbient_lighting\x18\x0b \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.AmbientLightingConfigH\x00\x12S\n\x10\x64\x65tection_sensor\x18\x0c \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.DetectionSensorConfigH\x00\x12H\n\npaxcounter\x18\r \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.PaxcounterConfigH\x00\x12N\n\rstatusmessage\x18\x0e \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.StatusMessageConfigH\x00\x12W\n\x12traffic_management\x18\x0f \x01(\x0b\x32\x39.meshtastic.protobuf.ModuleConfig.TrafficManagementConfigH\x00\x12:\n\x03tak\x18\x10 \x01(\x0b\x32+.meshtastic.protobuf.ModuleConfig.TAKConfigH\x00\x1a\xbd\x02\n\nMQTTConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07\x61\x64\x64ress\x18\x02 \x01(\t\x12\x10\n\x08username\x18\x03 \x01(\t\x12\x10\n\x08password\x18\x04 \x01(\t\x12\x1a\n\x12\x65ncryption_enabled\x18\x05 \x01(\x08\x12\x18\n\x0cjson_enabled\x18\x06 \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0btls_enabled\x18\x07 \x01(\x08\x12\x0c\n\x04root\x18\x08 \x01(\t\x12\x1f\n\x17proxy_to_client_enabled\x18\t \x01(\x08\x12\x1d\n\x15map_reporting_enabled\x18\n \x01(\x08\x12P\n\x13map_report_settings\x18\x0b \x01(\x0b\x32\x33.meshtastic.protobuf.ModuleConfig.MapReportSettings\x1an\n\x11MapReportSettings\x12\x1d\n\x15publish_interval_secs\x18\x01 \x01(\r\x12\x1a\n\x12position_precision\x18\x02 \x01(\r\x12\x1e\n\x16should_report_location\x18\x03 \x01(\x08\x1a\x8b\x01\n\x14RemoteHardwareConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\"\n\x1a\x61llow_undefined_pin_access\x18\x02 \x01(\x08\x12>\n\x0e\x61vailable_pins\x18\x03 \x03(\x0b\x32&.meshtastic.protobuf.RemoteHardwarePin\x1aZ\n\x12NeighborInfoConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x17\n\x0fupdate_interval\x18\x02 \x01(\r\x12\x1a\n\x12transmit_over_lora\x18\x03 \x01(\x08\x1a\xa0\x03\n\x15\x44\x65tectionSensorConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x1e\n\x16minimum_broadcast_secs\x18\x02 \x01(\r\x12\x1c\n\x14state_broadcast_secs\x18\x03 \x01(\r\x12\x11\n\tsend_bell\x18\x04 \x01(\x08\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x13\n\x0bmonitor_pin\x18\x06 \x01(\r\x12\x63\n\x16\x64\x65tection_trigger_type\x18\x07 \x01(\x0e\x32\x43.meshtastic.protobuf.ModuleConfig.DetectionSensorConfig.TriggerType\x12\x12\n\nuse_pullup\x18\x08 \x01(\x08\"\x88\x01\n\x0bTriggerType\x12\r\n\tLOGIC_LOW\x10\x00\x12\x0e\n\nLOGIC_HIGH\x10\x01\x12\x10\n\x0c\x46\x41LLING_EDGE\x10\x02\x12\x0f\n\x0bRISING_EDGE\x10\x03\x12\x1a\n\x16\x45ITHER_EDGE_ACTIVE_LOW\x10\x04\x12\x1b\n\x17\x45ITHER_EDGE_ACTIVE_HIGH\x10\x05\x1a\xed\x02\n\x0b\x41udioConfig\x12\x16\n\x0e\x63odec2_enabled\x18\x01 \x01(\x08\x12\x0f\n\x07ptt_pin\x18\x02 \x01(\r\x12I\n\x07\x62itrate\x18\x03 \x01(\x0e\x32\x38.meshtastic.protobuf.ModuleConfig.AudioConfig.Audio_Baud\x12\x0e\n\x06i2s_ws\x18\x04 \x01(\r\x12\x0e\n\x06i2s_sd\x18\x05 \x01(\r\x12\x0f\n\x07i2s_din\x18\x06 \x01(\r\x12\x0f\n\x07i2s_sck\x18\x07 \x01(\r\"\xa7\x01\n\nAudio_Baud\x12\x12\n\x0e\x43ODEC2_DEFAULT\x10\x00\x12\x0f\n\x0b\x43ODEC2_3200\x10\x01\x12\x0f\n\x0b\x43ODEC2_2400\x10\x02\x12\x0f\n\x0b\x43ODEC2_1600\x10\x03\x12\x0f\n\x0b\x43ODEC2_1400\x10\x04\x12\x0f\n\x0b\x43ODEC2_1300\x10\x05\x12\x0f\n\x0b\x43ODEC2_1200\x10\x06\x12\x0e\n\nCODEC2_700\x10\x07\x12\x0f\n\x0b\x43ODEC2_700B\x10\x08\x1av\n\x10PaxcounterConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\"\n\x1apaxcounter_update_interval\x18\x02 \x01(\r\x12\x16\n\x0ewifi_threshold\x18\x03 \x01(\x05\x12\x15\n\rble_threshold\x18\x04 \x01(\x05\x1a\xd3\x03\n\x17TrafficManagementConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x1e\n\x16position_dedup_enabled\x18\x02 \x01(\x08\x12\x1f\n\x17position_precision_bits\x18\x03 \x01(\r\x12\"\n\x1aposition_min_interval_secs\x18\x04 \x01(\r\x12 \n\x18nodeinfo_direct_response\x18\x05 \x01(\x08\x12)\n!nodeinfo_directLine truncated
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.module_config_pb2', globals())
@@ -25,368 +22,60 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\022ModuleConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_MODULECONFIG_MQTTCONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\030#:\014MQTT EnabledB\023Enable MQTT gateway'
_MODULECONFIG_MQTTCONFIG.fields_by_name['address']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['address']._serialized_options = b'\312\363\030\036:\007AddressB\023MQTT server address'
_MODULECONFIG_MQTTCONFIG.fields_by_name['username']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['username']._serialized_options = b'\312\363\030\031:\010UsernameB\rMQTT username'
_MODULECONFIG_MQTTCONFIG.fields_by_name['password']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['password']._serialized_options = b'\312\363\030\031:\010PasswordB\rMQTT password'
_MODULECONFIG_MQTTCONFIG.fields_by_name['encryption_enabled']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['encryption_enabled']._serialized_options = b'\312\363\0304:\022Encryption EnabledB\036Send encrypted packets to MQTT'
_MODULECONFIG_MQTTCONFIG.fields_by_name['json_enabled']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['json_enabled']._serialized_options = b'\030\001\312\363\030\007Z\0052.8.0'
_MODULECONFIG_MQTTCONFIG.fields_by_name['tls_enabled']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['tls_enabled']._serialized_options = b'\312\363\0303:\013TLS EnabledB$Connect to the MQTT server over TLS.'
_MODULECONFIG_MQTTCONFIG.fields_by_name['root']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['root']._serialized_options = b'\312\363\030\035:\nRoot TopicB\017MQTT root topic'
_MODULECONFIG_MQTTCONFIG.fields_by_name['proxy_to_client_enabled']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['proxy_to_client_enabled']._serialized_options = b'\312\363\030V:\021MQTT Client ProxyBAUtilizes the network connection on your phone to connect to MQTT.'
_MODULECONFIG_MQTTCONFIG.fields_by_name['map_reporting_enabled']._options = None
_MODULECONFIG_MQTTCONFIG.fields_by_name['map_reporting_enabled']._serialized_options = b'\312\363\030\213\002:\rMap ReportingB\371\001Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name.'
_MODULECONFIG_MAPREPORTSETTINGS.fields_by_name['publish_interval_secs']._options = None
_MODULECONFIG_MAPREPORTSETTINGS.fields_by_name['publish_interval_secs']._serialized_options = b'\312\363\030X\031\000\000\000\000\000 \254@*\001s:\024Map Publish IntervalB4How often a map report is published. Minimum 1 hour.'
_MODULECONFIG_MAPREPORTSETTINGS.fields_by_name['should_report_location']._options = None
_MODULECONFIG_MAPREPORTSETTINGS.fields_by_name['should_report_location']._serialized_options = b'\312\363\030\225\001:\014Share on MapB~Consent to publish this node\'s details and approximate location unencrypted to the MQTT map. No map report is sent without it.R\0052.6.8'
_MODULECONFIG_NEIGHBORINFOCONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_NEIGHBORINFOCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\030\233\001:\025Neighbor Info EnabledB\201\001Enable neighbor info broadcasting. Periodically sends information about directly-heard neighbors to help visualize mesh topology.'
_MODULECONFIG_NEIGHBORINFOCONFIG.fields_by_name['update_interval']._options = None
_MODULECONFIG_NEIGHBORINFOCONFIG.fields_by_name['update_interval']._serialized_options = b'\312\363\030U\031\000\000\000\000\000 \314@*\001s:\017Update IntervalB6How often to broadcast neighbor info. Minimum 4 hours.'
_MODULECONFIG_NEIGHBORINFOCONFIG.fields_by_name['transmit_over_lora']._options = None
_MODULECONFIG_NEIGHBORINFOCONFIG.fields_by_name['transmit_over_lora']._serialized_options = b'\312\363\030\242\001:\022Transmit over LoRaB\213\001Whether to transmit neighbor info over LoRa in addition to MQTT and the connected app. Not available on channels with default key and name.'
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["LOGIC_LOW"]._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["LOGIC_LOW"]._serialized_options = b'\312\363\030\005:\003Low'
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["LOGIC_HIGH"]._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["LOGIC_HIGH"]._serialized_options = b'\312\363\030\006:\004High'
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["FALLING_EDGE"]._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["FALLING_EDGE"]._serialized_options = b'\312\363\030\016:\014Falling Edge'
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["RISING_EDGE"]._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["RISING_EDGE"]._serialized_options = b'\312\363\030\r:\013Rising Edge'
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["EITHER_EDGE_ACTIVE_LOW"]._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["EITHER_EDGE_ACTIVE_LOW"]._serialized_options = b'\312\363\030\021:\017Either Edge Low'
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["EITHER_EDGE_ACTIVE_HIGH"]._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE.values_by_name["EITHER_EDGE_ACTIVE_HIGH"]._serialized_options = b'\312\363\030\022:\020Either Edge High'
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\030\354\001:\030Detection Sensor EnabledB\317\001Enables the detection sensor module, it needs to be enabled on both the node with the sensor, and any nodes that you want to receive detection sensor text messages or view the detection sensor log and chart.'
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['minimum_broadcast_secs']._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['minimum_broadcast_secs']._serialized_options = b'\312\363\030Z*\001s:)Minimum time between detection broadcastsB*Minimum time between detection broadcasts.'
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['state_broadcast_secs']._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['state_broadcast_secs']._serialized_options = b'\312\363\030\231\001*\001s:\030State Broadcast IntervalBzHow often to send the detection sensor state to the mesh, whether or not anything was detected. 0 sends only on detection.'
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['send_bell']._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['send_bell']._serialized_options = b'\312\363\030e:\tSend BellBXSend ASCII bell with alert message. Useful for triggering external notification on bell.'
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['name']._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['name']._serialized_options = b'\312\363\030%:\004NameB\035Sensor name for mesh messages'
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['monitor_pin']._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['monitor_pin']._serialized_options = b'\312\363\030Q:\023GPIO Pin to monitorB:GPIO pin watched for state changes. 0 disables the module.'
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['detection_trigger_type']._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['detection_trigger_type']._serialized_options = b'\312\363\030%:\014Trigger TypeB\025Type of trigger event'
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['use_pullup']._options = None
_MODULECONFIG_DETECTIONSENSORCONFIG.fields_by_name['use_pullup']._serialized_options = b'\312\363\030P:\024Use Internal Pull-upB8Enable the internal pull-up resistor on the monitor pin.'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_DEFAULT"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_DEFAULT"]._serialized_options = b'\312\363\030\t:\007Default'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_3200"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_3200"]._serialized_options = b'\312\363\030\n:\0103200 bps'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_2400"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_2400"]._serialized_options = b'\312\363\030\n:\0102400 bps'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_1600"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_1600"]._serialized_options = b'\312\363\030\n:\0101600 bps'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_1400"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_1400"]._serialized_options = b'\312\363\030\n:\0101400 bps'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_1300"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_1300"]._serialized_options = b'\312\363\030\n:\0101300 bps'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_1200"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_1200"]._serialized_options = b'\312\363\030\n:\0101200 bps'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_700"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_700"]._serialized_options = b'\010\001'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_700B"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_700B"]._serialized_options = b'\010\001'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_700C"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_700C"]._serialized_options = b'\312\363\030\020:\016700 bps (700C)'
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_450"]._options = None
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD.values_by_name["CODEC2_450"]._serialized_options = b'\312\363\030\t:\007450 bps'
_MODULECONFIG_AUDIOCONFIG.fields_by_name['codec2_enabled']._options = None
_MODULECONFIG_AUDIOCONFIG.fields_by_name['codec2_enabled']._serialized_options = b'\312\363\030^:\016Codec2 EnabledBLEnable Codec2 audio encoding/decoding for voice communication over the mesh.'
_MODULECONFIG_AUDIOCONFIG.fields_by_name['ptt_pin']._options = None
_MODULECONFIG_AUDIOCONFIG.fields_by_name['ptt_pin']._serialized_options = b'\312\363\0308:\007PTT PinB-Push-to-talk GPIO pin number. 0 uses GPIO 39.'
_MODULECONFIG_AUDIOCONFIG.fields_by_name['bitrate']._options = None
_MODULECONFIG_AUDIOCONFIG.fields_by_name['bitrate']._serialized_options = b'\312\363\030\202\001:\007BitrateBwThe Codec2 bitrate to use. The sample rate is always 8 kHz. Lower bitrates use less bandwidth but reduce audio quality.'
_MODULECONFIG_AUDIOCONFIG.fields_by_name['i2s_ws']._options = None
_MODULECONFIG_AUDIOCONFIG.fields_by_name['i2s_ws']._serialized_options = b'\312\363\030\025:\023I2S Word Select Pin'
_MODULECONFIG_AUDIOCONFIG.fields_by_name['i2s_sd']._options = None
_MODULECONFIG_AUDIOCONFIG.fields_by_name['i2s_sd']._serialized_options = b'\312\363\030\021:\017I2S Data In Pin'
_MODULECONFIG_AUDIOCONFIG.fields_by_name['i2s_din']._options = None
_MODULECONFIG_AUDIOCONFIG.fields_by_name['i2s_din']._serialized_options = b'\312\363\030\022:\020I2S Data Out Pin'
_MODULECONFIG_AUDIOCONFIG.fields_by_name['i2s_sck']._options = None
_MODULECONFIG_AUDIOCONFIG.fields_by_name['i2s_sck']._serialized_options = b'\312\363\030\017:\rI2S Clock Pin'
_MODULECONFIG_PAXCOUNTERCONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_PAXCOUNTERCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\030\250\001:\023PAX Counter EnabledB\220\001When enabled, the PAX Counter module counts nearby WiFi and Bluetooth devices. Both WiFi and Bluetooth must be disabled for PAX counter to work.'
_MODULECONFIG_PAXCOUNTERCONFIG.fields_by_name['paxcounter_update_interval']._options = None
_MODULECONFIG_PAXCOUNTERCONFIG.fields_by_name['paxcounter_update_interval']._serialized_options = b'\312\363\030F*\001s:\017Update IntervalB0How often to send the device counts to the mesh.'
_MODULECONFIG_PAXCOUNTERCONFIG.fields_by_name['wifi_threshold']._options = None
_MODULECONFIG_PAXCOUNTERCONFIG.fields_by_name['wifi_threshold']._serialized_options = b'\312\363\030@*\003dBm:\016WiFi ThresholdB)RSSI threshold for counting WiFi devices.'
_MODULECONFIG_PAXCOUNTERCONFIG.fields_by_name['ble_threshold']._options = None
_MODULECONFIG_PAXCOUNTERCONFIG.fields_by_name['ble_threshold']._serialized_options = b'\312\363\030>*\003dBm:\rBLE ThresholdB(RSSI threshold for counting BLE devices.'
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['position_min_interval_secs']._options = None
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['position_min_interval_secs']._serialized_options = b'\312\363\030c*\001s:\031Minimum Position IntervalBCPositions from the same node arriving sooner than this are dropped.'
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['nodeinfo_direct_response_max_hops']._options = None
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['nodeinfo_direct_response_max_hops']._serialized_options = b'\312\363\030\261\001!\000\000\000\000\000\000\010@:\030Direct NodeInfo Max HopsB\213\001Answer NodeInfo requests from cache for requestors within this many hops. Capped at 3 on routers; other roles answer direct neighbors only.'
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['rate_limit_window_secs']._options = None
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['rate_limit_window_secs']._serialized_options = b'\312\363\030A*\001s:\021Rate Limit WindowB)The time window packets are counted over.'
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['rate_limit_max_packets']._options = None
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['rate_limit_max_packets']._serialized_options = b'\312\363\030Q!\000\000\000\000\000\000N@:\026Rate Limit Max PacketsB.The most packets one node may send per window.'
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['unknown_packet_threshold']._options = None
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG.fields_by_name['unknown_packet_threshold']._serialized_options = b'\312\363\030o!\000\000\000\000\000\000N@:\030Unknown Packet ThresholdBJUndecryptable packets one node may send in 5 minutes before it is dropped.'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_DEFAULT"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_DEFAULT"]._serialized_options = b'\312\363\030\t:\007Default'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_110"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_110"]._serialized_options = b'\312\363\030\n:\010110 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_300"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_300"]._serialized_options = b'\312\363\030\n:\010300 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_600"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_600"]._serialized_options = b'\312\363\030\n:\010600 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_1200"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_1200"]._serialized_options = b'\312\363\030\013:\t1200 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_2400"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_2400"]._serialized_options = b'\312\363\030\013:\t2400 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_4800"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_4800"]._serialized_options = b'\312\363\030\013:\t4800 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_9600"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_9600"]._serialized_options = b'\312\363\030\013:\t9600 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_19200"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_19200"]._serialized_options = b'\312\363\030\014:\n19200 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_38400"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_38400"]._serialized_options = b'\312\363\030\014:\n38400 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_57600"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_57600"]._serialized_options = b'\312\363\030\014:\n57600 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_115200"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_115200"]._serialized_options = b'\312\363\030\r:\013115200 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_230400"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_230400"]._serialized_options = b'\312\363\030\r:\013230400 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_460800"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_460800"]._serialized_options = b'\312\363\030\r:\013460800 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_576000"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_576000"]._serialized_options = b'\312\363\030\r:\013576000 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_921600"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD.values_by_name["BAUD_921600"]._serialized_options = b'\312\363\030\r:\013921600 Baud'
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["DEFAULT"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["DEFAULT"]._serialized_options = b'\312\363\030\t:\007Default'
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["SIMPLE"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["SIMPLE"]._serialized_options = b'\312\363\030\010:\006Simple'
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["PROTO"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["PROTO"]._serialized_options = b'\312\363\030\013:\tProtobufs'
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["TEXTMSG"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["TEXTMSG"]._serialized_options = b'\312\363\030\016:\014Text Message'
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["NMEA"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["NMEA"]._serialized_options = b'\312\363\030\020:\016NMEA Positions'
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["CALTOPO"]._options = None
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE.values_by_name["CALTOPO"]._serialized_options = b'\312\363\030\t:\007CalTopo'
_MODULECONFIG_SERIALCONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_SERIALCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\030&:\016Serial EnabledB\024Enable serial module'
_MODULECONFIG_SERIALCONFIG.fields_by_name['echo']._options = None
_MODULECONFIG_SERIALCONFIG.fields_by_name['echo']._serialized_options = b'\312\363\030N:\004EchoBFIf set, any packets you send will be echoed back over the serial port.'
_MODULECONFIG_SERIALCONFIG.fields_by_name['rxd']._options = None
_MODULECONFIG_SERIALCONFIG.fields_by_name['rxd']._serialized_options = b'\312\363\030,:\033Receive data (rxd) GPIO pinB\rRX pin number'
_MODULECONFIG_SERIALCONFIG.fields_by_name['txd']._options = None
_MODULECONFIG_SERIALCONFIG.fields_by_name['txd']._serialized_options = b'\312\363\030-:\034Transmit data (txd) GPIO pinB\rTX pin number'
_MODULECONFIG_SERIALCONFIG.fields_by_name['baud']._options = None
_MODULECONFIG_SERIALCONFIG.fields_by_name['baud']._serialized_options = b'\312\363\030\030:\004BaudB\020Serial baud rate'
_MODULECONFIG_SERIALCONFIG.fields_by_name['timeout']._options = None
_MODULECONFIG_SERIALCONFIG.fields_by_name['timeout']._serialized_options = b'\312\363\030i*\002ms:\007TimeoutBZHow long to wait before treating received serial data as a complete packet. 0 uses 250 ms.'
_MODULECONFIG_SERIALCONFIG.fields_by_name['mode']._options = None
_MODULECONFIG_SERIALCONFIG.fields_by_name['mode']._serialized_options = b'\312\363\030$:\004ModeB\034Serial module operation mode'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\030>:\035External Notification EnabledB\035Enable external notifications'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['output_ms']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['output_ms']._serialized_options = b'\312\363\030I*\002ms:\024GPIO Output DurationB-In GPIO mode, how long to keep the output on.'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['output']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['output']._serialized_options = b'\312\363\030_:\017Output pin GPIOBLGPIO pin driven on notification. Defaults to the board\'s EXT_NOTIFY_OUT pin.'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['output_vibra']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['output_vibra']._serialized_options = b'\312\363\0303:\025Output pin vibra GPIOB\032Vibration motor output pin'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['output_buzzer']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['output_buzzer']._serialized_options = b'\312\363\030+:\026Output pin buzzer GPIOB\021Buzzer output pin'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['active']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['active']._serialized_options = b'\312\363\030]:\006ActiveBSIf enabled, the \'output\' Pin will be pulled active high, disabled means active low.'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_message']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_message']._serialized_options = b'\312\363\030;:\036Alert when receiving a messageB\031Alert on incoming message'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_message_vibra']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_message_vibra']._serialized_options = b'\312\363\030D:\021Vibra Motor AlertB/Alert GPIO vibra motor when receiving a message'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_message_buzzer']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_message_buzzer']._serialized_options = b'\312\363\030F:*Alert GPIO buzzer when receiving a messageB\030Buzz on incoming message'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_bell']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_bell']._serialized_options = b'\312\363\0306:\033Alert when receiving a bellB\027Alert on bell character'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_bell_vibra']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_bell_vibra']._serialized_options = b'\312\363\030I:,Alert GPIO vibra motor when receiving a bellB\031Vibrate on bell character'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_bell_buzzer']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['alert_bell_buzzer']._serialized_options = b'\312\363\030A:\'Alert GPIO buzzer when receiving a bellB\026Buzz on bell character'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['use_pwm']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['use_pwm']._serialized_options = b'\312\363\030\327\001:\016Use PWM BuzzerB\304\001Use a PWM output (like the RAK Buzzer) for tunes instead of an on/off output. This will ignore the output, output duration and active settings and use the device config buzzer GPIO option instead.'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['nag_timeout']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['nag_timeout']._serialized_options = b'\312\363\0302*\001s:\013Nag TimeoutB How long the notification lasts.'
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['use_i2s_as_buzzer']._options = None
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG.fields_by_name['use_i2s_as_buzzer']._serialized_options = b'\312\363\030\247\001:\021Use I2S As BuzzerB\221\001Enables devices with native I2S audio output to use the RTTTL over speaker like a buzzer. T-Watch S3 and T-Deck for example have this capability.'
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\030B:\031Store and Forward EnabledB%Enables the store and forward module.'
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['heartbeat']._options = None
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['heartbeat']._serialized_options = b'\312\363\030F:\016Send HeartbeatB4Send a heartbeat to advertise the server\'s presence.'
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['records']._options = None
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['records']._serialized_options = b'\312\363\030^:\021Number of recordsBIMaximum number of messages to store. 0 uses three quarters of free PSRAM.'
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['history_return_max']._options = None
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['history_return_max']._serialized_options = b'\312\363\030X:\022History Return MaxBBMaximum number of stored messages returned per request. 0 uses 25.'
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['history_return_window']._options = None
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['history_return_window']._serialized_options = b'\312\363\030\\:\025History Return WindowBCHow far back, in minutes, stored messages are returned. 0 uses 240.'
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['is_server']._options = None
_MODULECONFIG_STOREFORWARDCONFIG.fields_by_name['is_server']._serialized_options = b'\312\363\030`:\006ServerBVEnable this device as a Store and Forward server. Requires an ESP32 device with PSRAM.'
_MODULECONFIG_RANGETESTCONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_RANGETESTCONFIG.fields_by_name['enabled']._serialized_options = b'\312\363\030.:\022Range Test EnabledB\030Enable range test module'
_MODULECONFIG_RANGETESTCONFIG.fields_by_name['sender']._options = None
_MODULECONFIG_RANGETESTCONFIG.fields_by_name['sender']._serialized_options = b'\312\363\030q*\001s:\017Sender IntervalB[This device will send out range test messages on the selected interval. 0 disables sending.'
_MODULECONFIG_RANGETESTCONFIG.fields_by_name['save']._options = None
_MODULECONFIG_RANGETESTCONFIG.fields_by_name['save']._serialized_options = b'\312\363\030u:\004SaveBmSaves a CSV with the range test message details, currently only available on ESP32 devices with a web server.'
_MODULECONFIG_RANGETESTCONFIG.fields_by_name['clear_on_reboot']._options = None
_MODULECONFIG_RANGETESTCONFIG.fields_by_name['clear_on_reboot']._serialized_options = b'\312\363\030\010R\0062.7.11'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['device_update_interval']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['device_update_interval']._serialized_options = b'\312\363\030N*\001s:\027Device Metrics IntervalB0How often device metrics are sent over the mesh.'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['environment_update_interval']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['environment_update_interval']._serialized_options = b'\312\363\030X*\001s:\034Environment Metrics IntervalB5How often environment metrics are sent over the mesh.'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['environment_measurement_enabled']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['environment_measurement_enabled']._serialized_options = b'\312\363\030?:\033Environment Metrics EnabledB Collect environment measurements'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['environment_screen_enabled']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['environment_screen_enabled']._serialized_options = b'\312\363\030C:\025Show on device screenB*Display environment measurements on device'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['environment_display_fahrenheit']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['environment_display_fahrenheit']._serialized_options = b'\312\363\0307:\022Display FahrenheitB!Display environment in Fahrenheit'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['air_quality_enabled']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['air_quality_enabled']._serialized_options = b'\312\363\030::\033Air Quality Metrics EnabledB\033Collect air quality metrics'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['air_quality_interval']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['air_quality_interval']._serialized_options = b'\312\363\030X*\001s:\034Air Quality Metrics IntervalB5How often air quality metrics are sent over the mesh.'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['power_measurement_enabled']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['power_measurement_enabled']._serialized_options = b'\312\363\0302:\031Power Measurement EnabledB\025Collect power metrics'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['power_update_interval']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['power_update_interval']._serialized_options = b'\312\363\030L*\001s:\026Power Metrics IntervalB/How often power metrics are sent over the mesh.'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['power_screen_enabled']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['power_screen_enabled']._serialized_options = b'\312\363\030/:\014Power ScreenB\037Display power metrics on device'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['device_telemetry_enabled']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['device_telemetry_enabled']._serialized_options = b'\312\363\030\226\001:\030Broadcast Device MetricsBrEnable broadcasting device metrics to the mesh network. When disabled, metrics are only sent to connected clients.R\0062.7.13'
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['air_quality_screen_enabled']._options = None
_MODULECONFIG_TELEMETRYCONFIG.fields_by_name['air_quality_screen_enabled']._serialized_options = b'\312\363\030\010R\0062.7.18'
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["NONE"]._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["NONE"]._serialized_options = b'\312\363\030\006:\004None'
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["UP"]._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["UP"]._serialized_options = b'\312\363\030\004:\002Up'
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["DOWN"]._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["DOWN"]._serialized_options = b'\312\363\030\006:\004Down'
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["LEFT"]._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["LEFT"]._serialized_options = b'\312\363\030\006:\004Left'
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["RIGHT"]._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["RIGHT"]._serialized_options = b'\312\363\030\007:\005Right'
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["SELECT"]._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["SELECT"]._serialized_options = b'\312\363\030\010:\006Select'
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["BACK"]._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["BACK"]._serialized_options = b'\312\363\030\006:\004Back'
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["CANCEL"]._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR.values_by_name["CANCEL"]._serialized_options = b'\312\363\030\010:\006Cancel'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['rotary1_enabled']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['rotary1_enabled']._serialized_options = b'\312\363\030\':\016Rotary EncoderB\025Enable rotary encoder'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_pin_a']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_pin_a']._serialized_options = b'\312\363\030,:\005Pin AB#GPIO pin for rotary encoder A port.'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_pin_b']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_pin_b']._serialized_options = b'\312\363\030,:\005Pin BB#GPIO pin for rotary encoder B port.'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_pin_press']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_pin_press']._serialized_options = b'\312\363\0303:\tPress PinB&GPIO pin for the encoder press button.'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_event_cw']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_event_cw']._serialized_options = b'\312\363\030<:\026Clockwise Rotary EventB\"Input event for clockwise rotation'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_event_ccw']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_event_ccw']._serialized_options = b'\312\363\030K:\035Counterclockwise Rotary EventB*Input event for counter-clockwise rotation'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_event_press']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['inputbroker_event_press']._serialized_options = b'\312\363\0304:\023Encoder Press EventB\035Input event for encoder press'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['updown1_enabled']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['updown1_enabled']._serialized_options = b'\312\363\0303:\024Up/Down/Select InputB\033Enable up/down/select input'
_MODULECONFIG_MQTTCONFIG.fields_by_name['json_enabled']._serialized_options = b'\030\001'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['enabled']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['enabled']._serialized_options = b'\030\001\312\363\030\007Z\0052.7.0'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['enabled']._serialized_options = b'\030\001'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['allow_input_source']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['allow_input_source']._serialized_options = b'\030\001\312\363\030\007Z\0052.7.0'
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['send_bell']._options = None
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['send_bell']._serialized_options = b'\312\363\030.:\tSend BellB!Send bell character with messages'
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['led_state']._options = None
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['led_state']._serialized_options = b'\312\363\030*:\tLED StateB\035The state of the LED (on/off)'
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['current']._options = None
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['current']._serialized_options = b'\312\363\030_\031\000\000\000\000\000\000\000\000!\000\000\000\000\000\000?@:\007CurrentB!Drive current for the LED output.J\037led|brightness|ambient|lighting'
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['red']._options = None
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['red']._serialized_options = b'\312\363\030j\031\000\000\000\000\000\000\000\000!\000\000\000\000\000\340o@:\003RedB*The red level of the ambient lighting LED.J%color|colour|rgb|led|ambient|lighting'
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['green']._options = None
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['green']._serialized_options = b'\312\363\030n\031\000\000\000\000\000\000\000\000!\000\000\000\000\000\340o@:\005GreenB,The green level of the ambient lighting LED.J%color|colour|rgb|led|ambient|lighting'
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['blue']._options = None
_MODULECONFIG_AMBIENTLIGHTINGCONFIG.fields_by_name['blue']._serialized_options = b'\312\363\030l\031\000\000\000\000\000\000\000\000!\000\000\000\000\000\340o@:\004BlueB+The blue level of the ambient lighting LED.J%color|colour|rgb|led|ambient|lighting'
_MODULECONFIG_MESHBEACONCONFIG.fields_by_name['broadcast_message']._options = None
_MODULECONFIG_MESHBEACONCONFIG.fields_by_name['broadcast_message']._serialized_options = b'\312\363\0309:\007MessageB.Message for beacon broadcasts, up to 60 bytes.'
_MODULECONFIG_MESHBEACONCONFIG.fields_by_name['broadcast_interval_secs']._options = None
_MODULECONFIG_MESHBEACONCONFIG.fields_by_name['broadcast_interval_secs']._serialized_options = b'\312\363\030H\031\000\000\000\000\000 \254@*\001s:\010IntervalB0How often a beacon is broadcast. Minimum 1 hour.'
_MODULECONFIG_TAKCONFIG.fields_by_name['team']._options = None
_MODULECONFIG_TAKCONFIG.fields_by_name['team']._serialized_options = b'\312\363\030\026:\004TeamB\016TAK team color'
_MODULECONFIG_TAKCONFIG.fields_by_name['role']._options = None
_MODULECONFIG_TAKCONFIG.fields_by_name['role']._serialized_options = b'\312\363\030\027:\004RoleB\017TAK member role'
_MODULECONFIG.fields_by_name['statusmessage']._options = None
_MODULECONFIG.fields_by_name['statusmessage']._serialized_options = b'\312\363\030\010R\0062.7.20'
_MODULECONFIG.fields_by_name['traffic_management']._options = None
_MODULECONFIG.fields_by_name['traffic_management']._serialized_options = b'\312\363\030\007R\0052.8.0'
_MODULECONFIG.fields_by_name['tak']._options = None
_MODULECONFIG.fields_by_name['tak']._serialized_options = b'\312\363\030\007R\0052.8.0'
_MODULECONFIG.fields_by_name['mesh_beacon']._options = None
_MODULECONFIG.fields_by_name['mesh_beacon']._serialized_options = b'\312\363\030\007R\0052.8.0'
_REMOTEHARDWAREPINTYPE._serialized_start=16574
_REMOTEHARDWAREPINTYPE._serialized_end=16647
_MODULECONFIG._serialized_start=208
_MODULECONFIG._serialized_end=16461
_MODULECONFIG_MQTTCONFIG._serialized_start=1580
_MODULECONFIG_MQTTCONFIG._serialized_end=2565
_MODULECONFIG_MAPREPORTSETTINGS._serialized_start=2568
_MODULECONFIG_MAPREPORTSETTINGS._serialized_end=2930
_MODULECONFIG_REMOTEHARDWARECONFIG._serialized_start=2933
_MODULECONFIG_REMOTEHARDWARECONFIG._serialized_end=3072
_MODULECONFIG_NEIGHBORINFOCONFIG._serialized_start=3075
_MODULECONFIG_NEIGHBORINFOCONFIG._serialized_end=3591
_MODULECONFIG_DETECTIONSENSORCONFIG._serialized_start=3594
_MODULECONFIG_DETECTIONSENSORCONFIG._serialized_end=4989
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE._serialized_start=4744
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE._serialized_end=4989
_MODULECONFIG_AUDIOCONFIG._serialized_start=4992
_MODULECONFIG_AUDIOCONFIG._serialized_end=5942
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD._serialized_start=5586
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD._serialized_end=5942
_MODULECONFIG_PAXCOUNTERCONFIG._serialized_start=5945
_MODULECONFIG_PAXCOUNTERCONFIG._serialized_end=6454
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG._serialized_start=6457
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG._serialized_end=7474
_MODULECONFIG_SERIALCONFIG._serialized_start=7477
_MODULECONFIG_SERIALCONFIG._serialized_end=8977
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD._serialized_start=8166
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD._serialized_end=8712
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE._serialized_start=8715
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE._serialized_end=8977
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG._serialized_start=8980
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG._serialized_end=10675
_MODULECONFIG_STOREFORWARDCONFIG._serialized_start=10678
_MODULECONFIG_STOREFORWARDCONFIG._serialized_end=11371
_MODULECONFIG_RANGETESTCONFIG._serialized_start=11374
_MODULECONFIG_RANGETESTCONFIG._serialized_end=11773
_MODULECONFIG_TELEMETRYCONFIG._serialized_start=11776
_MODULECONFIG_TELEMETRYCONFIG._serialized_end=13207
_MODULECONFIG_CANNEDMESSAGECONFIG._serialized_start=13210
_MODULECONFIG_CANNEDMESSAGECONFIG._serialized_end=14484
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR._serialized_start=14286
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR._serialized_end=14484
_MODULECONFIG_AMBIENTLIGHTINGCONFIG._serialized_start=14487
_MODULECONFIG_AMBIENTLIGHTINGCONFIG._serialized_end=15080
_MODULECONFIG_STATUSMESSAGECONFIG._serialized_start=15082
_MODULECONFIG_STATUSMESSAGECONFIG._serialized_end=15124
_MODULECONFIG_MESHBEACONCONFIG._serialized_start=15127
_MODULECONFIG_MESHBEACONCONFIG._serialized_end=16283
_MODULECONFIG_MESHBEACONCONFIG_BROADCASTTARGET._serialized_start=15747
_MODULECONFIG_MESHBEACONCONFIG_BROADCASTTARGET._serialized_end=16009
_MODULECONFIG_MESHBEACONCONFIG_FLAGS._serialized_start=16011
_MODULECONFIG_MESHBEACONCONFIG_FLAGS._serialized_end=16109
_MODULECONFIG_TAKCONFIG._serialized_start=16286
_MODULECONFIG_TAKCONFIG._serialized_end=16442
_REMOTEHARDWAREPIN._serialized_start=16463
_REMOTEHARDWAREPIN._serialized_end=16572
_MODULECONFIG_CANNEDMESSAGECONFIG.fields_by_name['allow_input_source']._serialized_options = b'\030\001'
_REMOTEHARDWAREPINTYPE._serialized_start=6232
_REMOTEHARDWAREPINTYPE._serialized_end=6305
_MODULECONFIG._serialized_start=97
_MODULECONFIG._serialized_end=6119
_MODULECONFIG_MQTTCONFIG._serialized_start=1341
_MODULECONFIG_MQTTCONFIG._serialized_end=1658
_MODULECONFIG_MAPREPORTSETTINGS._serialized_start=1660
_MODULECONFIG_MAPREPORTSETTINGS._serialized_end=1770
_MODULECONFIG_REMOTEHARDWARECONFIG._serialized_start=1773
_MODULECONFIG_REMOTEHARDWARECONFIG._serialized_end=1912
_MODULECONFIG_NEIGHBORINFOCONFIG._serialized_start=1914
_MODULECONFIG_NEIGHBORINFOCONFIG._serialized_end=2004
_MODULECONFIG_DETECTIONSENSORCONFIG._serialized_start=2007
_MODULECONFIG_DETECTIONSENSORCONFIG._serialized_end=2423
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE._serialized_start=2287
_MODULECONFIG_DETECTIONSENSORCONFIG_TRIGGERTYPE._serialized_end=2423
_MODULECONFIG_AUDIOCONFIG._serialized_start=2426
_MODULECONFIG_AUDIOCONFIG._serialized_end=2791
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD._serialized_start=2624
_MODULECONFIG_AUDIOCONFIG_AUDIO_BAUD._serialized_end=2791
_MODULECONFIG_PAXCOUNTERCONFIG._serialized_start=2793
_MODULECONFIG_PAXCOUNTERCONFIG._serialized_end=2911
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG._serialized_start=2914
_MODULECONFIG_TRAFFICMANAGEMENTCONFIG._serialized_end=3381
_MODULECONFIG_SERIALCONFIG._serialized_start=3384
_MODULECONFIG_SERIALCONFIG._serialized_end=4077
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD._serialized_start=3661
_MODULECONFIG_SERIALCONFIG_SERIAL_BAUD._serialized_end=3927
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE._serialized_start=3930
_MODULECONFIG_SERIALCONFIG_SERIAL_MODE._serialized_end=4077
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG._serialized_start=4080
_MODULECONFIG_EXTERNALNOTIFICATIONCONFIG._serialized_end=4441
_MODULECONFIG_STOREFORWARDCONFIG._serialized_start=4444
_MODULECONFIG_STOREFORWARDCONFIG._serialized_end=4595
_MODULECONFIG_RANGETESTCONFIG._serialized_start=4597
_MODULECONFIG_RANGETESTCONFIG._serialized_end=4686
_MODULECONFIG_TELEMETRYCONFIG._serialized_start=4689
_MODULECONFIG_TELEMETRYCONFIG._serialized_end=5216
_MODULECONFIG_CANNEDMESSAGECONFIG._serialized_start=5219
_MODULECONFIG_CANNEDMESSAGECONFIG._serialized_end=5852
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR._serialized_start=5753
_MODULECONFIG_CANNEDMESSAGECONFIG_INPUTEVENTCHAR._serialized_end=5852
_MODULECONFIG_AMBIENTLIGHTINGCONFIG._serialized_start=5854
_MODULECONFIG_AMBIENTLIGHTINGCONFIG._serialized_end=5955
_MODULECONFIG_STATUSMESSAGECONFIG._serialized_start=5957
_MODULECONFIG_STATUSMESSAGECONFIG._serialized_end=5999
_MODULECONFIG_TAKCONFIG._serialized_start=6001
_MODULECONFIG_TAKCONFIG._serialized_end=6100
_REMOTEHARDWAREPIN._serialized_start=6121
_REMOTEHARDWAREPIN._serialized_end=6230
# @@protoc_insertion_point(module_scope)
+22 -48
View File
@@ -1,7 +1,4 @@
from meshtastic.protobuf import atak_pb2 as _atak_pb2
from meshtastic.protobuf import channel_pb2 as _channel_pb2
from meshtastic.protobuf import config_pb2 as _config_pb2
from meshtastic.protobuf import field_metadata_pb2 as _field_metadata_pb2
from google.protobuf.internal import containers as _containers
from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
from google.protobuf import descriptor as _descriptor
@@ -14,7 +11,7 @@ DIGITAL_WRITE: RemoteHardwarePinType
UNKNOWN: RemoteHardwarePinType
class ModuleConfig(_message.Message):
__slots__ = ["ambient_lighting", "audio", "canned_message", "detection_sensor", "external_notification", "mesh_beacon", "mqtt", "neighbor_info", "paxcounter", "range_test", "remote_hardware", "serial", "statusmessage", "store_forward", "tak", "telemetry", "traffic_management"]
__slots__ = ["ambient_lighting", "audio", "canned_message", "detection_sensor", "external_notification", "mqtt", "neighbor_info", "paxcounter", "range_test", "remote_hardware", "serial", "statusmessage", "store_forward", "tak", "telemetry", "traffic_management"]
class AmbientLightingConfig(_message.Message):
__slots__ = ["blue", "current", "green", "led_state", "red"]
BLUE_FIELD_NUMBER: _ClassVar[int]
@@ -39,10 +36,8 @@ class ModuleConfig(_message.Message):
CODEC2_1600: ModuleConfig.AudioConfig.Audio_Baud
CODEC2_2400: ModuleConfig.AudioConfig.Audio_Baud
CODEC2_3200: ModuleConfig.AudioConfig.Audio_Baud
CODEC2_450: ModuleConfig.AudioConfig.Audio_Baud
CODEC2_700: ModuleConfig.AudioConfig.Audio_Baud
CODEC2_700B: ModuleConfig.AudioConfig.Audio_Baud
CODEC2_700C: ModuleConfig.AudioConfig.Audio_Baud
CODEC2_DEFAULT: ModuleConfig.AudioConfig.Audio_Baud
CODEC2_ENABLED_FIELD_NUMBER: _ClassVar[int]
I2S_DIN_FIELD_NUMBER: _ClassVar[int]
@@ -187,42 +182,6 @@ class ModuleConfig(_message.Message):
publish_interval_secs: int
should_report_location: bool
def __init__(self, publish_interval_secs: _Optional[int] = ..., position_precision: _Optional[int] = ..., should_report_location: bool = ...) -> None: ...
class MeshBeaconConfig(_message.Message):
__slots__ = ["broadcast_interval_secs", "broadcast_message", "broadcast_offer_channel", "broadcast_offer_frequency_slot", "broadcast_offer_preset", "broadcast_offer_region", "broadcast_targets", "flags"]
class Flags(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class BroadcastTarget(_message.Message):
__slots__ = ["channel_index", "frequency_slot", "preset", "region"]
CHANNEL_INDEX_FIELD_NUMBER: _ClassVar[int]
FREQUENCY_SLOT_FIELD_NUMBER: _ClassVar[int]
PRESET_FIELD_NUMBER: _ClassVar[int]
REGION_FIELD_NUMBER: _ClassVar[int]
channel_index: int
frequency_slot: int
preset: _config_pb2.Config.LoRaConfig.ModemPreset
region: _config_pb2.Config.LoRaConfig.RegionCode
def __init__(self, preset: _Optional[_Union[_config_pb2.Config.LoRaConfig.ModemPreset, str]] = ..., region: _Optional[_Union[_config_pb2.Config.LoRaConfig.RegionCode, str]] = ..., channel_index: _Optional[int] = ..., frequency_slot: _Optional[int] = ...) -> None: ...
BROADCAST_INTERVAL_SECS_FIELD_NUMBER: _ClassVar[int]
BROADCAST_MESSAGE_FIELD_NUMBER: _ClassVar[int]
BROADCAST_OFFER_CHANNEL_FIELD_NUMBER: _ClassVar[int]
BROADCAST_OFFER_FREQUENCY_SLOT_FIELD_NUMBER: _ClassVar[int]
BROADCAST_OFFER_PRESET_FIELD_NUMBER: _ClassVar[int]
BROADCAST_OFFER_REGION_FIELD_NUMBER: _ClassVar[int]
BROADCAST_TARGETS_FIELD_NUMBER: _ClassVar[int]
FLAGS_FIELD_NUMBER: _ClassVar[int]
FLAG_BROADCAST_ENABLED: ModuleConfig.MeshBeaconConfig.Flags
FLAG_LEGACY_SPLIT: ModuleConfig.MeshBeaconConfig.Flags
FLAG_LISTEN_ENABLED: ModuleConfig.MeshBeaconConfig.Flags
FLAG_NONE: ModuleConfig.MeshBeaconConfig.Flags
broadcast_interval_secs: int
broadcast_message: str
broadcast_offer_channel: _channel_pb2.ChannelSettings
broadcast_offer_frequency_slot: int
broadcast_offer_preset: _config_pb2.Config.LoRaConfig.ModemPreset
broadcast_offer_region: _config_pb2.Config.LoRaConfig.RegionCode
broadcast_targets: _containers.RepeatedCompositeFieldContainer[ModuleConfig.MeshBeaconConfig.BroadcastTarget]
flags: int
def __init__(self, flags: _Optional[int] = ..., broadcast_offer_frequency_slot: _Optional[int] = ..., broadcast_message: _Optional[str] = ..., broadcast_offer_channel: _Optional[_Union[_channel_pb2.ChannelSettings, _Mapping]] = ..., broadcast_offer_region: _Optional[_Union[_config_pb2.Config.LoRaConfig.RegionCode, str]] = ..., broadcast_offer_preset: _Optional[_Union[_config_pb2.Config.LoRaConfig.ModemPreset, str]] = ..., broadcast_interval_secs: _Optional[int] = ..., broadcast_targets: _Optional[_Iterable[_Union[ModuleConfig.MeshBeaconConfig.BroadcastTarget, _Mapping]]] = ...) -> None: ...
class NeighborInfoConfig(_message.Message):
__slots__ = ["enabled", "transmit_over_lora", "update_interval"]
ENABLED_FIELD_NUMBER: _ClassVar[int]
@@ -292,7 +251,6 @@ class ModuleConfig(_message.Message):
ENABLED_FIELD_NUMBER: _ClassVar[int]
LOG: ModuleConfig.SerialConfig.Serial_Mode
LOGTEXT: ModuleConfig.SerialConfig.Serial_Mode
MODBUS: ModuleConfig.SerialConfig.Serial_Mode
MODE_FIELD_NUMBER: _ClassVar[int]
MS_CONFIG: ModuleConfig.SerialConfig.Serial_Mode
NMEA: ModuleConfig.SerialConfig.Serial_Mode
@@ -375,24 +333,41 @@ class ModuleConfig(_message.Message):
power_update_interval: int
def __init__(self, device_update_interval: _Optional[int] = ..., environment_update_interval: _Optional[int] = ..., environment_measurement_enabled: bool = ..., environment_screen_enabled: bool = ..., environment_display_fahrenheit: bool = ..., air_quality_enabled: bool = ..., air_quality_interval: _Optional[int] = ..., power_measurement_enabled: bool = ..., power_update_interval: _Optional[int] = ..., power_screen_enabled: bool = ..., health_measurement_enabled: bool = ..., health_update_interval: _Optional[int] = ..., health_screen_enabled: bool = ..., device_telemetry_enabled: bool = ..., air_quality_screen_enabled: bool = ...) -> None: ...
class TrafficManagementConfig(_message.Message):
__slots__ = ["nodeinfo_direct_response_max_hops", "position_min_interval_secs", "rate_limit_max_packets", "rate_limit_window_secs", "unknown_packet_threshold"]
__slots__ = ["drop_unknown_enabled", "enabled", "exhaust_hop_position", "exhaust_hop_telemetry", "nodeinfo_direct_response", "nodeinfo_direct_response_max_hops", "position_dedup_enabled", "position_min_interval_secs", "position_precision_bits", "rate_limit_enabled", "rate_limit_max_packets", "rate_limit_window_secs", "router_preserve_hops", "unknown_packet_threshold"]
DROP_UNKNOWN_ENABLED_FIELD_NUMBER: _ClassVar[int]
ENABLED_FIELD_NUMBER: _ClassVar[int]
EXHAUST_HOP_POSITION_FIELD_NUMBER: _ClassVar[int]
EXHAUST_HOP_TELEMETRY_FIELD_NUMBER: _ClassVar[int]
NODEINFO_DIRECT_RESPONSE_FIELD_NUMBER: _ClassVar[int]
NODEINFO_DIRECT_RESPONSE_MAX_HOPS_FIELD_NUMBER: _ClassVar[int]
POSITION_DEDUP_ENABLED_FIELD_NUMBER: _ClassVar[int]
POSITION_MIN_INTERVAL_SECS_FIELD_NUMBER: _ClassVar[int]
POSITION_PRECISION_BITS_FIELD_NUMBER: _ClassVar[int]
RATE_LIMIT_ENABLED_FIELD_NUMBER: _ClassVar[int]
RATE_LIMIT_MAX_PACKETS_FIELD_NUMBER: _ClassVar[int]
RATE_LIMIT_WINDOW_SECS_FIELD_NUMBER: _ClassVar[int]
ROUTER_PRESERVE_HOPS_FIELD_NUMBER: _ClassVar[int]
UNKNOWN_PACKET_THRESHOLD_FIELD_NUMBER: _ClassVar[int]
drop_unknown_enabled: bool
enabled: bool
exhaust_hop_position: bool
exhaust_hop_telemetry: bool
nodeinfo_direct_response: bool
nodeinfo_direct_response_max_hops: int
position_dedup_enabled: bool
position_min_interval_secs: int
position_precision_bits: int
rate_limit_enabled: bool
rate_limit_max_packets: int
rate_limit_window_secs: int
router_preserve_hops: bool
unknown_packet_threshold: int
def __init__(self, position_min_interval_secs: _Optional[int] = ..., nodeinfo_direct_response_max_hops: _Optional[int] = ..., rate_limit_window_secs: _Optional[int] = ..., rate_limit_max_packets: _Optional[int] = ..., unknown_packet_threshold: _Optional[int] = ...) -> None: ...
def __init__(self, enabled: bool = ..., position_dedup_enabled: bool = ..., position_precision_bits: _Optional[int] = ..., position_min_interval_secs: _Optional[int] = ..., nodeinfo_direct_response: bool = ..., nodeinfo_direct_response_max_hops: _Optional[int] = ..., rate_limit_enabled: bool = ..., rate_limit_window_secs: _Optional[int] = ..., rate_limit_max_packets: _Optional[int] = ..., drop_unknown_enabled: bool = ..., unknown_packet_threshold: _Optional[int] = ..., exhaust_hop_telemetry: bool = ..., exhaust_hop_position: bool = ..., router_preserve_hops: bool = ...) -> None: ...
AMBIENT_LIGHTING_FIELD_NUMBER: _ClassVar[int]
AUDIO_FIELD_NUMBER: _ClassVar[int]
CANNED_MESSAGE_FIELD_NUMBER: _ClassVar[int]
DETECTION_SENSOR_FIELD_NUMBER: _ClassVar[int]
EXTERNAL_NOTIFICATION_FIELD_NUMBER: _ClassVar[int]
MESH_BEACON_FIELD_NUMBER: _ClassVar[int]
MQTT_FIELD_NUMBER: _ClassVar[int]
NEIGHBOR_INFO_FIELD_NUMBER: _ClassVar[int]
PAXCOUNTER_FIELD_NUMBER: _ClassVar[int]
@@ -409,7 +384,6 @@ class ModuleConfig(_message.Message):
canned_message: ModuleConfig.CannedMessageConfig
detection_sensor: ModuleConfig.DetectionSensorConfig
external_notification: ModuleConfig.ExternalNotificationConfig
mesh_beacon: ModuleConfig.MeshBeaconConfig
mqtt: ModuleConfig.MQTTConfig
neighbor_info: ModuleConfig.NeighborInfoConfig
paxcounter: ModuleConfig.PaxcounterConfig
@@ -421,7 +395,7 @@ class ModuleConfig(_message.Message):
tak: ModuleConfig.TAKConfig
telemetry: ModuleConfig.TelemetryConfig
traffic_management: ModuleConfig.TrafficManagementConfig
def __init__(self, mqtt: _Optional[_Union[ModuleConfig.MQTTConfig, _Mapping]] = ..., serial: _Optional[_Union[ModuleConfig.SerialConfig, _Mapping]] = ..., external_notification: _Optional[_Union[ModuleConfig.ExternalNotificationConfig, _Mapping]] = ..., store_forward: _Optional[_Union[ModuleConfig.StoreForwardConfig, _Mapping]] = ..., range_test: _Optional[_Union[ModuleConfig.RangeTestConfig, _Mapping]] = ..., telemetry: _Optional[_Union[ModuleConfig.TelemetryConfig, _Mapping]] = ..., canned_message: _Optional[_Union[ModuleConfig.CannedMessageConfig, _Mapping]] = ..., audio: _Optional[_Union[ModuleConfig.AudioConfig, _Mapping]] = ..., remote_hardware: _Optional[_Union[ModuleConfig.RemoteHardwareConfig, _Mapping]] = ..., neighbor_info: _Optional[_Union[ModuleConfig.NeighborInfoConfig, _Mapping]] = ..., ambient_lighting: _Optional[_Union[ModuleConfig.AmbientLightingConfig, _Mapping]] = ..., detection_sensor: _Optional[_Union[ModuleConfig.DetectionSensorConfig, _Mapping]] = ..., paxcounter: _Optional[_Union[ModuleConfig.PaxcounterConfig, _Mapping]] = ..., statusmessage: _Optional[_Union[ModuleConfig.StatusMessageConfig, _Mapping]] = ..., traffic_management: _Optional[_Union[ModuleConfig.TrafficManagementConfig, _Mapping]] = ..., tak: _Optional[_Union[ModuleConfig.TAKConfig, _Mapping]] = ..., mesh_beacon: _Optional[_Union[ModuleConfig.MeshBeaconConfig, _Mapping]] = ...) -> None: ...
def __init__(self, mqtt: _Optional[_Union[ModuleConfig.MQTTConfig, _Mapping]] = ..., serial: _Optional[_Union[ModuleConfig.SerialConfig, _Mapping]] = ..., external_notification: _Optional[_Union[ModuleConfig.ExternalNotificationConfig, _Mapping]] = ..., store_forward: _Optional[_Union[ModuleConfig.StoreForwardConfig, _Mapping]] = ..., range_test: _Optional[_Union[ModuleConfig.RangeTestConfig, _Mapping]] = ..., telemetry: _Optional[_Union[ModuleConfig.TelemetryConfig, _Mapping]] = ..., canned_message: _Optional[_Union[ModuleConfig.CannedMessageConfig, _Mapping]] = ..., audio: _Optional[_Union[ModuleConfig.AudioConfig, _Mapping]] = ..., remote_hardware: _Optional[_Union[ModuleConfig.RemoteHardwareConfig, _Mapping]] = ..., neighbor_info: _Optional[_Union[ModuleConfig.NeighborInfoConfig, _Mapping]] = ..., ambient_lighting: _Optional[_Union[ModuleConfig.AmbientLightingConfig, _Mapping]] = ..., detection_sensor: _Optional[_Union[ModuleConfig.DetectionSensorConfig, _Mapping]] = ..., paxcounter: _Optional[_Union[ModuleConfig.PaxcounterConfig, _Mapping]] = ..., statusmessage: _Optional[_Union[ModuleConfig.StatusMessageConfig, _Mapping]] = ..., traffic_management: _Optional[_Union[ModuleConfig.TrafficManagementConfig, _Mapping]] = ..., tak: _Optional[_Union[ModuleConfig.TAKConfig, _Mapping]] = ...) -> None: ...
class RemoteHardwarePin(_message.Message):
__slots__ = ["gpio_pin", "name", "type"]
+2 -2
View File
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\xb4\x06\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\x14\n\x10REMOTE_SHELL_APP\x10\r\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x1e\n\x1aSTORE_FORWARD_PLUSPLUS_APP\x10#\x12\x13\n\x0fNODE_STATUS_APP\x10$\x12\x13\n\x0fMESH_BEACON_APP\x10%\x12\x0e\n\nPAGING_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\x12\n\x0eLORAWAN_BRIDGE\x10K\x12\x18\n\x14RETICULUM_TUNNEL_APP\x10L\x12\x0f\n\x0b\x43\x41YENNE_APP\x10M\x12\x12\n\x0e\x41TAK_PLUGIN_V2\x10N\x12\x10\n\x0cLORA_OTA_APP\x10O\x12\x12\n\x0eGROUPALARM_APP\x10p\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')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\xfd\x05\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\x14\n\x10REMOTE_SHELL_APP\x10\r\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x1e\n\x1aSTORE_FORWARD_PLUSPLUS_APP\x10#\x12\x13\n\x0fNODE_STATUS_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\x12\n\x0eLORAWAN_BRIDGE\x10K\x12\x18\n\x14RETICULUM_TUNNEL_APP\x10L\x12\x0f\n\x0b\x43\x41YENNE_APP\x10M\x12\x12\n\x0e\x41TAK_PLUGIN_V2\x10N\x12\x12\n\x0eGROUPALARM_APP\x10p\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')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.portnums_pb2', globals())
@@ -22,5 +22,5 @@ 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'
_PORTNUM._serialized_start=60
_PORTNUM._serialized_end=880
_PORTNUM._serialized_end=825
# @@protoc_insertion_point(module_scope)
-3
View File
@@ -15,14 +15,11 @@ GROUPALARM_APP: PortNum
IP_TUNNEL_APP: PortNum
KEY_VERIFICATION_APP: PortNum
LORAWAN_BRIDGE: PortNum
LORA_OTA_APP: PortNum
MAP_REPORT_APP: PortNum
MAX: PortNum
MESH_BEACON_APP: PortNum
NEIGHBORINFO_APP: PortNum
NODEINFO_APP: PortNum
NODE_STATUS_APP: PortNum
PAGING_APP: PortNum
PAXCOUNTER_APP: PortNum
POSITION_APP: PortNum
POWERSTRESS_APP: PortNum
+10 -10
View File
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&meshtastic/protobuf/storeforward.proto\x12\x13meshtastic.protobuf\"\xd5\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\x12\x13\n\x0boriginal_id\x18\x06 \x01(\r\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')
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')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.storeforward_pb2', globals())
@@ -22,13 +22,13 @@ 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'
_STOREANDFORWARD._serialized_start=64
_STOREANDFORWARD._serialized_end=1045
_STOREANDFORWARD_STATISTICS._serialized_start=387
_STOREANDFORWARD_STATISTICS._serialized_end=592
_STOREANDFORWARD_HISTORY._serialized_start=594
_STOREANDFORWARD_HISTORY._serialized_end=667
_STOREANDFORWARD_HEARTBEAT._serialized_start=669
_STOREANDFORWARD_HEARTBEAT._serialized_end=715
_STOREANDFORWARD_REQUESTRESPONSE._serialized_start=718
_STOREANDFORWARD_REQUESTRESPONSE._serialized_end=1034
_STOREANDFORWARD._serialized_end=1024
_STOREANDFORWARD_STATISTICS._serialized_start=366
_STOREANDFORWARD_STATISTICS._serialized_end=571
_STOREANDFORWARD_HISTORY._serialized_start=573
_STOREANDFORWARD_HISTORY._serialized_end=646
_STOREANDFORWARD_HEARTBEAT._serialized_start=648
_STOREANDFORWARD_HEARTBEAT._serialized_end=694
_STOREANDFORWARD_REQUESTRESPONSE._serialized_start=697
_STOREANDFORWARD_REQUESTRESPONSE._serialized_end=1013
# @@protoc_insertion_point(module_scope)
+2 -4
View File
@@ -6,7 +6,7 @@ from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Opti
DESCRIPTOR: _descriptor.FileDescriptor
class StoreAndForward(_message.Message):
__slots__ = ["heartbeat", "history", "original_id", "rr", "stats", "text"]
__slots__ = ["heartbeat", "history", "rr", "stats", "text"]
class RequestResponse(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = []
class Heartbeat(_message.Message):
@@ -54,7 +54,6 @@ class StoreAndForward(_message.Message):
CLIENT_STATS: StoreAndForward.RequestResponse
HEARTBEAT_FIELD_NUMBER: _ClassVar[int]
HISTORY_FIELD_NUMBER: _ClassVar[int]
ORIGINAL_ID_FIELD_NUMBER: _ClassVar[int]
ROUTER_BUSY: StoreAndForward.RequestResponse
ROUTER_ERROR: StoreAndForward.RequestResponse
ROUTER_HEARTBEAT: StoreAndForward.RequestResponse
@@ -70,8 +69,7 @@ class StoreAndForward(_message.Message):
UNSET: StoreAndForward.RequestResponse
heartbeat: StoreAndForward.Heartbeat
history: StoreAndForward.History
original_id: int
rr: StoreAndForward.RequestResponse
stats: StoreAndForward.Statistics
text: bytes
def __init__(self, rr: _Optional[_Union[StoreAndForward.RequestResponse, str]] = ..., stats: _Optional[_Union[StoreAndForward.Statistics, _Mapping]] = ..., history: _Optional[_Union[StoreAndForward.History, _Mapping]] = ..., heartbeat: _Optional[_Union[StoreAndForward.Heartbeat, _Mapping]] = ..., text: _Optional[bytes] = ..., original_id: _Optional[int] = ...) -> None: ...
def __init__(self, rr: _Optional[_Union[StoreAndForward.RequestResponse, str]] = ..., stats: _Optional[_Union[StoreAndForward.Statistics, _Mapping]] = ..., history: _Optional[_Union[StoreAndForward.History, _Mapping]] = ..., heartbeat: _Optional[_Union[StoreAndForward.Heartbeat, _Mapping]] = ..., text: _Optional[bytes] = ...) -> None: ...
+22 -58
View File
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/telemetry.proto\x12\x13meshtastic.protobuf\"\xf3\x01\n\rDeviceMetrics\x12\x1a\n\rbattery_level\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x14\n\x07voltage\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12 \n\x13\x63hannel_utilization\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x18\n\x0b\x61ir_util_tx\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x1b\n\x0euptime_seconds\x18\x05 \x01(\rH\x04\x88\x01\x01\x42\x10\n\x0e_battery_levelB\n\n\x08_voltageB\x16\n\x14_channel_utilizationB\x0e\n\x0c_air_util_txB\x11\n\x0f_uptime_seconds\"\xa9\x11\n\x12\x45nvironmentMetrics\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x1e\n\x11relative_humidity\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12 \n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x1b\n\x0egas_resistance\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x14\n\x07voltage\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x14\n\x07\x63urrent\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x10\n\x03iaq\x18\x07 \x01(\rH\x06\x88\x01\x01\x12\x15\n\x08\x64istance\x18\x08 \x01(\x02H\x07\x88\x01\x01\x12\x10\n\x03lux\x18\t \x01(\x02H\x08\x88\x01\x01\x12\x16\n\twhite_lux\x18\n \x01(\x02H\t\x88\x01\x01\x12\x13\n\x06ir_lux\x18\x0b \x01(\x02H\n\x88\x01\x01\x12\x13\n\x06uv_lux\x18\x0c \x01(\x02H\x0b\x88\x01\x01\x12\x1b\n\x0ewind_direction\x18\r \x01(\rH\x0c\x88\x01\x01\x12\x17\n\nwind_speed\x18\x0e \x01(\x02H\r\x88\x01\x01\x12\x13\n\x06weight\x18\x0f \x01(\x02H\x0e\x88\x01\x01\x12\x16\n\twind_gust\x18\x10 \x01(\x02H\x0f\x88\x01\x01\x12\x16\n\twind_lull\x18\x11 \x01(\x02H\x10\x88\x01\x01\x12\x16\n\tradiation\x18\x12 \x01(\x02H\x11\x88\x01\x01\x12\x18\n\x0brainfall_1h\x18\x13 \x01(\x02H\x12\x88\x01\x01\x12\x19\n\x0crainfall_24h\x18\x14 \x01(\x02H\x13\x88\x01\x01\x12\x1a\n\rsoil_moisture\x18\x15 \x01(\rH\x14\x88\x01\x01\x12\x1d\n\x10soil_temperature\x18\x16 \x01(\x02H\x15\x88\x01\x01\x12 \n\x14one_wire_temperature\x18\x17 \x03(\x02\x42\x02\x18\x01\x12\x1c\n\x0f\x61\x64\x63_voltage_ch0\x18\x18 \x01(\x02H\x16\x88\x01\x01\x12\x1c\n\x0f\x61\x64\x63_voltage_ch1\x18\x19 \x01(\x02H\x17\x88\x01\x01\x12\x1c\n\x0f\x61\x64\x63_voltage_ch2\x18\x1a \x01(\x02H\x18\x88\x01\x01\x12\x1c\n\x0f\x61\x64\x63_voltage_ch3\x18\x1b \x01(\x02H\x19\x88\x01\x01\x12\x1c\n\x0f\x61\x64\x63_voltage_ch4\x18\x1c \x01(\x02H\x1a\x88\x01\x01\x12\x1c\n\x0f\x61\x64\x63_voltage_ch5\x18\x1d \x01(\x02H\x1b\x88\x01\x01\x12\x1c\n\x0f\x61\x64\x63_voltage_ch6\x18\x1e \x01(\x02H\x1c\x88\x01\x01\x12\x1c\n\x0f\x61\x64\x63_voltage_ch7\x18\x1f \x01(\x02H\x1d\x88\x01\x01\x12%\n\x18one_wire_temperature_ch0\x18 \x01(\x02H\x1e\x88\x01\x01\x12%\n\x18one_wire_temperature_ch1\x18! \x01(\x02H\x1f\x88\x01\x01\x12%\n\x18one_wire_temperature_ch2\x18\" \x01(\x02H \x88\x01\x01\x12%\n\x18one_wire_temperature_ch3\x18# \x01(\x02H!\x88\x01\x01\x12%\n\x18one_wire_temperature_ch4\x18$ \x01(\x02H\"\x88\x01\x01\x12%\n\x18one_wire_temperature_ch5\x18% \x01(\x02H#\x88\x01\x01\x12%\n\x18one_wire_temperature_ch6\x18& \x01(\x02H$\x88\x01\x01\x12%\n\x18one_wire_temperature_ch7\x18\' \x01(\x02H%\x88\x01\x01\x12&\n\x19lightning_strike_count_1h\x18( \x01(\rH&\x88\x01\x01\x12\"\n\x15lightning_distance_km\x18) \x01(\x02H\'\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x14\n\x12_relative_humidityB\x16\n\x14_barometric_pressureB\x11\n\x0f_gas_resistanceB\n\n\x08_voltageB\n\n\x08_currentB\x06\n\x04_iaqB\x0b\n\t_distanceB\x06\n\x04_luxB\x0c\n\n_white_luxB\t\n\x07_ir_luxB\t\n\x07_uv_luxB\x11\n\x0f_wind_directionB\r\n\x0b_wind_speedB\t\n\x07_weightB\x0c\n\n_wind_gustB\x0c\n\n_wind_lullB\x0c\n\n_radiationB\x0e\n\x0c_rainfall_1hB\x0f\n\r_rainfall_24hB\x10\n\x0e_soil_moistureB\x13\n\x11_soil_temperatureB\x12\n\x10_adc_voltage_ch0B\x12\n\x10_adc_voltage_ch1B\x12\n\x10_adc_voltage_ch2B\x12\n\x10_adc_voltage_ch3B\x12\n\x10_adc_voltage_ch4B\x12\n\x10_adc_voltage_ch5B\x12\n\x10_adc_voltage_ch6B\x12\n\x10_adc_voltage_ch7B\x1b\n\x19_one_wire_temperature_ch0B\x1b\n\x19_one_wire_temperature_ch1B\x1b\n\x19_one_wire_temperature_ch2B\x1b\n\x19_one_wire_temperature_ch3B\x1b\n\x19_one_wire_temperature_ch4B\x1b\n\x19_one_wire_temperature_ch5B\x1b\n\x19_one_wire_temperature_ch6B\x1b\n\x19_one_wire_temperature_ch7B\x1c\n\x1a_lightning_strike_count_1hB\x18\n\x16_lightning_distance_kmJ\x04\x08*\x10\x39R\x07soil_phR\x02phR\x17\x65lectrical_conductivityR\x08salinityR\x08nitrogenR\nphosphorusR\tpotassiumR\x10\x64issolved_oxygenR\x03orpR\x16\x63hemical_oxygen_demandR\tturbidityR\x07nitrateR\x08\x61mmoniumR\x19\x62iochemical_oxygen_demandR\x10solar_irradiance\"\x98\x05\n\x10SoilWaterMetrics\x12\x14\n\x07soil_ph\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x0f\n\x02ph\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12$\n\x17\x65lectrical_conductivity\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x15\n\x08salinity\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x15\n\x08nitrogen\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x17\n\nphosphorus\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x16\n\tpotassium\x18\x07 \x01(\x02H\x06\x88\x01\x01\x12\x1d\n\x10\x64issolved_oxygen\x18\x08 \x01(\x02H\x07\xLine truncated
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/telemetry.proto\x12\x13meshtastic.protobuf\"\xf3\x01\n\rDeviceMetrics\x12\x1a\n\rbattery_level\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x14\n\x07voltage\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12 \n\x13\x63hannel_utilization\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x18\n\x0b\x61ir_util_tx\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x1b\n\x0euptime_seconds\x18\x05 \x01(\rH\x04\x88\x01\x01\x42\x10\n\x0e_battery_levelB\n\n\x08_voltageB\x16\n\x14_channel_utilizationB\x0e\n\x0c_air_util_txB\x11\n\x0f_uptime_seconds\"\xa0\x07\n\x12\x45nvironmentMetrics\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x1e\n\x11relative_humidity\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12 \n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x1b\n\x0egas_resistance\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x14\n\x07voltage\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x14\n\x07\x63urrent\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x10\n\x03iaq\x18\x07 \x01(\rH\x06\x88\x01\x01\x12\x15\n\x08\x64istance\x18\x08 \x01(\x02H\x07\x88\x01\x01\x12\x10\n\x03lux\x18\t \x01(\x02H\x08\x88\x01\x01\x12\x16\n\twhite_lux\x18\n \x01(\x02H\t\x88\x01\x01\x12\x13\n\x06ir_lux\x18\x0b \x01(\x02H\n\x88\x01\x01\x12\x13\n\x06uv_lux\x18\x0c \x01(\x02H\x0b\x88\x01\x01\x12\x1b\n\x0ewind_direction\x18\r \x01(\rH\x0c\x88\x01\x01\x12\x17\n\nwind_speed\x18\x0e \x01(\x02H\r\x88\x01\x01\x12\x13\n\x06weight\x18\x0f \x01(\x02H\x0e\x88\x01\x01\x12\x16\n\twind_gust\x18\x10 \x01(\x02H\x0f\x88\x01\x01\x12\x16\n\twind_lull\x18\x11 \x01(\x02H\x10\x88\x01\x01\x12\x16\n\tradiation\x18\x12 \x01(\x02H\x11\x88\x01\x01\x12\x18\n\x0brainfall_1h\x18\x13 \x01(\x02H\x12\x88\x01\x01\x12\x19\n\x0crainfall_24h\x18\x14 \x01(\x02H\x13\x88\x01\x01\x12\x1a\n\rsoil_moisture\x18\x15 \x01(\rH\x14\x88\x01\x01\x12\x1d\n\x10soil_temperature\x18\x16 \x01(\x02H\x15\x88\x01\x01\x12\x1c\n\x14one_wire_temperature\x18\x17 \x03(\x02\x42\x0e\n\x0c_temperatureB\x14\n\x12_relative_humidityB\x16\n\x14_barometric_pressureB\x11\n\x0f_gas_resistanceB\n\n\x08_voltageB\n\n\x08_currentB\x06\n\x04_iaqB\x0b\n\t_distanceB\x06\n\x04_luxB\x0c\n\n_white_luxB\t\n\x07_ir_luxB\t\n\x07_uv_luxB\x11\n\x0f_wind_directionB\r\n\x0b_wind_speedB\t\n\x07_weightB\x0c\n\n_wind_gustB\x0c\n\n_wind_lullB\x0c\n\n_radiationB\x0e\n\x0c_rainfall_1hB\x0f\n\r_rainfall_24hB\x10\n\x0e_soil_moistureB\x13\n\x11_soil_temperature\"\xae\x05\n\x0cPowerMetrics\x12\x18\n\x0b\x63h1_voltage\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x18\n\x0b\x63h1_current\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x18\n\x0b\x63h2_voltage\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x18\n\x0b\x63h2_current\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x18\n\x0b\x63h3_voltage\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x18\n\x0b\x63h3_current\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x18\n\x0b\x63h4_voltage\x18\x07 \x01(\x02H\x06\x88\x01\x01\x12\x18\n\x0b\x63h4_current\x18\x08 \x01(\x02H\x07\x88\x01\x01\x12\x18\n\x0b\x63h5_voltage\x18\t \x01(\x02H\x08\x88\x01\x01\x12\x18\n\x0b\x63h5_current\x18\n \x01(\x02H\t\x88\x01\x01\x12\x18\n\x0b\x63h6_voltage\x18\x0b \x01(\x02H\n\x88\x01\x01\x12\x18\n\x0b\x63h6_current\x18\x0c \x01(\x02H\x0b\x88\x01\x01\x12\x18\n\x0b\x63h7_voltage\x18\r \x01(\x02H\x0c\x88\x01\x01\x12\x18\n\x0b\x63h7_current\x18\x0e \x01(\x02H\r\x88\x01\x01\x12\x18\n\x0b\x63h8_voltage\x18\x0f \x01(\x02H\x0e\x88\x01\x01\x12\x18\n\x0b\x63h8_current\x18\x10 \x01(\x02H\x0f\x88\x01\x01\x42\x0e\n\x0c_ch1_voltageB\x0e\n\x0c_ch1_currentB\x0e\n\x0c_ch2_voltageB\x0e\n\x0c_ch2_currentB\x0e\n\x0c_ch3_voltageB\x0e\n\x0c_ch3_currentB\x0e\n\x0c_ch4_voltageB\x0e\n\x0c_ch4_currentB\x0e\n\x0c_ch5_voltageB\x0e\n\x0c_ch5_currentB\x0e\n\x0c_ch6_voltageB\x0e\n\x0c_ch6_currentB\x0e\n\x0c_ch7_voltageB\x0e\n\x0c_ch7_currentB\x0e\n\x0c_ch8_voltageB\x0e\n\x0c_ch8_current\"\xb1\t\n\x11\x41irQualityMetrics\x12\x1a\n\rpm10_standard\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x1a\n\rpm25_standard\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1b\n\x0epm100_standard\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x1f\n\x12pm10_environmental\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x1f\n\x12pm25_environmental\x18\x05 \x01(\rH\x04\x88\x01\x01\x12 \n\x13pm100_environmental\x18\x06 \x01(\rH\x05\x88\x01\x01\x12\x1b\n\x0eparticles_03um\x18\x07 \x01(\rH\x06\x88\x01\x01\x12\x1b\n\x0eparticles_05um\x18\x08 \x01(\rH\x07\x88\x01\x01\x12\x1b\n\x0eparticles_10um\x18\t \x01(\rH\x08\x88\x01\x01\x12\x1b\n\x0eparticles_25um\x18\n \x01(\rH\t\x88\x01\x01\x12\x1b\n\x0eparticles_50um\x18\x0b \x01(\rH\n\x88\x01\x01\x12\x1c\n\x0fparticles_100um\x18\x0c \x01(\rH\x0b\x88\x01\x01\x12\x10\n\x03\x63o2\x18\r \x01(\rH\x0c\x88\x01\x01\x12\x1c\n\x0f\x63o2_temperature\x18\x0e \x01(\x02H\r\x88\x01\x01\x12\x19\n\x0c\x63o2_humidity\x18\x0f \x01(\x02H\x0e\x88\x01\x01\x12\x1e\n\x11\x66orm_formaldehyde\x18\x10 \x01(\x02H\x0f\x88\x01\x01\x12\x1a\n\rform_humidity\x18\x11 \x01(\x02H\x10\x88\x01\x01\x12\x1d\n\x10\x66orm_temperature\x18\x12 \x01(\x02H\x11\x88\x01\x01\x12\x1a\n\rpm40_standard\x18\x13 \x01(\rH\x12\x88\x01Line truncated
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.telemetry_pb2', globals())
@@ -21,64 +21,28 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\017TelemetryProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_TELEMETRYSENSORTYPE.values_by_name["SHTC3"]._options = None
_TELEMETRYSENSORTYPE.values_by_name["SHTC3"]._serialized_options = b'\010\001'
_TELEMETRYSENSORTYPE.values_by_name["SHT31"]._options = None
_TELEMETRYSENSORTYPE.values_by_name["SHT31"]._serialized_options = b'\010\001'
_TELEMETRYSENSORTYPE.values_by_name["SHT4X"]._options = None
_TELEMETRYSENSORTYPE.values_by_name["SHT4X"]._serialized_options = b'\010\001'
_TELEMETRYSENSORTYPE.values_by_name["SHT21"]._options = None
_TELEMETRYSENSORTYPE.values_by_name["SHT21"]._serialized_options = b'\010\001'
_ENVIRONMENTMETRICS.fields_by_name['one_wire_temperature']._options = None
_ENVIRONMENTMETRICS.fields_by_name['one_wire_temperature']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch4_voltage']._options = None
_POWERMETRICS.fields_by_name['ch4_voltage']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch4_current']._options = None
_POWERMETRICS.fields_by_name['ch4_current']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch5_voltage']._options = None
_POWERMETRICS.fields_by_name['ch5_voltage']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch5_current']._options = None
_POWERMETRICS.fields_by_name['ch5_current']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch6_voltage']._options = None
_POWERMETRICS.fields_by_name['ch6_voltage']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch6_current']._options = None
_POWERMETRICS.fields_by_name['ch6_current']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch7_voltage']._options = None
_POWERMETRICS.fields_by_name['ch7_voltage']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch7_current']._options = None
_POWERMETRICS.fields_by_name['ch7_current']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch8_voltage']._options = None
_POWERMETRICS.fields_by_name['ch8_voltage']._serialized_options = b'\030\001'
_POWERMETRICS.fields_by_name['ch8_current']._options = None
_POWERMETRICS.fields_by_name['ch8_current']._serialized_options = b'\030\001'
_TELEMETRYSENSORTYPE._serialized_start=7413
_TELEMETRYSENSORTYPE._serialized_end=8207
_TELEMETRYSENSORTYPE._serialized_start=5017
_TELEMETRYSENSORTYPE._serialized_end=5749
_DEVICEMETRICS._serialized_start=61
_DEVICEMETRICS._serialized_end=304
_ENVIRONMENTMETRICS._serialized_start=307
_ENVIRONMENTMETRICS._serialized_end=2524
_SOILWATERMETRICS._serialized_start=2527
_SOILWATERMETRICS._serialized_end=3191
_POWERMETRICS._serialized_start=3194
_POWERMETRICS._serialized_end=3920
_AIRQUALITYMETRICS._serialized_start=3923
_AIRQUALITYMETRICS._serialized_end=5174
_LOCALSTATS._serialized_start=5177
_LOCALSTATS._serialized_end=5560
_TRAFFICMANAGEMENTSTATS._serialized_start=5563
_TRAFFICMANAGEMENTSTATS._serialized_end=5791
_HEALTHMETRICS._serialized_start=5793
_HEALTHMETRICS._serialized_end=5916
_HOSTMETRICS._serialized_start=5919
_HOSTMETRICS._serialized_end=6192
_TELEMETRY._serialized_start=6195
_TELEMETRY._serialized_end=6822
_NAU7802CONFIG._serialized_start=6824
_NAU7802CONFIG._serialized_end=6886
_AS3935STATE._serialized_start=6888
_AS3935STATE._serialized_end=6924
_SEN5XSTATE._serialized_start=6927
_SEN5XSTATE._serialized_end=7167
_SEN6XSTATE._serialized_start=7170
_SEN6XSTATE._serialized_end=7410
_ENVIRONMENTMETRICS._serialized_end=1235
_POWERMETRICS._serialized_start=1238
_POWERMETRICS._serialized_end=1924
_AIRQUALITYMETRICS._serialized_start=1927
_AIRQUALITYMETRICS._serialized_end=3128
_LOCALSTATS._serialized_start=3131
_LOCALSTATS._serialized_end=3514
_TRAFFICMANAGEMENTSTATS._serialized_start=3517
_TRAFFICMANAGEMENTSTATS._serialized_end=3745
_HEALTHMETRICS._serialized_start=3747
_HEALTHMETRICS._serialized_end=3870
_HOSTMETRICS._serialized_start=3873
_HOSTMETRICS._serialized_end=4146
_TELEMETRY._serialized_start=4149
_TELEMETRY._serialized_end=4707
_NAU7802CONFIG._serialized_start=4709
_NAU7802CONFIG._serialized_end=4771
_SEN5XSTATE._serialized_start=4774
_SEN5XSTATE._serialized_end=5014
# @@protoc_insertion_point(module_scope)
+6 -106
View File
@@ -7,7 +7,6 @@ from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Map
ADS1X15: TelemetrySensorType
ADS1X15_ALT: TelemetrySensorType
AHT10: TelemetrySensorType
AS3935: TelemetrySensorType
BH1750: TelemetrySensorType
BME280: TelemetrySensorType
BME680: TelemetrySensorType
@@ -21,7 +20,6 @@ DFROBOT_RAIN: TelemetrySensorType
DPS310: TelemetrySensorType
DS248X: TelemetrySensorType
HDC1080: TelemetrySensorType
HM330X: TelemetrySensorType
ICM20948: TelemetrySensorType
ICM42607P: TelemetrySensorType
INA219: TelemetrySensorType
@@ -50,7 +48,6 @@ RCWL9620: TelemetrySensorType
SCD30: TelemetrySensorType
SCD4X: TelemetrySensorType
SEN5X: TelemetrySensorType
SEN6X: TelemetrySensorType
SENSOR_UNSET: TelemetrySensorType
SFA30: TelemetrySensorType
SHT21: TelemetrySensorType
@@ -58,20 +55,13 @@ SHT31: TelemetrySensorType
SHT4X: TelemetrySensorType
SHTC3: TelemetrySensorType
SHTXX: TelemetrySensorType
SPA06: TelemetrySensorType
STC31: TelemetrySensorType
TSL2561: TelemetrySensorType
TSL25911FN: TelemetrySensorType
VEML7700: TelemetrySensorType
class AS3935State(_message.Message):
__slots__ = ["tuning_cap_pf"]
TUNING_CAP_PF_FIELD_NUMBER: _ClassVar[int]
tuning_cap_pf: int
def __init__(self, tuning_cap_pf: _Optional[int] = ...) -> None: ...
class AirQualityMetrics(_message.Message):
__slots__ = ["co2", "co2_humidity", "co2_temperature", "form_formaldehyde", "form_humidity", "form_temperature", "particles_03um", "particles_05um", "particles_100um", "particles_10um", "particles_25um", "particles_40um", "particles_50um", "particles_tps", "pm100_environmental", "pm100_standard", "pm10_environmental", "pm10_standard", "pm25_environmental", "pm25_standard", "pm40_standard", "pm_humidity", "pm_nox_idx", "pm_status_flags", "pm_temperature", "pm_voc_idx"]
__slots__ = ["co2", "co2_humidity", "co2_temperature", "form_formaldehyde", "form_humidity", "form_temperature", "particles_03um", "particles_05um", "particles_100um", "particles_10um", "particles_25um", "particles_40um", "particles_50um", "particles_tps", "pm100_environmental", "pm100_standard", "pm10_environmental", "pm10_standard", "pm25_environmental", "pm25_standard", "pm40_standard", "pm_humidity", "pm_nox_idx", "pm_temperature", "pm_voc_idx"]
CO2_FIELD_NUMBER: _ClassVar[int]
CO2_HUMIDITY_FIELD_NUMBER: _ClassVar[int]
CO2_TEMPERATURE_FIELD_NUMBER: _ClassVar[int]
@@ -95,7 +85,6 @@ class AirQualityMetrics(_message.Message):
PM40_STANDARD_FIELD_NUMBER: _ClassVar[int]
PM_HUMIDITY_FIELD_NUMBER: _ClassVar[int]
PM_NOX_IDX_FIELD_NUMBER: _ClassVar[int]
PM_STATUS_FLAGS_FIELD_NUMBER: _ClassVar[int]
PM_TEMPERATURE_FIELD_NUMBER: _ClassVar[int]
PM_VOC_IDX_FIELD_NUMBER: _ClassVar[int]
co2: int
@@ -121,10 +110,9 @@ class AirQualityMetrics(_message.Message):
pm40_standard: int
pm_humidity: float
pm_nox_idx: float
pm_status_flags: int
pm_temperature: float
pm_voc_idx: float
def __init__(self, pm10_standard: _Optional[int] = ..., pm25_standard: _Optional[int] = ..., pm100_standard: _Optional[int] = ..., pm10_environmental: _Optional[int] = ..., pm25_environmental: _Optional[int] = ..., pm100_environmental: _Optional[int] = ..., particles_03um: _Optional[int] = ..., particles_05um: _Optional[int] = ..., particles_10um: _Optional[int] = ..., particles_25um: _Optional[int] = ..., particles_50um: _Optional[int] = ..., particles_100um: _Optional[int] = ..., co2: _Optional[int] = ..., co2_temperature: _Optional[float] = ..., co2_humidity: _Optional[float] = ..., form_formaldehyde: _Optional[float] = ..., form_humidity: _Optional[float] = ..., form_temperature: _Optional[float] = ..., pm40_standard: _Optional[int] = ..., particles_40um: _Optional[int] = ..., pm_temperature: _Optional[float] = ..., pm_humidity: _Optional[float] = ..., pm_voc_idx: _Optional[float] = ..., pm_nox_idx: _Optional[float] = ..., particles_tps: _Optional[float] = ..., pm_status_flags: _Optional[int] = ...) -> None: ...
def __init__(self, pm10_standard: _Optional[int] = ..., pm25_standard: _Optional[int] = ..., pm100_standard: _Optional[int] = ..., pm10_environmental: _Optional[int] = ..., pm25_environmental: _Optional[int] = ..., pm100_environmental: _Optional[int] = ..., particles_03um: _Optional[int] = ..., particles_05um: _Optional[int] = ..., particles_10um: _Optional[int] = ..., particles_25um: _Optional[int] = ..., particles_50um: _Optional[int] = ..., particles_100um: _Optional[int] = ..., co2: _Optional[int] = ..., co2_temperature: _Optional[float] = ..., co2_humidity: _Optional[float] = ..., form_formaldehyde: _Optional[float] = ..., form_humidity: _Optional[float] = ..., form_temperature: _Optional[float] = ..., pm40_standard: _Optional[int] = ..., particles_40um: _Optional[int] = ..., pm_temperature: _Optional[float] = ..., pm_humidity: _Optional[float] = ..., pm_voc_idx: _Optional[float] = ..., pm_nox_idx: _Optional[float] = ..., particles_tps: _Optional[float] = ...) -> None: ...
class DeviceMetrics(_message.Message):
__slots__ = ["air_util_tx", "battery_level", "channel_utilization", "uptime_seconds", "voltage"]
@@ -141,32 +129,14 @@ class DeviceMetrics(_message.Message):
def __init__(self, battery_level: _Optional[int] = ..., voltage: _Optional[float] = ..., channel_utilization: _Optional[float] = ..., air_util_tx: _Optional[float] = ..., uptime_seconds: _Optional[int] = ...) -> None: ...
class EnvironmentMetrics(_message.Message):
__slots__ = ["adc_voltage_ch0", "adc_voltage_ch1", "adc_voltage_ch2", "adc_voltage_ch3", "adc_voltage_ch4", "adc_voltage_ch5", "adc_voltage_ch6", "adc_voltage_ch7", "barometric_pressure", "current", "distance", "gas_resistance", "iaq", "ir_lux", "lightning_distance_km", "lightning_strike_count_1h", "lux", "one_wire_temperature", "one_wire_temperature_ch0", "one_wire_temperature_ch1", "one_wire_temperature_ch2", "one_wire_temperature_ch3", "one_wire_temperature_ch4", "one_wire_temperature_ch5", "one_wire_temperature_ch6", "one_wire_temperature_ch7", "radiation", "rainfall_1h", "rainfall_24h", "relative_humidity", "soil_moisture", "soil_temperature", "temperature", "uv_lux", "voltage", "weight", "white_lux", "wind_direction", "wind_gust", "wind_lull", "wind_speed"]
ADC_VOLTAGE_CH0_FIELD_NUMBER: _ClassVar[int]
ADC_VOLTAGE_CH1_FIELD_NUMBER: _ClassVar[int]
ADC_VOLTAGE_CH2_FIELD_NUMBER: _ClassVar[int]
ADC_VOLTAGE_CH3_FIELD_NUMBER: _ClassVar[int]
ADC_VOLTAGE_CH4_FIELD_NUMBER: _ClassVar[int]
ADC_VOLTAGE_CH5_FIELD_NUMBER: _ClassVar[int]
ADC_VOLTAGE_CH6_FIELD_NUMBER: _ClassVar[int]
ADC_VOLTAGE_CH7_FIELD_NUMBER: _ClassVar[int]
__slots__ = ["barometric_pressure", "current", "distance", "gas_resistance", "iaq", "ir_lux", "lux", "one_wire_temperature", "radiation", "rainfall_1h", "rainfall_24h", "relative_humidity", "soil_moisture", "soil_temperature", "temperature", "uv_lux", "voltage", "weight", "white_lux", "wind_direction", "wind_gust", "wind_lull", "wind_speed"]
BAROMETRIC_PRESSURE_FIELD_NUMBER: _ClassVar[int]
CURRENT_FIELD_NUMBER: _ClassVar[int]
DISTANCE_FIELD_NUMBER: _ClassVar[int]
GAS_RESISTANCE_FIELD_NUMBER: _ClassVar[int]
IAQ_FIELD_NUMBER: _ClassVar[int]
IR_LUX_FIELD_NUMBER: _ClassVar[int]
LIGHTNING_DISTANCE_KM_FIELD_NUMBER: _ClassVar[int]
LIGHTNING_STRIKE_COUNT_1H_FIELD_NUMBER: _ClassVar[int]
LUX_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_CH0_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_CH1_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_CH2_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_CH3_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_CH4_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_CH5_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_CH6_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_CH7_FIELD_NUMBER: _ClassVar[int]
ONE_WIRE_TEMPERATURE_FIELD_NUMBER: _ClassVar[int]
RADIATION_FIELD_NUMBER: _ClassVar[int]
RAINFALL_1H_FIELD_NUMBER: _ClassVar[int]
@@ -183,32 +153,14 @@ class EnvironmentMetrics(_message.Message):
WIND_GUST_FIELD_NUMBER: _ClassVar[int]
WIND_LULL_FIELD_NUMBER: _ClassVar[int]
WIND_SPEED_FIELD_NUMBER: _ClassVar[int]
adc_voltage_ch0: float
adc_voltage_ch1: float
adc_voltage_ch2: float
adc_voltage_ch3: float
adc_voltage_ch4: float
adc_voltage_ch5: float
adc_voltage_ch6: float
adc_voltage_ch7: float
barometric_pressure: float
current: float
distance: float
gas_resistance: float
iaq: int
ir_lux: float
lightning_distance_km: float
lightning_strike_count_1h: int
lux: float
one_wire_temperature: _containers.RepeatedScalarFieldContainer[float]
one_wire_temperature_ch0: float
one_wire_temperature_ch1: float
one_wire_temperature_ch2: float
one_wire_temperature_ch3: float
one_wire_temperature_ch4: float
one_wire_temperature_ch5: float
one_wire_temperature_ch6: float
one_wire_temperature_ch7: float
radiation: float
rainfall_1h: float
rainfall_24h: float
@@ -224,7 +176,7 @@ class EnvironmentMetrics(_message.Message):
wind_gust: float
wind_lull: float
wind_speed: float
def __init__(self, temperature: _Optional[float] = ..., relative_humidity: _Optional[float] = ..., barometric_pressure: _Optional[float] = ..., gas_resistance: _Optional[float] = ..., voltage: _Optional[float] = ..., current: _Optional[float] = ..., iaq: _Optional[int] = ..., distance: _Optional[float] = ..., lux: _Optional[float] = ..., white_lux: _Optional[float] = ..., ir_lux: _Optional[float] = ..., uv_lux: _Optional[float] = ..., wind_direction: _Optional[int] = ..., wind_speed: _Optional[float] = ..., weight: _Optional[float] = ..., wind_gust: _Optional[float] = ..., wind_lull: _Optional[float] = ..., radiation: _Optional[float] = ..., rainfall_1h: _Optional[float] = ..., rainfall_24h: _Optional[float] = ..., soil_moisture: _Optional[int] = ..., soil_temperature: _Optional[float] = ..., one_wire_temperature: _Optional[_Iterable[float]] = ..., adc_voltage_ch0: _Optional[float] = ..., adc_voltage_ch1: _Optional[float] = ..., adc_voltage_ch2: _Optional[float] = ..., adc_voltage_ch3: _Optional[float] = ..., adc_voltage_ch4: _Optional[float] = ..., adc_voltage_ch5: _Optional[float] = ..., adc_voltage_ch6: _Optional[float] = ..., adc_voltage_ch7: _Optional[float] = ..., one_wire_temperature_ch0: _Optional[float] = ..., one_wire_temperature_ch1: _Optional[float] = ..., one_wire_temperature_ch2: _Optional[float] = ..., one_wire_temperature_ch3: _Optional[float] = ..., one_wire_temperature_ch4: _Optional[float] = ..., one_wire_temperature_ch5: _Optional[float] = ..., one_wire_temperature_ch6: _Optional[float] = ..., one_wire_temperature_ch7: _Optional[float] = ..., lightning_strike_count_1h: _Optional[int] = ..., lightning_distance_km: _Optional[float] = ...) -> None: ...
def __init__(self, temperature: _Optional[float] = ..., relative_humidity: _Optional[float] = ..., barometric_pressure: _Optional[float] = ..., gas_resistance: _Optional[float] = ..., voltage: _Optional[float] = ..., current: _Optional[float] = ..., iaq: _Optional[int] = ..., distance: _Optional[float] = ..., lux: _Optional[float] = ..., white_lux: _Optional[float] = ..., ir_lux: _Optional[float] = ..., uv_lux: _Optional[float] = ..., wind_direction: _Optional[int] = ..., wind_speed: _Optional[float] = ..., weight: _Optional[float] = ..., wind_gust: _Optional[float] = ..., wind_lull: _Optional[float] = ..., radiation: _Optional[float] = ..., rainfall_1h: _Optional[float] = ..., rainfall_24h: _Optional[float] = ..., soil_moisture: _Optional[int] = ..., soil_temperature: _Optional[float] = ..., one_wire_temperature: _Optional[_Iterable[float]] = ...) -> None: ...
class HealthMetrics(_message.Message):
__slots__ = ["heart_bpm", "spO2", "temperature"]
@@ -352,58 +304,8 @@ class SEN5XState(_message.Message):
voc_state_valid: bool
def __init__(self, last_cleaning_time: _Optional[int] = ..., last_cleaning_valid: bool = ..., one_shot_mode: bool = ..., voc_state_time: _Optional[int] = ..., voc_state_valid: bool = ..., voc_state_array: _Optional[int] = ...) -> None: ...
class SEN6XState(_message.Message):
__slots__ = ["last_cleaning_time", "last_cleaning_valid", "one_shot_mode", "voc_state_array", "voc_state_time", "voc_state_valid"]
LAST_CLEANING_TIME_FIELD_NUMBER: _ClassVar[int]
LAST_CLEANING_VALID_FIELD_NUMBER: _ClassVar[int]
ONE_SHOT_MODE_FIELD_NUMBER: _ClassVar[int]
VOC_STATE_ARRAY_FIELD_NUMBER: _ClassVar[int]
VOC_STATE_TIME_FIELD_NUMBER: _ClassVar[int]
VOC_STATE_VALID_FIELD_NUMBER: _ClassVar[int]
last_cleaning_time: int
last_cleaning_valid: bool
one_shot_mode: bool
voc_state_array: int
voc_state_time: int
voc_state_valid: bool
def __init__(self, last_cleaning_time: _Optional[int] = ..., last_cleaning_valid: bool = ..., one_shot_mode: bool = ..., voc_state_time: _Optional[int] = ..., voc_state_valid: bool = ..., voc_state_array: _Optional[int] = ...) -> None: ...
class SoilWaterMetrics(_message.Message):
__slots__ = ["ammonium", "biochemical_oxygen_demand", "chemical_oxygen_demand", "dissolved_oxygen", "electrical_conductivity", "nitrate", "nitrogen", "orp", "ph", "phosphorus", "potassium", "salinity", "soil_ph", "solar_irradiance", "turbidity"]
AMMONIUM_FIELD_NUMBER: _ClassVar[int]
BIOCHEMICAL_OXYGEN_DEMAND_FIELD_NUMBER: _ClassVar[int]
CHEMICAL_OXYGEN_DEMAND_FIELD_NUMBER: _ClassVar[int]
DISSOLVED_OXYGEN_FIELD_NUMBER: _ClassVar[int]
ELECTRICAL_CONDUCTIVITY_FIELD_NUMBER: _ClassVar[int]
NITRATE_FIELD_NUMBER: _ClassVar[int]
NITROGEN_FIELD_NUMBER: _ClassVar[int]
ORP_FIELD_NUMBER: _ClassVar[int]
PHOSPHORUS_FIELD_NUMBER: _ClassVar[int]
PH_FIELD_NUMBER: _ClassVar[int]
POTASSIUM_FIELD_NUMBER: _ClassVar[int]
SALINITY_FIELD_NUMBER: _ClassVar[int]
SOIL_PH_FIELD_NUMBER: _ClassVar[int]
SOLAR_IRRADIANCE_FIELD_NUMBER: _ClassVar[int]
TURBIDITY_FIELD_NUMBER: _ClassVar[int]
ammonium: float
biochemical_oxygen_demand: float
chemical_oxygen_demand: float
dissolved_oxygen: float
electrical_conductivity: float
nitrate: float
nitrogen: float
orp: float
ph: float
phosphorus: float
potassium: float
salinity: float
soil_ph: float
solar_irradiance: float
turbidity: float
def __init__(self, soil_ph: _Optional[float] = ..., ph: _Optional[float] = ..., electrical_conductivity: _Optional[float] = ..., salinity: _Optional[float] = ..., nitrogen: _Optional[float] = ..., phosphorus: _Optional[float] = ..., potassium: _Optional[float] = ..., dissolved_oxygen: _Optional[float] = ..., orp: _Optional[float] = ..., chemical_oxygen_demand: _Optional[float] = ..., turbidity: _Optional[float] = ..., nitrate: _Optional[float] = ..., ammonium: _Optional[float] = ..., biochemical_oxygen_demand: _Optional[float] = ..., solar_irradiance: _Optional[float] = ...) -> None: ...
class Telemetry(_message.Message):
__slots__ = ["air_quality_metrics", "device_metrics", "environment_metrics", "health_metrics", "host_metrics", "local_stats", "power_metrics", "soil_water_metrics", "time", "traffic_management_stats"]
__slots__ = ["air_quality_metrics", "device_metrics", "environment_metrics", "health_metrics", "host_metrics", "local_stats", "power_metrics", "time", "traffic_management_stats"]
AIR_QUALITY_METRICS_FIELD_NUMBER: _ClassVar[int]
DEVICE_METRICS_FIELD_NUMBER: _ClassVar[int]
ENVIRONMENT_METRICS_FIELD_NUMBER: _ClassVar[int]
@@ -411,7 +313,6 @@ class Telemetry(_message.Message):
HOST_METRICS_FIELD_NUMBER: _ClassVar[int]
LOCAL_STATS_FIELD_NUMBER: _ClassVar[int]
POWER_METRICS_FIELD_NUMBER: _ClassVar[int]
SOIL_WATER_METRICS_FIELD_NUMBER: _ClassVar[int]
TIME_FIELD_NUMBER: _ClassVar[int]
TRAFFIC_MANAGEMENT_STATS_FIELD_NUMBER: _ClassVar[int]
air_quality_metrics: AirQualityMetrics
@@ -421,10 +322,9 @@ class Telemetry(_message.Message):
host_metrics: HostMetrics
local_stats: LocalStats
power_metrics: PowerMetrics
soil_water_metrics: SoilWaterMetrics
time: int
traffic_management_stats: TrafficManagementStats
def __init__(self, time: _Optional[int] = ..., device_metrics: _Optional[_Union[DeviceMetrics, _Mapping]] = ..., environment_metrics: _Optional[_Union[EnvironmentMetrics, _Mapping]] = ..., air_quality_metrics: _Optional[_Union[AirQualityMetrics, _Mapping]] = ..., power_metrics: _Optional[_Union[PowerMetrics, _Mapping]] = ..., local_stats: _Optional[_Union[LocalStats, _Mapping]] = ..., health_metrics: _Optional[_Union[HealthMetrics, _Mapping]] = ..., host_metrics: _Optional[_Union[HostMetrics, _Mapping]] = ..., traffic_management_stats: _Optional[_Union[TrafficManagementStats, _Mapping]] = ..., soil_water_metrics: _Optional[_Union[SoilWaterMetrics, _Mapping]] = ...) -> None: ...
def __init__(self, time: _Optional[int] = ..., device_metrics: _Optional[_Union[DeviceMetrics, _Mapping]] = ..., environment_metrics: _Optional[_Union[EnvironmentMetrics, _Mapping]] = ..., air_quality_metrics: _Optional[_Union[AirQualityMetrics, _Mapping]] = ..., power_metrics: _Optional[_Union[PowerMetrics, _Mapping]] = ..., local_stats: _Optional[_Union[LocalStats, _Mapping]] = ..., health_metrics: _Optional[_Union[HealthMetrics, _Mapping]] = ..., host_metrics: _Optional[_Union[HostMetrics, _Mapping]] = ..., traffic_management_stats: _Optional[_Union[TrafficManagementStats, _Mapping]] = ...) -> None: ...
class TrafficManagementStats(_message.Message):
__slots__ = ["hop_exhausted_packets", "nodeinfo_cache_hits", "packets_inspected", "position_dedup_drops", "rate_limit_drops", "router_hops_preserved", "unknown_packet_drops"]
+1 -1
View File
@@ -4,7 +4,7 @@ import subprocess
from pathlib import Path
__version__ = "3.0.9"
__release_date__ = "2026-11-12"
__release_date__ = "2026-5-12"
def get_git_revision():
+2 -2
View File
@@ -2,7 +2,7 @@
"base": {
"chat": "Chat",
"nodes": "Nodes",
"everything": "Live Traffic",
"everything": "See Everything",
"graphs": "Mesh Graphs",
"net": "Weekly Net",
"map": "Live Map",
@@ -176,7 +176,7 @@
},
"firehose":
{
"live_feed": "📡 Live Traffic",
"live_feed": "📡 Live Feed",
"pause": "Pause",
"resume": "Resume",
"time": "Time",
+2 -2
View File
@@ -2,7 +2,7 @@
"base": {
"chat": "Conversaciones",
"nodes": "Nodos",
"everything": "Tráfico en vivo",
"everything": "Mostrar todo",
"graphs": "Gráficos de la Malla",
"net": "Red Semanal",
"map": "Mapa en Vivo",
@@ -175,7 +175,7 @@
},
"firehose": {
"live_feed": "📡 Tráfico en vivo",
"live_feed": "📡 Flujo en vivo",
"pause": "Pausar",
"resume": "Reanudar",
"time": "Hora",
+2 -2
View File
@@ -2,7 +2,7 @@
"base": {
"chat": "Чат",
"nodes": "Ноды",
"everything": "Трафик в реальном времени",
"everything": "Показать все",
"graphs": "Mesh графики",
"net": "Недельная сеть",
"map": "Живая карта",
@@ -159,7 +159,7 @@
"node_not_found": "Узел не найден в текущем канале!"
},
"firehose": {
"live_feed": "📡 Трафик в реальном времени",
"live_feed": "📡 Прямой эфир",
"pause": "Пауза",
"resume": "Продолжить",
"time": "Время",
+122 -93
View File
@@ -1,98 +1,127 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Meshview Chat API</title>
<link rel="icon" type="image/svg+xml" href="/static/meshview-icon.svg">
<script src="/static/theme.js"></script>
<style>
body { margin:0; background:#f5f9f6; color:#243247; font:15px/1.7 system-ui,sans-serif; }
main { max-width:760px; margin:40px auto; padding:24px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; }
h1 { color:var(--mesh-primary); font-size:24px; } a { color:var(--mesh-primary); }
code { background:var(--mesh-soft); padding:3px 6px; border-radius:4px; overflow-wrap:anywhere; }
@media(max-width:700px) { main { margin:16px; padding:18px; } }
</style>
<!-- mesh-theme:start -->
<style>
:root {
color-scheme:light;
--mesh-primary:#187346;
--mesh-primary-dark:#0f5132;
--mesh-primary-rgb:24,115,70;
--mesh-brand:#187346;
--mesh-brand-deep:#0f5132;
--mesh-surface:#ffffff;
--mesh-text:#243247;
--mesh-soft:#eaf5ee;
--mesh-hover:#dceee2;
--mesh-border:#dce7df;
--mesh-page:#f5f9f6;
--mesh-stripe:#f7faf8;
--mesh-muted:#64748b;
--mesh-chat-stripe:#eef6f0;
--mesh-pulse-soft:#edf8f0;
--mesh-pulse-peak:#ccebd7;
--mesh-pulse-mid:#e2f3e8;
}
[data-bs-theme="dark"] {
color-scheme:dark;
--mesh-primary:#80cfa3;
--mesh-primary-dark:#a3e3be;
--mesh-primary-rgb:128,207,163;
--mesh-brand:#14532d;
--mesh-brand-deep:#0c3a1f;
--mesh-surface:#18231e;
--mesh-text:#e2ece5;
--mesh-soft:#203c2b;
--mesh-hover:#294c36;
--mesh-border:#34483c;
--mesh-page:#101914;
--mesh-stripe:#1c2a22;
--mesh-muted:#9faea6;
--mesh-chat-stripe:#203227;
--mesh-pulse-soft:#203c2b;
--mesh-pulse-peak:#356b49;
--mesh-pulse-mid:#294c36;
--bs-link-color:var(--mesh-primary);
--bs-link-color-rgb:var(--mesh-primary-rgb);
--bs-link-hover-color:var(--mesh-primary-dark);
--bs-link-hover-color-rgb:163,227,190;
}
body { background:var(--mesh-page); color:var(--mesh-text); }
.mesh-theme-toggle { flex-shrink:0; display:inline-flex; align-items:center; justify-content:center; width:34px; height:34px; border:1px solid #ffffff70; border-radius:6px; background:transparent; color:white; font:22px/1 system-ui,sans-serif; cursor:pointer; }
.mesh-header .mesh-theme-toggle { margin-left:auto; }
.mesh-theme-toggle:hover { background:#ffffff20; }
.mesh-theme-toggle:focus-visible { outline:2px solid white; outline-offset:3px; }
@media(max-width:1000px) { .mesh-header .mesh-menu-toggle { margin-left:auto; } .mesh-header .mesh-theme-toggle { margin-left:12px; } .mesh-header #site-menu { order:4; } }
[data-bs-theme="dark"] :is(.chat-status,.chat-details,.chat-channel,.chat-status[data-state="paused"],.chat-status[data-state="loading"],.good-x) { background:var(--mesh-soft); color:var(--mesh-primary); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.chat-status[data-state="error"],.bad-x) { background:#472a24; color:#ffb4a6; }
[data-bs-theme="dark"] .ok-x { background:#453820; color:#f1d38a; }
[data-bs-theme="dark"] .chat-details:hover { background:var(--mesh-hover); color:var(--mesh-primary-dark); }
[data-bs-theme="dark"] .chat-nick { filter:brightness(1.4) saturate(.8); }
[data-bs-theme="dark"] :is(.summary-card:nth-child(2) .summary-count,.summary-card:nth-child(3) .summary-count,.summary-card:nth-child(4) .summary-count,.mesh-metric:nth-child(2) strong,.mesh-metric:nth-child(3) strong,.reach-metric:nth-child(2) .reach-metric-value) { color:var(--mesh-primary); }
[data-bs-theme="dark"] :is(.reliability-status-heard) { color:#8fd7aa!important; }
[data-bs-theme="dark"] .reliability-status-missed { color:#ffb4a6!important; }
[data-bs-theme="dark"] .reach-count-bar-value span { color:#17263c; }
[data-bs-theme="dark"] .leaflet-tile-pane { filter:invert(1) hue-rotate(180deg) brightness(.85) saturate(.75); }
[data-bs-theme="dark"] :is(.leaflet-container,.leaflet-control-layers,.leaflet-bar a,.leaflet-popup-content-wrapper,.leaflet-popup-tip,.leaflet-tooltip,.leaflet-control-attribution,.leaflet-control-scale-line,#unmapped-packets,#legend,#node-info,.legend) { background:var(--mesh-surface); color:var(--mesh-text); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.leaflet-control-layers label,.leaflet-popup-close-button,#unmapped-packets h3,.unmapped-node,.blinking-tooltip,.legend) { color:var(--mesh-text); }
[data-bs-theme="dark"] :is(.leaflet-bar a:hover,.leaflet-control-layers-expanded) { background:var(--mesh-stripe); }
[data-bs-theme="dark"] :is(.unmapped-empty,.reach-muted) { color:var(--mesh-muted); }
[data-bs-theme="dark"] :is(.source-marker,.reach-map-marker) { color:white; }
[data-bs-theme="dark"] .qr-image { background:white; }
[data-bs-theme="dark"] :is(#traceroute-error,#map-load-status,.text-danger) { color:#ffb4a6; }
[data-bs-theme="dark"] .reach-count-bar-track { background:var(--mesh-soft); }
</style>
<!-- mesh-theme:end -->
<meta charset="UTF-8" />
<title>API Documentation - Chat</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist/swagger-ui.css" />
<style>
body {
margin: 0;
background: #ffffff;
color: #000000;
}
#swagger-ui { background: #ffffff; color: #000; }
.swagger-ui { background-color: #ffffff !important; color: #000 !important; }
.swagger-ui .topbar,
.swagger-ui .info,
.swagger-ui .opblock-summary-description,
.swagger-ui .parameters-col_description,
.swagger-ui .response-col_description { color: #000 !important; }
.swagger-ui .opblock { background-color: #f9f9f9 !important; border-color: #ddd !important; }
.swagger-ui .opblock-summary { background-color: #eaeaea !important; color: #000 !important; }
.swagger-ui .opblock-section-header { color: #000 !important; }
.swagger-ui .parameters,
.swagger-ui .response { background-color: #fafafa !important; color: #000 !important; }
.swagger-ui table { color: #000 !important; }
.swagger-ui a { color: #1a0dab !important; }
.swagger-ui input,
.swagger-ui select,
.swagger-ui textarea { background-color: #fff !important; color: #000 !important; border: 1px solid #ccc !important; }
</style>
</head>
<body>
<button class="mesh-theme-toggle" style="position:fixed;top:12px;right:12px;z-index:2000;background:#187346" type="button" data-theme-toggle aria-label="Switch to night mode" aria-pressed="false">☾</button><main>
<h1>Chat messages API</h1>
<p>Chat uses <code>GET /api/packets?portnum=1</code>. There is no separate <code>/api/chat</code> endpoint.</p>
<p>Use <code>limit</code> and <code>since</code> for incremental polling. Direct port-1 text messages are returned as <code>&lt;redacted&gt;</code>.</p>
<p><a href="/api.html#get-api-packets">Read the complete packets API reference ↗</a></p>
<p><a href="/">Return to Meshview</a></p>
</main></body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"></script>
<script>
const spec = {
openapi: "3.0.0",
info: {
title: "Chat API",
version: "1.0.0",
description: "API for retrieving chat messages from the mesh network. Supports optional time-based filtering and result limits."
},
paths: {
"/api/chat": {
get: {
summary: "Get chat messages",
description: "Returns a list of chat messages. You can optionally filter by a timestamp (`since`) and limit the number of results (`limit`).",
parameters: [
{
name: "since",
in: "query",
required: false,
description: "ISO 8601 timestamp; only return messages newer than this.",
schema: { type: "string", format: "date-time", example: "2025-09-10T15:29:33.307782" }
},
{
name: "limit",
in: "query",
required: false,
description: "Maximum number of messages to return (1-200). Default is 100.",
schema: { type: "integer", minimum: 1, maximum: 200, default: 100 }
}
],
responses: {
"200": {
description: "Successful response",
content: {
"application/json": {
schema: {
type: "object",
properties: {
packets: {
type: "array",
description: "Array of chat messages",
items: {
type: "object",
properties: {
id: { type: "integer", example: 4285655910 },
import_time: { type: "string", format: "date-time", example: "2025-09-10T15:29:33.307782" },
channel: { type: "string", example: "MediumSlow" },
from_node_id: { type: "integer", example: 2695230252 },
long_name: { type: "string", example: "Fight The Empire With Sticks And Rocks" },
payload: { type: "string", example: "sunny in SF" },
reply_id: { type: "integer", example: 670731015, nullable: true }
}
}
},
latest_import_time: {
type: "string",
format: "date-time",
description: "Timestamp of the most recent message returned",
example: "2025-09-10T16:54:14.124001"
}
}
}
}
}
},
"500": {
description: "Server error",
content: {
"application/json": {
schema: { type: "object", properties: { error: { type: "string" } } }
}
}
}
}
}
}
}
};
window.onload = () => {
SwaggerUIBundle({
spec,
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "BaseLayout"
});
};
</script>
</body>
</html>
+264 -528
View File
@@ -1,537 +1,273 @@
<!doctype html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Meshview API Reference</title>
<script src="/static/theme.js"></script>
<link rel="icon" type="image/svg+xml" href="/static/meshview-icon.svg">
<title>Meshview API Documentation</title>
<style>
:root { color-scheme:light; --primary:var(--mesh-primary); --border:var(--mesh-border); }
* { box-sizing:border-box; }
html { scroll-padding-top:80px; }
body { margin:0; background:var(--mesh-page); color:var(--mesh-text); font:14px/1.7 system-ui,-apple-system,"Segoe UI",sans-serif; }
a { color:var(--primary); }
a:hover { color:var(--mesh-primary-dark); }
header { background:var(--mesh-brand); color:white; position:sticky; top:0; z-index:2; box-shadow:0 2px 8px #174b2d18; }
.header-inner { max-width:1180px; margin:auto; min-height:56px; display:flex; align-items:center; gap:12px; padding:8px 24px; }
header img { width:32px; height:32px; }
header a { color:white; text-decoration:none; }
header a:hover { color:white; text-decoration:underline; }
.brand { font-size:18px; font-weight:700; display:flex; align-items:center; gap:10px; }
.home-link { margin-left:auto; font-size:13px; }
main { max-width:1180px; margin:auto; padding:28px 24px 60px; min-width:0; }
h1 { font-size:28px; margin:0 0 16px; } h2 { font-size:21px; margin:32px 0 14px; } h3 { font-size:17px; margin:0 0 16px; }
p,li { overflow-wrap:anywhere; }
code { font:12px/1.7 ui-monospace,Consolas,monospace; color:var(--mesh-primary); background:var(--mesh-soft); border-radius:4px; padding:2px 5px; overflow-wrap:anywhere; }
pre { background:var(--mesh-stripe); border:1px solid var(--border); border-radius:7px; padding:16px; overflow:auto; }
pre code { background:none; padding:0; white-space:pre; color:var(--mesh-text); }
h3 code { font-size:15px; }
.endpoint { background:var(--mesh-surface); border:1px solid var(--border); border-radius:9px; padding:24px; margin-bottom:22px; scroll-margin-top:12px; min-width:0; }
.method { display:inline-block; background:var(--mesh-brand); color:white; font-size:11px; padding:3px 8px; border-radius:5px; margin-right:5px; }
hr { border:0; border-top:1px solid var(--border); margin:24px 0; }
.api-index { background:var(--mesh-surface); border:1px solid var(--border); border-radius:9px; padding:16px 20px; margin-bottom:24px; }
.api-index summary { color:var(--primary); font-weight:600; cursor:pointer; }
.api-index ul { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px 24px; padding-left:20px; }
.api-index a { font:12px ui-monospace,monospace; }
:focus-visible { outline:2px solid var(--primary); outline-offset:3px; }
footer { border-top:1px solid var(--border); padding:20px 24px; text-align:center; color:var(--mesh-muted); font-size:12px; }
@media(max-width:700px) { main { padding:20px 14px 40px; } .header-inner { padding:8px 14px; } h1 { font-size:24px; } h2 { font-size:19px; } h3 code { font-size:12px; } .endpoint { padding:16px; } .api-index ul { grid-template-columns:minmax(0,1fr); } }
body {
background: #121212;
color: #eee;
font-family: monospace;
margin: 20px;
line-height: 1.5;
}
h1, h2, h3 { color: #79c0ff; }
code {
background: #1e1e1e;
padding: 3px 6px;
border-radius: 4px;
color: #ffd479;
font-size: 0.95rem;
}
.endpoint {
border: 1px solid #333;
padding: 12px;
margin-bottom: 18px;
border-radius: 8px;
background: #1a1a1a;
}
.method {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
margin-right: 6px;
font-weight: bold;
}
.get { background: #0066cc; }
.path { font-weight: bold; color: #fff; }
table {
width: 100%;
border-collapse: collapse;
margin-top: 8px;
}
th, td {
border: 1px solid #444;
padding: 6px 10px;
}
th {
background: #222;
color: #9ddcff;
}
.example {
margin-top: 10px;
padding: 10px;
background: #161616;
border-radius: 6px;
border: 1px solid #333;
}
</style>
<style>
:root {
color-scheme:light;
--mesh-primary:#187346;
--mesh-primary-dark:#0f5132;
--mesh-primary-rgb:24,115,70;
--mesh-brand:#187346;
--mesh-brand-deep:#0f5132;
--mesh-surface:#ffffff;
--mesh-text:#243247;
--mesh-soft:#eaf5ee;
--mesh-hover:#dceee2;
--mesh-border:#dce7df;
--mesh-page:#f5f9f6;
--mesh-stripe:#f7faf8;
--mesh-muted:#64748b;
--mesh-chat-stripe:#eef6f0;
--mesh-pulse-soft:#edf8f0;
--mesh-pulse-peak:#ccebd7;
--mesh-pulse-mid:#e2f3e8;
}
[data-bs-theme="dark"] {
color-scheme:dark;
--mesh-primary:#80cfa3;
--mesh-primary-dark:#a3e3be;
--mesh-primary-rgb:128,207,163;
--mesh-brand:#14532d;
--mesh-brand-deep:#0c3a1f;
--mesh-surface:#18231e;
--mesh-text:#e2ece5;
--mesh-soft:#203c2b;
--mesh-hover:#294c36;
--mesh-border:#34483c;
--mesh-page:#101914;
--mesh-stripe:#1c2a22;
--mesh-muted:#9faea6;
--mesh-chat-stripe:#203227;
--mesh-pulse-soft:#203c2b;
--mesh-pulse-peak:#356b49;
--mesh-pulse-mid:#294c36;
--bs-link-color:var(--mesh-primary);
--bs-link-color-rgb:var(--mesh-primary-rgb);
--bs-link-hover-color:var(--mesh-primary-dark);
--bs-link-hover-color-rgb:163,227,190;
}
body { background:var(--mesh-page); color:var(--mesh-text); }
.mesh-theme-toggle { flex-shrink:0; display:inline-flex; align-items:center; justify-content:center; width:34px; height:34px; border:1px solid #ffffff70; border-radius:6px; background:transparent; color:white; font:22px/1 system-ui,sans-serif; cursor:pointer; }
.mesh-header .mesh-theme-toggle { margin-left:auto; }
.mesh-theme-toggle:hover { background:#ffffff20; }
.mesh-theme-toggle:focus-visible { outline:2px solid white; outline-offset:3px; }
@media(max-width:1000px) { .mesh-header .mesh-menu-toggle { margin-left:auto; } .mesh-header .mesh-theme-toggle { margin-left:12px; } .mesh-header #site-menu { order:4; } }
[data-bs-theme="dark"] :is(.chat-status,.chat-details,.chat-channel,.chat-status[data-state="paused"],.chat-status[data-state="loading"],.good-x) { background:var(--mesh-soft); color:var(--mesh-primary); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.chat-status[data-state="error"],.bad-x) { background:#472a24; color:#ffb4a6; }
[data-bs-theme="dark"] .ok-x { background:#453820; color:#f1d38a; }
[data-bs-theme="dark"] .chat-details:hover { background:var(--mesh-hover); color:var(--mesh-primary-dark); }
[data-bs-theme="dark"] .chat-nick { filter:brightness(1.4) saturate(.8); }
[data-bs-theme="dark"] :is(.summary-card:nth-child(2) .summary-count,.summary-card:nth-child(3) .summary-count,.summary-card:nth-child(4) .summary-count,.mesh-metric:nth-child(2) strong,.mesh-metric:nth-child(3) strong,.reach-metric:nth-child(2) .reach-metric-value) { color:var(--mesh-primary); }
[data-bs-theme="dark"] :is(.reliability-status-heard) { color:#8fd7aa!important; }
[data-bs-theme="dark"] .reliability-status-missed { color:#ffb4a6!important; }
[data-bs-theme="dark"] .reach-count-bar-value span { color:#17263c; }
[data-bs-theme="dark"] .leaflet-tile-pane { filter:invert(1) hue-rotate(180deg) brightness(.85) saturate(.75); }
[data-bs-theme="dark"] :is(.leaflet-container,.leaflet-control-layers,.leaflet-bar a,.leaflet-popup-content-wrapper,.leaflet-popup-tip,.leaflet-tooltip,.leaflet-control-attribution,.leaflet-control-scale-line,#unmapped-packets,#legend,#node-info,.legend) { background:var(--mesh-surface); color:var(--mesh-text); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.leaflet-control-layers label,.leaflet-popup-close-button,#unmapped-packets h3,.unmapped-node,.blinking-tooltip,.legend) { color:var(--mesh-text); }
[data-bs-theme="dark"] :is(.leaflet-bar a:hover,.leaflet-control-layers-expanded) { background:var(--mesh-stripe); }
[data-bs-theme="dark"] :is(.unmapped-empty,.reach-muted) { color:var(--mesh-muted); }
[data-bs-theme="dark"] :is(.source-marker,.reach-map-marker) { color:white; }
[data-bs-theme="dark"] .qr-image { background:white; }
[data-bs-theme="dark"] :is(#traceroute-error,#map-load-status,.text-danger) { color:#ffb4a6; }
[data-bs-theme="dark"] .reach-count-bar-track { background:var(--mesh-soft); }
</style>
</head>
<body>
<header><div class="header-inner"><a class="brand" href="/"><img src="/static/meshview-icon.svg" alt="" width="32" height="32">Meshview</a><span>API reference</span><a class="home-link" href="/">Home ↗</a><button class="mesh-theme-toggle" type="button" data-theme-toggle aria-label="Switch to night mode" aria-pressed="false">☾</button></div></header>
<main>
<details class="api-index"><summary>Browse all 16 endpoints</summary><nav aria-label="API endpoints"><ul><li><a href="#get-api-nodes">GET /api/nodes</a></li><li><a href="#get-api-packets">GET /api/packets</a></li><li><a href="#get-api-channels">GET /api/channels</a></li><li><a href="#get-api-stats">GET /api/stats</a></li><li><a href="#get-api-stats-count">GET /api/stats/count</a></li><li><a href="#get-api-stats-top">GET /api/stats/top</a></li><li><a href="#get-api-edges">GET /api/edges</a></li><li><a href="#get-api-snapshots-daily">GET /api/snapshots/daily</a></li><li><a href="#get-api-config">GET /api/config</a></li><li><a href="#get-api-lang">GET /api/lang</a></li><li><a href="#get-api-packets-seen-packet-id">GET /api/packets_seen/{packet_id}</a></li><li><a href="#get-api-traceroute-packet-id">GET /api/traceroute/{packet_id}</a></li><li><a href="#get-health">GET /health</a></li><li><a href="#get-version">GET /version</a></li><li><a href="#get-api-node-node-id-qr">GET /api/node/{node_id}/qr</a></li><li><a href="#get-api-coverage-node-id">GET /api/coverage/{node_id}</a></li></ul></nav></details>
<h1 id="api-documentation">API Documentation</h1>
<p>Base URL: <code>http(s)://&lt;host&gt;</code></p>
<p>This reference covers all 16 GET routes registered in <code>meshview/web_api/api.py</code>, including <code>/health</code> and <code>/version</code>. The browser version is served at <code>/api.html</code>. Responses below are illustrative examples; actual values depend on stored data. Regenerate the browser reference after editing this file with <code>node scripts/build-api-docs.mjs</code>.</p>
<h2 id="conventions">Conventions</h2>
<ul><li>Successful API responses are JSON. Explicit validation errors usually return JSON with an <code>error</code> field. Some unhandled errors return HTTP 500 with a plain-text body; check HTTP status and Content-Type before parsing an error response.</li><li>All routes are read-only. The application does not require an API token; a reverse proxy may impose authentication. There are no application-level write endpoints.</li><li><code>*_us</code> timestamps and <code>since</code> use microseconds since the Unix epoch. Snapshot dates and statistics buckets use UTC. Node latitude/longitude integers must be divided by 10,000,000 to obtain degrees; coverage coordinates are already degrees.</li><li>Packet <code>id</code> and <code>storage_id</code> are database row IDs. Use these for the <code>packet_id</code> query/path parameters on packet, observation, count, and traceroute endpoints. A response field named <code>packet_id</code> on a packet object is instead its over-the-air Meshtastic ID. <code>reply_id</code>, when present, is also an over-the-air ID. These ID types are not interchangeable. Node IDs are numeric Meshtastic node numbers; the node object&#39;s <code>id</code> is a separate string identifier.</li><li>Use decimal node IDs throughout. The packet sender/recipient filters and the QR and coverage paths also accept Python-style <code>0x</code> hexadecimal numbers. This is not supported consistently by the other routes.</li><li>Public broadcast text is readable. Direct text messages on port 1 are returned as <code>&lt;redacted&gt;</code>. Request chat with <code>/api/packets?portnum=1</code>; there is no <code>/api/chat</code> route. Do not treat a decoded <code>payload</code> string as trusted HTML.</li></ul>
<h2 id="quick-examples">Quick examples</h2>
<pre><code class="language-sh">curl &#39;http://localhost:8081/api/nodes?days_active=3&#39;
curl &#39;http://localhost:8081/api/packets?portnum=1&amp;limit=100&#39;
curl &#39;http://localhost:8081/api/stats/count&#39;
curl &#39;http://localhost:8081/api/coverage/1234?mode=perimeter&amp;radius_km=20&#39;</code></pre>
<h2 id="1-nodes-api">1. Nodes API</h2>
<section class="endpoint" id="get-api-nodes"><h3><span class="method">GET</span> <code>/api/nodes</code></h3>
<p>Returns a list of nodes, with optional filtering.</p>
<p>Query Parameters</p>
<ul><li><code>node_id</code> (optional, int): Exact node ID.</li><li><code>role</code> (optional, string): Node role.</li><li><code>channel</code> (optional, string): Channel name.</li><li><code>hw_model</code> (optional, string): Hardware model.</li><li><code>days_active</code> (optional, int): Nodes seen within the last N days. Omit for all nodes with a non-null last-seen timestamp; invalid integers are ignored.</li></ul>
<p>Nodes are sorted by <code>short_name</code> ascending. <code>role</code> is normalized to uppercase; channel and hardware filters are exact matches. No pagination is implemented.</p>
<p>Errors: HTTP 500 with <code>{&quot;error&quot;:&quot;Failed to fetch nodes&quot;}</code> for handler failures; the storage helper may return an empty list for database failures.</p>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;nodes&quot;: [
{
&quot;id&quot;: &quot;!000004d2&quot;,
&quot;node_id&quot;: 1234,
&quot;long_name&quot;: &quot;Alice&quot;,
&quot;short_name&quot;: &quot;A&quot;,
&quot;hw_model&quot;: &quot;T-Beam&quot;,
&quot;firmware&quot;: &quot;1.2.3&quot;,
&quot;role&quot;: &quot;client&quot;,
&quot;last_lat&quot;: 377749000,
&quot;last_long&quot;: -1224194000,
&quot;channel&quot;: &quot;main&quot;,
&quot;is_mqtt_gateway&quot;: true,
&quot;first_seen_us&quot;: 1736283723456789,
&quot;last_seen_us&quot;: 1736370123456789
}
]
}</code></pre>
<h1>Meshview API Documentation</h1>
<p>This page describes all REST endpoints provided by Meshview.</p>
<!------------------------------ NODES ------------------------------>
<h2>/api/nodes</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/api/nodes</span>
<p>Returns a list of mesh nodes.</p>
<h3>Query Parameters</h3>
<table>
<tr><th>Parameter</th><th>Description</th></tr>
<tr><td>role</td><td>Filter by node role</td></tr>
<tr><td>channel</td><td>Filter by channel</td></tr>
<tr><td>hw_model</td><td>Hardware model filter</td></tr>
<tr><td>days_active</td><td>Only nodes seen within X days</td></tr>
</table>
<div class="example">
<b>Example:</b><br>
<code>/api/nodes?days_active=3</code>
</div>
</div>
<!------------------------------ PACKETS ------------------------------>
<h2>/api/packets</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/api/packets</span>
<p>Fetch packets with many filters. Returns decoded packet data.</p>
<h3>Query Parameters</h3>
<table>
<tr><th>Parameter</th><th>Description</th></tr>
<tr><td>packet_id</td><td>Return exactly one packet</td></tr>
<tr><td>limit</td><td>Max number of results (1–100)</td></tr>
<tr><td>since</td><td>Only packets newer than import_time_us</td></tr>
<tr><td>from_node_id</td><td>Filter by sender node</td></tr>
<tr><td>to_node_id</td><td>Filter by destination node</td></tr>
<tr><td>node_id</td><td>Legacy: match either from or to</td></tr>
<tr><td>portnum</td><td>Filter by port number</td></tr>
<tr><td>contains</td><td>Substring filter for payload</td></tr>
</table>
<div class="example">
<b>Example:</b><br>
<code>/api/packets?from_node_id=123&limit=100</code>
</div>
</div>
<!------------------------------ PACKETS SEEN ------------------------------>
<h2>/api/packets_seen/{packet_id}</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/api/packets_seen/&lt;packet_id&gt;</span>
<p>Returns list of gateways that heard the packet (RSSI/SNR/hops).</p>
<div class="example">
<b>Example:</b><br>
<code>/api/packets_seen/3314808102</code>
</div>
</div>
<!------------------------------ STATS ------------------------------>
<h2>/api/stats</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/api/stats</span>
<p>Returns aggregated packet statistics for a node or globally.</p>
<h3>Query Parameters</h3>
<table>
<tr><th>Parameter</th><th>Description</th></tr>
<tr><td>period_type</td><td>"hour" or "day"</td></tr>
<tr><td>length</td><td>How many hours/days</td></tr>
<tr><td>node</td><td>Node ID for combined sent+seen stats</td></tr>
<tr><td>from_node</td><td>Filter by sender</td></tr>
<tr><td>to_node</td><td>Filter by receiver</td></tr>
<tr><td>portnum</td><td>Filter by port</td></tr>
<tr><td>channel</td><td>Filter by channel</td></tr>
</table>
<div class="example">
<b>Example:</b><br>
<code>/api/stats?node=1128180332&period_type=day&length=1</code>
</div>
</div>
<!------------------------------ STATS COUNT ------------------------------>
<h2>/api/stats/count</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/api/stats/count</span>
<p>
Returns <b>total packets</b> and <b>total packet_seen entries</b>.
When no filters are provided, it returns global totals.
When filters are specified, they narrow the time, channel,
direction, or specific packet.
</p>
<h3>Query Parameters</h3>
<table>
<tr><th>Parameter</th><th>Description</th></tr>
<tr><td>period_type</td><td>"hour" or "day"</td></tr>
<tr><td>length</td><td>Number of hours or days (depends on period_type)</td></tr>
<tr><td>channel</td><td>Filter by channel</td></tr>
<tr><td>from_node</td><td>Only packets sent by this node</td></tr>
<tr><td>to_node</td><td>Only packets received by this node</td></tr>
<tr><td>packet_id</td><td>Filter seen counts for specific packet_id</td></tr>
</table>
<div class="example">
<b>Example:</b><br>
<code>/api/stats/count?from_node=1128180332&period_type=day&length=1</code>
</div>
</div>
<!------------------------------ EDGES ------------------------------>
<h2>/api/edges</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/api/edges</span>
<p>Returns traceroute and/or neighbor edges for graph rendering.</p>
<h3>Query Parameters</h3>
<table>
<tr><th>Parameter</th><th>Description</th></tr>
<tr><td>type</td><td>"traceroute", "neighbor", or omitted for both</td></tr>
</table>
<div class="example">
<b>Example:</b><br>
<code>/api/edges?type=neighbor</code>
</div>
</div>
<!------------------------------ CONFIG ------------------------------>
<h2>/api/config</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/api/config</span>
<p>Returns Meshview configuration (site, MQTT, cleanup, etc.).</p>
<div class="example">
<code>/api/config</code>
</div>
</div>
<!------------------------------ LANG ------------------------------>
<h2>/api/lang</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/api/lang</span>
<p>Returns translated text for the UI.</p>
<h3>Parameters</h3>
<table>
<tr><th>lang</th><td>Language code (e.g. "en")</td></tr>
<tr><th>section</th><td>Optional UI section (firehose, map, top...)</td></tr>
</table>
<div class="example">
<code>/api/lang?lang=en&section=firehose</code>
</div>
</div>
<!------------------------------ HEALTH ------------------------------>
<h2>/health</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/health</span>
<p>Returns API + database status.</p>
</div>
<!------------------------------ VERSION ------------------------------>
<h2>/version</h2>
<div class="endpoint">
<span class="method get">GET</span>
<span class="path">/version</span>
<p>Returns Meshview version and Git revision.</p>
</div>
<br><br>
<hr>
</section>
<h2 id="2-packets-api">2. Packets API</h2>
<section class="endpoint" id="get-api-packets"><h3><span class="method">GET</span> <code>/api/packets</code></h3>
<p>Returns packets with optional filters.</p>
<p>Query Parameters</p>
<ul><li><code>packet_id</code> (optional, decimal int): Return one packet by database row ID (overrides other filters).</li><li><code>limit</code> (optional, int): Max packets to return, clamped 1-1000. Default: <code>50</code>.</li><li><code>since</code> (optional, int): Only packets imported after this microsecond timestamp.</li><li><code>portnum</code> (optional, int): Filter by port number.</li><li><code>contains</code> (optional, string): Payload substring filter.</li><li><code>from_node_id</code> (optional, int): Filter by sender node ID.</li><li><code>to_node_id</code> (optional, int): Filter by recipient node ID.</li><li><code>node_id</code> (optional, int): Legacy filter matching either from or to node ID.</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;packets&quot;: [
{
&quot;id&quot;: 123,
&quot;storage_id&quot;: 123,
&quot;packet_id&quot;: 3314808102,
&quot;import_time_us&quot;: 1736370123456789,
&quot;channel&quot;: &quot;main&quot;,
&quot;from_node_id&quot;: 5678,
&quot;to_node_id&quot;: 4294967295,
&quot;portnum&quot;: 1,
&quot;long_name&quot;: &quot;Alice&quot;,
&quot;payload&quot;: &quot;Hello, mesh!&quot;,
&quot;to_long_name&quot;: null,
&quot;reply_id&quot;: 122
}
],
&quot;latest_import_time&quot;: 1736370123456789
}</code></pre>
<p>Notes</p>
<ul><li>For <code>portnum=1</code> (text messages), packets are filtered to remove sequence-only payloads.</li><li>Results are newest first. <code>since</code> is strictly greater than the supplied timestamp. Store <code>latest_import_time</code> for the next poll and deduplicate by <code>id</code>. A bounded result can omit older records if more packets arrive than the requested limit; this endpoint is not a durable cursor or backfill API.</li><li><code>latest_import_time</code> is returned only when the list response has a positive import timestamp; it is absent for empty results and single-packet lookups.</li><li><code>packet_id</code> lookup returns <code>{&quot;packets&quot;:[]}</code> with HTTP 200 when missing. Its objects omit <code>to_long_name</code> and <code>reply_id</code>; nullable <code>portnum</code> is possible in this mode.</li><li><code>contains</code> is case-insensitive. With <code>portnum=1</code>, matching is performed on decoded displayed payload text (including redaction placeholders) after the database limit is applied, so fewer than <code>limit</code> results may be returned. For other requests, it searches stored payload bytes cast to text; this is not a general search over decoded protobuf fields.</li><li>Invalid <code>limit</code> falls back to 50. Invalid <code>since</code>, <code>portnum</code>, and node filters are logged and ignored. Invalid single-packet IDs return HTTP 400; handler failures return HTTP 500 with <code>{&quot;error&quot;:&quot;Failed to fetch packets&quot;}</code>.</li></ul>
<hr>
</section>
<h2 id="3-channels-api">3. Channels API</h2>
<section class="endpoint" id="get-api-channels"><h3><span class="method">GET</span> <code>/api/channels</code></h3>
<p>Returns channels seen in a time period.</p>
<p>Query Parameters</p>
<ul><li><code>period_type</code> (optional, string): <code>hour</code> or <code>day</code>. Default: <code>hour</code>.</li><li><code>length</code> (optional, int): Number of periods to look back. Default: <code>24</code>.</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;channels&quot;: [&quot;LongFast&quot;, &quot;MediumFast&quot;, &quot;ShortFast&quot;]
}</code></pre>
<hr>
<p>Errors: storage/period failures return HTTP 200 with <code>channels: []</code> and an <code>error</code> field. Non-integer <code>length</code> is parsed outside that handler and can return HTTP 500. Use a positive integer length and the literal <code>hour</code> or <code>day</code>.</p>
</section>
<h2 id="4-stats-api">4. Stats API</h2>
<section class="endpoint" id="get-api-stats"><h3><span class="method">GET</span> <code>/api/stats</code></h3>
<p>Returns packet statistics aggregated by time periods, with optional filtering.</p>
<p>Query Parameters</p>
<ul><li><code>period_type</code> (optional, string): <code>hour</code> or <code>day</code>. Default: <code>hour</code>.</li><li><code>length</code> (optional, int): Number of periods to include. Default: <code>24</code>.</li><li><code>channel</code> (optional, string): Filter by channel (case-insensitive).</li><li><code>portnum</code> (optional, int): Filter by port number.</li><li><code>to_node</code> (optional, int): Filter by destination node ID.</li><li><code>from_node</code> (optional, int): Filter by source node ID.</li><li><code>node</code> (optional, int): If provided, return combined <code>sent</code> and <code>seen</code> totals for that node.</li></ul>
<p>Response Example (series)</p>
<pre><code class="language-json">{
&quot;period_type&quot;: &quot;hour&quot;,
&quot;length&quot;: 24,
&quot;channel&quot;: &quot;LongFast&quot;,
&quot;portnum&quot;: 1,
&quot;to_node&quot;: 12345678,
&quot;from_node&quot;: 87654321,
&quot;data&quot;: [
{ &quot;period&quot;: &quot;2025-08-08 14:00&quot;, &quot;count&quot;: 10 },
{ &quot;period&quot;: &quot;2025-08-08 15:00&quot;, &quot;count&quot;: 7 }
]
}</code></pre>
<p>Response Example (<code>node</code> totals)</p>
<pre><code class="language-json">{
&quot;node_id&quot;: 12345678,
&quot;period_type&quot;: &quot;hour&quot;,
&quot;length&quot;: 24,
&quot;sent&quot;: 0,
&quot;seen&quot;: 0
}</code></pre>
<hr>
<p>The series response contains only buckets with records, ordered oldest first; missing hours/days are not filled with zeroes. Periods are UTC strings.</p>
<p>Current <code>node</code>-mode limitation: the handler reads a <code>total</code> key that the statistics helper does not provide, so <code>sent</code> and <code>seen</code> currently return zero. It also uses recipient filtering for the second query, rather than gateway observations. This mode ignores the other filters. For usable sent/observation totals, request <code>/api/stats/count?from_node=1234&amp;period_type=day&amp;length=1</code> instead.</p>
<p>Errors: HTTP 400 for an unsupported <code>period_type</code>, non-integer <code>length</code>, <code>node</code>, <code>portnum</code>, <code>from_node</code>, or <code>to_node</code>. Storage failures can return HTTP 500. Use a positive <code>length</code>; the handler does not impose a positive lower bound.</p>
</section>
<section class="endpoint" id="get-api-stats-count"><h3><span class="method">GET</span> <code>/api/stats/count</code></h3>
<p>Returns total packet counts, optionally filtered.</p>
<p>Query Parameters</p>
<ul><li><code>packet_id</code> (optional, int): Filter packet_seen by packet ID.</li><li><code>period_type</code> (optional, string): <code>hour</code> or <code>day</code>.</li><li><code>length</code> (optional, int): Number of periods to include.</li><li><code>channel</code> (optional, string): Filter by channel.</li><li><code>from_node</code> (optional, int): Filter by source node ID.</li><li><code>to_node</code> (optional, int): Filter by destination node ID.</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;total_packets&quot;: 12345,
&quot;total_seen&quot;: 67890
}</code></pre>
<hr>
<p>Without filters, counts cover the whole retained database. With time, channel, or direction filters, omitted time settings default to <code>period_type=day&amp;length=1</code>. <code>total_seen</code> counts observation rows for packets matching the packet import-time window, not distinct gateways. Channel matching is case-insensitive.</p>
<p><code>packet_id</code> applies only to <code>total_seen</code> and overrides its other filters: it counts all observations of that database packet ID. It does not narrow <code>total_packets</code>. In particular, <code>packet_id</code> alone leaves <code>total_packets</code> as the global packet total.</p>
<p>Errors: HTTP 400 for non-integer ID/length filters. Unsupported <code>period_type</code> or storage failures can return HTTP 500; use <code>hour</code> or <code>day</code> and a positive length.</p>
</section>
<section class="endpoint" id="get-api-stats-top"><h3><span class="method">GET</span> <code>/api/stats/top</code></h3>
<p>Returns nodes sorted by packets seen, with pagination.</p>
<p>Query Parameters</p>
<ul><li><code>period_type</code> (optional, string): <code>hour</code> or <code>day</code>. Default: <code>day</code>.</li><li><code>length</code> (optional, int): Number of periods to include. Default: <code>1</code>.</li><li><code>channel</code> (optional, string): Filter by channel.</li><li><code>limit</code> (optional, int): Max nodes to return. Default: <code>20</code>, max <code>100</code>.</li><li><code>offset</code> (optional, int): Pagination offset. Default: <code>0</code>.</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;total&quot;: 250,
&quot;limit&quot;: 20,
&quot;offset&quot;: 0,
&quot;nodes&quot;: [
{
&quot;node_id&quot;: 1234,
&quot;long_name&quot;: &quot;Alice&quot;,
&quot;short_name&quot;: &quot;A&quot;,
&quot;channel&quot;: &quot;main&quot;,
&quot;sent&quot;: 100,
&quot;seen&quot;: 240,
&quot;avg&quot;: 2.4
}
]
}</code></pre>
<hr>
<p><code>sent</code> counts packet records from each node; <code>seen</code> counts observation records for that sender&#39;s packets. <code>avg</code> is <code>round(seen / max(sent, 1), 2)</code>, not a distinct-gateway count. Windows are anchored to the newest packet and newest observation in the respective tables, not wall-clock time. Nodes with zero activity are included; <code>total</code> counts nodes matching the channel filter, not just active nodes.</p>
<p>Channel matching is exact. Use positive <code>length</code> and <code>limit</code>, and a nonnegative <code>offset</code>. Only the upper limit of 100 is enforced. Invalid numeric strings can return HTTP 500; any <code>period_type</code> other than the literal <code>hour</code> is treated as days.</p>
</section>
<h2 id="5-edges-api">5. Edges API</h2>
<section class="endpoint" id="get-api-edges"><h3><span class="method">GET</span> <code>/api/edges</code></h3>
<p>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.</p>
<p>A completed traceroute is observed as a response packet, whose <code>from</code>/<code>to</code> are reversed with respect to the traced path, so edges are built as <code>to -&gt; route[] -&gt; from</code>. <code>route[]</code> may contain <code>0xFFFFFFFF</code> placeholders for hops the mesh could not identify; the edges on either side of such a placeholder are omitted, because the nodes around an unknown hop are not neighbours.</p>
<p>Query Parameters</p>
<ul><li><code>type</code> (optional, string): <code>traceroute</code> or <code>neighbor</code>. If omitted, returns both.</li><li><code>node_id</code> (optional, int): Filter edges to only those touching a node.</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;edges&quot;: [
{ &quot;from&quot;: 12345678, &quot;to&quot;: 87654321, &quot;type&quot;: &quot;traceroute&quot; },
{ &quot;from&quot;: 11111111, &quot;to&quot;: 22222222, &quot;type&quot;: &quot;neighbor&quot; }
]
}</code></pre>
<hr>
<p>Unknown <code>type</code> values return an empty edge list. Invalid <code>node_id</code> returns HTTP 400; storage failures can return HTTP 500. A missing node is not an error and normally returns an empty list. Neighbor edges come from the latest stored port-71 sample (the storage helper defaults to 50 packets), not the traceroute 12-hour window.</p>
</section>
<h2 id="6-daily-snapshots-and-configuration">6. Daily Snapshots and Configuration</h2>
<section class="endpoint" id="get-api-snapshots-daily"><h3><span class="method">GET</span> <code>/api/snapshots/daily</code></h3>
<p>Returns stored daily snapshots. For new snapshots, <code>packet_count</code> is the number of packet records imported during <code>date</code> (00:00 UTC inclusive to the next midnight exclusive). The scheduled capture records the previous complete UTC day. Repeated observations of the same packet are not counted separately. <code>node_count</code> counts distinct packet senders whose packets were imported or observed during that UTC day (including observations of previously imported packets). <code>gateway_count</code> counts distinct MQTT gateways with packet observations imported during that day. These are activity counts, not database totals; recipients alone do not count as active nodes. Activity uses local import timestamps, not device timestamps. Older snapshots retain their originally stored counts and are not automatically converted. Counts depend on the packet and observation history still retained at capture time.</p>
<p>Query Parameters</p>
<ul><li><code>length</code> (optional, int): Return the latest N snapshot records, clamped to 1-3650. Omit for all stored snapshots. Results are always ordered by date ascending. This is a record limit, not a guarantee of consecutive calendar dates.</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{&quot;data&quot;:[{&quot;date&quot;:&quot;2026-10-24&quot;,&quot;node_count&quot;:143,&quot;packet_count&quot;:28465,&quot;gateway_count&quot;:17,&quot;captured_at_us&quot;:1792886400000000}]}</code></pre>
<p>No stored snapshots returns <code>{&quot;data&quot;:[]}</code>. Invalid <code>length</code> returns HTTP 400; storage failures return HTTP 500. <code>captured_at_us</code> is the capture time, which may be later than the day summarized by <code>date</code>.</p>
</section>
<section class="endpoint" id="get-api-config"><h3><span class="method">GET</span> <code>/api/config</code></h3>
<p>Returns a safe subset of server configuration.</p>
<p><code>site.map_channel_colors</code> contains channel color overrides from the optional <code>[map_channel_colors]</code> INI section. Each entry is <code>channel = #RRGGBB</code>; invalid colors are omitted. Channel matching on the map ignores case, spaces, hyphens, and underscores. Unlisted channels use generated colors. For example:</p>
<pre><code class="language-ini">[map_channel_colors]
LongFast = #4363d8
LocalChat = #18aa18</code></pre>
<p>No query parameters are supported. Only the <code>site</code>, MQTT server/topics, and cleanup fields shown here are exposed; credentials and the database connection string are not returned. Feature flags and cleanup booleans are lowercase strings (<code>&quot;true&quot;</code> / <code>&quot;false&quot;</code>), not JSON booleans. Cleanup scheduling values are strings; map bounds are numbers and refresh intervals are integers. The removed <code>starting</code> option is not returned: <code>/</code> always serves the dashboard. <code>site.api</code> controls visibility of the API documentation link in the navigation bar, defaults to <code>&quot;true&quot;</code>, and can be disabled with <code>api = False</code> in <code>[site]</code>. This setting does not disable documentation or API routes. Restart the web server and reload the page after changing it. Handler failures return HTTP 500.</p>
<p>Restart the web server and reload the map after changing these settings. Omitting the section uses generated colors for every channel.</p>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;site&quot;: {
&quot;domain&quot;: &quot;example.com&quot;,
&quot;language&quot;: &quot;en&quot;,
&quot;title&quot;: &quot;Meshview&quot;,
&quot;message&quot;: &quot;&quot;,
&quot;nodes&quot;: &quot;true&quot;,
&quot;chat&quot;: &quot;true&quot;,
&quot;everything&quot;: &quot;true&quot;,
&quot;graphs&quot;: &quot;true&quot;,
&quot;stats&quot;: &quot;true&quot;,
&quot;net&quot;: &quot;true&quot;,
&quot;map&quot;: &quot;true&quot;,
&quot;top&quot;: &quot;true&quot;,
&quot;api&quot;: &quot;true&quot;,
&quot;map_top_left_lat&quot;: 39.0,
&quot;map_top_left_lon&quot;: -123.0,
&quot;map_bottom_right_lat&quot;: 36.0,
&quot;map_bottom_right_lon&quot;: -121.0,
&quot;map_interval&quot;: 3,
&quot;map_channel_colors&quot;: {&quot;LongFast&quot;:&quot;#4363d8&quot;},
&quot;firehose_interval&quot;: 3,
&quot;weekly_net_message&quot;: &quot;Weekly Mesh check-in message.&quot;,
&quot;net_tag&quot;: &quot;#BayMeshNet&quot;,
&quot;version&quot;: &quot;3.0.0&quot;
},
&quot;mqtt&quot;: {
&quot;server&quot;: &quot;mqtt.example.com&quot;,
&quot;topics&quot;: [&quot;msh/region/#&quot;]
},
&quot;cleanup&quot;: {
&quot;enabled&quot;: &quot;false&quot;,
&quot;days_to_keep&quot;: &quot;14&quot;,
&quot;hour&quot;: &quot;2&quot;,
&quot;minute&quot;: &quot;0&quot;,
&quot;vacuum&quot;: &quot;false&quot;
}
}</code></pre>
<hr>
</section>
<h2 id="7-language-api">7. Language API</h2>
<section class="endpoint" id="get-api-lang"><h3><span class="method">GET</span> <code>/api/lang</code></h3>
<p>Returns translation strings.</p>
<p>Query Parameters</p>
<ul><li><code>lang</code> (optional, string): Language code (e.g., <code>en</code>, <code>es</code>). Default from config or <code>en</code>.</li><li><code>section</code> (optional, string): Return only one section (e.g., <code>nodelist</code>, <code>firehose</code>).</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;title&quot;: &quot;Meshview&quot;,
&quot;search_placeholder&quot;: &quot;Search...&quot;
}</code></pre>
<hr>
<p>Unknown or invalid language codes fall back to the English file. An unknown section returns HTTP 404. The response has no wrapper: it is either the full translation object or the requested section. Translation-file failures can return HTTP 500.</p>
</section>
<h2 id="8-packets-seen-api">8. Packets Seen API</h2>
<section class="endpoint" id="get-api-packets-seen-packet-id"><h3><span class="method">GET</span> <code>/api/packets_seen/{packet_id}</code></h3>
<p>Returns packet_seen entries for a packet.</p>
<p>Path Parameters</p>
<ul><li><code>packet_id</code> (required, int): Packet ID.</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;seen&quot;: [
{
&quot;packet_id&quot;: 123,
&quot;node_id&quot;: 456,
&quot;rx_time&quot;: 1753188300,
&quot;hop_limit&quot;: 7,
&quot;hop_start&quot;: 0,
&quot;channel&quot;: &quot;main&quot;,
&quot;rx_snr&quot;: 5.0,
&quot;rx_rssi&quot;: -90,
&quot;topic&quot;: &quot;msh/region/#&quot;,
&quot;import_time_us&quot;: 1736370123456789
}
]
}</code></pre>
<hr>
<p><code>node_id</code> identifies the observing MQTT gateway. <code>rx_time</code> is the device-provided receive time in Unix seconds, while <code>import_time_us</code> is local import time in microseconds. Signal fields can be null. Multiple rows can describe the same gateway; consumers wanting unique gateways must deduplicate them. Hop count is usually <code>max(0, hop_start - hop_limit)</code> when both values are known. Observations do not by themselves prove a direct radio link from the sender to that gateway.</p>
<p>No observations, including for an unknown packet, returns <code>{&quot;seen&quot;:[]}</code> with HTTP 200. Invalid path IDs return HTTP 400; handler failures return HTTP 500.</p>
</section>
<h2 id="9-traceroute-api">9. Traceroute API</h2>
<section class="endpoint" id="get-api-traceroute-packet-id"><h3><span class="method">GET</span> <code>/api/traceroute/{packet_id}</code></h3>
<p>Returns traceroute details and derived paths for a packet.</p>
<p>Path Parameters</p>
<ul><li><code>packet_id</code> (required, int): Packet ID.</li></ul>
<p>A completed traceroute is observed as a response packet, whose <code>from</code>/<code>to</code> are reversed with respect to the traced path. <code>initiator</code> and <code>target</code> resolve this: the forward path runs <code>initiator -&gt; forward_hops -&gt; target</code> and the return path runs <code>target -&gt; reverse_hops -&gt; initiator</code>, in both directions of travel. <code>forward_hops</code> and <code>reverse_hops</code> contain only the intermediate hops, never the endpoints.</p>
<p>A gateway usually reports a response that is still travelling home, so <code>reverse_hops</code> is often incomplete. <code>reverse_complete</code> says whether that observation had reached the initiator; only then does the corresponding <code>winning_paths.reverse</code> entry end at the initiator.</p>
<p><code>winning_paths</code> is built from response observations, since a response proves the request reached the target. <code>complete</code> on a <code>unique_forward_paths</code> entry says whether some response reported that hop list, and so whether it is known to end at the target.</p>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;packet&quot;: {
&quot;id&quot;: 123,
&quot;from&quot;: 222,
&quot;to&quot;: 111,
&quot;initiator&quot;: 111,
&quot;target&quot;: 222,
&quot;channel&quot;: &quot;main&quot;
},
&quot;traceroute_packets&quot;: [
{
&quot;index&quot;: 0,
&quot;gateway_node_id&quot;: 333,
&quot;done&quot;: true,
&quot;forward_hops&quot;: [444, 555],
&quot;reverse_hops&quot;: [555, 444],
&quot;reverse_complete&quot;: true
}
],
&quot;unique_forward_paths&quot;: [
{ &quot;path&quot;: [444, 555], &quot;count&quot;: 2, &quot;complete&quot;: true }
],
&quot;unique_reverse_paths&quot;: [
[555, 444]
],
&quot;winning_paths&quot;: {
&quot;forward&quot;: [[111, 444, 555, 222]],
&quot;reverse&quot;: [[222, 555, 444, 111]]
}
}</code></pre>
<hr>
<p><code>traceroute_packets</code> can be empty even when the packet exists. Unknown database packet IDs return HTTP 404. Invalid integer IDs and storage failures can return HTTP 500; this handler does not implement a separate HTTP 400 validation branch.</p>
</section>
<h2 id="10-health-api">10. Health API</h2>
<section class="endpoint" id="get-health"><h3><span class="method">GET</span> <code>/health</code></h3>
<p>Returns service health and database status.</p>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;status&quot;: &quot;healthy&quot;,
&quot;timestamp&quot;: &quot;2025-07-22T12:45:00+00:00&quot;,
&quot;version&quot;: &quot;3.0.3&quot;,
&quot;git_revision&quot;: &quot;abc1234&quot;,
&quot;cleanup&quot;: {
&quot;enabled&quot;: true,
&quot;days_to_keep&quot;: 14,
&quot;scheduled_time&quot;: &quot;02:00&quot;,
&quot;vacuum&quot;: false,
&quot;status&quot;: &quot;ok&quot;,
&quot;status_file&quot;: &quot;dbcleanup.status.json&quot;,
&quot;last_run&quot;: {
&quot;status&quot;: &quot;ok&quot;,
&quot;started_at&quot;: &quot;2026-06-04T09:00:00+00:00&quot;,
&quot;completed_at&quot;: &quot;2026-06-04T09:00:03+00:00&quot;,
&quot;cutoff_at&quot;: &quot;2026-05-21T09:00:00+00:00&quot;,
&quot;days_to_keep&quot;: 14,
&quot;vacuum_requested&quot;: false,
&quot;vacuum_completed&quot;: false,
&quot;rows_deleted&quot;: {
&quot;packet&quot;: 1200,
&quot;packet_seen&quot;: 3400,
&quot;traceroute&quot;: 42,
&quot;node&quot;: 3
},
&quot;error&quot;: null
}
},
&quot;backup&quot;: {
&quot;enabled&quot;: true,
&quot;backup_dir&quot;: &quot;./backups&quot;,
&quot;scheduled_time&quot;: &quot;02:00&quot;,
&quot;status&quot;: &quot;ok&quot;,
&quot;status_file&quot;: &quot;dbbackup.status.json&quot;,
&quot;last_run&quot;: {
&quot;status&quot;: &quot;ok&quot;,
&quot;started_at&quot;: &quot;2026-06-04T09:00:00+00:00&quot;,
&quot;completed_at&quot;: &quot;2026-06-04T09:00:02+00:00&quot;,
&quot;backup_dir&quot;: &quot;./backups&quot;,
&quot;database_path&quot;: &quot;packets.db&quot;,
&quot;backup_file&quot;: &quot;backups/packets_backup_20260604_090000.db.gz&quot;,
&quot;original_size_bytes&quot;: 12939444,
&quot;compressed_size_bytes&quot;: 4211560,
&quot;compression_percent&quot;: 67.5,
&quot;error&quot;: null
}
},
&quot;database&quot;: &quot;connected&quot;,
&quot;database_size&quot;: &quot;12.34 MB&quot;,
&quot;database_size_bytes&quot;: 12939444
}</code></pre>
<hr>
<p>No query parameters. HTTP 200 reports <code>status: &quot;healthy&quot;</code> with database connectivity. A database failure returns HTTP 503 with <code>status: &quot;unhealthy&quot;</code> and <code>database: &quot;disconnected&quot;</code>. <code>seconds_since_last_message</code> is included only when a latest imported packet exists; SQLite size fields appear only when available. Cleanup and backup reports include configured schedules and status-file contents when present. Their status may be <code>disabled</code>, <code>unknown</code>, <code>error</code>, or the last job&#39;s recorded status; a failed backup/cleanup does not itself change the top-level HTTP status. The optional <code>last_run</code> objects depend on the job&#39;s stored report.</p>
</section>
<h2 id="11-version-api">11. Version API</h2>
<section class="endpoint" id="get-version"><h3><span class="method">GET</span> <code>/version</code></h3>
<p>Returns version metadata.</p>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;version&quot;: &quot;3.0.3&quot;,
&quot;release_date&quot;: &quot;2026-1-15&quot;,
&quot;git_revision&quot;: &quot;abc1234&quot;,
&quot;git_revision_short&quot;: &quot;abc1234&quot;
}</code></pre>
<p>No query parameters. HTTP 500 with an <code>error</code> field if version metadata cannot be retrieved. A revision may be <code>unknown</code> if Git metadata is unavailable.</p>
</section>
<h2 id="12-node-contact-url">12. Node Contact URL</h2>
<section class="endpoint" id="get-api-node-node-id-qr"><h3><span class="method">GET</span> <code>/api/node/{node_id}/qr</code></h3>
<p>Returns a Meshtastic shared-contact URL as JSON, not a PNG or SVG image. The client can encode <code>meshtastic_url</code> in a QR code. No query parameters are supported.</p>
<p>Path Parameters</p>
<ul><li><code>node_id</code> (required, int): Node number in decimal or <code>0x</code> hexadecimal form.</li></ul>
<p>Response Example</p>
<pre><code class="language-json">{
&quot;node_id&quot;:1234,
&quot;long_name&quot;:&quot;Alice&quot;,
&quot;short_name&quot;:&quot;A&quot;,
&quot;role&quot;:&quot;CLIENT&quot;,
&quot;meshtastic_url&quot;:&quot;https://meshtastic.org/v/#BASE64URL_CONTACT&quot;
}</code></pre>
<p>The example contact payload is a placeholder, not an importable contact. The URL encodes node identity and available user metadata as a base64url SharedContact protobuf, with <code>manually_verified</code> false. Metadata can be null.</p>
<p>Errors: HTTP 400 for invalid IDs; HTTP 404 when the node is absent; HTTP 500 for contact serialization failures or unhandled storage errors.</p>
</section>
<h2 id="13-predicted-radio-coverage">13. Predicted Radio Coverage</h2>
<section class="endpoint" id="get-api-coverage-node-id"><h3><span class="method">GET</span> <code>/api/coverage/{node_id}</code></h3>
<p>Computes an ITM area-model prediction centered on the node&#39;s last stored position. This is a model prediction, not a measured coverage boundary or terrain profile. The optional <code>pyitm</code> dependency is required. Calculations run off the event loop and reuse cached model results. All parameters are optional except the node ID.</p>
<p>Path Parameters</p>
<ul><li><code>node_id</code> (required, int): Node number in decimal or <code>0x</code> hexadecimal form.</li></ul>
<p>Query Parameters</p>
<ul><li><code>mode</code> (string, default <code>perimeter</code>): <code>perimeter</code> or <code>heatmap</code>. Currently every value other than the exact string <code>perimeter</code> selects the heatmap branch.</li><li><code>freq_mhz</code> (number, default <code>907</code>): Frequency in MHz; range 1-10000.</li><li><code>tx_dbm</code> (number, default <code>20</code>): Transmit power in dBm; range -50 to 60.</li><li><code>tx_height_m</code> (number, default <code>5</code>): Transmit antenna height in meters; range 0-1000.</li><li><code>rx_height_m</code> (number, default <code>1.5</code>): Receive antenna height in meters; range 0-1000.</li><li><code>radius_km</code> (number, default <code>40</code>): Maximum distance in kilometers; range 1-200.</li><li><code>step_km</code> (number, default <code>0.25</code>): Radial sample spacing in kilometers; range 0.05-50.</li><li><code>reliability</code> (number, default <code>0.5</code>): ITM time fraction; range 0.01-0.99.</li><li><code>threshold_dbm</code> (number, default <code>-120</code>): Perimeter received-power threshold in dBm; range -200 to 0. Ignored by heatmap computation, although still validated.</li></ul>
<p>Numeric bounds are inclusive, values must be finite, and <code>radius_km / step_km</code> must not exceed 4000. Smaller steps increase computation cost.</p>
<p>Response Example (<code>mode=perimeter</code>)</p>
<pre><code class="language-json">{
&quot;mode&quot;:&quot;perimeter&quot;,
&quot;threshold_dbm&quot;:-120.0,
&quot;perimeter&quot;:[[30.21,-93.20],[30.209,-93.198]]
}</code></pre>
<p><code>perimeter</code> contains <code>[latitude, longitude]</code> degree pairs for the furthest qualifying sample on each modeled bearing. Bearings with no qualifying sample are omitted; the list is not necessarily a closed GeoJSON polygon.</p>
<p>Response Example (<code>mode=heatmap</code>)</p>
<pre><code class="language-json">{
&quot;mode&quot;:&quot;heatmap&quot;,
&quot;min_dbm&quot;:-130.0,
&quot;max_dbm&quot;:-80.0,
&quot;points&quot;:[[30.21,-93.20,-110.5]]
}</code></pre>
<p><code>points</code> contains <code>[latitude, longitude, received_power_dbm]</code> triples. Min/max values provide a color-scale range, extended from the defaults to include computed values. An empty perimeter or point list is a valid result when no samples qualify.</p>
<p>Errors: HTTP 400 for invalid IDs, nonnumeric/nonfinite/out-of-range parameters, or an excessive radius/step ratio; HTTP 404 for an unknown node or missing/zero-valued stored coordinates; HTTP 503 when <code>pyitm</code> is unavailable. Dependency availability is checked before numeric query validation and node lookup. Unexpected model/storage failures can return HTTP 500.</p>
</section>
</main>
<footer>Source: docs/API_Documentation.md · Generated with node scripts/build-api-docs.mjs</footer>
<p style="text-align:center; color:#666;">Meshview API — generated documentation</p>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

-166
View File
@@ -1,166 +0,0 @@
/* Read-only chat presentation using Meshview's existing packet API. */
document.addEventListener('DOMContentLoaded', async () => {
const log = document.getElementById('chat-log');
const channel = document.getElementById('channel-filter');
const search = document.getElementById('chat-search');
const status = document.getElementById('chat-status');
const pause = document.getElementById('chat-pause');
const latest = document.getElementById('chat-latest');
const packets = new Map();
let lastTime = null;
let paused = false;
let busy = false;
let loaded = false;
let unread = 0;
let chatLang = {};
const colors = ['#b54136', '#2563b4', '#23824d', '#8553af', '#a65d19', '#15817b', '#b63b79'];
const timeOf = p => Number(p.import_time_us) || Date.parse(p.import_time) * 1000 || 0;
const atBottom = () => log.scrollHeight - log.scrollTop - log.clientHeight < 60;
const nodeName = p => (p.long_name || '').trim() || `Node ${p.from_node_id}`;
const packetUrl = id => `/packet/${encodeURIComponent(id)}`;
function setStatus(text, state) { status.textContent = text; status.dataset.state = state; }
function goLatest() { log.scrollTop = log.scrollHeight; unread = 0; latest.textContent = '↓ Latest'; }
function render(scrollToBottom = false, highlights = new Set()) {
const query = search.value.trim().toLowerCase();
const sorted = [...packets.values()].sort((a, b) => timeOf(a) - timeOf(b));
const visible = sorted.filter(p => (!channel.value || (p.channel || '') === channel.value) &&
`${nodeName(p)} ${p.payload || ''} ${p.from_node_id} ${p.channel || ''}`.toLowerCase().includes(query));
const fragment = document.createDocumentFragment();
let lastDay = '';
const parents = new Map(sorted.map(p => [String(p.packet_id ?? p.id), p]));
for (const packet of visible) {
const date = new Date(timeOf(packet) / 1000);
const day = date.toLocaleDateString([], { weekday:'long', month:'long', day:'numeric', year:'numeric' });
if (day !== lastDay) {
const separator = document.createElement('div');
separator.className = 'chat-date-sep'; separator.textContent = day;
fragment.append(separator); lastDay = day;
}
const row = document.createElement('article');
row.className = `chat-line${highlights.has(String(packet.id)) ? ' flash' : ''}`;
row.dataset.packetId = packet.id;
let hash = 0;
for (const char of String(packet.from_node_id)) hash = (hash * 31 + char.charCodeAt(0)) >>> 0;
const time = document.createElement('time');
time.className = 'chat-time'; time.dateTime = date.toISOString(); time.title = date.toLocaleString();
time.textContent = date.toLocaleTimeString([], {hour:'2-digit', minute:'2-digit', hour12:false});
const nick = document.createElement('a');
nick.className = 'chat-nick'; nick.href = `/node/${encodeURIComponent(packet.from_node_id)}`;
nick.textContent = nodeName(packet); nick.title = nodeName(packet); nick.style.color = colors[hash % colors.length];
const message = document.createElement('div'); message.className = 'chat-message';
// Mesh payloads and node names are untrusted text, never markup.
message.textContent = packet.payload ?? '';
if (packet.reply_id) {
const reply = document.createElement('span'); reply.className = 'replying-to';
const parent = parents.get(String(packet.reply_id)) || packets.get(String(packet.reply_id));
reply.append(`${chatLang.replying_to || 'Replying to:'} `);
if (parent) reply.append(`${nodeName(parent)}: ${parent.payload || ''}`);
else {
const link = document.createElement('a'); link.href = packetUrl(packet.reply_id);
link.textContent = String(packet.reply_id); reply.append(link);
}
message.append(reply);
}
const meta = document.createElement('span'); meta.className = 'chat-meta';
const tag = document.createElement('span'); tag.className = 'chat-channel';
tag.textContent = packet.channel ? `# ${packet.channel}` : 'Unknown channel'; tag.title = packet.channel || 'Unknown channel';
const details = document.createElement('a'); details.className = 'chat-details'; details.href = packetUrl(packet.id);
details.textContent = 'Details ↗'; details.title = chatLang.view_packet_details || 'View packet details';
details.setAttribute('aria-label', details.title);
meta.append(tag, details); row.append(time, nick, message, meta); fragment.append(row);
}
if (!visible.length) {
const empty = document.createElement('p'); empty.className = 'chat-empty';
empty.textContent = packets.size ? 'No messages match your filters.' : 'No text messages received yet.';
fragment.append(empty);
}
const previousTop = log.scrollTop;
log.replaceChildren(fragment);
document.getElementById('chat-count').textContent = `${visible.length} message${visible.length === 1 ? '' : 's'}`;
if (scrollToBottom) goLatest(); else log.scrollTop = previousTop;
}
async function fetchMessages() {
if (paused || busy || document.hidden) return;
busy = true;
try {
const url = new URL('/api/packets', location.origin);
url.searchParams.set('portnum', '1'); url.searchParams.set('limit', '100');
if (lastTime) url.searchParams.set('since', lastTime);
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
if (!Array.isArray(data.packets)) throw new Error('Invalid packet response');
const follow = !loaded || atBottom();
const added = new Set();
for (const packet of data.packets) {
const id = String(packet.id);
if (!packets.has(id)) { packets.set(id, packet); added.add(id); }
if (packet.channel && ![...channel.options].some(o => o.value === packet.channel)) {
channel.add(new Option(packet.channel, packet.channel));
}
}
// Keep the browser's session history bounded without changing the API.
if (packets.size > 1000) {
const oldest = [...packets.values()].sort((a, b) => timeOf(a) - timeOf(b));
for (const p of oldest.slice(0, packets.size - 1000)) packets.delete(String(p.id));
}
if (!loaded || added.size) render(follow, loaded ? added : new Set());
if (loaded && !follow && added.size) {
unread += [...added].filter(id => {
const p = packets.get(id);
return p && (!channel.value || p.channel === channel.value) &&
`${nodeName(p)} ${p.payload || ''} ${p.from_node_id} ${p.channel || ''}`.toLowerCase().includes(search.value.trim().toLowerCase());
}).length;
latest.textContent = unread ? `↓ Latest (${unread})` : '↓ Latest';
}
lastTime = data.latest_import_time || lastTime;
loaded = true;
setStatus(paused ? 'Paused' : 'Live', paused ? 'paused' : 'live');
document.getElementById('chat-updated').textContent = `Updated ${new Date().toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'})}`;
} catch (error) {
console.error('Chat fetch:', error);
if (!paused) setStatus('Retrying…', 'error');
if (!loaded) log.innerHTML = '<p class="chat-empty">Unable to load messages. Retrying automatically…</p>';
} finally { busy = false; }
}
channel.addEventListener('change', () => render(true));
search.addEventListener('input', () => render(true));
latest.addEventListener('click', goLatest);
log.addEventListener('scroll', () => { if (atBottom()) { unread = 0; latest.textContent = '↓ Latest'; } });
pause.addEventListener('click', () => {
paused = !paused; pause.setAttribute('aria-pressed', String(paused));
pause.textContent = paused ? 'Resume' : 'Pause';
setStatus(paused ? 'Paused' : 'Connecting…', paused ? 'paused' : 'loading');
if (!paused) fetchMessages();
});
document.addEventListener('visibilitychange', () => { if (!document.hidden) fetchMessages(); });
// Load optional translations and channel metadata without delaying messages.
(async () => {
try {
const cfg = await window._siteConfigPromise;
const response = await fetch(`/api/lang?lang=${encodeURIComponent(cfg?.site?.language || 'en')}&section=chat`);
if (!response.ok) return;
chatLang = await response.json();
document.querySelectorAll('[data-chat-translate]').forEach(el => {
if (chatLang[el.dataset.chatTranslate]) el.textContent = chatLang[el.dataset.chatTranslate];
});
if (loaded) render(atBottom());
} catch (error) { console.error('Chat translations:', error); }
})();
(async () => {
try {
const response = await fetch('/api/channels');
if (!response.ok) return;
const data = await response.json();
for (const name of data.channels || []) {
if (![...channel.options].some(o => o.value === name)) channel.add(new Option(name, name));
}
} catch (error) { console.error('Chat channels:', error); }
})();
await fetchMessages();
setInterval(fetchMessages, 5000);
});
Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 15 KiB

-75
View File
@@ -4,7 +4,6 @@
<meta charset="utf-8" />
<title>Mesh Nodes Population Heatmap</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="/static/theme.js"></script>
<style>
body { margin: 0; background: #000; }
#map { height: 100vh; width: 100%; }
@@ -20,82 +19,8 @@
.legend-item { display: flex; align-items: center; margin-bottom: 5px; }
.legend-color { width: 18px; height: 18px; margin-right: 6px; border-radius: 3px; }
</style>
<!-- mesh-theme:start -->
<style>
:root {
color-scheme:light;
--mesh-primary:#187346;
--mesh-primary-dark:#0f5132;
--mesh-primary-rgb:24,115,70;
--mesh-brand:#187346;
--mesh-brand-deep:#0f5132;
--mesh-surface:#ffffff;
--mesh-text:#243247;
--mesh-soft:#eaf5ee;
--mesh-hover:#dceee2;
--mesh-border:#dce7df;
--mesh-page:#f5f9f6;
--mesh-stripe:#f7faf8;
--mesh-muted:#64748b;
--mesh-chat-stripe:#eef6f0;
--mesh-pulse-soft:#edf8f0;
--mesh-pulse-peak:#ccebd7;
--mesh-pulse-mid:#e2f3e8;
}
[data-bs-theme="dark"] {
color-scheme:dark;
--mesh-primary:#80cfa3;
--mesh-primary-dark:#a3e3be;
--mesh-primary-rgb:128,207,163;
--mesh-brand:#14532d;
--mesh-brand-deep:#0c3a1f;
--mesh-surface:#18231e;
--mesh-text:#e2ece5;
--mesh-soft:#203c2b;
--mesh-hover:#294c36;
--mesh-border:#34483c;
--mesh-page:#101914;
--mesh-stripe:#1c2a22;
--mesh-muted:#9faea6;
--mesh-chat-stripe:#203227;
--mesh-pulse-soft:#203c2b;
--mesh-pulse-peak:#356b49;
--mesh-pulse-mid:#294c36;
--bs-link-color:var(--mesh-primary);
--bs-link-color-rgb:var(--mesh-primary-rgb);
--bs-link-hover-color:var(--mesh-primary-dark);
--bs-link-hover-color-rgb:163,227,190;
}
body { background:var(--mesh-page); color:var(--mesh-text); }
.mesh-theme-toggle { flex-shrink:0; display:inline-flex; align-items:center; justify-content:center; width:34px; height:34px; border:1px solid #ffffff70; border-radius:6px; background:transparent; color:white; font:22px/1 system-ui,sans-serif; cursor:pointer; }
.mesh-header .mesh-theme-toggle { margin-left:auto; }
.mesh-theme-toggle:hover { background:#ffffff20; }
.mesh-theme-toggle:focus-visible { outline:2px solid white; outline-offset:3px; }
@media(max-width:1000px) { .mesh-header .mesh-menu-toggle { margin-left:auto; } .mesh-header .mesh-theme-toggle { margin-left:12px; } .mesh-header #site-menu { order:4; } }
[data-bs-theme="dark"] :is(.chat-status,.chat-details,.chat-channel,.chat-status[data-state="paused"],.chat-status[data-state="loading"],.good-x) { background:var(--mesh-soft); color:var(--mesh-primary); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.chat-status[data-state="error"],.bad-x) { background:#472a24; color:#ffb4a6; }
[data-bs-theme="dark"] .ok-x { background:#453820; color:#f1d38a; }
[data-bs-theme="dark"] .chat-details:hover { background:var(--mesh-hover); color:var(--mesh-primary-dark); }
[data-bs-theme="dark"] .chat-nick { filter:brightness(1.4) saturate(.8); }
[data-bs-theme="dark"] :is(.summary-card:nth-child(2) .summary-count,.summary-card:nth-child(3) .summary-count,.summary-card:nth-child(4) .summary-count,.mesh-metric:nth-child(2) strong,.mesh-metric:nth-child(3) strong,.reach-metric:nth-child(2) .reach-metric-value) { color:var(--mesh-primary); }
[data-bs-theme="dark"] :is(.reliability-status-heard) { color:#8fd7aa!important; }
[data-bs-theme="dark"] .reliability-status-missed { color:#ffb4a6!important; }
[data-bs-theme="dark"] .reach-count-bar-value span { color:#17263c; }
[data-bs-theme="dark"] .leaflet-tile-pane { filter:invert(1) hue-rotate(180deg) brightness(.85) saturate(.75); }
[data-bs-theme="dark"] :is(.leaflet-container,.leaflet-control-layers,.leaflet-bar a,.leaflet-popup-content-wrapper,.leaflet-popup-tip,.leaflet-tooltip,.leaflet-control-attribution,.leaflet-control-scale-line,#unmapped-packets,#legend,#node-info,.legend) { background:var(--mesh-surface); color:var(--mesh-text); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.leaflet-control-layers label,.leaflet-popup-close-button,#unmapped-packets h3,.unmapped-node,.blinking-tooltip,.legend) { color:var(--mesh-text); }
[data-bs-theme="dark"] :is(.leaflet-bar a:hover,.leaflet-control-layers-expanded) { background:var(--mesh-stripe); }
[data-bs-theme="dark"] :is(.unmapped-empty,.reach-muted) { color:var(--mesh-muted); }
[data-bs-theme="dark"] :is(.source-marker,.reach-map-marker) { color:white; }
[data-bs-theme="dark"] .qr-image { background:white; }
[data-bs-theme="dark"] :is(#traceroute-error,#map-load-status,.text-danger) { color:#ffb4a6; }
[data-bs-theme="dark"] .reach-count-bar-track { background:var(--mesh-soft); }
</style>
<!-- mesh-theme:end -->
</head>
<body>
<button class="mesh-theme-toggle" style="position:fixed;top:12px;right:12px;z-index:2000;background:#187346" type="button" data-theme-toggle aria-label="Switch to night mode" aria-pressed="false">☾</button>
<div id="map"></div>
<div id="legend"></div>
+2 -76
View File
@@ -4,7 +4,6 @@
<meta charset="utf-8" />
<title>Mesh Nodes Live Map</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin=""/>
<script src="/static/theme.js"></script>
<style>
body { margin: 0; font-family: monospace; background: #121212; color: #eee; }
#map { height: 100vh; width: 100%; }
@@ -34,82 +33,8 @@ body { margin: 0; font-family: monospace; background: #121212; color: #eee; }
padding: 2px 5px;
}
</style>
<!-- mesh-theme:start -->
<style>
:root {
color-scheme:light;
--mesh-primary:#187346;
--mesh-primary-dark:#0f5132;
--mesh-primary-rgb:24,115,70;
--mesh-brand:#187346;
--mesh-brand-deep:#0f5132;
--mesh-surface:#ffffff;
--mesh-text:#243247;
--mesh-soft:#eaf5ee;
--mesh-hover:#dceee2;
--mesh-border:#dce7df;
--mesh-page:#f5f9f6;
--mesh-stripe:#f7faf8;
--mesh-muted:#64748b;
--mesh-chat-stripe:#eef6f0;
--mesh-pulse-soft:#edf8f0;
--mesh-pulse-peak:#ccebd7;
--mesh-pulse-mid:#e2f3e8;
}
[data-bs-theme="dark"] {
color-scheme:dark;
--mesh-primary:#80cfa3;
--mesh-primary-dark:#a3e3be;
--mesh-primary-rgb:128,207,163;
--mesh-brand:#14532d;
--mesh-brand-deep:#0c3a1f;
--mesh-surface:#18231e;
--mesh-text:#e2ece5;
--mesh-soft:#203c2b;
--mesh-hover:#294c36;
--mesh-border:#34483c;
--mesh-page:#101914;
--mesh-stripe:#1c2a22;
--mesh-muted:#9faea6;
--mesh-chat-stripe:#203227;
--mesh-pulse-soft:#203c2b;
--mesh-pulse-peak:#356b49;
--mesh-pulse-mid:#294c36;
--bs-link-color:var(--mesh-primary);
--bs-link-color-rgb:var(--mesh-primary-rgb);
--bs-link-hover-color:var(--mesh-primary-dark);
--bs-link-hover-color-rgb:163,227,190;
}
body { background:var(--mesh-page); color:var(--mesh-text); }
.mesh-theme-toggle { flex-shrink:0; display:inline-flex; align-items:center; justify-content:center; width:34px; height:34px; border:1px solid #ffffff70; border-radius:6px; background:transparent; color:white; font:22px/1 system-ui,sans-serif; cursor:pointer; }
.mesh-header .mesh-theme-toggle { margin-left:auto; }
.mesh-theme-toggle:hover { background:#ffffff20; }
.mesh-theme-toggle:focus-visible { outline:2px solid white; outline-offset:3px; }
@media(max-width:1000px) { .mesh-header .mesh-menu-toggle { margin-left:auto; } .mesh-header .mesh-theme-toggle { margin-left:12px; } .mesh-header #site-menu { order:4; } }
[data-bs-theme="dark"] :is(.chat-status,.chat-details,.chat-channel,.chat-status[data-state="paused"],.chat-status[data-state="loading"],.good-x) { background:var(--mesh-soft); color:var(--mesh-primary); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.chat-status[data-state="error"],.bad-x) { background:#472a24; color:#ffb4a6; }
[data-bs-theme="dark"] .ok-x { background:#453820; color:#f1d38a; }
[data-bs-theme="dark"] .chat-details:hover { background:var(--mesh-hover); color:var(--mesh-primary-dark); }
[data-bs-theme="dark"] .chat-nick { filter:brightness(1.4) saturate(.8); }
[data-bs-theme="dark"] :is(.summary-card:nth-child(2) .summary-count,.summary-card:nth-child(3) .summary-count,.summary-card:nth-child(4) .summary-count,.mesh-metric:nth-child(2) strong,.mesh-metric:nth-child(3) strong,.reach-metric:nth-child(2) .reach-metric-value) { color:var(--mesh-primary); }
[data-bs-theme="dark"] :is(.reliability-status-heard) { color:#8fd7aa!important; }
[data-bs-theme="dark"] .reliability-status-missed { color:#ffb4a6!important; }
[data-bs-theme="dark"] .reach-count-bar-value span { color:#17263c; }
[data-bs-theme="dark"] .leaflet-tile-pane { filter:invert(1) hue-rotate(180deg) brightness(.85) saturate(.75); }
[data-bs-theme="dark"] :is(.leaflet-container,.leaflet-control-layers,.leaflet-bar a,.leaflet-popup-content-wrapper,.leaflet-popup-tip,.leaflet-tooltip,.leaflet-control-attribution,.leaflet-control-scale-line,#unmapped-packets,#legend,#node-info,.legend) { background:var(--mesh-surface); color:var(--mesh-text); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.leaflet-control-layers label,.leaflet-popup-close-button,#unmapped-packets h3,.unmapped-node,.blinking-tooltip,.legend) { color:var(--mesh-text); }
[data-bs-theme="dark"] :is(.leaflet-bar a:hover,.leaflet-control-layers-expanded) { background:var(--mesh-stripe); }
[data-bs-theme="dark"] :is(.unmapped-empty,.reach-muted) { color:var(--mesh-muted); }
[data-bs-theme="dark"] :is(.source-marker,.reach-map-marker) { color:white; }
[data-bs-theme="dark"] .qr-image { background:white; }
[data-bs-theme="dark"] :is(#traceroute-error,#map-load-status,.text-danger) { color:#ffb4a6; }
[data-bs-theme="dark"] .reach-count-bar-track { background:var(--mesh-soft); }
</style>
<!-- mesh-theme:end -->
</head>
<body>
<button class="mesh-theme-toggle" style="position:fixed;top:12px;right:12px;z-index:2000;background:#187346" type="button" data-theme-toggle aria-label="Switch to night mode" aria-pressed="false">☾</button>
<div id="map"></div>
@@ -180,12 +105,13 @@ body { background:var(--mesh-page); color:var(--mesh-text); }
if(isInvalidCoord(node)) return;
const lat = node.last_lat/1e7;
const lng = node.last_long/1e7;
const isRouter = node.role.toLowerCase().includes("router");
channels.add(node.channel);
nodeMap.set(node.node_id,node);
const color = hashToColor(node.channel);
const marker = L.circleMarker([lat,lng],{radius:6,color:"white",fillColor:color,fillOpacity:1,weight:0.7}).addTo(map);
const marker = L.circleMarker([lat,lng],{radius:isRouter?9:7,color:"white",fillColor:color,fillOpacity:1,weight:0.7}).addTo(map);
marker.nodeId = node.node_id;
marker.originalColor = color;
markerById[node.node_id]=marker;
-65
View File
@@ -1,65 +0,0 @@
/* UI only: reuse the map's nodes, markers, and existing API. */
function initializeNodeExplorer() {
const activeSince = Date.now() - 24 * 60 * 60 * 1000;
if (document.getElementById('metric-nodes')) {
document.getElementById('metric-nodes').textContent = nodes.length.toLocaleString();
document.getElementById('metric-active').textContent = nodes.filter(n => n.last_seen_us / 1000 >= activeSince).length.toLocaleString();
document.getElementById('metric-gateways').textContent = nodes.filter(n => n.is_mqtt_gateway).length.toLocaleString();
}
renderNodeExplorer();
}
function renderNodeExplorer() {
const query = document.getElementById('node-search').value.trim().toLowerCase();
const matches = nodes.filter(n => `${n.long_name} ${n.short_name} ${n.key} ${Number(n.key).toString(16)}`.toLowerCase().includes(query));
matches.sort((a, b) => (b.last_seen_us || 0) - (a.last_seen_us || 0));
const list = document.getElementById('mesh-node-list');
list.replaceChildren();
document.getElementById('node-result-count').textContent = matches.length;
if (!matches.length) {
const empty = document.createElement('p');
empty.className = 'mesh-empty';
empty.textContent = query ? 'No nodes match your search.' : 'No nodes seen in the last 3 days.';
list.append(empty);
}
for (const node of matches) {
const row = document.createElement('button');
row.type = 'button';
row.className = 'mesh-node-row';
const active = node.last_seen_us / 1000 >= Date.now() - 86400000;
row.innerHTML = `<span class="mesh-node-dot${active ? '' : ' offline'}" aria-hidden="true"></span><span class="mesh-node-copy"><strong>${escapeHtml(node.long_name || node.short_name || String(node.key))}</strong><small>${escapeHtml(node.short_name || 'Node')} · ${active ? 'Seen within 24h' : 'Seen within 3 days'}</small></span><span class="mesh-node-role">${markerById[node.key] ? '↗' : 'No GPS'}</span>`;
row.addEventListener('click', () => {
const marker = markerById[node.key];
if (!marker) {
openMapNodeInspector(node);
return;
}
// Selecting a search result also reveals it if a saved filter hid it.
nodeLayer.addTo(map);
nodeLayer.addLayer(marker);
map.setView(marker.getLatLng(), Math.max(map.getZoom(), 12));
marker.fire('click');
});
list.append(row);
}
}
document.getElementById('node-search').addEventListener('input', renderNodeExplorer);
document.getElementById('fit-network').addEventListener('click', () => {
const points = Object.values(markerById).filter(marker => nodeLayer.hasLayer(marker)).map(marker => marker.getLatLng());
if (points.length) map.fitBounds(L.latLngBounds(points), { padding: [35, 35], maxZoom: 13 });
});
(async () => {
if (!document.getElementById('metric-packets')) return;
try {
const response = await fetch('/api/stats/count');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const counts = await response.json();
document.getElementById('metric-packets').textContent = Number(counts.total_packets || 0).toLocaleString();
document.getElementById('metric-status').textContent = 'All packets in database';
} catch (error) {
document.getElementById('metric-status').textContent = 'Packet totals unavailable';
console.error('Dashboard totals:', error);
}
})();
-165
View File
@@ -1,165 +0,0 @@
/* Shared node inspector for Home and Map, using existing APIs and packet events. */
(() => {
const byId = id => document.getElementById(id);
let nodeRequest = null;
let inspectedNodeId = null;
let recentPackets = [];
let telemetryTime = -1;
const nodeKey = node => node.key ?? node.node_id;
const findNode = id => nodeMap.get(Number(id)) || nodeMap.get(id);
const nodeName = (id, fallback) => {
const node = findNode(id);
return node?.long_name || node?.short_name || fallback || `Node ${id}`;
};
const packetTime = packet => Number(packet.import_time_us) || 0;
const packetId = packet => packet.storage_id ?? packet.id;
const portName = packet => window.PORT_LABEL_MAP[packet.portnum] || `Port ${packet.portnum ?? '?'}`;
const dateText = us => us ? new Date(Number(us) / 1000).toLocaleString() : 'Unknown time';
const timeText = us => us ? new Date(Number(us) / 1000).toLocaleTimeString([], {hour:'2-digit', minute:'2-digit', hour12:false}) : '—';
async function fetchJson(url, signal) {
const response = await fetch(url, {signal});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
function note(container, text) {
const p = document.createElement('p');
p.className = 'mesh-inspector-note'; p.textContent = text;
container.replaceChildren(p);
}
function facts(node) {
byId('inspector-name').textContent = node.long_name || node.short_name || `Node ${nodeKey(node)}`;
byId('inspector-node-meta').textContent = `${node.short_name || 'Node'} · ${nodeKey(node)}`;
const container = byId('inspector-facts'); container.replaceChildren();
for (const [label, value] of [
['Role', node.role || 'Unknown'], ['Hardware', node.hw_model || 'Unknown'],
['Firmware', node.firmware || 'Unknown'], ['Channel', node.channel || 'Unknown'],
['Gateway', node.is_mqtt_gateway == null ? 'Unknown' : node.is_mqtt_gateway ? 'Yes' : 'No'],
['Last seen', dateText(node.last_seen_us)],
['Location', isInvalidCoord(node) ? 'No reported position' : `${node.lat.toFixed(5)}, ${node.long.toFixed(5)}`]
]) {
const dt = document.createElement('dt'); dt.textContent = label;
const dd = document.createElement('dd'); dd.textContent = value;
container.append(dt, dd);
}
}
function normalizeNode(node) {
return {...node, key: node.node_id, lat: node.last_lat / 1e7 || null, long: node.last_long / 1e7 || null};
}
function renderTelemetry(packet) {
const container = byId('inspector-telemetry');
if (packet && packetTime(packet) < telemetryTime) return;
if (packet) telemetryTime = packetTime(packet);
if (!packet && telemetryTime >= 0) return;
if (!packet) { note(container, 'No telemetry packets found.'); return; }
const payload = String(packet.payload || '');
const value = field => {
const match = payload.match(new RegExp(`(?:^|[\\s{])${field}:\\s*(-?\\d+(?:\\.\\d+)?)`));
return match ? Number(match[1]) : null;
};
const battery = value('battery_level');
const voltage = value('voltage');
const channelUtil = value('channel_utilization');
const airUtil = value('air_util_tx');
const values = [
['Battery', battery === null ? null : battery > 100 ? 'Powered' : `${battery}%`],
['Voltage', voltage === null ? null : `${voltage.toFixed(2)} V`],
['Channel utilization', channelUtil === null ? null : `${channelUtil.toFixed(1)}%`],
['Air utilization TX', airUtil === null ? null : `${airUtil.toFixed(1)}%`]
].filter(([, value]) => value !== null);
if (!values.length) { note(container, 'No device metrics in the latest telemetry packet.'); return; }
container.replaceChildren();
const grid = document.createElement('div'); grid.className = 'mesh-inspector-telemetry';
for (const [label, value] of values) {
const cell = document.createElement('div');
const strong = document.createElement('strong'); strong.textContent = value;
const span = document.createElement('span'); span.textContent = label;
cell.append(strong, span); grid.append(cell);
}
const stamp = document.createElement('p'); stamp.className = 'mesh-inspector-note';
stamp.textContent = `Reported ${dateText(packet.import_time_us)}`;
container.append(grid, stamp);
}
function renderRecent() {
const container = byId('inspector-recent');
if (!recentPackets.length) { note(container, 'No recent packets found.'); return; }
container.replaceChildren();
for (const packet of recentPackets) {
const button = document.createElement('a');
button.href = `/packet/${encodeURIComponent(packetId(packet))}`;
button.className = 'mesh-inspector-packet';
const heading = document.createElement('strong');
heading.textContent = `${portName(packet)} · ${timeText(packet.import_time_us)}`;
const preview = document.createElement('small');
preview.textContent = packet.payload || `From ${nodeName(packet.from_node_id, packet.long_name)}`;
button.append(heading, preview);
container.append(button);
}
}
window.openMapNodeInspector = async (node, force = false) => {
const id = String(nodeKey(node));
if (!force && inspectedNodeId === id && !byId('mesh-node-inspector').hidden) return;
nodeRequest?.abort();
const request = new AbortController(); nodeRequest = request;
inspectedNodeId = id; recentPackets = []; telemetryTime = -1;
byId('mesh-node-browser').hidden = true;
byId('mesh-node-inspector').hidden = false;
byId('inspector-node-link').href = `/node/${encodeURIComponent(id)}`;
byId('inspector-reliability-link').href = `/reliability?node_id=${encodeURIComponent(id)}`;
facts(node);
note(byId('inspector-telemetry'), 'Loading telemetry…');
note(byId('inspector-recent'), 'Loading recent packets…');
if (matchMedia('(max-width: 700px)').matches) byId('mesh-node-inspector').scrollIntoView({block:'nearest'});
// A sender/gateway may be outside the map's recent-node snapshot.
if (force || !findNode(id)) {
fetchJson(`/api/nodes?node_id=${encodeURIComponent(id)}`, request.signal).then(data => {
if (request.signal.aborted) return;
const raw = data.nodes?.[0];
if (raw) {
const complete = normalizeNode(raw); nodeMap.set(Number(id), complete); facts(complete);
} else byId('inspector-node-meta').textContent = `Node ${id} · no node information available`;
}).catch(error => {
if (error.name !== 'AbortError') byId('inspector-node-meta').textContent = `Node ${id} · details unavailable`;
});
}
await Promise.all([
fetchJson(`/api/packets?from_node_id=${encodeURIComponent(id)}&portnum=67&limit=1`, request.signal).then(data => {
if (request.signal.aborted) return;
if (!Array.isArray(data.packets)) throw new Error('Invalid telemetry response');
renderTelemetry(data.packets[0]);
}).catch(error => {
if (error.name !== 'AbortError') note(byId('inspector-telemetry'), 'Telemetry unavailable. Use Refresh data to retry.');
}),
fetchJson(`/api/packets?node_id=${encodeURIComponent(id)}&limit=8`, request.signal).then(data => {
if (request.signal.aborted) return;
if (!Array.isArray(data.packets)) throw new Error('Invalid packet response');
const merged = new Map([...data.packets, ...recentPackets].map(p => [String(packetId(p)), p]));
recentPackets = [...merged.values()].sort((a,b) => packetTime(b)-packetTime(a)).slice(0,8);
renderRecent();
}).catch(error => {
if (error.name !== 'AbortError') note(byId('inspector-recent'), 'Recent packets unavailable. Use Refresh data to retry.');
})
]);
};
byId('inspector-refresh').addEventListener('click', () => {
if (inspectedNodeId) openMapNodeInspector(findNode(inspectedNodeId) || {key:Number(inspectedNodeId)}, true);
});
byId('inspector-back').addEventListener('click', () => {
nodeRequest?.abort(); inspectedNodeId = null;
byId('mesh-node-inspector').hidden = true;
byId('mesh-node-browser').hidden = false;
byId('node-search').focus({preventScroll:true});
});
document.addEventListener('mesh:packets', event => {
for (const packet of event.detail) {
if (inspectedNodeId && [packet.from_node_id,packet.to_node_id].some(id => String(id) === inspectedNodeId)) {
const merged = new Map([...recentPackets,packet].map(p => [String(packetId(p)),p]));
recentPackets = [...merged.values()].sort((a,b) => packetTime(b)-packetTime(a)).slice(0,8);
renderRecent();
if (String(packet.from_node_id) === inspectedNodeId && Number(packet.portnum) === 67) renderTelemetry(packet);
}
}
});
})();
-138
View File
@@ -1,138 +0,0 @@
/* Home-only traffic table; shares packet polling with the map. */
(() => {
const byId = id => document.getElementById(id);
const packetHistory = new Map();
const expandedPackets = new Set();
const displayedPackets = new Set();
const packetArrivals = new Map();
let trafficLoaded = false;
let paused = false;
let trafficState = 'loading';
const findNode = id => nodeMap.get(Number(id)) || nodeMap.get(id);
const nodeName = (id, fallback) => {
const node = findNode(id);
return node?.long_name || node?.short_name || fallback || `Node ${id}`;
};
const packetTime = packet => Number(packet.import_time_us) || 0;
const packetId = packet => packet.storage_id ?? packet.id;
const portName = packet => window.PORT_LABEL_MAP[packet.portnum] || `Port ${packet.portnum ?? '?'}`;
const dateText = us => us ? new Date(Number(us) / 1000).toLocaleString() : 'Unknown time';
function renderTraffic() {
const list = byId('map-traffic-list');
const body = byId('map-traffic-body');
const scrollTop = list.scrollTop;
const focusedRow = document.activeElement?.closest('.mesh-traffic-row');
const focusedId = focusedRow?.dataset.packetId;
const focusedControl = document.activeElement?.dataset.trafficFocus;
body.replaceChildren();
const channel = byId('map-traffic-channel').value;
const packets = [...packetHistory.values()].sort((a,b) => packetTime(b)-packetTime(a))
.slice(0,30).filter(packet => !channel || packet.channel === channel);
if (!packets.length) {
const row = document.createElement('tr'); const cell = document.createElement('td');
cell.colSpan = 6; cell.className = 'mesh-empty';
cell.textContent = trafficState === 'error' ? 'Unable to load traffic. Use Refresh to try again.' :
channel ? 'No packets for this channel in the latest sample.' : 'No packets received yet.';
row.append(cell); body.append(row);
}
function nodeCell(id, label, isDestination = false) {
const cell = document.createElement('td');
if (Number(id) === 4294967295 || (isDestination && Number(id) === 1)) {
const muted = document.createElement('span'); muted.className = 'mesh-inspector-note';
muted.textContent = Number(id) === 4294967295 ? 'All' : 'Direct to MQTT'; cell.append(muted);
} else {
const link = document.createElement('a'); link.href = `/node/${encodeURIComponent(id)}`;
link.textContent = nodeName(id,label); cell.append(link);
}
return cell;
}
for (const packet of packets) {
const id = String(packetId(packet));
const row = document.createElement('tr'); row.className = 'mesh-traffic-row'; row.dataset.packetId = id;
const time = document.createElement('td'); time.className = 'mesh-traffic-time';
time.textContent = packet.import_time_us ? new Date(Number(packet.import_time_us)/1000).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit',second:'2-digit',hour12:false}) : '—';
time.title = dateText(packet.import_time_us);
const packetCell = document.createElement('td');
const toggle = document.createElement('button'); toggle.type = 'button'; toggle.className = 'mesh-traffic-toggle';
toggle.dataset.trafficFocus = 'toggle';
toggle.setAttribute('aria-label', `Toggle payload for packet ${id}`);
toggle.setAttribute('aria-expanded',String(expandedPackets.has(id)));
toggle.textContent = expandedPackets.has(id) ? '▼' : '▶';
const details = document.createElement('a'); details.href = `/packet/${encodeURIComponent(id)}`;
details.dataset.trafficFocus = 'details'; details.title = 'View packet details';
details.textContent = packet.packet_id == null ? 'Details' : String(packet.packet_id);
packetCell.append(toggle,details);
const channelCell = document.createElement('td'); channelCell.textContent = packet.channel || '—';
const port = document.createElement('td');
const tag = document.createElement('span'); tag.className = 'mesh-traffic-type'; tag.textContent = portName(packet);
tag.style.backgroundColor = window.PORT_COLOR_MAP[packet.portnum] || '#6c757d';
tag.title = packet.payload || '';
const number = document.createElement('span'); number.className = 'mesh-traffic-port-number'; number.textContent = `(${packet.portnum ?? '?'})`;
port.append(tag,number);
row.append(time,packetCell,nodeCell(packet.from_node_id,packet.long_name),nodeCell(packet.to_node_id,packet.to_long_name,true),channelCell,port);
const payloadRow = document.createElement('tr'); payloadRow.className = 'mesh-traffic-payload';
payloadRow.hidden = !expandedPackets.has(id);
const payloadCell = document.createElement('td'); payloadCell.colSpan = 6;
const payload = document.createElement('pre'); payload.textContent = packet.payload || '(No decoded payload)';
payloadCell.append(payload); payloadRow.append(payloadCell);
toggle.addEventListener('click', () => {
if (expandedPackets.has(id)) expandedPackets.delete(id); else expandedPackets.add(id);
payloadRow.hidden = !expandedPackets.has(id);
toggle.setAttribute('aria-expanded',String(!payloadRow.hidden)); toggle.textContent = payloadRow.hidden ? '▶' : '▼';
});
body.append(row,payloadRow);
if (!displayedPackets.has(id)) {
displayedPackets.add(id);
packetArrivals.set(id,Date.now());
}
if (packetArrivals.has(id)) markNewPacketArrival(row,packetArrivals.get(id));
}
list.scrollTop = scrollTop;
if (focusedId && focusedControl) {
const row = [...body.children].find(row => row.dataset.packetId === focusedId);
[...(row?.querySelectorAll('[data-traffic-focus]') || [])]
.find(el => el.dataset.trafficFocus === focusedControl)?.focus({preventScroll:true});
}
}
function renderTrafficStatus() {
const el = byId('map-traffic-status');
el.dataset.state = trafficState;
el.textContent = paused ? 'Feed paused' : trafficState === 'error' ? 'Traffic unavailable' :
trafficState === 'loading' ? 'Loading packets…' : mapInterval > 0 ? `Live · every ${mapInterval}s` : 'Snapshot · auto-refresh off';
}
document.addEventListener('mesh:traffic-status', event => {
trafficState = event.detail; renderTrafficStatus();
if (!paused && !packetHistory.size) renderTraffic();
});
document.addEventListener('mesh:packets', event => {
let added = false;
for (const packet of event.detail) {
if (!packetHistory.has(String(packetId(packet)))) added = true;
packetHistory.set(String(packetId(packet)),packet);
if (!trafficLoaded) displayedPackets.add(String(packetId(packet)));
if (packet.channel && ![...byId('map-traffic-channel').options].some(o => o.value === packet.channel)) {
byId('map-traffic-channel').add(new Option(packet.channel,packet.channel));
}
}
trafficLoaded = true;
if (packetHistory.size > 30) {
const sorted = [...packetHistory.values()].sort((a,b) => packetTime(b)-packetTime(a));
for (const packet of sorted.slice(30)) {
packetHistory.delete(String(packetId(packet))); expandedPackets.delete(String(packetId(packet)));
displayedPackets.delete(String(packetId(packet))); packetArrivals.delete(String(packetId(packet)));
}
}
if (!paused && added) renderTraffic();
});
byId('map-traffic-channel').addEventListener('change', () => renderTraffic());
byId('map-traffic-pause').addEventListener('click', () => {
paused = !paused;
byId('map-traffic-pause').textContent = paused ? 'Resume feed' : 'Pause feed';
byId('map-traffic-pause').setAttribute('aria-pressed',String(paused));
if (!paused) renderTraffic();
renderTrafficStatus();
});
byId('map-traffic-refresh').addEventListener('click', () => fetchLatestPacket());
})();
-13
View File
@@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" role="img" aria-labelledby="title">
<title id="title">Meshview: a mesh network through a magnifying glass</title>
<rect width="64" height="64" rx="15" fill="#eaf5ee"/>
<path d="M43 43 55 55" fill="none" stroke="#187346" stroke-width="7" stroke-linecap="round"/>
<circle cx="28" cy="28" r="19" fill="none" stroke="#187346" stroke-width="4"/>
<path d="m17 29 12-11 9 14-15 6-6-9 21 3" fill="none" stroke="#369361" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<g fill="#187346" stroke="#eaf5ee" stroke-width="1.5">
<circle cx="17" cy="29" r="3.8"/>
<circle cx="29" cy="18" r="3.8"/>
<circle cx="38" cy="32" r="3.8"/>
<circle cx="23" cy="38" r="3.8"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 796 B

-17
View File
@@ -1,17 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="396" height="88" viewBox="0 0 396 88" role="img" aria-labelledby="title desc">
<title id="title">Meshview</title>
<desc id="desc">Connected mesh nodes inside a green magnifying glass, alongside the Meshview wordmark.</desc>
<g transform="translate(4 8) scale(1.125)">
<rect width="64" height="64" rx="15" fill="#eaf5ee"/>
<path d="M43 43 55 55" fill="none" stroke="#187346" stroke-width="7" stroke-linecap="round"/>
<circle cx="28" cy="28" r="19" fill="none" stroke="#187346" stroke-width="4"/>
<path d="m17 29 12-11 9 14-15 6-6-9 21 3" fill="none" stroke="#369361" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<g fill="#187346" stroke="#eaf5ee" stroke-width="1.5">
<circle cx="17" cy="29" r="3.8"/>
<circle cx="29" cy="18" r="3.8"/>
<circle cx="38" cy="32" r="3.8"/>
<circle cx="23" cy="38" r="3.8"/>
</g>
</g>
<text x="94" y="61" fill="#143b29" font-family="Inter, system-ui, -apple-system, 'Segoe UI', sans-serif" font-size="51" font-weight="700" letter-spacing="-1.8">Meshview</text>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

-12
View File
@@ -1,12 +0,0 @@
/* A short, shared arrival cue for the two live packet tables. */
window.markNewPacketArrival = function (row, startedAt = Date.now()) {
const elapsed = Math.max(0, Date.now() - startedAt);
const remaining = 1000 - elapsed;
if (remaining <= 0) return;
row.classList.add('packet-arrival-glow');
row.style.setProperty('--packet-glow-delay', `${-elapsed}ms`);
setTimeout(() => {
row.classList.remove('packet-arrival-glow');
row.style.removeProperty('--packet-glow-delay');
}, remaining);
};
-95
View File
@@ -1,95 +0,0 @@
/* Apply before paint; one preference shared by every Meshview page. */
(() => {
const root = document.documentElement;
const key = 'meshview-theme';
const system = matchMedia('(prefers-color-scheme: dark)');
let preference = null;
try { preference = localStorage.getItem(key); } catch {}
if (!['light','dark'].includes(preference)) preference = null;
root.dataset.bsTheme = preference || (system.matches ? 'dark' : 'light');
const colors = () => {
const style = getComputedStyle(root);
return {
surface:style.getPropertyValue('--mesh-surface').trim(),
text:style.getPropertyValue('--mesh-text').trim(),
muted:style.getPropertyValue('--mesh-muted').trim(),
border:style.getPropertyValue('--mesh-border').trim()
};
};
// Neutral chart colors follow the theme; packet/route/series colors stay intact.
function chartOption(option) {
const palette = colors();
const text = new Set(['#333','#334155','#243247','#26364a','#e7eef7','#e2ece5']);
const muted = new Set(['#ccc','#64748b','#888','#9faea6','#8190a5']);
const border = new Set(['#aaa','#c3cfdf','#34483c','#dce7df']);
function visit(value, key) {
if (Array.isArray(value)) return value.map(item => visit(item,key));
if (value && Object.getPrototypeOf(value) === Object.prototype) {
return Object.fromEntries(Object.entries(value).map(([k,v]) => [k,visit(v,k)]));
}
if (typeof value !== 'string') return value;
const hex = value.toLowerCase();
if (key === 'backgroundColor' && ['#fff','#ffffff','#18231e'].includes(hex)) return palette.surface;
if (['borderColor','textBorderColor'].includes(key) && ['#fff','#ffffff','#000','#18231e'].includes(hex)) return palette.surface;
if (key === 'color' && text.has(hex)) return palette.text;
if (key === 'color' && muted.has(hex)) return palette.muted;
if (key === 'color' && border.has(hex)) return palette.border;
return value;
}
const themed = visit(option,'');
themed.textStyle = {...themed.textStyle,color:palette.text};
const tooltip = value => ({...value,backgroundColor:palette.surface,borderColor:palette.border,textStyle:{...value?.textStyle,color:palette.text}});
if (Array.isArray(themed.tooltip)) themed.tooltip = themed.tooltip.map(tooltip);
else themed.tooltip = tooltip(themed.tooltip);
return themed;
}
const wrapped = new WeakSet();
window.initMeshChart = (...args) => {
const chart = window.echarts.init(...args);
if (!wrapped.has(chart)) {
const setOption = chart.setOption.bind(chart);
chart.setOption = (option,...rest) => setOption(chartOption(option),...rest);
wrapped.add(chart);
}
return chart;
};
function updateButton() {
document.querySelectorAll('[data-theme-toggle]').forEach(button => {
const dark = root.dataset.bsTheme === 'dark';
button.textContent = dark ? '☀' : '☾';
button.setAttribute('aria-label',dark ? 'Switch to day mode' : 'Switch to night mode');
button.setAttribute('aria-pressed',String(dark));
button.title = dark ? 'Day mode' : 'Night mode';
});
}
function apply(theme) {
root.dataset.bsTheme = theme;
updateButton();
if (window.echarts) {
document.querySelectorAll('[_echarts_instance_]').forEach(el => {
const chart = window.echarts.getInstanceByDom(el);
if (chart) chart.setOption(chartOption(chart.getOption()));
});
}
document.dispatchEvent(new CustomEvent('meshview:themechange',{detail:theme}));
}
document.addEventListener('DOMContentLoaded',() => {
updateButton();
document.querySelectorAll('[data-theme-toggle]').forEach(button => {
button.addEventListener('click',() => {
preference = root.dataset.bsTheme === 'dark' ? 'light' : 'dark';
try { localStorage.setItem(key,preference); } catch {}
apply(preference);
});
});
});
system.addEventListener('change',event => {
if (!preference) apply(event.matches ? 'dark' : 'light');
});
window.addEventListener('storage',event => {
if (event.key !== key && event.key !== null) return;
preference = ['light','dark'].includes(event.newValue) ? event.newValue : null;
apply(preference || (system.matches ? 'dark' : 'light'));
});
})();
+20 -144
View File
@@ -1,23 +1,16 @@
<!doctype html>
<html lang="en" data-bs-theme="{% block theme %}dark{% endblock %}">
<html lang="en" data-bs-theme="dark">
<head>
<title>Meshview</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" sizes="16x16 32x32 48x48 64x64 256x256" href="/static/favicon.ico">
<link rel="icon" type="image/svg+xml" sizes="any" href="/static/meshview-icon.svg">
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<script src="/static/theme.js"></script>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
<script src="/static/html-escape.js"></script>
<script src="/static/packet-arrival.js"></script>
{% block head %}{% endblock %}
@@ -50,132 +43,22 @@
</style>
{% block css %}{% endblock %}
<style>
/* Shared dashboard chrome and map explorer. */
:root,[data-bs-theme="light"],[data-bs-theme="dark"] {
--bs-primary:var(--mesh-brand);
--bs-primary-rgb:var(--mesh-primary-rgb);
--bs-link-color:var(--mesh-primary);
--bs-link-color-rgb:var(--mesh-primary-rgb);
--bs-link-hover-color:var(--mesh-primary-dark);
--bs-link-hover-color-rgb:15,81,50;
--bs-focus-ring-color:rgba(var(--mesh-primary-rgb),.25);
}
[data-bs-theme="dark"] { --bs-link-color:#75c99c; --bs-link-color-rgb:117,201,156; --bs-link-hover-color:#a3dfbc; --bs-link-hover-color-rgb:163,223,188; }
.btn-primary {
--bs-btn-bg:var(--mesh-brand); --bs-btn-border-color:var(--mesh-brand);
--bs-btn-hover-bg:var(--mesh-brand-deep); --bs-btn-hover-border-color:var(--mesh-brand-deep);
--bs-btn-active-bg:var(--mesh-brand-deep); --bs-btn-active-border-color:var(--mesh-brand-deep);
--bs-btn-disabled-bg:var(--mesh-brand); --bs-btn-disabled-border-color:var(--mesh-brand);
--bs-btn-focus-shadow-rgb:var(--mesh-primary-rgb);
}
.btn-outline-primary {
--bs-btn-color:var(--mesh-primary); --bs-btn-border-color:var(--mesh-brand);
--bs-btn-hover-bg:var(--mesh-brand); --bs-btn-hover-border-color:var(--mesh-brand);
--bs-btn-active-bg:var(--mesh-brand-deep); --bs-btn-active-border-color:var(--mesh-brand-deep);
--bs-btn-focus-shadow-rgb:var(--mesh-primary-rgb);
}
.form-control:focus,.form-select:focus { border-color:#91bda1; box-shadow:0 0 0 .25rem rgba(var(--mesh-primary-rgb),.2); }
input[type="checkbox"],input[type="radio"] { accent-color:var(--mesh-primary); }
.leaflet-popup-content a,.leaflet-control-attribution a { color:var(--mesh-primary); }
.form-check-input:checked { background-color:var(--mesh-primary); border-color:var(--mesh-primary); }
.form-check-input:focus { border-color:#91bda1; box-shadow:0 0 0 .25rem rgba(var(--mesh-primary-rgb),.2); }
.page-link { --bs-pagination-color:var(--mesh-primary); --bs-pagination-hover-color:var(--mesh-primary-dark); --bs-pagination-active-bg:var(--mesh-primary); --bs-pagination-active-border-color:var(--mesh-primary); }
[data-bs-theme="light"] body { background:var(--mesh-page); color:var(--mesh-text); font-family:Inter,system-ui,-apple-system,"Segoe UI",sans-serif; }
/* Tint whole cells: an edge-only shadow is too subtle on wide packet tables. */
.packet-arrival-glow > td {
animation:packet-arrival-beat 1s ease-in-out 1;
animation-delay:var(--packet-glow-delay,0ms);
box-shadow:inset 0 0 14px rgba(24,115,70,.12);
}
.packet-arrival-glow > td:first-child {
box-shadow:inset 4px 0 0 var(--mesh-primary),inset 0 0 14px rgba(24,115,70,.12);
}
@keyframes packet-arrival-beat {
0%,100% { background-color:transparent; }
45% { background-color:var(--mesh-pulse-peak); }
75% { background-color:var(--mesh-pulse-mid); }
}
@media(prefers-reduced-motion:reduce) {
.packet-arrival-glow > td { animation:none; background:var(--mesh-soft); }
}
.mesh-header { background:var(--mesh-brand); color:white; box-shadow:0 2px 8px #174b2d18; }
.mesh-header-inner { max-width:1600px; margin:auto; padding:0 28px; min-height:56px; display:flex; align-items:center; gap:32px; }
.mesh-brand { display:flex; align-items:center; gap:10px; font-size:19px; font-weight:700; color:white; text-decoration:none; flex-shrink:0; }
.mesh-brand:hover { color:white; }
.mesh-brand-icon { width:32px; height:32px; display:block; flex-shrink:0; }
#site-menu { display:flex; align-items:center; flex-wrap:wrap; gap:4px; }
#site-menu a { color:#e6f4ea; text-decoration:none; padding:10px 12px; border-radius:6px; font-size:14px; text-transform:capitalize; }
#site-menu a:hover, #site-menu a.active { color:white; background:#ffffff26; }
.mesh-menu-toggle { display:none; color:white; background:none; border:1px solid #ffffff70; border-radius:5px; font-size:22px; }
.mesh-content { max-width:1600px; margin:0 auto; padding:28px; }
.mesh-announcement { text-align:center; padding:10px 20px; background:var(--mesh-soft); color:var(--mesh-text); font-size:14px; }
.mesh-announcement:empty { display:none; }
.mesh-footer { display:flex; justify-content:space-between; gap:16px; padding:20px 28px; border-top:1px solid var(--mesh-border); color:var(--mesh-muted); font-size:12px; }
.mesh-page-heading { display:flex; justify-content:space-between; align-items:center; gap:16px; margin-bottom:24px; }
.mesh-eyebrow { font-size:10px; letter-spacing:1.6px; font-weight:700; color:var(--mesh-primary); }
.mesh-page-heading h1 { font-size:28px; font-weight:650; margin:5px 0 7px; }
.mesh-page-heading p { color:var(--mesh-muted); font-size:14px; margin:0; }
.mesh-secondary-button,.mesh-fit-button { border:1px solid var(--mesh-border); background:var(--mesh-surface); color:var(--mesh-text); padding:9px 14px; border-radius:6px; text-decoration:none; font-size:13px; }
.mesh-secondary-button:hover,.mesh-fit-button:hover { background:var(--mesh-soft); }
.mesh-metrics { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:18px; margin-bottom:24px; }
.mesh-metric { padding:20px 24px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; box-shadow:0 2px 4px var(--mesh-text)04; display:flex; flex-direction:column; gap:5px; }
.mesh-metric>span { font-size:13px; font-weight:500; color:var(--mesh-muted); }
.mesh-metric strong { font-size:30px; font-weight:650; color:var(--mesh-primary); font-variant-numeric:tabular-nums; }
.mesh-metric:nth-child(2) strong { color:#198754; }
.mesh-metric:nth-child(3) strong { color:#397955; }
.mesh-metric small { font-size:11px; color:var(--mesh-muted); }
.mesh-explorer { display:grid; grid-template-columns:290px minmax(0,1fr); gap:20px; }
.mesh-node-panel,.mesh-map-panel { background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; overflow:hidden; min-width:0; }
.mesh-panel-title { display:flex; justify-content:space-between; align-items:center; padding:16px 18px; border-bottom:1px solid var(--mesh-border); gap:8px; min-height:64px; }
.mesh-panel-title h2 { font-size:15px; font-weight:650; margin:0; }
.mesh-count { color:var(--mesh-primary); background:var(--mesh-soft); padding:3px 8px; border-radius:5px; font-size:12px; }
.mesh-search-label { margin:16px 16px 5px; font-size:11px; color:var(--mesh-muted); }
.mesh-search { display:block; width:calc(100% - 32px); margin:0 16px 12px; border:1px solid var(--mesh-border); border-radius:6px; padding:10px; font-size:13px; }
.mesh-search:focus-visible { outline:2px solid var(--mesh-primary); outline-offset:2px; }
.mesh-node-list { max-height:535px; overflow:auto; }
.mesh-node-row { display:flex; align-items:center; gap:10px; width:100%; padding:14px 16px; border:0; border-top:1px solid var(--mesh-stripe); background:var(--mesh-surface); text-align:left; color:var(--mesh-text); }
.mesh-node-row:hover,.mesh-node-row:focus-visible { background:var(--mesh-soft); }
.mesh-node-dot { width:9px; height:9px; border-radius:50%; background:#198754; flex-shrink:0; }
.mesh-node-dot.offline { background:#c0c9d5; }
.mesh-node-copy { min-width:0; flex:1; }
.mesh-node-copy strong { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; font-weight:600; }
.mesh-node-copy small { display:block; color:var(--mesh-muted); font-size:11px; margin-top:4px; }
.mesh-node-role { font-size:10px; color:var(--mesh-muted); }
.mesh-empty { color:var(--mesh-muted); padding:20px 16px; font-size:13px; }
.mesh-map-panel #map-wrapper { height:520px; }
.mesh-map-panel #filter-container { display:flex; align-items:center; justify-content:flex-start; flex-wrap:wrap; gap:5px; margin:0; padding:12px; font-size:12px; border-top:1px solid var(--mesh-border); }
.mesh-map-panel .filter-checkbox { margin:0 2px 0 10px; accent-color:var(--mesh-primary); }
.mesh-map-panel #share-button,.mesh-map-panel #reset-filters-button { background:var(--mesh-soft); color:var(--mesh-primary); margin:5px; padding:8px 12px; font-size:12px; }
.mesh-map-panel #share-button.is-copied { background:var(--mesh-brand-deep); color:white; }
.mesh-map-panel #reset-filters-button { color:var(--mesh-muted); background:var(--mesh-stripe); }
.mesh-map-panel #map-legend { bottom:80px!important; left:12px; right:auto!important; box-shadow:0 2px 8px #0001; font-size:11px; }
.mesh-map-panel #unmapped-packets { bottom:25px; right:10px; width:190px; }
.mesh-map-panel .leaflet-control-layers { font-size:11px; border:1px solid var(--mesh-border); box-shadow:0 2px 8px #0001; }
@media(min-width:1000px) { .mesh-header-inner { gap:20px; } #site-menu a { padding:9px; } }
@media(max-width:1000px) { .mesh-header-inner { flex-wrap:wrap; gap:0; padding:8px 20px; justify-content:space-between; } .mesh-menu-toggle { display:block; } #site-menu { display:none; width:100%; padding-top:14px; } #site-menu.is-open { display:flex; } .mesh-explorer { grid-template-columns:240px minmax(0,1fr); } }
@media(max-width:700px) { .mesh-content { padding:20px 14px; } .mesh-page-heading { align-items:flex-start; } .mesh-page-heading h1 { font-size:24px; } .mesh-secondary-button { white-space:nowrap; font-size:11px; padding:8px; } .mesh-metrics { grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; } .mesh-metric { padding:14px; } .mesh-metric strong { font-size:26px; } .mesh-explorer { display:flex; flex-direction:column-reverse; gap:16px; } .mesh-map-panel #map-wrapper { height:440px; } .mesh-node-list { max-height:300px; } .mesh-map-panel #unmapped-packets { width:155px; font-size:10px; } .mesh-footer { flex-direction:column; } }
</style>
{% include "theme-styles.html" %}
</head>
<body class="{% block body_class %}{% endblock %}">
<header class="mesh-header">
<div class="mesh-header-inner">
<a class="mesh-brand" href="/"><img class="mesh-brand-icon" src="/static/meshview-icon.svg" width="32" height="32" alt=""> <span id="site-header">Meshview</span></a>
<button class="mesh-menu-toggle" type="button" aria-label="Toggle navigation" aria-expanded="false" aria-controls="site-menu">☰</button>
<nav id="site-menu" aria-label="Main navigation"></nav>
<button class="mesh-theme-toggle" type="button" data-theme-toggle aria-label="Switch to night mode" aria-pressed="false" title="Night mode">☾</button>
</div>
</header>
<div id="site-message" class="mesh-announcement"></div>
<main class="mesh-content">
<body>
<br>
<div style="text-align:center" id="site-header"></div>
<div style="text-align:center" id="site-message"></div>
<div style="text-align:center" id="site-menu"></div>
<br>
{% block body %}{% endblock %}
</main>
<footer class="mesh-footer">
<span id="footer" data-translate="footer"></span>
<span id="site-version">Meshview</span>
</footer>
<br>
<div style="text-align:center" id="footer" data-translate="footer"></div>
<div style="text-align:center"><small id="site-version">ver. unknown</small></div>
<br>
<script>
// --- Shared Promises ---
@@ -277,29 +160,27 @@ async function initializePage() {
document.title = "Meshview - " + (site.title || "");
// Header & Message
document.getElementById("site-header").textContent = site.title || "Meshview";
document.getElementById("site-header").innerHTML =
`<strong>${site.title || ""} ${site.domain ? "(" + site.domain + ")" : ""}</strong>`;
document.getElementById("site-message").textContent = site.message || "";
// Menu
const menu = document.getElementById("site-menu");
if (menu) {
const items = ['<a href="/"' + (["/", "/index", "/index.html"].includes(location.pathname) ? ' class="active" aria-current="page"' : "") + '>Home</a>'];
const items = [];
const keys = ["nodes", "chat", "everything", "graphs", "net", "map", "stats", "top"];
const urls = ["/nodelist", "/chat", "/firehose", "/nodegraph", "/net", "/map", "/stats", "/top"];
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (site[key] === "true" || site[key] === true) {
items.push(`<a href="${urls[i]}"${(location.pathname === urls[i] || (key === "map" && location.pathname === "/map.html")) ? ' class="active" aria-current="page"' : ""}>${escapeHtml(dict[key] || (key === "everything" ? "Live Traffic" : key))}</a>`);
if (site[key] === "true") {
items.push(`<a href="${urls[i]}">${dict[key] || key}</a>`);
}
}
if (site.api !== "false" && site.api !== false) {
items.push('<a href="/api.html">API</a>');
}
items.push('<a href="https://meshview.world" target="_blank" rel="noopener noreferrer">MeshviewWorld</a>');
menu.innerHTML = items.join("");
menu.innerHTML = items.join("&nbsp;-&nbsp;");
}
// Version
@@ -317,11 +198,6 @@ async function initializePage() {
}
}
document.querySelector(".mesh-menu-toggle").addEventListener("click", function () {
const expanded = this.getAttribute("aria-expanded") !== "true";
this.setAttribute("aria-expanded", String(expanded));
document.getElementById("site-menu").classList.toggle("is-open", expanded);
});
document.addEventListener("DOMContentLoaded", initializePage);
</script>
+292 -75
View File
@@ -1,87 +1,304 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block css %}
<style>
body:has(#chat-container) { height:100dvh; display:flex; flex-direction:column; overflow:hidden; }
body:has(#chat-container) .mesh-header { flex-shrink:0; }
body:has(#chat-container) .mesh-content { display:flex; flex:1; min-height:0; width:100%; max-width:none; padding:0; }
body:has(#chat-container) .mesh-footer { display:none; }
body:has(#chat-container) .mesh-announcement { flex-shrink:0; }
#chat-container { display:flex; flex-direction:column; flex:1; min-width:0; min-height:0; background:var(--mesh-stripe); }
.chat-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:12px; padding:12px 24px; border-bottom:1px solid var(--mesh-border); background:var(--mesh-surface); flex-shrink:0; }
.chat-heading { display:flex; align-items:center; gap:8px; margin:0 6px 0 0; font-size:15px; font-weight:650; }
.chat-heading span:first-child { color:var(--mesh-primary); }
.chat-channel-control { display:flex; align-items:center; gap:6px; color:var(--mesh-muted); }
.chat-filter { width:170px; font-size:12px; border-color:var(--mesh-border); }
.chat-search { width:210px; font-size:12px; border-color:var(--mesh-border); }
.chat-actions { display:flex; align-items:center; gap:8px; margin-left:auto; }
.chat-status { border-radius:20px; padding:4px 9px; background:#e8f5ee; color:#187346; font-size:11px; white-space:nowrap; }
.chat-status[data-state="error"] { background:#fff0ed; color:#b23d2f; }
.chat-status[data-state="paused"],.chat-status[data-state="loading"] { background:#eef2f7; color:var(--mesh-muted); }
.chat-control { font-size:12px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:5px; padding:5px 9px; color:var(--mesh-text); }
.chat-control:hover { background:var(--mesh-soft); }
.chat-messages { flex:1; min-height:0; overflow-y:auto; overflow-anchor:none; padding:12px 0; font-family:ui-monospace,"SFMono-Regular",Consolas,monospace; font-size:13px; line-height:1.6; scrollbar-gutter:stable; }
.chat-date-sep { display:flex; align-items:center; gap:14px; margin:12px 24px; color:var(--mesh-muted); font:600 10px system-ui,sans-serif; letter-spacing:.7px; text-transform:uppercase; }
.chat-date-sep::before,.chat-date-sep::after { content:""; flex:1; height:1px; background:var(--mesh-border); }
.chat-line { display:grid; grid-template-columns:64px 165px minmax(0,1fr) auto; gap:12px; align-items:baseline; padding:5px 24px; --chat-row-bg:var(--mesh-surface); background:var(--chat-row-bg); border-bottom:1px solid var(--mesh-border); }
.chat-line:nth-of-type(even) { --chat-row-bg:var(--mesh-chat-stripe); }
.chat-line:hover,.chat-line:focus-within { background:var(--mesh-hover); }
.chat-time { color:var(--mesh-muted); font-size:11px; text-align:right; white-space:nowrap; }
.chat-nick { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:600; font-size:12px; text-decoration:none; text-align:right; }
.chat-nick:hover { text-decoration:underline; }
.chat-message { min-width:0; color:var(--mesh-text); overflow-wrap:anywhere; white-space:pre-wrap; }
.chat-meta { display:flex; align-items:center; gap:10px; font:11px system-ui,sans-serif; }
.chat-channel { background:#edf1f7; color:var(--mesh-muted); border-radius:4px; padding:2px 6px; max-width:130px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.chat-details { display:inline-flex; align-items:center; padding:4px 8px; border:1px solid #9dceb0; border-radius:5px; background:#e8f5ee; color:#187346; font-weight:600; text-decoration:none; white-space:nowrap; }
.chat-details:hover { color:#0f5132; background:#d1e7dd; border-color:#69aa85; }
.chat-details:focus-visible { outline:2px solid #198754; outline-offset:2px; }
.replying-to { display:block; border-left:2px solid var(--mesh-border); margin:4px 0; padding:2px 9px; color:var(--mesh-muted); font-size:11px; white-space:normal; }
.chat-empty { text-align:center; color:var(--mesh-muted); padding:48px 20px; font:13px system-ui,sans-serif; }
.chat-bottom { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:8px 24px; border-top:1px solid var(--mesh-border); color:var(--mesh-muted); background:var(--mesh-surface); font-size:11px; flex-shrink:0; }
.chat-bottom p { margin:0; }
.chat-line.flash { animation:chat-flash 2s ease-out; }
@keyframes chat-flash { from { background:var(--mesh-hover); } to { background:var(--chat-row-bg); } }
@media(prefers-reduced-motion:reduce) { .chat-line.flash { animation:none; } }
@media(max-width:700px) {
.chat-toolbar { padding:10px 14px; gap:8px; }
.chat-heading { width:100%; }
.chat-filter { width:140px; }
.chat-search { flex:1; width:120px; min-width:0; }
.chat-actions { width:100%; margin-left:0; }
#chat-count { margin-right:auto; }
.chat-line { grid-template-columns:50px minmax(0,1fr) auto; gap:2px 8px; padding:7px 14px; }
.chat-time { grid-column:1; grid-row:1; }
.chat-nick { grid-column:2; grid-row:1; text-align:left; }
.chat-meta { grid-column:3; grid-row:1; gap:5px; }
.chat-channel { max-width:85px; }
.chat-message { grid-column:2 / 4; grid-row:2; }
.chat-date-sep { margin:12px 14px; }
.chat-bottom { padding:8px 14px; }
.timestamp {
min-width: 10em;
color: #ccc;
}
.chat-packet:nth-of-type(odd) { background-color: #3a3a3a; }
.chat-packet {
border-bottom: 1px solid #555;
padding: 3px 6px;
border-radius: 6px;
margin: 0;
}
/* Same column spacing as before */
.chat-packet > [class^="col-"] {
padding-left: 10px !important;
padding-right: 10px !important;
padding-top: 1px !important;
padding-bottom: 1px !important;
}
.chat-packet:nth-of-type(even) { background-color: #333333; }
.channel {
font-style: italic;
color: #bbb;
}
.channel a {
font-style: normal;
color: #999;
}
@keyframes flash {
0% { background-color: #ffe066; }
100% { background-color: inherit; }
}
.chat-packet.flash { animation: flash 3.5s ease-out; }
.replying-to {
font-size: 0.8em;
color: #aaa;
margin-top: 2px;
padding-left: 10px;
}
.replying-to .reply-preview { color: #aaa; }
.chat-controls {
gap: 12px;
margin-bottom: 10px;
}
.chat-filter {
min-width: 220px;
}
</style>
{% endblock %}
{% block body %}
<section id="chat-container" aria-label="Mesh chat">
<div class="chat-toolbar">
<h1 class="chat-heading"><span aria-hidden="true">#</span> <span data-chat-translate="chat_title">Mesh chat</span></h1>
<div class="chat-channel-control">
<label for="channel-filter" class="visually-hidden" data-chat-translate="channel">Channel</label>
<span aria-hidden="true">#</span>
<select id="channel-filter" class="form-select form-select-sm chat-filter"><option value="" data-chat-translate="all_channels">All channels</option></select>
</div>
<label for="chat-search" class="visually-hidden">Search messages or nodes</label>
<input id="chat-search" class="form-control form-control-sm chat-search" type="search" placeholder="Search messages or nodes…" autocomplete="off">
<div class="chat-actions">
<span id="chat-count" class="text-secondary small">0 messages</span>
<span id="chat-status" class="chat-status" data-state="loading" role="status">Connecting…</span>
<button id="chat-pause" class="chat-control" type="button" aria-pressed="false">Pause</button>
<button id="chat-latest" class="chat-control" type="button">↓ Latest</button>
<div id="chat-container" class="mt-3">
<!-- ⭐ CHAT TITLE WITH ICON, aligned to container ⭐ -->
<div class="container px-2">
<div class="d-flex align-items-center justify-content-between chat-controls">
<h2 style="color:white; margin:0;">
<span class="icon">💬</span>
<span data-translate="chat_title"></span>
</h2>
<div class="d-flex align-items-center gap-2">
<label for="channel-filter" class="mb-0" data-translate="channel">Channel</label>
<select id="channel-filter" class="form-select form-select-sm chat-filter">
<option value="" data-translate="all_channels">All Channels</option>
</select>
</div>
</div>
</div>
<div id="chat-log" class="chat-messages" role="region" aria-label="Messages, oldest to newest" tabindex="0"><p class="chat-empty">Loading messages…</p></div>
<div class="chat-bottom"><p>Received text messages · updates every 5 seconds</p><span id="chat-updated" role="status"></span></div>
</section>
<script src="/static/chat-dashboard.js"></script>
<div class="container" id="chat-log"></div>
</div>
<script>
document.addEventListener("DOMContentLoaded", async () => {
const chatContainer = document.querySelector("#chat-log");
if (!chatContainer) return console.error("#chat-log not found");
let lastTime = null;
let selectedChannel = "";
const renderedPacketIds = new Set();
const packetMap = new Map();
let chatLang = {};
/* ==========================================================
TRANSLATIONS FOR CHAT PAGE
========================================================== */
function applyTranslations(dict, root=document) {
root.querySelectorAll("[data-translate]").forEach(el => {
const key = el.dataset.translate;
const val = dict[key];
if (!val) return;
if (el.placeholder) el.placeholder = val;
else el.textContent = val;
});
}
async function loadChatLang() {
try {
const cfg = await window._siteConfigPromise;
const langCode = cfg?.site?.language || "en";
const res = await fetch(`/api/lang?lang=${langCode}&section=chat`);
chatLang = await res.json();
// Apply to existing DOM
applyTranslations(chatLang);
} catch (err) {
console.error("Chat translation load failed:", err);
}
}
async function loadChannels() {
try {
const res = await fetch("/api/channels");
if (!res.ok) return;
const data = await res.json();
const select = document.getElementById("channel-filter");
const channels = data.channels || [];
for (const channel of channels) {
const option = document.createElement("option");
option.value = channel;
option.textContent = channel;
select.appendChild(option);
}
} catch (err) {
console.error("Failed loading channels:", err);
}
}
/* ==========================================================
SAFE HTML
========================================================== */
function escapeHtml(text) {
const div = document.createElement("div");
div.textContent = text ?? "";
return div.innerHTML;
}
/* ==========================================================
RENDERING PACKETS
========================================================== */
function renderPacket(packet, highlight = false) {
if (renderedPacketIds.has(packet.id)) return;
renderedPacketIds.add(packet.id);
packetMap.set(packet.id, packet);
let date;
if (packet.import_time_us && packet.import_time_us > 0) {
date = new Date(packet.import_time_us / 1000);
} else if (packet.import_time) {
date = new Date(packet.import_time);
} else {
date = new Date();
}
const formattedTime = date.toLocaleTimeString([], {
hour:"numeric",
minute:"2-digit",
second:"2-digit",
hour12:true
});
const formattedDate =
`${(date.getMonth()+1).toString().padStart(2,"0")}/` +
`${date.getDate().toString().padStart(2,"0")}/` +
`${date.getFullYear()}`;
const formattedTimestamp = `${formattedTime} - ${formattedDate}`;
let replyHtml = "";
if (packet.reply_id) {
const parent = packetMap.get(packet.reply_id);
const replyPrefix = `<i data-translate="replying_to"></i>`;
if (parent) {
replyHtml = `
<div class="replying-to">
${replyPrefix}
<strong>${escapeHtml((parent.long_name || "").trim() || `Node ${parent.from_node_id}`)}</strong>:
${escapeHtml(parent.payload || "")}
</div>`;
} else {
replyHtml = `
<div class="replying-to">
${replyPrefix}
<a href="/packet/${packet.reply_id}">${packet.reply_id}</a>
</div>`;
}
}
const div = document.createElement("div");
div.className = "row chat-packet" + (highlight ? " flash" : "");
div.dataset.packetId = packet.id;
div.innerHTML = `
<span class="col-2 timestamp" title="${packet.import_time_us}">
${formattedTimestamp}
</span>
<span class="col-2 channel">
<a href="/packet/${packet.id}" title="${chatLang.view_packet_details || 'View details'}">🔎</a>
${escapeHtml(packet.channel || "")}
</span>
<span class="col-3 nodename">
<a href="/node/${packet.from_node_id}">
${escapeHtml((packet.long_name || "").trim() || `Node ${packet.from_node_id}`)}
</a>
</span>
<span class="col-5 message">
${escapeHtml(packet.payload)}${replyHtml}
</span>
`;
chatContainer.prepend(div);
// Translate newly added DOM
applyTranslations(chatLang, div);
if (highlight) setTimeout(() => div.classList.remove("flash"), 2500);
}
function matchesSelectedChannel(packet) {
if (!selectedChannel) return true;
return (packet.channel || "").toLowerCase() === selectedChannel.toLowerCase();
}
function resetChat() {
lastTime = null;
renderedPacketIds.clear();
packetMap.clear();
chatContainer.innerHTML = "";
}
function renderPacketsEnsureDescending(packets, highlight=false) {
if (!Array.isArray(packets) || packets.length===0) return;
const sortedDesc = packets.slice().sort((a,b)=>{
const aTime = a.import_time_us || (new Date(a.import_time).getTime() * 1000);
const bTime = b.import_time_us || (new Date(b.import_time).getTime() * 1000);
return bTime - aTime;
});
for (let i=sortedDesc.length-1; i>=0; i--) {
if (!matchesSelectedChannel(sortedDesc[i])) continue;
renderPacket(sortedDesc[i], highlight);
}
}
/* ==========================================================
FETCHING PACKETS
========================================================== */
async function fetchInitial() {
try {
const resp = await fetch("/api/packets?portnum=1&limit=100");
const data = await resp.json();
if (data?.packets?.length) renderPacketsEnsureDescending(data.packets);
lastTime = data?.latest_import_time || lastTime;
} catch(err){
console.error("Initial fetch error:", err);
}
}
async function fetchUpdates() {
try {
const url = new URL("/api/packets?portnum=1", window.location.origin);
url.searchParams.set("limit","100");
if (lastTime) url.searchParams.set("since", lastTime);
const resp = await fetch(url);
const data = await resp.json();
if (data?.packets?.length) renderPacketsEnsureDescending(data.packets, true);
lastTime = data?.latest_import_time || lastTime;
} catch(err){
console.error("Fetch updates error:", err);
}
}
/* ==========================================================
INIT
========================================================== */
await loadChatLang(); // load translations FIRST
await loadChannels();
document.getElementById("channel-filter").addEventListener("change", async (e) => {
selectedChannel = e.target.value;
resetChat();
await fetchInitial();
});
await fetchInitial(); // then fetch initial packets
setInterval(fetchUpdates, 5000);
});
</script>
{% endblock %}
-42
View File
@@ -1,42 +0,0 @@
{# Shared presentation for the diagnostic pages; no backend changes. #}
<style>
.mesh-data-page .mesh-content > .container { max-width:none; padding:0; }
.mesh-data-page .data-heading { display:flex; align-items:center; justify-content:space-between; gap:16px; margin-bottom:24px; }
.mesh-data-page .data-heading h1 { font-size:28px; font-weight:650; margin:5px 0 7px; overflow-wrap:anywhere; }
.mesh-data-page .data-heading p { margin:0; color:var(--mesh-muted); font-size:14px; }
.mesh-data-page .data-heading a { white-space:nowrap; }
.mesh-data-page .data-toolbar { display:flex; align-items:center; flex-wrap:wrap; gap:10px; background:var(--mesh-surface); border:1px solid var(--mesh-border); padding:16px; border-radius:9px; margin:0 0 18px; }
.mesh-data-page select,.mesh-data-page input[type="text"],.mesh-data-page input[type="search"] { min-width:0; max-width:100%; padding:8px 10px; border:1px solid var(--mesh-border); border-radius:5px; background:var(--mesh-surface); color:var(--mesh-text); font-size:13px; }
.mesh-data-page .mesh-content button { border:1px solid var(--mesh-border); border-radius:5px; background:var(--mesh-soft); color:var(--mesh-primary); padding:8px 12px; font-size:12px; cursor:pointer; }
.mesh-data-page .mesh-content button:hover { background:var(--mesh-hover); }
.mesh-data-page .mesh-content button:disabled { opacity:.5; cursor:default; }
.mesh-data-page :is(button,a,input,select):focus-visible { outline:2px solid var(--mesh-primary); outline-offset:2px; }
.mesh-data-page .data-table-wrap { width:100%; overflow:auto; border:1px solid var(--mesh-border); border-radius:9px; background:var(--mesh-surface); margin-bottom:20px; }
.mesh-data-page table { width:100%; border-collapse:collapse; font-size:13px; margin:0; color:var(--mesh-text); }
.mesh-data-page table th { padding:12px 14px; background:var(--mesh-brand); color:white; border:0; font-weight:500; font-size:12px; white-space:nowrap; text-align:left; }
.mesh-data-page table td { padding:11px 14px; border:0; border-bottom:1px solid var(--mesh-border); text-align:left; }
.mesh-data-page table tbody tr { background:var(--mesh-surface); }
.mesh-data-page table tbody tr:nth-child(even) { background:var(--mesh-stripe); }
.mesh-data-page table tbody tr:hover { background:var(--mesh-hover); }
.mesh-data-page table a { text-decoration:none; }
.mesh-data-page table a:hover { text-decoration:underline; }
.mesh-data-page .port-tag { display:inline-block; padding:3px 7px; border-radius:5px; color:white; font-size:10px; font-weight:500; white-space:nowrap; }
.mesh-data-page .to-mqtt { color:var(--mesh-muted); font-size:12px; font-style:italic; }
.mesh-data-page .payload-row { display:none; }
.mesh-data-page .packet-table tr.expanded + .payload-row { display:table-row; }
.mesh-data-page .payload-cell { font:12px/1.7 ui-monospace,Consolas,monospace; white-space:pre-wrap; overflow-wrap:anywhere; background:var(--mesh-soft); color:var(--mesh-text); }
.mesh-data-page .toggle-btn { cursor:pointer; color:var(--mesh-muted); display:inline-block; margin-right:7px; }
.mesh-data-page .inline-link { margin-left:6px; color:var(--mesh-primary); text-decoration:none; }
.mesh-data-page #map { width:100%; height:650px; border:1px solid var(--mesh-border); border-radius:9px; margin:18px 0 24px; }
.mesh-data-page .leaflet-container { background:var(--mesh-stripe); z-index:1; }
.mesh-data-page .data-empty { padding:30px 16px; text-align:center; color:var(--mesh-muted); }
@media(max-width:700px) {
.mesh-data-page .data-heading { align-items:flex-start; gap:10px; }
.mesh-data-page .data-heading h1 { font-size:23px; }
.mesh-data-page .data-heading p { font-size:12px; }
.mesh-data-page .data-toolbar { padding:12px; gap:8px; }
.mesh-data-page .data-table-wrap table { min-width:700px; }
.mesh-data-page #map { height:500px; }
.mesh-data-page .data-heading a { font-size:11px; padding:8px; }
}
</style>
+91 -19
View File
@@ -1,24 +1,104 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-firehose-page{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
<style>
.firehose-controls { justify-content:space-between; }
.firehose-controls h2 { font-size:15px; font-weight:600; }
.firehose-controls > div { flex-wrap:wrap; }
.firehose-filter { width:190px; }
@media(max-width:700px) { .firehose-controls > div { width:100%; } .firehose-filter { flex:1; width:120px; } }
.container {
margin: 0 auto;
padding: 10px;
}
#pause-button {
white-space: nowrap;
padding: 4px 10px;
font-size: 0.9rem;
border-radius: 6px;
}
.firehose-controls {
gap: 12px;
}
.firehose-filter {
min-width: 220px;
}
.port-tag {
display: inline-block;
padding: 2px 6px;
border-radius: 6px;
font-size: 0.75rem;
font-weight: 500;
color: #fff;
}
/* Packet table */
.packet-table {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
color: #e4e9ee;
}
.packet-table th, .packet-table td {
border: 1px solid #3a3f44;
padding: 6px 10px;
text-align: left;
}
.packet-table th {
background-color: #1f2226;
font-weight: bold;
}
.packet-table tr:nth-of-type(odd) { background-color: #272b2f; }
.packet-table tr:nth-of-type(even) { background-color: #212529; }
/* Port tag */
.port-tag {
display: inline-block;
padding: 1px 6px;
border-radius: 6px;
font-size: 0.75rem;
font-weight: 500;
color: #fff;
}
.to-mqtt { font-style: italic; color: #aaa; }
/* Payload rows */
.payload-row { display: none; background-color: #1b1e22; }
.payload-cell {
padding: 8px 12px;
font-family: monospace;
white-space: pre-wrap;
color: #b0bec5;
}
.packet-table tr.expanded + .payload-row {
display: table-row;
}
/* Toggle arrow */
.toggle-btn {
cursor: pointer;
color: #aaa;
margin-right: 6px;
font-weight: bold;
}
.toggle-btn:hover { color: #fff; }
/* Inline link next to port tag */
.inline-link {
margin-left: 6px;
font-weight: bold;
text-decoration: none;
color: #9fd4ff;
}
.inline-link:hover {
color: #c7e6ff;
}
</style>
{% endblock %}
{% block body %}
<div class="container">
<header class="data-heading"><div><span class="mesh-eyebrow">NETWORK ACTIVITY</span><h1>Live Traffic</h1><p>Follow packet traffic across your mesh network.</p></div><a class="mesh-secondary-button" href="/map">View map ↗</a></header>
<form class="data-toolbar firehose-controls">
<h2 class="mb-0" data-translate-lang="live_feed">📡 Live Traffic</h2>
<form class="d-flex align-items-center justify-content-between mb-3 firehose-controls">
<h2 class="mb-0" data-translate-lang="live_feed">📡 Live Feed</h2>
<div class="d-flex align-items-center gap-2">
<label for="channel-filter" class="mb-0" data-translate-lang="channel">Channel</label>
@@ -35,7 +115,6 @@
</div>
</form>
<div class="data-table-wrap" role="region" aria-label="Live packet table" tabindex="0">
<table class="packet-table">
<thead>
<tr>
@@ -49,7 +128,6 @@
</thead>
<tbody id="packet_list"></tbody>
</table>
</div>
</div>
@@ -174,7 +252,6 @@ function logPacketTimes(packet) {
FIREHOSE FETCHING
====================================================== */
let lastImportTimeUs = null;
let firehoseLoaded = false;
let updatesPaused = false;
let updateInterval = 3000;
let selectedChannel = "";
@@ -208,7 +285,6 @@ async function loadChannels() {
}
function resetFirehose() {
firehoseLoaded = false;
lastImportTimeUs = null;
document.getElementById("packet_list").innerHTML = "";
}
@@ -233,8 +309,6 @@ async function fetchUpdates() {
const data = await res.json();
const packets = data.packets || [];
const highlightNewPackets = firehoseLoaded;
firehoseLoaded = true;
if (!packets.length) return;
const list = document.getElementById("packet_list");
@@ -330,7 +404,6 @@ async function fetchUpdates() {
`;
list.insertAdjacentHTML("afterbegin", html);
if (highlightNewPackets) markNewPacketArrival(list.firstElementChild);
}
// Limit table size
@@ -353,7 +426,6 @@ document.addEventListener("DOMContentLoaded", async () => {
pauseBtn.addEventListener("click", () => {
updatesPaused = !updatesPaused;
pauseBtn.setAttribute("aria-pressed", String(updatesPaused));
pauseBtn.textContent =
updatesPaused
+5 -2
View File
@@ -1,2 +1,5 @@
{% extends "map-view.html" %}
{% set dashboard = true %}
{% extends "base.html" %}
{% block body %}
{% include "search_form.html" %}
{% endblock %}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+33 -29
View File
@@ -1,32 +1,44 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-net-page{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
<style>
#weekly-message { padding:18px 22px; background:var(--mesh-soft); border:1px solid var(--mesh-border); border-radius:9px; color:var(--mesh-primary-dark); font-size:14px; margin-bottom:18px; white-space:pre-wrap; overflow-wrap:anywhere; }
#weekly-message:empty { display:none; }
#total-count { padding:16px 20px; color:var(--mesh-muted); background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px 9px 0 0; font-size:13px; }
#total-count-value { font-size:20px; font-weight:650; color:var(--mesh-primary); margin-left:8px; }
#chat-log { padding:0; }
#chat-container { border:1px solid var(--mesh-border); border-top:0; border-radius:0 0 9px 9px; background:var(--mesh-surface); overflow:hidden; }
.chat-packet { display:grid; grid-template-columns:155px 130px 200px minmax(0,1fr); gap:16px; margin:0; padding:16px 20px; border-bottom:1px solid var(--mesh-border); font-size:13px; }
.chat-packet:nth-child(even) { background:var(--mesh-stripe); }
.chat-packet > span { width:auto; padding:0; min-width:0; overflow-wrap:anywhere; }
.chat-packet .timestamp { color:var(--mesh-muted); font-size:11px; }
.chat-packet .channel { color:var(--mesh-muted); font-size:12px; }
.chat-packet .nodename { font-weight:600; }
.chat-packet a { text-decoration:none; }
#net-note { color:var(--mesh-muted); font-size:12px; margin-top:14px; }
@media(max-width:900px) { .chat-packet { grid-template-columns:120px 100px minmax(0,1fr); } .chat-packet .message { grid-column:1 / -1; } }
@media(max-width:500px) { .chat-packet { grid-template-columns:1fr 1fr; gap:8px; } .chat-packet .nodename { grid-column:1 / -1; } }
.timestamp { min-width: 10em; color: #ccc; }
.chat-packet:nth-of-type(odd) { background-color: #3a3a3a; }
.chat-packet {
border-bottom: 1px solid #555;
padding: 3px 6px;
border-radius: 6px;
margin: 0;
}
.chat-packet > [class^="col-"] {
padding-left: 10px !important;
padding-right: 10px !important;
padding-top: 1px !important;
padding-bottom: 1px !important;
}
.chat-packet:nth-of-type(even) { background-color: #333333; }
.channel { font-style: italic; color: #bbb; }
.channel a { font-style: normal; color: #999; }
#weekly-message { margin: 15px 0; font-weight: bold; color: #ffeb3b; }
#total-count { margin-bottom: 10px; font-style: italic; color: #ccc; }
#net-note { margin: 16px 0 0; font-size: 0.9rem; color: #aaa; }
</style>
{% endblock %}
{% block body %}
<div class="container">
<header class="data-heading"><div><span class="mesh-eyebrow">COMMUNITY NET</span><h1><span data-translate-lang="net_title">Network check-in</span></h1><p>Weekly check-ins and reports from your mesh.</p></div><a class="mesh-secondary-button" href="/map">View map ↗</a></header>
<!-- ⭐ NET TITLE WITH ICON ⭐ -->
<div class="container px-2">
<h2 style="color:white; margin:0 0 10px 0;">
<span class="icon">💬</span>
<span data-translate-lang="net_title"></span>
</h2>
</div>
<!-- Weekly network message -->
<div id="weekly-message"></div>
@@ -120,7 +132,7 @@ document.addEventListener("DOMContentLoaded", async () => {
const fromName =
(packet.long_name || "").trim() ||
`${netTranslations.node_fallback || "Node"} ${packet.from_node_id}`;
`${netTranslations.node_fallback} ${packet.from_node_id}`;
const div = document.createElement("div");
div.className = "row chat-packet";
@@ -189,7 +201,6 @@ document.addEventListener("DOMContentLoaded", async () => {
`/api/packets?portnum=1&contains=${encodeURIComponent(tag)}&since=${sinceUs}&limit=1000`;
const resp = await fetch(url);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const data = await resp.json();
if (data?.packets?.length)
@@ -197,7 +208,6 @@ document.addEventListener("DOMContentLoaded", async () => {
} catch (err) {
console.error("Initial fetch error:", err);
chatContainer.innerHTML = '<p class="data-empty">Unable to load check-ins. Reload to try again.</p>';
}
}
@@ -229,12 +239,6 @@ document.addEventListener("DOMContentLoaded", async () => {
await loadTranslations(cfg);
await fetchInitialPackets(netTag);
if (!chatContainer.children.length) {
const empty = document.createElement("p");
empty.className = "data-empty";
empty.textContent = netTag ? "No check-ins received in the last six days." : "No network check-in tag configured.";
chatContainer.append(empty);
}
} catch (err) {
console.error("Initialization failed:", err);
+327 -59
View File
@@ -1,40 +1,311 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-node-page{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
<style>
.node-info { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:16px; margin-bottom:20px; font-size:13px; }
.node-info-col { background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; padding:20px; overflow-wrap:anywhere; }
.node-info-col > div { padding:5px 0; }
.node-info strong { color:var(--mesh-muted); font-weight:500; }
.node-actions { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:20px; }
.chart-container { width:100%; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; margin-bottom:20px; overflow:hidden; }
.chart-header { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:10px; padding:16px 20px; border-bottom:1px solid var(--mesh-border); font-size:14px; font-weight:600; }
.chart-actions { display:flex; gap:6px; }
.filter-container { display:flex; gap:10px; flex-wrap:wrap; padding:16px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; margin-bottom:18px; }
#chartModal,#qrModal { display:none; position:fixed; inset:0; background:#17263c99; z-index:9999; align-items:center; justify-content:center; padding:16px; }
#chartModal > div { background:var(--mesh-surface); border-radius:10px; width:95%; height:85%; padding:14px; }
#qrModal > div { background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:12px; padding:24px; width:380px; max-width:100%; text-align:center; }
.qr-header { display:flex; justify-content:space-between; align-items:center; gap:10px; }
.qr-title { font-size:18px; margin:0; }
.qr-node-name { font-size:15px; margin:16px 0; overflow-wrap:anywhere; }
.qr-image { display:inline-block; padding:16px; background:var(--mesh-surface); margin-bottom:14px; }
.qr-image img,.qr-image canvas { max-width:100%; }
.qr-url-container { border:1px solid var(--mesh-border); border-radius:6px; background:var(--mesh-page); padding:12px; margin-bottom:16px; }
.qr-url { display:block; max-height:80px; overflow:auto; overflow-wrap:anywhere; font:11px/1.6 monospace; color:var(--mesh-muted); }
.qr-actions { display:flex; justify-content:center; }
.mesh-data-page .copied { background:#e8f5ee; color:#187346; }
@media(max-width:900px) { .node-info { grid-template-columns:minmax(0,1fr); gap:10px; } }
@media(max-width:700px) { .chart-header { padding:12px; } .chart-actions button { padding:6px 8px; } }
{{ super() }}
/* --- Map --- */
#map {
width: 100%;
height: 400px;
margin-bottom: 20px;
border-radius: 8px;
display: block;
}
.leaflet-container {
background: #1a1a1a;
z-index: 1;
}
/* --- Node Info --- */
.node-info {
color: #ddd;
font-size: 0.88rem;
margin-bottom: 14px;
display: grid;
grid-template-columns: repeat(3, minmax(120px, 1fr));
grid-column-gap: 12px;
grid-row-gap: 12px;
}
.node-info-col {
background-color: #1f2226;
border: 1px solid #3a3f44;
border-radius: 8px;
padding: 12px 14px;
}
.node-info-col div { padding: 2px 0; }
.node-info strong {
color: #9fd4ff;
font-weight: 600;
}
/* --- Charts --- */
.chart-container {
width: 100%;
height: 380px;
margin-bottom: 25px;
border: 1px solid #3a3f44;
border-radius: 8px;
overflow: hidden;
background-color: #16191d;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
background: #1f2226;
padding: 6px 12px;
font-weight: bold;
border-bottom: 1px solid #333;
font-size: 1rem;
}
.chart-actions button {
background: rgba(255,255,255,0.05);
border: 1px solid #555;
border-radius: 4px;
color: #ccc;
font-size: 0.8rem;
padding: 2px 6px;
cursor: pointer;
}
.chart-actions button:hover {
color: #fff;
background: rgba(255,255,255,0.15);
border-color: #888;
}
/* --- Packet Table --- */
.packet-table {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
color: #e4e9ee;
}
.packet-table th, .packet-table td {
border: 1px solid #3a3f44;
padding: 6px 10px;
text-align: left;
}
.packet-table th {
background-color: #1f2226;
font-weight: bold;
}
.packet-table tr:nth-of-type(odd) { background-color: #272b2f; }
.packet-table tr:nth-of-type(even) { background-color: #212529; }
.port-tag {
padding: 2px 6px;
border-radius: 6px;
font-size: 0.75rem;
color: #fff;
}
.to-mqtt { font-style: italic; color: #aaa; }
.payload-row { display: none; background-color: #1b1e22; }
.payload-cell {
padding: 8px 12px;
font-family: monospace;
white-space: pre-wrap;
color: #b0bec5;
}
.packet-table tr.expanded + .payload-row { display: table-row; }
.toggle-btn { cursor: pointer; color: #aaa; margin-right: 6px; }
.toggle-btn:hover { color: #fff; }
/* --- Chart Modal --- */
#chartModal {
display:none; position:fixed; top:0; left:0; width:100%; height:100%;
background:rgba(0,0,0,0.9); z-index:9999;
align-items:center; justify-content:center;
}
#chartModal > div {
background:#1b1e22; border-radius:8px;
width:90%; height:85%; padding:10px;
}
/* Inline link */
.inline-link {
margin-left: 6px;
font-weight: bold;
text-decoration: none;
color: #9fd4ff;
}
.inline-link:hover { color: #c7e6ff; }
/* --- QR Code & Import --- */
.node-actions {
display: flex;
gap: 10px;
margin-bottom: 14px;
flex-wrap: wrap;
}
.node-actions {
display: flex;
gap: 10px;
margin-bottom: 16px;
flex-wrap: wrap;
}
.node-actions button {
background: linear-gradient(135deg, #2d3748 0%, #1a202c 100%);
border: 1px solid #4a5568;
border-radius: 8px;
color: #e4e9ee;
padding: 8px 16px;
font-size: 0.9rem;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
font-weight: 500;
transition: all 0.2s;
}
.node-actions button:hover {
background: linear-gradient(135deg, #3d4758 0%, #2a303c 100%);
border-color: #6a7788;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}
.node-actions button.copied {
background: linear-gradient(135deg, #276749 0%, #22543d 100%);
border-color: #48bb78;
color: #fff;
}
.copy-success {
color: #4ade80 !important;
transition: opacity 0.3s;
}
/* --- QR Modal --- */
#qrModal {
display:none;
position:fixed;
top:0; left:0; width:100%; height:100%;
background:rgba(0,0,0,0.95);
z-index:10000;
align-items:center;
justify-content:center;
backdrop-filter:blur(4px);
}
#qrModal > div {
background:linear-gradient(145deg, #1e2228, #16191d);
border:1px solid #3a4450;
border-radius:16px;
padding:28px;
max-width:380px;
text-align:center;
color:#e4e9ee;
box-shadow:0 25px 80px rgba(0,0,0,0.6);
}
#qrModal .qr-header {
display:flex;
justify-content:space-between;
align-items:center;
margin-bottom:16px;
}
#qrModal .qr-title {
font-size:1.3rem;
font-weight:600;
margin:0;
color:#9fd4ff;
}
#qrModal .qr-close {
background:rgba(255,255,255,0.05);
border:1px solid #4a5568;
color:#9ca3af;
width:32px;
height:32px;
border-radius:8px;
cursor:pointer;
font-size:1.2rem;
display:flex;
align-items:center;
justify-content:center;
transition:all 0.2s;
}
#qrModal .qr-close:hover {
background:rgba(255,255,255,0.1);
color:#fff;
border-color:#6a7788;
}
#qrModal .qr-node-name {
font-size:1.15rem;
color:#fff;
margin:12px 0 20px;
font-weight:500;
}
#qrModal .qr-image {
background:#fff;
padding:16px;
border-radius:12px;
display:inline-block;
margin-bottom:16px;
box-shadow:0 8px 30px rgba(0,0,0,0.4);
}
#qrModal .qr-image img {
display:block;
border-radius:4px;
}
#qrModal .qr-url-container {
background:rgba(0,0,0,0.4);
border-radius:8px;
padding:12px;
margin-bottom:18px;
}
#qrModal .qr-url {
font-size:0.65rem;
color:#9ca3af;
word-break:break-all;
font-family:'Monaco', 'Menlo', monospace;
line-height:1.4;
max-height:48px;
overflow-y:auto;
display:block;
}
#qrModal .qr-actions {
display:flex;
gap:12px;
justify-content:center;
}
#qrModal .qr-btn {
background:linear-gradient(135deg, #2d3748 0%, #1a202c 100%);
border:1px solid #4a5568;
color:#e4e9ee;
padding:12px 24px;
border-radius:10px;
cursor:pointer;
font-size:0.9rem;
font-weight:500;
transition:all 0.2s;
display:flex;
align-items:center;
gap:8px;
min-width:140px;
justify-content:center;
}
#qrModal .qr-btn:hover {
background:linear-gradient(135deg, #3d4758 0%, #2a303c 100%);
border-color:#6a7788;
transform:translateY(-2px);
box-shadow:0 4px 12px rgba(0,0,0,0.3);
}
#qrModal .qr-btn.copied {
background:linear-gradient(135deg, #276749 0%, #22543d 100%);
border-color:#48bb78;
color:#fff;
}
</style>
{% endblock %}
{% block body %}
<div class="container">
<header class="data-heading"><div><span class="mesh-eyebrow">DEVICE INSPECTOR</span><h1><span id="nodeLabel">Node details</span></h1><p>Device information, telemetry, and recent packet activity.</p></div><a class="mesh-secondary-button" href="/nodelist">All nodes ↗</a></header>
<h5 class="mb-3">
📡 <span data-translate-lang="specifications">Specifications:</span><strong>:</strong>
<span id="nodeLabel"></span>
</h5>
<!-- Node Actions -->
<div class="node-actions" id="nodeActions" style="display:none;">
@@ -151,18 +422,18 @@
<!-- Packet Filters -->
<div class="filter-container" style="margin-bottom:10px; display:flex; gap:12px; flex-wrap:wrap;">
<select id="packet_since" aria-label="Packet time range">
<select id="packet_since">
<option value="">All time</option>
<option value="3600">Last hour</option>
<option value="21600">Last 6 hours</option>
<option value="86400">Last 24 hours</option>
<option value="172800">Last 2 days</option>
<option value="259200" selected>Last 3 days</option>
<option value="259200">Last 3 days</option>
<option value="432000">Last 5 days</option>
<option value="604800">Last 7 days</option>
</select>
<select id="packet_port" aria-label="Packet port">
<select id="packet_port">
<option value="">All ports</option>
</select>
@@ -174,7 +445,6 @@
<!-- Packets -->
<div class="data-table-wrap" role="region" aria-label="Node packet table" tabindex="0">
<table class="packet-table">
<thead>
<tr>
@@ -189,7 +459,6 @@
<tbody id="packet_list"></tbody>
</table>
</div>
</div>
@@ -197,7 +466,7 @@
<div id="chartModal">
<div>
<div style="text-align:right;">
<button onclick="closeModal()" style="background:none;border:none;color:var(--mesh-muted);">✖</button>
<button onclick="closeModal()" style="background:none;border:none;color:#ccc;">✖</button>
</div>
<div id="modalChart" style="width:100%; height:90%;"></div>
</div>
@@ -399,7 +668,6 @@ async function loadNodeInfo(){
if (!node) {
document.getElementById("node-info").style.display = "none";
document.getElementById("nodeLabel").textContent = "Node unavailable";
return;
}
@@ -934,14 +1202,14 @@ async function loadTelemetryCharts(){
// Battery / Voltage chart
if (hasBattery || hasVoltage) {
batteryContainer.style.display = "block";
chart1 = initMeshChart(document.getElementById('chart_battery_voltage'));
chart1 = echarts.init(document.getElementById('chart_battery_voltage'));
chart1.setOption({
tooltip: { trigger:'axis' },
legend: { data:['Battery Level','Voltage'], textStyle:{ color:'#64748b' } },
xAxis: { type:'category', data:chartData.times, axisLabel:{ color:'#64748b' } },
legend: { data:['Battery Level','Voltage'], textStyle:{ color:'#ccc' } },
xAxis: { type:'category', data:chartData.times, axisLabel:{ color:'#ccc' } },
yAxis: [
{ type:'value', name:'Battery (%)', axisLabel:{ color:'#64748b' } },
{ type:'value', name:'Voltage (V)', axisLabel:{ color:'#64748b' } }
{ type:'value', name:'Battery (%)', axisLabel:{ color:'#ccc' } },
{ type:'value', name:'Voltage (V)', axisLabel:{ color:'#ccc' } }
],
series: [
makeLine('Battery Level', 'rgba(255,214,82,1)', chartData.battery),
@@ -955,12 +1223,12 @@ async function loadTelemetryCharts(){
// Air / Channel chart
if (hasAir || hasChan) {
airContainer.style.display = "block";
chart2 = initMeshChart(document.getElementById('chart_air_channel'));
chart2 = echarts.init(document.getElementById('chart_air_channel'));
chart2.setOption({
tooltip: { trigger:'axis' },
legend: { data:['Air Util Tx','Channel Utilization'], textStyle:{ color:'#64748b' } },
xAxis: { type:'category', data:chartData.times, axisLabel:{ color:'#64748b' } },
yAxis: { type:'value', name:'%', axisLabel:{ color:'#64748b' } },
legend: { data:['Air Util Tx','Channel Utilization'], textStyle:{ color:'#ccc' } },
xAxis: { type:'category', data:chartData.times, axisLabel:{ color:'#ccc' } },
yAxis: { type:'value', name:'%', axisLabel:{ color:'#ccc' } },
series: [
makeLine('Air Util Tx', 'rgba(138,255,108,1)', chartData.airUtil),
makeLine('Channel Utilization', 'rgba(255,102,204,1)', chartData.chanUtil)
@@ -973,14 +1241,14 @@ async function loadTelemetryCharts(){
// Environment chart
if (hasEnv) {
envContainer.style.display = "block";
chart3 = initMeshChart(document.getElementById('chart_environment'));
chart3 = echarts.init(document.getElementById('chart_environment'));
chart3.setOption({
tooltip: { trigger:'axis' },
legend: { data:['Temperature (°C)','Humidity (%)','Pressure (hPa)'], textStyle:{ color:'#64748b' } },
xAxis: { type:'category', data:chartData.times, axisLabel:{ color:'#64748b' } },
legend: { data:['Temperature (°C)','Humidity (%)','Pressure (hPa)'], textStyle:{ color:'#ccc' } },
xAxis: { type:'category', data:chartData.times, axisLabel:{ color:'#ccc' } },
yAxis: [
{ type:'value', name:'°C / %', axisLabel:{ color:'#64748b' } },
{ type:'value', name:'hPa', axisLabel:{ color:'#64748b' } }
{ type:'value', name:'°C / %', axisLabel:{ color:'#ccc' } },
{ type:'value', name:'hPa', axisLabel:{ color:'#ccc' } }
],
series: [
makeLine('Temperature (°C)', 'rgba(255,138,82,1)', chartData.temperature),
@@ -1170,7 +1438,7 @@ async function loadNeighborTimeSeries() {
.replace("{n}", kept.length)
.replace("{total}", ranked.length);
const chart = initMeshChart(chartEl);
const chart = echarts.init(chartEl);
chart.setOption({
title: {
@@ -1187,13 +1455,13 @@ async function loadNeighborTimeSeries() {
legend: {
type: "scroll",
data: legend,
textStyle: { color: "#64748b" }
textStyle: { color: "#ccc" }
},
xAxis: {
type: "category",
data: xTimes,
axisLabel: {
color: "#64748b",
color: "#ccc",
formatter: value =>
new Date(value / 1000).toLocaleString([], {
year: "2-digit",
@@ -1207,7 +1475,7 @@ async function loadNeighborTimeSeries() {
yAxis: {
type: "value",
name: "SNR",
axisLabel: { color: "#64748b" }
axisLabel: { color: "#ccc" }
},
series
});
@@ -1291,22 +1559,22 @@ async function loadPacketHistogram() {
data: dayKeys.map(d => counts[port]?.[d] || 0)
}));
const chart = initMeshChart(
const chart = echarts.init(
document.getElementById("chart_packet_histogram")
);
chart.setOption({
animation: false,
tooltip: { trigger: "axis" },
legend: { textStyle: { color: "#64748b" } },
legend: { textStyle: { color: "#ccc" } },
xAxis: {
type: "category",
data: dayLabels,
axisLabel: { color: "#64748b" }
axisLabel: { color: "#ccc" }
},
yAxis: {
type: "value",
axisLabel: { color: "#64748b" }
axisLabel: { color: "#ccc" }
},
series
});
@@ -1327,7 +1595,7 @@ function expandChart(type){
if (!sourceChart) return;
const modal = document.getElementById('chartModal');
const modalChart = initMeshChart(document.getElementById('modalChart'));
const modalChart = echarts.init(document.getElementById('modalChart'));
modal.style.display = "flex";
modalChart.setOption(sourceChart.getOption());
modalChart.resize();
@@ -1415,7 +1683,7 @@ document.addEventListener("DOMContentLoaded", async () => {
await drawNeighbors(fromNodeId, neighborIds);
}
await reloadPackets();
await loadPackets();
initPacketPortFilter();
await loadTelemetryCharts();
await loadNeighborTimeSeries();
@@ -1485,7 +1753,7 @@ async function loadNodeStats(nodeId) {
filters.portnum = portSel;
}
return loadPackets(filters);
loadPackets(filters);
}
function exportPacketsCSV() {
+11 -13
View File
@@ -9,8 +9,8 @@
#mynetwork {
width: 100%;
height: 100vh;
border: 1px solid var(--mesh-border);
background-color: var(--mesh-surface);
border: 1px solid #ddd;
background-color: #f8f9fa;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
@@ -30,15 +30,15 @@
.search-container button {
padding: 8px;
border-radius: 8px;
border: 1px solid var(--mesh-border);
border: 1px solid #ccc;
}
.search-container button {
background-color: var(--mesh-brand);
background-color: #007bff;
color: white;
cursor: pointer;
}
.search-container button:hover {
background-color: var(--mesh-brand-deep);
background-color: #0056b3;
}
/* Node info box */
@@ -49,10 +49,10 @@
background-color: rgba(255,255,255,0.95);
padding: 12px;
border-radius: 8px;
border: 1px solid var(--mesh-border);
border: 1px solid #ccc;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
font-size: 14px;
color: var(--mesh-text);
color: #333;
width: 260px;
max-height: 250px;
overflow-y: auto;
@@ -66,13 +66,11 @@
background: rgba(255,255,255,0.9);
padding: 10px;
border-radius: 5px;
border: 1px solid var(--mesh-border);
border: 1px solid #ccc;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
font-size: 14px;
display: flex;
flex-wrap: wrap;
max-width: calc(100% - 20px);
color: var(--mesh-text);
color: #333;
}
.legend-category {
margin-right: 10px;
@@ -93,7 +91,7 @@
<!-- SEARCH + FILTER -->
<div class="search-container">
<label style="color:var(--mesh-text);">Channel:</label>
<label style="color:#333;">Channel:</label>
<select id="channel-select" onchange="filterByChannel()"></select>
<input type="text" id="node-search" placeholder="Search node...">
@@ -133,7 +131,7 @@
<script>
// Initialize ECharts
const chart = initMeshChart(document.getElementById("mynetwork"));
const chart = echarts.init(document.getElementById("mynetwork"));
// -----------------------------------
// COLOR + ROLE HELPERS
+223 -32
View File
@@ -1,35 +1,226 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-nodelist-page{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
<style>
#node-list { width:100%; overflow:auto; border:1px solid var(--mesh-border); border-radius:9px; background:var(--mesh-surface); }
#node-list table { min-width:1150px; }
#node-list th { cursor:pointer; }
.filter-container { display:flex; flex-wrap:wrap; gap:10px; margin-bottom:18px; padding:16px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; }
.search-box { flex:1 1 220px; }
.count-container { font-size:13px; color:var(--mesh-muted); margin-bottom:10px; }
#node-count { color:var(--mesh-primary); font-weight:700; }
.node-list-note { display:flex; align-items:center; gap:8px; color:var(--mesh-muted); font-size:12px; margin-bottom:18px; flex-wrap:wrap; }
.node-status { opacity:0; padding:3px 8px; border-radius:20px; background:var(--mesh-soft); color:var(--mesh-primary); margin-left:10px; font-size:11px; }
.node-status.active { opacity:1; }
.favorite-star { cursor:pointer; font-size:20px; color:#8b98aa; user-select:none; }
.favorite-star.active { color:#ad7800; }
.mesh-data-page .favorites-btn.active { background:#fff3d6; border-color:#eacb80; color:#8b6200; }
.sort-icon { font-size:10px; }
#mobile-node-list { display:none; }
.node-card { background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; padding:16px; margin-bottom:12px; font-size:13px; overflow-wrap:anywhere; }
.node-card-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:10px; font-size:16px; font-weight:600; }
.node-card-field { padding:3px 0; }
.node-card-field b { color:var(--mesh-muted); font-weight:500; }
@media(max-width:768px) { #node-list { display:none; } #mobile-node-list { display:block!important; } .filter-container { padding:12px; gap:8px; } .filter-container select { flex:1 1 130px; } }
html, body {
overflow-x: auto !important;
}
table {
/* FIX: allow table to keep natural width so scrolling works */
width: max-content;
min-width: 100%;
border-collapse: collapse;
margin: 1em auto;
}
/* Desktop scroll wrapper */
#node-list {
width: 100%;
overflow-x: auto; /* allows horizontal scroll */
overflow-y: hidden;
/* !!! removed display:flex because it prevents scrolling */
}
#node-list table {
width: max-content; /* table keeps its natural width */
min-width: 100%; /* won't shrink smaller than viewport */
}
th, td {
padding: 10px;
border: 1px solid #333;
text-align: left;
}
th {
background-color: #1f1f1f;
color: white;
position: sticky;
top: 0;
z-index: 2;
cursor: pointer;
}
.sort-icon {
font-size: 0.7em;
margin-left: 4px;
}
tr:nth-child(even) {
background-color: #181818;
}
tr:nth-child(odd) {
background-color: #222;
}
tr:hover {
background-color: #2a2a2a;
}
.filter-container {
width: 80%;
margin: 1em auto;
display: flex;
gap: 10px;
flex-wrap: wrap;
}
select, .export-btn, .search-box, .clear-btn {
padding: 6px;
border-radius: 4px;
border: 1px solid #333;
cursor: pointer;
}
.search-box {
flex: 1;
}
.export-btn {
background-color: #28a745;
color: white;
border: none;
}
.export-btn:hover {
background-color: #218838;
}
.clear-btn {
background-color: #dc3545;
color: white;
border: none;
}
.clear-btn:hover {
background-color: #c82333;
}
.count-container {
width: 80%;
margin: 0 auto 10px;
font-weight: bold;
color: white;
}
.node-list-note {
width: 80%;
margin: -4px auto 10px;
color: rgba(255, 255, 255, 0.68);
font-size: 0.9em;
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.node-list-note select {
padding: 3px 6px;
min-width: 70px;
}
.node-status {
margin-left: 10px;
padding: 2px 8px;
border-radius: 12px;
border: 1px solid #2a6a8a;
background: #0d2a3a;
color: #9fd4ff;
font-size: 0.9em;
display: inline-block;
opacity: 0;
transition: opacity 0.15s ease-in-out;
}
.node-status.active {
opacity: 1;
}
/* Favorite stars */
.favorite-star {
cursor: pointer;
font-size: 1.2em;
user-select: none;
transition: color 0.2s;
}
.favorite-star:hover {
transform: scale(1.2);
}
.favorite-star.active {
color: #ffd700;
}
/* Favorite filter button */
.favorites-btn {
background-color: #ffd700;
color: #000;
border: none;
}
.favorites-btn:hover {
background-color: #ffed4e;
}
.favorites-btn.active {
background-color: #ff6b6b;
color: white;
}
/* --------------------------------------------- */
/* MOBILE CARD VIEW */
/* --------------------------------------------- */
@media (max-width: 768px) {
/* Hide desktop view */
#node-list table {
display: none;
}
/* Show mobile cards */
#mobile-node-list {
display: block !important;
width: 100%;
padding: 0 10px;
/* If you want horizontal swiping, uncomment:
overflow-x: auto;
white-space: nowrap; */
}
.node-card {
background: #1e1e1e;
border: 1px solid #333;
border-radius: 8px;
padding: 12px 15px;
margin-bottom: 12px;
color: white;
}
.node-card-header {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 1.2em;
font-weight: bold;
margin-bottom: 8px;
}
.node-card-field {
margin: 4px 0;
font-size: 0.9em;
}
.node-card-field b {
color: #9fd4ff;
}
.favorite-star {
font-size: 1.4em;
}
}
</style>
{% endblock %}
{% block body %}
<header class="data-heading"><div><span class="mesh-eyebrow">NODE DIRECTORY</span><h1>Network nodes</h1><p>Find devices, inspect their activity, and manage your favorites.</p></div><a class="mesh-secondary-button" href="/map">View map ↗</a></header>
<div class="filter-container">
<input
@@ -40,19 +231,19 @@
placeholder="Search by name or ID or HEX ID..."
/>
<select id="role-filter" aria-label="Filter by role">
<select id="role-filter">
<option value="" data-translate-lang="all_roles">All Roles</option>
</select>
<select id="channel-filter" aria-label="Filter by channel">
<select id="channel-filter">
<option value="" data-translate-lang="all_channels">All Channels</option>
</select>
<select id="hw-filter" aria-label="Filter by hardware">
<select id="hw-filter">
<option value="" data-translate-lang="all_hw">All HW Models</option>
</select>
<select id="firmware-filter" aria-label="Filter by firmware">
<select id="firmware-filter">
<option value="" data-translate-lang="all_firmware">All Firmware</option>
</select>
@@ -105,7 +296,7 @@
</thead>
<tbody id="node-table-body">
<tr>
<td colspan="11" style="text-align:center; color:var(--mesh-muted);" data-translate-lang="loading_nodes">
<td colspan="11" style="text-align:center; color:white;" data-translate-lang="loading_nodes">
Loading nodes...
</td>
</tr>
@@ -439,12 +630,12 @@ document.addEventListener("DOMContentLoaded", async function() {
if (!nodes.length) {
if (shouldRenderTable) {
tbody.innerHTML = `<tr>
<td colspan="11" style="text-align:center; color:var(--mesh-muted);">
<td colspan="11" style="text-align:center; color:white;">
${nodelistTranslations.no_nodes_found || "No nodes found"}
</td>
</tr>`;
} else {
mobileList.innerHTML = `<div style="text-align:center; color:var(--mesh-muted);">
mobileList.innerHTML = `<div style="text-align:center; color:white;">
${nodelistTranslations.no_nodes_found || "No nodes found"}
</div>`;
}
@@ -502,7 +693,7 @@ document.addEventListener("DOMContentLoaded", async function() {
<div class="node-card-field"><b>Channel:</b> ${escapeHtml(node.channel || "N/A")}</div>
<div class="node-card-field"><b>Last Seen:</b> ${timeAgoFromMs(node.last_seen_ms)}</div>
<a href="/node/${node.node_id}" style="color:var(--mesh-primary); text-decoration:none; margin-top:10px; display:block;">
<a href="/node/${node.node_id}" style="color:#9fd4ff; text-decoration:underline; margin-top:5px; display:block;">
View Node →
</a>
`;
+94 -27
View File
@@ -1,6 +1,4 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-packet-page{% endblock %}
{% block title %}Packet Details{% endblock %}
@@ -9,30 +7,99 @@
{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
{{ super() }}
<style>
.mesh-data-page .packet-container { max-width:1150px!important; margin:0 auto!important; }
.packet-card { background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; overflow:hidden; color:var(--mesh-text); }
.packet-card .card-header { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; background:var(--mesh-soft); padding:18px 22px; border-bottom:1px solid var(--mesh-border); color:var(--mesh-primary-dark); font-size:15px; font-weight:600; }
.packet-card .card-header small { font-size:11px; font-weight:400; }
.packet-card .card-body { padding:24px; }
.packet-card dl { display:grid; grid-template-columns:180px minmax(0,1fr); gap:16px 24px; margin:0; font-size:13px; }
.packet-card dt { color:var(--mesh-muted); font-weight:500; }
.packet-card dd { margin:0; overflow-wrap:anywhere; }
.packet-card pre { padding:14px; background:var(--mesh-stripe); border:1px solid var(--mesh-border); border-radius:6px; color:var(--mesh-text); font-size:12px; white-space:pre-wrap; overflow-wrap:anywhere; margin:0; }
#map { display:none; }
.source-marker { width:24px; height:24px; background:#f4484866; border:3px solid #e33; border-radius:50%; box-shadow:0 0 6px #f007; }
#seen-container { background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; overflow:hidden; }
#seen-container h5 { padding:16px 20px; margin:0!important; color:var(--mesh-text); font-size:15px; }
.seen-table { margin:0; }
#loading { color:var(--mesh-muted); padding:24px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; }
@media(max-width:700px) { .packet-card dl { grid-template-columns:minmax(0,1fr); gap:6px; } .packet-card dd { margin-bottom:14px; } .packet-card .card-body { padding:18px; } }
/* --- Packet page container --- */
.packet-container {
max-width: 900px;
margin: 0 auto;
padding: 20px 15px;
font-family: "JetBrains Mono", monospace;
}
/* --- Packet Details Card --- */
.packet-card .card-body { padding: 26px 30px; }
.packet-card {
background-color: #1e1f22;
border: 1px solid #3a3a3a;
border-radius: 12px;
color: #ddd;
margin-top: 35px;
box-shadow: 0 0 20px rgba(0,0,0,0.35);
overflow: hidden;
}
.packet-card .card-header {
background: linear-gradient(90deg, #2c2f35, #25262a);
border-bottom: 1px solid #3f3f3f;
font-weight: 600;
font-size: 1.1em;
padding: 14px 18px;
color: #e2e6ea;
display: flex;
justify-content: space-between;
align-items: center;
}
/* --- Map --- */
#map {
width: 100%;
height: 640px;
border-radius: 10px;
margin-top: 20px;
border: 1px solid #333;
display: none;
}
/* --- SOURCE MARKER --- */
.source-marker {
width: 24px;
height: 24px;
background: rgba(255,0,0,0.55);
border: 3px solid #ff0000;
border-radius: 50%;
box-shadow: 0 0 6px rgba(255,0,0,0.7);
}
/* --- Seen Table --- */
.seen-table {
border-collapse: separate;
border-spacing: 0 6px;
font-size: 0.92em;
}
.seen-table thead th {
background-color: #2a2b2f;
color: #e2e2e2;
padding: 10px 12px;
border: none !important;
text-transform: uppercase;
font-size: 0.75em;
}
.seen-table tbody td {
background: #323338;
color: #f0f0f0;
border-top: 1px solid #4a4c4f !important;
border-bottom: 1px solid #4a4c4f !important;
padding: 10px 12px !important;
}
.seen-table tbody tr:hover td { background-color: #3a3c41 !important; }
.seen-table tbody tr td:first-child {
border-left: 1px solid #4a4c4f;
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
}
.seen-table tbody tr td:last-child {
border-right: 1px solid #4a4c4f;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
</style>
{% endblock %}
{% block body %}
<div class="container packet-container">
<header class="data-heading"><div><span class="mesh-eyebrow">PACKET INSPECTOR</span><h1>Packet details</h1><p>Inspect the payload, route, and gateways that received this packet.</p></div><a class="mesh-secondary-button" href="/firehose">Live packets ↗</a></header>
<div class="container mt-4 mb-5 packet-container">
<div id="loading" data-translate-lang="loading">Loading packet information...</div>
<div id="packet-card" class="packet-card d-none"></div>
@@ -40,13 +107,13 @@
<div id="map"></div>
<div id="seen-container" class="mt-4 d-none">
<h5 >
<h5 style="color:#ccc; margin:15px 0 10px 0;">
📡 <span data-translate-lang="seen_by">Seen By</span>
<span id="seen-count" style="color:var(--mesh-primary);"></span>
<span id="seen-count" style="color:#4da6ff;"></span>
</h5>
<div class="table-responsive">
<table class="table table-sm seen-table">
<table class="table table-dark table-sm seen-table">
<thead>
<tr>
<th data-translate-lang="gateway">Gateway</th>
@@ -443,10 +510,10 @@ seenTableBody.innerHTML = Object.keys(hopGroups)
<tr>
<td colspan="6"
style="
background:var(--mesh-soft);
background:#1f2327;
font-weight:700;
color:var(--mesh-primary-dark);
border-top:1px solid var(--mesh-border);
color:#9ecbff;
border-top:1px solid #444;
padding:8px 12px;
">
🔁 ${hopLabel} (${hopGroups[hopKey].length})
+287 -67
View File
@@ -1,60 +1,280 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-reliability-page{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
<style>
.reach-page { width:100%; }
.reach-description { margin-bottom:20px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; padding:14px 18px; font-size:13px; color:var(--mesh-muted); }
.reach-description summary { cursor:pointer; color:var(--mesh-text); font-weight:500; }
.reach-description p { margin:12px 0 0; line-height:1.7; }
.reach-controls { display:flex; align-items:center; flex-wrap:wrap; gap:10px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; padding:16px; margin-bottom:20px; }
.reach-search { flex:1 1 260px; }
.reach-search-label,.reach-limit-label { color:var(--mesh-muted); font-size:12px; }
.reach-node-link { white-space:nowrap; font-size:12px; }
.reach-summary { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; margin-bottom:20px; }
.reach-metric { background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; padding:20px 24px; font-size:13px; }
.reach-metric-value { font-size:30px; font-weight:650; color:var(--mesh-primary); margin-top:6px; font-variant-numeric:tabular-nums; }
.reach-metric:nth-child(2) .reach-metric-value { color:#198754; }
.reach-table-wrap { overflow-x:auto; border:1px solid var(--mesh-border); border-radius:9px; background:var(--mesh-surface); margin-bottom:20px; }
.reach-table { min-width:520px; }
.reach-map { width:100%; height:450px; border:1px solid var(--mesh-border); border-radius:9px; overflow:hidden; margin-bottom:20px; background:var(--mesh-stripe); }
.reach-map-marker { width:34px; height:34px; border:2px solid white; border-radius:50%; display:flex; align-items:center; justify-content:center; color:white; font-size:10px; font-weight:800; line-height:1; text-shadow:0 1px 2px #000b; box-shadow:0 2px 8px #0003; }
.reach-map-marker-source { font-size:14px; }
.reach-gateway-panels { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:20px; }
.reach-gateway-panel { min-width:0; overflow:auto; border:1px solid var(--mesh-border); border-radius:9px; background:var(--mesh-surface); margin-bottom:20px; }
.reach-gateway-table { min-width:480px; }
.reach-count-bar-cell { min-width:180px; }
.reach-count-bar-track { position:relative; height:24px; border-radius:5px; background:#edf1f7; overflow:hidden; }
.reach-count-bar-value span { background:#fffffff2; border-radius:3px; padding:0 5px; }
.reach-count-bar-fill { height:100%; border-radius:inherit; background:var(--reach-bar-color,#22c55e); }
.reach-count-bar-value { position:absolute; inset:0; display:flex; align-items:center; padding-left:9px; font:600 12px ui-monospace,monospace; color:#17263c; }
.reach-muted { color:var(--mesh-muted); }
.mesh-data-page .mesh-content .reach-heard-link { padding:2px 7px; font-weight:600; }
.reliability-modal { display:none; position:fixed; inset:0; z-index:9999; align-items:center; justify-content:center; padding:16px; background:#17263c99; }
.reliability-modal.open { display:flex; }
.reliability-modal-panel { width:min(900px,100%); max-height:90dvh; overflow:auto; border:1px solid var(--mesh-border); border-radius:10px; background:var(--mesh-surface); padding:20px; box-shadow:0 16px 48px #17263c33; }
.reliability-modal-header { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:18px; }
.reliability-modal-title { font-size:15px; font-weight:600; overflow-wrap:anywhere; }
.reliability-status-heard { color:#187346!important; font-weight:600; }
.reliability-status-missed { color:#b23d2f!important; font-weight:600; }
.reliability-status-skipped { color:var(--mesh-muted)!important; font-weight:600; }
.reliability-row-skipped td { text-decoration:line-through; color:var(--mesh-muted)!important; }
@media(max-width:1000px) { .reach-gateway-panels { grid-template-columns:minmax(0,1fr); gap:0; } }
@media(max-width:600px) { .reach-controls { align-items:stretch; } .reach-search-label { width:100%; } .reach-search { flex-basis:100%; } .reach-summary { gap:10px; } .reach-metric { padding:16px; } .reach-metric-value { font-size:26px; } .reach-map { height:340px; } .reliability-modal-panel { padding:14px; } }
.reach-page {
max-width: 1200px;
margin: 0 auto;
padding: 0 16px;
}
.reach-header {
margin-bottom: 10px;
}
.reach-header h1 {
font-size: 1.35rem;
margin-bottom: 2px;
}
.reach-panel {
border: 1px solid rgba(255, 255, 255, 0.18);
border-radius: 8px;
padding: 12px;
background: rgba(255, 255, 255, 0.04);
}
.reach-controls {
display: flex;
gap: 8px;
margin-top: 8px;
}
.reach-search {
min-width: 0;
flex: 0 1 420px;
}
.reach-search-label,
.reach-limit-label {
align-self: center;
white-space: nowrap;
color: rgba(255, 255, 255, 0.72);
font-size: 0.9rem;
}
.reach-limit-label {
margin-left: auto;
}
.reach-node-link {
align-self: center;
white-space: nowrap;
}
@media (max-width: 600px) {
.reach-controls {
flex-direction: column;
}
}
.reach-summary {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 8px;
margin-top: 10px;
}
.reach-metric {
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 8px;
padding: 8px 10px;
background: rgba(0, 0, 0, 0.18);
}
.reach-metric-value {
font-size: 1.2rem;
line-height: 1.2;
}
.reach-table-wrap {
overflow-x: auto;
margin-top: 10px;
}
.reach-table {
width: 100%;
min-width: 760px;
font-size: 0.9rem;
}
.reach-map {
width: 100%;
height: 520px;
margin-top: 10px;
border: 1px solid rgba(255, 255, 255, 0.14);
border-radius: 8px;
overflow: hidden;
background: rgba(0, 0, 0, 0.18);
}
.reach-map-marker {
width: 34px;
height: 34px;
border: 2px solid #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 0.65rem;
font-weight: 800;
line-height: 1;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.75);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
}
.reach-map-marker-source {
background: #111827;
font-size: 0.95rem;
}
.reach-gateway-panels {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
margin-top: 10px;
}
.reach-gateway-panel {
overflow-x: auto;
}
.reach-gateway-table {
min-width: 0;
}
.reach-table th,
.reach-table td {
vertical-align: top;
padding: 0.35rem 0.5rem;
}
.reach-count-bar-cell {
min-width: 180px;
}
.reach-count-bar-track {
position: relative;
height: 20px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.12);
overflow: hidden;
}
.reach-count-bar-fill {
height: 100%;
min-width: 24px;
border-radius: inherit;
background: var(--reach-bar-color, #4ade80);
}
.reach-count-bar-value {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: flex-start;
padding-left: 8px;
font-family: monospace;
font-size: 0.85rem;
color: #fff;
font-weight: 700;
}
.reach-muted {
color: rgba(255, 255, 255, 0.62);
}
.reach-heard-link {
padding: 0;
border: 0;
background: transparent;
color: #8ab4f8;
text-decoration: underline;
cursor: pointer;
}
.port-tag {
display: inline-block;
padding: 1px 6px;
border-radius: 6px;
font-size: 0.75rem;
font-weight: 500;
color: #fff;
}
.reliability-modal {
display: none;
position: fixed;
inset: 0;
z-index: 5000;
align-items: center;
justify-content: center;
padding: 16px;
background: rgba(0, 0, 0, 0.72);
}
.reliability-modal.open {
display: flex;
}
.reliability-modal-panel {
width: min(760px, 100%);
max-height: min(720px, 92vh);
overflow: auto;
border: 1px solid rgba(255, 255, 255, 0.18);
border-radius: 8px;
background: #111827;
padding: 12px;
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
}
.reliability-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}
.reliability-modal-title {
font-size: 1rem;
font-weight: 600;
}
.reliability-status-heard {
color: #4ade80 !important;
font-weight: 700;
}
.reliability-status-missed {
color: #f87171 !important;
font-weight: 700;
}
.reliability-status-skipped {
color: #cbd5e1 !important;
font-weight: 700;
}
.reliability-row-skipped td {
text-decoration: line-through;
text-decoration-thickness: 1px;
color: rgba(255, 255, 255, 0.58) !important;
}
@media (max-width: 600px) {
.reach-gateway-panels {
grid-template-columns: 1fr;
}
}
</style>
{% endblock %}
{% block body %}
<section class="reach-page">
<header class="data-heading"><div><span class="mesh-eyebrow">GATEWAY DIAGNOSTICS</span><h1>Reliability</h1><p>See how consistently gateways hear packets from a selected node.</p></div><a class="mesh-secondary-button" href="/nodelist">All nodes ↗</a></header>
<details class="reach-description"><summary>How reliability is calculated</summary><p>Review how often each gateway hears packets from a selected node. The report uses the
<main class="reach-page">
<div class="reach-header">
<h1>Reliability</h1>
<p class="text-secondary mb-0">
Review how often each gateway hears packets from a selected node. The report uses the
latest selected packet sample and calculates reliability as heard packets divided by packets
reviewed. The range table groups gateways by reliability bands, while the gateway list
shows each gateway's heard count and percentage for the same sample. Reliability is
calculated only from Text, Position, Node Info, and Telemetry packets; other packet types
are shown in packet details but skipped from the calculation.</p></details>
are shown in packet details but skipped from the calculation.
</p>
</div>
<section class="reach-panel">
<form class="reach-controls" id="reach-search-form">
@@ -94,19 +314,8 @@
</a>
</form>
<div class="reach-summary">
<div class="reach-metric">
<div class="text-secondary">Latest Packets</div>
<div class="reach-metric-value" id="reach-packet-count">...</div>
</div>
<div class="reach-metric">
<div class="text-secondary">Unique Gateways</div>
<div class="reach-metric-value" id="reach-gateway-count">...</div>
</div>
</div>
<div class="reach-table-wrap" role="region" aria-label="Reliability report table" tabindex="0">
<table class="table table-sm reach-table">
<div class="reach-table-wrap">
<table class="table table-dark table-sm table-striped reach-table">
<thead>
<tr>
<th>Reliability Bands</th>
@@ -123,9 +332,20 @@
<div id="reach-gateway-map" class="reach-map"></div>
<div class="reach-summary">
<div class="reach-metric">
<div class="text-secondary">Latest Packets</div>
<div class="reach-metric-value" id="reach-packet-count">...</div>
</div>
<div class="reach-metric">
<div class="text-secondary">Unique Gateways</div>
<div class="reach-metric-value" id="reach-gateway-count">...</div>
</div>
</div>
<div class="reach-gateway-panels">
<div class="reach-gateway-panel" role="region" aria-label="Gateway reliability table" tabindex="0">
<table class="table table-sm reach-table reach-gateway-table">
<div class="reach-gateway-panel">
<table class="table table-dark table-sm table-striped reach-table reach-gateway-table">
<thead>
<tr>
<th>Gateway</th>
@@ -141,8 +361,8 @@
</tbody>
</table>
</div>
<div class="reach-gateway-panel" role="region" aria-label="Gateway reliability table" tabindex="0">
<table class="table table-sm reach-table reach-gateway-table">
<div class="reach-gateway-panel">
<table class="table table-dark table-sm table-striped reach-table reach-gateway-table">
<thead>
<tr>
<th>Gateway</th>
@@ -160,16 +380,16 @@
</div>
</div>
</section>
</section>
</main>
<div class="reliability-modal" id="gateway-packet-modal" role="dialog" aria-modal="true" aria-labelledby="gateway-packet-title">
<div class="reliability-modal-panel">
<div class="reliability-modal-header">
<div class="reliability-modal-title" id="gateway-packet-title">Packet Details</div>
<button class="btn btn-sm btn-outline-secondary" type="button" onclick="closeGatewayPacketModal()">Close</button>
<button class="btn btn-sm btn-outline-light" type="button" onclick="closeGatewayPacketModal()">Close</button>
</div>
<div class="reach-table-wrap" role="region" aria-label="Reliability report table" tabindex="0">
<table class="table table-sm reach-table">
<div class="reach-table-wrap">
<table class="table table-dark table-sm table-striped reach-table">
<thead>
<tr>
<th>Packet</th>
@@ -541,7 +761,7 @@ async function loadReachReport(nodeId = reachNodeId) {
<td class="reach-count-bar-cell">
<div class="reach-count-bar-track">
<div class="reach-count-bar-fill" style="width:${width}%; --reach-bar-color:${row.color};"></div>
<div class="reach-count-bar-value"><span>${row.count}</span></div>
<div class="reach-count-bar-value">${row.count}</div>
</div>
</td>
</tr>
+158 -64
View File
@@ -1,29 +1,100 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-stats-page{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
<style>
.main-container { width:100%; }
.summary-container { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:18px; margin-bottom:24px; }
.summary-card { padding:20px 24px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; min-width:0; }
.summary-card p { color:var(--mesh-muted); font-size:13px; margin:0 0 8px; }
.summary-count { font-size:30px; font-weight:650; color:var(--mesh-primary); font-variant-numeric:tabular-nums; }
.summary-card:nth-child(2) .summary-count { color:#198754; }
.summary-card:nth-child(3) .summary-count { color:#236b4b; }
.summary-card:nth-child(4) .summary-count { color:#497b55; }
.stats-chart-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:20px; }
.card-section { min-width:0; display:flex; align-items:center; align-content:flex-start; flex-wrap:wrap; gap:10px; padding:20px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; }
.section-header { width:100%; font-size:15px; font-weight:600; color:var(--mesh-text); padding-bottom:14px; margin:0 0 2px; border-bottom:1px solid var(--mesh-border); }
.total-count { font-size:12px; color:var(--mesh-muted); margin-right:auto; }
.chart { width:100%; min-width:0; height:340px; margin-top:8px; }
#chartModal { display:none; position:fixed; inset:0; background:#17263c99; z-index:9999; justify-content:center; align-items:center; padding:16px; }
#chartModal > div { position:relative; width:95%; max-width:1200px; height:85%; background:var(--mesh-surface); border-radius:10px; padding:48px 16px 16px; display:flex; flex-direction:column; }
#chartModal #closeModal { position:absolute; top:10px; right:12px; font-size:22px; padding:0; width:32px; height:32px; line-height:1; }
#modalChart { flex:1; min-height:0; width:100%; }
@media(max-width:1000px) { .stats-chart-grid { grid-template-columns:minmax(0,1fr); } }
@media(max-width:700px) { .summary-container { grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; } .summary-card { padding:16px; } .summary-count { font-size:26px; } .card-section { padding:14px; gap:8px; } .chart { height:320px; } }
#packet_details {
height: 95vh;
overflow: auto;
}
.main-container, .container {
max-width: 900px;
margin: 0 auto;
text-align: center;
}
.card-section {
background-color: #272b2f;
border: 1px solid #474b4e;
padding: 15px 20px;
margin-bottom: 20px;
border-radius: 10px;
transition: background-color 0.2s ease;
}
.card-section:hover {
background-color: #2f3338;
}
.section-header {
font-size: 16px;
margin: 0 0 6px 0;
font-weight: 500;
color: #fff;
}
.main-header {
font-size: 22px;
margin-bottom: 20px;
font-weight: 600;
}
.chart {
height: 400px;
margin-top: 10px;
}
.total-count {
color: #ccc;
font-size: 14px;
margin-bottom: 8px;
}
.expand-btn, .export-btn {
margin-bottom: 8px;
padding: 4px 8px;
cursor: pointer;
background-color: #444;
color: #fff;
border: none;
border-radius: 4px;
font-size: 12px;
}
.expand-btn:hover { background-color: #666; }
.export-btn:hover { background-color: #777; }
/* Summary cards at top */
.summary-card {
background-color: #1f2124;
border: 1px solid #474b4e;
padding: 10px 15px;
margin-bottom: 15px;
border-radius: 8px;
}
.summary-count {
font-size: 18px;
color: #66bb6a;
font-weight: bold;
}
#channelSelect {
margin-bottom: 8px;
padding: 4px 6px;
background:#444;
color:#fff;
border:none;
border-radius:4px;
}
.chart-filter {
margin-bottom: 8px;
padding: 4px 6px;
background: #444;
color: #fff;
border: none;
border-radius: 4px;
}
</style>
{% endblock %}
@@ -34,29 +105,30 @@
{% block body %}
<div class="main-container">
<header class="data-heading"><div><span class="mesh-eyebrow">NETWORK ANALYTICS</span><h1>Mesh statistics</h1><p>Explore packet history, device activity, and gateway distribution.</p></div><a class="mesh-secondary-button" href="/top">Top nodes ↗</a></header>
<h2 class="main-header" data-translate-lang="mesh_stats_summary">
Mesh Statistics - Summary (all available in Database)
</h2>
<!-- Summary cards now fully driven by API + JS -->
<div class="summary-container">
<div class="summary-card">
<div class="summary-container" style="display:flex; justify-content:space-between; gap:10px; margin-bottom:20px;">
<div class="summary-card" style="flex:1;">
<p data-translate-lang="total_nodes">Total Nodes</p>
<div class="summary-count" id="summary_nodes">0</div>
</div>
<div class="summary-card">
<div class="summary-card" style="flex:1;">
<p data-translate-lang="total_packets">Total Packets</p>
<div class="summary-count" id="summary_packets">0</div>
</div>
<div class="summary-card">
<div class="summary-card" style="flex:1;">
<p data-translate-lang="total_packets_seen">Total Packets Seen</p>
<div class="summary-count" id="summary_seen">0</div>
</div>
<div class="summary-card">
<div class="summary-card" style="flex:1;">
<p data-translate-lang="total_gateways">Total Gateways</p>
<div class="summary-count" id="summary_gateways">0</div>
</div>
</div>
<div class="stats-chart-grid">
<div class="card-section">
<p class="section-header" data-translate-lang="daily_snapshot_packets_history">
Daily Packet Snapshot History
@@ -96,7 +168,7 @@
<p class="section-header" data-translate-lang="packet_types_last_24h">
Packet Types - Last 24 Hours
</p>
<select id="channelSelect" aria-label="Packet type channel">
<select id="channelSelect">
<option value="" data-translate-lang="all_channels">All Channels</option>
</select>
<button class="expand-btn" data-chart="chart_packet_types" data-translate-lang="expand_chart">Expand Chart</button>
@@ -179,13 +251,17 @@
<div id="chart_gateway_firmware" class="chart"></div>
</div>
</div>
</div>
<!-- Modal for expanded charts -->
<div id="chartModal" role="dialog" aria-modal="true" aria-label="Expanded chart">
<div>
<button id="closeModal" type="button" aria-label="Close expanded chart">&times;</button>
<div id="modalChart"></div>
<div id="chartModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%;
background:rgba(0,0,0,0.7); z-index:1000; justify-content:center; align-items:center;">
<div style="position:relative; width:80%; max-width:1000px; height:80%;
background:#272b2f; border-radius:10px; padding:10px; display:flex; flex-direction:column;">
<button id="closeModal" style="position:absolute; top:10px; right:10px; z-index:1010;
background:#ff4c4c; border:none; color:white; font-size:24px; width:36px; height:36px;
border-radius:50%; cursor:pointer;">&times;</button>
<div id="modalChart" style="flex:1; width:100%; height:100%;"></div>
</div>
</div>
@@ -292,23 +368,23 @@ function filterSnapshotsByRange(data, rangeValue){
function renderChart(domId,data,type,color){
const el=document.getElementById(domId);
if(!el) return;
const chart=initMeshChart(el);
const chart=echarts.init(el);
const periods=data.map(d=>(d.period??d.period===0)?d.period.toString():'');
const counts=data.map(d=>d.count??d.packet_count??0);
chart.setOption({
backgroundColor:'#ffffff',
backgroundColor:'#272b2f',
tooltip:{trigger:'axis'},
grid:{left:'6%', right:'6%', bottom:'18%'},
xAxis:{
type:'category',
data:periods,
axisLine:{lineStyle:{color:'#c3cfdf'}},
axisLabel:{rotate:45,color:'#64748b'}
axisLine:{lineStyle:{color:'#aaa'}},
axisLabel:{rotate:45,color:'#ccc'}
},
yAxis:{
type:'value',
axisLine:{lineStyle:{color:'#c3cfdf'}},
axisLabel:{color:'#64748b'}
axisLine:{lineStyle:{color:'#aaa'}},
axisLabel:{color:'#ccc'}
},
series:[{
data:counts,
@@ -324,10 +400,10 @@ function renderChart(domId,data,type,color){
function renderPieChart(elId,data,name){
const el=document.getElementById(elId);
if(!el) return;
const chart=initMeshChart(el);
const chart=echarts.init(el);
const top20=prepareTopN(data,20);
chart.setOption({
backgroundColor:"#ffffff",
backgroundColor:"#272b2f",
tooltip:{
trigger:"item",
formatter: params=>`${params.name}: ${Math.round(params.percent)}% (${params.value})`
@@ -340,13 +416,13 @@ function renderPieChart(elId,data,name){
avoidLabelOverlap:true,
itemStyle:{
borderRadius:6,
borderColor:"#ffffff",
borderColor:"#272b2f",
borderWidth:2
},
label:{
show:true,
formatter:"{b}\n{d}%",
color:"#64748b",
color:"#ccc",
fontSize:10
},
labelLine:{
@@ -395,28 +471,28 @@ function makeTelemetryLine(name, color, seriesData) {
function renderDailySnapshotPacketsChart(domId,data){
const el=document.getElementById(domId);
if(!el) return;
const chart=echarts.getInstanceByDom(el) || initMeshChart(el);
const chart=echarts.getInstanceByDom(el) || echarts.init(el);
const labels=data.map(d=>d.date||"");
const packetCounts=data.map(d=>d.packet_count??0);
chart.setOption({
backgroundColor:'#ffffff',
backgroundColor:'#272b2f',
tooltip:{trigger:'axis'},
legend:{
data:['Packets'],
textStyle:{color:'#64748b'}
textStyle:{color:'#ccc'}
},
grid:{left:'6%', right:'6%', bottom:'18%'},
xAxis:{
type:'category',
data:labels,
axisLine:{lineStyle:{color:'#c3cfdf'}},
axisLabel:{rotate:45,color:'#64748b'}
axisLine:{lineStyle:{color:'#aaa'}},
axisLabel:{rotate:45,color:'#ccc'}
},
yAxis:{
type:'value',
axisLine:{lineStyle:{color:'#c3cfdf'}},
axisLabel:{color:'#64748b'}
axisLine:{lineStyle:{color:'#aaa'}},
axisLabel:{color:'#ccc'}
},
series:[
makeTelemetryLine("Packets", "rgba(255,214,82,1)", packetCounts)
@@ -428,29 +504,29 @@ function renderDailySnapshotPacketsChart(domId,data){
function renderDailySnapshotNodesGatewaysChart(domId,data){
const el=document.getElementById(domId);
if(!el) return;
const chart=echarts.getInstanceByDom(el) || initMeshChart(el);
const chart=echarts.getInstanceByDom(el) || echarts.init(el);
const labels=data.map(d=>d.date||"");
const nodeCounts=data.map(d=>d.node_count??0);
const gatewayCounts=data.map(d=>d.gateway_count??0);
chart.setOption({
backgroundColor:'#ffffff',
backgroundColor:'#272b2f',
tooltip:{trigger:'axis'},
legend:{
data:['Nodes','Gateways'],
textStyle:{color:'#64748b'}
textStyle:{color:'#ccc'}
},
grid:{left:'6%', right:'6%', bottom:'18%'},
xAxis:{
type:'category',
data:labels,
axisLine:{lineStyle:{color:'#c3cfdf'}},
axisLabel:{rotate:45,color:'#64748b'}
axisLine:{lineStyle:{color:'#aaa'}},
axisLabel:{rotate:45,color:'#ccc'}
},
yAxis:{
type:'value',
axisLine:{lineStyle:{color:'#c3cfdf'}},
axisLabel:{color:'#64748b'}
axisLine:{lineStyle:{color:'#aaa'}},
axisLabel:{color:'#ccc'}
},
series:[
makeTelemetryLine("Nodes", "rgba(79,155,255,1)", nodeCounts),
@@ -526,11 +602,11 @@ async function init(){
// Hourly all ports
const hourlyAllData=await fetchStats('hour',24);
updateTotalCount('total_hourly_all',hourlyAllData);
chartHourlyAll=renderChart('chart_hourly_all',hourlyAllData,'bar','#168e84');
chartHourlyAll=renderChart('chart_hourly_all',hourlyAllData,'bar','#03dac6');
// Hourly per port
const portnums=[1,3,4,67,70,71];
const colors=['#ff5722','#2196f3','#9c27b0','#b88a15','#795548','#4caf50'];
const colors=['#ff5722','#2196f3','#9c27b0','#ffeb3b','#795548','#4caf50'];
const domIds=['chart_portnum_1','chart_portnum_3','chart_portnum_4','chart_portnum_67','chart_portnum_70','chart_portnum_71'];
const totalIds=['total_portnum_1','total_portnum_3','total_portnum_4','total_portnum_67','total_portnum_70','total_portnum_71'];
@@ -606,8 +682,26 @@ async function init(){
}
window.addEventListener('resize',()=>{
document.querySelectorAll('.chart').forEach(el => echarts.getInstanceByDom(el)?.resize());
modalChart?.resize();
[
chartHourlyAll,
chartPortnum1,
chartPortnum3,
chartPortnum4,
chartPortnum67,
chartPortnum70,
chartPortnum71,
chartDailySnapshotPackets,
chartDailySnapshotNodesGateways,
chartDailyAll,
chartDailyPortnum1,
chartHwModel,
chartRole,
chartChannel,
chartGatewayChannel,
chartGatewayRole,
chartGatewayFirmware,
chartPacketTypes
].forEach(c=>c?.resize());
});
const modal=document.getElementById("chartModal");
@@ -620,7 +714,7 @@ document.querySelectorAll(".expand-btn").forEach(btn=>{
const sourceChart=echarts.getInstanceByDom(document.getElementById(chartId));
if(!sourceChart)return;
modal.style.display="flex";
modalChart=initMeshChart(modalChartEl);
modalChart=echarts.init(modalChartEl);
modalChart.setOption(sourceChart.getOption());
});
});
-70
View File
@@ -1,70 +0,0 @@
<style>
:root {
color-scheme:light;
--mesh-primary:#187346;
--mesh-primary-dark:#0f5132;
--mesh-primary-rgb:24,115,70;
--mesh-brand:#187346;
--mesh-brand-deep:#0f5132;
--mesh-surface:#ffffff;
--mesh-text:#243247;
--mesh-soft:#eaf5ee;
--mesh-hover:#dceee2;
--mesh-border:#dce7df;
--mesh-page:#f5f9f6;
--mesh-stripe:#f7faf8;
--mesh-muted:#64748b;
--mesh-chat-stripe:#eef6f0;
--mesh-pulse-soft:#edf8f0;
--mesh-pulse-peak:#ccebd7;
--mesh-pulse-mid:#e2f3e8;
}
[data-bs-theme="dark"] {
color-scheme:dark;
--mesh-primary:#80cfa3;
--mesh-primary-dark:#a3e3be;
--mesh-primary-rgb:128,207,163;
--mesh-brand:#14532d;
--mesh-brand-deep:#0c3a1f;
--mesh-surface:#18231e;
--mesh-text:#e2ece5;
--mesh-soft:#203c2b;
--mesh-hover:#294c36;
--mesh-border:#34483c;
--mesh-page:#101914;
--mesh-stripe:#1c2a22;
--mesh-muted:#9faea6;
--mesh-chat-stripe:#203227;
--mesh-pulse-soft:#203c2b;
--mesh-pulse-peak:#356b49;
--mesh-pulse-mid:#294c36;
--bs-link-color:var(--mesh-primary);
--bs-link-color-rgb:var(--mesh-primary-rgb);
--bs-link-hover-color:var(--mesh-primary-dark);
--bs-link-hover-color-rgb:163,227,190;
}
body { background:var(--mesh-page); color:var(--mesh-text); }
.mesh-theme-toggle { flex-shrink:0; display:inline-flex; align-items:center; justify-content:center; width:34px; height:34px; border:1px solid #ffffff70; border-radius:6px; background:transparent; color:white; font:22px/1 system-ui,sans-serif; cursor:pointer; }
.mesh-header .mesh-theme-toggle { margin-left:auto; }
.mesh-theme-toggle:hover { background:#ffffff20; }
.mesh-theme-toggle:focus-visible { outline:2px solid white; outline-offset:3px; }
@media(max-width:1000px) { .mesh-header .mesh-menu-toggle { margin-left:auto; } .mesh-header .mesh-theme-toggle { margin-left:12px; } .mesh-header #site-menu { order:4; } }
[data-bs-theme="dark"] :is(.chat-status,.chat-details,.chat-channel,.chat-status[data-state="paused"],.chat-status[data-state="loading"],.good-x) { background:var(--mesh-soft); color:var(--mesh-primary); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.chat-status[data-state="error"],.bad-x) { background:#472a24; color:#ffb4a6; }
[data-bs-theme="dark"] .ok-x { background:#453820; color:#f1d38a; }
[data-bs-theme="dark"] .chat-details:hover { background:var(--mesh-hover); color:var(--mesh-primary-dark); }
[data-bs-theme="dark"] .chat-nick { filter:brightness(1.4) saturate(.8); }
[data-bs-theme="dark"] :is(.summary-card:nth-child(2) .summary-count,.summary-card:nth-child(3) .summary-count,.summary-card:nth-child(4) .summary-count,.mesh-metric:nth-child(2) strong,.mesh-metric:nth-child(3) strong,.reach-metric:nth-child(2) .reach-metric-value) { color:var(--mesh-primary); }
[data-bs-theme="dark"] :is(.reliability-status-heard) { color:#8fd7aa!important; }
[data-bs-theme="dark"] .reliability-status-missed { color:#ffb4a6!important; }
[data-bs-theme="dark"] .reach-count-bar-value span { color:#17263c; }
[data-bs-theme="dark"] .leaflet-tile-pane { filter:invert(1) hue-rotate(180deg) brightness(.85) saturate(.75); }
[data-bs-theme="dark"] :is(.leaflet-container,.leaflet-control-layers,.leaflet-bar a,.leaflet-popup-content-wrapper,.leaflet-popup-tip,.leaflet-tooltip,.leaflet-control-attribution,.leaflet-control-scale-line,#unmapped-packets,#legend,#node-info,.legend) { background:var(--mesh-surface); color:var(--mesh-text); border-color:var(--mesh-border); }
[data-bs-theme="dark"] :is(.leaflet-control-layers label,.leaflet-popup-close-button,#unmapped-packets h3,.unmapped-node,.blinking-tooltip,.legend) { color:var(--mesh-text); }
[data-bs-theme="dark"] :is(.leaflet-bar a:hover,.leaflet-control-layers-expanded) { background:var(--mesh-stripe); }
[data-bs-theme="dark"] :is(.unmapped-empty,.reach-muted) { color:var(--mesh-muted); }
[data-bs-theme="dark"] :is(.source-marker,.reach-map-marker) { color:white; }
[data-bs-theme="dark"] .qr-image { background:white; }
[data-bs-theme="dark"] :is(#traceroute-error,#map-load-status,.text-danger) { color:#ffb4a6; }
[data-bs-theme="dark"] .reach-count-bar-track { background:var(--mesh-soft); }
</style>
+63 -35
View File
@@ -1,49 +1,87 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-top-page{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
<style>
.top-container { width:100%; }
.filter-bar { display:flex; align-items:center; flex-wrap:wrap; gap:12px; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; padding:16px; margin-bottom:18px; }
.filter-bar > div { display:flex; align-items:center; flex-wrap:wrap; gap:10px; }
.filter-bar label { color:var(--mesh-muted); font-size:13px; }
#channelFilter { width:200px; }
.top-count { color:var(--mesh-muted); font-size:13px; margin-bottom:14px; }
#node-count { font-weight:650; color:var(--mesh-primary); }
#nodesTable tbody tr { cursor:pointer; }
#nodesTable td:nth-child(n+4) { font-variant-numeric:tabular-nums; }
.good-x,.ok-x,.bad-x { display:inline-block; padding:3px 8px; border-radius:5px; font-weight:600; font-size:12px; }
.good-x { background:#e8f5ee; color:#187346; }
.ok-x { background:#fff4d9; color:#8a6200; }
.bad-x { background:#fff0ed; color:#b23d2f; }
.pagination { display:flex; align-items:center; justify-content:center; gap:16px; margin:20px 0 0; }
#pageInfo { font-size:12px; color:var(--mesh-muted); }
@media(max-width:700px) { #channelFilter { width:180px; } }
body { background-color: #121212; color: #ddd; }
h1 { text-align: center; margin-top: 20px; color: #fff; }
.top-container {
max-width: 1100px;
margin: 25px auto;
padding: 0 15px;
}
.filter-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 20px;
margin-bottom: 15px;
}
.filter-bar select {
background-color: #1f2327;
border: 1px solid #444;
color: #ddd;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
table th, table td {
padding: 12px;
border: 1px solid #444;
text-align: left;
color: #ddd;
}
table th { background-color: #333; }
table tbody tr:nth-child(odd) { background-color: #272b2f; }
table tbody tr:nth-child(even) { background-color: #212529; }
table tbody tr:hover { background-color: #555; cursor: pointer; }
.node-link {
color: #9fd4ff;
text-decoration: none;
}
.node-link:hover { text-decoration: underline; }
.good-x { color: #81ff81; font-weight: bold; }
.ok-x { color: #e8e86d; font-weight: bold; }
.bad-x { color: #ff6464; font-weight: bold; }
.pagination {
display: flex;
justify-content: center;
gap: 12px;
margin-top: 15px;
}
</style>
{% endblock %}
{% block body %}
<header class="data-heading"><div><span class="mesh-eyebrow">TRAFFIC LEADERBOARD</span><h1 data-translate-lang="top_traffic_nodes">Top nodes</h1><p>Compare packets sent and gateway observations over the last 24 hours.</p></div><a class="mesh-secondary-button" href="/stats">View statistics ↗</a></header>
<h1 data-translate-lang="top_traffic_nodes">Top Nodes Traffic</h1>
<div class="top-container">
<div class="filter-bar">
<div>
<label for="channelFilter" data-translate-lang="channel">Channel:</label>
<label data-translate-lang="channel">Channel:</label>
<select id="channelFilter"></select>
</div>
</div>
<div class="top-count">
<div style="margin-bottom:10px;font-weight:bold;">
<span data-translate-lang="showing_nodes">Showing</span>
<span id="node-count">0</span>
<span data-translate-lang="nodes_suffix">nodes</span>
</div>
<div class="data-table-wrap" role="region" aria-label="Top nodes traffic table" tabindex="0">
<table id="nodesTable">
<thead>
<tr>
@@ -57,11 +95,10 @@
</thead>
<tbody></tbody>
</table>
</div>
<div class="pagination" aria-label="Leaderboard pagination">
<div class="pagination">
<button id="prevPage" class="btn btn-sm btn-secondary">Prev</button>
<span id="pageInfo" role="status"></span>
<span id="pageInfo"></span>
<button id="nextPage" class="btn btn-sm btn-secondary">Next</button>
</div>
@@ -148,15 +185,6 @@ async function renderTable() {
const data = await res.json();
totalRows = data.total || 0;
if (!(data.nodes || []).length) {
const row = document.createElement("tr");
const cell = document.createElement("td");
cell.colSpan = 6;
cell.className = "data-empty";
cell.textContent = "No node traffic found for this channel.";
row.append(cell);
tbody.append(row);
}
for (const n of data.nodes || []) {
const tr = document.createElement("tr");
+62 -28
View File
@@ -1,35 +1,75 @@
{% extends "base.html" %}
{% block theme %}light{% endblock %}
{% block body_class %}mesh-data-page mesh-traceroute-page{% endblock %}
{% block head %}
<script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
{% endblock %}
{% block css %}
{% include "data-page-styles.html" %}
<style>
#traceroute-graph-wrap { position:relative; background:var(--mesh-surface); border:1px solid var(--mesh-border); border-radius:9px; overflow:hidden; }
#traceroute-graph { width:100%; height:clamp(460px,calc(100dvh - 280px),900px); }
#traceroute-legend { position:absolute; right:16px; bottom:16px; z-index:2; display:grid; gap:9px; padding:14px 16px; color:var(--mesh-muted); background:#fffffff2; border:1px solid var(--mesh-border); border-radius:7px; font-size:12px; box-shadow:0 2px 8px #17263c08; pointer-events:none; }
.traceroute-legend-row { display:grid; grid-template-columns:34px auto; align-items:center; gap:10px; }
.traceroute-legend-line { height:0; border-top:3px solid var(--line-color); }
.traceroute-legend-line.muted { border-top-width:2px; opacity:.55; }
.traceroute-legend-line.dashed { border-top-style:dashed; }
#traceroute-meta { display:flex; align-items:center; flex-wrap:wrap; gap:12px; padding:14px 18px; border:1px solid var(--mesh-border); border-radius:9px; background:var(--mesh-surface); margin-bottom:18px; color:var(--mesh-muted); font-size:13px; }
#traceroute-title { color:var(--mesh-primary); font-weight:600; }
#traceroute-error { color:#b23d2f; }
.traceroute-help { margin-left:auto; font-size:12px; }
@media(max-width:700px) { #traceroute-graph { height:500px; } #traceroute-legend { left:12px; right:auto; bottom:12px; font-size:11px; padding:12px; } .traceroute-help { width:100%; margin:0; } }
#traceroute-graph {
width: 100%;
height: calc(100vh - 270px);
border: 1px solid #2a2f36;
background: linear-gradient(135deg, #0f1216 0%, #171b22 100%);
border-radius: 10px;
}
#traceroute-graph-wrap {
position: relative;
}
#traceroute-legend {
position: absolute;
right: 16px;
bottom: 16px;
z-index: 2;
display: grid;
gap: 8px;
padding: 10px 12px;
color: #d6dde6;
background: rgba(15, 18, 22, 0.88);
border: 1px solid #303743;
border-radius: 8px;
font-size: 13px;
}
.traceroute-legend-row {
display: grid;
grid-template-columns: 34px auto;
align-items: center;
gap: 8px;
white-space: nowrap;
}
.traceroute-legend-line {
height: 0;
border-top: 3px solid var(--line-color);
}
.traceroute-legend-line.muted {
border-top-width: 2px;
opacity: 0.55;
}
.traceroute-legend-line.dashed {
border-top-style: dashed;
}
#traceroute-meta {
padding: 12px 16px;
color: #c8d0da;
}
#traceroute-error {
color: #ff6b6b;
}
</style>
{% endblock %}
{% block body %}
<header class="data-heading"><div><span class="mesh-eyebrow">ROUTE EXPLORER</span><h1>Traceroute</h1><p>Explore forward paths, reported return routes, and the nodes along the way.</p></div><a class="mesh-secondary-button" href="/firehose">Live packets ↗</a></header>
<div id="traceroute-meta">
<div><b>Traceroute</b> <span id="traceroute-title"></span></div>
<div id="traceroute-error" role="status"></div>
<span class="traceroute-help">Drag nodes to rearrange · Scroll to zoom</span>
<div id="traceroute-error"></div>
</div>
<div id="traceroute-graph-wrap">
<div id="traceroute-graph"></div>
@@ -51,7 +91,7 @@
<script>
const el = document.getElementById("traceroute-graph");
const chart = initMeshChart(el);
const chart = echarts.init(el);
function packetIdFromPath() {
const parts = window.location.pathname.split("/").filter(Boolean);
@@ -184,10 +224,7 @@ async function loadTraceroute() {
itemStyle: { color },
label: {
show: true,
color: "#334155",
position: "bottom",
textBorderColor: "#ffffff",
textBorderWidth: 3,
color: "#e7eef7",
fontWeight: "bold"
},
tooltip: {
@@ -201,7 +238,7 @@ async function loadTraceroute() {
const option = {
backgroundColor: "transparent",
tooltip: { trigger: "item", renderMode: "richText" },
tooltip: { trigger: "item" },
series: [
{
type: "graph",
@@ -222,10 +259,7 @@ async function loadTraceroute() {
chart.setOption(option);
}
loadTraceroute().catch(error => {
console.error("Failed to load traceroute:", error);
document.getElementById("traceroute-error").textContent = "Unable to load traceroute. Reload to try again.";
});
loadTraceroute();
window.addEventListener("resize", () => chart.resize());
</script>
{% endblock %}
+8 -12
View File
@@ -214,14 +214,14 @@ routes = web.RouteTableDef()
@routes.get("/")
@routes.get("/index")
@routes.get("/index.html")
async def index(request):
"""Render the network dashboard as the home page."""
return web.Response(
text=env.get_template("index.html").render(),
content_type="text/html",
)
"""
Redirect root URL '/' to the page specified in CONFIG['site']['starting'].
Defaults to '/map' if not set.
"""
# Get the starting page from config
starting_url = CONFIG["site"].get("starting", "/map") # default to /map if not set
raise web.HTTPFound(location=starting_url)
# redirect for backwards compatibility
@@ -232,6 +232,7 @@ async def redirect_packet_list(request):
# Generic static HTML route
@routes.get("/{page}")
async def serve_page(request):
"""Serve static HTML pages from meshview/static."""
page = request.match_info["page"]
@@ -274,7 +275,6 @@ async def net(request):
@routes.get("/map")
@routes.get("/map.html")
async def map(request):
template = env.get_template("map.html")
return web.Response(text=template.render(), content_type="text/html")
@@ -481,10 +481,6 @@ async def graph_traceroute(request):
)
# Register the static-page fallback after named pages so it cannot shadow them.
routes.get("/{page}")(serve_page)
async def run_server():
"""Start the aiohttp web server after migrations are complete."""
# Wait for database migrations to complete before starting web server
+1 -1
View File
@@ -730,6 +730,7 @@ async def api_config(request):
"language": get_str(site, "language", "en"),
"title": get_str(site, "title", ""),
"message": get_str(site, "message", ""),
"starting": get_str(site, "starting", "/chat"),
"nodes": get_bool(site, "nodes", True),
"chat": get_bool(site, "chat", True),
"everything": get_bool(site, "everything", True),
@@ -738,7 +739,6 @@ async def api_config(request):
"net": get_bool(site, "net", True),
"map": get_bool(site, "map", True),
"top": get_bool(site, "top", True),
"api": get_bool(site, "api", True),
"map_top_left_lat": get_float(site, "map_top_left_lat", 39.0),
"map_top_left_lon": get_float(site, "map_top_left_lon", -123.0),
"map_bottom_right_lat": get_float(site, "map_bottom_right_lat", 36.0),
+3 -2
View File
@@ -31,6 +31,9 @@ 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
@@ -40,8 +43,6 @@ stats = True
net = True
map = True
top = True
# Show the API documentation link in the navigation bar (default: True).
api = True
# Map boundaries (used for the map view).
map_top_left_lat = 39
-135
View File
@@ -1,135 +0,0 @@
// Build the static API reference from the canonical Markdown, without runtime dependencies.
// Supports the headings, paragraphs, lists, links, rules, and fenced code used by this reference.
import { readFileSync, writeFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
const source = new URL('../docs/API_Documentation.md', import.meta.url);
const output = new URL('../meshview/static/api.html', import.meta.url);
const markdown = readFileSync(source, 'utf8');
const themeStyles = readFileSync(new URL('../meshview/templates/theme-styles.html', import.meta.url), 'utf8');
const escape = text => text.replace(/[&<>"']/g, char => ({
'&':'&amp;', '<':'&lt;', '>':'&gt;', '"':'&quot;', "'":'&#39;'
}[char]));
const slug = text => text.toLowerCase().replace(/`/g, '').replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
function inline(text) {
const tokens = /`([^`]+)`|\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*/g;
let html = '', cursor = 0;
for (const match of text.matchAll(tokens)) {
html += escape(text.slice(cursor, match.index));
if (match[1] !== undefined) html += `<code>${escape(match[1])}</code>`;
else if (match[2] !== undefined && /^(#|\/|https?:\/\/)/.test(match[3])) {
html += `<a href="${escape(match[3])}">${escape(match[2])}</a>`;
} else if (match[4] !== undefined) html += `<strong>${escape(match[4])}</strong>`;
else html += escape(match[0]);
cursor = match.index + match[0].length;
}
return html + escape(text.slice(cursor));
}
const endpoints = [];
const blocks = [];
const lines = markdown.split('\n');
let sectionOpen = false;
for (let i = 0; i < lines.length;) {
const line = lines[i];
if (!line.trim()) { i++; continue; }
if (line.startsWith('```')) {
const language = line.slice(3).trim(); const code = []; i++;
while (i < lines.length && !lines[i].startsWith('```')) code.push(lines[i++]);
if (i === lines.length) throw new Error('Unclosed code fence');
if (language === 'json') JSON.parse(code.join('\n'));
blocks.push(`<pre><code class="language-${escape(language)}">${escape(code.join('\n'))}</code></pre>`);
i++; continue;
}
const heading = line.match(/^(#{1,3})\s+(.+)$/);
if (heading) {
if (sectionOpen) { blocks.push('</section>'); sectionOpen = false; }
const level = heading[1].length; const text = heading[2];
if (level === 3 && text.startsWith('GET ')) {
const id = slug(text); endpoints.push({text:text.replace(/`/g, ''),id});
blocks.push(`<section class="endpoint" id="${id}"><h3><span class="method">GET</span> ${inline(text.slice(4))}</h3>`);
sectionOpen = true;
} else blocks.push(`<h${level} id="${slug(text)}">${inline(text)}</h${level}>`);
i++; continue;
}
if (/^---+$/.test(line)) { blocks.push('<hr>'); i++; continue; }
if (/^- /.test(line)) {
const items = [];
while (i < lines.length && /^- /.test(lines[i])) {
let item = lines[i++].slice(2);
while (i < lines.length && /^\s+\S/.test(lines[i])) item += ` ${lines[i++].trim()}`;
items.push(`<li>${inline(item)}</li>`);
}
blocks.push(`<ul>${items.join('')}</ul>`); continue;
}
const paragraph = [line]; i++;
while (i < lines.length && lines[i].trim() && !/^(#{1,3} |```|- |---+$)/.test(lines[i])) paragraph.push(lines[i++]);
blocks.push(`<p>${inline(paragraph.join(' '))}</p>`);
}
if (sectionOpen) blocks.push('</section>');
const index = endpoints.map(({text,id}) => `<li><a href="#${id}">${escape(text)}</a></li>`).join('');
writeFileSync(output, `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Meshview API Reference</title>
<script src="/static/theme.js"></script>
<link rel="icon" type="image/svg+xml" href="/static/meshview-icon.svg">
<style>
:root { color-scheme:light; --primary:var(--mesh-primary); --border:var(--mesh-border); }
* { box-sizing:border-box; }
html { scroll-padding-top:80px; }
body { margin:0; background:var(--mesh-page); color:var(--mesh-text); font:14px/1.7 system-ui,-apple-system,"Segoe UI",sans-serif; }
a { color:var(--primary); }
a:hover { color:var(--mesh-primary-dark); }
header { background:var(--mesh-brand); color:white; position:sticky; top:0; z-index:2; box-shadow:0 2px 8px #174b2d18; }
.header-inner { max-width:1180px; margin:auto; min-height:56px; display:flex; align-items:center; gap:12px; padding:8px 24px; }
header img { width:32px; height:32px; }
header a { color:white; text-decoration:none; }
header a:hover { color:white; text-decoration:underline; }
.brand { font-size:18px; font-weight:700; display:flex; align-items:center; gap:10px; }
.home-link { margin-left:auto; font-size:13px; }
main { max-width:1180px; margin:auto; padding:28px 24px 60px; min-width:0; }
h1 { font-size:28px; margin:0 0 16px; } h2 { font-size:21px; margin:32px 0 14px; } h3 { font-size:17px; margin:0 0 16px; }
p,li { overflow-wrap:anywhere; }
code { font:12px/1.7 ui-monospace,Consolas,monospace; color:var(--mesh-primary); background:var(--mesh-soft); border-radius:4px; padding:2px 5px; overflow-wrap:anywhere; }
pre { background:var(--mesh-stripe); border:1px solid var(--border); border-radius:7px; padding:16px; overflow:auto; }
pre code { background:none; padding:0; white-space:pre; color:var(--mesh-text); }
h3 code { font-size:15px; }
.endpoint { background:var(--mesh-surface); border:1px solid var(--border); border-radius:9px; padding:24px; margin-bottom:22px; scroll-margin-top:12px; min-width:0; }
.method { display:inline-block; background:var(--mesh-brand); color:white; font-size:11px; padding:3px 8px; border-radius:5px; margin-right:5px; }
hr { border:0; border-top:1px solid var(--border); margin:24px 0; }
.api-index { background:var(--mesh-surface); border:1px solid var(--border); border-radius:9px; padding:16px 20px; margin-bottom:24px; }
.api-index summary { color:var(--primary); font-weight:600; cursor:pointer; }
.api-index ul { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px 24px; padding-left:20px; }
.api-index a { font:12px ui-monospace,monospace; }
:focus-visible { outline:2px solid var(--primary); outline-offset:3px; }
footer { border-top:1px solid var(--border); padding:20px 24px; text-align:center; color:var(--mesh-muted); font-size:12px; }
@media(max-width:700px) { main { padding:20px 14px 40px; } .header-inner { padding:8px 14px; } h1 { font-size:24px; } h2 { font-size:19px; } h3 code { font-size:12px; } .endpoint { padding:16px; } .api-index ul { grid-template-columns:minmax(0,1fr); } }
</style>
${themeStyles}
</head>
<body>
<header><div class="header-inner"><a class="brand" href="/"><img src="/static/meshview-icon.svg" alt="" width="32" height="32">Meshview</a><span>API reference</span><a class="home-link" href="/">Home ↗</a><button class="mesh-theme-toggle" type="button" data-theme-toggle aria-label="Switch to night mode" aria-pressed="false">☾</button></div></header>
<main>
<details class="api-index"><summary>Browse all ${endpoints.length} endpoints</summary><nav aria-label="API endpoints"><ul>${index}</ul></nav></details>
${blocks.join('\n')}
</main>
<footer>Source: docs/API_Documentation.md · Generated with node scripts/build-api-docs.mjs</footer>
</body>
</html>
`);
console.log(`Built ${endpoints.length} endpoint sections: ${fileURLToPath(output)}`);
// The legacy chat reference and standalone maps use the same saved preference.
for (const filename of ['api-chat.html','kiosk.html','heatmap.html']) {
const path = new URL('../meshview/static/' + filename, import.meta.url);
let html = readFileSync(path,'utf8');
const themeBlock = '<!-- mesh-theme:start -->\n' + themeStyles + '\n<!-- mesh-theme:end -->';
if (!html.includes('/static/theme.js')) html = html.replace('<style>','<script src="/static/theme.js"></script>\n<style>');
if (html.includes('<!-- mesh-theme:start -->')) html = html.replace(/<!-- mesh-theme:start -->[\s\S]*?<!-- mesh-theme:end -->/,themeBlock);
else html = html.replace('</head>',themeBlock + '\n</head>');
if (!html.includes('data-theme-toggle')) html = html.replace('<body>','<body>\n<button class="mesh-theme-toggle" style="position:fixed;top:12px;right:12px;z-index:2000;background:#187346" type="button" data-theme-toggle aria-label="Switch to night mode" aria-pressed="false">☾</button>');
writeFileSync(path,html);
}
-2
View File
@@ -36,8 +36,6 @@ def stage_meshtastic_package(proto_root, tmp_path):
text = text.replace('import "meshtastic/', 'import "meshtastic/protobuf/')
text = text.replace('import "nanopb.proto"', 'import "meshtastic/protobuf/nanopb.proto"')
text = text.replace("package meshtastic;", "package meshtastic.protobuf;")
# Custom options are qualified with the upstream package name too.
text = text.replace("(meshtastic.", "(meshtastic.protobuf.")
(staged_proto_root / proto.name).write_text(text, encoding="utf-8")
nanopb = tmp_path / "nanopb.proto"