Compare commits

..

2 Commits

Author SHA1 Message Date
Jonathan Bennett
7cfd6f4508 Wait for location to set time 2025-12-12 21:34:22 -06:00
Austin
bf32f17f28 Actions: Compact manifest job output summary (#8957) 2025-12-13 12:32:01 +11:00
60 changed files with 286 additions and 668 deletions

View File

@@ -76,7 +76,7 @@ runs:
done done
- name: PlatformIO ${{ inputs.arch }} download cache - name: PlatformIO ${{ inputs.arch }} download cache
uses: actions/cache@v5 uses: actions/cache@v4
with: with:
path: ~/.platformio/.cache path: ~/.platformio/.cache
key: pio-cache-${{ inputs.arch }}-${{ hashFiles('.github/actions/**', '**.ini') }} key: pio-cache-${{ inputs.arch }}-${{ hashFiles('.github/actions/**', '**.ini') }}
@@ -100,7 +100,7 @@ runs:
id: version id: version
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v5
with: with:
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }} name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}
overwrite: true overwrite: true

View File

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

View File

@@ -70,7 +70,7 @@ jobs:
echo "</details>" >> $GITHUB_STEP_SUMMARY echo "</details>" >> $GITHUB_STEP_SUMMARY
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v5
id: upload id: upload
with: with:
name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }} name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}

View File

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

View File

@@ -173,7 +173,7 @@ jobs:
ref: ${{github.event.pull_request.head.ref}} ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}} repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v7 - uses: actions/download-artifact@v6
with: with:
path: ./ path: ./
pattern: firmware-${{matrix.arch}}-* pattern: firmware-${{matrix.arch}}-*
@@ -183,7 +183,7 @@ jobs:
run: ls -R run: ls -R
- name: Repackage in single firmware zip - name: Repackage in single firmware zip
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v5
with: with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }} name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true overwrite: true
@@ -200,7 +200,7 @@ jobs:
./Meshtastic_nRF52_factory_erase*.uf2 ./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30 retention-days: 30
- uses: actions/download-artifact@v7 - uses: actions/download-artifact@v6
with: with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }} name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true merge-multiple: true
@@ -219,7 +219,7 @@ jobs:
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- name: Repackage in single elfs zip - name: Repackage in single elfs zip
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v5
with: with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }} name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true overwrite: true
@@ -260,14 +260,14 @@ jobs:
Autogenerated by github action, developer should edit as required before publishing... Autogenerated by github action, developer should edit as required before publishing...
- name: Download source deb - name: Download source deb
uses: actions/download-artifact@v7 uses: actions/download-artifact@v6
with: with:
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
merge-multiple: true merge-multiple: true
path: ./output/debian-src path: ./output/debian-src
- name: Download `native-tft` pio deps - name: Download `native-tft` pio deps
uses: actions/download-artifact@v7 uses: actions/download-artifact@v6
with: with:
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }} pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
merge-multiple: true merge-multiple: true
@@ -291,7 +291,7 @@ jobs:
}' > firmware-${{ needs.version.outputs.long }}.json }' > firmware-${{ needs.version.outputs.long }}.json
- name: Save Release manifest artifact - name: Save Release manifest artifact
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v5
with: with:
name: manifest-${{ needs.version.outputs.long }} name: manifest-${{ needs.version.outputs.long }}
overwrite: true overwrite: true
@@ -332,7 +332,7 @@ jobs:
with: with:
python-version: 3.x python-version: 3.x
- uses: actions/download-artifact@v7 - uses: actions/download-artifact@v6
with: with:
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }} pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true merge-multiple: true
@@ -349,7 +349,7 @@ jobs:
- name: Zip firmware - name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- uses: actions/download-artifact@v7 - uses: actions/download-artifact@v6
with: with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }} name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true merge-multiple: true
@@ -388,14 +388,14 @@ jobs:
python-version: 3.x python-version: 3.x
- name: Get firmware artifacts - name: Get firmware artifacts
uses: actions/download-artifact@v7 uses: actions/download-artifact@v6
with: with:
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }} pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
merge-multiple: true merge-multiple: true
path: ./publish path: ./publish
- name: Get manifest artifact - name: Get manifest artifact
uses: actions/download-artifact@v7 uses: actions/download-artifact@v6
with: with:
pattern: manifest-${{ needs.version.outputs.long }} pattern: manifest-${{ needs.version.outputs.long }}
path: ./publish path: ./publish

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,14 +21,13 @@ rm -f $BUILDDIR/firmware*
export APP_VERSION=$VERSION export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION basename=firmware-$1-$VERSION
ota_basename=${basename}-ota
pio run --environment $1 -t mtjson # -v pio run --environment $1 -t mtjson # -v
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
echo "Copying NRF52 dfu (OTA) file" echo "Copying NRF52 dfu (OTA) file"
cp $BUILDDIR/$basename.zip $OUTDIR/$ota_basename.zip cp $BUILDDIR/$basename.zip $OUTDIR/$basename.zip
echo "Copying NRF52 UF2 file" echo "Copying NRF52 UF2 file"
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2 cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2

View File

@@ -184,8 +184,6 @@ Input:
Logging: Logging:
LogLevel: info # debug, info, warn, error LogLevel: info # debug, info, warn, error
# TraceFile: /var/log/meshtasticd.json # 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 # AsciiLogs: true # default if not specified is !isatty() on stdout
Webserver: Webserver:

View File

@@ -17,8 +17,6 @@ lfsbin = f"{progname.replace('firmware-', 'littlefs-')}.bin"
def manifest_gather(source, target, env): def manifest_gather(source, target, env):
out = [] out = []
board_platform = env.BoardConfig().get("platform")
needs_ota_suffix = board_platform == "nordicnrf52"
check_paths = [ check_paths = [
progname, progname,
f"{progname}.elf", f"{progname}.elf",
@@ -34,11 +32,8 @@ def manifest_gather(source, target, env):
for p in check_paths: for p in check_paths:
f = env.File(env.subst(f"$BUILD_DIR/{p}")) f = env.File(env.subst(f"$BUILD_DIR/{p}"))
if f.exists(): if f.exists():
manifest_name = p
if needs_ota_suffix and p == f"{progname}.zip":
manifest_name = f"{progname}-ota.zip"
d = { d = {
"name": manifest_name, "name": p,
"md5": f.get_content_hash(), # Returns MD5 hash "md5": f.get_content_hash(), # Returns MD5 hash
"bytes": f.get_size() # Returns file size in bytes "bytes": f.get_size() # Returns file size in bytes
} }

View File

@@ -123,7 +123,7 @@ lib_deps =
[device-ui_base] [device-ui_base]
lib_deps = lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/862ed040c4ab44f0dfbbe492691f144886102588.zip https://github.com/meshtastic/device-ui/archive/4fb5f24787caa841b58dbf623a52c4c5861d6722.zip
; Common libs for environmental measurements in telemetry module ; Common libs for environmental measurements in telemetry module
[environmental_base] [environmental_base]

View File

@@ -31,9 +31,6 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST: case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
return useShortName ? "LongF" : "LongFast"; return useShortName ? "LongF" : "LongFast";
break; break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO:
return useShortName ? "LongT" : "LongTurbo";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
return useShortName ? "LongM" : "LongMod"; return useShortName ? "LongM" : "LongMod";
break; break;

View File

@@ -1133,13 +1133,10 @@ int32_t GPS::runOnce()
// if gps_update_interval is <=10s, GPS never goes off, so we treat that differently // if gps_update_interval is <=10s, GPS never goes off, so we treat that differently
uint32_t updateInterval = Default::getConfiguredOrDefaultMs(config.position.gps_update_interval); uint32_t updateInterval = Default::getConfiguredOrDefaultMs(config.position.gps_update_interval);
// 1. Got a time for the first time // Got a time for the first time
bool gotTime = (getRTCQuality() >= RTCQualityGPS); bool gotTime = (getRTCQuality() >= RTCQualityGPS);
if (!gotTime && lookForTime()) { // Note: we count on this && short-circuiting and not resetting the RTC time
gotTime = true;
}
// 2. Got a lock for the first time, or 3. Got a lock after turning back on // Got a lock for the first time, or Got a lock after turning back on
bool gotLoc = lookForLocation(); bool gotLoc = lookForLocation();
if (gotLoc) { if (gotLoc) {
#ifdef GPS_DEBUG #ifdef GPS_DEBUG
@@ -1147,6 +1144,10 @@ int32_t GPS::runOnce()
LOG_DEBUG("hasValidLocation RISING EDGE"); LOG_DEBUG("hasValidLocation RISING EDGE");
} }
#endif #endif
if (!gotTime && lookForTime()) { // Note: we count on this && short-circuiting and not resetting the RTC time
gotTime = true;
}
if (updateInterval <= GPS_UPDATE_ALWAYS_ON_THRESHOLD_MS) { if (updateInterval <= GPS_UPDATE_ALWAYS_ON_THRESHOLD_MS) {
hasValidLocation = true; hasValidLocation = true;
shouldPublish = true; shouldPublish = true;

View File

@@ -20,41 +20,12 @@
#include "modules/KeyVerificationModule.h" #include "modules/KeyVerificationModule.h"
#include "modules/TraceRouteModule.h" #include "modules/TraceRouteModule.h"
#include <algorithm>
#include <array>
#include <functional> #include <functional>
#include <utility>
extern uint16_t TFT_MESH; extern uint16_t TFT_MESH;
namespace graphics namespace graphics
{ {
namespace
{
// Caller must ensure the provided options array outlives the banner callback.
template <typename T, size_t N, typename Callback>
BannerOverlayOptions createStaticBannerOptions(const char *message, const MenuOption<T> (&options)[N],
std::array<const char *, N> &labels, Callback &&onSelection)
{
for (size_t i = 0; i < N; ++i) {
labels[i] = options[i].label;
}
const MenuOption<T> *optionsPtr = options;
auto callback = std::function<void(const MenuOption<T> &, int)>(std::forward<Callback>(onSelection));
BannerOverlayOptions bannerOptions;
bannerOptions.message = message;
bannerOptions.optionsArrayPtr = labels.data();
bannerOptions.optionsCount = static_cast<uint8_t>(N);
bannerOptions.bannerCallback = [optionsPtr, callback](int selected) -> void { callback(optionsPtr[selected], selected); };
return bannerOptions;
}
} // namespace
menuHandler::screenMenus menuHandler::menuQueue = menu_none; menuHandler::screenMenus menuHandler::menuQueue = menu_none;
bool test_enabled = false; bool test_enabled = false;
uint8_t test_count = 0; uint8_t test_count = 0;
@@ -226,38 +197,48 @@ void menuHandler::DeviceRolePicker()
void menuHandler::RadioPresetPicker() void menuHandler::RadioPresetPicker()
{ {
static const RadioPresetOption presetOptions[] = { static const char *optionsArray[] = {"Back", "LongSlow", "LongModerate", "LongFast", "MediumSlow",
{"Back", OptionsAction::Back}, "MediumFast", "ShortSlow", "ShortFast", "ShortTurbo"};
{"LongTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO}, enum optionsNumbers {
{"LongModerate", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE}, Back = 0,
{"LongFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, radiopreset_LongSlow = 1,
{"MediumSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW}, radiopreset_LongModerate = 2,
{"MediumFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST}, radiopreset_LongFast = 3,
{"ShortSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW}, radiopreset_MediumSlow = 4,
{"ShortFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST}, radiopreset_MediumFast = 5,
{"ShortTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO}, radiopreset_ShortSlow = 6,
radiopreset_ShortFast = 7,
radiopreset_ShortTurbo = 8
};
BannerOverlayOptions bannerOptions;
bannerOptions.message = "Radio Preset";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 9;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == Back) {
menuHandler::menuQueue = menuHandler::lora_Menu;
screen->runNow();
return;
} else if (selected == radiopreset_LongSlow) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW;
} else if (selected == radiopreset_LongModerate) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE;
} else if (selected == radiopreset_LongFast) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST;
} else if (selected == radiopreset_MediumSlow) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW;
} else if (selected == radiopreset_MediumFast) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST;
} else if (selected == radiopreset_ShortSlow) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW;
} else if (selected == radiopreset_ShortFast) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST;
} else if (selected == radiopreset_ShortTurbo) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO;
}
service->reloadConfig(SEGMENT_CONFIG);
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
}; };
constexpr size_t presetCount = sizeof(presetOptions) / sizeof(presetOptions[0]);
static std::array<const char *, presetCount> presetLabels{};
auto bannerOptions =
createStaticBannerOptions("Radio Preset", presetOptions, presetLabels, [](const RadioPresetOption &option, int) -> void {
if (option.action == OptionsAction::Back) {
menuHandler::menuQueue = menuHandler::lora_Menu;
screen->runNow();
return;
}
if (!option.hasValue) {
return;
}
config.lora.modem_preset = option.value;
service->reloadConfig(SEGMENT_CONFIG);
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
});
screen->showOverlayBanner(bannerOptions); screen->showOverlayBanner(bannerOptions);
} }

View File

@@ -99,24 +99,5 @@ class menuHandler
static void BluetoothToggleMenu(); static void BluetoothToggleMenu();
}; };
/* Generic Menu Options designations */
enum class OptionsAction { Back, Select };
template <typename T> struct MenuOption {
const char *label;
OptionsAction action;
bool hasValue;
T value;
MenuOption(const char *labelIn, OptionsAction actionIn, T valueIn)
: label(labelIn), action(actionIn), hasValue(true), value(valueIn)
{
}
MenuOption(const char *labelIn, OptionsAction actionIn) : label(labelIn), action(actionIn), hasValue(false), value() {}
};
using RadioPresetOption = MenuOption<meshtastic_Config_LoRaConfig_ModemPreset>;
} // namespace graphics } // namespace graphics
#endif #endif

View File

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

View File

@@ -3,9 +3,6 @@
#include "RotaryEncoderImpl.h" #include "RotaryEncoderImpl.h"
#include "InputBroker.h" #include "InputBroker.h"
#include "RotaryEncoder.h" #include "RotaryEncoder.h"
#ifdef ARCH_ESP32
#include "sleep.h"
#endif
#define ORIGIN_NAME "RotaryEncoder" #define ORIGIN_NAME "RotaryEncoder"
@@ -14,20 +11,6 @@ RotaryEncoderImpl *rotaryEncoderImpl;
RotaryEncoderImpl::RotaryEncoderImpl() RotaryEncoderImpl::RotaryEncoderImpl()
{ {
rotary = nullptr; 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() bool RotaryEncoderImpl::init()
@@ -42,22 +25,15 @@ bool RotaryEncoderImpl::init()
eventCcw = static_cast<input_broker_event>(moduleConfig.canned_message.inputbroker_event_ccw); eventCcw = static_cast<input_broker_event>(moduleConfig.canned_message.inputbroker_event_ccw);
eventPressed = static_cast<input_broker_event>(moduleConfig.canned_message.inputbroker_event_press); 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,
rotary = new RotaryEncoder(moduleConfig.canned_message.inputbroker_pin_a, moduleConfig.canned_message.inputbroker_pin_b, moduleConfig.canned_message.inputbroker_pin_press);
moduleConfig.canned_message.inputbroker_pin_press); rotary->resetButton();
}
attachRotaryEncoderInterrupts(); interruptInstance = this;
auto interruptHandler = []() { inputBroker->requestPollSoon(interruptInstance); };
#ifdef ARCH_ESP32 attachInterrupt(moduleConfig.canned_message.inputbroker_pin_a, interruptHandler, CHANGE);
// Register callbacks for before and after lightsleep attachInterrupt(moduleConfig.canned_message.inputbroker_pin_b, interruptHandler, CHANGE);
// Used to detach and reattach interrupts attachInterrupt(moduleConfig.canned_message.inputbroker_pin_press, interruptHandler, CHANGE);
if (isFirstInit) {
lsObserver.observe(&notifyLightSleep);
lsEndObserver.observe(&notifyLightSleepEnd);
isFirstInit = false;
}
#endif
LOG_INFO("RotaryEncoder initialized pins(%d, %d, %d), events(%d, %d, %d)", moduleConfig.canned_message.inputbroker_pin_a, 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, 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; RotaryEncoderImpl *RotaryEncoderImpl::interruptInstance;
#endif #endif

View File

@@ -8,18 +8,12 @@
class RotaryEncoder; class RotaryEncoder;
class RotaryEncoderImpl final : public InputPollable class RotaryEncoderImpl : public InputPollable
{ {
public: public:
RotaryEncoderImpl(); RotaryEncoderImpl();
~RotaryEncoderImpl() override; bool init(void);
bool init();
virtual void pollOnce() override; 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: protected:
static RotaryEncoderImpl *interruptInstance; static RotaryEncoderImpl *interruptInstance;
@@ -29,21 +23,6 @@ class RotaryEncoderImpl final : public InputPollable
input_broker_event eventPressed = INPUT_BROKER_NONE; input_broker_event eventPressed = INPUT_BROKER_NONE;
RotaryEncoder *rotary; 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; extern RotaryEncoderImpl *rotaryEncoderImpl;

View File

@@ -440,11 +440,9 @@ void setup()
LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n"); LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n");
#if defined(ARCH_ESP32) && defined(BOARD_HAS_PSRAM) #if defined(ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
#ifndef SENSECAP_INDICATOR
// use PSRAM for malloc calls > 256 bytes // use PSRAM for malloc calls > 256 bytes
heap_caps_malloc_extmem_enable(256); heap_caps_malloc_extmem_enable(256);
#endif #endif
#endif
#if defined(DEBUG_MUTE) && defined(DEBUG_PORT) #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("\r\n\r\n//\\ E S H T /\\ S T / C\r\n");

View File

@@ -124,10 +124,6 @@ void FloodingRouter::perhapsCancelDupe(const meshtastic_MeshPacket *p)
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE && iface) { if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE && iface) {
iface->clampToLateRebroadcastWindow(getFrom(p), p->id); iface->clampToLateRebroadcastWindow(getFrom(p), p->id);
} }
if (config.device.role == meshtastic_Config_DeviceConfig_Role_CLIENT_BASE && iface && nodeDB &&
nodeDB->isFromOrToFavoritedNode(*p)) {
iface->clampToLateRebroadcastWindow(getFrom(p), p->id);
}
} }
bool FloodingRouter::isRebroadcaster() bool FloodingRouter::isRebroadcaster()

