Merge branch 'develop' into kill-led-builtin

This commit is contained in:
Jonathan Bennett
2025-12-09 23:20:19 -06:00
committed by GitHub
50 changed files with 604 additions and 453 deletions

View File

@@ -51,7 +51,7 @@ for f in .clusterfuzzlite/*_fuzzer.cpp; do
fuzzer=$(basename "$f" .cpp) fuzzer=$(basename "$f" .cpp)
cp -f "$f" src/fuzzer.cpp cp -f "$f" src/fuzzer.cpp
pio run -vvv --environment "$PIO_ENV" pio run -vvv --environment "$PIO_ENV"
program="$PLATFORMIO_WORKSPACE_DIR/build/$PIO_ENV/program" program="$PLATFORMIO_WORKSPACE_DIR/build/$PIO_ENV/meshtasticd"
cp "$program" "$OUT/$fuzzer" cp "$program" "$OUT/$fuzzer"
# Copy shared libraries used by the fuzzer. # Copy shared libraries used by the fuzzer.

View File

@@ -2,4 +2,5 @@
self-hosted-runner: self-hosted-runner:
# Labels of self-hosted runner in array of strings. # Labels of self-hosted runner in array of strings.
labels: labels:
- arctastic
- test-runner - test-runner

View File

@@ -102,7 +102,7 @@ runs:
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
with: with:
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}
overwrite: true overwrite: true
path: | path: |
${{ inputs.artifact-paths }} ${{ inputs.artifact-paths }}

View File

@@ -18,7 +18,8 @@ permissions: read-all
jobs: jobs:
pio-build: pio-build:
name: build-${{ inputs.platform }} name: build-${{ inputs.platform }}
runs-on: ubuntu-24.04 # Use 'arctastic' self-hosted runner pool when building in the main repo
runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }}
outputs: outputs:
artifact-id: ${{ steps.upload.outputs.artifact-id }} artifact-id: ${{ steps.upload.outputs.artifact-id }}
steps: steps:
@@ -55,15 +56,29 @@ jobs:
ota_firmware_source: ${{ steps.ota_dir.outputs.src || '' }} ota_firmware_source: ${{ steps.ota_dir.outputs.src || '' }}
ota_firmware_target: ${{ steps.ota_dir.outputs.tgt || '' }} ota_firmware_target: ${{ steps.ota_dir.outputs.tgt || '' }}
- name: Echo manifest from release/firmware-*.mt.json to job summary
if: ${{ always() }}
env:
PIO_ENV: ${{ inputs.pio_env }}
run: |
echo "## Manifest: \`$PIO_ENV\`" >> $GITHUB_STEP_SUMMARY
echo '```json' >> $GITHUB_STEP_SUMMARY
cat release/firmware-*.mt.json >> $GITHUB_STEP_SUMMARY
echo '' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
id: upload id: upload
with: with:
name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}.zip name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}
overwrite: true overwrite: true
path: | path: |
release/*.mt.json
release/*.bin release/*.bin
release/*.elf release/*.elf
release/*.uf2 release/*.uf2
release/*.hex release/*.hex
release/*-ota.zip release/*.zip
release/device-*.sh
release/device-*.bat

View File

@@ -119,7 +119,7 @@ jobs:
./firmware-*.bin ./firmware-*.bin
./firmware-*.uf2 ./firmware-*.uf2
./firmware-*.hex ./firmware-*.hex
./firmware-*-ota.zip ./firmware-*.zip
./device-*.sh ./device-*.sh
./device-*.bat ./device-*.bat
./littlefs-*.bin ./littlefs-*.bin
@@ -139,8 +139,8 @@ jobs:
- name: Device scripts permissions - name: Device scripts permissions
run: | run: |
chmod +x ./output/device-install.sh chmod +x ./output/device-install.sh || true
chmod +x ./output/device-update.sh chmod +x ./output/device-update.sh || true
- name: Zip firmware - name: Zip firmware
run: zip -j -9 -r ./firmware-${{inputs.target}}-${{ needs.version.outputs.long }}.zip ./output run: zip -j -9 -r ./firmware-${{inputs.target}}-${{ needs.version.outputs.long }}.zip ./output

View File

@@ -177,19 +177,17 @@ jobs:
- name: Display structure of downloaded files - name: Display structure of downloaded files
run: ls -R run: ls -R
- name: Move files up
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
- name: Repackage in single firmware zip - name: Repackage in single firmware zip
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
with: with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }} name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true overwrite: true
path: | path: |
./firmware-*.mt.json
./firmware-*.bin ./firmware-*.bin
./firmware-*.uf2 ./firmware-*.uf2
./firmware-*.hex ./firmware-*.hex
./firmware-*-ota.zip ./firmware-*.zip
./device-*.sh ./device-*.sh
./device-*.bat ./device-*.bat
./littlefs-*.bin ./littlefs-*.bin
@@ -209,8 +207,8 @@ jobs:
- name: Device scripts permissions - name: Device scripts permissions
run: | run: |
chmod +x ./output/device-install.sh chmod +x ./output/device-install.sh || true
chmod +x ./output/device-update.sh chmod +x ./output/device-update.sh || true
- name: Zip firmware - name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
@@ -218,7 +216,7 @@ jobs:
- name: Repackage in single elfs zip - name: Repackage in single elfs zip
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
with: with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true overwrite: true
path: ./*.elf path: ./*.elf
retention-days: 30 retention-days: 30
@@ -236,6 +234,7 @@ jobs:
outputs: outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
needs: needs:
- setup
- version - version
- gather-artifacts - gather-artifacts
- build-debian-src - build-debian-src
@@ -244,11 +243,6 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: 3.x
- name: Create release - name: Create release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
id: create_release id: create_release
@@ -284,10 +278,25 @@ jobs:
- name: Display structure of downloaded files - name: Display structure of downloaded files
run: ls -lR run: ls -lR
- name: Add Linux sources to GtiHub Release - name: Generate Release manifest
run: |
jq -n --arg ver "${{ needs.version.outputs.long }}" --argjson targets ${{ toJson(needs.setup.outputs.all) }} '{
"version": $ver,
"targets": $targets
}' > firmware-${{ needs.version.outputs.long }}.json
- name: Save Release manifest artifact
uses: actions/upload-artifact@v5
with:
name: manifest-${{ needs.version.outputs.long }}
overwrite: true
path: firmware-${{ needs.version.outputs.long }}.json
- name: Add sources to GitHub Release
# Only run when targeting master branch with workflow_dispatch # Only run when targeting master branch with workflow_dispatch
if: ${{ github.ref_name == 'master' }} if: ${{ github.ref_name == 'master' }}
run: | run: |
gh release upload v${{ needs.version.outputs.long }} ./firmware-${{ needs.version.outputs.long }}.json
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/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 gh release upload v${{ needs.version.outputs.long }} ./output/platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip
env: env:
@@ -329,15 +338,15 @@ jobs:
- name: Device scripts permissions - name: Device scripts permissions
run: | run: |
chmod +x ./output/device-install.sh chmod +x ./output/device-install.sh || true
chmod +x ./output/device-update.sh chmod +x ./output/device-update.sh || true
- name: Zip firmware - name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- uses: actions/download-artifact@v6 - uses: actions/download-artifact@v6
with: with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true merge-multiple: true
path: ./elfs path: ./elfs
@@ -373,12 +382,19 @@ jobs:
with: with:
python-version: 3.x python-version: 3.x
- uses: actions/download-artifact@v6 - name: Get firmware artifacts
uses: actions/download-artifact@v6
with: with:
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }} pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
merge-multiple: true merge-multiple: true
path: ./publish path: ./publish
- name: Get manifest artifact
uses: actions/download-artifact@v6
with:
pattern: manifest-${{ needs.version.outputs.long }}
path: ./publish
- name: Publish firmware to meshtastic.github.io - name: Publish firmware to meshtastic.github.io
uses: peaceiris/actions-gh-pages@v4 uses: peaceiris/actions-gh-pages@v4
env: env:

View File

@@ -168,7 +168,7 @@ jobs:
./firmware-*.bin ./firmware-*.bin
./firmware-*.uf2 ./firmware-*.uf2
./firmware-*.hex ./firmware-*.hex
./firmware-*-ota.zip ./firmware-*.zip
./device-*.sh ./device-*.sh
./device-*.bat ./device-*.bat
./littlefs-*.bin ./littlefs-*.bin
@@ -188,8 +188,8 @@ jobs:
- name: Device scripts permissions - name: Device scripts permissions
run: | run: |
chmod +x ./output/device-install.sh chmod +x ./output/device-install.sh || true
chmod +x ./output/device-update.sh chmod +x ./output/device-update.sh || true
- name: Zip firmware - name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
@@ -197,7 +197,7 @@ jobs:
- name: Repackage in single elfs zip - name: Repackage in single elfs zip
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
with: with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true overwrite: true
path: ./*.elf path: ./*.elf
retention-days: 30 retention-days: 30
@@ -223,11 +223,6 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: 3.x
- name: Create release - name: Create release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
id: create_release id: create_release
@@ -308,15 +303,15 @@ jobs:
- name: Device scripts permissions - name: Device scripts permissions
run: | run: |
chmod +x ./output/device-install.sh chmod +x ./output/device-install.sh || true
chmod +x ./output/device-update.sh chmod +x ./output/device-update.sh || true
- name: Zip firmware - name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- uses: actions/download-artifact@v6 - uses: actions/download-artifact@v6
with: with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true merge-multiple: true
path: ./elfs path: ./elfs

View File

@@ -17,7 +17,7 @@ jobs:
with: with:
script: | script: |
const labels = context.payload.pull_request.labels.map(label => label.name); const labels = context.payload.pull_request.labels.map(label => label.name);
const requiredLabels = ['bugfix', 'enhancement', 'hardware-support', 'dependencies', 'submodules', 'github_actions', 'trunk']; const requiredLabels = ['bugfix', 'enhancement', 'hardware-support', 'dependencies', 'submodules', 'github_actions', 'trunk', 'cleanup'];
const hasRequiredLabel = labels.some(label => requiredLabels.includes(label)); const hasRequiredLabel = labels.some(label => requiredLabels.includes(label));
if (!hasRequiredLabel) { if (!hasRequiredLabel) {
core.setFailed(`PR must have at least one of the following labels before it can be merged: ${requiredLabels.join(', ')}.`); core.setFailed(`PR must have at least one of the following labels before it can be merged: ${requiredLabels.join(', ')}.`);

View File

@@ -52,7 +52,7 @@ jobs:
if: needs.native-tests.result != 'skipped' if: needs.native-tests.result != 'skipped'
uses: actions/download-artifact@v6 uses: actions/download-artifact@v6
with: with:
name: platformio-test-report-${{ steps.version.outputs.long }}.zip name: platformio-test-report-${{ steps.version.outputs.long }}
merge-multiple: true merge-multiple: true
- name: Parse test results and create detailed summary - name: Parse test results and create detailed summary

View File

@@ -17,7 +17,7 @@ jobs:
steps: steps:
- name: Stale PR+Issues - name: Stale PR+Issues
uses: actions/stale@v10.1.0 uses: actions/stale@v10.1.1
with: with:
days-before-stale: 45 days-before-stale: 45
stale-issue-message: This issue has not had any comment or update in the last month. If it is still relevant, please post update comments. If no comments are made, this issue will be closed automagically in 7 days. stale-issue-message: This issue has not had any comment or update in the last month. If it is still relevant, please post update comments. If no comments are made, this issue will be closed automagically in 7 days.

View File

@@ -40,7 +40,7 @@ jobs:
- name: Integration test - name: Integration test
run: | run: |
.pio/build/coverage/program -s & .pio/build/coverage/meshtasticd -s &
PID=$! PID=$!
timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done" timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done"
echo "Simulator started, launching python test..." echo "Simulator started, launching python test..."
@@ -62,7 +62,7 @@ jobs:
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
if: always() # run this step even if previous step failed if: always() # run this step even if previous step failed
with: with:
name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}.zip name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}
overwrite: true overwrite: true
path: ./coverage_*.info path: ./coverage_*.info
@@ -96,7 +96,7 @@ jobs:
if: always() # run this step even if previous step failed if: always() # run this step even if previous step failed
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
with: with:
name: platformio-test-report-${{ steps.version.outputs.long }}.zip name: platformio-test-report-${{ steps.version.outputs.long }}
overwrite: true overwrite: true
path: ./testreport.xml path: ./testreport.xml
@@ -111,7 +111,7 @@ jobs:
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
if: always() # run this step even if previous step failed if: always() # run this step even if previous step failed
with: with:
name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}.zip name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}
overwrite: true overwrite: true
path: ./coverage_*.info path: ./coverage_*.info
@@ -139,7 +139,7 @@ jobs:
- name: Download test artifacts - name: Download test artifacts
uses: actions/download-artifact@v6 uses: actions/download-artifact@v6
with: with:
name: platformio-test-report-${{ steps.version.outputs.long }}.zip name: platformio-test-report-${{ steps.version.outputs.long }}
merge-multiple: true merge-multiple: true
- name: Test Report - name: Test Report
@@ -152,7 +152,7 @@ jobs:
- name: Download coverage artifacts - name: Download coverage artifacts
uses: actions/download-artifact@v6 uses: actions/download-artifact@v6
with: with:
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}.zip pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}
path: code-coverage-report path: code-coverage-report
merge-multiple: true merge-multiple: true
@@ -165,5 +165,5 @@ jobs:
- name: Save Code Coverage Report - name: Save Code Coverage Report
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v5
with: with:
name: code-coverage-report-${{ steps.version.outputs.long }}.zip name: code-coverage-report-${{ steps.version.outputs.long }}
path: code-coverage-report path: code-coverage-report

View File

@@ -22,7 +22,7 @@ jobs:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v6 uses: actions/checkout@v6
# - uses: actions/setup-python@v5 # - uses: actions/setup-python@v6
# with: # with:
# python-version: '3.10' # python-version: '3.10'

View File

@@ -9,9 +9,9 @@ plugins:
lint: lint:
enabled: enabled:
- checkov@3.2.495 - checkov@3.2.495
- renovate@42.27.1 - renovate@42.30.4
- prettier@3.7.3 - prettier@3.7.4
- trufflehog@3.91.1 - trufflehog@3.91.2
- yamllint@1.37.1 - yamllint@1.37.1
- bandit@1.9.2 - bandit@1.9.2
- trivy@0.67.2 - trivy@0.67.2

View File

@@ -28,7 +28,7 @@ RUN bash ./bin/build-native.sh "$PIO_ENV" && \
# ##### PRODUCTION BUILD ############# # ##### PRODUCTION BUILD #############
FROM alpine:3.22 FROM alpine:3.23
LABEL org.opencontainers.image.title="Meshtastic" \ LABEL org.opencontainers.image.title="Meshtastic" \
org.opencontainers.image.description="Alpine Meshtastic daemon" \ org.opencontainers.image.description="Alpine Meshtastic daemon" \
org.opencontainers.image.url="https://meshtastic.org" \ org.opencontainers.image.url="https://meshtastic.org" \

View File

@@ -5,7 +5,8 @@ set -e
VERSION=`bin/buildinfo.py long` VERSION=`bin/buildinfo.py long`
SHORT_VERSION=`bin/buildinfo.py short` SHORT_VERSION=`bin/buildinfo.py short`
OUTDIR=release/ BUILDDIR=.pio/build/$1
OUTDIR=release
rm -f $OUTDIR/firmware* rm -f $OUTDIR/firmware*
rm -r $OUTDIR/* || true rm -r $OUTDIR/* || true
@@ -14,7 +15,7 @@ rm -r $OUTDIR/* || true
platformio pkg install -e $1 platformio pkg install -e $1
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS" echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$1/firmware.* rm -f $BUILDDIR/firmware*
# The shell vars the build tool expects to find # The shell vars the build tool expects to find
export APP_VERSION=$VERSION export APP_VERSION=$VERSION
@@ -22,16 +23,14 @@ export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION basename=firmware-$1-$VERSION
pio run --environment $1 # -v pio run --environment $1 # -v
SRCELF=.pio/build/$1/firmware.elf
cp $SRCELF $OUTDIR/$basename.elf cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
echo "Copying ESP32 bin file" echo "Copying ESP32 bin file"
SRCBIN=.pio/build/$1/firmware.factory.bin cp $BUILDDIR/$basename.factory.bin $OUTDIR/$basename.factory.bin
cp $SRCBIN $OUTDIR/$basename.bin
echo "Copying ESP32 update bin file" echo "Copying ESP32 update bin file"
SRCBIN=.pio/build/$1/firmware.bin cp $BUILDDIR/$basename.bin $OUTDIR/$basename.bin
cp $SRCBIN $OUTDIR/$basename-update.bin
echo "Building Filesystem for ESP32 targets" echo "Building Filesystem for ESP32 targets"
# If you want to build the webui, uncomment the following lines # If you want to build the webui, uncomment the following lines
@@ -40,7 +39,13 @@ echo "Building Filesystem for ESP32 targets"
# # Remove webserver files from the filesystem and rebuild # # Remove webserver files from the filesystem and rebuild
# ls -l data/static # Diagnostic list of files # ls -l data/static # Diagnostic list of files
# rm -rf data/static # rm -rf data/static
pio run --environment $1 -t buildfs pio run --environment $1 -t buildfs --disable-auto-clean
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefs-$1-$VERSION.bin cp $BUILDDIR/littlefs-$1-$VERSION.bin $OUTDIR/littlefs-$1-$VERSION.bin
cp bin/device-install.* $OUTDIR cp bin/device-install.* $OUTDIR/
cp bin/device-update.* $OUTDIR cp bin/device-update.* $OUTDIR/
# Generate the manifest file
echo "Generating Meshtastic manifest"
TIMEFORMAT="Generated manifest in %E seconds"
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json

View File

@@ -17,15 +17,19 @@ VERSION=$(bin/buildinfo.py long)
SHORT_VERSION=$(bin/buildinfo.py short) SHORT_VERSION=$(bin/buildinfo.py short)
PIO_ENV=${1:-native} PIO_ENV=${1:-native}
OUTDIR=release/ BUILDDIR=.pio/build/$PIO_ENV
OUTDIR=release
rm -f $OUTDIR/firmware* rm -f $OUTDIR/meshtasticd*
mkdir -p $OUTDIR/ mkdir -p $OUTDIR/
rm -r $OUTDIR/* || true rm -r $OUTDIR/* || true
basename=meshtasticd-$1-$VERSION
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
pio pkg install --environment "$PIO_ENV" || platformioFailed pio pkg install --environment "$PIO_ENV" || platformioFailed
pio run --environment "$PIO_ENV" || platformioFailed pio run --environment "$PIO_ENV" || platformioFailed
cp ".pio/build/$PIO_ENV/program" "$OUTDIR/meshtasticd_linux_$(uname -m)"
cp bin/native-install.* $OUTDIR cp "$BUILDDIR/meshtasticd" "$OUTDIR/meshtasticd_linux_$(uname -m)"
cp bin/native-install.* $OUTDIR/

View File

@@ -5,7 +5,8 @@ set -e
VERSION=$(bin/buildinfo.py long) VERSION=$(bin/buildinfo.py long)
SHORT_VERSION=$(bin/buildinfo.py short) SHORT_VERSION=$(bin/buildinfo.py short)
OUTDIR=release/ BUILDDIR=.pio/build/$1
OUTDIR=release
rm -f $OUTDIR/firmware* rm -f $OUTDIR/firmware*
rm -r $OUTDIR/* || true rm -r $OUTDIR/* || true
@@ -14,7 +15,7 @@ rm -r $OUTDIR/* || true
platformio pkg install -e $1 platformio pkg install -e $1
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS" echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$1/firmware.* rm -f $BUILDDIR/firmware*
# The shell vars the build tool expects to find # The shell vars the build tool expects to find
export APP_VERSION=$VERSION export APP_VERSION=$VERSION
@@ -22,32 +23,32 @@ export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION basename=firmware-$1-$VERSION
pio run --environment $1 # -v pio run --environment $1 # -v
SRCELF=.pio/build/$1/firmware.elf
cp $SRCELF $OUTDIR/$basename.elf
echo "Generating NRF52 dfu file" cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
DFUPKG=.pio/build/$1/firmware.zip
cp $DFUPKG $OUTDIR/$basename-ota.zip
echo "Generating NRF52 uf2 file" echo "Copying NRF52 dfu (OTA) file"
SRCHEX=.pio/build/$1/firmware.hex cp $BUILDDIR/$basename.zip $OUTDIR/$basename.zip
# if WM1110 target, merge hex with softdevice 7.3.0 echo "Copying NRF52 UF2 file"
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2
cp bin/*.uf2 $OUTDIR/
SRCHEX=$BUILDDIR/$basename.hex
# if WM1110 target, copy the merged.hex
if (echo $1 | grep -q "wio-sdk-wm1110"); then if (echo $1 | grep -q "wio-sdk-wm1110"); then
echo "Merging with softdevice" echo "Copying .merged.hex file"
bin/mergehex -m bin/s140_nrf52_7.3.0_softdevice.hex $SRCHEX -o .pio/build/$1/$basename.hex SRCHEX=$BUILDDIR/$basename.merged.hex
SRCHEX=.pio/build/$1/$basename.hex cp $SRCHEX $OUTDIR/
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/$basename.uf2 -f 0xADA52840
cp $SRCHEX $OUTDIR
cp bin/*.uf2 $OUTDIR
else
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/$basename.uf2 -f 0xADA52840
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR
cp bin/*.uf2 $OUTDIR
fi fi
if (echo $1 | grep -q "rak4631"); then if (echo $1 | grep -q "rak4631"); then
echo "Copying hex file" echo "Copying .hex file"
cp .pio/build/$1/firmware.hex $OUTDIR/$basename.hex cp $SRCHEX $OUTDIR/
fi fi
# Generate the manifest file
echo "Generating Meshtastic manifest"
TIMEFORMAT="Generated manifest in %E seconds"
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json

View File

@@ -5,7 +5,8 @@ set -e
VERSION=`bin/buildinfo.py long` VERSION=`bin/buildinfo.py long`
SHORT_VERSION=`bin/buildinfo.py short` SHORT_VERSION=`bin/buildinfo.py short`
OUTDIR=release/ BUILDDIR=.pio/build/$1
OUTDIR=release
rm -f $OUTDIR/firmware* rm -f $OUTDIR/firmware*
rm -r $OUTDIR/* || true rm -r $OUTDIR/* || true
@@ -14,7 +15,7 @@ rm -r $OUTDIR/* || true
platformio pkg install -e $1 platformio pkg install -e $1
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS" echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$1/firmware.* rm -f $BUILDDIR/firmware*
# The shell vars the build tool expects to find # The shell vars the build tool expects to find
export APP_VERSION=$VERSION export APP_VERSION=$VERSION
@@ -22,12 +23,14 @@ export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION basename=firmware-$1-$VERSION
pio run --environment $1 # -v pio run --environment $1 # -v
SRCELF=.pio/build/$1/firmware.elf
cp $SRCELF $OUTDIR/$basename.elf cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
echo "Copying uf2 file" echo "Copying uf2 file"
SRCBIN=.pio/build/$1/firmware.uf2 cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2
cp $SRCBIN $OUTDIR/$basename.uf2
cp bin/device-install.* $OUTDIR # Generate the manifest file
cp bin/device-update.* $OUTDIR echo "Generating Meshtastic manifest"
TIMEFORMAT="Generated manifest in %E seconds"
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json

View File

@@ -5,7 +5,8 @@ set -e
VERSION=$(bin/buildinfo.py long) VERSION=$(bin/buildinfo.py long)
SHORT_VERSION=$(bin/buildinfo.py short) SHORT_VERSION=$(bin/buildinfo.py short)
OUTDIR=release/ BUILDDIR=.pio/build/$1
OUTDIR=release
rm -f $OUTDIR/firmware* rm -f $OUTDIR/firmware*
rm -r $OUTDIR/* || true rm -r $OUTDIR/* || true
@@ -14,7 +15,7 @@ rm -r $OUTDIR/* || true
platformio pkg install -e $1 platformio pkg install -e $1
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS" echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$1/firmware.* rm -f $BUILDDIR/firmware*
# The shell vars the build tool expects to find # The shell vars the build tool expects to find
export APP_VERSION=$VERSION export APP_VERSION=$VERSION
@@ -22,8 +23,14 @@ export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION basename=firmware-$1-$VERSION
pio run --environment $1 # -v pio run --environment $1 # -v
SRCELF=.pio/build/$1/firmware.elf
cp $SRCELF $OUTDIR/$basename.elf
SRCBIN=.pio/build/$1/firmware.bin cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
cp $SRCBIN $OUTDIR/$basename.bin
echo "Copying STM32 bin file"
cp $BUILDDIR/$basename.bin $OUTDIR/$basename.bin
# Generate the manifest file
echo "Generating Meshtastic manifest"
TIMEFORMAT="Generated manifest in %E seconds"
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json

View File

@@ -5,22 +5,14 @@ TITLE Meshtastic device-install
SET "SCRIPT_NAME=%~nx0" SET "SCRIPT_NAME=%~nx0"
SET "DEBUG=0" SET "DEBUG=0"
SET "PYTHON=" SET "PYTHON="
SET "TFT_BUILD=0"
SET "BIGDB8=0"
SET "MUIDB8=0"
SET "BIGDB16=0"
SET "ESPTOOL_BAUD=115200" SET "ESPTOOL_BAUD=115200"
SET "ESPTOOL_CMD=" SET "ESPTOOL_CMD="
SET "LOGCOUNTER=0" SET "LOGCOUNTER=0"
SET "BPS_RESET=0" SET "BPS_RESET=0"
@REM Default offsets.
@REM FIXME: Determine mcu from PlatformIO variant, this is unmaintainable. @REM https://github.com/meshtastic/web-flasher/blob/main/stores/firmwareStore.ts#L202
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone t-eth-elite tlora-pager mesh-tab dreamcatcher ESP32-S3-Pico seeed-sensecap-indicator heltec_capsule_sensor_v3 vision-master icarus tracksenger elecrow-adv heltec-v4" SET "OTA_OFFSET=0x260000"
SET "C3=esp32c3" SET "SPIFFS_OFFSET=0x300000"
@REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable.
SET "BIGDB_8MB=crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core tracksenger"
SET "MUIDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator"
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite tlora-pager t-watch-s3 elecrow-adv heltec-v4"
GOTO getopts GOTO getopts
:help :help
@@ -29,7 +21,7 @@ ECHO.
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] [--1200bps-reset] ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] [--1200bps-reset]
ECHO. ECHO.
ECHO Options: ECHO Options:
ECHO -f filename The firmware .bin file to flash. Custom to your device type and region. (required) ECHO -f filename The firmware .factory.bin file to flash. Custom to your device type and region. (required)
ECHO The file must be located in this current directory. ECHO The file must be located in this current directory.
ECHO -p PORT Set the environment variable for ESPTOOL_PORT. ECHO -p PORT Set the environment variable for ESPTOOL_PORT.
ECHO If not set, ESPTOOL iterates all ports (Dangerous). ECHO If not set, ESPTOOL iterates all ports (Dangerous).
@@ -40,12 +32,12 @@ ECHO --1200bps-reset Attempt to place the device in correct mode. (1200bps
ECHO Some hardware requires this twice. ECHO Some hardware requires this twice.
ECHO. ECHO.
ECHO Example: %SCRIPT_NAME% -p COM17 --1200bps-reset ECHO Example: %SCRIPT_NAME% -p COM17 --1200bps-reset
ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4.bin -p COM11 ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4.factory.bin -p COM11
ECHO Example: %SCRIPT_NAME% -f firmware-unphone-2.6.0.0b106d4.bin -p COM11 ECHO Example: %SCRIPT_NAME% -f firmware-unphone-2.6.0.0b106d4.factory.bin -p COM11
GOTO eof GOTO eof
:version :version
ECHO %SCRIPT_NAME% [Version 2.6.2] ECHO %SCRIPT_NAME% [Version 2.7.0]
ECHO Meshtastic ECHO Meshtastic
GOTO eof GOTO eof
@@ -78,8 +70,8 @@ IF "__!FILENAME!__"=="____" (
CALL :LOG_MESSAGE ERROR "Filename containing spaces are not supported." CALL :LOG_MESSAGE ERROR "Filename containing spaces are not supported."
GOTO help GOTO help
) )
IF "__!FILENAME:firmware-=!__"=="__!FILENAME!__" ( IF NOT "__!FILENAME:.factory.bin=!__"=="__!FILENAME!__" (
CALL :LOG_MESSAGE ERROR "Filename must be a firmware-* file." CALL :LOG_MESSAGE ERROR "Filename must be a firmware-*.factory.bin file."
GOTO help GOTO help
) )
@REM Remove ".\" or "./" file prefix if present. @REM Remove ".\" or "./" file prefix if present.
@@ -93,12 +85,26 @@ IF NOT EXIST !FILENAME! (
GOTO eof GOTO eof
) )
IF NOT "!FILENAME:update=!"=="!FILENAME!" ( CALL :LOG_MESSAGE DEBUG "Checking for metadata..."
CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!" @REM Derive metadata filename from firmware filename.
CALL :LOG_MESSAGE INFO "Use script device-update.bat to flash update !FILENAME!." SET "METAFILE=!FILENAME:.factory.bin=!.mt.json"
GOTO eof IF EXIST !METAFILE! (
@REM Print parsed json with powershell
CALL :LOG_MESSAGE INFO "Firmware metadata: !METAFILE!"
powershell -NoProfile -Command "(Get-Content '!METAFILE!' | ConvertFrom-Json | Out-String).Trim()"
@REM Save metadata values to variables for later use.
FOR /f "usebackq" %%A IN (`powershell -NoProfile -Command ^
"(Get-Content '!METAFILE!' | ConvertFrom-Json).mcu"`) DO SET "MCU=%%A"
FOR /f "usebackq" %%A IN (`powershell -NoProfile -Command ^
"(Get-Content '!METAFILE!' | ConvertFrom-Json).part | Where-Object { $_.subtype -eq 'ota_1' } | Select-Object -ExpandProperty offset"`
) DO SET "OTA_OFFSET=%%A"
FOR /f "usebackq" %%A IN (`powershell -NoProfile -Command ^
"(Get-Content '!METAFILE!' | ConvertFrom-Json).part | Where-Object { $_.subtype -eq 'spiffs' } | Select-Object -ExpandProperty offset"`
) DO SET "SPIFFS_OFFSET=%%A"
) ELSE ( ) ELSE (
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!" CALL :LOG_MESSAGE ERROR "No metadata file found: !METAFILE!"
GOTO eof
) )
:skip-filename :skip-filename
@@ -108,7 +114,7 @@ IF NOT "__%PYTHON%__"=="____" (
SET "ESPTOOL_CMD=!PYTHON! -m esptool" SET "ESPTOOL_CMD=!PYTHON! -m esptool"
CALL :LOG_MESSAGE DEBUG "Python interpreter supplied." CALL :LOG_MESSAGE DEBUG "Python interpreter supplied."
) ELSE ( ) ELSE (
CALL :LOG_MESSAGE DEBUG "Python interpreter NOT supplied. Looking for esptool... CALL :LOG_MESSAGE DEBUG "Python interpreter NOT supplied. Looking for esptool..."
WHERE esptool >nul 2>&1 WHERE esptool >nul 2>&1
IF %ERRORLEVEL% EQU 0 ( IF %ERRORLEVEL% EQU 0 (
@REM WHERE exits with code 0 if esptool is found. @REM WHERE exits with code 0 if esptool is found.
@@ -146,100 +152,26 @@ IF %BPS_RESET% EQU 1 (
GOTO eof GOTO eof
) )
@REM Check if FILENAME contains "-tft-" and set target partitionScheme accordingly. @REM Extract PROGNAME from %FILENAME% for later use.
@REM https://github.com/meshtastic/web-flasher/blob/main/types/resources.ts#L3 SET "PROGNAME=!FILENAME:.factory.bin=!"
IF NOT "!FILENAME:-tft-=!"=="!FILENAME!" ( CALL :LOG_MESSAGE DEBUG "Computed PROGNAME: !PROGNAME!"
CALL :LOG_MESSAGE DEBUG "We are working with a *-tft-* file. !FILENAME!"
SET "TFT_BUILD=1" IF "__!MCU!__" == "__esp32s3__" (
@REM We are working with ESP32-S3
SET "OTA_FILENAME=bleota-s3.bin"
) ELSE IF "__!MCU!__" == "__esp32c3__" (
@REM We are working with ESP32-C3
SET "OTA_FILENAME=bleota-c3.bin"
) ELSE ( ) ELSE (
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *-tft-* file. !FILENAME!" @REM Everything else
SET "OTA_FILENAME=bleota.bin"
) )
FOR %%a IN (%BIGDB_8MB%) DO (
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
@REM We are working with any of %BIGDB_8MB%.
SET "BIGDB8=1"
GOTO end_loop_bigdb_8mb
)
)
:end_loop_bigdb_8mb
FOR %%a IN (%MUIDB_8MB%) DO (
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
@REM We are working with any of %MUIDB_8MB%.
SET "MUIDB8=1"
GOTO end_loop_muidb_8mb
)
)
:end_loop_muidb_8mb
FOR %%a IN (%BIGDB_16MB%) DO (
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
@REM We are working with any of %BIGDB_16MB%.
SET "BIGDB16=1"
GOTO end_loop_bigdb_16mb
)
)
:end_loop_bigdb_16mb
IF %BIGDB8% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 8mb partition selected."
IF %MUIDB8% EQU 1 CALL :LOG_MESSAGE INFO "MUIDB 8mb partition selected."
IF %BIGDB16% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 16mb partition selected."
@REM Extract BASENAME from %FILENAME% for later use.
SET "BASENAME=!FILENAME:firmware-=!"
CALL :LOG_MESSAGE DEBUG "Computed firmware basename: !BASENAME!"
@REM Account for S3 and C3 board's different OTA partition.
FOR %%a IN (%S3%) DO (
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
@REM We are working with any of %S3%.
SET "OTA_FILENAME=bleota-s3.bin"
GOTO :end_loop_s3
)
)
FOR %%a IN (%C3%) DO (
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
@REM We are working with any of %C3%.
SET "OTA_FILENAME=bleota-c3.bin"
GOTO :end_loop_c3
)
)
@REM Everything else
SET "OTA_FILENAME=bleota.bin"
:end_loop_s3
:end_loop_c3
CALL :LOG_MESSAGE DEBUG "Set OTA_FILENAME to: !OTA_FILENAME!" CALL :LOG_MESSAGE DEBUG "Set OTA_FILENAME to: !OTA_FILENAME!"
@REM Set SPIFFS filename with "littlefs-" prefix. @REM Set SPIFFS filename with "littlefs-" prefix.
SET "SPIFFS_FILENAME=littlefs-%BASENAME%" SET "SPIFFS_FILENAME=littlefs-!PROGNAME:firmware-=!.bin"
CALL :LOG_MESSAGE DEBUG "Set SPIFFS_FILENAME to: !SPIFFS_FILENAME!" CALL :LOG_MESSAGE DEBUG "Set SPIFFS_FILENAME to: !SPIFFS_FILENAME!"
@REM Default offsets.
@REM https://github.com/meshtastic/web-flasher/blob/main/stores/firmwareStore.ts#L202
SET "OTA_OFFSET=0x260000"
SET "SPIFFS_OFFSET=0x300000"
@REM Offsets for BigDB 8mb.
IF %BIGDB8% EQU 1 (
SET "OTA_OFFSET=0x340000"
SET "SPIFFS_OFFSET=0x670000"
)
@REM Offsets for MUIDB 8mb.
IF %MUIDB8% EQU 1 (
SET "OTA_OFFSET=0x5D0000"
SET "SPIFFS_OFFSET=0x670000"
)
@REM Offsets for BigDB 16mb.
IF %BIGDB16% EQU 1 (
SET "OTA_OFFSET=0x650000"
SET "SPIFFS_OFFSET=0xc90000"
)
CALL :LOG_MESSAGE DEBUG "Set OTA_OFFSET to: !OTA_OFFSET!" CALL :LOG_MESSAGE DEBUG "Set OTA_OFFSET to: !OTA_OFFSET!"
CALL :LOG_MESSAGE DEBUG "Set SPIFFS_OFFSET to: !SPIFFS_OFFSET!" CALL :LOG_MESSAGE DEBUG "Set SPIFFS_OFFSET to: !SPIFFS_OFFSET!"

View File

@@ -2,69 +2,15 @@
PYTHON=${PYTHON:-$(which python3 python | head -n 1)} PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
BPS_RESET=false BPS_RESET=false
TFT_BUILD=false
MCU="" MCU=""
# Constants # Constants
RESET_BAUD=1200 RESET_BAUD=1200
FIRMWARE_OFFSET=0x00 FIRMWARE_OFFSET=0x00
# Default littlefs* offset.
# Variant groups OFFSET=0x300000
BIGDB_8MB=( # Default OTA Offset
"crowpanel-esp32s3" OTA_OFFSET=0x260000
"heltec_capsule_sensor_v3"
"heltec-v3"
"heltec-vision-master-e213"
"heltec-vision-master-e290"
"heltec-vision-master-t190"
"heltec-wireless-paper"
"heltec-wireless-tracker"
"heltec-wsl-v3"
"icarus"
"seeed-xiao-s3"
"tbeam-s3-core"
"tracksenger"
)
MUIDB_8MB=(
"picomputer-s3"
"unphone"
"seeed-sensecap-indicator"
)
BIGDB_16MB=(
"dreamcatcher"
"elecrow-adv"
"ESP32-S3-Pico"
"heltec-v4"
"m5stack-cores3"
"mesh-tab"
"station-g2"
"t-deck"
"t-energy-s3"
"t-eth-elite"
"t-watch-s3"
"tlora-pager"
)
S3_VARIANTS=(
"s3"
"-v3"
"-v4"
"t-deck"
"wireless-paper"
"wireless-tracker"
"station-g2"
"unphone"
"t-eth-elite"
"tlora-pager"
"mesh-tab"
"dreamcatcher"
"ESP32-S3-Pico"
"seeed-sensecap-indicator"
"heltec_capsule_sensor_v3"
"vision-master"
"icarus"
"tracksenger"
"elecrow-adv"
)
# Determine the correct esptool command to use # Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then if "$PYTHON" -m esptool version >/dev/null 2>&1; then
@@ -78,6 +24,14 @@ else
exit 1 exit 1
fi fi
# Check for jq
if ! command -v jq >/dev/null 2>&1; then
echo "Error: jq not found" >&2
echo "Install jq with your package manager." >&2
echo "e.g. 'apt install jq', 'dnf install jq', 'brew install jq', etc." >&2
exit 1
fi
set -e set -e
# Usage info # Usage info
@@ -89,7 +43,7 @@ Flash image file to device, but first erasing and writing system information.
-h Display this help and exit. -h Display this help and exit.
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous). -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON") -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The firmware .bin file to flash. Custom to your device type and region. -f FILENAME The firmware *.factory.bin file to flash. Custom to your device type and region.
--1200bps-reset Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset) --1200bps-reset Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset)
EOF EOF
@@ -138,69 +92,43 @@ fi
shift shift
} }
if [[ "$FILENAME" != firmware-* ]]; then if [[ $(basename "$FILENAME") != firmware-*.factory.bin ]]; then
echo "Filename must be a firmware-* file." echo "Filename must be a firmware-*.factory.bin file."
exit 1 exit 1
fi fi
# Check if FILENAME contains "-tft-" and set target partitionScheme accordingly. # Extract PROGNAME from %FILENAME% for later use.
if [[ "${FILENAME//-tft-/}" != "$FILENAME" ]]; then PROGNAME="${FILENAME/.factory.bin/}"
TFT_BUILD=true # Derive metadata filename from %PROGNAME%.
fi METAFILE="${PROGNAME}.mt.json"
# Extract BASENAME from %FILENAME% for later use. if [[ -f "$FILENAME" && "$FILENAME" == *.factory.bin ]]; then
BASENAME="${FILENAME/firmware-/}" # Display metadata if it exists
if [[ -f "$METAFILE" ]]; then
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then echo "Firmware metadata: ${METAFILE}"
# Default littlefs* offset. jq . "$METAFILE"
OFFSET=0x300000 # Extract relevant fields from metadata
if [[ $(jq -r '.part' "$METAFILE") != "null" ]]; then
# Default OTA Offset OTA_OFFSET=$(jq -r '.part[] | select(.subtype == "ota_1") | .offset' "$METAFILE")
OTA_OFFSET=0x260000 SPIFFS_OFFSET=$(jq -r '.part[] | select(.subtype == "spiffs") | .offset' "$METAFILE")
# littlefs* offset for BigDB 8mb and OTA OFFSET.
for variant in "${BIGDB_8MB[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0x670000
OTA_OFFSET=0x340000
fi
done
for variant in "${MUIDB_8MB[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0x670000
OTA_OFFSET=0x5D0000
fi
done
# littlefs* offset for BigDB 16mb and OTA OFFSET.
for variant in "${BIGDB_16MB[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0xc90000
OTA_OFFSET=0x650000
fi
done
# Account for S3 board's different OTA partition
# FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
for variant in "${S3_VARIANTS[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
MCU="esp32s3"
fi
done
if [ "$MCU" != "esp32s3" ]; then
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
OTAFILE=bleota.bin
else
OTAFILE=bleota-c3.bin
fi fi
MCU=$(jq -r '.mcu' "$METAFILE")
else else
echo "ERROR: No metadata file found at ${METAFILE}"
exit 1
fi
# Determine OTA filename based on MCU type
if [ "$MCU" == "esp32s3" ]; then
OTAFILE=bleota-s3.bin OTAFILE=bleota-s3.bin
elif [ "$MCU" == "esp32c3" ]; then
OTAFILE=bleota-c3.bin
else
OTAFILE=bleota.bin
fi fi
# Set SPIFFS filename with "littlefs-" prefix. # Set SPIFFS filename with "littlefs-" prefix.
SPIFFSFILE=littlefs-${BASENAME} SPIFFSFILE="littlefs-${PROGNAME/firmware-/}.bin"
if [[ ! -f "$FILENAME" ]]; then if [[ ! -f "$FILENAME" ]]; then
echo "Error: file ${FILENAME} wasn't found. Terminating." echo "Error: file ${FILENAME} wasn't found. Terminating."

View File

@@ -30,11 +30,11 @@ ECHO --change-mode Attempt to place the device in correct mode. (1200bps
ECHO Some hardware requires this twice. ECHO Some hardware requires this twice.
ECHO. ECHO.
ECHO Example: %SCRIPT_NAME% -p COM17 --change-mode ECHO Example: %SCRIPT_NAME% -p COM17 --change-mode
ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4-update.bin -p COM11 ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4.bin -p COM11
GOTO eof GOTO eof
:version :version
ECHO %SCRIPT_NAME% [Version 2.6.2] ECHO %SCRIPT_NAME% [Version 2.7.0]
ECHO Meshtastic ECHO Meshtastic
GOTO eof GOTO eof
@@ -78,12 +78,12 @@ IF NOT EXIST !FILENAME! (
GOTO eof GOTO eof
) )
IF "!FILENAME:update=!"=="!FILENAME!" ( IF NOT "__!FILENAME:.factory.bin=!__"=="__!FILENAME!__" (
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!" CALL :LOG_MESSAGE DEBUG "We are working with a *.factory.bin* file. !FILENAME!"
CALL :LOG_MESSAGE INFO "Use script device-install.bat to flash !FILENAME!." CALL :LOG_MESSAGE INFO "Use script device-install.bat to flash !FILENAME!."
GOTO eof GOTO eof
) ELSE ( ) ELSE (
CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!" CALL :LOG_MESSAGE DEBUG "We are not working with a *.factory.bin* file. !FILENAME!"
) )
:skip-filename :skip-filename

View File

@@ -29,7 +29,7 @@ Flash image file to device, leave existing system intact."
-h Display this help and exit -h Display this help and exit
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous). -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON") -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The *update.bin file to flash. Custom to your device type. -f FILENAME The *.bin file to flash. Custom to your device type.
--change-mode Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset) --change-mode Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset)
EOF EOF
@@ -78,7 +78,7 @@ fi
shift shift
} }
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then if [[ -f "$FILENAME" && "$FILENAME" != *.factory.bin ]]; then
echo "Trying to flash update ${FILENAME}" echo "Trying to flash update ${FILENAME}"
$ESPTOOL_CMD --baud $FLASH_BAUD write-flash $UPDATE_OFFSET "${FILENAME}" $ESPTOOL_CMD --baud $FLASH_BAUD write-flash $UPDATE_OFFSET "${FILENAME}"
else else

View File

@@ -75,7 +75,7 @@ TOOLS = {
} }
BACKTRACE_REGEX = re.compile( BACKTRACE_REGEX = re.compile(
r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b" r"\b(0x4[0-9a-fA-F]{7,8}):0x[0-9a-fA-F]{8}\b"
) )
EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$") EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
COUNTER_REGEX = re.compile( COUNTER_REGEX = re.compile(
@@ -89,7 +89,7 @@ POINTER_REGEX = re.compile(
STACK_BEGIN = ">>>stack>>>" STACK_BEGIN = ">>>stack>>>"
STACK_END = "<<<stack<<<" STACK_END = "<<<stack<<<"
STACK_REGEX = re.compile( STACK_REGEX = re.compile(
"^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$" r"^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$"
) )
StackLine = namedtuple("StackLine", ["offset", "content"]) StackLine = namedtuple("StackLine", ["offset", "content"])
@@ -223,7 +223,7 @@ class AddressResolver(object):
if match is None: if match is None:
if last is not None and line.startswith("(inlined by)"): if last is not None and line.startswith("(inlined by)"):
line = line[12:].strip() line = line[12:].strip()
self._address_map[last] += "\n \-> inlined by: " + line self._address_map[last] += "\n \\-> inlined by: " + line
continue continue
if match.group("result") == "?? ??:0": if match.group("result") == "?? ??:0":

View File

@@ -2,4 +2,4 @@
set -e set -e
pio run --environment native pio run --environment native
gdbserver --once localhost:2345 .pio/build/native/program "$@" gdbserver --once localhost:2345 .pio/build/native/meshtasticd "$@"

View File

@@ -2,4 +2,4 @@
set -e set -e
pio run --environment native pio run --environment native
.pio/build/native/program "$@" .pio/build/native/meshtasticd "$@"

View File

@@ -2,98 +2,77 @@
# trunk-ignore-all(ruff/F821) # trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821): For SConstruct imports # trunk-ignore-all(flake8/F821): For SConstruct imports
import sys import sys
from os.path import join from os.path import join, basename, isfile
import subprocess import subprocess
import json import json
import re import re
import time
from datetime import datetime from datetime import datetime
from readprops import readProps from readprops import readProps
Import("env") Import("env")
platform = env.PioPlatform() platform = env.PioPlatform()
progname = env.get("PROGNAME")
lfsbin = f"{progname.replace('firmware-', 'littlefs-')}.bin"
def manifest_gather(source, target, env):
def esp32_create_combined_bin(source, target, env): out = []
# this sub is borrowed from ESPEasy build toolchain. It's licensed under GPL V3 check_paths = [
# https://github.com/letscontrolit/ESPEasy/blob/mega/tools/pio/post_esp32.py progname,
print("Generating combined binary for serial flashing") f"{progname}.elf",
f"{progname}.bin",
app_offset = 0x10000 f"{progname}.factory.bin",
f"{progname}.hex",
new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin") f"{progname}.merged.hex",
sections = env.subst(env.get("FLASH_EXTRA_IMAGES")) f"{progname}.uf2",
firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin") f"{progname}.factory.uf2",
chip = env.get("BOARD_MCU") f"{progname}.zip",
flash_size = env.BoardConfig().get("upload.flash_size") lfsbin
flash_freq = env.BoardConfig().get("build.f_flash", "40m")
flash_freq = flash_freq.replace("000000L", "m")
flash_mode = env.BoardConfig().get("build.flash_mode", "dio")
memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi")
if flash_mode == "qio" or flash_mode == "qout":
flash_mode = "dio"
if memory_type == "opi_opi" or memory_type == "opi_qspi":
flash_mode = "dout"
cmd = [
"--chip",
chip,
"merge_bin",
"-o",
new_file_name,
"--flash_mode",
flash_mode,
"--flash_freq",
flash_freq,
"--flash_size",
flash_size,
] ]
for p in check_paths:
f = env.File(env.subst(f"$BUILD_DIR/{p}"))
if f.exists():
d = {
"name": p,
"md5": f.get_content_hash(), # Returns MD5 hash
"bytes": f.get_size() # Returns file size in bytes
}
out.append(d)
print(d)
manifest_write(out, env)
print(" Offset | File") def manifest_write(files, env):
for section in sections: manifest = {
sect_adr, sect_file = section.split(" ", 1) "version": verObj["long"],
print(f" - {sect_adr} | {sect_file}") "build_epoch": build_epoch,
cmd += [sect_adr, sect_file] "board": env.get("PIOENV"),
"mcu": env.get("BOARD_MCU"),
"repo": repo_owner,
"files": files,
"part": None,
"has_mui": False,
"has_inkhud": False,
}
# Get partition table (generated in esp32_pre.py) if it exists
if env.get("custom_mtjson_part"):
# custom_mtjson_part is a JSON string, convert it back to a dict
pj = json.loads(env.get("custom_mtjson_part"))
manifest["part"] = pj
# Enable has_mui for TFT builds
if ("HAS_TFT", 1) in env.get("CPPDEFINES", []):
manifest["has_mui"] = True
if "MESHTASTIC_INCLUDE_INKHUD" in env.get("CPPDEFINES", []):
manifest["has_inkhud"] = True
print(f" - {hex(app_offset)} | {firmware_name}") # Write the manifest to the build directory
cmd += [hex(app_offset), firmware_name] with open(env.subst("$BUILD_DIR/${PROGNAME}.mt.json"), "w") as f:
json.dump(manifest, f, indent=2)
print("Using esptool.py arguments: %s" % " ".join(cmd))
esptool.main(cmd)
if platform.name == "espressif32":
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
import esptool
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
esp32_kind = env.GetProjectOption("custom_esp32_kind")
if esp32_kind == "esp32":
# Free up some IRAM by removing auxiliary SPI flash chip drivers.
# Wrapped stub symbols are defined in src/platform/esp32/iram-quirk.c.
env.Append(
LINKFLAGS=[
"-Wl,--wrap=esp_flash_chip_gd",
"-Wl,--wrap=esp_flash_chip_issi",
"-Wl,--wrap=esp_flash_chip_winbond",
]
)
else:
# For newer ESP32 targets, using newlib nano works better.
env.Append(LINKFLAGS=["--specs=nano.specs", "-u", "_printf_float"])
if platform.name == "nordicnrf52":
env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex",
env.VerboseAction(f"\"{sys.executable}\" ./bin/uf2conv.py \"$BUILD_DIR/firmware.hex\" -c -f 0xADA52840 -o \"$BUILD_DIR/firmware.uf2\"",
"Generating UF2 file"))
Import("projenv") Import("projenv")
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties" prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
verObj = readProps(prefsLoc) verObj = readProps(prefsLoc)
print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"] + " on " + env.get("PIOENV")) print(f"Using meshtastic platformio-custom.py, firmware version {verObj['long']} on {env.get('PIOENV')}")
# get repository owner if git is installed # get repository owner if git is installed
try: try:
@@ -139,10 +118,10 @@ flags = [
"-DBUILD_EPOCH=" + str(build_epoch), "-DBUILD_EPOCH=" + str(build_epoch),
] + pref_flags ] + pref_flags
print ("Using flags:") print("Using flags:")
for flag in flags: for flag in flags:
print(flag) print(flag)
projenv.Append( projenv.Append(
CCFLAGS=flags, CCFLAGS=flags,
) )
@@ -181,3 +160,19 @@ def load_boot_logo(source, target, env):
# Load the boot logo on TFT builds # Load the boot logo on TFT builds
if ("HAS_TFT", 1) in env.get("CPPDEFINES", []): if ("HAS_TFT", 1) in env.get("CPPDEFINES", []):
env.AddPreAction('$BUILD_DIR/littlefs.bin', load_boot_logo) env.AddPreAction('$BUILD_DIR/littlefs.bin', load_boot_logo)
# Rename (mv) littlefs.bin to include the PROGNAME
# This ensures the littlefs.bin is named consistently with the firmware
env.AddPostAction('$BUILD_DIR/littlefs.bin', env.VerboseAction(
f'mv $BUILD_DIR/littlefs.bin $BUILD_DIR/{lfsbin}',
f'Renaming littlefs.bin to {lfsbin}'
))
env.AddCustomTarget(
name="mtjson",
dependencies=None,
actions=[manifest_gather],
title="Meshtastic Manifest",
description="Generating Meshtastic manifest JSON + Checksums",
always_build=True,
)

16
bin/platformio-pre.py Normal file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python3
# trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821): For SConstruct imports
Import("env")
platform = env.PioPlatform()
if platform.name == "native":
env.Replace(PROGNAME="meshtasticd")
else:
from readprops import readProps
prefsLoc = env["PROJECT_DIR"] + "/version.properties"
verObj = readProps(prefsLoc)
env.Replace(PROGNAME=f"firmware-{env.get('PIOENV')}-{verObj['long']}")
# Print the new program name for verification
print(f"PROGNAME: {env.get('PROGNAME')}")

View File

@@ -3,7 +3,7 @@
set -e set -e
echo "Starting simulator" echo "Starting simulator"
.pio/build/native/program & .pio/build/native/meshtasticd -s &
sleep 20 # 5 seconds was not enough sleep 20 # 5 seconds was not enough
echo "Simulator started, launching python test..." echo "Simulator started, launching python test..."

1
debian/rules vendored
View File

@@ -28,5 +28,4 @@ override_dh_auto_build:
# Build with platformio # Build with platformio
$(PIO_ENV) platformio run -e native-tft $(PIO_ENV) platformio run -e native-tft
# Move the binary and default config to the correct name # Move the binary and default config to the correct name
mv .pio/build/native-tft/program .pio/build/native-tft/meshtasticd
cp bin/config-dist.yaml bin/config.yaml cp bin/config-dist.yaml bin/config.yaml

View File

@@ -1,10 +1,9 @@
#!/usr/bin/env python3
# trunk-ignore-all(flake8/F821) # trunk-ignore-all(flake8/F821)
# trunk-ignore-all(ruff/F821) # trunk-ignore-all(ruff/F821)
Import("env") Import("env")
# NOTE: This is not currently used, but can serve as an example on how to write extra_scripts
# print("Current CLI targets", COMMAND_LINE_TARGETS) # print("Current CLI targets", COMMAND_LINE_TARGETS)
# print("Current Build targets", BUILD_TARGETS) # print("Current Build targets", BUILD_TARGETS)
# print("CPP defs", env.get("CPPDEFINES")) # print("CPP defs", env.get("CPPDEFINES"))

80
extra_scripts/esp32_extra.py Executable file
View File

@@ -0,0 +1,80 @@
#!/usr/bin/env python3
# trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821): For SConstruct imports
# trunk-ignore-all(ruff/E402): Hacky esptool import
# trunk-ignore-all(flake8/E402): Hacky esptool import
import sys
from os.path import join
Import("env")
platform = env.PioPlatform()
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
import esptool
def esp32_create_combined_bin(source, target, env):
# this sub is borrowed from ESPEasy build toolchain. It's licensed under GPL V3
# https://github.com/letscontrolit/ESPEasy/blob/mega/tools/pio/post_esp32.py
print("Generating combined binary for serial flashing")
app_offset = 0x10000
new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin")
sections = env.subst(env.get("FLASH_EXTRA_IMAGES"))
firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin")
chip = env.get("BOARD_MCU")
board = env.BoardConfig()
flash_size = board.get("upload.flash_size")
flash_freq = board.get("build.f_flash", "40m")
flash_freq = flash_freq.replace("000000L", "m")
flash_mode = board.get("build.flash_mode", "dio")
memory_type = board.get("build.arduino.memory_type", "qio_qspi")
if flash_mode == "qio" or flash_mode == "qout":
flash_mode = "dio"
if memory_type == "opi_opi" or memory_type == "opi_qspi":
flash_mode = "dout"
cmd = [
"--chip",
chip,
"merge_bin",
"-o",
new_file_name,
"--flash_mode",
flash_mode,
"--flash_freq",
flash_freq,
"--flash_size",
flash_size,
]
print(" Offset | File")
for section in sections:
sect_adr, sect_file = section.split(" ", 1)
print(f" - {sect_adr} | {sect_file}")
cmd += [sect_adr, sect_file]
print(f" - {hex(app_offset)} | {firmware_name}")
cmd += [hex(app_offset), firmware_name]
print("Using esptool.py arguments: %s" % " ".join(cmd))
esptool.main(cmd)
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
esp32_kind = env.GetProjectOption("custom_esp32_kind")
if esp32_kind == "esp32":
# Free up some IRAM by removing auxiliary SPI flash chip drivers.
# Wrapped stub symbols are defined in src/platform/esp32/iram-quirk.c.
env.Append(
LINKFLAGS=[
"-Wl,--wrap=esp_flash_chip_gd",
"-Wl,--wrap=esp_flash_chip_issi",
"-Wl,--wrap=esp_flash_chip_winbond",
]
)
else:
# For newer ESP32 targets, using newlib nano works better.
env.Append(LINKFLAGS=["--specs=nano.specs", "-u", "_printf_float"])

73
extra_scripts/esp32_pre.py Executable file
View File

@@ -0,0 +1,73 @@
#!/usr/bin/env python3
# trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821): For SConstruct imports
import json
import sys
from os.path import isfile
Import("env")
# From https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py
def _parse_size(value):
if isinstance(value, int):
return value
elif value.isdigit():
return int(value)
elif value.startswith("0x"):
return int(value, 16)
elif value[-1].upper() in ("K", "M"):
base = 1024 if value[-1].upper() == "K" else 1024 * 1024
return int(value[:-1]) * base
return value
def _parse_partitions(env):
partitions_csv = env.subst("$PARTITIONS_TABLE_CSV")
if not isfile(partitions_csv):
sys.stderr.write(
"Could not find the file %s with partitions " "table.\n" % partitions_csv
)
env.Exit(1)
return
result = []
# The first offset is 0x9000 because partition table is flashed to 0x8000 and
# occupies an entire flash sector, which size is 0x1000
next_offset = 0x9000
with open(partitions_csv) as fp:
for line in fp.readlines():
line = line.strip()
if not line or line.startswith("#"):
continue
tokens = [t.strip() for t in line.split(",")]
if len(tokens) < 5:
continue
bound = 0x10000 if tokens[1] in ("0", "app") else 4
calculated_offset = (next_offset + bound - 1) & ~(bound - 1)
partition = {
"name": tokens[0],
"type": tokens[1],
"subtype": tokens[2],
"offset": tokens[3] or calculated_offset,
"size": tokens[4],
"flags": tokens[5] if len(tokens) > 5 else None,
}
result.append(partition)
next_offset = _parse_size(partition["offset"]) + _parse_size(
partition["size"]
)
return result
def mtjson_esp32_part(target, source, env):
part = _parse_partitions(env)
pj = json.dumps(part)
# print(f"JSON_PARTITIONS: {pj}")
# Dump json string to 'custom_mtjson_part' variable to use later when writing the manifest
env.Replace(custom_mtjson_part=pj)
env.AddPreAction("mtjson", mtjson_esp32_part)

50
extra_scripts/nrf52_extra.py Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python3
# trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821): For SConstruct imports
import sys
from os.path import basename
Import("env")
# Custom HEX from ELF
# Convert hex to uf2 for nrf52
def nrf52_hex_to_uf2(source, target, env):
hex_path = target[0].get_abspath()
# When using merged hex, drop 'merged' from uf2 filename
uf2_path = hex_path.replace(".merged.", ".")
uf2_path = uf2_path.replace(".hex", ".uf2")
env.Execute(
env.VerboseAction(
f'"{sys.executable}" ./bin/uf2conv.py "{hex_path}" -c -f 0xADA52840 -o "{uf2_path}"',
f"Generating UF2 file from {basename(hex_path)}",
)
)
def nrf52_mergehex(source, target, env):
hex_path = target[0].get_abspath()
merged_hex_path = hex_path.replace(".hex", ".merged.hex")
merge_with = None
if "wio-sdk-wm1110" == str(env.get("PIOENV")):
merge_with = env.subst("$PROJECT_DIR/bin/s140_nrf52_7.3.0_softdevice.hex")
else:
print("merge_with not defined for this target")
if merge_with is not None:
env.Execute(
env.VerboseAction(
f'"$PROJECT_DIR/bin/mergehex" -m "{hex_path}" "{merge_with}" -o "{merged_hex_path}"',
"Merging HEX with SoftDevice",
)
)
print(f'Merged file saved at "{basename(merged_hex_path)}"')
nrf52_hex_to_uf2([hex_path, merge_with], [env.File(merged_hex_path)], env)
# if WM1110 target, merge hex with softdevice 7.3.0
if "wio-sdk-wm1110" == env.get("PIOENV"):
env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex", nrf52_mergehex)
else:
env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex", nrf52_hex_to_uf2)

View File

@@ -1,7 +1,9 @@
#!/usr/bin/env python3
# trunk-ignore-all(ruff/F821) # trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821): For SConstruct imports # trunk-ignore-all(flake8/F821): For SConstruct imports
Import("env") Import("env")
# Custom HEX from ELF # Custom HEX from ELF
env.AddPostAction( env.AddPostAction(
"$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.elf",

View File

@@ -76,7 +76,7 @@ platformio run -e native-tft
%install %install
# Install meshtasticd binary # Install meshtasticd binary
mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{_bindir}
install -m 0755 .pio/build/native-tft/program %{buildroot}%{_bindir}/meshtasticd install -m 0755 .pio/build/native-tft/meshtasticd %{buildroot}%{_bindir}/meshtasticd
# Install portduino VFS dir # Install portduino VFS dir
install -p -d -m 0770 %{buildroot}%{_localstatedir}/lib/meshtasticd install -p -d -m 0770 %{buildroot}%{_localstatedir}/lib/meshtasticd

View File

@@ -14,7 +14,9 @@ description = Meshtastic
[env] [env]
test_build_src = true test_build_src = true
extra_scripts = bin/platformio-custom.py extra_scripts =
pre:bin/platformio-pre.py
bin/platformio-custom.py
; note: we add src to our include search path so that lmic_project_config can override ; note: we add src to our include search path so that lmic_project_config can override
; note: TINYGPS_OPTION_NO_CUSTOM_FIELDS is VERY important. We don't use custom fields and somewhere in that pile ; note: TINYGPS_OPTION_NO_CUSTOM_FIELDS is VERY important. We don't use custom fields and somewhere in that pile
; of code is a heap corruption bug! ; of code is a heap corruption bug!
@@ -122,7 +124,7 @@ 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/3bf332240416c5cb8c919fac2a0ec7260eb3be75.zip https://github.com/meshtastic/device-ui/archive/4fb5f24787caa841b58dbf623a52c4c5861d6722.zip
; Common libs for environmental measurements in telemetry module ; Common libs for environmental measurements in telemetry module
[environmental_base] [environmental_base]
@@ -183,8 +185,8 @@ lib_deps =
dfrobot/DFRobot_BMM150@1.0.0 dfrobot/DFRobot_BMM150@1.0.0
# renovate: datasource=custom.pio depName=Adafruit_TSL2561 packageName=adafruit/library/Adafruit TSL2561 # renovate: datasource=custom.pio depName=Adafruit_TSL2561 packageName=adafruit/library/Adafruit TSL2561
adafruit/Adafruit TSL2561@1.1.2 adafruit/Adafruit TSL2561@1.1.2
# renovate: datasource=custom.pio depName=BH1750_WE packageName=wollewald/BH1750_WE@^1.1.10 # renovate: datasource=custom.pio depName=BH1750_WE packageName=wollewald/library/BH1750_WE
wollewald/BH1750_WE@^1.1.10 wollewald/BH1750_WE@1.1.10
; (not included in native / portduino) ; (not included in native / portduino)
[environmental_extra] [environmental_extra]
@@ -206,7 +208,7 @@ lib_deps =
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library # renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6 sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
ClosedCube OPT3001@1.1.2 closedcube/ClosedCube OPT3001@1.1.2
# renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2 # renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2
boschsensortec/bsec2@1.10.2610 boschsensortec/bsec2@1.10.2610
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library # renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library

View File

@@ -237,8 +237,8 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_T_ETH_ELITE = 91, meshtastic_HardwareModel_T_ETH_ELITE = 91,
/* Heltec HRI-3621 industrial probe */ /* Heltec HRI-3621 industrial probe */
meshtastic_HardwareModel_HELTEC_SENSOR_HUB = 92, meshtastic_HardwareModel_HELTEC_SENSOR_HUB = 92,
/* Reserved Fried Chicken ID for future use */ /* Muzi Works Muzi-Base device */
meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN = 93, meshtastic_HardwareModel_MUZI_BASE = 93,
/* Heltec Magnetic Power Bank with Meshtastic compatible */ /* Heltec Magnetic Power Bank with Meshtastic compatible */
meshtastic_HardwareModel_HELTEC_MESH_POCKET = 94, meshtastic_HardwareModel_HELTEC_MESH_POCKET = 94,
/* Seeed Solar Node */ /* Seeed Solar Node */

