mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-14 14:52:32 +00:00
Compare commits
4 Commits
renovate/n
...
multicast-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8e6b39bc9 | ||
|
|
bf7afd657a | ||
|
|
ca951caa38 | ||
|
|
16a1c9f148 |
@@ -51,7 +51,7 @@ for f in .clusterfuzzlite/*_fuzzer.cpp; do
|
||||
fuzzer=$(basename "$f" .cpp)
|
||||
cp -f "$f" src/fuzzer.cpp
|
||||
pio run -vvv --environment "$PIO_ENV"
|
||||
program="$PLATFORMIO_WORKSPACE_DIR/build/$PIO_ENV/meshtasticd"
|
||||
program="$PLATFORMIO_WORKSPACE_DIR/build/$PIO_ENV/program"
|
||||
cp "$program" "$OUT/$fuzzer"
|
||||
|
||||
# Copy shared libraries used by the fuzzer.
|
||||
|
||||
@@ -76,7 +76,7 @@ bool loopCanSleep()
|
||||
// Called just prior to starting Meshtastic. Allows for setting config values before startup.
|
||||
void lateInitVariant()
|
||||
{
|
||||
portduino_config.logoutputlevel = level_error;
|
||||
settingsMap[logoutputlevel] = level_error;
|
||||
channelFile.channels[0] = meshtastic_Channel{
|
||||
.has_settings = true,
|
||||
.settings =
|
||||
@@ -132,7 +132,7 @@ int portduino_main(int argc, char **argv); // Renamed "main" function from Mesht
|
||||
// Start Meshtastic in a thread and wait till it has reached the ON state.
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv)
|
||||
{
|
||||
portduino_config.maxtophone = 5;
|
||||
settingsMap[maxtophone] = 5;
|
||||
|
||||
meshtasticThread = std::thread([program = *argv[0]]() {
|
||||
char nodeIdStr[12];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions
|
||||
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
|
||||
FROM mcr.microsoft.com/devcontainers/cpp:2-debian-13
|
||||
FROM mcr.microsoft.com/devcontainers/cpp:1-debian-12
|
||||
|
||||
USER root
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"installTools": true,
|
||||
"version": "3.14"
|
||||
"version": "latest"
|
||||
}
|
||||
},
|
||||
"customizations": {
|
||||
|
||||
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
@@ -1,3 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
open_collective: meshtastic
|
||||
9
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
9
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -72,15 +72,6 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: mui
|
||||
attributes:
|
||||
label: Is this bug report about any UI component firmware like InkHUD or Meshtatic UI (MUI)?
|
||||
options:
|
||||
- label: Meshtastic UI aka MUI colorTFT
|
||||
- label: InkHUD ePaper
|
||||
- label: OLED slide UI on any display
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
|
||||
1
.github/actionlint.yaml
vendored
1
.github/actionlint.yaml
vendored
@@ -2,5 +2,4 @@
|
||||
self-hosted-runner:
|
||||
# Labels of self-hosted runner in array of strings.
|
||||
labels:
|
||||
- arctastic
|
||||
- test-runner
|
||||
|
||||
51
.github/actions/build-variant/action.yml
vendored
51
.github/actions/build-variant/action.yml
vendored
@@ -27,10 +27,10 @@ inputs:
|
||||
description: A newline separated list of paths to store as artifacts
|
||||
required: false
|
||||
default: ""
|
||||
# include-web-ui:
|
||||
# description: Include the web UI in the build
|
||||
# required: false
|
||||
# default: "false"
|
||||
include-web-ui:
|
||||
description: Include the web UI in the build
|
||||
required: false
|
||||
default: "false"
|
||||
arch:
|
||||
description: Processor arch name
|
||||
required: true
|
||||
@@ -43,29 +43,22 @@ runs:
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
# - name: Get web ui version
|
||||
# if: inputs.include-web-ui == 'true'
|
||||
# id: webver
|
||||
# shell: bash
|
||||
# run: |
|
||||
# echo "ver=$(cat bin/web.version)" >> $GITHUB_OUTPUT
|
||||
- name: Pull web ui
|
||||
if: inputs.include-web-ui == 'true'
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: meshtastic/web
|
||||
file: build.tar
|
||||
target: build.tar
|
||||
token: ${{ inputs.github_token }}
|
||||
version: tags/v2.5.3
|
||||
|
||||
# - name: Pull web ui
|
||||
# if: inputs.include-web-ui == 'true'
|
||||
# uses: dsaltares/fetch-gh-release-asset@master
|
||||
# with:
|
||||
# repo: meshtastic/web
|
||||
# file: build.tar
|
||||
# target: build.tar
|
||||
# token: ${{ inputs.github_token }}
|
||||
# version: tags/v${{ steps.webver.outputs.ver }}
|
||||
|
||||
# - name: Unpack web ui
|
||||
# if: inputs.include-web-ui == 'true'
|
||||
# shell: bash
|
||||
# run: |
|
||||
# tar -xf build.tar -C data/static
|
||||
# rm build.tar
|
||||
- name: Unpack web ui
|
||||
if: inputs.include-web-ui == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
tar -xf build.tar -C data/static
|
||||
rm build.tar
|
||||
|
||||
- name: Remove debug flags for release
|
||||
shell: bash
|
||||
@@ -76,7 +69,7 @@ runs:
|
||||
done
|
||||
|
||||
- name: PlatformIO ${{ inputs.arch }} download cache
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.platformio/.cache
|
||||
key: pio-cache-${{ inputs.arch }}-${{ hashFiles('.github/actions/**', '**.ini') }}
|
||||
@@ -100,9 +93,9 @@ runs:
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}
|
||||
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
${{ inputs.artifact-paths }}
|
||||
|
||||
11
.github/actions/setup-base/action.yml
vendored
11
.github/actions/setup-base/action.yml
vendored
@@ -5,20 +5,25 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Uncomment build epoch
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's/#-DBUILD_EPOCH=$UNIX_TIME/-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get -y update --fix-missing
|
||||
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev lsb-release
|
||||
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev libuv1-dev lsb-release
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
cache: pip
|
||||
|
||||
29
.github/dependabot.yml
vendored
Normal file
29
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
#trunk-ignore-all(yamllint/quoted-strings): required by dependabot syntax check
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: docker
|
||||
directory: /.devcontainer
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00"
|
||||
timezone: US/Pacific
|
||||
- package-ecosystem: docker
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00"
|
||||
timezone: US/Pacific
|
||||
- package-ecosystem: gitsubmodule
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00"
|
||||
timezone: US/Pacific
|
||||
ignore:
|
||||
- dependency-name: protobufs
|
||||
- package-ecosystem: github-actions
|
||||
directory: /.github/workflows
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00"
|
||||
timezone: US/Pacific
|
||||
17
.github/pull_request_template.md
vendored
17
.github/pull_request_template.md
vendored
@@ -1,7 +1,7 @@
|
||||
## 🙏 Thank you for sending in a pull request, here's some tips to get started!
|
||||
|
||||
### ❌ (Please delete all these tips and replace them with your text) ❌
|
||||
|
||||
## Thank you for sending in a pull request, here's some tips to get started!
|
||||
|
||||
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
|
||||
to say "Hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
|
||||
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
|
||||
@@ -12,17 +12,4 @@
|
||||
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
|
||||
- If your other co-developers have comments on your PR please tweak as needed.
|
||||
- Please also enable "Allow edits by maintainers".
|
||||
- Please do not submit untested code.
|
||||
- If you do not have the affected hardware to test your code changes adequately against regressions, please indicate this, so that contributors and commnunity members can help test your changes.
|
||||
- If your PR gets accepted you can request a "Contributor" role in the Meshtastic Discord
|
||||
|
||||
## 🤝 Attestations
|
||||
|
||||
- [ ] I have tested that my proposed changes behave as described.
|
||||
- [ ] I have tested that my proposed changes do not cause any obvious regressions on the following devices:
|
||||
- [ ] Heltec (Lora32) V3
|
||||
- [ ] LilyGo T-Deck
|
||||
- [ ] LilyGo T-Beam
|
||||
- [ ] RAK WisBlock 4631
|
||||
- [ ] Seeed Studio T-1000E tracker card
|
||||
- [ ] Other (please specify below)
|
||||
|
||||
4
.github/workflows/build_debian_src.yml
vendored
4
.github/workflows/build_debian_src.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
PKG_VERSION: ${{ steps.version.outputs.deb }}
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
overwrite: true
|
||||
|
||||
37
.github/workflows/build_esp32.yml
vendored
Normal file
37
.github/workflows/build_esp32.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Build ESP32
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-esp32:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build ESP32
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
remove-debug-flags: >-
|
||||
./arch/esp32/esp32.ini
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
./arch/esp32/esp32c6.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware.bin
|
||||
ota-firmware-target: release/bleota.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
include-web-ui: true
|
||||
arch: esp32
|
||||
37
.github/workflows/build_esp32_c3.yml
vendored
Normal file
37
.github/workflows/build_esp32_c3.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Build ESP32-C3
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-esp32-c3:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build ESP32-C3
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
remove-debug-flags: >-
|
||||
./arch/esp32/esp32.ini
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
./arch/esp32/esp32c6.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware-c3.bin
|
||||
ota-firmware-target: release/bleota-c3.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
include-web-ui: true
|
||||
arch: esp32c3
|
||||
37
.github/workflows/build_esp32_c6.yml
vendored
Normal file
37
.github/workflows/build_esp32_c6.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Build ESP32-C6
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-esp32-c6:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build ESP32-C6
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
remove-debug-flags: >-
|
||||
./arch/esp32/esp32.ini
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
./arch/esp32/esp32c6.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware-c3.bin
|
||||
ota-firmware-target: release/bleota-c3.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
include-web-ui: true
|
||||
arch: esp32c6
|
||||
37
.github/workflows/build_esp32_s3.yml
vendored
Normal file
37
.github/workflows/build_esp32_s3.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Build ESP32-S3
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-esp32-s3:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build ESP32-S3
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
remove-debug-flags: >-
|
||||
./arch/esp32/esp32.ini
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
./arch/esp32/esp32c6.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware-s3.bin
|
||||
ota-firmware-target: release/bleota-s3.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
include-web-ui: true
|
||||
arch: esp32s3
|
||||
84
.github/workflows/build_firmware.yml
vendored
84
.github/workflows/build_firmware.yml
vendored
@@ -1,84 +0,0 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
required: true
|
||||
type: string
|
||||
platform:
|
||||
required: true
|
||||
type: string
|
||||
pio_env:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
pio-build:
|
||||
name: build-${{ inputs.platform }}
|
||||
# Use 'arctastic' self-hosted runner pool when building in the main repo
|
||||
runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }}
|
||||
outputs:
|
||||
artifact-id: ${{ steps.upload.outputs.artifact-id }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Set OTA firmware source and target
|
||||
if: startsWith(inputs.platform, 'esp32')
|
||||
id: ota_dir
|
||||
env:
|
||||
PIO_PLATFORM: ${{ inputs.platform }}
|
||||
run: |
|
||||
if [ "$PIO_PLATFORM" = "esp32s3" ]; then
|
||||
echo "src=firmware-s3.bin" >> $GITHUB_OUTPUT
|
||||
echo "tgt=release/bleota-s3.bin" >> $GITHUB_OUTPUT
|
||||
elif [ "$PIO_PLATFORM" = "esp32c3" ] || [ "$PIO_PLATFORM" = "esp32c6" ]; then
|
||||
echo "src=firmware-c3.bin" >> $GITHUB_OUTPUT
|
||||
echo "tgt=release/bleota-c3.bin" >> $GITHUB_OUTPUT
|
||||
elif [ "$PIO_PLATFORM" = "esp32" ]; then
|
||||
echo "src=firmware.bin" >> $GITHUB_OUTPUT
|
||||
echo "tgt=release/bleota.bin" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build ${{ inputs.platform }}
|
||||
id: build
|
||||
uses: meshtastic/gh-action-firmware@main
|
||||
with:
|
||||
pio_platform: ${{ inputs.platform }}
|
||||
pio_env: ${{ inputs.pio_env }}
|
||||
pio_target: build
|
||||
ota_firmware_source: ${{ steps.ota_dir.outputs.src || '' }}
|
||||
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
|
||||
uses: actions/upload-artifact@v5
|
||||
id: upload
|
||||
with:
|
||||
name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}
|
||||
overwrite: true
|
||||
path: |
|
||||
release/*.mt.json
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
release/*.uf2
|
||||
release/*.hex
|
||||
release/*.zip
|
||||
release/device-*.sh
|
||||
release/device-*.bat
|
||||
30
.github/workflows/build_nrf52.yml
vendored
Normal file
30
.github/workflows/build_nrf52.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Build NRF52
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-nrf52:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build NRF52
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
build-script-path: bin/build-nrf52.sh
|
||||
artifact-paths: |
|
||||
release/*.hex
|
||||
release/*.uf2
|
||||
release/*.elf
|
||||
release/*.zip
|
||||
arch: nrf52840
|
||||
161
.github/workflows/build_one_target.yml
vendored
161
.github/workflows/build_one_target.yml
vendored
@@ -1,161 +0,0 @@
|
||||
name: Build One Target
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
# trunk-ignore(checkov/CKV_GHA_7)
|
||||
arch:
|
||||
type: choice
|
||||
options:
|
||||
- esp32
|
||||
- esp32s3
|
||||
- esp32c3
|
||||
- esp32c6
|
||||
- nrf52840
|
||||
- rp2040
|
||||
- rp2350
|
||||
- stm32
|
||||
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'
|
||||
|
||||
permissions: read-all
|
||||
|
||||
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@v6
|
||||
- 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}} --level 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 | jq -r 'sort_by(.board) |.[] | "- " + .board' >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
version:
|
||||
if: ${{ inputs.target != '' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- 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:
|
||||
if: ${{ inputs.target != '' && inputs.arch != 'native' }}
|
||||
needs: [version]
|
||||
uses: ./.github/workflows/build_firmware.yml
|
||||
with:
|
||||
version: ${{ needs.version.outputs.long }}
|
||||
pio_env: ${{ inputs.target }}
|
||||
platform: ${{ inputs.arch }}
|
||||
|
||||
gather-artifacts:
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
needs: [version, build]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
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@v5
|
||||
with:
|
||||
name: firmware-${{inputs.target}}-${{ needs.version.outputs.long }}
|
||||
overwrite: true
|
||||
path: |
|
||||
./firmware-*.bin
|
||||
./firmware-*.uf2
|
||||
./firmware-*.hex
|
||||
./firmware-*.zip
|
||||
./device-*.sh
|
||||
./device-*.bat
|
||||
./littlefs-*.bin
|
||||
./bleota*bin
|
||||
./Meshtastic_nRF52_factory_erase*.uf2
|
||||
retention-days: 30
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
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 || true
|
||||
chmod +x ./output/device-update.sh || true
|
||||
|
||||
- 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@v5
|
||||
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 }}
|
||||
28
.github/workflows/build_rpi2040.yml
vendored
Normal file
28
.github/workflows/build_rpi2040.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Build RPI2040
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-rpi2040:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build Raspberry Pi 2040
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
build-script-path: bin/build-rpi2040.sh
|
||||
artifact-paths: |
|
||||
release/*.uf2
|
||||
release/*.elf
|
||||
arch: rp2040
|
||||
29
.github/workflows/build_stm32.yml
vendored
Normal file
29
.github/workflows/build_stm32.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Build STM32
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-stm32:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build STM32WL
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
build-script-path: bin/build-stm32.sh
|
||||
artifact-paths: |
|
||||
release/*.hex
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
arch: stm32
|
||||
12
.github/workflows/daily_packaging.yml
vendored
12
.github/workflows/daily_packaging.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: Daily Packaging
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 2 * * *
|
||||
- cron: 0 9 * * *
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
@@ -21,22 +21,16 @@ permissions:
|
||||
|
||||
jobs:
|
||||
docker-multiarch:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/docker_manifest.yml
|
||||
with:
|
||||
release_channel: daily
|
||||
secrets: inherit
|
||||
|
||||
package-ppa:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
series:
|
||||
- jammy # 22.04 LTS
|
||||
- noble # 24.04 LTS
|
||||
- plucky # 25.04
|
||||
- questing # 25.10
|
||||
series: [plucky, oracular, noble, jammy]
|
||||
uses: ./.github/workflows/package_ppa.yml
|
||||
with:
|
||||
ppa_repo: ppa:meshtastic/daily
|
||||
@@ -44,7 +38,6 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
package-obs:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/package_obs.yml
|
||||
with:
|
||||
obs_project: network:Meshtastic:daily
|
||||
@@ -52,7 +45,6 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
hook-copr:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/hook_copr.yml
|
||||
with:
|
||||
copr_project: daily
|
||||
|
||||
9
.github/workflows/docker_build.yml
vendored
9
.github/workflows/docker_build.yml
vendored
@@ -26,11 +26,6 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
pio_env:
|
||||
description: PlatformIO environment to build
|
||||
required: false
|
||||
type: string
|
||||
default: native
|
||||
outputs:
|
||||
digest:
|
||||
description: Digest of built image
|
||||
@@ -47,7 +42,7 @@ jobs:
|
||||
runs-on: ${{ inputs.runs-on }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
@@ -95,5 +90,3 @@ jobs:
|
||||
push: ${{ inputs.push }}
|
||||
tags: ${{ steps.meta.outputs.tags }} # Tag is only meant to be consumed by the "manifest" job
|
||||
platforms: ${{ inputs.platform }}
|
||||
build-args: |
|
||||
PIO_ENV=${{ inputs.pio_env }}
|
||||
|
||||
2
.github/workflows/docker_manifest.yml
vendored
2
.github/workflows/docker_manifest.yml
vendored
@@ -83,7 +83,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
|
||||
2
.github/workflows/hook_copr.yml
vendored
2
.github/workflows/hook_copr.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
438
.github/workflows/main_matrix.yml
vendored
438
.github/workflows/main_matrix.yml
vendored
@@ -3,22 +3,16 @@ concurrency:
|
||||
group: ci-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
# # Triggers the workflow on push but only for the main branches
|
||||
# # Triggers the workflow on push but only for the master branch
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- event/*
|
||||
branches: [master, develop]
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- version.properties
|
||||
|
||||
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
|
||||
pull_request_target:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- event/*
|
||||
branches: [master, develop]
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
#- "**.yml"
|
||||
@@ -28,85 +22,113 @@ on:
|
||||
jobs:
|
||||
setup:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch:
|
||||
- all
|
||||
- check
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- 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}} --level pr)
|
||||
fi
|
||||
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF"
|
||||
echo "${{matrix.arch}}=$TARGETS" >> $GITHUB_OUTPUT
|
||||
echo "$TARGETS" >> $GITHUB_STEP_SUMMARY
|
||||
outputs:
|
||||
all: ${{ steps.jsonStep.outputs.all }}
|
||||
check: ${{ steps.jsonStep.outputs.check }}
|
||||
|
||||
version:
|
||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32, check]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Get release version string
|
||||
- id: checkout
|
||||
uses: actions/checkout@v4
|
||||
name: Checkout base
|
||||
- id: jsonStep
|
||||
run: |
|
||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
env:
|
||||
BUILD_LOCATION: local
|
||||
if [[ "${{ github.head_ref }}" == "" ]]; then
|
||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
|
||||
else
|
||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
|
||||
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:
|
||||
long: ${{ steps.version.outputs.long }}
|
||||
deb: ${{ steps.version.outputs.deb }}
|
||||
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 }}
|
||||
stm32: ${{ steps.jsonStep.outputs.stm32 }}
|
||||
check: ${{ steps.jsonStep.outputs.check }}
|
||||
|
||||
check:
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
check: ${{ fromJson(needs.setup.outputs.check) }}
|
||||
# Use 'arctastic' self-hosted runner pool when checking in the main repo
|
||||
runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }}
|
||||
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
- name: Check ${{ matrix.check.board }}
|
||||
uses: meshtastic/gh-action-firmware@main
|
||||
with:
|
||||
pio_platform: ${{ matrix.check.platform }}
|
||||
pio_env: ${{ matrix.check.board }}
|
||||
pio_target: check
|
||||
matrix: ${{ fromJson(needs.setup.outputs.check) }}
|
||||
|
||||
build:
|
||||
needs: [setup, version]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- 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
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build: ${{ fromJson(needs.setup.outputs.all) }}
|
||||
uses: ./.github/workflows/build_firmware.yml
|
||||
matrix: ${{ fromJson(needs.setup.outputs.esp32) }}
|
||||
uses: ./.github/workflows/build_esp32.yml
|
||||
with:
|
||||
version: ${{ needs.version.outputs.long }}
|
||||
pio_env: ${{ matrix.build.board }}
|
||||
platform: ${{ matrix.build.platform }}
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-esp32-s3:
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.esp32s3) }}
|
||||
uses: ./.github/workflows/build_esp32_s3.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-esp32-c3:
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
|
||||
uses: ./.github/workflows/build_esp32_c3.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-esp32-c6:
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.esp32c6) }}
|
||||
uses: ./.github/workflows/build_esp32_c6.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-nrf52:
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
|
||||
uses: ./.github/workflows/build_nrf52.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-rpi2040:
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
|
||||
uses: ./.github/workflows/build_rpi2040.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-stm32:
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.stm32) }}
|
||||
uses: ./.github/workflows/build_stm32.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-debian-src:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/build_debian_src.yml
|
||||
with:
|
||||
series: UNRELEASED
|
||||
@@ -114,66 +136,85 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
package-pio-deps-native-tft:
|
||||
if: ${{ github.repository == 'meshtastic/firmware' && github.event_name == 'workflow_dispatch' }}
|
||||
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/') && github.repository == 'meshtastic/firmware' }}
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
docker:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
distro: [debian, alpine]
|
||||
platform: [linux/amd64, linux/arm64, linux/arm/v7]
|
||||
pio_env: [native, native-tft]
|
||||
exclude:
|
||||
- distro: alpine
|
||||
platform: linux/arm/v7
|
||||
- pio_env: native-tft
|
||||
platform: linux/arm64
|
||||
- pio_env: native-tft
|
||||
platform: linux/arm/v7
|
||||
docker-debian-amd64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: ${{ matrix.distro }}
|
||||
platform: ${{ matrix.platform }}
|
||||
runs-on: ${{ contains(matrix.platform, 'arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
|
||||
pio_env: ${{ matrix.pio_env }}
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-alpine-amd64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-debian-arm64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
docker-debian-armv7:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/arm/v7
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
after-checks:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
needs: [check]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
gather-artifacts:
|
||||
# trunk-ignore(checkov/CKV2_GHA_1)
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch:
|
||||
- esp32
|
||||
- esp32s3
|
||||
- esp32c3
|
||||
- esp32c6
|
||||
- nrf52840
|
||||
- rp2040
|
||||
- rp2350
|
||||
- stm32
|
||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32]
|
||||
runs-on: ubuntu-latest
|
||||
needs: [version, build]
|
||||
needs:
|
||||
[
|
||||
build-esp32,
|
||||
build-esp32-s3,
|
||||
build-esp32-c3,
|
||||
build-esp32-c6,
|
||||
build-nrf52,
|
||||
build-rpi2040,
|
||||
build-stm32,
|
||||
]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./
|
||||
pattern: firmware-${{matrix.arch}}-*
|
||||
@@ -182,27 +223,34 @@ jobs:
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Move files up
|
||||
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
||||
overwrite: true
|
||||
path: |
|
||||
./firmware-*.mt.json
|
||||
./firmware-*.bin
|
||||
./firmware-*.uf2
|
||||
./firmware-*.hex
|
||||
./firmware-*.zip
|
||||
./firmware-*-ota.zip
|
||||
./device-*.sh
|
||||
./device-*.bat
|
||||
./littlefs-*.bin
|
||||
./littlefswebui-*.bin
|
||||
./bleota*bin
|
||||
./Meshtastic_nRF52_factory_erase*.uf2
|
||||
retention-days: 30
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
@@ -212,16 +260,16 @@ jobs:
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh || true
|
||||
chmod +x ./output/device-update.sh || true
|
||||
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
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./output
|
||||
|
||||
- name: Repackage in single elfs zip
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: ./*.elf
|
||||
retention-days: 30
|
||||
@@ -229,24 +277,35 @@ jobs:
|
||||
- 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"
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
||||
description: "Download firmware-${{matrix.arch}}-${{ steps.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' && github.repository == 'meshtastic/firmware' }}
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
outputs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
needs:
|
||||
- setup
|
||||
- version
|
||||
- gather-artifacts
|
||||
- build-debian-src
|
||||
- package-pio-deps-native-tft
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- 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
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v2
|
||||
@@ -254,56 +313,39 @@ jobs:
|
||||
with:
|
||||
draft: true
|
||||
prerelease: true
|
||||
name: Meshtastic Firmware ${{ needs.version.outputs.long }} Alpha
|
||||
tag_name: v${{ needs.version.outputs.long }}
|
||||
name: Meshtastic Firmware ${{ steps.version.outputs.long }} Alpha
|
||||
tag_name: v${{ steps.version.outputs.long }}
|
||||
body: |
|
||||
Autogenerated by github action, developer should edit as required before publishing...
|
||||
|
||||
- name: Download source deb
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
|
||||
pattern: firmware-debian-${{ steps.version.outputs.deb }}~UNRELEASED-src
|
||||
merge-multiple: true
|
||||
path: ./output/debian-src
|
||||
|
||||
- name: Download `native-tft` pio deps
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
|
||||
pattern: platformio-deps-native-tft-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
path: ./output/pio-deps-native-tft
|
||||
|
||||
- name: Zip Linux sources
|
||||
- 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
|
||||
zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src
|
||||
zip -9 -r ./platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip ./pio-deps-native-tft
|
||||
|
||||
# For diagnostics
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lR
|
||||
|
||||
- name: Generate Release manifest
|
||||
- name: Add linux sources to release
|
||||
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
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
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/platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip
|
||||
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip
|
||||
gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -311,30 +353,26 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch:
|
||||
- esp32
|
||||
- esp32s3
|
||||
- esp32c3
|
||||
- esp32c6
|
||||
- nrf52840
|
||||
- rp2040
|
||||
- rp2350
|
||||
- stm32
|
||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware'}}
|
||||
needs: [release-artifacts, version]
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
needs: [release-artifacts]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
pattern: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
@@ -343,76 +381,28 @@ jobs:
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh || true
|
||||
chmod +x ./output/device-update.sh || true
|
||||
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
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./output
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
name: debug-elfs-${{matrix.arch}}-${{ steps.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
|
||||
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ steps.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' }}
|
||||
- name: Add bins and debug elfs to release
|
||||
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
|
||||
gh release upload v${{ steps.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
||||
gh release upload v${{ steps.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ steps.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@v6
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get firmware artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
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
|
||||
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
|
||||
|
||||
371
.github/workflows/merge_queue.yml
vendored
371
.github/workflows/merge_queue.yml
vendored
@@ -1,371 +0,0 @@
|
||||
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:
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
arch:
|
||||
- all
|
||||
- check
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- 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}} --level pr)
|
||||
fi
|
||||
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF"
|
||||
echo "${{matrix.arch}}=$TARGETS" >> $GITHUB_OUTPUT
|
||||
outputs:
|
||||
all: ${{ steps.jsonStep.outputs.all }}
|
||||
check: ${{ steps.jsonStep.outputs.check }}
|
||||
|
||||
version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- 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:
|
||||
check: ${{ fromJson(needs.setup.outputs.check) }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
- name: Check ${{ matrix.check.board }}
|
||||
run: bin/check-all.sh ${{ matrix.check.board }}
|
||||
|
||||
build:
|
||||
needs: [setup, version]
|
||||
strategy:
|
||||
matrix:
|
||||
build: ${{ fromJson(needs.setup.outputs.all) }}
|
||||
uses: ./.github/workflows/build_firmware.yml
|
||||
with:
|
||||
version: ${{ needs.version.outputs.long }}
|
||||
pio_env: ${{ matrix.build.board }}
|
||||
platform: ${{ matrix.build.platform }}
|
||||
|
||||
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:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
distro: [debian, alpine]
|
||||
platform: [linux/amd64, linux/arm64, linux/arm/v7]
|
||||
pio_env: [native, native-tft]
|
||||
exclude:
|
||||
- distro: alpine
|
||||
platform: linux/arm/v7
|
||||
- pio_env: native-tft
|
||||
platform: linux/arm64
|
||||
- pio_env: native-tft
|
||||
platform: linux/arm/v7
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: ${{ matrix.distro }}
|
||||
platform: ${{ matrix.platform }}
|
||||
runs-on: ${{ contains(matrix.platform, 'arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
|
||||
pio_env: ${{ matrix.pio_env }}
|
||||
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]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
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@v5
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
overwrite: true
|
||||
path: |
|
||||
./firmware-*.bin
|
||||
./firmware-*.uf2
|
||||
./firmware-*.hex
|
||||
./firmware-*.zip
|
||||
./device-*.sh
|
||||
./device-*.bat
|
||||
./littlefs-*.bin
|
||||
./bleota*bin
|
||||
./Meshtastic_nRF52_factory_erase*.uf2
|
||||
retention-days: 30
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
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 || true
|
||||
chmod +x ./output/device-update.sh || true
|
||||
|
||||
- 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@v5
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
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@v6
|
||||
|
||||
- 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@v6
|
||||
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@v6
|
||||
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@v6
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
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 || true
|
||||
chmod +x ./output/device-update.sh || true
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
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@v6
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
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
|
||||
6
.github/workflows/nightly.yml
vendored
6
.github/workflows/nightly.yml
vendored
@@ -8,13 +8,12 @@ permissions: read-all
|
||||
|
||||
jobs:
|
||||
trunk_check:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
name: Trunk Check and Upload
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Trunk Check
|
||||
uses: trunk-io/trunk-action@v1
|
||||
@@ -22,7 +21,6 @@ jobs:
|
||||
trunk-token: ${{ secrets.TRUNK_TOKEN }}
|
||||
|
||||
trunk_upgrade:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
# See: https://github.com/trunk-io/trunk-action/blob/v1/readme.md#automatic-upgrades
|
||||
name: Trunk Upgrade (PR)
|
||||
runs-on: ubuntu-24.04
|
||||
@@ -31,7 +29,7 @@ jobs:
|
||||
pull-requests: write # For trunk to create PRs
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Trunk Upgrade
|
||||
uses: trunk-io/trunk-action/upgrade@v1
|
||||
|
||||
4
.github/workflows/package_obs.yml
vendored
4
.github/workflows/package_obs.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
needs: build-debian-src
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
merge-multiple: true
|
||||
|
||||
6
.github/workflows/package_pio_deps.yml
vendored
6
.github/workflows/package_pio_deps.yml
vendored
@@ -24,14 +24,14 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
PLATFORMIO_CORE_DIR: pio/core
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: platformio-deps-${{ inputs.pio_env }}-${{ steps.version.outputs.long }}
|
||||
overwrite: true
|
||||
|
||||
4
.github/workflows/package_ppa.yml
vendored
4
.github/workflows/package_ppa.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
needs: build-debian-src
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
merge-multiple: true
|
||||
|
||||
24
.github/workflows/pr_enforce_labels.yml
vendored
24
.github/workflows/pr_enforce_labels.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Check PR Labels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, labeled, unlabeled, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
pull-requests: read
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check for PR labels
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const labels = context.payload.pull_request.labels.map(label => label.name);
|
||||
const requiredLabels = ['bugfix', 'enhancement', 'hardware-support', 'dependencies', 'submodules', 'github_actions', 'trunk', 'cleanup'];
|
||||
const hasRequiredLabel = labels.some(label => requiredLabels.includes(label));
|
||||
if (!hasRequiredLabel) {
|
||||
core.setFailed(`PR must have at least one of the following labels before it can be merged: ${requiredLabels.join(', ')}.`);
|
||||
}
|
||||
238
.github/workflows/pr_tests.yml
vendored
238
.github/workflows/pr_tests.yml
vendored
@@ -1,238 +0,0 @@
|
||||
name: Tests
|
||||
|
||||
# DISABLED: Changed from automatic PR triggers to manual only
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
reason:
|
||||
description: "Reason for manual test run"
|
||||
required: false
|
||||
default: "Manual test execution"
|
||||
|
||||
concurrency:
|
||||
group: tests-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
checks: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
native-tests:
|
||||
name: "🧪 Native Tests"
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
checks: write
|
||||
|
||||
test-summary:
|
||||
name: "📊 Test Results"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [native-tests]
|
||||
if: always()
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
checks: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Download test artifacts
|
||||
if: needs.native-tests.result != 'skipped'
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
|
||||
- name: Parse test results and create detailed summary
|
||||
id: test-results
|
||||
run: |
|
||||
echo "## 🧪 Test Results Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Check overall job status first
|
||||
if [[ "${{ needs.native-tests.result }}" == "success" ]]; then
|
||||
echo "✅ **Overall Status**: PASSED" >> $GITHUB_STEP_SUMMARY
|
||||
elif [[ "${{ needs.native-tests.result }}" == "failure" ]]; then
|
||||
echo "❌ **Overall Status**: FAILED" >> $GITHUB_STEP_SUMMARY
|
||||
elif [[ "${{ needs.native-tests.result }}" == "cancelled" ]]; then
|
||||
echo "⏸️ **Overall Status**: CANCELLED" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Tests were cancelled before completion." >> $GITHUB_STEP_SUMMARY
|
||||
exit 0
|
||||
else
|
||||
echo "⚠️ **Overall Status**: SKIPPED" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Tests were skipped." >> $GITHUB_STEP_SUMMARY
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Parse detailed test results if available
|
||||
if [ -f "testreport.xml" ]; then
|
||||
echo "### 🔍 Individual Test Results" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
python3 << 'EOF'
|
||||
import xml.etree.ElementTree as ET
|
||||
import os
|
||||
|
||||
try:
|
||||
tree = ET.parse('testreport.xml')
|
||||
root = tree.getroot()
|
||||
|
||||
total_tests = 0
|
||||
passed_tests = 0
|
||||
failed_tests = 0
|
||||
skipped_tests = 0
|
||||
|
||||
# Parse testsuite elements
|
||||
for testsuite in root.findall('.//testsuite'):
|
||||
suite_name = testsuite.get('name', 'Unknown')
|
||||
suite_tests = int(testsuite.get('tests', '0'))
|
||||
suite_failures = int(testsuite.get('failures', '0'))
|
||||
suite_errors = int(testsuite.get('errors', '0'))
|
||||
suite_skipped = int(testsuite.get('skipped', '0'))
|
||||
|
||||
total_tests += suite_tests
|
||||
failed_tests += suite_failures + suite_errors
|
||||
skipped_tests += suite_skipped
|
||||
passed_tests += suite_tests - suite_failures - suite_errors - suite_skipped
|
||||
|
||||
if suite_tests > 0:
|
||||
status = "✅" if (suite_failures + suite_errors) == 0 else "❌"
|
||||
print(f"**{status} Test Suite: {suite_name}**")
|
||||
print(f"- Total: {suite_tests}")
|
||||
print(f"- Passed: ✅ {suite_tests - suite_failures - suite_errors - suite_skipped}")
|
||||
print(f"- Failed: ❌ {suite_failures + suite_errors}")
|
||||
if suite_skipped > 0:
|
||||
print(f"- Skipped: ⏭️ {suite_skipped}")
|
||||
print("")
|
||||
|
||||
# Show individual test results for failed suites
|
||||
if suite_failures + suite_errors > 0:
|
||||
print("**Failed Tests:**")
|
||||
for testcase in testsuite.findall('testcase'):
|
||||
test_name = testcase.get('name', 'Unknown')
|
||||
failure = testcase.find('failure')
|
||||
error = testcase.find('error')
|
||||
|
||||
if failure is not None:
|
||||
msg = failure.get('message', 'Unknown error')[:100]
|
||||
print(f"- ❌ `{test_name}`: {msg}")
|
||||
elif error is not None:
|
||||
msg = error.get('message', 'Unknown error')[:100]
|
||||
print(f"- ❌ `{test_name}`: ERROR - {msg}")
|
||||
print("")
|
||||
else:
|
||||
# Show passed tests for successful suites
|
||||
passed_count = 0
|
||||
for testcase in testsuite.findall('testcase'):
|
||||
if testcase.find('failure') is None and testcase.find('error') is None:
|
||||
if passed_count < 5: # Limit to first 5 to avoid spam
|
||||
test_name = testcase.get('name', 'Unknown')
|
||||
print(f"- ✅ `{test_name}`: PASSED")
|
||||
passed_count += 1
|
||||
if passed_count > 5:
|
||||
print(f"- ... and {passed_count - 5} more tests passed")
|
||||
print("")
|
||||
|
||||
# Summary statistics
|
||||
print("### 📊 Test Statistics")
|
||||
print(f"- **Total Tests**: {total_tests}")
|
||||
print(f"- **Passed**: ✅ {passed_tests}")
|
||||
print(f"- **Failed**: ❌ {failed_tests}")
|
||||
if skipped_tests > 0:
|
||||
print(f"- **Skipped**: ⏭️ {skipped_tests}")
|
||||
|
||||
if failed_tests > 0:
|
||||
print(f"\n❌ **{failed_tests} tests failed out of {total_tests} total**")
|
||||
else:
|
||||
print(f"\n✅ **All {total_tests} tests passed!**")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error parsing test results: {e}")
|
||||
EOF
|
||||
else
|
||||
echo "⚠️ **No detailed test report available**" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Test artifacts may not have been generated properly." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "---" >> $GITHUB_STEP_SUMMARY
|
||||
echo "View detailed logs in the [Actions tab](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Comment test results on PR
|
||||
if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped'
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
// Read the step summary to use as PR comment
|
||||
let testSummary = "## 🧪 Test Results Summary\n\n";
|
||||
|
||||
if ("${{ needs.native-tests.result }}" === "success") {
|
||||
testSummary += "✅ **All tests passed!**\n\n";
|
||||
} else if ("${{ needs.native-tests.result }}" === "failure") {
|
||||
testSummary += "❌ **Some tests failed.**\n\n";
|
||||
} else {
|
||||
testSummary += "⚠️ **Tests did not complete normally.**\n\n";
|
||||
}
|
||||
|
||||
testSummary += `View detailed results: [Actions Run](${context.payload.repository.html_url}/actions/runs/${context.runId})\n\n`;
|
||||
testSummary += "---\n";
|
||||
testSummary += "*This comment will be automatically updated when new commits are pushed.*";
|
||||
|
||||
// Find existing comment
|
||||
const comments = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number
|
||||
});
|
||||
|
||||
const botComment = comments.data.find(comment =>
|
||||
comment.user.type === 'Bot' &&
|
||||
comment.body.includes('🧪 Test Results Summary')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
// Update existing comment
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: testSummary
|
||||
});
|
||||
} else {
|
||||
// Create new comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: testSummary
|
||||
});
|
||||
}
|
||||
|
||||
- name: Set overall status
|
||||
run: |
|
||||
if [[ "${{ needs.native-tests.result }}" == "success" ]]; then
|
||||
echo "All tests passed! ✅"
|
||||
exit 0
|
||||
else
|
||||
echo "Some tests failed! ❌"
|
||||
exit 1
|
||||
fi
|
||||
62
.github/workflows/release_channels.yml
vendored
62
.github/workflows/release_channels.yml
vendored
@@ -20,11 +20,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
series:
|
||||
- jammy # 22.04 LTS
|
||||
- noble # 24.04 LTS
|
||||
- plucky # 25.04
|
||||
- questing # 25.10
|
||||
series: [plucky, oracular, noble, jammy]
|
||||
uses: ./.github/workflows/package_ppa.yml
|
||||
with:
|
||||
ppa_repo: |-
|
||||
@@ -50,66 +46,46 @@ jobs:
|
||||
|
||||
# Create a PR to bump version when a release is Published
|
||||
bump-version:
|
||||
if: github.event.action == 'published'
|
||||
if: ${{ github.event.release.published }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
# Always use master branch for version bumps
|
||||
ref: master
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Bump version.properties
|
||||
- name: Get release version string
|
||||
run: |
|
||||
# Bump version.properties
|
||||
chmod +x ./bin/bump_version.py
|
||||
./bin/bump_version.py
|
||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
env:
|
||||
BUILD_LOCATION: local
|
||||
|
||||
- name: Get new release version string
|
||||
run: |
|
||||
echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT
|
||||
id: new_version
|
||||
- name: Bump version.properties
|
||||
run: >-
|
||||
bin/bump_version.py
|
||||
|
||||
- name: Ensure debian deps are installed
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y devscripts
|
||||
|
||||
- name: Update debian changelog
|
||||
run: |
|
||||
# Update debian changelog
|
||||
chmod +x ./debian/ci_changelog.sh
|
||||
./debian/ci_changelog.sh
|
||||
run: >-
|
||||
debian/ci_changelog.sh
|
||||
|
||||
- name: Bump org.meshtastic.meshtasticd.metainfo.xml
|
||||
run: |
|
||||
# Bump org.meshtastic.meshtasticd.metainfo.xml
|
||||
pip install -r bin/bump_metainfo/requirements.txt -q
|
||||
chmod +x ./bin/bump_metainfo/bump_metainfo.py
|
||||
./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.new_version.outputs.short }}"
|
||||
env:
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: 1
|
||||
|
||||
- name: Create Bumps pull request
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
- name: Create version.properties pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
base: ${{ github.event.repository.default_branch }}
|
||||
branch: create-pull-request/bump-version
|
||||
labels: github_actions
|
||||
title: Bump release version
|
||||
commit-message: Automated version bumps
|
||||
title: Bump version.properties
|
||||
add-paths: |
|
||||
version.properties
|
||||
debian/changelog
|
||||
bin/org.meshtastic.meshtasticd.metainfo.xml
|
||||
|
||||
9
.github/workflows/sec_sast_semgrep_cron.yml
vendored
9
.github/workflows/sec_sast_semgrep_cron.yml
vendored
@@ -13,15 +13,14 @@ permissions:
|
||||
|
||||
jobs:
|
||||
semgrep-full:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
container:
|
||||
image: semgrep/semgrep
|
||||
|
||||
steps:
|
||||
# step 1
|
||||
- name: clone application source code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# step 2
|
||||
- name: full scan
|
||||
@@ -33,7 +32,7 @@ jobs:
|
||||
|
||||
# step 3
|
||||
- name: save report as pipeline artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: report.sarif
|
||||
overwrite: true
|
||||
@@ -41,7 +40,7 @@ jobs:
|
||||
|
||||
# step 4
|
||||
- name: publish code scanning alerts
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: report.sarif
|
||||
category: semgrep
|
||||
|
||||
4
.github/workflows/sec_sast_semgrep_pull.yml
vendored
4
.github/workflows/sec_sast_semgrep_pull.yml
vendored
@@ -6,14 +6,14 @@ permissions: read-all
|
||||
|
||||
jobs:
|
||||
semgrep-diff:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
container:
|
||||
image: semgrep/semgrep
|
||||
|
||||
steps:
|
||||
# step 1
|
||||
- name: clone application source code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
9
.github/workflows/stale_bot.yml
vendored
9
.github/workflows/stale_bot.yml
vendored
@@ -11,16 +11,13 @@ permissions:
|
||||
|
||||
jobs:
|
||||
stale_issues:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
name: Close Stale Issues
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Stale PR+Issues
|
||||
uses: actions/stale@v10.1.1
|
||||
uses: actions/stale@v9.1.0
|
||||
with:
|
||||
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.
|
||||
close-issue-message: This issue has not had any comment since the last notice. It has been closed automatically. If this is incorrect, or the issue becomes relevant again, please request that it is reopened.
|
||||
exempt-issue-labels: pinned,3.0,triaged,backlog
|
||||
exempt-pr-labels: pinned,3.0,triaged,backlog
|
||||
exempt-issue-labels: pinned,3.0
|
||||
exempt-pr-labels: pinned,3.0
|
||||
|
||||
34
.github/workflows/test_native.yml
vendored
34
.github/workflows/test_native.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
name: Native Simulator Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
- name: Integration test
|
||||
run: |
|
||||
.pio/build/coverage/meshtasticd -s &
|
||||
.pio/build/coverage/program &
|
||||
PID=$!
|
||||
timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done"
|
||||
echo "Simulator started, launching python test..."
|
||||
@@ -59,10 +59,10 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Save coverage information
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always() # run this step even if previous step failed
|
||||
with:
|
||||
name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}
|
||||
name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: ./coverage_*.info
|
||||
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
name: Native PlatformIO Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
@@ -94,9 +94,9 @@ jobs:
|
||||
|
||||
- name: Save test results
|
||||
if: always() # run this step even if previous step failed
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: ./testreport.xml
|
||||
|
||||
@@ -108,10 +108,10 @@ jobs:
|
||||
sed -i -e "s#${PWD}#.#" coverage_tests.info # Make paths relative.
|
||||
|
||||
- name: Save coverage information
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always() # run this step even if previous step failed
|
||||
with:
|
||||
name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}
|
||||
name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: ./coverage_*.info
|
||||
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
- platformio-tests
|
||||
if: always()
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
@@ -137,22 +137,22 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Download test artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
|
||||
merge-multiple: true
|
||||
|
||||
- name: Test Report
|
||||
uses: dorny/test-reporter@v2.3.0
|
||||
uses: dorny/test-reporter@v2.0.0
|
||||
with:
|
||||
name: PlatformIO Tests
|
||||
path: testreport.xml
|
||||
reporter: java-junit
|
||||
|
||||
- name: Download coverage artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}
|
||||
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}.zip
|
||||
path: code-coverage-report
|
||||
merge-multiple: true
|
||||
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report
|
||||
|
||||
- name: Save Code Coverage Report
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: code-coverage-report-${{ steps.version.outputs.long }}
|
||||
name: code-coverage-report-${{ steps.version.outputs.long }}.zip
|
||||
path: code-coverage-report
|
||||
|
||||
15
.github/workflows/tests.yml
vendored
15
.github/workflows/tests.yml
vendored
@@ -5,24 +5,19 @@ on:
|
||||
- cron: 0 0 * * * # Run every day at midnight
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
checks: write
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
native-tests:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
hardware-tests:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
runs-on: test-runner
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# - uses: actions/setup-python@v6
|
||||
# - uses: actions/setup-python@v5
|
||||
# with:
|
||||
# python-version: '3.10'
|
||||
|
||||
@@ -47,9 +42,9 @@ jobs:
|
||||
pio upgrade
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
node-version: 18
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
2
.github/workflows/trunk_annotate_pr.yml
vendored
2
.github/workflows/trunk_annotate_pr.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Trunk Check
|
||||
uses: trunk-io/trunk-action@v1
|
||||
|
||||
2
.github/workflows/trunk_check.yml
vendored
2
.github/workflows/trunk_check.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Trunk Check
|
||||
uses: trunk-io/trunk-action@v1
|
||||
|
||||
4
.github/workflows/trunk_format_pr.yml
vendored
4
.github/workflows/trunk_format_pr.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
git push
|
||||
|
||||
- name: Comment on PR
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
||||
7
.github/workflows/update_protobufs.yml
vendored
7
.github/workflows/update_protobufs.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -31,12 +31,9 @@ jobs:
|
||||
./bin/regen-protos.sh
|
||||
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
branch: create-pull-request/update-protobufs
|
||||
labels: submodules
|
||||
title: Update protobufs and classes
|
||||
commit-message: Update protobufs
|
||||
add-paths: |
|
||||
protobufs
|
||||
src/mesh
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -37,7 +37,4 @@ release/
|
||||
.vscode/extensions.json
|
||||
/compile_commands.json
|
||||
src/mesh/raspihttp/certificate.pem
|
||||
src/mesh/raspihttp/private_key.pem
|
||||
|
||||
# Ignore logo (set at build time with platformio-custom.py)
|
||||
data/boot/logo.*
|
||||
src/mesh/raspihttp/private_key.pem
|
||||
@@ -1 +0,0 @@
|
||||
renovate.json
|
||||
@@ -1,34 +1,34 @@
|
||||
version: 0.1
|
||||
cli:
|
||||
version: 1.25.0
|
||||
version: 1.22.11
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.7.4
|
||||
ref: v1.6.7
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.495
|
||||
- renovate@42.48.0
|
||||
- prettier@3.7.4
|
||||
- trufflehog@3.92.3
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.9.2
|
||||
- trivy@0.68.1
|
||||
- taplo@0.10.0
|
||||
- ruff@0.14.9
|
||||
- isort@7.0.0
|
||||
- markdownlint@0.47.0
|
||||
- oxipng@10.0.0
|
||||
- svgo@4.0.0
|
||||
- actionlint@1.7.9
|
||||
- flake8@7.3.0
|
||||
- hadolint@2.14.0
|
||||
- prettier@3.5.3
|
||||
- trufflehog@3.88.17
|
||||
- yamllint@1.36.0
|
||||
- bandit@1.8.3
|
||||
- checkov@3.2.386
|
||||
- terrascan@1.19.9
|
||||
- trivy@0.60.0
|
||||
- taplo@0.9.3
|
||||
- ruff@0.10.0
|
||||
- isort@6.0.1
|
||||
- markdownlint@0.44.0
|
||||
- oxipng@9.1.4
|
||||
- svgo@3.3.2
|
||||
- actionlint@1.7.7
|
||||
- flake8@7.1.2
|
||||
- hadolint@2.12.1-beta
|
||||
- shfmt@3.6.0
|
||||
- shellcheck@0.11.0
|
||||
- black@25.12.0
|
||||
- shellcheck@0.10.0
|
||||
- black@25.1.0
|
||||
- git-diff-check
|
||||
- gitleaks@8.30.0
|
||||
- gitleaks@8.24.0
|
||||
- clang-format@16.0.3
|
||||
ignore:
|
||||
- linters: [ALL]
|
||||
@@ -38,7 +38,7 @@ runtimes:
|
||||
enabled:
|
||||
- python@3.10.8
|
||||
- go@1.21.0
|
||||
- node@22.16.0
|
||||
- node@18.20.5
|
||||
actions:
|
||||
disabled:
|
||||
- trunk-announce
|
||||
|
||||
40
Dockerfile
40
Dockerfile
@@ -1,20 +1,20 @@
|
||||
# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore-all(trivy/DS002): We must run as root for this container
|
||||
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions
|
||||
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
|
||||
|
||||
FROM python:3.14-slim-trixie AS builder
|
||||
ARG PIO_ENV=native
|
||||
FROM python:3.13-bookworm AS builder
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Etc/UTC
|
||||
|
||||
# Install Dependencies
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
curl wget g++ zip git ca-certificates pkg-config \
|
||||
wget g++ zip git ca-certificates \
|
||||
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
|
||||
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
|
||||
libx11-dev libinput-dev libxkbcommon-x11-dev \
|
||||
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
|
||||
&& pip install --no-cache-dir -U platformio \
|
||||
&& mkdir /tmp/firmware
|
||||
@@ -24,26 +24,13 @@ WORKDIR /tmp/firmware
|
||||
COPY . /tmp/firmware
|
||||
|
||||
# Build
|
||||
RUN bash ./bin/build-native.sh "$PIO_ENV" && \
|
||||
RUN bash ./bin/build-native.sh && \
|
||||
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||
|
||||
# Fetch web assets
|
||||
RUN curl -L "https://github.com/meshtastic/web/releases/download/v$(cat /tmp/firmware/bin/web.version)/build.tar" -o /tmp/web.tar \
|
||||
&& mkdir -p /tmp/web \
|
||||
&& tar -xf /tmp/web.tar -C /tmp/web/ \
|
||||
&& gzip -dr /tmp/web \
|
||||
&& rm /tmp/web.tar
|
||||
|
||||
##### PRODUCTION BUILD #############
|
||||
|
||||
FROM debian:trixie-slim
|
||||
LABEL org.opencontainers.image.title="Meshtastic" \
|
||||
org.opencontainers.image.description="Debian Meshtastic daemon and web interface" \
|
||||
org.opencontainers.image.url="https://meshtastic.org" \
|
||||
org.opencontainers.image.documentation="https://meshtastic.org/docs/" \
|
||||
org.opencontainers.image.authors="Meshtastic" \
|
||||
org.opencontainers.image.licenses="GPL-3.0-or-later" \
|
||||
org.opencontainers.image.source="https://github.com/meshtastic/firmware/"
|
||||
FROM debian:bookworm-slim
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Etc/UTC
|
||||
|
||||
@@ -51,17 +38,14 @@ ENV TZ=Etc/UTC
|
||||
USER root
|
||||
|
||||
RUN apt-get update && apt-get --no-install-recommends -y install \
|
||||
libc-bin libc6 libgpiod3 libyaml-cpp0.8 libi2c0 libuv1t64 libusb-1.0-0-dev \
|
||||
liborcania2.3 libulfius2.7t64 libssl3t64 \
|
||||
libx11-6 libinput10 libxkbcommon-x11-0 \
|
||||
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev liborcania2.3 libulfius2.7 libssl3 \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
|
||||
&& mkdir -p /var/lib/meshtasticd \
|
||||
&& mkdir -p /etc/meshtasticd/config.d \
|
||||
&& mkdir -p /etc/meshtasticd/ssl
|
||||
|
||||
# Fetch compiled binary from the builder
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
|
||||
COPY --from=builder /tmp/web /usr/share/meshtasticd/web/
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
|
||||
# Copy config templates
|
||||
COPY ./bin/config.d /etc/meshtasticd/available.d
|
||||
|
||||
@@ -70,9 +54,7 @@ VOLUME /var/lib/meshtasticd
|
||||
|
||||
# Expose Meshtastic TCP API port from the host
|
||||
EXPOSE 4403
|
||||
# Expose Meshtastic Web UI port from the host
|
||||
EXPOSE 9443
|
||||
|
||||
CMD [ "sh", "-cx", "meshtasticd --fsdir=/var/lib/meshtasticd" ]
|
||||
CMD [ "sh", "-cx", "meshtasticd -d /var/lib/meshtasticd" ]
|
||||
|
||||
HEALTHCHECK NONE
|
||||
HEALTHCHECK NONE
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
| Firmware Version | Supported |
|
||||
| ---------------- | ------------------ |
|
||||
| 2.6.x | :white_check_mark: |
|
||||
| <= 2.5.x | :x: |
|
||||
| 2.5.x | :white_check_mark: |
|
||||
| <= 2.4.x | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
# trunk-ignore-all(trivy/DS002): We must run as root for this container
|
||||
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions
|
||||
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
|
||||
|
||||
FROM python:3.14-alpine3.22 AS builder
|
||||
ARG PIO_ENV=native
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
FROM python:3.13-alpine3.21 AS builder
|
||||
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
RUN apk --no-cache add \
|
||||
bash g++ libstdc++-dev linux-headers zip git ca-certificates libbsd-dev \
|
||||
libgpiod-dev yaml-cpp-dev bluez-dev \
|
||||
bash g++ libstdc++-dev linux-headers zip git ca-certificates libgpiod-dev yaml-cpp-dev bluez-dev \
|
||||
libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \
|
||||
libx11-dev libinput-dev libxkbcommon-dev \
|
||||
&& rm -rf /var/cache/apk/* \
|
||||
&& pip install --no-cache-dir -U platformio \
|
||||
&& mkdir /tmp/firmware
|
||||
@@ -23,35 +21,23 @@ COPY . /tmp/firmware
|
||||
# Add `argp` for musl
|
||||
ENV PLATFORMIO_BUILD_FLAGS="-Os -ffunction-sections -fdata-sections -Wl,--gc-sections -largp"
|
||||
|
||||
RUN bash ./bin/build-native.sh "$PIO_ENV" && \
|
||||
RUN bash ./bin/build-native.sh && \
|
||||
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||
|
||||
# ##### PRODUCTION BUILD #############
|
||||
|
||||
FROM alpine:3.23
|
||||
LABEL org.opencontainers.image.title="Meshtastic" \
|
||||
org.opencontainers.image.description="Alpine Meshtastic daemon" \
|
||||
org.opencontainers.image.url="https://meshtastic.org" \
|
||||
org.opencontainers.image.documentation="https://meshtastic.org/docs/" \
|
||||
org.opencontainers.image.authors="Meshtastic" \
|
||||
org.opencontainers.image.licenses="GPL-3.0-or-later" \
|
||||
org.opencontainers.image.source="https://github.com/meshtastic/firmware/"
|
||||
FROM alpine:3.21
|
||||
|
||||
# nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root
|
||||
USER root
|
||||
|
||||
RUN apk --no-cache add \
|
||||
shadow libstdc++ libbsd libgpiod yaml-cpp libusb \
|
||||
i2c-tools libuv libx11 libinput libxkbcommon \
|
||||
libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \
|
||||
&& rm -rf /var/cache/apk/* \
|
||||
&& mkdir -p /var/lib/meshtasticd \
|
||||
&& mkdir -p /etc/meshtasticd/config.d \
|
||||
&& mkdir -p /etc/meshtasticd/ssl
|
||||
|
||||
# Fetch compiled binary from the builder
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
|
||||
# Copy config templates
|
||||
COPY ./bin/config.d /etc/meshtasticd/available.d
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
|
||||
|
||||
WORKDIR /var/lib/meshtasticd
|
||||
VOLUME /var/lib/meshtasticd
|
||||
|
||||
@@ -2,15 +2,7 @@
|
||||
[esp32_base]
|
||||
extends = arduino_base
|
||||
custom_esp32_kind = esp32
|
||||
custom_mtjson_part =
|
||||
platform =
|
||||
# renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32
|
||||
platformio/espressif32@6.12.0
|
||||
|
||||
extra_scripts =
|
||||
${env.extra_scripts}
|
||||
pre:extra_scripts/esp32_pre.py
|
||||
extra_scripts/esp32_extra.py
|
||||
platform = platformio/espressif32@6.10.0
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
||||
@@ -37,13 +29,11 @@ build_flags =
|
||||
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
-DCONFIG_BT_NIMBLE_ENABLED
|
||||
-DCONFIG_BT_NIMBLE_MAX_BONDS=6 # default is 3
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DSERIAL_BUFFER_SIZE=4096
|
||||
-DSERIAL_HAS_ON_RECEIVE
|
||||
-DLIBPAX_ARDUINO
|
||||
-DLIBPAX_WIFI
|
||||
-DLIBPAX_BLE
|
||||
@@ -54,20 +44,13 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master
|
||||
https://github.com/meshtastic/esp32_https_server/archive/3223704846752e6d545139204837bdb2a55459ca.zip
|
||||
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
|
||||
h2zero/NimBLE-Arduino@2.3.7
|
||||
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
|
||||
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
|
||||
# renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib
|
||||
https://github.com/lewisxhe/XPowersLib/archive/v0.3.2.zip
|
||||
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.3
|
||||
https://github.com/dbinfrago/libpax.git#3cdc0371c375676a97967547f4065607d4c53fd1
|
||||
lewisxhe/XPowersLib@^0.2.7
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
@@ -1,8 +1,6 @@
|
||||
[esp32c6_base]
|
||||
extends = esp32_base
|
||||
platform =
|
||||
# Do not renovate until we have switched to pioarduino tagged builds
|
||||
https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
|
||||
platform = https://github.com/Jason2866/platform-espressif32.git#22faa566df8c789000f8136cd8d0aca49617af55
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Wall
|
||||
@@ -25,14 +23,10 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
|
||||
lewisxhe/XPowersLib@0.3.2
|
||||
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
lewisxhe/XPowersLib@^0.2.7
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter} -<mesh/http>
|
||||
@@ -16,4 +16,4 @@ build_flags =
|
||||
lib_ignore =
|
||||
${esp32_base.lib_ignore}
|
||||
NimBLE-Arduino
|
||||
libpax
|
||||
libpax
|
||||
@@ -3,3 +3,4 @@ extends = esp32_base
|
||||
custom_esp32_kind = esp32s3
|
||||
|
||||
monitor_speed = 115200
|
||||
|
||||
@@ -1,50 +1,32 @@
|
||||
[nrf52_base]
|
||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||
platform =
|
||||
# renovate: datasource=custom.pio depName=platformio/nordicnrf52 packageName=platformio/platform/nordicnrf52
|
||||
platformio/nordicnrf52@^10.8.0
|
||||
platform = platformio/nordicnrf52@^10.7.0
|
||||
extends = arduino_base
|
||||
platform_packages =
|
||||
; our custom Git version until they merge our PR
|
||||
# TODO renovate
|
||||
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#c770c8a16a351b55b86e347a3d9d7b74ad0bbf39
|
||||
; Don't renovate toolchain-gccarmnoneeabi
|
||||
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino.git#e13f5820002a4fb2a5e6754b42ace185277e5adf
|
||||
platformio/toolchain-gccarmnoneeabi@~1.90301.0
|
||||
|
||||
extra_scripts =
|
||||
${env.extra_scripts}
|
||||
extra_scripts/nrf52_extra.py
|
||||
|
||||
build_type = release
|
||||
build_type = debug
|
||||
build_flags =
|
||||
-include variants/nrf52840/cpp_overrides/lfs_util.h
|
||||
-include arch/nrf52/cpp_overrides/lfs_util.h
|
||||
${arduino_base.build_flags}
|
||||
-DSERIAL_BUFFER_SIZE=1024
|
||||
-Wno-unused-variable
|
||||
-Isrc/platform/nrf52
|
||||
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
|
||||
-DMESHTASTIC_EXCLUDE_AUDIO=1
|
||||
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
|
||||
-Os
|
||||
build_unflags =
|
||||
-Ofast
|
||||
-Og
|
||||
-ggdb3
|
||||
-ggdb2
|
||||
-g3
|
||||
-g2
|
||||
-g
|
||||
-g1
|
||||
-g0
|
||||
-DMAX_NUM_NODES=80
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp> -<serialization/>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
||||
|
||||
lib_deps=
|
||||
${arduino_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
lvgl
|
||||
lvgl
|
||||
@@ -1,9 +1,7 @@
|
||||
[nrf52832_base]
|
||||
extends = nrf52_base
|
||||
|
||||
build_flags =
|
||||
${nrf52_base.build_flags}
|
||||
-DSERIAL_BUFFER_SIZE=1024
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
@@ -1,16 +1,12 @@
|
||||
[nrf52840_base]
|
||||
extends = nrf52_base
|
||||
|
||||
build_flags =
|
||||
${nrf52_base.build_flags}
|
||||
-DSERIAL_BUFFER_SIZE=4096
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
# renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master
|
||||
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/8cde7189b5ead9dcd49f72601b43b969c0bbc06e.zip
|
||||
https://github.com/Kongduino/Adafruit_nRFCrypto.git#e31a8825ea3300b163a0a3c1ddd5de34e10e1371
|
||||
|
||||
; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board.
|
||||
|
||||
45
arch/portduino/portduino.ini
Normal file
45
arch/portduino/portduino.ini
Normal file
@@ -0,0 +1,45 @@
|
||||
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
|
||||
[portduino_base]
|
||||
platform = https://github.com/Jorropo/platform-native.git#17fa89daec4402af491512f75278a7fec8a5818c
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
${env.build_src_filter}
|
||||
-<platform/esp32/>
|
||||
-<nimble/>
|
||||
-<platform/nrf52/>
|
||||
-<platform/stm32wl/>
|
||||
-<platform/rp2xx0>
|
||||
-<mesh/wifi/>
|
||||
-<mesh/http/>
|
||||
+<mesh/raspihttp/>
|
||||
-<mesh/eth/>
|
||||
-<modules/esp32>
|
||||
-<modules/Telemetry/EnvironmentTelemetry.cpp>
|
||||
-<modules/Telemetry/AirQualityTelemetry.cpp>
|
||||
-<modules/Telemetry/Sensor>
|
||||
+<../variants/portduino>
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
lovyan03/LovyanGFX@^1.2.0
|
||||
https://github.com/pine64/libch341-spi-userspace#a9b17e3452f7fb747000d9b4ad4409155b39f6ef
|
||||
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-fPIC
|
||||
-Isrc/platform/portduino
|
||||
-DRADIOLIB_EEPROM_UNSUPPORTED
|
||||
-DPORTDUINO_LINUX_HARDWARE
|
||||
-DHAS_UDP_MULTICAST
|
||||
-lpthread
|
||||
-lstdc++fs
|
||||
-lbluetooth
|
||||
-lgpiod
|
||||
-lyaml-cpp
|
||||
-li2c
|
||||
-luv
|
||||
-std=c++17
|
||||
@@ -1,13 +1,8 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2040_base]
|
||||
platform =
|
||||
# TODO renovate
|
||||
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
|
||||
; For arduino-pico >= 4.4.3
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
|
||||
extends = arduino_base
|
||||
platform_packages =
|
||||
# TODO renovate
|
||||
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.4.3
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -28,7 +23,5 @@ lib_ignore =
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
rweather/Crypto
|
||||
@@ -1,13 +1,8 @@
|
||||
; Common settings for rp2350 Processor based targets
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2350_base]
|
||||
platform =
|
||||
# TODO renovate
|
||||
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
|
||||
; For arduino-pico >= 4.4.3
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
|
||||
extends = arduino_base
|
||||
platform_packages =
|
||||
# TODO renovate
|
||||
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.4.3
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -25,7 +20,5 @@ lib_ignore =
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
rweather/Crypto
|
||||
44
arch/stm32/stm32.ini
Normal file
44
arch/stm32/stm32.ini
Normal file
@@ -0,0 +1,44 @@
|
||||
[stm32_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/ststm32
|
||||
platform_packages = platformio/framework-arduinoststm32@^4.20900.0
|
||||
|
||||
build_type = release
|
||||
|
||||
;board_build.flash_offset = 0x08000000
|
||||
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-flto
|
||||
-Isrc/platform/stm32wl -g
|
||||
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
-DMESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
-DMESHTASTIC_EXCLUDE_I2C
|
||||
-DMESHTASTIC_EXCLUDE_POWERMON
|
||||
-DMESHTASTIC_EXCLUDE_SCREEN
|
||||
-DMESHTASTIC_EXCLUDE_MQTT
|
||||
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
-DMESHTASTIC_EXCLUDE_PKI
|
||||
-DMESHTASTIC_EXCLUDE_GPS
|
||||
; -DVECT_TAB_OFFSET=0x08000000
|
||||
-DconfigUSE_CMSIS_RTOS_V2=1
|
||||
; -DSPI_MODE_0=SPI_MODE0
|
||||
-fmerge-all-constants
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>
|
||||
|
||||
board_upload.offset_address = 0x08000000
|
||||
upload_protocol = stlink
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
charlesbaynham/OSFS@^1.2.3
|
||||
jgromes/RadioLib@7.0.2
|
||||
https://github.com/caveman99/Crypto.git#f61ae26a53f7a2d0ba5511625b8bf8eff3a35d5e
|
||||
|
||||
lib_ignore =
|
||||
mathertel/OneButton@2.6.1
|
||||
Wire
|
||||
@@ -1,7 +0,0 @@
|
||||
# Set spidev ownership to 'spi' group
|
||||
SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660"
|
||||
# Allow access to USB CH341 devices
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666"
|
||||
# Set gpio ownership to 'gpio' group
|
||||
SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660"
|
||||
SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"
|
||||
@@ -1,165 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Summarise linker map output to highlight heavy object files and libraries.
|
||||
|
||||
Usage:
|
||||
python bin/analyze_map.py --map .pio/build/rak4631/output.map --top 20
|
||||
|
||||
The script parses GNU ld map files and aggregates section sizes per object file
|
||||
and per archive/library, then prints sortable tables that make it easy to spot
|
||||
modules worth trimming or hiding behind feature flags.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import collections
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from typing import DefaultDict, Dict, Tuple
|
||||
|
||||
|
||||
SECTION_LINE_RE = re.compile(r"^\s+(?P<section>\S+)\s+0x[0-9A-Fa-f]+\s+0x(?P<size>[0-9A-Fa-f]+)\s+(?P<object>.+)$")
|
||||
ARCHIVE_MEMBER_RE = re.compile(r"^(?P<archive>.+)\((?P<object>[^)]+)\)$")
|
||||
|
||||
|
||||
def human_size(num_bytes: int) -> str:
|
||||
"""Return a friendly size string with one decimal place."""
|
||||
if num_bytes < 1024:
|
||||
return f"{num_bytes:,} B"
|
||||
num = float(num_bytes)
|
||||
for unit in ("KB", "MB", "GB"):
|
||||
num /= 1024.0
|
||||
if num < 1024.0:
|
||||
return f"{num:.1f} {unit}"
|
||||
return f"{num:.1f} TB"
|
||||
|
||||
|
||||
def shorten_path(path: str, root: str) -> str:
|
||||
"""Prefer repository-relative paths for readability."""
|
||||
path = path.strip()
|
||||
if not path:
|
||||
return path
|
||||
|
||||
# Normalise Windows archives (backslashes) to POSIX style for consistency.
|
||||
path = path.replace("\\", "/")
|
||||
|
||||
# Attempt to strip the root when an absolute path lives inside the repo.
|
||||
if os.path.isabs(path):
|
||||
try:
|
||||
rel = os.path.relpath(path, root)
|
||||
if not rel.startswith(".."):
|
||||
return rel
|
||||
except ValueError:
|
||||
# relpath can fail on mixed drives on Windows; fall back to basename.
|
||||
pass
|
||||
return path
|
||||
|
||||
|
||||
def describe_object(raw_object: str, root: str) -> Tuple[str, str]:
|
||||
"""Return a human friendly object label and the library it belongs to."""
|
||||
raw_object = raw_object.strip()
|
||||
lib_label = "[app]"
|
||||
match = ARCHIVE_MEMBER_RE.match(raw_object)
|
||||
if match:
|
||||
archive = shorten_path(match.group("archive"), root)
|
||||
obj = match.group("object")
|
||||
lib_label = os.path.basename(archive) or archive
|
||||
label = f"{archive}:{obj}"
|
||||
else:
|
||||
label = shorten_path(raw_object, root)
|
||||
# If the object lives under libs, hint at the containing directory.
|
||||
parent = os.path.basename(os.path.dirname(label))
|
||||
if parent:
|
||||
lib_label = parent
|
||||
return label, lib_label
|
||||
|
||||
|
||||
def parse_map(map_path: str, repo_root: str) -> Tuple[Dict[str, int], Dict[str, int], Dict[str, Dict[str, int]]]:
|
||||
per_object: DefaultDict[str, int] = collections.defaultdict(int)
|
||||
per_library: DefaultDict[str, int] = collections.defaultdict(int)
|
||||
per_object_sections: DefaultDict[str, DefaultDict[str, int]] = collections.defaultdict(lambda: collections.defaultdict(int))
|
||||
|
||||
try:
|
||||
with open(map_path, "r", encoding="utf-8", errors="ignore") as handle:
|
||||
for line in handle:
|
||||
match = SECTION_LINE_RE.match(line)
|
||||
if not match:
|
||||
continue
|
||||
|
||||
section = match.group("section")
|
||||
if section.startswith("*") or section in {"LOAD", "ORIGIN"}:
|
||||
continue
|
||||
|
||||
size = int(match.group("size"), 16)
|
||||
if size == 0:
|
||||
continue
|
||||
|
||||
obj_token = match.group("object").strip()
|
||||
if not obj_token or obj_token.startswith("*") or "load address" in obj_token:
|
||||
continue
|
||||
|
||||
label, lib_label = describe_object(obj_token, repo_root)
|
||||
per_object[label] += size
|
||||
per_library[lib_label] += size
|
||||
per_object_sections[label][section] += size
|
||||
except FileNotFoundError:
|
||||
raise SystemExit(f"error: map file '{map_path}' not found. Run a build first.")
|
||||
|
||||
return per_object, per_library, per_object_sections
|
||||
|
||||
|
||||
def format_section_breakdown(section_sizes: Dict[str, int], total: int, limit: int = 3) -> str:
|
||||
items = sorted(section_sizes.items(), key=lambda kv: kv[1], reverse=True)
|
||||
parts = []
|
||||
for section, size in items[:limit]:
|
||||
pct = (size / total) * 100 if total else 0
|
||||
parts.append(f"{section} {pct:.1f}%")
|
||||
if len(items) > limit:
|
||||
remainder = total - sum(size for _, size in items[:limit])
|
||||
pct = (remainder / total) * 100 if total else 0
|
||||
parts.append(f"other {pct:.1f}%")
|
||||
return ", ".join(parts)
|
||||
|
||||
|
||||
def print_report(map_path: str, top_n: int, per_object: Dict[str, int], per_library: Dict[str, int], per_object_sections: Dict[str, Dict[str, int]]):
|
||||
total_bytes = sum(per_object.values())
|
||||
if total_bytes == 0:
|
||||
print("No section data found in map file.")
|
||||
return
|
||||
|
||||
print(f"Map file: {map_path}")
|
||||
print(f"Accounted size: {human_size(total_bytes)} across {len(per_object)} object files\n")
|
||||
|
||||
sorted_objects = sorted(per_object.items(), key=lambda kv: kv[1], reverse=True)
|
||||
print(f"Top {min(top_n, len(sorted_objects))} object files by linked size:")
|
||||
for idx, (obj, size) in enumerate(sorted_objects[:top_n], 1):
|
||||
pct = (size / total_bytes) * 100
|
||||
breakdown = format_section_breakdown(per_object_sections[obj], size)
|
||||
print(f"{idx:2}. {human_size(size):>9} ({size:,} B, {pct:5.2f}% of linked size)")
|
||||
print(f" {obj}")
|
||||
if breakdown:
|
||||
print(f" sections: {breakdown}")
|
||||
print()
|
||||
|
||||
sorted_libs = sorted(per_library.items(), key=lambda kv: kv[1], reverse=True)
|
||||
print(f"Top {min(top_n, len(sorted_libs))} libraries or source roots:")
|
||||
for idx, (lib, size) in enumerate(sorted_libs[:top_n], 1):
|
||||
pct = (size / total_bytes) * 100
|
||||
print(f"{idx:2}. {human_size(size):>9} ({size:,} B, {pct:5.2f}% of linked size) {lib}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="Highlight heavy object files from a GNU ld map file.")
|
||||
parser.add_argument("--map", default=".pio/build/rak4631/output.map", help="Path to the map file (default: %(default)s)")
|
||||
parser.add_argument("--top", type=int, default=20, help="Number of entries to display per table (default: %(default)s)")
|
||||
args = parser.parse_args()
|
||||
|
||||
map_path = os.path.abspath(args.map)
|
||||
repo_root = os.path.abspath(os.getcwd())
|
||||
|
||||
per_object, per_library, per_object_sections = parse_map(map_path, repo_root)
|
||||
print_report(os.path.relpath(map_path, repo_root), args.top, per_object, per_library, per_object_sections)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -5,37 +5,41 @@ set -e
|
||||
VERSION=`bin/buildinfo.py long`
|
||||
SHORT_VERSION=`bin/buildinfo.py short`
|
||||
|
||||
BUILDDIR=.pio/build/$1
|
||||
OUTDIR=release
|
||||
OUTDIR=release/
|
||||
|
||||
rm -f $OUTDIR/firmware*
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio pkg install -e $1
|
||||
platformio pkg update -e $1
|
||||
|
||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f $BUILDDIR/firmware*
|
||||
rm -f .pio/build/$1/firmware.*
|
||||
|
||||
# The shell vars the build tool expects to find
|
||||
export APP_VERSION=$VERSION
|
||||
|
||||
basename=firmware-$1-$VERSION
|
||||
|
||||
pio run --environment $1 -t mtjson # -v
|
||||
|
||||
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
|
||||
pio run --environment $1 # -v
|
||||
SRCELF=.pio/build/$1/firmware.elf
|
||||
cp $SRCELF $OUTDIR/$basename.elf
|
||||
|
||||
echo "Copying ESP32 bin file"
|
||||
cp $BUILDDIR/$basename.factory.bin $OUTDIR/$basename.factory.bin
|
||||
SRCBIN=.pio/build/$1/firmware.factory.bin
|
||||
cp $SRCBIN $OUTDIR/$basename.bin
|
||||
|
||||
echo "Copying ESP32 update bin file"
|
||||
cp $BUILDDIR/$basename.bin $OUTDIR/$basename.bin
|
||||
SRCBIN=.pio/build/$1/firmware.bin
|
||||
cp $SRCBIN $OUTDIR/$basename-update.bin
|
||||
|
||||
echo "Copying Filesystem for ESP32 targets"
|
||||
cp $BUILDDIR/littlefs-$1-$VERSION.bin $OUTDIR/littlefs-$1-$VERSION.bin
|
||||
cp bin/device-install.* $OUTDIR/
|
||||
cp bin/device-update.* $OUTDIR/
|
||||
|
||||
echo "Copying manifest"
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json
|
||||
echo "Building Filesystem for ESP32 targets"
|
||||
pio run --environment $1 -t buildfs
|
||||
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefswebui-$1-$VERSION.bin
|
||||
# Remove webserver files from the filesystem and rebuild
|
||||
ls -l data/static # Diagnostic list of files
|
||||
rm -rf data/static
|
||||
pio run --environment $1 -t buildfs
|
||||
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefs-$1-$VERSION.bin
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sed -i 's/#-DBUILD_EPOCH=$UNIX_TIME/-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
|
||||
|
||||
export PIP_BREAK_SYSTEM_PACKAGES=1
|
||||
|
||||
if (echo $2 | grep -q "esp32"); then
|
||||
@@ -9,7 +11,7 @@ elif (echo $2 | grep -q "nrf52"); then
|
||||
elif (echo $2 | grep -q "stm32"); then
|
||||
bin/build-stm32.sh $1
|
||||
elif (echo $2 | grep -q "rpi2040"); then
|
||||
bin/build-rp2xx0.sh $1
|
||||
bin/build-rpi2040.sh $1
|
||||
else
|
||||
echo "Unknown target $2"
|
||||
exit 1
|
||||
|
||||
@@ -15,21 +15,16 @@ platformioFailed() {
|
||||
|
||||
VERSION=$(bin/buildinfo.py long)
|
||||
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||
PIO_ENV=${1:-native}
|
||||
|
||||
BUILDDIR=.pio/build/$PIO_ENV
|
||||
OUTDIR=release
|
||||
OUTDIR=release/
|
||||
|
||||
rm -f $OUTDIR/meshtasticd*
|
||||
rm -f $OUTDIR/firmware*
|
||||
|
||||
mkdir -p $OUTDIR/
|
||||
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
|
||||
pio pkg install --environment "$PIO_ENV" || platformioFailed
|
||||
pio run --environment "$PIO_ENV" || platformioFailed
|
||||
|
||||
cp "$BUILDDIR/meshtasticd" "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||
cp bin/native-install.* $OUTDIR/
|
||||
pio pkg update --environment native || platformioFailed
|
||||
pio run --environment native || platformioFailed
|
||||
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||
cp bin/native-install.* $OUTDIR
|
||||
|
||||
@@ -5,47 +5,49 @@ set -e
|
||||
VERSION=$(bin/buildinfo.py long)
|
||||
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||
|
||||
BUILDDIR=.pio/build/$1
|
||||
OUTDIR=release
|
||||
OUTDIR=release/
|
||||
|
||||
rm -f $OUTDIR/firmware*
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio pkg install -e $1
|
||||
platformio pkg update -e $1
|
||||
|
||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f $BUILDDIR/firmware*
|
||||
rm -f .pio/build/$1/firmware.*
|
||||
|
||||
# The shell vars the build tool expects to find
|
||||
export APP_VERSION=$VERSION
|
||||
|
||||
basename=firmware-$1-$VERSION
|
||||
|
||||
pio run --environment $1 -t mtjson # -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 "Generating NRF52 dfu file"
|
||||
DFUPKG=.pio/build/$1/firmware.zip
|
||||
cp $DFUPKG $OUTDIR/$basename-ota.zip
|
||||
|
||||
echo "Copying NRF52 dfu (OTA) file"
|
||||
cp $BUILDDIR/$basename.zip $OUTDIR/$basename.zip
|
||||
echo "Generating NRF52 uf2 file"
|
||||
SRCHEX=.pio/build/$1/firmware.hex
|
||||
|
||||
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 WM1110 target, merge hex with softdevice 7.3.0
|
||||
if (echo $1 | grep -q "wio-sdk-wm1110"); then
|
||||
echo "Copying .merged.hex file"
|
||||
SRCHEX=$BUILDDIR/$basename.merged.hex
|
||||
cp $SRCHEX $OUTDIR/
|
||||
echo "Merging with softdevice"
|
||||
bin/mergehex -m bin/s140_nrf52_7.3.0_softdevice.hex $SRCHEX -o .pio/build/$1/$basename.hex
|
||||
SRCHEX=.pio/build/$1/$basename.hex
|
||||
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
|
||||
|
||||
if (echo $1 | grep -q "rak4631"); then
|
||||
echo "Copying .hex file"
|
||||
cp $SRCHEX $OUTDIR/
|
||||
fi
|
||||
|
||||
echo "Copying manifest"
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json
|
||||
echo "Copying hex file"
|
||||
cp .pio/build/$1/firmware.hex $OUTDIR/$basename.hex
|
||||
fi
|
||||
@@ -5,29 +5,29 @@ set -e
|
||||
VERSION=`bin/buildinfo.py long`
|
||||
SHORT_VERSION=`bin/buildinfo.py short`
|
||||
|
||||
BUILDDIR=.pio/build/$1
|
||||
OUTDIR=release
|
||||
OUTDIR=release/
|
||||
|
||||
rm -f $OUTDIR/firmware*
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio pkg install -e $1
|
||||
platformio pkg update -e $1
|
||||
|
||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f $BUILDDIR/firmware*
|
||||
rm -f .pio/build/$1/firmware.*
|
||||
|
||||
# The shell vars the build tool expects to find
|
||||
export APP_VERSION=$VERSION
|
||||
|
||||
basename=firmware-$1-$VERSION
|
||||
|
||||
pio run --environment $1 -t mtjson # -v
|
||||
|
||||
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
|
||||
pio run --environment $1 # -v
|
||||
SRCELF=.pio/build/$1/firmware.elf
|
||||
cp $SRCELF $OUTDIR/$basename.elf
|
||||
|
||||
echo "Copying uf2 file"
|
||||
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2
|
||||
SRCBIN=.pio/build/$1/firmware.uf2
|
||||
cp $SRCBIN $OUTDIR/$basename.uf2
|
||||
|
||||
echo "Copying manifest"
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
@@ -5,29 +5,25 @@ set -e
|
||||
VERSION=$(bin/buildinfo.py long)
|
||||
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||
|
||||
BUILDDIR=.pio/build/$1
|
||||
OUTDIR=release
|
||||
OUTDIR=release/
|
||||
|
||||
rm -f $OUTDIR/firmware*
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio pkg install -e $1
|
||||
platformio pkg update -e $1
|
||||
|
||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f $BUILDDIR/firmware*
|
||||
rm -f .pio/build/$1/firmware.*
|
||||
|
||||
# The shell vars the build tool expects to find
|
||||
export APP_VERSION=$VERSION
|
||||
|
||||
basename=firmware-$1-$VERSION
|
||||
|
||||
pio run --environment $1 -t mtjson # -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 STM32 bin file"
|
||||
cp $BUILDDIR/$basename.bin $OUTDIR/$basename.bin
|
||||
|
||||
echo "Copying manifest"
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json
|
||||
SRCBIN=.pio/build/$1/firmware.bin
|
||||
cp $SRCBIN $OUTDIR/$basename.bin
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import xml.etree.ElementTree as ET
|
||||
from defusedxml.ElementTree import parse
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
# Indent by 2 spaces to align with xml formatting.
|
||||
def indent(elem, level=0):
|
||||
i = "\n" + level * " "
|
||||
if len(elem):
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = i + " "
|
||||
for child in elem:
|
||||
indent(child, level + 1)
|
||||
if not child.tail or not child.tail.strip():
|
||||
child.tail = i
|
||||
if level and (not elem.tail or not elem.tail.strip()):
|
||||
elem.tail = i
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Prepend new release entry to metainfo.xml file.")
|
||||
parser.add_argument("--file", help="Path to the metainfo.xml file",
|
||||
default="org.meshtastic.meshtasticd.metainfo.xml")
|
||||
parser.add_argument("version", help="Version string (e.g. 2.6.4)")
|
||||
parser.add_argument("--date", help="Release date (YYYY-MM-DD), defaults to today",
|
||||
default=datetime.now(timezone.utc).date().isoformat())
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
tree = parse(args.file)
|
||||
root = tree.getroot()
|
||||
|
||||
releases = root.find('releases')
|
||||
if releases is None:
|
||||
raise RuntimeError("<releases> element not found in XML.")
|
||||
|
||||
existing_versions = {
|
||||
release.get('version'): release
|
||||
for release in releases.findall('release')
|
||||
}
|
||||
existing_release = existing_versions.get(args.version)
|
||||
|
||||
if existing_release is not None:
|
||||
if not existing_release.get('date'):
|
||||
print(f"Version {args.version} found without date. Adding date...")
|
||||
existing_release.set('date', args.date)
|
||||
else:
|
||||
print(
|
||||
f"Version {args.version} is already present with date, skipping insertion.")
|
||||
else:
|
||||
new_release = ET.Element('release', {
|
||||
'version': args.version,
|
||||
'date': args.date
|
||||
})
|
||||
url = ET.SubElement(new_release, 'url', {'type': 'details'})
|
||||
url.text = f"https://github.com/meshtastic/firmware/releases?q=tag%3Av{args.version}"
|
||||
|
||||
releases.insert(0, new_release)
|
||||
|
||||
indent(releases, level=1)
|
||||
releases.tail = "\n"
|
||||
|
||||
print(f"Inserted new release: {args.version}")
|
||||
|
||||
tree.write(args.file, encoding='UTF-8', xml_declaration=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1 +0,0 @@
|
||||
defusedxml==0.7.1
|
||||
@@ -23,4 +23,4 @@ for BOARD in $BOARDS; do
|
||||
CHECK="${CHECK} -e ${BOARD}"
|
||||
done
|
||||
|
||||
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt --inline-suppr" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high
|
||||
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high
|
||||
|
||||
@@ -6,12 +6,6 @@
|
||||
### Including the "Module:" line!
|
||||
---
|
||||
Lora:
|
||||
# Default to auto-detecting the module type
|
||||
# This will be overridden by configs from config.d
|
||||
Module: auto
|
||||
|
||||
# # Uncomment to enable Simulation mode, or use --sim
|
||||
# Module: sim
|
||||
|
||||
# Module: sx1262 # Waveshare SX1302 LISTEN ONLY AT THIS TIME!
|
||||
# CS: 7
|
||||
@@ -96,9 +90,9 @@ Lora:
|
||||
### Some devices, like the pinedio, may require spidev0.1 as a workaround.
|
||||
# spidev: spidev0.0
|
||||
|
||||
### Deprecated location for User Button:
|
||||
### Define GPIO buttons here:
|
||||
|
||||
#GPIO:
|
||||
GPIO:
|
||||
# User: 6
|
||||
|
||||
### Define GPS
|
||||
@@ -115,6 +109,17 @@ I2C:
|
||||
|
||||
Display:
|
||||
|
||||
### Waveshare 1.44inch LCD HAT
|
||||
# Panel: ST7735S
|
||||
# CS: 8 #Chip Select
|
||||
# DC: 25 # Data/Command pin
|
||||
# Backlight: 24
|
||||
# Width: 128
|
||||
# Height: 128
|
||||
# Reset: 27
|
||||
# OffsetX: 0
|
||||
# OffsetY: 0
|
||||
|
||||
### Adafruit PiTFT 2.8 TFT+Touchscreen
|
||||
# Panel: ILI9341
|
||||
# CS: 8
|
||||
@@ -169,46 +174,22 @@ Input:
|
||||
|
||||
# KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd
|
||||
|
||||
### Standard User Button Config
|
||||
# UserButton: 6
|
||||
|
||||
### Trackball/Joystick input
|
||||
# TrackballUp: 6
|
||||
# TrackballDown: 19
|
||||
# TrackballLeft: 5
|
||||
# TrackballRight: 26
|
||||
# TrackballPress: 13
|
||||
|
||||
###
|
||||
|
||||
Logging:
|
||||
LogLevel: info # debug, info, warn, error
|
||||
# TraceFile: /var/log/meshtasticd.json
|
||||
# JSONFile: /packets.json # File location for JSON output of decoded packets
|
||||
# JSONFilter: position # filter for packets to save to JSON file
|
||||
# AsciiLogs: true # default if not specified is !isatty() on stdout
|
||||
|
||||
Webserver:
|
||||
# Port: 9443 # Port for Webserver & Webservices
|
||||
# Port: 443 # Port for Webserver & Webservices
|
||||
# RootPath: /usr/share/meshtasticd/web # Root Dir of WebServer
|
||||
# SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if not present
|
||||
# SSLCert: /etc/meshtasticd/ssl/certificate.pem # Path to SSL Certificate, generated if not present
|
||||
|
||||
|
||||
HostMetrics:
|
||||
# ReportInterval: 30 # Interval in minutes between HostMetrics report packets, or 0 for disabled
|
||||
# Channel: 0 # channel to send Host Metrics over. Defaults to the primary channel.
|
||||
# UserStringCommand: cat /sys/firmware/devicetree/base/serial-number # Command to execute, to send the results as the userString
|
||||
|
||||
|
||||
Config:
|
||||
# DisplayMode: TWOCOLOR # uncomment to force BaseUI
|
||||
# DisplayMode: COLOR # uncomment to force MUI
|
||||
|
||||
General:
|
||||
MaxNodes: 200
|
||||
MaxMessageQueue: 100
|
||||
ConfigDirectory: /etc/meshtasticd/config.d/
|
||||
AvailableDirectory: /etc/meshtasticd/available.d/
|
||||
# MACAddress: AA:BB:CC:DD:EE:FF
|
||||
# MACAddressSource: eth0
|
||||
# MACAddressSource: eth0
|
||||
@@ -1,26 +0,0 @@
|
||||
### Waveshare 1.44inch LCD HAT
|
||||
Display:
|
||||
Panel: ST7735S
|
||||
spidev: spidev0.0 # Specify either the spidev here, or the CS below
|
||||
# CS: 8 #Chip Select # Optional, as this is the default pin for spidev0.0
|
||||
DC: 25 # Data/Command pin
|
||||
Backlight: 24
|
||||
Width: 128
|
||||
Height: 128
|
||||
Reset: 27
|
||||
OffsetX: 2
|
||||
OffsetY: 1
|
||||
|
||||
|
||||
# OffsetY: 31 # These two options are used to properly flip the screen 180 degrees
|
||||
# OffsetRotate: 3
|
||||
|
||||
|
||||
Input:
|
||||
TrackballUp: 6
|
||||
TrackballDown: 19
|
||||
TrackballLeft: 5
|
||||
TrackballRight: 26
|
||||
TrackballPress: 13
|
||||
TrackballDirection: FALLING
|
||||
# User: 21
|
||||
5
bin/config.d/lora-Adafruit-RFM9x
Normal file
5
bin/config.d/lora-Adafruit-RFM9x
Normal file
@@ -0,0 +1,5 @@
|
||||
# Module: RF95 # Adafruit RFM9x
|
||||
# Reset: 25
|
||||
# CS: 7
|
||||
# IRQ: 22
|
||||
# Busy: 23
|
||||
@@ -1,6 +0,0 @@
|
||||
Lora:
|
||||
Module: RF95 # Adafruit RFM9x
|
||||
Reset: 25
|
||||
CS: 7
|
||||
IRQ: 22
|
||||
# Busy: 23
|
||||
@@ -1,5 +1,3 @@
|
||||
# MeshAdv-Pi E22-900M30S
|
||||
# https://github.com/chrismyers2000/MeshAdv-Pi-Hat
|
||||
Lora:
|
||||
Module: sx1262
|
||||
CS: 21
|
||||
@@ -11,4 +9,4 @@ Lora:
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
# Only for E22-900M33S:
|
||||
# Limit the output power to 8 dBm
|
||||
# SX126X_MAX_POWER: 8
|
||||
# SX126X_MAX_POWER: 8
|
||||
@@ -1,11 +0,0 @@
|
||||
# MeshAdv Mini E22-900M22S
|
||||
# https://github.com/chrismyers2000/MeshAdv-Mini
|
||||
Lora:
|
||||
Module: sx1262 # Ebyte E22-900M22S
|
||||
CS: 8
|
||||
IRQ: 16
|
||||
Busy: 20
|
||||
Reset: 24
|
||||
RXen: 12
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
@@ -1,12 +0,0 @@
|
||||
Lora:
|
||||
|
||||
### RAK13300in Slot 1
|
||||
Module: sx1262
|
||||
IRQ: 22 #IO6
|
||||
Reset: 16 # IO4
|
||||
Busy: 24 # IO5
|
||||
# Ant_sw: 13 # IO3
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
# CS: 8
|
||||
@@ -1,8 +0,0 @@
|
||||
Lora:
|
||||
### RAK13300in Slot 2 pins
|
||||
IRQ: 18 #IO6
|
||||
Reset: 24 # IO4
|
||||
Busy: 19 # IO5
|
||||
# Ant_sw: 23 # IO3
|
||||
spidev: spidev0.1
|
||||
# CS: 7
|
||||
@@ -1,18 +0,0 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
gpiochip: 0
|
||||
MOSI: 12
|
||||
MISO: 13
|
||||
IRQ: 1
|
||||
Busy: 23
|
||||
Reset: 22
|
||||
RXen: 0
|
||||
gpiochip: 1
|
||||
CS: 9
|
||||
SCK: 11
|
||||
# TXen: bridge to DIO2 on E22 module
|
||||
SX126X_MAX_POWER: 22
|
||||
spidev: spidev1.0
|
||||
spiSpeed: 2000000
|
||||
@@ -1,11 +0,0 @@
|
||||
Lora:
|
||||
Module: lr1121
|
||||
CS: 0
|
||||
IRQ: 6
|
||||
Reset: 2
|
||||
Busy: 4
|
||||
spidev: ch341
|
||||
DIO3_TCXO_VOLTAGE: 1.8
|
||||
# USB_Serialnum: 12345678
|
||||
USB_PID: 0x5512
|
||||
USB_VID: 0x1A86
|
||||
@@ -1,17 +0,0 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
CS: 0
|
||||
IRQ: 6
|
||||
Reset: 2
|
||||
Busy: 4
|
||||
RXen: 1
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
spidev: ch341
|
||||
USB_PID: 0x5512
|
||||
USB_VID: 0x1A86
|
||||
# Optional: Reduce power to 10 dBm to
|
||||
# avoid over-drawing the USB port
|
||||
# SX126X_MAX_POWER: 10
|
||||
# Optional: Set the serial number for multi-radio support
|
||||
# USB_Serialnum: 13374201
|
||||
@@ -1,52 +0,0 @@
|
||||
# https://www.waveshare.com/pico-lora-sx1262-868m.htm
|
||||
# http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-Zero-3.html
|
||||
#
|
||||
# See Orange Pi Zero3 manual, chapter 3.16, page 124 for 26-pin header pinout
|
||||
#
|
||||
# Pin Connection
|
||||
# Waveshare Orange Pi Zero3
|
||||
# 36 3.3V 17
|
||||
# 15 MOSI 19
|
||||
# 16 MISO 21
|
||||
# 14 CLK 23
|
||||
# 38 GND 25
|
||||
# 4 BUSY 18
|
||||
# 20 RESET 22
|
||||
# 5 CS 24
|
||||
# 26 DIO1/IRQ 26
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Waveshare Raspberry Pico Lora module
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
# Specify either the spidev1_1 or the CS below, not both!
|
||||
# On DietPi Linux, when using the user overlay dietpi-spi1_1.dtbo, CS will be configured with spidev1.1
|
||||
spidev: spidev1.1 # See Orange Pi Zero3 manual, chapter 3.18.3, page 130
|
||||
# CS: # CS PIN_24 -> chip 1, line 233
|
||||
# pin: 24
|
||||
# gpiochip: 1
|
||||
# line: 233
|
||||
SCK: # SCK PIN_23 -> chip 1, line 230
|
||||
pin: 23
|
||||
gpiochip: 1
|
||||
line: 230
|
||||
Busy: # BUSY PIN_18 -> chip 1, line 78
|
||||
pin: 18
|
||||
gpiochip: 1
|
||||
line: 78
|
||||
MOSI: # MOSI PIN_19 -> chip 1, line 231
|
||||
pin: 19
|
||||
gpiochip: 1
|
||||
line: 231
|
||||
MISO: # MISO PIN_21 -> chip 1, line 232
|
||||
pin: 21
|
||||
gpiochip: 1
|
||||
line: 232
|
||||
Reset: # NRST PIN_22 -> chip 1, line 71
|
||||
pin: 22
|
||||
gpiochip: 1
|
||||
line: 71
|
||||
IRQ: # DIO1 PIN_26 -> chip 1, line 74
|
||||
pin: 26
|
||||
gpiochip: 1
|
||||
line: 74
|
||||
@@ -5,39 +5,36 @@ TITLE Meshtastic device-install
|
||||
SET "SCRIPT_NAME=%~nx0"
|
||||
SET "DEBUG=0"
|
||||
SET "PYTHON="
|
||||
SET "WEB_APP=0"
|
||||
SET "TFT_BUILD=0"
|
||||
SET "TFT8=0"
|
||||
SET "TFT16=0"
|
||||
SET "ESPTOOL_BAUD=115200"
|
||||
SET "ESPTOOL_CMD="
|
||||
SET "LOGCOUNTER=0"
|
||||
SET "BPS_RESET=0"
|
||||
@REM Default offsets.
|
||||
@REM https://github.com/meshtastic/web-flasher/blob/main/stores/firmwareStore.ts#L202
|
||||
SET "OTA_OFFSET=0x260000"
|
||||
SET "SPIFFS_OFFSET=0x300000"
|
||||
|
||||
GOTO getopts
|
||||
:help
|
||||
ECHO Flash image file to device, but first erasing and writing system information.
|
||||
ECHO.
|
||||
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] [--1200bps-reset]
|
||||
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] (--web)
|
||||
ECHO.
|
||||
ECHO Options:
|
||||
ECHO -f filename The firmware .factory.bin file to flash. Custom to your device type and region. (required)
|
||||
ECHO -f filename The firmware .bin file to flash. Custom to your device type and region. (required)
|
||||
ECHO The file must be located in this current directory.
|
||||
ECHO -p PORT Set the environment variable for ESPTOOL_PORT.
|
||||
ECHO If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
ECHO -P python Specify alternate python interpreter to use to invoke esptool. (default: python)
|
||||
ECHO If supplied the script will use python.
|
||||
ECHO If not supplied the script will try to find esptool in Path.
|
||||
ECHO --1200bps-reset Attempt to place the device in correct mode. (1200bps Reset)
|
||||
ECHO Some hardware requires this twice.
|
||||
ECHO --web Enable WebUI. (default: false)
|
||||
ECHO.
|
||||
ECHO Example: %SCRIPT_NAME% -p COM17 --1200bps-reset
|
||||
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.factory.bin -p COM11
|
||||
ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4.bin -p COM11
|
||||
ECHO Example: %SCRIPT_NAME% -f firmware-unphone-2.6.0.0b106d4.bin -p COM11 --web
|
||||
GOTO eof
|
||||
|
||||
:version
|
||||
ECHO %SCRIPT_NAME% [Version 2.7.0]
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.0]
|
||||
ECHO Meshtastic
|
||||
GOTO eof
|
||||
|
||||
@@ -53,13 +50,11 @@ IF /I "%~1"=="-f" SET "FILENAME=%~2" & SHIFT
|
||||
IF "%~1"=="-p" SET "ESPTOOL_PORT=%~2" & SHIFT
|
||||
IF /I "%~1"=="--port" SET "ESPTOOL_PORT=%~2" & SHIFT
|
||||
IF "%~1"=="-P" SET "PYTHON=%~2" & SHIFT
|
||||
IF /I "%~1"=="--1200bps-reset" SET "BPS_RESET=1"
|
||||
IF /I "%~1"=="--web" SET "WEB_APP=1"
|
||||
SHIFT
|
||||
GOTO getopts
|
||||
:endopts
|
||||
|
||||
IF %BPS_RESET% EQU 1 GOTO skip-filename
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..."
|
||||
IF "__!FILENAME!__"=="____" (
|
||||
CALL :LOG_MESSAGE DEBUG "Missing -f filename input."
|
||||
@@ -70,8 +65,8 @@ IF "__!FILENAME!__"=="____" (
|
||||
CALL :LOG_MESSAGE ERROR "Filename containing spaces are not supported."
|
||||
GOTO help
|
||||
)
|
||||
IF NOT "__!FILENAME:.factory.bin=!__"=="__!FILENAME!__" (
|
||||
CALL :LOG_MESSAGE ERROR "Filename must be a firmware-*.factory.bin file."
|
||||
IF "__!FILENAME:firmware-=!__"=="__!FILENAME!__" (
|
||||
CALL :LOG_MESSAGE ERROR "Filename must be a firmware-* file."
|
||||
GOTO help
|
||||
)
|
||||
@REM Remove ".\" or "./" file prefix if present.
|
||||
@@ -85,36 +80,20 @@ IF NOT EXIST !FILENAME! (
|
||||
GOTO eof
|
||||
)
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking for metadata..."
|
||||
@REM Derive metadata filename from firmware filename.
|
||||
SET "METAFILE=!FILENAME:.factory.bin=!.mt.json"
|
||||
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 (
|
||||
CALL :LOG_MESSAGE ERROR "No metadata file found: !METAFILE!"
|
||||
IF NOT "!FILENAME:update=!"=="!FILENAME!" (
|
||||
CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!"
|
||||
CALL :LOG_MESSAGE INFO "Use script device-update.bat to flash update !FILENAME!."
|
||||
GOTO eof
|
||||
) ELSE (
|
||||
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!"
|
||||
)
|
||||
|
||||
:skip-filename
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
|
||||
IF NOT "__%PYTHON%__"=="____" (
|
||||
SET "ESPTOOL_CMD=!PYTHON! -m esptool"
|
||||
CALL :LOG_MESSAGE DEBUG "Python interpreter supplied."
|
||||
) 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
|
||||
IF %ERRORLEVEL% EQU 0 (
|
||||
@REM WHERE exits with code 0 if esptool is found.
|
||||
@@ -127,10 +106,11 @@ IF NOT "__%PYTHON%__"=="____" (
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
||||
!ESPTOOL_CMD! >nul 2>&1
|
||||
IF %ERRORLEVEL% EQU 9009 (
|
||||
@REM 9009 = command not found on Windows
|
||||
IF %ERRORLEVEL% GTR 2 (
|
||||
@REM esptool exits with code 1 if help is displayed.
|
||||
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
||||
EXIT /B 1
|
||||
GOTO eof
|
||||
)
|
||||
IF %DEBUG% EQU 1 (
|
||||
CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps."
|
||||
@@ -141,37 +121,105 @@ CALL :LOG_MESSAGE DEBUG "Using esptool command: !ESPTOOL_CMD!"
|
||||
IF "__!ESPTOOL_PORT!__" == "____" (
|
||||
CALL :LOG_MESSAGE WARN "Using esptool port: UNSET."
|
||||
) ELSE (
|
||||
SET "ESPTOOL_CMD=!ESPTOOL_CMD! --port !ESPTOOL_PORT!"
|
||||
CALL :LOG_MESSAGE INFO "Using esptool port: !ESPTOOL_PORT!."
|
||||
)
|
||||
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
|
||||
|
||||
IF %BPS_RESET% EQU 1 (
|
||||
@REM Attempt to change mode via 1200bps Reset.
|
||||
CALL :RUN_ESPTOOL 1200 --after no_reset read_flash_status
|
||||
GOTO eof
|
||||
)
|
||||
|
||||
@REM Extract PROGNAME from %FILENAME% for later use.
|
||||
SET "PROGNAME=!FILENAME:.factory.bin=!"
|
||||
CALL :LOG_MESSAGE DEBUG "Computed PROGNAME: !PROGNAME!"
|
||||
|
||||
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"
|
||||
@REM Check if FILENAME contains "-tft-" and set target partitionScheme accordingly.
|
||||
@REM https://github.com/meshtastic/web-flasher/blob/main/types/resources.ts#L3
|
||||
IF NOT "!FILENAME:-tft-=!"=="!FILENAME!" (
|
||||
CALL :LOG_MESSAGE DEBUG "We are working with a *-tft-* file. !FILENAME!"
|
||||
IF %WEB_APP% EQU 1 (
|
||||
CALL :LOG_MESSAGE ERROR "Cannot enable WebUI (--web) and MUI." & GOTO eof
|
||||
)
|
||||
SET "TFT_BUILD=1"
|
||||
GOTO tft
|
||||
) ELSE (
|
||||
@REM Everything else
|
||||
SET "OTA_FILENAME=bleota.bin"
|
||||
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *-tft-* file. !FILENAME!"
|
||||
GOTO no_tft
|
||||
)
|
||||
|
||||
:tft
|
||||
SET "TFT8MB=picomputer-s3 unphone seeed-sensecap-indicator"
|
||||
FOR %%a IN (%TFT8MB%) DO (
|
||||
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
||||
@REM We are working with any of %TFT8MB%.
|
||||
SET "TFT8=1"
|
||||
GOTO end_loop_tft8mb
|
||||
)
|
||||
)
|
||||
:end_loop_tft8mb
|
||||
|
||||
SET "TFT16MB=t-deck"
|
||||
FOR %%a IN (%TFT16MB%) DO (
|
||||
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
||||
@REM We are working with any of %TFT16MB%.
|
||||
SET "TFT16=1"
|
||||
GOTO end_loop_tft16mb
|
||||
)
|
||||
)
|
||||
:end_loop_tft16mb
|
||||
|
||||
IF %TFT8% EQU 1 CALL :LOG_MESSAGE INFO "tft and MUI 8mb selected."
|
||||
IF %TFT16% EQU 1 CALL :LOG_MESSAGE INFO "tft and MUI 16mb selected."
|
||||
|
||||
:no_tft
|
||||
|
||||
@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.
|
||||
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
|
||||
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
|
||||
)
|
||||
)
|
||||
|
||||
SET "C3=esp32c3"
|
||||
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!"
|
||||
|
||||
@REM Set SPIFFS filename with "littlefs-" prefix.
|
||||
SET "SPIFFS_FILENAME=littlefs-!PROGNAME:firmware-=!.bin"
|
||||
@REM Check if (--web) is enabled and prefix BASENAME with "littlefswebui-" else "littlefs-".
|
||||
IF %WEB_APP% EQU 1 (
|
||||
CALL :LOG_MESSAGE INFO "WebUI selected."
|
||||
SET "SPIFFS_FILENAME=littlefswebui-%BASENAME%"
|
||||
) ELSE (
|
||||
SET "SPIFFS_FILENAME=littlefs-%BASENAME%"
|
||||
)
|
||||
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 MUI 8mb.
|
||||
IF %TFT8% EQU 1 IF %TFT_BUILD% EQU 1 (
|
||||
SET "OTA_OFFSET=0x340000"
|
||||
SET "SPIFFS_OFFSET=0x670000"
|
||||
)
|
||||
|
||||
@REM Offsets for MUI 16mb.
|
||||
IF %TFT16% EQU 1 IF %TFT_BUILD% 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 SPIFFS_OFFSET to: !SPIFFS_OFFSET!"
|
||||
|
||||
@@ -207,7 +255,6 @@ EXIT /B %ERRORLEVEL%
|
||||
IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||
CALL :RESET_ERROR
|
||||
!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4
|
||||
IF %BPS_RESET% EQU 1 GOTO :eof
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||
EXIT /B %ERRORLEVEL%
|
||||
|
||||
@@ -1,159 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
|
||||
BPS_RESET=false
|
||||
MCU=""
|
||||
|
||||
# Constants
|
||||
RESET_BAUD=1200
|
||||
FIRMWARE_OFFSET=0x00
|
||||
# Default littlefs* offset.
|
||||
OFFSET=0x300000
|
||||
# Default OTA Offset
|
||||
OTA_OFFSET=0x260000
|
||||
WEB_APP=false
|
||||
TFT8=false
|
||||
TFT16=false
|
||||
TFT_BUILD=false
|
||||
|
||||
# Determine the correct esptool command to use
|
||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="$PYTHON -m esptool"
|
||||
ESPTOOL_CMD="$PYTHON -m esptool"
|
||||
elif command -v esptool >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="esptool"
|
||||
ESPTOOL_CMD="esptool"
|
||||
elif command -v esptool.py >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="esptool.py"
|
||||
ESPTOOL_CMD="esptool.py"
|
||||
else
|
||||
echo "Error: esptool not found"
|
||||
exit 1
|
||||
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
|
||||
echo "Error: esptool not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME] [--1200bps-reset]
|
||||
cat <<EOF
|
||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME] [--web]
|
||||
Flash image file to device, but first erasing and writing system information.
|
||||
|
||||
-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 PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-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)
|
||||
-f FILENAME The firmware .bin file to flash. Custom to your device type and region.
|
||||
--web Enable WebUI. (Default: false)
|
||||
|
||||
EOF
|
||||
}
|
||||
# Parse arguments using a single while loop
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-p)
|
||||
ESPTOOL_CMD="$ESPTOOL_CMD --port $2"
|
||||
shift
|
||||
;;
|
||||
-P)
|
||||
PYTHON="$2"
|
||||
shift
|
||||
;;
|
||||
-f)
|
||||
FILENAME="$2"
|
||||
shift
|
||||
;;
|
||||
--1200bps-reset)
|
||||
BPS_RESET=true
|
||||
;;
|
||||
--) # Stop parsing options
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift # Move to the next argument
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-p)
|
||||
ESPTOOL_PORT="$2"
|
||||
shift # Shift past the option argument
|
||||
;;
|
||||
-P)
|
||||
PYTHON="$2"
|
||||
shift
|
||||
;;
|
||||
-f)
|
||||
FILENAME="$2"
|
||||
shift
|
||||
;;
|
||||
--web)
|
||||
WEB_APP=true
|
||||
;;
|
||||
--) # Stop parsing options
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift # Move to the next argument
|
||||
done
|
||||
|
||||
if [[ $BPS_RESET == true ]]; then
|
||||
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset read_flash_status
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -z "$FILENAME" ] && [ -n "$1" ] && {
|
||||
FILENAME="$1"
|
||||
shift
|
||||
[ -z "$FILENAME" -a -n "$1" ] && {
|
||||
FILENAME=$1
|
||||
shift
|
||||
}
|
||||
|
||||
if [[ $(basename "$FILENAME") != firmware-*.factory.bin ]]; then
|
||||
echo "Filename must be a firmware-*.factory.bin file."
|
||||
if [[ $FILENAME != firmware-* ]]; then
|
||||
echo "Filename must be a firmware-* file."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract PROGNAME from %FILENAME% for later use.
|
||||
PROGNAME="${FILENAME/.factory.bin/}"
|
||||
# Derive metadata filename from %PROGNAME%.
|
||||
METAFILE="${PROGNAME}.mt.json"
|
||||
# Check if FILENAME contains "-tft-" and set target partitionScheme accordingly.
|
||||
if [[ ${FILENAME//-tft-/} != "$FILENAME" ]]; then
|
||||
TFT_BUILD=true
|
||||
if [[ $WEB_APP == true ]] && [[ $TFT_BUILD == true ]]; then
|
||||
echo "Cannot enable WebUI (--web) and MUI."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -f "$FILENAME" && "$FILENAME" == *.factory.bin ]]; then
|
||||
# Display metadata if it exists
|
||||
if [[ -f "$METAFILE" ]]; then
|
||||
echo "Firmware metadata: ${METAFILE}"
|
||||
jq . "$METAFILE"
|
||||
# Extract relevant fields from metadata
|
||||
if [[ $(jq -r '.part' "$METAFILE") != "null" ]]; then
|
||||
OTA_OFFSET=$(jq -r '.part[] | select(.subtype == "ota_1") | .offset' "$METAFILE")
|
||||
SPIFFS_OFFSET=$(jq -r '.part[] | select(.subtype == "spiffs") | .offset' "$METAFILE")
|
||||
fi
|
||||
MCU=$(jq -r '.mcu' "$METAFILE")
|
||||
else
|
||||
echo "ERROR: No metadata file found at ${METAFILE}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $FILENAME == *"picomputer-s3"* || $FILENAME == *"unphone"* || $FILENAME == *"seeed-sensecap-indicator"* ]]; then
|
||||
TFT8=true
|
||||
fi
|
||||
|
||||
# Determine OTA filename based on MCU type
|
||||
if [ "$MCU" == "esp32s3" ]; then
|
||||
OTAFILE=bleota-s3.bin
|
||||
elif [ "$MCU" == "esp32c3" ]; then
|
||||
OTAFILE=bleota-c3.bin
|
||||
else
|
||||
OTAFILE=bleota.bin
|
||||
fi
|
||||
if [[ $FILENAME == *"t-deck"* ]]; then
|
||||
TFT16=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set SPIFFS filename with "littlefs-" prefix.
|
||||
SPIFFSFILE="littlefs-${PROGNAME/firmware-/}.bin"
|
||||
# Extract BASENAME from %FILENAME% for later use.
|
||||
BASENAME="${FILENAME/firmware-/}"
|
||||
|
||||
if [[ ! -f "$FILENAME" ]]; then
|
||||
echo "Error: file ${FILENAME} wasn't found. Terminating."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$OTAFILE" ]]; then
|
||||
echo "Error: file ${OTAFILE} wasn't found. Terminating."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$SPIFFSFILE" ]]; then
|
||||
echo "Error: file ${SPIFFSFILE} wasn't found. Terminating."
|
||||
exit 1
|
||||
fi
|
||||
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
||||
# Default littlefs* offset (--web).
|
||||
OFFSET=0x300000
|
||||
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
$ESPTOOL_CMD erase-flash
|
||||
$ESPTOOL_CMD write-flash $FIRMWARE_OFFSET "${FILENAME}"
|
||||
echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
|
||||
$ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
|
||||
echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
|
||||
$ESPTOOL_CMD write_flash $OFFSET "${SPIFFSFILE}"
|
||||
# Default OTA Offset
|
||||
OTA_OFFSET=0x260000
|
||||
|
||||
# littlefs* offset for MUI 8mb and OTA OFFSET.
|
||||
if [ "$TFT8" = true ] && [ "$TFT_BUILD" = true ]; then
|
||||
OFFSET=0x670000
|
||||
OTA_OFFSET=0x340000
|
||||
fi
|
||||
|
||||
# littlefs* offset for MUI 16mb and OTA OFFSET.
|
||||
if [ "$TFT16" = true ] && [ "$TFT_BUILD" = true ]; then
|
||||
OFFSET=0xc90000
|
||||
OTA_OFFSET=0x650000
|
||||
fi
|
||||
|
||||
# Account for S3 board's different OTA partition
|
||||
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then
|
||||
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
|
||||
OTAFILE=bleota.bin
|
||||
else
|
||||
OTAFILE=bleota-c3.bin
|
||||
fi
|
||||
else
|
||||
OTAFILE=bleota-s3.bin
|
||||
fi
|
||||
|
||||
# Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-".
|
||||
if [ "$WEB_APP" = true ]; then
|
||||
SPIFFSFILE=littlefswebui-${BASENAME}
|
||||
else
|
||||
SPIFFSFILE=littlefs-${BASENAME}
|
||||
fi
|
||||
|
||||
if [[ ! -f $FILENAME ]]; then
|
||||
echo "Error: file ${FILENAME} wasn't found. Terminating."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f $OTAFILE ]]; then
|
||||
echo "Error: file ${OTAFILE} wasn't found. Terminating."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f $SPIFFSFILE ]]; then
|
||||
echo "Error: file ${SPIFFSFILE} wasn't found. Terminating."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
$ESPTOOL_CMD erase_flash
|
||||
$ESPTOOL_CMD write_flash 0x00 "${FILENAME}"
|
||||
echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
|
||||
$ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
|
||||
echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
|
||||
$ESPTOOL_CMD write_flash $OFFSET "${SPIFFSFILE}"
|
||||
|
||||
else
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -6,35 +6,29 @@ SET "SCRIPT_NAME=%~nx0"
|
||||
SET "DEBUG=0"
|
||||
SET "PYTHON="
|
||||
SET "ESPTOOL_BAUD=115200"
|
||||
SET "RESET_BAUD=1200"
|
||||
SET "UPDATE_OFFSET=0x10000"
|
||||
SET "ESPTOOL_CMD="
|
||||
SET "LOGCOUNTER=0"
|
||||
SET "CHANGE_MODE=0"
|
||||
|
||||
GOTO getopts
|
||||
:help
|
||||
ECHO Flash image file to device, but leave existing system intact.
|
||||
ECHO.
|
||||
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] [--change-mode]
|
||||
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python]
|
||||
ECHO.
|
||||
ECHO Options:
|
||||
ECHO -f filename The update .bin file to flash. Custom to your device type and region. (required)
|
||||
ECHO -f filename The .bin file to flash. Custom to your device type and region. (required)
|
||||
ECHO The file must be located in this current directory.
|
||||
ECHO -p PORT Set the environment variable for ESPTOOL_PORT.
|
||||
ECHO If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
ECHO -P python Specify alternate python interpreter to use to invoke esptool. (default: python)
|
||||
ECHO If supplied the script will use python.
|
||||
ECHO If not supplied the script will try to find esptool in Path.
|
||||
ECHO --change-mode Attempt to place the device in correct mode. (1200bps Reset)
|
||||
ECHO Some hardware requires this twice.
|
||||
ECHO.
|
||||
ECHO Example: %SCRIPT_NAME% -p COM17 --change-mode
|
||||
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-update.bin -p COM11
|
||||
GOTO eof
|
||||
|
||||
:version
|
||||
ECHO %SCRIPT_NAME% [Version 2.7.0]
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.0]
|
||||
ECHO Meshtastic
|
||||
GOTO eof
|
||||
|
||||
@@ -50,19 +44,15 @@ IF /I "%~1"=="-f" SET "FILENAME=%~2" & SHIFT
|
||||
IF "%~1"=="-p" SET "ESPTOOL_PORT=%~2" & SHIFT
|
||||
IF /I "%~1"=="--port" SET "ESPTOOL_PORT=%~2" & SHIFT
|
||||
IF "%~1"=="-P" SET "PYTHON=%~2" & SHIFT
|
||||
IF /I "%~1"=="--change-mode" SET "CHANGE_MODE=1"
|
||||
SHIFT
|
||||
GOTO getopts
|
||||
:endopts
|
||||
|
||||
IF %CHANGE_MODE% EQU 1 GOTO skip-filename
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..."
|
||||
IF "__!FILENAME!__"=="____" (
|
||||
CALL :LOG_MESSAGE DEBUG "Missing -f filename input."
|
||||
GOTO help
|
||||
) ELSE (
|
||||
CALL :LOG_MESSAGE DEBUG "Filename: !FILENAME!"
|
||||
IF NOT "__!FILENAME: =!__"=="__!FILENAME!__" (
|
||||
CALL :LOG_MESSAGE ERROR "Filename containing spaces are not supported."
|
||||
GOTO help
|
||||
@@ -72,28 +62,27 @@ IF "__!FILENAME!__"=="____" (
|
||||
SET "FILENAME=!FILENAME:./=!"
|
||||
)
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Filename: !FILENAME!"
|
||||
CALL :LOG_MESSAGE DEBUG "Checking if !FILENAME! exists..."
|
||||
IF NOT EXIST !FILENAME! (
|
||||
CALL :LOG_MESSAGE ERROR "File does not exist: !FILENAME!. Terminating."
|
||||
GOTO eof
|
||||
)
|
||||
|
||||
IF NOT "__!FILENAME:.factory.bin=!__"=="__!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!."
|
||||
IF "!FILENAME:update=!"=="!FILENAME!" (
|
||||
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!"
|
||||
CALL :LOG_MESSAGE INFO "Use script device-install.bat to flash update !FILENAME!."
|
||||
GOTO eof
|
||||
) ELSE (
|
||||
CALL :LOG_MESSAGE DEBUG "We are not working with a *.factory.bin* file. !FILENAME!"
|
||||
CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!"
|
||||
)
|
||||
|
||||
:skip-filename
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
|
||||
IF NOT "__%PYTHON%__"=="____" (
|
||||
SET "ESPTOOL_CMD=""!PYTHON!"" -m esptool"
|
||||
SET "ESPTOOL_CMD=!PYTHON! -m esptool"
|
||||
CALL :LOG_MESSAGE DEBUG "Python interpreter supplied."
|
||||
) 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
|
||||
IF %ERRORLEVEL% EQU 0 (
|
||||
@REM WHERE exits with code 0 if esptool is found.
|
||||
@@ -106,11 +95,11 @@ IF NOT "__%PYTHON%__"=="____" (
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
||||
!ESPTOOL_CMD! >nul 2>&1
|
||||
CALL :LOG_MESSAGE DEBUG "esptool exit code: %ERRORLEVEL%"
|
||||
IF %ERRORLEVEL% EQU 9009 (
|
||||
@REM 9009 = command not found on Windows
|
||||
IF %ERRORLEVEL% GTR 2 (
|
||||
@REM esptool exits with code 1 if help is displayed.
|
||||
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
||||
EXIT /B 1
|
||||
GOTO eof
|
||||
)
|
||||
IF %DEBUG% EQU 1 (
|
||||
CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps."
|
||||
@@ -121,20 +110,13 @@ CALL :LOG_MESSAGE DEBUG "Using esptool command: !ESPTOOL_CMD!"
|
||||
IF "__!ESPTOOL_PORT!__" == "____" (
|
||||
CALL :LOG_MESSAGE WARN "Using esptool port: UNSET."
|
||||
) ELSE (
|
||||
SET "ESPTOOL_CMD=!ESPTOOL_CMD! --port !ESPTOOL_PORT!"
|
||||
CALL :LOG_MESSAGE INFO "Using esptool port: !ESPTOOL_PORT!."
|
||||
)
|
||||
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
|
||||
|
||||
IF %CHANGE_MODE% EQU 1 (
|
||||
@REM Attempt to change mode via 1200bps Reset.
|
||||
CALL :RUN_ESPTOOL !RESET_BAUD! --after no_reset read_flash_status
|
||||
GOTO eof
|
||||
)
|
||||
|
||||
@REM Flashing operations.
|
||||
CALL :LOG_MESSAGE INFO "Trying to flash update "!FILENAME!" at OFFSET !UPDATE_OFFSET!..."
|
||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write-flash !UPDATE_OFFSET! "!FILENAME!" || GOTO eof
|
||||
CALL :LOG_MESSAGE INFO "Trying to flash update "!FILENAME!" at OFFSET 0x10000..."
|
||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write_flash 0x10000 "!FILENAME!" || GOTO eof
|
||||
|
||||
CALL :LOG_MESSAGE INFO "Script complete!."
|
||||
|
||||
@@ -146,13 +128,12 @@ EXIT /B %ERRORLEVEL%
|
||||
:RUN_ESPTOOL
|
||||
@REM Subroutine used to run ESPTOOL_CMD with arguments.
|
||||
@REM Also handles %ERRORLEVEL%.
|
||||
@REM CALL :RUN_ESPTOOL [Baud] [erase-flash|write-flash] [OFFSET] [Filename]
|
||||
@REM CALL :RUN_ESPTOOL [Baud] [erase_flash|write_flash] [OFFSET] [Filename]
|
||||
@REM.
|
||||
@REM Example:: CALL :RUN_ESPTOOL 115200 write-flash 0x10000 "firmwarefile.bin"
|
||||
@REM Example:: CALL :RUN_ESPTOOL 115200 write_flash 0x10000 "firmwarefile.bin"
|
||||
IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||
CALL :RESET_ERROR
|
||||
!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4
|
||||
IF %CHANGE_MODE% EQU 1 GOTO :eof
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||
EXIT /B %ERRORLEVEL%
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
|
||||
CHANGE_MODE=false
|
||||
|
||||
# Constants
|
||||
FLASH_BAUD=115200
|
||||
RESET_BAUD=1200
|
||||
UPDATE_OFFSET=0x10000
|
||||
|
||||
# Determine the correct esptool command to use
|
||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||
@@ -23,29 +17,17 @@ fi
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Usage: $(basename "$0") [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--change-mode]
|
||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
|
||||
Flash image file to device, leave existing system intact."
|
||||
|
||||
-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 PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-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)
|
||||
|
||||
-f FILENAME The *update.bin file to flash. Custom to your device type.
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Check for --change-mode and remove it from arguments
|
||||
NEW_ARGS=()
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" = "--change-mode" ]; then
|
||||
CHANGE_MODE=true
|
||||
else
|
||||
NEW_ARGS+=("$arg")
|
||||
fi
|
||||
done
|
||||
|
||||
set -- "${NEW_ARGS[@]}"
|
||||
|
||||
while getopts ":hp:P:f:" opt; do
|
||||
case "${opt}" in
|
||||
@@ -53,14 +35,14 @@ while getopts ":hp:P:f:" opt; do
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
p) ESPTOOL_CMD="$ESPTOOL_CMD --port ${OPTARG}"
|
||||
;;
|
||||
p) export ESPTOOL_PORT=${OPTARG}
|
||||
;;
|
||||
P) PYTHON=${OPTARG}
|
||||
;;
|
||||
f) FILENAME=${OPTARG}
|
||||
;;
|
||||
*)
|
||||
echo "Invalid flag."
|
||||
echo "Invalid flag."
|
||||
show_help >&2
|
||||
exit 1
|
||||
;;
|
||||
@@ -68,22 +50,17 @@ while getopts ":hp:P:f:" opt; do
|
||||
done
|
||||
shift "$((OPTIND-1))"
|
||||
|
||||
if [ "$CHANGE_MODE" = true ]; then
|
||||
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset read_flash_status
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -z "$FILENAME" ] && [ -n "$1" ] && {
|
||||
FILENAME="$1"
|
||||
[ -z "$FILENAME" -a -n "$1" ] && {
|
||||
FILENAME=$1
|
||||
shift
|
||||
}
|
||||
|
||||
if [[ -f "$FILENAME" && "$FILENAME" != *.factory.bin ]]; then
|
||||
echo "Trying to flash update ${FILENAME}"
|
||||
$ESPTOOL_CMD --baud $FLASH_BAUD write-flash $UPDATE_OFFSET "${FILENAME}"
|
||||
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
|
||||
printf "Trying to flash update ${FILENAME}"
|
||||
$ESPTOOL_CMD --baud 115200 write_flash 0x10000 ${FILENAME}
|
||||
else
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -75,7 +75,7 @@ TOOLS = {
|
||||
}
|
||||
|
||||
BACKTRACE_REGEX = re.compile(
|
||||
r"\b(0x4[0-9a-fA-F]{7,8}):0x[0-9a-fA-F]{8}\b"
|
||||
r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b"
|
||||
)
|
||||
EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
|
||||
COUNTER_REGEX = re.compile(
|
||||
@@ -89,7 +89,7 @@ POINTER_REGEX = re.compile(
|
||||
STACK_BEGIN = ">>>stack>>>"
|
||||
STACK_END = "<<<stack<<<"
|
||||
STACK_REGEX = re.compile(
|
||||
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.*)?$"
|
||||
"^(?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"])
|
||||
@@ -223,7 +223,7 @@ class AddressResolver(object):
|
||||
if match is None:
|
||||
if last is not None and line.startswith("(inlined by)"):
|
||||
line = line[12:].strip()
|
||||
self._address_map[last] += "\n \\-> inlined by: " + line
|
||||
self._address_map[last] += "\n \-> inlined by: " + line
|
||||
continue
|
||||
|
||||
if match.group("result") == "?? ??:0":
|
||||
|
||||
@@ -1,75 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Generate the CI matrix."""
|
||||
|
||||
import argparse
|
||||
import configparser
|
||||
import json
|
||||
import re
|
||||
from platformio.project.config import ProjectConfig
|
||||
import os
|
||||
import sys
|
||||
import random
|
||||
|
||||
parser = argparse.ArgumentParser(description="Generate the CI matrix")
|
||||
parser.add_argument("platform", help="Platform to build for")
|
||||
parser.add_argument(
|
||||
"--level",
|
||||
choices=["extra", "pr"],
|
||||
nargs="*",
|
||||
default=[],
|
||||
help="Board level to build for (omit for full release boards)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
rootdir = "variants/"
|
||||
|
||||
options = sys.argv[1:]
|
||||
|
||||
outlist = []
|
||||
|
||||
cfg = ProjectConfig.get_instance()
|
||||
pio_envs = cfg.envs()
|
||||
if len(options) < 1:
|
||||
print(json.dumps(outlist))
|
||||
exit()
|
||||
|
||||
# Gather all PlatformIO environments for filtering later
|
||||
all_envs = []
|
||||
for pio_env in pio_envs:
|
||||
env_build_flags = cfg.get(f"env:{pio_env}", "build_flags")
|
||||
env_platform = None
|
||||
for flag in env_build_flags:
|
||||
# Extract the platform from the build flags
|
||||
# Example flag: -I variants/esp32s3/heltec-v3
|
||||
match = re.search(r"-I\s?variants/([^/]+)", flag)
|
||||
if match:
|
||||
env_platform = match.group(1)
|
||||
break
|
||||
# Intentionally fail if platform cannot be determined
|
||||
if not env_platform:
|
||||
print(f"Error: Could not determine platform for environment '{pio_env}'")
|
||||
exit(1)
|
||||
# Store env details as a dictionary, and add to 'all_envs' list
|
||||
env = {
|
||||
"ci": {"board": pio_env, "platform": env_platform},
|
||||
"board_level": cfg.get(f"env:{pio_env}", "board_level", default=None),
|
||||
"board_check": bool(cfg.get(f"env:{pio_env}", "board_check", default=False)),
|
||||
}
|
||||
all_envs.append(env)
|
||||
|
||||
# Filter outputs based on options
|
||||
# Check is mutually exclusive with other options (except 'pr')
|
||||
if "check" in args.platform:
|
||||
for env in all_envs:
|
||||
if env["board_check"]:
|
||||
if "pr" in args.level:
|
||||
if env["board_level"] == "pr":
|
||||
outlist.append(env["ci"])
|
||||
else:
|
||||
outlist.append(env["ci"])
|
||||
# Filter (non-check) builds by platform
|
||||
for subdir, dirs, files in os.walk(rootdir):
|
||||
for file in files:
|
||||
if file == "platformio.ini":
|
||||
config = configparser.ConfigParser()
|
||||
config.read(subdir + "/" + file)
|
||||
for c in config.sections():
|
||||
if c.startswith("env:"):
|
||||
section = config[c].name[4:]
|
||||
if "extends" in config[config[c].name]:
|
||||
if config[config[c].name]["extends"] == options[0] + "_base":
|
||||
if "board_level" in config[config[c].name]:
|
||||
if (
|
||||
config[config[c].name]["board_level"] == "extra"
|
||||
) & ("extra" in options):
|
||||
outlist.append(section)
|
||||
else:
|
||||
outlist.append(section)
|
||||
# Add the TFT variants if the base variant is selected
|
||||
elif section.replace("-tft", "") in outlist and config[config[c].name].get("board_level") != "extra":
|
||||
outlist.append(section)
|
||||
elif section.replace("-inkhud", "") in outlist and config[config[c].name].get("board_level") != "extra":
|
||||
outlist.append(section)
|
||||
if "board_check" in config[config[c].name]:
|
||||
if (config[config[c].name]["board_check"] == "true") & (
|
||||
"check" in options
|
||||
):
|
||||
outlist.append(section)
|
||||
if ("quick" in options) & (len(outlist) > 3):
|
||||
print(json.dumps(random.sample(outlist, 3)))
|
||||
else:
|
||||
for env in all_envs:
|
||||
if args.platform == env["ci"]["platform"] or args.platform == "all":
|
||||
# Always include board_level = 'pr'
|
||||
if env["board_level"] == "pr":
|
||||
outlist.append(env["ci"])
|
||||
# Include board_level = 'extra' when requested
|
||||
elif "extra" in args.level and env["board_level"] == "extra":
|
||||
outlist.append(env["ci"])
|
||||
# If no board level is specified, include in release builds (not PR)
|
||||
elif "pr" not in args.level and not env["board_level"]:
|
||||
outlist.append(env["ci"])
|
||||
|
||||
# Return as a JSON list
|
||||
print(json.dumps(outlist))
|
||||
print(json.dumps(outlist))
|
||||
@@ -1,116 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to cancel all running GitHub Actions workflows
|
||||
# Requires GitHub CLI (gh) to be installed and authenticated
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Check if gh CLI is installed
|
||||
if ! command -v gh &> /dev/null; then
|
||||
print_error "GitHub CLI (gh) is not installed. Please install it first:"
|
||||
echo " brew install gh"
|
||||
echo " Or visit: https://cli.github.com/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if authenticated
|
||||
if ! gh auth status &> /dev/null; then
|
||||
print_error "GitHub CLI is not authenticated. Please run:"
|
||||
echo " gh auth login"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get repository info
|
||||
REPO=$(gh repo view --json owner,name -q '.owner.login + "/" + .name')
|
||||
if [[ -z "$REPO" ]]; then
|
||||
print_error "Could not determine repository. Make sure you're in a GitHub repository."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Working with repository: $REPO"
|
||||
|
||||
# Get all active workflows (both queued and in-progress)
|
||||
print_status "Fetching active workflows (queued and in-progress)..."
|
||||
QUEUED_WORKFLOWS=$(gh run list --status queued --json databaseId,displayTitle,headBranch,status --limit 100)
|
||||
IN_PROGRESS_WORKFLOWS=$(gh run list --status in_progress --json databaseId,displayTitle,headBranch,status --limit 100)
|
||||
|
||||
# Combine both lists
|
||||
ALL_WORKFLOWS=$(echo "$QUEUED_WORKFLOWS $IN_PROGRESS_WORKFLOWS" | jq -s 'add | unique_by(.databaseId)')
|
||||
|
||||
if [[ "$ALL_WORKFLOWS" == "[]" ]]; then
|
||||
print_status "No active workflows found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Parse and display active workflows
|
||||
echo
|
||||
print_warning "Found active workflows:"
|
||||
echo "$ALL_WORKFLOWS" | jq -r '.[] | " - \(.displayTitle) (Branch: \(.headBranch), Status: \(.status), ID: \(.databaseId))"'
|
||||
|
||||
echo
|
||||
read -p "Do you want to cancel ALL these workflows? (y/N): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_status "Cancelled by user."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Cancel each workflow
|
||||
print_status "Cancelling workflows..."
|
||||
CANCELLED_COUNT=0
|
||||
FAILED_COUNT=0
|
||||
|
||||
while IFS= read -r WORKFLOW_ID; do
|
||||
if [[ -n "$WORKFLOW_ID" ]]; then
|
||||
print_status "Cancelling workflow ID: $WORKFLOW_ID"
|
||||
if gh run cancel "$WORKFLOW_ID" 2>/dev/null; then
|
||||
((CANCELLED_COUNT++))
|
||||
else
|
||||
print_error "Failed to cancel workflow ID: $WORKFLOW_ID"
|
||||
((FAILED_COUNT++))
|
||||
fi
|
||||
fi
|
||||
done < <(echo "$ALL_WORKFLOWS" | jq -r '.[].databaseId')
|
||||
|
||||
echo
|
||||
print_status "Summary:"
|
||||
echo " - Cancelled: $CANCELLED_COUNT workflows"
|
||||
if [[ $FAILED_COUNT -gt 0 ]]; then
|
||||
echo " - Failed: $FAILED_COUNT workflows"
|
||||
fi
|
||||
|
||||
print_status "Done!"
|
||||
|
||||
# Optional: Show remaining active workflows
|
||||
echo
|
||||
print_status "Checking for any remaining active workflows..."
|
||||
REMAINING_QUEUED=$(gh run list --status queued --json databaseId --limit 10)
|
||||
REMAINING_IN_PROGRESS=$(gh run list --status in_progress --json databaseId --limit 10)
|
||||
REMAINING_ALL=$(echo "$REMAINING_QUEUED $REMAINING_IN_PROGRESS" | jq -s 'add | unique_by(.databaseId)')
|
||||
|
||||
if [[ "$REMAINING_ALL" == "[]" ]]; then
|
||||
print_status "All workflows successfully cancelled."
|
||||
else
|
||||
REMAINING_COUNT=$(echo "$REMAINING_ALL" | jq '. | length')
|
||||
print_warning "Still $REMAINING_COUNT workflows active (may take a moment to update status)"
|
||||
fi
|
||||
@@ -5,11 +5,10 @@ StartLimitInterval=200
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
User=meshtasticd
|
||||
Group=meshtasticd
|
||||
User=root
|
||||
Group=root
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/meshtasticd
|
||||
ExecStart=/usr/sbin/meshtasticd
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
set -e
|
||||
pio run --environment native
|
||||
gdbserver --once localhost:2345 .pio/build/native/meshtasticd "$@"
|
||||
gdbserver --once localhost:2345 .pio/build/native/program "$@"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cp "release/meshtasticd_linux_$(uname -m)" /usr/bin/meshtasticd
|
||||
cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd
|
||||
mkdir -p /etc/meshtasticd
|
||||
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
|
||||
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
set -e
|
||||
pio run --environment native
|
||||
.pio/build/native/meshtasticd "$@"
|
||||
.pio/build/native/program "$@"
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Meshtastic
|
||||
Comment=Meshtastic App
|
||||
Exec=meshtasticd
|
||||
Icon=org.meshtastic.meshtasticd
|
||||
Terminal=true
|
||||
Type=Application
|
||||
Categories=Network;Chat;HamRadio;
|
||||
@@ -1,175 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<component type="desktop-application">
|
||||
<id>org.meshtastic.meshtasticd</id>
|
||||
|
||||
<name>Meshtastic</name>
|
||||
<summary>Decentralized mesh communication</summary>
|
||||
|
||||
<metadata_license>CC-BY-4.0</metadata_license>
|
||||
<project_license>GPL-3.0-or-later</project_license>
|
||||
|
||||
<developer id="org.meshtastic">
|
||||
<name>Meshtastic</name>
|
||||
</developer>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
Meshtastic is an open source project for creating off-grid, affordable, and resilient communication with LoRa mesh networks.
|
||||
</p>
|
||||
</description>
|
||||
|
||||
<launchable type="desktop-id">org.meshtastic.meshtasticd.desktop</launchable>
|
||||
|
||||
<categories>
|
||||
<category>Network</category>
|
||||
<category>Chat</category>
|
||||
<category>HamRadio</category>
|
||||
</categories>
|
||||
<keywords>
|
||||
<keyword>mesh</keyword>
|
||||
<keyword>LoRa</keyword>
|
||||
</keywords>
|
||||
|
||||
<recommends>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
<control>touch</control>
|
||||
</recommends>
|
||||
<requires>
|
||||
<display_length compare="ge">360</display_length>
|
||||
</requires>
|
||||
|
||||
<branding>
|
||||
<color type="primary" scheme_preference="light">#97be89</color>
|
||||
<color type="primary" scheme_preference="dark">#206538</color>
|
||||
</branding>
|
||||
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
<content_attribute id="social-location">intense</content_attribute>
|
||||
</content_rating>
|
||||
|
||||
<url type="bugtracker">https://github.com/meshtastic/firmware/issues</url>
|
||||
<url type="homepage">https://meshtastic.org/</url>
|
||||
<url type="donation">https://opencollective.com/meshtastic</url>
|
||||
<url type="faq">https://meshtastic.org/docs/software/linux/usage/</url>
|
||||
<url type="vcs-browser">https://github.com/meshtastic/firmware/</url>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_home_dashboard_dark.webp</image>
|
||||
<caption>Home Dashboard</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_initial_boot.webp</image>
|
||||
<caption>Setup</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_node_list_dark.webp</image>
|
||||
<caption>Nodes List</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_chat_list_dark.webp</image>
|
||||
<caption>Chats List</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_chat_message_dark.webp</image>
|
||||
<caption>Messages</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_map_dark.webp</image>
|
||||
<caption>Map</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_settings_dark.webp</image>
|
||||
<caption>Settings</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.7.17" date="2025-11-28">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.17</url>
|
||||
</release>
|
||||
<release version="2.7.16" date="2025-11-19">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.16</url>
|
||||
</release>
|
||||
<release version="2.7.15" date="2025-11-13">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.15</url>
|
||||
</release>
|
||||
<release version="2.7.14" date="2025-11-03">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.14</url>
|
||||
</release>
|
||||
<release version="2.7.13" date="2025-10-11">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.13</url>
|
||||
</release>
|
||||
<release version="2.7.12" date="2025-10-01">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.12</url>
|
||||
</release>
|
||||
<release version="2.7.11" date="2025-09-24">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.11</url>
|
||||
</release>
|
||||
<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">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.9</url>
|
||||
</release>
|
||||
<release version="2.7.8" date="2025-08-30">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.8</url>
|
||||
</release>
|
||||
<release version="2.7.7" date="2025-08-28">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.7</url>
|
||||
</release>
|
||||
<release version="2.7.6" date="2025-08-12">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.6</url>
|
||||
</release>
|
||||
<release version="2.7.5" date="2025-08-09">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.5</url>
|
||||
</release>
|
||||
<release version="2.7.4" date="2025-07-19">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.4</url>
|
||||
</release>
|
||||
<release version="2.7.3" date="2025-07-10">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.3</url>
|
||||
</release>
|
||||
<release version="2.7.2" date="2025-07-04">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.2</url>
|
||||
</release>
|
||||
<release version="2.7.1" date="2025-06-27">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.1</url>
|
||||
</release>
|
||||
<release version="2.7.0" date="2025-06-20">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.0</url>
|
||||
</release>
|
||||
<release version="2.6.13" date="2025-06-16">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.13</url>
|
||||
</release>
|
||||
<release version="2.6.12" date="2025-06-15">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.12</url>
|
||||
</release>
|
||||
<release version="2.6.11" date="2025-06-02">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.11</url>
|
||||
</release>
|
||||
<release version="2.6.10" date="2025-05-25">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.10</url>
|
||||
</release>
|
||||
<release version="2.6.9" date="2025-05-15">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.9</url>
|
||||
</release>
|
||||
<release version="2.6.8" date="2025-05-05">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.8</url>
|
||||
</release>
|
||||
<release version="2.6.7" date="2025-04-28">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.7</url>
|
||||
</release>
|
||||
<release version="2.6.6" date="2025-04-15">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.6</url>
|
||||
</release>
|
||||
<release version="2.6.5" date="2025-03-30">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.5</url>
|
||||
</release>
|
||||
<release version="2.6.4" date="2025-03-28">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.4</url>
|
||||
</release>
|
||||
</releases>
|
||||
</component>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="512" height="512" viewBox="0 0 512 512" xml:space="preserve">
|
||||
<desc>Created with Fabric.js 4.6.0</desc>
|
||||
<defs>
|
||||
</defs>
|
||||
<g transform="matrix(1 0 0 1 256 256)" id="xYQ9Gk9Jwpgj_HMOXB3F_" >
|
||||
<path style="stroke: rgb(213,130,139); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(103,234,148); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-256, -256)" d="M 0 0 L 512 0 L 512 512 L 0 512 z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(1.79 0 0 1.79 313.74 258.36)" id="1xBsk2n9FZp60Rz1O-ceJ" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-250.97, -362.41)" d="M 250.908 330.267 L 193.126 415.005 L 180.938 406.694 L 244.802 313.037 C 246.174 311.024 248.453 309.819 250.889 309.816 C 253.326 309.814 255.606 311.015 256.982 313.026 L 320.994 406.536 L 308.821 414.869 L 250.908 330.267 Z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(1.81 0 0 1.81 145 256.15)" id="KxN7E9YpbyPgz0S4z4Cl6" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-115.14, -528.06)" d="M 87.642 581.398 L 154.757 482.977 L 142.638 474.713 L 75.523 573.134 L 87.642 581.398 Z" stroke-linecap="round" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
@@ -2,88 +2,95 @@
|
||||
# trunk-ignore-all(ruff/F821)
|
||||
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
||||
import sys
|
||||
from os.path import join, basename, isfile
|
||||
import subprocess
|
||||
from os.path import join
|
||||
import json
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
from readprops import readProps
|
||||
|
||||
Import("env")
|
||||
platform = env.PioPlatform()
|
||||
progname = env.get("PROGNAME")
|
||||
lfsbin = f"{progname.replace('firmware-', 'littlefs-')}.bin"
|
||||
|
||||
def manifest_gather(source, target, env):
|
||||
out = []
|
||||
check_paths = [
|
||||
progname,
|
||||
f"{progname}.elf",
|
||||
f"{progname}.bin",
|
||||
f"{progname}.factory.bin",
|
||||
f"{progname}.hex",
|
||||
f"{progname}.merged.hex",
|
||||
f"{progname}.uf2",
|
||||
f"{progname}.factory.uf2",
|
||||
f"{progname}.zip",
|
||||
lfsbin
|
||||
|
||||
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")
|
||||
flash_size = env.BoardConfig().get("upload.flash_size")
|
||||
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)
|
||||
|
||||
def manifest_write(files, env):
|
||||
manifest = {
|
||||
"version": verObj["long"],
|
||||
"build_epoch": build_epoch,
|
||||
"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(" Offset | File")
|
||||
for section in sections:
|
||||
sect_adr, sect_file = section.split(" ", 1)
|
||||
print(f" - {sect_adr} | {sect_file}")
|
||||
cmd += [sect_adr, sect_file]
|
||||
|
||||
# Write the manifest to the build directory
|
||||
with open(env.subst("$BUILD_DIR/${PROGNAME}.mt.json"), "w") as f:
|
||||
json.dump(manifest, f, indent=2)
|
||||
print(f" - {hex(app_offset)} | {firmware_name}")
|
||||
cmd += [hex(app_offset), firmware_name]
|
||||
|
||||
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")
|
||||
|
||||
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
||||
verObj = readProps(prefsLoc)
|
||||
print(f"Using meshtastic platformio-custom.py, firmware version {verObj['long']} on {env.get('PIOENV')}")
|
||||
|
||||
# get repository owner if git is installed
|
||||
try:
|
||||
r_owner = (
|
||||
subprocess.check_output(["git", "config", "--get", "remote.origin.url"])
|
||||
.decode("utf-8")
|
||||
.strip().split("/")
|
||||
)
|
||||
repo_owner = r_owner[-2] + "/" + r_owner[-1].replace(".git", "")
|
||||
except subprocess.CalledProcessError:
|
||||
repo_owner = "unknown"
|
||||
print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"] + " on " + env.get("PIOENV"))
|
||||
|
||||
jsonLoc = env["PROJECT_DIR"] + "/userPrefs.jsonc"
|
||||
with open(jsonLoc) as f:
|
||||
@@ -106,22 +113,16 @@ for pref in userPrefs:
|
||||
pref_flags.append("-D" + pref + "=" + env.StringifyMacro(userPrefs[pref]) + "")
|
||||
|
||||
# General options that are passed to the C and C++ compilers
|
||||
# Calculate unix epoch for current day (midnight)
|
||||
current_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
build_epoch = int(current_date.timestamp())
|
||||
|
||||
flags = [
|
||||
"-DAPP_VERSION=" + verObj["long"],
|
||||
"-DAPP_VERSION_SHORT=" + verObj["short"],
|
||||
"-DAPP_ENV=" + env.get("PIOENV"),
|
||||
"-DAPP_REPO=" + repo_owner,
|
||||
"-DBUILD_EPOCH=" + str(build_epoch),
|
||||
] + pref_flags
|
||||
|
||||
print("Using flags:")
|
||||
print ("Using flags:")
|
||||
for flag in flags:
|
||||
print(flag)
|
||||
|
||||
|
||||
projenv.Append(
|
||||
CCFLAGS=flags,
|
||||
)
|
||||
@@ -130,51 +131,3 @@ for lb in env.GetLibBuilders():
|
||||
if lb.name == "meshtastic-device-ui":
|
||||
lb.env.Append(CPPDEFINES=[("APP_VERSION", verObj["long"])])
|
||||
break
|
||||
|
||||
# Get the display resolution from macros
|
||||
def get_display_resolution(build_flags):
|
||||
# Check "DISPLAY_SIZE" to determine the screen resolution
|
||||
for flag in build_flags:
|
||||
if isinstance(flag, tuple) and flag[0] == "DISPLAY_SIZE":
|
||||
screen_width, screen_height = map(int, flag[1].split("x"))
|
||||
return screen_width, screen_height
|
||||
print("No screen resolution defined in build_flags. Please define DISPLAY_SIZE.")
|
||||
exit(1)
|
||||
|
||||
def load_boot_logo(source, target, env):
|
||||
build_flags = env.get("CPPDEFINES", [])
|
||||
logo_w, logo_h = get_display_resolution(build_flags)
|
||||
print(f"TFT build with {logo_w}x{logo_h} resolution detected")
|
||||
|
||||
# Load the boot logo from `branding/logo_<width>x<height>.png` if it exists
|
||||
source_path = join(env["PROJECT_DIR"], "branding", f"logo_{logo_w}x{logo_h}.png")
|
||||
dest_dir = join(env["PROJECT_DIR"], "data", "boot")
|
||||
dest_path = join(dest_dir, "logo.png")
|
||||
if env.File(source_path).exists():
|
||||
print(f"Loading boot logo from {source_path}")
|
||||
# Prepare the destination
|
||||
env.Execute(f"mkdir -p {dest_dir} && rm -f {dest_path}")
|
||||
# Copy the logo to the `data/boot` directory
|
||||
env.Execute(f"cp {source_path} {dest_path}")
|
||||
|
||||
# Load the boot logo on TFT builds
|
||||
if ("HAS_TFT", 1) in env.get("CPPDEFINES", []):
|
||||
env.AddPreAction(f"$BUILD_DIR/{lfsbin}", load_boot_logo)
|
||||
|
||||
mtjson_deps = ["buildprog"]
|
||||
if platform.name == "espressif32":
|
||||
# Build littlefs image as part of mtjson target
|
||||
# Equivalent to `pio run -t buildfs`
|
||||
target_lfs = env.DataToBin(
|
||||
join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}"), "$PROJECT_DATA_DIR"
|
||||
)
|
||||
mtjson_deps.append(target_lfs)
|
||||
|
||||
env.AddCustomTarget(
|
||||
name="mtjson",
|
||||
dependencies=mtjson_deps,
|
||||
actions=[manifest_gather],
|
||||
title="Meshtastic Manifest",
|
||||
description="Generating Meshtastic manifest JSON + Checksums",
|
||||
always_build=False,
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user