diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 6eba5cc..8db5e30 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -10,3 +10,21 @@ - [ ] All top level messages commented - [ ] All enum members have unique descriptions + + +### New Hardware Model Acceptance Policy + +Due to limited availability and ongoing support, new Hardware Models will only be accepted from [Meshtastic Backers and Partners](https://meshtastic.com/). The Meshtastic team reserves the right to make exceptions to this policy. + +#### Alternative for Community Contributors + +You are welcome to use one of the existing DIY hardware models in your PlatformIO environment and create a pull request in the firmware project. Please note the following conditions: + +- The device will **not** be officially supported by the core Meshtastic team. +- The device will **not** appear in the [Web Flasher](https://flasher.meshtastic.org/) or Github release assets. +- You will be responsible for ongoing maintenance and support. +- Community-contributed / DIY hardware models are considered experimental and will likely have limited or no testing. + +#### Getting Official Support + +To have your hardware model officially supported and included in the Meshtastic ecosystem, consider becoming a Meshtastic Backer or Partner. Visit [meshtastic.com](https://meshtastic.com/) for more information about partnership opportunities. diff --git a/.github/workflows/create_tag.yml b/.github/workflows/create_tag.yml index e8233c7..a1e9768 100644 --- a/.github/workflows/create_tag.yml +++ b/.github/workflows/create_tag.yml @@ -58,14 +58,14 @@ jobs: token: ${{ github.token }} - name: Setup Buf - uses: bufbuild/buf-setup-action@v1.30.0 + uses: bufbuild/buf-action@v1.2.0 with: github_token: ${{ github.token }} + token: ${{ secrets.BUF_TOKEN }} + setup_only: true - name: Push to schema registry - # uses: bufbuild/buf-push-action@v1 - # with: - # buf_token: ${{ secrets.BUF_TOKEN }} + env: + BUF_TOKEN: ${{ secrets.BUF_TOKEN }} run: | - export BUF_TOKEN=${{ secrets.BUF_TOKEN }} buf push --tag ${{ steps.version.outputs.NEW_VERSION }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8ea8360..6c61aed 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,30 +1,263 @@ -name: Push new version to schema registry - -permissions: - contents: read +name: Publish to JSR & NPM on: push: tags: - - "**" + - "v*" + workflow_dispatch: + inputs: + version: + description: "Version to publish (e.g. v1.2.3). Used when manually dispatching." + required: false + type: string + dry_run: + description: "Dry run mode - generate artifacts without publishing" + required: false + type: boolean + default: false + +permissions: + contents: write + id-token: write jobs: - push_to_registry: - runs-on: ubuntu-latest + codegen: + runs-on: ubuntu-24.04 + outputs: + version: ${{ steps.version.outputs.VERSION }} + tag: ${{ steps.version.outputs.TAG }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Determine version + id: version + run: | + set -euo pipefail + if [ "${{ github.ref_type }}" = "tag" ]; then + TAG="${{ github.ref_name }}" + elif [ -n "${{ inputs.version || '' }}" ]; then + TAG="${{ inputs.version }}" + else + echo "No tag ref and no 'version' input. Provide a tag (push a tag) or pass inputs.version." >&2 + exit 1 + fi + VERSION="${TAG#v}" + echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" + echo "TAG=$TAG" >> "$GITHUB_OUTPUT" + echo "Resolved VERSION=$VERSION, TAG=$TAG" + + - name: Setup Buf + uses: bufbuild/buf-setup-action@main + with: + github_token: ${{ github.token }} + + - name: Generate protobuf code + run: buf generate + + - name: Move generated files to lib root + run: | + set -euo pipefail + src_dir="packages/ts/lib/meshtastic" + dest_dir="packages/ts/lib" + + if [ ! -d "$src_dir" ]; then + echo "Expected source directory '$src_dir' does not exist. 'buf generate' may have failed or changed its output paths." >&2 + exit 1 + fi + + if ! compgen -G "$src_dir"/*_pb.ts > /dev/null; then + echo "No '*_pb.ts' files found in '$src_dir'. 'buf generate' may have produced no TypeScript files or changed their naming." >&2 + exit 1 + fi + + mv "$src_dir"/*_pb.ts "$dest_dir"/ + - name: Show generated files + run: | + echo "=== packages/ts contents ===" + ls -la packages/ts/ + echo "=== packages/ts/lib contents ===" + ls -la packages/ts/lib/ || echo "lib folder not found" + + - name: Set package versions + run: | + set -euo pipefail + VERSION="${{ steps.version.outputs.VERSION }}" + for f in packages/ts/deno.json packages/ts/package.json; do + test -f "$f" || { echo "Missing $f" >&2; exit 1; } + sed -i "s/__PACKAGE_VERSION__/${VERSION}/g" "$f" + done + + - name: Copy license & README + run: cp LICENSE README.md packages/ts/ + + - name: Upload TypeScript code + uses: actions/upload-artifact@v4 + with: + name: ts_code + path: packages/ts + + build-typescript: + runs-on: ubuntu-24.04 + needs: codegen + steps: + - name: Download TypeScript code + uses: actions/download-artifact@v4 + with: + name: ts_code + + - name: Show downloaded files + run: | + echo "=== Working directory ===" + pwd + echo "=== Contents ===" + ls -la + echo "=== lib/ contents ===" + ls -la lib/ || echo "lib folder not found" + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + + - name: Install dependencies + run: npm install + + - name: Build with tsdown + run: npm run build + + - name: Show build output + run: | + echo "=== Build output ===" + ls -la + ls -la dist/ + + - name: Upload built NPM package + uses: actions/upload-artifact@v4 + with: + name: npm_package + path: | + dist/ + package.json + LICENSE + README.md + + - name: Upload JSR package + uses: actions/upload-artifact@v4 + with: + name: jsr_package + path: | + lib/ + mod.ts + deno.json + LICENSE + README.md + + create-release-zips: + runs-on: ubuntu-24.04 + needs: [codegen, build-typescript] + steps: + - name: Download NPM package + uses: actions/download-artifact@v4 + with: + name: npm_package + path: npm_package + + - name: Download JSR package + uses: actions/download-artifact@v4 + with: + name: jsr_package + path: jsr_package + + - name: Create zip archives + run: | + cd npm_package && zip -r ../meshtastic-protobufs-npm.zip . && cd .. + cd jsr_package && zip -r ../meshtastic-protobufs-jsr.zip . && cd .. + + - name: Upload release zips + uses: actions/upload-artifact@v4 + with: + name: release_zips + path: | + meshtastic-protobufs-npm.zip + meshtastic-protobufs-jsr.zip + + upload-release-assets: + runs-on: ubuntu-24.04 + needs: [codegen, create-release-zips] + if: ${{ !inputs.dry_run }} + steps: + - name: Download release zips + uses: actions/download-artifact@v4 + with: + name: release_zips + + - name: Upload assets to GitHub release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.codegen.outputs.tag }} + files: | + meshtastic-protobufs-npm.zip + meshtastic-protobufs-jsr.zip + + push-buf-registry: + runs-on: ubuntu-24.04 + needs: codegen + if: ${{ !inputs.dry_run }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Buf - uses: bufbuild/buf-setup-action@v1.30.0 + uses: bufbuild/buf-setup-action@main with: github_token: ${{ github.token }} - name: Push to schema registry - # uses: bufbuild/buf-push-action@v1 - # with: - # buf_token: ${{ secrets.BUF_TOKEN }} - run: | - export BUF_TOKEN=${{ secrets.BUF_TOKEN }} - buf push --tag ${{ github.ref_name }} + env: + BUF_TOKEN: ${{ secrets.BUF_TOKEN }} + run: buf push --tag ${{ needs.codegen.outputs.tag }} + + publish-npm: + runs-on: ubuntu-24.04 + needs: [codegen, build-typescript] + if: ${{ !inputs.dry_run }} + steps: + - name: Download NPM package + uses: actions/download-artifact@v4 + with: + name: npm_package + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + registry-url: "https://registry.npmjs.org" + + - name: Publish to NPM + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + publish-jsr: + runs-on: ubuntu-24.04 + needs: [codegen, build-typescript] + if: ${{ !inputs.dry_run }} + permissions: + contents: read + id-token: write + steps: + - name: Download JSR package + uses: actions/download-artifact@v4 + with: + name: jsr_package + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + + - name: Publish to JSR + run: npx jsr publish diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 179d09a..6df3b32 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -2,6 +2,7 @@ name: pull-request permissions: contents: read + pull-requests: write on: pull_request jobs: @@ -12,17 +13,11 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Setup Buf - uses: bufbuild/buf-setup-action@v1.30.0 + - name: Buf PR Checks + uses: bufbuild/buf-action@v1.2.0 with: github_token: ${{ github.token }} - - - name: Lint - uses: bufbuild/buf-lint-action@v1.1.1 - - - name: Push to schema registry - uses: bufbuild/buf-push-action@v1.2.0 - if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }} - with: - buf_token: ${{ secrets.BUF_TOKEN }} - draft: ${{ github.ref_name != 'master'}} + token: ${{ secrets.BUF_TOKEN }} + format: true + lint: true + breaking: true diff --git a/.github/workflows/ci.yml b/.github/workflows/schema-registry.yml similarity index 67% rename from .github/workflows/ci.yml rename to .github/workflows/schema-registry.yml index 1023c96..f38ad9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/schema-registry.yml @@ -16,12 +16,9 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Setup Buf - uses: bufbuild/buf-setup-action@v1.30.0 + - name: Push to schema registry + uses: bufbuild/buf-action@v1.2.0 with: github_token: ${{ github.token }} - - - name: Push to schema registry - uses: bufbuild/buf-push-action@v1.2.0 - with: - buf_token: ${{ secrets.BUF_TOKEN }} + token: ${{ secrets.BUF_TOKEN }} + push: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd68173 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store + +# Generated protobuf files +packages/ts/lib/ +.bin/ diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 0000000..652f41a --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,5 @@ +version: v2 +plugins: + - remote: buf.build/bufbuild/es:v2.1.0 + out: packages/ts/lib + opt: target=ts,import_extension=.ts diff --git a/buf.yaml b/buf.yaml index 642e538..2a93588 100644 --- a/buf.yaml +++ b/buf.yaml @@ -1,14 +1,23 @@ -version: v1 -name: buf.build/meshtastic/protobufs -deps: [] -build: - excludes: [] -breaking: - use: - - FILE -lint: - ignore_only: - PACKAGE_DEFINED: - - nanopb.proto - use: - - MINIMAL +version: v2 +modules: + - path: . + name: buf.build/meshtastic/protobufs + excludes: + - .trunk/ + - meshtastic/device_only/ + lint: + use: + - MINIMAL + except: + - PACKAGE_NO_IMPORT_CYCLE + ignore_only: + PACKAGE_DEFINED: + - nanopb.proto + disallow_comment_ignores: true + breaking: + use: + - FILE + except: + - EXTENSION_NO_DELETE + - FIELD_SAME_DEFAULT + diff --git a/meshtastic/admin.options b/meshtastic/admin.options index 022c4fd..6574db5 100644 --- a/meshtastic/admin.options +++ b/meshtastic/admin.options @@ -2,6 +2,13 @@ *AdminMessage.session_passkey max_size:8 +*AdminMessage.OTAEvent.ota_hash max_size:32 + +*AdminMessage.InputEvent.event_code int_size:8 +*AdminMessage.InputEvent.kb_char int_size:8 +*AdminMessage.InputEvent.touch_x int_size:16 +*AdminMessage.InputEvent.touch_y int_size:16 + *AdminMessage.set_canned_message_module_messages max_size:201 *AdminMessage.get_canned_message_module_messages_response max_size:201 *AdminMessage.delete_file_request max_size:201 diff --git a/meshtastic/admin.proto b/meshtastic/admin.proto index f4718c1..ac29cc8 100644 --- a/meshtastic/admin.proto +++ b/meshtastic/admin.proto @@ -2,17 +2,18 @@ syntax = "proto3"; package meshtastic; +/* trunk-ignore(buf-lint/COMPILE) */ import "meshtastic/channel.proto"; import "meshtastic/config.proto"; import "meshtastic/connection_status.proto"; +import "meshtastic/device_ui.proto"; import "meshtastic/mesh.proto"; import "meshtastic/module_config.proto"; -import "meshtastic/device_ui.proto"; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "AdminProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -21,7 +22,6 @@ option swift_prefix = ""; * (Prior to 1.2 these operations were done via special ToRadio operations) */ message AdminMessage { - /* * The node generates this key and sends it with any get_x_response packets. * The client MUST include the same key with any set_x commands. Key expires after 300 seconds. @@ -152,6 +152,21 @@ message AdminMessage { * TODO: REPLACE */ PAXCOUNTER_CONFIG = 12; + + /* + * TODO: REPLACE + */ + STATUSMESSAGE_CONFIG = 13; + + /* + * Traffic management module config + */ + TRAFFICMANAGEMENT_CONFIG = 14; + + /* + * TAK module config + */ + TAK_CONFIG = 15; } enum BackupLocation { @@ -166,6 +181,45 @@ message AdminMessage { SD = 1; } + /* + * Input event message to be sent to the node. + */ + message InputEvent { + /* + * The input event code + */ + uint32 event_code = 1; + /* + * Keyboard character code + */ + uint32 kb_char = 2; + /* + * The touch X coordinate + */ + uint32 touch_x = 3; + /* + * The touch Y coordinate + */ + uint32 touch_y = 4; + } + + /* + * User is requesting an over the air update. + * Node will reboot into the OTA loader + */ + message OTAEvent { + /* + * Tell the node to reboot into OTA mode for firmware update via BLE or WiFi (ESP32 only for now) + */ + OTAMode reboot_ota_mode = 1; + + /* + * A 32 byte hash of the OTA firmware. + * Used to verify the integrity of the firmware before applying an update. + */ + bytes ota_hash = 2; + } + /* * TODO: REPLACE */ @@ -296,6 +350,13 @@ message AdminMessage { * Remove backups of the node's preferences */ BackupLocation remove_backup_preferences = 26; + + /* + * Send an input event to the node. + * This is used to trigger physical input events like button presses, touch events, etc. + */ + InputEvent send_input_event = 27; + /* * Set the owner for this node */ @@ -386,6 +447,11 @@ message AdminMessage { */ uint32 remove_ignored_node = 48; + /* + * Set specified node-num to be muted + */ + uint32 toggle_muted_node = 49; + /* * Begins an edit transaction for config, module config, owner, and channel settings changes * This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings) @@ -397,6 +463,16 @@ message AdminMessage { */ bool commit_edit_settings = 65; + /* + * Add a contact (User) to the nodedb + */ + SharedContact add_contact = 66; + + /* + * Initiate or respond to a key verification request + */ + KeyVerificationAdmin key_verification = 67; + /* * Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */ @@ -405,8 +481,9 @@ message AdminMessage { /* * Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) * Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. + * Deprecated in favor of reboot_ota_mode in 2.7.17 */ - int32 reboot_ota_seconds = 95; + int32 reboot_ota_seconds = 95 [deprecated = true]; /* * This message is only supported for the simulator Portduino build. @@ -431,11 +508,42 @@ message AdminMessage { /* * Tell the node to reset the nodedb. + * When true, favorites are preserved through reset. */ - int32 nodedb_reset = 100; + bool nodedb_reset = 100; + + /* + * Tell the node to reset into the OTA Loader + */ + OTAEvent ota_request = 102; + + /* + * Parameters and sensor configuration + */ + SensorConfig sensor_config = 103; } } +/* + * Firmware update mode for OTA updates + */ +enum OTAMode { + /* + * Do not reboot into OTA mode + */ + NO_REBOOT_OTA = 0; + + /* + * Reboot into OTA mode for BLE firmware update + */ + OTA_BLE = 1; + + /* + * Reboot into OTA mode for WiFi firmware update + */ + OTA_WIFI = 2; +} + /* * Parameters for setting up Meshtastic for ameteur radio usage */ @@ -472,3 +580,183 @@ message NodeRemoteHardwarePinsResponse { */ repeated NodeRemoteHardwarePin node_remote_hardware_pins = 1; } + +message SharedContact { + /* + * The node number of the contact + */ + uint32 node_num = 1; + + /* + * The User of the contact + */ + User user = 2; + + /* + * Add this contact to the blocked / ignored list + */ + bool should_ignore = 3; + + /* + * Set the IS_KEY_MANUALLY_VERIFIED bit + */ + bool manually_verified = 4; +} + +/* + * This message is used by a client to initiate or complete a key verification + */ +message KeyVerificationAdmin { + /* + * Three stages of this request. + */ + enum MessageType { + /* + * This is the first stage, where a client initiates + */ + INITIATE_VERIFICATION = 0; + + /* + * After the nonce has been returned over the mesh, the client prompts for the security number + * And uses this message to provide it to the node. + */ + PROVIDE_SECURITY_NUMBER = 1; + + /* + * Once the user has compared the verification message, this message notifies the node. + */ + DO_VERIFY = 2; + + /* + * This is the cancel path, can be taken at any point + */ + DO_NOT_VERIFY = 3; + } + + MessageType message_type = 1; + + /* + * The nodenum we're requesting + */ + uint32 remote_nodenum = 2; + + /* + * The nonce is used to track the connection + */ + uint64 nonce = 3; + + /* + * The 4 digit code generated by the remote node, and communicated outside the mesh + */ + optional uint32 security_number = 4; +} + +message SensorConfig { + /* + * SCD4X CO2 Sensor configuration + */ + SCD4X_config scd4x_config = 1; + + /* + * SEN5X PM Sensor configuration + */ + SEN5X_config sen5x_config = 2; + + /* + * SCD30 CO2 Sensor configuration + */ + SCD30_config scd30_config = 3; + + /* + * SHTXX temperature and relative humidity sensor configuration + */ + SHTXX_config shtxx_config = 4; +} + +message SCD4X_config { + /* + * Set Automatic self-calibration enabled + */ + optional bool set_asc = 1; + + /* + * Recalibration target CO2 concentration in ppm (FRC or ASC) + */ + optional uint32 set_target_co2_conc = 2; + + /* + * Reference temperature in degC + */ + optional float set_temperature = 3; + + /* + * Altitude of sensor in meters above sea level. 0 - 3000m (overrides ambient pressure) + */ + optional uint32 set_altitude = 4; + + /* + * Sensor ambient pressure in Pa. 70000 - 120000 Pa (overrides altitude) + */ + optional uint32 set_ambient_pressure = 5; + + /* + * Perform a factory reset of the sensor + */ + optional bool factory_reset = 6; + + /* + * Power mode for sensor (true for low power, false for normal) + */ + optional bool set_power_mode = 7; +} + +message SEN5X_config { + /* + * Reference temperature in degC + */ + optional float set_temperature = 1; + + /* + * One-shot mode (true for low power - one-shot mode, false for normal - continuous mode) + */ + optional bool set_one_shot_mode = 2; +} + +message SCD30_config { + /* + * Set Automatic self-calibration enabled + */ + optional bool set_asc = 1; + + /* + * Recalibration target CO2 concentration in ppm (FRC or ASC) + */ + optional uint32 set_target_co2_conc = 2; + + /* + * Reference temperature in degC + */ + optional float set_temperature = 3; + + /* + * Altitude of sensor in meters above sea level. 0 - 3000m (overrides ambient pressure) + */ + optional uint32 set_altitude = 4; + + /* + * Power mode for sensor (true for low power, false for normal) + */ + optional uint32 set_measurement_interval = 5; + + /* + * Perform a factory reset of the sensor + */ + optional bool soft_reset = 6; +} + +message SHTXX_config { + /* + * Accuracy mode (0 = low, 1 = medium, 2 = high) + */ + optional uint32 set_accuracy = 1; +} diff --git a/meshtastic/apponly.proto b/meshtastic/apponly.proto index 100833f..2612ed6 100644 --- a/meshtastic/apponly.proto +++ b/meshtastic/apponly.proto @@ -8,7 +8,7 @@ import "meshtastic/config.proto"; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "AppOnlyProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* diff --git a/meshtastic/atak.options b/meshtastic/atak.options index cec1ca3..29ec3e1 100644 --- a/meshtastic/atak.options +++ b/meshtastic/atak.options @@ -5,4 +5,106 @@ *GeoChat.message max_size:200 *GeoChat.to max_size:120 *GeoChat.to_callsign max_size:120 -*TAKPacket.detail max_size:220 \ No newline at end of file +*TAKPacket.detail max_size:220 +*TAKPacketV2.cot_type_str max_size:32 +*TAKPacketV2.callsign max_size:120 +*TAKPacketV2.uid max_size:48 +*TAKPacketV2.device_callsign max_size:120 +*TAKPacketV2.tak_version max_size:64 +*TAKPacketV2.tak_device max_size:32 +*TAKPacketV2.tak_platform max_size:32 +*TAKPacketV2.tak_os max_size:16 +*TAKPacketV2.endpoint max_size:32 +*TAKPacketV2.phone max_size:20 +*TAKPacketV2.raw_detail max_size:220 +*TAKPacketV2.stale_seconds int_size:16 +*TAKPacketV2.battery int_size:8 +*TAKPacketV2.course int_size:16 +*AircraftTrack.icao max_size:8 +*AircraftTrack.registration max_size:16 +*AircraftTrack.flight max_size:16 +*AircraftTrack.aircraft_type max_size:8 +*AircraftTrack.squawk int_size:16 +*AircraftTrack.category max_size:4 +*AircraftTrack.cot_host_id max_size:64 + +# --- Typed geometry payloads (v2 protocol extension) --- +# +# CotGeoPoint: sint32 deltas from the enclosing event's latitude_i/longitude_i. +# For nearby vertices (telestrations, small rectangles) the varint+zigzag +# encoding is 2-3 bytes per field, cutting telestration vertex data in half +# versus sfixed32. int_size:32 keeps the C type a plain int32. +# Named with a `Cot` prefix to avoid a collision with `meshtastic.GeoPoint` +# in device_ui.proto, which is an unrelated zoom/latitude/longitude type. +*CotGeoPoint.lat_delta_i int_size:32 +*CotGeoPoint.lon_delta_i int_size:32 +# +# DrawnShape pool sizing. `kind` and `style` are varint enums (no int_size +# needed). stroke_color / fill_color are Team enum, also varint. stroke_argb +# / fill_argb are fixed32 (always 4 bytes on the wire). Vertex pool is 32 +# entries x ~12B each ~= 384B worst case. Telestrations beyond 32 vertices +# MUST be pre-truncated by the sender with `truncated = true`. +*DrawnShape.vertices max_count:32 +*DrawnShape.major_cm int_size:32 +*DrawnShape.minor_cm int_size:32 +*DrawnShape.angle_deg int_size:16 +*DrawnShape.stroke_weight_x10 int_size:16 +*DrawnShape.bullseye_distance_dm int_size:32 +*DrawnShape.bullseye_bearing_ref int_size:8 +*DrawnShape.bullseye_flags int_size:8 +*DrawnShape.bullseye_uid_ref max_size:48 + +# Marker pool sizing. Strings bounded tight to keep fixed pool small on +# ESP32 nanopb. parent_uid matches existing TAKPacketV2.uid cap (48). +# iconset fits "f7f71666-8b28-4b57-9fbb-e38e61d33b79/Google/hiker.png" +# (~52 chars) with slack. +*Marker.parent_uid max_size:48 +*Marker.parent_type max_size:24 +*Marker.parent_callsign max_size:24 +*Marker.iconset max_size:80 + +# RangeAndBearing pool sizing. +*RangeAndBearing.anchor_uid max_size:48 +*RangeAndBearing.range_cm int_size:32 +*RangeAndBearing.bearing_cdeg int_size:16 +*RangeAndBearing.stroke_weight_x10 int_size:16 + +# Route pool sizing. 16 links x ~24B each ~= 384B worst case. prefix is +# ATAK's short waypoint name prefix ("CP", "RP", etc.) — 8 chars is plenty. +*Route.links max_count:16 +*Route.prefix max_size:8 +*Route.stroke_weight_x10 int_size:16 +*Route.Link.uid max_size:48 +*Route.Link.callsign max_size:16 +*Route.Link.link_type int_size:8 + +# GeoChat receipt extension. receipt_for_uid matches TAKPacketV2.uid caps. +*GeoChat.receipt_for_uid max_size:48 + +# CasevacReport pool sizing. All numeric fields are small (0..255 for +# patient counts, 1 byte for flags bitfields); strings are short. +*CasevacReport.equipment_flags int_size:8 +*CasevacReport.terrain_flags int_size:8 +*CasevacReport.litter_patients int_size:8 +*CasevacReport.ambulatory_patients int_size:8 +*CasevacReport.us_military int_size:8 +*CasevacReport.us_civilian int_size:8 +*CasevacReport.non_us_military int_size:8 +*CasevacReport.non_us_civilian int_size:8 +*CasevacReport.epw int_size:8 +*CasevacReport.child int_size:8 +*CasevacReport.zone_marker max_size:16 +*CasevacReport.frequency max_size:16 + +# EmergencyAlert pool sizing. UIDs match TAKPacketV2.uid caps (48). +*EmergencyAlert.authoring_uid max_size:48 +*EmergencyAlert.cancel_reference_uid max_size:48 + +# TaskRequest pool sizing. All four strings are capped tight so the +# worst-case wire size stays under the LoRa MTU with headroom. task_type +# is a short category tag; target_uid/assignee_uid match TAKPacketV2.uid +# conventions; note is the one user-entered field. +*TaskRequest.task_type max_size:12 +*TaskRequest.target_uid max_size:32 +*TaskRequest.assignee_uid max_size:32 +*TaskRequest.note max_size:48 \ No newline at end of file diff --git a/meshtastic/atak.proto b/meshtastic/atak.proto index 5dc08c9..873e0b6 100644 --- a/meshtastic/atak.proto +++ b/meshtastic/atak.proto @@ -1,11 +1,12 @@ syntax = "proto3"; +/* trunk-ignore(buf-lint/PACKAGE_DIRECTORY_MATCH) */ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "ATAKProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -54,7 +55,21 @@ message TAKPacket { */ message GeoChat { /* - * The text message + * Receipt discriminator. Set alongside cot_type_id = b-t-f-d (delivered) + * or b-t-f-r (read). ReceiptType_None is the default for a normal chat + * message (cot_type_id = b-t-f). + * + * Receivers can detect a receipt by checking receipt_type != ReceiptType_None + * without re-parsing the envelope cot_type_id. + */ + enum ReceiptType { + ReceiptType_None = 0; // normal chat message + ReceiptType_Delivered = 1; // b-t-f-d delivered receipt + ReceiptType_Read = 2; // b-t-f-r read receipt + } + + /* + * The text message. Empty for receipts. */ string message = 1; @@ -67,6 +82,20 @@ message GeoChat { * Callsign of the recipient for the message */ optional string to_callsign = 3; + + /* + * UID of the chat message this event is acknowledging. Empty for a + * normal chat message; set for delivered / read receipts. Paired with + * receipt_type so receivers can match the ack back to the original + * outbound GeoChat by its event uid. + */ + string receipt_for_uid = 4; + + /* + * Receipt kind discriminator. See ReceiptType doc. Default ReceiptType_None + * means this is a regular chat message, not a receipt. + */ + ReceiptType receipt_type = 5; } /* @@ -261,3 +290,1728 @@ message PLI { */ uint32 course = 5; } + +/* + * CoT how field values. + * Represents how the coordinates were generated. + */ +enum CotHow { + /* + * Unspecified + */ + CotHow_Unspecified = 0; + /* + * Human entered + */ + CotHow_h_e = 1; + /* + * Machine generated + */ + CotHow_m_g = 2; + /* + * Human GPS/INS derived + */ + CotHow_h_g_i_g_o = 3; + /* + * Machine relayed (imported from another system/gateway) + */ + CotHow_m_r = 4; + /* + * Machine fused (corroborated from multiple sources) + */ + CotHow_m_f = 5; + /* + * Machine predicted + */ + CotHow_m_p = 6; + /* + * Machine simulated + */ + CotHow_m_s = 7; +} + +/* + * Well-known CoT event types. + * When the type is known, use the enum value for efficient encoding. + * For unknown types, set cot_type_id to CotType_Other and populate cot_type_str. + */ +enum CotType { + /* + * Unknown or unmapped type, use cot_type_str + */ + CotType_Other = 0; + /* + * a-f-G-U-C: Friendly ground unit combat + */ + CotType_a_f_G_U_C = 1; + /* + * a-f-G-U-C-I: Friendly ground unit combat infantry + */ + CotType_a_f_G_U_C_I = 2; + /* + * a-n-A-C-F: Neutral aircraft civilian fixed-wing + */ + CotType_a_n_A_C_F = 3; + /* + * a-n-A-C-H: Neutral aircraft civilian helicopter + */ + CotType_a_n_A_C_H = 4; + /* + * a-n-A-C: Neutral aircraft civilian + */ + CotType_a_n_A_C = 5; + /* + * a-f-A-M-H: Friendly aircraft military helicopter + */ + CotType_a_f_A_M_H = 6; + /* + * a-f-A-M: Friendly aircraft military + */ + CotType_a_f_A_M = 7; + /* + * a-f-A-M-F-F: Friendly aircraft military fixed-wing fighter + */ + CotType_a_f_A_M_F_F = 8; + /* + * a-f-A-M-H-A: Friendly aircraft military helicopter attack + */ + CotType_a_f_A_M_H_A = 9; + /* + * a-f-A-M-H-U-M: Friendly aircraft military helicopter utility medium + */ + CotType_a_f_A_M_H_U_M = 10; + /* + * a-h-A-M-F-F: Hostile aircraft military fixed-wing fighter + */ + CotType_a_h_A_M_F_F = 11; + /* + * a-h-A-M-H-A: Hostile aircraft military helicopter attack + */ + CotType_a_h_A_M_H_A = 12; + /* + * a-u-A-C: Unknown aircraft civilian + */ + CotType_a_u_A_C = 13; + /* + * t-x-d-d: Tasking delete/disconnect + */ + CotType_t_x_d_d = 14; + /* + * a-f-G-E-S-E: Friendly ground equipment sensor + */ + CotType_a_f_G_E_S_E = 15; + /* + * a-f-G-E-V-C: Friendly ground equipment vehicle + */ + CotType_a_f_G_E_V_C = 16; + /* + * a-f-S: Friendly sea + */ + CotType_a_f_S = 17; + /* + * a-f-A-M-F: Friendly aircraft military fixed-wing + */ + CotType_a_f_A_M_F = 18; + /* + * a-f-A-M-F-C-H: Friendly aircraft military fixed-wing cargo heavy + */ + CotType_a_f_A_M_F_C_H = 19; + /* + * a-f-A-M-F-U-L: Friendly aircraft military fixed-wing utility light + */ + CotType_a_f_A_M_F_U_L = 20; + /* + * a-f-A-M-F-L: Friendly aircraft military fixed-wing liaison + */ + CotType_a_f_A_M_F_L = 21; + /* + * a-f-A-M-F-P: Friendly aircraft military fixed-wing patrol + */ + CotType_a_f_A_M_F_P = 22; + /* + * a-f-A-C-H: Friendly aircraft civilian helicopter + */ + CotType_a_f_A_C_H = 23; + /* + * a-n-A-M-F-Q: Neutral aircraft military fixed-wing drone + */ + CotType_a_n_A_M_F_Q = 24; + + // --- Chat / messaging --- + + /* + * b-t-f: GeoChat message + */ + CotType_b_t_f = 25; + + // --- CASEVAC / MEDEVAC --- + + /* + * b-r-f-h-c: CASEVAC/MEDEVAC report + */ + CotType_b_r_f_h_c = 26; + + // --- Alerts --- + + /* + * b-a-o-pan: Ring the bell / alert all + */ + CotType_b_a_o_pan = 27; + /* + * b-a-o-opn: Troops in contact + */ + CotType_b_a_o_opn = 28; + /* + * b-a-o-can: Cancel alert + */ + CotType_b_a_o_can = 29; + /* + * b-a-o-tbl: 911 alert + */ + CotType_b_a_o_tbl = 30; + /* + * b-a-g: Geofence breach alert + */ + CotType_b_a_g = 31; + + // --- Generic ground atoms (simplified affiliation types) --- + + /* + * a-f-G: Friendly ground (generic) + */ + CotType_a_f_G = 32; + /* + * a-f-G-U: Friendly ground unit (generic) + */ + CotType_a_f_G_U = 33; + /* + * a-h-G: Hostile ground (generic) + */ + CotType_a_h_G = 34; + /* + * a-u-G: Unknown ground (generic) + */ + CotType_a_u_G = 35; + /* + * a-n-G: Neutral ground (generic) + */ + CotType_a_n_G = 36; + + // --- Routes and waypoints --- + + /* + * b-m-r: Route + */ + CotType_b_m_r = 37; + /* + * b-m-p-w: Route waypoint + */ + CotType_b_m_p_w = 38; + /* + * b-m-p-s-p-i: Self-position marker + */ + CotType_b_m_p_s_p_i = 39; + + // --- Drawing / tactical graphics --- + + /* + * u-d-f: Freeform shape (line/polygon) + */ + CotType_u_d_f = 40; + /* + * u-d-r: Rectangle + */ + CotType_u_d_r = 41; + /* + * u-d-c-c: Circle + */ + CotType_u_d_c_c = 42; + /* + * u-rb-a: Range/bearing line + */ + CotType_u_rb_a = 43; + + // --- Additional hostile/unknown aircraft --- + + /* + * a-h-A: Hostile aircraft (generic) + */ + CotType_a_h_A = 44; + /* + * a-u-A: Unknown aircraft (generic) + */ + CotType_a_u_A = 45; + /* + * a-f-A-M-H-Q: Friendly aircraft military helicopter observation + */ + CotType_a_f_A_M_H_Q = 46; + + // Friendly aircraft civilian + + /* + * a-f-A-C-F: Friendly aircraft civilian fixed-wing + */ + CotType_a_f_A_C_F = 47; + /* + * a-f-A-C: Friendly aircraft civilian (generic) + */ + CotType_a_f_A_C = 48; + /* + * a-f-A-C-L: Friendly aircraft civilian lighter-than-air + */ + CotType_a_f_A_C_L = 49; + /* + * a-f-A: Friendly aircraft (generic) + */ + CotType_a_f_A = 50; + + // Friendly aircraft military helicopter variants + + /* + * a-f-A-M-H-C: Friendly aircraft military helicopter cargo + */ + CotType_a_f_A_M_H_C = 51; + + // Neutral aircraft military + + /* + * a-n-A-M-F-F: Neutral aircraft military fixed-wing fighter + */ + CotType_a_n_A_M_F_F = 52; + + // Unknown aircraft civilian + + /* + * a-u-A-C-F: Unknown aircraft civilian fixed-wing + */ + CotType_a_u_A_C_F = 53; + + // Friendly ground unit subtypes + + /* + * a-f-G-U-C-F-T-A: Friendly ground unit combat forces theater aviation + */ + CotType_a_f_G_U_C_F_T_A = 54; + /* + * a-f-G-U-C-V-S: Friendly ground unit combat vehicle support + */ + CotType_a_f_G_U_C_V_S = 55; + /* + * a-f-G-U-C-R-X: Friendly ground unit combat reconnaissance exploitation + */ + CotType_a_f_G_U_C_R_X = 56; + /* + * a-f-G-U-C-I-Z: Friendly ground unit combat infantry mechanized + */ + CotType_a_f_G_U_C_I_Z = 57; + /* + * a-f-G-U-C-E-C-W: Friendly ground unit combat engineer construction wheeled + */ + CotType_a_f_G_U_C_E_C_W = 58; + /* + * a-f-G-U-C-I-L: Friendly ground unit combat infantry light + */ + CotType_a_f_G_U_C_I_L = 59; + /* + * a-f-G-U-C-R-O: Friendly ground unit combat reconnaissance other + */ + CotType_a_f_G_U_C_R_O = 60; + /* + * a-f-G-U-C-R-V: Friendly ground unit combat reconnaissance cavalry + */ + CotType_a_f_G_U_C_R_V = 61; + /* + * a-f-G-U-H: Friendly ground unit headquarters + */ + CotType_a_f_G_U_H = 62; + /* + * a-f-G-U-U-M-S-E: Friendly ground unit support medical surgical evacuation + */ + CotType_a_f_G_U_U_M_S_E = 63; + /* + * a-f-G-U-S-M-C: Friendly ground unit support maintenance collection + */ + CotType_a_f_G_U_S_M_C = 64; + + // Friendly ground equipment + + /* + * a-f-G-E-S: Friendly ground equipment sensor (generic) + */ + CotType_a_f_G_E_S = 65; + /* + * a-f-G-E: Friendly ground equipment (generic) + */ + CotType_a_f_G_E = 66; + /* + * a-f-G-E-V-C-U: Friendly ground equipment vehicle utility + */ + CotType_a_f_G_E_V_C_U = 67; + /* + * a-f-G-E-V-C-ps: Friendly ground equipment vehicle public safety + */ + CotType_a_f_G_E_V_C_ps = 68; + + // Unknown ground + + /* + * a-u-G-E-V: Unknown ground equipment vehicle + */ + CotType_a_u_G_E_V = 69; + + // Sea + + /* + * a-f-S-N-N-R: Friendly sea surface non-naval rescue + */ + CotType_a_f_S_N_N_R = 70; + + // Friendly force (non-domain-specific) + + /* + * a-f-F-B: Friendly force boundary + */ + CotType_a_f_F_B = 71; + + // Bits / data messages + + /* + * b-m-p-s-p-loc: Self-position location marker + */ + CotType_b_m_p_s_p_loc = 72; + /* + * b-i-v: Imagery/video + */ + CotType_b_i_v = 73; + /* + * b-f-t-r: File transfer request + */ + CotType_b_f_t_r = 74; + /* + * b-f-t-a: File transfer acknowledgment + */ + CotType_b_f_t_a = 75; + + // --- Additional drawing / tactical graphics --- + + /* + * u-d-f-m: Freehand telestration / annotation. Anchor at event point, + * geometry carried via DrawnShape.vertices. May be truncated to + * MAX_VERTICES by the sender. + */ + CotType_u_d_f_m = 76; + /* + * u-d-p: Closed polygon. Geometry carried via DrawnShape.vertices, + * implicitly closed (receiver duplicates first vertex as needed). + */ + CotType_u_d_p = 77; + + // --- Additional markers --- + + /* + * b-m-p-s-m: Spot map marker (colored dot at a point of interest). + */ + CotType_b_m_p_s_m = 78; + /* + * b-m-p-c: Checkpoint (intermediate route control point). + */ + CotType_b_m_p_c = 79; + + // --- Ranging tools --- + + /* + * u-r-b-c-c: Ranging circle (range rings centered on the event point). + */ + CotType_u_r_b_c_c = 80; + /* + * u-r-b-bullseye: Bullseye with configurable range rings and bearing + * reference (magnetic / true / grid). + */ + CotType_u_r_b_bullseye = 81; + + // ====================================================================== + // Expanded coverage from the ATAK-CIV quick-drop pallet (values 82-124). + // ====================================================================== + // + // All of these types existed as cot_type_str strings; promoting them to + // enum values turns a ~10-byte string into a 1-byte varint on the wire + // for every event that uses them. Grouped below by pallet section. + + // --- PLI self-reporting (1) ------------------------------------------ + /* + * a-f-G-E-V-A: Friendly armored vehicle, user-selectable self PLI. + */ + CotType_a_f_G_E_V_A = 82; + + // --- 2525 quick-drop: basic affiliation gaps ------------------------- + /* + * a-n-A: Neutral aircraft (friendly/hostile/unknown already present). + */ + CotType_a_n_A = 83; + + // --- 2525 quick-drop: artillery (4) ---------------------------------- + CotType_a_u_G_U_C_F = 84; + CotType_a_n_G_U_C_F = 85; + CotType_a_h_G_U_C_F = 86; + CotType_a_f_G_U_C_F = 87; + + // --- 2525 quick-drop: building (4) ----------------------------------- + CotType_a_u_G_I = 88; + CotType_a_n_G_I = 89; + CotType_a_h_G_I = 90; + CotType_a_f_G_I = 91; + + // --- 2525 quick-drop: mine (4) --------------------------------------- + CotType_a_u_G_E_X_M = 92; + CotType_a_n_G_E_X_M = 93; + CotType_a_h_G_E_X_M = 94; + CotType_a_f_G_E_X_M = 95; + + // --- 2525 quick-drop: ship (3; a-f-S already at 17) ------------------ + CotType_a_u_S = 96; + CotType_a_n_S = 97; + CotType_a_h_S = 98; + + // --- 2525 quick-drop: sniper (4) ------------------------------------- + CotType_a_u_G_U_C_I_d = 99; + CotType_a_n_G_U_C_I_d = 100; + CotType_a_h_G_U_C_I_d = 101; + CotType_a_f_G_U_C_I_d = 102; + + // --- 2525 quick-drop: tank (4) --------------------------------------- + CotType_a_u_G_E_V_A_T = 103; + CotType_a_n_G_E_V_A_T = 104; + CotType_a_h_G_E_V_A_T = 105; + CotType_a_f_G_E_V_A_T = 106; + + // --- 2525 quick-drop: troops (3; a-f-G-U-C-I already at 2) ----------- + CotType_a_u_G_U_C_I = 107; + CotType_a_n_G_U_C_I = 108; + CotType_a_h_G_U_C_I = 109; + + // --- 2525 quick-drop: generic vehicle (3; a-u-G-E-V already at 69) --- + CotType_a_n_G_E_V = 110; + CotType_a_h_G_E_V = 111; + CotType_a_f_G_E_V = 112; + + // --- Mission-specific points (4) ------------------------------------- + /* + * b-m-p-w-GOTO: Go To / bloodhound navigation target. + */ + CotType_b_m_p_w_GOTO = 113; + /* + * b-m-p-c-ip: Initial point (mission planning). + */ + CotType_b_m_p_c_ip = 114; + /* + * b-m-p-c-cp: Contact point (mission planning). + */ + CotType_b_m_p_c_cp = 115; + /* + * b-m-p-s-p-op: Observation post. + */ + CotType_b_m_p_s_p_op = 116; + + // --- Vehicle drawings (2) -------------------------------------------- + /* + * u-d-v: 2D vehicle outline drawn on the map. + */ + CotType_u_d_v = 117; + /* + * u-d-v-m: 3D vehicle model reference. + */ + CotType_u_d_v_m = 118; + + // --- Drawing shapes (1) ---------------------------------------------- + /* + * u-d-c-e: Non-circular ellipse (circle with distinct major/minor axes). + */ + CotType_u_d_c_e = 119; + + // --- Image / media marker (1) ---------------------------------------- + /* + * b-i-x-i: Quick Pic geotagged image marker. The image itself does not + * ride on LoRa; this event references the image via iconset metadata. + */ + CotType_b_i_x_i = 120; + + // --- GeoChat receipts (2) -------------------------------------------- + /* + * b-t-f-d: GeoChat delivered receipt. Carried on the existing `chat` + * payload_variant via GeoChat.receipt_for_uid + receipt_type. + */ + CotType_b_t_f_d = 121; + /* + * b-t-f-r: GeoChat read receipt. Same wire slot as b-t-f-d. + */ + CotType_b_t_f_r = 122; + + // --- Custom emergency (1) -------------------------------------------- + /* + * b-a-o-c: Custom / generic emergency beacon. + */ + CotType_b_a_o_c = 123; + + // --- Tasking (1) ----------------------------------------------------- + /* + * t-s: Task / engage request. Structured payload carried via the new + * TaskRequest typed variant. + */ + CotType_t_s = 124; +} + +/* + * Geopoint and altitude source + */ +enum GeoPointSource { + /* + * Unspecified + */ + GeoPointSource_Unspecified = 0; + /* + * GPS derived + */ + GeoPointSource_GPS = 1; + /* + * User entered + */ + GeoPointSource_USER = 2; + /* + * Network/external + */ + GeoPointSource_NETWORK = 3; +} + +/* + * Aircraft track information from ADS-B or military air tracking. + * Covers the majority of observed real-world CoT traffic. + */ +message AircraftTrack { + /* + * ICAO hex identifier (e.g. "AD237C") + */ + string icao = 1; + /* + * Aircraft registration (e.g. "N946AK") + */ + string registration = 2; + /* + * Flight number/callsign (e.g. "ASA864") + */ + string flight = 3; + /* + * ICAO aircraft type designator (e.g. "B39M") + */ + string aircraft_type = 4; + /* + * Transponder squawk code (0-7777 octal) + */ + uint32 squawk = 5; + /* + * ADS-B emitter category (e.g. "A3") + */ + string category = 6; + /* + * Received signal strength * 10 (e.g. -194 for -19.4 dBm) + */ + sint32 rssi_x10 = 7; + /* + * Whether receiver has GPS fix + */ + bool gps = 8; + /* + * CoT host ID for source attribution + */ + string cot_host_id = 9; +} + +/* + * Compact geographic vertex used by repeated vertex lists in TAK geometry + * payloads. Named with a `Cot` prefix to avoid a namespace collision with + * `meshtastic.GeoPoint` in `device_ui.proto`, which is an unrelated zoom/ + * latitude/longitude type used by the on-device map UI. + * + * Encoded as a signed DELTA from TAKPacketV2.latitude_i / longitude_i (the + * enclosing event's anchor point). The absolute coordinate is recovered by + * the receiver as `event.latitude_i + vertex.lat_delta_i` (and likewise for + * longitude). + * + * Why deltas: a 32-vertex telestration with vertices clustered within a few + * hundred meters of the anchor has per-vertex deltas in the ±10^4 range. + * Under sint32+zigzag those encode as 2 bytes each (tag+varint), versus the + * 4 bytes that sfixed32 would always require. At 32 vertices that is ~128 + * bytes of savings — the difference between fitting under the LoRa MTU or + * not. Absolute coordinates (values ~10^9) would cost sint32 varint 5 bytes + * per field, which is why TAKPacketV2's top-level latitude_i / longitude_i + * stay sfixed32 — only small values win with sint32. + */ +message CotGeoPoint { + /* + * Latitude delta from TAKPacketV2.latitude_i, in 1e-7 degree units. + * Add to the enclosing event's latitude_i to recover the absolute latitude. + */ + sint32 lat_delta_i = 1; + /* + * Longitude delta from TAKPacketV2.longitude_i, in 1e-7 degree units. + */ + sint32 lon_delta_i = 2; +} + +/* + * User-drawn tactical graphic: circle, rectangle, polygon, polyline, freehand + * telestration, ranging circle, or bullseye. + * + * Covers CoT types u-d-c-c, u-d-r, u-d-f, u-d-f-m, u-d-p, u-r-b-c-c, + * u-r-b-bullseye. The shape's anchor position is carried on + * TAKPacketV2.latitude_i/longitude_i; polyline/polygon vertices are in the + * `vertices` repeated field as `CotGeoPoint` deltas from that anchor. + * + * Colors use the Team enum as a 14-color palette (see color encoding below) + * with a fixed32 exact-ARGB fallback for custom user-picked colors that + * don't map to a palette entry. + */ +message DrawnShape { + /* + * Shape kind discriminator. Drives receiver rendering and also controls + * which optional fields below are meaningful. + */ + enum Kind { + /* + * Unspecified (do not use on the wire) + */ + Kind_Unspecified = 0; + /* + * u-d-c-c: User-drawn circle (uses major/minor/angle, anchor = event point) + */ + Kind_Circle = 1; + /* + * u-d-r: User-drawn rectangle (uses vertices = 4 corners) + */ + Kind_Rectangle = 2; + /* + * u-d-f: User-drawn polyline (uses vertices, not closed) + */ + Kind_Freeform = 3; + /* + * u-d-f-m: Freehand telestration / annotation (uses vertices, may be truncated) + */ + Kind_Telestration = 4; + /* + * u-d-p: Closed polygon (uses vertices, implicitly closed) + */ + Kind_Polygon = 5; + /* + * u-r-b-c-c: Ranging circle (major/minor/angle, stroke + optional fill) + */ + Kind_RangingCircle = 6; + /* + * u-r-b-bullseye: Bullseye ring with range rings and bearing reference + */ + Kind_Bullseye = 7; + /* + * u-d-c-e: Ellipse with distinct major/minor axes (same storage as + * Kind_Circle — uses major_cm/minor_cm/angle_deg — but receivers + * render it as a non-circular ellipse rather than a round circle). + */ + Kind_Ellipse = 8; + /* + * u-d-v: 2D vehicle outline drawn on the map. Vertices carry the + * outline polygon; receivers draw it as a filled polygon. + */ + Kind_Vehicle2D = 9; + /* + * u-d-v-m: 3D vehicle model reference. Same vertex polygon as + * Kind_Vehicle2D; receivers that support 3D rendering extrude it. + */ + Kind_Vehicle3D = 10; + } + /* + * Explicit stroke/fill/both discriminator. + * + * ATAK's source XML distinguishes "stroke-only polyline" from "closed shape + * with both stroke and fill" by the presence of the element. + * Both states can hash to all-zero color fields, so we carry the signal + * explicitly. Parser sets this from (sawStrokeColor, sawFillColor) at the + * end of parse; builder uses it to decide which of / + * to emit in the reconstructed XML. + */ + enum StyleMode { + /* + * Unspecified — receiver infers from which color fields are non-zero. + */ + StyleMode_Unspecified = 0; + /* + * Stroke only. No in the source XML. Used for polylines, + * ranging lines, bullseye rings. + */ + StyleMode_StrokeOnly = 1; + /* + * Fill only. No in the source XML. Rare but valid in + * ATAK (solid region with no outline). + */ + StyleMode_FillOnly = 2; + /* + * Both stroke and fill present. Closed shapes: circle, rectangle, + * polygon, ranging circle. + */ + StyleMode_StrokeAndFill = 3; + } + /* + * Shape kind (circle, rectangle, freeform, etc.) + */ + Kind kind = 1; + /* + * Explicit stroke/fill/both discriminator. See StyleMode doc. + */ + StyleMode style = 2; + /* + * Ellipse major radius in centimeters. 0 for non-ellipse kinds. + */ + uint32 major_cm = 3; + /* + * Ellipse minor radius in centimeters. 0 for non-ellipse kinds. + */ + uint32 minor_cm = 4; + /* + * Ellipse rotation angle in degrees. Valid values are 0..360 inclusive; + * 0 and 360 are equivalent rotations. In proto3, an unset uint32 reads + * as 0, so senders should emit 0 when the angle is unspecified. + */ + uint32 angle_deg = 5; + /* + * Stroke color as a named palette entry from the Team enum. If + * Unspecifed_Color, the exact ARGB is carried in stroke_argb. + * Valid only when style is StrokeOnly or StrokeAndFill. + */ + Team stroke_color = 6; + /* + * Stroke color as an exact 32-bit ARGB bit pattern. Always populated + * on the wire; readers MUST use this value when stroke_color == + * Unspecifed_Color and MAY use it to recover the exact original bytes + * even when a palette entry is set. + */ + fixed32 stroke_argb = 7; + /* + * Stroke weight in tenths of a unit (e.g. 30 = 3.0). Typical ATAK + * range 10..60. + */ + uint32 stroke_weight_x10 = 8; + /* + * Fill color as a named palette entry. See stroke_color docs. + * Valid only when style is FillOnly or StrokeAndFill. + */ + Team fill_color = 9; + /* + * Fill color exact ARGB fallback. See stroke_argb docs. + */ + fixed32 fill_argb = 10; + /* + * Whether labels are rendered on this shape. + */ + bool labels_on = 11; + /* + * Vertex list for polyline/polygon/rectangle shapes. Capped at 32 by + * the nanopb pool; senders MUST truncate longer inputs and set + * `truncated = true`. + */ + repeated CotGeoPoint vertices = 12; + /* + * True if the sender truncated `vertices` to fit the pool. + */ + bool truncated = 13; + // --- Bullseye-only fields. All ignored unless kind == Kind_Bullseye. --- + /* + * Bullseye distance in meters * 10 (e.g. 3285 = 328.5 m). 0 = unset. + */ + uint32 bullseye_distance_dm = 14; + /* + * Bullseye bearing reference: 0 unset, 1 Magnetic, 2 True, 3 Grid. + */ + uint32 bullseye_bearing_ref = 15; + /* + * Bullseye attribute bit flags: + * bit 0: rangeRingVisible + * bit 1: hasRangeRings + * bit 2: edgeToCenter + * bit 3: mils + */ + uint32 bullseye_flags = 16; + /* + * Bullseye reference UID (anchor marker). Empty = anchor is self. + */ + string bullseye_uid_ref = 17; +} + +/* + * Fixed point of interest: spot marker, waypoint, checkpoint, 2525 symbol, + * or custom icon. + * + * Covers CoT types b-m-p-s-m, b-m-p-w, b-m-p-c, b-m-p-s-p-i, b-m-p-s-p-loc, + * plus a-u-G / a-f-G / a-h-G / a-n-G with iconset paths. The marker position + * is carried on TAKPacketV2.latitude_i/longitude_i; fields below carry only + * the marker-specific metadata. + */ +message Marker { + /* + * Marker kind. Used to pick sensible receiver defaults when the CoT type + * alone is ambiguous (e.g. a-u-G could be a 2525 symbol or a custom icon + * depending on the iconset path). + */ + enum Kind { + /* + * Unspecified — fall back to TAKPacketV2.cot_type_id + */ + Kind_Unspecified = 0; + /* + * b-m-p-s-m: Spot map marker + */ + Kind_Spot = 1; + /* + * b-m-p-w: Route waypoint + */ + Kind_Waypoint = 2; + /* + * b-m-p-c: Checkpoint + */ + Kind_Checkpoint = 3; + /* + * b-m-p-s-p-i / b-m-p-s-p-loc: Self-position marker + */ + Kind_SelfPosition = 4; + /* + * 2525B/C military symbol (iconsetpath = COT_MAPPING_2525B/...) + */ + Kind_Symbol2525 = 5; + /* + * COT_MAPPING_SPOTMAP icon (e.g. colored dot) + */ + Kind_SpotMap = 6; + /* + * Custom icon set (UUID/GroupName/filename.png) + */ + Kind_CustomIcon = 7; + /* + * b-m-p-w-GOTO: Go To / bloodhound navigation waypoint. + */ + Kind_GoToPoint = 8; + /* + * b-m-p-c-ip: Initial point (mission planning control point). + */ + Kind_InitialPoint = 9; + /* + * b-m-p-c-cp: Contact point (mission planning control point). + */ + Kind_ContactPoint = 10; + /* + * b-m-p-s-p-op: Observation post. + */ + Kind_ObservationPost = 11; + /* + * b-i-x-i: Quick Pic geotagged image marker. iconset carries the + * image reference (local filename or remote URL); the image itself + * does not ride on the LoRa wire. + */ + Kind_ImageMarker = 12; + } + /* + * Marker kind + */ + Kind kind = 1; + /* + * Marker color as a named palette entry. If Unspecifed_Color, the exact + * ARGB is in color_argb. + */ + Team color = 2; + /* + * Marker color exact ARGB bit pattern. Always populated on the wire. + */ + fixed32 color_argb = 3; + /* + * Status readiness flag (ATAK ). + */ + bool readiness = 4; + /* + * Parent link UID (ATAK ). Empty = no parent. + * For spot/waypoint markers this is typically the producing TAK user's UID. + */ + string parent_uid = 5; + /* + * Parent CoT type (e.g. "a-f-G-U-C"). Usually the parent TAK user's type. + */ + string parent_type = 6; + /* + * Parent callsign (e.g. "HOPE"). + */ + string parent_callsign = 7; + /* + * Iconset path stored verbatim. ATAK emits three flavors: + * Kind_Symbol2525 -> "COT_MAPPING_2525B//" + * Kind_SpotMap -> "COT_MAPPING_SPOTMAP//" + * Kind_CustomIcon -> "//.png" + * Stored end-to-end without prefix stripping; the ~19 bytes saved by + * stripping well-known prefixes are not worth the builder-side bug + * surface, and the dict compresses the repetition effectively. + */ + string iconset = 8; +} + +/* + * Range and bearing measurement line from the event anchor to a target point. + * + * Covers CoT type u-rb-a. The anchor position is on + * TAKPacketV2.latitude_i/longitude_i; the target endpoint is carried as a + * CotGeoPoint — same delta-from-anchor encoding used by DrawnShape.vertices + * so a self-anchored RAB (common case) encodes in zero bytes. + */ +message RangeAndBearing { + /* + * Target/anchor endpoint (delta-encoded from TAKPacketV2.latitude_i/longitude_i). + */ + CotGeoPoint anchor = 1; + /* + * Anchor UID (from ). Empty = free-standing. + */ + string anchor_uid = 2; + /* + * Range in centimeters (value * 100). Range 0..4294 km. + */ + uint32 range_cm = 3; + /* + * Bearing in degrees * 100 (0..36000). + */ + uint32 bearing_cdeg = 4; + /* + * Stroke color as a Team palette entry. See DrawnShape.stroke_color doc. + */ + Team stroke_color = 5; + /* + * Stroke color exact ARGB fallback. + */ + fixed32 stroke_argb = 6; + /* + * Stroke weight * 10 (e.g. 30 = 3.0). + */ + uint32 stroke_weight_x10 = 7; +} + +/* + * Named route consisting of ordered waypoints and control points. + * + * Covers CoT type b-m-r. The first waypoint's position is on + * TAKPacketV2.latitude_i/longitude_i; subsequent waypoints and checkpoints + * are in `links`. Link count is capped at 16 by the nanopb pool; senders + * MUST truncate longer routes and set `truncated = true`. + */ +message Route { + /* + * Travel method for the route. + */ + enum Method { + /* + * Unspecified / unknown + */ + Method_Unspecified = 0; + /* + * Driving / vehicle + */ + Method_Driving = 1; + /* + * Walking / foot + */ + Method_Walking = 2; + /* + * Flying + */ + Method_Flying = 3; + /* + * Swimming (individual) + */ + Method_Swimming = 4; + /* + * Watercraft (boat) + */ + Method_Watercraft = 5; + } + /* + * Route direction (infil = ingress, exfil = egress). + */ + enum Direction { + /* + * Unspecified + */ + Direction_Unspecified = 0; + /* + * Infiltration (ingress) + */ + Direction_Infil = 1; + /* + * Exfiltration (egress) + */ + Direction_Exfil = 2; + } + /* + * Route waypoint or control point. Each link corresponds to one ATAK + * entry inside the b-m-r event. + */ + message Link { + /* + * Waypoint position (delta-encoded from TAKPacketV2.latitude_i/longitude_i). + */ + CotGeoPoint point = 1; + /* + * Optional UID (empty = receiver derives). + */ + string uid = 2; + /* + * Optional display callsign (e.g. "CP1"). Empty for unnamed control points. + */ + string callsign = 3; + /* + * Link role: 0 = waypoint (b-m-p-w), 1 = checkpoint (b-m-p-c). + */ + uint32 link_type = 4; + } + /* + * Travel method + */ + Method method = 1; + /* + * Direction (infil/exfil) + */ + Direction direction = 2; + /* + * Waypoint name prefix (e.g. "CP"). + */ + string prefix = 3; + /* + * Stroke weight * 10 (e.g. 30 = 3.0). 0 = default. + */ + uint32 stroke_weight_x10 = 4; + /* + * Ordered list of route control points. Capped at 16. + */ + repeated Link links = 5; + /* + * True if the sender truncated `links` to fit the pool. + */ + bool truncated = 6; +} + +/* + * 9-line MEDEVAC request (CoT type b-r-f-h-c). + * + * Mirrors the ATAK MedLine tool's <_medevac_> detail element. Every field + * is optional (proto3 default); senders omit lines they don't have. The + * envelope (TAKPacketV2.uid, cot_type_id=b-r-f-h-c, latitude_i/longitude_i, + * altitude, callsign) carries Line 1 (location) and Line 2 (callsign). + * + * All numeric fields are tight varints so a complete 9-line request fits + * in well under 100 bytes of proto on the wire. + */ +message CasevacReport { + /* + * Line 3: precedence / urgency. + */ + enum Precedence { + Precedence_Unspecified = 0; + Precedence_Urgent = 1; // A - immediate, life-threatening + Precedence_UrgentSurgical = 2; // B - needs surgery + Precedence_Priority = 3; // C - within 4 hours + Precedence_Routine = 4; // D - within 24 hours + Precedence_Convenience = 5; // E - convenience + } + /* + * Line 7: HLZ marking method. + */ + enum HlzMarking { + HlzMarking_Unspecified = 0; + HlzMarking_Panels = 1; + HlzMarking_PyroSignal = 2; + HlzMarking_Smoke = 3; + HlzMarking_None = 4; + HlzMarking_Other = 5; + } + /* + * Line 6: security situation at the pickup zone. + */ + enum Security { + Security_Unspecified = 0; + Security_NoEnemy = 1; // N - no enemy activity + Security_PossibleEnemy = 2; // P - possible enemy + Security_EnemyInArea = 3; // E - enemy, approach with caution + Security_EnemyInArmedContact = 4; // X - armed escort required + } + + /* + * Line 3: precedence / urgency. + */ + Precedence precedence = 1; + /* + * Line 4: special equipment required, as a bitfield. + * bit 0: none + * bit 1: hoist + * bit 2: extraction equipment + * bit 3: ventilator + * bit 4: blood + */ + uint32 equipment_flags = 2; + /* + * Line 5: number of litter (stretcher-bound) patients. + */ + uint32 litter_patients = 3; + /* + * Line 5: number of ambulatory (walking-wounded) patients. + */ + uint32 ambulatory_patients = 4; + /* + * Line 6: security situation at the PZ. + */ + Security security = 5; + /* + * Line 7: HLZ marking method. + */ + HlzMarking hlz_marking = 6; + /* + * Line 7 supplementary: short free-text describing the zone marker + * (e.g. "Green smoke", "VS-17 panel west"). Capped tight in options. + */ + string zone_marker = 7; + // --- Line 8: patient nationality counts --- + uint32 us_military = 8; + uint32 us_civilian = 9; + uint32 non_us_military = 10; + uint32 non_us_civilian = 11; + uint32 epw = 12; // enemy prisoner of war + uint32 child = 13; + /* + * Line 9: terrain and obstacles at the PZ, as a bitfield. + * bit 0: slope + * bit 1: rough + * bit 2: loose + * bit 3: trees + * bit 4: wires + * bit 5: other + */ + uint32 terrain_flags = 14; + /* + * Line 2: radio frequency / callsign metadata (e.g. "38.90 Mhz" or + * "Victor 6"). Capped tight in options. + */ + string frequency = 15; + + // --- v2.x medline extensions (tags 16–33) -------------------------------- + // + // Fields 16+ cost a 2-byte tag instead of 1 byte, but they're usually + // sparse so the on-wire delta is modest when most stay unset. A fully + // populated CASEVAC with 13 free-text fields + 2 ZMIST entries can run + // 200-400 bytes compressed, i.e. potentially over the 237 B LoRa MTU. + // Callers that hit the MTU on the `compressWithRemarksFallback` path + // SHOULD strip the tier-2 situational fields (tags 28-32 + terrain_other_detail) + // before dropping the packet entirely. See README "CASEVAC tier-2 stripping". + + /* + * Short title / MEDEVAC identifier (e.g. "EAGLE.15.181230"). Usually the + * same as the envelope callsign but ATAK sometimes carries a distinct + * ops-number here. + */ + string title = 16; + /* + * Primary medline free-text — the single most clinically important line + * on a MEDLINE form (e.g. "2 urgent litter patients, smoke on approach"). + * MUST be preserved under MTU pressure as long as any casevac is sent. + */ + string medline_remarks = 17; + + /* + * Line 3 (newer ATAK format): patient counts by precedence level. + * Coexists with the enum-style `precedence` field (tag 1) — older ATAK + * emits a single enum, newer ATAK emits these counts, and both can be + * set simultaneously. Senders populate whichever style(s) the source + * XML had; receivers prefer counts when non-zero. + */ + uint32 urgent_count = 18; + uint32 urgent_surgical_count = 19; + uint32 priority_count = 20; + uint32 routine_count = 21; + uint32 convenience_count = 22; + + /* + * Line 4 supplementary: free-text description of non-standard equipment + * (e.g. "Blood warmer"). Pairs with the `equipment_flags` bitfield. + */ + string equipment_detail = 23; + /* + * Line 1 override: MGRS grid when distinct from the event anchor point + * (e.g. "34T CQ 12345 67890"). Event lat/lon/hae still carries the + * numeric location; this field preserves the exact MGRS string the + * medic entered. + */ + string zone_protected_coord = 24; + /* + * Line 9 supplementary: slope direction (e.g. "N", "NE", "SSW") when + * `terrain_flags` bit 0 (slope) is set. + */ + string terrain_slope_dir = 25; + /* + * Line 9 supplementary: free-text description of "other" terrain hazards + * (e.g. "Loose debris on west edge") when `terrain_flags` bit 5 (other) + * is set. Tier-2 strippable under MTU pressure. + */ + string terrain_other_detail = 26; + /* + * Line 7 supplementary: how the zone is being marked right now + * (e.g. "Orange smoke", "VS-17 panel"). Complements the structured + * `hlz_marking` enum with a specific human-readable description. + */ + string marked_by = 27; + + // --- Tier-2 situational awareness (stripped first under MTU pressure) --- + // These fields are free-text context that helps the receiver plan the + // approach but aren't strictly required to evacuate the patient. + + /* + * Nearby obstacles on the approach (e.g. "Power lines north of HLZ"). + */ + string obstacles = 28; + /* + * Wind direction and speed (e.g. "270 at 12 kts"). + */ + string winds_are_from = 29; + /* + * Friendly forces posture near the pickup zone + * (e.g. "Squad east of HLZ"). + */ + string friendlies = 30; + /* + * Known or suspected enemy positions near the pickup zone + * (e.g. "Possible enemy on south ridge"). + */ + string enemy = 31; + /* + * Free-text description of the HLZ itself + * (e.g. "Primary HLZ is soccer field"). + */ + string hlz_remarks = 32; + + /* + * Per-patient clinical records. Each entry is one patient's ZMIST card + * (Zap number / Mechanism / Injuries / Signs / Treatment). Repeatable — + * a mass-casualty event can carry 1-6 entries in practice, limited by + * the 237 B LoRa MTU. + */ + repeated ZMistEntry zmist = 33; +} + +/* + * Per-patient clinical summary record — one entry per patient in a CASEVAC. + * Maps directly to ATAK's child element inside . + * All fields are optional free-text; senders populate what they have. + */ +message ZMistEntry { + /* + * Patient identifier / sequence label (e.g. "ZMIST-1", "ZMIST-2"). + */ + string title = 1; + /* + * Zap number — unique patient tracking ID (often a terse code like + * "Gunshot" or a serial). + */ + string z = 2; + /* + * Mechanism of injury (e.g. "Penetrating trauma", "Blast injury"). + */ + string m = 3; + /* + * Injuries observed (e.g. "Left thigh", "Concussion"). + */ + string i = 4; + /* + * Signs / vital stats (e.g. "Stable", "Priority", "BP 110/70"). + */ + string s = 5; + /* + * Treatment given (e.g. "Tourniquet 1810Z", "O2 administered"). + */ + string t = 6; +} + +/* + * Emergency alert / 911 beacon (CoT types b-a-o-tbl, b-a-o-pan, b-a-o-opn, + * b-a-o-can, b-a-o-c, b-a-g). + * + * Small, high-priority structured record. The CoT type string is still set + * on cot_type_id so receivers that ignore payload_variant can still display + * the alert from the enum alone; the typed fields let modern receivers show + * the authoring unit and handle cancel-referencing without XML parsing. + */ +message EmergencyAlert { + enum Type { + Type_Unspecified = 0; + Type_Alert911 = 1; // b-a-o-tbl + Type_RingTheBell = 2; // b-a-o-pan + Type_InContact = 3; // b-a-o-opn + Type_GeoFenceBreached = 4; // b-a-g + Type_Custom = 5; // b-a-o-c + Type_Cancel = 6; // b-a-o-can + } + /* + * Alert discriminator. + */ + Type type = 1; + /* + * UID of the unit that raised the alert. Often the same as + * TAKPacketV2.uid but can be a parent device uid when a tracker raises + * an alert on behalf of a dismount. + */ + string authoring_uid = 2; + /* + * For Type_Cancel: the uid of the alert being cancelled. Empty for + * non-cancel alert types. + */ + string cancel_reference_uid = 3; +} + +/* + * Task / engage request (CoT type t-s). + * + * Mirrors ATAK's TaskCotReceiver / CotTaskBuilder workflow. The envelope + * carries the task's originating uid (implicit requester), position, and + * creation time; the fields below carry structured metadata the raw-detail + * fallback currently loses. + * + * Fields are deliberately lean — this variant is closer to the MTU ceiling + * than the others, so every string is capped in options. + */ +message TaskRequest { + enum Priority { + Priority_Unspecified = 0; + Priority_Low = 1; + Priority_Normal = 2; + Priority_High = 3; + Priority_Critical = 4; + } + enum Status { + Status_Unspecified = 0; + Status_Pending = 1; // assigned, not yet acknowledged + Status_Acknowledged = 2; // assignee has seen it + Status_InProgress = 3; // assignee is working it + Status_Completed = 4; // task done + Status_Cancelled = 5; // cancelled before completion + } + + /* + * Short tag for the task category (e.g. "engage", "observe", "recon", + * "rescue"). Free text on the wire so ATAK-specific task taxonomies + * don't need proto coordination; capped tight in options. + */ + string task_type = 1; + /* + * UID of the target / map item being tasked. + */ + string target_uid = 2; + /* + * UID of the assigned unit. Empty = unassigned / broadcast task. + */ + string assignee_uid = 3; + Priority priority = 4; + Status status = 5; + /* + * Optional short note (reason, constraints, grid reference). Capped + * tight in options to keep the worst-case under the LoRa MTU. + */ + string note = 6; +} + +/* + * Weather annotation from CoT detail element. + * + * Attaches to any TAKPacketV2 regardless of payload_variant — an Aircraft, + * PLI, or Marker can all carry observed conditions at the emitting station. + * ATAK-CIV ships an XSD for but no dedicated handler, so the + * element round-trips through the generic detail pipeline; this message + * promotes it to a first-class structured field. + * + * Target wire cost: ~6-8 bytes compressed with a fully populated instance. + * + * Named `TAKEnvironment` (not just `Environment`) because the bare name + * collides with `SwiftUI.Environment` — every SwiftUI view in a consuming + * iOS app uses the `@Environment` property wrapper, and importing the + * generated proto module would make `Environment` ambiguous in every one + * of those files. The `TAK` prefix matches the convention used by the + * outer `TAKPacketV2` wrapper and is unambiguous across all target + * languages (Swift, Kotlin, Python, TypeScript, C#). + */ +message TAKEnvironment { + /* + * Temperature in deci-degrees Celsius. 225 = 22.5°C. + * Range covers -50°C to +50°C (-500 to +500) which spans every realistic + * outdoor TAK deployment. sint32 because negative temps are common in + * cold-weather ops. + */ + sint32 temperature_c_x10 = 1; + /* + * Wind direction in whole degrees, 0-359. "Direction FROM" per + * meteorological convention (matches CoT / ATAK). + */ + uint32 wind_direction_deg = 2; + /* + * Wind speed in cm/s. Matches the unit of TAKPacketV2.speed for + * consistency. 1200 = 12.00 m/s = ~27 mph. + */ + uint32 wind_speed_cm_s = 3; +} + +/* + * Sensor field-of-view cone from CoT detail element. + * + * Encodes the 8 geometry attributes that ATAK-CIV's SensorDetailHandler + * reads from the wire; drops the 9 visual-styling attributes that are + * receiver-side render hints (fovAlpha, fovRed/Green/Blue, strokeColor, + * strokeWeight, displayMagneticReference, hideFov, fovLabels, rangeLines). + * The receiving ATAK client restores those from its own defaults, same as + * every other CoT carried over Meshtastic today. + * + * Attaches to any TAKPacketV2 — a PLI with a sensor on the operator's head, + * an Aircraft with a FLIR turret, a Marker dropped on a UAV. + * Target wire cost: ~7-14 bytes compressed (dominated by model string). + */ +message SensorFov { + /* + * Coarse sensor category, inferred from `model` on parse when the source + * XML doesn't label it. Receivers that render differently per sensor + * class (thermal overlay vs daylight cone) use this. + */ + enum SensorType { + SensorType_Unspecified = 0; + SensorType_Camera = 1; // daylight / general optical + SensorType_Thermal = 2; // FLIR, thermal imager + SensorType_Laser = 3; // rangefinder, LRF, designator + SensorType_Nvg = 4; // night vision goggles + SensorType_Rf = 5; // radio/radar direction-finding + SensorType_Other = 6; + } + + SensorType type = 1; + /* + * Azimuth in whole degrees, 0-359. "Pointing direction" of the cone axis, + * measured clockwise from true north. Whole degrees match ATAK-CIV's + * SensorDetailHandler default (270°) and save varint bytes over centi-deg. + */ + uint32 azimuth_deg = 2; + /* + * Maximum range of the cone in meters. + * Optional — if unset, receivers should use the ATAK-CIV default of 100m. + */ + optional uint32 range_m = 3; + /* + * Horizontal field of view in whole degrees (cone's angular width). + * ATAK-CIV default is 45°. + */ + uint32 fov_horizontal_deg = 4; + /* + * Vertical field of view in whole degrees. ATAK-CIV default is 45°. + * Optional — a value of 0 means "not set / use horizontal FOV". + */ + uint32 fov_vertical_deg = 5; + /* + * Elevation angle in whole degrees. Positive = up, negative = down. + * Range -90 to +90. sint32 for varint efficiency on small negatives. + */ + sint32 elevation_deg = 6; + /* + * Roll (camera tilt) in whole degrees, -180 to +180. + * Optional — use 0 if the sensor doesn't track roll. + */ + sint32 roll_deg = 7; + /* + * Free-form device model identifier, e.g. "FLIR-Boson-640", "SEEK". + * Optional — empty string means "unknown model" (ATAK-CIV default). + */ + string model = 8; +} + +/* + * ATAK v2 packet with expanded CoT field support and zstd dictionary compression. + * Sent on ATAK_PLUGIN_V2 port. The wire payload is: + * [1 byte flags][zstd-compressed TAKPacketV2 protobuf] + * Flags byte: bits 0-5 = dictionary ID, bits 6-7 = reserved. + */ +message TAKPacketV2 { + /* + * Well-known CoT event type enum. + * Use CotType_Other with cot_type_str for unknown types. + */ + CotType cot_type_id = 1; + /* + * How the coordinates were generated + */ + CotHow how = 2; + /* + * Callsign + */ + string callsign = 3; + /* + * Team color assignment + */ + Team team = 4; + /* + * Role of the group member + */ + MemberRole role = 5; + /* + * Latitude, multiply by 1e-7 to get degrees in floating point + */ + sfixed32 latitude_i = 6; + /* + * Longitude, multiply by 1e-7 to get degrees in floating point + */ + sfixed32 longitude_i = 7; + /* + * Altitude in meters (HAE) + */ + sint32 altitude = 8; + /* + * Speed in cm/s + */ + uint32 speed = 9; + /* + * Course in degrees * 100 (0-36000) + */ + uint32 course = 10; + /* + * Battery level 0-100 + */ + uint32 battery = 11; + /* + * Geopoint source + */ + GeoPointSource geo_src = 12; + /* + * Altitude source + */ + GeoPointSource alt_src = 13; + /* + * Device UID (UUID string or device ID like "ANDROID-xxxx") + */ + string uid = 14; + /* + * Device callsign + */ + string device_callsign = 15; + /* + * Stale time as seconds offset from event time + */ + uint32 stale_seconds = 16; + /* + * TAK client version string + */ + string tak_version = 17; + /* + * TAK device model + */ + string tak_device = 18; + /* + * TAK platform (ATAK-CIV, WebTAK, etc.) + */ + string tak_platform = 19; + /* + * TAK OS version + */ + string tak_os = 20; + /* + * Connection endpoint + */ + string endpoint = 21; + /* + * Phone number + */ + string phone = 22; + /* + * CoT event type string, only populated when cot_type_id is CotType_Other + */ + string cot_type_str = 23; + /* + * Optional remarks / free-text annotation from the element. + * Populated for non-GeoChat payload types (shapes, markers, routes, etc.) + * when the original CoT event carried non-empty remarks text. + * GeoChat messages carry their text in GeoChat.message instead. + * Empty string (proto3 default) means no remarks were present. + */ + string remarks = 24; + + // --- Sensor / environment annotations ---------------------------------- + // + // Both fields are OPTIONAL and attach to any payload_variant. They + // describe observed conditions at the emitting station — a PLI with + // environment data, an Aircraft with a sensor cone, a Marker with both. + // Absent by default; presence is signaled by the message being non-null. + + /* + * Observed weather conditions (temperature, wind). From . + * Type is `TAKEnvironment`, not `Environment`, to avoid colliding with + * SwiftUI's `@Environment` property wrapper in iOS consumers. + */ + optional TAKEnvironment environment = 25; + /* + * Sensor field-of-view cone (camera, FLIR, laser, etc.). From . + */ + optional SensorFov sensor_fov = 26; + + reserved 27, 28, 29; + // Tags 27, 28, 29 reserved for future top-level annotations before the + // payload_variant oneof resumes at 30. + + /* + * The payload of the packet + */ + oneof payload_variant { + /* + * Position report (true = PLI, no extra fields beyond the common ones above) + */ + bool pli = 30; + /* + * ATAK GeoChat message + */ + GeoChat chat = 31; + /* + * Aircraft track data (ADS-B, military air) + */ + AircraftTrack aircraft = 32; + /* + * Generic CoT detail XML for unmapped types. Kept as a fallback for CoT + * types not yet promoted to a typed variant; drawings, markers, ranging + * tools, and routes have dedicated variants below and should not land here. + */ + bytes raw_detail = 33; + /* + * User-drawn tactical graphic: circle, rectangle, polygon, polyline, + * telestration, ranging circle, or bullseye. See DrawnShape. + */ + DrawnShape shape = 34; + /* + * Fixed point of interest: spot marker, waypoint, checkpoint, 2525 + * symbol, or custom icon. See Marker. + */ + Marker marker = 35; + /* + * Range and bearing measurement line. See RangeAndBearing. + */ + RangeAndBearing rab = 36; + /* + * Named route with ordered waypoints and control points. See Route. + */ + Route route = 37; + /* + * 9-line MEDEVAC request. See CasevacReport. + */ + CasevacReport casevac = 38; + /* + * Emergency beacon / 911 alert. See EmergencyAlert. + */ + EmergencyAlert emergency = 39; + /* + * Task / engage request. See TaskRequest. + */ + TaskRequest task = 40; + } +} diff --git a/meshtastic/cannedmessages.proto b/meshtastic/cannedmessages.proto index baa5134..59f3dcc 100644 --- a/meshtastic/cannedmessages.proto +++ b/meshtastic/cannedmessages.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "CannedMessageConfigProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* diff --git a/meshtastic/channel.proto b/meshtastic/channel.proto index 16c8c19..f49895a 100644 --- a/meshtastic/channel.proto +++ b/meshtastic/channel.proto @@ -1,11 +1,12 @@ syntax = "proto3"; +/* trunk-ignore(buf-lint/PACKAGE_DIRECTORY_MATCH) */ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "ChannelProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -98,10 +99,10 @@ message ModuleSettings { uint32 position_precision = 1; /* - * Controls whether or not the phone / clients should mute the current channel + * Controls whether or not the client / device should mute the current channel * Useful for noisy public channels you don't necessarily want to disable */ - bool is_client_muted = 2; + bool is_muted = 2; } /* diff --git a/meshtastic/clientonly.proto b/meshtastic/clientonly.proto index 2b919ef..c80f428 100644 --- a/meshtastic/clientonly.proto +++ b/meshtastic/clientonly.proto @@ -8,7 +8,7 @@ import "meshtastic/mesh.proto"; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "ClientOnlyProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* diff --git a/meshtastic/config.options b/meshtastic/config.options index 9310cf0..3f6d81c 100644 --- a/meshtastic/config.options +++ b/meshtastic/config.options @@ -1,5 +1,7 @@ # longest current is 45 chars, plan with a bit of buffer *DeviceConfig.tzdef max_size:65 +*DeviceConfig.buzzer_mode int_size:8 + *NetworkConfig.wifi_ssid max_size:33 *NetworkConfig.wifi_psk max_size:65 diff --git a/meshtastic/config.proto b/meshtastic/config.proto index 06a66b8..33eaa58 100644 --- a/meshtastic/config.proto +++ b/meshtastic/config.proto @@ -7,7 +7,7 @@ import "meshtastic/device_ui.proto"; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "ConfigProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; message Config { @@ -48,8 +48,9 @@ message Config { * Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list. * Technical Details: Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry * or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. + * Deprecated in v2.7.11 because it creates "holes" in the mesh rebroadcast chain. */ - REPEATER = 4; + REPEATER = 4 [deprecated = true]; /* * Description: Broadcasts GPS position packets as priority. @@ -108,6 +109,14 @@ message Config { * consuming hops. */ ROUTER_LATE = 11; + + /* + * Description: Treats packets from or to favorited nodes as ROUTER_LATE, and all other packets as CLIENT. + * Technical Details: Used for stronger attic/roof nodes to distribute messages more widely + * from weaker, indoor, or less-well-positioned nodes. Recommended for users with multiple nodes + * where one CLIENT_BASE acts as a more powerful base station, such as an attic/roof node. + */ + CLIENT_BASE = 12; } /* @@ -150,6 +159,43 @@ message Config { CORE_PORTNUMS_ONLY = 5; } + /* + * Defines buzzer behavior for audio feedback + */ + enum BuzzerMode { + /* + * Default behavior. + * Buzzer is enabled for all audio feedback including button presses and alerts. + */ + ALL_ENABLED = 0; + + /* + * Disabled. + * All buzzer audio feedback is disabled. + */ + DISABLED = 1; + + /* + * Notifications Only. + * Buzzer is enabled only for notifications and alerts, but not for button presses. + * External notification config determines the specifics of the notification behavior. + */ + NOTIFICATIONS_ONLY = 2; + + /* + * Non-notification system buzzer tones only. + * Buzzer is enabled only for non-notification tones such as button presses, startup, shutdown, but not for alerts. + */ + SYSTEM_ONLY = 3; + + /* + * Direct Message notifications only. + * Buzzer is enabled only for direct messages and alerts, but not for button presses. + * External notification config determines the specifics of the notification behavior. + */ + DIRECT_MSG_ONLY = 4; + } + /* * Sets the role of node */ @@ -159,7 +205,7 @@ message Config { * Disabling this will disable the SerialConsole by not initilizing the StreamAPI * Moved to SecurityConfig */ - bool serial_enabled = 2[deprecated = true]; + bool serial_enabled = 2 [deprecated = true]; /* * For boards without a hard wired button, this is the pin number that will be used @@ -194,7 +240,7 @@ message Config { * Clients should then limit available configuration and administrative options inside the user interface * Moved to SecurityConfig */ - bool is_managed = 9[deprecated = true]; + bool is_managed = 9 [deprecated = true]; /* * Disables the triple-press of user button to enable or disable GPS @@ -210,6 +256,12 @@ message Config { * If true, disable the default blinking LED (LED_PIN) behavior on the device */ bool led_heartbeat_disabled = 12; + + /* + * Controls buzzer behavior for audio feedback + * Defaults to ENABLED + */ + BuzzerMode buzzer_mode = 13; } /* @@ -434,7 +486,7 @@ message Config { * If non-zero, we want powermon log outputs. With the particular (bitfield) sources enabled. * Note: we picked an ID of 32 so that lower more efficient IDs can be used for more frequently used options. */ - uint64 powermon_enables = 32; + uint64 powermon_enables = 32; } /* @@ -521,6 +573,11 @@ message Config { */ uint32 enabled_protocols = 10; + /* + * Enable/Disable ipv6 support + */ + bool ipv6_enabled = 11; + /* * Available flags auxiliary network protocols */ @@ -542,45 +599,10 @@ message Config { */ message DisplayConfig { /* - * How the GPS coordinates are displayed on the OLED screen. + * Deprecated in 2.7.4: Unused */ - enum GpsCoordinateFormat { - /* - * GPS coordinates are displayed in the normal decimal degrees format: - * DD.DDDDDD DDD.DDDDDD - */ - DEC = 0; - - /* - * GPS coordinates are displayed in the degrees minutes seconds format: - * DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant - */ - DMS = 1; - - /* - * Universal Transverse Mercator format: - * ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing - */ - UTM = 2; - - /* - * Military Grid Reference System format: - * ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square, - * E is easting, N is northing - */ - MGRS = 3; - - /* - * Open Location Code (aka Plus Codes). - */ - OLC = 4; - - /* - * Ordnance Survey Grid Reference (the National Grid System of the UK). - * Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square, - * E is the easting, N is the northing - */ - OSGR = 5; + enum DeprecatedGpsCoordinateFormat { + UNUSED = 0; } /* @@ -603,24 +625,29 @@ message Config { */ enum OledType { /* - * Default / Auto + * Default / Autodetect */ OLED_AUTO = 0; /* - * Default / Auto + * Default / Autodetect */ OLED_SSD1306 = 1; /* - * Default / Auto + * Default / Autodetect */ OLED_SH1106 = 2; /* - * Can not be auto detected but set by proto. Used for 128x128 screens + * Can not be auto detected but set by proto. Used for 128x64 screens */ OLED_SH1107 = 3; + + /* + * Can not be auto detected but set by proto. Used for 128x128 screens + */ + OLED_SH1107_128_128 = 4; } /* @@ -630,9 +657,10 @@ message Config { uint32 screen_on_secs = 1; /* + * Deprecated in 2.7.4: Unused * How the GPS coordinates are formatted on the OLED screen. */ - GpsCoordinateFormat gps_format = 2; + DeprecatedGpsCoordinateFormat gps_format = 2 [deprecated = true]; /* * Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds. @@ -644,7 +672,7 @@ message Config { * If this is set, the displayed compass will always point north. if unset, the old behaviour * (top of display is heading direction) is used. */ - bool compass_north_top = 4; + bool compass_north_top = 4 [deprecated = true]; /* * Flip screen vertically, for cases that mount the screen upside down @@ -737,7 +765,7 @@ message Config { * Rotate the compass by 270 degrees and invert. */ DEGREES_270_INVERTED = 7; - } + } /* * Indicates how to rotate or invert the compass output to accurate display on the display. @@ -749,6 +777,17 @@ message Config { * If true, the device will display the time in 12-hour format on screen. */ bool use_12h_clock = 12; + + /* + * If false (default), the device will use short names for various display screens. + * If true, node names will show in long format + */ + bool use_long_node_name = 13; + + /* + * If true, the device will display message bubbles on screen. + */ + bool enable_message_bubbles = 14; } /* @@ -865,6 +904,31 @@ message Config { * Philippines 915mhz */ PH_915 = 21; + + /* + * Australia / New Zealand 433MHz + */ + ANZ_433 = 22; + + /* + * Kazakhstan 433MHz + */ + KZ_433 = 23; + + /* + * Kazakhstan 863MHz + */ + KZ_863 = 24; + + /* + * Nepal 865MHz + */ + NP_865 = 25; + + /* + * Brazil 902MHz + */ + BR_902 = 26; } /* @@ -879,8 +943,9 @@ message Config { /* * Long Range - Slow + * Deprecated in 2.7: Unpopular slow preset. */ - LONG_SLOW = 1; + LONG_SLOW = 1 [deprecated = true]; /* * Very Long Range - Slow @@ -919,6 +984,29 @@ message Config { * It is not legal to use in all regions due to this wider bandwidth. */ SHORT_TURBO = 8; + + /* + * Long Range - Turbo + * This preset performs similarly to LongFast, but with 500Khz bandwidth. + */ + LONG_TURBO = 9; + } + + enum FEM_LNA_Mode { + /* + * FEM_LNA is present but disabled + */ + DISABLED = 0; + + /* + * FEM_LNA is present and enabled + */ + ENABLED = 1; + + /* + * FEM_LNA is not present on the device + */ + NOT_PRESENT = 2; } /* @@ -1041,6 +1129,10 @@ message Config { * Sets the ok_to_mqtt bit on outgoing packets */ bool config_ok_to_mqtt = 105; + /* + * Set where LORA FEM is enabled, disabled, or not present + */ + FEM_LNA_Mode fem_lna_mode = 106; } message BluetoothConfig { @@ -1078,17 +1170,16 @@ message Config { } message SecurityConfig { - - /* - * The public key of the user's device. - * Sent out to other nodes on the mesh to allow them to compute a shared secret key. - */ + /* + * The public key of the user's device. + * Sent out to other nodes on the mesh to allow them to compute a shared secret key. + */ bytes public_key = 1; - /* - * The private key of the device. - * Used to create a shared key with a remote device. - */ + /* + * The private key of the device. + * Used to create a shared key with a remote device. + */ bytes private_key = 2; /* diff --git a/meshtastic/connection_status.proto b/meshtastic/connection_status.proto index 7551596..641e916 100644 --- a/meshtastic/connection_status.proto +++ b/meshtastic/connection_status.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "ConnStatusProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; message DeviceConnectionStatus { diff --git a/meshtastic/device_ui.options b/meshtastic/device_ui.options index 5aa61d0..a8fab46 100644 --- a/meshtastic/device_ui.options +++ b/meshtastic/device_ui.options @@ -2,6 +2,8 @@ *DeviceUIConfig.screen_timeout int_size:16 *DeviceUIConfig.ring_tone_id int_size:8 *DeviceUIConfig.calibration_data max_size:16 +*DeviceUIConfig.compass_mode int_size:8 +*DeviceUIConfig.gps_format int_size:8 *NodeFilter.node_name max_size:16 *NodeFilter.hops_away int_size:8 *NodeFilter.channel int_size:8 diff --git a/meshtastic/device_ui.proto b/meshtastic/device_ui.proto index 138f5e8..28d2910 100644 --- a/meshtastic/device_ui.proto +++ b/meshtastic/device_ui.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "DeviceUIProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -71,8 +71,77 @@ message DeviceUIConfig { * Map related data */ Map map_data = 15; -} + /* + * Compass mode + */ + CompassMode compass_mode = 16; + + /* + * RGB color for BaseUI + * 0xRRGGBB format, e.g. 0xFF0000 for red + */ + uint32 screen_rgb_color = 17; + + /* + * Clockface analog style + * true for analog clockface, false for digital clockface + */ + bool is_clockface_analog = 18; + + /* + * How the GPS coordinates are formatted on the OLED screen. + */ + GpsCoordinateFormat gps_format = 19; + + /* + * How the GPS coordinates are displayed on the OLED screen. + */ + enum GpsCoordinateFormat { + /* + * GPS coordinates are displayed in the normal decimal degrees format: + * DD.DDDDDD DDD.DDDDDD + */ + DEC = 0; + + /* + * GPS coordinates are displayed in the degrees minutes seconds format: + * DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant + */ + DMS = 1; + + /* + * Universal Transverse Mercator format: + * ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing + */ + UTM = 2; + + /* + * Military Grid Reference System format: + * ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square, + * E is easting, N is northing + */ + MGRS = 3; + + /* + * Open Location Code (aka Plus Codes). + */ + OLC = 4; + + /* + * Ordnance Survey Grid Reference (the National Grid System of the UK). + * Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square, + * E is the easting, N is the northing + */ + OSGR = 5; + + /* + * Maidenhead Locator System + * Described here: https://en.wikipedia.org/wiki/Maidenhead_Locator_System + */ + MLS = 6; + } +} message NodeFilter { /* @@ -109,7 +178,6 @@ message NodeFilter { * Filter based on channel */ int32 channel = 7; - } message NodeHighlight { @@ -137,7 +205,6 @@ message NodeHighlight { * Highlight nodes by matching name string */ string node_name = 5; - } message GeoPoint { @@ -146,14 +213,14 @@ message GeoPoint { */ int32 zoom = 1; - /* - * Coordinate: latitude - */ + /* + * Coordinate: latitude + */ int32 latitude = 2; - /* - * Coordinate: longitude - */ + /* + * Coordinate: longitude + */ int32 longitude = 3; } @@ -174,6 +241,23 @@ message Map { bool follow_gps = 3; } +enum CompassMode { + /* + * Compass with dynamic ring and heading + */ + DYNAMIC = 0; + + /* + * Compass with fixed ring and heading + */ + FIXED_RING = 1; + + /* + * Compass with heading and freeze option + */ + FREEZE_HEADING = 2; +} + enum Theme { /* * Dark @@ -278,7 +362,22 @@ enum Language { */ UKRAINIAN = 16; - /* + /* + * Bulgarian + */ + BULGARIAN = 17; + + /* + * Czech + */ + CZECH = 18; + + /* + * Danish + */ + DANISH = 19; + + /* * Simplified Chinese (experimental) */ SIMPLIFIED_CHINESE = 30; @@ -287,4 +386,4 @@ enum Language { * Traditional Chinese (experimental) */ TRADITIONAL_CHINESE = 31; - } +} diff --git a/meshtastic/deviceonly.proto b/meshtastic/deviceonly.proto index ea6ef25..b7c377a 100644 --- a/meshtastic/deviceonly.proto +++ b/meshtastic/deviceonly.proto @@ -2,21 +2,21 @@ syntax = "proto3"; package meshtastic; +/* trunk-ignore(buf-lint/COMPILE) */ import "meshtastic/channel.proto"; -import "meshtastic/mesh.proto"; -import "meshtastic/telemetry.proto"; import "meshtastic/config.proto"; import "meshtastic/localonly.proto"; +import "meshtastic/mesh.proto"; +import "meshtastic/telemetry.proto"; import "nanopb.proto"; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "DeviceOnly"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; option (nanopb_fileopt).include = ""; - /* * Position with static location information only for NodeDBLite */ @@ -94,6 +94,11 @@ message UserLite { * This is sent out to other nodes on the mesh to allow them to compute a shared secret key. */ bytes public_key = 7; + + /* + * Whether or not the node can be messaged + */ + optional bool is_unmessagable = 9; } message NodeInfoLite { @@ -159,6 +164,13 @@ message NodeInfoLite { * Last byte of the node number of the node that should be used as the next hop to reach this node. */ uint32 next_hop = 12; + + /* + * Bitfield for storing booleans. + * LSB 0 is_key_manually_verified + * LSB 1 is_muted + */ + uint32 bitfield = 13; } /* @@ -258,7 +270,7 @@ message ChannelFile { /* * The on-disk backup of the node's preferences */ - message BackupPreferences { +message BackupPreferences { /* * The version of the backup */ diff --git a/meshtastic/interdevice.proto b/meshtastic/interdevice.proto index 54e950f..f646368 100644 --- a/meshtastic/interdevice.proto +++ b/meshtastic/interdevice.proto @@ -5,16 +5,16 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "InterdeviceProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; // encapsulate up to 1k of NMEA string data enum MessageType { ACK = 0; - COLLECT_INTERVAL = 160; // in ms - BEEP_ON = 161; // duration ms - BEEP_OFF = 162; // cancel prematurely + COLLECT_INTERVAL = 160; // in ms + BEEP_ON = 161; // duration ms + BEEP_OFF = 162; // cancel prematurely SHUTDOWN = 163; POWER_ON = 164; SCD41_TEMP = 176; diff --git a/meshtastic/localonly.proto b/meshtastic/localonly.proto index bcb2796..2a6c7ca 100644 --- a/meshtastic/localonly.proto +++ b/meshtastic/localonly.proto @@ -8,7 +8,7 @@ import "meshtastic/module_config.proto"; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "LocalOnlyProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -131,6 +131,21 @@ message LocalModuleConfig { */ ModuleConfig.PaxcounterConfig paxcounter = 14; + /* + * StatusMessage Config + */ + ModuleConfig.StatusMessageConfig statusmessage = 15; + + /* + * The part of the config that is specific to the Traffic Management module + */ + ModuleConfig.TrafficManagementConfig traffic_management = 16; + + /* + * TAK Config + */ + ModuleConfig.TAKConfig tak = 17; + /* * A version integer used to invalidate old save files when we make * incompatible changes This integer is set at build time and is private to diff --git a/meshtastic/mesh.options b/meshtastic/mesh.options index e2c905d..2341e6c 100644 --- a/meshtastic/mesh.options +++ b/meshtastic/mesh.options @@ -31,6 +31,9 @@ *MyNodeInfo.air_period_tx max_count:8 *MyNodeInfo.air_period_rx max_count:8 +*MyNodeInfo.firmware_edition int_size:8 +*MyNodeInfo.nodedb_count int_size:16 + # Note: the actual limit (because of header bytes) on the size of encrypted payloads is 251 bytes, but I use 256 # here because we might need to fill with zeros for padding to encryption block size (16 bytes per block) *MeshPacket.encrypted max_size:256 @@ -58,6 +61,23 @@ *ClientNotification.message max_size:400 +*KeyVerificationNumberInform.remote_longname max_size:40 +*KeyVerificationNumberRequest.remote_longname max_size:40 +*KeyVerificationFinal.remote_longname max_size:40 +*KeyVerificationFinal.verification_characters max_size:10 + +*KeyVerification.hash1 max_size:32 +*KeyVerification.hash2 max_size:32 + +*StoreForwardPlusPlus.message_hash max_size:32 +*StoreForwardPlusPlus.commit_hash max_size:32 +*StoreForwardPlusPlus.root_hash max_size:32 +*StoreForwardPlusPlus.message max_size:240 + +*RemoteShell.payload max_size:200 + +*StatusMessage.status max_size:80 + # MyMessage.name max_size:40 # or fixed_length or fixed_count, or max_count @@ -77,4 +97,4 @@ *ChunkedPayload.chunk_count int_size:16 *ChunkedPayload.chunk_index int_size:16 -*ChunkedPayload.payload_chunk max_size:228 \ No newline at end of file +*ChunkedPayload.payload_chunk max_size:228 diff --git a/meshtastic/mesh.proto b/meshtastic/mesh.proto index 7ce744c..fb585b9 100644 --- a/meshtastic/mesh.proto +++ b/meshtastic/mesh.proto @@ -4,16 +4,16 @@ package meshtastic; import "meshtastic/channel.proto"; import "meshtastic/config.proto"; +import "meshtastic/device_ui.proto"; import "meshtastic/module_config.proto"; import "meshtastic/portnums.proto"; import "meshtastic/telemetry.proto"; import "meshtastic/xmodem.proto"; -import "meshtastic/device_ui.proto"; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "MeshProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -388,9 +388,9 @@ enum HardwareModel { LORA_RELAY_V1 = 32; /* - * TODO: REPLACE + * T-Echo Plus device from LilyGo */ - NRF52840DK = 33; + T_ECHO_PLUS = 33; /* * TODO: REPLACE @@ -564,22 +564,22 @@ enum HardwareModel { */ HELTEC_CAPSULE_SENSOR_V3 = 65; - /* + /* * Heltec Vision Master T190 with ESP32-S3 CPU, and a 1.90 inch TFT display */ HELTEC_VISION_MASTER_T190 = 66; - /* + /* * Heltec Vision Master E213 with ESP32-S3 CPU, and a 2.13 inch E-Ink display */ HELTEC_VISION_MASTER_E213 = 67; - /* + /* * Heltec Vision Master E290 with ESP32-S3 CPU, and a 2.9 inch E-Ink display */ HELTEC_VISION_MASTER_E290 = 68; - /* + /* * Heltec Mesh Node T114 board with nRF52840 CPU, and a 1.14 inch TFT display, Ultimate low-power design, * specifically adapted for the Meshtatic project */ @@ -590,7 +590,7 @@ enum HardwareModel { */ SENSECAP_INDICATOR = 70; - /* + /* * Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors. */ TRACKER_T1000_E = 71; @@ -611,7 +611,7 @@ enum HardwareModel { */ RADIOMASTER_900_BANDIT = 74; - /* + /* * Minewsemi ME25LS01 (ME25LE01_V1.0). NRF52840 w/ LR1110 radio, buttons and leds and pins. */ ME25LS01_4Y10TD = 75; @@ -640,7 +640,7 @@ enum HardwareModel { /* Seeed XIAO S3 DK*/ SEEED_XIAO_S3 = 81; - /* + /* * Nordic nRF52840+Semtech SX1262 LoRa BLE Combo Module. nRF52840+SX1262 MS24SF1 */ MS24SF1 = 82; @@ -680,7 +680,7 @@ enum HardwareModel { * Seeed XIAO nRF52840 + Wio SX1262 kit */ XIAO_NRF52_KIT = 88; - + /* * Elecrow ThinkNode M1 & M2 * https://www.elecrow.com/wiki/ThinkNode-M1_Transceiver_Device(Meshtastic)_Power_By_nRF52840.html @@ -694,6 +694,200 @@ enum HardwareModel { */ T_ETH_ELITE = 91; + /* + * Heltec HRI-3621 industrial probe + */ + HELTEC_SENSOR_HUB = 92; + + /* + * Muzi Works Muzi-Base device + */ + MUZI_BASE = 93; + + /* + * Heltec Magnetic Power Bank with Meshtastic compatible + */ + HELTEC_MESH_POCKET = 94; + + /* + * Seeed Solar Node + */ + SEEED_SOLAR_NODE = 95; + + /* + * NomadStar Meteor Pro https://nomadstar.ch/ + */ + NOMADSTAR_METEOR_PRO = 96; + + /* + * Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin + */ + CROWPANEL = 97; + + /* + * Lilygo LINK32 board with sensors + */ + LINK_32 = 98; + + /* + * Seeed Tracker L1 + */ + SEEED_WIO_TRACKER_L1 = 99; + + /* + * Seeed Tracker L1 EINK driver + */ + SEEED_WIO_TRACKER_L1_EINK = 100; + + /* + * Muzi Works R1 Neo + */ + MUZI_R1_NEO = 101; + + /* + * Lilygo T-Deck Pro + */ + T_DECK_PRO = 102; + + /* + * Lilygo TLora Pager + */ + T_LORA_PAGER = 103; + + /* + * M5Stack Reserved + */ + M5STACK_RESERVED = 104; // 0x68 + + /* + * RAKwireless WisMesh Tag + */ + WISMESH_TAG = 105; + + /* + * RAKwireless WisBlock Core RAK3312 https://docs.rakwireless.com/product-categories/wisduo/rak3112-module/overview/ + */ + RAK3312 = 106; + + /* + * Elecrow ThinkNode M5 https://www.elecrow.com/wiki/ThinkNode_M5_Meshtastic_LoRa_Signal_Transceiver_ESP32-S3.html + */ + THINKNODE_M5 = 107; + + /* + * MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices. + * https://heltec.org/project/meshsolar/ + */ + HELTEC_MESH_SOLAR = 108; + + /* + * Lilygo T-Echo Lite + */ + T_ECHO_LITE = 109; + + /* + * New Heltec LoRA32 with ESP32-S3 CPU + */ + HELTEC_V4 = 110; + + /* + * M5Stack C6L + */ + M5STACK_C6L = 111; + + /* + * M5Stack Cardputer Adv + */ + M5STACK_CARDPUTER_ADV = 112; + + /* + * ESP32S3 main controller with GPS and TFT screen. + */ + HELTEC_WIRELESS_TRACKER_V2 = 113; + + /* + * LilyGo T-Watch Ultra + */ + T_WATCH_ULTRA = 114; + + /* + * Elecrow ThinkNode M3 + */ + THINKNODE_M3 = 115; + + /* + * RAK WISMESH_TAP_V2 with ESP32-S3 CPU + */ + WISMESH_TAP_V2 = 116; + + /* + * RAK3401 + */ + RAK3401 = 117; + + /* + * RAK6421 Hat+ + */ + RAK6421 = 118; + + /* + * Elecrow ThinkNode M4 + */ + THINKNODE_M4 = 119; + + /* + * Elecrow ThinkNode M6 + */ + THINKNODE_M6 = 120; + + /* + * Elecrow Meshstick 1262 + */ + MESHSTICK_1262 = 121; + + /* + * LilyGo T-Beam 1W + */ + TBEAM_1_WATT = 122; + + /* + * LilyGo T5 S3 ePaper Pro (V1 and V2) + */ + T5_S3_EPAPER_PRO = 123; + + /* + * LilyGo T-Beam BPF (144-148Mhz) + */ + TBEAM_BPF = 124; + + /* + * LilyGo T-Mini E-paper S3 Kit + */ + MINI_EPAPER_S3 = 125; + + /* + * LilyGo T-Display S3 Pro LR1121 + */ + TDISPLAY_S3_PRO = 126; + + /* + * Heltec Mesh Node T096 board features an nRF52840 CPU and a TFT screen. + */ + HELTEC_MESH_NODE_T096 = 127; + + /* + * Seeed studio T1000-E Pro tracker card. NRF52840 w/ LR2021 radio, + * GPS, button, buzzer, and sensors. + */ + TRACKER_T1000_E_PRO = 128; + + /* + * Elecrow ThinkNode M7, M8 and M9 + */ + THINKNODE_M7 = 129; + THINKNODE_M8 = 130; + THINKNODE_M9 = 131; + /* * ------------------------------------------------------------------------------------------------------------------------------------------ * Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. @@ -776,6 +970,11 @@ message User { * This is sent out to other nodes on the mesh to allow them to compute a shared secret key. */ bytes public_key = 8; + + /* + * Whether or not the node can be messaged + */ + optional bool is_unmessagable = 9; } /* @@ -893,6 +1092,18 @@ message Routing { * Admin packet sent using PKC, but not from a public key on the admin key list */ ADMIN_PUBLIC_KEY_UNAUTHORIZED = 37; + + /* + * Airtime fairness rate limit exceeded for a packet + * This typically enforced per portnum and is used to prevent a single node from monopolizing airtime + */ + RATE_LIMIT_EXCEEDED = 38; + + /* + * PKI encryption failed, due to no public key for the remote node + * This is different from PKI_UNKNOWN_PUBKEY which indicates a failure upon receiving a packet + */ + PKI_SEND_FAIL_PUBLIC_KEY = 39; } oneof variant { @@ -976,6 +1187,197 @@ message Data { optional uint32 bitfield = 9; } +/* + * The actual over-the-mesh message doing KeyVerification + */ +message KeyVerification { + /* + * random value Selected by the requesting node + */ + uint64 nonce = 1; + + /* + * The final authoritative hash, only to be sent by NodeA at the end of the handshake + */ + bytes hash1 = 2; + + /* + * The intermediary hash (actually derived from hash1), + * sent from NodeB to NodeA in response to the initial message. + */ + bytes hash2 = 3; +} + +/* + * The actual over-the-mesh message doing store and forward++ + */ +message StoreForwardPlusPlus { + /* + * Enum of message types + */ + enum SFPP_message_type { + /* + * Send an announcement of the canonical tip of a chain + */ + CANON_ANNOUNCE = 0; + + /* + * Query whether a specific link is on the chain + */ + CHAIN_QUERY = 1; + + /* + * Request the next link in the chain + */ + LINK_REQUEST = 3; + + /* + * Provide a link to add to the chain + */ + LINK_PROVIDE = 4; + + /* + * If we must fragment, send the first half + */ + LINK_PROVIDE_FIRSTHALF = 5; + + /* + * If we must fragment, send the second half + */ + LINK_PROVIDE_SECONDHALF = 6; + } + + /* + * Which message type is this + */ + SFPP_message_type sfpp_message_type = 1; + + /* + * The hash of the specific message + */ + bytes message_hash = 2; + + /* + * The hash of a link on a chain + */ + bytes commit_hash = 3; + + /* + * the root hash of a chain + */ + bytes root_hash = 4; + + /* + * The encrypted bytes from a message + */ + bytes message = 5; + + /* + * Message ID of the contained message + */ + uint32 encapsulated_id = 6; + + /* + * Destination of the contained message + */ + uint32 encapsulated_to = 7; + + /* + * Sender of the contained message + */ + uint32 encapsulated_from = 8; + + /* + * The receive time of the message in question + */ + uint32 encapsulated_rxtime = 9; + + /* + * Used in a LINK_REQUEST to specify the message X spots back from head + */ + uint32 chain_count = 10; +} + +/* + * The actual over-the-mesh message doing RemoteShell + */ +message RemoteShell { + /* + * Frame op code for PTY session control and stream transport. + * + * Values 1-63 are client->server requests. + * Values 64-127 are server->client responses/events. + */ + enum OpCode { + OP_UNSET = 0; + + // Client -> server + OPEN = 1; + INPUT = 2; + RESIZE = 3; + CLOSE = 4; + PING = 5; + ACK = 6; + + // Server -> client + OPEN_OK = 64; + OUTPUT = 65; + CLOSED = 66; + ERROR = 67; + PONG = 68; + } + + /* + * Structured frame operation. + */ + OpCode op = 1; + + /* + * Logical PTY session identifier. + */ + uint32 session_id = 2; + + /* + * Monotonic sequence number for this frame. + */ + uint32 seq = 3; + + /* + * Cumulative ack sequence number. + */ + uint32 ack_seq = 4; + + /* + * Opaque bytes payload for INPUT/OUTPUT/ERROR and other frame bodies. + */ + bytes payload = 5; + + /* + * Terminal size columns used for OPEN/RESIZE signaling. + */ + uint32 cols = 6; + + /* + * Terminal size rows used for OPEN/RESIZE signaling. + */ + uint32 rows = 7; + + /* + * Bit flags for protocol extensions. + */ + uint32 flags = 8; + + /* + * The last sequence number TX'd. + */ + uint32 last_tx_seq = 9; + + /* + * The last sequence number RX'd. + */ + uint32 last_rx_seq = 10; +} + /* * Waypoint message, used to share arbitrary locations across the mesh */ @@ -1022,6 +1424,13 @@ message Waypoint { fixed32 icon = 8; } +/* + * Message for node status + */ +message StatusMessage { + string status = 1; +} + /* * This message will be proxied over the PhoneAPI for the client to deliver to the MQTT server */ @@ -1154,6 +1563,51 @@ message MeshPacket { DELAYED_DIRECT = 2; } + /* + * Enum to identify which transport mechanism this packet arrived over + */ + enum TransportMechanism { + /* + * The default case is that the node generated a packet itself + */ + TRANSPORT_INTERNAL = 0; + + /* + * Arrived via the primary LoRa radio + */ + TRANSPORT_LORA = 1; + + /* + * Arrived via a secondary LoRa radio + */ + TRANSPORT_LORA_ALT1 = 2; + + /* + * Arrived via a tertiary LoRa radio + */ + TRANSPORT_LORA_ALT2 = 3; + + /* + * Arrived via a quaternary LoRa radio + */ + TRANSPORT_LORA_ALT3 = 4; + + /* + * Arrived via an MQTT connection + */ + TRANSPORT_MQTT = 5; + + /* + * Arrived via Multicast UDP + */ + TRANSPORT_MULTICAST_UDP = 6; + + /* + * Arrived via API connection + */ + TRANSPORT_API = 7; + } + /* * The sending node number. * Note: Our crypto implementation uses this field as well. @@ -1163,6 +1617,10 @@ message MeshPacket { /* * The (immediate) destination for this packet + * If the value is 4,294,967,295 (maximum value of an unsigned 32bit integer), this indicates that the packet was + * not destined for a specific node, but for a channel as indicated by the value of `channel` below. + * If the value is another, this indicates that the packet was destined for a specific + * node (i.e. a kind of "Direct Message" to this node) and not broadcast on a channel. */ fixed32 to = 2; @@ -1301,6 +1759,11 @@ message MeshPacket { * Set by the firmware internally, clients are not supposed to set this. */ uint32 tx_after = 20; + + /* + * Indicates which transport mechanism this packet arrived over + */ + TransportMechanism transport_mechanism = 21; } /* @@ -1424,6 +1887,19 @@ message NodeInfo { * Persists between NodeDB internal clean ups */ bool is_ignored = 11; + + /* + * True if node public key has been verified. + * Persists between NodeDB internal clean ups + * LSB 0 of the bitfield + */ + bool is_key_manually_verified = 12; + + /* + * True if node has been muted + * Persistes between NodeDB internal clean ups + */ + bool is_muted = 13; } /* @@ -1508,6 +1984,47 @@ enum CriticalErrorCode { FLASH_CORRUPTION_UNRECOVERABLE = 13; } +/* + * Enum to indicate to clients whether this firmware is a special firmware build, like an event. + * The first 16 values are reserved for non-event special firmwares, like the Smart Citizen use case. + */ +enum FirmwareEdition { + /* + * Vanilla firmware + */ + VANILLA = 0; + + /* + * Firmware for use in the Smart Citizen environmental monitoring network + */ + SMART_CITIZEN = 1; + + /* + * Open Sauce, the maker conference held yearly in CA + */ + OPEN_SAUCE = 16; + + /* + * DEFCON, the yearly hacker conference + */ + DEFCON = 17; + + /* + * Burning Man, the yearly hippie gathering in the desert + */ + BURNING_MAN = 18; + + /* + * Hamvention, the Dayton amateur radio convention + */ + HAMVENTION = 19; + + /* + * Placeholder for DIY and unofficial events + */ + DIY_EDITION = 127; +} + /* * Unique local debugging info for this node * Note: we don't include position or the user info, because that will come in the @@ -1541,6 +2058,17 @@ message MyNodeInfo { * The PlatformIO environment used to build this firmware */ string pio_env = 13; + + /* + * The indicator for whether this device is running event firmware and which + */ + FirmwareEdition firmware_edition = 14; + + /* + * The number of nodes in the nodedb. + * This is used by the phone to know how many NodeInfo packets to expect on want_config + */ + uint32 nodedb_count = 15; } /* @@ -1758,8 +2286,34 @@ message ClientNotification { * The message body of the notification */ string message = 4; + + oneof payload_variant { + KeyVerificationNumberInform key_verification_number_inform = 11; + KeyVerificationNumberRequest key_verification_number_request = 12; + KeyVerificationFinal key_verification_final = 13; + DuplicatedPublicKey duplicated_public_key = 14; + LowEntropyKey low_entropy_key = 15; + } } +message KeyVerificationNumberInform { + uint64 nonce = 1; + string remote_longname = 2; + uint32 security_number = 3; +} +message KeyVerificationNumberRequest { + uint64 nonce = 1; + string remote_longname = 2; +} +message KeyVerificationFinal { + uint64 nonce = 1; + string remote_longname = 2; + bool isSender = 3; + string verification_characters = 4; +} +message DuplicatedPublicKey {} +message LowEntropyKey {} + /* * Individual File info for the device */ @@ -2032,13 +2586,28 @@ enum ExcludedModules { * Paxcounter module */ PAXCOUNTER_CONFIG = 0x1000; + + /* + * Bluetooth config (not technically a module, but used to indicate bluetooth capabilities) + */ + BLUETOOTH_CONFIG = 0x2000; + + /* + * Network config (not technically a module, but used to indicate network capabilities) + */ + NETWORK_CONFIG = 0x4000; } /* * A heartbeat message is sent to the node from the client to keep the connection alive. * This is currently only needed to keep serial connections alive, but can be used by any PhoneAPI. */ -message Heartbeat {} +message Heartbeat { + /* + * The nonce of the heartbeat message + */ + uint32 nonce = 1; +} /* * RemoteHardwarePins associated with a node @@ -2081,7 +2650,7 @@ message ChunkedPayload { * Wrapper message for broken repeated oneof support */ message resend_chunks { - repeated uint32 chunks = 1; + repeated uint32 chunks = 1; } /* diff --git a/meshtastic/module_config.options b/meshtastic/module_config.options index bf2a5f4..c6158be 100644 --- a/meshtastic/module_config.options +++ b/meshtastic/module_config.options @@ -27,3 +27,5 @@ *DetectionSensorConfig.monitor_pin int_size:8 *DetectionSensorConfig.name max_size:20 *DetectionSensorConfig.detection_trigger_type max_size:8 + +*StatusMessageConfig.node_status max_size:80 diff --git a/meshtastic/module_config.proto b/meshtastic/module_config.proto index 4f18d5f..10753c6 100644 --- a/meshtastic/module_config.proto +++ b/meshtastic/module_config.proto @@ -2,10 +2,12 @@ syntax = "proto3"; package meshtastic; +import "meshtastic/atak.proto"; + option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "ModuleConfigProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -95,6 +97,11 @@ message ModuleConfig { * Bits of precision for the location sent (default of 32 is full precision). */ uint32 position_precision = 2; + + /* + * Whether we have opted-in to report our location to the map + */ + bool should_report_location = 3; } /* @@ -143,7 +150,6 @@ message ModuleConfig { * Detection Sensor Module Config */ message DetectionSensorConfig { - enum TriggerType { // Event is triggered if pin is low LOGIC_LOW = 0; @@ -289,7 +295,82 @@ message ModuleConfig { * BLE RSSI threshold. Defaults to -80 */ int32 ble_threshold = 4; + } + /* + * Config for the Traffic Management module. + * Provides packet inspection and traffic shaping to help reduce channel utilization + */ + message TrafficManagementConfig { + /* + * Master enable for traffic management module + */ + bool enabled = 1; + + /* + * Enable position deduplication to drop redundant position broadcasts + */ + bool position_dedup_enabled = 2; + + /* + * Number of bits of precision for position deduplication (0-32) + */ + uint32 position_precision_bits = 3; + + /* + * Minimum interval in seconds between position updates from the same node + */ + uint32 position_min_interval_secs = 4; + + /* + * Enable direct response to NodeInfo requests from local cache + */ + bool nodeinfo_direct_response = 5; + + /* + * Minimum hop distance from requestor before responding to NodeInfo requests + */ + uint32 nodeinfo_direct_response_max_hops = 6; + + /* + * Enable per-node rate limiting to throttle chatty nodes + */ + bool rate_limit_enabled = 7; + + /* + * Time window in seconds for rate limiting calculations + */ + uint32 rate_limit_window_secs = 8; + + /* + * Maximum packets allowed per node within the rate limit window + */ + uint32 rate_limit_max_packets = 9; + + /* + * Enable dropping of unknown/undecryptable packets per rate_limit_window_secs + */ + bool drop_unknown_enabled = 10; + + /* + * Number of unknown packets before dropping from a node + */ + uint32 unknown_packet_threshold = 11; + + /* + * Set hop_limit to 0 for relayed telemetry broadcasts (own packets unaffected) + */ + bool exhaust_hop_telemetry = 12; + + /* + * Set hop_limit to 0 for relayed position broadcasts (own packets unaffected) + */ + bool exhaust_hop_position = 13; + + /* + * Preserve hop_limit for router-to-router traffic + */ + bool router_preserve_hops = 14; } /* @@ -331,6 +412,15 @@ message ModuleConfig { CALTOPO = 5; // Ecowitt WS85 weather station WS85 = 6; + // VE.Direct is a serial protocol used by Victron Energy products + // https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable + VE_DIRECT = 7; + // Used to configure and view some parameters of MeshSolar. + // https://heltec.org/project/meshsolar/ + MS_CONFIG = 8; + // Logs mesh traffic to the serial pins, ideal for logging via openLog or similar. + LOG = 9; // includes other packets + LOGTEXT = 10; // only text (channel & DM) } /* @@ -521,6 +611,12 @@ message ModuleConfig { * ESP32 Only */ bool save = 3; + + /* + * Bool indicating that the node should cleanup / destroy it's RangeTest.csv file. + * ESP32 Only + */ + bool clear_on_reboot = 4; } /* @@ -600,6 +696,17 @@ message ModuleConfig { * Enable/Disable the health telemetry module on-device display */ bool health_screen_enabled = 13; + + /* + * Enable/Disable the device telemetry module to send metrics to the mesh + * Note: We will still send telemtry to the connected phone / client every minute over the API + */ + bool device_telemetry_enabled = 14; + + /* + * Enable/Disable the air quality telemetry measurement module on-device display + */ + bool air_quality_screen_enabled = 15; } /* @@ -694,13 +801,13 @@ message ModuleConfig { /* * Enable/disable CannedMessageModule. */ - bool enabled = 9; + bool enabled = 9 [deprecated = true]; /* * Input event origin accepted by the canned message module. * Can be e.g. "rotEnc1", "upDownEnc1", "scanAndSelect", "cardkb", "serialkb", or keyword "_any" */ - string allow_input_source = 10; + string allow_input_source = 10 [deprecated = true]; /* * CannedMessageModule also sends a bell character with the messages. @@ -740,6 +847,16 @@ message ModuleConfig { uint32 blue = 5; } + /* + * StatusMessage config - Allows setting a status message for a node to periodically rebroadcast + */ + message StatusMessageConfig { + /* + * The actual status string + */ + string node_status = 1; + } + /* * TODO: REPLACE */ @@ -808,6 +925,37 @@ message ModuleConfig { * TODO: REPLACE */ PaxcounterConfig paxcounter = 13; + + /* + * TODO: REPLACE + */ + StatusMessageConfig statusmessage = 14; + + /* + * Traffic management module config for mesh network optimization + */ + TrafficManagementConfig traffic_management = 15; + + /* + * TAK team/role configuration for TAK_TRACKER + */ + TAKConfig tak = 16; + } + + /* + * TAK team/role configuration + */ + message TAKConfig { + /* + * Team color. + * Default Unspecifed_Color -> firmware uses Cyan + */ + Team team = 1; + /* + * Member role. + * Default Unspecifed -> firmware uses TeamMember + */ + MemberRole role = 2; } } diff --git a/meshtastic/mqtt.proto b/meshtastic/mqtt.proto index 2dbc820..616780d 100644 --- a/meshtastic/mqtt.proto +++ b/meshtastic/mqtt.proto @@ -8,7 +8,7 @@ import "meshtastic/mesh.proto"; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "MQTTProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -103,4 +103,10 @@ message MapReport { * Number of online nodes (heard in the last 2 hours) this node has in its list that were received locally (not via MQTT) */ uint32 num_online_local_nodes = 13; + + /* + * User has opted in to share their location (map report) with the mqtt server + * Controlled by map_report.should_report_location + */ + bool has_opted_report_location = 14; } diff --git a/meshtastic/paxcount.proto b/meshtastic/paxcount.proto index 47b2639..5084f9d 100644 --- a/meshtastic/paxcount.proto +++ b/meshtastic/paxcount.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "PaxcountProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* diff --git a/meshtastic/portnums.proto b/meshtastic/portnums.proto index 76df5db..61412cf 100644 --- a/meshtastic/portnums.proto +++ b/meshtastic/portnums.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "Portnums"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -110,6 +110,16 @@ enum PortNum { */ ALERT_APP = 11; + /* + * Module/port for handling key verification requests. + */ + KEY_VERIFICATION_APP = 12; + + /* + * Module/port for handling primitive remote shell access. + */ + REMOTE_SHELL_APP = 13; + /* * Provides a 'ping' service that replies to any packet it receives. * Also serves as a small example module. @@ -129,6 +139,22 @@ enum PortNum { */ PAXCOUNTER_APP = 34; + /* + * Store and Forward++ module included in the firmware + * ENCODING: protobuf + * This module is specifically for Native Linux nodes, and provides a Git-style + * chain of messages. + */ + STORE_FORWARD_PLUSPLUS_APP = 35; + + /* + * Node Status module + * ENCODING: protobuf + * This module allows setting an extra string of status for a node. + * Broadcasts on change and on a timer, possibly once a day. + */ + NODE_STATUS_APP = 36; + /* * Provides a hardware serial interface to send and receive from the Meshtastic network. * Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic @@ -206,12 +232,39 @@ enum PortNum { */ POWERSTRESS_APP = 74; + /* + * LoraWAN Payload Transport + * ENCODING: compact binary LoRaWAN uplink (10-byte RF metadata + PHY payload) - see LoRaWANBridgeModule + */ + LORAWAN_BRIDGE = 75; + /* * Reticulum Network Stack Tunnel App * ENCODING: Fragmented RNS Packet. Handled by Meshtastic RNS interface */ RETICULUM_TUNNEL_APP = 76; + /* + * App for transporting Cayenne Low Power Payload, popular for LoRaWAN sensor nodes. Offers ability to send + * arbitrary telemetry over meshtastic that is not covered by telemetry.proto + * ENCODING: CayenneLLP + */ + CAYENNE_APP = 77; + + /* + * ATAK Plugin V2 + * Portnum for payloads from the official Meshtastic ATAK plugin using + * TAKPacketV2 with zstd dictionary compression. + */ + ATAK_PLUGIN_V2 = 78; + + /* + * GroupAlarm integration + * Used for transporting GroupAlarm-related messages between Meshtastic nodes + * and companion applications/services. + */ + GROUPALARM_APP = 112; + /* * Private applications should use portnums >= 256. * To simplify initial development and testing you can use "PRIVATE_APP" diff --git a/meshtastic/powermon.proto b/meshtastic/powermon.proto index dbb89b9..5973b16 100644 --- a/meshtastic/powermon.proto +++ b/meshtastic/powermon.proto @@ -1,20 +1,20 @@ syntax = "proto3"; +package meshtastic; + option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "PowerMonProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; -package meshtastic; - /* Note: There are no 'PowerMon' messages normally in use (PowerMons are sent only as structured logs - slogs). -But we wrap our State enum in this message to effectively nest a namespace (without our linter yelling at us) -*/ + * But we wrap our State enum in this message to effectively nest a namespace (without our linter yelling at us) + */ message PowerMon { /* Any significant power changing event in meshtastic should be tagged with a powermon state transition. - If you are making new meshtastic features feel free to add new entries at the end of this definition. - */ + * If you are making new meshtastic features feel free to add new entries at the end of this definition. + */ enum State { None = 0; @@ -22,14 +22,14 @@ message PowerMon { CPU_LightSleep = 0x02; /* - The external Vext1 power is on. Many boards have auxillary power rails that the CPU turns on only - occasionally. In cases where that rail has multiple devices on it we usually want to have logging on - the state of that rail as an independent record. - For instance on the Heltec Tracker 1.1 board, this rail is the power source for the GPS and screen. + The external Vext1 power is on. Many boards have auxillary power rails that the CPU turns on only + occasionally. In cases where that rail has multiple devices on it we usually want to have logging on + the state of that rail as an independent record. + For instance on the Heltec Tracker 1.1 board, this rail is the power source for the GPS and screen. - The log messages will be short and complete (see PowerMon.Event in the protobufs for details). - something like "S:PM:C,0x00001234,REASON" where the hex number is the bitmask of all current states. - (We use a bitmask for states so that if a log message gets lost it won't be fatal) + The log messages will be short and complete (see PowerMon.Event in the protobufs for details). + something like "S:PM:C,0x00001234,REASON" where the hex number is the bitmask of all current states. + (We use a bitmask for states so that if a log message gets lost it won't be fatal) */ Vext1_On = 0x04; @@ -44,22 +44,21 @@ message PowerMon { Wifi_On = 0x400; /* - GPS is actively trying to find our location - See GPSPowerState for more details - */ + * GPS is actively trying to find our location + * See GPSPowerState for more details + */ GPS_Active = 0x800; } } - /* * PowerStress testing support via the C++ PowerStress module */ message PowerStressMessage { /* * What operation would we like the UUT to perform. - note: senders should probably set want_response in their request packets, so that they can know when the state - machine has started processing their request + * note: senders should probably set want_response in their request packets, so that they can know when the state + * machine has started processing their request */ enum Opcode { /* @@ -69,7 +68,7 @@ message PowerStressMessage { PRINT_INFO = 1; // Print board version slog and send an ack that we are alive and ready to process commands FORCE_QUIET = 2; // Try to turn off all automatic processing of packets, screen, sleeping, etc (to make it easier to measure in isolation) - END_QUIET = 3; // Stop powerstress processing - probably by just rebooting the board + END_QUIET = 3; // Stop powerstress processing - probably by just rebooting the board SCREEN_ON = 16; // Turn the screen on SCREEN_OFF = 17; // Turn the screen off diff --git a/meshtastic/remote_hardware.proto b/meshtastic/remote_hardware.proto index ba4a693..d919203 100644 --- a/meshtastic/remote_hardware.proto +++ b/meshtastic/remote_hardware.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "RemoteHardware"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* diff --git a/meshtastic/rtttl.proto b/meshtastic/rtttl.proto index 11c8b92..06d94fc 100644 --- a/meshtastic/rtttl.proto +++ b/meshtastic/rtttl.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "RTTTLConfigProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* diff --git a/meshtastic/storeforward.proto b/meshtastic/storeforward.proto index 651eae5..a4a18b2 100644 --- a/meshtastic/storeforward.proto +++ b/meshtastic/storeforward.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "StoreAndForwardProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* diff --git a/meshtastic/telemetry.options b/meshtastic/telemetry.options index a429c3e..5db1af5 100644 --- a/meshtastic/telemetry.options +++ b/meshtastic/telemetry.options @@ -4,9 +4,16 @@ *EnvironmentMetrics.iaq int_size:16 *EnvironmentMetrics.wind_direction int_size:16 *EnvironmentMetrics.soil_moisture int_size:8 +*EnvironmentMetrics.one_wire_temperature max_count:8 *LocalStats.num_online_nodes int_size:16 *LocalStats.num_total_nodes int_size:16 +*LocalStats.num_tx_dropped int_size:16 *HealthMetrics.heart_bpm int_size:8 *HealthMetrics.spO2 int_size:8 + +*HostMetrics.load1 int_size:16 +*HostMetrics.load5 int_size:16 +*HostMetrics.load15 int_size:16 +*HostMetrics.user_string max_size:200 diff --git a/meshtastic/telemetry.proto b/meshtastic/telemetry.proto index 1285b70..f541ca9 100644 --- a/meshtastic/telemetry.proto +++ b/meshtastic/telemetry.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "TelemetryProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; /* @@ -130,21 +130,21 @@ message EnvironmentMetrics { optional float wind_lull = 17; /* - * Radiation in µR/h - */ + * Radiation in µR/h + */ optional float radiation = 18; /* - * Rainfall in the last hour in mm - */ + * Rainfall in the last hour in mm + */ optional float rainfall_1h = 19; - /* - * Rainfall in the last 24 hours in mm - */ + /* + * Rainfall in the last 24 hours in mm + */ optional float rainfall_24h = 20; - /* + /* * Soil moisture measured (% 1-100) */ optional uint32 soil_moisture = 21; @@ -153,6 +153,11 @@ message EnvironmentMetrics { * Soil temperature measured (*C) */ optional float soil_temperature = 22; + + /* + * One-wire temperature (*C) + */ + repeated float one_wire_temperature = 23; } /* @@ -188,6 +193,56 @@ message PowerMetrics { * Current (Ch3) */ optional float ch3_current = 6; + + /* + * Voltage (Ch4) + */ + optional float ch4_voltage = 7; + + /* + * Current (Ch4) + */ + optional float ch4_current = 8; + + /* + * Voltage (Ch5) + */ + optional float ch5_voltage = 9; + + /* + * Current (Ch5) + */ + optional float ch5_current = 10; + + /* + * Voltage (Ch6) + */ + optional float ch6_voltage = 11; + + /* + * Current (Ch6) + */ + optional float ch6_current = 12; + + /* + * Voltage (Ch7) + */ + optional float ch7_voltage = 13; + + /* + * Current (Ch7) + */ + optional float ch7_current = 14; + + /* + * Voltage (Ch8) + */ + optional float ch8_voltage = 15; + + /* + * Current (Ch8) + */ + optional float ch8_current = 16; } /* @@ -195,69 +250,129 @@ message PowerMetrics { */ message AirQualityMetrics { /* - * Concentration Units Standard PM1.0 + * Concentration Units Standard PM1.0 in ug/m3 */ optional uint32 pm10_standard = 1; /* - * Concentration Units Standard PM2.5 + * Concentration Units Standard PM2.5 in ug/m3 */ optional uint32 pm25_standard = 2; /* - * Concentration Units Standard PM10.0 + * Concentration Units Standard PM10.0 in ug/m3 */ optional uint32 pm100_standard = 3; /* - * Concentration Units Environmental PM1.0 + * Concentration Units Environmental PM1.0 in ug/m3 */ optional uint32 pm10_environmental = 4; /* - * Concentration Units Environmental PM2.5 + * Concentration Units Environmental PM2.5 in ug/m3 */ optional uint32 pm25_environmental = 5; /* - * Concentration Units Environmental PM10.0 + * Concentration Units Environmental PM10.0 in ug/m3 */ optional uint32 pm100_environmental = 6; /* - * 0.3um Particle Count + * 0.3um Particle Count in #/0.1l */ optional uint32 particles_03um = 7; /* - * 0.5um Particle Count + * 0.5um Particle Count in #/0.1l */ optional uint32 particles_05um = 8; /* - * 1.0um Particle Count + * 1.0um Particle Count in #/0.1l */ optional uint32 particles_10um = 9; /* - * 2.5um Particle Count + * 2.5um Particle Count in #/0.1l */ optional uint32 particles_25um = 10; /* - * 5.0um Particle Count + * 5.0um Particle Count in #/0.1l */ optional uint32 particles_50um = 11; /* - * 10.0um Particle Count + * 10.0um Particle Count in #/0.1l */ optional uint32 particles_100um = 12; /* - * 10.0um Particle Count + * CO2 concentration in ppm */ optional uint32 co2 = 13; + + /* + * CO2 sensor temperature in degC + */ + optional float co2_temperature = 14; + + /* + * CO2 sensor relative humidity in % + */ + optional float co2_humidity = 15; + + /* + * Formaldehyde sensor formaldehyde concentration in ppb + */ + optional float form_formaldehyde = 16; + + /* + * Formaldehyde sensor relative humidity in %RH + */ + optional float form_humidity = 17; + + /* + * Formaldehyde sensor temperature in degrees Celsius + */ + optional float form_temperature = 18; + + /* + * Concentration Units Standard PM4.0 in ug/m3 + */ + optional uint32 pm40_standard = 19; + + /* + * 4.0um Particle Count in #/0.1l + */ + optional uint32 particles_40um = 20; + + /* + * PM Sensor Temperature + */ + optional float pm_temperature = 21; + + /* + * PM Sensor humidity + */ + optional float pm_humidity = 22; + + /* + * PM Sensor VOC Index + */ + optional float pm_voc_idx = 23; + + /* + * PM Sensor NOx Index + */ + optional float pm_nox_idx = 24; + + /* + * Typical Particle Size in um + */ + optional float particles_tps = 25; } /* @@ -318,12 +433,72 @@ message LocalStats { * This will always be zero for ROUTERs/REPEATERs. If this number is high, some other node(s) is/are relaying faster than you. */ uint32 num_tx_relay_canceled = 11; + + /* + * Number of bytes used in the heap + */ + uint32 heap_total_bytes = 12; + + /* + * Number of bytes free in the heap + */ + uint32 heap_free_bytes = 13; + + /* + * Number of packets that were dropped because the transmit queue was full. + */ + uint32 num_tx_dropped = 14; + + /* + * Noise floor value measured in dBm + */ + int32 noise_floor = 15; +} + +/* + * Traffic management statistics for mesh network optimization + */ +message TrafficManagementStats { + /* + * Total number of packets inspected by traffic management + */ + uint32 packets_inspected = 1; + + /* + * Number of position packets dropped due to deduplication + */ + uint32 position_dedup_drops = 2; + + /* + * Number of NodeInfo requests answered from cache + */ + uint32 nodeinfo_cache_hits = 3; + + /* + * Number of packets dropped due to rate limiting + */ + uint32 rate_limit_drops = 4; + + /* + * Number of unknown/undecryptable packets dropped + */ + uint32 unknown_packet_drops = 5; + + /* + * Number of packets with hop_limit exhausted for local-only broadcast + */ + uint32 hop_exhausted_packets = 6; + + /* + * Number of times router hop preservation was applied + */ + uint32 router_hops_preserved = 7; } /* * Health telemetry metrics */ - message HealthMetrics { +message HealthMetrics { /* * Heart rate (beats per minute) */ @@ -340,6 +515,57 @@ message LocalStats { optional float temperature = 3; } +/* + * Linux host metrics + */ +message HostMetrics { + /* + * Host system uptime + */ + uint32 uptime_seconds = 1; + + /* + * Host system free memory + */ + uint64 freemem_bytes = 2; + + /* + * Host system disk space free for / + */ + uint64 diskfree1_bytes = 3; + + /* + * Secondary system disk space free + */ + optional uint64 diskfree2_bytes = 4; + + /* + * Tertiary disk space free + */ + optional uint64 diskfree3_bytes = 5; + + /* + * Host system one minute load in 1/100ths + */ + uint32 load1 = 6; + + /* + * Host system five minute load in 1/100ths + */ + uint32 load5 = 7; + + /* + * Host system fifteen minute load in 1/100ths + */ + uint32 load15 = 8; + + /* + * Optional User-provided string for arbitrary host system information + * that doesn't make sense as a dedicated entry. + */ + optional string user_string = 9; +} + /* * Types of Measurements the telemetry module is equipped to handle */ @@ -379,6 +605,16 @@ message Telemetry { * Health telemetry metrics */ HealthMetrics health_metrics = 7; + + /* + * Linux host metrics + */ + HostMetrics host_metrics = 8; + + /* + * Traffic management statistics + */ + TrafficManagementStats traffic_management_stats = 9; } } @@ -422,7 +658,7 @@ enum TelemetrySensorType { BMP280 = 6; /* - * High accuracy temperature and humidity + * TODO - REMOVE High accuracy temperature and humidity */ SHTC3 = 7; @@ -447,7 +683,7 @@ enum TelemetrySensorType { QMC5883L = 11; /* - * High accuracy temperature and humidity + * TODO - REMOVE High accuracy temperature and humidity */ SHT31 = 12; @@ -472,7 +708,7 @@ enum TelemetrySensorType { RCWL9620 = 16; /* - * Sensirion High accuracy temperature and humidity + * TODO - REMOVE Sensirion High accuracy temperature and humidity */ SHT4X = 17; @@ -575,6 +811,76 @@ enum TelemetrySensorType { * RAKWireless RAK12035 Soil Moisture Sensor Module */ RAK12035 = 37; + + /* + * MAX17261 lipo battery gauge + */ + MAX17261 = 38; + + /* + * PCT2075 Temperature Sensor + */ + PCT2075 = 39; + + /* + * ADS1X15 ADC + */ + ADS1X15 = 40; + + /* + * ADS1X15 ADC_ALT + */ + ADS1X15_ALT = 41; + + /* + * Sensirion SFA30 Formaldehyde sensor + */ + SFA30 = 42; + + /* + * SEN5X PM SENSORS + */ + SEN5X = 43; + + /* + * TSL2561 light sensor + */ + TSL2561 = 44; + + /* + * BH1750 light sensor + */ + BH1750 = 45; + + /* + * HDC1080 Temperature and Humidity Sensor + */ + HDC1080 = 46; + + /* + * TODO - REMOVE STH21 Temperature and R. Humidity sensor + */ + SHT21 = 47; + + /* + * Sensirion STC31 CO2 sensor + */ + STC31 = 48; + + /* + * SCD30 CO2, humidity, temperature sensor + */ + SCD30 = 49; + + /* + * SHT family of sensors for temperature and humidity + */ + SHTXX = 50; + + /* + * DS248X Bridge for one-wire temperature sensors + */ + DS248X = 51; } /* @@ -591,3 +897,38 @@ message Nau7802Config { */ float calibrationFactor = 2; } + +/* + * SEN5X State, for saving to flash + */ +message SEN5XState { + /* + * Last cleaning time for SEN5X + */ + uint32 last_cleaning_time = 1; + + /* + * Last cleaning time for SEN5X - valid flag + */ + bool last_cleaning_valid = 2; + + /* + * Config flag for one-shot mode (see admin.proto) + */ + bool one_shot_mode = 3; + + /* + * Last VOC state time for SEN55 + */ + optional uint32 voc_state_time = 4; + + /* + * Last VOC state validity flag for SEN55 + */ + optional bool voc_state_valid = 5; + + /* + * VOC state array (8x uint8t) for SEN55 + */ + optional fixed64 voc_state_array = 6; +} diff --git a/meshtastic/xmodem.proto b/meshtastic/xmodem.proto index 732780a..2a049d1 100644 --- a/meshtastic/xmodem.proto +++ b/meshtastic/xmodem.proto @@ -5,7 +5,7 @@ package meshtastic; option csharp_namespace = "Meshtastic.Protobufs"; option go_package = "github.com/meshtastic/go/generated"; option java_outer_classname = "XmodemProtos"; -option java_package = "com.geeksville.mesh"; +option java_package = "org.meshtastic.proto"; option swift_prefix = ""; message XModem { diff --git a/nanopb.proto b/nanopb.proto index 2f27e34..1c107c1 100644 --- a/nanopb.proto +++ b/nanopb.proto @@ -9,6 +9,7 @@ syntax = "proto2"; import "google/protobuf/descriptor.proto"; +option go_package = "github.com/meshtastic/go/generated"; option java_package = "fi.kapsi.koti.jpa.nanopb"; enum FieldType { diff --git a/packages/rust/Cargo.lock b/packages/rust/Cargo.lock new file mode 100644 index 0000000..0b80556 --- /dev/null +++ b/packages/rust/Cargo.lock @@ -0,0 +1,105 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "meshtastic_protobufs" +version = "2.5.5" +dependencies = [ + "prost", + "prost-types", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +dependencies = [ + "prost", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/packages/rust/Cargo.toml b/packages/rust/Cargo.toml new file mode 100644 index 0000000..f8dda5d --- /dev/null +++ b/packages/rust/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "meshtastic_protobufs" +edition = "2021" +version = "__PACKAGE_VERSION__" +description = "Meshtastic Protobuf definitions" +repository = "https://github.com/meshtastic/protobufs" +license-file = "LICENSE" +include = [ + "**/*.rs", + "Cargo.toml", +] + +[dependencies] +prost = "0.14.3" +prost-types = "0.14.3" diff --git a/packages/rust/src/generated/.gitkeep b/packages/rust/src/generated/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/packages/rust/src/lib.rs b/packages/rust/src/lib.rs new file mode 100644 index 0000000..a5bf95a --- /dev/null +++ b/packages/rust/src/lib.rs @@ -0,0 +1,5 @@ +extern crate prost; +extern crate core; +extern crate prost_types; + +include!("generated/mod.rs"); diff --git a/packages/ts/deno.json b/packages/ts/deno.json new file mode 100644 index 0000000..99b801a --- /dev/null +++ b/packages/ts/deno.json @@ -0,0 +1,15 @@ +{ + "name": "@meshtastic/protobufs", + "version": "__PACKAGE_VERSION__", + "exports": { + ".": "./mod.ts" + }, + "imports": { + "@bufbuild/protobuf": "npm:@bufbuild/protobuf@^2.2.3" + }, + "publish": { + "exclude": [ + "!lib" + ] + } +} diff --git a/packages/ts/deno.lock b/packages/ts/deno.lock new file mode 100644 index 0000000..d39f28e --- /dev/null +++ b/packages/ts/deno.lock @@ -0,0 +1,16 @@ +{ + "version": "4", + "specifiers": { + "npm:@bufbuild/protobuf@^2.2.3": "2.2.3" + }, + "npm": { + "@bufbuild/protobuf@2.2.3": { + "integrity": "sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==" + } + }, + "workspace": { + "dependencies": [ + "npm:@bufbuild/protobuf@^2.2.3" + ] + } +} diff --git a/packages/ts/lib/.gitkeep b/packages/ts/lib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/packages/ts/mod.ts b/packages/ts/mod.ts new file mode 100644 index 0000000..b043e49 --- /dev/null +++ b/packages/ts/mod.ts @@ -0,0 +1,20 @@ +export * as Admin from "./lib/admin_pb.ts"; +export * as AppOnly from "./lib/apponly_pb.ts"; +export * as ATAK from "./lib/atak_pb.ts"; +export * as CannedMessages from "./lib/cannedmessages_pb.ts"; +export * as Channel from "./lib/channel_pb.ts"; +export * as ClientOnly from "./lib/clientonly_pb.ts"; +export * as Config from "./lib/config_pb.ts"; +export * as ConnectionStatus from "./lib/connection_status_pb.ts"; +export * as LocalOnly from "./lib/localonly_pb.ts"; +export * as Mesh from "./lib/mesh_pb.ts"; +export * as ModuleConfig from "./lib/module_config_pb.ts"; +export * as Mqtt from "./lib/mqtt_pb.ts"; +export * as PaxCount from "./lib/paxcount_pb.ts"; +export * as Portnums from "./lib/portnums_pb.ts"; +export * as PowerMon from "./lib/powermon_pb.ts"; +export * as RemoteHardware from "./lib/remote_hardware_pb.ts"; +export * as Rtttl from "./lib/rtttl_pb.ts"; +export * as StoreForward from "./lib/storeforward_pb.ts"; +export * as Telemetry from "./lib/telemetry_pb.ts"; +export * as Xmodem from "./lib/xmodem_pb.ts"; diff --git a/packages/ts/package.json b/packages/ts/package.json new file mode 100755 index 0000000..04f1162 --- /dev/null +++ b/packages/ts/package.json @@ -0,0 +1,32 @@ +{ + "name": "@meshtastic/protobufs", + "description": "Protobuf definitions for the Meshtastic project", + "version": "__PACKAGE_VERSION__", + "homepage": "https://github.com/meshtastic/protobufs", + "license": "GPLV3", + "publishConfig": { + "access": "public" + }, + "type": "module", + "main": "./dist/mod.js", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", + "dependencies": { + "@bufbuild/protobuf": "^2.2.3" + }, + "devDependencies": { + "tsdown": "^0.13.4", + "typescript": "^5.8.3" + }, + "scripts": { + "build": "tsdown" + }, + "tsdown": { + "entry": "mod.ts", + "dts": true, + "format": [ + "esm" + ], + "splitting": false + } +} diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..5db72dd --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +}