Compare commits

..

18 Commits

Author SHA1 Message Date
Manuel
469abe8dec Merge branch 'master' into crowpanelV2 2025-12-10 13:38:41 +01:00
Manuel
fefce15b1a Merge branch 'master' into crowpanelV2 2025-12-05 10:59:34 +01:00
Manuel
50ea7ace98 Merge branch 'master' into crowpanelV2 2025-10-11 23:32:09 +02:00
Manuel
96f371eafd Merge branch 'master' into crowpanelV2 2025-10-07 14:22:46 +02:00
Manuel
dbc52c7576 update device-ui commit 2025-10-07 14:21:55 +02:00
Manuel
232e0412ff cosmetic print when STC8H1K28 is found 2025-10-07 14:19:45 +02:00
Manuel
b94659ff6a Update device-ui commit reference 2025-10-05 22:32:08 +02:00
Manuel
059e17b3e2 Update device-ui commit reference 2025-10-05 11:12:25 +02:00
Manuel
b09f6db9e2 Merge branch 'master' into crowpanelV2 2025-10-05 11:00:02 +02:00
Manuel
64706153e0 Merge branch 'master' into crowpanelV2 2025-10-02 16:35:36 +02:00
Manuel
f94043e4f2 Merge branch 'master' into crowpanelV2 2025-10-01 18:06:45 +02:00
Manuel
bc82cd803c Merge branch 'master' into crowpanelV2 2025-09-29 10:49:38 +02:00
Manuel
c15b6de138 Merge branch 'master' into crowpanelV2 2025-09-28 00:30:03 +02:00
Manuel
fbf32b93b6 fix lora radio detection 2025-09-22 22:23:03 +02:00
Manuel
b7289f7f2d Merge branch 'master' into crowpanelV2 2025-09-22 10:40:10 +02:00
Manuel
d3d932ccee Merge branch 'master' into crowpanelV2 2025-09-21 14:11:29 +02:00
Manuel
3a267b440d Merge branch 'master' into crowpanelV2 2025-09-21 09:39:49 +02:00
Manuel
b1821bfd4f CrowPanel Advanced V2 support 2025-09-18 16:00:49 +02:00
59 changed files with 221 additions and 419 deletions

View File

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

View File

@@ -76,7 +76,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,7 +100,7 @@ runs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}
overwrite: true

View File

@@ -64,7 +64,7 @@ jobs:
PKG_VERSION: ${{ steps.version.outputs.deb }}
- name: Store binaries as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
overwrite: true

View File

@@ -18,8 +18,7 @@ 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' }}
runs-on: ubuntu-24.04
outputs:
artifact-id: ${{ steps.upload.outputs.artifact-id }}
steps:
@@ -68,7 +67,7 @@ jobs:
echo '```' >> $GITHUB_STEP_SUMMARY
- name: Store binaries as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
id: upload
with:
name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}

View File

@@ -98,7 +98,7 @@ jobs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
path: ./
pattern: firmware-*-*
@@ -111,7 +111,7 @@ jobs:
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: firmware-${{inputs.target}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -127,7 +127,7 @@ jobs:
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
pattern: firmware-*-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -139,14 +139,14 @@ 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-${{inputs.target}}-${{ needs.version.outputs.long }}.zip ./output
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: debug-elfs-${{inputs.target}}-${{ needs.version.outputs.long }}.zip
overwrite: true

View File

@@ -77,21 +77,16 @@ jobs:
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' }}
runs-on: 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: Build base
id: base
uses: ./.github/actions/setup-base
- 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
run: bin/check-all.sh ${{ matrix.check.board }}
build:
needs: [setup, version]
@@ -173,7 +168,7 @@ jobs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
path: ./
pattern: firmware-${{matrix.arch}}-*
@@ -183,7 +178,7 @@ jobs:
run: ls -R
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -200,7 +195,7 @@ jobs:
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -212,14 +207,14 @@ 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
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -260,14 +255,14 @@ jobs:
Autogenerated by github action, developer should edit as required before publishing...
- name: Download source deb
uses: actions/download-artifact@v7
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@v7
uses: actions/download-artifact@v6
with:
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -285,13 +280,13 @@ jobs:
- name: Generate Release manifest
run: |
jq -n --arg ver "${{ needs.version.outputs.long }}" --argjson targets ${{ toJson(needs.setup.outputs.all) }} '{
jq -n --arg ver "${{ needs.version.outputs.long }}" --arg targets "${{ toJson(needs.setup.outputs.all) }}" '{
"version": $ver,
"targets": $targets
"targets": ($targets | fromjson)
}' > firmware-${{ needs.version.outputs.long }}.json
- name: Save Release manifest artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: manifest-${{ needs.version.outputs.long }}
overwrite: true
@@ -332,7 +327,7 @@ jobs:
with:
python-version: 3.x
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -343,13 +338,13 @@ 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
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -388,14 +383,14 @@ jobs:
python-version: 3.x
- name: Get firmware artifacts
uses: actions/download-artifact@v7
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@v7
uses: actions/download-artifact@v6
with:
pattern: manifest-${{ needs.version.outputs.long }}
path: ./publish

View File

@@ -147,7 +147,7 @@ jobs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
path: ./
pattern: firmware-${{matrix.arch}}-*
@@ -160,7 +160,7 @@ jobs:
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -176,7 +176,7 @@ jobs:
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -188,14 +188,14 @@ 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
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -235,14 +235,14 @@ jobs:
Autogenerated by github action, developer should edit as required before publishing...
- name: Download source deb
uses: actions/download-artifact@v7
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@v7
uses: actions/download-artifact@v6
with:
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -292,7 +292,7 @@ jobs:
with:
python-version: 3.x
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -303,13 +303,13 @@ 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
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -347,7 +347,7 @@ jobs:
with:
python-version: 3.x
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
merge-multiple: true

View File