View File

@@ -651,8 +651,8 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
{ {
LOG_INFO("BLE incoming connection %s", connInfo.getAddress().toString().c_str()); LOG_INFO("BLE incoming connection %s", connInfo.getAddress().toString().c_str());
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)
const uint16_t connHandle = connInfo.getConnHandle(); const uint16_t connHandle = connInfo.getConnHandle();
#if NIMBLE_ENABLE_2M_PHY && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6))
int phyResult = int phyResult =
ble_gap_set_prefered_le_phy(connHandle, BLE_GAP_LE_PHY_2M_MASK, BLE_GAP_LE_PHY_2M_MASK, BLE_GAP_LE_PHY_CODED_ANY); ble_gap_set_prefered_le_phy(connHandle, BLE_GAP_LE_PHY_2M_MASK, BLE_GAP_LE_PHY_2M_MASK, BLE_GAP_LE_PHY_CODED_ANY);
if (phyResult == 0) { if (phyResult == 0) {
@@ -660,6 +660,7 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
} else { } else {
LOG_WARN("Failed to prefer 2M PHY for conn %u, rc=%d", connHandle, phyResult); LOG_WARN("Failed to prefer 2M PHY for conn %u, rc=%d", connHandle, phyResult);
} }
#endif
int dataLenResult = ble_gap_set_data_len(connHandle, kPreferredBleTxOctets, kPreferredBleTxTimeUs); int dataLenResult = ble_gap_set_data_len(connHandle, kPreferredBleTxOctets, kPreferredBleTxTimeUs);
if (dataLenResult == 0) { if (dataLenResult == 0) {
@@ -670,9 +671,10 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
LOG_INFO("BLE conn %u initial MTU %u (target %u)", connHandle, connInfo.getMTU(), kPreferredBleMtu); LOG_INFO("BLE conn %u initial MTU %u (target %u)", connHandle, connInfo.getMTU(), kPreferredBleMtu);
pServer->updateConnParams(connHandle, 6, 12, 0, 200); pServer->updateConnParams(connHandle, 6, 12, 0, 200);
#endif
} }
#endif
#ifdef NIMBLE_TWO
virtual void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) virtual void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason)
{ {
LOG_INFO("BLE disconnect reason: %d", reason); LOG_INFO("BLE disconnect reason: %d", reason);
@@ -818,7 +820,7 @@ void NimbleBluetooth::setup()
NimBLEDevice::init(getDeviceName()); NimBLEDevice::init(getDeviceName());
NimBLEDevice::setPower(ESP_PWR_LVL_P9); NimBLEDevice::setPower(ESP_PWR_LVL_P9);
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6) #if NIMBLE_ENABLE_2M_PHY && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6))
int mtuResult = NimBLEDevice::setMTU(kPreferredBleMtu); int mtuResult = NimBLEDevice::setMTU(kPreferredBleMtu);
if (mtuResult == 0) { if (mtuResult == 0) {
LOG_INFO("BLE MTU request set to %u", kPreferredBleMtu); LOG_INFO("BLE MTU request set to %u", kPreferredBleMtu);

View File

@@ -109,7 +109,7 @@
#elif defined(HELTEC_MESH_SOLAR) #elif defined(HELTEC_MESH_SOLAR)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_SOLAR #define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_SOLAR
#elif defined(MUZI_BASE) #elif defined(MUZI_BASE)
#define HW_VENDOR meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN #define HW_VENDOR meshtastic_HardwareModel_MUZI_BASE
#else #else
#define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN #define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN
#endif #endif

View File

@@ -335,6 +335,16 @@ void cpuDeepSleep(uint32_t msecToWake)
if (Serial1) // A straightforward solution to the wake from deepsleep problem if (Serial1) // A straightforward solution to the wake from deepsleep problem
Serial1.end(); Serial1.end();
#endif #endif
#ifdef TTGO_T_ECHO
// To power off the T-Echo, the display must be set
// as an input pin; otherwise, there will be leakage current.
pinMode(PIN_EINK_CS, INPUT);
pinMode(PIN_EINK_DC, INPUT);
pinMode(PIN_EINK_RES, INPUT);
pinMode(PIN_EINK_BUSY, INPUT);
#endif
setBluetoothEnable(false); setBluetoothEnable(false);
#ifdef RAK4630 #ifdef RAK4630

View File

@@ -2,10 +2,16 @@
[esp32_base] [esp32_base]
extends = arduino_base extends = arduino_base
custom_esp32_kind = esp32 custom_esp32_kind = esp32
custom_mtjson_part =
platform = platform =
# renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32 # renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32
platformio/espressif32@6.11.0 platformio/espressif32@6.11.0
extra_scripts =
${env.extra_scripts}
pre:extra_scripts/esp32_pre.py
extra_scripts/esp32_extra.py
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp> ${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>

View File

@@ -13,7 +13,10 @@ build_flags =
-DEINK_WIDTH=250 -DEINK_WIDTH=250
-DEINK_HEIGHT=122 -DEINK_HEIGHT=122
-DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk -DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
-DEINK_LIMIT_FASTREFRESH=10 ; How many consecutive fast-refreshes are permitted -DEINK_LIMIT_FASTREFRESH=20 ; How many consecutive fast-refreshes are permitted //20
-DEINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates //30
-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates
-DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}

View File

@@ -114,5 +114,5 @@ extends = env:native
build_flags = -lgcov --coverage -fprofile-abs-path -fsanitize=address ${env:native.build_flags} build_flags = -lgcov --coverage -fprofile-abs-path -fsanitize=address ${env:native.build_flags}
; https://docs.platformio.org/en/latest/projectconf/sections/env/options/test/test_testing_command.html ; https://docs.platformio.org/en/latest/projectconf/sections/env/options/test/test_testing_command.html
test_testing_command = test_testing_command =
${platformio.build_dir}/${this.__env__}/program ${platformio.build_dir}/${this.__env__}/meshtasticd
-s -s

View File

@@ -61,17 +61,11 @@ extern "C" {
/* /*
* Buttons * Buttons
*/ */
#define PIN_BUTTON2 (32 + 10) #define PIN_BUTTON1 (32 + 10)
#define PIN_BUTTON2 (32 + 7)
#define ALT_BUTTON_PIN PIN_BUTTON2 #define ALT_BUTTON_PIN PIN_BUTTON2
#define ALT_BUTTON_ACTIVE_LOW true #define ALT_BUTTON_ACTIVE_LOW true
#define ALT_BUTTON_ACTIVE_PULLUP true #define ALT_BUTTON_ACTIVE_PULLUP true
#define PIN_BUTTON1 (32 + 7)
// #define PIN_BUTTON1 (0 + 11)
// #define PIN_BUTTON1 (32 + 7)
// #define BUTTON_CLICK_MS 400
// #define BUTTON_TOUCH_MS 200
/* /*
* Analog pins * Analog pins
@@ -202,4 +196,4 @@ External serial flash WP25R1635FZUIL0
} }
#endif #endif
#endif #endif

View File

@@ -11,6 +11,10 @@ platform_packages =
; Don't renovate toolchain-gccarmnoneeabi ; Don't renovate toolchain-gccarmnoneeabi
platformio/toolchain-gccarmnoneeabi@~1.90301.0 platformio/toolchain-gccarmnoneeabi@~1.90301.0
extra_scripts =
${env.extra_scripts}
extra_scripts/nrf52_extra.py
build_type = release build_type = release
build_flags = build_flags =
-include variants/nrf52840/cpp_overrides/lfs_util.h -include variants/nrf52840/cpp_overrides/lfs_util.h

View File

@@ -180,9 +180,9 @@ External serial flash WP25R1635FZUIL0
#define PIN_GPS_STANDBY (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake #define PIN_GPS_STANDBY (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake
// Seems to be missing on this new board // Seems to be missing on this new board
// #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS
#define GPS_TX_PIN (32 + 8) // This is for bits going TOWARDS the CPU #define GPS_TX_PIN (32 + 8) // This is for bits going TOWARDS the CPU
#define GPS_RX_PIN (32 + 9) // This is for bits going TOWARDS the GPS #define GPS_RX_PIN (32 + 9) // This is for bits going TOWARDS the GPS
#define GPS_THREAD_INTERVAL 50 #define GPS_THREAD_INTERVAL 50
@@ -202,8 +202,6 @@ External serial flash WP25R1635FZUIL0
#define PIN_SPI_MOSI (0 + 22) #define PIN_SPI_MOSI (0 + 22)
#define PIN_SPI_SCK (0 + 19) #define PIN_SPI_SCK (0 + 19)
#define PIN_PWR_EN (0 + 6)
// To debug via the segger JLINK console rather than the CDC-ACM serial device // To debug via the segger JLINK console rather than the CDC-ACM serial device
// #define USE_SEGGER // #define USE_SEGGER

View File

@@ -4,11 +4,22 @@ extends = nrf52840_base
board = wio-sdk-wm1110 board = wio-sdk-wm1110
extra_scripts = extra_scripts =
${env.extra_scripts} ${nrf52840_base.extra_scripts}
extra_scripts/disable_adafruit_usb.py extra_scripts/disable_adafruit_usb.py
# Remove adafruit USB serial from the build (it is incompatible with using the ch340 serial chip on this board) # Remove adafruit USB serial from the build (it is incompatible with using the ch340 serial chip on this board)
build_unflags = ${nrf52840_base:build_unflags} -DUSBCON -DUSE_TINYUSB build_unflags =
-Ofast
-Og
-ggdb3
-ggdb2
-g3
-g2
-g
-g1
-g0
-DUSBCON
-DUSE_TINYUSB
build_flags = ${nrf52840_base.build_flags} build_flags = ${nrf52840_base.build_flags}
-Ivariants/nrf52840/wio-sdk-wm1110 -Ivariants/nrf52840/wio-sdk-wm1110
-Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice

View File

@@ -8,7 +8,7 @@ platform_packages =
platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
extra_scripts = extra_scripts =
${env.extra_scripts} ${env.extra_scripts}
post:extra_scripts/extra_stm32.py extra_scripts/stm32_extra.py
build_type = release build_type = release