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 11232ca..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,16 +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 - 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 1d582e2..6574db5 100644 --- a/meshtastic/admin.options +++ b/meshtastic/admin.options @@ -1,5 +1,14 @@ *AdminMessage.payload_variant anonymous_oneof:true +*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 @@ -8,5 +17,5 @@ *AdminMessage.get_ringtone_response max_size:231 *HamParameters.call_sign max_size:8 -*HamParameters.short_name max_size:6 -*NodeRemoteHardwarePinsResponse.node_remote_hardware_pins max_count:16 \ No newline at end of file +*HamParameters.short_name max_size:5 +*NodeRemoteHardwarePinsResponse.node_remote_hardware_pins max_count:16 diff --git a/meshtastic/admin.proto b/meshtastic/admin.proto index 3b227d8..ac29cc8 100644 --- a/meshtastic/admin.proto +++ b/meshtastic/admin.proto @@ -2,16 +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"; 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 = ""; /* @@ -20,6 +22,13 @@ 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. + * Prevents replay attacks for admin messages. + */ + bytes session_passkey = 101; + /* * TODO: REPLACE */ @@ -58,6 +67,21 @@ message AdminMessage { * TODO: REPLACE */ BLUETOOTH_CONFIG = 6; + + /* + * TODO: REPLACE + */ + SECURITY_CONFIG = 7; + + /* + * Session key config + */ + SESSIONKEY_CONFIG = 8; + + /* + * device-ui config + */ + DEVICEUI_CONFIG = 9; } /* @@ -128,6 +152,72 @@ 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 { + /* + * Backup to the internal flash + */ + FLASH = 0; + + /* + * Backup to the SD card + */ + 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; } /* @@ -241,6 +331,32 @@ message AdminMessage { */ string delete_file_request = 22; + /* + * Set zero and offset for scale chips + */ + uint32 set_scale = 23; + + /* + * Backup the node's preferences + */ + BackupLocation backup_preferences = 24; + + /* + * Restore the node's preferences + */ + BackupLocation restore_preferences = 25; + + /* + * 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 */ @@ -300,6 +416,42 @@ message AdminMessage { */ bool remove_fixed_position = 42; + /* + * Set time only on the node + * Convenience method to set the time on the node (as Net quality) without any other position data + */ + fixed32 set_time_only = 43; + + /* + * Tell the node to send the stored ui data. + */ + bool get_ui_config_request = 44; + + /* + * Reply stored device ui data. + */ + DeviceUIConfig get_ui_config_response = 45; + + /* + * Tell the node to store UI data persistently. + */ + DeviceUIConfig store_ui_config = 46; + + /* + * Set specified node-num to be ignored on the NodeDB on the device + */ + uint32 set_ignored_node = 47; + + /* + * Set specified node-num to be un-ignored on the NodeDB on the device + */ + 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) @@ -311,11 +463,27 @@ 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. + */ + int32 factory_reset_device = 94; + /* * 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. @@ -334,17 +502,48 @@ message AdminMessage { int32 shutdown_seconds = 98; /* - * Tell the node to factory reset, all device settings will be returned to factory defaults. + * Tell the node to factory reset config; all device state and configuration will be returned to factory defaults; BLE bonds will be preserved. */ - int32 factory_reset = 99; + int32 factory_reset_config = 99; /* * 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 */ @@ -381,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 c341400..29ec3e1 100644 --- a/meshtastic/atak.options +++ b/meshtastic/atak.options @@ -3,4 +3,108 @@ *Status.battery int_size:8 *PLI.course int_size:16 *GeoChat.message max_size:200 -*GeoChat.to max_size:120 \ No newline at end of file +*GeoChat.to max_size:120 +*GeoChat.to_callsign max_size:120 +*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 199f06b..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 = ""; /* @@ -40,6 +41,12 @@ message TAKPacket { * ATAK GeoChat message */ GeoChat chat = 6; + + /* + * Generic CoT detail XML + * May be compressed / truncated by the sender (EUD) + */ + bytes detail = 7; } } @@ -48,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; @@ -56,6 +77,25 @@ message GeoChat { * Uid recipient of the message */ optional string to = 2; + + /* + * 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; } /* @@ -250,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 d2ec81a..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 = ""; /* @@ -96,6 +97,12 @@ message ModuleSettings { * Bits of precision for the location sent in position packets. */ uint32 position_precision = 1; + + /* + * 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_muted = 2; } /* diff --git a/meshtastic/clientonly.options b/meshtastic/clientonly.options index bc98b39..c47944a 100644 --- a/meshtastic/clientonly.options +++ b/meshtastic/clientonly.options @@ -1,2 +1,4 @@ *DeviceProfile.long_name max_size:40 -*DeviceProfile.short_name max_size:5 \ No newline at end of file +*DeviceProfile.short_name max_size:5 +*DeviceProfile.ringtone max_size:231 +*DeviceProfile.canned_messages max_size:201 \ No newline at end of file diff --git a/meshtastic/clientonly.proto b/meshtastic/clientonly.proto index b1a27b1..c80f428 100644 --- a/meshtastic/clientonly.proto +++ b/meshtastic/clientonly.proto @@ -3,11 +3,12 @@ syntax = "proto3"; package meshtastic; import "meshtastic/localonly.proto"; +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 = ""; /* @@ -39,4 +40,19 @@ message DeviceProfile { * The ModuleConfig of the node */ optional LocalModuleConfig module_config = 5; + + /* + * Fixed position data + */ + optional Position fixed_position = 6; + + /* + * Ringtone for ExternalNotification + */ + optional string ringtone = 7; + + /* + * Predefined messages for CannedMessage + */ + optional string canned_messages = 8; } diff --git a/meshtastic/config.options b/meshtastic/config.options index 22dcc88..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 @@ -15,3 +17,8 @@ *LoRaConfig.channel_num int_size:16 *PowerConfig.device_battery_ina_address int_size:8 + +*SecurityConfig.public_key max_size:32 +*SecurityConfig.private_key max_size:32 +*SecurityConfig.admin_key max_size:32 +*SecurityConfig.admin_key max_count:3 diff --git a/meshtastic/config.proto b/meshtastic/config.proto index 77e1bef..33eaa58 100644 --- a/meshtastic/config.proto +++ b/meshtastic/config.proto @@ -2,10 +2,12 @@ syntax = "proto3"; package meshtastic; +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 { @@ -37,15 +39,18 @@ message Config { /* * Description: Combination of both ROUTER and CLIENT. Not for mobile devices. + * Deprecated in v2.3.15 because improper usage is impacting public meshes: Use ROUTER or CLIENT instead. */ - ROUTER_CLIENT = 3; + + ROUTER_CLIENT = 3 [deprecated = true]; /* * 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. @@ -95,6 +100,23 @@ message Config { * Uses position module configuration to determine TAK PLI broadcast interval. */ TAK_TRACKER = 10; + + /* + * Description: Will always rebroadcast packets, but will do so after all other modes. + * Technical Details: Used for router nodes that are intended to provide additional coverage + * in areas not already covered by other routers, or to bridge around problematic terrain, + * but should not be given priority over other routers in order to avoid unnecessaraily + * 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; } /* @@ -124,6 +146,54 @@ message Config { * but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB) */ KNOWN_ONLY = 3; + + /* + * Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role. + */ + NONE = 4; + + /* + * Ignores packets from non-standard portnums such as: TAK, RangeTest, PaxCounter, etc. + * Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing. + */ + 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; } /* @@ -133,14 +203,9 @@ message Config { /* * Disabling this will disable the SerialConsole by not initilizing the StreamAPI + * Moved to SecurityConfig */ - bool serial_enabled = 2; - - /* - * By default we turn off logging as soon as an API client connects (to keep shared serial link quiet). - * Set this to true to leave the debug log outputting even when API is active. - */ - bool debug_log_enabled = 3; + bool serial_enabled = 2 [deprecated = true]; /* * For boards without a hard wired button, this is the pin number that will be used @@ -173,8 +238,9 @@ message Config { /* * If true, device is considered to be "managed" by a mesh administrator * Clients should then limit available configuration and administrative options inside the user interface + * Moved to SecurityConfig */ - bool is_managed = 9; + bool is_managed = 9 [deprecated = true]; /* * Disables the triple-press of user button to enable or disable GPS @@ -185,6 +251,17 @@ message Config { * POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */ string tzdef = 11; + + /* + * 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; } /* @@ -355,30 +432,28 @@ message Config { */ message PowerConfig { /* - * If set, we are powered from a low-current source (i.e. solar), so even if it looks like we have power flowing in - * we should try to minimize power consumption as much as possible. - * YOU DO NOT NEED TO SET THIS IF YOU'VE set is_router (it is implied in that case). - * Advanced Option + * Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio. + * Don't use this setting if you want to use your device with the phone apps or are using a device without a user button. + * Technical Details: Works for ESP32 devices and NRF52 devices in the Sensor or Tracker roles */ bool is_power_saving = 1; /* - * If non-zero, the device will fully power off this many seconds after external power is removed. + * Description: If non-zero, the device will fully power off this many seconds after external power is removed. */ uint32 on_battery_shutdown_after_secs = 2; /* * Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k) * Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation. - * Should be set to floating point value between 2 and 4 - * Fixes issues on Heltec v2 + * https://meshtastic.org/docs/configuration/radio/power/#adc-multiplier-override + * Should be set to floating point value between 2 and 6 */ float adc_multiplier_override = 3; /* - * Wait Bluetooth Seconds - * The number of seconds for to wait before turning off BLE in No Bluetooth states - * 0 for default of 1 minute + * Description: The number of seconds for to wait before turning off BLE in No Bluetooth states + * Technical Details: ESP32 Only 0 for default of 1 minute */ uint32 wait_bluetooth_secs = 4; @@ -391,17 +466,14 @@ message Config { uint32 sds_secs = 6; /* - * Light Sleep Seconds - * In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on - * ESP32 Only - * 0 for default of 300 + * Description: In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on + * Technical Details: ESP32 Only 0 for default of 300 */ uint32 ls_secs = 7; /* - * Minimum Wake Seconds - * While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value - * 0 for default of 10 seconds + * Description: While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value + * Technical Details: ESP32 Only 0 for default of 10 seconds */ uint32 min_wake_secs = 8; @@ -409,6 +481,12 @@ message Config { * I2C address of INA_2XX to use for reading device battery voltage */ uint32 device_battery_ina_address = 9; + + /* + * 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; } /* @@ -466,7 +544,7 @@ message Config { string wifi_psk = 4; /* - * NTP server to use if WiFi is conneced, defaults to `0.pool.ntp.org` + * NTP server to use if WiFi is conneced, defaults to `meshtastic.pool.ntp.org` */ string ntp_server = 5; @@ -489,6 +567,31 @@ message Config { * rsyslog Server and Port */ string rsyslog_server = 9; + + /* + * Flags for enabling/disabling network protocols + */ + uint32 enabled_protocols = 10; + + /* + * Enable/Disable ipv6 support + */ + bool ipv6_enabled = 11; + + /* + * Available flags auxiliary network protocols + */ + enum ProtocolFlags { + /* + * Do not broadcast packets over any network protocol + */ + NO_BROADCAST = 0x0000; + + /* + * Enable broadcasting packets via UDP over the local network + */ + UDP_BROADCAST = 0x0001; + } } /* @@ -496,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; } /* @@ -557,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; } /* @@ -584,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. @@ -598,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 @@ -650,6 +724,70 @@ message Config { * Should we wake the screen up on accelerometer detected motion or tap */ bool wake_on_tap_or_motion = 10; + + enum CompassOrientation { + /* + * The compass and the display are in the same orientation. + */ + DEGREES_0 = 0; + + /* + * Rotate the compass by 90 degrees. + */ + DEGREES_90 = 1; + + /* + * Rotate the compass by 180 degrees. + */ + DEGREES_180 = 2; + + /* + * Rotate the compass by 270 degrees. + */ + DEGREES_270 = 3; + + /* + * Don't rotate the compass, but invert the result. + */ + DEGREES_0_INVERTED = 4; + + /* + * Rotate the compass by 90 degrees and invert. + */ + DEGREES_90_INVERTED = 5; + + /* + * Rotate the compass by 180 degrees and invert. + */ + DEGREES_180_INVERTED = 6; + + /* + * 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. + */ + CompassOrientation compass_orientation = 11; + + /* + * If false (default), the device will display the time in 24-hour format on screen. + * 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; } /* @@ -751,6 +889,46 @@ message Config { * Singapore 923mhz */ SG_923 = 18; + + /* + * Philippines 433mhz + */ + PH_433 = 19; + + /* + * Philippines 868mhz + */ + PH_868 = 20; + + /* + * 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; } /* @@ -765,13 +943,15 @@ message Config { /* * Long Range - Slow + * Deprecated in 2.7: Unpopular slow preset. */ - LONG_SLOW = 1; + LONG_SLOW = 1 [deprecated = true]; /* * Very Long Range - Slow + * Deprecated in 2.5: Works only with txco and is unusably slow */ - VERY_LONG_SLOW = 2; + VERY_LONG_SLOW = 2 [deprecated = true]; /* * Medium Range - Slow @@ -797,6 +977,36 @@ message Config { * Long Range - Moderately Fast */ LONG_MODERATE = 7; + + /* + * Short Range - Turbo + * This is the fastest preset and the only one with 500kHz bandwidth. + * 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; } /* @@ -898,6 +1108,11 @@ message Config { */ float override_frequency = 14; + /* + * If true, disable the build-in PA FAN using pin define in RF95_FAN_EN. + */ + bool pa_fan_disabled = 15; + /* * For testing it is useful sometimes to force a node to never listen to * particular other nodes (simulating radio out of range). All nodenums listed @@ -909,6 +1124,15 @@ message Config { * If true, the device will not process any packets received via LoRa that passed via MQTT anywhere on the path towards it. */ bool ignore_mqtt = 104; + + /* + * 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 { @@ -945,6 +1169,52 @@ message Config { uint32 fixed_pin = 3; } + 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. + */ + bytes public_key = 1; + + /* + * The private key of the device. + * Used to create a shared key with a remote device. + */ + bytes private_key = 2; + + /* + * The public key authorized to send admin messages to this node. + */ + repeated bytes admin_key = 3; + + /* + * If true, device is considered to be "managed" by a mesh administrator via admin messages + * Device is managed by a mesh administrator. + */ + bool is_managed = 4; + + /* + * Serial Console over the Stream API." + */ + bool serial_enabled = 5; + + /* + * By default we turn off logging as soon as an API client connects (to keep shared serial link quiet). + * Output live debug logging over serial or bluetooth is set to true. + */ + bool debug_log_api_enabled = 6; + + /* + * Allow incoming device control over the insecure legacy admin channel. + */ + bool admin_channel_enabled = 8; + } + + /* + * Blank config request, strictly for getting the session key + */ + message SessionkeyConfig {} + /* * Payload Variant */ @@ -956,5 +1226,8 @@ message Config { DisplayConfig display = 5; LoRaConfig lora = 6; BluetoothConfig bluetooth = 7; + SecurityConfig security = 8; + SessionkeyConfig sessionkey = 9; + DeviceUIConfig device_ui = 10; } } 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 new file mode 100644 index 0000000..a8fab46 --- /dev/null +++ b/meshtastic/device_ui.options @@ -0,0 +1,12 @@ +*DeviceUIConfig.screen_brightness int_size: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 +*NodeHighlight.node_name max_size:16 +*GeoPoint.zoom int_size:8 +*Map.style max_size:20 diff --git a/meshtastic/device_ui.proto b/meshtastic/device_ui.proto new file mode 100644 index 0000000..28d2910 --- /dev/null +++ b/meshtastic/device_ui.proto @@ -0,0 +1,389 @@ +syntax = "proto3"; + +package meshtastic; + +option csharp_namespace = "Meshtastic.Protobufs"; +option go_package = "github.com/meshtastic/go/generated"; +option java_outer_classname = "DeviceUIProtos"; +option java_package = "org.meshtastic.proto"; +option swift_prefix = ""; + +/* + * Protobuf structures for device-ui persistency + */ + +message DeviceUIConfig { + /* + * A version integer used to invalidate saved files when we make incompatible changes. + */ + uint32 version = 1; + + /* + * TFT display brightness 1..255 + */ + uint32 screen_brightness = 2; + + /* + * Screen timeout 0..900 + */ + uint32 screen_timeout = 3; + + /* + * Screen/Settings lock enabled + */ + bool screen_lock = 4; + bool settings_lock = 5; + uint32 pin_code = 6; + + /* + * Color theme + */ + Theme theme = 7; + + /* + * Audible message, banner and ring tone + */ + bool alert_enabled = 8; + bool banner_enabled = 9; + uint32 ring_tone_id = 10; + + /* + * Localization + */ + Language language = 11; + + /* + * Node list filter + */ + NodeFilter node_filter = 12; + + /* + * Node list highlightening + */ + NodeHighlight node_highlight = 13; + + /* + * 8 integers for screen calibration data + */ + bytes calibration_data = 14; + + /* + * 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 { + /* + * Filter unknown nodes + */ + bool unknown_switch = 1; + + /* + * Filter offline nodes + */ + bool offline_switch = 2; + + /* + * Filter nodes w/o public key + */ + bool public_key_switch = 3; + + /* + * Filter based on hops away + */ + int32 hops_away = 4; + + /* + * Filter nodes w/o position + */ + bool position_switch = 5; + + /* + * Filter nodes by matching name string + */ + string node_name = 6; + + /* + * Filter based on channel + */ + int32 channel = 7; +} + +message NodeHighlight { + /* + * Hightlight nodes w/ active chat + */ + bool chat_switch = 1; + + /* + * Highlight nodes w/ position + */ + bool position_switch = 2; + + /* + * Highlight nodes w/ telemetry data + */ + bool telemetry_switch = 3; + + /* + * Highlight nodes w/ iaq data + */ + bool iaq_switch = 4; + + /* + * Highlight nodes by matching name string + */ + string node_name = 5; +} + +message GeoPoint { + /* + * Zoom level + */ + int32 zoom = 1; + + /* + * Coordinate: latitude + */ + int32 latitude = 2; + + /* + * Coordinate: longitude + */ + int32 longitude = 3; +} + +message Map { + /* + * Home coordinates + */ + GeoPoint home = 1; + + /* + * Map tile style + */ + string style = 2; + + /* + * Map scroll follows GPS + */ + 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 + */ + DARK = 0; + /* + * Light + */ + LIGHT = 1; + /* + * Red + */ + RED = 2; +} + +/* + * Localization + */ +enum Language { + /* + * English + */ + ENGLISH = 0; + + /* + * French + */ + FRENCH = 1; + + /* + * German + */ + GERMAN = 2; + + /* + * Italian + */ + ITALIAN = 3; + + /* + * Portuguese + */ + PORTUGUESE = 4; + + /* + * Spanish + */ + SPANISH = 5; + + /* + * Swedish + */ + SWEDISH = 6; + + /* + * Finnish + */ + FINNISH = 7; + + /* + * Polish + */ + POLISH = 8; + + /* + * Turkish + */ + TURKISH = 9; + + /* + * Serbian + */ + SERBIAN = 10; + + /* + * Russian + */ + RUSSIAN = 11; + + /* + * Dutch + */ + DUTCH = 12; + + /* + * Greek + */ + GREEK = 13; + + /* + * Norwegian + */ + NORWEGIAN = 14; + + /* + * Slovenian + */ + SLOVENIAN = 15; + + /* + * Ukrainian + */ + UKRAINIAN = 16; + + /* + * Bulgarian + */ + BULGARIAN = 17; + + /* + * Czech + */ + CZECH = 18; + + /* + * Danish + */ + DANISH = 19; + + /* + * Simplified Chinese (experimental) + */ + SIMPLIFIED_CHINESE = 30; + + /* + * Traditional Chinese (experimental) + */ + TRADITIONAL_CHINESE = 31; +} diff --git a/meshtastic/deviceonly.options b/meshtastic/deviceonly.options index e9477a0..d6aae0c 100644 --- a/meshtastic/deviceonly.options +++ b/meshtastic/deviceonly.options @@ -6,11 +6,13 @@ *ChannelFile.channels max_count:8 -*OEMStore.oem_text max_size:40 -*OEMStore.oem_icon_bits max_size:2048 -*OEMStore.oem_aes_key max_size:32 - *DeviceState.node_remote_hardware_pins max_count:12 *NodeInfoLite.channel int_size:8 *NodeInfoLite.hops_away int_size:8 +*NodeInfoLite.next_hop int_size:8 + +*UserLite.long_name max_size:40 +*UserLite.short_name max_size:5 +*UserLite.public_key max_size:32 # public key +*UserLite.macaddr max_size:6 fixed_length:true \ No newline at end of file diff --git a/meshtastic/deviceonly.proto b/meshtastic/deviceonly.proto index eef59a7..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/config.proto"; import "meshtastic/localonly.proto"; import "meshtastic/mesh.proto"; -import "meshtastic/module_config.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 */ @@ -52,6 +52,55 @@ message PositionLite { Position.LocSource location_source = 5; } +message UserLite { + /* + * This is the addr of the radio. + */ + bytes macaddr = 1 [deprecated = true]; + + /* + * A full name for this user, i.e. "Kevin Hester" + */ + string long_name = 2; + + /* + * A VERY short name, ideally two characters. + * Suitable for a tiny OLED screen + */ + string short_name = 3; + + /* + * TBEAM, HELTEC, etc... + * Starting in 1.2.11 moved to hw_model enum in the NodeInfo object. + * Apps will still need the string here for older builds + * (so OTA update can find the right image), but if the enum is available it will be used instead. + */ + HardwareModel hw_model = 4; + + /* + * In some regions Ham radio operators have different bandwidth limitations than others. + * If this user is a licensed operator, set this flag. + * Also, "long_name" should be their licence number. + */ + bool is_licensed = 5; + + /* + * Indicates that the user's role in the mesh + */ + Config.DeviceConfig.Role role = 6; + + /* + * The public key of the user's device. + * This is sent out to other nodes on the mesh to allow them to compute a shared secret key. + */ + bytes public_key = 7; + + /* + * Whether or not the node can be messaged + */ + optional bool is_unmessagable = 9; +} + message NodeInfoLite { /* * The node number @@ -61,7 +110,7 @@ message NodeInfoLite { /* * The user info for this node */ - User user = 2; + UserLite user = 2; /* * This position data. Note: before 1.2.14 we would also store the last time we've heard from this node in position.time, that is no longer true. @@ -95,38 +144,35 @@ message NodeInfoLite { bool via_mqtt = 8; /* - * Number of hops away from us this node is (0 if adjacent) + * Number of hops away from us this node is (0 if direct neighbor) */ - uint32 hops_away = 9; + optional uint32 hops_away = 9; /* * True if node is in our favorites list * Persists between NodeDB internal clean ups */ bool is_favorite = 10; + + /* + * True if node is in our ignored list + * Persists between NodeDB internal clean ups + */ + bool is_ignored = 11; + + /* + * 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; } -/* - * Font sizes for the device screen - */ -enum ScreenFonts { - /* - * TODO: REPLACE - */ - FONT_SMALL = 0; - - /* - * TODO: REPLACE - */ - FONT_MEDIUM = 1; - - /* - * TODO: REPLACE - */ - FONT_LARGE = 2; -} - - /* * This message is never sent over the wire, but it is used for serializing DB * state to flash in the device code @@ -172,9 +218,10 @@ message DeviceState { bool no_save = 9 [deprecated = true]; /* - * Some GPS receivers seem to have bogus settings from the factory, so we always do one factory reset. + * Previously used to manage GPS factory resets. + * Deprecated in 2.5.23 */ - bool did_gps_reset = 11; + bool did_gps_reset = 11 [deprecated = true]; /* * We keep the last received waypoint stored in the device flash, @@ -187,11 +234,20 @@ message DeviceState { * The mesh's nodes with their available gpio pins for RemoteHardware module */ repeated NodeRemoteHardwarePin node_remote_hardware_pins = 13; +} + +message NodeDatabase { + /* + * A version integer used to invalidate old save files when we make + * incompatible changes This integer is set at build time and is private to + * NodeDB.cpp in the device code. + */ + uint32 version = 1; /* * New lite version of NodeDB to decrease memory footprint */ - repeated NodeInfoLite node_db_lite = 14 [(nanopb).callback_datatype = "std::vector"]; + repeated NodeInfoLite nodes = 2 [(nanopb).callback_datatype = "std::vector"]; } /* @@ -212,47 +268,36 @@ message ChannelFile { } /* - * This can be used for customizing the firmware distribution. If populated, - * show a secondary bootup screen with custom logo and text for 2.5 seconds. + * The on-disk backup of the node's preferences */ -message OEMStore { +message BackupPreferences { /* - * The Logo width in Px + * The version of the backup */ - uint32 oem_icon_width = 1; + uint32 version = 1; /* - * The Logo height in Px + * The timestamp of the backup (if node has time) */ - uint32 oem_icon_height = 2; + fixed32 timestamp = 2; /* - * The Logo in XBM bytechar format + * The node's configuration */ - bytes oem_icon_bits = 3; + LocalConfig config = 3; /* - * Use this font for the OEM text. + * The node's module configuration */ - ScreenFonts oem_font = 4; + LocalModuleConfig module_config = 4; /* - * Use this font for the OEM text. + * The node's channels */ - string oem_text = 5; + ChannelFile channels = 5; /* - * The default device encryption key, 16 or 32 byte + * The node's user (owner) information */ - bytes oem_aes_key = 6; - - /* - * A Preset LocalConfig to apply during factory reset - */ - LocalConfig oem_local_config = 7; - - /* - * A Preset LocalModuleConfig to apply during factory reset - */ - LocalModuleConfig oem_local_module_config = 8; + User owner = 6; } diff --git a/meshtastic/interdevice.options b/meshtastic/interdevice.options new file mode 100644 index 0000000..97df282 --- /dev/null +++ b/meshtastic/interdevice.options @@ -0,0 +1 @@ +*InterdeviceMessage.nmea max_size:1024 diff --git a/meshtastic/interdevice.proto b/meshtastic/interdevice.proto new file mode 100644 index 0000000..f646368 --- /dev/null +++ b/meshtastic/interdevice.proto @@ -0,0 +1,44 @@ +syntax = "proto3"; + +package meshtastic; + +option csharp_namespace = "Meshtastic.Protobufs"; +option go_package = "github.com/meshtastic/go/generated"; +option java_outer_classname = "InterdeviceProtos"; +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 + SHUTDOWN = 163; + POWER_ON = 164; + SCD41_TEMP = 176; + SCD41_HUMIDITY = 177; + SCD41_CO2 = 178; + AHT20_TEMP = 179; + AHT20_HUMIDITY = 180; + TVOC_INDEX = 181; +} + +message SensorData { + // The message type + MessageType type = 1; + // The sensor data, either as a float or an uint32 + oneof data { + float float_value = 2; + uint32 uint32_value = 3; + } +} + +message InterdeviceMessage { + // The message data + oneof data { + string nmea = 1; + SensorData sensor = 2; + } +} diff --git a/meshtastic/localonly.proto b/meshtastic/localonly.proto index 9694d7b..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 = ""; /* @@ -58,6 +58,11 @@ message LocalConfig { * NodeDB.cpp in the device code. */ uint32 version = 8; + + /* + * The part of the config that is specific to Security settings + */ + Config.SecurityConfig security = 9; } message LocalModuleConfig { @@ -126,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 aedfe99..2341e6c 100644 --- a/meshtastic/mesh.options +++ b/meshtastic/mesh.options @@ -3,25 +3,37 @@ *macaddr max_size:6 fixed_length:true # macaddrs *id max_size:16 # node id strings +*public_key max_size:32 # public key *User.long_name max_size:40 *User.short_name max_size:5 *RouteDiscovery.route max_count:8 +*RouteDiscovery.snr_towards max_count:8 +*RouteDiscovery.snr_towards int_size:8 +*RouteDiscovery.route_back max_count:8 +*RouteDiscovery.snr_back max_count:8 +*RouteDiscovery.snr_back int_size:8 # note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is # outside of this envelope -*Data.payload max_size:237 +*Data.payload max_size:233 +*Data.bitfield int_size:8 *NodeInfo.channel int_size:8 *NodeInfo.hops_away int_size:8 # Big enough for 1.2.28.568032c-d *MyNodeInfo.firmware_version max_size:18 +*MyNodeInfo.device_id max_size:16 +*MyNodeInfo.pio_env max_size:40 *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 @@ -29,6 +41,8 @@ *MeshPacket.hop_limit int_size:8 *MeshPacket.hop_start int_size:8 *MeshPacket.channel int_size:8 +*MeshPacket.next_hop int_size:8 +*MeshPacket.relay_node int_size:8 *QueueStatus.res int_size:8 *QueueStatus.free int_size:8 @@ -40,14 +54,35 @@ *Routing.variant anonymous_oneof:true -*LogRecord.message max_size:64 -*LogRecord.source max_size:8 +*LogRecord.message max_size:384 +*LogRecord.source max_size:32 + +*FileInfo.file_name max_size:228 + +*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 #This value may want to be a few bytes smaller to compensate for the parent fields. -*Compressed.data max_size:237 +*Compressed.data max_size:233 *Waypoint.name max_size:30 *Waypoint.description max_size:100 @@ -59,3 +94,7 @@ *MqttClientProxyMessage.topic max_size:60 *MqttClientProxyMessage.data max_size:435 *MqttClientProxyMessage.text max_size:435 + +*ChunkedPayload.chunk_count int_size:16 +*ChunkedPayload.chunk_index int_size:16 +*ChunkedPayload.payload_chunk max_size:228 diff --git a/meshtastic/mesh.proto b/meshtastic/mesh.proto index ade29d8..fb585b9 100644 --- a/meshtastic/mesh.proto +++ b/meshtastic/mesh.proto @@ -4,6 +4,7 @@ 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"; @@ -12,28 +13,28 @@ import "meshtastic/xmodem.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 = ""; /* - * a gps position + * A GPS Position */ message Position { /* * The new preferred location encoding, multiply by 1e-7 to get degrees * in floating point */ - sfixed32 latitude_i = 1; + optional sfixed32 latitude_i = 1; /* * TODO: REPLACE */ - sfixed32 longitude_i = 2; + optional sfixed32 longitude_i = 2; /* * In meters above MSL (but see issue #359) */ - int32 altitude = 3; + optional int32 altitude = 3; /* * This is usually not sent over the mesh (to save space), but it is sent @@ -122,12 +123,12 @@ message Position { /* * HAE altitude in meters - can be used instead of MSL altitude */ - sint32 altitude_hae = 9; + optional sint32 altitude_hae = 9; /* * Geoidal separation in meters */ - sint32 altitude_geoidal_separation = 10; + optional sint32 altitude_geoidal_separation = 10; /* * Horizontal, Vertical and Position Dilution of Precision, in 1/100 units @@ -163,12 +164,12 @@ message Position { * - "yaw" indicates a relative rotation about the vertical axis * TODO: REMOVE/INTEGRATE */ - uint32 ground_speed = 15; + optional uint32 ground_speed = 15; /* * TODO: REPLACE */ - uint32 ground_track = 16; + optional uint32 ground_track = 16; /* * GPS fix quality (from NMEA GxGGA statement or similar) @@ -319,6 +320,31 @@ enum HardwareModel { */ LORA_TYPE = 19; + /* + * wiphone https://www.wiphone.io/ + */ + WIPHONE = 20; + + /* + * WIO Tracker WM1110 family from Seeed Studio. Includes wio-1110-tracker and wio-1110-sdk + */ + WIO_WM1110 = 21; + + /* + * RAK2560 Solar base station based on RAK4630 + */ + RAK2560 = 22; + + /* + * Heltec HRU-3601: https://heltec.org/project/hru-3601/ + */ + HELTEC_HRU_3601 = 23; + + /* + * Heltec Wireless Bridge + */ + HELTEC_WIRELESS_BRIDGE = 24; + /* * B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */ @@ -362,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 @@ -407,7 +433,7 @@ enum HardwareModel { DR_DEV = 41; /* - * M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ + * M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */ M5STACK = 42; @@ -510,6 +536,358 @@ enum HardwareModel { */ TD_LORAC = 60; + /* + * CDEBYTE EoRa-S3 board using their own MM modules, clone of LILYGO T3S3 + */ + CDEBYTE_EORA_S3 = 61; + + /* + * TWC_MESH_V4 + * Adafruit NRF52840 feather express with SX1262, SSD1306 OLED and NEO6M GPS + */ + TWC_MESH_V4 = 62; + + /* + * NRF52_PROMICRO_DIY + * Promicro NRF52840 with SX1262/LLCC68, SSD1306 OLED and NEO6M GPS + */ + NRF52_PROMICRO_DIY = 63; + + /* + * RadioMaster 900 Bandit Nano, https://www.radiomasterrc.com/products/bandit-nano-expresslrs-rf-module + * ESP32-D0WDQ6 With SX1276/SKY66122, SSD1306 OLED and No GPS + */ + RADIOMASTER_900_BANDIT_NANO = 64; + + /* + * Heltec Capsule Sensor V3 with ESP32-S3 CPU, Portable LoRa device that can replace GNSS modules or sensors + */ + 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 + */ + HELTEC_MESH_NODE_T114 = 69; + + /* + * Sensecap Indicator from Seeed Studio. ESP32-S3 device with TFT and RP2040 coprocessor + */ + SENSECAP_INDICATOR = 70; + + /* + * Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors. + */ + TRACKER_T1000_E = 71; + + /* + * RAK3172 STM32WLE5 Module (https://store.rakwireless.com/products/wisduo-lpwan-module-rak3172) + */ + RAK3172 = 72; + + /* + * Seeed Studio Wio-E5 (either mini or Dev kit) using STM32WL chip. + */ + WIO_E5 = 73; + + /* + * RadioMaster 900 Bandit, https://www.radiomasterrc.com/products/bandit-expresslrs-rf-module + * SSD1306 OLED and No GPS + */ + RADIOMASTER_900_BANDIT = 74; + + /* + * Minewsemi ME25LS01 (ME25LE01_V1.0). NRF52840 w/ LR1110 radio, buttons and leds and pins. + */ + ME25LS01_4Y10TD = 75; + + /* + * RP2040_FEATHER_RFM95 + * Adafruit Feather RP2040 with RFM95 LoRa Radio RFM95 with SX1272, SSD1306 OLED + * https://www.adafruit.com/product/5714 + * https://www.adafruit.com/product/326 + * https://www.adafruit.com/product/938 + * ^^^ short A0 to switch to I2C address 0x3C + * + */ + RP2040_FEATHER_RFM95 = 76; + + /* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */ + M5STACK_COREBASIC = 77; + M5STACK_CORE2 = 78; + + /* Pico2 with Waveshare Hat, same as Pico */ + RPI_PICO2 = 79; + + /* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */ + M5STACK_CORES3 = 80; + + /* Seeed XIAO S3 DK*/ + SEEED_XIAO_S3 = 81; + + /* + * Nordic nRF52840+Semtech SX1262 LoRa BLE Combo Module. nRF52840+SX1262 MS24SF1 + */ + MS24SF1 = 82; + + /* + * Lilygo TLora-C6 with the new ESP32-C6 MCU + */ + TLORA_C6 = 83; + + /* + * WisMesh Tap + * RAK-4631 w/ TFT in injection modled case + */ + WISMESH_TAP = 84; + + /* + * Similar to PORTDUINO but used by Routastic devices, this is not any + * particular device and does not run Meshtastic's code but supports + * the same frame format. + * Runs on linux, see https://github.com/Jorropo/routastic + */ + ROUTASTIC = 85; + + /* + * Mesh-Tab, esp32 based + * https://github.com/valzzu/Mesh-Tab + */ + MESH_TAB = 86; + + /* + * MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog + * https://www.loraitalia.it + */ + MESHLINK = 87; + + /* + * 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 + * https://www.elecrow.com/wiki/ThinkNode-M2_Transceiver_Device(Meshtastic)_Power_By_NRF52840.html (this actually uses ESP32-S3) + */ + THINKNODE_M1 = 89; + THINKNODE_M2 = 90; + + /* + * Lilygo T-ETH-Elite + */ + 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. @@ -586,16 +964,42 @@ message User { * Indicates that the user's role in the mesh */ Config.DeviceConfig.Role role = 7; + + /* + * The public key of the user's device. + * This is sent out to other nodes on the mesh to allow them to compute a shared secret key. + */ + bytes public_key = 8; + + /* + * Whether or not the node can be messaged + */ + optional bool is_unmessagable = 9; } /* - * A message used in our Dynamic Source Routing protocol (RFC 4728 based) + * A message used in a traceroute */ message RouteDiscovery { /* - * The list of nodenums this packet has visited so far + * The list of nodenums this packet has visited so far to the destination. */ repeated fixed32 route = 1; + + /* + * The list of SNRs (in dB, scaled by 4) in the route towards the destination. + */ + repeated int32 snr_towards = 2; + + /* + * The list of nodenums the packet has visited on the way back from the destination. + */ + repeated fixed32 route_back = 3; + + /* + * The list of SNRs (in dB, scaled by 4) in the route back from the destination. + */ + repeated int32 snr_back = 4; } /* @@ -668,6 +1072,38 @@ message Routing { * (i.e you did not send the request on the required bound channel) */ NOT_AUTHORIZED = 33; + + /* + * The client specified a PKI transport, but the node was unable to send the packet using PKI (and did not send the message at all) + */ + PKI_FAILED = 34; + + /* + * The receiving node does not have a Public Key to decode with + */ + PKI_UNKNOWN_PUBKEY = 35; + + /* + * Admin packet otherwise checks out, but uses a bogus or expired session key + */ + ADMIN_BAD_SESSION_KEY = 36; + + /* + * 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 { @@ -744,6 +1180,202 @@ message Data { * a message a heart or poop emoji. */ fixed32 emoji = 8; + + /* + * Bitfield for extra flags. First use is to indicate that user approves the packet being uploaded to MQTT. + */ + 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; } /* @@ -758,12 +1390,12 @@ message Waypoint { /* * latitude_i */ - sfixed32 latitude_i = 2; + optional sfixed32 latitude_i = 2; /* * longitude_i */ - sfixed32 longitude_i = 3; + optional sfixed32 longitude_i = 3; /* * Time the waypoint is to expire (epoch) @@ -792,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 */ @@ -876,6 +1515,22 @@ message MeshPacket { */ RELIABLE = 70; + /* + * If priority is unset but the packet is a response to a request, we want it to get there relatively quickly. + * Furthermore, responses stop relaying packets directed to a node early. + */ + RESPONSE = 80; + + /* + * Higher priority for specific message types (portnums) to distinguish between other reliable packets. + */ + HIGH = 100; + + /* + * Higher priority alert message used for critical alerts which take priority over other reliable packets. + */ + ALERT = 110; + /* * Ack/naks are sent with very high priority to ensure that retransmission * stops as soon as possible @@ -908,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. @@ -917,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; @@ -980,7 +1684,7 @@ message MeshPacket { float rx_snr = 8; /* - * If unset treated as zero (no forwarding, send to adjacent nodes only) + * If unset treated as zero (no forwarding, send to direct neighbor nodes only) * if 1, allow hopping through one node, etc... * For our usecase real world topologies probably have a max of about 3. * This field is normally placed into a few of bits in the header. @@ -1026,6 +1730,40 @@ message MeshPacket { * When receiving a packet, the difference between hop_start and hop_limit gives how many hops it traveled. */ uint32 hop_start = 15; + + /* + * Records the public key the packet was encrypted with, if applicable. + */ + bytes public_key = 16; + + /* + * Indicates whether the packet was en/decrypted using PKI + */ + bool pki_encrypted = 17; + + /* + * Last byte of the node number of the node that should be used as the next hop in routing. + * Set by the firmware internally, clients are not supposed to set this. + */ + uint32 next_hop = 18; + + /* + * Last byte of the node number of the node that will relay/relayed this packet. + * Set by the firmware internally, clients are not supposed to set this. + */ + uint32 relay_node = 19; + + /* + * *Never* sent over the radio links. + * Timestamp after which this packet may be sent. + * 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; } /* @@ -1043,7 +1781,7 @@ enum Constants { * note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is * outside of this envelope */ - DATA_PAYLOAD_LEN = 237; + DATA_PAYLOAD_LEN = 233; } /* @@ -1110,7 +1848,7 @@ message NodeInfo { /* * TODO: REMOVE/INTEGRATE * Not currently used (till full DSR deployment?) Our current preferred node node for routing - might be the same as num if - * we are adjacent Or zero if we don't yet know a route to this node. + * we are direct neighbor or zero if we don't yet know a route to this node. * fixed32 next_hop = 5; */ @@ -1134,15 +1872,34 @@ message NodeInfo { bool via_mqtt = 8; /* - * Number of hops away from us this node is (0 if adjacent) + * Number of hops away from us this node is (0 if direct neighbor) */ - uint32 hops_away = 9; + optional uint32 hops_away = 9; /* * True if node is in our favorites list * Persists between NodeDB internal clean ups */ bool is_favorite = 10; + + /* + * True if node is in our ignored list + * 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; } /* @@ -1212,6 +1969,60 @@ enum CriticalErrorCode { * If this occurs on your board, please post in the forum so that we can ask you to collect some information to allow fixing this bug */ RADIO_SPI_BUG = 11; + + /* + * Corruption was detected on the flash filesystem but we were able to repair things. + * If you see this failure in the field please post in the forum because we are interested in seeing if this is occurring in the field. + */ + FLASH_CORRUPTION_RECOVERABLE = 12; + + /* + * Corruption was detected on the flash filesystem but we were unable to repair things. + * NOTE: Your node will probably need to be reconfigured the next time it reboots (it will lose the region code etc...) + * If you see this failure in the field please post in the forum because we are interested in seeing if this is occurring in the field. + */ + 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; } /* @@ -1237,6 +2048,27 @@ message MyNodeInfo { * Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */ uint32 min_app_version = 11; + + /* + * Unique hardware identifier for this device + */ + bytes device_id = 12; + + /* + * 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; } /* @@ -1411,9 +2243,92 @@ message FromRadio { * MQTT Client Proxy Message (device sending to client / phone for publishing to MQTT) */ MqttClientProxyMessage mqttClientProxyMessage = 14; + + /* + * File system manifest messages + */ + FileInfo fileInfo = 15; + + /* + * Notification message to the client + */ + ClientNotification clientNotification = 16; + + /* + * Persistent data for device-ui + */ + DeviceUIConfig deviceuiConfig = 17; } } +/* + * A notification message from the device to the client + * To be used for important messages that should to be displayed to the user + * in the form of push notifications or validation messages when saving + * invalid configuration. + */ +message ClientNotification { + /* + * The id of the packet we're notifying in response to + */ + optional uint32 reply_id = 1; + + /* + * Seconds since 1970 - or 0 for unknown/unset + */ + fixed32 time = 2; + + /* + * The level type of notification + */ + LogRecord.Level level = 3; + /* + * 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 + */ +message FileInfo { + /* + * The fully qualified path of the file + */ + string file_name = 1; + + /* + * The size of the file in bytes + */ + uint32 size_bytes = 2; +} + /* * Packets/commands to the radio will be written (reliably) to the toRadio characteristic. * Once the write completes the phone can assume it is handled. @@ -1583,13 +2498,116 @@ message DeviceMetadata { * Has Remote Hardware enabled */ bool hasRemoteHardware = 10; + + /* + * Has PKC capabilities + */ + bool hasPKC = 11; + + /* + * Bit field of boolean for excluded modules + * (bitwise OR of ExcludedModules) + */ + uint32 excluded_modules = 12; +} + +/* + * Enum for modules excluded from a device's configuration. + * Each value represents a ModuleConfigType that can be toggled as excluded + * by setting its corresponding bit in the `excluded_modules` bitmask field. + */ +enum ExcludedModules { + /* + * Default value of 0 indicates no modules are excluded. + */ + EXCLUDED_NONE = 0x0000; + + /* + * MQTT module + */ + MQTT_CONFIG = 0x0001; + + /* + * Serial module + */ + SERIAL_CONFIG = 0x0002; + + /* + * External Notification module + */ + EXTNOTIF_CONFIG = 0x0004; + + /* + * Store and Forward module + */ + STOREFORWARD_CONFIG = 0x0008; + + /* + * Range Test module + */ + RANGETEST_CONFIG = 0x0010; + + /* + * Telemetry module + */ + TELEMETRY_CONFIG = 0x0020; + + /* + * Canned Message module + */ + CANNEDMSG_CONFIG = 0x0040; + + /* + * Audio module + */ + AUDIO_CONFIG = 0x0080; + + /* + * Remote Hardware module + */ + REMOTEHARDWARE_CONFIG = 0x0100; + + /* + * Neighbor Info module + */ + NEIGHBORINFO_CONFIG = 0x0200; + + /* + * Ambient Lighting module + */ + AMBIENTLIGHTING_CONFIG = 0x0400; + + /* + * Detection Sensor module + */ + DETECTIONSENSOR_CONFIG = 0x0800; + + /* + * 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 @@ -1605,3 +2623,58 @@ message NodeRemoteHardwarePin { */ RemoteHardwarePin pin = 2; } + +message ChunkedPayload { + /* + * The ID of the entire payload + */ + uint32 payload_id = 1; + + /* + * The total number of chunks in the payload + */ + uint32 chunk_count = 2; + + /* + * The current chunk index in the total + */ + uint32 chunk_index = 3; + + /* + * The binary data of the current chunk + */ + bytes payload_chunk = 4; +} + +/* + * Wrapper message for broken repeated oneof support + */ +message resend_chunks { + repeated uint32 chunks = 1; +} + +/* + * Responses to a ChunkedPayload request + */ +message ChunkedPayloadResponse { + /* + * The ID of the entire payload + */ + uint32 payload_id = 1; + + oneof payload_variant { + /* + * Request to transfer chunked payload + */ + bool request_transfer = 2; + + /* + * Accept the transfer chunked payload + */ + bool accept_transfer = 3; + /* + * Request missing indexes in the chunked payload + */ + resend_chunks resend_chunks = 4; + } +} diff --git a/meshtastic/module_config.options b/meshtastic/module_config.options index 68aba7c..c6158be 100644 --- a/meshtastic/module_config.options +++ b/meshtastic/module_config.options @@ -2,7 +2,7 @@ *MQTTConfig.address max_size:64 *MQTTConfig.username max_size:64 -*MQTTConfig.password max_size:64 +*MQTTConfig.password max_size:32 *MQTTConfig.root max_size:32 *AudioConfig.ptt_pin int_size:8 @@ -26,3 +26,6 @@ *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 36a2b4b..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; } /* @@ -128,31 +135,56 @@ message ModuleConfig { /* * Interval in seconds of how often we should try to send our - * Neighbor Info to the mesh + * Neighbor Info (minimum is 14400, i.e., 4 hours) */ uint32 update_interval = 2; + + /* + * Whether in addition to sending it to MQTT and the PhoneAPI, our NeighborInfo should be transmitted over LoRa. + * Note that this is not available on a channel with default key and name. + */ + bool transmit_over_lora = 3; } /* * Detection Sensor Module Config */ message DetectionSensorConfig { + enum TriggerType { + // Event is triggered if pin is low + LOGIC_LOW = 0; + // Event is triggered if pin is high + LOGIC_HIGH = 1; + // Event is triggered when pin goes high to low + FALLING_EDGE = 2; + // Event is triggered when pin goes low to high + RISING_EDGE = 3; + // Event is triggered on every pin state change, low is considered to be + // "active" + EITHER_EDGE_ACTIVE_LOW = 4; + // Event is triggered on every pin state change, high is considered to be + // "active" + EITHER_EDGE_ACTIVE_HIGH = 5; + } /* * Whether the Module is enabled */ bool enabled = 1; /* - * Interval in seconds of how often we can send a message to the mesh when a state change is detected + * Interval in seconds of how often we can send a message to the mesh when a + * trigger event is detected */ uint32 minimum_broadcast_secs = 2; /* - * Interval in seconds of how often we should send a message to the mesh with the current state regardless of changes - * When set to 0, only state changes will be broadcasted - * Works as a sort of status heartbeat for peace of mind + * Interval in seconds of how often we should send a message to the mesh + * with the current state regardless of trigger events When set to 0, only + * trigger events will be broadcasted Works as a sort of status heartbeat + * for peace of mind */ uint32 state_broadcast_secs = 3; + /* * Send ASCII bell with alert message * Useful for triggering ext. notification on bell @@ -172,10 +204,9 @@ message ModuleConfig { uint32 monitor_pin = 6; /* - * Whether or not the GPIO pin state detection is triggered on HIGH (1) - * Otherwise LOW (0) + * The type of trigger event to be used */ - bool detection_triggered_high = 7; + TriggerType detection_trigger_type = 7; /* * Whether or not use INPUT_PULLUP mode for GPIO pin @@ -254,6 +285,92 @@ message ModuleConfig { */ uint32 paxcounter_update_interval = 2; + + /* + * WiFi RSSI threshold. Defaults to -80 + */ + int32 wifi_threshold = 3; + + /* + * 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; } /* @@ -293,6 +410,17 @@ message ModuleConfig { NMEA = 4; // NMEA messages specifically tailored for CalTopo 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) } /* @@ -457,6 +585,11 @@ message ModuleConfig { * TODO: REPLACE */ uint32 history_return_window = 5; + + /* + * Set to true to let this node act as a server that stores received messages and resends them upon request. + */ + bool is_server = 6; } /* @@ -478,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; } /* @@ -526,26 +665,52 @@ message ModuleConfig { uint32 air_quality_interval = 7; /* - * Interval in seconds of how often we should try to send our - * air quality metrics to the mesh + * Enable/disable Power metrics */ bool power_measurement_enabled = 8; /* * Interval in seconds of how often we should try to send our - * air quality metrics to the mesh + * power metrics to the mesh */ uint32 power_update_interval = 9; /* - * Interval in seconds of how often we should try to send our - * air quality metrics to the mesh + * Enable/Disable the power measurement module on-device display */ bool power_screen_enabled = 10; + + /* + * Preferences for the (Health) Telemetry Module + * Enable/Disable the telemetry measurement module measurement collection + */ + bool health_measurement_enabled = 11; + + /* + * Interval in seconds of how often we should try to send our + * health metrics to the mesh + */ + uint32 health_update_interval = 12; + + /* + * 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; } /* - * TODO: REPLACE + * Canned Messages Module Config */ message CannedMessageConfig { /* @@ -636,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" or keyword "_any" + * 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. @@ -682,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 */ @@ -750,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 5808eb7..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 = ""; /* @@ -105,6 +105,21 @@ enum PortNum { */ DETECTION_SENSOR_APP = 10; + /* + * Same as Text Message but used for critical alerts. + */ + 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. @@ -124,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 @@ -174,7 +205,7 @@ enum PortNum { /* * Provides a traceroute functionality to show the route a packet towards - * a certain destination would take on the mesh. + * a certain destination would take on the mesh. Contains a RouteDiscovery message as payload. * ENCODING: Protobuf */ TRACEROUTE_APP = 70; @@ -196,6 +227,44 @@ enum PortNum { */ MAP_REPORT_APP = 73; + /* + * PowerStress based monitoring support (for automated power consumption testing) + */ + 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 new file mode 100644 index 0000000..5973b16 --- /dev/null +++ b/meshtastic/powermon.proto @@ -0,0 +1,103 @@ +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 = "org.meshtastic.proto"; +option swift_prefix = ""; + +/* 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) + */ +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. + */ + enum State { + None = 0; + + CPU_DeepSleep = 0x01; + 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 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; + + Lora_RXOn = 0x08; + Lora_TXOn = 0x10; + Lora_RXActive = 0x20; + BT_On = 0x40; + LED_On = 0x80; + + Screen_On = 0x100; + Screen_Drawing = 0x200; + Wifi_On = 0x400; + + /* + * 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 + */ + enum Opcode { + /* + * Unset/unused + */ + UNSET = 0; + + 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 + + SCREEN_ON = 16; // Turn the screen on + SCREEN_OFF = 17; // Turn the screen off + + CPU_IDLE = 32; // Let the CPU run but we assume mostly idling for num_seconds + CPU_DEEPSLEEP = 33; // Force deep sleep for FIXME seconds + CPU_FULLON = 34; // Spin the CPU as fast as possible for num_seconds + + LED_ON = 48; // Turn the LED on for num_seconds (and leave it on - for baseline power measurement purposes) + LED_OFF = 49; // Force the LED off for num_seconds + + LORA_OFF = 64; // Completely turn off the LORA radio for num_seconds + LORA_TX = 65; // Send Lora packets for num_seconds + LORA_RX = 66; // Receive Lora packets for num_seconds (node will be mostly just listening, unless an external agent is helping stress this by sending packets on the current channel) + + BT_OFF = 80; // Turn off the BT radio for num_seconds + BT_ON = 81; // Turn on the BT radio for num_seconds + + WIFI_OFF = 96; // Turn off the WIFI radio for num_seconds + WIFI_ON = 97; // Turn on the WIFI radio for num_seconds + + GPS_OFF = 112; // Turn off the GPS radio for num_seconds + GPS_ON = 113; // Turn on the GPS radio for num_seconds + } + + /* + * What type of HardwareMessage is this? + */ + Opcode cmd = 1; + + float num_seconds = 2; +} 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.options b/meshtastic/rtttl.options index 1ae0c2f..171e426 100644 --- a/meshtastic/rtttl.options +++ b/meshtastic/rtttl.options @@ -1 +1 @@ -*RTTTLConfig.ringtone max_size:230 +*RTTTLConfig.ringtone max_size:231 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.options b/meshtastic/storeforward.options index 8580aab..57a122c 100644 --- a/meshtastic/storeforward.options +++ b/meshtastic/storeforward.options @@ -1 +1 @@ -*StoreAndForward.text max_size:237 \ No newline at end of file +*StoreAndForward.text max_size:233 \ No newline at end of file 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 6c80df9..5db1af5 100644 --- a/meshtastic/telemetry.options +++ b/meshtastic/telemetry.options @@ -1,4 +1,19 @@ # options for nanopb # https://jpa.kapsi.fi/nanopb/docs/reference.html#proto-file-options +*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 a822c5d..f541ca9 100644 --- a/meshtastic/telemetry.proto +++ b/meshtastic/telemetry.proto @@ -1,286 +1,934 @@ -syntax = "proto3"; - -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 swift_prefix = ""; - -/* - * Key native device metrics such as battery level - */ -message DeviceMetrics { - /* - * 0-100 (>100 means powered) - */ - uint32 battery_level = 1; - - /* - * Voltage measured - */ - float voltage = 2; - - /* - * Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). - */ - float channel_utilization = 3; - - /* - * Percent of airtime for transmission used within the last hour. - */ - float air_util_tx = 4; -} - -/* - * Weather station or other environmental metrics - */ -message EnvironmentMetrics { - /* - * Temperature measured - */ - float temperature = 1; - - /* - * Relative humidity percent measured - */ - float relative_humidity = 2; - - /* - * Barometric pressure in hPA measured - */ - float barometric_pressure = 3; - - /* - * Gas resistance in MOhm measured - */ - float gas_resistance = 4; - - /* - * Voltage measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x) - */ - float voltage = 5; - - /* - * Current measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x) - */ - float current = 6; -} - -/* - * Power Metrics (voltage / current / etc) - */ -message PowerMetrics { - /* - * Voltage (Ch1) - */ - float ch1_voltage = 1; - - /* - * Current (Ch1) - */ - float ch1_current = 2; - - /* - * Voltage (Ch2) - */ - float ch2_voltage = 3; - - /* - * Current (Ch2) - */ - float ch2_current = 4; - - /* - * Voltage (Ch3) - */ - float ch3_voltage = 5; - - /* - * Current (Ch3) - */ - float ch3_current = 6; -} - -/* - * Air quality metrics - */ -message AirQualityMetrics { - /* - * Concentration Units Standard PM1.0 - */ - uint32 pm10_standard = 1; - - /* - * Concentration Units Standard PM2.5 - */ - uint32 pm25_standard = 2; - - /* - * Concentration Units Standard PM10.0 - */ - uint32 pm100_standard = 3; - - /* - * Concentration Units Environmental PM1.0 - */ - uint32 pm10_environmental = 4; - - /* - * Concentration Units Environmental PM2.5 - */ - uint32 pm25_environmental = 5; - - /* - * Concentration Units Environmental PM10.0 - */ - uint32 pm100_environmental = 6; - - /* - * 0.3um Particle Count - */ - uint32 particles_03um = 7; - - /* - * 0.5um Particle Count - */ - uint32 particles_05um = 8; - - /* - * 1.0um Particle Count - */ - uint32 particles_10um = 9; - - /* - * 2.5um Particle Count - */ - uint32 particles_25um = 10; - - /* - * 5.0um Particle Count - */ - uint32 particles_50um = 11; - - /* - * 10.0um Particle Count - */ - uint32 particles_100um = 12; -} - -/* - * Types of Measurements the telemetry module is equipped to handle - */ -message Telemetry { - /* - * Seconds since 1970 - or 0 for unknown/unset - */ - fixed32 time = 1; - - oneof variant { - /* - * Key native device metrics such as battery level - */ - DeviceMetrics device_metrics = 2; - - /* - * Weather station or other environmental metrics - */ - EnvironmentMetrics environment_metrics = 3; - - /* - * Air quality metrics - */ - AirQualityMetrics air_quality_metrics = 4; - - /* - * Power Metrics - */ - PowerMetrics power_metrics = 5; - } -} - -/* - * Supported I2C Sensors for telemetry in Meshtastic - */ -enum TelemetrySensorType { - /* - * No external telemetry sensor explicitly set - */ - SENSOR_UNSET = 0; - - /* - * High accuracy temperature, pressure, humidity - */ - BME280 = 1; - - /* - * High accuracy temperature, pressure, humidity, and air resistance - */ - BME680 = 2; - - /* - * Very high accuracy temperature - */ - MCP9808 = 3; - - /* - * Moderate accuracy current and voltage - */ - INA260 = 4; - - /* - * Moderate accuracy current and voltage - */ - INA219 = 5; - - /* - * High accuracy temperature and pressure - */ - BMP280 = 6; - - /* - * High accuracy temperature and humidity - */ - SHTC3 = 7; - - /* - * High accuracy pressure - */ - LPS22 = 8; - - /* - * 3-Axis magnetic sensor - */ - QMC6310 = 9; - - /* - * 6-Axis inertial measurement sensor - */ - QMI8658 = 10; - - /* - * 3-Axis magnetic sensor - */ - QMC5883L = 11; - - /* - * High accuracy temperature and humidity - */ - SHT31 = 12; - - /* - * PM2.5 air quality sensor - */ - PMSA003I = 13; - - /* - * INA3221 3 Channel Voltage / Current Sensor - */ - INA3221 = 14; - - /* - * BMP085/BMP180 High accuracy temperature and pressure (older Version of BMP280) - */ - BMP085 = 15; -} +syntax = "proto3"; + +package meshtastic; + +option csharp_namespace = "Meshtastic.Protobufs"; +option go_package = "github.com/meshtastic/go/generated"; +option java_outer_classname = "TelemetryProtos"; +option java_package = "org.meshtastic.proto"; +option swift_prefix = ""; + +/* + * Key native device metrics such as battery level + */ +message DeviceMetrics { + /* + * 0-100 (>100 means powered) + */ + optional uint32 battery_level = 1; + + /* + * Voltage measured + */ + optional float voltage = 2; + + /* + * Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). + */ + optional float channel_utilization = 3; + + /* + * Percent of airtime for transmission used within the last hour. + */ + optional float air_util_tx = 4; + + /* + * How long the device has been running since the last reboot (in seconds) + */ + optional uint32 uptime_seconds = 5; +} + +/* + * Weather station or other environmental metrics + */ +message EnvironmentMetrics { + /* + * Temperature measured + */ + optional float temperature = 1; + + /* + * Relative humidity percent measured + */ + optional float relative_humidity = 2; + + /* + * Barometric pressure in hPA measured + */ + optional float barometric_pressure = 3; + + /* + * Gas resistance in MOhm measured + */ + optional float gas_resistance = 4; + + /* + * Voltage measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x) + */ + optional float voltage = 5; + + /* + * Current measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x) + */ + optional float current = 6; + + /* + * relative scale IAQ value as measured by Bosch BME680 . value 0-500. + * Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. + */ + optional uint32 iaq = 7; + + /* + * RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm. + */ + optional float distance = 8; + + /* + * VEML7700 high accuracy ambient light(Lux) digital 16-bit resolution sensor. + */ + optional float lux = 9; + + /* + * VEML7700 high accuracy white light(irradiance) not calibrated digital 16-bit resolution sensor. + */ + optional float white_lux = 10; + + /* + * Infrared lux + */ + optional float ir_lux = 11; + + /* + * Ultraviolet lux + */ + optional float uv_lux = 12; + + /* + * Wind direction in degrees + * 0 degrees = North, 90 = East, etc... + */ + optional uint32 wind_direction = 13; + + /* + * Wind speed in m/s + */ + optional float wind_speed = 14; + + /* + * Weight in KG + */ + optional float weight = 15; + + /* + * Wind gust in m/s + */ + optional float wind_gust = 16; + + /* + * Wind lull in m/s + */ + optional float wind_lull = 17; + + /* + * Radiation in µR/h + */ + optional float radiation = 18; + + /* + * Rainfall in the last hour in mm + */ + optional float rainfall_1h = 19; + + /* + * Rainfall in the last 24 hours in mm + */ + optional float rainfall_24h = 20; + + /* + * Soil moisture measured (% 1-100) + */ + optional uint32 soil_moisture = 21; + + /* + * Soil temperature measured (*C) + */ + optional float soil_temperature = 22; + + /* + * One-wire temperature (*C) + */ + repeated float one_wire_temperature = 23; +} + +/* + * Power Metrics (voltage / current / etc) + */ +message PowerMetrics { + /* + * Voltage (Ch1) + */ + optional float ch1_voltage = 1; + + /* + * Current (Ch1) + */ + optional float ch1_current = 2; + + /* + * Voltage (Ch2) + */ + optional float ch2_voltage = 3; + + /* + * Current (Ch2) + */ + optional float ch2_current = 4; + + /* + * Voltage (Ch3) + */ + optional float ch3_voltage = 5; + + /* + * 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; +} + +/* + * Air quality metrics + */ +message AirQualityMetrics { + /* + * Concentration Units Standard PM1.0 in ug/m3 + */ + optional uint32 pm10_standard = 1; + + /* + * Concentration Units Standard PM2.5 in ug/m3 + */ + optional uint32 pm25_standard = 2; + + /* + * Concentration Units Standard PM10.0 in ug/m3 + */ + optional uint32 pm100_standard = 3; + + /* + * Concentration Units Environmental PM1.0 in ug/m3 + */ + optional uint32 pm10_environmental = 4; + + /* + * Concentration Units Environmental PM2.5 in ug/m3 + */ + optional uint32 pm25_environmental = 5; + + /* + * Concentration Units Environmental PM10.0 in ug/m3 + */ + optional uint32 pm100_environmental = 6; + + /* + * 0.3um Particle Count in #/0.1l + */ + optional uint32 particles_03um = 7; + + /* + * 0.5um Particle Count in #/0.1l + */ + optional uint32 particles_05um = 8; + + /* + * 1.0um Particle Count in #/0.1l + */ + optional uint32 particles_10um = 9; + + /* + * 2.5um Particle Count in #/0.1l + */ + optional uint32 particles_25um = 10; + + /* + * 5.0um Particle Count in #/0.1l + */ + optional uint32 particles_50um = 11; + + /* + * 10.0um Particle Count in #/0.1l + */ + optional uint32 particles_100um = 12; + + /* + * 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; +} + +/* + * Local device mesh statistics + */ +message LocalStats { + /* + * How long the device has been running since the last reboot (in seconds) + */ + uint32 uptime_seconds = 1; + /* + * Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). + */ + float channel_utilization = 2; + /* + * Percent of airtime for transmission used within the last hour. + */ + float air_util_tx = 3; + + /* + * Number of packets sent + */ + uint32 num_packets_tx = 4; + + /* + * Number of packets received (both good and bad) + */ + uint32 num_packets_rx = 5; + + /* + * Number of packets received that are malformed or violate the protocol + */ + uint32 num_packets_rx_bad = 6; + + /* + * Number of nodes online (in the past 2 hours) + */ + uint32 num_online_nodes = 7; + + /* + * Number of nodes total + */ + uint32 num_total_nodes = 8; + + /* + * Number of received packets that were duplicates (due to multiple nodes relaying). + * If this number is high, there are nodes in the mesh relaying packets when it's unnecessary, for example due to the ROUTER/REPEATER role. + */ + uint32 num_rx_dupe = 9; + + /* + * Number of packets we transmitted that were a relay for others (not originating from ourselves). + */ + uint32 num_tx_relay = 10; + + /* + * Number of times we canceled a packet to be relayed, because someone else did it before us. + * 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 { + /* + * Heart rate (beats per minute) + */ + optional uint32 heart_bpm = 1; + + /* + * SpO2 (blood oxygen saturation) level + */ + optional uint32 spO2 = 2; + + /* + * Body temperature in degrees Celsius + */ + 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 + */ +message Telemetry { + /* + * Seconds since 1970 - or 0 for unknown/unset + */ + fixed32 time = 1; + + oneof variant { + /* + * Key native device metrics such as battery level + */ + DeviceMetrics device_metrics = 2; + + /* + * Weather station or other environmental metrics + */ + EnvironmentMetrics environment_metrics = 3; + + /* + * Air quality metrics + */ + AirQualityMetrics air_quality_metrics = 4; + + /* + * Power Metrics + */ + PowerMetrics power_metrics = 5; + + /* + * Local device mesh statistics + */ + LocalStats local_stats = 6; + + /* + * Health telemetry metrics + */ + HealthMetrics health_metrics = 7; + + /* + * Linux host metrics + */ + HostMetrics host_metrics = 8; + + /* + * Traffic management statistics + */ + TrafficManagementStats traffic_management_stats = 9; + } +} + +/* + * Supported I2C Sensors for telemetry in Meshtastic + */ +enum TelemetrySensorType { + /* + * No external telemetry sensor explicitly set + */ + SENSOR_UNSET = 0; + + /* + * High accuracy temperature, pressure, humidity + */ + BME280 = 1; + + /* + * High accuracy temperature, pressure, humidity, and air resistance + */ + BME680 = 2; + + /* + * Very high accuracy temperature + */ + MCP9808 = 3; + + /* + * Moderate accuracy current and voltage + */ + INA260 = 4; + + /* + * Moderate accuracy current and voltage + */ + INA219 = 5; + + /* + * High accuracy temperature and pressure + */ + BMP280 = 6; + + /* + * TODO - REMOVE High accuracy temperature and humidity + */ + SHTC3 = 7; + + /* + * High accuracy pressure + */ + LPS22 = 8; + + /* + * 3-Axis magnetic sensor + */ + QMC6310 = 9; + + /* + * 6-Axis inertial measurement sensor + */ + QMI8658 = 10; + + /* + * 3-Axis magnetic sensor + */ + QMC5883L = 11; + + /* + * TODO - REMOVE High accuracy temperature and humidity + */ + SHT31 = 12; + + /* + * PM2.5 air quality sensor + */ + PMSA003I = 13; + + /* + * INA3221 3 Channel Voltage / Current Sensor + */ + INA3221 = 14; + + /* + * BMP085/BMP180 High accuracy temperature and pressure (older Version of BMP280) + */ + BMP085 = 15; + + /* + * RCWL-9620 Doppler Radar Distance Sensor, used for water level detection + */ + RCWL9620 = 16; + + /* + * TODO - REMOVE Sensirion High accuracy temperature and humidity + */ + SHT4X = 17; + + /* + * VEML7700 high accuracy ambient light(Lux) digital 16-bit resolution sensor. + */ + VEML7700 = 18; + + /* + * MLX90632 non-contact IR temperature sensor. + */ + MLX90632 = 19; + + /* + * TI OPT3001 Ambient Light Sensor + */ + OPT3001 = 20; + + /* + * Lite On LTR-390UV-01 UV Light Sensor + */ + LTR390UV = 21; + + /* + * AMS TSL25911FN RGB Light Sensor + */ + TSL25911FN = 22; + + /* + * AHT10 Integrated temperature and humidity sensor + */ + AHT10 = 23; + + /* + * DFRobot Lark Weather station (temperature, humidity, pressure, wind speed and direction) + */ + DFROBOT_LARK = 24; + + /* + * NAU7802 Scale Chip or compatible + */ + NAU7802 = 25; + + /* + * BMP3XX High accuracy temperature and pressure + */ + BMP3XX = 26; + + /* + * ICM-20948 9-Axis digital motion processor + */ + ICM20948 = 27; + + /* + * MAX17048 1S lipo battery sensor (voltage, state of charge, time to go) + */ + MAX17048 = 28; + + /* + * Custom I2C sensor implementation based on https://github.com/meshtastic/i2c-sensor + */ + CUSTOM_SENSOR = 29; + + /* + * MAX30102 Pulse Oximeter and Heart-Rate Sensor + */ + MAX30102 = 30; + + /* + * MLX90614 non-contact IR temperature sensor + */ + MLX90614 = 31; + + /* + * SCD40/SCD41 CO2, humidity, temperature sensor + */ + SCD4X = 32; + + /* + * ClimateGuard RadSens, radiation, Geiger-Muller Tube + */ + RADSENS = 33; + + /* + * High accuracy current and voltage + */ + INA226 = 34; + + /* + * DFRobot Gravity tipping bucket rain gauge + */ + DFROBOT_RAIN = 35; + + /* + * Infineon DPS310 High accuracy pressure and temperature + */ + DPS310 = 36; + + /* + * 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; +} + +/* + * NAU7802 Telemetry configuration, for saving to flash + */ +message Nau7802Config { + /* + * The offset setting for the NAU7802 + */ + int32 zeroOffset = 1; + + /* + * The calibration factor for the NAU7802 + */ + 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" + ] +}