@@ -58,7 +58,7 @@ jobs:
id: version
- name: Download artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v6
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
merge-multiple: true

View File

@@ -56,7 +56,7 @@ jobs:
PLATFORMIO_CORE_DIR: pio/core
- name: Store binaries as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: platformio-deps-${{ inputs.pio_env }}-${{ steps.version.outputs.long }}
overwrite: true

View File

@@ -60,7 +60,7 @@ jobs:
id: version
- name: Download artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v6
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
merge-multiple: true

View File

@@ -50,7 +50,7 @@ jobs:
- name: Download test artifacts
if: needs.native-tests.result != 'skipped'
uses: actions/download-artifact@v7
uses: actions/download-artifact@v6
with:
name: platformio-test-report-${{ steps.version.outputs.long }}
merge-multiple: true

View File

@@ -33,7 +33,7 @@ jobs:
# step 3
- name: save report as pipeline artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: report.sarif
overwrite: true

View File

@@ -59,7 +59,7 @@ jobs:
id: version
- name: Save coverage information
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
if: always() # run this step even if previous step failed
with:
name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}
@@ -94,7 +94,7 @@ jobs:
- name: Save test results
if: always() # run this step even if previous step failed
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: platformio-test-report-${{ steps.version.outputs.long }}
overwrite: true
@@ -108,7 +108,7 @@ jobs:
sed -i -e "s#${PWD}#.#" coverage_tests.info # Make paths relative.
- name: Save coverage information
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
if: always() # run this step even if previous step failed
with:
name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}
@@ -137,7 +137,7 @@ jobs:
id: version
- name: Download test artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v6
with:
name: platformio-test-report-${{ steps.version.outputs.long }}
merge-multiple: true
@@ -150,7 +150,7 @@ jobs:
reporter: java-junit
- name: Download coverage artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v6
with:
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}
path: code-coverage-report
@@ -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@v6
uses: actions/upload-artifact@v5
with:
name: code-coverage-report-${{ steps.version.outputs.long }}
path: code-coverage-report

View File

@@ -9,16 +9,16 @@ plugins:
lint:
enabled:
- checkov@3.2.495
- renovate@42.48.0
- renovate@42.42.2
- prettier@3.7.4
- trufflehog@3.92.3
- trufflehog@3.92.1
- yamllint@1.37.1
- bandit@1.9.2
- trivy@0.68.1
- taplo@0.10.0
- ruff@0.14.9
- ruff@0.14.8
- isort@7.0.0
- markdownlint@0.47.0
- markdownlint@0.46.0
- oxipng@10.0.0
- svgo@4.0.0
- actionlint@1.7.9

View File

@@ -22,7 +22,7 @@ export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION
pio run --environment $1 -t mtjson # -v
pio run --environment $1 # -v
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
@@ -32,10 +32,20 @@ cp $BUILDDIR/$basename.factory.bin $OUTDIR/$basename.factory.bin
echo "Copying ESP32 update bin file"
cp $BUILDDIR/$basename.bin $OUTDIR/$basename.bin
echo "Copying Filesystem for ESP32 targets"
echo "Building Filesystem for ESP32 targets"
# If you want to build the webui, uncomment the following lines
# 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 --disable-auto-clean
cp $BUILDDIR/littlefs-$1-$VERSION.bin $OUTDIR/littlefs-$1-$VERSION.bin
cp bin/device-install.* $OUTDIR/
cp bin/device-update.* $OUTDIR/
echo "Copying manifest"
# Generate the manifest file
echo "Generating Meshtastic manifest"
TIMEFORMAT="Generated manifest in %E seconds"
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json

View File

@@ -22,7 +22,7 @@ export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION
pio run --environment $1 -t mtjson # -v
pio run --environment $1 # -v
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
@@ -47,5 +47,8 @@ if (echo $1 | grep -q "rak4631"); then
cp $SRCHEX $OUTDIR/
fi
echo "Copying manifest"
# Generate the manifest file
echo "Generating Meshtastic manifest"
TIMEFORMAT="Generated manifest in %E seconds"
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json

View File

@@ -22,12 +22,15 @@ export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION
pio run --environment $1 -t mtjson # -v
pio run --environment $1 # -v
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
echo "Copying uf2 file"
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2
echo "Copying manifest"
# Generate the manifest file
echo "Generating Meshtastic manifest"
TIMEFORMAT="Generated manifest in %E seconds"
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json

View File

@@ -22,12 +22,15 @@ export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION
pio run --environment $1 -t mtjson # -v
pio run --environment $1 # -v
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
echo "Copying STM32 bin file"
cp $BUILDDIR/$basename.bin $OUTDIR/$basename.bin
echo "Copying manifest"
# Generate the manifest file
echo "Generating Meshtastic manifest"
TIMEFORMAT="Generated manifest in %E seconds"
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json

View File

@@ -184,8 +184,6 @@ Input:
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:

View File

@@ -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":

View File

@@ -159,22 +159,20 @@ def load_boot_logo(source, target, env):
# Load the boot logo on TFT builds
if ("HAS_TFT", 1) in env.get("CPPDEFINES", []):
env.AddPreAction(f"$BUILD_DIR/{lfsbin}", load_boot_logo)
env.AddPreAction('$BUILD_DIR/littlefs.bin', 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)
# Rename (mv) littlefs.bin to include the PROGNAME
# This ensures the littlefs.bin is named consistently with the firmware
env.AddPostAction('$BUILD_DIR/littlefs.bin', env.VerboseAction(
f'mv $BUILD_DIR/littlefs.bin $BUILD_DIR/{lfsbin}',
f'Renaming littlefs.bin to {lfsbin}'
))
env.AddCustomTarget(
name="mtjson",
dependencies=mtjson_deps,
dependencies=None,
actions=[manifest_gather],
title="Meshtastic Manifest",
description="Generating Meshtastic manifest JSON + Checksums",
always_build=False,
always_build=True,
)

