Merge remote-tracking branch 'upstream/develop' into fix/tlora-pager-rotary-amplifier
This commit is contained in:
@@ -0,0 +1,500 @@
|
|||||||
|
name: Build One Arch
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
arch:
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
- native
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
setup:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
cache: pip
|
||||||
|
- run: pip install -U platformio
|
||||||
|
- name: Generate matrix
|
||||||
|
id: jsonStep
|
||||||
|
run: |
|
||||||
|
if [[ "$GITHUB_HEAD_REF" == "" ]]; then
|
||||||
|
TARGETS=$(./bin/generate_ci_matrix.py ${{inputs.arch}} extra)
|
||||||
|
else
|
||||||
|
TARGETS=$(./bin/generate_ci_matrix.py ${{inputs.arch}} pr)
|
||||||
|
fi
|
||||||
|
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF Targets: $TARGETS"
|
||||||
|
echo "${{inputs.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
|
||||||
|
outputs:
|
||||||
|
esp32: ${{ steps.jsonStep.outputs.esp32 }}
|
||||||
|
esp32s3: ${{ steps.jsonStep.outputs.esp32s3 }}
|
||||||
|
esp32c3: ${{ steps.jsonStep.outputs.esp32c3 }}
|
||||||
|
esp32c6: ${{ steps.jsonStep.outputs.esp32c6 }}
|
||||||
|
nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
|
||||||
|
rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
|
||||||
|
rp2350: ${{ steps.jsonStep.outputs.rp2350 }}
|
||||||
|
stm32: ${{ steps.jsonStep.outputs.stm32 }}
|
||||||
|
check: ${{ steps.jsonStep.outputs.check }}
|
||||||
|
|
||||||
|
version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- name: Get release version string
|
||||||
|
run: |
|
||||||
|
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
env:
|
||||||
|
BUILD_LOCATION: local
|
||||||
|
outputs:
|
||||||
|
long: ${{ steps.version.outputs.long }}
|
||||||
|
deb: ${{ steps.version.outputs.deb }}
|
||||||
|
|
||||||
|
build-esp32:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'esp32'}}
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.esp32) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32
|
||||||
|
|
||||||
|
build-esp32s3:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'esp32s3'}}
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.esp32s3) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32s3
|
||||||
|
|
||||||
|
build-esp32c3:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'esp32c3'}}
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32c3
|
||||||
|
|
||||||
|
build-esp32c6:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'esp32c6'}}
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.esp32c6) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32c6
|
||||||
|
|
||||||
|
build-nrf52840:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'nrf52840'}}
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: nrf52840
|
||||||
|
|
||||||
|
build-rp2040:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'rp2040'}}
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: rp2040
|
||||||
|
|
||||||
|
build-rp2350:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'rp2350'}}
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.rp2350) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: rp2350
|
||||||
|
|
||||||
|
build-stm32:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'stm32' }}
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.stm32) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: stm32
|
||||||
|
|
||||||
|
build-debian-src:
|
||||||
|
if: ${{ github.repository == 'meshtastic/firmware' && github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/build_debian_src.yml
|
||||||
|
with:
|
||||||
|
series: UNRELEASED
|
||||||
|
build_location: local
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
package-pio-deps-native-tft:
|
||||||
|
if: ${{ inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/package_pio_deps.yml
|
||||||
|
with:
|
||||||
|
pio_env: native-tft
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
test-native:
|
||||||
|
if: ${{ !contains(github.ref_name, 'event/') && github.event_name != 'workflow_dispatch' || !contains(github.ref_name, 'event/') && inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/test_native.yml
|
||||||
|
|
||||||
|
docker-deb-amd64:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-deb-amd64-tft:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
pio_env: native-tft
|
||||||
|
|
||||||
|
docker-alp-amd64:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: alpine
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-alp-amd64-tft:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: alpine
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
pio_env: native-tft
|
||||||
|
|
||||||
|
docker-deb-arm64:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/arm64
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-deb-armv7:
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/arm/v7
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
push: false
|
||||||
|
|
||||||
|
gather-artifacts:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
arch:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
[
|
||||||
|
version,
|
||||||
|
build-esp32,
|
||||||
|
build-esp32s3,
|
||||||
|
build-esp32c3,
|
||||||
|
build-esp32c6,
|
||||||
|
build-nrf52840,
|
||||||
|
build-rp2040,
|
||||||
|
build-rp2350,
|
||||||
|
build-stm32,
|
||||||
|
]
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
path: ./
|
||||||
|
pattern: firmware-${{inputs.arch}}-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
|
- name: Move files up
|
||||||
|
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
||||||
|
|
||||||
|
- name: Repackage in single firmware zip
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
./firmware-*.bin
|
||||||
|
./firmware-*.uf2
|
||||||
|
./firmware-*.hex
|
||||||
|
./firmware-*-ota.zip
|
||||||
|
./device-*.sh
|
||||||
|
./device-*.bat
|
||||||
|
./littlefs-*.bin
|
||||||
|
./bleota*bin
|
||||||
|
./Meshtastic_nRF52_factory_erase*.uf2
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
name: firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Show artifacts
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Device scripts permissions
|
||||||
|
run: |
|
||||||
|
chmod +x ./output/device-install.sh
|
||||||
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
|
- name: Zip firmware
|
||||||
|
run: zip -j -9 -r ./firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||||
|
|
||||||
|
- name: Repackage in single elfs zip
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: debug-elfs-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
overwrite: true
|
||||||
|
path: ./*.elf
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- uses: scruplelesswizard/comment-artifact@main
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
with:
|
||||||
|
name: firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}
|
||||||
|
description: "Download firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
release-artifacts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
outputs:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
needs:
|
||||||
|
- version
|
||||||
|
- gather-artifacts
|
||||||
|
- build-debian-src
|
||||||
|
- package-pio-deps-native-tft
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
id: create_release
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
prerelease: true
|
||||||
|
name: Meshtastic Firmware ${{ needs.version.outputs.long }} Alpha
|
||||||
|
tag_name: v${{ needs.version.outputs.long }}
|
||||||
|
body: |
|
||||||
|
Autogenerated by github action, developer should edit as required before publishing...
|
||||||
|
|
||||||
|
- name: Download source deb
|
||||||
|
uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output/debian-src
|
||||||
|
|
||||||
|
- name: Download `native-tft` pio deps
|
||||||
|
uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output/pio-deps-native-tft
|
||||||
|
|
||||||
|
- name: Zip Linux sources
|
||||||
|
working-directory: output
|
||||||
|
run: |
|
||||||
|
zip -j -9 -r ./meshtasticd-${{ needs.version.outputs.deb }}-src.zip ./debian-src
|
||||||
|
zip -9 -r ./platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip ./pio-deps-native-tft
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Add Linux sources to GtiHub Release
|
||||||
|
# Only run when targeting master branch with workflow_dispatch
|
||||||
|
if: ${{ github.ref_name == 'master' }}
|
||||||
|
run: |
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./output/meshtasticd-${{ needs.version.outputs.deb }}-src.zip
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./output/platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
release-firmware:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
arch:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
needs: [release-artifacts, version]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Device scripts permissions
|
||||||
|
run: |
|
||||||
|
chmod +x ./output/device-install.sh
|
||||||
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
|
- name: Zip firmware
|
||||||
|
run: zip -j -9 -r ./firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
name: debug-elfs-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./elfs
|
||||||
|
|
||||||
|
- name: Zip debug elfs
|
||||||
|
run: zip -j -9 -r ./debug-elfs-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip ./elfs
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Add bins and debug elfs to GitHub Release
|
||||||
|
# Only run when targeting master branch with workflow_dispatch
|
||||||
|
if: ${{ github.ref_name == 'master' }}
|
||||||
|
run: |
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./debug-elfs-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
publish-firmware:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
needs: [release-firmware, version]
|
||||||
|
env:
|
||||||
|
targets: |-
|
||||||
|
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./publish
|
||||||
|
|
||||||
|
- name: Publish firmware to meshtastic.github.io
|
||||||
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
|
env:
|
||||||
|
# On event/* branches, use the event name as the destination prefix
|
||||||
|
DEST_PREFIX: ${{ contains(github.ref_name, 'event/') && format('{0}/', github.ref_name) || '' }}
|
||||||
|
with:
|
||||||
|
deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }}
|
||||||
|
external_repository: meshtastic/meshtastic.github.io
|
||||||
|
publish_branch: master
|
||||||
|
publish_dir: ./publish
|
||||||
|
destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ needs.version.outputs.long }}
|
||||||
|
keep_files: true
|
||||||
|
user_name: github-actions[bot]
|
||||||
|
user_email: github-actions[bot]@users.noreply.github.com
|
||||||
|
commit_message: ${{ needs.version.outputs.long }}
|
||||||
|
enable_jekyll: true
|
||||||
@@ -0,0 +1,395 @@
|
|||||||
|
name: Build One Target
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
arch:
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
- native
|
||||||
|
target:
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
description: Choose the target board, e.g. nrf52_promicro_diy_tcxo. If blank, will find available targets.
|
||||||
|
|
||||||
|
# find-target:
|
||||||
|
# type: boolean
|
||||||
|
# default: true
|
||||||
|
# description: 'Find the available targets'
|
||||||
|
jobs:
|
||||||
|
find-targets:
|
||||||
|
if: ${{ inputs.target == '' }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
arch:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
cache: pip
|
||||||
|
- run: pip install -U platformio
|
||||||
|
- name: Generate matrix
|
||||||
|
id: jsonStep
|
||||||
|
run: |
|
||||||
|
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} extra)
|
||||||
|
echo "Name: $GITHUB_REF_NAME" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "Base: $GITHUB_BASE_REF" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "Arch: ${{matrix.arch}}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "Ref: $GITHUB_REF" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "Targets:" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo $TARGETS | sed 's/[][]//g; s/", "/\n- /g; s/"//g; s/^/- /' >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
version:
|
||||||
|
if: ${{ inputs.target != '' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- name: Get release version string
|
||||||
|
run: |
|
||||||
|
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
env:
|
||||||
|
BUILD_LOCATION: local
|
||||||
|
outputs:
|
||||||
|
long: ${{ steps.version.outputs.long }}
|
||||||
|
deb: ${{ steps.version.outputs.deb }}
|
||||||
|
|
||||||
|
build-arch:
|
||||||
|
if: ${{ inputs.target != '' && inputs.arch != 'native' }}
|
||||||
|
needs: [version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ inputs.target }}
|
||||||
|
platform: ${{ inputs.arch }}
|
||||||
|
|
||||||
|
build-debian-src:
|
||||||
|
if: ${{ github.repository == 'meshtastic/firmware' && inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/build_debian_src.yml
|
||||||
|
with:
|
||||||
|
series: UNRELEASED
|
||||||
|
build_location: local
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
package-pio-deps-native-tft:
|
||||||
|
if: ${{ inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/package_pio_deps.yml
|
||||||
|
with:
|
||||||
|
pio_env: native-tft
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
test-native:
|
||||||
|
if: ${{ !contains(github.ref_name, 'event/') && github.event_name != 'workflow_dispatch' || !contains(github.ref_name, 'event/') && inputs.arch == 'native' && inputs.target != '' }}
|
||||||
|
uses: ./.github/workflows/test_native.yml
|
||||||
|
|
||||||
|
docker-deb-amd64:
|
||||||
|
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-deb-amd64-tft:
|
||||||
|
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
pio_env: native-tft
|
||||||
|
|
||||||
|
docker-alp-amd64:
|
||||||
|
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: alpine
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-alp-amd64-tft:
|
||||||
|
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: alpine
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
pio_env: native-tft
|
||||||
|
|
||||||
|
docker-deb-arm64:
|
||||||
|
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/arm64
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-deb-armv7:
|
||||||
|
if: ${{ inputs.target != '' && inputs.arch == 'native' }}
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/arm/v7
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
push: false
|
||||||
|
|
||||||
|
gather-artifacts:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [version, build-arch]
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
path: ./
|
||||||
|
pattern: firmware-*-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
|
- name: Move files up
|
||||||
|
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
||||||
|
|
||||||
|
- name: Repackage in single firmware zip
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-${{inputs.target}}-${{ needs.version.outputs.long }}
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
./firmware-*.bin
|
||||||
|
./firmware-*.uf2
|
||||||
|
./firmware-*.hex
|
||||||
|
./firmware-*-ota.zip
|
||||||
|
./device-*.sh
|
||||||
|
./device-*.bat
|
||||||
|
./littlefs-*.bin
|
||||||
|
./bleota*bin
|
||||||
|
./Meshtastic_nRF52_factory_erase*.uf2
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-*-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Show artifacts
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Device scripts permissions
|
||||||
|
run: |
|
||||||
|
chmod +x ./output/device-install.sh
|
||||||
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
|
- name: Zip firmware
|
||||||
|
run: zip -j -9 -r ./firmware-${{inputs.target}}-${{ needs.version.outputs.long }}.zip ./output
|
||||||
|
|
||||||
|
- name: Repackage in single elfs zip
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: debug-elfs-${{inputs.target}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
overwrite: true
|
||||||
|
path: ./*.elf
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- uses: scruplelesswizard/comment-artifact@main
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
with:
|
||||||
|
name: firmware-${{inputs.target}}-${{ needs.version.outputs.long }}
|
||||||
|
description: "Download firmware-${{inputs.target}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
release-artifacts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && inputs.target != ''}}
|
||||||
|
outputs:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
needs:
|
||||||
|
- version
|
||||||
|
- gather-artifacts
|
||||||
|
- build-debian-src
|
||||||
|
- package-pio-deps-native-tft
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
id: create_release
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
prerelease: true
|
||||||
|
name: Meshtastic Firmware ${{ needs.version.outputs.long }} Alpha
|
||||||
|
tag_name: v${{ needs.version.outputs.long }}
|
||||||
|
body: |
|
||||||
|
Autogenerated by github action, developer should edit as required before publishing...
|
||||||
|
|
||||||
|
- name: Download source deb
|
||||||
|
uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output/debian-src
|
||||||
|
|
||||||
|
- name: Download `native-tft` pio deps
|
||||||
|
uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output/pio-deps-native-tft
|
||||||
|
|
||||||
|
- name: Zip Linux sources
|
||||||
|
working-directory: output
|
||||||
|
run: |
|
||||||
|
zip -j -9 -r ./meshtasticd-${{ needs.version.outputs.deb }}-src.zip ./debian-src
|
||||||
|
zip -9 -r ./platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip ./pio-deps-native-tft
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Add Linux sources to GtiHub Release
|
||||||
|
# Only run when targeting master branch with workflow_dispatch
|
||||||
|
if: ${{ github.ref_name == 'master' }}
|
||||||
|
run: |
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./output/meshtasticd-${{ needs.version.outputs.deb }}-src.zip
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./output/platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
release-firmware:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && inputs.target != ''}}
|
||||||
|
needs: [release-artifacts, version]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-*-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Device scripts permissions
|
||||||
|
run: |
|
||||||
|
chmod +x ./output/device-install.sh
|
||||||
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
|
- name: Zip firmware
|
||||||
|
run: zip -j -9 -r ./firmware-${{inputs.target}}-${{ needs.version.outputs.long }}.zip ./output
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: debug-elfs-*-${{ needs.version.outputs.long }}.zip
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./elfs
|
||||||
|
|
||||||
|
- name: Zip debug elfs
|
||||||
|
run: zip -j -9 -r ./debug-elfs-${{inputs.target}}-${{ needs.version.outputs.long }}.zip ./elfs
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Add bins and debug elfs to GitHub Release
|
||||||
|
# Only run when targeting master branch with workflow_dispatch
|
||||||
|
if: ${{ github.ref_name == 'master' }}
|
||||||
|
run: |
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./firmware-${{inputs.target}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./debug-elfs-${{inputs.target}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
publish-firmware:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware' && inputs.target != '' }}
|
||||||
|
needs: [release-firmware, version]
|
||||||
|
env:
|
||||||
|
targets: |-
|
||||||
|
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./publish
|
||||||
|
|
||||||
|
- name: Publish firmware to meshtastic.github.io
|
||||||
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
|
env:
|
||||||
|
# On event/* branches, use the event name as the destination prefix
|
||||||
|
DEST_PREFIX: ${{ contains(github.ref_name, 'event/') && format('{0}/', github.ref_name) || '' }}
|
||||||
|
with:
|
||||||
|
deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }}
|
||||||
|
external_repository: meshtastic/meshtastic.github.io
|
||||||
|
publish_branch: master
|
||||||
|
publish_dir: ./publish
|
||||||
|
destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ needs.version.outputs.long }}
|
||||||
|
keep_files: true
|
||||||
|
user_name: github-actions[bot]
|
||||||
|
user_email: github-actions[bot]@users.noreply.github.com
|
||||||
|
commit_message: ${{ needs.version.outputs.long }}
|
||||||
|
enable_jekyll: true
|
||||||
@@ -21,12 +21,14 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker-multiarch:
|
docker-multiarch:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/docker_manifest.yml
|
uses: ./.github/workflows/docker_manifest.yml
|
||||||
with:
|
with:
|
||||||
release_channel: daily
|
release_channel: daily
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
package-ppa:
|
package-ppa:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -42,6 +44,7 @@ jobs:
|
|||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
package-obs:
|
package-obs:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/package_obs.yml
|
uses: ./.github/workflows/package_obs.yml
|
||||||
with:
|
with:
|
||||||
obs_project: network:Meshtastic:daily
|
obs_project: network:Meshtastic:daily
|
||||||
@@ -49,6 +52,7 @@ jobs:
|
|||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
hook-copr:
|
hook-copr:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/hook_copr.yml
|
uses: ./.github/workflows/hook_copr.yml
|
||||||
with:
|
with:
|
||||||
copr_project: daily
|
copr_project: daily
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ concurrency:
|
|||||||
group: ci-${{ github.head_ref || github.run_id }}
|
group: ci-${{ github.head_ref || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
on:
|
on:
|
||||||
# # Triggers the workflow on push but only for the master branch
|
# # Triggers the workflow on push but only for the main branches
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
@@ -27,6 +27,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -74,6 +75,7 @@ jobs:
|
|||||||
check: ${{ steps.jsonStep.outputs.check }}
|
check: ${{ steps.jsonStep.outputs.check }}
|
||||||
|
|
||||||
version:
|
version:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
@@ -95,7 +97,7 @@ jobs:
|
|||||||
matrix: ${{ fromJson(needs.setup.outputs.check) }}
|
matrix: ${{ fromJson(needs.setup.outputs.check) }}
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
- name: Build base
|
- name: Build base
|
||||||
@@ -208,10 +210,11 @@ jobs:
|
|||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
test-native:
|
test-native:
|
||||||
if: ${{ !contains(github.ref_name, 'event/') }}
|
if: ${{ !contains(github.ref_name, 'event/') && github.repository == 'meshtastic/firmware' }}
|
||||||
uses: ./.github/workflows/test_native.yml
|
uses: ./.github/workflows/test_native.yml
|
||||||
|
|
||||||
docker-deb-amd64:
|
docker-deb-amd64:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/docker_build.yml
|
uses: ./.github/workflows/docker_build.yml
|
||||||
with:
|
with:
|
||||||
distro: debian
|
distro: debian
|
||||||
@@ -220,6 +223,7 @@ jobs:
|
|||||||
push: false
|
push: false
|
||||||
|
|
||||||
docker-deb-amd64-tft:
|
docker-deb-amd64-tft:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/docker_build.yml
|
uses: ./.github/workflows/docker_build.yml
|
||||||
with:
|
with:
|
||||||
distro: debian
|
distro: debian
|
||||||
@@ -229,6 +233,7 @@ jobs:
|
|||||||
pio_env: native-tft
|
pio_env: native-tft
|
||||||
|
|
||||||
docker-alp-amd64:
|
docker-alp-amd64:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/docker_build.yml
|
uses: ./.github/workflows/docker_build.yml
|
||||||
with:
|
with:
|
||||||
distro: alpine
|
distro: alpine
|
||||||
@@ -237,6 +242,7 @@ jobs:
|
|||||||
push: false
|
push: false
|
||||||
|
|
||||||
docker-alp-amd64-tft:
|
docker-alp-amd64-tft:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/docker_build.yml
|
uses: ./.github/workflows/docker_build.yml
|
||||||
with:
|
with:
|
||||||
distro: alpine
|
distro: alpine
|
||||||
@@ -246,6 +252,7 @@ jobs:
|
|||||||
pio_env: native-tft
|
pio_env: native-tft
|
||||||
|
|
||||||
docker-deb-arm64:
|
docker-deb-arm64:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/docker_build.yml
|
uses: ./.github/workflows/docker_build.yml
|
||||||
with:
|
with:
|
||||||
distro: debian
|
distro: debian
|
||||||
@@ -254,6 +261,7 @@ jobs:
|
|||||||
push: false
|
push: false
|
||||||
|
|
||||||
docker-deb-armv7:
|
docker-deb-armv7:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
uses: ./.github/workflows/docker_build.yml
|
uses: ./.github/workflows/docker_build.yml
|
||||||
with:
|
with:
|
||||||
distro: debian
|
distro: debian
|
||||||
@@ -262,6 +270,8 @@ jobs:
|
|||||||
push: false
|
push: false
|
||||||
|
|
||||||
gather-artifacts:
|
gather-artifacts:
|
||||||
|
# trunk-ignore(checkov/CKV2_GHA_1)
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
@@ -361,7 +371,7 @@ jobs:
|
|||||||
|
|
||||||
release-artifacts:
|
release-artifacts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
||||||
outputs:
|
outputs:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
needs:
|
needs:
|
||||||
@@ -436,7 +446,7 @@ jobs:
|
|||||||
- rp2350
|
- rp2350
|
||||||
- stm32
|
- stm32
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware'}}
|
||||||
needs: [release-artifacts, version]
|
needs: [release-artifacts, version]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -0,0 +1,508 @@
|
|||||||
|
name: Merge Queue
|
||||||
|
# Not sure how concurrency works in merge_queue, removing for now.
|
||||||
|
# concurrency:
|
||||||
|
# group: merge-queue-${{ github.head_ref || github.run_id }}
|
||||||
|
# cancel-in-progress: true
|
||||||
|
on:
|
||||||
|
# Merge group is a special trigger that is used to trigger the workflow when a merge group is created.
|
||||||
|
merge_group:
|
||||||
|
|
||||||
|
env:
|
||||||
|
FAIL_FAST_PER_ARCH: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
setup:
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
arch:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
- check
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
cache: pip
|
||||||
|
- run: pip install -U platformio
|
||||||
|
- name: Generate matrix
|
||||||
|
id: jsonStep
|
||||||
|
run: |
|
||||||
|
if [[ "$GITHUB_HEAD_REF" == "" ]]; then
|
||||||
|
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
|
||||||
|
else
|
||||||
|
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} pr)
|
||||||
|
fi
|
||||||
|
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF Targets: $TARGETS"
|
||||||
|
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
|
||||||
|
outputs:
|
||||||
|
esp32: ${{ steps.jsonStep.outputs.esp32 }}
|
||||||
|
esp32s3: ${{ steps.jsonStep.outputs.esp32s3 }}
|
||||||
|
esp32c3: ${{ steps.jsonStep.outputs.esp32c3 }}
|
||||||
|
esp32c6: ${{ steps.jsonStep.outputs.esp32c6 }}
|
||||||
|
nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
|
||||||
|
rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
|
||||||
|
rp2350: ${{ steps.jsonStep.outputs.rp2350 }}
|
||||||
|
stm32: ${{ steps.jsonStep.outputs.stm32 }}
|
||||||
|
check: ${{ steps.jsonStep.outputs.check }}
|
||||||
|
|
||||||
|
version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- name: Get release version string
|
||||||
|
run: |
|
||||||
|
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
env:
|
||||||
|
BUILD_LOCATION: local
|
||||||
|
outputs:
|
||||||
|
long: ${{ steps.version.outputs.long }}
|
||||||
|
deb: ${{ steps.version.outputs.deb }}
|
||||||
|
|
||||||
|
check:
|
||||||
|
needs: setup
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.check) }}
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- name: Build base
|
||||||
|
id: base
|
||||||
|
uses: ./.github/actions/setup-base
|
||||||
|
- name: Check ${{ matrix.board }}
|
||||||
|
run: bin/check-all.sh ${{ matrix.board }}
|
||||||
|
|
||||||
|
build-esp32:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: ${{ vars.FAIL_FAST_PER_ARCH == true }}
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.esp32) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32
|
||||||
|
|
||||||
|
build-esp32s3:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: ${{ vars.FAIL_FAST_PER_ARCH == true }}
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.esp32s3) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32s3
|
||||||
|
|
||||||
|
build-esp32c3:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: ${{ vars.FAIL_FAST_PER_ARCH == true }}
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32c3
|
||||||
|
|
||||||
|
build-esp32c6:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: ${{ vars.FAIL_FAST_PER_ARCH == true }}
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.esp32c6) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32c6
|
||||||
|
|
||||||
|
build-nrf52840:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: ${{ vars.FAIL_FAST_PER_ARCH == true }}
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: nrf52840
|
||||||
|
|
||||||
|
build-rp2040:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: ${{ vars.FAIL_FAST_PER_ARCH == true }}
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: rp2040
|
||||||
|
|
||||||
|
build-rp2350:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: ${{ vars.FAIL_FAST_PER_ARCH == true }}
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.rp2350) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: rp2350
|
||||||
|
|
||||||
|
build-stm32:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: ${{ vars.FAIL_FAST_PER_ARCH == true }}
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.stm32) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: stm32
|
||||||
|
|
||||||
|
build-debian-src:
|
||||||
|
if: github.repository == 'meshtastic/firmware'
|
||||||
|
uses: ./.github/workflows/build_debian_src.yml
|
||||||
|
with:
|
||||||
|
series: UNRELEASED
|
||||||
|
build_location: local
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
package-pio-deps-native-tft:
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
uses: ./.github/workflows/package_pio_deps.yml
|
||||||
|
with:
|
||||||
|
pio_env: native-tft
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
test-native:
|
||||||
|
if: ${{ !contains(github.ref_name, 'event/') }}
|
||||||
|
uses: ./.github/workflows/test_native.yml
|
||||||
|
|
||||||
|
docker-deb-amd64:
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-deb-amd64-tft:
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
pio_env: native-tft
|
||||||
|
|
||||||
|
docker-alp-amd64:
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: alpine
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-alp-amd64-tft:
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: alpine
|
||||||
|
platform: linux/amd64
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
push: false
|
||||||
|
pio_env: native-tft
|
||||||
|
|
||||||
|
docker-deb-arm64:
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/arm64
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
push: false
|
||||||
|
|
||||||
|
docker-deb-armv7:
|
||||||
|
uses: ./.github/workflows/docker_build.yml
|
||||||
|
with:
|
||||||
|
distro: debian
|
||||||
|
platform: linux/arm/v7
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
push: false
|
||||||
|
|
||||||
|
gather-artifacts:
|
||||||
|
# trunk-ignore(checkov/CKV2_GHA_1)
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
arch:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
[
|
||||||
|
version,
|
||||||
|
build-esp32,
|
||||||
|
build-esp32s3,
|
||||||
|
build-esp32c3,
|
||||||
|
build-esp32c6,
|
||||||
|
build-nrf52840,
|
||||||
|
build-rp2040,
|
||||||
|
build-rp2350,
|
||||||
|
build-stm32,
|
||||||
|
]
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
path: ./
|
||||||
|
pattern: firmware-${{matrix.arch}}-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
|
- name: Move files up
|
||||||
|
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
||||||
|
|
||||||
|
- name: Repackage in single firmware zip
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
./firmware-*.bin
|
||||||
|
./firmware-*.uf2
|
||||||
|
./firmware-*.hex
|
||||||
|
./firmware-*-ota.zip
|
||||||
|
./device-*.sh
|
||||||
|
./device-*.bat
|
||||||
|
./littlefs-*.bin
|
||||||
|
./bleota*bin
|
||||||
|
./Meshtastic_nRF52_factory_erase*.uf2
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Show artifacts
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Device scripts permissions
|
||||||
|
run: |
|
||||||
|
chmod +x ./output/device-install.sh
|
||||||
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
|
- name: Zip firmware
|
||||||
|
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||||
|
|
||||||
|
- name: Repackage in single elfs zip
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
overwrite: true
|
||||||
|
path: ./*.elf
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- uses: scruplelesswizard/comment-artifact@main
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
with:
|
||||||
|
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||||
|
description: "Download firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
release-artifacts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
outputs:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
needs:
|
||||||
|
- version
|
||||||
|
- gather-artifacts
|
||||||
|
- build-debian-src
|
||||||
|
- package-pio-deps-native-tft
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
id: create_release
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
prerelease: true
|
||||||
|
name: Meshtastic Firmware ${{ needs.version.outputs.long }} Alpha
|
||||||
|
tag_name: v${{ needs.version.outputs.long }}
|
||||||
|
body: |
|
||||||
|
Autogenerated by github action, developer should edit as required before publishing...
|
||||||
|
|
||||||
|
- name: Download source deb
|
||||||
|
uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output/debian-src
|
||||||
|
|
||||||
|
- name: Download `native-tft` pio deps
|
||||||
|
uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output/pio-deps-native-tft
|
||||||
|
|
||||||
|
- name: Zip Linux sources
|
||||||
|
working-directory: output
|
||||||
|
run: |
|
||||||
|
zip -j -9 -r ./meshtasticd-${{ needs.version.outputs.deb }}-src.zip ./debian-src
|
||||||
|
zip -9 -r ./platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip ./pio-deps-native-tft
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Add Linux sources to GtiHub Release
|
||||||
|
# Only run when targeting master branch with workflow_dispatch
|
||||||
|
if: ${{ github.ref_name == 'master' }}
|
||||||
|
run: |
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./output/meshtasticd-${{ needs.version.outputs.deb }}-src.zip
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./output/platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
release-firmware:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
arch:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
needs: [release-artifacts, version]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Device scripts permissions
|
||||||
|
run: |
|
||||||
|
chmod +x ./output/device-install.sh
|
||||||
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
|
- name: Zip firmware
|
||||||
|
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./elfs
|
||||||
|
|
||||||
|
- name: Zip debug elfs
|
||||||
|
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./elfs
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Add bins and debug elfs to GitHub Release
|
||||||
|
# Only run when targeting master branch with workflow_dispatch
|
||||||
|
if: ${{ github.ref_name == 'master' }}
|
||||||
|
run: |
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
gh release upload v${{ needs.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
publish-firmware:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
needs: [release-firmware, version]
|
||||||
|
env:
|
||||||
|
targets: |-
|
||||||
|
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v5
|
||||||
|
with:
|
||||||
|
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./publish
|
||||||
|
|
||||||
|
- name: Publish firmware to meshtastic.github.io
|
||||||
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
|
env:
|
||||||
|
# On event/* branches, use the event name as the destination prefix
|
||||||
|
DEST_PREFIX: ${{ contains(github.ref_name, 'event/') && format('{0}/', github.ref_name) || '' }}
|
||||||
|
with:
|
||||||
|
deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }}
|
||||||
|
external_repository: meshtastic/meshtastic.github.io
|
||||||
|
publish_branch: master
|
||||||
|
publish_dir: ./publish
|
||||||
|
destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ needs.version.outputs.long }}
|
||||||
|
keep_files: true
|
||||||
|
user_name: github-actions[bot]
|
||||||
|
user_email: github-actions[bot]@users.noreply.github.com
|
||||||
|
commit_message: ${{ needs.version.outputs.long }}
|
||||||
|
enable_jekyll: true
|
||||||
+4
-4
@@ -8,15 +8,15 @@ plugins:
|
|||||||
uri: https://github.com/trunk-io/plugins
|
uri: https://github.com/trunk-io/plugins
|
||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- checkov@3.2.469
|
- checkov@3.2.471
|
||||||
- renovate@41.94.0
|
- renovate@41.115.6
|
||||||
- prettier@3.6.2
|
- prettier@3.6.2
|
||||||
- trufflehog@3.90.5
|
- trufflehog@3.90.6
|
||||||
- yamllint@1.37.1
|
- yamllint@1.37.1
|
||||||
- bandit@1.8.6
|
- bandit@1.8.6
|
||||||
- trivy@0.66.0
|
- trivy@0.66.0
|
||||||
- taplo@0.10.0
|
- taplo@0.10.0
|
||||||
- ruff@0.12.11
|
- ruff@0.13.0
|
||||||
- isort@6.0.1
|
- isort@6.0.1
|
||||||
- markdownlint@0.45.0
|
- markdownlint@0.45.0
|
||||||
- oxipng@9.1.5
|
- oxipng@9.1.5
|
||||||
|
|||||||
@@ -87,6 +87,9 @@
|
|||||||
</screenshots>
|
</screenshots>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="2.7.10" date="2025-09-18">
|
||||||
|
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.10</url>
|
||||||
|
</release>
|
||||||
<release version="2.7.9" date="2025-09-03">
|
<release version="2.7.9" date="2025-09-03">
|
||||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.9</url>
|
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.9</url>
|
||||||
</release>
|
</release>
|
||||||
|
|||||||
Vendored
+45
-105
@@ -1,109 +1,49 @@
|
|||||||
meshtasticd (2.7.9.0) unstable; urgency=medium
|
meshtasticd (2.7.10.0) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
* Version 2.7.9
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Wed, 03 Sep 2025 23:39:17 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.7.8.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.7.8
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Sat, 30 Aug 2025 00:26:04 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.7.7.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.7.7
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Thu, 28 Aug 2025 10:33:25 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.7.6.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.7.6
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Tue, 12 Aug 2025 23:48:48 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.7.5.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.7.5
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Sat, 09 Aug 2025 12:46:53 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.7.4.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.7.4
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Sat, 19 Jul 2025 11:36:55 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.7.3.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.7.3
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Thu, 10 Jul 2025 16:29:27 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.7.2.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.7.2
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Fri, 04 Jul 2025 11:58:01 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.7.1.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.7.1
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Fri, 27 Jun 2025 20:12:21 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.6.13) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.6.13
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Mon, 16 Jun 2025 02:10:49 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.6.11) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.6.11
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Mon, 02 Jun 2025 20:00:55 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.6.10) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.6.10
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Sun, 25 May 2025 20:46:49 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.6.9) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.6.9
|
|
||||||
* Run as non-root user, 'meshtasticd'
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Thu, 15 May 2025 11:13:30 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.6.8) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.6.8
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Tue, 06 May 2025 01:32:49 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.5.22) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.5.22
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Wed, 05 Feb 2025 01:10:33 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.5.21) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.5.21
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Sat, 25 Jan 2025 01:39:16 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.5.20) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Version 2.5.20
|
|
||||||
|
|
||||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Mon, 13 Jan 2025 19:24:14 +0000
|
|
||||||
|
|
||||||
meshtasticd (2.5.19) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Initial packaging
|
* Initial packaging
|
||||||
* Version 2.5.19
|
* Version 2.5.19
|
||||||
|
|
||||||
-- Austin Lane <vidplace7@gmail.com> Thu, 02 Jan 2025 12:00:00 +0000
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ Ubuntu ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
-- <github-actions[bot]@users.noreply.github.com> Thu, 18 Sep 2025 22:11:37 +0000
|
||||||
|
|||||||
+3
-2
@@ -55,6 +55,7 @@ build_flags = -Wno-missing-field-initializers
|
|||||||
-D MAX_THREADS=40 ; As we've split modules, we have more threads to manage
|
-D MAX_THREADS=40 ; As we've split modules, we have more threads to manage
|
||||||
#-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now
|
#-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now
|
||||||
#-D OLED_PL=1
|
#-D OLED_PL=1
|
||||||
|
#-D DEBUG_HEAP=1 ; uncomment to add free heap space / memory leak debugging logs
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_filters = direct
|
monitor_filters = direct
|
||||||
@@ -118,13 +119,13 @@ lib_deps =
|
|||||||
[device-ui_base]
|
[device-ui_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||||
https://github.com/meshtastic/device-ui/archive/3677476c8a823ee85056b5fb1d146a3e193f8276.zip
|
https://github.com/meshtastic/device-ui/archive/9ed5355a24059750e9b2eb5d669574d9ea42a37b.zip
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
[environmental_base]
|
[environmental_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO
|
# renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO
|
||||||
adafruit/Adafruit BusIO@1.17.2
|
adafruit/Adafruit BusIO@1.17.3
|
||||||
# renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor
|
# renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor
|
||||||
adafruit/Adafruit Unified Sensor@1.1.15
|
adafruit/Adafruit Unified Sensor@1.1.15
|
||||||
# renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library
|
# renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library
|
||||||
|
|||||||
+1
-1
Submodule protobufs updated: 8caf423964...46b81e822a
@@ -183,9 +183,9 @@ class AmbientLightingThread : public concurrency::OSThread
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
pixels.show();
|
pixels.show();
|
||||||
LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
|
// LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
|
||||||
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
|
// moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
|
||||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
// moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||||
#endif
|
#endif
|
||||||
#ifdef RGBLED_CA
|
#ifdef RGBLED_CA
|
||||||
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
|
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
|
||||||
|
|||||||
@@ -6,7 +6,5 @@ class DisplayFormatters
|
|||||||
public:
|
public:
|
||||||
static const char *getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName,
|
static const char *getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName,
|
||||||
bool usePreset);
|
bool usePreset);
|
||||||
|
|
||||||
public:
|
|
||||||
static const char *getDeviceRole(meshtastic_Config_DeviceConfig_Role role);
|
static const char *getDeviceRole(meshtastic_Config_DeviceConfig_Role role);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "memGet.h"
|
||||||
#include "mesh/generated/meshtastic/mesh.pb.h"
|
#include "mesh/generated/meshtastic/mesh.pb.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -166,6 +167,16 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
|
|||||||
print(thread->ThreadName);
|
print(thread->ThreadName);
|
||||||
print("] ");
|
print("] ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_HEAP
|
||||||
|
// Add heap free space bytes prefix before every log message
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
::printf("[heap %u] ", memGet.getFreeHeap());
|
||||||
|
#else
|
||||||
|
printf("[heap %u] ", memGet.getFreeHeap());
|
||||||
|
#endif
|
||||||
|
#endif // DEBUG_HEAP
|
||||||
|
|
||||||
r += vprintf(logLevel, format, arg);
|
r += vprintf(logLevel, format, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -262,6 +262,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define VEXT_ON_VALUE LOW
|
#define VEXT_ON_VALUE LOW
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Rotary encoder
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
#ifndef ROTARY_DELAY
|
||||||
|
#define ROTARY_DELAY 5
|
||||||
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// GPS
|
// GPS
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -431,7 +438,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define MESHTASTIC_EXCLUDE_SERIAL 1
|
#define MESHTASTIC_EXCLUDE_SERIAL 1
|
||||||
#define MESHTASTIC_EXCLUDE_POWERSTRESS 1
|
#define MESHTASTIC_EXCLUDE_POWERSTRESS 1
|
||||||
#define MESHTASTIC_EXCLUDE_ADMIN 1
|
#define MESHTASTIC_EXCLUDE_ADMIN 1
|
||||||
#define MESHTASTIC_EXCLUDE_AMBIENTLIGHTING 1
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// // Turn off wifi even if HW supports wifi (webserver relies on wifi and is also disabled)
|
// // Turn off wifi even if HW supports wifi (webserver relies on wifi and is also disabled)
|
||||||
|
|||||||
@@ -294,6 +294,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
type = AHT10;
|
type = AHT10;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
case INA_ADDR:
|
case INA_ADDR:
|
||||||
case INA_ADDR_ALTERNATE:
|
case INA_ADDR_ALTERNATE:
|
||||||
case INA_ADDR_WAVESHARE_UPS:
|
case INA_ADDR_WAVESHARE_UPS:
|
||||||
@@ -340,6 +341,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
// else: probably a RAK12500/UBLOX GPS on I2C
|
// else: probably a RAK12500/UBLOX GPS on I2C
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case MCP9808_ADDR:
|
case MCP9808_ADDR:
|
||||||
// We need to check for STK8BAXX first, since register 0x07 is new data flag for the z-axis and can produce some
|
// We need to check for STK8BAXX first, since register 0x07 is new data flag for the z-axis and can produce some
|
||||||
// weird result. and register 0x00 doesn't seems to be colliding with MCP9808 and LIS3DH chips.
|
// weird result. and register 0x00 doesn't seems to be colliding with MCP9808 and LIS3DH chips.
|
||||||
|
|||||||
+630
-592
File diff suppressed because it is too large
Load Diff
@@ -81,6 +81,8 @@ class Screen
|
|||||||
#include <SSD1306Wire.h>
|
#include <SSD1306Wire.h>
|
||||||
#elif defined(USE_ST7789)
|
#elif defined(USE_ST7789)
|
||||||
#include <ST7789Spi.h>
|
#include <ST7789Spi.h>
|
||||||
|
#elif defined(USE_SPISSD1306)
|
||||||
|
#include <SSD1306Spi.h>
|
||||||
#else
|
#else
|
||||||
// the SH1106/SSD1306 variant is auto-detected
|
// the SH1106/SSD1306 variant is auto-detected
|
||||||
#include <AutoOLEDWire.h>
|
#include <AutoOLEDWire.h>
|
||||||
|
|||||||
@@ -79,6 +79,10 @@
|
|||||||
#define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19
|
#define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19
|
||||||
#define FONT_MEDIUM FONT_LARGE_LOCAL // Height: 28
|
#define FONT_MEDIUM FONT_LARGE_LOCAL // Height: 28
|
||||||
#define FONT_LARGE FONT_LARGE_LOCAL // Height: 28
|
#define FONT_LARGE FONT_LARGE_LOCAL // Height: 28
|
||||||
|
#elif defined(M5STACK_UNITC6L)
|
||||||
|
#define FONT_SMALL FONT_SMALL_LOCAL // Height: 13
|
||||||
|
#define FONT_MEDIUM FONT_SMALL_LOCAL // Height: 13
|
||||||
|
#define FONT_LARGE FONT_SMALL_LOCAL // Height: 13
|
||||||
#else
|
#else
|
||||||
#define FONT_SMALL FONT_SMALL_LOCAL // Height: 13
|
#define FONT_SMALL FONT_SMALL_LOCAL // Height: 13
|
||||||
#define FONT_MEDIUM FONT_MEDIUM_LOCAL // Height: 19
|
#define FONT_MEDIUM FONT_MEDIUM_LOCAL // Height: 19
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
|||||||
|
|
||||||
int batteryX = 1;
|
int batteryX = 1;
|
||||||
int batteryY = HEADER_OFFSET_Y + 1;
|
int batteryY = HEADER_OFFSET_Y + 1;
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
// === Battery Icons ===
|
// === Battery Icons ===
|
||||||
if (usbPowered && !isCharging) { // This is a basic check to determine USB Powered is flagged but not charging
|
if (usbPowered && !isCharging) { // This is a basic check to determine USB Powered is flagged but not charging
|
||||||
batteryX += 1;
|
batteryX += 1;
|
||||||
@@ -368,7 +368,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
display->setColor(WHITE); // Reset for other UI
|
display->setColor(WHITE); // Reset for other UI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
#if HAS_SCREEN
|
#if HAS_SCREEN
|
||||||
#include "ClockRenderer.h"
|
#include "ClockRenderer.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
|
#include "UIRenderer.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "gps/GeoCoord.h"
|
#include "gps/GeoCoord.h"
|
||||||
#include "gps/RTC.h"
|
#include "gps/RTC.h"
|
||||||
#include "graphics/ScreenFonts.h"
|
#include "graphics/ScreenFonts.h"
|
||||||
#include "graphics/SharedUIDisplay.h"
|
#include "graphics/SharedUIDisplay.h"
|
||||||
|
#include "graphics/draw/UIRenderer.h"
|
||||||
#include "graphics/emotes.h"
|
#include "graphics/emotes.h"
|
||||||
#include "graphics/images.h"
|
#include "graphics/images.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
@@ -190,6 +192,7 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
const char *titleStr = "";
|
const char *titleStr = "";
|
||||||
// === Header ===
|
// === Header ===
|
||||||
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
||||||
|
int line = 0;
|
||||||
|
|
||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
||||||
@@ -314,6 +317,7 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
const char *titleStr = "";
|
const char *titleStr = "";
|
||||||
// === Header ===
|
// === Header ===
|
||||||
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
||||||
|
int line = 0;
|
||||||
|
|
||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
||||||
|
|||||||
@@ -277,12 +277,13 @@ void drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
std::string uptime = UIRenderer::drawTimeDelta(days, hours, minutes, seconds);
|
std::string uptime = UIRenderer::drawTimeDelta(days, hours, minutes, seconds);
|
||||||
|
|
||||||
// Line 1 (Still)
|
// Line 1 (Still)
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
|
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
|
||||||
if (config.display.heading_bold)
|
if (config.display.heading_bold)
|
||||||
display->drawString(x - 1 + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
|
display->drawString(x - 1 + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
|
||||||
|
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
|
#endif
|
||||||
// Setup string to assemble analogClock string
|
// Setup string to assemble analogClock string
|
||||||
std::string analogClock = "";
|
std::string analogClock = "";
|
||||||
|
|
||||||
@@ -329,8 +330,7 @@ void drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
#if HAS_GPS
|
#if HAS_GPS
|
||||||
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||||
// Line 3
|
// Line 3
|
||||||
if (config.display.gps_format !=
|
if (uiconfig.gps_format != meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude
|
||||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude
|
|
||||||
UIRenderer::drawGpsAltitude(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
|
UIRenderer::drawGpsAltitude(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
|
||||||
|
|
||||||
// Line 4
|
// Line 4
|
||||||
@@ -386,7 +386,11 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
char shortnameble[35];
|
char shortnameble[35];
|
||||||
getMacAddr(dmac);
|
getMacAddr(dmac);
|
||||||
snprintf(screen->ourId, sizeof(screen->ourId), "%02x%02x", dmac[4], dmac[5]);
|
snprintf(screen->ourId, sizeof(screen->ourId), "%02x%02x", dmac[4], dmac[5]);
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
snprintf(shortnameble, sizeof(shortnameble), "%s", screen->ourId);
|
||||||
|
#else
|
||||||
snprintf(shortnameble, sizeof(shortnameble), "BLE: %s", screen->ourId);
|
snprintf(shortnameble, sizeof(shortnameble), "BLE: %s", screen->ourId);
|
||||||
|
#endif
|
||||||
int textWidth = display->getStringWidth(shortnameble);
|
int textWidth = display->getStringWidth(shortnameble);
|
||||||
int nameX = (SCREEN_WIDTH - textWidth);
|
int nameX = (SCREEN_WIDTH - textWidth);
|
||||||
display->drawString(nameX, getTextPositions(display)[line++], shortnameble);
|
display->drawString(nameX, getTextPositions(display)[line++], shortnameble);
|
||||||
@@ -405,7 +409,11 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
char regionradiopreset[25];
|
char regionradiopreset[25];
|
||||||
const char *region = myRegion ? myRegion->name : NULL;
|
const char *region = myRegion ? myRegion->name : NULL;
|
||||||
if (region != nullptr) {
|
if (region != nullptr) {
|
||||||
snprintf(regionradiopreset, sizeof(regionradiopreset), "Reg: %s/%s", region, mode);
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
snprintf(regionradiopreset, sizeof(regionradiopreset), "%s", region);
|
||||||
|
#else
|
||||||
|
snprintf(regionradiopreset, sizeof(regionradiopreset), "%s/%s", region, mode);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
textWidth = display->getStringWidth(regionradiopreset);
|
textWidth = display->getStringWidth(regionradiopreset);
|
||||||
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
@@ -417,9 +425,17 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
float freq = RadioLibInterface::instance->getFreq();
|
float freq = RadioLibInterface::instance->getFreq();
|
||||||
snprintf(freqStr, sizeof(freqStr), "%.3f", freq);
|
snprintf(freqStr, sizeof(freqStr), "%.3f", freq);
|
||||||
if (config.lora.channel_num == 0) {
|
if (config.lora.channel_num == 0) {
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
snprintf(frequencyslot, sizeof(frequencyslot), "%sMHz", freqStr);
|
||||||
|
#else
|
||||||
snprintf(frequencyslot, sizeof(frequencyslot), "Freq: %sMHz", freqStr);
|
snprintf(frequencyslot, sizeof(frequencyslot), "Freq: %sMHz", freqStr);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
snprintf(frequencyslot, sizeof(frequencyslot), "%sMHz (%d)", freqStr, config.lora.channel_num);
|
||||||
|
#else
|
||||||
snprintf(frequencyslot, sizeof(frequencyslot), "Freq/Ch: %sMHz (%d)", freqStr, config.lora.channel_num);
|
snprintf(frequencyslot, sizeof(frequencyslot), "Freq/Ch: %sMHz (%d)", freqStr, config.lora.channel_num);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
size_t len = strlen(frequencyslot);
|
size_t len = strlen(frequencyslot);
|
||||||
if (len >= 4 && strcmp(frequencyslot + len - 4, " (0)") == 0) {
|
if (len >= 4 && strcmp(frequencyslot + len - 4, " (0)") == 0) {
|
||||||
@@ -429,6 +445,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
display->drawString(nameX, getTextPositions(display)[line++], frequencyslot);
|
display->drawString(nameX, getTextPositions(display)[line++], frequencyslot);
|
||||||
|
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
// === Fifth Row: Channel Utilization ===
|
// === Fifth Row: Channel Utilization ===
|
||||||
const char *chUtil = "ChUtil:";
|
const char *chUtil = "ChUtil:";
|
||||||
char chUtilPercentage[10];
|
char chUtilPercentage[10];
|
||||||
@@ -485,6 +502,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
|
|
||||||
display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, getTextPositions(display)[line++],
|
display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, getTextPositions(display)[line++],
|
||||||
chUtilPercentage);
|
chUtilPercentage);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ****************************
|
// ****************************
|
||||||
@@ -510,8 +528,11 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
#ifdef USE_EINK
|
#ifdef USE_EINK
|
||||||
barsOffset -= 12;
|
barsOffset -= 12;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
const int barX = x + 45 + barsOffset;
|
||||||
|
#else
|
||||||
const int barX = x + 40 + barsOffset;
|
const int barX = x + 40 + barsOffset;
|
||||||
|
#endif
|
||||||
auto drawUsageRow = [&](const char *label, uint32_t used, uint32_t total, bool isHeap = false) {
|
auto drawUsageRow = [&](const char *label, uint32_t used, uint32_t total, bool isHeap = false) {
|
||||||
if (total == 0)
|
if (total == 0)
|
||||||
return;
|
return;
|
||||||
@@ -536,7 +557,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
// Label
|
// Label
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
display->drawString(labelX, getTextPositions(display)[line], label);
|
display->drawString(labelX, getTextPositions(display)[line], label);
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
// Bar
|
// Bar
|
||||||
int barY = getTextPositions(display)[line] + (FONT_HEIGHT_SMALL - barHeight) / 2;
|
int barY = getTextPositions(display)[line] + (FONT_HEIGHT_SMALL - barHeight) / 2;
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
@@ -544,7 +565,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
|
|
||||||
display->fillRect(barX, barY, fillWidth, barHeight);
|
display->fillRect(barX, barY, fillWidth, barHeight);
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
|
#endif
|
||||||
// Value string
|
// Value string
|
||||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
display->drawString(SCREEN_WIDTH - 2, getTextPositions(display)[line], combinedStr);
|
display->drawString(SCREEN_WIDTH - 2, getTextPositions(display)[line], combinedStr);
|
||||||
@@ -597,10 +618,16 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
line += 1;
|
line += 1;
|
||||||
}
|
}
|
||||||
line += 1;
|
line += 1;
|
||||||
|
|
||||||
char appversionstr[35];
|
char appversionstr[35];
|
||||||
snprintf(appversionstr, sizeof(appversionstr), "Ver: %s", optstr(APP_VERSION));
|
snprintf(appversionstr, sizeof(appversionstr), "Ver: %s", optstr(APP_VERSION));
|
||||||
char appversionstr_formatted[40];
|
char appversionstr_formatted[40];
|
||||||
char *lastDot = strrchr(appversionstr, '.');
|
char *lastDot = strrchr(appversionstr, '.');
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
if (lastDot != nullptr) {
|
||||||
|
*lastDot = '\0'; // truncate string
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (lastDot) {
|
if (lastDot) {
|
||||||
size_t prefixLen = lastDot - appversionstr;
|
size_t prefixLen = lastDot - appversionstr;
|
||||||
strncpy(appversionstr_formatted, appversionstr, prefixLen);
|
strncpy(appversionstr_formatted, appversionstr, prefixLen);
|
||||||
@@ -611,10 +638,12 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
strncpy(appversionstr, appversionstr_formatted, sizeof(appversionstr) - 1);
|
strncpy(appversionstr, appversionstr_formatted, sizeof(appversionstr) - 1);
|
||||||
appversionstr[sizeof(appversionstr) - 1] = '\0';
|
appversionstr[sizeof(appversionstr) - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
int textWidth = display->getStringWidth(appversionstr);
|
int textWidth = display->getStringWidth(appversionstr);
|
||||||
int nameX = (SCREEN_WIDTH - textWidth) / 2;
|
int nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
display->drawString(nameX, getTextPositions(display)[line], appversionstr);
|
|
||||||
|
|
||||||
|
display->drawString(nameX, getTextPositions(display)[line], appversionstr);
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
if (SCREEN_HEIGHT > 64 || (SCREEN_HEIGHT <= 64 && line < 4)) { // Only show uptime if the screen can show it
|
if (SCREEN_HEIGHT > 64 || (SCREEN_HEIGHT <= 64 && line < 4)) { // Only show uptime if the screen can show it
|
||||||
line += 1;
|
line += 1;
|
||||||
char uptimeStr[32] = "";
|
char uptimeStr[32] = "";
|
||||||
@@ -633,6 +662,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
display->drawString(nameX, getTextPositions(display)[line], uptimeStr);
|
display->drawString(nameX, getTextPositions(display)[line], uptimeStr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ****************************
|
// ****************************
|
||||||
@@ -661,6 +691,7 @@ void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int1
|
|||||||
textX = (display->getWidth() / 2) - textX_offset - (display->getStringWidth("World!") / 2);
|
textX = (display->getWidth() / 2) - textX_offset - (display->getStringWidth("World!") / 2);
|
||||||
display->drawString(textX, getTextPositions(display)[line++], "World!");
|
display->drawString(textX, getTextPositions(display)[line++], "World!");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace DebugRenderer
|
} // namespace DebugRenderer
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
#endif
|
#endif
|
||||||
@@ -33,7 +33,6 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
|
|
||||||
// System screen display
|
// System screen display
|
||||||
void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||||
|
|
||||||
// Chirpy screen display
|
// Chirpy screen display
|
||||||
void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||||
} // namespace DebugRenderer
|
} // namespace DebugRenderer
|
||||||
|
|||||||
@@ -102,7 +102,11 @@ void menuHandler::LoraRegionPicker(uint32_t duration)
|
|||||||
"NP_865",
|
"NP_865",
|
||||||
"BR_902"};
|
"BR_902"};
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "LoRa Region";
|
||||||
|
#else
|
||||||
bannerOptions.message = "Set the LoRa region";
|
bannerOptions.message = "Set the LoRa region";
|
||||||
|
#endif
|
||||||
bannerOptions.durationMs = duration;
|
bannerOptions.durationMs = duration;
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 27;
|
bannerOptions.optionsCount = 27;
|
||||||
@@ -317,7 +321,11 @@ void menuHandler::TZPicker()
|
|||||||
|
|
||||||
void menuHandler::clockMenu()
|
void menuHandler::clockMenu()
|
||||||
{
|
{
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
static const char *optionsArray[] = {"Back", "Time Format", "Timezone"};
|
||||||
|
#else
|
||||||
static const char *optionsArray[] = {"Back", "Clock Face", "Time Format", "Timezone"};
|
static const char *optionsArray[] = {"Back", "Clock Face", "Time Format", "Timezone"};
|
||||||
|
#endif
|
||||||
enum optionsNumbers { Back = 0, Clock = 1, Time = 2, Timezone = 3 };
|
enum optionsNumbers { Back = 0, Clock = 1, Time = 2, Timezone = 3 };
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
bannerOptions.message = "Clock Action";
|
bannerOptions.message = "Clock Action";
|
||||||
@@ -341,8 +349,11 @@ void menuHandler::clockMenu()
|
|||||||
void menuHandler::messageResponseMenu()
|
void menuHandler::messageResponseMenu()
|
||||||
{
|
{
|
||||||
enum optionsNumbers { Back = 0, Dismiss = 1, Preset = 2, Freetext = 3, Aloud = 4, enumEnd = 5 };
|
enum optionsNumbers { Back = 0, Dismiss = 1, Preset = 2, Freetext = 3, Aloud = 4, enumEnd = 5 };
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
static const char *optionsArray[enumEnd] = {"Back", "Dismiss", "Reply Preset"};
|
||||||
|
#else
|
||||||
static const char *optionsArray[enumEnd] = {"Back", "Dismiss", "Reply via Preset"};
|
static const char *optionsArray[enumEnd] = {"Back", "Dismiss", "Reply via Preset"};
|
||||||
|
#endif
|
||||||
static int optionsEnumArray[enumEnd] = {Back, Dismiss, Preset};
|
static int optionsEnumArray[enumEnd] = {Back, Dismiss, Preset};
|
||||||
int options = 3;
|
int options = 3;
|
||||||
|
|
||||||
@@ -356,7 +367,11 @@ void menuHandler::messageResponseMenu()
|
|||||||
optionsEnumArray[options++] = Aloud;
|
optionsEnumArray[options++] = Aloud;
|
||||||
#endif
|
#endif
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "Message";
|
||||||
|
#else
|
||||||
bannerOptions.message = "Message Action";
|
bannerOptions.message = "Message Action";
|
||||||
|
#endif
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
||||||
bannerOptions.optionsCount = options;
|
bannerOptions.optionsCount = options;
|
||||||
@@ -409,7 +424,11 @@ void menuHandler::homeBaseMenu()
|
|||||||
optionsArray[options] = "Send Node Info";
|
optionsArray[options] = "Send Node Info";
|
||||||
}
|
}
|
||||||
optionsEnumArray[options++] = Position;
|
optionsEnumArray[options++] = Position;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
optionsArray[options] = "New Preset";
|
||||||
|
#else
|
||||||
optionsArray[options] = "New Preset Msg";
|
optionsArray[options] = "New Preset Msg";
|
||||||
|
#endif
|
||||||
optionsEnumArray[options++] = Preset;
|
optionsEnumArray[options++] = Preset;
|
||||||
if (kb_found) {
|
if (kb_found) {
|
||||||
optionsArray[options] = "New Freetext Msg";
|
optionsArray[options] = "New Freetext Msg";
|
||||||
@@ -417,7 +436,11 @@ void menuHandler::homeBaseMenu()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "Home";
|
||||||
|
#else
|
||||||
bannerOptions.message = "Home Action";
|
bannerOptions.message = "Home Action";
|
||||||
|
#endif
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
||||||
bannerOptions.optionsCount = options;
|
bannerOptions.optionsCount = options;
|
||||||
@@ -456,6 +479,11 @@ void menuHandler::homeBaseMenu()
|
|||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menuHandler::textMessageMenu()
|
||||||
|
{
|
||||||
|
cannedMessageModule->LaunchWithDestination(NODENUM_BROADCAST);
|
||||||
|
}
|
||||||
|
|
||||||
void menuHandler::textMessageBaseMenu()
|
void menuHandler::textMessageBaseMenu()
|
||||||
{
|
{
|
||||||
enum optionsNumbers { Back, Preset, Freetext, enumEnd };
|
enum optionsNumbers { Back, Preset, Freetext, enumEnd };
|
||||||
@@ -502,11 +530,17 @@ void menuHandler::systemBaseMenu()
|
|||||||
|
|
||||||
optionsArray[options] = "Frame Visiblity Toggle";
|
optionsArray[options] = "Frame Visiblity Toggle";
|
||||||
optionsEnumArray[options++] = FrameToggles;
|
optionsEnumArray[options++] = FrameToggles;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
optionsArray[options] = "Bluetooth";
|
||||||
|
#else
|
||||||
optionsArray[options] = "Bluetooth Toggle";
|
optionsArray[options] = "Bluetooth Toggle";
|
||||||
|
#endif
|
||||||
optionsEnumArray[options++] = Bluetooth;
|
optionsEnumArray[options++] = Bluetooth;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
optionsArray[options] = "Power";
|
||||||
|
#else
|
||||||
optionsArray[options] = "Reboot/Shutdown";
|
optionsArray[options] = "Reboot/Shutdown";
|
||||||
|
#endif
|
||||||
optionsEnumArray[options++] = PowerMenu;
|
optionsEnumArray[options++] = PowerMenu;
|
||||||
|
|
||||||
if (test_enabled) {
|
if (test_enabled) {
|
||||||
@@ -515,7 +549,11 @@ void menuHandler::systemBaseMenu()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "System";
|
||||||
|
#else
|
||||||
bannerOptions.message = "System Action";
|
bannerOptions.message = "System Action";
|
||||||
|
#endif
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = options;
|
bannerOptions.optionsCount = options;
|
||||||
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
||||||
@@ -551,7 +589,11 @@ void menuHandler::systemBaseMenu()
|
|||||||
void menuHandler::favoriteBaseMenu()
|
void menuHandler::favoriteBaseMenu()
|
||||||
{
|
{
|
||||||
enum optionsNumbers { Back, Preset, Freetext, Remove, TraceRoute, enumEnd };
|
enum optionsNumbers { Back, Preset, Freetext, Remove, TraceRoute, enumEnd };
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
static const char *optionsArray[enumEnd] = {"Back", "New Preset"};
|
||||||
|
#else
|
||||||
static const char *optionsArray[enumEnd] = {"Back", "New Preset Msg"};
|
static const char *optionsArray[enumEnd] = {"Back", "New Preset Msg"};
|
||||||
|
#endif
|
||||||
static int optionsEnumArray[enumEnd] = {Back, Preset};
|
static int optionsEnumArray[enumEnd] = {Back, Preset};
|
||||||
int options = 2;
|
int options = 2;
|
||||||
|
|
||||||
@@ -559,13 +601,19 @@ void menuHandler::favoriteBaseMenu()
|
|||||||
optionsArray[options] = "New Freetext Msg";
|
optionsArray[options] = "New Freetext Msg";
|
||||||
optionsEnumArray[options++] = Freetext;
|
optionsEnumArray[options++] = Freetext;
|
||||||
}
|
}
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
optionsArray[options] = "Trace Route";
|
optionsArray[options] = "Trace Route";
|
||||||
optionsEnumArray[options++] = TraceRoute;
|
optionsEnumArray[options++] = TraceRoute;
|
||||||
|
#endif
|
||||||
optionsArray[options] = "Remove Favorite";
|
optionsArray[options] = "Remove Favorite";
|
||||||
optionsEnumArray[options++] = Remove;
|
optionsEnumArray[options++] = Remove;
|
||||||
|
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "Favorites";
|
||||||
|
#else
|
||||||
bannerOptions.message = "Favorites Action";
|
bannerOptions.message = "Favorites Action";
|
||||||
|
#endif
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
||||||
bannerOptions.optionsCount = options;
|
bannerOptions.optionsCount = options;
|
||||||
@@ -624,11 +672,19 @@ void menuHandler::positionBaseMenu()
|
|||||||
void menuHandler::nodeListMenu()
|
void menuHandler::nodeListMenu()
|
||||||
{
|
{
|
||||||
enum optionsNumbers { Back, Favorite, TraceRoute, Verify, Reset, enumEnd };
|
enum optionsNumbers { Back, Favorite, TraceRoute, Verify, Reset, enumEnd };
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
static const char *optionsArray[] = {"Back", "Add Favorite", "Reset Node"};
|
||||||
|
#else
|
||||||
static const char *optionsArray[] = {"Back", "Add Favorite", "Trace Route", "Key Verification", "Reset NodeDB"};
|
static const char *optionsArray[] = {"Back", "Add Favorite", "Trace Route", "Key Verification", "Reset NodeDB"};
|
||||||
|
#endif
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
bannerOptions.message = "Node Action";
|
bannerOptions.message = "Node Action";
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.optionsCount = 3;
|
||||||
|
#else
|
||||||
bannerOptions.optionsCount = 5;
|
bannerOptions.optionsCount = 5;
|
||||||
|
#endif
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
if (selected == Favorite) {
|
if (selected == Favorite) {
|
||||||
menuQueue = add_favorite;
|
menuQueue = add_favorite;
|
||||||
@@ -738,36 +794,40 @@ void menuHandler::GPSFormatMenu()
|
|||||||
isHighResolution ? "Universal Transverse Mercator" : "UTM",
|
isHighResolution ? "Universal Transverse Mercator" : "UTM",
|
||||||
isHighResolution ? "Military Grid Reference System" : "MGRS",
|
isHighResolution ? "Military Grid Reference System" : "MGRS",
|
||||||
isHighResolution ? "Open Location Code" : "OLC",
|
isHighResolution ? "Open Location Code" : "OLC",
|
||||||
isHighResolution ? "Ordnance Survey Grid Ref" : "OSGR"};
|
isHighResolution ? "Ordnance Survey Grid Ref" : "OSGR",
|
||||||
|
isHighResolution ? "Maidenhead Locator" : "MLS"};
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
bannerOptions.message = "GPS Format";
|
bannerOptions.message = "GPS Format";
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 7;
|
bannerOptions.optionsCount = 8;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
if (selected == 1) {
|
if (selected == 1) {
|
||||||
config.display.gps_format = meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC;
|
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC;
|
||||||
service->reloadConfig(SEGMENT_CONFIG);
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
} else if (selected == 2) {
|
} else if (selected == 2) {
|
||||||
config.display.gps_format = meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS;
|
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS;
|
||||||
service->reloadConfig(SEGMENT_CONFIG);
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
} else if (selected == 3) {
|
} else if (selected == 3) {
|
||||||
config.display.gps_format = meshtastic_Config_DisplayConfig_GpsCoordinateFormat_UTM;
|
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_UTM;
|
||||||
service->reloadConfig(SEGMENT_CONFIG);
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
} else if (selected == 4) {
|
} else if (selected == 4) {
|
||||||
config.display.gps_format = meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MGRS;
|
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_MGRS;
|
||||||
service->reloadConfig(SEGMENT_CONFIG);
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
} else if (selected == 5) {
|
} else if (selected == 5) {
|
||||||
config.display.gps_format = meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OLC;
|
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC;
|
||||||
service->reloadConfig(SEGMENT_CONFIG);
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
} else if (selected == 6) {
|
} else if (selected == 6) {
|
||||||
config.display.gps_format = meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR;
|
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_OSGR;
|
||||||
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
|
} else if (selected == 7) {
|
||||||
|
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS;
|
||||||
service->reloadConfig(SEGMENT_CONFIG);
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
} else {
|
} else {
|
||||||
menuQueue = position_base_menu;
|
menuQueue = position_base_menu;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
bannerOptions.InitialSelected = config.display.gps_format + 1;
|
bannerOptions.InitialSelected = uiconfig.gps_format + 1;
|
||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -776,7 +836,11 @@ void menuHandler::BluetoothToggleMenu()
|
|||||||
{
|
{
|
||||||
static const char *optionsArray[] = {"Back", "Enabled", "Disabled"};
|
static const char *optionsArray[] = {"Back", "Enabled", "Disabled"};
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "Bluetooth";
|
||||||
|
#else
|
||||||
bannerOptions.message = "Toggle Bluetooth";
|
bannerOptions.message = "Toggle Bluetooth";
|
||||||
|
#endif
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 3;
|
bannerOptions.optionsCount = 3;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
@@ -968,7 +1032,11 @@ void menuHandler::rebootMenu()
|
|||||||
{
|
{
|
||||||
static const char *optionsArray[] = {"Back", "Confirm"};
|
static const char *optionsArray[] = {"Back", "Confirm"};
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "Reboot";
|
||||||
|
#else
|
||||||
bannerOptions.message = "Reboot Device?";
|
bannerOptions.message = "Reboot Device?";
|
||||||
|
#endif
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 2;
|
bannerOptions.optionsCount = 2;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
@@ -988,7 +1056,11 @@ void menuHandler::shutdownMenu()
|
|||||||
{
|
{
|
||||||
static const char *optionsArray[] = {"Back", "Confirm"};
|
static const char *optionsArray[] = {"Back", "Confirm"};
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "Shutdown";
|
||||||
|
#else
|
||||||
bannerOptions.message = "Shutdown Device?";
|
bannerOptions.message = "Shutdown Device?";
|
||||||
|
#endif
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 2;
|
bannerOptions.optionsCount = 2;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
@@ -1005,7 +1077,12 @@ void menuHandler::shutdownMenu()
|
|||||||
|
|
||||||
void menuHandler::addFavoriteMenu()
|
void menuHandler::addFavoriteMenu()
|
||||||
{
|
{
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
screen->showNodePicker("Node Favorite", 30000, [](uint32_t nodenum) -> void {
|
||||||
|
#else
|
||||||
screen->showNodePicker("Node To Favorite", 30000, [](uint32_t nodenum) -> void {
|
screen->showNodePicker("Node To Favorite", 30000, [](uint32_t nodenum) -> void {
|
||||||
|
|
||||||
|
#endif
|
||||||
LOG_WARN("Nodenum: %u", nodenum);
|
LOG_WARN("Nodenum: %u", nodenum);
|
||||||
nodeDB->set_favorite(true, nodenum);
|
nodeDB->set_favorite(true, nodenum);
|
||||||
screen->setFrames(graphics::Screen::FOCUS_PRESERVE);
|
screen->setFrames(graphics::Screen::FOCUS_PRESERVE);
|
||||||
@@ -1218,7 +1295,11 @@ void menuHandler::powerMenu()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
bannerOptions.message = "Power";
|
||||||
|
#else
|
||||||
bannerOptions.message = "Reboot / Shutdown";
|
bannerOptions.message = "Reboot / Shutdown";
|
||||||
|
#endif
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = options;
|
bannerOptions.optionsCount = options;
|
||||||
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class menuHandler
|
|||||||
static void screenOptionsMenu();
|
static void screenOptionsMenu();
|
||||||
static void powerMenu();
|
static void powerMenu();
|
||||||
static void FrameToggles_menu();
|
static void FrameToggles_menu();
|
||||||
|
static void textMessageMenu();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void saveUIConfig();
|
static void saveUIConfig();
|
||||||
|
|||||||
@@ -181,12 +181,19 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
display->clear();
|
display->clear();
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
const int fixedTopHeight = 24;
|
||||||
|
const int windowX = 0;
|
||||||
|
const int windowY = fixedTopHeight;
|
||||||
|
const int windowWidth = 64;
|
||||||
|
const int windowHeight = SCREEN_HEIGHT - fixedTopHeight;
|
||||||
|
#else
|
||||||
const int navHeight = FONT_HEIGHT_SMALL;
|
const int navHeight = FONT_HEIGHT_SMALL;
|
||||||
const int scrollBottom = SCREEN_HEIGHT - navHeight;
|
const int scrollBottom = SCREEN_HEIGHT - navHeight;
|
||||||
const int usableHeight = scrollBottom;
|
const int usableHeight = scrollBottom;
|
||||||
const int textWidth = SCREEN_WIDTH;
|
const int textWidth = SCREEN_WIDTH;
|
||||||
|
|
||||||
|
#endif
|
||||||
bool isInverted = (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_INVERTED);
|
bool isInverted = (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_INVERTED);
|
||||||
bool isBold = config.display.heading_bold;
|
bool isBold = config.display.heading_bold;
|
||||||
|
|
||||||
@@ -201,7 +208,11 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
graphics::drawCommonHeader(display, x, y, titleStr);
|
graphics::drawCommonHeader(display, x, y, titleStr);
|
||||||
const char *messageString = "No messages";
|
const char *messageString = "No messages";
|
||||||
int center_text = (SCREEN_WIDTH / 2) - (display->getStringWidth(messageString) / 2);
|
int center_text = (SCREEN_WIDTH / 2) - (display->getStringWidth(messageString) / 2);
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
display->drawString(center_text, windowY + (windowHeight / 2) - (FONT_HEIGHT_SMALL / 2) - 5, messageString);
|
||||||
|
#else
|
||||||
display->drawString(center_text, getTextPositions(display)[2], messageString);
|
display->drawString(center_text, getTextPositions(display)[2], messageString);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,6 +220,10 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(getFrom(&mp));
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(getFrom(&mp));
|
||||||
char headerStr[80];
|
char headerStr[80];
|
||||||
const char *sender = "???";
|
const char *sender = "???";
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
if (node && node->has_user)
|
||||||
|
sender = node->user.short_name;
|
||||||
|
#else
|
||||||
if (node && node->has_user) {
|
if (node && node->has_user) {
|
||||||
if (SCREEN_WIDTH >= 200 && strlen(node->user.long_name) > 0) {
|
if (SCREEN_WIDTH >= 200 && strlen(node->user.long_name) > 0) {
|
||||||
sender = node->user.long_name;
|
sender = node->user.long_name;
|
||||||
@@ -216,6 +231,7 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
sender = node->user.short_name;
|
sender = node->user.short_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
uint32_t seconds = sinceReceived(&mp), minutes = seconds / 60, hours = minutes / 60, days = hours / 24;
|
uint32_t seconds = sinceReceived(&mp), minutes = seconds / 60, hours = minutes / 60, days = hours / 24;
|
||||||
uint8_t timestampHours, timestampMinutes;
|
uint8_t timestampHours, timestampMinutes;
|
||||||
int32_t daysAgo;
|
int32_t daysAgo;
|
||||||
@@ -235,10 +251,61 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
sender);
|
sender);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
snprintf(headerStr, sizeof(headerStr), "%s from %s", UIRenderer::drawTimeDelta(days, hours, minutes, seconds).c_str(),
|
||||||
|
sender);
|
||||||
|
#else
|
||||||
snprintf(headerStr, sizeof(headerStr), "%s ago from %s", UIRenderer::drawTimeDelta(days, hours, minutes, seconds).c_str(),
|
snprintf(headerStr, sizeof(headerStr), "%s ago from %s", UIRenderer::drawTimeDelta(days, hours, minutes, seconds).c_str(),
|
||||||
sender);
|
sender);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
graphics::drawCommonHeader(display, x, y, titleStr);
|
||||||
|
int headerY = getTextPositions(display)[1];
|
||||||
|
display->drawString(x, headerY, headerStr);
|
||||||
|
for (int separatorX = 0; separatorX < SCREEN_WIDTH; separatorX += 2) {
|
||||||
|
display->setPixel(separatorX, fixedTopHeight - 1);
|
||||||
|
}
|
||||||
|
cachedLines.clear();
|
||||||
|
std::string fullMsg(messageBuf);
|
||||||
|
std::string currentLine;
|
||||||
|
for (size_t i = 0; i < fullMsg.size();) {
|
||||||
|
unsigned char c = fullMsg[i];
|
||||||
|
size_t charLen = 1;
|
||||||
|
if ((c & 0xE0) == 0xC0)
|
||||||
|
charLen = 2;
|
||||||
|
else if ((c & 0xF0) == 0xE0)
|
||||||
|
charLen = 3;
|
||||||
|
else if ((c & 0xF8) == 0xF0)
|
||||||
|
charLen = 4;
|
||||||
|
std::string nextChar = fullMsg.substr(i, charLen);
|
||||||
|
std::string testLine = currentLine + nextChar;
|
||||||
|
if (display->getStringWidth(testLine.c_str()) > windowWidth) {
|
||||||
|
cachedLines.push_back(currentLine);
|
||||||
|
currentLine = nextChar;
|
||||||
|
} else {
|
||||||
|
currentLine = testLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += charLen;
|
||||||
|
}
|
||||||
|
if (!currentLine.empty())
|
||||||
|
cachedLines.push_back(currentLine);
|
||||||
|
cachedHeights = calculateLineHeights(cachedLines, emotes);
|
||||||
|
int yOffset = windowY;
|
||||||
|
int linesDrawn = 0;
|
||||||
|
for (size_t i = 0; i < cachedLines.size(); ++i) {
|
||||||
|
if (linesDrawn >= 2)
|
||||||
|
break;
|
||||||
|
int lineHeight = cachedHeights[i];
|
||||||
|
if (yOffset + lineHeight > windowY + windowHeight)
|
||||||
|
break;
|
||||||
|
drawStringWithEmotes(display, windowX, yOffset, cachedLines[i], emotes, numEmotes);
|
||||||
|
yOffset += lineHeight;
|
||||||
|
linesDrawn++;
|
||||||
|
}
|
||||||
|
screen->forceDisplay();
|
||||||
|
#else
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
#ifndef EXCLUDE_EMOJI
|
#ifndef EXCLUDE_EMOJI
|
||||||
// === Bounce animation setup ===
|
// === Bounce animation setup ===
|
||||||
@@ -355,6 +422,7 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
|
|
||||||
// Draw header at the end to sort out overlapping elements
|
// Draw header at the end to sort out overlapping elements
|
||||||
graphics::drawCommonHeader(display, x, y, titleStr);
|
graphics::drawCommonHeader(display, x, y, titleStr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> generateLines(OLEDDisplay *display, const char *headerStr, const char *messageBuf, int textWidth)
|
std::vector<std::string> generateLines(OLEDDisplay *display, const char *headerStr, const char *messageBuf, int textWidth)
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ extern bool haveGlyphs(const char *str);
|
|||||||
// Global screen instance
|
// Global screen instance
|
||||||
extern graphics::Screen *screen;
|
extern graphics::Screen *screen;
|
||||||
|
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
static uint32_t lastSwitchTime = 0;
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
namespace NodeListRenderer
|
namespace NodeListRenderer
|
||||||
@@ -393,9 +397,11 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
{
|
{
|
||||||
const int COMMON_HEADER_HEIGHT = FONT_HEIGHT_SMALL - 1;
|
const int COMMON_HEADER_HEIGHT = FONT_HEIGHT_SMALL - 1;
|
||||||
const int rowYOffset = FONT_HEIGHT_SMALL - 3;
|
const int rowYOffset = FONT_HEIGHT_SMALL - 3;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
int columnWidth = display->getWidth();
|
||||||
|
#else
|
||||||
int columnWidth = display->getWidth() / 2;
|
int columnWidth = display->getWidth() / 2;
|
||||||
|
#endif
|
||||||
display->clear();
|
display->clear();
|
||||||
|
|
||||||
// Draw the battery/time header
|
// Draw the battery/time header
|
||||||
@@ -408,8 +414,11 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
int totalRowsAvailable = (display->getHeight() - y) / rowYOffset;
|
int totalRowsAvailable = (display->getHeight() - y) / rowYOffset;
|
||||||
|
|
||||||
int visibleNodeRows = totalRowsAvailable;
|
int visibleNodeRows = totalRowsAvailable;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
int totalColumns = 1;
|
||||||
|
#else
|
||||||
int totalColumns = 2;
|
int totalColumns = 2;
|
||||||
|
#endif
|
||||||
int startIndex = scrollIndex * visibleNodeRows * totalColumns;
|
int startIndex = scrollIndex * visibleNodeRows * totalColumns;
|
||||||
if (nodeDB->getMeshNodeByIndex(startIndex)->num == nodeDB->getNodeNum()) {
|
if (nodeDB->getMeshNodeByIndex(startIndex)->num == nodeDB->getNodeNum()) {
|
||||||
startIndex++; // skip own node
|
startIndex++; // skip own node
|
||||||
@@ -445,12 +454,14 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
// Draw column separator
|
// Draw column separator
|
||||||
if (shownCount > 0) {
|
if (shownCount > 0) {
|
||||||
const int firstNodeY = y + 3;
|
const int firstNodeY = y + 3;
|
||||||
drawColumnSeparator(display, x, firstNodeY, lastNodeY);
|
drawColumnSeparator(display, x, firstNodeY, lastNodeY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
const int scrollStartY = y + 3;
|
const int scrollStartY = y + 3;
|
||||||
drawScrollbar(display, visibleNodeRows, totalEntries, scrollIndex, 2, scrollStartY);
|
drawScrollbar(display, visibleNodeRows, totalEntries, scrollIndex, 2, scrollStartY);
|
||||||
}
|
}
|
||||||
@@ -468,6 +479,13 @@ void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state,
|
|||||||
|
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
display->clear();
|
||||||
|
if (now - lastSwitchTime >= 3000) {
|
||||||
|
display->display();
|
||||||
|
lastSwitchTime = now;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// On very first call (on boot or state enter)
|
// On very first call (on boot or state enter)
|
||||||
if (lastRenderedMode == MODE_COUNT) {
|
if (lastRenderedMode == MODE_COUNT) {
|
||||||
currentMode = MODE_LAST_HEARD;
|
currentMode = MODE_LAST_HEARD;
|
||||||
@@ -522,6 +540,14 @@ void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state,
|
|||||||
double lat = DegD(ourNode->position.latitude_i);
|
double lat = DegD(ourNode->position.latitude_i);
|
||||||
double lon = DegD(ourNode->position.longitude_i);
|
double lon = DegD(ourNode->position.longitude_i);
|
||||||
|
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
display->clear();
|
||||||
|
uint32_t now = millis();
|
||||||
|
if (now - lastSwitchTime >= 2000) {
|
||||||
|
display->display();
|
||||||
|
lastSwitchTime = now;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (uiconfig.compass_mode != meshtastic_CompassMode_FREEZE_HEADING) {
|
if (uiconfig.compass_mode != meshtastic_CompassMode_FREEZE_HEADING) {
|
||||||
#if HAS_GPS
|
#if HAS_GPS
|
||||||
if (screen->hasHeading()) {
|
if (screen->hasHeading()) {
|
||||||
|
|||||||
@@ -250,9 +250,11 @@ void NotificationRenderer::drawNodePicker(OLEDDisplay *display, OLEDDisplayUiSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle input
|
// Handle input
|
||||||
if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_ALT_PRESS) {
|
if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_LEFT ||
|
||||||
|
inEvent.inputEvent == INPUT_BROKER_ALT_PRESS) {
|
||||||
curSelected--;
|
curSelected--;
|
||||||
} else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_USER_PRESS) {
|
} else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_RIGHT ||
|
||||||
|
inEvent.inputEvent == INPUT_BROKER_USER_PRESS) {
|
||||||
curSelected++;
|
curSelected++;
|
||||||
} else if (inEvent.inputEvent == INPUT_BROKER_SELECT) {
|
} else if (inEvent.inputEvent == INPUT_BROKER_SELECT) {
|
||||||
alertBannerCallback(selectedNodenum);
|
alertBannerCallback(selectedNodenum);
|
||||||
@@ -365,9 +367,11 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
|
|||||||
|
|
||||||
// Handle input
|
// Handle input
|
||||||
if (alertBannerOptions > 0) {
|
if (alertBannerOptions > 0) {
|
||||||
if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_ALT_PRESS) {
|
if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_LEFT ||
|
||||||
|
inEvent.inputEvent == INPUT_BROKER_ALT_PRESS) {
|
||||||
curSelected--;
|
curSelected--;
|
||||||
} else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_USER_PRESS) {
|
} else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_RIGHT ||
|
||||||
|
inEvent.inputEvent == INPUT_BROKER_USER_PRESS) {
|
||||||
curSelected++;
|
curSelected++;
|
||||||
} else if (inEvent.inputEvent == INPUT_BROKER_SELECT) {
|
} else if (inEvent.inputEvent == INPUT_BROKER_SELECT) {
|
||||||
if (optionsEnumPtr != nullptr) {
|
if (optionsEnumPtr != nullptr) {
|
||||||
@@ -491,6 +495,135 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
|||||||
// count lines
|
// count lines
|
||||||
|
|
||||||
uint16_t boxWidth = hPadding * 2 + maxWidth;
|
uint16_t boxWidth = hPadding * 2 + maxWidth;
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
if (needs_bell) {
|
||||||
|
if (isHighResolution && boxWidth <= 150)
|
||||||
|
boxWidth += 26;
|
||||||
|
if (!isHighResolution && boxWidth <= 100)
|
||||||
|
boxWidth += 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t screenHeight = display->height();
|
||||||
|
uint8_t effectiveLineHeight = FONT_HEIGHT_SMALL - 3;
|
||||||
|
uint8_t visibleTotalLines = std::min<uint8_t>(lineCount, (screenHeight - vPadding * 2) / effectiveLineHeight);
|
||||||
|
uint16_t contentHeight = visibleTotalLines * effectiveLineHeight;
|
||||||
|
uint16_t boxHeight = contentHeight + vPadding * 2;
|
||||||
|
if (visibleTotalLines == 1)
|
||||||
|
boxHeight += (isHighResolution ? 4 : 3);
|
||||||
|
|
||||||
|
int16_t boxLeft = (display->width() / 2) - (boxWidth / 2);
|
||||||
|
if (totalLines > visibleTotalLines)
|
||||||
|
boxWidth += (isHighResolution ? 4 : 2);
|
||||||
|
int16_t boxTop = (display->height() / 2) - (boxHeight / 2);
|
||||||
|
|
||||||
|
if (visibleTotalLines == 1) {
|
||||||
|
boxTop += 25;
|
||||||
|
}
|
||||||
|
if (alertBannerOptions < 3) {
|
||||||
|
int missingLines = 3 - alertBannerOptions;
|
||||||
|
int moveUp = missingLines * (effectiveLineHeight / 2);
|
||||||
|
boxTop -= moveUp;
|
||||||
|
if (boxTop < 0)
|
||||||
|
boxTop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Draw Box ===
|
||||||
|
display->setColor(BLACK);
|
||||||
|
display->fillRect(boxLeft, boxTop, boxWidth, boxHeight);
|
||||||
|
display->setColor(WHITE);
|
||||||
|
display->drawRect(boxLeft, boxTop, boxWidth, boxHeight);
|
||||||
|
display->fillRect(boxLeft, boxTop - 2, boxWidth, 1);
|
||||||
|
display->fillRect(boxLeft - 2, boxTop, 1, boxHeight);
|
||||||
|
display->fillRect(boxLeft + boxWidth + 1, boxTop, 1, boxHeight);
|
||||||
|
display->setColor(BLACK);
|
||||||
|
display->fillRect(boxLeft, boxTop, 1, 1);
|
||||||
|
display->fillRect(boxLeft + boxWidth - 1, boxTop, 1, 1);
|
||||||
|
display->fillRect(boxLeft, boxTop + boxHeight - 1, 1, 1);
|
||||||
|
display->fillRect(boxLeft + boxWidth - 1, boxTop + boxHeight - 1, 1, 1);
|
||||||
|
display->setColor(WHITE);
|
||||||
|
int16_t lineY = boxTop + vPadding;
|
||||||
|
int swingRange = 8;
|
||||||
|
static int swingOffset = 0;
|
||||||
|
static bool swingRight = true;
|
||||||
|
static unsigned long lastSwingTime = 0;
|
||||||
|
unsigned long now = millis();
|
||||||
|
int swingSpeedMs = 10 / (swingRange * 2);
|
||||||
|
if (now - lastSwingTime >= (unsigned long)swingSpeedMs) {
|
||||||
|
lastSwingTime = now;
|
||||||
|
if (swingRight) {
|
||||||
|
swingOffset++;
|
||||||
|
if (swingOffset >= swingRange)
|
||||||
|
swingRight = false;
|
||||||
|
} else {
|
||||||
|
swingOffset--;
|
||||||
|
if (swingOffset <= 0)
|
||||||
|
swingRight = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < lineCount; i++) {
|
||||||
|
bool isTitle = (i == 0);
|
||||||
|
int globalOptionIndex = (i - 1) + firstOptionToShow;
|
||||||
|
bool isSelectedOption = (!isTitle && globalOptionIndex >= 0 && globalOptionIndex == curSelected);
|
||||||
|
|
||||||
|
uint16_t visibleWidth = 64 - hPadding * 2;
|
||||||
|
if (totalLines > visibleTotalLines)
|
||||||
|
visibleWidth -= 6;
|
||||||
|
char lineBuffer[lineLengths[i] + 1];
|
||||||
|
strncpy(lineBuffer, lines[i], lineLengths[i]);
|
||||||
|
lineBuffer[lineLengths[i]] = '\0';
|
||||||
|
|
||||||
|
if (isTitle) {
|
||||||
|
if (visibleTotalLines == 1) {
|
||||||
|
display->setColor(BLACK);
|
||||||
|
display->fillRect(boxLeft, boxTop, boxWidth, effectiveLineHeight);
|
||||||
|
display->setColor(WHITE);
|
||||||
|
display->drawString(boxLeft + (boxWidth - lineWidths[i]) / 2, boxTop, lineBuffer);
|
||||||
|
} else {
|
||||||
|
display->setColor(WHITE);
|
||||||
|
display->fillRect(boxLeft, boxTop, boxWidth, effectiveLineHeight);
|
||||||
|
display->setColor(BLACK);
|
||||||
|
display->drawString(boxLeft + (boxWidth - lineWidths[i]) / 2, boxTop, lineBuffer);
|
||||||
|
display->setColor(WHITE);
|
||||||
|
if (needs_bell) {
|
||||||
|
int bellY = boxTop + (FONT_HEIGHT_SMALL - 8) / 2;
|
||||||
|
display->drawXbm(boxLeft + (boxWidth - lineWidths[i]) / 2 - 10, bellY, 8, 8, bell_alert);
|
||||||
|
display->drawXbm(boxLeft + (boxWidth + lineWidths[i]) / 2 + 2, bellY, 8, 8, bell_alert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineY = boxTop + effectiveLineHeight + 1;
|
||||||
|
} else if (isSelectedOption) {
|
||||||
|
display->setColor(WHITE);
|
||||||
|
display->fillRect(boxLeft, lineY, boxWidth, effectiveLineHeight);
|
||||||
|
display->setColor(BLACK);
|
||||||
|
if (lineLengths[i] > 15 && lineWidths[i] > visibleWidth) {
|
||||||
|
int textX = boxLeft + hPadding + swingOffset;
|
||||||
|
display->drawString(textX, lineY - 1, lineBuffer);
|
||||||
|
} else {
|
||||||
|
display->drawString(boxLeft + (boxWidth - lineWidths[i]) / 2, lineY - 1, lineBuffer);
|
||||||
|
}
|
||||||
|
display->setColor(WHITE);
|
||||||
|
lineY += effectiveLineHeight;
|
||||||
|
} else {
|
||||||
|
display->setColor(BLACK);
|
||||||
|
display->fillRect(boxLeft, lineY, boxWidth, effectiveLineHeight);
|
||||||
|
display->setColor(WHITE);
|
||||||
|
display->drawString(boxLeft + (boxWidth - lineWidths[i]) / 2, lineY, lineBuffer);
|
||||||
|
lineY += effectiveLineHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (totalLines > visibleTotalLines) {
|
||||||
|
const uint8_t scrollBarWidth = 5;
|
||||||
|
int16_t scrollBarX = boxLeft + boxWidth - scrollBarWidth - 2;
|
||||||
|
int16_t scrollBarY = boxTop + vPadding + effectiveLineHeight;
|
||||||
|
uint16_t scrollBarHeight = boxHeight - vPadding * 2 - effectiveLineHeight;
|
||||||
|
float ratio = (float)visibleTotalLines / totalLines;
|
||||||
|
uint16_t indicatorHeight = std::max((int)(scrollBarHeight * ratio), 4);
|
||||||
|
float scrollRatio = (float)(firstOptionToShow + lineCount - visibleTotalLines) / (totalLines - visibleTotalLines);
|
||||||
|
uint16_t indicatorY = scrollBarY + scrollRatio * (scrollBarHeight - indicatorHeight);
|
||||||
|
display->drawRect(scrollBarX, scrollBarY, scrollBarWidth, scrollBarHeight);
|
||||||
|
display->fillRect(scrollBarX + 1, indicatorY, scrollBarWidth - 2, indicatorHeight);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (needs_bell) {
|
if (needs_bell) {
|
||||||
if (isHighResolution && boxWidth <= 150)
|
if (isHighResolution && boxWidth <= 150)
|
||||||
boxWidth += 26;
|
boxWidth += 26;
|
||||||
@@ -579,6 +712,7 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
|||||||
display->drawRect(scrollBarX, scrollBarY, scrollBarWidth, scrollBarHeight);
|
display->drawRect(scrollBarX, scrollBarY, scrollBarWidth, scrollBarHeight);
|
||||||
display->fillRect(scrollBarX + 1, indicatorY, scrollBarWidth - 2, indicatorHeight);
|
display->fillRect(scrollBarX + 1, indicatorY, scrollBarWidth - 2, indicatorHeight);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the last text message we received
|
/// Draw the last text message we received
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
// External variables
|
// External variables
|
||||||
extern graphics::Screen *screen;
|
extern graphics::Screen *screen;
|
||||||
|
static uint32_t lastSwitchTime = 0;
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
NodeNum UIRenderer::currentFavoriteNodeNum = 0;
|
NodeNum UIRenderer::currentFavoriteNodeNum = 0;
|
||||||
@@ -119,7 +119,7 @@ void UIRenderer::drawGpsAltitude(OLEDDisplay *display, int16_t x, int16_t y, con
|
|||||||
void UIRenderer::drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gps,
|
void UIRenderer::drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gps,
|
||||||
const char *mode)
|
const char *mode)
|
||||||
{
|
{
|
||||||
auto gpsFormat = config.display.gps_format;
|
auto gpsFormat = uiconfig.gps_format;
|
||||||
char displayLine[32];
|
char displayLine[32];
|
||||||
|
|
||||||
if (!gps->getIsConnected() && !config.position.fixed_position) {
|
if (!gps->getIsConnected() && !config.position.fixed_position) {
|
||||||
@@ -132,25 +132,25 @@ void UIRenderer::drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y,
|
|||||||
|
|
||||||
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
|
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
|
||||||
|
|
||||||
if (gpsFormat != meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) {
|
if (gpsFormat != meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS) {
|
||||||
char coordinateLine_1[22];
|
char coordinateLine_1[22];
|
||||||
char coordinateLine_2[22];
|
char coordinateLine_2[22];
|
||||||
if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC) { // Decimal Degrees
|
if (gpsFormat == meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC) { // Decimal Degrees
|
||||||
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "Lat: %f", geoCoord.getLatitude() * 1e-7);
|
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "Lat: %f", geoCoord.getLatitude() * 1e-7);
|
||||||
snprintf(coordinateLine_2, sizeof(coordinateLine_2), "Lon: %f", geoCoord.getLongitude() * 1e-7);
|
snprintf(coordinateLine_2, sizeof(coordinateLine_2), "Lon: %f", geoCoord.getLongitude() * 1e-7);
|
||||||
} else if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_UTM) { // Universal Transverse Mercator
|
} else if (gpsFormat == meshtastic_DeviceUIConfig_GpsCoordinateFormat_UTM) { // Universal Transverse Mercator
|
||||||
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "%2i%1c %06u E", geoCoord.getUTMZone(),
|
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "%2i%1c %06u E", geoCoord.getUTMZone(),
|
||||||
geoCoord.getUTMBand(), geoCoord.getUTMEasting());
|
geoCoord.getUTMBand(), geoCoord.getUTMEasting());
|
||||||
snprintf(coordinateLine_2, sizeof(coordinateLine_2), "%07u N", geoCoord.getUTMNorthing());
|
snprintf(coordinateLine_2, sizeof(coordinateLine_2), "%07u N", geoCoord.getUTMNorthing());
|
||||||
} else if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MGRS) { // Military Grid Reference System
|
} else if (gpsFormat == meshtastic_DeviceUIConfig_GpsCoordinateFormat_MGRS) { // Military Grid Reference System
|
||||||
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "%2i%1c %1c%1c", geoCoord.getMGRSZone(),
|
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "%2i%1c %1c%1c", geoCoord.getMGRSZone(),
|
||||||
geoCoord.getMGRSBand(), geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k());
|
geoCoord.getMGRSBand(), geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k());
|
||||||
snprintf(coordinateLine_2, sizeof(coordinateLine_2), "%05u E %05u N", geoCoord.getMGRSEasting(),
|
snprintf(coordinateLine_2, sizeof(coordinateLine_2), "%05u E %05u N", geoCoord.getMGRSEasting(),
|
||||||
geoCoord.getMGRSNorthing());
|
geoCoord.getMGRSNorthing());
|
||||||
} else if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OLC) { // Open Location Code
|
} else if (gpsFormat == meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC) { // Open Location Code
|
||||||
geoCoord.getOLCCode(coordinateLine_1);
|
geoCoord.getOLCCode(coordinateLine_1);
|
||||||
coordinateLine_2[0] = '\0';
|
coordinateLine_2[0] = '\0';
|
||||||
} else if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR) { // Ordnance Survey Grid Reference
|
} else if (gpsFormat == meshtastic_DeviceUIConfig_GpsCoordinateFormat_OSGR) { // Ordnance Survey Grid Reference
|
||||||
if (geoCoord.getOSGRE100k() == 'I' || geoCoord.getOSGRN100k() == 'I') { // OSGR is only valid around the UK region
|
if (geoCoord.getOSGRE100k() == 'I' || geoCoord.getOSGRN100k() == 'I') { // OSGR is only valid around the UK region
|
||||||
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "%s", "Out of Boundary");
|
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "%s", "Out of Boundary");
|
||||||
coordinateLine_2[0] = '\0';
|
coordinateLine_2[0] = '\0';
|
||||||
@@ -160,6 +160,48 @@ void UIRenderer::drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y,
|
|||||||
snprintf(coordinateLine_2, sizeof(coordinateLine_2), "%05u E %05u N", geoCoord.getOSGREasting(),
|
snprintf(coordinateLine_2, sizeof(coordinateLine_2), "%05u E %05u N", geoCoord.getOSGREasting(),
|
||||||
geoCoord.getOSGRNorthing());
|
geoCoord.getOSGRNorthing());
|
||||||
}
|
}
|
||||||
|
} else if (gpsFormat == meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS) { // Maidenhead Locator System
|
||||||
|
double lat = geoCoord.getLatitude() * 1e-7;
|
||||||
|
double lon = geoCoord.getLongitude() * 1e-7;
|
||||||
|
|
||||||
|
// Normalize
|
||||||
|
if (lat > 90.0)
|
||||||
|
lat = 90.0;
|
||||||
|
if (lat < -90.0)
|
||||||
|
lat = -90.0;
|
||||||
|
while (lon < -180.0)
|
||||||
|
lon += 360.0;
|
||||||
|
while (lon >= 180.0)
|
||||||
|
lon -= 360.0;
|
||||||
|
|
||||||
|
double adjLon = lon + 180.0;
|
||||||
|
double adjLat = lat + 90.0;
|
||||||
|
|
||||||
|
char maiden[10]; // enough for 8-char + null
|
||||||
|
|
||||||
|
// Field (2 letters)
|
||||||
|
int lonField = int(adjLon / 20.0);
|
||||||
|
int latField = int(adjLat / 10.0);
|
||||||
|
adjLon -= lonField * 20.0;
|
||||||
|
adjLat -= latField * 10.0;
|
||||||
|
|
||||||
|
// Square (2 digits)
|
||||||
|
int lonSquare = int(adjLon / 2.0);
|
||||||
|
int latSquare = int(adjLat / 1.0);
|
||||||
|
adjLon -= lonSquare * 2.0;
|
||||||
|
adjLat -= latSquare * 1.0;
|
||||||
|
|
||||||
|
// Subsquare (2 letters)
|
||||||
|
double lonUnit = 2.0 / 24.0;
|
||||||
|
double latUnit = 1.0 / 24.0;
|
||||||
|
int lonSub = int(adjLon / lonUnit);
|
||||||
|
int latSub = int(adjLat / latUnit);
|
||||||
|
|
||||||
|
snprintf(maiden, sizeof(maiden), "%c%c%c%c%c%c", 'A' + lonField, 'A' + latField, '0' + lonSquare, '0' + latSquare,
|
||||||
|
'A' + lonSub, 'A' + latSub);
|
||||||
|
|
||||||
|
snprintf(coordinateLine_1, sizeof(coordinateLine_1), "MH: %s", maiden);
|
||||||
|
coordinateLine_2[0] = '\0'; // only need one line
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(mode, "line1") == 0) {
|
if (strcmp(mode, "line1") == 0) {
|
||||||
@@ -232,7 +274,6 @@ void UIRenderer::drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const mes
|
|||||||
// **********************
|
// **********************
|
||||||
void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t x, int16_t y)
|
void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (favoritedNodes.empty())
|
if (favoritedNodes.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -244,8 +285,15 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
|
|||||||
meshtastic_NodeInfoLite *node = favoritedNodes[nodeIndex];
|
meshtastic_NodeInfoLite *node = favoritedNodes[nodeIndex];
|
||||||
if (!node || node->num == nodeDB->getNodeNum() || !node->is_favorite)
|
if (!node || node->num == nodeDB->getNodeNum() || !node->is_favorite)
|
||||||
return;
|
return;
|
||||||
|
uint32_t now = millis();
|
||||||
display->clear();
|
display->clear();
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
if (now - lastSwitchTime >= 10000) // 10000 ms = 10 秒
|
||||||
|
{
|
||||||
|
display->display();
|
||||||
|
lastSwitchTime = now;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
currentFavoriteNodeNum = node->num;
|
currentFavoriteNodeNum = node->num;
|
||||||
// === Create the shortName and title string ===
|
// === Create the shortName and title string ===
|
||||||
const char *shortName = (node->has_user && haveGlyphs(node->user.short_name)) ? node->user.short_name : "Node";
|
const char *shortName = (node->has_user && haveGlyphs(node->user.short_name)) ? node->user.short_name : "Node";
|
||||||
@@ -264,9 +312,13 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
|
|||||||
// List of available macro Y positions in order, from top to bottom.
|
// List of available macro Y positions in order, from top to bottom.
|
||||||
int line = 1; // which slot to use next
|
int line = 1; // which slot to use next
|
||||||
std::string usernameStr;
|
std::string usernameStr;
|
||||||
|
|
||||||
// === 1. Long Name (always try to show first) ===
|
// === 1. Long Name (always try to show first) ===
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
const char *username = (node->has_user && node->user.long_name[0]) ? node->user.short_name : nullptr;
|
||||||
|
#else
|
||||||
const char *username = (node->has_user && node->user.long_name[0]) ? node->user.long_name : nullptr;
|
const char *username = (node->has_user && node->user.long_name[0]) ? node->user.long_name : nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (username) {
|
if (username) {
|
||||||
usernameStr = sanitizeString(username); // Sanitize the incoming long_name just in case
|
usernameStr = sanitizeString(username); // Sanitize the incoming long_name just in case
|
||||||
// Print node's long name (e.g. "Backpack Node")
|
// Print node's long name (e.g. "Backpack Node")
|
||||||
@@ -321,7 +373,7 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
|
|||||||
if (seenStr[0] && line < 5) {
|
if (seenStr[0] && line < 5) {
|
||||||
display->drawString(x, getTextPositions(display)[line++], seenStr);
|
display->drawString(x, getTextPositions(display)[line++], seenStr);
|
||||||
}
|
}
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
// === 4. Uptime (only show if metric is present) ===
|
// === 4. Uptime (only show if metric is present) ===
|
||||||
char uptimeStr[32] = "";
|
char uptimeStr[32] = "";
|
||||||
if (node->has_device_metrics && node->device_metrics.has_uptime_seconds) {
|
if (node->has_device_metrics && node->device_metrics.has_uptime_seconds) {
|
||||||
@@ -493,6 +545,7 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
|
|||||||
}
|
}
|
||||||
// else show nothing
|
// else show nothing
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ****************************
|
// ****************************
|
||||||
@@ -506,7 +559,11 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
|||||||
int line = 1;
|
int line = 1;
|
||||||
|
|
||||||
// === Header ===
|
// === Header ===
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
graphics::drawCommonHeader(display, x, y, "Home");
|
||||||
|
#else
|
||||||
graphics::drawCommonHeader(display, x, y, "");
|
graphics::drawCommonHeader(display, x, y, "");
|
||||||
|
#endif
|
||||||
|
|
||||||
// === Content below header ===
|
// === Content below header ===
|
||||||
|
|
||||||
@@ -521,20 +578,25 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
|||||||
config.display.heading_bold = false;
|
config.display.heading_bold = false;
|
||||||
|
|
||||||
// Display Region and Channel Utilization
|
// Display Region and Channel Utilization
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
drawNodes(display, x, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
||||||
|
#else
|
||||||
drawNodes(display, x + 1, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
drawNodes(display, x + 1, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
||||||
|
#endif
|
||||||
char uptimeStr[32] = "";
|
char uptimeStr[32] = "";
|
||||||
uint32_t uptime = millis() / 1000;
|
uint32_t uptime = millis() / 1000;
|
||||||
uint32_t days = uptime / 86400;
|
uint32_t days = uptime / 86400;
|
||||||
uint32_t hours = (uptime % 86400) / 3600;
|
uint32_t hours = (uptime % 86400) / 3600;
|
||||||
uint32_t mins = (uptime % 3600) / 60;
|
uint32_t mins = (uptime % 3600) / 60;
|
||||||
// Show as "Up: 2d 3h", "Up: 5h 14m", or "Up: 37m"
|
// Show as "Up: 2d 3h", "Up: 5h 14m", or "Up: 37m"
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
if (days)
|
if (days)
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %ud %uh", days, hours);
|
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %ud %uh", days, hours);
|
||||||
else if (hours)
|
else if (hours)
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %uh %um", hours, mins);
|
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %uh %um", hours, mins);
|
||||||
else
|
else
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %um", mins);
|
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %um", mins);
|
||||||
|
#endif
|
||||||
display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), getTextPositions(display)[line++], uptimeStr);
|
display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), getTextPositions(display)[line++], uptimeStr);
|
||||||
|
|
||||||
// === Second Row: Satellites and Voltage ===
|
// === Second Row: Satellites and Voltage ===
|
||||||
@@ -563,6 +625,21 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
line += 1;
|
||||||
|
|
||||||
|
// === Node Identity ===
|
||||||
|
int textWidth = 0;
|
||||||
|
int nameX = 0;
|
||||||
|
char shortnameble[35];
|
||||||
|
snprintf(shortnameble, sizeof(shortnameble), "%s",
|
||||||
|
graphics::UIRenderer::haveGlyphs(owner.short_name) ? owner.short_name : "");
|
||||||
|
|
||||||
|
// === ShortName Centered ===
|
||||||
|
textWidth = display->getStringWidth(shortnameble);
|
||||||
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
|
display->drawString(nameX, getTextPositions(display)[line++], shortnameble);
|
||||||
|
#else
|
||||||
if (powerStatus->getHasBattery()) {
|
if (powerStatus->getHasBattery()) {
|
||||||
char batStr[20];
|
char batStr[20];
|
||||||
int batV = powerStatus->getBatteryVoltageMv() / 1000;
|
int batV = powerStatus->getBatteryVoltageMv() / 1000;
|
||||||
@@ -688,6 +765,7 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
|||||||
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
display->drawString(nameX, getTextPositions(display)[line++], shortnameble);
|
display->drawString(nameX, getTextPositions(display)[line++], shortnameble);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start Functions to write date/time to the screen
|
// Start Functions to write date/time to the screen
|
||||||
@@ -846,6 +924,28 @@ void UIRenderer::drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLED
|
|||||||
// needs to be drawn relative to x and y
|
// needs to be drawn relative to x and y
|
||||||
|
|
||||||
// draw centered icon left to right and centered above the one line of app text
|
// draw centered icon left to right and centered above the one line of app text
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
display->drawXbm(x + (SCREEN_WIDTH - 50) / 2, y + (SCREEN_HEIGHT - 28) / 2, icon_width, icon_height, icon_bits);
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
// Draw region in upper left
|
||||||
|
if (upperMsg) {
|
||||||
|
int msgWidth = display->getStringWidth(upperMsg);
|
||||||
|
int msgX = x + (SCREEN_WIDTH - msgWidth) / 2;
|
||||||
|
int msgY = y;
|
||||||
|
display->drawString(msgX, msgY, upperMsg);
|
||||||
|
}
|
||||||
|
// Draw version and short name in bottom middle
|
||||||
|
char buf[25];
|
||||||
|
snprintf(buf, sizeof(buf), "%s %s", xstr(APP_VERSION_SHORT),
|
||||||
|
graphics::UIRenderer::haveGlyphs(owner.short_name) ? owner.short_name : "");
|
||||||
|
|
||||||
|
display->drawString(x + getStringCenteredX(buf), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, buf);
|
||||||
|
screen->forceDisplay();
|
||||||
|
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code
|
||||||
|
#else
|
||||||
display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2,
|
display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2,
|
||||||
icon_width, icon_height, icon_bits);
|
icon_width, icon_height, icon_bits);
|
||||||
|
|
||||||
@@ -854,7 +954,6 @@ void UIRenderer::drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLED
|
|||||||
const char *title = "meshtastic.org";
|
const char *title = "meshtastic.org";
|
||||||
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
|
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
|
|
||||||
// Draw region in upper left
|
// Draw region in upper left
|
||||||
if (upperMsg)
|
if (upperMsg)
|
||||||
display->drawString(x + 0, y + 0, upperMsg);
|
display->drawString(x + 0, y + 0, upperMsg);
|
||||||
@@ -869,6 +968,7 @@ void UIRenderer::drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLED
|
|||||||
screen->forceDisplay();
|
screen->forceDisplay();
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code
|
display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ****************************
|
// ****************************
|
||||||
@@ -968,11 +1068,11 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
|||||||
#if defined(USE_EINK)
|
#if defined(USE_EINK)
|
||||||
// E-Ink: skip seconds, show only days/hours/mins
|
// E-Ink: skip seconds, show only days/hours/mins
|
||||||
if (days > 0) {
|
if (days > 0) {
|
||||||
snprintf(buf, sizeof(buf), " Last: %ud %uh", days, hours);
|
snprintf(buf, sizeof(buf), "Last: %ud %uh", days, hours);
|
||||||
} else if (hours > 0) {
|
} else if (hours > 0) {
|
||||||
snprintf(buf, sizeof(buf), " Last: %uh %um", hours, mins);
|
snprintf(buf, sizeof(buf), "Last: %uh %um", hours, mins);
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof(buf), " Last: %um", mins);
|
snprintf(buf, sizeof(buf), "Last: %um", mins);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Non E-Ink: include seconds where useful
|
// Non E-Ink: include seconds where useful
|
||||||
@@ -995,24 +1095,13 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
|||||||
// === Third Row: Line 1 GPS Info ===
|
// === Third Row: Line 1 GPS Info ===
|
||||||
UIRenderer::drawGpsCoordinates(display, x, getTextPositions(display)[line++], gpsStatus, "line1");
|
UIRenderer::drawGpsCoordinates(display, x, getTextPositions(display)[line++], gpsStatus, "line1");
|
||||||
|
|
||||||
if (config.display.gps_format != meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OLC) {
|
if (uiconfig.gps_format != meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC &&
|
||||||
|
uiconfig.gps_format != meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS) {
|
||||||
// === Fourth Row: Line 2 GPS Info ===
|
// === Fourth Row: Line 2 GPS Info ===
|
||||||
UIRenderer::drawGpsCoordinates(display, x, getTextPositions(display)[line++], gpsStatus, "line2");
|
UIRenderer::drawGpsCoordinates(display, x, getTextPositions(display)[line++], gpsStatus, "line2");
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Fourth/Fifth Row: Altitude ===
|
|
||||||
char DisplayLineTwo[32] = {0};
|
|
||||||
int32_t alt = (strcmp(displayLine, "Phone GPS") == 0 && ourNode && nodeDB->hasValidPosition(ourNode))
|
|
||||||
? ourNode->position.altitude
|
|
||||||
: geoCoord.getAltitude();
|
|
||||||
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
|
||||||
snprintf(DisplayLineTwo, sizeof(DisplayLineTwo), "Alt: %.0fft", geoCoord.getAltitude() * METERS_TO_FEET);
|
|
||||||
} else {
|
|
||||||
snprintf(DisplayLineTwo, sizeof(DisplayLineTwo), "Alt: %.0im", geoCoord.getAltitude());
|
|
||||||
}
|
|
||||||
display->drawString(x, getTextPositions(display)[line++], DisplayLineTwo);
|
|
||||||
}
|
}
|
||||||
|
#if !defined(M5STACK_UNITC6L)
|
||||||
// === Draw Compass if heading is valid ===
|
// === Draw Compass if heading is valid ===
|
||||||
if (validHeading) {
|
if (validHeading) {
|
||||||
// --- Compass Rendering: landscape (wide) screens use original side-aligned logic ---
|
// --- Compass Rendering: landscape (wide) screens use original side-aligned logic ---
|
||||||
@@ -1095,6 +1184,7 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif // HAS_GPS
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USERPREFS_OEM_TEXT
|
#ifdef USERPREFS_OEM_TEXT
|
||||||
@@ -1251,7 +1341,6 @@ void UIRenderer::drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *sta
|
|||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Knock the corners off the square
|
// Knock the corners off the square
|
||||||
display->setColor(BLACK);
|
display->setColor(BLACK);
|
||||||
display->drawRect(rectX, y - 2, 1, 1);
|
display->drawRect(rectX, y - 2, 1, 1);
|
||||||
|
|||||||
@@ -287,7 +287,9 @@ const uint8_t digital_icon_clock[] PROGMEM = {0b00111100, 0b01000010, 0b10000101
|
|||||||
#define analog_icon_clock_height 8
|
#define analog_icon_clock_height 8
|
||||||
const uint8_t analog_icon_clock[] PROGMEM = {0b11111111, 0b01000010, 0b00100100, 0b00011000,
|
const uint8_t analog_icon_clock[] PROGMEM = {0b11111111, 0b01000010, 0b00100100, 0b00011000,
|
||||||
0b00100100, 0b01000010, 0b01000010, 0b11111111};
|
0b00100100, 0b01000010, 0b01000010, 0b11111111};
|
||||||
|
#ifdef M5STACK_UNITC6L
|
||||||
|
#include "img/icon_small.xbm"
|
||||||
|
#else
|
||||||
#define chirpy_width 38
|
#define chirpy_width 38
|
||||||
#define chirpy_height 50
|
#define chirpy_height 50
|
||||||
static unsigned char chirpy[] = {
|
static unsigned char chirpy[] = {
|
||||||
@@ -361,4 +363,5 @@ static unsigned char chirpy_hirez[] = {
|
|||||||
static unsigned char small_chirpy[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
|
static unsigned char small_chirpy[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
|
||||||
|
|
||||||
#include "img/icon.xbm"
|
#include "img/icon.xbm"
|
||||||
|
#endif
|
||||||
static_assert(sizeof(icon_bits) >= 0, "Silence unused variable warning");
|
static_assert(sizeof(icon_bits) >= 0, "Silence unused variable warning");
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
#ifndef USERPREFS_HAS_SPLASH
|
||||||
|
#define icon_width 50
|
||||||
|
#define icon_height 20
|
||||||
|
static uint8_t icon_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x80, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80,
|
||||||
|
0x07, 0xc0, 0x07, 0x00, 0x00, 0x00, 0xc0, 0x0f,
|
||||||
|
0xc0, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xe0,
|
||||||
|
0x0f, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xf0, 0x1f,
|
||||||
|
0x00, 0x00, 0x00, 0xf0, 0x03, 0xf0, 0x3f, 0x00,
|
||||||
|
0x00, 0x00, 0xf8, 0x03, 0xf8, 0x7f, 0x00, 0x00,
|
||||||
|
0x00, 0xf8, 0x01, 0xfc, 0x7e, 0x00, 0x00, 0x00,
|
||||||
|
0xfc, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0xfe,
|
||||||
|
0x00, 0x7e, 0xf8, 0x00, 0x00, 0x00, 0x7e, 0x00,
|
||||||
|
0x3f, 0xf8, 0x01, 0x00, 0x00, 0x3f, 0x00, 0x1f,
|
||||||
|
0xf0, 0x01, 0x00, 0x00, 0x1f, 0x80, 0x1f, 0xe0,
|
||||||
|
0x03, 0x00, 0x80, 0x1f, 0xc0, 0x0f, 0xe0, 0x03,
|
||||||
|
0x00, 0x80, 0x0f, 0xc0, 0x07, 0xc0, 0x07, 0x00,
|
||||||
|
0xc0, 0x0f, 0xe0, 0x07, 0x80, 0x0f, 0x00, 0xe0,
|
||||||
|
0x07, 0xf0, 0x03, 0x80, 0x1f, 0x00, 0xe0, 0x03,
|
||||||
|
0xf8, 0x03, 0x00, 0x1f, 0x00, 0xf0, 0x03, 0xf8,
|
||||||
|
0x01, 0x00, 0x3f, 0x00, 0xf8, 0x01, 0xfc, 0x00,
|
||||||
|
0x00, 0x7e, 0x00, 0xfc, 0x00, 0xfe, 0x00, 0x00,
|
||||||
|
0x7e, 0x00, 0xfc, 0x00, 0x7e, 0x00, 0x00, 0xfc,
|
||||||
|
0x00, 0x7e, 0x00, 0x3f, 0x00, 0x00, 0xf8, 0x00,
|
||||||
|
0x7e, 0x00, 0x3e, 0x00, 0x00, 0xf8, 0x00, 0x38,
|
||||||
|
0x00, 0x1c, 0x00, 0x00, 0x70, 0x00, 0x10, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00 };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Chirpy image definitions for M5STACK_UNITC6L compatibility
|
||||||
|
#define chirpy_width 38
|
||||||
|
#define chirpy_height 50
|
||||||
|
static unsigned char chirpy[] = {
|
||||||
|
0xfe, 0xff, 0xff, 0xff, 0xdf, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01,
|
||||||
|
0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01, 0x00,
|
||||||
|
0x00, 0x00, 0xe0, 0x81, 0xff, 0xff, 0x7f, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xcf, 0x7f,
|
||||||
|
0xfe, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc,
|
||||||
|
0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0,
|
||||||
|
0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1,
|
||||||
|
0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0xcf, 0x7f, 0xfe, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0x81, 0xff,
|
||||||
|
0xff, 0x7f, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0xc3, 0x00, 0xe0, 0x01, 0x00, 0xc3,
|
||||||
|
0x00, 0xe0, 0x01, 0x80, 0xe1, 0x01, 0xe0, 0x01, 0x80, 0xe1, 0x01, 0xe0, 0x01, 0xc0, 0x30, 0x03, 0xe0, 0x01, 0xc0, 0x30, 0x03,
|
||||||
|
0xe0, 0x01, 0x60, 0x18, 0x06, 0xe0, 0x01, 0x60, 0x18, 0x06, 0xe0, 0x01, 0x30, 0x0c, 0x0c, 0xe0, 0x01, 0x30, 0x0c, 0x0c, 0xe0,
|
||||||
|
0x01, 0x18, 0x06, 0x18, 0xe0, 0x01, 0x18, 0x06, 0x18, 0xe0, 0x01, 0x0c, 0x03, 0x30, 0xe0, 0x01, 0x0c, 0x03, 0x30, 0xe0, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xdf};
|
||||||
|
|
||||||
|
#define chirpy_width_hirez 76
|
||||||
|
#define chirpy_height_hirez 100
|
||||||
|
static unsigned char chirpy_hirez[] = {
|
||||||
|
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x03,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
|
||||||
|
0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc,
|
||||||
|
0x03, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
|
||||||
|
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
|
||||||
|
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f,
|
||||||
|
0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe,
|
||||||
|
0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff,
|
||||||
|
0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f,
|
||||||
|
0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0,
|
||||||
|
0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f,
|
||||||
|
0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00,
|
||||||
|
0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc,
|
||||||
|
0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
|
||||||
|
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
|
||||||
|
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f,
|
||||||
|
0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe,
|
||||||
|
0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff,
|
||||||
|
0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f,
|
||||||
|
0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0,
|
||||||
|
0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f,
|
||||||
|
0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00,
|
||||||
|
0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc,
|
||||||
|
0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
|
||||||
|
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
|
||||||
|
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x1f,
|
||||||
|
0xff, 0xff, 0xff, 0xf8, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00,
|
||||||
|
0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x80, 0x87, 0xe1, 0x01, 0x00,
|
||||||
|
0x00, 0xfc, 0x03, 0x00, 0x00, 0x80, 0x87, 0xe1, 0x01, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xc0, 0x83, 0xc1, 0x03, 0x00, 0x00,
|
||||||
|
0xfc, 0x03, 0x00, 0x00, 0xc0, 0x83, 0xc1, 0x03, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x00, 0xfc,
|
||||||
|
0x03, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xfc, 0x03,
|
||||||
|
0x00, 0x00, 0xf0, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x78, 0x00, 0x00, 0x1e, 0x00, 0x00, 0xfc, 0x03, 0x00,
|
||||||
|
0x00, 0x78, 0x00, 0x00, 0x1e, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
|
||||||
|
0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x1e,
|
||||||
|
0x00, 0x00, 0x78, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0x00,
|
||||||
|
0x00, 0xf0, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x80, 0x07, 0x00, 0x00, 0xe0, 0x01, 0x00, 0xfc, 0x03, 0x00, 0x80, 0x07, 0x00, 0x00,
|
||||||
|
0xe0, 0x01, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0,
|
||||||
|
0x03, 0x00, 0xfc, 0x03, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0x07, 0x00, 0xfc, 0x03, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0x07,
|
||||||
|
0x00, 0xfc, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
|
||||||
|
0xfc, 0x03, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xfc, 0x03, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xfc,
|
||||||
|
0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfc, 0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfc, 0x03,
|
||||||
|
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00,
|
||||||
|
0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xfc, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xfc, 0x03, 0x80, 0x07,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xfc, 0x03, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xfc, 0x03, 0xc0, 0x03, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xc0, 0x03, 0xfc, 0x03, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xfc, 0x03, 0xe0, 0x01, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x07, 0xfc, 0x03, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0xfc, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0f, 0xfc, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3
|
||||||
|
};
|
||||||
|
|
||||||
|
#define chirpy_small_image_width 8
|
||||||
|
#define chirpy_small_image_height 8
|
||||||
|
static unsigned char small_chirpy[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
|
||||||
@@ -188,7 +188,7 @@ void ExpressLRSFiveWay::determineAction(KeyType key, PressLength length)
|
|||||||
// Feed input to the canned messages module
|
// Feed input to the canned messages module
|
||||||
void ExpressLRSFiveWay::sendKey(input_broker_event key)
|
void ExpressLRSFiveWay::sendKey(input_broker_event key)
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.source = inputSourceName;
|
e.source = inputSourceName;
|
||||||
e.inputEvent = key;
|
e.inputEvent = key;
|
||||||
notifyObservers(&e);
|
notifyObservers(&e);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ int32_t LinuxInput::runOnce()
|
|||||||
int rd = read(events[i].data.fd, ev, sizeof(ev));
|
int rd = read(events[i].data.fd, ev, sizeof(ev));
|
||||||
assert(rd > ((signed int)sizeof(struct input_event)));
|
assert(rd > ((signed int)sizeof(struct input_event)));
|
||||||
for (int j = 0; j < rd / ((signed int)sizeof(struct input_event)); j++) {
|
for (int j = 0; j < rd / ((signed int)sizeof(struct input_event)); j++) {
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
e.kbchar = 0;
|
e.kbchar = 0;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ void RotaryEncoderInterruptBase::init(
|
|||||||
|
|
||||||
int32_t RotaryEncoderInterruptBase::runOnce()
|
int32_t RotaryEncoderInterruptBase::runOnce()
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
@@ -151,7 +151,7 @@ RotaryEncoderInterruptBaseStateType RotaryEncoderInterruptBase::intHandler(bool
|
|||||||
// Logic to prevent bouncing.
|
// Logic to prevent bouncing.
|
||||||
newState = ROTARY_EVENT_CLEARED;
|
newState = ROTARY_EVENT_CLEARED;
|
||||||
}
|
}
|
||||||
setIntervalFromNow(50); // TODO: this modifies a non-volatile variable!
|
setIntervalFromNow(ROTARY_DELAY); // TODO: this modifies a non-volatile variable!
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ bool SeesawRotary::init()
|
|||||||
|
|
||||||
int32_t SeesawRotary::runOnce()
|
int32_t SeesawRotary::runOnce()
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
bool currentlyPressed = !ss.digitalRead(SS_SWITCH);
|
bool currentlyPressed = !ss.digitalRead(SS_SWITCH);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ SerialKeyboard::SerialKeyboard(const char *name) : concurrency::OSThread(name)
|
|||||||
|
|
||||||
void SerialKeyboard::erase()
|
void SerialKeyboard::erase()
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_BACK;
|
e.inputEvent = INPUT_BROKER_BACK;
|
||||||
e.kbchar = 0x08;
|
e.kbchar = 0x08;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
@@ -80,7 +80,7 @@ int32_t SerialKeyboard::runOnce()
|
|||||||
|
|
||||||
if (keys < prevKeys) { // a new key has been pressed (and not released), doesn't works for multiple presses at once but
|
if (keys < prevKeys) { // a new key has been pressed (and not released), doesn't works for multiple presses at once but
|
||||||
// shouldn't be a limitation
|
// shouldn't be a limitation
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
// SELECT OR SEND OR CANCEL EVENT
|
// SELECT OR SEND OR CANCEL EVENT
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ bool TouchScreenImpl1::getTouch(int16_t &x, int16_t &y)
|
|||||||
*/
|
*/
|
||||||
void TouchScreenImpl1::onEvent(const TouchEvent &event)
|
void TouchScreenImpl1::onEvent(const TouchEvent &event)
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.source = event.source;
|
e.source = event.source;
|
||||||
e.kbchar = 0;
|
e.kbchar = 0;
|
||||||
e.touchX = event.x;
|
e.touchX = event.x;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ void TrackballInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLef
|
|||||||
|
|
||||||
int32_t TrackballInterruptBase::runOnce()
|
int32_t TrackballInterruptBase::runOnce()
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
|
|
||||||
// Handle long press detection for press button
|
// Handle long press detection for press button
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ void UpDownInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinPress,
|
|||||||
|
|
||||||
int32_t UpDownInterruptBase::runOnce()
|
int32_t UpDownInterruptBase::runOnce()
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
#include "i2cButton.h"
|
||||||
|
#include "meshUtils.h"
|
||||||
|
|
||||||
|
#include "configuration.h"
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
|
||||||
|
#include "MeshService.h"
|
||||||
|
#include "RadioLibInterface.h"
|
||||||
|
#include "buzz.h"
|
||||||
|
#include "input/InputBroker.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "modules/CannedMessageModule.h"
|
||||||
|
#include "modules/ExternalNotificationModule.h"
|
||||||
|
#include "power.h"
|
||||||
|
#include "sleep.h"
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
#include "platform/portduino/PortduinoGlue.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
i2cButtonThread *i2cButton;
|
||||||
|
|
||||||
|
using namespace concurrency;
|
||||||
|
|
||||||
|
extern void i2c_read_byte(uint8_t addr, uint8_t reg, uint8_t *value);
|
||||||
|
|
||||||
|
extern void i2c_write_byte(uint8_t addr, uint8_t reg, uint8_t value);
|
||||||
|
|
||||||
|
#define PI4IO_M_ADDR 0x43
|
||||||
|
#define getbit(x, y) ((x) >> (y)&0x01)
|
||||||
|
#define PI4IO_REG_IRQ_STA 0x13
|
||||||
|
#define PI4IO_REG_IN_STA 0x0F
|
||||||
|
#define PI4IO_REG_CHIP_RESET 0x01
|
||||||
|
|
||||||
|
i2cButtonThread::i2cButtonThread(const char *name) : OSThread(name)
|
||||||
|
{
|
||||||
|
_originName = name;
|
||||||
|
if (inputBroker)
|
||||||
|
inputBroker->registerSource(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t i2cButtonThread::runOnce()
|
||||||
|
{
|
||||||
|
static bool btn1_pressed = false;
|
||||||
|
static uint32_t press_start_time = 0;
|
||||||
|
const uint32_t LONG_PRESS_TIME = 1000;
|
||||||
|
static bool long_press_triggered = false;
|
||||||
|
|
||||||
|
uint8_t in_data;
|
||||||
|
i2c_read_byte(PI4IO_M_ADDR, PI4IO_REG_IRQ_STA, &in_data);
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_IRQ_STA, in_data);
|
||||||
|
if (getbit(in_data, 0)) {
|
||||||
|
uint8_t input_state;
|
||||||
|
i2c_read_byte(PI4IO_M_ADDR, PI4IO_REG_IN_STA, &input_state);
|
||||||
|
|
||||||
|
if (!getbit(input_state, 0)) {
|
||||||
|
if (!btn1_pressed) {
|
||||||
|
btn1_pressed = true;
|
||||||
|
press_start_time = millis();
|
||||||
|
long_press_triggered = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (btn1_pressed) {
|
||||||
|
btn1_pressed = false;
|
||||||
|
uint32_t press_duration = millis() - press_start_time;
|
||||||
|
if (long_press_triggered) {
|
||||||
|
long_press_triggered = false;
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (press_duration < LONG_PRESS_TIME) {
|
||||||
|
InputEvent evt;
|
||||||
|
evt.source = "UserButton";
|
||||||
|
evt.inputEvent = INPUT_BROKER_USER_PRESS;
|
||||||
|
evt.kbchar = 0;
|
||||||
|
evt.touchX = 0;
|
||||||
|
evt.touchY = 0;
|
||||||
|
this->notifyObservers(&evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btn1_pressed && !long_press_triggered && (millis() - press_start_time >= LONG_PRESS_TIME)) {
|
||||||
|
long_press_triggered = true;
|
||||||
|
InputEvent evt;
|
||||||
|
evt.source = "UserButton";
|
||||||
|
evt.inputEvent = INPUT_BROKER_SELECT;
|
||||||
|
evt.kbchar = 0;
|
||||||
|
evt.touchX = 0;
|
||||||
|
evt.touchY = 0;
|
||||||
|
this->notifyObservers(&evt);
|
||||||
|
}
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "InputBroker.h"
|
||||||
|
#include "OneButton.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
|
||||||
|
class i2cButtonThread : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char *_originName;
|
||||||
|
explicit i2cButtonThread(const char *name);
|
||||||
|
int32_t runOnce() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern i2cButtonThread *i2cButton;
|
||||||
|
#endif
|
||||||
@@ -90,7 +90,7 @@ int32_t KbI2cBase::runOnce()
|
|||||||
while (keyCount--) {
|
while (keyCount--) {
|
||||||
const BBQ10Keyboard::KeyEvent key = Q10keyboard.keyEvent();
|
const BBQ10Keyboard::KeyEvent key = Q10keyboard.keyEvent();
|
||||||
if ((key.key != 0x00) && (key.state == BBQ10Keyboard::StateRelease)) {
|
if ((key.key != 0x00) && (key.state == BBQ10Keyboard::StateRelease)) {
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
switch (key.key) {
|
switch (key.key) {
|
||||||
@@ -187,7 +187,7 @@ int32_t KbI2cBase::runOnce()
|
|||||||
}
|
}
|
||||||
case 0x37: { // MPR121
|
case 0x37: { // MPR121
|
||||||
MPRkeyboard.trigger();
|
MPRkeyboard.trigger();
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
|
|
||||||
while (MPRkeyboard.hasEvent()) {
|
while (MPRkeyboard.hasEvent()) {
|
||||||
char nextEvent = MPRkeyboard.dequeueEvent();
|
char nextEvent = MPRkeyboard.dequeueEvent();
|
||||||
@@ -250,7 +250,7 @@ int32_t KbI2cBase::runOnce()
|
|||||||
}
|
}
|
||||||
case 0x84: { // Adafruit TCA8418
|
case 0x84: { // Adafruit TCA8418
|
||||||
TCAKeyboard.trigger();
|
TCAKeyboard.trigger();
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
while (TCAKeyboard.hasEvent()) {
|
while (TCAKeyboard.hasEvent()) {
|
||||||
char nextEvent = TCAKeyboard.dequeueEvent();
|
char nextEvent = TCAKeyboard.dequeueEvent();
|
||||||
e.inputEvent = INPUT_BROKER_ANYKEY;
|
e.inputEvent = INPUT_BROKER_ANYKEY;
|
||||||
@@ -350,7 +350,7 @@ int32_t KbI2cBase::runOnce()
|
|||||||
}
|
}
|
||||||
if (PrintDataBuf != 0) {
|
if (PrintDataBuf != 0) {
|
||||||
LOG_DEBUG("RAK14004 key 0x%x pressed", PrintDataBuf);
|
LOG_DEBUG("RAK14004 key 0x%x pressed", PrintDataBuf);
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_MATRIXKEY;
|
e.inputEvent = INPUT_BROKER_MATRIXKEY;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
e.kbchar = PrintDataBuf;
|
e.kbchar = PrintDataBuf;
|
||||||
@@ -365,7 +365,7 @@ int32_t KbI2cBase::runOnce()
|
|||||||
|
|
||||||
if (i2cBus->available()) {
|
if (i2cBus->available()) {
|
||||||
char c = i2cBus->read();
|
char c = i2cBus->read();
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ int32_t KbMatrixBase::runOnce()
|
|||||||
if (key != 0) {
|
if (key != 0) {
|
||||||
LOG_DEBUG("Key 0x%x pressed", key);
|
LOG_DEBUG("Key 0x%x pressed", key);
|
||||||
// reset shift now that we have a keypress
|
// reset shift now that we have a keypress
|
||||||
InputEvent e;
|
InputEvent e = {};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
|||||||
+12
-19
@@ -387,7 +387,6 @@ void setup()
|
|||||||
io.digitalWrite(EXPANDS_GPIO_EN, HIGH);
|
io.digitalWrite(EXPANDS_GPIO_EN, HIGH);
|
||||||
io.pinMode(EXPANDS_SD_PULLEN, INPUT);
|
io.pinMode(EXPANDS_SD_PULLEN, INPUT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
concurrency::hasBeenSetup = true;
|
concurrency::hasBeenSetup = true;
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
SPISettings spiSettings(portduino_config.spiSpeed, MSBFIRST, SPI_MODE0);
|
SPISettings spiSettings(portduino_config.spiSpeed, MSBFIRST, SPI_MODE0);
|
||||||
@@ -546,6 +545,12 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
pinMode(LORA_CS, OUTPUT);
|
||||||
|
digitalWrite(LORA_CS, 1);
|
||||||
|
c6l_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PIN_LCD_RESET
|
#ifdef PIN_LCD_RESET
|
||||||
// FIXME - move this someplace better, LCD is at address 0x3F
|
// FIXME - move this someplace better, LCD is at address 0x3F
|
||||||
pinMode(PIN_LCD_RESET, OUTPUT);
|
pinMode(PIN_LCD_RESET, OUTPUT);
|
||||||
@@ -879,7 +884,8 @@ void setup()
|
|||||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
||||||
|
|
||||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
||||||
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS)
|
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || \
|
||||||
|
defined(USE_SPISSD1306)
|
||||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||||
#elif defined(ARCH_PORTDUINO)
|
#elif defined(ARCH_PORTDUINO)
|
||||||
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || portduino_config.displayPanel) &&
|
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || portduino_config.displayPanel) &&
|
||||||
@@ -1142,7 +1148,8 @@ void setup()
|
|||||||
// Don't call screen setup until after nodedb is setup (because we need
|
// Don't call screen setup until after nodedb is setup (because we need
|
||||||
// the current region name)
|
// the current region name)
|
||||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
||||||
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS)
|
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || \
|
||||||
|
defined(USE_SPISSD1306)
|
||||||
if (screen)
|
if (screen)
|
||||||
screen->setup();
|
screen->setup();
|
||||||
#elif defined(ARCH_PORTDUINO)
|
#elif defined(ARCH_PORTDUINO)
|
||||||
@@ -1506,9 +1513,6 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
|||||||
deviceMetadata.hw_model = HW_VENDOR;
|
deviceMetadata.hw_model = HW_VENDOR;
|
||||||
deviceMetadata.hasRemoteHardware = moduleConfig.remote_hardware.enabled;
|
deviceMetadata.hasRemoteHardware = moduleConfig.remote_hardware.enabled;
|
||||||
deviceMetadata.excluded_modules = meshtastic_ExcludedModules_EXCLUDED_NONE;
|
deviceMetadata.excluded_modules = meshtastic_ExcludedModules_EXCLUDED_NONE;
|
||||||
#if MESHTASTIC_EXCLUDE_MQTT
|
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_MQTT_CONFIG;
|
|
||||||
#endif
|
|
||||||
#if MESHTASTIC_EXCLUDE_REMOTEHARDWARE
|
#if MESHTASTIC_EXCLUDE_REMOTEHARDWARE
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_REMOTEHARDWARE_CONFIG;
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_REMOTEHARDWARE_CONFIG;
|
||||||
#endif
|
#endif
|
||||||
@@ -1531,21 +1535,10 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
|||||||
#if NO_EXT_GPIO && NO_GPS || MESHTASTIC_EXCLUDE_SERIAL
|
#if NO_EXT_GPIO && NO_GPS || MESHTASTIC_EXCLUDE_SERIAL
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_SERIAL_CONFIG;
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_SERIAL_CONFIG;
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
#ifndef ARCH_ESP32
|
||||||
// PAXCOUNTER is only supported on ESP32 due to memory constraints
|
|
||||||
#else
|
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_PAXCOUNTER_CONFIG;
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_PAXCOUNTER_CONFIG;
|
||||||
#endif
|
#endif
|
||||||
#if MESHTASTIC_EXCLUDE_STOREFORWARD
|
#if !defined(HAS_RGB_LED) && !RAK_4631
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_STOREFORWARD_CONFIG;
|
|
||||||
#endif
|
|
||||||
#if MESHTASTIC_EXCLUDE_RANGETEST
|
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_RANGETEST_CONFIG;
|
|
||||||
#endif
|
|
||||||
#if MESHTASTIC_EXCLUDE_NEIGHBORINFO
|
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_NEIGHBORINFO_CONFIG;
|
|
||||||
#endif
|
|
||||||
#if (!defined(HAS_RGB_LED) && !defined(RAK_4631)) || defined(MESHTASTIC_EXCLUDE_AMBIENTLIGHTING)
|
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AMBIENTLIGHTING_CONFIG;
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AMBIENTLIGHTING_CONFIG;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -423,6 +423,33 @@ bool Channels::decryptForHash(ChannelIndex chIndex, ChannelHash channelHash)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Channels::setDefaultPresetCryptoForHash(ChannelHash channelHash)
|
||||||
|
{
|
||||||
|
// Iterate all known presets
|
||||||
|
for (int preset = _meshtastic_Config_LoRaConfig_ModemPreset_MIN; preset <= _meshtastic_Config_LoRaConfig_ModemPreset_MAX;
|
||||||
|
++preset) {
|
||||||
|
const char *name =
|
||||||
|
DisplayFormatters::getModemPresetDisplayName((meshtastic_Config_LoRaConfig_ModemPreset)preset, false, false);
|
||||||
|
if (!name)
|
||||||
|
continue;
|
||||||
|
if (strcmp(name, "Invalid") == 0)
|
||||||
|
continue; // skip invalid placeholder
|
||||||
|
uint8_t h = xorHash((const uint8_t *)name, strlen(name));
|
||||||
|
// Expand default PSK alias 1 to actual bytes and xor into hash
|
||||||
|
uint8_t tmp = h ^ xorHash(defaultpsk, sizeof(defaultpsk));
|
||||||
|
if (tmp == channelHash) {
|
||||||
|
// Set crypto to defaultpsk and report success
|
||||||
|
CryptoKey k;
|
||||||
|
memcpy(k.bytes, defaultpsk, sizeof(defaultpsk));
|
||||||
|
k.length = sizeof(defaultpsk);
|
||||||
|
crypto->setKey(k);
|
||||||
|
LOG_INFO("Matched default preset '%s' for hash 0x%x; set default PSK", name, channelHash);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured)
|
/** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured)
|
||||||
*
|
*
|
||||||
* This method is called before encoding outbound packets
|
* This method is called before encoding outbound packets
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ class Channels
|
|||||||
|
|
||||||
bool ensureLicensedOperation();
|
bool ensureLicensedOperation();
|
||||||
|
|
||||||
|
bool setDefaultPresetCryptoForHash(ChannelHash channelHash);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Given a channel index, change to use the crypto key specified by that index
|
/** Given a channel index, change to use the crypto key specified by that index
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-21
@@ -663,7 +663,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
config.bluetooth.fixed_pin = defaultBLEPin;
|
config.bluetooth.fixed_pin = defaultBLEPin;
|
||||||
|
|
||||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \
|
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \
|
||||||
defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS)
|
defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_SPISSD1306)
|
||||||
bool hasScreen = true;
|
bool hasScreen = true;
|
||||||
#ifdef HELTEC_MESH_NODE_T114
|
#ifdef HELTEC_MESH_NODE_T114
|
||||||
uint32_t st7789_id = get_st7789_id(ST7789_NSS, ST7789_SCK, ST7789_SDA, ST7789_RS, ST7789_RESET);
|
uint32_t st7789_id = get_st7789_id(ST7789_NSS, ST7789_SCK, ST7789_SDA, ST7789_RS, ST7789_RESET);
|
||||||
@@ -775,9 +775,7 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
|
|
||||||
moduleConfig.version = DEVICESTATE_CUR_VER;
|
moduleConfig.version = DEVICESTATE_CUR_VER;
|
||||||
moduleConfig.has_mqtt = true;
|
moduleConfig.has_mqtt = true;
|
||||||
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
|
||||||
moduleConfig.has_range_test = true;
|
moduleConfig.has_range_test = true;
|
||||||
#endif
|
|
||||||
moduleConfig.has_serial = true;
|
moduleConfig.has_serial = true;
|
||||||
moduleConfig.has_store_forward = true;
|
moduleConfig.has_store_forward = true;
|
||||||
moduleConfig.has_telemetry = true;
|
moduleConfig.has_telemetry = true;
|
||||||
@@ -843,12 +841,6 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
moduleConfig.canned_message.inputbroker_event_press = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
moduleConfig.canned_message.inputbroker_event_press = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||||
#endif
|
#endif
|
||||||
moduleConfig.has_canned_message = true;
|
moduleConfig.has_canned_message = true;
|
||||||
#if !MESHTASTIC_EXCLUDE_AUDIO
|
|
||||||
moduleConfig.has_audio = true;
|
|
||||||
#endif
|
|
||||||
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
|
||||||
moduleConfig.has_paxcounter = true;
|
|
||||||
#endif
|
|
||||||
#if USERPREFS_MQTT_ENABLED && !MESHTASTIC_EXCLUDE_MQTT
|
#if USERPREFS_MQTT_ENABLED && !MESHTASTIC_EXCLUDE_MQTT
|
||||||
moduleConfig.mqtt.enabled = true;
|
moduleConfig.mqtt.enabled = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -891,14 +883,12 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
moduleConfig.detection_sensor.detection_trigger_type = meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_HIGH;
|
moduleConfig.detection_sensor.detection_trigger_type = meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_HIGH;
|
||||||
moduleConfig.detection_sensor.minimum_broadcast_secs = 45;
|
moduleConfig.detection_sensor.minimum_broadcast_secs = 45;
|
||||||
|
|
||||||
#if !MESHTASTIC_EXCLUDE_AMBIENTLIGHTING
|
|
||||||
moduleConfig.has_ambient_lighting = true;
|
moduleConfig.has_ambient_lighting = true;
|
||||||
moduleConfig.ambient_lighting.current = 10;
|
moduleConfig.ambient_lighting.current = 10;
|
||||||
// Default to a color based on our node number
|
// Default to a color based on our node number
|
||||||
moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
|
moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
|
||||||
moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
|
moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
|
||||||
moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
|
moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
|
||||||
#endif
|
|
||||||
|
|
||||||
initModuleConfigIntervals();
|
initModuleConfigIntervals();
|
||||||
}
|
}
|
||||||
@@ -1438,25 +1428,15 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
|||||||
moduleConfig.has_canned_message = true;
|
moduleConfig.has_canned_message = true;
|
||||||
moduleConfig.has_external_notification = true;
|
moduleConfig.has_external_notification = true;
|
||||||
moduleConfig.has_mqtt = true;
|
moduleConfig.has_mqtt = true;
|
||||||
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
|
||||||
moduleConfig.has_range_test = true;
|
moduleConfig.has_range_test = true;
|
||||||
#endif
|
|
||||||
moduleConfig.has_serial = true;
|
moduleConfig.has_serial = true;
|
||||||
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
|
||||||
moduleConfig.has_store_forward = true;
|
moduleConfig.has_store_forward = true;
|
||||||
#endif
|
|
||||||
moduleConfig.has_telemetry = true;
|
moduleConfig.has_telemetry = true;
|
||||||
moduleConfig.has_neighbor_info = true;
|
moduleConfig.has_neighbor_info = true;
|
||||||
moduleConfig.has_detection_sensor = true;
|
moduleConfig.has_detection_sensor = true;
|
||||||
#if !MESHTASTIC_EXCLUDE_AMBIENTLIGHTING
|
|
||||||
moduleConfig.has_ambient_lighting = true;
|
moduleConfig.has_ambient_lighting = true;
|
||||||
#endif
|
|
||||||
#if !MESHTASTIC_EXCLUDE_AUDIO
|
|
||||||
moduleConfig.has_audio = true;
|
moduleConfig.has_audio = true;
|
||||||
#endif
|
|
||||||
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
|
||||||
moduleConfig.has_paxcounter = true;
|
moduleConfig.has_paxcounter = true;
|
||||||
#endif
|
|
||||||
|
|
||||||
success &=
|
success &=
|
||||||
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||||
|
|||||||
@@ -34,21 +34,6 @@
|
|||||||
// Flag to indicate a heartbeat was received and we should send queue status
|
// Flag to indicate a heartbeat was received and we should send queue status
|
||||||
bool heartbeatReceived = false;
|
bool heartbeatReceived = false;
|
||||||
|
|
||||||
// Helper function to skip excluded module configs and advance state
|
|
||||||
size_t PhoneAPI::skipExcludedModuleConfig(uint8_t *buf)
|
|
||||||
{
|
|
||||||
config_state++;
|
|
||||||
if (config_state > (_meshtastic_AdminMessage_ModuleConfigType_MAX + 1)) {
|
|
||||||
if (config_nonce == SPECIAL_NONCE_ONLY_CONFIG) {
|
|
||||||
state = STATE_SEND_FILEMANIFEST;
|
|
||||||
} else {
|
|
||||||
state = STATE_SEND_OTHER_NODEINFOS;
|
|
||||||
}
|
|
||||||
config_state = 0;
|
|
||||||
}
|
|
||||||
return getFromRadio(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
PhoneAPI::PhoneAPI()
|
PhoneAPI::PhoneAPI()
|
||||||
{
|
{
|
||||||
lastContactMsec = millis();
|
lastContactMsec = millis();
|
||||||
@@ -370,35 +355,20 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
|
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
|
||||||
break;
|
break;
|
||||||
case meshtastic_ModuleConfig_external_notification_tag:
|
case meshtastic_ModuleConfig_external_notification_tag:
|
||||||
#if !(NO_EXT_GPIO || MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION)
|
|
||||||
LOG_DEBUG("Send module config: ext notification");
|
LOG_DEBUG("Send module config: ext notification");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
|
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
|
||||||
break;
|
break;
|
||||||
#else
|
|
||||||
LOG_DEBUG("External Notification module excluded from build, skipping");
|
|
||||||
return skipExcludedModuleConfig(buf);
|
|
||||||
#endif
|
|
||||||
case meshtastic_ModuleConfig_store_forward_tag:
|
case meshtastic_ModuleConfig_store_forward_tag:
|
||||||
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
|
||||||
LOG_DEBUG("Send module config: store forward");
|
LOG_DEBUG("Send module config: store forward");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.store_forward = moduleConfig.store_forward;
|
fromRadioScratch.moduleConfig.payload_variant.store_forward = moduleConfig.store_forward;
|
||||||
break;
|
break;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Store & Forward module excluded from build, skipping");
|
|
||||||
return skipExcludedModuleConfig(buf);
|
|
||||||
#endif
|
|
||||||
case meshtastic_ModuleConfig_range_test_tag:
|
case meshtastic_ModuleConfig_range_test_tag:
|
||||||
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
|
||||||
LOG_DEBUG("Send module config: range test");
|
LOG_DEBUG("Send module config: range test");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
|
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
|
||||||
break;
|
break;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Range Test module excluded from build, skipping");
|
|
||||||
return skipExcludedModuleConfig(buf);
|
|
||||||
#endif
|
|
||||||
case meshtastic_ModuleConfig_telemetry_tag:
|
case meshtastic_ModuleConfig_telemetry_tag:
|
||||||
LOG_DEBUG("Send module config: telemetry");
|
LOG_DEBUG("Send module config: telemetry");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_telemetry_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_telemetry_tag;
|
||||||
@@ -410,15 +380,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
|
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
|
||||||
break;
|
break;
|
||||||
case meshtastic_ModuleConfig_audio_tag:
|
case meshtastic_ModuleConfig_audio_tag:
|
||||||
#if !MESHTASTIC_EXCLUDE_AUDIO
|
|
||||||
LOG_DEBUG("Send module config: audio");
|
LOG_DEBUG("Send module config: audio");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.audio = moduleConfig.audio;
|
fromRadioScratch.moduleConfig.payload_variant.audio = moduleConfig.audio;
|
||||||
break;
|
break;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Audio module excluded from build, skipping");
|
|
||||||
return skipExcludedModuleConfig(buf);
|
|
||||||
#endif
|
|
||||||
case meshtastic_ModuleConfig_remote_hardware_tag:
|
case meshtastic_ModuleConfig_remote_hardware_tag:
|
||||||
LOG_DEBUG("Send module config: remote hardware");
|
LOG_DEBUG("Send module config: remote hardware");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
||||||
@@ -435,25 +400,15 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
fromRadioScratch.moduleConfig.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
fromRadioScratch.moduleConfig.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
||||||
break;
|
break;
|
||||||
case meshtastic_ModuleConfig_ambient_lighting_tag:
|
case meshtastic_ModuleConfig_ambient_lighting_tag:
|
||||||
#if !MESHTASTIC_EXCLUDE_AMBIENTLIGHTING
|
|
||||||
LOG_DEBUG("Send module config: ambient lighting");
|
LOG_DEBUG("Send module config: ambient lighting");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
fromRadioScratch.moduleConfig.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
||||||
break;
|
break;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Ambient Lighting module excluded from build, skipping");
|
|
||||||
return skipExcludedModuleConfig(buf);
|
|
||||||
#endif
|
|
||||||
case meshtastic_ModuleConfig_paxcounter_tag:
|
case meshtastic_ModuleConfig_paxcounter_tag:
|
||||||
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
|
||||||
LOG_DEBUG("Send module config: paxcounter");
|
LOG_DEBUG("Send module config: paxcounter");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.paxcounter = moduleConfig.paxcounter;
|
fromRadioScratch.moduleConfig.payload_variant.paxcounter = moduleConfig.paxcounter;
|
||||||
break;
|
break;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Paxcounter module excluded from build, skipping");
|
|
||||||
return skipExcludedModuleConfig(buf);
|
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Unknown module config type %d", config_state);
|
LOG_ERROR("Unknown module config type %d", config_state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,4 @@ class PhoneAPI
|
|||||||
|
|
||||||
/// If the mesh service tells us fromNum has changed, tell the phone
|
/// If the mesh service tells us fromNum has changed, tell the phone
|
||||||
virtual int onNotify(uint32_t newValue) override;
|
virtual int onNotify(uint32_t newValue) override;
|
||||||
|
|
||||||
/// Helper function to skip excluded module configs and advance state
|
|
||||||
size_t skipExcludedModuleConfig(uint8_t *buf);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -430,6 +430,36 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAS_UDP_MULTICAST
|
||||||
|
// Fallback: for UDP multicast, try default preset names with default PSK if normal channel match failed
|
||||||
|
if (!decrypted && p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP) {
|
||||||
|
if (channels.setDefaultPresetCryptoForHash(p->channel)) {
|
||||||
|
memcpy(bytes, p->encrypted.bytes, rawSize);
|
||||||
|
crypto->decrypt(p->from, p->id, rawSize, bytes);
|
||||||
|
|
||||||
|
meshtastic_Data decodedtmp;
|
||||||
|
memset(&decodedtmp, 0, sizeof(decodedtmp));
|
||||||
|
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp) &&
|
||||||
|
decodedtmp.portnum != meshtastic_PortNum_UNKNOWN_APP) {
|
||||||
|
p->decoded = decodedtmp;
|
||||||
|
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag;
|
||||||
|
// Map to our local default channel index (name+PSK default), not necessarily primary
|
||||||
|
ChannelIndex defaultIndex = channels.getPrimaryIndex();
|
||||||
|
for (ChannelIndex i = 0; i < channels.getNumChannels(); ++i) {
|
||||||
|
if (channels.isDefaultChannel(i)) {
|
||||||
|
defaultIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chIndex = defaultIndex;
|
||||||
|
decrypted = true;
|
||||||
|
} else {
|
||||||
|
LOG_WARN("UDP fallback decode attempted but failed for hash 0x%x", p->channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (decrypted) {
|
if (decrypted) {
|
||||||
// parsing was successful
|
// parsing was successful
|
||||||
p->channel = chIndex; // change to store the index instead of the hash
|
p->channel = chIndex; // change to store the index instead of the hash
|
||||||
|
|||||||
@@ -50,15 +50,15 @@ class StreamAPI : public PhoneAPI
|
|||||||
* phone.
|
* phone.
|
||||||
*/
|
*/
|
||||||
virtual int32_t runOncePart();
|
virtual int32_t runOncePart();
|
||||||
virtual int32_t runOncePart(char *buf,uint16_t bufLen);
|
virtual int32_t runOncePart(char *buf, uint16_t bufLen);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Read any rx chars from the link and call handleToRadio
|
* Read any rx chars from the link and call handleToRadio
|
||||||
*/
|
*/
|
||||||
int32_t readStream();
|
int32_t readStream();
|
||||||
int32_t readStream(char *buf,uint16_t bufLen);
|
int32_t readStream(char *buf, uint16_t bufLen);
|
||||||
int32_t handleRecStream(char *buf,uint16_t bufLen);
|
int32_t handleRecStream(char *buf, uint16_t bufLen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* call getFromRadio() and deliver encapsulated packets to the Stream
|
* call getFromRadio() and deliver encapsulated packets to the Stream
|
||||||
|
|||||||
@@ -173,28 +173,10 @@ typedef enum _meshtastic_Config_NetworkConfig_ProtocolFlags {
|
|||||||
meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST = 1
|
meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST = 1
|
||||||
} meshtastic_Config_NetworkConfig_ProtocolFlags;
|
} meshtastic_Config_NetworkConfig_ProtocolFlags;
|
||||||
|
|
||||||
/* How the GPS coordinates are displayed on the OLED screen. */
|
/* Deprecated in 2.7.4: Unused */
|
||||||
typedef enum _meshtastic_Config_DisplayConfig_GpsCoordinateFormat {
|
typedef enum _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat {
|
||||||
/* GPS coordinates are displayed in the normal decimal degrees format:
|
meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED = 0
|
||||||
DD.DDDDDD DDD.DDDDDD */
|
} meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat;
|
||||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC = 0,
|
|
||||||
/* GPS coordinates are displayed in the degrees minutes seconds format:
|
|
||||||
DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant */
|
|
||||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS = 1,
|
|
||||||
/* Universal Transverse Mercator format:
|
|
||||||
ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing */
|
|
||||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_UTM = 2,
|
|
||||||
/* Military Grid Reference System format:
|
|
||||||
ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square,
|
|
||||||
E is easting, N is northing */
|
|
||||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MGRS = 3,
|
|
||||||
/* Open Location Code (aka Plus Codes). */
|
|
||||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OLC = 4,
|
|
||||||
/* Ordnance Survey Grid Reference (the National Grid System of the UK).
|
|
||||||
Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square,
|
|
||||||
E is the easting, N is the northing */
|
|
||||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR = 5
|
|
||||||
} meshtastic_Config_DisplayConfig_GpsCoordinateFormat;
|
|
||||||
|
|
||||||
/* Unit display preference */
|
/* Unit display preference */
|
||||||
typedef enum _meshtastic_Config_DisplayConfig_DisplayUnits {
|
typedef enum _meshtastic_Config_DisplayConfig_DisplayUnits {
|
||||||
@@ -491,7 +473,7 @@ typedef struct _meshtastic_Config_DisplayConfig {
|
|||||||
uint32_t screen_on_secs;
|
uint32_t screen_on_secs;
|
||||||
/* Deprecated in 2.7.4: Unused
|
/* Deprecated in 2.7.4: Unused
|
||||||
How the GPS coordinates are formatted on the OLED screen. */
|
How the GPS coordinates are formatted on the OLED screen. */
|
||||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat gps_format;
|
meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat gps_format;
|
||||||
/* Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds.
|
/* Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds.
|
||||||
Potentially useful for devices without user buttons. */
|
Potentially useful for devices without user buttons. */
|
||||||
uint32_t auto_screen_carousel_secs;
|
uint32_t auto_screen_carousel_secs;
|
||||||
@@ -515,6 +497,9 @@ typedef struct _meshtastic_Config_DisplayConfig {
|
|||||||
/* If false (default), the device will display the time in 24-hour format on screen.
|
/* If false (default), the device will display the time in 24-hour format on screen.
|
||||||
If true, the device will display the time in 12-hour format on screen. */
|
If true, the device will display the time in 12-hour format on screen. */
|
||||||
bool use_12h_clock;
|
bool use_12h_clock;
|
||||||
|
/* If false (default), the device will use short names for various display screens.
|
||||||
|
If true, node names will show in long format */
|
||||||
|
bool use_long_node_name;
|
||||||
} meshtastic_Config_DisplayConfig;
|
} meshtastic_Config_DisplayConfig;
|
||||||
|
|
||||||
/* Lora Config */
|
/* Lora Config */
|
||||||
@@ -678,9 +663,9 @@ extern "C" {
|
|||||||
#define _meshtastic_Config_NetworkConfig_ProtocolFlags_MAX meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST
|
#define _meshtastic_Config_NetworkConfig_ProtocolFlags_MAX meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST
|
||||||
#define _meshtastic_Config_NetworkConfig_ProtocolFlags_ARRAYSIZE ((meshtastic_Config_NetworkConfig_ProtocolFlags)(meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST+1))
|
#define _meshtastic_Config_NetworkConfig_ProtocolFlags_ARRAYSIZE ((meshtastic_Config_NetworkConfig_ProtocolFlags)(meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC
|
#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED
|
||||||
#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MAX meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR
|
#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MAX meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED
|
||||||
#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_ARRAYSIZE ((meshtastic_Config_DisplayConfig_GpsCoordinateFormat)(meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR+1))
|
#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat)(meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_DisplayConfig_DisplayUnits_MIN meshtastic_Config_DisplayConfig_DisplayUnits_METRIC
|
#define _meshtastic_Config_DisplayConfig_DisplayUnits_MIN meshtastic_Config_DisplayConfig_DisplayUnits_METRIC
|
||||||
#define _meshtastic_Config_DisplayConfig_DisplayUnits_MAX meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL
|
#define _meshtastic_Config_DisplayConfig_DisplayUnits_MAX meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL
|
||||||
@@ -721,7 +706,7 @@ extern "C" {
|
|||||||
#define meshtastic_Config_NetworkConfig_address_mode_ENUMTYPE meshtastic_Config_NetworkConfig_AddressMode
|
#define meshtastic_Config_NetworkConfig_address_mode_ENUMTYPE meshtastic_Config_NetworkConfig_AddressMode
|
||||||
|
|
||||||
|
|
||||||
#define meshtastic_Config_DisplayConfig_gps_format_ENUMTYPE meshtastic_Config_DisplayConfig_GpsCoordinateFormat
|
#define meshtastic_Config_DisplayConfig_gps_format_ENUMTYPE meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat
|
||||||
#define meshtastic_Config_DisplayConfig_units_ENUMTYPE meshtastic_Config_DisplayConfig_DisplayUnits
|
#define meshtastic_Config_DisplayConfig_units_ENUMTYPE meshtastic_Config_DisplayConfig_DisplayUnits
|
||||||
#define meshtastic_Config_DisplayConfig_oled_ENUMTYPE meshtastic_Config_DisplayConfig_OledType
|
#define meshtastic_Config_DisplayConfig_oled_ENUMTYPE meshtastic_Config_DisplayConfig_OledType
|
||||||
#define meshtastic_Config_DisplayConfig_displaymode_ENUMTYPE meshtastic_Config_DisplayConfig_DisplayMode
|
#define meshtastic_Config_DisplayConfig_displaymode_ENUMTYPE meshtastic_Config_DisplayConfig_DisplayMode
|
||||||
@@ -742,7 +727,7 @@ extern "C" {
|
|||||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0, 0}
|
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0, 0}
|
||||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
||||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0}
|
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0, 0}
|
||||||
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0}
|
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0}
|
||||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||||
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
|
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
|
||||||
@@ -753,7 +738,7 @@ extern "C" {
|
|||||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0, 0}
|
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0, 0}
|
||||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
||||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0}
|
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0, 0}
|
||||||
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0}
|
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0}
|
||||||
#define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
#define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||||
#define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
|
#define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
|
||||||
@@ -820,6 +805,7 @@ extern "C" {
|
|||||||
#define meshtastic_Config_DisplayConfig_wake_on_tap_or_motion_tag 10
|
#define meshtastic_Config_DisplayConfig_wake_on_tap_or_motion_tag 10
|
||||||
#define meshtastic_Config_DisplayConfig_compass_orientation_tag 11
|
#define meshtastic_Config_DisplayConfig_compass_orientation_tag 11
|
||||||
#define meshtastic_Config_DisplayConfig_use_12h_clock_tag 12
|
#define meshtastic_Config_DisplayConfig_use_12h_clock_tag 12
|
||||||
|
#define meshtastic_Config_DisplayConfig_use_long_node_name_tag 13
|
||||||
#define meshtastic_Config_LoRaConfig_use_preset_tag 1
|
#define meshtastic_Config_LoRaConfig_use_preset_tag 1
|
||||||
#define meshtastic_Config_LoRaConfig_modem_preset_tag 2
|
#define meshtastic_Config_LoRaConfig_modem_preset_tag 2
|
||||||
#define meshtastic_Config_LoRaConfig_bandwidth_tag 3
|
#define meshtastic_Config_LoRaConfig_bandwidth_tag 3
|
||||||
@@ -965,7 +951,8 @@ X(a, STATIC, SINGULAR, UENUM, displaymode, 8) \
|
|||||||
X(a, STATIC, SINGULAR, BOOL, heading_bold, 9) \
|
X(a, STATIC, SINGULAR, BOOL, heading_bold, 9) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, wake_on_tap_or_motion, 10) \
|
X(a, STATIC, SINGULAR, BOOL, wake_on_tap_or_motion, 10) \
|
||||||
X(a, STATIC, SINGULAR, UENUM, compass_orientation, 11) \
|
X(a, STATIC, SINGULAR, UENUM, compass_orientation, 11) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, use_12h_clock, 12)
|
X(a, STATIC, SINGULAR, BOOL, use_12h_clock, 12) \
|
||||||
|
X(a, STATIC, SINGULAR, BOOL, use_long_node_name, 13)
|
||||||
#define meshtastic_Config_DisplayConfig_CALLBACK NULL
|
#define meshtastic_Config_DisplayConfig_CALLBACK NULL
|
||||||
#define meshtastic_Config_DisplayConfig_DEFAULT NULL
|
#define meshtastic_Config_DisplayConfig_DEFAULT NULL
|
||||||
|
|
||||||
@@ -1043,7 +1030,7 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg;
|
|||||||
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
|
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
|
||||||
#define meshtastic_Config_BluetoothConfig_size 10
|
#define meshtastic_Config_BluetoothConfig_size 10
|
||||||
#define meshtastic_Config_DeviceConfig_size 100
|
#define meshtastic_Config_DeviceConfig_size 100
|
||||||
#define meshtastic_Config_DisplayConfig_size 32
|
#define meshtastic_Config_DisplayConfig_size 34
|
||||||
#define meshtastic_Config_LoRaConfig_size 85
|
#define meshtastic_Config_LoRaConfig_size 85
|
||||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||||
#define meshtastic_Config_NetworkConfig_size 204
|
#define meshtastic_Config_NetworkConfig_size 204
|
||||||
|
|||||||
@@ -28,3 +28,5 @@ PB_BIND(meshtastic_Map, meshtastic_Map, AUTO)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,32 @@ typedef enum _meshtastic_Language {
|
|||||||
meshtastic_Language_TRADITIONAL_CHINESE = 31
|
meshtastic_Language_TRADITIONAL_CHINESE = 31
|
||||||
} meshtastic_Language;
|
} meshtastic_Language;
|
||||||
|
|
||||||
|
/* How the GPS coordinates are displayed on the OLED screen. */
|
||||||
|
typedef enum _meshtastic_DeviceUIConfig_GpsCoordinateFormat {
|
||||||
|
/* GPS coordinates are displayed in the normal decimal degrees format:
|
||||||
|
DD.DDDDDD DDD.DDDDDD */
|
||||||
|
meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC = 0,
|
||||||
|
/* GPS coordinates are displayed in the degrees minutes seconds format:
|
||||||
|
DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant */
|
||||||
|
meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS = 1,
|
||||||
|
/* Universal Transverse Mercator format:
|
||||||
|
ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing */
|
||||||
|
meshtastic_DeviceUIConfig_GpsCoordinateFormat_UTM = 2,
|
||||||
|
/* Military Grid Reference System format:
|
||||||
|
ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square,
|
||||||
|
E is easting, N is northing */
|
||||||
|
meshtastic_DeviceUIConfig_GpsCoordinateFormat_MGRS = 3,
|
||||||
|
/* Open Location Code (aka Plus Codes). */
|
||||||
|
meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC = 4,
|
||||||
|
/* Ordnance Survey Grid Reference (the National Grid System of the UK).
|
||||||
|
Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square,
|
||||||
|
E is the easting, N is the northing */
|
||||||
|
meshtastic_DeviceUIConfig_GpsCoordinateFormat_OSGR = 5,
|
||||||
|
/* Maidenhead Locator System
|
||||||
|
Described here: https://en.wikipedia.org/wiki/Maidenhead_Locator_System */
|
||||||
|
meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS = 6
|
||||||
|
} meshtastic_DeviceUIConfig_GpsCoordinateFormat;
|
||||||
|
|
||||||
/* Struct definitions */
|
/* Struct definitions */
|
||||||
typedef struct _meshtastic_NodeFilter {
|
typedef struct _meshtastic_NodeFilter {
|
||||||
/* Filter unknown nodes */
|
/* Filter unknown nodes */
|
||||||
@@ -163,6 +189,8 @@ typedef struct _meshtastic_DeviceUIConfig {
|
|||||||
/* Clockface analog style
|
/* Clockface analog style
|
||||||
true for analog clockface, false for digital clockface */
|
true for analog clockface, false for digital clockface */
|
||||||
bool is_clockface_analog;
|
bool is_clockface_analog;
|
||||||
|
/* How the GPS coordinates are formatted on the OLED screen. */
|
||||||
|
meshtastic_DeviceUIConfig_GpsCoordinateFormat gps_format;
|
||||||
} meshtastic_DeviceUIConfig;
|
} meshtastic_DeviceUIConfig;
|
||||||
|
|
||||||
|
|
||||||
@@ -183,9 +211,14 @@ extern "C" {
|
|||||||
#define _meshtastic_Language_MAX meshtastic_Language_TRADITIONAL_CHINESE
|
#define _meshtastic_Language_MAX meshtastic_Language_TRADITIONAL_CHINESE
|
||||||
#define _meshtastic_Language_ARRAYSIZE ((meshtastic_Language)(meshtastic_Language_TRADITIONAL_CHINESE+1))
|
#define _meshtastic_Language_ARRAYSIZE ((meshtastic_Language)(meshtastic_Language_TRADITIONAL_CHINESE+1))
|
||||||
|
|
||||||
|
#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC
|
||||||
|
#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MAX meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS
|
||||||
|
#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_ARRAYSIZE ((meshtastic_DeviceUIConfig_GpsCoordinateFormat)(meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS+1))
|
||||||
|
|
||||||
#define meshtastic_DeviceUIConfig_theme_ENUMTYPE meshtastic_Theme
|
#define meshtastic_DeviceUIConfig_theme_ENUMTYPE meshtastic_Theme
|
||||||
#define meshtastic_DeviceUIConfig_language_ENUMTYPE meshtastic_Language
|
#define meshtastic_DeviceUIConfig_language_ENUMTYPE meshtastic_Language
|
||||||
#define meshtastic_DeviceUIConfig_compass_mode_ENUMTYPE meshtastic_CompassMode
|
#define meshtastic_DeviceUIConfig_compass_mode_ENUMTYPE meshtastic_CompassMode
|
||||||
|
#define meshtastic_DeviceUIConfig_gps_format_ENUMTYPE meshtastic_DeviceUIConfig_GpsCoordinateFormat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -193,12 +226,12 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
/* Initializer values for message structs */
|
/* Initializer values for message structs */
|
||||||
#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}, false, meshtastic_Map_init_default, _meshtastic_CompassMode_MIN, 0, 0}
|
#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}, false, meshtastic_Map_init_default, _meshtastic_CompassMode_MIN, 0, 0, _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN}
|
||||||
#define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, "", 0}
|
#define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, "", 0}
|
||||||
#define meshtastic_NodeHighlight_init_default {0, 0, 0, 0, ""}
|
#define meshtastic_NodeHighlight_init_default {0, 0, 0, 0, ""}
|
||||||
#define meshtastic_GeoPoint_init_default {0, 0, 0}
|
#define meshtastic_GeoPoint_init_default {0, 0, 0}
|
||||||
#define meshtastic_Map_init_default {false, meshtastic_GeoPoint_init_default, "", 0}
|
#define meshtastic_Map_init_default {false, meshtastic_GeoPoint_init_default, "", 0}
|
||||||
#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}, false, meshtastic_Map_init_zero, _meshtastic_CompassMode_MIN, 0, 0}
|
#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}, false, meshtastic_Map_init_zero, _meshtastic_CompassMode_MIN, 0, 0, _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN}
|
||||||
#define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, "", 0}
|
#define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, "", 0}
|
||||||
#define meshtastic_NodeHighlight_init_zero {0, 0, 0, 0, ""}
|
#define meshtastic_NodeHighlight_init_zero {0, 0, 0, 0, ""}
|
||||||
#define meshtastic_GeoPoint_init_zero {0, 0, 0}
|
#define meshtastic_GeoPoint_init_zero {0, 0, 0}
|
||||||
@@ -241,6 +274,7 @@ extern "C" {
|
|||||||
#define meshtastic_DeviceUIConfig_compass_mode_tag 16
|
#define meshtastic_DeviceUIConfig_compass_mode_tag 16
|
||||||
#define meshtastic_DeviceUIConfig_screen_rgb_color_tag 17
|
#define meshtastic_DeviceUIConfig_screen_rgb_color_tag 17
|
||||||
#define meshtastic_DeviceUIConfig_is_clockface_analog_tag 18
|
#define meshtastic_DeviceUIConfig_is_clockface_analog_tag 18
|
||||||
|
#define meshtastic_DeviceUIConfig_gps_format_tag 19
|
||||||
|
|
||||||
/* Struct field encoding specification for nanopb */
|
/* Struct field encoding specification for nanopb */
|
||||||
#define meshtastic_DeviceUIConfig_FIELDLIST(X, a) \
|
#define meshtastic_DeviceUIConfig_FIELDLIST(X, a) \
|
||||||
@@ -261,7 +295,8 @@ X(a, STATIC, SINGULAR, BYTES, calibration_data, 14) \
|
|||||||
X(a, STATIC, OPTIONAL, MESSAGE, map_data, 15) \
|
X(a, STATIC, OPTIONAL, MESSAGE, map_data, 15) \
|
||||||
X(a, STATIC, SINGULAR, UENUM, compass_mode, 16) \
|
X(a, STATIC, SINGULAR, UENUM, compass_mode, 16) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, screen_rgb_color, 17) \
|
X(a, STATIC, SINGULAR, UINT32, screen_rgb_color, 17) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, is_clockface_analog, 18)
|
X(a, STATIC, SINGULAR, BOOL, is_clockface_analog, 18) \
|
||||||
|
X(a, STATIC, SINGULAR, UENUM, gps_format, 19)
|
||||||
#define meshtastic_DeviceUIConfig_CALLBACK NULL
|
#define meshtastic_DeviceUIConfig_CALLBACK NULL
|
||||||
#define meshtastic_DeviceUIConfig_DEFAULT NULL
|
#define meshtastic_DeviceUIConfig_DEFAULT NULL
|
||||||
#define meshtastic_DeviceUIConfig_node_filter_MSGTYPE meshtastic_NodeFilter
|
#define meshtastic_DeviceUIConfig_node_filter_MSGTYPE meshtastic_NodeFilter
|
||||||
@@ -318,7 +353,7 @@ extern const pb_msgdesc_t meshtastic_Map_msg;
|
|||||||
|
|
||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define MESHTASTIC_MESHTASTIC_DEVICE_UI_PB_H_MAX_SIZE meshtastic_DeviceUIConfig_size
|
#define MESHTASTIC_MESHTASTIC_DEVICE_UI_PB_H_MAX_SIZE meshtastic_DeviceUIConfig_size
|
||||||
#define meshtastic_DeviceUIConfig_size 201
|
#define meshtastic_DeviceUIConfig_size 204
|
||||||
#define meshtastic_GeoPoint_size 33
|
#define meshtastic_GeoPoint_size 33
|
||||||
#define meshtastic_Map_size 58
|
#define meshtastic_Map_size 58
|
||||||
#define meshtastic_NodeFilter_size 47
|
#define meshtastic_NodeFilter_size 47
|
||||||
|
|||||||
@@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
|
|||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
/* meshtastic_NodeDatabase_size depends on runtime parameters */
|
/* meshtastic_NodeDatabase_size depends on runtime parameters */
|
||||||
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
|
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
|
||||||
#define meshtastic_BackupPreferences_size 2273
|
#define meshtastic_BackupPreferences_size 2277
|
||||||
#define meshtastic_ChannelFile_size 718
|
#define meshtastic_ChannelFile_size 718
|
||||||
#define meshtastic_DeviceState_size 1737
|
#define meshtastic_DeviceState_size 1737
|
||||||
#define meshtastic_NodeInfoLite_size 196
|
#define meshtastic_NodeInfoLite_size 196
|
||||||
|
|||||||
@@ -187,8 +187,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
|||||||
|
|
||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size
|
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size
|
||||||
#define meshtastic_LocalConfig_size 747
|
#define meshtastic_LocalConfig_size 749
|
||||||
#define meshtastic_LocalModuleConfig_size 671
|
#define meshtastic_LocalModuleConfig_size 673
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
|||||||
@@ -259,8 +259,8 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
meshtastic_HardwareModel_T_DECK_PRO = 102,
|
meshtastic_HardwareModel_T_DECK_PRO = 102,
|
||||||
/* Lilygo TLora Pager */
|
/* Lilygo TLora Pager */
|
||||||
meshtastic_HardwareModel_T_LORA_PAGER = 103,
|
meshtastic_HardwareModel_T_LORA_PAGER = 103,
|
||||||
/* GAT562 Mesh Trial Tracker */
|
/* M5Stack Reserved */
|
||||||
meshtastic_HardwareModel_GAT562_MESH_TRIAL_TRACKER = 104,
|
meshtastic_HardwareModel_M5STACK_RESERVED = 104, /* 0x68 */
|
||||||
/* RAKwireless WisMesh Tag */
|
/* RAKwireless WisMesh Tag */
|
||||||
meshtastic_HardwareModel_WISMESH_TAG = 105,
|
meshtastic_HardwareModel_WISMESH_TAG = 105,
|
||||||
/* RAKwireless WisBlock Core RAK3312 https://docs.rakwireless.com/product-categories/wisduo/rak3112-module/overview/ */
|
/* RAKwireless WisBlock Core RAK3312 https://docs.rakwireless.com/product-categories/wisduo/rak3112-module/overview/ */
|
||||||
@@ -274,6 +274,10 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
meshtastic_HardwareModel_T_ECHO_LITE = 109,
|
meshtastic_HardwareModel_T_ECHO_LITE = 109,
|
||||||
/* New Heltec LoRA32 with ESP32-S3 CPU */
|
/* New Heltec LoRA32 with ESP32-S3 CPU */
|
||||||
meshtastic_HardwareModel_HELTEC_V4 = 110,
|
meshtastic_HardwareModel_HELTEC_V4 = 110,
|
||||||
|
/* M5Stack C6L */
|
||||||
|
meshtastic_HardwareModel_M5STACK_C6L = 111,
|
||||||
|
/* M5Stack Cardputer Adv */
|
||||||
|
meshtastic_HardwareModel_M5STACK_CARDPUTER_ADV = 112,
|
||||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
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.
|
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.
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||||
|
|||||||
@@ -356,6 +356,9 @@ typedef struct _meshtastic_ModuleConfig_TelemetryConfig {
|
|||||||
uint32_t health_update_interval;
|
uint32_t health_update_interval;
|
||||||
/* Enable/Disable the health telemetry module on-device display */
|
/* Enable/Disable the health telemetry module on-device display */
|
||||||
bool health_screen_enabled;
|
bool health_screen_enabled;
|
||||||
|
/* Enable/Disable the device telemetry module to send metrics to the mesh
|
||||||
|
Note: We will still send telemtry to the connected phone / client every minute over the API */
|
||||||
|
bool device_telemetry_enabled;
|
||||||
} meshtastic_ModuleConfig_TelemetryConfig;
|
} meshtastic_ModuleConfig_TelemetryConfig;
|
||||||
|
|
||||||
/* Canned Messages Module Config */
|
/* Canned Messages Module Config */
|
||||||
@@ -523,7 +526,7 @@ extern "C" {
|
|||||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0, 0}
|
||||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||||
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0}
|
||||||
#define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN}
|
#define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN}
|
||||||
@@ -539,7 +542,7 @@ extern "C" {
|
|||||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0, 0}
|
||||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
#define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||||
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0}
|
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0}
|
||||||
#define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN}
|
#define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN}
|
||||||
@@ -627,6 +630,7 @@ extern "C" {
|
|||||||
#define meshtastic_ModuleConfig_TelemetryConfig_health_measurement_enabled_tag 11
|
#define meshtastic_ModuleConfig_TelemetryConfig_health_measurement_enabled_tag 11
|
||||||
#define meshtastic_ModuleConfig_TelemetryConfig_health_update_interval_tag 12
|
#define meshtastic_ModuleConfig_TelemetryConfig_health_update_interval_tag 12
|
||||||
#define meshtastic_ModuleConfig_TelemetryConfig_health_screen_enabled_tag 13
|
#define meshtastic_ModuleConfig_TelemetryConfig_health_screen_enabled_tag 13
|
||||||
|
#define meshtastic_ModuleConfig_TelemetryConfig_device_telemetry_enabled_tag 14
|
||||||
#define meshtastic_ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1
|
#define meshtastic_ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1
|
||||||
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2
|
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2
|
||||||
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3
|
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3
|
||||||
@@ -825,7 +829,8 @@ X(a, STATIC, SINGULAR, UINT32, power_update_interval, 9) \
|
|||||||
X(a, STATIC, SINGULAR, BOOL, power_screen_enabled, 10) \
|
X(a, STATIC, SINGULAR, BOOL, power_screen_enabled, 10) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, health_measurement_enabled, 11) \
|
X(a, STATIC, SINGULAR, BOOL, health_measurement_enabled, 11) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, health_update_interval, 12) \
|
X(a, STATIC, SINGULAR, UINT32, health_update_interval, 12) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, health_screen_enabled, 13)
|
X(a, STATIC, SINGULAR, BOOL, health_screen_enabled, 13) \
|
||||||
|
X(a, STATIC, SINGULAR, BOOL, device_telemetry_enabled, 14)
|
||||||
#define meshtastic_ModuleConfig_TelemetryConfig_CALLBACK NULL
|
#define meshtastic_ModuleConfig_TelemetryConfig_CALLBACK NULL
|
||||||
#define meshtastic_ModuleConfig_TelemetryConfig_DEFAULT NULL
|
#define meshtastic_ModuleConfig_TelemetryConfig_DEFAULT NULL
|
||||||
|
|
||||||
@@ -910,7 +915,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
|
|||||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96
|
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96
|
||||||
#define meshtastic_ModuleConfig_SerialConfig_size 28
|
#define meshtastic_ModuleConfig_SerialConfig_size 28
|
||||||
#define meshtastic_ModuleConfig_StoreForwardConfig_size 24
|
#define meshtastic_ModuleConfig_StoreForwardConfig_size 24
|
||||||
#define meshtastic_ModuleConfig_TelemetryConfig_size 46
|
#define meshtastic_ModuleConfig_TelemetryConfig_size 48
|
||||||
#define meshtastic_ModuleConfig_size 227
|
#define meshtastic_ModuleConfig_size 227
|
||||||
#define meshtastic_RemoteHardwarePin_size 21
|
#define meshtastic_RemoteHardwarePin_size 21
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ class UdpMulticastHandler final
|
|||||||
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
|
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
|
||||||
#endif
|
#endif
|
||||||
meshtastic_MeshPacket mp;
|
meshtastic_MeshPacket mp;
|
||||||
mp.transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP;
|
|
||||||
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetLength);
|
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetLength);
|
||||||
bool isPacketDecoded = pb_decode_from_bytes(packet.data(), packetLength, &meshtastic_MeshPacket_msg, &mp);
|
bool isPacketDecoded = pb_decode_from_bytes(packet.data(), packetLength, &meshtastic_MeshPacket_msg, &mp);
|
||||||
if (isPacketDecoded && router && mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
|
if (isPacketDecoded && router && mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
|
||||||
|
mp.transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP;
|
||||||
mp.pki_encrypted = false;
|
mp.pki_encrypted = false;
|
||||||
mp.public_key.size = 0;
|
mp.public_key.size = 0;
|
||||||
memset(mp.public_key.bytes, 0, sizeof(mp.public_key.bytes));
|
memset(mp.public_key.bytes, 0, sizeof(mp.public_key.bytes));
|
||||||
|
|||||||
@@ -104,6 +104,10 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
|||||||
(config.security.admin_key[2].size == 32 &&
|
(config.security.admin_key[2].size == 32 &&
|
||||||
memcmp(mp.public_key.bytes, config.security.admin_key[2].bytes, 32) == 0)) {
|
memcmp(mp.public_key.bytes, config.security.admin_key[2].bytes, 32) == 0)) {
|
||||||
LOG_INFO("PKC admin payload with authorized sender key");
|
LOG_INFO("PKC admin payload with authorized sender key");
|
||||||
|
auto remoteNode = nodeDB->getMeshNode(mp.from);
|
||||||
|
if (remoteNode && !remoteNode->is_favorite) {
|
||||||
|
remoteNode->is_favorite = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
myReply = allocErrorResponse(meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED, &mp);
|
myReply = allocErrorResponse(meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED, &mp);
|
||||||
LOG_INFO("Received PKC admin payload, but the sender public key does not match the admin authorized key!");
|
LOG_INFO("Received PKC admin payload, but the sender public key does not match the admin authorized key!");
|
||||||
@@ -1040,32 +1044,19 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.payload_variant.serial = moduleConfig.serial;
|
res.get_module_config_response.payload_variant.serial = moduleConfig.serial;
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_EXTNOTIF_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_EXTNOTIF_CONFIG:
|
||||||
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
|
|
||||||
LOG_INFO("Get module config: External Notification");
|
LOG_INFO("Get module config: External Notification");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
|
||||||
res.get_module_config_response.payload_variant.external_notification = moduleConfig.external_notification;
|
res.get_module_config_response.payload_variant.external_notification = moduleConfig.external_notification;
|
||||||
#else
|
|
||||||
LOG_DEBUG("External Notification module excluded from build, skipping config");
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG:
|
||||||
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
|
||||||
LOG_INFO("Get module config: Store & Forward");
|
LOG_INFO("Get module config: Store & Forward");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
|
||||||
res.get_module_config_response.payload_variant.store_forward = moduleConfig.store_forward;
|
res.get_module_config_response.payload_variant.store_forward = moduleConfig.store_forward;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Store & Forward module excluded from build, skipping config");
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_RANGETEST_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_RANGETEST_CONFIG:
|
||||||
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
|
||||||
LOG_INFO("Get module config: Range Test");
|
LOG_INFO("Get module config: Range Test");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
|
||||||
res.get_module_config_response.payload_variant.range_test = moduleConfig.range_test;
|
res.get_module_config_response.payload_variant.range_test = moduleConfig.range_test;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Range Test module excluded from build, skipping config");
|
|
||||||
// Don't set payload variant - will result in empty response
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_TELEMETRY_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_TELEMETRY_CONFIG:
|
||||||
LOG_INFO("Get module config: Telemetry");
|
LOG_INFO("Get module config: Telemetry");
|
||||||
@@ -1078,13 +1069,9 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.payload_variant.canned_message = moduleConfig.canned_message;
|
res.get_module_config_response.payload_variant.canned_message = moduleConfig.canned_message;
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_AUDIO_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_AUDIO_CONFIG:
|
||||||
#if !MESHTASTIC_EXCLUDE_AUDIO
|
|
||||||
LOG_INFO("Get module config: Audio");
|
LOG_INFO("Get module config: Audio");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
|
||||||
res.get_module_config_response.payload_variant.audio = moduleConfig.audio;
|
res.get_module_config_response.payload_variant.audio = moduleConfig.audio;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Audio module excluded from build, skipping config");
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG:
|
||||||
LOG_INFO("Get module config: Remote Hardware");
|
LOG_INFO("Get module config: Remote Hardware");
|
||||||
@@ -1097,31 +1084,19 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG:
|
||||||
#if !(NO_EXT_GPIO || MESHTASTIC_EXCLUDE_DETECTIONSENSOR)
|
|
||||||
LOG_INFO("Get module config: Detection Sensor");
|
LOG_INFO("Get module config: Detection Sensor");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
|
||||||
res.get_module_config_response.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
res.get_module_config_response.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Detection Sensor module excluded from build, skipping config");
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG:
|
||||||
#if !MESHTASTIC_EXCLUDE_AMBIENTLIGHTING
|
|
||||||
LOG_INFO("Get module config: Ambient Lighting");
|
LOG_INFO("Get module config: Ambient Lighting");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
||||||
res.get_module_config_response.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
res.get_module_config_response.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Ambient Lighting module excluded from build, skipping config");
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG:
|
||||||
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
|
||||||
LOG_INFO("Get module config: Paxcounter");
|
LOG_INFO("Get module config: Paxcounter");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
||||||
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
|
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
|
||||||
#else
|
|
||||||
LOG_DEBUG("Paxcounter module excluded from build, skipping config");
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -404,14 +404,14 @@ bool CannedMessageModule::isUpEvent(const InputEvent *event)
|
|||||||
return event->inputEvent == INPUT_BROKER_UP ||
|
return event->inputEvent == INPUT_BROKER_UP ||
|
||||||
((runState == CANNED_MESSAGE_RUN_STATE_ACTIVE || runState == CANNED_MESSAGE_RUN_STATE_EMOTE_PICKER ||
|
((runState == CANNED_MESSAGE_RUN_STATE_ACTIVE || runState == CANNED_MESSAGE_RUN_STATE_EMOTE_PICKER ||
|
||||||
runState == CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION) &&
|
runState == CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION) &&
|
||||||
event->inputEvent == INPUT_BROKER_ALT_PRESS);
|
(event->inputEvent == INPUT_BROKER_LEFT || event->inputEvent == INPUT_BROKER_ALT_PRESS));
|
||||||
}
|
}
|
||||||
bool CannedMessageModule::isDownEvent(const InputEvent *event)
|
bool CannedMessageModule::isDownEvent(const InputEvent *event)
|
||||||
{
|
{
|
||||||
return event->inputEvent == INPUT_BROKER_DOWN ||
|
return event->inputEvent == INPUT_BROKER_DOWN ||
|
||||||
((runState == CANNED_MESSAGE_RUN_STATE_ACTIVE || runState == CANNED_MESSAGE_RUN_STATE_EMOTE_PICKER ||
|
((runState == CANNED_MESSAGE_RUN_STATE_ACTIVE || runState == CANNED_MESSAGE_RUN_STATE_EMOTE_PICKER ||
|
||||||
runState == CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION) &&
|
runState == CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION) &&
|
||||||
event->inputEvent == INPUT_BROKER_USER_PRESS);
|
(event->inputEvent == INPUT_BROKER_RIGHT || event->inputEvent == INPUT_BROKER_USER_PRESS));
|
||||||
}
|
}
|
||||||
bool CannedMessageModule::isSelectEvent(const InputEvent *event)
|
bool CannedMessageModule::isSelectEvent(const InputEvent *event)
|
||||||
{
|
{
|
||||||
@@ -1560,10 +1560,17 @@ void CannedMessageModule::drawDestinationSelectionScreen(OLEDDisplay *display, O
|
|||||||
meshtastic_NodeInfoLite *node = this->filteredNodes[nodeIndex].node;
|
meshtastic_NodeInfoLite *node = this->filteredNodes[nodeIndex].node;
|
||||||
if (node) {
|
if (node) {
|
||||||
if (node->is_favorite) {
|
if (node->is_favorite) {
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
snprintf(entryText, sizeof(entryText), "* %s", node->user.short_name);
|
||||||
|
} else {
|
||||||
|
snprintf(entryText, sizeof(entryText), "%s", node->user.short_name);
|
||||||
|
}
|
||||||
|
#else
|
||||||
snprintf(entryText, sizeof(entryText), "* %s", node->user.long_name);
|
snprintf(entryText, sizeof(entryText), "* %s", node->user.long_name);
|
||||||
} else {
|
} else {
|
||||||
snprintf(entryText, sizeof(entryText), "%s", node->user.long_name);
|
snprintf(entryText, sizeof(entryText), "%s", node->user.long_name);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1734,7 +1741,11 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
|||||||
int yOffset = y + 10;
|
int yOffset = y + 10;
|
||||||
#else
|
#else
|
||||||
display->setFont(FONT_MEDIUM);
|
display->setFont(FONT_MEDIUM);
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
int yOffset = y;
|
||||||
|
#else
|
||||||
int yOffset = y + 10;
|
int yOffset = y + 10;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --- Delivery Status Message ---
|
// --- Delivery Status Message ---
|
||||||
@@ -1759,13 +1770,20 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
|||||||
}
|
}
|
||||||
|
|
||||||
display->drawString(display->getWidth() / 2 + x, yOffset, buffer);
|
display->drawString(display->getWidth() / 2 + x, yOffset, buffer);
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
yOffset += lineCount * FONT_HEIGHT_MEDIUM - 5; // only 1 line gap, no extra padding
|
||||||
|
#else
|
||||||
yOffset += lineCount * FONT_HEIGHT_MEDIUM; // only 1 line gap, no extra padding
|
yOffset += lineCount * FONT_HEIGHT_MEDIUM; // only 1 line gap, no extra padding
|
||||||
|
#endif
|
||||||
#ifndef USE_EINK
|
#ifndef USE_EINK
|
||||||
// --- SNR + RSSI Compact Line ---
|
// --- SNR + RSSI Compact Line ---
|
||||||
if (this->ack) {
|
if (this->ack) {
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
snprintf(buffer, sizeof(buffer), "SNR: %.1f dB \nRSSI: %d", this->lastRxSnr, this->lastRxRssi);
|
||||||
|
#else
|
||||||
snprintf(buffer, sizeof(buffer), "SNR: %.1f dB RSSI: %d", this->lastRxSnr, this->lastRxRssi);
|
snprintf(buffer, sizeof(buffer), "SNR: %.1f dB RSSI: %d", this->lastRxSnr, this->lastRxRssi);
|
||||||
|
#endif
|
||||||
display->drawString(display->getWidth() / 2 + x, yOffset, buffer);
|
display->drawString(display->getWidth() / 2 + x, yOffset, buffer);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "input/RotaryEncoderInterruptImpl1.h"
|
#include "input/RotaryEncoderInterruptImpl1.h"
|
||||||
#include "input/SerialKeyboardImpl.h"
|
#include "input/SerialKeyboardImpl.h"
|
||||||
#include "input/UpDownInterruptImpl1.h"
|
#include "input/UpDownInterruptImpl1.h"
|
||||||
|
#include "input/i2cButton.h"
|
||||||
#include "modules/SystemCommandsModule.h"
|
#include "modules/SystemCommandsModule.h"
|
||||||
#if HAS_TRACKBALL
|
#if HAS_TRACKBALL
|
||||||
#include "input/TrackballInterruptImpl1.h"
|
#include "input/TrackballInterruptImpl1.h"
|
||||||
@@ -198,6 +199,9 @@ void setupModules()
|
|||||||
#endif
|
#endif
|
||||||
cardKbI2cImpl = new CardKbI2cImpl();
|
cardKbI2cImpl = new CardKbI2cImpl();
|
||||||
cardKbI2cImpl->init();
|
cardKbI2cImpl->init();
|
||||||
|
#if defined(M5STACK_UNITC6L)
|
||||||
|
i2cButton = new i2cButtonThread("i2cButtonThread");
|
||||||
|
#endif
|
||||||
#ifdef INPUTBROKER_MATRIX_TYPE
|
#ifdef INPUTBROKER_MATRIX_TYPE
|
||||||
kbMatrixImpl = new KbMatrixImpl();
|
kbMatrixImpl = new KbMatrixImpl();
|
||||||
kbMatrixImpl->init();
|
kbMatrixImpl->init();
|
||||||
|
|||||||
@@ -11,6 +11,12 @@
|
|||||||
#include <NimBLEDevice.h>
|
#include <NimBLEDevice.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
#include "NimBLEAdvertising.h"
|
||||||
|
#include "NimBLEExtAdvertising.h"
|
||||||
|
#include "PowerStatus.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
NimBLECharacteristic *fromNumCharacteristic;
|
NimBLECharacteristic *fromNumCharacteristic;
|
||||||
NimBLECharacteristic *BatteryCharacteristic;
|
NimBLECharacteristic *BatteryCharacteristic;
|
||||||
NimBLECharacteristic *logRadioCharacteristic;
|
NimBLECharacteristic *logRadioCharacteristic;
|
||||||
@@ -56,13 +62,18 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
|
|||||||
{
|
{
|
||||||
PhoneAPI::onNowHasData(fromRadioNum);
|
PhoneAPI::onNowHasData(fromRadioNum);
|
||||||
|
|
||||||
LOG_DEBUG("BLE notify fromNum");
|
uint8_t cc = bleServer->getConnectedCount();
|
||||||
|
LOG_DEBUG("BLE notify fromNum: %d connections: %d", fromRadioNum, cc);
|
||||||
|
|
||||||
uint8_t val[4];
|
uint8_t val[4];
|
||||||
put_le32(val, fromRadioNum);
|
put_le32(val, fromRadioNum);
|
||||||
|
|
||||||
fromNumCharacteristic->setValue(val, sizeof(val));
|
fromNumCharacteristic->setValue(val, sizeof(val));
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
fromNumCharacteristic->notify(val, sizeof(val), BLE_HS_CONN_HANDLE_NONE);
|
||||||
|
#else
|
||||||
fromNumCharacteristic->notify();
|
fromNumCharacteristic->notify();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check the current underlying physical link to see if the client is currently connected
|
/// Check the current underlying physical link to see if the client is currently connected
|
||||||
@@ -79,7 +90,12 @@ static uint8_t lastToRadio[MAX_TO_FROM_RADIO_SIZE];
|
|||||||
|
|
||||||
class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
|
class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
|
||||||
{
|
{
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
virtual void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo)
|
||||||
|
#else
|
||||||
virtual void onWrite(NimBLECharacteristic *pCharacteristic)
|
virtual void onWrite(NimBLECharacteristic *pCharacteristic)
|
||||||
|
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
auto val = pCharacteristic->getValue();
|
auto val = pCharacteristic->getValue();
|
||||||
|
|
||||||
@@ -97,7 +113,11 @@ class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
|
|||||||
|
|
||||||
class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
||||||
{
|
{
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
virtual void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo)
|
||||||
|
#else
|
||||||
virtual void onRead(NimBLECharacteristic *pCharacteristic)
|
virtual void onRead(NimBLECharacteristic *pCharacteristic)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
bluetoothPhoneAPI->phoneWants = true;
|
bluetoothPhoneAPI->phoneWants = true;
|
||||||
@@ -107,9 +127,7 @@ class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
|||||||
tries++;
|
tries++;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> guard(bluetoothPhoneAPI->nimble_mutex);
|
std::lock_guard<std::mutex> guard(bluetoothPhoneAPI->nimble_mutex);
|
||||||
std::string fromRadioByteString(bluetoothPhoneAPI->fromRadioBytes,
|
pCharacteristic->setValue(bluetoothPhoneAPI->fromRadioBytes, bluetoothPhoneAPI->numBytes);
|
||||||
bluetoothPhoneAPI->fromRadioBytes + bluetoothPhoneAPI->numBytes);
|
|
||||||
pCharacteristic->setValue(fromRadioByteString);
|
|
||||||
|
|
||||||
if (bluetoothPhoneAPI->numBytes != 0) // if we did send something, queue it up right away to reload
|
if (bluetoothPhoneAPI->numBytes != 0) // if we did send something, queue it up right away to reload
|
||||||
bluetoothPhoneAPI->setIntervalFromNow(0);
|
bluetoothPhoneAPI->setIntervalFromNow(0);
|
||||||
@@ -121,7 +139,17 @@ class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
|||||||
|
|
||||||
class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
||||||
{
|
{
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
public:
|
||||||
|
NimbleBluetoothServerCallback(NimbleBluetooth *ble) { this->ble = ble; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
NimbleBluetooth *ble;
|
||||||
|
|
||||||
|
virtual uint32_t onPassKeyDisplay()
|
||||||
|
#else
|
||||||
virtual uint32_t onPassKeyRequest()
|
virtual uint32_t onPassKeyRequest()
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
uint32_t passkey = config.bluetooth.fixed_pin;
|
uint32_t passkey = config.bluetooth.fixed_pin;
|
||||||
|
|
||||||
@@ -170,7 +198,11 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
|||||||
return passkey;
|
return passkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
virtual void onAuthenticationComplete(NimBLEConnInfo &connInfo)
|
||||||
|
#else
|
||||||
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc)
|
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
LOG_INFO("BLE authentication complete");
|
LOG_INFO("BLE authentication complete");
|
||||||
|
|
||||||
@@ -185,9 +217,20 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
virtual void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo)
|
||||||
|
{
|
||||||
|
LOG_INFO("BLE incoming connection %s", connInfo.getAddress().toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason)
|
||||||
|
{
|
||||||
|
LOG_INFO("BLE disconnect reason: %d", reason);
|
||||||
|
#else
|
||||||
virtual void onDisconnect(NimBLEServer *pServer, ble_gap_conn_desc *desc)
|
virtual void onDisconnect(NimBLEServer *pServer, ble_gap_conn_desc *desc)
|
||||||
{
|
{
|
||||||
LOG_INFO("BLE disconnect");
|
LOG_INFO("BLE disconnect");
|
||||||
|
#endif
|
||||||
|
|
||||||
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED);
|
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED);
|
||||||
bluetoothStatus->updateStatus(&newStatus);
|
bluetoothStatus->updateStatus(&newStatus);
|
||||||
@@ -200,6 +243,10 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
|||||||
bluetoothPhoneAPI->numBytes = 0;
|
bluetoothPhoneAPI->numBytes = 0;
|
||||||
bluetoothPhoneAPI->queue_size = 0;
|
bluetoothPhoneAPI->queue_size = 0;
|
||||||
}
|
}
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
// Restart Advertising
|
||||||
|
ble->startAdvertising();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -251,7 +298,11 @@ int NimbleBluetooth::getRssi()
|
|||||||
if (bleServer && isConnected()) {
|
if (bleServer && isConnected()) {
|
||||||
auto service = bleServer->getServiceByUUID(MESH_SERVICE_UUID);
|
auto service = bleServer->getServiceByUUID(MESH_SERVICE_UUID);
|
||||||
uint16_t handle = service->getHandle();
|
uint16_t handle = service->getHandle();
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
return NimBLEDevice::getClientByHandle(handle)->getRssi();
|
||||||
|
#else
|
||||||
return NimBLEDevice::getClientByID(handle)->getRssi();
|
return NimBLEDevice::getClientByID(handle)->getRssi();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return 0; // FIXME figure out where to source this
|
return 0; // FIXME figure out where to source this
|
||||||
}
|
}
|
||||||
@@ -273,8 +324,11 @@ void NimbleBluetooth::setup()
|
|||||||
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
|
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
|
||||||
}
|
}
|
||||||
bleServer = NimBLEDevice::createServer();
|
bleServer = NimBLEDevice::createServer();
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback(this);
|
||||||
|
#else
|
||||||
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback();
|
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback();
|
||||||
|
#endif
|
||||||
bleServer->setCallbacks(serverCallbacks, true);
|
bleServer->setCallbacks(serverCallbacks, true);
|
||||||
setupService();
|
setupService();
|
||||||
startAdvertising();
|
startAdvertising();
|
||||||
@@ -318,8 +372,11 @@ void NimbleBluetooth::setupService()
|
|||||||
NimBLEService *batteryService = bleServer->createService(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
|
NimBLEService *batteryService = bleServer->createService(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
|
||||||
BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic)
|
BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic)
|
||||||
(uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY, 1);
|
(uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY, 1);
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
NimBLE2904 *batteryLevelDescriptor = BatteryCharacteristic->create2904();
|
||||||
|
#else
|
||||||
NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->createDescriptor((uint16_t)0x2904);
|
NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->createDescriptor((uint16_t)0x2904);
|
||||||
|
#endif
|
||||||
batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8);
|
batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8);
|
||||||
batteryLevelDescriptor->setNamespace(1);
|
batteryLevelDescriptor->setNamespace(1);
|
||||||
batteryLevelDescriptor->setUnit(0x27ad);
|
batteryLevelDescriptor->setUnit(0x27ad);
|
||||||
@@ -329,11 +386,40 @@ void NimbleBluetooth::setupService()
|
|||||||
|
|
||||||
void NimbleBluetooth::startAdvertising()
|
void NimbleBluetooth::startAdvertising()
|
||||||
{
|
{
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
NimBLEExtAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
|
NimBLEExtAdvertisement legacyAdvertising;
|
||||||
|
|
||||||
|
legacyAdvertising.setLegacyAdvertising(true);
|
||||||
|
legacyAdvertising.setScannable(true);
|
||||||
|
legacyAdvertising.setConnectable(true);
|
||||||
|
legacyAdvertising.setFlags(BLE_HS_ADV_F_DISC_GEN);
|
||||||
|
if (powerStatus->getHasBattery() == 1) {
|
||||||
|
legacyAdvertising.setCompleteServices(NimBLEUUID((uint16_t)0x180f));
|
||||||
|
}
|
||||||
|
legacyAdvertising.setCompleteServices(NimBLEUUID(MESH_SERVICE_UUID));
|
||||||
|
legacyAdvertising.setMinInterval(500);
|
||||||
|
legacyAdvertising.setMaxInterval(1000);
|
||||||
|
|
||||||
|
NimBLEExtAdvertisement legacyScanResponse;
|
||||||
|
legacyScanResponse.setLegacyAdvertising(true);
|
||||||
|
legacyScanResponse.setConnectable(true);
|
||||||
|
legacyScanResponse.setName(getDeviceName());
|
||||||
|
|
||||||
|
if (!pAdvertising->setInstanceData(0, legacyAdvertising)) {
|
||||||
|
LOG_ERROR("BLE failed to set legacyAdvertising");
|
||||||
|
} else if (!pAdvertising->setScanResponseData(0, legacyScanResponse)) {
|
||||||
|
LOG_ERROR("BLE failed to set legacyScanResponse");
|
||||||
|
} else if (!pAdvertising->start(0, 0, 0)) {
|
||||||
|
LOG_ERROR("BLE failed to start legacyAdvertising");
|
||||||
|
}
|
||||||
|
#else
|
||||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
pAdvertising->reset();
|
pAdvertising->reset();
|
||||||
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
|
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
|
||||||
pAdvertising->addServiceUUID(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
|
pAdvertising->addServiceUUID(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
|
||||||
pAdvertising->start(0);
|
pAdvertising->start(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a level between 0-100, update the BLE attribute
|
/// Given a level between 0-100, update the BLE attribute
|
||||||
@@ -341,7 +427,11 @@ void updateBatteryLevel(uint8_t level)
|
|||||||
{
|
{
|
||||||
if ((config.bluetooth.enabled == true) && bleServer && nimbleBluetooth->isConnected()) {
|
if ((config.bluetooth.enabled == true) && bleServer && nimbleBluetooth->isConnected()) {
|
||||||
BatteryCharacteristic->setValue(&level, 1);
|
BatteryCharacteristic->setValue(&level, 1);
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
BatteryCharacteristic->notify(&level, 1, BLE_HS_CONN_HANDLE_NONE);
|
||||||
|
#else
|
||||||
BatteryCharacteristic->notify();
|
BatteryCharacteristic->notify();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,7 +446,11 @@ void NimbleBluetooth::sendLog(const uint8_t *logMessage, size_t length)
|
|||||||
if (!bleServer || !isConnected() || length > 512) {
|
if (!bleServer || !isConnected() || length > 512) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef NIMBLE_TWO
|
||||||
|
logRadioCharacteristic->notify(logMessage, length, BLE_HS_CONN_HANDLE_NONE);
|
||||||
|
#else
|
||||||
logRadioCharacteristic->notify(logMessage, length, true);
|
logRadioCharacteristic->notify(logMessage, length, true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearNVS()
|
void clearNVS()
|
||||||
@@ -366,4 +460,4 @@ void clearNVS()
|
|||||||
ESP.restart();
|
ESP.restart();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -12,10 +12,15 @@ class NimbleBluetooth : BluetoothApi
|
|||||||
bool isConnected();
|
bool isConnected();
|
||||||
int getRssi();
|
int getRssi();
|
||||||
void sendLog(const uint8_t *logMessage, size_t length);
|
void sendLog(const uint8_t *logMessage, size_t length);
|
||||||
|
#if defined(NIMBLE_TWO)
|
||||||
|
void startAdvertising();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupService();
|
void setupService();
|
||||||
|
#if !defined(NIMBLE_TWO)
|
||||||
void startAdvertising();
|
void startAdvertising();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void setBluetoothEnable(bool enable);
|
void setBluetoothEnable(bool enable);
|
||||||
|
|||||||
@@ -197,6 +197,8 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_T_DECK_PRO
|
#define HW_VENDOR meshtastic_HardwareModel_T_DECK_PRO
|
||||||
#elif defined(T_LORA_PAGER)
|
#elif defined(T_LORA_PAGER)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_T_LORA_PAGER
|
#define HW_VENDOR meshtastic_HardwareModel_T_LORA_PAGER
|
||||||
|
#elif defined(M5STACK_UNITC6L)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_M5STACK_C6L
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef Pins_Arduino_h
|
||||||
|
#define Pins_Arduino_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define USB_VID 0x2886
|
||||||
|
#define USB_PID 0x0048
|
||||||
|
|
||||||
|
static const uint8_t TX = 16;
|
||||||
|
static const uint8_t RX = 17;
|
||||||
|
|
||||||
|
static const uint8_t SDA = 10;
|
||||||
|
static const uint8_t SCL = 8;
|
||||||
|
|
||||||
|
// Default SPI will be mapped to Radio
|
||||||
|
static const uint8_t MISO = 22;
|
||||||
|
static const uint8_t SCK = 20;
|
||||||
|
static const uint8_t MOSI = 21;
|
||||||
|
static const uint8_t SS = 6;
|
||||||
|
|
||||||
|
// #define SPI_MOSI (11)
|
||||||
|
// #define SPI_SCK (14)
|
||||||
|
// #define SPI_MISO (2)
|
||||||
|
// #define SPI_CS (13)
|
||||||
|
|
||||||
|
// #define SDCARD_CS SPI_CS
|
||||||
|
|
||||||
|
#endif /* Pins_Arduino_h */
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
[env:m5stack-unitc6l]
|
||||||
|
extends = esp32c6_base
|
||||||
|
board = esp32-c6-devkitc-1
|
||||||
|
;OpenOCD flash method
|
||||||
|
;upload_protocol = esp-builtin
|
||||||
|
;Normal method
|
||||||
|
upload_protocol = esptool
|
||||||
|
;upload_port = /dev/ttyACM2
|
||||||
|
build_unflags =
|
||||||
|
-D HAS_BLUETOOTH
|
||||||
|
-D MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
|
-D HAS_WIFI
|
||||||
|
lib_deps =
|
||||||
|
${esp32c6_base.lib_deps}
|
||||||
|
adafruit/Adafruit NeoPixel@^1.12.3
|
||||||
|
h2zero/NimBLE-Arduino@^2.3.6
|
||||||
|
build_flags =
|
||||||
|
${esp32c6_base.build_flags}
|
||||||
|
-D M5STACK_UNITC6L
|
||||||
|
-I variants/esp32c6/m5stack_unitc6l
|
||||||
|
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
|
||||||
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
-DARDUINO_USB_MODE=1
|
||||||
|
-D HAS_BLUETOOTH=1
|
||||||
|
-D MESHTASTIC_EXCLUDE_WEBSERVER
|
||||||
|
-D MESHTASTIC_EXCLUDE_MQTT
|
||||||
|
-DCONFIG_BT_NIMBLE_EXT_ADV=1
|
||||||
|
-DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2
|
||||||
|
-D NIMBLE_TWO
|
||||||
|
monitor_speed=115200
|
||||||
|
lib_ignore =
|
||||||
|
NonBlockingRTTTL
|
||||||
|
libpax
|
||||||
|
build_src_filter =
|
||||||
|
${esp32c6_base.build_src_filter} +<../variants/esp32c6/m5stack_unitc6l>
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#include "driver/gpio.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
// I2C device addr
|
||||||
|
#define PI4IO_M_ADDR 0x43
|
||||||
|
|
||||||
|
// PI4IO registers
|
||||||
|
#define PI4IO_REG_CHIP_RESET 0x01
|
||||||
|
#define PI4IO_REG_IO_DIR 0x03
|
||||||
|
#define PI4IO_REG_OUT_SET 0x05
|
||||||
|
#define PI4IO_REG_OUT_H_IM 0x07
|
||||||
|
#define PI4IO_REG_IN_DEF_STA 0x09
|
||||||
|
#define PI4IO_REG_PULL_EN 0x0B
|
||||||
|
#define PI4IO_REG_PULL_SEL 0x0D
|
||||||
|
#define PI4IO_REG_IN_STA 0x0F
|
||||||
|
#define PI4IO_REG_INT_MASK 0x11
|
||||||
|
#define PI4IO_REG_IRQ_STA 0x13
|
||||||
|
// PI4IO
|
||||||
|
|
||||||
|
#define setbit(x, y) x |= (0x01 << y)
|
||||||
|
#define clrbit(x, y) x &= ~(0x01 << y)
|
||||||
|
#define reversebit(x, y) x ^= (0x01 << y)
|
||||||
|
#define getbit(x, y) ((x) >> (y)&0x01)
|
||||||
|
|
||||||
|
void i2c_read_byte(uint8_t addr, uint8_t reg, uint8_t *value)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(addr);
|
||||||
|
Wire.write(reg);
|
||||||
|
Wire.endTransmission();
|
||||||
|
Wire.requestFrom(addr, 1);
|
||||||
|
*value = Wire.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
void i2c_write_byte(uint8_t addr, uint8_t reg, uint8_t value)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(addr);
|
||||||
|
Wire.write(reg);
|
||||||
|
Wire.write(value);
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
/*******************************************************************/
|
||||||
|
void c6l_init()
|
||||||
|
{
|
||||||
|
// P7 LoRa Reset
|
||||||
|
// P6 RF Switch
|
||||||
|
// P5 LNA Enable
|
||||||
|
|
||||||
|
printf("pi4io_init\n");
|
||||||
|
uint8_t in_data;
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_CHIP_RESET, 0xFF);
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_read_byte(PI4IO_M_ADDR, PI4IO_REG_CHIP_RESET, &in_data);
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_IO_DIR, 0b11000000); // 0: input 1: output
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_OUT_H_IM, 0b00111100); // 使用到的引脚关闭High-Impedance
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_PULL_SEL, 0b11000011); // pull up/down select, 0 down, 1 up
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_PULL_EN, 0b11000011); // pull up/down enable, 0 disable, 1 enable
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_IN_DEF_STA, 0b00000011); // P0 P1 默认高电平, 按键按下触发中断
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_INT_MASK, 0b11111100); // P0 P1 中断使能 0 enable, 1 disable
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_OUT_SET, 0b10000000); // 默认输出为0
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_read_byte(PI4IO_M_ADDR, PI4IO_REG_IRQ_STA, &in_data); // 读取IRQ_STA清除标志
|
||||||
|
|
||||||
|
i2c_read_byte(PI4IO_M_ADDR, PI4IO_REG_OUT_SET, &in_data);
|
||||||
|
setbit(in_data, 6); // HIGH
|
||||||
|
i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_OUT_SET, in_data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
void c6l_init();
|
||||||
|
|
||||||
|
#define HAS_GPS 1
|
||||||
|
#define GPS_RX_PIN 4
|
||||||
|
#define GPS_TX_PIN 5
|
||||||
|
|
||||||
|
#define I2C_SDA 10
|
||||||
|
#define I2C_SCL 8
|
||||||
|
|
||||||
|
#define PIN_BUZZER 11
|
||||||
|
|
||||||
|
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||||
|
#define NEOPIXEL_COUNT 1 // How many neopixels are connected
|
||||||
|
#define NEOPIXEL_DATA 2 // gpio pin used to send data to the neopixels
|
||||||
|
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // type of neopixels in use
|
||||||
|
#define ENABLE_AMBIENTLIGHTING // Turn on Ambient Lighting
|
||||||
|
|
||||||
|
// #define BUTTON_PIN 9
|
||||||
|
#define BUTTON_EXTENDER
|
||||||
|
|
||||||
|
#undef LORA_SCK
|
||||||
|
#undef LORA_MISO
|
||||||
|
#undef LORA_MOSI
|
||||||
|
#undef LORA_CS
|
||||||
|
|
||||||
|
// WaveShare Core1262-868M OK
|
||||||
|
// https://www.waveshare.com/wiki/Core1262-868M
|
||||||
|
#define USE_SX1262
|
||||||
|
|
||||||
|
#define LORA_MISO 22
|
||||||
|
#define LORA_SCK 20
|
||||||
|
#define LORA_MOSI 21
|
||||||
|
#define LORA_CS 23
|
||||||
|
#define LORA_RESET RADIOLIB_NC
|
||||||
|
#define LORA_DIO1 7
|
||||||
|
#define LORA_BUSY 19
|
||||||
|
#define SX126X_CS LORA_CS
|
||||||
|
#define SX126X_DIO1 LORA_DIO1
|
||||||
|
#define SX126X_BUSY LORA_BUSY
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
#define SX126X_DIO2_AS_RF_SWITCH
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 3.0
|
||||||
|
|
||||||
|
#define USE_SPISSD1306
|
||||||
|
#ifdef USE_SPISSD1306
|
||||||
|
#define SSD1306_NSS 6 // CS
|
||||||
|
#define SSD1306_RS 18 // DC
|
||||||
|
#define SSD1306_RESET 15
|
||||||
|
// #define OLED_DG 1
|
||||||
|
#endif
|
||||||
|
#define SCREEN_TRANSITION_FRAMERATE 10
|
||||||
|
#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness
|
||||||
@@ -93,11 +93,10 @@
|
|||||||
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
|
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
|
||||||
// code)
|
// code)
|
||||||
|
|
||||||
#define MODEM_POWER_EN 41
|
#define MODEM_POWER_EN 41
|
||||||
#define MODEM_PWRKEY 40
|
#define MODEM_PWRKEY 40
|
||||||
#define MODEM_RST 9
|
#define MODEM_RST 9
|
||||||
#define MODEM_RI 7
|
#define MODEM_RI 7
|
||||||
#define MODEM_DTR 8
|
#define MODEM_DTR 8
|
||||||
#define MODEM_RX 10
|
#define MODEM_RX 10
|
||||||
#define MODEM_TX 11
|
#define MODEM_TX 11
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,8 @@ static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11
|
|||||||
|
|
||||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||||
// mode DIO5 DIO6
|
// mode DIO5 DIO6
|
||||||
{LR11x0::MODE_STBY, {LOW, LOW}},
|
{LR11x0::MODE_STBY, {LOW, LOW}}, {LR11x0::MODE_RX, {LOW, HIGH}},
|
||||||
{LR11x0::MODE_RX, {LOW, HIGH}},
|
{LR11x0::MODE_TX, {HIGH, LOW}}, {LR11x0::MODE_TX_HP, {HIGH, LOW}},
|
||||||
{LR11x0::MODE_TX, {HIGH, LOW}},
|
{LR11x0::MODE_TX_HF, {LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW}},
|
||||||
{LR11x0::MODE_TX_HP, {HIGH, LOW}},
|
{LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE,
|
||||||
{LR11x0::MODE_TX_HF, {LOW, LOW}},
|
|
||||||
{LR11x0::MODE_GNSS, {LOW, LOW}},
|
|
||||||
{LR11x0::MODE_WIFI, {LOW, LOW}},
|
|
||||||
END_OF_MODE_TABLE,
|
|
||||||
};
|
};
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
[VERSION]
|
[VERSION]
|
||||||
major = 2
|
major = 2
|
||||||
minor = 7
|
minor = 7
|
||||||
build = 9
|
build = 10
|
||||||
|
|||||||
Reference in New Issue
Block a user