diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml index 72987c01e..d9b23a7e8 100644 --- a/.github/workflows/docker_build.yml +++ b/.github/workflows/docker_build.yml @@ -56,6 +56,25 @@ jobs: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT id: version + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + with: + cache-image: true + + - name: Docker setup + uses: docker/setup-buildx-action@v4 + with: + # Add Google/Amazon DockerHub mirrors to buildkit config + # https://docs.docker.com/build/ci/github-actions/configure-builder/#registry-mirror + buildkitd-config-inline: | + [registry."docker.io"] + mirrors = ["mirror.gcr.io", "public.ecr.aws"] + + - name: Sanitize platform string + id: sanitize_platform + # Replace slashes with underscores + run: echo "cleaned_platform=${{ inputs.platform }}" | sed 's/\//_/g' >> $GITHUB_OUTPUT + - name: Docker login if: ${{ inputs.push }} uses: docker/login-action@v4 @@ -63,17 +82,6 @@ jobs: username: meshtastic password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }} - - name: Set up QEMU - uses: docker/setup-qemu-action@v4 - - - name: Docker setup - uses: docker/setup-buildx-action@v4 - - - name: Sanitize platform string - id: sanitize_platform - # Replace slashes with underscores - run: echo "cleaned_platform=${{ inputs.platform }}" | sed 's/\//_/g' >> $GITHUB_OUTPUT - - name: Docker tag id: meta uses: docker/metadata-action@v6 @@ -95,3 +103,6 @@ jobs: platforms: ${{ inputs.platform }} build-args: | PIO_ENV=${{ inputs.pio_env }} + # Cache image layers in GitHub Actions cache to speed up subsequent builds. + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 1221c171f..88395600a 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -301,15 +301,17 @@ jobs: id: release_notes run: | chmod +x ./bin/generate_release_notes.py - NOTES=$(./bin/generate_release_notes.py ${{ needs.version.outputs.long }}) + NOTES=$(./bin/generate_release_notes.py ${{ needs.version.outputs.long }} --compare-ref HEAD 2>release_notes.log) echo "notes<> $GITHUB_OUTPUT echo "$NOTES" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT + echo "### Release note range" >> $GITHUB_STEP_SUMMARY + cat release_notes.log >> $GITHUB_STEP_SUMMARY env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Create release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 id: create_release with: draft: true @@ -466,7 +468,7 @@ jobs: - name: Generate release notes run: | chmod +x ./bin/generate_release_notes.py - ./bin/generate_release_notes.py ${{ needs.version.outputs.long }} > ./publish/release_notes.md + ./bin/generate_release_notes.py ${{ needs.version.outputs.long }} --compare-ref HEAD > ./publish/release_notes.md env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/models_issue_triage.yml b/.github/workflows/models_issue_triage.yml index ef12885f8..a02646ea0 100644 --- a/.github/workflows/models_issue_triage.yml +++ b/.github/workflows/models_issue_triage.yml @@ -38,7 +38,7 @@ jobs: - name: Apply quality label if needed if: steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok' - uses: actions/github-script@v8 + uses: actions/github-script@v9 env: QUALITY_LABEL: ${{ steps.quality.outputs.response }} with: @@ -80,7 +80,7 @@ jobs: # ───────────────────────────────────────────────────────────────────────── - name: Determine if completeness check should be skipped if: steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == '' - uses: actions/github-script@v8 + uses: actions/github-script@v9 id: check-skip with: script: | @@ -134,7 +134,7 @@ jobs: - name: Process analysis result if: (steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == '') && steps.check-skip.outputs.should_skip != 'true' && steps.analysis.outputs.response != '' - uses: actions/github-script@v8 + uses: actions/github-script@v9 id: process env: AI_RESPONSE: ${{ steps.analysis.outputs.response }} @@ -174,7 +174,7 @@ jobs: - name: Apply triage label if: steps.process.outputs.label != '' && steps.process.outputs.label != 'none' - uses: actions/github-script@v8 + uses: actions/github-script@v9 env: LABEL_NAME: ${{ steps.process.outputs.label }} with: @@ -200,7 +200,7 @@ jobs: - name: Comment on issue if: steps.process.outputs.should_comment == 'true' - uses: actions/github-script@v8 + uses: actions/github-script@v9 env: COMMENT_BODY: ${{ steps.process.outputs.comment_body }} with: diff --git a/.github/workflows/models_pr_triage.yml b/.github/workflows/models_pr_triage.yml index d4c8509d2..f39ee4845 100644 --- a/.github/workflows/models_pr_triage.yml +++ b/.github/workflows/models_pr_triage.yml @@ -22,7 +22,7 @@ jobs: # Step 1: Check if PR already has automation/type labels (skip if so) # ───────────────────────────────────────────────────────────────────────── - name: Check existing labels - uses: actions/github-script@v8 + uses: actions/github-script@v9 id: check-labels with: script: | @@ -58,7 +58,7 @@ jobs: - name: Apply quality label if needed if: steps.check-labels.outputs.skip_all != 'true' && steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok' - uses: actions/github-script@v8 + uses: actions/github-script@v9 id: quality-label env: QUALITY_LABEL: ${{ steps.quality.outputs.response }} @@ -113,7 +113,7 @@ jobs: - name: Apply type label if: steps.check-labels.outputs.skip_all != 'true' && steps.check-labels.outputs.has_type_label != 'true' && steps.classify.outputs.response != '' - uses: actions/github-script@v8 + uses: actions/github-script@v9 env: TYPE_LABEL: ${{ steps.classify.outputs.response }} with: diff --git a/.github/workflows/package_ppa.yml b/.github/workflows/package_ppa.yml index 334a7016d..c51e64e78 100644 --- a/.github/workflows/package_ppa.yml +++ b/.github/workflows/package_ppa.yml @@ -5,6 +5,8 @@ on: secrets: PPA_GPG_PRIVATE_KEY: required: true + PPA_SFTP_PRIVATE_KEY: + required: true inputs: ppa_repo: description: Meshtastic PPA to target @@ -27,6 +29,7 @@ jobs: build_location: ppa package-ppa: + if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }} runs-on: ubuntu-24.04 needs: build-debian-src steps: @@ -40,7 +43,7 @@ jobs: shell: bash run: | sudo apt-get update -y --fix-missing - sudo apt-get install -y dput + sudo apt-get install -y dput openssh-client - name: Import GPG key uses: crazy-max/ghaction-import-gpg@v7 @@ -65,8 +68,42 @@ jobs: - name: Display structure of downloaded files run: ls -lah - - name: Publish with dput - if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }} - timeout-minutes: 15 # dput is terrible, sometimes runs 'forever' + - name: Trust Launchpad's SSH key run: | - dput ${{ inputs.ppa_repo }} meshtasticd_${{ steps.version.outputs.deb }}~${{ inputs.series }}_source.changes + mkdir -p ~/.ssh + ssh-keyscan -H ppa.launchpad.net >> ~/.ssh/known_hosts + + - name: Setup dput config + env: + ppa_login: meshtasticorg + run: | + sudo tee /etc/meshtastic-dput.cf >/dev/null < + dput -c /etc/meshtastic-dput.cf + ssh-${up_ppa_repo} + meshtasticd_${up_version}~${up_series}_source.changes diff --git a/.github/workflows/pr_enforce_labels.yml b/.github/workflows/pr_enforce_labels.yml index d60c9c8ca..bf2239f63 100644 --- a/.github/workflows/pr_enforce_labels.yml +++ b/.github/workflows/pr_enforce_labels.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check for PR labels - uses: actions/github-script@v8 + uses: actions/github-script@v9 with: script: | const labels = context.payload.pull_request.labels.map(label => label.name); diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml index 3556226ba..e3321712e 100644 --- a/.github/workflows/pr_tests.yml +++ b/.github/workflows/pr_tests.yml @@ -177,7 +177,7 @@ jobs: - name: Comment test results on PR if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped' - uses: actions/github-script@v8 + uses: actions/github-script@v9 with: script: | const fs = require('fs'); diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index daa18e6af..be5142843 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -52,7 +52,7 @@ jobs: node-version: 24 - name: Setup pnpm - uses: pnpm/action-setup@v5 + uses: pnpm/action-setup@v6 with: version: latest diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 05f1bb22e..d0cbaa8bc 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -8,10 +8,10 @@ plugins: uri: https://github.com/trunk-io/plugins lint: enabled: - - checkov@3.2.513 - - renovate@43.104.6 + - checkov@3.2.517 + - renovate@43.110.9 - prettier@3.8.1 - - trufflehog@3.94.2 + - trufflehog@3.94.3 - yamllint@1.38.0 - bandit@1.9.4 - trivy@0.69.3 diff --git a/bin/config.d/lora-ecb41-pge-MeshAdv-900M30S.yaml b/bin/config.d/lora-ecb41-pge-MeshAdv-900M30S.yaml new file mode 100644 index 000000000..25fd5e359 --- /dev/null +++ b/bin/config.d/lora-ecb41-pge-MeshAdv-900M30S.yaml @@ -0,0 +1,39 @@ +# MeshAdv-Pi E22-900M30S +# https://github.com/chrismyers2000/MeshAdv-Pi-Hat +Meta: + name: MeshAdv-Pi E22-900M30S + support: community + compatible: + - ebyte-ecb41-pge # Armbian + +Lora: + Module: sx1262 + CS: # GPIO0_A1 (physical 40) + pin: 1 + gpiochip: 0 + line: 1 + IRQ: # GPIO0_A3 (physical 36) + pin: 3 + gpiochip: 0 + line: 3 + Busy: # GPIO0_A0 (physical 38) + pin: 0 + gpiochip: 0 + line: 0 + Reset: # GPIO0_B4 (physical 12) + pin: 12 + gpiochip: 0 + line: 12 + TXen: # GPIO1_D1 (physical 33) + pin: 57 + gpiochip: 1 + line: 25 + RXen: # GPIO1_B3 (physical 32) + pin: 43 + gpiochip: 1 + line: 11 + DIO3_TCXO_VOLTAGE: true + # Only for E22-900M33S: + # Limit the output power to 8 dBm + # SX126X_MAX_POWER: 8 + spidev: spidev0.0 diff --git a/bin/config.d/lora-ecb41-pge-MeshAdv-Mini-900M22S.yaml b/bin/config.d/lora-ecb41-pge-MeshAdv-Mini-900M22S.yaml new file mode 100644 index 000000000..e1f385312 --- /dev/null +++ b/bin/config.d/lora-ecb41-pge-MeshAdv-Mini-900M22S.yaml @@ -0,0 +1,33 @@ +# MeshAdv Mini E22-900M22S +# https://github.com/chrismyers2000/MeshAdv-Mini +Meta: + name: MeshAdv Mini E22-900M22S + support: community + compatible: + - ebyte-ecb41-pge # Armbian + +Lora: + Module: sx1262 # Ebyte E22-900M22S + CS: # GPIO0_B6 (physical 24, SPI1_CSN0) + pin: 14 + gpiochip: 0 + line: 14 + IRQ: # GPIO0_A3 (physical 36) + pin: 3 + gpiochip: 0 + line: 3 + Busy: # GPIO0_A0 (physical 38) + pin: 0 + gpiochip: 0 + line: 0 + Reset: # GPIO1_C3 (physical 18) + pin: 51 + gpiochip: 1 + line: 19 + RXen: # GPIO1_B3 (physical 32) + pin: 43 + gpiochip: 1 + line: 11 + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true + spidev: spidev0.0 diff --git a/bin/config.d/lora-ecb41-pge-RAK6421-13300-slot1.yaml b/bin/config.d/lora-ecb41-pge-RAK6421-13300-slot1.yaml new file mode 100644 index 000000000..8782876ac --- /dev/null +++ b/bin/config.d/lora-ecb41-pge-RAK6421-13300-slot1.yaml @@ -0,0 +1,38 @@ +Meta: + name: RAK6421 + RAK13300 Slot 1 + support: community # Promote when tested + compatible: + - ebyte-ecb41-pge # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_A5 (IO6, physical 15) + pin: 5 + gpiochip: 0 + line: 5 + Reset: # GPIO0_A3 (IO4, physical 36) + pin: 3 + gpiochip: 0 + line: 3 + Busy: # GPIO1_C3 (IO5, physical 18) + pin: 51 + gpiochip: 1 + line: 19 + # Ant_sw: # GPIO1_C2 (IO3, physical 16) + # pin: 50 + # gpiochip: 1 + # line: 18 + Enable_Pins: + - pin: 43 # GPIO1_B3 (physical 32) + gpiochip: 1 + line: 11 + - pin: 57 # GPIO1_D1 (physical 33) + gpiochip: 1 + line: 25 + DIO3_TCXO_VOLTAGE: true + DIO2_AS_RF_SWITCH: true + spidev: spidev0.0 + # CS: # GPIO0_B6 (SPI1_CSN0, physical 24) + # pin: 14 + # gpiochip: 0 + # line: 14 diff --git a/bin/config.d/lora-ecb41-pge-RAK6421-13300-slot2.yaml b/bin/config.d/lora-ecb41-pge-RAK6421-13300-slot2.yaml new file mode 100644 index 000000000..e0ef946d9 --- /dev/null +++ b/bin/config.d/lora-ecb41-pge-RAK6421-13300-slot2.yaml @@ -0,0 +1,36 @@ +Meta: + name: RAK6421 + RAK13300 Slot 2 + support: community # Promote when tested + compatible: + - ebyte-ecb41-pge # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_B4 (IO6, physical 12) + pin: 12 + gpiochip: 0 + line: 12 + Reset: # GPIO1_C3 (IO4, physical 18) + pin: 51 + gpiochip: 1 + line: 19 + Busy: # GPIO0_B3 (IO5, physical 35) + pin: 11 + gpiochip: 0 + line: 11 + # Ant_sw: # GPIO1_C2 (IO3, physical 16) + # pin: 50 + # gpiochip: 1 + # line: 18 + Enable_Pins: + - pin: 2 # GPIO0_A2 (physical 37) + gpiochip: 0 + line: 2 + - pin: 50 # GPIO1_C2 (physical 16) + gpiochip: 1 + line: 18 + spidev: spidev0.1 + # CS: # GPIO0_A7 (SPI1_CSN1, physical 26) + # pin: 7 + # gpiochip: 0 + # line: 7 diff --git a/bin/config.d/lora-ecb41-pge-RAK6421-13302-slot1.yaml b/bin/config.d/lora-ecb41-pge-RAK6421-13302-slot1.yaml new file mode 100644 index 000000000..374be8e35 --- /dev/null +++ b/bin/config.d/lora-ecb41-pge-RAK6421-13302-slot1.yaml @@ -0,0 +1,39 @@ +Meta: + name: RAK6421 + RAK13302 Slot 1 + support: community # Promote when tested + compatible: + - ebyte-ecb41-pge # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_A5 (IO6, physical 15) + pin: 5 + gpiochip: 0 + line: 5 + Reset: # GPIO0_A3 (IO4, physical 36) + pin: 3 + gpiochip: 0 + line: 3 + Busy: # GPIO1_C3 (IO5, physical 18) + pin: 51 + gpiochip: 1 + line: 19 + # Ant_sw: # GPIO1_C2 (IO3, physical 16) + # pin: 50 + # gpiochip: 1 + # line: 18 + Enable_Pins: + - pin: 43 # GPIO1_B3 (physical 32) + gpiochip: 1 + line: 11 + - pin: 57 # GPIO1_D1 (physical 33) + gpiochip: 1 + line: 25 + DIO3_TCXO_VOLTAGE: true + DIO2_AS_RF_SWITCH: true + spidev: spidev0.0 + # CS: # GPIO0_B6 (SPI1_CSN0, physical 24) + # pin: 14 + # gpiochip: 0 + # line: 14 + TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8] diff --git a/bin/config.d/lora-ecb41-pge-RAK6421-13302-slot2.yaml b/bin/config.d/lora-ecb41-pge-RAK6421-13302-slot2.yaml new file mode 100644 index 000000000..5548bc5c7 --- /dev/null +++ b/bin/config.d/lora-ecb41-pge-RAK6421-13302-slot2.yaml @@ -0,0 +1,37 @@ +Meta: + name: RAK6421 + RAK13302 Slot 2 + support: community # Promote when tested + compatible: + - ebyte-ecb41-pge # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_B4 (IO6, physical 12) + pin: 12 + gpiochip: 0 + line: 12 + Reset: # GPIO1_C3 (IO4, physical 18) + pin: 51 + gpiochip: 1 + line: 19 + Busy: # GPIO0_B3 (IO5, physical 35) + pin: 11 + gpiochip: 0 + line: 11 + # Ant_sw: # GPIO1_C2 (IO3, physical 16) + # pin: 50 + # gpiochip: 1 + # line: 18 + Enable_Pins: + - pin: 2 # GPIO0_A2 (physical 37) + gpiochip: 0 + line: 2 + - pin: 50 # GPIO1_C2 (physical 16) + gpiochip: 1 + line: 18 + spidev: spidev0.1 + # CS: # GPIO0_A7 (SPI1_CSN1, physical 26) + # pin: 7 + # gpiochip: 0 + # line: 7 + TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8] diff --git a/bin/config.d/lora-ecb41-pge-waveshare-sxxx.yaml b/bin/config.d/lora-ecb41-pge-waveshare-sxxx.yaml new file mode 100644 index 000000000..1253d3e31 --- /dev/null +++ b/bin/config.d/lora-ecb41-pge-waveshare-sxxx.yaml @@ -0,0 +1,30 @@ +Meta: + name: Waveshare SX1262 + support: deprecated + compatible: + - ebyte-ecb41-pge # Armbian + +Lora: + Module: sx1262 # Waveshare SX126X XXXM + DIO2_AS_RF_SWITCH: true + CS: # GPIO0_A1 (physical 40) + pin: 1 + gpiochip: 0 + line: 1 + IRQ: # GPIO0_A3 (physical 36) + pin: 3 + gpiochip: 0 + line: 3 + Busy: # GPIO0_A0 (physical 38) + pin: 0 + gpiochip: 0 + line: 0 + Reset: # GPIO0_B4 (physical 12) + pin: 12 + gpiochip: 0 + line: 12 + SX126X_ANT_SW: # GPIO1_B2 (physical 31) + pin: 42 + gpiochip: 1 + line: 10 + spidev: spidev0.0 diff --git a/bin/config.d/lora-ok3506-MeshAdv-900M30S.yaml b/bin/config.d/lora-ok3506-MeshAdv-900M30S.yaml new file mode 100644 index 000000000..c39a07ccd --- /dev/null +++ b/bin/config.d/lora-ok3506-MeshAdv-900M30S.yaml @@ -0,0 +1,41 @@ +# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards) + +# MeshAdv-Pi E22-900M30S +# https://github.com/chrismyers2000/MeshAdv-Pi-Hat +Meta: + name: MeshAdv-Pi E22-900M30S + support: community + compatible: + - forlinx-ok3506-s12 # Armbian + +Lora: + Module: sx1262 + CS: # GPIO0_B0 (physical 40) + pin: 8 + gpiochip: 0 + line: 8 + IRQ: # GPIO3_B0 (physical 36) + pin: 104 + gpiochip: 3 + line: 8 + Busy: # GPIO0_B1 (physical 38) + pin: 9 + gpiochip: 0 + line: 9 + Reset: # GPIO0_B6 (physical 12) + pin: 14 + gpiochip: 0 + line: 14 + TXen: # GPIO0_A3 (physical 33) + pin: 3 + gpiochip: 0 + line: 3 + RXen: # GPIO0_A2 (physical 32) + pin: 2 + gpiochip: 0 + line: 2 + DIO3_TCXO_VOLTAGE: true + # Only for E22-900M33S: + # Limit the output power to 8 dBm + # SX126X_MAX_POWER: 8 + spidev: spidev0.0 diff --git a/bin/config.d/lora-ok3506-MeshAdv-Mini-900M22S.yaml b/bin/config.d/lora-ok3506-MeshAdv-Mini-900M22S.yaml new file mode 100644 index 000000000..8f2c4a417 --- /dev/null +++ b/bin/config.d/lora-ok3506-MeshAdv-Mini-900M22S.yaml @@ -0,0 +1,35 @@ +# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards) + +# MeshAdv Mini E22-900M22S +# https://github.com/chrismyers2000/MeshAdv-Mini +Meta: + name: MeshAdv Mini E22-900M22S + support: community + compatible: + - forlinx-ok3506-s12 # Armbian + +Lora: + Module: sx1262 # Ebyte E22-900M22S + CS: # GPIO0_C3 (physical 24, SPI0_CSN0) + pin: 19 + gpiochip: 0 + line: 19 + IRQ: # GPIO3_B0 (physical 36) + pin: 104 + gpiochip: 3 + line: 8 + Busy: # GPIO0_B1 (physical 38) + pin: 9 + gpiochip: 0 + line: 9 + Reset: # GPIO3_A6 (physical 18) + pin: 102 + gpiochip: 3 + line: 6 + RXen: # GPIO0_A2 (physical 32) + pin: 2 + gpiochip: 0 + line: 2 + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true + spidev: spidev0.0 diff --git a/bin/config.d/lora-ok3506-RAK6421-13300-slot1.yaml b/bin/config.d/lora-ok3506-RAK6421-13300-slot1.yaml new file mode 100644 index 000000000..d97bdd327 --- /dev/null +++ b/bin/config.d/lora-ok3506-RAK6421-13300-slot1.yaml @@ -0,0 +1,40 @@ +# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards) + +Meta: + name: RAK6421 + RAK13300 Slot 1 + support: community # Promote when tested + compatible: + - forlinx-ok3506-s12 # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO3_B5 (IO6, physical 15) + pin: 109 + gpiochip: 3 + line: 13 + Reset: # GPIO3_B0 (IO4, physical 36) + pin: 104 + gpiochip: 3 + line: 8 + Busy: # GPIO3_A6 (IO5, physical 18) + pin: 102 + gpiochip: 3 + line: 6 + # Ant_sw: # GPIO0_A3 (IO3, physical 33) + # pin: 3 + # gpiochip: 0 + # line: 3 + Enable_Pins: + - pin: 2 # GPIO0_A2 (physical 32) + gpiochip: 0 + line: 2 + - pin: 3 # GPIO0_A3 (physical 33) + gpiochip: 0 + line: 3 + DIO3_TCXO_VOLTAGE: true + DIO2_AS_RF_SWITCH: true + spidev: spidev0.0 + # CS: # GPIO0_C3 (SPI0_CSN0, physical 24) + # pin: 19 + # gpiochip: 0 + # line: 19 diff --git a/bin/config.d/lora-ok3506-RAK6421-13300-slot2.yaml b/bin/config.d/lora-ok3506-RAK6421-13300-slot2.yaml new file mode 100644 index 000000000..969c20ad3 --- /dev/null +++ b/bin/config.d/lora-ok3506-RAK6421-13300-slot2.yaml @@ -0,0 +1,38 @@ +# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards) + +Meta: + name: RAK6421 + RAK13300 Slot 2 + support: community # Promote when tested + compatible: + - forlinx-ok3506-s12 # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_B6 (IO6, physical 12) + pin: 14 + gpiochip: 0 + line: 14 + Reset: # GPIO3_A6 (IO4, physical 18) + pin: 102 + gpiochip: 3 + line: 6 + Busy: # GPIO0_B2 (IO5, physical 35) + pin: 10 + gpiochip: 0 + line: 10 + # Ant_sw: # GPIO3_A7 (IO3, physical 16) + # pin: 103 + # gpiochip: 3 + # line: 7 + Enable_Pins: + - pin: 106 # GPIO3_B2 (physical 37) + gpiochip: 3 + line: 10 + - pin: 103 # GPIO3_A7 (physical 16) + gpiochip: 3 + line: 7 + spidev: spidev0.1 + # CS: # GPIO0_B7 (SPI0_CSN1, physical 26) + # pin: 15 + # gpiochip: 0 + # line: 15 diff --git a/bin/config.d/lora-ok3506-RAK6421-13302-slot1.yaml b/bin/config.d/lora-ok3506-RAK6421-13302-slot1.yaml new file mode 100644 index 000000000..d73eaf7a0 --- /dev/null +++ b/bin/config.d/lora-ok3506-RAK6421-13302-slot1.yaml @@ -0,0 +1,41 @@ +# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards) + +Meta: + name: RAK6421 + RAK13302 Slot 1 + support: community # Promote when tested + compatible: + - forlinx-ok3506-s12 # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO3_B5 (IO6, physical 15) + pin: 109 + gpiochip: 3 + line: 13 + Reset: # GPIO3_B0 (IO4, physical 36) + pin: 104 + gpiochip: 3 + line: 8 + Busy: # GPIO3_A6 (IO5, physical 18) + pin: 102 + gpiochip: 3 + line: 6 + # Ant_sw: # GPIO0_A3 (IO3, physical 33) + # pin: 3 + # gpiochip: 0 + # line: 3 + Enable_Pins: + - pin: 2 # GPIO0_A2 (physical 32) + gpiochip: 0 + line: 2 + - pin: 3 # GPIO0_A3 (physical 33) + gpiochip: 0 + line: 3 + DIO3_TCXO_VOLTAGE: true + DIO2_AS_RF_SWITCH: true + spidev: spidev0.0 + # CS: # GPIO0_C3 (SPI0_CSN0, physical 24) + # pin: 19 + # gpiochip: 0 + # line: 19 + TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8] diff --git a/bin/config.d/lora-ok3506-RAK6421-13302-slot2.yaml b/bin/config.d/lora-ok3506-RAK6421-13302-slot2.yaml new file mode 100644 index 000000000..36b70658b --- /dev/null +++ b/bin/config.d/lora-ok3506-RAK6421-13302-slot2.yaml @@ -0,0 +1,39 @@ +# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards) + +Meta: + name: RAK6421 + RAK13302 Slot 2 + support: community # Promote when tested + compatible: + - forlinx-ok3506-s12 # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_B6 (IO6, physical 12) + pin: 14 + gpiochip: 0 + line: 14 + Reset: # GPIO3_A6 (IO4, physical 18) + pin: 102 + gpiochip: 3 + line: 6 + Busy: # GPIO0_B2 (IO5, physical 35) + pin: 10 + gpiochip: 0 + line: 10 + # Ant_sw: # GPIO3_A7 (IO3, physical 16) + # pin: 103 + # gpiochip: 3 + # line: 7 + Enable_Pins: + - pin: 106 # GPIO3_B2 (physical 37) + gpiochip: 3 + line: 10 + - pin: 103 # GPIO3_A7 (physical 16) + gpiochip: 3 + line: 7 + spidev: spidev0.1 + # CS: # GPIO0_B7 (SPI0_CSN1, physical 26) + # pin: 15 + # gpiochip: 0 + # line: 15 + TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8] diff --git a/bin/config.d/lora-ok3506-waveshare-sxxx.yaml b/bin/config.d/lora-ok3506-waveshare-sxxx.yaml new file mode 100644 index 000000000..1f5795f92 --- /dev/null +++ b/bin/config.d/lora-ok3506-waveshare-sxxx.yaml @@ -0,0 +1,32 @@ +# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards) + +Meta: + name: Waveshare SX1262 + support: deprecated + compatible: + - forlinx-ok3506-s12 # Armbian + +Lora: + Module: sx1262 # Waveshare SX126X XXXM + DIO2_AS_RF_SWITCH: true + CS: # GPIO0_B0 (physical 40) + pin: 8 + gpiochip: 0 + line: 8 + IRQ: # GPIO3_B0 (physical 36) + pin: 104 + gpiochip: 3 + line: 8 + Busy: # GPIO0_B1 (physical 38) + pin: 9 + gpiochip: 0 + line: 9 + Reset: # GPIO0_B6 (physical 12) + pin: 14 + gpiochip: 0 + line: 14 + SX126X_ANT_SW: # GPIO3_B3 (physical 31) + pin: 107 + gpiochip: 3 + line: 11 + spidev: spidev0.0 diff --git a/bin/generate_release_notes.py b/bin/generate_release_notes.py index d0f1147da..533ff6909 100755 --- a/bin/generate_release_notes.py +++ b/bin/generate_release_notes.py @@ -1,25 +1,31 @@ #!/usr/bin/env python3 -""" -Generate release notes from merged PRs on develop and master branches. -Categorizes PRs into Enhancements and Bug Fixes/Maintenance sections. -""" +"""Generate release notes from the actual release commit range.""" -import subprocess -import re +import argparse import json +import re +import subprocess import sys -from datetime import datetime -def get_last_release_tag(): - """Get the most recent release tag.""" +def get_last_release_tag(compare_ref, exclude_tag=None): + """Get the most recent version tag merged into compare_ref.""" result = subprocess.run( - ["git", "describe", "--tags", "--abbrev=0"], + ["git", "tag", "--merged", compare_ref, "--sort=-version:refname", "v*"], capture_output=True, text=True, check=True, ) - return result.stdout.strip() + + for line in result.stdout.splitlines(): + candidate = line.strip() + if not candidate: + continue + if exclude_tag and candidate == exclude_tag: + continue + return candidate + + raise subprocess.CalledProcessError(result.returncode, result.args, output=result.stdout, stderr=result.stderr) def get_tag_date(tag): @@ -33,18 +39,18 @@ def get_tag_date(tag): return result.stdout.strip() -def get_merged_prs_since_tag(tag, branch): - """Get all merged PRs since the given tag on the specified branch.""" - # Get commits since tag on the branch - look for PR numbers in parentheses +def get_merged_prs_in_range(tag, compare_ref): + """Get all merged PRs in the git range between tag and compare_ref.""" result = subprocess.run( [ "git", "log", - f"{tag}..origin/{branch}", + f"{tag}..{compare_ref}", "--oneline", ], capture_output=True, text=True, + check=True, ) prs = [] @@ -65,6 +71,25 @@ def get_merged_prs_since_tag(tag, branch): return prs +def parse_args(): + """Parse CLI arguments.""" + parser = argparse.ArgumentParser( + description="Generate release notes from the actual release commit range." + ) + parser.add_argument("new_version", help="Version that will be tagged for this release") + parser.add_argument( + "--base-tag", + dest="base_tag", + help="Existing version tag to diff from. Defaults to the latest version tag merged into the compare ref.", + ) + parser.add_argument( + "--compare-ref", + default="HEAD", + help="Git ref to diff to. Defaults to HEAD.", + ) + return parser.parse_args() + + def get_pr_details(pr_number): """Get PR details from GitHub API via gh CLI.""" try: @@ -268,28 +293,28 @@ def get_new_contributors(pr_details_list, tag, repo="meshtastic/firmware"): def main(): - if len(sys.argv) < 2: - print("Usage: generate_release_notes.py ", file=sys.stderr) - sys.exit(1) - - new_version = sys.argv[1] + args = parse_args() + new_version = args.new_version + compare_ref = args.compare_ref + current_tag = f"v{new_version}" # Get last release tag try: - last_tag = get_last_release_tag() + last_tag = args.base_tag or get_last_release_tag(compare_ref, exclude_tag=current_tag) except subprocess.CalledProcessError: print("Error: Could not find last release tag", file=sys.stderr) sys.exit(1) - # Collect PRs from both branches - all_pr_numbers = set() + print( + f"Resolved release note range: {last_tag}..{compare_ref}", + file=sys.stderr, + ) - for branch in ["develop", "master"]: - try: - prs = get_merged_prs_since_tag(last_tag, branch) - all_pr_numbers.update(prs) - except Exception as e: - print(f"Warning: Could not get PRs from {branch}: {e}", file=sys.stderr) + try: + all_pr_numbers = set(get_merged_prs_in_range(last_tag, compare_ref)) + except subprocess.CalledProcessError as e: + print(f"Error: Could not get PRs for range {last_tag}..{compare_ref}: {e}", file=sys.stderr) + sys.exit(1) # Get details for all PRs enhancements = [] diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index 0642fdb07..a1690186b 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.23 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.22 diff --git a/debian/changelog b/debian/changelog index b13a2ae9d..c3f1424a5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +meshtasticd (2.7.23.0) unstable; urgency=medium + + * Version 2.7.23 + + -- GitHub Actions Tue, 14 Apr 2026 12:29:48 +0000 + meshtasticd (2.7.22.0) unstable; urgency=medium * Version 2.7.22 diff --git a/platformio.ini b/platformio.ini index 6be0579ec..46170fe09 100644 --- a/platformio.ini +++ b/platformio.ini @@ -131,103 +131,117 @@ lib_deps = ; Common libs for environmental measurements in telemetry module [environmental_base] lib_deps = - # renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO - adafruit/Adafruit BusIO@1.17.4 - # renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor - adafruit/Adafruit Unified Sensor@1.1.15 - # renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library - adafruit/Adafruit BMP280 Library@3.0.0 - # renovate: datasource=custom.pio depName=Adafruit BMP085 packageName=adafruit/library/Adafruit BMP085 Library - adafruit/Adafruit BMP085 Library@1.2.4 - # renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library - adafruit/Adafruit BME280 Library@2.3.0 - # renovate: datasource=custom.pio depName=Adafruit DPS310 packageName=adafruit/library/Adafruit DPS310 - adafruit/Adafruit DPS310@1.1.6 - # renovate: datasource=custom.pio depName=Adafruit MCP9808 packageName=adafruit/library/Adafruit MCP9808 Library - adafruit/Adafruit MCP9808 Library@2.0.2 - # renovate: datasource=custom.pio depName=Adafruit INA260 packageName=adafruit/library/Adafruit INA260 Library - adafruit/Adafruit INA260 Library@1.5.3 - # renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219 - adafruit/Adafruit INA219@1.2.3 - # renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050 - adafruit/Adafruit MPU6050@2.2.9 - # renovate: datasource=custom.pio depName=Adafruit LIS3DH packageName=adafruit/library/Adafruit LIS3DH - adafruit/Adafruit LIS3DH@1.3.0 - # renovate: datasource=custom.pio depName=Adafruit AHTX0 packageName=adafruit/library/Adafruit AHTX0 - adafruit/Adafruit AHTX0@2.0.6 - # renovate: datasource=custom.pio depName=Adafruit LSM6DS packageName=adafruit/library/Adafruit LSM6DS - adafruit/Adafruit LSM6DS@4.7.4 - # renovate: datasource=custom.pio depName=Adafruit TSL2591 packageName=adafruit/library/Adafruit TSL2591 Library - adafruit/Adafruit TSL2591 Library@1.4.5 - # renovate: datasource=custom.pio depName=EmotiBit MLX90632 packageName=emotibit/library/EmotiBit MLX90632 - emotibit/EmotiBit MLX90632@1.0.8 - # renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library - adafruit/Adafruit MLX90614 Library@2.1.6 + # renovate: datasource=github-tags depName=Adafruit BusIO packageName=adafruit/Adafruit_BusIO + https://github.com/adafruit/Adafruit_BusIO/archive/refs/tags/1.17.4.zip + # renovate: datasource=github-tags depName=Adafruit Unified Sensor packageName=adafruit/Adafruit_Sensor + https://github.com/adafruit/Adafruit_Sensor/archive/refs/tags/1.1.15.zip + # renovate: datasource=github-tags depName=Adafruit GFX packageName=adafruit/Adafruit-GFX-Library + https://github.com/adafruit/Adafruit-GFX-Library/archive/refs/tags/1.12.6.zip + # renovate: datasource=github-tags depName=NeoPixel packageName=adafruit/Adafruit_NeoPixel + https://github.com/adafruit/Adafruit_NeoPixel/archive/refs/tags/1.15.4.zip + # renovate: datasource=github-tags depName=Adafruit SSD1306 packageName=adafruit/Adafruit_SSD1306 + https://github.com/adafruit/Adafruit_SSD1306/archive/refs/tags/2.5.16.zip + # renovate: datasource=github-tags depName=Adafruit BMP280 packageName=adafruit/Adafruit_BMP280_Library + https://github.com/adafruit/Adafruit_BMP280_Library/archive/refs/tags/3.0.0.zip + # renovate: datasource=github-tags depName=Adafruit BMP085 packageName=adafruit/Adafruit-BMP085-Library + https://github.com/adafruit/Adafruit-BMP085-Library/archive/refs/tags/1.2.4.zip + # renovate: datasource=github-tags depName=Adafruit BME280 packageName=adafruit/Adafruit_BME280_Library + https://github.com/adafruit/Adafruit_BME280_Library/archive/refs/tags/2.3.0.zip + # renovate: datasource=github-tags depName=Adafruit DPS310 packageName=adafruit/Adafruit_DPS310 + https://github.com/adafruit/Adafruit_DPS310/archive/refs/tags/1.1.6.zip + # renovate: datasource=github-tags depName=Adafruit SH110x packageName=adafruit/Adafruit_SH110x + https://github.com/adafruit/Adafruit_SH110x/archive/refs/tags/2.1.14.zip + # renovate: datasource=github-tags depName=Adafruit MCP9808 packageName=adafruit/Adafruit_MCP9808_Library + https://github.com/adafruit/Adafruit_MCP9808_Library/archive/refs/tags/2.0.2.zip + # renovate: datasource=github-tags depName=Adafruit INA260 packageName=adafruit/Adafruit_INA260 + https://github.com/adafruit/Adafruit_INA260/archive/refs/tags/1.5.3.zip + # renovate: datasource=github-tags depName=Adafruit INA219 packageName=adafruit/Adafruit_INA219 + https://github.com/adafruit/Adafruit_INA219/archive/refs/tags/1.2.3.zip + # renovate: datasource=github-tags depName=Adafruit MPU6050 packageName=adafruit/Adafruit_MPU6050 + https://github.com/adafruit/Adafruit_MPU6050/archive/refs/tags/2.2.9.zip + # renovate: datasource=github-tags depName=Adafruit LIS3DH packageName=adafruit/Adafruit_LIS3DH + https://github.com/adafruit/Adafruit_LIS3DH/archive/refs/tags/1.3.0.zip + # renovate: datasource=github-tags depName=Adafruit AHTX0 packageName=adafruit/Adafruit_AHTX0 + https://github.com/adafruit/Adafruit_AHTX0/archive/refs/tags/2.0.6.zip + # renovate: datasource=github-tags depName=Adafruit LSM6DS packageName=adafruit/Adafruit_LSM6DS + https://github.com/adafruit/Adafruit_LSM6DS/archive/refs/tags/4.7.4.zip + # renovate: datasource=github-tags depName=Adafruit TSL2591 packageName=adafruit/Adafruit_TSL2591_Library + https://github.com/adafruit/Adafruit_TSL2591_Library/archive/refs/tags/1.4.5.zip + # renovate: datasource=github-tags depName=EmotiBit MLX90632 packageName=emotibit/EmotiBit_MLX90632 + https://github.com/EmotiBit/EmotiBit_MLX90632/archive/refs/tags/v1.0.8.zip + # renovate: datasource=github-tags depName=Adafruit MLX90614 packageName=adafruit/Adafruit_MLX90614 + https://github.com/adafruit/Adafruit-MLX90614-Library/archive/refs/tags/2.1.6.zip # renovate: datasource=git-refs depName=INA3221 packageName=https://github.com/sgtwilko/INA3221 gitBranch=FixOverflow https://github.com/sgtwilko/INA3221/archive/bb03d7e9bfcc74fc798838a54f4f99738f29fc6a.zip - # renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass - mprograms/QMC5883LCompass@1.2.3 - # renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU - dfrobot/DFRobot_RTU@1.0.6 + # renovate: datasource=github-tags depName=QMC5883L Compass packageName=mprograms/QMC5883LCompass + https://github.com/mprograms/QMC5883LCompass/archive/refs/tags/v1.2.3.zip + # renovate: datasource=github-tags depName=DFRobot_RTU packageName=dfrobot/DFRobot_RTU + https://github.com/DFRobot/DFRobot_RTU/archive/refs/tags/V1.0.6.zip # renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip - # renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226 - robtillaart/INA226@0.6.6 - # renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library - sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2 - # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library - sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2 - # renovate: datasource=custom.pio depName=Adafruit LTR390 Library packageName=adafruit/library/Adafruit LTR390 Library - adafruit/Adafruit LTR390 Library@1.1.2 - # renovate: datasource=custom.pio depName=Adafruit PCT2075 packageName=adafruit/library/Adafruit PCT2075 - adafruit/Adafruit PCT2075@1.0.6 - # renovate: datasource=custom.pio depName=DFRobot_BMM150 packageName=dfrobot/library/DFRobot_BMM150 - dfrobot/DFRobot_BMM150@1.0.0 - # renovate: datasource=custom.pio depName=Adafruit_TSL2561 packageName=adafruit/library/Adafruit TSL2561 - adafruit/Adafruit TSL2561@1.1.3 - # renovate: datasource=custom.pio depName=BH1750_WE packageName=wollewald/library/BH1750_WE - wollewald/BH1750_WE@1.1.10 + # renovate: datasource=github-tags depName=INA226 packageName=robtillaart/INA226 + https://github.com/RobTillaart/INA226/archive/refs/tags/0.6.6.zip + # renovate: datasource=github-tags depName=SparkFun MAX3010x packageName=sparkfun/SparkFun_MAX3010x_Sensor_Library + https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/archive/refs/tags/v1.1.2.zip + # renovate: datasource=github-tags depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/SparkFun_ICM-20948_ArduinoLibrary + https://github.com/sparkfun/SparkFun_ICM-20948_ArduinoLibrary/archive/refs/tags/v1.3.2.zip + # renovate: datasource=github-tags depName=Adafruit LTR390 Library packageName=adafruit/Adafruit_LTR390 + https://github.com/adafruit/Adafruit_LTR390/archive/refs/tags/1.1.2.zip + # renovate: datasource=github-tags depName=Adafruit PCT2075 packageName=adafruit/Adafruit_PCT2075 + https://github.com/adafruit/Adafruit_PCT2075/archive/refs/tags/1.0.6.zip + # renovate: datasource=github-tags depName=DFRobot_BMM150 packageName=dfrobot/DFRobot_BMM150 + https://github.com/DFRobot/DFRobot_BMM150/archive/refs/tags/V1.0.0.zip + # renovate: datasource=github-tags depName=Adafruit_TSL2561 packageName=adafruit/Adafruit_TSL2561 + https://github.com/adafruit/Adafruit_TSL2561/archive/refs/tags/1.1.3.zip + # renovate: datasource=github-tags depName=BH1750_WE packageName=wollewald/BH1750_WE + https://github.com/wollewald/BH1750_WE/archive/refs/tags/1.1.10.zip ; Common environmental sensor libraries (not included in native / portduino) [environmental_extra_common] lib_deps = - # renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library - adafruit/Adafruit BMP3XX Library@2.1.6 - # renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X - adafruit/Adafruit MAX1704X@1.0.3 - # renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X - adafruit/Adafruit LPS2X@2.0.6 - # renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library - adafruit/Adafruit VEML7700 Library@2.1.6 - # renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library - sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6 + # renovate: datasource=github-tags depName=Adafruit BMP3XX packageName=adafruit/Adafruit_BMP3XX + https://github.com/adafruit/Adafruit_BMP3XX/archive/refs/tags/2.1.6.zip + # renovate: datasource=github-tags depName=Adafruit MAX1704X packageName=adafruit/Adafruit_MAX1704X + https://github.com/adafruit/Adafruit_MAX1704X/archive/refs/tags/1.0.3.zip + # renovate: datasource=github-tags depName=Adafruit SHTC3 packageName=adafruit/Adafruit_SHTC3 + https://github.com/adafruit/Adafruit_SHTC3/archive/refs/tags/1.0.2.zip + # renovate: datasource=github-tags depName=Adafruit LPS2X packageName=adafruit/Adafruit_LPS2X + https://github.com/adafruit/Adafruit_LPS2X/archive/refs/tags/2.0.6.zip + # renovate: datasource=github-tags depName=Adafruit SHT31 packageName=adafruit/Adafruit_SHT31 + https://github.com/adafruit/Adafruit_SHT31/archive/refs/tags/2.2.2.zip + # renovate: datasource=github-tags depName=Adafruit VEML7700 packageName=adafruit/Adafruit_VEML7700 + https://github.com/adafruit/Adafruit_VEML7700/archive/refs/tags/2.1.6.zip + # renovate: datasource=github-tags depName=Adafruit SHT4x packageName=adafruit/Adafruit_SHT4X + https://github.com/adafruit/Adafruit_SHT4X/archive/refs/tags/1.0.5.zip + # renovate: datasource=github-tags depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/SparkFun_Qwiic_Scale_NAU7802_Arduino_Library + https://github.com/sparkfun/SparkFun_Qwiic_Scale_NAU7802_Arduino_Library/archive/refs/tags/v1.0.6.zip # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 closedcube/ClosedCube OPT3001@1.1.2 # renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip - # renovate: datasource=custom.pio depName=Sensirion Core packageName=sensirion/library/Sensirion Core - sensirion/Sensirion Core@0.7.3 - # renovate: datasource=custom.pio depName=Sensirion I2C SCD4x packageName=sensirion/library/Sensirion I2C SCD4x - sensirion/Sensirion I2C SCD4x@1.1.0 - # renovate: datasource=custom.pio depName=Sensirion I2C SFA3x packageName=sensirion/library/Sensirion I2C SFA3x - sensirion/Sensirion I2C SFA3x@1.0.0 - # renovate: datasource=custom.pio depName=Sensirion I2C SCD30 packageName=sensirion/library/Sensirion I2C SCD30 - sensirion/Sensirion I2C SCD30@1.0.0 - # renovate: datasource=custom.pio depName=arduino-sht packageName=sensirion/library/arduino-sht - sensirion/arduino-sht@1.2.6 + # renovate: datasource=github-tags depName=Sensirion Core packageName=sensirion/arduino-core + https://github.com/Sensirion/arduino-core/archive/refs/tags/0.7.3.zip + # renovate: datasource=github-tags depName=Sensirion I2C SCD4x packageName=sensirion/arduino-i2c-scd4x + https://github.com/Sensirion/arduino-i2c-scd4x/archive/refs/tags/1.1.0.zip + # renovate: datasource=github-tags depName=Sensirion I2C SFA3x packageName=sensirion/arduino-i2c-sfa3x + https://github.com/Sensirion/arduino-i2c-sfa3x/archive/refs/tags/1.0.0.zip + # renovate: datasource=github-tags depName=Sensirion I2C SCD30 packageName=sensirion/arduino-i2c-scd30 + https://github.com/Sensirion/arduino-i2c-scd30/archive/refs/tags/1.0.0.zip + # renovate: datasource=github-tags depName=arduino-sht packageName=sensirion/arduino-sht + https://github.com/Sensirion/arduino-sht/archive/refs/tags/v1.2.6.zip ; Environmental sensors with BSEC2 (Bosch proprietary IAQ) [environmental_extra] lib_deps = ${environmental_extra_common.lib_deps} - # renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2 - boschsensortec/bsec2@1.10.2610 - # renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library - boschsensortec/BME68x Sensor Library@1.3.40408 + # renovate: datasource=github-tags depName=Bosch BSEC2 packageName=boschsensortec/Bosch-BSEC2-Library + https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/refs/tags/1.10.2610.zip + # renovate: datasource=github-tags depName=Bosch BME68x packageName=boschsensortec/Bosch-BME68x-Library + https://github.com/boschsensortec/Bosch-BME68x-Library/archive/refs/tags/v1.3.40408.zip ; Environmental sensors without BSEC (saves ~3.5KB DRAM for original ESP32 targets) [environmental_extra_no_bsec] lib_deps = ${environmental_extra_common.lib_deps} - # renovate: datasource=custom.pio depName=Adafruit_BME680 packageName=adafruit/library/Adafruit BME680 Library - adafruit/Adafruit BME680 Library@2.0.6 + # renovate: datasource=github-tags depName=Adafruit_BME680 packageName=adafruit/Adafruit_BME680 + https://github.com/adafruit/Adafruit_BME680/archive/refs/tags/2.0.6.zip diff --git a/protobufs b/protobufs index e30092e61..940ac382a 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit e30092e6168b13341c2b7ec4be19c789ad5cd77f +Subproject commit 940ac382a7d143040da5a880237f84c48ee31f2b diff --git a/src/MessageStore.h b/src/MessageStore.h index 6203d8ed0..77271f1c9 100644 --- a/src/MessageStore.h +++ b/src/MessageStore.h @@ -21,8 +21,15 @@ // How many messages are stored (RAM + flash). // Define -DMESSAGE_HISTORY_LIMIT=N in build_flags to control memory usage. #ifndef MESSAGE_HISTORY_LIMIT +#if defined(ARCH_ESP32) && \ + !(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2)) +// Baseline ESP32 (non-PSRAM variants) has limited heap; reduce message history on resource-constrained builds. +// Override with -DMESSAGE_HISTORY_LIMIT=N if needed. +#define MESSAGE_HISTORY_LIMIT 10 +#else #define MESSAGE_HISTORY_LIMIT 20 #endif +#endif // Internal alias used everywhere in code – do NOT redefine elsewhere. #define MAX_MESSAGES_SAVED MESSAGE_HISTORY_LIMIT diff --git a/src/Power.cpp b/src/Power.cpp index d82c870ed..26b961525 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -40,6 +40,22 @@ #include "concurrency/LockGuard.h" #endif +#if defined(ARCH_STM32WL) && defined(BATTERY_PIN) +#include "stm32yyxx_ll_adc.h" + +/* Analog read resolution */ +#if defined(LL_ADC_RESOLUTION_12B) +#define LL_ADC_RESOLUTION LL_ADC_RESOLUTION_12B +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#elif defined(LL_ADC_DS_DATA_WIDTH_12_BIT) +#define LL_ADC_RESOLUTION LL_ADC_DS_DATA_WIDTH_12_BIT +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#else +#error "ADC resolution could not be defined!" +#endif +#define ADC_RANGE (1 << BATTERY_SENSE_RESOLUTION_BITS) +#endif + #if defined(DEBUG_HEAP_MQTT) && !MESHTASTIC_EXCLUDE_MQTT #include "mqtt/MQTT.h" #include "target_specific.h" @@ -328,11 +344,17 @@ class AnalogBatteryLevel : public HasBatteryLevel float scaled = 0; battery_adcEnable(); -#ifdef ARCH_ESP32 // ADC block for espressif platforms +#ifdef ARCH_STM32WL + // STM32 ADC with VREFINT runtime calibration + Vref = __LL_ADC_CALC_VREFANALOG_VOLTAGE(analogRead(AVREF), LL_ADC_RESOLUTION); + raw = analogRead(BATTERY_PIN); + scaled = __LL_ADC_CALC_DATA_TO_VOLTAGE(Vref, raw, LL_ADC_RESOLUTION); + scaled *= operativeAdcMultiplier; +#elif defined(ARCH_ESP32) // ADC block for espressif platforms raw = espAdcRead(); scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs); scaled *= operativeAdcMultiplier; -#else // block for all other platforms +#else // block for all other platforms #ifdef ARCH_NRF52 concurrency::LockGuard saadcGuard(concurrency::nrf52SaadcLock); #endif @@ -530,6 +552,11 @@ class AnalogBatteryLevel : public HasBatteryLevel bool initial_read_done = false; float last_read_value = (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS); uint32_t last_read_time_ms = 0; +#ifdef ARCH_STM32WL + // 3300mV placeholder for STM32 errata where VREFINT factory calibration may be missing + // (e.g. STM32U0, see DS14756 Rev 3 §2.4.1 "VREFINT offset") + uint32_t Vref = 3300; +#endif #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) @@ -639,7 +666,9 @@ bool Power::analogInit() #define BATTERY_SENSE_RESOLUTION_BITS 10 #endif -#ifdef ARCH_ESP32 // ESP32 needs special analog stuff +#ifdef ARCH_STM32WL + analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS); +#elif defined(ARCH_ESP32) // ESP32 needs special analog stuff #ifndef ADC_WIDTH // max resolution by default static const adc_bits_width_t width = ADC_WIDTH_BIT_12; @@ -649,7 +678,7 @@ bool Power::analogInit() #ifndef BAT_MEASURE_ADC_UNIT // ADC1 adc1_config_width(width); adc1_config_channel_atten(adc_channel, atten); -#else // ADC2 +#else // ADC2 adc2_config_channel_atten(adc_channel, atten); #ifndef CONFIG_IDF_TARGET_ESP32S3 // ADC2 wifi bug workaround @@ -679,7 +708,7 @@ bool Power::analogInit() // NRF52 ADC init moved to powerHAL_init in nrf52 platform -#ifndef ARCH_ESP32 +#if !defined(ARCH_ESP32) && !defined(ARCH_STM32WL) analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS); #endif diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index e24aa3c57..2a3f08cbc 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -30,6 +30,9 @@ SerialConsole *console; void consoleInit() { + if (console) { + return; + } auto sc = new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread #if defined(SERIAL_HAS_ON_RECEIVE) diff --git a/src/concurrency/BinarySemaphorePosix.cpp b/src/concurrency/BinarySemaphorePosix.cpp index dc49a489b..4bc60c31f 100644 --- a/src/concurrency/BinarySemaphorePosix.cpp +++ b/src/concurrency/BinarySemaphorePosix.cpp @@ -1,10 +1,85 @@ #include "concurrency/BinarySemaphorePosix.h" #include "configuration.h" +#include +#include + #ifndef HAS_FREE_RTOS namespace concurrency { +#ifdef ARCH_PORTDUINO + +BinarySemaphorePosix::BinarySemaphorePosix() +{ + if (pthread_mutex_init(&mutex, NULL) != 0) { + throw std::runtime_error("pthread_mutex_init failed"); + } + if (pthread_cond_init(&cond, NULL) != 0) { + pthread_mutex_destroy(&mutex); + throw std::runtime_error("pthread_cond_init failed"); + } + signaled = false; +} + +BinarySemaphorePosix::~BinarySemaphorePosix() +{ + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&mutex); +} + +/** + * Returns false if we timed out + */ +bool BinarySemaphorePosix::take(uint32_t msec) +{ + pthread_mutex_lock(&mutex); + + if (!signaled) { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + + ts.tv_sec += msec / 1000; + ts.tv_nsec += (msec % 1000) * 1000000L; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_sec += 1; + ts.tv_nsec -= 1000000000L; + } + + while (!signaled) { + int rc = pthread_cond_timedwait(&cond, &mutex, &ts); + if (rc == ETIMEDOUT) + break; + if (rc != 0) { + // Some other error occurred + pthread_mutex_unlock(&mutex); + throw std::runtime_error("pthread_cond_timedwait failed: " + std::to_string(rc)); + } + } + } + + bool wasSignaled = signaled; + signaled = false; // consume the signal (binary semaphore) + + pthread_mutex_unlock(&mutex); + return wasSignaled; +} + +void BinarySemaphorePosix::give() +{ + pthread_mutex_lock(&mutex); + signaled = true; + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); +} + +IRAM_ATTR void BinarySemaphorePosix::giveFromISR(BaseType_t *pxHigherPriorityTaskWoken) +{ + give(); + if (pxHigherPriorityTaskWoken) + *pxHigherPriorityTaskWoken = true; +} +#else BinarySemaphorePosix::BinarySemaphorePosix() {} @@ -22,7 +97,8 @@ bool BinarySemaphorePosix::take(uint32_t msec) void BinarySemaphorePosix::give() {} IRAM_ATTR void BinarySemaphorePosix::giveFromISR(BaseType_t *pxHigherPriorityTaskWoken) {} +#endif } // namespace concurrency -#endif \ No newline at end of file +#endif diff --git a/src/concurrency/BinarySemaphorePosix.h b/src/concurrency/BinarySemaphorePosix.h index 475b29874..80edb567b 100644 --- a/src/concurrency/BinarySemaphorePosix.h +++ b/src/concurrency/BinarySemaphorePosix.h @@ -2,6 +2,10 @@ #include "../freertosinc.h" +#ifdef ARCH_PORTDUINO +#include +#endif + namespace concurrency { @@ -9,7 +13,12 @@ namespace concurrency class BinarySemaphorePosix { - // SemaphoreHandle_t semaphore; + +#ifdef ARCH_PORTDUINO + pthread_mutex_t mutex; + pthread_cond_t cond; + bool signaled; +#endif public: BinarySemaphorePosix(); @@ -27,4 +36,4 @@ class BinarySemaphorePosix #endif -} // namespace concurrency \ No newline at end of file +} // namespace concurrency diff --git a/src/graphics/EInkParallelDisplay.cpp b/src/graphics/EInkParallelDisplay.cpp index b870e111b..293f57e81 100644 --- a/src/graphics/EInkParallelDisplay.cpp +++ b/src/graphics/EInkParallelDisplay.cpp @@ -202,7 +202,7 @@ void EInkParallelDisplay::display(void) // Get pointers to internal buffers uint8_t *cur = epaper->currentBuffer(); - uint8_t *prev = epaper->previousBuffer(); // may be NULL on first init + const uint8_t *prev = epaper->previousBuffer(); // may be NULL on first init // Track changed row range while converting int newTop = h; // min changed row (initialized to out-of-range) diff --git a/src/graphics/draw/MessageRenderer.cpp b/src/graphics/draw/MessageRenderer.cpp index 501a7ae2c..2fd9bf541 100644 --- a/src/graphics/draw/MessageRenderer.cpp +++ b/src/graphics/draw/MessageRenderer.cpp @@ -422,6 +422,17 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 std::vector isMine; // track alignment std::vector isHeader; // track header lines std::vector ackForLine; + // Hard limit on total cached lines to prevent unbounded growth from a single long message. + // Reserve to the actual cache cap up front, because a single message can expand to many more + // wrapped display lines than a small per-message estimate would predict. For a display + // rendering only ~5-30 lines at a time, caching more than this limit wastes heap. Stop + // appending once we reach MAX_CACHED_LINES to prevent a single message from blowing out the + // heap. + constexpr size_t MAX_CACHED_LINES = 100U; // ~5-6KB for std::string overhead on 32-bit (if each ~50-60 bytes avg) + allLines.reserve(MAX_CACHED_LINES); + isMine.reserve(MAX_CACHED_LINES); + isHeader.reserve(MAX_CACHED_LINES); + ackForLine.reserve(MAX_CACHED_LINES); for (auto it = filtered.rbegin(); it != filtered.rend(); ++it) { const auto &m = *it; @@ -565,16 +576,23 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 int wrapWidth = mine ? rightTextWidth : leftTextWidth; std::vector wrapped = generateLines(display, "", msgText, wrapWidth); + // Per-message wrap-line limit: even if wrapping produces many lines, cap them to prevent + // a single long message from consuming most or all of the cache. + constexpr size_t MAX_WRAPPED_LINES_PER_MSG = 20U; + size_t wrappedCount = 0; for (auto &ln : wrapped) { - allLines.push_back(ln); + if (allLines.size() >= MAX_CACHED_LINES || wrappedCount >= MAX_WRAPPED_LINES_PER_MSG) + break; // Cache limit or per-message limit reached; stop adding lines from this message + allLines.emplace_back(std::move(ln)); isMine.push_back(mine); isHeader.push_back(false); ackForLine.push_back(AckStatus::NONE); + ++wrappedCount; } } // Cache lines and heights - cachedLines = allLines; + cachedLines.swap(allLines); cachedHeights = calculateLineHeights(cachedLines, emotes, isHeader); std::vector blocks = buildMessageBlocks(isHeader, isMine); diff --git a/src/input/CardputerKeyboard.cpp b/src/input/CardputerKeyboard.cpp index ec1ed383a..1bd695461 100644 --- a/src/input/CardputerKeyboard.cpp +++ b/src/input/CardputerKeyboard.cpp @@ -121,7 +121,6 @@ void CardputerKeyboard::pressed(uint8_t key) modifierFlag = 0; } - uint8_t next_key = 0; int row = (key - 1) / 10; int col = (key - 1) % 10; diff --git a/src/mesh/CryptoEngine.cpp b/src/mesh/CryptoEngine.cpp index 4a613b644..daa7a3a75 100644 --- a/src/mesh/CryptoEngine.cpp +++ b/src/mesh/CryptoEngine.cpp @@ -4,6 +4,7 @@ #include #if !(MESHTASTIC_EXCLUDE_PKI) +#include "HardwareRNG.h" #include "NodeDB.h" #include "aes-ccm.h" #include "meshUtils.h" @@ -26,6 +27,15 @@ void CryptoEngine::generateKeyPair(uint8_t *pubKey, uint8_t *privKey) { // Mix in any randomness we can, to make key generation stronger. CryptRNG.begin(optstr(APP_VERSION)); + + uint8_t hardwareEntropy[64] = {0}; + if (HardwareRNG::fill(hardwareEntropy, sizeof(hardwareEntropy), true)) { + CryptRNG.stir(hardwareEntropy, sizeof(hardwareEntropy)); + } else { + LOG_WARN("Hardware entropy unavailable, falling back to software RNG"); + } + memset(hardwareEntropy, 0, sizeof(hardwareEntropy)); + if (myNodeInfo.device_id.size == 16) { CryptRNG.stir(myNodeInfo.device_id.bytes, myNodeInfo.device_id.size); } diff --git a/src/mesh/HardwareRNG.cpp b/src/mesh/HardwareRNG.cpp new file mode 100644 index 000000000..f5a805487 --- /dev/null +++ b/src/mesh/HardwareRNG.cpp @@ -0,0 +1,160 @@ +#include "HardwareRNG.h" + +#include +#include +#include + +#include "configuration.h" + +#if HAS_RADIO +#include "RadioLibInterface.h" +#endif + +#if defined(ARCH_NRF52) +#include +extern Adafruit_nRFCrypto nRFCrypto; +#elif defined(ARCH_ESP32) +#include +#elif defined(ARCH_RP2040) +#include +#elif defined(ARCH_PORTDUINO) +#include +#include +#include +#endif + +namespace HardwareRNG +{ + +namespace +{ +void fillWithRandomDevice(uint8_t *buffer, size_t length) +{ + std::random_device rd; + size_t offset = 0; + while (offset < length) { + uint32_t value = rd(); + size_t toCopy = std::min(length - offset, sizeof(value)); + memcpy(buffer + offset, &value, toCopy); + offset += toCopy; + } +} + +#if HAS_RADIO +bool mixWithLoRaEntropy(uint8_t *buffer, size_t length) +{ + // Only attempt to pull entropy from the modem if it is initialized and exposes the helper. + // When the radio stack is disabled or has not yet been configured, we simply skip this step + // and return false so callers know no extra mixing occurred. + RadioLibInterface *radio = RadioLibInterface::instance; + if (!radio) { + // Intentionally silent: this path runs during portduinoSetup() before the + // console/SerialConsole is initialized, so LOG_* here would dereference a null pointer. + return false; + } + + constexpr size_t chunkSize = 16; + uint8_t scratch[chunkSize]; + size_t offset = 0; + bool mixed = false; + + while (offset < length) { + size_t toCopy = std::min(length - offset, chunkSize); + + // randomBytes() returns false if the modem does not support it or is not ready + // (for instance, when the radio is powered down). We break immediately to avoid + // blocking or returning partially-filled entropy and simply report failure. + if (!radio->randomBytes(scratch, toCopy)) { + break; + } + + for (size_t i = 0; i < toCopy; ++i) { + buffer[offset + i] ^= scratch[i]; + } + + mixed = true; + offset += toCopy; + } + + // Avoid leaving the modem-sourced bytes sitting on the stack longer than needed. + if (mixed) { + memset(scratch, 0, sizeof(scratch)); + } + + return mixed; +} +#endif +} // namespace + +bool fill(uint8_t *buffer, size_t length, bool useRadioEntropy) +{ + if (!buffer || length == 0) { + return false; + } + + bool filled = false; + +#if defined(ARCH_NRF52) + // The Nordic SDK RNG provides cryptographic-quality randomness backed by hardware. + nRFCrypto.begin(); + auto result = nRFCrypto.Random.generate(buffer, length); + nRFCrypto.end(); + filled = result; +#elif defined(ARCH_ESP32) + // ESP32 exposes a true RNG via esp_fill_random(). + esp_fill_random(buffer, length); + filled = true; +#elif defined(ARCH_RP2040) + // RP2040 has a hardware random number generator accessible through the Arduino core. + size_t offset = 0; + while (offset < length) { + uint32_t value = rp2040.hwrand32(); + size_t toCopy = std::min(length - offset, sizeof(value)); + memcpy(buffer + offset, &value, toCopy); + offset += toCopy; + } + filled = true; +#elif defined(ARCH_PORTDUINO) + // Prefer the host OS RNG first when running under Portduino. + ssize_t generated = ::getrandom(buffer, length, 0); + if (generated == static_cast(length)) { + filled = true; + } + + if (!filled) { + fillWithRandomDevice(buffer, length); + filled = true; + } +#endif + + if (!filled) { + // As a last resort, fall back to std::random_device. This should only be reached + // if a platform-specific source was unavailable. + fillWithRandomDevice(buffer, length); + filled = true; + } + +#if HAS_RADIO + if (useRadioEntropy) { + // Best-effort: if the radio is active and can provide modem entropy, XOR it over the + // buffer to improve overall quality. We consider the filling a success if either a + // good platform RNG or the modem RNG provided data, so we return true as long as at + // least one of those steps succeeded. + filled = mixWithLoRaEntropy(buffer, length) || filled; + } +#endif + + return filled; +} + +bool seed(uint32_t &seedOut) +{ + uint32_t candidate = 0; + if (!fill(reinterpret_cast(&candidate), sizeof(candidate), true)) { + return false; + } + seedOut = candidate; + return true; +} + +} // namespace HardwareRNG diff --git a/src/mesh/HardwareRNG.h b/src/mesh/HardwareRNG.h new file mode 100644 index 000000000..2dacb6c23 --- /dev/null +++ b/src/mesh/HardwareRNG.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +namespace HardwareRNG +{ + +/** + * Fill the provided buffer with random bytes sourced from the most + * appropriate hardware-backed RNG available on the current platform. + * + * @param buffer Destination buffer for random bytes + * @param length Number of bytes to write + * @param useRadioEntropy If true, attempt to mix radio entropy into the output as well. + * @return true if the buffer was fully populated with entropy, false on failure + */ +bool fill(uint8_t *buffer, size_t length, bool useRadioEntropy = false); + +/** + * Populate a 32-bit seed value with hardware-backed randomness where possible. + * + * @param seedOut Destination for the generated seed value + * @return true if a seed was produced from a reliable entropy source + */ +bool seed(uint32_t &seedOut); + +} // namespace HardwareRNG diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 3c3a4cf65..089b4b189 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -4,6 +4,7 @@ #include "MeshTypes.h" #include "PointerQueue.h" #include "configuration.h" +#include "detect/LoRaRadioType.h" // Sentinel marking the end of a modem preset array static constexpr meshtastic_Config_LoRaConfig_ModemPreset MODEM_PRESET_END = @@ -59,7 +60,7 @@ extern const RegionInfo *myRegion; extern void initRegion(); // Valid LoRa spread factor range and defaults -constexpr uint8_t LORA_SF_MIN = 7; +constexpr uint8_t LORA_SF_MIN = 5; constexpr uint8_t LORA_SF_MAX = 12; constexpr uint8_t LORA_SF_DEFAULT = 11; // LONG_FAST default @@ -71,10 +72,14 @@ constexpr uint8_t LORA_CR_DEFAULT = 5; // LONG_FAST default // Default bandwidth in kHz (LONG_FAST) constexpr float LORA_BW_DEFAULT_KHZ = 250.0f; -/// Clamp spread factor to the valid LoRa range [7, 12]. +/// Clamp spread factor to the valid LoRa range [5, 12]. /// Out-of-range values (including 0 from unset preset mode) return LORA_SF_DEFAULT. static inline uint8_t clampSpreadFactor(uint8_t sf) { + // We check for RF95 radios that are incompatible with Spreading Factors 5 and 6. + if (radioType == RF95_RADIO && (sf == 5 || sf == 6)) + return LORA_SF_DEFAULT; + if (sf < LORA_SF_MIN || sf > LORA_SF_MAX) return LORA_SF_DEFAULT; return sf; diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 30cd587da..7ef707e0d 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -246,6 +246,24 @@ bool RadioLibInterface::findInTxQueue(NodeNum from, PacketId id) return txQueue.find(from, id); } +bool RadioLibInterface::randomBytes(uint8_t *buffer, size_t length) +{ + if (!buffer || length == 0 || !iface) { + return false; + } + + // Older RadioLib versions only expose random(min, max), so fill the buffer byte-by-byte. + for (size_t i = 0; i < length; ++i) { + int32_t value = iface->random(0, 255); + if (value < 0) { + return false; + } + buffer[i] = static_cast(value & 0xFF); + } + + return true; +} + /** radio helper thread callback. We never immediately transmit after any operation (either Rx or Tx). Instead we should wait a random multiple of 'slotTimes' (see definition in RadioInterface.h) taken from a contention window (CW) to lower the chance of collision. @@ -587,4 +605,4 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp) return res == RADIOLIB_ERR_NONE; } -} \ No newline at end of file +} diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index ca3d78503..310ca76bb 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -172,6 +172,12 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified /** Attempt to find a packet in the TxQueue. Returns true if the packet was found. */ virtual bool findInTxQueue(NodeNum from, PacketId id) override; + /** + * Request randomness sourced from the LoRa modem, if supported by the active RadioLib interface. + * @return true if len bytes were produced, false otherwise. + */ + bool randomBytes(uint8_t *buffer, size_t length); + private: /** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually * doing the transmit */ diff --git a/src/mesh/generated/meshtastic/atak.pb.cpp b/src/mesh/generated/meshtastic/atak.pb.cpp index bbafa33e2..3f1adea53 100644 --- a/src/mesh/generated/meshtastic/atak.pb.cpp +++ b/src/mesh/generated/meshtastic/atak.pb.cpp @@ -27,6 +27,33 @@ PB_BIND(meshtastic_PLI, meshtastic_PLI, AUTO) PB_BIND(meshtastic_AircraftTrack, meshtastic_AircraftTrack, AUTO) +PB_BIND(meshtastic_CotGeoPoint, meshtastic_CotGeoPoint, AUTO) + + +PB_BIND(meshtastic_DrawnShape, meshtastic_DrawnShape, 2) + + +PB_BIND(meshtastic_Marker, meshtastic_Marker, AUTO) + + +PB_BIND(meshtastic_RangeAndBearing, meshtastic_RangeAndBearing, AUTO) + + +PB_BIND(meshtastic_Route, meshtastic_Route, 2) + + +PB_BIND(meshtastic_Route_Link, meshtastic_Route_Link, AUTO) + + +PB_BIND(meshtastic_CasevacReport, meshtastic_CasevacReport, AUTO) + + +PB_BIND(meshtastic_EmergencyAlert, meshtastic_EmergencyAlert, AUTO) + + +PB_BIND(meshtastic_TaskRequest, meshtastic_TaskRequest, AUTO) + + PB_BIND(meshtastic_TAKPacketV2, meshtastic_TAKPacketV2, 2) @@ -41,3 +68,27 @@ PB_BIND(meshtastic_TAKPacketV2, meshtastic_TAKPacketV2, 2) + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mesh/generated/meshtastic/atak.pb.h b/src/mesh/generated/meshtastic/atak.pb.h index c12b042f4..d25fa6543 100644 --- a/src/mesh/generated/meshtastic/atak.pb.h +++ b/src/mesh/generated/meshtastic/atak.pb.h @@ -241,7 +241,91 @@ typedef enum _meshtastic_CotType { /* b-f-t-r: File transfer request */ meshtastic_CotType_CotType_b_f_t_r = 74, /* b-f-t-a: File transfer acknowledgment */ - meshtastic_CotType_CotType_b_f_t_a = 75 + meshtastic_CotType_CotType_b_f_t_a = 75, + /* 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. */ + meshtastic_CotType_CotType_u_d_f_m = 76, + /* u-d-p: Closed polygon. Geometry carried via DrawnShape.vertices, + implicitly closed (receiver duplicates first vertex as needed). */ + meshtastic_CotType_CotType_u_d_p = 77, + /* b-m-p-s-m: Spot map marker (colored dot at a point of interest). */ + meshtastic_CotType_CotType_b_m_p_s_m = 78, + /* b-m-p-c: Checkpoint (intermediate route control point). */ + meshtastic_CotType_CotType_b_m_p_c = 79, + /* u-r-b-c-c: Ranging circle (range rings centered on the event point). */ + meshtastic_CotType_CotType_u_r_b_c_c = 80, + /* u-r-b-bullseye: Bullseye with configurable range rings and bearing + reference (magnetic / true / grid). */ + meshtastic_CotType_CotType_u_r_b_bullseye = 81, + /* a-f-G-E-V-A: Friendly armored vehicle, user-selectable self PLI. */ + meshtastic_CotType_CotType_a_f_G_E_V_A = 82, + /* a-n-A: Neutral aircraft (friendly/hostile/unknown already present). */ + meshtastic_CotType_CotType_a_n_A = 83, + /* --- 2525 quick-drop: artillery (4) ---------------------------------- */ + meshtastic_CotType_CotType_a_u_G_U_C_F = 84, + meshtastic_CotType_CotType_a_n_G_U_C_F = 85, + meshtastic_CotType_CotType_a_h_G_U_C_F = 86, + meshtastic_CotType_CotType_a_f_G_U_C_F = 87, + /* --- 2525 quick-drop: building (4) ----------------------------------- */ + meshtastic_CotType_CotType_a_u_G_I = 88, + meshtastic_CotType_CotType_a_n_G_I = 89, + meshtastic_CotType_CotType_a_h_G_I = 90, + meshtastic_CotType_CotType_a_f_G_I = 91, + /* --- 2525 quick-drop: mine (4) --------------------------------------- */ + meshtastic_CotType_CotType_a_u_G_E_X_M = 92, + meshtastic_CotType_CotType_a_n_G_E_X_M = 93, + meshtastic_CotType_CotType_a_h_G_E_X_M = 94, + meshtastic_CotType_CotType_a_f_G_E_X_M = 95, + /* --- 2525 quick-drop: ship (3; a-f-S already at 17) ------------------ */ + meshtastic_CotType_CotType_a_u_S = 96, + meshtastic_CotType_CotType_a_n_S = 97, + meshtastic_CotType_CotType_a_h_S = 98, + /* --- 2525 quick-drop: sniper (4) ------------------------------------- */ + meshtastic_CotType_CotType_a_u_G_U_C_I_d = 99, + meshtastic_CotType_CotType_a_n_G_U_C_I_d = 100, + meshtastic_CotType_CotType_a_h_G_U_C_I_d = 101, + meshtastic_CotType_CotType_a_f_G_U_C_I_d = 102, + /* --- 2525 quick-drop: tank (4) --------------------------------------- */ + meshtastic_CotType_CotType_a_u_G_E_V_A_T = 103, + meshtastic_CotType_CotType_a_n_G_E_V_A_T = 104, + meshtastic_CotType_CotType_a_h_G_E_V_A_T = 105, + meshtastic_CotType_CotType_a_f_G_E_V_A_T = 106, + /* --- 2525 quick-drop: troops (3; a-f-G-U-C-I already at 2) ----------- */ + meshtastic_CotType_CotType_a_u_G_U_C_I = 107, + meshtastic_CotType_CotType_a_n_G_U_C_I = 108, + meshtastic_CotType_CotType_a_h_G_U_C_I = 109, + /* --- 2525 quick-drop: generic vehicle (3; a-u-G-E-V already at 69) --- */ + meshtastic_CotType_CotType_a_n_G_E_V = 110, + meshtastic_CotType_CotType_a_h_G_E_V = 111, + meshtastic_CotType_CotType_a_f_G_E_V = 112, + /* b-m-p-w-GOTO: Go To / bloodhound navigation target. */ + meshtastic_CotType_CotType_b_m_p_w_GOTO = 113, + /* b-m-p-c-ip: Initial point (mission planning). */ + meshtastic_CotType_CotType_b_m_p_c_ip = 114, + /* b-m-p-c-cp: Contact point (mission planning). */ + meshtastic_CotType_CotType_b_m_p_c_cp = 115, + /* b-m-p-s-p-op: Observation post. */ + meshtastic_CotType_CotType_b_m_p_s_p_op = 116, + /* u-d-v: 2D vehicle outline drawn on the map. */ + meshtastic_CotType_CotType_u_d_v = 117, + /* u-d-v-m: 3D vehicle model reference. */ + meshtastic_CotType_CotType_u_d_v_m = 118, + /* u-d-c-e: Non-circular ellipse (circle with distinct major/minor axes). */ + meshtastic_CotType_CotType_u_d_c_e = 119, + /* 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. */ + meshtastic_CotType_CotType_b_i_x_i = 120, + /* b-t-f-d: GeoChat delivered receipt. Carried on the existing `chat` + payload_variant via GeoChat.receipt_for_uid + receipt_type. */ + meshtastic_CotType_CotType_b_t_f_d = 121, + /* b-t-f-r: GeoChat read receipt. Same wire slot as b-t-f-d. */ + meshtastic_CotType_CotType_b_t_f_r = 122, + /* b-a-o-c: Custom / generic emergency beacon. */ + meshtastic_CotType_CotType_b_a_o_c = 123, + /* t-s: Task / engage request. Structured payload carried via the new + TaskRequest typed variant. */ + meshtastic_CotType_CotType_t_s = 124 } meshtastic_CotType; /* Geopoint and altitude source */ @@ -256,10 +340,191 @@ typedef enum _meshtastic_GeoPointSource { meshtastic_GeoPointSource_GeoPointSource_NETWORK = 3 } meshtastic_GeoPointSource; +/* 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. */ +typedef enum _meshtastic_GeoChat_ReceiptType { + meshtastic_GeoChat_ReceiptType_ReceiptType_None = 0, /* normal chat message */ + meshtastic_GeoChat_ReceiptType_ReceiptType_Delivered = 1, /* b-t-f-d delivered receipt */ + meshtastic_GeoChat_ReceiptType_ReceiptType_Read = 2 /* b-t-f-r read receipt */ +} meshtastic_GeoChat_ReceiptType; + +/* Shape kind discriminator. Drives receiver rendering and also controls + which optional fields below are meaningful. */ +typedef enum _meshtastic_DrawnShape_Kind { + /* Unspecified (do not use on the wire) */ + meshtastic_DrawnShape_Kind_Kind_Unspecified = 0, + /* u-d-c-c: User-drawn circle (uses major/minor/angle, anchor = event point) */ + meshtastic_DrawnShape_Kind_Kind_Circle = 1, + /* u-d-r: User-drawn rectangle (uses vertices = 4 corners) */ + meshtastic_DrawnShape_Kind_Kind_Rectangle = 2, + /* u-d-f: User-drawn polyline (uses vertices, not closed) */ + meshtastic_DrawnShape_Kind_Kind_Freeform = 3, + /* u-d-f-m: Freehand telestration / annotation (uses vertices, may be truncated) */ + meshtastic_DrawnShape_Kind_Kind_Telestration = 4, + /* u-d-p: Closed polygon (uses vertices, implicitly closed) */ + meshtastic_DrawnShape_Kind_Kind_Polygon = 5, + /* u-r-b-c-c: Ranging circle (major/minor/angle, stroke + optional fill) */ + meshtastic_DrawnShape_Kind_Kind_RangingCircle = 6, + /* u-r-b-bullseye: Bullseye ring with range rings and bearing reference */ + meshtastic_DrawnShape_Kind_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). */ + meshtastic_DrawnShape_Kind_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. */ + meshtastic_DrawnShape_Kind_Kind_Vehicle2D = 9, + /* u-d-v-m: 3D vehicle model reference. Same vertex polygon as + Kind_Vehicle2D; receivers that support 3D rendering extrude it. */ + meshtastic_DrawnShape_Kind_Kind_Vehicle3D = 10 +} meshtastic_DrawnShape_Kind; + +/* 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. */ +typedef enum _meshtastic_DrawnShape_StyleMode { + /* Unspecified — receiver infers from which color fields are non-zero. */ + meshtastic_DrawnShape_StyleMode_StyleMode_Unspecified = 0, + /* Stroke only. No in the source XML. Used for polylines, + ranging lines, bullseye rings. */ + meshtastic_DrawnShape_StyleMode_StyleMode_StrokeOnly = 1, + /* Fill only. No in the source XML. Rare but valid in + ATAK (solid region with no outline). */ + meshtastic_DrawnShape_StyleMode_StyleMode_FillOnly = 2, + /* Both stroke and fill present. Closed shapes: circle, rectangle, + polygon, ranging circle. */ + meshtastic_DrawnShape_StyleMode_StyleMode_StrokeAndFill = 3 +} meshtastic_DrawnShape_StyleMode; + +/* 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). */ +typedef enum _meshtastic_Marker_Kind { + /* Unspecified — fall back to TAKPacketV2.cot_type_id */ + meshtastic_Marker_Kind_Kind_Unspecified = 0, + /* b-m-p-s-m: Spot map marker */ + meshtastic_Marker_Kind_Kind_Spot = 1, + /* b-m-p-w: Route waypoint */ + meshtastic_Marker_Kind_Kind_Waypoint = 2, + /* b-m-p-c: Checkpoint */ + meshtastic_Marker_Kind_Kind_Checkpoint = 3, + /* b-m-p-s-p-i / b-m-p-s-p-loc: Self-position marker */ + meshtastic_Marker_Kind_Kind_SelfPosition = 4, + /* 2525B/C military symbol (iconsetpath = COT_MAPPING_2525B/...) */ + meshtastic_Marker_Kind_Kind_Symbol2525 = 5, + /* COT_MAPPING_SPOTMAP icon (e.g. colored dot) */ + meshtastic_Marker_Kind_Kind_SpotMap = 6, + /* Custom icon set (UUID/GroupName/filename.png) */ + meshtastic_Marker_Kind_Kind_CustomIcon = 7, + /* b-m-p-w-GOTO: Go To / bloodhound navigation waypoint. */ + meshtastic_Marker_Kind_Kind_GoToPoint = 8, + /* b-m-p-c-ip: Initial point (mission planning control point). */ + meshtastic_Marker_Kind_Kind_InitialPoint = 9, + /* b-m-p-c-cp: Contact point (mission planning control point). */ + meshtastic_Marker_Kind_Kind_ContactPoint = 10, + /* b-m-p-s-p-op: Observation post. */ + meshtastic_Marker_Kind_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. */ + meshtastic_Marker_Kind_Kind_ImageMarker = 12 +} meshtastic_Marker_Kind; + +/* Travel method for the route. */ +typedef enum _meshtastic_Route_Method { + /* Unspecified / unknown */ + meshtastic_Route_Method_Method_Unspecified = 0, + /* Driving / vehicle */ + meshtastic_Route_Method_Method_Driving = 1, + /* Walking / foot */ + meshtastic_Route_Method_Method_Walking = 2, + /* Flying */ + meshtastic_Route_Method_Method_Flying = 3, + /* Swimming (individual) */ + meshtastic_Route_Method_Method_Swimming = 4, + /* Watercraft (boat) */ + meshtastic_Route_Method_Method_Watercraft = 5 +} meshtastic_Route_Method; + +/* Route direction (infil = ingress, exfil = egress). */ +typedef enum _meshtastic_Route_Direction { + /* Unspecified */ + meshtastic_Route_Direction_Direction_Unspecified = 0, + /* Infiltration (ingress) */ + meshtastic_Route_Direction_Direction_Infil = 1, + /* Exfiltration (egress) */ + meshtastic_Route_Direction_Direction_Exfil = 2 +} meshtastic_Route_Direction; + +/* Line 3: precedence / urgency. */ +typedef enum _meshtastic_CasevacReport_Precedence { + meshtastic_CasevacReport_Precedence_Precedence_Unspecified = 0, + meshtastic_CasevacReport_Precedence_Precedence_Urgent = 1, /* A - immediate, life-threatening */ + meshtastic_CasevacReport_Precedence_Precedence_UrgentSurgical = 2, /* B - needs surgery */ + meshtastic_CasevacReport_Precedence_Precedence_Priority = 3, /* C - within 4 hours */ + meshtastic_CasevacReport_Precedence_Precedence_Routine = 4, /* D - within 24 hours */ + meshtastic_CasevacReport_Precedence_Precedence_Convenience = 5 /* E - convenience */ +} meshtastic_CasevacReport_Precedence; + +/* Line 7: HLZ marking method. */ +typedef enum _meshtastic_CasevacReport_HlzMarking { + meshtastic_CasevacReport_HlzMarking_HlzMarking_Unspecified = 0, + meshtastic_CasevacReport_HlzMarking_HlzMarking_Panels = 1, + meshtastic_CasevacReport_HlzMarking_HlzMarking_PyroSignal = 2, + meshtastic_CasevacReport_HlzMarking_HlzMarking_Smoke = 3, + meshtastic_CasevacReport_HlzMarking_HlzMarking_None = 4, + meshtastic_CasevacReport_HlzMarking_HlzMarking_Other = 5 +} meshtastic_CasevacReport_HlzMarking; + +/* Line 6: security situation at the pickup zone. */ +typedef enum _meshtastic_CasevacReport_Security { + meshtastic_CasevacReport_Security_Security_Unspecified = 0, + meshtastic_CasevacReport_Security_Security_NoEnemy = 1, /* N - no enemy activity */ + meshtastic_CasevacReport_Security_Security_PossibleEnemy = 2, /* P - possible enemy */ + meshtastic_CasevacReport_Security_Security_EnemyInArea = 3, /* E - enemy, approach with caution */ + meshtastic_CasevacReport_Security_Security_EnemyInArmedContact = 4 /* X - armed escort required */ +} meshtastic_CasevacReport_Security; + +typedef enum _meshtastic_EmergencyAlert_Type { + meshtastic_EmergencyAlert_Type_Type_Unspecified = 0, + meshtastic_EmergencyAlert_Type_Type_Alert911 = 1, /* b-a-o-tbl */ + meshtastic_EmergencyAlert_Type_Type_RingTheBell = 2, /* b-a-o-pan */ + meshtastic_EmergencyAlert_Type_Type_InContact = 3, /* b-a-o-opn */ + meshtastic_EmergencyAlert_Type_Type_GeoFenceBreached = 4, /* b-a-g */ + meshtastic_EmergencyAlert_Type_Type_Custom = 5, /* b-a-o-c */ + meshtastic_EmergencyAlert_Type_Type_Cancel = 6 /* b-a-o-can */ +} meshtastic_EmergencyAlert_Type; + +typedef enum _meshtastic_TaskRequest_Priority { + meshtastic_TaskRequest_Priority_Priority_Unspecified = 0, + meshtastic_TaskRequest_Priority_Priority_Low = 1, + meshtastic_TaskRequest_Priority_Priority_Normal = 2, + meshtastic_TaskRequest_Priority_Priority_High = 3, + meshtastic_TaskRequest_Priority_Priority_Critical = 4 +} meshtastic_TaskRequest_Priority; + +typedef enum _meshtastic_TaskRequest_Status { + meshtastic_TaskRequest_Status_Status_Unspecified = 0, + meshtastic_TaskRequest_Status_Status_Pending = 1, /* assigned, not yet acknowledged */ + meshtastic_TaskRequest_Status_Status_Acknowledged = 2, /* assignee has seen it */ + meshtastic_TaskRequest_Status_Status_InProgress = 3, /* assignee is working it */ + meshtastic_TaskRequest_Status_Status_Completed = 4, /* task done */ + meshtastic_TaskRequest_Status_Status_Cancelled = 5 /* cancelled before completion */ +} meshtastic_TaskRequest_Status; + /* Struct definitions */ /* ATAK GeoChat message */ typedef struct _meshtastic_GeoChat { - /* The text message */ + /* The text message. Empty for receipts. */ char message[200]; /* Uid recipient of the message */ bool has_to; @@ -267,6 +532,14 @@ typedef struct _meshtastic_GeoChat { /* Callsign of the recipient for the message */ bool has_to_callsign; char to_callsign[120]; + /* 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. */ + char receipt_for_uid[48]; + /* Receipt kind discriminator. See ReceiptType doc. Default ReceiptType_None + means this is a regular chat message, not a receipt. */ + meshtastic_GeoChat_ReceiptType receipt_type; } meshtastic_GeoChat; /* ATAK Group @@ -360,6 +633,284 @@ typedef struct _meshtastic_AircraftTrack { char cot_host_id[64]; } meshtastic_AircraftTrack; +/* 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. */ +typedef struct _meshtastic_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. */ + int32_t lat_delta_i; + /* Longitude delta from TAKPacketV2.longitude_i, in 1e-7 degree units. */ + int32_t lon_delta_i; +} meshtastic_CotGeoPoint; + +/* 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. */ +typedef struct _meshtastic_DrawnShape { + /* Shape kind (circle, rectangle, freeform, etc.) */ + meshtastic_DrawnShape_Kind kind; + /* Explicit stroke/fill/both discriminator. See StyleMode doc. */ + meshtastic_DrawnShape_StyleMode style; + /* Ellipse major radius in centimeters. 0 for non-ellipse kinds. */ + uint32_t major_cm; + /* Ellipse minor radius in centimeters. 0 for non-ellipse kinds. */ + uint32_t minor_cm; + /* 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. */ + uint16_t angle_deg; + /* 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. */ + meshtastic_Team stroke_color; + /* 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. */ + uint32_t stroke_argb; + /* Stroke weight in tenths of a unit (e.g. 30 = 3.0). Typical ATAK + range 10..60. */ + uint16_t stroke_weight_x10; + /* Fill color as a named palette entry. See stroke_color docs. + Valid only when style is FillOnly or StrokeAndFill. */ + meshtastic_Team fill_color; + /* Fill color exact ARGB fallback. See stroke_argb docs. */ + uint32_t fill_argb; + /* Whether labels are rendered on this shape. */ + bool labels_on; + /* Vertex list for polyline/polygon/rectangle shapes. Capped at 32 by + the nanopb pool; senders MUST truncate longer inputs and set + `truncated = true`. */ + pb_size_t vertices_count; + meshtastic_CotGeoPoint vertices[32]; + /* True if the sender truncated `vertices` to fit the pool. */ + bool truncated; /* --- Bullseye-only fields. All ignored unless kind == Kind_Bullseye. --- */ + /* Bullseye distance in meters * 10 (e.g. 3285 = 328.5 m). 0 = unset. */ + uint32_t bullseye_distance_dm; + /* Bullseye bearing reference: 0 unset, 1 Magnetic, 2 True, 3 Grid. */ + uint8_t bullseye_bearing_ref; + /* Bullseye attribute bit flags: + bit 0: rangeRingVisible + bit 1: hasRangeRings + bit 2: edgeToCenter + bit 3: mils */ + uint8_t bullseye_flags; + /* Bullseye reference UID (anchor marker). Empty = anchor is self. */ + char bullseye_uid_ref[48]; +} meshtastic_DrawnShape; + +/* 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. */ +typedef struct _meshtastic_Marker { + /* Marker kind */ + meshtastic_Marker_Kind kind; + /* Marker color as a named palette entry. If Unspecifed_Color, the exact + ARGB is in color_argb. */ + meshtastic_Team color; + /* Marker color exact ARGB bit pattern. Always populated on the wire. */ + uint32_t color_argb; + /* Status readiness flag (ATAK ). */ + bool readiness; + /* Parent link UID (ATAK ). Empty = no parent. + For spot/waypoint markers this is typically the producing TAK user's UID. */ + char parent_uid[48]; + /* Parent CoT type (e.g. "a-f-G-U-C"). Usually the parent TAK user's type. */ + char parent_type[24]; + /* Parent callsign (e.g. "HOPE"). */ + char parent_callsign[24]; + /* 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. */ + char iconset[80]; +} meshtastic_Marker; + +/* 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. */ +typedef struct _meshtastic_RangeAndBearing { + /* Target/anchor endpoint (delta-encoded from TAKPacketV2.latitude_i/longitude_i). */ + bool has_anchor; + meshtastic_CotGeoPoint anchor; + /* Anchor UID (from ). Empty = free-standing. */ + char anchor_uid[48]; + /* Range in centimeters (value * 100). Range 0..4294 km. */ + uint32_t range_cm; + /* Bearing in degrees * 100 (0..36000). */ + uint16_t bearing_cdeg; + /* Stroke color as a Team palette entry. See DrawnShape.stroke_color doc. */ + meshtastic_Team stroke_color; + /* Stroke color exact ARGB fallback. */ + uint32_t stroke_argb; + /* Stroke weight * 10 (e.g. 30 = 3.0). */ + uint16_t stroke_weight_x10; +} meshtastic_RangeAndBearing; + +/* Route waypoint or control point. Each link corresponds to one ATAK + entry inside the b-m-r event. */ +typedef struct _meshtastic_Route_Link { + /* Waypoint position (delta-encoded from TAKPacketV2.latitude_i/longitude_i). */ + bool has_point; + meshtastic_CotGeoPoint point; + /* Optional UID (empty = receiver derives). */ + char uid[48]; + /* Optional display callsign (e.g. "CP1"). Empty for unnamed control points. */ + char callsign[16]; + /* Link role: 0 = waypoint (b-m-p-w), 1 = checkpoint (b-m-p-c). */ + uint8_t link_type; +} meshtastic_Route_Link; + +/* 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`. */ +typedef struct _meshtastic_Route { + /* Travel method */ + meshtastic_Route_Method method; + /* Direction (infil/exfil) */ + meshtastic_Route_Direction direction; + /* Waypoint name prefix (e.g. "CP"). */ + char prefix[8]; + /* Stroke weight * 10 (e.g. 30 = 3.0). 0 = default. */ + uint16_t stroke_weight_x10; + /* Ordered list of route control points. Capped at 16. */ + pb_size_t links_count; + meshtastic_Route_Link links[16]; + /* True if the sender truncated `links` to fit the pool. */ + bool truncated; +} meshtastic_Route; + +/* 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. */ +typedef struct _meshtastic_CasevacReport { + /* Line 3: precedence / urgency. */ + meshtastic_CasevacReport_Precedence precedence; + /* Line 4: special equipment required, as a bitfield. + bit 0: none + bit 1: hoist + bit 2: extraction equipment + bit 3: ventilator + bit 4: blood */ + uint8_t equipment_flags; + /* Line 5: number of litter (stretcher-bound) patients. */ + uint8_t litter_patients; + /* Line 5: number of ambulatory (walking-wounded) patients. */ + uint8_t ambulatory_patients; + /* Line 6: security situation at the PZ. */ + meshtastic_CasevacReport_Security security; + /* Line 7: HLZ marking method. */ + meshtastic_CasevacReport_HlzMarking hlz_marking; + /* Line 7 supplementary: short free-text describing the zone marker + (e.g. "Green smoke", "VS-17 panel west"). Capped tight in options. */ + char zone_marker[16]; + /* --- Line 8: patient nationality counts --- */ + uint8_t us_military; + uint8_t us_civilian; + uint8_t non_us_military; + uint8_t non_us_civilian; + uint8_t epw; /* enemy prisoner of war */ + uint8_t child; + /* 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 */ + uint8_t terrain_flags; + /* Line 2: radio frequency / callsign metadata (e.g. "38.90 Mhz" or + "Victor 6"). Capped tight in options. */ + char frequency[16]; +} meshtastic_CasevacReport; + +/* 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. */ +typedef struct _meshtastic_EmergencyAlert { + /* Alert discriminator. */ + meshtastic_EmergencyAlert_Type type; + /* 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. */ + char authoring_uid[48]; + /* For Type_Cancel: the uid of the alert being cancelled. Empty for + non-cancel alert types. */ + char cancel_reference_uid[48]; +} meshtastic_EmergencyAlert; + +/* 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. */ +typedef struct _meshtastic_TaskRequest { + /* 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. */ + char task_type[12]; + /* UID of the target / map item being tasked. */ + char target_uid[32]; + /* UID of the assigned unit. Empty = unassigned / broadcast task. */ + char assignee_uid[32]; + meshtastic_TaskRequest_Priority priority; + meshtastic_TaskRequest_Status status; + /* Optional short note (reason, constraints, grid reference). Capped + tight in options to keep the worst-case under the LoRa MTU. */ + char note[48]; +} meshtastic_TaskRequest; + typedef PB_BYTES_ARRAY_T(220) meshtastic_TAKPacketV2_raw_detail_t; /* ATAK v2 packet with expanded CoT field support and zstd dictionary compression. Sent on ATAK_PLUGIN_V2 port. The wire payload is: @@ -413,6 +964,12 @@ typedef struct _meshtastic_TAKPacketV2 { char phone[20]; /* CoT event type string, only populated when cot_type_id is CotType_Other */ char cot_type_str[32]; + /* 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. */ + pb_callback_t remarks; pb_size_t which_payload_variant; union { /* Position report (true = PLI, no extra fields beyond the common ones above) */ @@ -421,8 +978,26 @@ typedef struct _meshtastic_TAKPacketV2 { meshtastic_GeoChat chat; /* Aircraft track data (ADS-B, military air) */ meshtastic_AircraftTrack aircraft; - /* Generic CoT detail XML for unmapped types */ + /* 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. */ meshtastic_TAKPacketV2_raw_detail_t raw_detail; + /* User-drawn tactical graphic: circle, rectangle, polygon, polyline, + telestration, ranging circle, or bullseye. See DrawnShape. */ + meshtastic_DrawnShape shape; + /* Fixed point of interest: spot marker, waypoint, checkpoint, 2525 + symbol, or custom icon. See Marker. */ + meshtastic_Marker marker; + /* Range and bearing measurement line. See RangeAndBearing. */ + meshtastic_RangeAndBearing rab; + /* Named route with ordered waypoints and control points. See Route. */ + meshtastic_Route route; + /* 9-line MEDEVAC request. See CasevacReport. */ + meshtastic_CasevacReport casevac; + /* Emergency beacon / 911 alert. See EmergencyAlert. */ + meshtastic_EmergencyAlert emergency; + /* Task / engage request. See TaskRequest. */ + meshtastic_TaskRequest task; } payload_variant; } meshtastic_TAKPacketV2; @@ -445,14 +1020,63 @@ extern "C" { #define _meshtastic_CotHow_ARRAYSIZE ((meshtastic_CotHow)(meshtastic_CotHow_CotHow_m_s+1)) #define _meshtastic_CotType_MIN meshtastic_CotType_CotType_Other -#define _meshtastic_CotType_MAX meshtastic_CotType_CotType_b_f_t_a -#define _meshtastic_CotType_ARRAYSIZE ((meshtastic_CotType)(meshtastic_CotType_CotType_b_f_t_a+1)) +#define _meshtastic_CotType_MAX meshtastic_CotType_CotType_t_s +#define _meshtastic_CotType_ARRAYSIZE ((meshtastic_CotType)(meshtastic_CotType_CotType_t_s+1)) #define _meshtastic_GeoPointSource_MIN meshtastic_GeoPointSource_GeoPointSource_Unspecified #define _meshtastic_GeoPointSource_MAX meshtastic_GeoPointSource_GeoPointSource_NETWORK #define _meshtastic_GeoPointSource_ARRAYSIZE ((meshtastic_GeoPointSource)(meshtastic_GeoPointSource_GeoPointSource_NETWORK+1)) +#define _meshtastic_GeoChat_ReceiptType_MIN meshtastic_GeoChat_ReceiptType_ReceiptType_None +#define _meshtastic_GeoChat_ReceiptType_MAX meshtastic_GeoChat_ReceiptType_ReceiptType_Read +#define _meshtastic_GeoChat_ReceiptType_ARRAYSIZE ((meshtastic_GeoChat_ReceiptType)(meshtastic_GeoChat_ReceiptType_ReceiptType_Read+1)) +#define _meshtastic_DrawnShape_Kind_MIN meshtastic_DrawnShape_Kind_Kind_Unspecified +#define _meshtastic_DrawnShape_Kind_MAX meshtastic_DrawnShape_Kind_Kind_Vehicle3D +#define _meshtastic_DrawnShape_Kind_ARRAYSIZE ((meshtastic_DrawnShape_Kind)(meshtastic_DrawnShape_Kind_Kind_Vehicle3D+1)) + +#define _meshtastic_DrawnShape_StyleMode_MIN meshtastic_DrawnShape_StyleMode_StyleMode_Unspecified +#define _meshtastic_DrawnShape_StyleMode_MAX meshtastic_DrawnShape_StyleMode_StyleMode_StrokeAndFill +#define _meshtastic_DrawnShape_StyleMode_ARRAYSIZE ((meshtastic_DrawnShape_StyleMode)(meshtastic_DrawnShape_StyleMode_StyleMode_StrokeAndFill+1)) + +#define _meshtastic_Marker_Kind_MIN meshtastic_Marker_Kind_Kind_Unspecified +#define _meshtastic_Marker_Kind_MAX meshtastic_Marker_Kind_Kind_ImageMarker +#define _meshtastic_Marker_Kind_ARRAYSIZE ((meshtastic_Marker_Kind)(meshtastic_Marker_Kind_Kind_ImageMarker+1)) + +#define _meshtastic_Route_Method_MIN meshtastic_Route_Method_Method_Unspecified +#define _meshtastic_Route_Method_MAX meshtastic_Route_Method_Method_Watercraft +#define _meshtastic_Route_Method_ARRAYSIZE ((meshtastic_Route_Method)(meshtastic_Route_Method_Method_Watercraft+1)) + +#define _meshtastic_Route_Direction_MIN meshtastic_Route_Direction_Direction_Unspecified +#define _meshtastic_Route_Direction_MAX meshtastic_Route_Direction_Direction_Exfil +#define _meshtastic_Route_Direction_ARRAYSIZE ((meshtastic_Route_Direction)(meshtastic_Route_Direction_Direction_Exfil+1)) + +#define _meshtastic_CasevacReport_Precedence_MIN meshtastic_CasevacReport_Precedence_Precedence_Unspecified +#define _meshtastic_CasevacReport_Precedence_MAX meshtastic_CasevacReport_Precedence_Precedence_Convenience +#define _meshtastic_CasevacReport_Precedence_ARRAYSIZE ((meshtastic_CasevacReport_Precedence)(meshtastic_CasevacReport_Precedence_Precedence_Convenience+1)) + +#define _meshtastic_CasevacReport_HlzMarking_MIN meshtastic_CasevacReport_HlzMarking_HlzMarking_Unspecified +#define _meshtastic_CasevacReport_HlzMarking_MAX meshtastic_CasevacReport_HlzMarking_HlzMarking_Other +#define _meshtastic_CasevacReport_HlzMarking_ARRAYSIZE ((meshtastic_CasevacReport_HlzMarking)(meshtastic_CasevacReport_HlzMarking_HlzMarking_Other+1)) + +#define _meshtastic_CasevacReport_Security_MIN meshtastic_CasevacReport_Security_Security_Unspecified +#define _meshtastic_CasevacReport_Security_MAX meshtastic_CasevacReport_Security_Security_EnemyInArmedContact +#define _meshtastic_CasevacReport_Security_ARRAYSIZE ((meshtastic_CasevacReport_Security)(meshtastic_CasevacReport_Security_Security_EnemyInArmedContact+1)) + +#define _meshtastic_EmergencyAlert_Type_MIN meshtastic_EmergencyAlert_Type_Type_Unspecified +#define _meshtastic_EmergencyAlert_Type_MAX meshtastic_EmergencyAlert_Type_Type_Cancel +#define _meshtastic_EmergencyAlert_Type_ARRAYSIZE ((meshtastic_EmergencyAlert_Type)(meshtastic_EmergencyAlert_Type_Type_Cancel+1)) + +#define _meshtastic_TaskRequest_Priority_MIN meshtastic_TaskRequest_Priority_Priority_Unspecified +#define _meshtastic_TaskRequest_Priority_MAX meshtastic_TaskRequest_Priority_Priority_Critical +#define _meshtastic_TaskRequest_Priority_ARRAYSIZE ((meshtastic_TaskRequest_Priority)(meshtastic_TaskRequest_Priority_Priority_Critical+1)) + +#define _meshtastic_TaskRequest_Status_MIN meshtastic_TaskRequest_Status_Status_Unspecified +#define _meshtastic_TaskRequest_Status_MAX meshtastic_TaskRequest_Status_Status_Cancelled +#define _meshtastic_TaskRequest_Status_ARRAYSIZE ((meshtastic_TaskRequest_Status)(meshtastic_TaskRequest_Status_Status_Cancelled+1)) + + +#define meshtastic_GeoChat_receipt_type_ENUMTYPE meshtastic_GeoChat_ReceiptType #define meshtastic_Group_role_ENUMTYPE meshtastic_MemberRole #define meshtastic_Group_team_ENUMTYPE meshtastic_Team @@ -461,6 +1085,30 @@ extern "C" { + +#define meshtastic_DrawnShape_kind_ENUMTYPE meshtastic_DrawnShape_Kind +#define meshtastic_DrawnShape_style_ENUMTYPE meshtastic_DrawnShape_StyleMode +#define meshtastic_DrawnShape_stroke_color_ENUMTYPE meshtastic_Team +#define meshtastic_DrawnShape_fill_color_ENUMTYPE meshtastic_Team + +#define meshtastic_Marker_kind_ENUMTYPE meshtastic_Marker_Kind +#define meshtastic_Marker_color_ENUMTYPE meshtastic_Team + +#define meshtastic_RangeAndBearing_stroke_color_ENUMTYPE meshtastic_Team + +#define meshtastic_Route_method_ENUMTYPE meshtastic_Route_Method +#define meshtastic_Route_direction_ENUMTYPE meshtastic_Route_Direction + + +#define meshtastic_CasevacReport_precedence_ENUMTYPE meshtastic_CasevacReport_Precedence +#define meshtastic_CasevacReport_security_ENUMTYPE meshtastic_CasevacReport_Security +#define meshtastic_CasevacReport_hlz_marking_ENUMTYPE meshtastic_CasevacReport_HlzMarking + +#define meshtastic_EmergencyAlert_type_ENUMTYPE meshtastic_EmergencyAlert_Type + +#define meshtastic_TaskRequest_priority_ENUMTYPE meshtastic_TaskRequest_Priority +#define meshtastic_TaskRequest_status_ENUMTYPE meshtastic_TaskRequest_Status + #define meshtastic_TAKPacketV2_cot_type_id_ENUMTYPE meshtastic_CotType #define meshtastic_TAKPacketV2_how_ENUMTYPE meshtastic_CotHow #define meshtastic_TAKPacketV2_team_ENUMTYPE meshtastic_Team @@ -471,26 +1119,46 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_TAKPacket_init_default {0, false, meshtastic_Contact_init_default, false, meshtastic_Group_init_default, false, meshtastic_Status_init_default, 0, {meshtastic_PLI_init_default}} -#define meshtastic_GeoChat_init_default {"", false, "", false, ""} +#define meshtastic_GeoChat_init_default {"", false, "", false, "", "", _meshtastic_GeoChat_ReceiptType_MIN} #define meshtastic_Group_init_default {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN} #define meshtastic_Status_init_default {0} #define meshtastic_Contact_init_default {"", ""} #define meshtastic_PLI_init_default {0, 0, 0, 0, 0} #define meshtastic_AircraftTrack_init_default {"", "", "", "", 0, "", 0, 0, ""} -#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", 0, {0}} +#define meshtastic_CotGeoPoint_init_default {0, 0} +#define meshtastic_DrawnShape_init_default {_meshtastic_DrawnShape_Kind_MIN, _meshtastic_DrawnShape_StyleMode_MIN, 0, 0, 0, _meshtastic_Team_MIN, 0, 0, _meshtastic_Team_MIN, 0, 0, 0, {meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default, meshtastic_CotGeoPoint_init_default}, 0, 0, 0, 0, ""} +#define meshtastic_Marker_init_default {_meshtastic_Marker_Kind_MIN, _meshtastic_Team_MIN, 0, 0, "", "", "", ""} +#define meshtastic_RangeAndBearing_init_default {false, meshtastic_CotGeoPoint_init_default, "", 0, 0, _meshtastic_Team_MIN, 0, 0} +#define meshtastic_Route_init_default {_meshtastic_Route_Method_MIN, _meshtastic_Route_Direction_MIN, "", 0, 0, {meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default}, 0} +#define meshtastic_Route_Link_init_default {false, meshtastic_CotGeoPoint_init_default, "", "", 0} +#define meshtastic_CasevacReport_init_default {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, ""} +#define meshtastic_EmergencyAlert_init_default {_meshtastic_EmergencyAlert_Type_MIN, "", ""} +#define meshtastic_TaskRequest_init_default {"", "", "", _meshtastic_TaskRequest_Priority_MIN, _meshtastic_TaskRequest_Status_MIN, ""} +#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, 0, {0}} #define meshtastic_TAKPacket_init_zero {0, false, meshtastic_Contact_init_zero, false, meshtastic_Group_init_zero, false, meshtastic_Status_init_zero, 0, {meshtastic_PLI_init_zero}} -#define meshtastic_GeoChat_init_zero {"", false, "", false, ""} +#define meshtastic_GeoChat_init_zero {"", false, "", false, "", "", _meshtastic_GeoChat_ReceiptType_MIN} #define meshtastic_Group_init_zero {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN} #define meshtastic_Status_init_zero {0} #define meshtastic_Contact_init_zero {"", ""} #define meshtastic_PLI_init_zero {0, 0, 0, 0, 0} #define meshtastic_AircraftTrack_init_zero {"", "", "", "", 0, "", 0, 0, ""} -#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", 0, {0}} +#define meshtastic_CotGeoPoint_init_zero {0, 0} +#define meshtastic_DrawnShape_init_zero {_meshtastic_DrawnShape_Kind_MIN, _meshtastic_DrawnShape_StyleMode_MIN, 0, 0, 0, _meshtastic_Team_MIN, 0, 0, _meshtastic_Team_MIN, 0, 0, 0, {meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero, meshtastic_CotGeoPoint_init_zero}, 0, 0, 0, 0, ""} +#define meshtastic_Marker_init_zero {_meshtastic_Marker_Kind_MIN, _meshtastic_Team_MIN, 0, 0, "", "", "", ""} +#define meshtastic_RangeAndBearing_init_zero {false, meshtastic_CotGeoPoint_init_zero, "", 0, 0, _meshtastic_Team_MIN, 0, 0} +#define meshtastic_Route_init_zero {_meshtastic_Route_Method_MIN, _meshtastic_Route_Direction_MIN, "", 0, 0, {meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero}, 0} +#define meshtastic_Route_Link_init_zero {false, meshtastic_CotGeoPoint_init_zero, "", "", 0} +#define meshtastic_CasevacReport_init_zero {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, ""} +#define meshtastic_EmergencyAlert_init_zero {_meshtastic_EmergencyAlert_Type_MIN, "", ""} +#define meshtastic_TaskRequest_init_zero {"", "", "", _meshtastic_TaskRequest_Priority_MIN, _meshtastic_TaskRequest_Status_MIN, ""} +#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, 0, {0}} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_GeoChat_message_tag 1 #define meshtastic_GeoChat_to_tag 2 #define meshtastic_GeoChat_to_callsign_tag 3 +#define meshtastic_GeoChat_receipt_for_uid_tag 4 +#define meshtastic_GeoChat_receipt_type_tag 5 #define meshtastic_Group_role_tag 1 #define meshtastic_Group_team_tag 2 #define meshtastic_Status_battery_tag 1 @@ -517,6 +1185,74 @@ extern "C" { #define meshtastic_AircraftTrack_rssi_x10_tag 7 #define meshtastic_AircraftTrack_gps_tag 8 #define meshtastic_AircraftTrack_cot_host_id_tag 9 +#define meshtastic_CotGeoPoint_lat_delta_i_tag 1 +#define meshtastic_CotGeoPoint_lon_delta_i_tag 2 +#define meshtastic_DrawnShape_kind_tag 1 +#define meshtastic_DrawnShape_style_tag 2 +#define meshtastic_DrawnShape_major_cm_tag 3 +#define meshtastic_DrawnShape_minor_cm_tag 4 +#define meshtastic_DrawnShape_angle_deg_tag 5 +#define meshtastic_DrawnShape_stroke_color_tag 6 +#define meshtastic_DrawnShape_stroke_argb_tag 7 +#define meshtastic_DrawnShape_stroke_weight_x10_tag 8 +#define meshtastic_DrawnShape_fill_color_tag 9 +#define meshtastic_DrawnShape_fill_argb_tag 10 +#define meshtastic_DrawnShape_labels_on_tag 11 +#define meshtastic_DrawnShape_vertices_tag 12 +#define meshtastic_DrawnShape_truncated_tag 13 +#define meshtastic_DrawnShape_bullseye_distance_dm_tag 14 +#define meshtastic_DrawnShape_bullseye_bearing_ref_tag 15 +#define meshtastic_DrawnShape_bullseye_flags_tag 16 +#define meshtastic_DrawnShape_bullseye_uid_ref_tag 17 +#define meshtastic_Marker_kind_tag 1 +#define meshtastic_Marker_color_tag 2 +#define meshtastic_Marker_color_argb_tag 3 +#define meshtastic_Marker_readiness_tag 4 +#define meshtastic_Marker_parent_uid_tag 5 +#define meshtastic_Marker_parent_type_tag 6 +#define meshtastic_Marker_parent_callsign_tag 7 +#define meshtastic_Marker_iconset_tag 8 +#define meshtastic_RangeAndBearing_anchor_tag 1 +#define meshtastic_RangeAndBearing_anchor_uid_tag 2 +#define meshtastic_RangeAndBearing_range_cm_tag 3 +#define meshtastic_RangeAndBearing_bearing_cdeg_tag 4 +#define meshtastic_RangeAndBearing_stroke_color_tag 5 +#define meshtastic_RangeAndBearing_stroke_argb_tag 6 +#define meshtastic_RangeAndBearing_stroke_weight_x10_tag 7 +#define meshtastic_Route_Link_point_tag 1 +#define meshtastic_Route_Link_uid_tag 2 +#define meshtastic_Route_Link_callsign_tag 3 +#define meshtastic_Route_Link_link_type_tag 4 +#define meshtastic_Route_method_tag 1 +#define meshtastic_Route_direction_tag 2 +#define meshtastic_Route_prefix_tag 3 +#define meshtastic_Route_stroke_weight_x10_tag 4 +#define meshtastic_Route_links_tag 5 +#define meshtastic_Route_truncated_tag 6 +#define meshtastic_CasevacReport_precedence_tag 1 +#define meshtastic_CasevacReport_equipment_flags_tag 2 +#define meshtastic_CasevacReport_litter_patients_tag 3 +#define meshtastic_CasevacReport_ambulatory_patients_tag 4 +#define meshtastic_CasevacReport_security_tag 5 +#define meshtastic_CasevacReport_hlz_marking_tag 6 +#define meshtastic_CasevacReport_zone_marker_tag 7 +#define meshtastic_CasevacReport_us_military_tag 8 +#define meshtastic_CasevacReport_us_civilian_tag 9 +#define meshtastic_CasevacReport_non_us_military_tag 10 +#define meshtastic_CasevacReport_non_us_civilian_tag 11 +#define meshtastic_CasevacReport_epw_tag 12 +#define meshtastic_CasevacReport_child_tag 13 +#define meshtastic_CasevacReport_terrain_flags_tag 14 +#define meshtastic_CasevacReport_frequency_tag 15 +#define meshtastic_EmergencyAlert_type_tag 1 +#define meshtastic_EmergencyAlert_authoring_uid_tag 2 +#define meshtastic_EmergencyAlert_cancel_reference_uid_tag 3 +#define meshtastic_TaskRequest_task_type_tag 1 +#define meshtastic_TaskRequest_target_uid_tag 2 +#define meshtastic_TaskRequest_assignee_uid_tag 3 +#define meshtastic_TaskRequest_priority_tag 4 +#define meshtastic_TaskRequest_status_tag 5 +#define meshtastic_TaskRequest_note_tag 6 #define meshtastic_TAKPacketV2_cot_type_id_tag 1 #define meshtastic_TAKPacketV2_how_tag 2 #define meshtastic_TAKPacketV2_callsign_tag 3 @@ -540,10 +1276,18 @@ extern "C" { #define meshtastic_TAKPacketV2_endpoint_tag 21 #define meshtastic_TAKPacketV2_phone_tag 22 #define meshtastic_TAKPacketV2_cot_type_str_tag 23 +#define meshtastic_TAKPacketV2_remarks_tag 24 #define meshtastic_TAKPacketV2_pli_tag 30 #define meshtastic_TAKPacketV2_chat_tag 31 #define meshtastic_TAKPacketV2_aircraft_tag 32 #define meshtastic_TAKPacketV2_raw_detail_tag 33 +#define meshtastic_TAKPacketV2_shape_tag 34 +#define meshtastic_TAKPacketV2_marker_tag 35 +#define meshtastic_TAKPacketV2_rab_tag 36 +#define meshtastic_TAKPacketV2_route_tag 37 +#define meshtastic_TAKPacketV2_casevac_tag 38 +#define meshtastic_TAKPacketV2_emergency_tag 39 +#define meshtastic_TAKPacketV2_task_tag 40 /* Struct field encoding specification for nanopb */ #define meshtastic_TAKPacket_FIELDLIST(X, a) \ @@ -565,7 +1309,9 @@ X(a, STATIC, ONEOF, BYTES, (payload_variant,detail,payload_variant.detai #define meshtastic_GeoChat_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, message, 1) \ X(a, STATIC, OPTIONAL, STRING, to, 2) \ -X(a, STATIC, OPTIONAL, STRING, to_callsign, 3) +X(a, STATIC, OPTIONAL, STRING, to_callsign, 3) \ +X(a, STATIC, SINGULAR, STRING, receipt_for_uid, 4) \ +X(a, STATIC, SINGULAR, UENUM, receipt_type, 5) #define meshtastic_GeoChat_CALLBACK NULL #define meshtastic_GeoChat_DEFAULT NULL @@ -608,6 +1354,114 @@ X(a, STATIC, SINGULAR, STRING, cot_host_id, 9) #define meshtastic_AircraftTrack_CALLBACK NULL #define meshtastic_AircraftTrack_DEFAULT NULL +#define meshtastic_CotGeoPoint_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, SINT32, lat_delta_i, 1) \ +X(a, STATIC, SINGULAR, SINT32, lon_delta_i, 2) +#define meshtastic_CotGeoPoint_CALLBACK NULL +#define meshtastic_CotGeoPoint_DEFAULT NULL + +#define meshtastic_DrawnShape_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, kind, 1) \ +X(a, STATIC, SINGULAR, UENUM, style, 2) \ +X(a, STATIC, SINGULAR, UINT32, major_cm, 3) \ +X(a, STATIC, SINGULAR, UINT32, minor_cm, 4) \ +X(a, STATIC, SINGULAR, UINT32, angle_deg, 5) \ +X(a, STATIC, SINGULAR, UENUM, stroke_color, 6) \ +X(a, STATIC, SINGULAR, FIXED32, stroke_argb, 7) \ +X(a, STATIC, SINGULAR, UINT32, stroke_weight_x10, 8) \ +X(a, STATIC, SINGULAR, UENUM, fill_color, 9) \ +X(a, STATIC, SINGULAR, FIXED32, fill_argb, 10) \ +X(a, STATIC, SINGULAR, BOOL, labels_on, 11) \ +X(a, STATIC, REPEATED, MESSAGE, vertices, 12) \ +X(a, STATIC, SINGULAR, BOOL, truncated, 13) \ +X(a, STATIC, SINGULAR, UINT32, bullseye_distance_dm, 14) \ +X(a, STATIC, SINGULAR, UINT32, bullseye_bearing_ref, 15) \ +X(a, STATIC, SINGULAR, UINT32, bullseye_flags, 16) \ +X(a, STATIC, SINGULAR, STRING, bullseye_uid_ref, 17) +#define meshtastic_DrawnShape_CALLBACK NULL +#define meshtastic_DrawnShape_DEFAULT NULL +#define meshtastic_DrawnShape_vertices_MSGTYPE meshtastic_CotGeoPoint + +#define meshtastic_Marker_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, kind, 1) \ +X(a, STATIC, SINGULAR, UENUM, color, 2) \ +X(a, STATIC, SINGULAR, FIXED32, color_argb, 3) \ +X(a, STATIC, SINGULAR, BOOL, readiness, 4) \ +X(a, STATIC, SINGULAR, STRING, parent_uid, 5) \ +X(a, STATIC, SINGULAR, STRING, parent_type, 6) \ +X(a, STATIC, SINGULAR, STRING, parent_callsign, 7) \ +X(a, STATIC, SINGULAR, STRING, iconset, 8) +#define meshtastic_Marker_CALLBACK NULL +#define meshtastic_Marker_DEFAULT NULL + +#define meshtastic_RangeAndBearing_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, anchor, 1) \ +X(a, STATIC, SINGULAR, STRING, anchor_uid, 2) \ +X(a, STATIC, SINGULAR, UINT32, range_cm, 3) \ +X(a, STATIC, SINGULAR, UINT32, bearing_cdeg, 4) \ +X(a, STATIC, SINGULAR, UENUM, stroke_color, 5) \ +X(a, STATIC, SINGULAR, FIXED32, stroke_argb, 6) \ +X(a, STATIC, SINGULAR, UINT32, stroke_weight_x10, 7) +#define meshtastic_RangeAndBearing_CALLBACK NULL +#define meshtastic_RangeAndBearing_DEFAULT NULL +#define meshtastic_RangeAndBearing_anchor_MSGTYPE meshtastic_CotGeoPoint + +#define meshtastic_Route_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, method, 1) \ +X(a, STATIC, SINGULAR, UENUM, direction, 2) \ +X(a, STATIC, SINGULAR, STRING, prefix, 3) \ +X(a, STATIC, SINGULAR, UINT32, stroke_weight_x10, 4) \ +X(a, STATIC, REPEATED, MESSAGE, links, 5) \ +X(a, STATIC, SINGULAR, BOOL, truncated, 6) +#define meshtastic_Route_CALLBACK NULL +#define meshtastic_Route_DEFAULT NULL +#define meshtastic_Route_links_MSGTYPE meshtastic_Route_Link + +#define meshtastic_Route_Link_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, point, 1) \ +X(a, STATIC, SINGULAR, STRING, uid, 2) \ +X(a, STATIC, SINGULAR, STRING, callsign, 3) \ +X(a, STATIC, SINGULAR, UINT32, link_type, 4) +#define meshtastic_Route_Link_CALLBACK NULL +#define meshtastic_Route_Link_DEFAULT NULL +#define meshtastic_Route_Link_point_MSGTYPE meshtastic_CotGeoPoint + +#define meshtastic_CasevacReport_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, precedence, 1) \ +X(a, STATIC, SINGULAR, UINT32, equipment_flags, 2) \ +X(a, STATIC, SINGULAR, UINT32, litter_patients, 3) \ +X(a, STATIC, SINGULAR, UINT32, ambulatory_patients, 4) \ +X(a, STATIC, SINGULAR, UENUM, security, 5) \ +X(a, STATIC, SINGULAR, UENUM, hlz_marking, 6) \ +X(a, STATIC, SINGULAR, STRING, zone_marker, 7) \ +X(a, STATIC, SINGULAR, UINT32, us_military, 8) \ +X(a, STATIC, SINGULAR, UINT32, us_civilian, 9) \ +X(a, STATIC, SINGULAR, UINT32, non_us_military, 10) \ +X(a, STATIC, SINGULAR, UINT32, non_us_civilian, 11) \ +X(a, STATIC, SINGULAR, UINT32, epw, 12) \ +X(a, STATIC, SINGULAR, UINT32, child, 13) \ +X(a, STATIC, SINGULAR, UINT32, terrain_flags, 14) \ +X(a, STATIC, SINGULAR, STRING, frequency, 15) +#define meshtastic_CasevacReport_CALLBACK NULL +#define meshtastic_CasevacReport_DEFAULT NULL + +#define meshtastic_EmergencyAlert_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, type, 1) \ +X(a, STATIC, SINGULAR, STRING, authoring_uid, 2) \ +X(a, STATIC, SINGULAR, STRING, cancel_reference_uid, 3) +#define meshtastic_EmergencyAlert_CALLBACK NULL +#define meshtastic_EmergencyAlert_DEFAULT NULL + +#define meshtastic_TaskRequest_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, task_type, 1) \ +X(a, STATIC, SINGULAR, STRING, target_uid, 2) \ +X(a, STATIC, SINGULAR, STRING, assignee_uid, 3) \ +X(a, STATIC, SINGULAR, UENUM, priority, 4) \ +X(a, STATIC, SINGULAR, UENUM, status, 5) \ +X(a, STATIC, SINGULAR, STRING, note, 6) +#define meshtastic_TaskRequest_CALLBACK NULL +#define meshtastic_TaskRequest_DEFAULT NULL + #define meshtastic_TAKPacketV2_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, cot_type_id, 1) \ X(a, STATIC, SINGULAR, UENUM, how, 2) \ @@ -632,14 +1486,29 @@ X(a, STATIC, SINGULAR, STRING, tak_os, 20) \ X(a, STATIC, SINGULAR, STRING, endpoint, 21) \ X(a, STATIC, SINGULAR, STRING, phone, 22) \ X(a, STATIC, SINGULAR, STRING, cot_type_str, 23) \ +X(a, CALLBACK, SINGULAR, STRING, remarks, 24) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,pli,payload_variant.pli), 30) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat), 31) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,aircraft,payload_variant.aircraft), 32) \ -X(a, STATIC, ONEOF, BYTES, (payload_variant,raw_detail,payload_variant.raw_detail), 33) -#define meshtastic_TAKPacketV2_CALLBACK NULL +X(a, STATIC, ONEOF, BYTES, (payload_variant,raw_detail,payload_variant.raw_detail), 33) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,shape,payload_variant.shape), 34) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,marker,payload_variant.marker), 35) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,rab,payload_variant.rab), 36) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,route,payload_variant.route), 37) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,casevac,payload_variant.casevac), 38) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,emergency,payload_variant.emergency), 39) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,task,payload_variant.task), 40) +#define meshtastic_TAKPacketV2_CALLBACK pb_default_field_callback #define meshtastic_TAKPacketV2_DEFAULT NULL #define meshtastic_TAKPacketV2_payload_variant_chat_MSGTYPE meshtastic_GeoChat #define meshtastic_TAKPacketV2_payload_variant_aircraft_MSGTYPE meshtastic_AircraftTrack +#define meshtastic_TAKPacketV2_payload_variant_shape_MSGTYPE meshtastic_DrawnShape +#define meshtastic_TAKPacketV2_payload_variant_marker_MSGTYPE meshtastic_Marker +#define meshtastic_TAKPacketV2_payload_variant_rab_MSGTYPE meshtastic_RangeAndBearing +#define meshtastic_TAKPacketV2_payload_variant_route_MSGTYPE meshtastic_Route +#define meshtastic_TAKPacketV2_payload_variant_casevac_MSGTYPE meshtastic_CasevacReport +#define meshtastic_TAKPacketV2_payload_variant_emergency_MSGTYPE meshtastic_EmergencyAlert +#define meshtastic_TAKPacketV2_payload_variant_task_MSGTYPE meshtastic_TaskRequest extern const pb_msgdesc_t meshtastic_TAKPacket_msg; extern const pb_msgdesc_t meshtastic_GeoChat_msg; @@ -648,6 +1517,15 @@ extern const pb_msgdesc_t meshtastic_Status_msg; extern const pb_msgdesc_t meshtastic_Contact_msg; extern const pb_msgdesc_t meshtastic_PLI_msg; extern const pb_msgdesc_t meshtastic_AircraftTrack_msg; +extern const pb_msgdesc_t meshtastic_CotGeoPoint_msg; +extern const pb_msgdesc_t meshtastic_DrawnShape_msg; +extern const pb_msgdesc_t meshtastic_Marker_msg; +extern const pb_msgdesc_t meshtastic_RangeAndBearing_msg; +extern const pb_msgdesc_t meshtastic_Route_msg; +extern const pb_msgdesc_t meshtastic_Route_Link_msg; +extern const pb_msgdesc_t meshtastic_CasevacReport_msg; +extern const pb_msgdesc_t meshtastic_EmergencyAlert_msg; +extern const pb_msgdesc_t meshtastic_TaskRequest_msg; extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ @@ -658,18 +1536,36 @@ extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg; #define meshtastic_Contact_fields &meshtastic_Contact_msg #define meshtastic_PLI_fields &meshtastic_PLI_msg #define meshtastic_AircraftTrack_fields &meshtastic_AircraftTrack_msg +#define meshtastic_CotGeoPoint_fields &meshtastic_CotGeoPoint_msg +#define meshtastic_DrawnShape_fields &meshtastic_DrawnShape_msg +#define meshtastic_Marker_fields &meshtastic_Marker_msg +#define meshtastic_RangeAndBearing_fields &meshtastic_RangeAndBearing_msg +#define meshtastic_Route_fields &meshtastic_Route_msg +#define meshtastic_Route_Link_fields &meshtastic_Route_Link_msg +#define meshtastic_CasevacReport_fields &meshtastic_CasevacReport_msg +#define meshtastic_EmergencyAlert_fields &meshtastic_EmergencyAlert_msg +#define meshtastic_TaskRequest_fields &meshtastic_TaskRequest_msg #define meshtastic_TAKPacketV2_fields &meshtastic_TAKPacketV2_msg /* Maximum encoded size of messages (where known) */ -#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_TAKPacketV2_size +/* meshtastic_TAKPacketV2_size depends on runtime parameters */ +#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_Route_size #define meshtastic_AircraftTrack_size 134 +#define meshtastic_CasevacReport_size 70 #define meshtastic_Contact_size 242 -#define meshtastic_GeoChat_size 444 +#define meshtastic_CotGeoPoint_size 12 +#define meshtastic_DrawnShape_size 553 +#define meshtastic_EmergencyAlert_size 100 +#define meshtastic_GeoChat_size 495 #define meshtastic_Group_size 4 +#define meshtastic_Marker_size 191 #define meshtastic_PLI_size 31 +#define meshtastic_RangeAndBearing_size 84 +#define meshtastic_Route_Link_size 83 +#define meshtastic_Route_size 1379 #define meshtastic_Status_size 3 -#define meshtastic_TAKPacketV2_size 1027 -#define meshtastic_TAKPacket_size 705 +#define meshtastic_TAKPacket_size 756 +#define meshtastic_TaskRequest_size 132 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.cpp b/src/mesh/generated/meshtastic/mesh.pb.cpp index 7f1a738c6..3648d8850 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.cpp +++ b/src/mesh/generated/meshtastic/mesh.pb.cpp @@ -27,6 +27,9 @@ PB_BIND(meshtastic_KeyVerification, meshtastic_KeyVerification, AUTO) PB_BIND(meshtastic_StoreForwardPlusPlus, meshtastic_StoreForwardPlusPlus, 2) +PB_BIND(meshtastic_RemoteShell, meshtastic_RemoteShell, AUTO) + + PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO) @@ -129,6 +132,8 @@ PB_BIND(meshtastic_ChunkedPayloadResponse, meshtastic_ChunkedPayloadResponse, AU + + diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index fc6931d73..1c7eecd0d 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -308,8 +308,13 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_TDISPLAY_S3_PRO = 126, /* Heltec Mesh Node T096 board features an nRF52840 CPU and a TFT screen. */ meshtastic_HardwareModel_HELTEC_MESH_NODE_T096 = 127, - /* Seeed studio T1000-E Pro tracker card. NRF52840 w/ LR2021 radio, GPS, button, buzzer, and sensors. */ + /* Seeed studio T1000-E Pro tracker card. NRF52840 w/ LR2021 radio, + GPS, button, buzzer, and sensors. */ meshtastic_HardwareModel_TRACKER_T1000_E_PRO = 128, + /* Elecrow ThinkNode M7, M8 and M9 */ + meshtastic_HardwareModel_THINKNODE_M7 = 129, + meshtastic_HardwareModel_THINKNODE_M8 = 130, + meshtastic_HardwareModel_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. ------------------------------------------------------------------------------------------------------------------------------------------ */ @@ -513,6 +518,27 @@ typedef enum _meshtastic_StoreForwardPlusPlus_SFPP_message_type { meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF = 6 } meshtastic_StoreForwardPlusPlus_SFPP_message_type; +/* 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. */ +typedef enum _meshtastic_RemoteShell_OpCode { + meshtastic_RemoteShell_OpCode_OP_UNSET = 0, + /* Client -> server */ + meshtastic_RemoteShell_OpCode_OPEN = 1, + meshtastic_RemoteShell_OpCode_INPUT = 2, + meshtastic_RemoteShell_OpCode_RESIZE = 3, + meshtastic_RemoteShell_OpCode_CLOSE = 4, + meshtastic_RemoteShell_OpCode_PING = 5, + meshtastic_RemoteShell_OpCode_ACK = 6, + /* Server -> client */ + meshtastic_RemoteShell_OpCode_OPEN_OK = 64, + meshtastic_RemoteShell_OpCode_OUTPUT = 65, + meshtastic_RemoteShell_OpCode_CLOSED = 66, + meshtastic_RemoteShell_OpCode_ERROR = 67, + meshtastic_RemoteShell_OpCode_PONG = 68 +} meshtastic_RemoteShell_OpCode; + /* The priority of this message for sending. Higher priorities are sent first (when managing the transmit queue). This field is never sent over the air, it is only used internally inside of a local device node. @@ -845,6 +871,27 @@ typedef struct _meshtastic_StoreForwardPlusPlus { uint32_t chain_count; } meshtastic_StoreForwardPlusPlus; +typedef PB_BYTES_ARRAY_T(200) meshtastic_RemoteShell_payload_t; +/* The actual over-the-mesh message doing RemoteShell */ +typedef struct _meshtastic_RemoteShell { + /* Structured frame operation. */ + meshtastic_RemoteShell_OpCode op; + /* Logical PTY session identifier. */ + uint32_t session_id; + /* Monotonic sequence number for this frame. */ + uint32_t seq; + /* Cumulative ack sequence number. */ + uint32_t ack_seq; + /* Opaque bytes payload for INPUT/OUTPUT/ERROR and other frame bodies. */ + meshtastic_RemoteShell_payload_t payload; + /* Terminal size columns used for OPEN/RESIZE signaling. */ + uint32_t cols; + /* Terminal size rows used for OPEN/RESIZE signaling. */ + uint32_t rows; + /* Bit flags for protocol extensions. */ + uint32_t flags; +} meshtastic_RemoteShell; + /* Waypoint message, used to share arbitrary locations across the mesh */ typedef struct _meshtastic_Waypoint { /* Id of the waypoint */ @@ -1385,6 +1432,10 @@ extern "C" { #define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF #define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_ARRAYSIZE ((meshtastic_StoreForwardPlusPlus_SFPP_message_type)(meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF+1)) +#define _meshtastic_RemoteShell_OpCode_MIN meshtastic_RemoteShell_OpCode_OP_UNSET +#define _meshtastic_RemoteShell_OpCode_MAX meshtastic_RemoteShell_OpCode_PONG +#define _meshtastic_RemoteShell_OpCode_ARRAYSIZE ((meshtastic_RemoteShell_OpCode)(meshtastic_RemoteShell_OpCode_PONG+1)) + #define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET #define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX #define _meshtastic_MeshPacket_Priority_ARRAYSIZE ((meshtastic_MeshPacket_Priority)(meshtastic_MeshPacket_Priority_MAX+1)) @@ -1415,6 +1466,8 @@ extern "C" { #define meshtastic_StoreForwardPlusPlus_sfpp_message_type_ENUMTYPE meshtastic_StoreForwardPlusPlus_SFPP_message_type +#define meshtastic_RemoteShell_op_ENUMTYPE meshtastic_RemoteShell_OpCode + @@ -1459,6 +1512,7 @@ extern "C" { #define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} #define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}} #define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0} +#define meshtastic_RemoteShell_init_default {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0} #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_StatusMessage_init_default {""} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} @@ -1492,6 +1546,7 @@ extern "C" { #define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} #define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}} #define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0} +#define meshtastic_RemoteShell_init_zero {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0} #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_StatusMessage_init_zero {""} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} @@ -1581,6 +1636,14 @@ extern "C" { #define meshtastic_StoreForwardPlusPlus_encapsulated_from_tag 8 #define meshtastic_StoreForwardPlusPlus_encapsulated_rxtime_tag 9 #define meshtastic_StoreForwardPlusPlus_chain_count_tag 10 +#define meshtastic_RemoteShell_op_tag 1 +#define meshtastic_RemoteShell_session_id_tag 2 +#define meshtastic_RemoteShell_seq_tag 3 +#define meshtastic_RemoteShell_ack_seq_tag 4 +#define meshtastic_RemoteShell_payload_tag 5 +#define meshtastic_RemoteShell_cols_tag 6 +#define meshtastic_RemoteShell_rows_tag 7 +#define meshtastic_RemoteShell_flags_tag 8 #define meshtastic_Waypoint_id_tag 1 #define meshtastic_Waypoint_latitude_i_tag 2 #define meshtastic_Waypoint_longitude_i_tag 3 @@ -1813,6 +1876,18 @@ X(a, STATIC, SINGULAR, UINT32, chain_count, 10) #define meshtastic_StoreForwardPlusPlus_CALLBACK NULL #define meshtastic_StoreForwardPlusPlus_DEFAULT NULL +#define meshtastic_RemoteShell_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, op, 1) \ +X(a, STATIC, SINGULAR, UINT32, session_id, 2) \ +X(a, STATIC, SINGULAR, UINT32, seq, 3) \ +X(a, STATIC, SINGULAR, UINT32, ack_seq, 4) \ +X(a, STATIC, SINGULAR, BYTES, payload, 5) \ +X(a, STATIC, SINGULAR, UINT32, cols, 6) \ +X(a, STATIC, SINGULAR, UINT32, rows, 7) \ +X(a, STATIC, SINGULAR, UINT32, flags, 8) +#define meshtastic_RemoteShell_CALLBACK NULL +#define meshtastic_RemoteShell_DEFAULT NULL + #define meshtastic_Waypoint_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, id, 1) \ X(a, STATIC, OPTIONAL, SFIXED32, latitude_i, 2) \ @@ -2095,6 +2170,7 @@ extern const pb_msgdesc_t meshtastic_Routing_msg; extern const pb_msgdesc_t meshtastic_Data_msg; extern const pb_msgdesc_t meshtastic_KeyVerification_msg; extern const pb_msgdesc_t meshtastic_StoreForwardPlusPlus_msg; +extern const pb_msgdesc_t meshtastic_RemoteShell_msg; extern const pb_msgdesc_t meshtastic_Waypoint_msg; extern const pb_msgdesc_t meshtastic_StatusMessage_msg; extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg; @@ -2130,6 +2206,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_Data_fields &meshtastic_Data_msg #define meshtastic_KeyVerification_fields &meshtastic_KeyVerification_msg #define meshtastic_StoreForwardPlusPlus_fields &meshtastic_StoreForwardPlusPlus_msg +#define meshtastic_RemoteShell_fields &meshtastic_RemoteShell_msg #define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg #define meshtastic_StatusMessage_fields &meshtastic_StatusMessage_msg #define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg @@ -2185,6 +2262,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_NodeRemoteHardwarePin_size 29 #define meshtastic_Position_size 144 #define meshtastic_QueueStatus_size 23 +#define meshtastic_RemoteShell_size 241 #define meshtastic_RouteDiscovery_size 256 #define meshtastic_Routing_size 259 #define meshtastic_StatusMessage_size 81 diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index a474e5b92..494ef4a54 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -76,6 +76,8 @@ typedef enum _meshtastic_PortNum { meshtastic_PortNum_ALERT_APP = 11, /* Module/port for handling key verification requests. */ meshtastic_PortNum_KEY_VERIFICATION_APP = 12, + /* Module/port for handling primitive remote shell access. */ + meshtastic_PortNum_REMOTE_SHELL_APP = 13, /* Provides a 'ping' service that replies to any packet it receives. Also serves as a small example module. ENCODING: ASCII Plaintext */ diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index f48d946a4..8c0fdd563 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -113,7 +113,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* SCD30 CO2, humidity, temperature sensor */ meshtastic_TelemetrySensorType_SCD30 = 49, /* SHT family of sensors for temperature and humidity */ - meshtastic_TelemetrySensorType_SHTXX = 50 + meshtastic_TelemetrySensorType_SHTXX = 50, + /* DS248X Bridge for one-wire temperature sensors */ + meshtastic_TelemetrySensorType_DS248X = 51 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -206,6 +208,9 @@ typedef struct _meshtastic_EnvironmentMetrics { /* Soil temperature measured (*C) */ bool has_soil_temperature; float soil_temperature; + /* One-wire temperature (*C) */ + pb_size_t one_wire_temperature_count; + float one_wire_temperature[8]; } meshtastic_EnvironmentMetrics; /* Power Metrics (voltage / current / etc) */ @@ -491,8 +496,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SHTXX -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SHTXX+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_DS248X +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_DS248X+1)) @@ -508,7 +513,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0} -#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} +#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @@ -519,7 +524,7 @@ extern "C" { #define meshtastic_Nau7802Config_init_default {0, 0} #define meshtastic_SEN5XState_init_default {0, 0, 0, false, 0, false, 0, false, 0} #define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0} -#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} +#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @@ -558,6 +563,7 @@ extern "C" { #define meshtastic_EnvironmentMetrics_rainfall_24h_tag 20 #define meshtastic_EnvironmentMetrics_soil_moisture_tag 21 #define meshtastic_EnvironmentMetrics_soil_temperature_tag 22 +#define meshtastic_EnvironmentMetrics_one_wire_temperature_tag 23 #define meshtastic_PowerMetrics_ch1_voltage_tag 1 #define meshtastic_PowerMetrics_ch1_current_tag 2 #define meshtastic_PowerMetrics_ch2_voltage_tag 3 @@ -683,7 +689,8 @@ X(a, STATIC, OPTIONAL, FLOAT, radiation, 18) \ X(a, STATIC, OPTIONAL, FLOAT, rainfall_1h, 19) \ X(a, STATIC, OPTIONAL, FLOAT, rainfall_24h, 20) \ X(a, STATIC, OPTIONAL, UINT32, soil_moisture, 21) \ -X(a, STATIC, OPTIONAL, FLOAT, soil_temperature, 22) +X(a, STATIC, OPTIONAL, FLOAT, soil_temperature, 22) \ +X(a, STATIC, REPEATED, FLOAT, one_wire_temperature, 23) #define meshtastic_EnvironmentMetrics_CALLBACK NULL #define meshtastic_EnvironmentMetrics_DEFAULT NULL @@ -852,7 +859,7 @@ extern const pb_msgdesc_t meshtastic_SEN5XState_msg; #define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size #define meshtastic_AirQualityMetrics_size 150 #define meshtastic_DeviceMetrics_size 27 -#define meshtastic_EnvironmentMetrics_size 113 +#define meshtastic_EnvironmentMetrics_size 161 #define meshtastic_HealthMetrics_size 11 #define meshtastic_HostMetrics_size 264 #define meshtastic_LocalStats_size 87 diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 9a52a9aff..05bc0aa5d 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -480,7 +480,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta #if HAS_SCREEN IF_SCREEN(screen->showSimpleBanner("Device is rebooting\ninto DFU mode.", 0)); #endif -#if defined(ARCH_NRF52) || defined(ARCH_RP2040) +#if defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL) enterDfuMode(); #endif break; diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index 73780b6eb..5cf3a4465 100644 --- a/src/platform/nrf52/main-nrf52.cpp +++ b/src/platform/nrf52/main-nrf52.cpp @@ -17,6 +17,7 @@ #include #include // #include +#include "HardwareRNG.h" #include "NodeDB.h" #include "PowerMon.h" #include "error.h" @@ -398,15 +399,14 @@ void nrf52Setup() #endif // Init random seed - union seedParts { - uint32_t seed32; - uint8_t seed8[4]; - } seed; - nRFCrypto.begin(); - nRFCrypto.Random.generate(seed.seed8, sizeof(seed.seed8)); - LOG_DEBUG("Set random seed %u", seed.seed32); - randomSeed(seed.seed32); - nRFCrypto.end(); + uint32_t seed = 0; + if (!HardwareRNG::seed(seed)) { + LOG_WARN("Hardware RNG seed unavailable, using PRNG fallback"); + // Use a hardware timer value as a fallback seed for better entropy + seed = micros(); + } + LOG_DEBUG("Set random seed %u", seed); + randomSeed(seed); // Set up nrfx watchdog. Do not enable the watchdog yet (we do that // the first time through the main loop), so that other threads can diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 4bbdbee7a..7833b3603 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -1,4 +1,5 @@ #include "CryptoEngine.h" +#include "HardwareRNG.h" #include "PortduinoGPIO.h" #include "SPIChip.h" #include "mesh/RF95Interface.h" @@ -181,6 +182,10 @@ void portduinoSetup() // Force stdout to be line buffered setvbuf(stdout, stdoutBuffer, _IOLBF, sizeof(stdoutBuffer)); + // We do this super early so that we can log from the rest of the init code + concurrency::hasBeenSetup = true; + consoleInit(); + if (portduino_config.force_simradio == true) { portduino_config.lora_module = use_simradio; } else if (configPath != nullptr) { @@ -233,7 +238,9 @@ void portduinoSetup() std::cout << "Running in simulated mode." << std::endl; portduino_config.MaxNodes = 200; // Default to 200 nodes // Set the random seed equal to TCPPort to have a different seed per instance - randomSeed(TCPPort); + uint32_t seed = TCPPort; + HardwareRNG::seed(seed); + randomSeed(seed); return; } @@ -512,7 +519,9 @@ void portduinoSetup() #endif printf("MAC ADDRESS: %02X:%02X:%02X:%02X:%02X:%02X\n", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]); // Rather important to set this, if not running simulated. - randomSeed(time(NULL)); + uint32_t seed = static_cast(time(NULL)); + HardwareRNG::seed(seed); + randomSeed(seed); std::string defaultGpioChipName = gpioChipName + std::to_string(portduino_config.lora_default_gpiochip); @@ -645,7 +654,9 @@ void portduinoSetup() if (verboseEnabled && portduino_config.logoutputlevel != level_trace) { portduino_config.logoutputlevel = level_debug; } - + if (portduino_config.lora_spi_dev != "") { + portduinoSetOptions({.realHardware = true}); + } return; } diff --git a/src/platform/rp2xx0/main-rp2xx0.cpp b/src/platform/rp2xx0/main-rp2xx0.cpp index 6c73e385a..e59b0a9cd 100644 --- a/src/platform/rp2xx0/main-rp2xx0.cpp +++ b/src/platform/rp2xx0/main-rp2xx0.cpp @@ -1,3 +1,4 @@ +#include "HardwareRNG.h" #include "configuration.h" #include "hardware/xosc.h" #include @@ -98,10 +99,12 @@ void getMacAddr(uint8_t *dmac) void rp2040Setup() { - /* Sets a random seed to make sure we get different random numbers on each boot. - Taken from CPU cycle counter and ROSC oscillator, so should be pretty random. - */ - randomSeed(rp2040.hwrand32()); + /* Sets a random seed to make sure we get different random numbers on each boot. */ + uint32_t seed = 0; + if (!HardwareRNG::seed(seed)) { + seed = rp2040.hwrand32(); + } + randomSeed(seed); #ifdef RP2040_SLOW_CLOCK uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY); diff --git a/src/platform/stm32wl/main-stm32wl.cpp b/src/platform/stm32wl/main-stm32wl.cpp index 93080f840..241020126 100644 --- a/src/platform/stm32wl/main-stm32wl.cpp +++ b/src/platform/stm32wl/main-stm32wl.cpp @@ -4,6 +4,57 @@ #include #include +// ─── Bootloader redirect ────────────────────────────────────────────────────── +// +// Why .noinit + constructor instead of TAMP backup registers: +// +// The STM32duino startup sequence initialises clocks which may call +// __HAL_RCC_BACKUPRESET_FORCE/RELEASE when configuring the LSE oscillator, +// wiping the entire backup domain (including TAMP->BKP0R) before setup() +// ever runs. The backup-register approach therefore cannot reliably survive +// a soft reset in this toolchain. +// +// Solution: store the magic in a .noinit SRAM variable. +// - NVIC_SystemReset() does NOT clear SRAM. +// - The linker script skips zero-init for .noinit sections. +// - __attribute__((constructor)) fires before main()/HAL_Init(), so we can +// intercept and jump before anything disturbs peripheral state. + +#define BOOTLOADER_MAGIC 0xD00DB007UL +#define SYS_MEM_BASE 0x1FFF0000UL + +// Placed in .noinit — not zeroed at startup, survives NVIC_SystemReset(). +__attribute__((section(".noinit"), used)) volatile uint32_t g_bootloaderMagic; + +// Fires before main() / HAL_Init(). Must use only core Cortex-M registers. +__attribute__((constructor(101), used)) static void earlyBootCheck(void) +{ + if (g_bootloaderMagic != BOOTLOADER_MAGIC) + return; + g_bootloaderMagic = 0; + + SysTick->CTRL = 0; + SysTick->LOAD = 0; + SysTick->VAL = 0; + for (int i = 0; i < 8; i++) { + NVIC->ICER[i] = 0xFFFFFFFF; + NVIC->ICPR[i] = 0xFFFFFFFF; + } + __DSB(); + __ISB(); + SCB->VTOR = SYS_MEM_BASE; + __set_MSP(*(volatile uint32_t *)SYS_MEM_BASE); + ((void (*)(void))(*(volatile uint32_t *)(SYS_MEM_BASE + 4)))(); + while (1) + ; +} + +void enterDfuMode() +{ + g_bootloaderMagic = BOOTLOADER_MAGIC; + HAL_NVIC_SystemReset(); +} + void setBluetoothEnable(bool enable) {} void playStartMelody() {} diff --git a/src/power.h b/src/power.h index b129e2b74..d46eaadd2 100644 --- a/src/power.h +++ b/src/power.h @@ -15,8 +15,13 @@ // Device specific curves go in variant.h #ifndef OCV_ARRAY +#if defined(ARCH_STM32WL) && BATTERY_PIN == AVBAT +// STM32 VDD/VBAT absolute maximum is 4V so use an LFP curve +#define OCV_ARRAY 3650, 3400, 3340, 3320, 3300, 3280, 3270, 3260, 3240, 3200, 2500 +#else #define OCV_ARRAY 4190, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100 #endif +#endif /*Note: 12V lead acid is 6 cells, most board accept only 1 cell LiIon/LiPo*/ #ifndef NUM_CELLS diff --git a/variants/esp32/betafpv_2400_tx_micro/platformio.ini b/variants/esp32/betafpv_2400_tx_micro/platformio.ini index 068d71011..c2e89b333 100644 --- a/variants/esp32/betafpv_2400_tx_micro/platformio.ini +++ b/variants/esp32/betafpv_2400_tx_micro/platformio.ini @@ -13,7 +13,3 @@ board_build.f_cpu = 240000000L upload_protocol = esptool ;upload_port = /dev/ttyUSB0 upload_speed = 460800 -lib_deps = - ${esp32_base.lib_deps} - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 diff --git a/variants/esp32/esp32-common.ini b/variants/esp32/esp32-common.ini index db826b3f9..b9d6f5c50 100644 --- a/variants/esp32/esp32-common.ini +++ b/variants/esp32/esp32-common.ini @@ -39,7 +39,6 @@ build_flags = -Wall -Wextra -Isrc/platform/esp32 - -include mbedtls/error.h -std=gnu++17 -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG diff --git a/variants/esp32/heltec_wireless_bridge/platformio.ini b/variants/esp32/heltec_wireless_bridge/platformio.ini index 6f9de7a84..42a35697c 100644 --- a/variants/esp32/heltec_wireless_bridge/platformio.ini +++ b/variants/esp32/heltec_wireless_bridge/platformio.ini @@ -10,6 +10,7 @@ build_flags = -D BOARD_HAS_PSRAM -D RADIOLIB_EXCLUDE_LR11X0=1 -D RADIOLIB_EXCLUDE_SX128X=1 + -D RADIOLIB_EXCLUDE_LR2021=1 -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 -D MESHTASTIC_EXCLUDE_DETECTIONSENSOR=1 -D MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1 diff --git a/variants/esp32c3/heltec_hru_3601/platformio.ini b/variants/esp32c3/heltec_hru_3601/platformio.ini index aa62fb4fc..5eb1c9977 100644 --- a/variants/esp32c3/heltec_hru_3601/platformio.ini +++ b/variants/esp32c3/heltec_hru_3601/platformio.ini @@ -5,6 +5,3 @@ build_flags = ${esp32c3_base.build_flags} -D HELTEC_HRU_3601 -I variants/esp32c3/heltec_hru_3601 -lib_deps = ${esp32c3_base.lib_deps} - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 diff --git a/variants/esp32c6/m5stack_unitc6l/platformio.ini b/variants/esp32c6/m5stack_unitc6l/platformio.ini index 4c04d0c26..bf605ca61 100644 --- a/variants/esp32c6/m5stack_unitc6l/platformio.ini +++ b/variants/esp32c6/m5stack_unitc6l/platformio.ini @@ -23,8 +23,6 @@ build_unflags = -D HAS_WIFI lib_deps = ${esp32c6_base.lib_deps} - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 # renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino h2zero/NimBLE-Arduino@2.3.7 build_flags = diff --git a/variants/esp32s3/diy/my_esp32s3_diy_eink/platformio.ini b/variants/esp32s3/diy/my_esp32s3_diy_eink/platformio.ini index c2805425b..90e4910f4 100644 --- a/variants/esp32s3/diy/my_esp32s3_diy_eink/platformio.ini +++ b/variants/esp32s3/diy/my_esp32s3_diy_eink/platformio.ini @@ -12,8 +12,6 @@ lib_deps = ${esp32s3_base.lib_deps} # renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2 zinggjm/GxEPD2@1.6.8 - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 build_unflags = ${esp32s3_base.build_unflags} -DARDUINO_USB_MODE=1 diff --git a/variants/esp32s3/diy/my_esp32s3_diy_oled/platformio.ini b/variants/esp32s3/diy/my_esp32s3_diy_oled/platformio.ini index c53831c9f..60b030d42 100644 --- a/variants/esp32s3/diy/my_esp32s3_diy_oled/platformio.ini +++ b/variants/esp32s3/diy/my_esp32s3_diy_oled/platformio.ini @@ -8,10 +8,6 @@ board_build.f_cpu = 240000000L upload_protocol = esptool ;upload_port = /dev/ttyACM0 upload_speed = 921600 -lib_deps = - ${esp32s3_base.lib_deps} - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 build_unflags = ${esp32s3_base.build_unflags} -DARDUINO_USB_MODE=1 diff --git a/variants/esp32s3/esp32-s3-pico/platformio.ini b/variants/esp32s3/esp32-s3-pico/platformio.ini index 07ca069f3..64f50f80e 100644 --- a/variants/esp32s3/esp32-s3-pico/platformio.ini +++ b/variants/esp32s3/esp32-s3-pico/platformio.ini @@ -24,5 +24,3 @@ build_flags = ${esp32s3_base.build_flags} lib_deps = ${esp32s3_base.lib_deps} # renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2 zinggjm/GxEPD2@1.6.8 - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 diff --git a/variants/esp32s3/heltec_sensor_hub/platformio.ini b/variants/esp32s3/heltec_sensor_hub/platformio.ini index 013280db1..9a5384ccd 100644 --- a/variants/esp32s3/heltec_sensor_hub/platformio.ini +++ b/variants/esp32s3/heltec_sensor_hub/platformio.ini @@ -8,7 +8,3 @@ build_flags = -I variants/esp32s3/heltec_sensor_hub -D HELTEC_SENSOR_HUB -ULED_BUILTIN - -lib_deps = ${esp32s3_base.lib_deps} - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 diff --git a/variants/esp32s3/heltec_vision_master_t190/platformio.ini b/variants/esp32s3/heltec_vision_master_t190/platformio.ini index 44e8b2f2d..be1ea192d 100644 --- a/variants/esp32s3/heltec_vision_master_t190/platformio.ini +++ b/variants/esp32s3/heltec_vision_master_t190/platformio.ini @@ -20,5 +20,5 @@ build_flags = lib_deps = ${esp32s3_base.lib_deps} # renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main - https://github.com/meshtastic/st7789/archive/9ee76d6b18b9a8f45a2c5cae06b1134a587691eb.zip + https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip upload_speed = 921600 diff --git a/variants/esp32s3/link32_s3_v1/platformio.ini b/variants/esp32s3/link32_s3_v1/platformio.ini index acce3dafb..b11ffaad0 100644 --- a/variants/esp32s3/link32_s3_v1/platformio.ini +++ b/variants/esp32s3/link32_s3_v1/platformio.ini @@ -11,3 +11,4 @@ build_flags = -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 diff --git a/variants/esp32s3/m5stack_cardputer_adv/platformio.ini b/variants/esp32s3/m5stack_cardputer_adv/platformio.ini index e2411bc6e..7da039cd4 100644 --- a/variants/esp32s3/m5stack_cardputer_adv/platformio.ini +++ b/variants/esp32s3/m5stack_cardputer_adv/platformio.ini @@ -16,12 +16,10 @@ build_src_filter = lib_deps = ${esp32s3_base.lib_deps} # renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main - https://github.com/meshtastic/st7789/archive/9ee76d6b18b9a8f45a2c5cae06b1134a587691eb.zip + https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip # renovate: datasource=github-tags depName=pschatzmann_arduino-audio-driver packageName=pschatzmann/arduino-audio-driver https://github.com/pschatzmann/arduino-audio-driver/archive/v0.2.1.zip # renovate: datasource=git-refs depName=ESP8266Audio packageName=https://github.com/meshtastic/ESP8266Audio gitBranch=meshtastic-2.0.0-dacfix https://github.com/meshtastic/ESP8266Audio/archive/343024632ee78d6216907b2353fc943a62422d80.zip # renovate: datasource=custom.pio depName=ESP8266SAM packageName=earlephilhower/library/ESP8266SAM earlephilhower/ESP8266SAM@1.1.0 - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 diff --git a/variants/esp32s3/mini-epaper-s3/nicheGraphics.h b/variants/esp32s3/mini-epaper-s3/nicheGraphics.h index 86da4b8ce..0cbd6a192 100644 --- a/variants/esp32s3/mini-epaper-s3/nicheGraphics.h +++ b/variants/esp32s3/mini-epaper-s3/nicheGraphics.h @@ -98,7 +98,7 @@ void setupNicheGraphics() buttons->setTwoWayRockerPressHandlers( [inkhud]() { bool systemHandlingInput = false; - for (InkHUD::SystemApplet *sa : inkhud->systemApplets) { + for (const InkHUD::SystemApplet *sa : inkhud->systemApplets) { if (sa->handleInput) { systemHandlingInput = true; break; @@ -112,7 +112,7 @@ void setupNicheGraphics() }, [inkhud]() { bool systemHandlingInput = false; - for (InkHUD::SystemApplet *sa : inkhud->systemApplets) { + for (const InkHUD::SystemApplet *sa : inkhud->systemApplets) { if (sa->handleInput) { systemHandlingInput = true; break; diff --git a/variants/esp32s3/unphone/platformio.ini b/variants/esp32s3/unphone/platformio.ini index 1d4af52f3..3c342e2ac 100644 --- a/variants/esp32s3/unphone/platformio.ini +++ b/variants/esp32s3/unphone/platformio.ini @@ -40,8 +40,6 @@ lib_deps = ${esp32s3_base.lib_deps} lovyan03/LovyanGFX@1.2.19 # TODO renovate https://gitlab.com/hamishcunningham/unphonelibrary#meshtastic@9.0.0 https://gitlab.com/hamishcunningham/unphonelibrary/-/archive/meshtastic/unphonelibrary-meshtastic.zip - # renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel - adafruit/Adafruit NeoPixel@1.15.4 [env:unphone-tft] board_level = extra diff --git a/variants/native/portduino.ini b/variants/native/portduino.ini index a247b0af1..87d8431a3 100644 --- a/variants/native/portduino.ini +++ b/variants/native/portduino.ini @@ -2,7 +2,7 @@ [portduino_base] platform = # renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop - https://github.com/meshtastic/platform-native/archive/f566d364204416cdbf298e349213f7d551f793d9.zip + https://github.com/meshtastic/platform-native/archive/71ed55bb95feb3c43ebde1ec1e2e17643a424c04.zip framework = arduino build_src_filter = @@ -34,8 +34,8 @@ lib_deps = adafruit/Adafruit seesaw Library@1.7.9 # renovate: datasource=git-refs depName=RAK12034-BMX160 packageName=https://github.com/RAKWireless/RAK12034-BMX160 gitBranch=main https://github.com/RAKWireless/RAK12034-BMX160/archive/dcead07ffa267d3c906e9ca4a1330ab989e957e2.zip - # renovate: datasource=custom.pio depName=Adafruit_BME680 packageName=adafruit/library/Adafruit BME680 Library - adafruit/Adafruit BME680 Library@2.0.6 + # renovate: datasource=github-tags depName=Adafruit_BME680 packageName=adafruit/Adafruit_BME680 + https://github.com/adafruit/Adafruit_BME680/archive/refs/tags/2.0.6.zip build_flags = ${arduino_base.build_flags} @@ -59,4 +59,5 @@ build_flags = lib_ignore = Adafruit NeoPixel Adafruit ST7735 and ST7789 Library + Adafruit SSD1306 SD diff --git a/variants/nrf52840/gat562_mesh_trial_tracker/platformio.ini b/variants/nrf52840/gat562_mesh_trial_tracker/platformio.ini index e7eede80f..cecca3d81 100644 --- a/variants/nrf52840/gat562_mesh_trial_tracker/platformio.ini +++ b/variants/nrf52840/gat562_mesh_trial_tracker/platformio.ini @@ -11,4 +11,5 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/gat562_mesh_trial_tracker> diff --git a/variants/nrf52840/heltec_mesh_node_t114/platformio.ini b/variants/nrf52840/heltec_mesh_node_t114/platformio.ini index 7cbc5f6a9..ef8bd4a17 100644 --- a/variants/nrf52840/heltec_mesh_node_t114/platformio.ini +++ b/variants/nrf52840/heltec_mesh_node_t114/platformio.ini @@ -23,4 +23,4 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_ lib_deps = ${nrf52840_base.lib_deps} # renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main - https://github.com/meshtastic/st7789/archive/9ee76d6b18b9a8f45a2c5cae06b1134a587691eb.zip + https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip diff --git a/variants/nrf52840/heltec_mesh_solar/platformio.ini b/variants/nrf52840/heltec_mesh_solar/platformio.ini index 6935920cd..1b15c0758 100644 --- a/variants/nrf52840/heltec_mesh_solar/platformio.ini +++ b/variants/nrf52840/heltec_mesh_solar/platformio.ini @@ -132,4 +132,4 @@ build_flags = ${heltec_mesh_solar_base.build_flags} lib_deps = ${heltec_mesh_solar_base.lib_deps} # renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main - https://github.com/meshtastic/st7789/archive/9ee76d6b18b9a8f45a2c5cae06b1134a587691eb.zip + https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip diff --git a/variants/nrf52840/meshlink/platformio.ini b/variants/nrf52840/meshlink/platformio.ini index 28122d9bd..f3dc6185c 100644 --- a/variants/nrf52840/meshlink/platformio.ini +++ b/variants/nrf52840/meshlink/platformio.ini @@ -12,6 +12,7 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/meshlink> debug_tool = jlink @@ -30,6 +31,7 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 -D USE_EINK -D EINK_DISPLAY_MODEL=GxEPD2_213_B74 -D EINK_WIDTH=250 @@ -51,4 +53,4 @@ lib_deps = debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds -;upload_protocol = jlink \ No newline at end of file +;upload_protocol = jlink diff --git a/variants/nrf52840/r1-neo/platformio.ini b/variants/nrf52840/r1-neo/platformio.ini index 85fe49cf1..0aaec2330 100644 --- a/variants/nrf52840/r1-neo/platformio.ini +++ b/variants/nrf52840/r1-neo/platformio.ini @@ -18,6 +18,7 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/r1-neo> + + lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/nrf52840/rak2560/platformio.ini b/variants/nrf52840/rak2560/platformio.ini index 1703a13ae..54b66f4b2 100644 --- a/variants/nrf52840/rak2560/platformio.ini +++ b/variants/nrf52840/rak2560/platformio.ini @@ -18,6 +18,7 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 -DHAS_RAKPROT=1 ; Define if RAk OneWireSerial is used (disables GPS) build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak2560> + + + lib_deps = diff --git a/variants/nrf52840/rak3401_1watt/platformio.ini b/variants/nrf52840/rak3401_1watt/platformio.ini index bb8fa28df..889a17ed6 100644 --- a/variants/nrf52840/rak3401_1watt/platformio.ini +++ b/variants/nrf52840/rak3401_1watt/platformio.ini @@ -22,6 +22,7 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak3401_1watt> + lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/nrf52840/rak4631/platformio.ini b/variants/nrf52840/rak4631/platformio.ini index 4a96fc8d9..179d73e92 100644 --- a/variants/nrf52840/rak4631/platformio.ini +++ b/variants/nrf52840/rak4631/platformio.ini @@ -21,6 +21,7 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 build_src_filter = ${nrf52_base.build_src_filter} \ +<../variants/nrf52840/rak4631> \ + \ diff --git a/variants/nrf52840/rak4631_epaper/platformio.ini b/variants/nrf52840/rak4631_epaper/platformio.ini index caa6ea328..f71fb6301 100644 --- a/variants/nrf52840/rak4631_epaper/platformio.ini +++ b/variants/nrf52840/rak4631_epaper/platformio.ini @@ -11,6 +11,7 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_epaper> lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/nrf52840/rak4631_epaper_onrxtx/platformio.ini b/variants/nrf52840/rak4631_epaper_onrxtx/platformio.ini index 84a582fd9..670b2c415 100644 --- a/variants/nrf52840/rak4631_epaper_onrxtx/platformio.ini +++ b/variants/nrf52840/rak4631_epaper_onrxtx/platformio.ini @@ -13,6 +13,7 @@ build_flags = ${nrf52840_base.build_flags} -D RADIOLIB_EXCLUDE_SX128X=1 -D RADIOLIB_EXCLUDE_SX127X=1 -D RADIOLIB_EXCLUDE_LR11X0=1 + -D RADIOLIB_EXCLUDE_LR2021=1 build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_epaper_onrxtx> lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/nrf52840/rak4631_nomadstar_meteor_pro/platformio.ini b/variants/nrf52840/rak4631_nomadstar_meteor_pro/platformio.ini index 9b15e668a..f1641e7e4 100644 --- a/variants/nrf52840/rak4631_nomadstar_meteor_pro/platformio.ini +++ b/variants/nrf52840/rak4631_nomadstar_meteor_pro/platformio.ini @@ -21,6 +21,7 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_nomadstar_meteor_pro> + + lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/nrf52840/rak_wismeshtag/platformio.ini b/variants/nrf52840/rak_wismeshtag/platformio.ini index 1e6e63e60..07fd6e73f 100644 --- a/variants/nrf52840/rak_wismeshtag/platformio.ini +++ b/variants/nrf52840/rak_wismeshtag/platformio.ini @@ -19,5 +19,6 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 -DMESHTASTIC_EXCLUDE_WIFI=1 build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak_wismeshtag> diff --git a/variants/stm32/rak3172/variant.h b/variants/stm32/rak3172/variant.h index bd6decd4c..75e3e0c91 100644 --- a/variants/stm32/rak3172/variant.h +++ b/variants/stm32/rak3172/variant.h @@ -16,6 +16,11 @@ Do not expect a working Meshtastic device with this target. #define LED_POWER PA0 // Green LED #define LED_STATE_ON 1 +#define BATTERY_PIN AVBAT +// ADC_MULTIPLIER: 3.0 = internal 1:3 bridge divider (DS13105§3.18.3) +// Margin: 1.10 = AVBAT divider tolerance ±10% (Table 82) +#define ADC_MULTIPLIER (1.01f * 3) + #define RAK3172 #define SERIAL_PRINT_PORT 1 diff --git a/variants/stm32/russell/variant.h b/variants/stm32/russell/variant.h index 8773d5d8d..7b5d4e9a1 100644 --- a/variants/stm32/russell/variant.h +++ b/variants/stm32/russell/variant.h @@ -13,6 +13,16 @@ // #define EXT_CHRG_DETECT PA5 // #define EXT_PWR_DETECT PA4 +#define BATTERY_PIN AVBAT +// ADC_MULTIPLIER: 3.0 = internal 1:3 bridge divider (DS13105§3.18.3) +// Margin: 1.10 = AVBAT divider tolerance ±10% (Table 82) +#define ADC_MULTIPLIER (1.01f * 3) +/* +Sample OCV curve for Li-SOCl2 primary lithium cells (e.g. Saft cells have fresh OCV of 3.67V) +#define NUM_OCV_POINTS 11 +#define OCV_ARRAY 3670, 3650, 3630, 3610, 3590, 3560, 3530, 3480, 3400, 3200, 2500 +*/ + // Bosch Sensortec BME280 #define HAS_SENSOR 1 diff --git a/variants/stm32/stm32.ini b/variants/stm32/stm32.ini index d2c155398..542d08800 100644 --- a/variants/stm32/stm32.ini +++ b/variants/stm32/stm32.ini @@ -35,6 +35,7 @@ build_flags = -DRADIOLIB_EXCLUDE_SX128X=1 -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 + -DRADIOLIB_EXCLUDE_LR2021=1 -DHAL_DAC_MODULE_ONLY -DHAL_RNG_MODULE_ENABLED -Wl,--wrap=__assert_func diff --git a/version.properties b/version.properties index 8621dd9c9..4ee342bb8 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 7 -build = 22 +build = 23