View File

@@ -11,9 +11,6 @@ else:
prefsLoc = env["PROJECT_DIR"] + "/version.properties"
verObj = readProps(prefsLoc)
env.Replace(PROGNAME=f"firmware-{env.get('PIOENV')}-{verObj['long']}")
env.Replace(ESP32_FS_IMAGE_NAME=f"littlefs-{env.get('PIOENV')}-{verObj['long']}")
# Print the new program name for verification
print(f"PROGNAME: {env.get('PROGNAME')}")
if platform.name == "espressif32":
print(f"ESP32_FS_IMAGE_NAME: {env.get('ESP32_FS_IMAGE_NAME')}")

View File

@@ -123,7 +123,7 @@ lib_deps =
[device-ui_base]
lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/2746a1ce3804998460a2cb319b8ea8a238dfd8c9.zip
https://github.com/meshtastic/device-ui/archive/14dc991a4b57066e0a83599be1a87ff08e5e5308.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
@@ -207,7 +207,7 @@ lib_deps =
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
closedcube/ClosedCube OPT3001@1.1.2
ClosedCube OPT3001@1.1.2
# renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2
boschsensortec/bsec2@1.10.2610
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library

View File

@@ -269,6 +269,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define TCA9535_ADDR 0x20
#define TCA9555_ADDR 0x26
// used for display brightness control
#define STC8H1K28_ADDR 0x30
// -----------------------------------------------------------------------------
// Touchscreen
// -----------------------------------------------------------------------------

View File

@@ -61,6 +61,7 @@ class ScanI2C
NAU7802,
FT6336U,
STK8BAXX,
STC8H1K28,
ICM20948,
SCD4X,
MAX30102,

View File

@@ -234,6 +234,8 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
#endif
#ifdef HAS_LP5562
SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address);
#else
SCAN_SIMPLE_CASE(STC8H1K28_ADDR, LP5562, "STC8H1K28", (uint8_t)addr.address);
#endif
case XPOWERS_AXP192_AXP2101_ADDRESS:
// Do we have the axp2101/192 or the TCA8418

View File

@@ -532,10 +532,8 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
const int labelX = x;
int barsOffset = (isHighResolution) ? 24 : 0;
#ifdef USE_EINK
#ifndef T_DECK_PRO
barsOffset -= 12;
#endif
#endif
#if defined(M5STACK_UNITC6L)
const int barX = x + 45 + barsOffset;
#else
@@ -576,7 +574,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
#endif
// Value string
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(SCREEN_WIDTH, getTextPositions(display)[line], combinedStr);
display->drawString(SCREEN_WIDTH - 2, getTextPositions(display)[line], combinedStr);
};
// === Memory values ===

View File

