diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh index 0b2665f84..7c7487cc8 100755 --- a/.devcontainer/setup.sh +++ b/.devcontainer/setup.sh @@ -1,3 +1,6 @@ #!/usr/bin/env sh git submodule update --init + +pip install --no-cache-dir setuptools +pipx install esptool diff --git a/.gitattributes b/.gitattributes index 584097061..79d1800fc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ * text=auto eol=lf *.{cmd,[cC][mM][dD]} text eol=crlf *.{bat,[bB][aA][tT]} text eol=crlf +*.{ps1,[pP][sS]} text eol=crlf *.{sh,[sS][hH]} text eol=lf diff --git a/.github/workflows/build_debian_src.yml b/.github/workflows/build_debian_src.yml index 714542047..5c441f085 100644 --- a/.github/workflows/build_debian_src.yml +++ b/.github/workflows/build_debian_src.yml @@ -4,7 +4,7 @@ on: workflow_call: secrets: PPA_GPG_PRIVATE_KEY: - required: true + required: false inputs: series: description: Ubuntu/Debian series to target diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index da4b4e6f3..5b11926f2 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -136,6 +136,7 @@ jobs: secrets: inherit package-pio-deps-native-tft: + if: ${{ github.event_name == 'workflow_dispatch' }} uses: ./.github/workflows/package_pio_deps.yml with: pio_env: native-tft @@ -329,13 +330,13 @@ jobs: with: pattern: platformio-deps-native-tft-${{ steps.version.outputs.long }} merge-multiple: true - path: ./output/pio-deps-native + path: ./output/pio-deps-native-tft - name: Zip linux sources working-directory: output run: | zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src - zip -9 -r ./platformio-deps-native-${{ steps.version.outputs.long }}.zip ./pio-deps-native + zip -9 -r ./platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip ./pio-deps-native-tft # For diagnostics - name: Display structure of downloaded files @@ -344,32 +345,10 @@ jobs: - name: Add linux sources to release run: | gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip - gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-${{ steps.version.outputs.long }}.zip + gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Bump version.properties - run: >- - bin/bump_version.py - - - name: Ensure debian deps are installed - shell: bash - run: | - sudo apt-get update -y --fix-missing - sudo apt-get install -y devscripts - - - name: Update debian changelog - run: >- - debian/ci_changelog.sh - - - name: Create version.properties pull request - uses: peter-evans/create-pull-request@v7 - with: - title: Bump version.properties - add-paths: | - version.properties - debian/changelog - release-firmware: strategy: fail-fast: false diff --git a/.github/workflows/release_channels.yml b/.github/workflows/release_channels.yml index 9cdabde9e..710e8e51d 100644 --- a/.github/workflows/release_channels.yml +++ b/.github/workflows/release_channels.yml @@ -43,3 +43,49 @@ jobs: copr_project: |- ${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }} secrets: inherit + + # Create a PR to bump version when a release is Published + bump-version: + if: ${{ github.event.release.published }} + runs-on: ubuntu-latest + permissions: + pull-requests: write + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + + - name: Get release version string + run: | + echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT + echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT + id: version + env: + BUILD_LOCATION: local + + - name: Bump version.properties + run: >- + bin/bump_version.py + + - name: Ensure debian deps are installed + shell: bash + run: | + sudo apt-get update -y --fix-missing + sudo apt-get install -y devscripts + + - name: Update debian changelog + run: >- + debian/ci_changelog.sh + + - name: Create version.properties pull request + uses: peter-evans/create-pull-request@v7 + with: + title: Bump version.properties + add-paths: | + version.properties + debian/changelog diff --git a/.github/workflows/sec_sast_semgrep_cron.yml b/.github/workflows/sec_sast_semgrep_cron.yml index 944103562..db308c9f5 100644 --- a/.github/workflows/sec_sast_semgrep_cron.yml +++ b/.github/workflows/sec_sast_semgrep_cron.yml @@ -6,11 +6,14 @@ on: schedule: - cron: 0 1 * * 6 -permissions: read-all +permissions: + actions: read + contents: read + security-events: write jobs: semgrep-full: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 container: image: semgrep/semgrep diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index b1df7e417..85211b0f2 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,12 +9,12 @@ plugins: lint: enabled: - prettier@3.5.3 - - trufflehog@3.88.14 + - trufflehog@3.88.15 - yamllint@1.35.1 - bandit@1.8.3 - - checkov@3.2.379 + - checkov@3.2.382 - terrascan@1.19.9 - - trivy@0.59.1 + - trivy@0.60.0 - taplo@0.9.3 - ruff@0.9.9 - isort@6.0.1 diff --git a/.vscode/settings.json b/.vscode/settings.json index bf9b82111..81deca8f9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,8 @@ "cmake.configureOnOpen": false, "[cpp]": { "editor.defaultFormatter": "trunk.io" + }, + "[powershell]": { + "editor.defaultFormatter": "ms-vscode.powershell" } } diff --git a/bin/device-install.bat b/bin/device-install.bat index 4d13d9f3b..926338464 100755 --- a/bin/device-install.bat +++ b/bin/device-install.bat @@ -1,149 +1,296 @@ @ECHO OFF SETLOCAL EnableDelayedExpansion -set "SCRIPTNAME=%~nx0" -set "PYTHON=python" -set "WEB_APP=0" -set "TFT8=0" -set "TFT16=0" -SET "TFT_BUILD=0" -SET "DO_SPECIAL_OTA=0" +TITLE Meshtastic device-install -:: Determine the correct esptool command to use -where esptool >nul 2>&1 -if %ERRORLEVEL% EQU 0 ( - set "ESPTOOL_CMD=esptool" -) else ( - set "ESPTOOL_CMD=%PYTHON% -m esptool" -) - -goto GETOPTS -:HELP -echo Usage: %SCRIPTNAME% [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME] [--web] [--tft] [--tft-16mb] -echo Flash image file to device, but first erasing and writing system information -echo. -echo -h Display this help and exit -echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous). -echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%) -echo -f FILENAME The .bin file to flash. Custom to your device type and region. -echo --web Flash WEB APP. -echo --tft Flash MUI 8mb -echo --tft-16mb Flash MUI 16mb -goto EOF - -:GETOPTS -if /I "%~1"=="-h" goto HELP & exit /b -if /I "%~1"=="--help" goto HELP & exit /b -if "%~1"=="-p" set "ESPTOOL_PORT=%~2" & SHIFT & SHIFT & goto GETOPTS -if "%~1"=="-P" set "PYTHON=%~2" & SHIFT & SHIFT & goto GETOPTS -if /I "%~1"=="-f" set "FILENAME=%~2" & SHIFT & SHIFT & goto GETOPTS -if /I "%~1"=="--web" set "WEB_APP=1" & SHIFT & goto GETOPTS -if /I "%~1"=="--tft" set "TFT8=1" & SHIFT & goto GETOPTS -if /I "%~1"=="--tft-16mb" set "TFT16=1" & SHIFT & goto GETOPTS -SHIFT -IF NOT "%~1"=="" goto GETOPTS - -IF "__%FILENAME%__" == "____" ( - echo "Missing FILENAME" - goto HELP -) - -:: Check if FILENAME contains "-tft-" and either TFT8 or TFT16 is 1 (--tft, -tft-16mb) -IF NOT "%FILENAME:-tft-=%"=="%FILENAME%" ( - SET "TFT_BUILD=1" - IF NOT "%TFT8%"=="1" IF NOT "%TFT16%"=="1" ( - echo Error: Either --tft or --tft-16mb must be set to use a TFT build. - goto EOF - ) - IF "%TFT8%"=="1" IF "%TFT16%"=="1" ( - echo Error: Both --tft and --tft-16mb must NOT be set at the same time. - goto EOF - ) -) - -:: Extract BASENAME from %FILENAME% for later use. -SET BASENAME=%FILENAME:firmware-=% - -IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% ( - @REM Default littlefs* offset (--web). - SET "OFFSET=0x300000" - - @REM Default OTA Offset - SET "OTA_OFFSET=0x260000" - - @REM littlefs* offset for MUI 8mb (--tft) and OTA OFFSET. - IF "%TFT8%"=="1" IF "%TFT_BUILD%"=="1" ( - SET "OFFSET=0x670000" - SET "OTA_OFFSET=0x340000" - ) else ( - echo Ignoring --tft, not a TFT Build. - ) - - @REM littlefs* offset for MUI 16mb (--tft-16mb) and OTA OFFSET. - IF "%TFT16%"=="1" IF "%TFT_BUILD%"=="1" ( - SET "OFFSET=0xc90000" - SET "OTA_OFFSET=0x650000" - ) else ( - echo Ignoring --tft-16mb, not a TFT Build. - ) - - echo Trying to flash update %FILENAME%, but first erasing and writing system information" - %ESPTOOL_CMD% --baud 115200 erase_flash - %ESPTOOL_CMD% --baud 115200 write_flash 0x00 "%FILENAME%" - - @REM Account for S3 and C3 board's different OTA partition - IF NOT "%FILENAME%"=="%FILENAME:s3=%" SET "DO_SPECIAL_OTA=1" - IF NOT "%FILENAME%"=="%FILENAME:v3=%" SET "DO_SPECIAL_OTA=1" - IF NOT "%FILENAME%"=="%FILENAME:t-deck=%" SET "DO_SPECIAL_OTA=1" - IF NOT "%FILENAME%"=="%FILENAME:wireless-paper=%" SET "DO_SPECIAL_OTA=1" - IF NOT "%FILENAME%"=="%FILENAME:wireless-tracker=%" SET "DO_SPECIAL_OTA=1" - IF NOT "%FILENAME%"=="%FILENAME:station-g2=%" SET "DO_SPECIAL_OTA=1" - IF NOT "%FILENAME%"=="%FILENAME:unphone=%" SET "DO_SPECIAL_OTA=1" - IF NOT "%FILENAME%"=="%FILENAME:esp32c3=%" SET "DO_SPECIAL_OTA=1" - - IF "!DO_SPECIAL_OTA!"=="1" ( - IF NOT "%FILENAME%"=="%FILENAME:esp32c3=%" ( - %ESPTOOL_CMD% --baud 115200 write_flash !OTA_OFFSET! bleota-c3.bin - ) ELSE ( - %ESPTOOL_CMD% --baud 115200 write_flash !OTA_OFFSET! bleota-s3.bin - ) - ) ELSE ( - %ESPTOOL_CMD% --baud 115200 write_flash !OTA_OFFSET! bleota.bin - ) - - @REM Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-". - IF "%WEB_APP%"=="1" ( - @REM Check it the file exist before trying to write it. - IF EXIST "littlefswebui-%BASENAME%" ( - %ESPTOOL_CMD% --baud 115200 write_flash !OFFSET! "littlefswebui-%BASENAME%" - ) else ( - echo Error: file "littlefswebui-%BASENAME%" wasn't found, littlefswebui not written. - goto EOF - ) - ) else ( - @REM Check it the file exist before trying to write it. - IF EXIST "littlefs-%BASENAME%" ( - %ESPTOOL_CMD% --baud 115200 write_flash !OFFSET! "littlefs-%BASENAME%" - ) else ( - echo Error: file "littlefs-%BASENAME%" wasn't found, littlefs not written. - goto EOF - ) - ) -) else ( - echo "Invalid file: %FILENAME%" - goto HELP -) - -:EOF -@REM Cleanup vars. -SET "SCRIPTNAME=" +SET "SCRIPT_NAME=%~nx0" +SET "DEBUG=0" SET "PYTHON=" -SET "WEB_APP=" -SET "TFT8=" -Set "TFT16=" -SET "OFFSET=" -SET "OTA_OFFSET=" -SET "DO_SPECIAL_OTA=" -SET "FILENAME=" -SET "BASENAME=" -endlocal -exit /b 0 \ No newline at end of file +SET "WEB_APP=0" +SET "TFT_BUILD=0" +SET "TFT8=0" +SET "TFT16=0" +SET "ESPTOOL_BAUD=115200" +SET "ESPTOOL_CMD=" +SET "LOGCOUNTER=0" + +GOTO getopts +:help +ECHO Flash image file to device, but first erasing and writing system information. +ECHO. +ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] (--web) +ECHO. +ECHO Options: +ECHO -f filename The firmware .bin file to flash. Custom to your device type and region. (required) +ECHO The file must be located in this current directory. +ECHO -p PORT Set the environment variable for ESPTOOL_PORT. +ECHO If not set, ESPTOOL iterates all ports (Dangerous). +ECHO -P python Specify alternate python interpreter to use to invoke esptool. (default: python) +ECHO If supplied the script will use python. +ECHO If not supplied the script will try to find esptool in Path. +ECHO --web Enable WebUI. (default: false) +ECHO. +ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4.bin -p COM11 +ECHO Example: %SCRIPT_NAME% -f firmware-unphone-2.6.0.0b106d4.bin -p COM11 --web +GOTO eof + +:version +ECHO %SCRIPT_NAME% [Version 2.6.0] +ECHO Meshtastic +GOTO eof + +:getopts +IF "%~1"=="" GOTO endopts +IF /I "%~1"=="-?" GOTO help +IF /I "%~1"=="-h" GOTO help +IF /I "%~1"=="--help" GOTO help +IF /I "%~1"=="-v" GOTO version +IF /I "%~1"=="--version" GOTO version +IF /I "%~1"=="--debug" SET "DEBUG=1" & CALL :LOG_MESSAGE DEBUG "DEBUG mode: enabled." +IF /I "%~1"=="-f" SET "FILENAME=%~2" & SHIFT +IF "%~1"=="-p" SET "ESPTOOL_PORT=%~2" & SHIFT +IF /I "%~1"=="--port" SET "ESPTOOL_PORT=%~2" & SHIFT +IF "%~1"=="-P" SET "PYTHON=%~2" & SHIFT +IF /I "%~1"=="--web" SET "WEB_APP=1" +SHIFT +GOTO getopts +:endopts + +CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..." +IF "__!FILENAME!__"=="____" ( + CALL :LOG_MESSAGE DEBUG "Missing -f filename input." + GOTO help +) ELSE ( + CALL :LOG_MESSAGE DEBUG "Filename: !FILENAME!" + IF NOT "__!FILENAME: =!__"=="__!FILENAME!__" ( + CALL :LOG_MESSAGE ERROR "Filename containing spaces are not supported." + GOTO help + ) + IF "__!FILENAME:firmware-=!__"=="__!FILENAME!__" ( + CALL :LOG_MESSAGE ERROR "Filename must be a firmware-* file." + GOTO help + ) + @REM Remove ".\" or "./" file prefix if present. + SET "FILENAME=!FILENAME:.\=!" + SET "FILENAME=!FILENAME:./=!" +) + +CALL :LOG_MESSAGE DEBUG "Checking if !FILENAME! exists..." +IF NOT EXIST !FILENAME! ( + CALL :LOG_MESSAGE ERROR "File does not exist: !FILENAME!. Terminating." + GOTO eof +) + +IF NOT "!FILENAME:update=!"=="!FILENAME!" ( + CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!" + CALL :LOG_MESSAGE INFO "Use script device-update.bat to flash update !FILENAME!." + GOTO eof +) ELSE ( + CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!" +) + +CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..." +IF NOT "__%PYTHON%__"=="____" ( + SET "ESPTOOL_CMD=!PYTHON! -m esptool" + CALL :LOG_MESSAGE DEBUG "Python interpreter supplied." +) ELSE ( + CALL :LOG_MESSAGE DEBUG "Python interpreter NOT supplied. Looking for esptool... + WHERE esptool >nul 2>&1 + IF %ERRORLEVEL% EQU 0 ( + @REM WHERE exits with code 0 if esptool is found. + SET "ESPTOOL_CMD=esptool" + ) ELSE ( + SET "ESPTOOL_CMD=python -m esptool" + CALL :RESET_ERROR + ) +) + +CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..." +!ESPTOOL_CMD! >nul 2>&1 +IF %ERRORLEVEL% GTR 2 ( + @REM esptool exits with code 1 if help is displayed. + CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!" + EXIT /B 1 + GOTO eof +) +IF %DEBUG% EQU 1 ( + CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps." + SET "ESPTOOL_CMD=REM !ESPTOOL_CMD!" +) + +CALL :LOG_MESSAGE DEBUG "Using esptool command: !ESPTOOL_CMD!" +IF "__!ESPTOOL_PORT!__" == "____" ( + CALL :LOG_MESSAGE WARN "Using esptool port: UNSET." +) ELSE ( + CALL :LOG_MESSAGE INFO "Using esptool port: !ESPTOOL_PORT!." +) +CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!." + +@REM Check if FILENAME contains "-tft-" and set target partitionScheme accordingly. +@REM https://github.com/meshtastic/web-flasher/blob/main/types/resources.ts#L3 +IF NOT "!FILENAME:-tft-=!"=="!FILENAME!" ( + CALL :LOG_MESSAGE DEBUG "We are working with a *-tft-* file. !FILENAME!" + IF %WEB_APP% EQU 1 ( + CALL :LOG_MESSAGE ERROR "Cannot enable WebUI (--web) and MUI." & GOTO eof + ) + SET "TFT_BUILD=1" + GOTO tft +) ELSE ( + CALL :LOG_MESSAGE DEBUG "We are NOT working with a *-tft-* file. !FILENAME!" + GOTO no_tft +) + +:tft +SET "TFT8MB=picomputer-s3 unphone seeed-sensecap-indicator" +FOR %%a IN (%TFT8MB%) DO ( + IF NOT "!FILENAME:%%a=!"=="!FILENAME!" ( + @REM We are working with any of %TFT8MB%. + SET "TFT8=1" + GOTO end_loop_tft8mb + ) +) +:end_loop_tft8mb + +SET "TFT16MB=t-deck" +FOR %%a IN (%TFT16MB%) DO ( + IF NOT "!FILENAME:%%a=!"=="!FILENAME!" ( + @REM We are working with any of %TFT16MB%. + SET "TFT16=1" + GOTO end_loop_tft16mb + ) +) +:end_loop_tft16mb + +IF %TFT8% EQU 1 CALL :LOG_MESSAGE INFO "tft and MUI 8mb selected." +IF %TFT16% EQU 1 CALL :LOG_MESSAGE INFO "tft and MUI 16mb selected." + +:no_tft + +@REM Extract BASENAME from %FILENAME% for later use. +SET "BASENAME=!FILENAME:firmware-=!" +CALL :LOG_MESSAGE DEBUG "Computed firmware basename: !BASENAME!" + +@REM Account for S3 and C3 board's different OTA partition. +SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone" +FOR %%a IN (%S3%) DO ( + IF NOT "!FILENAME:%%a=!"=="!FILENAME!" ( + @REM We are working with any of %S3%. + SET "OTA_FILENAME=bleota-s3.bin" + GOTO :end_loop_s3 + ) +) + +SET "C3=esp32c3" +FOR %%a IN (%C3%) DO ( + IF NOT "!FILENAME:%%a=!"=="!FILENAME!" ( + @REM We are working with any of %C3%. + SET "OTA_FILENAME=bleota-c3.bin" + GOTO :end_loop_c3 + ) +) + +@REM Everything else +SET "OTA_FILENAME=bleota.bin" +:end_loop_s3 +:end_loop_c3 +CALL :LOG_MESSAGE DEBUG "Set OTA_FILENAME to: !OTA_FILENAME!" + +@REM Check if (--web) is enabled and prefix BASENAME with "littlefswebui-" else "littlefs-". +IF %WEB_APP% EQU 1 ( + CALL :LOG_MESSAGE INFO "WebUI selected." + SET "SPIFFS_FILENAME=littlefswebui-%BASENAME%" +) ELSE ( + SET "SPIFFS_FILENAME=littlefs-%BASENAME%" +) +CALL :LOG_MESSAGE DEBUG "Set SPIFFS_FILENAME to: !SPIFFS_FILENAME!" + +@REM Default offsets. +@REM https://github.com/meshtastic/web-flasher/blob/main/stores/firmwareStore.ts#L202 +SET "OTA_OFFSET=0x260000" +SET "SPIFFS_OFFSET=0x300000" + +@REM Offsets for MUI 8mb. +IF %TFT8% EQU 1 IF %TFT_BUILD% EQU 1 ( + SET "OTA_OFFSET=0x340000" + SET "SPIFFS_OFFSET=0x670000" +) + +@REM Offsets for MUI 16mb. +IF %TFT16% EQU 1 IF %TFT_BUILD% EQU 1 ( + SET "OTA_OFFSET=0x650000" + SET "SPIFFS_OFFSET=0xc90000" +) + +CALL :LOG_MESSAGE DEBUG "Set OTA_OFFSET to: !OTA_OFFSET!" +CALL :LOG_MESSAGE DEBUG "Set SPIFFS_OFFSET to: !SPIFFS_OFFSET!" + +@REM Ensure target files exist before flashing operations. +IF NOT EXIST !FILENAME! CALL :LOG_MESSAGE ERROR "File does not exist: "!FILENAME!". Terminating." & EXIT /B 2 & GOTO eof +IF NOT EXIST !OTA_FILENAME! CALL :LOG_MESSAGE ERROR "File does not exist: "!OTA_FILENAME!". Terminating." & EXIT /B 2 & GOTO eof +IF NOT EXIST !SPIFFS_FILENAME! CALL :LOG_MESSAGE ERROR "File does not exist: "!SPIFFS_FILENAME!". Terminating." & EXIT /B 2 & GOTO eof + +@REM Flashing operations. +CALL :LOG_MESSAGE INFO "Trying to flash "!FILENAME!", but first erasing and writing system information..." +CALL :RUN_ESPTOOL !ESPTOOL_BAUD! erase_flash || GOTO eof +CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write_flash 0x00 "!FILENAME!" || GOTO eof + +CALL :LOG_MESSAGE INFO "Trying to flash BLEOTA "!OTA_FILENAME!" at OTA_OFFSET !OTA_OFFSET!..." +CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write_flash !OTA_OFFSET! "!OTA_FILENAME!" || GOTO eof + +CALL :LOG_MESSAGE INFO "Trying to flash SPIFFS "!SPIFFS_FILENAME!" at SPIFFS_OFFSET !SPIFFS_OFFSET!..." +CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write_flash !SPIFFS_OFFSET! "!SPIFFS_FILENAME!" || GOTO eof + +CALL :LOG_MESSAGE INFO "Script complete!." + +:eof +ENDLOCAL +EXIT /B %ERRORLEVEL% + + +:RUN_ESPTOOL +@REM Subroutine used to run ESPTOOL_CMD with arguments. +@REM Also handles %ERRORLEVEL%. +@REM CALL :RUN_ESPTOOL [Baud] [erase_flash|write_flash] [OFFSET] [Filename] +@REM. +@REM Example:: CALL :RUN_ESPTOOL 115200 write_flash 0x10000 "firmwarefile.bin" +IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4" +CALL :RESET_ERROR +!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4 +IF %ERRORLEVEL% NEQ 0 ( + CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4" + EXIT /B %ERRORLEVEL% +) +GOTO :eof + +:LOG_MESSAGE +@REM Subroutine used to print log messages in four different levels. +@REM DEBUG messages only get printed if [-d] flag is passed to script. +@REM CALL :LOG_MESSAGE [ERROR|INFO|WARN|DEBUG] "Message" +@REM. +@REM Example:: CALL :LOG_MESSAGE INFO "Message." +SET /A LOGCOUNTER=LOGCOUNTER+1 +IF "%1" == "ERROR" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "INFO" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "WARN" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "DEBUG" IF %DEBUG% EQU 1 CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +GOTO :eof + +:GET_TIMESTAMP +@REM Subroutine used to set !TIMESTAMP! to HH:MM:ss. +@REM CALL :GET_TIMESTAMP +@REM. +@REM Updates: !TIMESTAMP! +FOR /F "tokens=1,2,3 delims=:,." %%a IN ("%TIME%") DO ( + SET "HH=%%a" + SET "MM=%%b" + SET "ss=%%c" +) +SET "TIMESTAMP=!HH!:!MM!:!ss!" +GOTO :eof + +:RESET_ERROR +@REM Subroutine to reset %ERRORLEVEL% to 0. +@REM CALL :RESET_ERROR +@REM. +@REM Updates: %ERRORLEVEL% +EXIT /B 0 +GOTO :eof diff --git a/bin/device-install.sh b/bin/device-install.sh index 96a204a5a..61c72bc2e 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -8,158 +8,157 @@ TFT_BUILD=false # Determine the correct esptool command to use if "$PYTHON" -m esptool version >/dev/null 2>&1; then - ESPTOOL_CMD="$PYTHON -m esptool" + ESPTOOL_CMD="$PYTHON -m esptool" elif command -v esptool >/dev/null 2>&1; then - ESPTOOL_CMD="esptool" + ESPTOOL_CMD="esptool" elif command -v esptool.py >/dev/null 2>&1; then - ESPTOOL_CMD="esptool.py" + ESPTOOL_CMD="esptool.py" else - echo "Error: esptool not found" - exit 1 + echo "Error: esptool not found" + exit 1 fi set -e # Usage info show_help() { - cat <&2 - exit 1 - ;; - esac - shift # Move to the next argument + case "$1" in + -h | --help) + show_help + exit 0 + ;; + -p) + ESPTOOL_PORT="$2" + shift # Shift past the option argument + ;; + -P) + PYTHON="$2" + shift + ;; + -f) + FILENAME="$2" + shift + ;; + --web) + WEB_APP=true + ;; + --) # Stop parsing options + shift + break + ;; + *) + echo "Unknown argument: $1" >&2 + exit 1 + ;; + esac + shift # Move to the next argument done [ -z "$FILENAME" -a -n "$1" ] && { - FILENAME=$1 - shift + FILENAME=$1 + shift } -# Check if FILENAME contains "-tft-" and either TFT8 or TFT16 is 1 (--tft, -tft-16mb) -if [[ "${FILENAME//-tft-/}" != "$FILENAME" ]]; then - TFT_BUILD=true - if [[ "$TFT8" != true && "$TFT16" != true ]]; then - echo "Error: Either --tft or --tft-16mb must be set to use a TFT build." - exit 1 - fi - if [[ "$TFT8" == true && "$TFT16" == true ]]; then - echo "Error: Both --tft and --tft-16mb must NOT be set at the same time." - exit 1 - fi +if [[ $FILENAME != firmware-* ]]; then + echo "Filename must be a firmware-* file." + exit 1 +fi + +# Check if FILENAME contains "-tft-" and set target partitionScheme accordingly. +if [[ ${FILENAME//-tft-/} != "$FILENAME" ]]; then + TFT_BUILD=true + if [[ $WEB_APP == true ]] && [[ $TFT_BUILD == true ]]; then + echo "Cannot enable WebUI (--web) and MUI." + exit 1 + fi + + if [[ $FILENAME == *"picomputer-s3"* || $FILENAME == *"unphone"* || $FILENAME == *"seeed-sensecap-indicator"* ]]; then + TFT8=true + fi + + if [[ $FILENAME == *"t-deck"* ]]; then + TFT16=true + fi fi # Extract BASENAME from %FILENAME% for later use. BASENAME="${FILENAME/firmware-/}" if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then - # Default littlefs* offset (--web). - OFFSET=0x300000 + # Default littlefs* offset (--web). + OFFSET=0x300000 - # Default OTA Offset - OTA_OFFSET=0x260000 + # Default OTA Offset + OTA_OFFSET=0x260000 - # littlefs* offset for MUI 8mb (--tft) and OTA OFFSET. - if [ "$TFT8" = true ]; then - if [ "$TFT_BUILD" = true ]; then - OFFSET=0x670000 - OTA_OFFSET=0x340000 - else - echo "Ignoring --tft, not a TFT Build." - fi - fi + # littlefs* offset for MUI 8mb and OTA OFFSET. + if [ "$TFT8" = true ] && [ "$TFT_BUILD" = true ]; then + OFFSET=0x670000 + OTA_OFFSET=0x340000 + fi - # littlefs* offset for MUI 16mb (--tft-16mb) and OTA OFFSET. - if [ "$TFT16" = true ]; then - if [ "$TFT_BUILD" = true ]; then - OFFSET=0xc90000 - OTA_OFFSET=0x650000 - else - echo "Ignoring --tft-16mb, not a TFT Build." - fi - fi + # littlefs* offset for MUI 16mb and OTA OFFSET. + if [ "$TFT16" = true ] && [ "$TFT_BUILD" = true ]; then + OFFSET=0xc90000 + OTA_OFFSET=0x650000 + fi - echo "Trying to flash ${FILENAME}, but first erasing and writing system information" - $ESPTOOL_CMD erase_flash - $ESPTOOL_CMD write_flash 0x00 "${FILENAME}" - # Account for S3 board's different OTA partition - if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then - if [ -n "${FILENAME##*"esp32c3"*}" ]; then - $ESPTOOL_CMD write_flash $OTA_OFFSET bleota.bin - else - $ESPTOOL_CMD write_flash $OTA_OFFSET bleota-c3.bin - fi - else - $ESPTOOL_CMD write_flash $OTA_OFFSET bleota-s3.bin - fi + # Account for S3 board's different OTA partition + if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then + if [ -n "${FILENAME##*"esp32c3"*}" ]; then + OTAFILE=bleota.bin + else + OTAFILE=bleota-c3.bin + fi + else + OTAFILE=bleota-s3.bin + fi - # Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-". - if [ "$WEB_APP" = true ]; then - # Check it the file exist before trying to write it. - if [ -f "littlefswebui-${BASENAME}" ]; then - $ESPTOOL_CMD write_flash $OFFSET "littlefswebui-${BASENAME}" - else - echo "Error: file "littlefswebui-${BASENAME}" wasn't found, littlefs not written." - exit 1 - fi - else - # Check it the file exist before trying to write it. - if [ -f "littlefs-${BASENAME}" ]; then - $ESPTOOL_CMD write_flash $OFFSET "littlefs-${BASENAME}" - else - echo "Error: file "littlefs-${BASENAME}" wasn't found, littlefs not written." - exit 1 - fi - fi + # Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-". + if [ "$WEB_APP" = true ]; then + SPIFFSFILE=littlefswebui-${BASENAME} + else + SPIFFSFILE=littlefs-${BASENAME} + fi + + if [[ ! -f $FILENAME ]]; then + echo "Error: file ${FILENAME} wasn't found. Terminating." + exit 1 + fi + if [[ ! -f $OTAFILE ]]; then + echo "Error: file ${OTAFILE} wasn't found. Terminating." + exit 1 + fi + if [[ ! -f $SPIFFSFILE ]]; then + echo "Error: file ${SPIFFSFILE} wasn't found. Terminating." + exit 1 + fi + + echo "Trying to flash ${FILENAME}, but first erasing and writing system information" + $ESPTOOL_CMD erase_flash + $ESPTOOL_CMD write_flash 0x00 "${FILENAME}" + echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}" + $ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}" + echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}" + $ESPTOOL_CMD write_flash $OFFSET "${SPIFFSFILE}" else - show_help - echo "Invalid file: ${FILENAME}" + show_help + echo "Invalid file: ${FILENAME}" fi exit 0 diff --git a/bin/device-install_test.ps1 b/bin/device-install_test.ps1 new file mode 100644 index 000000000..ae4a61cb7 --- /dev/null +++ b/bin/device-install_test.ps1 @@ -0,0 +1,112 @@ +<# + .SYNOPSIS + Unit-test for .\device-install.bat. + + .DESCRIPTION + This script performs a positive unit-test on .\device-install.bat by creating the expected .bin + files for a device followed by running the .bat script without flashing the firmware (--debug). + If any errors are hit they are presented in the standard output. Investigate accordingly. + + This script needs to be placed in the same directory as .\device-install.bat. + + .EXAMPLE + .\device-install_test.ps1 + + .EXAMPLE + .\device-install_test.ps1 -Verbose + + .LINK + .\device-install.bat --help +#> + +[CmdletBinding()] +param() + +function New-EmptyFile() { + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + # Specifies the file name. + [string]$FileName, + [Parameter(Position = 1)] + # Specifies the target path. (Get-Location).Path is the default. + [string]$Directory = (Get-Location).Path + ) + + $filePath = Join-Path -Path $Directory -ChildPath $FileName + + Write-Verbose -Message "Create empty test file if it doesn't exist: $($FileName)" + New-Item -Path "$filePath" -ItemType File -ErrorAction SilentlyContinue | Out-Null +} + +function Remove-EmptyFile() { + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + # Specifies the file name. + [string]$FileName, + [Parameter(Position = 1)] + # Specifies the target path. (Get-Location).Path is the default. + [string]$Directory = (Get-Location).Path + ) + + $filePath = Join-Path -Path $Directory -ChildPath $FileName + + Write-Verbose -Message "Deleted empty test file: $($FileName)" + Remove-Item -Path "$filePath" | Out-Null +} + + +$TestCases = New-Object -TypeName PSObject -Property @{ + # Use this PSObject to define testcases according to this syntax: + # "testname" = @("firmware-testname","bleota","littlefs-testname","args") + "t-deck" = @("firmware-t-deck-2.6.0.0b106d4.bin", "bleota-s3.bin", "littlefs-t-deck-2.6.0.0b106d4.bin", "") + "t-deck_web" = @("firmware-t-deck-2.6.0.0b106d4.bin", "bleota-s3.bin", "littlefswebui-t-deck-2.6.0.0b106d4.bin", "--web") + "t-deck-tft" = @("firmware-t-deck-tft-2.6.0.0b106d4.bin", "bleota-s3.bin", "littlefs-t-deck-tft-2.6.0.0b106d4.bin", "") + "heltec-ht62-esp32c3" = @("firmware-heltec-ht62-esp32c3-sx1262-2.6.0.0b106d4.bin", "bleota-c3.bin", "littlefs-heltec-ht62-esp32c3-sx1262-2.6.0.0b106d4.bin", "") + "tlora-c6" = @("firmware-tlora-c6-2.6.0.0b106d4.bin", "bleota.bin", "littlefs-tlora-c6-2.6.0.0b106d4.bin", "") + "heltec-v3_web" = @("firmware-heltec-v3-2.6.0.0b106d4.bin", "bleota-s3.bin", "littlefswebui-heltec-v3-2.6.0.0b106d4.bin", "--web") + "seeed-sensecap-indicator-tft" = @("firmware-seeed-sensecap-indicator-tft-2.6.0.0b106d4.bin", "bleota.bin", "littlefs-seeed-sensecap-indicator-tft-2.6.0.0b106d4.bin", "") + "picomputer-s3-tft" = @("firmware-picomputer-s3-tft-2.6.0.0b106d4.bin", "bleota-s3.bin", "littlefs-picomputer-s3-tft-2.6.0.0b106d4.bin", "") +} + +foreach ($TestCase in $TestCases.PSObject.Properties) { + $Name = $TestCase.Name + $Files = $TestCase.Value + $Errors = $null + $Counter = 0 + + Write-Host -Object "Testcase: $Name`:" -ForegroundColor Green + foreach ($File in $Files) { + if ($File.EndsWith(".bin")) { + New-EmptyFile -FileName $File + } + } + + Write-Host -Object "Performing test on $Name..." -ForegroundColor Blue + $Test = Invoke-Expression -Command "cmd /c .\device-install.bat --debug -f $($TestCases."$Name"[0]) $($TestCases."$Name"[3])" + + foreach ($Line in $Test) { + if ($Line -match "Set OTA_OFFSET to" -or ` + $Line -match "Set SPIFFS_OFFSET to") { + Write-Host -Object "$($Line -replace "^.*?Set","Set")" -ForegroundColor Blue + } + elseif ($VerbosePreference -eq "Continue") { + Write-Host -Object $Line + } + if ($Line -match "ERROR") { + $Errors += $Line + $Counter++ + } + } + if ($null -ne $Errors) { + Write-Host -Object "$Counter ERROR(s) detected!" -ForegroundColor Red + if (-not ($VerbosePreference -eq "Continue")) { Write-Host -Object $Errors } + } + + foreach ($File in $Files) { + if ($File.EndsWith(".bin")) { + Remove-EmptyFile -FileName $File + } + } +} diff --git a/bin/device-update.bat b/bin/device-update.bat index a52f3d33f..ecfeec187 100755 --- a/bin/device-update.bat +++ b/bin/device-update.bat @@ -1,48 +1,175 @@ @ECHO OFF +SETLOCAL EnableDelayedExpansion +TITLE Meshtastic device-update -set PYTHON=python +SET "SCRIPT_NAME=%~nx0" +SET "DEBUG=0" +SET "PYTHON=" +SET "ESPTOOL_BAUD=115200" +SET "ESPTOOL_CMD=" +SET "LOGCOUNTER=0" -:: Determine the correct esptool command to use -where esptool >nul 2>&1 -if %ERRORLEVEL% EQU 0 ( - set "ESPTOOL_CMD=esptool" -) else ( - set "ESPTOOL_CMD=%PYTHON% -m esptool" -) +GOTO getopts +:help +ECHO Flash image file to device, but leave existing system intact. +ECHO. +ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] +ECHO. +ECHO Options: +ECHO -f filename The .bin file to flash. Custom to your device type and region. (required) +ECHO The file must be located in this current directory. +ECHO -p PORT Set the environment variable for ESPTOOL_PORT. +ECHO If not set, ESPTOOL iterates all ports (Dangerous). +ECHO -P python Specify alternate python interpreter to use to invoke esptool. (default: python) +ECHO If supplied the script will use python. +ECHO If not supplied the script will try to find esptool in Path. +ECHO. +ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4-update.bin -p COM11 +GOTO eof -goto GETOPTS -:HELP -echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME] -echo Flash image file to device, leave existing system intact. -echo. -echo -h Display this help and exit -echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous). -echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%) -echo -f FILENAME The *update.bin file to flash. Custom to your device type. -goto EOF +:version +ECHO %SCRIPT_NAME% [Version 2.6.0] +ECHO Meshtastic +GOTO eof -:GETOPTS -if /I "%1"=="-h" goto HELP -if /I "%1"=="--help" goto HELP -if /I "%1"=="-F" set "FILENAME=%2" & SHIFT -if /I "%1"=="-p" set ESPTOOL_PORT=%2 & SHIFT -if /I "%1"=="-P" set PYTHON=%2 & SHIFT +:getopts +IF "%~1"=="" GOTO endopts +IF /I "%~1"=="-?" GOTO help +IF /I "%~1"=="-h" GOTO help +IF /I "%~1"=="--help" GOTO help +IF /I "%~1"=="-v" GOTO version +IF /I "%~1"=="--version" GOTO version +IF /I "%~1"=="--debug" SET "DEBUG=1" & CALL :LOG_MESSAGE DEBUG "DEBUG mode: enabled." +IF /I "%~1"=="-f" SET "FILENAME=%~2" & SHIFT +IF "%~1"=="-p" SET "ESPTOOL_PORT=%~2" & SHIFT +IF /I "%~1"=="--port" SET "ESPTOOL_PORT=%~2" & SHIFT +IF "%~1"=="-P" SET "PYTHON=%~2" & SHIFT SHIFT -IF NOT "__%1__"=="____" goto GETOPTS +GOTO getopts +:endopts -IF "__%FILENAME%__" == "____" ( - echo "Missing FILENAME" - goto HELP -) -IF EXIST %FILENAME% IF NOT x%FILENAME:update=%==x%FILENAME% ( - echo Trying to flash update %FILENAME% - %ESPTOOL_CMD% --baud 115200 write_flash 0x10000 %FILENAME% -) else ( - echo "Invalid file: %FILENAME%" - goto HELP -) else ( - echo "Invalid file: %FILENAME%" - goto HELP +CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..." +IF "__!FILENAME!__"=="____" ( + CALL :LOG_MESSAGE DEBUG "Missing -f filename input." + GOTO help +) ELSE ( + IF NOT "__!FILENAME: =!__"=="__!FILENAME!__" ( + CALL :LOG_MESSAGE ERROR "Filename containing spaces are not supported." + GOTO help + ) + @REM Remove ".\" or "./" file prefix if present. + SET "FILENAME=!FILENAME:.\=!" + SET "FILENAME=!FILENAME:./=!" ) -:EOF +CALL :LOG_MESSAGE DEBUG "Filename: !FILENAME!" +CALL :LOG_MESSAGE DEBUG "Checking if !FILENAME! exists..." +IF NOT EXIST !FILENAME! ( + CALL :LOG_MESSAGE ERROR "File does not exist: !FILENAME!. Terminating." + GOTO eof +) + +IF "!FILENAME:update=!"=="!FILENAME!" ( + CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!" + CALL :LOG_MESSAGE INFO "Use script device-install.bat to flash update !FILENAME!." + GOTO eof +) ELSE ( + CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!" +) + +CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..." +IF NOT "__%PYTHON%__"=="____" ( + SET "ESPTOOL_CMD=!PYTHON! -m esptool" + CALL :LOG_MESSAGE DEBUG "Python interpreter supplied." +) ELSE ( + CALL :LOG_MESSAGE DEBUG "Python interpreter NOT supplied. Looking for esptool... + WHERE esptool >nul 2>&1 + IF %ERRORLEVEL% EQU 0 ( + @REM WHERE exits with code 0 if esptool is found. + SET "ESPTOOL_CMD=esptool" + ) ELSE ( + SET "ESPTOOL_CMD=python -m esptool" + CALL :RESET_ERROR + ) +) + +CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..." +!ESPTOOL_CMD! >nul 2>&1 +IF %ERRORLEVEL% GTR 2 ( + @REM esptool exits with code 1 if help is displayed. + CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!" + EXIT /B 1 + GOTO eof +) +IF %DEBUG% EQU 1 ( + CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps." + SET "ESPTOOL_CMD=REM !ESPTOOL_CMD!" +) + +CALL :LOG_MESSAGE DEBUG "Using esptool command: !ESPTOOL_CMD!" +IF "__!ESPTOOL_PORT!__" == "____" ( + CALL :LOG_MESSAGE WARN "Using esptool port: UNSET." +) ELSE ( + CALL :LOG_MESSAGE INFO "Using esptool port: !ESPTOOL_PORT!." +) +CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!." + +@REM Flashing operations. +CALL :LOG_MESSAGE INFO "Trying to flash update "!FILENAME!" at OFFSET 0x10000..." +CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write_flash 0x10000 "!FILENAME!" || GOTO eof + +CALL :LOG_MESSAGE INFO "Script complete!." + +:eof +ENDLOCAL +EXIT /B %ERRORLEVEL% + + +:RUN_ESPTOOL +@REM Subroutine used to run ESPTOOL_CMD with arguments. +@REM Also handles %ERRORLEVEL%. +@REM CALL :RUN_ESPTOOL [Baud] [erase_flash|write_flash] [OFFSET] [Filename] +@REM. +@REM Example:: CALL :RUN_ESPTOOL 115200 write_flash 0x10000 "firmwarefile.bin" +IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4" +CALL :RESET_ERROR +!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4 +IF %ERRORLEVEL% NEQ 0 ( + CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4" + EXIT /B %ERRORLEVEL% +) +GOTO :eof + +:LOG_MESSAGE +@REM Subroutine used to print log messages in four different levels. +@REM DEBUG messages only get printed if [-d] flag is passed to script. +@REM CALL :LOG_MESSAGE [ERROR|INFO|WARN|DEBUG] "Message" +@REM. +@REM Example:: CALL :LOG_MESSAGE INFO "Message." +SET /A LOGCOUNTER=LOGCOUNTER+1 +IF "%1" == "ERROR" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "INFO" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "WARN" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "DEBUG" IF %DEBUG% EQU 1 CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +GOTO :eof + +:GET_TIMESTAMP +@REM Subroutine used to set !TIMESTAMP! to HH:MM:ss. +@REM CALL :GET_TIMESTAMP +@REM. +@REM Updates: !TIMESTAMP! +FOR /F "tokens=1,2,3 delims=:,." %%a IN ("%TIME%") DO ( + SET "HH=%%a" + SET "MM=%%b" + SET "ss=%%c" +) +SET "TIMESTAMP=!HH!:!MM!:!ss!" +GOTO :eof + +:RESET_ERROR +@REM Subroutine to reset %ERRORLEVEL% to 0. +@REM CALL :RESET_ERROR +@REM. +@REM Updates: %ERRORLEVEL% +EXIT /B 0 +GOTO :eof diff --git a/bin/regen-protos.bat b/bin/regen-protos.bat index 7fa8f333d..0bbfbe38a 100644 --- a/bin/regen-protos.bat +++ b/bin/regen-protos.bat @@ -1 +1,10 @@ -cd protobufs && ..\nanopb-0.4.9\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated" -I=..\protobufs\ ..\protobufs\meshtastic\*.proto +@ECHO OFF +SETLOCAL + +cd protobufs +..\nanopb-0.4.9\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated" -I=..\protobufs\ ..\protobufs\meshtastic\*.proto +GOTO eof + +:eof +ENDLOCAL +EXIT /B %ERRORLEVEL% diff --git a/bin/uf2-convert.bat b/bin/uf2-convert.bat index 242bec3ab..5e36617e3 100644 --- a/bin/uf2-convert.bat +++ b/bin/uf2-convert.bat @@ -1,2 +1,124 @@ -@echo off -if [%1]==[] (echo "Please specify a platformio NRF target (i.e. rak4631) as the first argument.") else (python3 .\bin\uf2conv.py .\.pio\build\%1\firmware.hex -c -o .\.pio\build\%1\firmware.uf2 -f 0xADA52840) \ No newline at end of file +@ECHO OFF +SETLOCAL EnableDelayedExpansion +TITLE Meshtastic uf2-convert + +SET "SCRIPT_NAME=%~nx0" +SET "DEBUG=0" +SET "NRF=0" +SET "UF2CONV_CMD=python3 .\bin\uf2conv.py" + +GOTO getopts +:help +ECHO. +ECHO Usage: %SCRIPT_NAME% -t [t-echo^|rak4631^|nano-g2-ultra^|wio-tracker-wm1110^|canaryone^| +ECHO heltec-mesh-node-t114^|tracker-t1000-e^|rak_wismeshtap^|rak2560^| +ECHO nrf52_promicro_diy_tcxo] +ECHO. +ECHO Options: +ECHO -t target Specify a platformio NRF target to build for. (required) +ECHO. +ECHO Example: %SCRIPT_NAME% -t rak4631 +GOTO eof + +:version +ECHO %SCRIPT_NAME% [Version 2.6.0] +ECHO Meshtastic +GOTO eof + +:getopts +IF "%~1"=="" GOTO endopts +IF /I "%~1"=="-?" GOTO help +IF /I "%~1"=="-h" GOTO help +IF /I "%~1"=="--help" GOTO help +IF /I "%~1"=="-v" GOTO version +IF /I "%~1"=="--version" GOTO version +IF /I "%~1"=="--debug" SET "DEBUG=1" & CALL :LOG_MESSAGE DEBUG "DEBUG mode: enabled." +IF /I "%~1"=="-t" SET "TARGETNAME=%~2" & SHIFT +IF /I "%~1"=="--target" SET "TARGETNAME=%~2" & SHIFT +SHIFT +GOTO getopts +:endopts + +CALL :LOG_MESSAGE DEBUG "Checking TARGETNAME parameter..." +IF "__!TARGETNAME!__"=="____" ( + CALL :LOG_MESSAGE DEBUG "Missing -t target input." + GOTO help +) + +IF %DEBUG% EQU 1 SET "UF2CONV_CMD=REM python3 .\bin\uf2conv.py" + +SET "NRFTARGETS=t-echo rak4631 nano-g2-ultra wio-tracker-wm1110 canaryone heltec-mesh-node-t114 tracker-t1000-e rak_wismeshtap rak2560 nrf52_promicro_diy_tcxo" +FOR %%a IN (%NRFTARGETS%) DO ( + IF /I "%%a"=="!TARGETNAME!" ( + @REM We are working with any of %NRFTARGETS%. + SET "NRF=1" + GOTO end_loop_nrf + ) +) +:end_loop_nrf + +@REM Building operations. +IF !NRF! EQU 1 ( + CALL :LOG_MESSAGE INFO "Trying to build for !TARGETNAME!..." + CALL :RUN_UF2CONV !TARGETNAME! || GOTO eof +) ELSE ( + CALL :LOG_MESSAGE WARN "!TARGETNAME! is not supported..." + GOTO eof +) + +CALL :LOG_MESSAGE INFO "Script complete!." + + +:eof +ENDLOCAL +EXIT /B %ERRORLEVEL% + + +:RUN_UF2CONV +@REM Subroutine used to run .\bin\uf2conv.py with arguments. +@REM Also handles %ERRORLEVEL%. +@REM CALL :RUN_UF2CONV [target] +@REM. +@REM Example:: CALL :RUN_UF2CONV rak4631 +IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !UF2CONV_CMD! .\.pio\build\%~1\firmware.hex -c -o .\.pio\build\%~1\firmware.uf2 -f 0xADA52840" +CALL :RESET_ERROR +!UF2CONV_CMD! .\.pio\build\%~1\firmware.hex -c -o .\.pio\build\%~1\firmware.uf2 -f 0xADA52840 +IF %ERRORLEVEL% NEQ 0 ( + CALL :LOG_MESSAGE ERROR "Error running command: !UF2CONV_CMD! .\.pio\build\%~1\firmware.hex -c -o .\.pio\build\%~1\firmware.uf2 -f 0xADA52840" + EXIT /B %ERRORLEVEL% +) +GOTO :eof + +:LOG_MESSAGE +@REM Subroutine used to print log messages in four different levels. +@REM DEBUG messages only get printed if [-d] flag is passed to script. +@REM CALL :LOG_MESSAGE [ERROR|INFO|WARN|DEBUG] "Message" +@REM. +@REM Example:: CALL :LOG_MESSAGE INFO "Message." +SET /A LOGCOUNTER=LOGCOUNTER+1 +IF "%1" == "ERROR" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "INFO" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "WARN" CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +IF "%1" == "DEBUG" IF %DEBUG% EQU 1 CALL :GET_TIMESTAMP & ECHO %1 ^| !TIMESTAMP! !LOGCOUNTER! %~2 +GOTO :eof + +:GET_TIMESTAMP +@REM Subroutine used to set !TIMESTAMP! to HH:MM:ss. +@REM CALL :GET_TIMESTAMP +@REM. +@REM Updates: !TIMESTAMP! +FOR /F "tokens=1,2,3 delims=:,." %%a IN ("%TIME%") DO ( + SET "HH=%%a" + SET "MM=%%b" + SET "ss=%%c" +) +SET "TIMESTAMP=!HH!:!MM!:!ss!" +GOTO :eof + +:RESET_ERROR +@REM Subroutine to reset %ERRORLEVEL% to 0. +@REM CALL :RESET_ERROR +@REM. +@REM Updates: %ERRORLEVEL% +EXIT /B 0 +GOTO :eof diff --git a/platformio.ini b/platformio.ini index e5c14522d..ed2f164a2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,7 +60,7 @@ lib_deps = mathertel/OneButton@2.6.1 https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4 - https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0 + https://github.com/meshtastic/ArduinoThread.git#7c3ee9e1951551b949763b1f5280f8db1fa4068d nanopb/Nanopb@0.4.91 erriez/ErriezCRC32@1.0.1 @@ -94,7 +94,7 @@ lib_deps = [device-ui_base] lib_deps = - https://github.com/meshtastic/device-ui.git#8c3183e177a1d6452ce12b4f328bd3357bf7e21b + https://github.com/meshtastic/device-ui.git#d7b18e98704f988fcda9e5fa7404e677b3d11f8c ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) diff --git a/protobufs b/protobufs index c261bd71a..035a8017b 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit c261bd71aaf416f3bcef5dbc774d06b797fc58c6 +Subproject commit 035a8017b87379f17624f7bba9b6a5b127bc026c diff --git a/src/configuration.h b/src/configuration.h index 6f5255ec9..fd4a5b196 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -135,6 +135,7 @@ along with this program. If not, see . #define LPS22HB_ADDR 0x5C #define LPS22HB_ADDR_ALT 0x5D #define SHT31_4x_ADDR 0x44 +#define SHT31_4x_ADDR_ALT 0x45 #define PMSA0031_ADDR 0x12 #define QMA6100P_ADDR 0x12 #define AHT10_ADDR 0x38 @@ -150,6 +151,7 @@ along with this program. If not, see . #define MAX30102_ADDR 0x57 #define MLX90614_ADDR_DEF 0x5A #define CGRADSENS_ADDR 0x66 +#define LTR390UV_ADDR 0x53 // ----------------------------------------------------------------------------- // ACCELEROMETER diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 6828169a8..5b6bbe629 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -68,6 +68,7 @@ class ScanI2C NXP_SE050, DFROBOT_RAIN, DPS310, + LTR390UV, } DeviceType; // typedef uint8_t DeviceAddress; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 0eca5cad3..8b779277d 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -349,7 +349,8 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) } break; } - case SHT31_4x_ADDR: + case SHT31_4x_ADDR: // same as OPT3001_ADDR_ALT + case SHT31_4x_ADDR_ALT: // same as OPT3001_ADDR registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2); if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0xe9c) { type = SHT4X; @@ -422,11 +423,11 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address); SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address); SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591", (uint8_t)addr.address); - SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001", (uint8_t)addr.address); SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address); SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address); SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address); SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address); #ifdef HAS_TPS65233 SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address); #endif diff --git a/src/main.cpp b/src/main.cpp index db0087db8..dcb00dbfa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -641,6 +641,7 @@ void setup() scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_RAIN, meshtastic_TelemetrySensorType_DFROBOT_RAIN); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LTR390UV, meshtastic_TelemetrySensorType_LTR390UV); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DPS310, meshtastic_TelemetrySensorType_DPS310); i2cScanner.reset(); @@ -1224,8 +1225,12 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() #if MESHTASTIC_EXCLUDE_AUDIO deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AUDIO_CONFIG; #endif -#if !HAS_SCREEN || NO_EXT_GPIO - deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_CANNEDMSG_CONFIG | meshtastic_ExcludedModules_EXTNOTIF_CONFIG; +// Option to explicitly include canned messages for edge cases, e.g. niche graphics +#if (!HAS_SCREEN && NO_EXT_GPIO) && !MESHTASTIC_INCLUDE_CANNEDMSG + deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_CANNEDMSG_CONFIG; +#endif +#if NO_EXT_GPIO + deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_EXTNOTIF_CONFIG; #endif // Only edge case here is if we apply this a device with built in Accelerometer and want to detect interrupts // We'll have to macro guard against those targets potentially diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 58ea58b32..53dffece7 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -88,8 +88,16 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp) } else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user && nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) { if (airTime->isTxAllowedChannelUtil(true)) { - LOG_INFO("Heard new node on ch. %d, send NodeInfo and ask for response", mp->channel); - nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel); + // Hops used by the request. If somebody in between running modified firmware modified it, ignore it + auto hopStart = mp->hop_start; + auto hopLimit = mp->hop_limit; + uint8_t hopsUsed = hopStart < hopLimit ? config.lora.hop_limit : hopStart - hopLimit; + if (hopsUsed > config.lora.hop_limit + 2) { + LOG_DEBUG("Skip send NodeInfo: %d hops away is too far away", hopsUsed); + } else { + LOG_INFO("Heard new node on ch. %d, send NodeInfo and ask for response", mp->channel); + nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel); + } } else { LOG_DEBUG("Skip sending NodeInfo > 25%% ch. util"); } diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index d7dc47785..4e7c43e58 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -128,6 +128,9 @@ typedef enum _meshtastic_PortNum { meshtastic_PortNum_MAP_REPORT_APP = 73, /* PowerStress based monitoring support (for automated power consumption testing) */ meshtastic_PortNum_POWERSTRESS_APP = 74, + /* Reticulum Network Stack Tunnel App + ENCODING: Fragmented RNS Packet. Handled by Meshtastic RNS interface */ + meshtastic_PortNum_RETICULUM_TUNNEL_APP = 76, /* Private applications should use portnums >= 256. To simplify initial development and testing you can use "PRIVATE_APP" in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */ diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index aa39a1ce4..69cdd33fe 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -85,7 +85,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* DFRobot Gravity tipping bucket rain gauge */ meshtastic_TelemetrySensorType_DFROBOT_RAIN = 35, /* Infineon DPS310 High accuracy pressure and temperature */ - meshtastic_TelemetrySensorType_DPS310 = 36 + meshtastic_TelemetrySensorType_DPS310 = 36, + /* RAKWireless RAK12035 Soil Moisture Sensor Module */ + meshtastic_TelemetrySensorType_RAK12035 = 37 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -172,6 +174,12 @@ typedef struct _meshtastic_EnvironmentMetrics { /* Rainfall in the last 24 hours in mm */ bool has_rainfall_24h; float rainfall_24h; + /* Soil moisture measured (% 1-100) */ + bool has_soil_moisture; + uint8_t soil_moisture; + /* Soil temperature measured (*C) */ + bool has_soil_temperature; + float soil_temperature; } meshtastic_EnvironmentMetrics; /* Power Metrics (voltage / current / etc) */ @@ -316,8 +324,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_DPS310 -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_DPS310+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RAK12035 +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RAK12035+1)) @@ -330,7 +338,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0} -#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} +#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @@ -338,7 +346,7 @@ extern "C" { #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Nau7802Config_init_default {0, 0} #define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0} -#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} +#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @@ -372,6 +380,8 @@ extern "C" { #define meshtastic_EnvironmentMetrics_radiation_tag 18 #define meshtastic_EnvironmentMetrics_rainfall_1h_tag 19 #define meshtastic_EnvironmentMetrics_rainfall_24h_tag 20 +#define meshtastic_EnvironmentMetrics_soil_moisture_tag 21 +#define meshtastic_EnvironmentMetrics_soil_temperature_tag 22 #define meshtastic_PowerMetrics_ch1_voltage_tag 1 #define meshtastic_PowerMetrics_ch1_current_tag 2 #define meshtastic_PowerMetrics_ch2_voltage_tag 3 @@ -445,7 +455,9 @@ X(a, STATIC, OPTIONAL, FLOAT, wind_gust, 16) \ X(a, STATIC, OPTIONAL, FLOAT, wind_lull, 17) \ X(a, STATIC, OPTIONAL, FLOAT, radiation, 18) \ X(a, STATIC, OPTIONAL, FLOAT, rainfall_1h, 19) \ -X(a, STATIC, OPTIONAL, FLOAT, rainfall_24h, 20) +X(a, STATIC, OPTIONAL, FLOAT, rainfall_24h, 20) \ +X(a, STATIC, OPTIONAL, UINT32, soil_moisture, 21) \ +X(a, STATIC, OPTIONAL, FLOAT, soil_temperature, 22) #define meshtastic_EnvironmentMetrics_CALLBACK NULL #define meshtastic_EnvironmentMetrics_DEFAULT NULL @@ -544,12 +556,12 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size #define meshtastic_AirQualityMetrics_size 78 #define meshtastic_DeviceMetrics_size 27 -#define meshtastic_EnvironmentMetrics_size 103 +#define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 #define meshtastic_LocalStats_size 60 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 30 -#define meshtastic_Telemetry_size 110 +#define meshtastic_Telemetry_size 120 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index 2c51dc1cc..bf7fce29a 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -76,7 +76,7 @@ #elif defined(HELTEC_T114) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_NODE_T114 #elif defined(SEEED_XIAO_NRF52840_KIT) -#define HW_VENDOR meshtastic_HardwareModel_SEEED_XIAO_NRF52840_KIT +#define HW_VENDOR meshtastic_HardwareModel_XIAO_NRF52_KIT #else #define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN #endif diff --git a/variants/CDEBYTE_E77-MBL/platformio.ini b/variants/CDEBYTE_E77-MBL/platformio.ini new file mode 100644 index 000000000..a8d90f676 --- /dev/null +++ b/variants/CDEBYTE_E77-MBL/platformio.ini @@ -0,0 +1,41 @@ +[env:CDEBYTE_E77-MBL] +extends = stm32_base +; `ebyte_e77_dev` was added in this commit. Remove when a new release is used in the base. +platform = https://github.com/platformio/platform-ststm32.git#3208828db447f4373cd303b7f7393c8fc0dae623 +board = ebyte_e77_dev +board_level = extra +build_flags = + ${stm32_base.build_flags} + -Ivariants/CDEBYTE_E77-MBL + -DSERIAL_UART_INSTANCE=1 + -DPIN_SERIAL_RX=PA3 + -DPIN_SERIAL_TX=PA2 + -DHAL_DAC_MODULE_ONLY + -DHAL_ADC_MODULE_DISABLED + -DHAL_COMP_MODULE_DISABLED + -DHAL_CRC_MODULE_DISABLED + -DHAL_CRYP_MODULE_DISABLED + -DHAL_GTZC_MODULE_DISABLED + -DHAL_HSEM_MODULE_DISABLED + -DHAL_I2C_MODULE_DISABLED + -DHAL_I2S_MODULE_DISABLED + -DHAL_IPCC_MODULE_DISABLED + -DHAL_IRDA_MODULE_DISABLED + -DHAL_IWDG_MODULE_DISABLED + -DHAL_LPTIM_MODULE_DISABLED + -DHAL_PKA_MODULE_DISABLED + -DHAL_RNG_MODULE_DISABLED + -DHAL_RTC_MODULE_DISABLED + -DHAL_SMARTCARD_MODULE_DISABLED + -DHAL_SMBUS_MODULE_DISABLED + -DHAL_TIM_MODULE_DISABLED + -DHAL_WWDG_MODULE_DISABLED + -DHAL_EXTI_MODULE_DISABLED + -DHAL_SAI_MODULE_DISABLED + -DHAL_ICACHE_MODULE_DISABLED + -DRADIOLIB_EXCLUDE_SX128X=1 + -DRADIOLIB_EXCLUDE_SX127X=1 + -DRADIOLIB_EXCLUDE_LR11X0=1 +; -D PIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF + +upload_port = stlink \ No newline at end of file diff --git a/variants/CDEBYTE_E77-MBL/variant.h b/variants/CDEBYTE_E77-MBL/variant.h new file mode 100644 index 000000000..7331dcedc --- /dev/null +++ b/variants/CDEBYTE_E77-MBL/variant.h @@ -0,0 +1,23 @@ +/* +EByte E77-MBL series +https://www.cdebyte.com/products/E77-900MBL-01 +https://www.cdebyte.com/products/E77-400MBL-01 +https://github.com/olliw42/mLRS-docu/blob/master/docs/EBYTE_E77_MBL.md +*/ + +/* +This variant is a work in progress. +Do not expect a working Meshtastic device with this target. +*/ + +#ifndef _VARIANT_EBYTE_E77_ +#define _VARIANT_EBYTE_E77_ + +#define USE_STM32WLx +#define MAX_NUM_NODES 10 + +#define LED_PIN PB4 // LED1 +// #define LED_PIN PB3 // LED2 +#define LED_STATE_ON 1 + +#endif diff --git a/variants/crowpanel-esp32s3-5-epaper/platformio.ini b/variants/crowpanel-esp32s3-5-epaper/platformio.ini index 83d57a0ef..2393e168d 100644 --- a/variants/crowpanel-esp32s3-5-epaper/platformio.ini +++ b/variants/crowpanel-esp32s3-5-epaper/platformio.ini @@ -15,8 +15,6 @@ build_flags = -DBOARD_HAS_PSRAM -DGPS_POWER_TOGGLE -DEINK_DISPLAY_MODEL=GxEPD2_579_GDEY0579T93 ;https://www.good-display.com/product/439.html - ;-DEINK_DISPLAY_MODEL=GxEPD2_290_GDEY029T94 ;https://www.good-display.com/product/389.html - ;-DEINK_DISPLAY_MODEL=GxEPD2_420_GYE042A87 ; similar Panel: GDEY042T81 : https://www.good-display.com/product/386.html -DEINK_WIDTH=792 -DEINK_HEIGHT=272 -DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk @@ -25,4 +23,58 @@ build_flags = ;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 lib_deps = ${esp32s3_base.lib_deps} - https://github.com/markbirss/GxEPD2#markbirss-patch-1 + https://github.com/meshtastic/GxEPD2 + +[env:crowpanel-esp32s3-4-epaper] +extends = esp32s3_base +board_build.arduino.memory_type = qio_opi +board_build.flash_mode = qio +board_build.psram_type = opi +board_upload.flash_size = 8MB +board_upload.maximum_size = 8388608 +board = esp32-s3-devkitc-1 +upload_port = /dev/ttyUSB0 +board_level = extra +upload_protocol = esptool +build_flags = + ${esp32_base.build_flags} -D CROWPANEL_ESP32S3_5_EPAPER -I variants/crowpanel-esp32s3-5-epaper + -D PRIVATE_HW + -DBOARD_HAS_PSRAM + -DGPS_POWER_TOGGLE + -DEINK_DISPLAY_MODEL=GxEPD2_420_GYE042A87 ; similar Panel: GDEY042T81 : https://www.good-display.com/product/386.html + -DEINK_WIDTH=400 + -DEINK_HEIGHT=300 + -DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk + -DEINK_LIMIT_FASTREFRESH=100 ; How many consecutive fast-refreshes are permitted + ;-DEINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates + ;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 +lib_deps = + ${esp32s3_base.lib_deps} + https://github.com/meshtastic/GxEPD2 + +[env:crowpanel-esp32s3-2-epaper] +extends = esp32s3_base +board_build.arduino.memory_type = qio_opi +board_build.flash_mode = qio +board_build.psram_type = opi +board_upload.flash_size = 8MB +board_upload.maximum_size = 8388608 +board = esp32-s3-devkitc-1 +upload_port = /dev/ttyUSB0 +board_level = extra +upload_protocol = esptool +build_flags = + ${esp32_base.build_flags} -D CROWPANEL_ESP32S3_5_EPAPER -I variants/crowpanel-esp32s3-5-epaper + -D PRIVATE_HW + -DBOARD_HAS_PSRAM + -DGPS_POWER_TOGGLE + -DEINK_DISPLAY_MODEL=GxEPD2_290_GDEY029T94 ;https://www.good-display.com/product/389.html + -DEINK_WIDTH=296 + -DEINK_HEIGHT=128 + -DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk + -DEINK_LIMIT_FASTREFRESH=100 ; How many consecutive fast-refreshes are permitted + ;-DEINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates + ;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 +lib_deps = + ${esp32s3_base.lib_deps} + https://github.com/meshtastic/GxEPD2