View File

@@ -276,10 +276,6 @@ bool MeshService::trySendPosition(NodeNum dest, bool wantReplies)
if (nodeDB->hasValidPosition(node)) { if (nodeDB->hasValidPosition(node)) {
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS #if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
if (positionModule) { if (positionModule) {
if (!config.position.fixed_position && !nodeDB->hasLocalPositionSinceBoot()) {
LOG_DEBUG("Skip position ping; no fresh position since boot");
return false;
}
LOG_INFO("Send position ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel); LOG_INFO("Send position ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel);
positionModule->sendOurPosition(dest, wantReplies, node->channel); positionModule->sendOurPosition(dest, wantReplies, node->channel);
return true; return true;

View File

@@ -805,11 +805,11 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.external_notification.output_ms = 500; moduleConfig.external_notification.output_ms = 500;
moduleConfig.external_notification.nag_timeout = 2; moduleConfig.external_notification.nag_timeout = 2;
#endif #endif
#if defined(RAK4630) || defined(RAK11310) || defined(RAK3312) || defined(MUZI_BASE) || defined(ELECROW_ThinkNode_M3) #if defined(RAK4630) || defined(RAK11310) || defined(RAK3312) || defined(MUZI_BASE)
// Default to PIN_LED2 for external notification output (LED color depends on device variant) // Default to RAK led pin 2 (blue)
moduleConfig.external_notification.enabled = true; moduleConfig.external_notification.enabled = true;
moduleConfig.external_notification.output = PIN_LED2; moduleConfig.external_notification.output = PIN_LED2;
#if defined(MUZI_BASE) || defined(ELECROW_ThinkNode_M3) #if defined(MUZI_BASE)
moduleConfig.external_notification.active = false; moduleConfig.external_notification.active = false;
#else #else
moduleConfig.external_notification.active = true; moduleConfig.external_notification.active = true;
@@ -1043,7 +1043,6 @@ void NodeDB::clearLocalPosition()
node->position.altitude = 0; node->position.altitude = 0;
node->position.time = 0; node->position.time = 0;
setLocalPosition(meshtastic_Position_init_default); setLocalPosition(meshtastic_Position_init_default);
localPositionUpdatedSinceBoot = false;
} }
void NodeDB::cleanupMeshDB() void NodeDB::cleanupMeshDB()

View File

@@ -279,13 +279,9 @@ class NodeDB
LOG_DEBUG("Set local position: lat=%i lon=%i time=%u timestamp=%u", position.latitude_i, position.longitude_i, LOG_DEBUG("Set local position: lat=%i lon=%i time=%u timestamp=%u", position.latitude_i, position.longitude_i,
position.time, position.timestamp); position.time, position.timestamp);
localPosition = position; localPosition = position;
if (position.latitude_i != 0 || position.longitude_i != 0) {
localPositionUpdatedSinceBoot = true;
}
} }
bool hasValidPosition(const meshtastic_NodeInfoLite *n); bool hasValidPosition(const meshtastic_NodeInfoLite *n);
bool hasLocalPositionSinceBoot() const { return localPositionUpdatedSinceBoot; }
#if !defined(MESHTASTIC_EXCLUDE_PKI) #if !defined(MESHTASTIC_EXCLUDE_PKI)
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest); bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
@@ -305,7 +301,6 @@ class NodeDB
private: private:
bool duplicateWarned = false; bool duplicateWarned = false;
bool localPositionUpdatedSinceBoot = false;
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually
uint32_t lastSort = 0; // When last sorted the nodeDB uint32_t lastSort = 0; // When last sorted the nodeDB

View File

@@ -296,6 +296,11 @@ bool RadioInterface::shouldRebroadcastEarlyLikeRouter(meshtastic_MeshPacket *p)
return true; return true;
} }
// If we are a CLIENT_BASE and the packet is from or to a favorited node, we should rebroadcast early
if (config.device.role == meshtastic_Config_DeviceConfig_Role_CLIENT_BASE) {
return nodeDB->isFromOrToFavoritedNode(*p);
}
return false; return false;
} }
@@ -498,11 +503,6 @@ void RadioInterface::applyModemConfig()
cr = 5; cr = 5;
sf = 10; sf = 10;
break; break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO:
bw = (myRegion->wideLora) ? 1625.0 : 500;
cr = 8;
sf = 11;
break;
default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal. default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal.
bw = (myRegion->wideLora) ? 812.5 : 250; bw = (myRegion->wideLora) ? 812.5 : 250;
cr = 5; cr = 5;
@@ -539,26 +539,13 @@ void RadioInterface::applyModemConfig()
} }
if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) { if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) {
const float regionSpanKHz = (myRegion->freqEnd - myRegion->freqStart) * 1000.0f; static const char *err_string = "Regional frequency range is smaller than bandwidth. Fall back to default preset";
const float requestedBwKHz = bw; LOG_ERROR(err_string);
const bool isWideRequest = requestedBwKHz >= 499.5f; // treat as 500 kHz preset
const char *presetName =
DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset);
char err_string[160];
if (isWideRequest) {
snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to LongFast.",
myRegion->name, presetName);
} else {
snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to LongFast.",
myRegion->name, regionSpanKHz, requestedBwKHz);
}
LOG_ERROR("%s", err_string);
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_ERROR; cn->level = meshtastic_LogRecord_Level_ERROR;
snprintf(cn->message, sizeof(cn->message), "%s", err_string); sprintf(cn->message, err_string);
service->sendClientNotification(cn); service->sendClientNotification(cn);
// Set to default modem preset // Set to default modem preset

View File