@@ -1041,13 +1041,12 @@ void menuHandler::switchToMUIMenu()
void menuHandler::TFTColorPickerMenu(OLEDDisplay *display)
{
static const char *optionsArray[] = {
"Back", "Default", "Meshtastic Green", "Yellow", "Red", "Orange", "Purple", "Blue", "Teal", "Cyan", "Ice", "Pink",
"White", "Gray"};
static const char *optionsArray[] = {"Back", "Default", "Meshtastic Green", "Yellow", "Red", "Orange", "Purple", "Teal",
"Pink", "White"};
BannerOverlayOptions bannerOptions;
bannerOptions.message = "Select Screen Color";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 14;
bannerOptions.optionsCount = 10;
bannerOptions.bannerCallback = [display](int selected) -> void {
#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || defined(T_DECK) || defined(T_LORA_PAGER) || \
HAS_TFT || defined(HACKADAY_COMMUNICATOR)
@@ -1083,40 +1082,20 @@ void menuHandler::TFTColorPickerMenu(OLEDDisplay *display)
TFT_MESH_g = 153;
TFT_MESH_b = 255;
} else if (selected == 7) {
LOG_INFO("Setting color to Blue");
TFT_MESH_r = 0;
TFT_MESH_g = 0;
TFT_MESH_b = 255;
} else if (selected == 8) {
LOG_INFO("Setting color to Teal");
TFT_MESH_r = 16;
TFT_MESH_g = 102;
TFT_MESH_b = 102;
} else if (selected == 9) {
LOG_INFO("Setting color to Cyan");
TFT_MESH_r = 0;
TFT_MESH_g = 255;
TFT_MESH_b = 255;
} else if (selected == 10) {
LOG_INFO("Setting color to Ice");
TFT_MESH_r = 173;
TFT_MESH_g = 216;
TFT_MESH_b = 230;
} else if (selected == 11) {
TFT_MESH_r = 64;
TFT_MESH_g = 224;
TFT_MESH_b = 208;
} else if (selected == 8) {
LOG_INFO("Setting color to Pink");
TFT_MESH_r = 255;
TFT_MESH_g = 105;
TFT_MESH_b = 180;
} else if (selected == 12) {
} else if (selected == 9) {
LOG_INFO("Setting color to White");
TFT_MESH_r = 255;
TFT_MESH_g = 255;
TFT_MESH_b = 255;
} else if (selected == 13) {
LOG_INFO("Setting color to Gray");
TFT_MESH_r = 128;
TFT_MESH_g = 128;
TFT_MESH_b = 128;
} else {
menuQueue = system_base_menu;
screen->runNow();

View File

@@ -53,7 +53,6 @@ typedef struct _InputEvent {
class InputPollable
{
public:
virtual ~InputPollable() = default;
virtual void pollOnce() = 0;
};

View File

@@ -3,9 +3,6 @@
#include "RotaryEncoderImpl.h"
#include "InputBroker.h"
#include "RotaryEncoder.h"
#ifdef ARCH_ESP32
#include "sleep.h"
#endif
#define ORIGIN_NAME "RotaryEncoder"
@@ -14,20 +11,6 @@ RotaryEncoderImpl *rotaryEncoderImpl;
RotaryEncoderImpl::RotaryEncoderImpl()
{
rotary = nullptr;
#ifdef ARCH_ESP32
isFirstInit = true;
#endif
}
RotaryEncoderImpl::~RotaryEncoderImpl()
{
LOG_DEBUG("RotaryEncoderImpl destructor");
detachRotaryEncoderInterrupts();
if (rotary != nullptr) {
delete rotary;
rotary = nullptr;
}
}
bool RotaryEncoderImpl::init()
@@ -42,22 +25,15 @@ bool RotaryEncoderImpl::init()
eventCcw = static_cast<input_broker_event>(moduleConfig.canned_message.inputbroker_event_ccw);
eventPressed = static_cast<input_broker_event>(moduleConfig.canned_message.inputbroker_event_press);
if (rotary == nullptr) {
rotary = new RotaryEncoder(moduleConfig.canned_message.inputbroker_pin_a, moduleConfig.canned_message.inputbroker_pin_b,
moduleConfig.canned_message.inputbroker_pin_press);
}
rotary = new RotaryEncoder(moduleConfig.canned_message.inputbroker_pin_a, moduleConfig.canned_message.inputbroker_pin_b,
moduleConfig.canned_message.inputbroker_pin_press);
rotary->resetButton();
attachRotaryEncoderInterrupts();
#ifdef ARCH_ESP32
// Register callbacks for before and after lightsleep
// Used to detach and reattach interrupts
if (isFirstInit) {
lsObserver.observe(&notifyLightSleep);
lsEndObserver.observe(&notifyLightSleepEnd);
isFirstInit = false;
}
#endif
interruptInstance = this;
auto interruptHandler = []() { inputBroker->requestPollSoon(interruptInstance); };
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_a, interruptHandler, CHANGE);
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_b, interruptHandler, CHANGE);
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_press, interruptHandler, CHANGE);
LOG_INFO("RotaryEncoder initialized pins(%d, %d, %d), events(%d, %d, %d)", moduleConfig.canned_message.inputbroker_pin_a,
moduleConfig.canned_message.inputbroker_pin_b, moduleConfig.canned_message.inputbroker_pin_press, eventCw, eventCcw,
@@ -95,50 +71,6 @@ void RotaryEncoderImpl::pollOnce()
}
}
void RotaryEncoderImpl::detachRotaryEncoderInterrupts()
{
LOG_DEBUG("RotaryEncoderImpl detach button interrupts");
if (interruptInstance == this) {
detachInterrupt(moduleConfig.canned_message.inputbroker_pin_a);
detachInterrupt(moduleConfig.canned_message.inputbroker_pin_b);
detachInterrupt(moduleConfig.canned_message.inputbroker_pin_press);
interruptInstance = nullptr;
} else {
LOG_WARN("RotaryEncoderImpl: interrupts already detached");
}
}
void RotaryEncoderImpl::attachRotaryEncoderInterrupts()
{
LOG_DEBUG("RotaryEncoderImpl attach button interrupts");
if (rotary != nullptr && interruptInstance == nullptr) {
rotary->resetButton();
interruptInstance = this;
auto interruptHandler = []() { inputBroker->requestPollSoon(interruptInstance); };
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_a, interruptHandler, CHANGE);
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_b, interruptHandler, CHANGE);
attachInterrupt(moduleConfig.canned_message.inputbroker_pin_press, interruptHandler, CHANGE);
} else {
LOG_WARN("RotaryEncoderImpl: interrupts already attached");
}
}
#ifdef ARCH_ESP32
int RotaryEncoderImpl::beforeLightSleep(void *unused)
{
detachRotaryEncoderInterrupts();
return 0; // Indicates success;
}
int RotaryEncoderImpl::afterLightSleep(esp_sleep_wakeup_cause_t cause)
{
attachRotaryEncoderInterrupts();
return 0; // Indicates success;
}
#endif
RotaryEncoderImpl *RotaryEncoderImpl::interruptInstance;
#endif

View File

@@ -8,18 +8,12 @@
class RotaryEncoder;
class RotaryEncoderImpl final : public InputPollable
class RotaryEncoderImpl : public InputPollable
{
public:
RotaryEncoderImpl();
~RotaryEncoderImpl() override;
bool init();
bool init(void);
virtual void pollOnce() override;
// Disconnect and reconnect interrupts for light sleep
#ifdef ARCH_ESP32
int beforeLightSleep(void *unused);
int afterLightSleep(esp_sleep_wakeup_cause_t cause);
#endif
protected:
static RotaryEncoderImpl *interruptInstance;
@@ -29,21 +23,6 @@ class RotaryEncoderImpl final : public InputPollable
input_broker_event eventPressed = INPUT_BROKER_NONE;
RotaryEncoder *rotary;
private:
#ifdef ARCH_ESP32
bool isFirstInit;
#endif
void detachRotaryEncoderInterrupts();
void attachRotaryEncoderInterrupts();
#ifdef ARCH_ESP32
// Get notified when lightsleep begins and ends
CallbackObserver<RotaryEncoderImpl, void *> lsObserver =
CallbackObserver<RotaryEncoderImpl, void *>(this, &RotaryEncoderImpl::beforeLightSleep);
CallbackObserver<RotaryEncoderImpl, esp_sleep_wakeup_cause_t> lsEndObserver =
CallbackObserver<RotaryEncoderImpl, esp_sleep_wakeup_cause_t>(this, &RotaryEncoderImpl::afterLightSleep);
#endif
};
extern RotaryEncoderImpl *rotaryEncoderImpl;

View File

@@ -439,11 +439,6 @@ void setup()
LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n");
#if defined(ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
// use PSRAM for malloc calls > 256 bytes
heap_caps_malloc_extmem_enable(256);
#endif
#if defined(DEBUG_MUTE) && defined(DEBUG_PORT)
DEBUG_PORT.printf("\r\n\r\n//\\ E S H T /\\ S T / C\r\n");
DEBUG_PORT.printf("Version %s for %s from %s\r\n", optstr(APP_VERSION), optstr(APP_ENV), optstr(APP_REPO));

View File

@@ -225,4 +225,4 @@ class MeshModule
/** set the destination and packet parameters of packet p intended as a reply to a particular "to" packet
* This ensures that if the request packet was sent reliably, the reply is sent that way as well.
*/
void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to);
void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to);

View File

@@ -805,15 +805,11 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.external_notification.output_ms = 500;
moduleConfig.external_notification.nag_timeout = 2;
#endif
#if defined(RAK4630) || defined(RAK11310) || defined(RAK3312) || defined(MUZI_BASE)
#if defined(RAK4630) || defined(RAK11310) || defined(RAK3312)
// Default to RAK led pin 2 (blue)
moduleConfig.external_notification.enabled = true;
moduleConfig.external_notification.output = PIN_LED2;
#if defined(MUZI_BASE)
moduleConfig.external_notification.active = false;
#else
moduleConfig.external_notification.active = true;
#endif
moduleConfig.external_notification.alert_message = true;
moduleConfig.external_notification.output_ms = 1000;
moduleConfig.external_notification.nag_timeout = default_ringtone_nag_secs;

View File

@@ -150,9 +150,7 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
PacketId nakId = (c && c->error_reason != meshtastic_Routing_Error_NONE) ? p->decoded.request_id : 0;
// We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records
if ((ackId || nakId) &&
// Implicit ACKs from MQTT should not stop retransmissions
!(isFromUs(p) && p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MQTT)) {
if (ackId || nakId) {
LOG_DEBUG("Received a %s for 0x%x, stopping retransmissions", ackId ? "ACK" : "NAK", ackId);
if (ackId) {
stopRetransmission(p->to, ackId);

View File

@@ -37,8 +37,8 @@
static MemoryDynamic<meshtastic_MeshPacket> dynamicPool;
Allocator<meshtastic_MeshPacket> &packetPool = dynamicPool;
#elif defined(ARCH_STM32WL) || defined(BOARD_HAS_PSRAM)
// On STM32 and boards with PSRAM, there isn't enough heap left over for the rest of the firmware if we allocate this statically.
#elif defined(ARCH_STM32WL)
// On STM32 there isn't enough heap left over for the rest of the firmware if we allocate this statically.
// For now, make it dynamic again.
#define MAX_PACKETS \
(MAX_RX_TOPHONE + MAX_RX_FROMRADIO + 2 * MAX_TX_QUEUE + \
@@ -526,10 +526,6 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
#elif ARCH_PORTDUINO
if (portduino_config.traceFilename != "" || portduino_config.logoutputlevel == level_trace) {
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str());
} else if (portduino_config.JSONFilename != "") {
if (portduino_config.JSONFilter == (_meshtastic_PortNum)0 || portduino_config.JSONFilter == p->decoded.portnum) {
JSONFile << MeshPacketSerializer::JsonSerialize(p, false) << std::endl;
}
}
#endif
return DecodeState::DECODE_SUCCESS;

View File

@@ -217,7 +217,7 @@ void setupModules()
}
#endif // HAS_BUTTON
#if ARCH_PORTDUINO
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR && portduino_config.i2cdev != "") {
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
seesawRotary = new SeesawRotary("SeesawRotary");
if (!seesawRotary->init()) {
delete seesawRotary;

View File

@@ -45,12 +45,8 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
{
auto p = *pptr;
const auto transport = mp.transport_mechanism;
if (isFromUs(&mp) && !IS_ONE_OF(transport, meshtastic_MeshPacket_TransportMechanism_TRANSPORT_INTERNAL,
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API)) {
LOG_WARN("Ignoring packet supposedly from us over external transport");
return true;
}
// If inbound message is a replay (or spoof!) of our own messages, we shouldn't process
// (why use second-hand sources for our own data?)
// FIXME this can in fact happen with packets sent from EUD (src=RX_SRC_USER)
// to set fixed location, EUD-GPS location or just the time (see also issue #900)
@@ -476,53 +472,19 @@ void PositionModule::sendLostAndFoundText()
delete[] message;
}
// Helper: return imprecise (truncated + centered) lat/lon as int32 using current precision
static inline void computeImpreciseLatLon(int32_t inLat, int32_t inLon, uint8_t precisionBits, int32_t &outLat, int32_t &outLon)
{
if (precisionBits > 0 && precisionBits < 32) {
// Build mask for top 'precisionBits' bits of a 32-bit unsigned field
const uint32_t mask = (precisionBits == 32) ? UINT32_MAX : (UINT32_MAX << (32 - precisionBits));
// Note: latitude_i/longitude_i are stored as signed 32-bit in meshtastic code but
// the bitmask logic used previously operated as unsigned—preserve that behavior by
// casting to uint32_t for masking, then back to int32_t.
uint32_t lat_u = static_cast<uint32_t>(inLat) & mask;
uint32_t lon_u = static_cast<uint32_t>(inLon) & mask;
// Add the "center of cell" offset used elsewhere:
// The code previously added (1 << (31 - precision)) to produce the middle of the possible location.
uint32_t center_offset = (1u << (31 - precisionBits));
lat_u += center_offset;
lon_u += center_offset;
outLat = static_cast<int32_t>(lat_u);
outLon = static_cast<int32_t>(lon_u);
} else {
// full precision: return input unchanged
outLat = inLat;
outLon = inLon;
}
}
struct SmartPosition PositionModule::getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition)
{
// The minimum distance to travel before we are able to send a new position packet.
const uint32_t distanceTravelThreshold =
Default::getConfiguredOrDefault(config.position.broadcast_smart_minimum_distance, 100);
int32_t lastLatImprecise, lastLonImprecise;
int32_t currentLatImprecise, currentLonImprecise;
// Determine the distance in meters between two points on the globe
float distanceTraveledSinceLastSend = GeoCoord::latLongToMeter(
lastGpsLatitude * 1e-7, lastGpsLongitude * 1e-7, currentPosition.latitude_i * 1e-7, currentPosition.longitude_i * 1e-7);
computeImpreciseLatLon(lastGpsLatitude, lastGpsLongitude, precision, lastLatImprecise, lastLonImprecise);
computeImpreciseLatLon(currentPosition.latitude_i, currentPosition.longitude_i, precision, currentLatImprecise,
currentLonImprecise);
float distMeters = GeoCoord::latLongToMeter(lastLatImprecise * 1e-7, lastLonImprecise * 1e-7, currentLatImprecise * 1e-7,
currentLonImprecise * 1e-7);
float distanceTraveled = fabsf(distMeters);
return SmartPosition{.distanceTraveled = distanceTraveled,
return SmartPosition{.distanceTraveled = abs(distanceTraveledSinceLastSend),
.distanceThreshold = distanceTravelThreshold,
.hasTraveledOverThreshold = distanceTraveled >= distanceTravelThreshold};
.hasTraveledOverThreshold = abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold};
}
void PositionModule::handleNewPosition()

View File

@@ -75,12 +75,6 @@ uint8_t RoutingModule::getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit
return Default::getConfiguredOrDefaultHopLimit(config.lora.hop_limit); // Use the default hop limit
}
meshtastic_MeshPacket *RoutingModule::allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex,
uint8_t hopLimit)
{
return MeshModule::allocAckNak(err, to, idFrom, chIndex, hopLimit);
}
RoutingModule::RoutingModule() : ProtobufModule("routing", meshtastic_PortNum_ROUTING_APP, &meshtastic_Routing_msg)
{
isPromiscuous = true;

View File

@@ -16,9 +16,6 @@ class RoutingModule : public ProtobufModule<meshtastic_Routing>
virtual void sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, uint8_t hopLimit = 0,
bool ackWantsAck = false);
meshtastic_MeshPacket *allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex,
uint8_t hopLimit = 0);
// Given the hopStart and hopLimit upon reception of a request, return the hop limit to use for the response
uint8_t getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit);