@@ -526,10 +526,6 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
if (portduino_config.traceFilename != "" || portduino_config.logoutputlevel == level_trace) { if (portduino_config.traceFilename != "" || portduino_config.logoutputlevel == level_trace) {
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str()); 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 #endif
return DecodeState::DECODE_SUCCESS; return DecodeState::DECODE_SUCCESS;

View File

@@ -293,8 +293,7 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
typedef enum _meshtastic_Config_LoRaConfig_ModemPreset { typedef enum _meshtastic_Config_LoRaConfig_ModemPreset {
/* Long Range - Fast */ /* Long Range - Fast */
meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST = 0, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST = 0,
/* Long Range - Slow /* Long Range - Slow */
Deprecated in 2.7: Unpopular slow preset. */
meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW = 1, meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW = 1,
/* Very Long Range - Slow /* Very Long Range - Slow
Deprecated in 2.5: Works only with txco and is unusably slow */ Deprecated in 2.5: Works only with txco and is unusably slow */
@@ -312,10 +311,7 @@ typedef enum _meshtastic_Config_LoRaConfig_ModemPreset {
/* Short Range - Turbo /* Short Range - Turbo
This is the fastest preset and the only one with 500kHz bandwidth. This is the fastest preset and the only one with 500kHz bandwidth.
It is not legal to use in all regions due to this wider bandwidth. */ It is not legal to use in all regions due to this wider bandwidth. */
meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO = 8, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO = 8
/* Long Range - Turbo
This preset performs similarly to LongFast, but with 500Khz bandwidth. */
meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO = 9
} meshtastic_Config_LoRaConfig_ModemPreset; } meshtastic_Config_LoRaConfig_ModemPreset;
typedef enum _meshtastic_Config_BluetoothConfig_PairingMode { typedef enum _meshtastic_Config_BluetoothConfig_PairingMode {
@@ -693,8 +689,8 @@ extern "C" {
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_BR_902+1)) #define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_BR_902+1))
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST #define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO #define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO
#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO+1)) #define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO+1))
#define _meshtastic_Config_BluetoothConfig_PairingMode_MIN meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN #define _meshtastic_Config_BluetoothConfig_PairingMode_MIN meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN
#define _meshtastic_Config_BluetoothConfig_PairingMode_MAX meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN #define _meshtastic_Config_BluetoothConfig_PairingMode_MAX meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN

View File

@@ -417,9 +417,6 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
} }
case meshtastic_AdminMessage_enter_dfu_mode_request_tag: { case meshtastic_AdminMessage_enter_dfu_mode_request_tag: {
LOG_INFO("Client requesting to enter DFU mode"); LOG_INFO("Client requesting to enter DFU mode");
#if HAS_SCREEN
IF_SCREEN(screen->showSimpleBanner("Device is rebooting\ninto DFU mode.", 0));
#endif
#if defined(ARCH_NRF52) || defined(ARCH_RP2040) #if defined(ARCH_NRF52) || defined(ARCH_RP2040)
enterDfuMode(); enterDfuMode();
#endif #endif

View File

@@ -7,41 +7,17 @@
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#include <Throttle.h> #include <Throttle.h>
#include <algorithm>
#ifndef USERPREFS_NODEINFO_REPLY_SUPPRESS_SECS
#define USERPREFS_NODEINFO_REPLY_SUPPRESS_SECS (12 * 60 * 60)
#endif
NodeInfoModule *nodeInfoModule; NodeInfoModule *nodeInfoModule;
static constexpr uint32_t NodeInfoReplySuppressSeconds = USERPREFS_NODEINFO_REPLY_SUPPRESS_SECS;
bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *pptr) bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *pptr)
{ {
suppressReplyForCurrentRequest = false;
if (mp.from == nodeDB->getNodeNum()) { if (mp.from == nodeDB->getNodeNum()) {
LOG_WARN("Ignoring packet supposed to be from our own node: %08x", mp.from); LOG_WARN("Ignoring packet supposed to be from our own node: %08x", mp.from);
return false; return false;
} }
auto p = *pptr; auto p = *pptr;
if (mp.decoded.want_response) {
const NodeNum sender = getFrom(&mp);
const uint32_t now = mp.rx_time ? mp.rx_time : getTime();
auto it = lastNodeInfoSeen.find(sender);
if (it != lastNodeInfoSeen.end()) {
uint32_t sinceLast = now >= it->second ? now - it->second : 0;
if (sinceLast < NodeInfoReplySuppressSeconds) {
suppressReplyForCurrentRequest = true;
}
}
lastNodeInfoSeen[sender] = now;
pruneLastNodeInfoCache();
}
if (p.is_licensed != owner.is_licensed) { if (p.is_licensed != owner.is_licensed) {
LOG_WARN("Invalid nodeInfo detected, is_licensed mismatch!"); LOG_WARN("Invalid nodeInfo detected, is_licensed mismatch!");
return true; return true;
@@ -66,8 +42,6 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
service->sendToPhone(packetCopy); service->sendToPhone(packetCopy);
} }
pruneLastNodeInfoCache();
// LOG_DEBUG("did handleReceived"); // LOG_DEBUG("did handleReceived");
return false; // Let others look at this message also if they want return false; // Let others look at this message also if they want
} }
@@ -94,11 +68,9 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
if (p) { // Check whether we didn't ignore it if (p) { // Check whether we didn't ignore it
p->to = dest; p->to = dest;
bool requestWantResponse = (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER && p->decoded.want_response = (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) && config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
wantReplies; wantReplies;
p->decoded.want_response = requestWantResponse;
if (_shorterTimeout) if (_shorterTimeout)
p->priority = meshtastic_MeshPacket_Priority_DEFAULT; p->priority = meshtastic_MeshPacket_Priority_DEFAULT;
else else
@@ -117,13 +89,6 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
meshtastic_MeshPacket *NodeInfoModule::allocReply() meshtastic_MeshPacket *NodeInfoModule::allocReply()
{ {
if (suppressReplyForCurrentRequest) {
LOG_DEBUG("Skip send NodeInfo since we heard the requester <12h ago");
ignoreRequest = true;
suppressReplyForCurrentRequest = false;
return NULL;
}
if (!airTime->isTxAllowedChannelUtil(false)) { if (!airTime->isTxAllowedChannelUtil(false)) {
ignoreRequest = true; // Mark it as ignored for MeshModule ignoreRequest = true; // Mark it as ignored for MeshModule
LOG_DEBUG("Skip send NodeInfo > 40%% ch. util"); LOG_DEBUG("Skip send NodeInfo > 40%% ch. util");
@@ -160,29 +125,6 @@ meshtastic_MeshPacket *NodeInfoModule::allocReply()
} }
} }
void NodeInfoModule::pruneLastNodeInfoCache()
{
if (!nodeDB || !nodeDB->meshNodes)
return;
const size_t maxEntries = nodeDB->meshNodes->size();
for (auto it = lastNodeInfoSeen.begin(); it != lastNodeInfoSeen.end();) {
if (!nodeDB->getMeshNode(it->first)) {
it = lastNodeInfoSeen.erase(it);
} else {
++it;
}
}
while (!lastNodeInfoSeen.empty() && lastNodeInfoSeen.size() > maxEntries) {
auto oldestIt = std::min_element(lastNodeInfoSeen.begin(), lastNodeInfoSeen.end(),
[](const std::pair<const NodeNum, uint32_t> &lhs,
const std::pair<const NodeNum, uint32_t> &rhs) { return lhs.second < rhs.second; });
lastNodeInfoSeen.erase(oldestIt);
}
}
NodeInfoModule::NodeInfoModule() NodeInfoModule::NodeInfoModule()
: ProtobufModule("nodeinfo", meshtastic_PortNum_NODEINFO_APP, &meshtastic_User_msg), concurrency::OSThread("NodeInfo") : ProtobufModule("nodeinfo", meshtastic_PortNum_NODEINFO_APP, &meshtastic_User_msg), concurrency::OSThread("NodeInfo")
{ {

View File

@@ -1,6 +1,5 @@
#pragma once #pragma once
#include "ProtobufModule.h" #include "ProtobufModule.h"
#include <map>
/** /**
* NodeInfo module for sending/receiving NodeInfos into the mesh * NodeInfo module for sending/receiving NodeInfos into the mesh
@@ -44,10 +43,6 @@ class NodeInfoModule : public ProtobufModule<meshtastic_User>, private concurren
private: private:
uint32_t lastSentToMesh = 0; // Last time we sent our NodeInfo to the mesh uint32_t lastSentToMesh = 0; // Last time we sent our NodeInfo to the mesh
bool shorterTimeout = false; bool shorterTimeout = false;
bool suppressReplyForCurrentRequest = false;
std::map<NodeNum, uint32_t> lastNodeInfoSeen;
void pruneLastNodeInfoCache();
}; };
extern NodeInfoModule *nodeInfoModule; extern NodeInfoModule *nodeInfoModule;

View File

@@ -349,11 +349,6 @@ void PositionModule::sendOurPosition()
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel) void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
{ {
if (!config.position.fixed_position && !nodeDB->hasLocalPositionSinceBoot()) {
LOG_DEBUG("Skip position send; no fresh position since boot");
return;
}
// cancel any not yet sent (now stale) position packets // cancel any not yet sent (now stale) position packets
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal) if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
service->cancelSending(prevPacketId); service->cancelSending(prevPacketId);
@@ -425,14 +420,8 @@ int32_t PositionModule::runOnce()
return RUNONCE_INTERVAL; return RUNONCE_INTERVAL;
} }
bool waitingForFreshPosition = (lastGpsSend == 0) && !config.position.fixed_position && !nodeDB->hasLocalPositionSinceBoot();
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) { if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
if (waitingForFreshPosition) { if (nodeDB->hasValidPosition(node)) {
#ifdef GPS_DEBUG
LOG_DEBUG("Skip initial position send; no fresh position since boot");
#endif
} else if (nodeDB->hasValidPosition(node)) {
lastGpsSend = now; lastGpsSend = now;
lastGpsLatitude = node->position.latitude_i; lastGpsLatitude = node->position.latitude_i;

View File

@@ -20,17 +20,13 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
switch (arg->getStatusType()) { switch (arg->getStatusType()) {
case STATUS_TYPE_POWER: { case STATUS_TYPE_POWER: {
meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg; meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg;
if (powerStatus->getHasUSB() || powerStatus->getIsCharging()) { if (powerStatus->getHasUSB()) {
power_state = charging; power_state = charging;
if (powerStatus->getBatteryChargePercent() >= 100) { if (powerStatus->getBatteryChargePercent() >= 100) {
power_state = charged; power_state = charged;
} }
} else { } else {
if (powerStatus->getBatteryChargePercent() > 5) { power_state = discharging;
power_state = discharging;
} else {
power_state = critical;
}
} }
break; break;
} }
@@ -62,33 +58,16 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
int32_t StatusLEDModule::runOnce() int32_t StatusLEDModule::runOnce()
{ {
my_interval = 1000;
if (power_state == charging) { if (power_state == charging) {
CHARGE_LED_state = !CHARGE_LED_state; CHARGE_LED_state = !CHARGE_LED_state;
} else if (power_state == charged) { } else if (power_state == charged) {
CHARGE_LED_state = LED_STATE_ON; CHARGE_LED_state = LED_STATE_ON;
} else if (power_state == critical) {
if (POWER_LED_starttime + 30000 < millis() && !doing_fast_blink) {
doing_fast_blink = true;
POWER_LED_starttime = millis();
}
if (doing_fast_blink) {
PAIRING_LED_state = LED_STATE_OFF;
CHARGE_LED_state = !CHARGE_LED_state;
my_interval = 250;
if (POWER_LED_starttime + 2000 < millis()) {
doing_fast_blink = false;
}
} else {
CHARGE_LED_state = LED_STATE_OFF;
}
} else { } else {
CHARGE_LED_state = LED_STATE_OFF; CHARGE_LED_state = LED_STATE_OFF;
} }
if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis() || doing_fast_blink) { if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis()) {
PAIRING_LED_state = LED_STATE_OFF; PAIRING_LED_state = LED_STATE_OFF;
} else if (ble_state == unpaired) { } else if (ble_state == unpaired) {
if (slowTrack) { if (slowTrack) {

View File

@@ -31,10 +31,8 @@ class StatusLEDModule : private concurrency::OSThread
bool PAIRING_LED_state = LED_STATE_OFF; bool PAIRING_LED_state = LED_STATE_OFF;
uint32_t PAIRING_LED_starttime = 0; uint32_t PAIRING_LED_starttime = 0;
uint32_t POWER_LED_starttime = 0;
bool doing_fast_blink = false;
enum PowerState { discharging, charging, charged, critical }; enum PowerState { discharging, charging, charged };
PowerState power_state = discharging; PowerState power_state = discharging;

View File

@@ -14,11 +14,11 @@
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
#ifdef NIMBLE_TWO
#include "NimBLEAdvertising.h" #include "NimBLEAdvertising.h"
#ifdef CONFIG_BT_NIMBLE_EXT_ADV
#include "NimBLEExtAdvertising.h" #include "NimBLEExtAdvertising.h"
#endif
#include "PowerStatus.h" #include "PowerStatus.h"
#endif
#if defined(CONFIG_NIMBLE_CPP_IDF) #if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_gap.h" #include "host/ble_gap.h"
@@ -26,15 +26,7 @@
#include "nimble/nimble/host/include/host/ble_gap.h" #include "nimble/nimble/host/include/host/ble_gap.h"
#endif #endif
#ifdef ARCH_ESP32 #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_store.h"
#else
#include "nimble/nimble/host/include/host/ble_store.h"
#endif
#include <nvs.h>
#include <nvs_flash.h>
#endif
namespace namespace
{ {
@@ -42,71 +34,6 @@ constexpr uint16_t kPreferredBleMtu = 517;
constexpr uint16_t kPreferredBleTxOctets = 251; constexpr uint16_t kPreferredBleTxOctets = 251;
constexpr uint16_t kPreferredBleTxTimeUs = (kPreferredBleTxOctets + 14) * 8; constexpr uint16_t kPreferredBleTxTimeUs = (kPreferredBleTxOctets + 14) * 8;
} // namespace } // namespace
#ifdef ARCH_ESP32
// Credit: https://github.com/h2zero/NimBLE-Arduino/issues/740#issuecomment-2539923656
// Note: Despite the name, this function is invoked on every device boot (from setup()).
// It performs a routine startup check on the stored NimBLE bond data and deletes bonds
// only if a mismatch or migration condition is detected. It is not a one-time hook that
// runs only when the NimBLE version changes.
static void deleteBondsIfNimBLEVersionChanged()
{
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
err = nvs_flash_erase();
if (err != ESP_OK) {
LOG_ERROR("Failed to erase NVS for NimBLE migration, err=%d", err);
return;
}
err = nvs_flash_init();
if (err != ESP_OK) {
LOG_ERROR("Failed to re-init NVS after erase, err=%d", err);
return;
}
} else if (err != ESP_OK) {
LOG_ERROR("nvs_flash_init failed, err=%d", err);
return;
}
nvs_handle_t nimbleHandle = 0;
err = nvs_open("nimble_bond", NVS_READWRITE, &nimbleHandle);
if (err == ESP_ERR_NVS_NOT_FOUND) {
return;
}
if (err != ESP_OK) {
LOG_ERROR("Failed to open nimble_bond namespace, err=%d", err);
return;
}
size_t requiredSize = 0;
bool bondExists = nvs_get_blob(nimbleHandle, "peer_sec_1", nullptr, &requiredSize) == ESP_OK;
bool rpaExists = nvs_get_blob(nimbleHandle, "rpa_rec_1", nullptr, &requiredSize) == ESP_OK;
bool irkExists = nvs_get_blob(nimbleHandle, "local_irk_1", nullptr, &requiredSize) == ESP_OK;
bool erasePartition = false;
#if defined(BLE_STORE_OBJ_TYPE_LOCAL_IRK)
erasePartition = bondExists && !rpaExists;
#else
erasePartition = rpaExists || irkExists;
#endif
bool restartRequired = false;
if (erasePartition) {
LOG_WARN("Clearing NimBLE bonds due to version migration");
if (nvs_erase_all(nimbleHandle) != ESP_OK || nvs_commit(nimbleHandle) != ESP_OK) {
LOG_ERROR("Failed to erase nimble_bond namespace");
} else {
restartRequired = true;
}
}
nvs_close(nimbleHandle);
if (restartRequired) {
LOG_INFO("Restarting after NimBLE bond cleanup");
ESP.restart();
}
}
#endif #endif
// Debugging options: careful, they slow things down quite a bit! // Debugging options: careful, they slow things down quite a bit!
@@ -386,9 +313,11 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
{ {
PhoneAPI::onNowHasData(fromRadioNum); PhoneAPI::onNowHasData(fromRadioNum);
#ifdef DEBUG_NIMBLE_NOTIFY
int currentNotifyCount = notifyCount.fetch_add(1); int currentNotifyCount = notifyCount.fetch_add(1);
uint8_t cc = bleServer->getConnectedCount(); uint8_t cc = bleServer->getConnectedCount();
#ifdef DEBUG_NIMBLE_NOTIFY
// This logging slows things down when there are lots of packets going to the phone, like initial connection: // This logging slows things down when there are lots of packets going to the phone, like initial connection:
LOG_DEBUG("BLE notify(%d) fromNum: %d connections: %d", currentNotifyCount, fromRadioNum, cc); LOG_DEBUG("BLE notify(%d) fromNum: %d connections: %d", currentNotifyCount, fromRadioNum, cc);
#endif #endif
@@ -397,7 +326,13 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
put_le32(val, fromRadioNum); put_le32(val, fromRadioNum);
fromNumCharacteristic->setValue(val, sizeof(val)); fromNumCharacteristic->setValue(val, sizeof(val));
#ifdef NIMBLE_TWO
// NOTE: I don't have any NIMBLE_TWO devices, but this line makes me suspicious, and I suspect it needs to just be
// notify().
fromNumCharacteristic->notify(val, sizeof(val), BLE_HS_CONN_HANDLE_NONE); fromNumCharacteristic->notify(val, sizeof(val), BLE_HS_CONN_HANDLE_NONE);
#else
fromNumCharacteristic->notify();
#endif
} }
/// Check the current underlying physical link to see if the client is currently connected /// Check the current underlying physical link to see if the client is currently connected
@@ -462,7 +397,12 @@ static uint8_t lastToRadio[MAX_TO_FROM_RADIO_SIZE];
class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
{ {
void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &) override #ifdef NIMBLE_TWO
virtual void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo)
#else
virtual void onWrite(NimBLECharacteristic *pCharacteristic)
#endif
{ {
// CAUTION: This callback runs in the NimBLE task!!! Don't do anything except communicate with the main task's runOnce. // CAUTION: This callback runs in the NimBLE task!!! Don't do anything except communicate with the main task's runOnce.
// Assumption: onWrite is serialized by NimBLE, so we don't need to lock here against multiple concurrent onWrite calls. // Assumption: onWrite is serialized by NimBLE, so we don't need to lock here against multiple concurrent onWrite calls.
@@ -509,7 +449,11 @@ class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
{ {
void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &) override #ifdef NIMBLE_TWO
virtual void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo)
#else
virtual void onRead(NimBLECharacteristic *pCharacteristic)
#endif
{ {
// CAUTION: This callback runs in the NimBLE task!!! Don't do anything except communicate with the main task's runOnce. // CAUTION: This callback runs in the NimBLE task!!! Don't do anything except communicate with the main task's runOnce.
@@ -617,27 +561,32 @@ class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
class NimbleBluetoothServerCallback : public NimBLEServerCallbacks class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
{ {
#ifdef NIMBLE_TWO
public: public:
explicit NimbleBluetoothServerCallback(NimbleBluetooth *ble) : ble(ble) {} NimbleBluetoothServerCallback(NimbleBluetooth *ble) { this->ble = ble; }
private: private:
NimbleBluetooth *ble; NimbleBluetooth *ble;
uint32_t onPassKeyDisplay() override virtual uint32_t onPassKeyDisplay()
#else
virtual uint32_t onPassKeyRequest()
#endif
{ {
uint32_t passkey = config.bluetooth.fixed_pin; uint32_t passkey = config.bluetooth.fixed_pin;
if (config.bluetooth.mode == meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN) { if (config.bluetooth.mode == meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN) {
LOG_INFO("Use random passkey"); LOG_INFO("Use random passkey");
// This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
passkey = random(100000, 999999); passkey = random(100000, 999999);
} }
LOG_INFO("*** Enter passkey %06u on the peer side ***", passkey); LOG_INFO("*** Enter passkey %d on the peer side ***", passkey);
powerFSM.trigger(EVENT_BLUETOOTH_PAIR); powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
meshtastic::BluetoothStatus newStatus(std::to_string(passkey)); meshtastic::BluetoothStatus newStatus(std::to_string(passkey));
bluetoothStatus->updateStatus(&newStatus); bluetoothStatus->updateStatus(&newStatus);
#if HAS_SCREEN #if HAS_SCREEN // Todo: migrate this display code back into Screen class, and observe bluetoothStatus
if (screen) { if (screen) {
screen->startAlert([passkey](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void { screen->startAlert([passkey](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
char btPIN[16] = "888888"; char btPIN[16] = "888888";
@@ -666,29 +615,39 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
}); });
} }
#endif #endif
passkeyShowing = true; passkeyShowing = true;
return passkey; return passkey;
} }
void onAuthenticationComplete(NimBLEConnInfo &connInfo) override #ifdef NIMBLE_TWO
virtual void onAuthenticationComplete(NimBLEConnInfo &connInfo)
#else
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc)
#endif
{ {
LOG_INFO("BLE authentication complete"); LOG_INFO("BLE authentication complete");
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::CONNECTED); meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::CONNECTED);
bluetoothStatus->updateStatus(&newStatus); bluetoothStatus->updateStatus(&newStatus);
// Todo: migrate this display code back into Screen class, and observe bluetoothStatus
if (passkeyShowing) { if (passkeyShowing) {
passkeyShowing = false; passkeyShowing = false;
if (screen) { if (screen)
screen->endAlert(); screen->endAlert();
}
} }
// Store the connection handle for future use
#ifdef NIMBLE_TWO
nimbleBluetoothConnHandle = connInfo.getConnHandle(); nimbleBluetoothConnHandle = connInfo.getConnHandle();
#else
nimbleBluetoothConnHandle = desc->conn_handle;
#endif
} }
void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo) override #ifdef NIMBLE_TWO
virtual void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo)
{ {
LOG_INFO("BLE incoming connection %s", connInfo.getAddress().toString().c_str()); LOG_INFO("BLE incoming connection %s", connInfo.getAddress().toString().c_str());
@@ -713,12 +672,21 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
LOG_INFO("BLE conn %u initial MTU %u (target %u)", connHandle, connInfo.getMTU(), kPreferredBleMtu); LOG_INFO("BLE conn %u initial MTU %u (target %u)", connHandle, connInfo.getMTU(), kPreferredBleMtu);
pServer->updateConnParams(connHandle, 6, 12, 0, 200); pServer->updateConnParams(connHandle, 6, 12, 0, 200);
} }
#endif
void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) override #ifdef NIMBLE_TWO
virtual void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason)
{ {
LOG_INFO("BLE disconnect reason: %d", reason); LOG_INFO("BLE disconnect reason: %d", reason);
#else
virtual void onDisconnect(NimBLEServer *pServer, ble_gap_conn_desc *desc)
{
LOG_INFO("BLE disconnect");
#endif
#ifdef NIMBLE_TWO
if (ble->isDeInit) if (ble->isDeInit)
return; return;
#endif
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED); meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED);
bluetoothStatus->updateStatus(&newStatus); bluetoothStatus->updateStatus(&newStatus);
@@ -742,69 +710,35 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
bluetoothPhoneAPI->writeCount = 0; bluetoothPhoneAPI->writeCount = 0;
} }
// Clear the last ToRadio packet buffer to avoid rejecting first packet from new connection
memset(lastToRadio, 0, sizeof(lastToRadio)); memset(lastToRadio, 0, sizeof(lastToRadio));
nimbleBluetoothConnHandle = BLE_HS_CONN_HANDLE_NONE; nimbleBluetoothConnHandle = BLE_HS_CONN_HANDLE_NONE; // BLE_HS_CONN_HANDLE_NONE means "no connection"
#ifdef NIMBLE_TWO
// Restart Advertising
ble->startAdvertising(); ble->startAdvertising();
#else
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
if (!pAdvertising->start(0)) {
if (pAdvertising->isAdvertising()) {
LOG_DEBUG("BLE advertising already running");
} else {
LOG_ERROR("BLE failed to restart advertising");
}
}
#endif
} }
}; };
static NimbleBluetoothToRadioCallback *toRadioCallbacks; static NimbleBluetoothToRadioCallback *toRadioCallbacks;
static NimbleBluetoothFromRadioCallback *fromRadioCallbacks; static NimbleBluetoothFromRadioCallback *fromRadioCallbacks;
void NimbleBluetooth::startAdvertising()
{
#if defined(CONFIG_BT_NIMBLE_EXT_ADV)
NimBLEExtAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
NimBLEExtAdvertisement legacyAdvertising;
legacyAdvertising.setLegacyAdvertising(true);
legacyAdvertising.setScannable(true);
legacyAdvertising.setConnectable(true);
legacyAdvertising.setFlags(BLE_HS_ADV_F_DISC_GEN);
if (powerStatus->getHasBattery() == 1) {
legacyAdvertising.setCompleteServices(NimBLEUUID((uint16_t)0x180f));
}
legacyAdvertising.setCompleteServices(NimBLEUUID(MESH_SERVICE_UUID));
legacyAdvertising.setMinInterval(500);
legacyAdvertising.setMaxInterval(1000);
NimBLEExtAdvertisement legacyScanResponse;
legacyScanResponse.setLegacyAdvertising(true);
legacyScanResponse.setConnectable(true);
legacyScanResponse.setName(getDeviceName());
if (!pAdvertising->setInstanceData(0, legacyAdvertising)) {
LOG_ERROR("BLE failed to set legacyAdvertising");
} else if (!pAdvertising->setScanResponseData(0, legacyScanResponse)) {
LOG_ERROR("BLE failed to set legacyScanResponse");
} else if (!pAdvertising->start(0, 0, 0)) {
LOG_ERROR("BLE failed to start legacyAdvertising");
}
#else
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset();
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
if (powerStatus->getHasBattery() == 1) {
pAdvertising->addServiceUUID(NimBLEUUID((uint16_t)0x180f));
}
NimBLEAdvertisementData scan;
scan.setName(getDeviceName());
pAdvertising->setScanResponseData(scan);
pAdvertising->enableScanResponse(true);
if (!pAdvertising->start(0)) {
LOG_ERROR("BLE failed to start advertising");
}
#endif
LOG_DEBUG("BLE Advertising started");
}
void NimbleBluetooth::shutdown() void NimbleBluetooth::shutdown()
{ {
// No measurable power saving for ESP32 during light-sleep(?)
#ifndef ARCH_ESP32 #ifndef ARCH_ESP32
// Shutdown bluetooth for minimum power draw
LOG_INFO("Disable bluetooth"); LOG_INFO("Disable bluetooth");
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset(); pAdvertising->reset();
@@ -812,6 +746,7 @@ void NimbleBluetooth::shutdown()
#endif #endif
} }
// Proper shutdown for ESP32. Needs reboot to reverse.
void NimbleBluetooth::deinit() void NimbleBluetooth::deinit()
{ {
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
@@ -825,17 +760,21 @@ void NimbleBluetooth::deinit()
digitalWrite(BLE_LED, LOW); digitalWrite(BLE_LED, LOW);
#endif #endif
#endif #endif
#ifndef NIMBLE_TWO
NimBLEDevice::deinit();
#endif
#endif #endif
} }
// Has initial setup been completed
bool NimbleBluetooth::isActive() bool NimbleBluetooth::isActive()
{ {
return bleServer != nullptr; return bleServer;
} }
bool NimbleBluetooth::isConnected() bool NimbleBluetooth::isConnected()
{ {
return bleServer && bleServer->getConnectedCount() > 0; return bleServer->getConnectedCount() > 0;
} }
int NimbleBluetooth::getRssi() int NimbleBluetooth::getRssi()
@@ -876,14 +815,10 @@ void NimbleBluetooth::setup()
// Uncomment for testing // Uncomment for testing
// NimbleBluetooth::clearBonds(); // NimbleBluetooth::clearBonds();
#ifdef ARCH_ESP32
deleteBondsIfNimBLEVersionChanged();
#endif
LOG_INFO("Init the NimBLE bluetooth module"); LOG_INFO("Init the NimBLE bluetooth module");
NimBLEDevice::init(getDeviceName()); NimBLEDevice::init(getDeviceName());
NimBLEDevice::setPower(9); NimBLEDevice::setPower(ESP_PWR_LVL_P9);
#if NIMBLE_ENABLE_2M_PHY && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)) #if NIMBLE_ENABLE_2M_PHY && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6))
int mtuResult = NimBLEDevice::setMTU(kPreferredBleMtu); int mtuResult = NimBLEDevice::setMTU(kPreferredBleMtu);
@@ -916,7 +851,11 @@ void NimbleBluetooth::setup()
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY); NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
} }
bleServer = NimBLEDevice::createServer(); bleServer = NimBLEDevice::createServer();
auto *serverCallbacks = new NimbleBluetoothServerCallback(this); #ifdef NIMBLE_TWO
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback(this);
#else
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback();
#endif
bleServer->setCallbacks(serverCallbacks, true); bleServer->setCallbacks(serverCallbacks, true);
setupService(); setupService();
startAdvertising(); startAdvertising();
@@ -961,7 +900,11 @@ void NimbleBluetooth::setupService()
NimBLEService *batteryService = bleServer->createService(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service NimBLEService *batteryService = bleServer->createService(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic) BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic)
(uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY, 1); (uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY, 1);
#ifdef NIMBLE_TWO
NimBLE2904 *batteryLevelDescriptor = BatteryCharacteristic->create2904(); NimBLE2904 *batteryLevelDescriptor = BatteryCharacteristic->create2904();
#else
NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->createDescriptor((uint16_t)0x2904);
#endif
batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8); batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8);
batteryLevelDescriptor->setNamespace(1); batteryLevelDescriptor->setNamespace(1);
batteryLevelDescriptor->setUnit(0x27ad); batteryLevelDescriptor->setUnit(0x27ad);
@@ -969,12 +912,54 @@ void NimbleBluetooth::setupService()
batteryService->start(); batteryService->start();
} }
void NimbleBluetooth::startAdvertising()
{
#ifdef NIMBLE_TWO
NimBLEExtAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
NimBLEExtAdvertisement legacyAdvertising;
legacyAdvertising.setLegacyAdvertising(true);
legacyAdvertising.setScannable(true);
legacyAdvertising.setConnectable(true);
legacyAdvertising.setFlags(BLE_HS_ADV_F_DISC_GEN);
if (powerStatus->getHasBattery() == 1) {
legacyAdvertising.setCompleteServices(NimBLEUUID((uint16_t)0x180f));
}
legacyAdvertising.setCompleteServices(NimBLEUUID(MESH_SERVICE_UUID));
legacyAdvertising.setMinInterval(500);
legacyAdvertising.setMaxInterval(1000);
NimBLEExtAdvertisement legacyScanResponse;
legacyScanResponse.setLegacyAdvertising(true);
legacyScanResponse.setConnectable(true);
legacyScanResponse.setName(getDeviceName());
if (!pAdvertising->setInstanceData(0, legacyAdvertising)) {
LOG_ERROR("BLE failed to set legacyAdvertising");
} else if (!pAdvertising->setScanResponseData(0, legacyScanResponse)) {
LOG_ERROR("BLE failed to set legacyScanResponse");
} else if (!pAdvertising->start(0, 0, 0)) {
LOG_ERROR("BLE failed to start legacyAdvertising");
}
#else
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset();
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
pAdvertising->addServiceUUID(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
pAdvertising->start(0);
#endif
}
/// Given a level between 0-100, update the BLE attribute /// Given a level between 0-100, update the BLE attribute
void updateBatteryLevel(uint8_t level) void updateBatteryLevel(uint8_t level)
{ {
if ((config.bluetooth.enabled == true) && bleServer && nimbleBluetooth->isConnected()) { if ((config.bluetooth.enabled == true) && bleServer && nimbleBluetooth->isConnected()) {
BatteryCharacteristic->setValue(&level, 1); BatteryCharacteristic->setValue(&level, 1);
#ifdef NIMBLE_TWO
BatteryCharacteristic->notify(&level, 1, BLE_HS_CONN_HANDLE_NONE); BatteryCharacteristic->notify(&level, 1, BLE_HS_CONN_HANDLE_NONE);
#else
BatteryCharacteristic->notify();
#endif
} }
} }
@@ -989,7 +974,11 @@ void NimbleBluetooth::sendLog(const uint8_t *logMessage, size_t length)
if (!bleServer || !isConnected() || length > 512) { if (!bleServer || !isConnected() || length > 512) {
return; return;
} }
#ifdef NIMBLE_TWO
logRadioCharacteristic->notify(logMessage, length, BLE_HS_CONN_HANDLE_NONE); logRadioCharacteristic->notify(logMessage, length, BLE_HS_CONN_HANDLE_NONE);
#else
logRadioCharacteristic->notify(logMessage, length, true);
#endif
} }
void clearNVS() void clearNVS()

View File

@@ -12,11 +12,16 @@ class NimbleBluetooth : BluetoothApi
bool isConnected(); bool isConnected();
int getRssi(); int getRssi();
void sendLog(const uint8_t *logMessage, size_t length); void sendLog(const uint8_t *logMessage, size_t length);
#if defined(NIMBLE_TWO)
void startAdvertising(); void startAdvertising();
#endif
bool isDeInit = false; bool isDeInit = false;
private: private:
void setupService(); void setupService();
#if !defined(NIMBLE_TWO)
void startAdvertising();
#endif
}; };
void setBluetoothEnable(bool enable); void setBluetoothEnable(bool enable);

View File

@@ -29,7 +29,6 @@
portduino_config_struct portduino_config; portduino_config_struct portduino_config;
std::ofstream traceFile; std::ofstream traceFile;
std::ofstream JSONFile;
Ch341Hal *ch341Hal = nullptr; Ch341Hal *ch341Hal = nullptr;
char *configPath = nullptr; char *configPath = nullptr;
char *optionMac = nullptr; char *optionMac = nullptr;
@@ -464,7 +463,6 @@ void portduinoSetup()
if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") { if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") {
SPI.begin(portduino_config.lora_spi_dev.c_str()); SPI.begin(portduino_config.lora_spi_dev.c_str());
} }
if (portduino_config.traceFilename != "") { if (portduino_config.traceFilename != "") {
try { try {
traceFile.open(portduino_config.traceFilename, std::ios::out | std::ios::app); 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; std::cout << "*** traceFile Exception " << e.what() << std::endl;
exit(EXIT_FAILURE); 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) { if (verboseEnabled && portduino_config.logoutputlevel != level_trace) {
portduino_config.logoutputlevel = level_debug; portduino_config.logoutputlevel = level_debug;
@@ -534,29 +517,6 @@ bool loadConfig(const char *configPath)
portduino_config.logoutputlevel = level_error; portduino_config.logoutputlevel = level_error;
} }
portduino_config.traceFilename = yamlConfig["Logging"]["TraceFile"].as<std::string>(""); 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"]) { if (yamlConfig["Logging"]["AsciiLogs"]) {
// Default is !isatty(1) but can be set explicitly in config.yaml // Default is !isatty(1) but can be set explicitly in config.yaml
portduino_config.ascii_logs = yamlConfig["Logging"]["AsciiLogs"].as<bool>(); portduino_config.ascii_logs = yamlConfig["Logging"]["AsciiLogs"].as<bool>();

View File

@@ -5,7 +5,6 @@
#include "LR11x0Interface.h" #include "LR11x0Interface.h"
#include "Module.h" #include "Module.h"
#include "mesh/generated/meshtastic/mesh.pb.h"
#include "platform/portduino/USBHal.h" #include "platform/portduino/USBHal.h"
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
@@ -47,8 +46,6 @@ struct pinMapping {
}; };
extern std::ofstream traceFile; extern std::ofstream traceFile;
extern std::ofstream JSONFile;
extern Ch341Hal *ch341Hal; extern Ch341Hal *ch341Hal;
int initGPIOPin(int pinNum, std::string gpioChipname, int line); int initGPIOPin(int pinNum, std::string gpioChipname, int line);
bool loadConfig(const char *configPath); bool loadConfig(const char *configPath);
@@ -151,9 +148,6 @@ extern struct portduino_config_struct {
bool ascii_logs = !isatty(1); bool ascii_logs = !isatty(1);
bool ascii_logs_explicit = false; bool ascii_logs_explicit = false;
std::string JSONFilename;
meshtastic_PortNum JSONFilter = (_meshtastic_PortNum)0;
// Webserver // Webserver
std::string webserver_root_path = ""; std::string webserver_root_path = "";
std::string webserver_ssl_key_path = "/etc/meshtasticd/ssl/private_key.pem"; std::string webserver_ssl_key_path = "/etc/meshtasticd/ssl/private_key.pem";
@@ -419,29 +413,6 @@ extern struct portduino_config_struct {
} }
if (traceFilename != "") if (traceFilename != "")
out << YAML::Key << "TraceFile" << YAML::Value << 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) { if (ascii_logs_explicit) {
out << YAML::Key << "AsciiLogs" << YAML::Value << ascii_logs; 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()); unitTest->publish(&p, nodeDB->getNodeId().c_str());
// FIXME: Better assertion for this test TEST_ASSERT_TRUE(mockRouter->packets_.empty());
// TEST_ASSERT_TRUE(mockRouter->packets_.empty()); TEST_ASSERT_EQUAL(1, mockRoutingModule->ackNacks_.size());
// TEST_ASSERT_EQUAL(1, mockRoutingModule->ackNacks_.size()); const auto &[err, to, idFrom, chIndex, hopLimit] = mockRoutingModule->ackNacks_.front();
// const auto &[err, to, idFrom, chIndex, hopLimit] = mockRoutingModule->ackNacks_.front(); TEST_ASSERT_EQUAL(meshtastic_Routing_Error_NONE, err);
// TEST_ASSERT_EQUAL(meshtastic_Routing_Error_NONE, err); TEST_ASSERT_EQUAL(myNodeInfo.my_node_num, to);
// TEST_ASSERT_EQUAL(myNodeInfo.my_node_num, to); TEST_ASSERT_EQUAL(p.id, idFrom);
// TEST_ASSERT_EQUAL(p.id, idFrom);
} }
// Should ignore our own messages from MQTT that were heard by other nodes. // Should ignore our own messages from MQTT that were heard by other nodes.

View File

@@ -55,7 +55,6 @@
// "USERPREFS_MQTT_TLS_ENABLED": "false", // "USERPREFS_MQTT_TLS_ENABLED": "false",
// "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME", // "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME",
// "USERPREFS_RINGTONE_NAG_SECS": "60", // "USERPREFS_RINGTONE_NAG_SECS": "60",
// "USERPREFS_NODEINFO_REPLY_SUPPRESS_SECS": "43200",
"USERPREFS_RINGTONE_RTTTL": "24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p", "USERPREFS_RINGTONE_RTTTL": "24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p",
// "USERPREFS_NETWORK_IPV6_ENABLED": "1", // "USERPREFS_NETWORK_IPV6_ENABLED": "1",
"USERPREFS_TZ_STRING": "tzplaceholder " "USERPREFS_TZ_STRING": "tzplaceholder "

View File

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

View File

@@ -38,7 +38,6 @@ build_flags =
-DAXP_DEBUG_PORT=Serial -DAXP_DEBUG_PORT=Serial
-DCONFIG_BT_NIMBLE_ENABLED -DCONFIG_BT_NIMBLE_ENABLED
-DCONFIG_BT_NIMBLE_MAX_BONDS=6 # default is 3 -DCONFIG_BT_NIMBLE_MAX_BONDS=6 # default is 3
-DCONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2 -DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192 -DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192
@@ -60,7 +59,7 @@ lib_deps =
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master # 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 https://github.com/meshtastic/esp32_https_server/archive/3223704846752e6d545139204837bdb2a55459ca.zip
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino # renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
h2zero/NimBLE-Arduino@^2.3.7 h2zero/NimBLE-Arduino@^1.4.3
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master # renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
# renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib # renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib

View File

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

View File

@@ -4,8 +4,3 @@ custom_esp32_kind = esp32c3
monitor_speed = 115200 monitor_speed = 115200
monitor_filters = esp32_c3_exception_decoder monitor_filters = esp32_c3_exception_decoder
build_flags =
${esp32_base.build_flags}
-DCONFIG_BT_NIMBLE_EXT_ADV=1
-DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2

View File

@@ -13,7 +13,7 @@ build_unflags =
lib_deps = lib_deps =
${esp32c6_base.lib_deps} ${esp32c6_base.lib_deps}
adafruit/Adafruit NeoPixel@^1.12.3 adafruit/Adafruit NeoPixel@^1.12.3
h2zero/NimBLE-Arduino@^2.3.7 h2zero/NimBLE-Arduino@^2.3.6
build_flags = build_flags =
${esp32c6_base.build_flags} ${esp32c6_base.build_flags}
-D M5STACK_UNITC6L -D M5STACK_UNITC6L
@@ -24,6 +24,7 @@ build_flags =
-D HAS_BLUETOOTH=1 -D HAS_BLUETOOTH=1
-DCONFIG_BT_NIMBLE_EXT_ADV=1 -DCONFIG_BT_NIMBLE_EXT_ADV=1
-DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2 -DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2
-D NIMBLE_TWO
monitor_speed=115200 monitor_speed=115200
lib_ignore = lib_ignore =
NonBlockingRTTTL NonBlockingRTTTL

View File

@@ -3,8 +3,3 @@ extends = esp32_base
custom_esp32_kind = esp32s3 custom_esp32_kind = esp32s3
monitor_speed = 115200 monitor_speed = 115200
build_flags =
${esp32_base.build_flags}
-DCONFIG_BT_NIMBLE_EXT_ADV=1
-DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2

View File

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

View File

@@ -63,20 +63,9 @@ void initVariant()
// called from main-nrf52.cpp during the cpuDeepSleep() function // called from main-nrf52.cpp during the cpuDeepSleep() function
void variant_shutdown() 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(EEPROM_POWER, LOW);
digitalWrite(KEY_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++) { for (int pin = 0; pin < 48; pin++) {
if (pin == PIN_POWER_USB || pin == BUTTON_PIN || pin == PIN_EN1 || pin == PIN_EN2 || pin == DHT_POWER || 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 || pin == ACC_POWER || pin == Battery_POWER || pin == GPS_POWER || pin == LR1110_SPI_MISO_PIN ||

View File

@@ -54,7 +54,6 @@ extern "C" {
#define LED_POWER red_LED_PIN #define LED_POWER red_LED_PIN
#define LED_CHARGE LED_POWER // Signals the Status LED Module to handle this LED #define LED_CHARGE LED_POWER // Signals the Status LED Module to handle this LED
#define green_LED_PIN 35 #define green_LED_PIN 35
#define PIN_LED2 green_LED_PIN
#define LED_BLUE 37 #define LED_BLUE 37
#define LED_PAIRING LED_BLUE // Signals the Status LED Module to handle this LED #define LED_PAIRING LED_BLUE // Signals the Status LED Module to handle this LED

View File

@@ -19,6 +19,7 @@ build_type = release
build_flags = build_flags =
-include variants/nrf52840/cpp_overrides/lfs_util.h -include variants/nrf52840/cpp_overrides/lfs_util.h
${arduino_base.build_flags} ${arduino_base.build_flags}
-DSERIAL_BUFFER_SIZE=1024
-Wno-unused-variable -Wno-unused-variable
-Isrc/platform/nrf52 -Isrc/platform/nrf52
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818 -DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818

View File

@@ -1,9 +1,7 @@
[nrf52832_base] [nrf52832_base]
extends = nrf52_base extends = nrf52_base
build_flags = build_flags = ${nrf52_base.build_flags}
${nrf52_base.build_flags}
-DSERIAL_BUFFER_SIZE=1024
lib_deps = lib_deps =
${nrf52_base.lib_deps} ${nrf52_base.lib_deps}

View File

@@ -1,9 +1,7 @@
[nrf52840_base] [nrf52840_base]
extends = nrf52_base extends = nrf52_base
build_flags = build_flags = ${nrf52_base.build_flags}
${nrf52_base.build_flags}
-DSERIAL_BUFFER_SIZE=4096
lib_deps = lib_deps =
${nrf52_base.lib_deps} ${nrf52_base.lib_deps}

View File

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

View File

@@ -2,12 +2,12 @@
[rp2040_base] [rp2040_base]
platform = platform =
# TODO renovate # TODO renovate
https://github.com/maxgerhardt/platform-raspberrypi#cc24cfef37ed22ca9f2a6aead28c2deb76c39f24 https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
; For arduino-pico >= 5.4.4 ; For arduino-pico >= 4.4.3
extends = arduino_base extends = arduino_base
platform_packages = platform_packages =
# TODO renovate # TODO renovate
arduino-pico@https://github.com/earlephilhower/arduino-pico/releases/download/5.4.4/rp2040-5.4.4.zip framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
board_build.core = earlephilhower board_build.core = earlephilhower
board_build.filesystem_size = 0.5m board_build.filesystem_size = 0.5m
@@ -17,7 +17,6 @@ build_flags =
-Isrc/platform/rp2xx0/hardware_rosc/include -Isrc/platform/rp2xx0/hardware_rosc/include
-Isrc/platform/rp2xx0/pico_sleep/include -Isrc/platform/rp2xx0/pico_sleep/include
-D__PLAT_RP2040__ -D__PLAT_RP2040__
-D__FREERTOS=1
# -D _POSIX_THREADS # -D _POSIX_THREADS
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp> ${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>

View File

@@ -2,12 +2,12 @@
[rp2350_base] [rp2350_base]
platform = platform =
# TODO renovate # TODO renovate
https://github.com/maxgerhardt/platform-raspberrypi#cc24cfef37ed22ca9f2a6aead28c2deb76c39f24 https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
; For arduino-pico >= 5.4.4 ; For arduino-pico >= 4.4.3
extends = arduino_base extends = arduino_base
platform_packages = platform_packages =
# TODO renovate # TODO renovate
arduino-pico@https://github.com/earlephilhower/arduino-pico/releases/download/5.4.4/rp2040-5.4.4.zip framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
board_build.core = earlephilhower board_build.core = earlephilhower
board_build.filesystem_size = 0.5m board_build.filesystem_size = 0.5m
@@ -15,7 +15,6 @@ build_flags =
${arduino_base.build_flags} -Wno-unused-variable -Wcast-align ${arduino_base.build_flags} -Wno-unused-variable -Wcast-align
-Isrc/platform/rp2xx0 -Isrc/platform/rp2xx0
-D__PLAT_RP2350__ -D__PLAT_RP2350__
-D__FREERTOS=1
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp> -<platform/rp2xx0/pico_sleep> -<platform/rp2xx0/hardware_rosc> ${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp> -<platform/rp2xx0/pico_sleep> -<platform/rp2xx0/hardware_rosc>