View File

@@ -87,13 +87,10 @@ inline void onReceiveProto(char *topic, byte *payload, size_t length)
// Generate an implicit ACK towards ourselves (handled and processed only locally!) for this message.
// We do this because packets are not rebroadcasted back into MQTT anymore and we assume that at least one node
// receives it when we get our own packet back. Then we'll stop our retransmissions.
if (isFromUs(e.packet)) {
auto pAck = routingModule->allocAckNak(meshtastic_Routing_Error_NONE, getFrom(e.packet), e.packet->id, ch.index);
pAck->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MQTT;
router->sendLocal(pAck);
} else {
if (isFromUs(e.packet))
routingModule->sendAckNak(meshtastic_Routing_Error_NONE, getFrom(e.packet), e.packet->id, ch.index);
else
LOG_INFO("Ignore downlink message we originally sent");
}
return;
}
if (isFromUs(e.packet)) {

View File

@@ -64,6 +64,16 @@ void onConnect(uint16_t conn_handle)
connection->getPeerName(central_name, sizeof(central_name));
LOG_INFO("BLE Connected to %s", central_name);
// negotiate connections params as soon as possible
ble_gap_conn_params_t newParams;
newParams.min_conn_interval = 24;
newParams.max_conn_interval = 40;
newParams.slave_latency = 5;
newParams.conn_sup_timeout = 400;
sd_ble_gap_conn_param_update(conn_handle, &newParams);
// Notify UI (or any other interested firmware components)
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::CONNECTED);
bluetoothStatus->updateStatus(&newStatus);
@@ -119,7 +129,7 @@ void startAdv(void)
Bluefruit.Advertising.addService(meshBleService);
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Interval: fast mode = 20 ms, slow mode = 417,5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
@@ -127,7 +137,7 @@ void startAdv(void)
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setInterval(32, 668); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds. FIXME, we should stop advertising after X
}
@@ -272,6 +282,24 @@ void NRF52Bluetooth::setup()
// Set the connect/disconnect callback handlers
Bluefruit.Periph.setConnectCallback(onConnect);
Bluefruit.Periph.setDisconnectCallback(onDisconnect);
// Set slave latency to 5 to conserve power
// Despite name this does not impact data transfer
// https://docs.silabs.com/bluetooth/2.13/bluetooth-general-system-and-performance/optimizing-current-consumption-in-bluetooth-low-energy-devices
Bluefruit.Periph.setConnSlaveLatency(5);
// TODO: Adafruit defaul min, max interval seems to be (20,30) [in 1.25 ms units] -> (25.00, 31.25) milliseconds
// so using formula Interval Max * (Slave Latency + 1) ≤ 2 seconds
// max slave latency we can use is 30 (max available in BLE)
// and even double max inteval (see apple doc linked above for formulas)
// See Periph.SetConnInterval method
// Tweak this later for even more power savings once those changes are confirmed to work well.
// Changing min, max interval may slow BLE transfer a bit - bumping slave latency will most likely not.
#ifndef BLE_DFU_SECURE
bledfu.setPermission(SECMODE_ENC_WITH_MITM, SECMODE_ENC_WITH_MITM);
bledfu.begin(); // Install the DFU helper
@@ -300,7 +328,7 @@ void NRF52Bluetooth::setup()
void NRF52Bluetooth::resumeAdvertising()
{
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setInterval(32, 668); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0);
}

View File

@@ -337,7 +337,7 @@ void cpuDeepSleep(uint32_t msecToWake)
#endif
#ifdef TTGO_T_ECHO
// To power off the T-Echo, the display must be set
// To power off the T-Echo, the display must be set
// as an input pin; otherwise, there will be leakage current.
pinMode(PIN_EINK_CS, INPUT);
pinMode(PIN_EINK_DC, INPUT);

View File

@@ -29,7 +29,6 @@
portduino_config_struct portduino_config;
std::ofstream traceFile;
std::ofstream JSONFile;
Ch341Hal *ch341Hal = nullptr;
char *configPath = nullptr;
char *optionMac = nullptr;
@@ -464,7 +463,6 @@ void portduinoSetup()
if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") {
SPI.begin(portduino_config.lora_spi_dev.c_str());
}
if (portduino_config.traceFilename != "") {
try {
traceFile.open(portduino_config.traceFilename, std::ios::out | std::ios::app);
@@ -472,21 +470,6 @@ void portduinoSetup()
std::cout << "*** traceFile Exception " << e.what() << std::endl;
exit(EXIT_FAILURE);
}
if (!traceFile.is_open()) {
std::cout << "*** traceFile open failure" << std::endl;
exit(EXIT_FAILURE);
}
} else if (portduino_config.JSONFilename != "") {
try {
JSONFile.open(portduino_config.JSONFilename, std::ios::out | std::ios::app);
} catch (std::ofstream::failure &e) {
std::cout << "*** JSONFile Exception " << e.what() << std::endl;
exit(EXIT_FAILURE);
}
if (!JSONFile.is_open()) {
std::cout << "*** JSONFile open failure" << std::endl;
exit(EXIT_FAILURE);
}
}
if (verboseEnabled && portduino_config.logoutputlevel != level_trace) {
portduino_config.logoutputlevel = level_debug;
@@ -534,29 +517,6 @@ bool loadConfig(const char *configPath)
portduino_config.logoutputlevel = level_error;
}
portduino_config.traceFilename = yamlConfig["Logging"]["TraceFile"].as<std::string>("");
portduino_config.JSONFilename = yamlConfig["Logging"]["JSONFile"].as<std::string>("");
portduino_config.JSONFilter = (_meshtastic_PortNum)yamlConfig["Logging"]["JSONFilter"].as<int>(0);
if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "textmessage")
portduino_config.JSONFilter = meshtastic_PortNum_TEXT_MESSAGE_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "telemetry")
portduino_config.JSONFilter = meshtastic_PortNum_TELEMETRY_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "nodeinfo")
portduino_config.JSONFilter = meshtastic_PortNum_NODEINFO_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "position")
portduino_config.JSONFilter = meshtastic_PortNum_POSITION_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "waypoint")
portduino_config.JSONFilter = meshtastic_PortNum_WAYPOINT_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "neighborinfo")
portduino_config.JSONFilter = meshtastic_PortNum_NEIGHBORINFO_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "traceroute")
portduino_config.JSONFilter = meshtastic_PortNum_TRACEROUTE_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "detection")
portduino_config.JSONFilter = meshtastic_PortNum_DETECTION_SENSOR_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "paxcounter")
portduino_config.JSONFilter = meshtastic_PortNum_PAXCOUNTER_APP;
else if (yamlConfig["Logging"]["JSONFilter"].as<std::string>("") == "remotehardware")
portduino_config.JSONFilter = meshtastic_PortNum_REMOTE_HARDWARE_APP;
if (yamlConfig["Logging"]["AsciiLogs"]) {
// Default is !isatty(1) but can be set explicitly in config.yaml
portduino_config.ascii_logs = yamlConfig["Logging"]["AsciiLogs"].as<bool>();

View File

@@ -5,7 +5,6 @@
#include "LR11x0Interface.h"
#include "Module.h"
#include "mesh/generated/meshtastic/mesh.pb.h"
#include "platform/portduino/USBHal.h"
#include "yaml-cpp/yaml.h"
@@ -47,8 +46,6 @@ struct pinMapping {
};
extern std::ofstream traceFile;
extern std::ofstream JSONFile;
extern Ch341Hal *ch341Hal;
int initGPIOPin(int pinNum, std::string gpioChipname, int line);
bool loadConfig(const char *configPath);
@@ -151,9 +148,6 @@ extern struct portduino_config_struct {
bool ascii_logs = !isatty(1);
bool ascii_logs_explicit = false;
std::string JSONFilename;
meshtastic_PortNum JSONFilter = (_meshtastic_PortNum)0;
// Webserver
std::string webserver_root_path = "";
std::string webserver_ssl_key_path = "/etc/meshtasticd/ssl/private_key.pem";
@@ -419,29 +413,6 @@ extern struct portduino_config_struct {
}
if (traceFilename != "")
out << YAML::Key << "TraceFile" << YAML::Value << traceFilename;
if (JSONFilename != "") {
out << YAML::Key << "JSONFile" << YAML::Value << JSONFilename;
if (JSONFilter == meshtastic_PortNum_TEXT_MESSAGE_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "textmessage";
else if (JSONFilter == meshtastic_PortNum_TELEMETRY_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "telemetry";
else if (JSONFilter == meshtastic_PortNum_NODEINFO_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "nodeinfo";
else if (JSONFilter == meshtastic_PortNum_POSITION_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "position";
else if (JSONFilter == meshtastic_PortNum_WAYPOINT_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "waypoint";
else if (JSONFilter == meshtastic_PortNum_NEIGHBORINFO_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "neighborinfo";
else if (JSONFilter == meshtastic_PortNum_TRACEROUTE_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "traceroute";
else if (JSONFilter == meshtastic_PortNum_DETECTION_SENSOR_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "detection";
else if (JSONFilter == meshtastic_PortNum_PAXCOUNTER_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "paxcounter";
else if (JSONFilter == meshtastic_PortNum_REMOTE_HARDWARE_APP)
out << YAML::Key << "JSONFilter" << YAML::Value << "remotehardware";
}
if (ascii_logs_explicit) {
out << YAML::Key << "AsciiLogs" << YAML::Value << ascii_logs;
}

View File

@@ -605,13 +605,12 @@ void test_receiveAcksOwnSentMessages(void)
unitTest->publish(&p, nodeDB->getNodeId().c_str());
// FIXME: Better assertion for this test
// TEST_ASSERT_TRUE(mockRouter->packets_.empty());
// TEST_ASSERT_EQUAL(1, mockRoutingModule->ackNacks_.size());
// const auto &[err, to, idFrom, chIndex, hopLimit] = mockRoutingModule->ackNacks_.front();
// TEST_ASSERT_EQUAL(meshtastic_Routing_Error_NONE, err);
// TEST_ASSERT_EQUAL(myNodeInfo.my_node_num, to);
// TEST_ASSERT_EQUAL(p.id, idFrom);
TEST_ASSERT_TRUE(mockRouter->packets_.empty());
TEST_ASSERT_EQUAL(1, mockRoutingModule->ackNacks_.size());
const auto &[err, to, idFrom, chIndex, hopLimit] = mockRoutingModule->ackNacks_.front();
TEST_ASSERT_EQUAL(meshtastic_Routing_Error_NONE, err);
TEST_ASSERT_EQUAL(myNodeInfo.my_node_num, to);
TEST_ASSERT_EQUAL(p.id, idFrom);
}
// Should ignore our own messages from MQTT that were heard by other nodes.

View File

@@ -2,7 +2,6 @@
[env:meshtastic-dr-dev]
extends = esp32_base
board = esp32doit-devkit-v1
board_level = extra
board_upload.maximum_size = 4194304
board_upload.maximum_ram_size = 532480
build_flags =

View File

@@ -2,7 +2,7 @@
[env:tbeam]
extends = esp32_base
board = ttgo-t-beam
board_level = extra
board_level = pr
board_check = true
lib_deps = ${esp32_base.lib_deps}
build_flags = ${esp32_base.build_flags}

View File

@@ -128,3 +128,6 @@ build_flags =
${crowpanel_large_esp32s3_base.build_flags}
-D VIEW_320x240
-D DISPLAY_SIZE=800x480 ; landscape mode
build_src_filter =
${esp32s3_base.build_src_filter}
+<../variants/esp32s3/elecrow_panel>

View File

@@ -0,0 +1,21 @@
// meshtastic/firmware/variants/elecrow_panel/variant.cpp
#include "variant.h"
#include "Arduino.h"
#include "Wire.h"
bool elecrow_v2 = false; // false = v1, true = v2
extern "C" {
void initVariant()
{
Wire.begin(I2C_SDA, I2C_SCL, 100000);
delay(50);
Wire.beginTransmission(0x30);
if (Wire.endTransmission() == 0) {
elecrow_v2 = true;
}
Wire.end();
}
}

View File

@@ -1,6 +1,8 @@
#define I2C_SDA 15
#define I2C_SCL 16
extern bool elecrow_v2; // false = v1, true = v2
#if CROW_SELECT == 1
#define WAKE_ON_TOUCH
#define SCREEN_TOUCH_INT 47
@@ -17,7 +19,7 @@
#define DAC_I2S_DOUT 12
#define DAC_I2S_MCLK 8 // don't use GPIO0 because it's assigned to LoRa or button
#else
#define PIN_BUZZER 8
#define PIN_BUZZER (elecrow_v2 ? 0 : 8)
#endif
// GPS via UART1 connector
@@ -72,7 +74,7 @@
#define SENSOR_POWER_ON LOW
#else
// 4.3", 5.0", 7.0"
#define LORA_CS 0
#define LORA_CS (elecrow_v2 ? 8 : 0)
#define LORA_SCK 5
#define LORA_MISO 4
#define LORA_MOSI 6

View File

@@ -1,7 +1,6 @@
[env:link32-s3-v1]
extends = esp32s3_base
board = esp32-s3-devkitc-1
board_level = extra
build_flags =
${esp32_base.build_flags}
-D LINK_32

View File

@@ -63,20 +63,9 @@ void initVariant()
// called from main-nrf52.cpp during the cpuDeepSleep() function
void variant_shutdown()
{
digitalWrite(red_LED_PIN, HIGH);
digitalWrite(green_LED_PIN, HIGH);
digitalWrite(LED_BLUE, HIGH);
digitalWrite(PIN_EN1, LOW);
digitalWrite(PIN_EN2, LOW);
digitalWrite(EEPROM_POWER, LOW);
digitalWrite(KEY_POWER, LOW);
digitalWrite(DHT_POWER, LOW);
digitalWrite(ACC_POWER, LOW);
digitalWrite(Battery_POWER, LOW);
digitalWrite(GPS_POWER, LOW);
// This sets the pin to OUTPUT and LOW for the pins *not* in the if block.
for (int pin = 0; pin < 48; pin++) {
if (pin == PIN_POWER_USB || pin == BUTTON_PIN || pin == PIN_EN1 || pin == PIN_EN2 || pin == DHT_POWER ||
pin == ACC_POWER || pin == Battery_POWER || pin == GPS_POWER || pin == LR1110_SPI_MISO_PIN ||

View File

@@ -21,8 +21,8 @@
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
//#define USE_LFXO // Board uses 32khz crystal for LF
#define USE_LFRC // Board uses RC for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/

View File

@@ -19,6 +19,7 @@ build_type = release
build_flags =
-include variants/nrf52840/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

View File

@@ -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}

View File

@@ -1,9 +1,7 @@
[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}

View File

@@ -22,7 +22,9 @@
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
//#define USE_LFXO // Board uses 32khz crystal for LF
#define USE_LFRC
/*----------------------------------------------------------------------------
* Headers

View File

@@ -1,7 +1,6 @@
[env:feather_rp2040_rfm95]
extends = rp2040_base
board = adafruit_feather
board_level = extra
upload_protocol = picotool
# add our variants files to the include and src paths
build_flags =