Compare commits

...

34 Commits

Author SHA1 Message Date
Mike
31c0e8fa2c Support WiFi OTA (#6352)
* Support WiFi OTA

* Fix trunk warnings

* Make getVersion() check for project name too

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-03-20 13:39:33 -05:00
raulperdomo
0d95b1afcc Added bounds checking to memcpy and use memory-safe strlcpy (#6351)
* Added bounds checking to memcpy and use memory-safe strlcpy for reading serial data in processWXSerial() function.

* Fixed linting with trunk
2025-03-20 10:40:13 -05:00
Austin
46235f6f8b RP2xx0: Add UDP Multicast support (#6327) 2025-03-20 08:49:28 -05:00
Jorropo
d1068fd1e4 Add UDP multicast support on linux. (#6342)
* Add UDP multicast support on linux.

Closes #6326

We tested it an it works.

This is really hacky to say the least.

* Add libuv to Linux packaging

* Trunkadunk

* Correct ref

* Add libuv1-dev to setup-native

---------

Co-authored-by: vidplace7 <vidplace7@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-03-20 08:47:39 -05:00
Jorropo
f41afb14b1 raise the multicast UDP TTL limit (#6343)
Since 96ba94843b we don't spray packets to all machines on the network.

So we can allow ourself to raise the TTL limit, this allows users who run L3 IGMP Routing infrastructure to pass meshtastic frames over UDP.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-03-20 05:41:29 -05:00
Ben Meadors
f8ad02aab3 Update version.properties 2025-03-19 06:20:50 -05:00
github-actions[bot]
077759e15d Upgrade trunk (#6347)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-03-19 05:11:42 -05:00
Bob Reese
22aa2d7582 Fixed UF2 generation problem with sys.executable path has spaces in it (#6346) 2025-03-18 20:20:15 -05:00
Austin
6673cb9292 Increase MAX_NUM_NODES on high-flash ESP32_S3 (#6311) 2025-03-18 20:19:51 -05:00
Kalle Lilja
8efc9702d3 device-install/update: fix esptool --port (#6341)
* fix errorlevel check

* add esptool --port if supplied

* match device-install

* add --port if supplied

* update logmessage

* bump version

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-03-17 20:16:16 -05:00
Austin
2876eec7ed MeshToad - USB 1W 'MeshStick' (#6339) 2025-03-17 20:14:01 -05:00
Ben Meadors
9cc13e628a Stubbed out backup / restore methods for now and fixed bug 2025-03-17 19:24:47 -05:00
Jorropo
af8b64e84e pass pointer to UDP multicast packet to protobuf decoder (#6333)
The packet.readBytes API is not available on all targets:
- RP2040 & RP2340
- yet to be written portduino API

Instead pass the data buffer as-is.
It also removes a memcpy which do not need to exists.

I've tested it successfully on a tbeam.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-03-16 19:36:33 -05:00
Jorropo
96ba94843b Send UDP packets to multicast address rather than broadcast address (#6331)
A smart router or switch is able to snoop the multicast address to
only send the packets to nodes listening on the multicast address.

Before all machines reachable on the L2 layer would receive the packet.
2025-03-16 19:36:02 -05:00
Thomas Göttgens
2d565c2921 trunk'd 2025-03-16 16:18:12 +01:00
HarukiToreda
2525111c39 E-ink partial refresh limitation removed for free text screen (#6201) 2025-03-16 16:15:33 +01:00
dylanli
64b9cfe199 update seeed-xiao-nrf52840-kit board defination (#6318)
- Due to the lack of pins, we have temporarily removed the button. There are some technical solutions that can solve this problem, and we are currently exploring and researching them
2025-03-16 16:04:24 +01:00
Ben Meadors
dc100e4d3e Cleanup 2025-03-16 08:19:46 -05:00
Thomas Göttgens
1640fb105d new device: Lilygo T-Eth-Elite (#6321) 2025-03-15 14:15:35 +01:00
github-actions[bot]
99e42b4d22 [create-pull-request] automated change (#6323)
Co-authored-by: caveman99 <25002+caveman99@users.noreply.github.com>
2025-03-15 07:03:53 -05:00
Thomas Göttgens
79233fe99d mainline tlora v3 (#6322) 2025-03-15 11:30:58 +01:00
Chris Danis
f66784ed2a Don't allow is_managed without any valid admin_keys (#6310) 2025-03-14 10:10:38 -05:00
github-actions[bot]
f198d5d49f Upgrade trunk to 1.22.11 (#6316)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-03-14 06:58:08 -05:00
dependabot[bot]
4d34b3d73c Bump dorny/test-reporter from 1.9.1 to 2.0.0 in /.github/workflows (#6309)
Bumps [dorny/test-reporter](https://github.com/dorny/test-reporter) from 1.9.1 to 2.0.0.
- [Release notes](https://github.com/dorny/test-reporter/releases)
- [Changelog](https://github.com/dorny/test-reporter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dorny/test-reporter/compare/v1.9.1...v2.0.0)

---
updated-dependencies:
- dependency-name: dorny/test-reporter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 08:32:49 -05:00
paragonnov
8efe8a2ea3 Fix KR920's Tx power limitation (#6307) 2025-03-13 18:14:41 +08:00
Kalle Lilja
499ea56e3b update devcontainer (#6299) 2025-03-12 15:32:34 -05:00
Ben Meadors
2473af6995 45 days stale 2025-03-12 12:43:55 -05:00
github-actions[bot]
508ab171d6 Upgrade trunk (#6295)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-03-12 06:22:24 -05:00
Manuel
ec59f7d7dd fix packet queue full (#6292) 2025-03-11 18:59:44 -05:00
Kalle Lilja
f4c79530ec update gitattributes for windows (#6289) 2025-03-11 13:05:51 -05:00
Mark Trevor Birss
e9effb9fff Update platformio.ini (#6286) 2025-03-11 15:45:20 +02:00
Mark Trevor Birss
cb6dfb66d2 Update ME25LS01/MS24SF1 comment out upload port (#6285)
* Update platformio.ini

* Update platformio.ini

* Update platformio.ini
2025-03-11 14:56:12 +02:00
github-actions[bot]
8795a63427 Upgrade trunk (#6283)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-03-11 06:26:45 -05:00
Mark Trevor Birss
186e509607 Update esp32-s3-pico.json (#6284)
* Update esp32-s3-pico.json

* Update esp32-s3-pico.json
2025-03-11 13:11:11 +02:00
100 changed files with 977 additions and 314 deletions

View File

@@ -29,7 +29,11 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
gpg \
gnupg2 \
libusb-1.0-0-dev \
libuv1-dev \
libi2c-dev \
libxcb-xkb-dev \
libxkbcommon-dev \
libinput-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
RUN pipx install platformio

6
.gitattributes vendored
View File

@@ -1,5 +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
*.cmd text eol=crlf
*.bat text eol=crlf
*.ps1 text eol=crlf
*.{sh,[sS][hH]} text eol=lf

View File

@@ -11,4 +11,4 @@ runs:
- name: Install libs needed for native build
shell: bash
run: |
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev libuv1-dev

View File

@@ -18,5 +18,6 @@ jobs:
- name: Stale PR+Issues
uses: actions/stale@v9.1.0
with:
days-before-stale: 45
exempt-issue-labels: pinned,3.0
exempt-pr-labels: pinned,3.0

View File

@@ -143,7 +143,7 @@ jobs:
merge-multiple: true
- name: Test Report
uses: dorny/test-reporter@v1.9.1
uses: dorny/test-reporter@v2.0.0
with:
name: PlatformIO Tests
path: testreport.xml

View File

@@ -1,6 +1,6 @@
version: 0.1
cli:
version: 1.22.10
version: 1.22.11
plugins:
sources:
- id: trunk
@@ -9,14 +9,14 @@ plugins:
lint:
enabled:
- prettier@3.5.3
- trufflehog@3.88.15
- yamllint@1.35.1
- trufflehog@3.88.17
- yamllint@1.36.2
- bandit@1.8.3
- checkov@3.2.382
- checkov@3.2.386
- terrascan@1.19.9
- trivy@0.60.0
- taplo@0.9.3
- ruff@0.9.9
- ruff@0.11.0
- isort@6.0.1
- markdownlint@0.44.0
- oxipng@9.1.4

View File

@@ -13,7 +13,7 @@ ENV TZ=Etc/UTC
ENV PIP_ROOT_USER_ACTION=ignore
RUN apt-get update && apt-get install --no-install-recommends -y \
wget g++ zip git ca-certificates \
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev \
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& pip install --no-cache-dir -U platformio \
@@ -38,7 +38,7 @@ ENV TZ=Etc/UTC
USER root
RUN apt-get update && apt-get --no-install-recommends -y install \
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libulfius2.7 libusb-1.0-0-dev liborcania2.3 libssl3 \
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev liborcania2.3 libulfius2.7 libssl3 \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d \

View File

@@ -9,7 +9,7 @@ FROM python:3.13-alpine3.21 AS builder
ENV PIP_ROOT_USER_ACTION=ignore
RUN apk --no-cache add \
bash g++ libstdc++-dev linux-headers zip git ca-certificates libgpiod-dev yaml-cpp-dev bluez-dev \
libusb-dev i2c-tools-dev openssl-dev pkgconf argp-standalone \
libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \
&& rm -rf /var/cache/apk/* \
&& pip install --no-cache-dir -U platformio \
&& mkdir /tmp/firmware
@@ -32,7 +32,7 @@ FROM alpine:3.21
USER root
RUN apk --no-cache add \
libstdc++ libgpiod yaml-cpp libusb i2c-tools \
libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \
&& rm -rf /var/cache/apk/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d \

View File

@@ -17,7 +17,6 @@ build_flags =
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
-DMESHTASTIC_EXCLUDE_AUDIO=1
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
-DMAX_NUM_NODES=80
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>

View File

@@ -1,6 +1,6 @@
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
[portduino_base]
platform = https://github.com/meshtastic/platform-native.git#562d189828f09fbf4c4093b3c0104bae9d8e9ff9
platform = https://github.com/meshtastic/platform-native.git#df71ed0040e9aad767a002829330965b78fc452a
framework = arduino
build_src_filter =
@@ -34,10 +34,12 @@ build_flags =
-Isrc/platform/portduino
-DRADIOLIB_EEPROM_UNSUPPORTED
-DPORTDUINO_LINUX_HARDWARE
-DHAS_UDP_MULTICAST
-lpthread
-lstdc++fs
-lbluetooth
-lgpiod
-lyaml-cpp
-li2c
-luv
-std=c++17

View File

@@ -0,0 +1,17 @@
Lora:
Module: sx1262
CS: 0
IRQ: 6
Reset: 2
Busy: 4
RXen: 1
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
spidev: ch341
USB_PID: 0x5512
USB_VID: 0x1A86
# Optional: Reduce power to 10 dBm to
# avoid over-drawing the USB port
# SX126X_MAX_POWER: 10
# Optional: Set the serial number for multi-radio support
# USB_Serialnum: 13374201

View File

@@ -7,12 +7,19 @@ SET "DEBUG=0"
SET "PYTHON="
SET "WEB_APP=0"
SET "TFT_BUILD=0"
SET "TFT8=0"
SET "TFT16=0"
SET "BIGDB8=0"
SET "BIGDB16=0"
SET "ESPTOOL_BAUD=115200"
SET "ESPTOOL_CMD="
SET "LOGCOUNTER=0"
@REM FIXME: Determine mcu from PlatformIO variant, this is unmaintainable.
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
SET "C3=esp32c3"
@REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable.
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core tracksenger"
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite t-watch-s3"
GOTO getopts
:help
ECHO Flash image file to device, but first erasing and writing system information.
@@ -34,7 +41,7 @@ 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 %SCRIPT_NAME% [Version 2.6.1]
ECHO Meshtastic
GOTO eof
@@ -106,7 +113,7 @@ IF NOT "__%PYTHON%__"=="____" (
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
!ESPTOOL_CMD! >nul 2>&1
IF %ERRORLEVEL% GTR 2 (
IF %ERRORLEVEL% GEQ 2 (
@REM esptool exits with code 1 if help is displayed.
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
EXIT /B 1
@@ -121,6 +128,7 @@ CALL :LOG_MESSAGE DEBUG "Using esptool command: !ESPTOOL_CMD!"
IF "__!ESPTOOL_PORT!__" == "____" (
CALL :LOG_MESSAGE WARN "Using esptool port: UNSET."
) ELSE (
SET "ESPTOOL_CMD=!ESPTOOL_CMD! --port !ESPTOOL_PORT!"
CALL :LOG_MESSAGE INFO "Using esptool port: !ESPTOOL_PORT!."
)
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
@@ -133,44 +141,36 @@ IF NOT "!FILENAME:-tft-=!"=="!FILENAME!" (
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 (
FOR %%a IN (%BIGDB_8MB%) DO (
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
@REM We are working with any of %TFT8MB%.
SET "TFT8=1"
GOTO end_loop_tft8mb
@REM We are working with any of %BIGDB_8MB%.
SET "BIGDB8=1"
GOTO end_loop_bigdb_8mb
)
)
:end_loop_tft8mb
:end_loop_bigdb_8mb
SET "TFT16MB=t-deck"
FOR %%a IN (%TFT16MB%) DO (
FOR %%a IN (%BIGDB_16MB%) DO (
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
@REM We are working with any of %TFT16MB%.
SET "TFT16=1"
GOTO end_loop_tft16mb
@REM We are working with any of %BIGDB_16MB%.
SET "BIGDB16=1"
GOTO end_loop_bigdb_16mb
)
)
:end_loop_tft16mb
:end_loop_bigdb_16mb
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
IF %BIGDB8% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 8mb partition selected."
IF %BIGDB16% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 16mb partition selected."
@REM Extract BASENAME from %FILENAME% for later use.
SET "BASENAME=!FILENAME:firmware-=!"
CALL :LOG_MESSAGE DEBUG "Computed firmware basename: !BASENAME!"
@REM Account for S3 and C3 board's different OTA partition.
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%.
@@ -179,7 +179,6 @@ FOR %%a IN (%S3%) DO (
)
)
SET "C3=esp32c3"
FOR %%a IN (%C3%) DO (
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
@REM We are working with any of %C3%.
@@ -208,14 +207,14 @@ CALL :LOG_MESSAGE DEBUG "Set SPIFFS_FILENAME to: !SPIFFS_FILENAME!"
SET "OTA_OFFSET=0x260000"
SET "SPIFFS_OFFSET=0x300000"
@REM Offsets for MUI 8mb.
IF %TFT8% EQU 1 IF %TFT_BUILD% EQU 1 (
@REM Offsets for BigDB 8mb.
IF %BIGDB8% EQU 1 (
SET "OTA_OFFSET=0x340000"
SET "SPIFFS_OFFSET=0x670000"
)
@REM Offsets for MUI 16mb.
IF %TFT16% EQU 1 IF %TFT_BUILD% EQU 1 (
@REM Offsets for BigDB 16mb.
IF %BIGDB16% EQU 1 (
SET "OTA_OFFSET=0x650000"
SET "SPIFFS_OFFSET=0xc90000"
)

View File

@@ -2,9 +2,48 @@
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
WEB_APP=false
TFT8=false
TFT16=false
TFT_BUILD=false
MCU=""
# Variant groups
BIGDB_8MB=(
"picomputer-s3"
"unphone"
"seeed-sensecap-indicator"
"crowpanel-esp32s3"
"heltec_capsule_sensor_v3"
"heltec-v3"
"heltec-vision-master-e213"
"heltec-vision-master-e290"
"heltec-vision-master-t190"
"heltec-wireless-paper"
"heltec-wireless-tracker"
"heltec-wsl-v3"
"icarus"
"seeed-xiao-s3"
"tbeam-s3-core"
"tracksenger"
)
BIGDB_16MB=(
"t-deck"
"mesh-tab"
"t-energy-s3"
"dreamcatcher"
"ESP32-S3-Pico"
"m5stack-cores3"
"station-g2"
"t-eth-elite"
"t-watch-s3"
)
S3_VARIANTS=(
"s3"
"-v3"
"t-deck"
"wireless-paper"
"wireless-tracker"
"station-g2"
"unphone"
)
# Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
@@ -42,8 +81,8 @@ while [ $# -gt 0 ]; do
exit 0
;;
-p)
ESPTOOL_PORT="$2"
shift # Shift past the option argument
ESPTOOL_CMD="$ESPTOOL_CMD --port $2"
shift
;;
-P)
PYTHON="$2"
@@ -78,21 +117,13 @@ if [[ $FILENAME != firmware-* ]]; then
exit 1
fi
# Check if FILENAME contains "-tft-" and set target partitionScheme accordingly.
# Check if FILENAME contains "-tft-" and prevent web/mui comingling.
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.
@@ -105,20 +136,31 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
# Default OTA Offset
OTA_OFFSET=0x260000
# littlefs* offset for MUI 8mb and OTA OFFSET.
if [ "$TFT8" = true ] && [ "$TFT_BUILD" = true ]; then
OFFSET=0x670000
OTA_OFFSET=0x340000
fi
# littlefs* offset for BigDB 8mb and OTA OFFSET.
for variant in "${BIGDB_8MB[@]}"; do
if [ -n "${FILENAME##*"$variant"*}" ]; then
OFFSET=0x670000
OTA_OFFSET=0x340000
fi
done
# littlefs* offset for MUI 16mb and OTA OFFSET.
if [ "$TFT16" = true ] && [ "$TFT_BUILD" = true ]; then
OFFSET=0xc90000
OTA_OFFSET=0x650000
fi
# littlefs* offset for BigDB 16mb and OTA OFFSET.
for variant in "${BIGDB_16MB[@]}"; do
if [ -n "${FILENAME##*"$variant"*}" ]; then
OFFSET=0xc90000
OTA_OFFSET=0x650000
fi
done
# 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
# FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
for variant in "${S3_VARIANTS[@]}"; do
if [ -n "${FILENAME##*"$variant"*}" ]; then
MCU="esp32s3"
fi
done
if [ "$MCU" != "esp32s3" ]; then
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
OTAFILE=bleota.bin
else

View File

@@ -16,7 +16,7 @@ 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 -f filename The update .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).
@@ -28,7 +28,7 @@ ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4-update.bin -p C
GOTO eof
:version
ECHO %SCRIPT_NAME% [Version 2.6.0]
ECHO %SCRIPT_NAME% [Version 2.6.1]
ECHO Meshtastic
GOTO eof
@@ -53,6 +53,7 @@ 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
@@ -62,7 +63,6 @@ IF "__!FILENAME!__"=="____" (
SET "FILENAME=!FILENAME:./=!"
)
CALL :LOG_MESSAGE DEBUG "Filename: !FILENAME!"
CALL :LOG_MESSAGE DEBUG "Checking if !FILENAME! exists..."
IF NOT EXIST !FILENAME! (
CALL :LOG_MESSAGE ERROR "File does not exist: !FILENAME!. Terminating."
@@ -71,7 +71,7 @@ IF NOT EXIST !FILENAME! (
IF "!FILENAME:update=!"=="!FILENAME!" (
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!"
CALL :LOG_MESSAGE INFO "Use script device-install.bat to flash update !FILENAME!."
CALL :LOG_MESSAGE INFO "Use script device-install.bat to flash !FILENAME!."
GOTO eof
) ELSE (
CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!"
@@ -95,7 +95,7 @@ IF NOT "__%PYTHON%__"=="____" (
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
!ESPTOOL_CMD! >nul 2>&1
IF %ERRORLEVEL% GTR 2 (
IF %ERRORLEVEL% GEQ 2 (
@REM esptool exits with code 1 if help is displayed.
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
EXIT /B 1
@@ -110,6 +110,7 @@ CALL :LOG_MESSAGE DEBUG "Using esptool command: !ESPTOOL_CMD!"
IF "__!ESPTOOL_PORT!__" == "____" (
CALL :LOG_MESSAGE WARN "Using esptool port: UNSET."
) ELSE (
SET "ESPTOOL_CMD=!ESPTOOL_CMD! --port !ESPTOOL_PORT!"
CALL :LOG_MESSAGE INFO "Using esptool port: !ESPTOOL_PORT!."
)
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."

View File

@@ -35,8 +35,8 @@ while getopts ":hp:P:f:" opt; do
show_help
exit 0
;;
p) export ESPTOOL_PORT=${OPTARG}
;;
p) ESPTOOL_CMD="$ESPTOOL_CMD --port ${OPTARG}"
;;
P) PYTHON=${OPTARG}
;;
f) FILENAME=${OPTARG}

View File

@@ -83,7 +83,7 @@ if platform.name == "espressif32":
if platform.name == "nordicnrf52":
env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex",
env.VerboseAction(f"{sys.executable} ./bin/uf2conv.py $BUILD_DIR/firmware.hex -c -f 0xADA52840 -o $BUILD_DIR/firmware.uf2",
env.VerboseAction(f"\"{sys.executable}\" ./bin/uf2conv.py $BUILD_DIR/firmware.hex -c -f 0xADA52840 -o $BUILD_DIR/firmware.uf2",
"Generating UF2 file"))
Import("projenv")

View File

@@ -7,13 +7,15 @@
"core": "esp32",
"extra_flags": [
"-DARDUINO_ESP32S3_DEV",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
"-DARDUINO_EVENT_RUNNING_CORE=1",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DBOARD_HAS_PSRAM"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "qio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "esp32s3"

1
debian/control vendored
View File

@@ -17,6 +17,7 @@ Build-Depends: debhelper-compat (= 13),
libbluetooth-dev,
libusb-1.0-0-dev,
libi2c-dev,
libuv1-dev,
openssl,
libssl-dev,
libulfius-dev,

View File

@@ -36,6 +36,7 @@ BuildRequires: pkgconfig(libgpiod)
BuildRequires: pkgconfig(bluez)
BuildRequires: pkgconfig(libusb-1.0)
BuildRequires: libi2c-devel
BuildRequires: pkgconfig(libuv)
# Web components:
BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(liborcania)

View File

@@ -121,10 +121,15 @@ extern "C" void logLegacy(const char *level, const char *fmt, ...);
// Default Bluetooth PIN
#define defaultBLEPin 123456
#if HAS_ETHERNET
#if HAS_ETHERNET && !defined(USE_WS5500)
#include <RAK13800_W5100S.h>
#endif // HAS_ETHERNET
#if HAS_ETHERNET && defined(USE_WS5500)
#include <ETHClass2.h>
#define ETH ETH2
#endif // HAS_ETHERNET
#if HAS_WIFI
#include <WiFi.h>
#endif // HAS_WIFI
@@ -164,4 +169,4 @@ class Syslog
bool vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
};
#endif // HAS_ETHERNET || HAS_WIFI
#endif // HAS_NETWORKING

View File

@@ -32,6 +32,11 @@
#include <WiFi.h>
#endif
#if HAS_ETHERNET && defined(USE_WS5500)
#include <ETHClass2.h>
#define ETH ETH2
#endif // HAS_ETHERNET
#endif
#ifndef DELAY_FOREVER

View File

@@ -11,12 +11,18 @@ static File openFile(const char *filename, bool fullAtomic)
FSCom.remove(filename);
return FSCom.open(filename, FILE_O_WRITE);
#endif
if (!fullAtomic)
if (!fullAtomic) {
FSCom.remove(filename); // Nuke the old file to make space (ignore if it !exists)
}
String filenameTmp = filename;
filenameTmp += ".tmp";
// FIXME: If we are doing a full atomic write, we may need to remove the old tmp file now
// if (fullAtomic) {
// FSCom.remove(filename);
// }
// clear any previous LFS errors
return FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
}

View File

@@ -1104,12 +1104,16 @@ int32_t GPS::runOnce()
return (powerState == GPS_ACTIVE) ? GPS_THREAD_INTERVAL : 5000;
}
// clear the GPS rx buffer as quickly as possible
// clear the GPS rx/tx buffer as quickly as possible
void GPS::clearBuffer()
{
#ifdef ARCH_ESP32
_serial_gps->flush(false);
#else
int x = _serial_gps->available();
while (x--)
_serial_gps->read();
#endif
}
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs

View File

@@ -324,6 +324,14 @@ void EInkDynamicDisplay::checkConsecutiveFastRefreshes()
if (refresh != UNSPECIFIED)
return;
// Bypass limit if UNLIMITED_FAST mode is active
if (frameFlags & UNLIMITED_FAST) {
refresh = FAST;
reason = NO_OBJECTIONS;
LOG_DEBUG("refresh=FAST, reason=UNLIMITED_FAST_MODE_ACTIVE, frameFlags=0x%x", frameFlags);
return;
}
// If too many FAST refreshes consecutively - force a FULL refresh
if (fastRefreshCount >= EINK_LIMIT_FASTREFRESH) {
refresh = FULL;

View File

@@ -23,6 +23,10 @@ class EInkDynamicDisplay : public EInkDisplay, protected concurrency::NotifiedWo
EInkDynamicDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus);
~EInkDynamicDisplay();
// Methods to enable or disable unlimited fast refresh mode
void enableUnlimitedFastMode() { addFrameFlag(UNLIMITED_FAST); }
void disableUnlimitedFastMode() { frameFlags = (frameFlagTypes)(frameFlags & ~UNLIMITED_FAST); }
// What kind of frame is this
enum frameFlagTypes : uint8_t {
BACKGROUND = (1 << 0), // For frames via display()
@@ -30,6 +34,7 @@ class EInkDynamicDisplay : public EInkDisplay, protected concurrency::NotifiedWo
COSMETIC = (1 << 2), // For splashes
DEMAND_FAST = (1 << 3), // Special case only
BLOCKING = (1 << 4), // Modifier - block while refresh runs
UNLIMITED_FAST = (1 << 5)
};
void addFrameFlag(frameFlagTypes flag);

View File

@@ -55,12 +55,12 @@ NimbleBluetooth *nimbleBluetooth = nullptr;
NRF52Bluetooth *nrf52Bluetooth = nullptr;
#endif
#if HAS_WIFI
#if HAS_WIFI || defined(USE_WS5500)
#include "mesh/api/WiFiServerAPI.h"
#include "mesh/wifi/WiFiAPClient.h"
#endif
#if HAS_ETHERNET
#if HAS_ETHERNET && !defined(USE_WS5500)
#include "mesh/api/ethServerAPI.h"
#include "mesh/eth/ethClient.h"
#endif
@@ -822,6 +822,11 @@ void setup()
#ifdef HAS_UDP_MULTICAST
LOG_DEBUG("Start multicast thread");
udpThread = new UdpMulticastThread();
#ifdef ARCH_PORTDUINO
// FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call
// onNetworkConnected there
udpThread->start();
#endif
#endif
service = new MeshService();
service->init();

View File

@@ -25,7 +25,7 @@ template class LR11x0Interface<LR1121>;
template class SX126xInterface<STM32WLx>;
#endif
#if HAS_ETHERNET
#if HAS_ETHERNET && !defined(USE_WS5500)
#include "api/ethServerAPI.h"
template class ServerAPI<EthernetClient>;
template class APIServerPort<ethServerAPI, EthernetServer>;

View File

@@ -125,17 +125,15 @@ void MeshService::loop()
}
/// The radioConfig object just changed, call this to force the hw to change to the new settings
bool MeshService::reloadConfig(int saveWhat)
void MeshService::reloadConfig(int saveWhat)
{
// If we can successfully set this radio to these settings, save them to disk
// This will also update the region as needed
bool didReset = nodeDB->resetRadioConfig(); // Don't let the phone send us fatally bad settings
nodeDB->resetRadioConfig(); // Don't let the phone send us fatally bad settings
configChanged.notifyObservers(NULL); // This will cause radio hardware to change freqs etc
nodeDB->saveToDisk(saveWhat);
return didReset;
}
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh

View File

@@ -118,7 +118,7 @@ class MeshService
/** The radioConfig object just changed, call this to force the hw to change to the new settings
* @return true if client devices should be sent a new set of radio configs
*/
bool reloadConfig(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
void reloadConfig(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
void reloadOwner(bool shouldSave = true);

View File

@@ -51,6 +51,10 @@
#include <utility/bonding.h>
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
#include <WiFiOTA.h>
#endif
NodeDB *nodeDB = nullptr;
// we have plenty of ram so statically alloc this tempbuf (for now)
@@ -400,18 +404,12 @@ bool isBroadcast(uint32_t dest)
return dest == NODENUM_BROADCAST || dest == NODENUM_BROADCAST_NO_LORA;
}
bool NodeDB::resetRadioConfig(bool factory_reset, bool is_fresh_install)
void NodeDB::resetRadioConfig(bool is_fresh_install)
{
bool didFactoryReset = false;
if (is_fresh_install) {
radioGeneration++;
}
if (factory_reset) {
didFactoryReset = factoryReset();
}
if (channelFile.channels_count != MAX_NUM_CHANNELS) {
LOG_INFO("Set default channel and radio preferences!");
@@ -422,14 +420,6 @@ bool NodeDB::resetRadioConfig(bool factory_reset, bool is_fresh_install)
// Update the global myRegion
initRegion();
if (didFactoryReset) {
LOG_INFO("Reboot due to factory reset");
screen->startAlert("Rebooting...");
rebootAtMsec = millis() + (5 * 1000);
}
return didFactoryReset;
}
bool NodeDB::factoryReset(bool eraseBleBonds)
@@ -591,7 +581,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
config.device.node_info_broadcast_secs = default_node_info_broadcast_secs;
config.security.serial_enabled = true;
config.security.admin_channel_enabled = false;
resetRadioConfig(false, true); // This also triggers NodeInfo/Position requests since we're fresh
resetRadioConfig(true); // This also triggers NodeInfo/Position requests since we're fresh
strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32);
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR)) && \
@@ -649,6 +639,12 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
config.display.wake_on_tap_or_motion = true;
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
if (WiFiOTA::isUpdated()) {
WiFiOTA::recoverConfig(&config.network);
}
#endif
initConfigIntervals();
}
@@ -1612,6 +1608,94 @@ UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
}
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
{
bool success = false;
lastBackupAttempt = millis();
#ifdef FSCom
if (location == meshtastic_AdminMessage_BackupLocation_FLASH) {
meshtastic_BackupPreferences backup = meshtastic_BackupPreferences_init_zero;
backup.version = DEVICESTATE_CUR_VER;
backup.timestamp = getValidTime(RTCQuality::RTCQualityDevice, false);
backup.has_config = true;
backup.config = config;
backup.has_module_config = true;
backup.module_config = moduleConfig;
backup.has_channels = true;
backup.channels = channelFile;
backup.has_owner = true;
backup.owner = owner;
size_t backupSize;
pb_get_encoded_size(&backupSize, meshtastic_BackupPreferences_fields, &backup);
spiLock->lock();
FSCom.mkdir("/backups");
spiLock->unlock();
success = saveProto(backupFileName, backupSize, &meshtastic_BackupPreferences_msg, &backup);
if (success) {
LOG_INFO("Saved backup preferences");
} else {
LOG_ERROR("Failed to save backup preferences to file");
}
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
// TODO: After more mainline SD card support
}
#endif
return success;
}
bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location, int restoreWhat)
{
bool success = false;
#ifdef FSCom
if (location == meshtastic_AdminMessage_BackupLocation_FLASH) {
spiLock->lock();
if (!FSCom.exists(backupFileName)) {
spiLock->unlock();
LOG_WARN("Could not restore. No backup file found");
return false;
} else {
spiLock->unlock();
}
meshtastic_BackupPreferences backup = meshtastic_BackupPreferences_init_zero;
success = loadProto(backupFileName, meshtastic_BackupPreferences_size, sizeof(meshtastic_BackupPreferences),
&meshtastic_BackupPreferences_msg, &backup);
if (success) {
if (restoreWhat & SEGMENT_CONFIG) {
config = backup.config;
LOG_DEBUG("Restored config");
}
if (restoreWhat & SEGMENT_MODULECONFIG) {
moduleConfig = backup.module_config;
LOG_DEBUG("Restored module config");
}
if (restoreWhat & SEGMENT_DEVICESTATE) {
devicestate.owner = backup.owner;
LOG_DEBUG("Restored device state");
}
if (restoreWhat & SEGMENT_CHANNELS) {
channelFile = backup.channels;
LOG_DEBUG("Restored channels");
}
success = saveToDisk(restoreWhat);
if (success) {
LOG_INFO("Restored preferences from backup");
} else {
LOG_ERROR("Failed to save restored preferences to flash");
}
} else {
LOG_ERROR("Failed to restore preferences from backup file");
}
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
// TODO: After more mainline SD card support
}
return success;
#endif
}
/// Record an error that should be reported via analytics
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
{

View File

@@ -48,6 +48,7 @@ static constexpr const char *configFileName = "/prefs/config.proto";
static constexpr const char *uiconfigFileName = "/prefs/uiconfig.proto";
static constexpr const char *moduleConfigFileName = "/prefs/module.proto";
static constexpr const char *channelFileName = "/prefs/channels.proto";
static constexpr const char *backupFileName = "/backups/backup.proto";
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n);
@@ -103,7 +104,7 @@ class NodeDB
* @param is_fresh_install set to true after a fresh install, to trigger NodeInfo/Position requests
* @return true if the config was completely reset, in that case, we should send it back to the client
*/
bool resetRadioConfig(bool factory_reset = false, bool is_fresh_install = false);
void resetRadioConfig(bool is_fresh_install = false);
/// given a subpacket sniffed from the network, update our DB state
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
@@ -202,8 +203,13 @@ class NodeDB
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
int restoreWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
private:
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
/// Find a node in our DB, create an empty NodeInfoLite if missing
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);

View File

@@ -73,9 +73,10 @@ const RegionInfo regions[] = {
RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false),
/*
???
https://www.law.go.kr/LSW/admRulLsInfoP.do?admRulId=53943&efYd=0
https://resources.lora-alliance.org/technical-specifications/rp002-1-0-4-regional-parameters
*/
RDEF(KR, 920.0f, 923.0f, 100, 0, 0, true, false, false),
RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false),
/*
Taiwan, 920-925Mhz, limited to 0.5W indoor or coastal, 1.0W outdoor.
@@ -655,7 +656,7 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
// if the sender nodenum is zero, that means uninitialized
assert(radioBuffer.header.from);
assert(p->encrypted.size <= sizeof(radioBuffer.payload));
memcpy(radioBuffer.payload, p->encrypted.bytes, p->encrypted.size);
sendingPacket = p;

View File

@@ -198,6 +198,14 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
return send(p);
}
}
/**
* Send a packet on a suitable interface.
*/
ErrorCode Router::rawSend(meshtastic_MeshPacket *p)
{
assert(iface); // This should have been detected already in sendLocal (or we just received a packet from outside)
return iface->send(p);
}
/**
* Send a packet on a suitable interface. This routine will
@@ -319,27 +327,27 @@ void Router::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Rout
// FIXME, update nodedb here for any packet that passes through us
}
bool perhapsDecode(meshtastic_MeshPacket *p)
DecodeState perhapsDecode(meshtastic_MeshPacket *p)
{
concurrency::LockGuard g(cryptLock);
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING)
return false;
return DecodeState::DECODE_FAILURE;
if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY &&
(nodeDB->getMeshNode(p->from) == NULL || !nodeDB->getMeshNode(p->from)->has_user)) {
LOG_DEBUG("Node 0x%x not in nodeDB-> Rebroadcast mode KNOWN_ONLY will ignore packet", p->from);
return false;
return DecodeState::DECODE_FAILURE;
}
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag)
return true; // If packet was already decoded just return
return DecodeState::DECODE_SUCCESS; // If packet was already decoded just return
size_t rawSize = p->encrypted.size;
if (rawSize > sizeof(bytes)) {
LOG_ERROR("Packet too large to attempt decryption! (rawSize=%d > 256)", rawSize);
return false;
return DecodeState::DECODE_FATAL;
}
bool decrypted = false;
ChannelIndex chIndex = 0;
@@ -353,18 +361,22 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
if (crypto->decryptCurve25519(p->from, nodeDB->getMeshNode(p->from)->user.public_key, p->id, rawSize, p->encrypted.bytes,
bytes)) {
LOG_INFO("PKI Decryption worked!");
memset(&p->decoded, 0, sizeof(p->decoded));
meshtastic_Data decodedtmp;
memset(&decodedtmp, 0, sizeof(decodedtmp));
rawSize -= MESHTASTIC_PKC_OVERHEAD;
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded) &&
p->decoded.portnum != meshtastic_PortNum_UNKNOWN_APP) {
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp) &&
decodedtmp.portnum != meshtastic_PortNum_UNKNOWN_APP) {
decrypted = true;
LOG_INFO("Packet decrypted using PKI!");
p->pki_encrypted = true;
memcpy(&p->public_key.bytes, nodeDB->getMeshNode(p->from)->user.public_key.bytes, 32);
p->public_key.size = 32;
p->decoded = decodedtmp;
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded
} else {
LOG_ERROR("PKC Decrypted, but pb_decode failed!");
return false;
return DecodeState::DECODE_FAILURE;
}
} else {
LOG_WARN("PKC decrypt attempted but failed!");
@@ -387,12 +399,15 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
// printBytes("plaintext", bytes, p->encrypted.size);
// Take those raw bytes and convert them back into a well structured protobuf we can understand
memset(&p->decoded, 0, sizeof(p->decoded));
if (!pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded)) {
meshtastic_Data decodedtmp;
memset(&decodedtmp, 0, sizeof(decodedtmp));
if (!pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp)) {
LOG_ERROR("Invalid protobufs in received mesh packet id=0x%08x (bad psk?)!", p->id);
} else if (p->decoded.portnum == meshtastic_PortNum_UNKNOWN_APP) {
} else if (decodedtmp.portnum == meshtastic_PortNum_UNKNOWN_APP) {
LOG_ERROR("Invalid portnum (bad psk?)!");
} else {
p->decoded = decodedtmp;
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded
decrypted = true;
break;
}
@@ -401,8 +416,7 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
}
if (decrypted) {
// parsing was successful
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded
p->channel = chIndex; // change to store the index instead of the hash
p->channel = chIndex; // change to store the index instead of the hash
if (p->decoded.has_bitfield)
p->decoded.want_response |= p->decoded.bitfield & BITFIELD_WANT_RESPONSE_MASK;
@@ -434,10 +448,10 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str());
}
#endif
return true;
return DecodeState::DECODE_SUCCESS;
} else {
LOG_WARN("No suitable channel found for decoding, hash was 0x%x!", p->channel);
return false;
return DecodeState::DECODE_FAILURE;
}
}
@@ -592,8 +606,13 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
meshtastic_MeshPacket *p_encrypted = packetPool.allocCopy(*p);
// Take those raw bytes and convert them back into a well structured protobuf we can understand
bool decoded = perhapsDecode(p);
if (decoded) {
auto decodedState = perhapsDecode(p);
if (decodedState == DecodeState::DECODE_FATAL) {
// Fatal decoding error, we can't do anything with this packet
LOG_WARN("Fatal decode error, dropping packet");
cancelSending(p->from, p->id);
skipHandle = true;
} else if (decodedState == DecodeState::DECODE_SUCCESS) {
// parsing was successful, queue for our recipient
if (src == RX_SRC_LOCAL)
printPacket("handleReceived(LOCAL)", p);
@@ -636,10 +655,12 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
#if !MESHTASTIC_EXCLUDE_MQTT
// Mark as pki_encrypted if it is not yet decoded and MQTT encryption is also enabled, hash matches and it's a DM not to
// us (because we would be able to decrypt it)
if (!decoded && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 && !isBroadcast(p->to) && !isToUs(p))
if (decodedState == DecodeState::DECODE_FAILURE && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 &&
!isBroadcast(p->to) && !isToUs(p))
p_encrypted->pki_encrypted = true;
// After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet
if ((decoded || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled && !isFromUs(p) && mqtt)
if ((decodedState == DecodeState::DECODE_SUCCESS || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled &&
!isFromUs(p) && mqtt)
mqtt->onSend(*p_encrypted, *p, p->channel);
#endif
}

View File

@@ -85,6 +85,7 @@ class Router : protected concurrency::OSThread, protected PacketHistory
* NOTE: This method will free the provided packet (even if we return an error code)
*/
virtual ErrorCode send(meshtastic_MeshPacket *p);
virtual ErrorCode rawSend(meshtastic_MeshPacket *p);
/* Statistics for the amount of duplicate received packets and the amount of times we cancel a relay because someone did it
before us */
@@ -139,12 +140,14 @@ class Router : protected concurrency::OSThread, protected PacketHistory
void abortSendAndNak(meshtastic_Routing_Error err, meshtastic_MeshPacket *p);
};
enum DecodeState { DECODE_SUCCESS, DECODE_FAILURE, DECODE_FATAL };
/** FIXME - move this into a mesh packet class
* Remove any encryption and decode the protobufs inside this packet (if necessary).
*
* @return true for success, false for corrupt packet.
*/
bool perhapsDecode(meshtastic_MeshPacket *p);
DecodeState perhapsDecode(meshtastic_MeshPacket *p);
/** Return 0 for success or a Routing_Error code for failure
*/

View File

@@ -89,18 +89,20 @@ bool PacketAPI::receivePacket(void)
bool PacketAPI::sendPacket(void)
{
// fill dummy buffer; we don't use it, we directly send the fromRadio structure
uint32_t len = getFromRadio(txBuf);
if (len != 0) {
static uint32_t id = 0;
fromRadioScratch.id = ++id;
bool result = server->sendPacket(DataPacket<meshtastic_FromRadio>(id, fromRadioScratch));
if (!result) {
LOG_ERROR("send queue full");
if (server->available()) {
// fill dummy buffer; we don't use it, we directly send the fromRadio structure
uint32_t len = getFromRadio(txBuf);
if (len != 0) {
static uint32_t id = 0;
fromRadioScratch.id = ++id;
bool result = server->sendPacket(DataPacket<meshtastic_FromRadio>(id, fromRadioScratch));
if (!result) {
LOG_ERROR("send queue full");
}
return result;
}
return result;
} else
return false;
}
return false;
}
bool PacketAPI::notifyProgrammingMode(void)

View File

@@ -3,6 +3,11 @@
#include "ServerAPI.h"
#include <WiFi.h>
#if HAS_ETHERNET && defined(USE_WS5500)
#include <ETHClass2.h>
#define ETH ETH2
#endif // HAS_ETHERNET
/**
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).

View File

@@ -1,7 +1,7 @@
#include "configuration.h"
#include <Arduino.h>
#if HAS_ETHERNET
#if HAS_ETHERNET && !defined(USE_WS5500)
#include "ethServerAPI.h"

View File

@@ -1,6 +1,7 @@
#pragma once
#include "ServerAPI.h"
#ifndef USE_WS5500
#include <RAK13800_W5100S.h>
/**
@@ -23,3 +24,4 @@ class ethServerPort : public APIServerPort<ethServerAPI, EthernetServer>
};
void initApiServer(int port = SERVER_API_DEFAULT_PORT);
#endif

View File

@@ -34,7 +34,7 @@ typedef enum _meshtastic_AdminMessage_ConfigType {
meshtastic_AdminMessage_ConfigType_BLUETOOTH_CONFIG = 6,
/* TODO: REPLACE */
meshtastic_AdminMessage_ConfigType_SECURITY_CONFIG = 7,
/* */
/* Session key config */
meshtastic_AdminMessage_ConfigType_SESSIONKEY_CONFIG = 8,
/* device-ui config */
meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG = 9

View File

@@ -374,7 +374,7 @@ typedef struct _meshtastic_Config_PositionConfig {
/* Power Config\
See [Power Config](/docs/settings/config/power) for additional power config details. */
typedef struct _meshtastic_Config_PowerConfig {
/* Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio.
/* Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio.
Don't use this setting if you want to use your device with the phone apps or are using a device without a user button.
Technical Details: Works for ESP32 devices and NRF52 devices in the Sensor or Tracker roles */
bool is_power_saving;
@@ -426,7 +426,7 @@ typedef struct _meshtastic_Config_NetworkConfig {
char wifi_ssid[33];
/* If set, will be use to authenticate to the named wifi */
char wifi_psk[65];
/* NTP server to use if WiFi is conneced, defaults to `0.pool.ntp.org` */
/* NTP server to use if WiFi is conneced, defaults to `meshtastic.pool.ntp.org` */
char ntp_server[33];
/* Enable Ethernet */
bool eth_enabled;

View File

@@ -53,6 +53,8 @@ typedef enum _meshtastic_Language {
meshtastic_Language_NORWEGIAN = 14,
/* Slovenian */
meshtastic_Language_SLOVENIAN = 15,
/* Ukrainian */
meshtastic_Language_UKRAINIAN = 16,
/* Simplified Chinese (experimental) */
meshtastic_Language_SIMPLIFIED_CHINESE = 30,
/* Traditional Chinese (experimental) */

View File

@@ -159,7 +159,7 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_TD_LORAC = 60,
/* CDEBYTE EoRa-S3 board using their own MM modules, clone of LILYGO T3S3 */
meshtastic_HardwareModel_CDEBYTE_EORA_S3 = 61,
/* TWC_MESH_V4
/* TWC_MESH_V4
Adafruit NRF52840 feather express with SX1262, SSD1306 OLED and NEO6M GPS */
meshtastic_HardwareModel_TWC_MESH_V4 = 62,
/* NRF52_PROMICRO_DIY
@@ -228,6 +228,13 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_MESHLINK = 87,
/* Seeed XIAO nRF52840 + Wio SX1262 kit */
meshtastic_HardwareModel_XIAO_NRF52_KIT = 88,
/* Elecrow ThinkNode M1 & M2
https://www.elecrow.com/wiki/ThinkNode-M1_Transceiver_Device(Meshtastic)_Power_By_nRF52840.html
https://www.elecrow.com/wiki/ThinkNode-M2_Transceiver_Device(Meshtastic)_Power_By_NRF52840.html (this actually uses ESP32-S3) */
meshtastic_HardwareModel_THINKNODE_M1 = 89,
meshtastic_HardwareModel_THINKNODE_M2 = 90,
/* Lilygo T-ETH-Elite */
meshtastic_HardwareModel_T_ETH_ELITE = 91,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -769,7 +776,7 @@ typedef struct _meshtastic_MeshPacket {
meshtastic_MeshPacket_public_key_t public_key;
/* Indicates whether the packet was en/decrypted using PKI */
bool pki_encrypted;
/* Last byte of the node number of the node that should be used as the next hop in routing.
/* Last byte of the node number of the node that should be used as the next hop in routing.
Set by the firmware internally, clients are not supposed to set this. */
uint8_t next_hop;
/* Last byte of the node number of the node that will relay/relayed this packet.

View File

@@ -12,6 +12,11 @@
#include <WebServer.h>
#include <WiFi.h>
#if HAS_ETHERNET && defined(USE_WS5500)
#include <ETHClass2.h>
#define ETH ETH2
#endif // HAS_ETHERNET
#ifdef ARCH_ESP32
#include "esp_task_wdt.h"
#endif
@@ -166,14 +171,14 @@ WebServerThread *webServerThread;
WebServerThread::WebServerThread() : concurrency::OSThread("WebServer")
{
if (!config.network.wifi_enabled) {
if (!config.network.wifi_enabled && !config.network.eth_enabled) {
disable();
}
}
int32_t WebServerThread::runOnce()
{
if (!config.network.wifi_enabled) {
if (!config.network.wifi_enabled && !config.network.eth_enabled) {
disable();
}

View File

@@ -18,10 +18,30 @@
#define MAX_RX_TOPHONE 32
#endif
/// max number of nodes allowed in the mesh
/// max number of nodes allowed in the nodeDB
#ifndef MAX_NUM_NODES
#if defined(ARCH_STM32WL)
#define MAX_NUM_NODES 10
#elif defined(ARCH_NRF52)
#define MAX_NUM_NODES 80
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
#include "Esp.h"
static inline int get_max_num_nodes()
{
uint32_t flash_size = ESP.getFlashChipSize() / (1024 * 1024); // Convert Bytes to MB
if (flash_size >= 15) {
return 250;
} else if (flash_size >= 7) {
return 200;
} else {
return 100;
}
}
#define MAX_NUM_NODES get_max_num_nodes()
#else
#define MAX_NUM_NODES 100
#endif
#endif
/// Max number of channels allowed
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))

View File

@@ -7,6 +7,11 @@
#include <AsyncUDP.h>
#include <WiFi.h>
#if HAS_ETHERNET && defined(USE_WS5500)
#include <ETHClass2.h>
#define ETH ETH2
#endif // HAS_ETHERNET
#define UDP_MULTICAST_DEFAUL_PORT 4403 // Default port for UDP multicast is same as TCP api server
#define UDP_MULTICAST_THREAD_INTERVAL_MS 15000
@@ -17,8 +22,13 @@ class UdpMulticastThread : public concurrency::OSThread
void start()
{
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT)) {
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT, 64)) {
#if !defined(ARCH_PORTDUINO)
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
#else
LOG_DEBUG("UDP Listening");
#endif
udp.onPacket([this](AsyncUDPPacket packet) { onReceive(packet); });
} else {
LOG_DEBUG("Failed to listen on UDP");
@@ -28,12 +38,13 @@ class UdpMulticastThread : public concurrency::OSThread
void onReceive(AsyncUDPPacket packet)
{
size_t packetLength = packet.length();
#ifndef ARCH_PORTDUINO
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
#endif
meshtastic_MeshPacket mp;
uint8_t bytes[meshtastic_MeshPacket_size]; // Allocate buffer for the data
size_t packetSize = packet.readBytes(bytes, packet.length());
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetSize);
bool isPacketDecoded = pb_decode_from_bytes(bytes, packetLength, &meshtastic_MeshPacket_msg, &mp);
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetLength);
bool isPacketDecoded = pb_decode_from_bytes(packet.data(), packetLength, &meshtastic_MeshPacket_msg, &mp);
if (isPacketDecoded && router) {
UniquePacketPoolPacket p = packetPool.allocUniqueCopy(mp);
// Unset received SNR/RSSI
@@ -45,13 +56,18 @@ class UdpMulticastThread : public concurrency::OSThread
bool onSend(const meshtastic_MeshPacket *mp)
{
if (!mp || WiFi.status() != WL_CONNECTED) {
if (!mp || !udp) {
return false;
}
#if !defined(ARCH_PORTDUINO)
if (WiFi.status() != WL_CONNECTED) {
return false;
}
#endif
LOG_DEBUG("Broadcasting packet over UDP (id=%u)", mp->id);
uint8_t buffer[meshtastic_MeshPacket_size];
size_t encodedLength = pb_encode_to_bytes(buffer, sizeof(buffer), &meshtastic_MeshPacket_msg, mp);
udp.broadcastTo(buffer, encodedLength, UDP_MULTICAST_DEFAUL_PORT);
udp.writeTo(buffer, encodedLength, udpIpAddress, UDP_MULTICAST_DEFAUL_PORT);
return true;
}
@@ -67,4 +83,4 @@ class UdpMulticastThread : public concurrency::OSThread
IPAddress udpIpAddress;
AsyncUDP udp;
};
#endif // ARCH_ESP32
#endif // HAS_UDP_MULTICAST

View File

@@ -9,6 +9,12 @@
#include "mesh/api/WiFiServerAPI.h"
#include "target_specific.h"
#include <WiFi.h>
#if HAS_ETHERNET && defined(USE_WS5500)
#include <ETHClass2.h>
#define ETH ETH2
#endif // HAS_ETHERNET
#include <WiFiUdp.h>
#ifdef ARCH_ESP32
#if !MESHTASTIC_EXCLUDE_WEBSERVER
@@ -52,11 +58,28 @@ Syslog syslog(syslogClient);
Periodic *wifiReconnect;
#ifdef USE_WS5500
// Startup Ethernet
bool initEthernet()
{
if ((config.network.eth_enabled) && (ETH.begin(ETH_PHY_W5500, 1, ETH_CS_PIN, ETH_INT_PIN, ETH_RST_PIN, SPI3_HOST,
ETH_SCLK_PIN, ETH_MISO_PIN, ETH_MOSI_PIN))) {
WiFi.onEvent(WiFiEvent);
#if !MESHTASTIC_EXCLUDE_WEBSERVER
createSSLCert(); // For WebServer
#endif
return true;
}
return false;
}
#endif
static void onNetworkConnected()
{
if (!APStartupComplete) {
// Start web server
LOG_INFO("Start WiFi network services");
LOG_INFO("Start network services");
// start mdns
if (!MDNS.begin("Meshtastic")) {
@@ -188,6 +211,10 @@ bool isWifiAvailable()
if (config.network.wifi_enabled && (config.network.wifi_ssid[0])) {
return true;
#ifdef USE_WS5500
} else if (config.network.eth_enabled) {
return true;
#endif
} else {
return false;
}
@@ -282,7 +309,7 @@ bool initWifi()
// Called by the Espressif SDK to
static void WiFiEvent(WiFiEvent_t event)
{
LOG_DEBUG("WiFi-Event %d: ", event);
LOG_DEBUG("Network-Event %d: ", event);
switch (event) {
case ARDUINO_EVENT_WIFI_READY:
@@ -377,19 +404,32 @@ static void WiFiEvent(WiFiEvent_t event)
LOG_INFO("Ethernet started");
break;
case ARDUINO_EVENT_ETH_STOP:
syslog.disable();
LOG_INFO("Ethernet stopped");
break;
case ARDUINO_EVENT_ETH_CONNECTED:
LOG_INFO("Ethernet connected");
break;
case ARDUINO_EVENT_ETH_DISCONNECTED:
syslog.disable();
LOG_INFO("Ethernet disconnected");
break;
case ARDUINO_EVENT_ETH_GOT_IP:
LOG_INFO("Obtained IP address (ARDUINO_EVENT_ETH_GOT_IP)");
#ifdef USE_WS5500
LOG_INFO("Obtained IP address: %s, %u Mbps, %s", ETH.localIP().toString().c_str(), ETH.linkSpeed(),
ETH.fullDuplex() ? "FULL_DUPLEX" : "HALF_DUPLEX");
onNetworkConnected();
#endif
break;
case ARDUINO_EVENT_ETH_GOT_IP6:
LOG_INFO("Obtained IP6 address (ARDUINO_EVENT_ETH_GOT_IP6)");
#ifdef USE_WS5500
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
LOG_INFO("Obtained Local IP6 address: %s", ETH.linkLocalIPv6().toString().c_str());
LOG_INFO("Obtained GlobalIP6 address: %s", ETH.globalIPv6().toString().c_str());
#else
LOG_INFO("Obtained IP6 address: %s", ETH.localIPv6().toString().c_str());
#endif
#endif
break;
case ARDUINO_EVENT_SC_SCAN_DONE:
LOG_INFO("SmartConfig: Scan done");

View File

@@ -9,6 +9,11 @@
#include <WiFi.h>
#endif
#if HAS_ETHERNET && defined(USE_WS5500)
#include <ETHClass2.h>
#define ETH ETH2
#endif // HAS_ETHERNET
extern bool needReconnect;
extern concurrency::Periodic *wifiReconnect;
@@ -19,4 +24,9 @@ void deinitWifi();
bool isWifiAvailable();
uint8_t getWifiDisconnectReason();
uint8_t getWifiDisconnectReason();
#ifdef USE_WS5500
// Startup Ethernet
bool initEthernet();
#endif

View File

@@ -10,6 +10,9 @@
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
#include "BleOta.h"
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
#include "WiFiOTA.h"
#endif
#include "Router.h"
#include "configuration.h"
#include "main.h"
@@ -194,19 +197,23 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
}
case meshtastic_AdminMessage_reboot_ota_seconds_tag: {
int32_t s = r->reboot_ota_seconds;
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
if (BleOta::getOtaAppVersion().isEmpty()) {
LOG_INFO("No OTA firmware available, scheduling regular reboot in %d seconds", s);
screen->startAlert("Rebooting...");
} else {
#if defined(ARCH_ESP32)
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
if (!BleOta::getOtaAppVersion().isEmpty()) {
screen->startFirmwareUpdateScreen();
BleOta::switchToOtaApp();
LOG_INFO("Reboot to OTA in %d seconds", s);
LOG_INFO("Rebooting to BLE OTA");
}
#else
LOG_INFO("Not on ESP32, scheduling regular reboot in %d seconds", s);
screen->startAlert("Rebooting...");
#endif
#if !MESHTASTIC_EXCLUDE_WIFI
if (WiFiOTA::trySwitchToOTA()) {
screen->startFirmwareUpdateScreen();
WiFiOTA::saveConfig(&config.network);
LOG_INFO("Rebooting to WiFi OTA");
}
#endif
#endif
LOG_INFO("Reboot in %d seconds", s);
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break;
}
@@ -370,6 +377,42 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
LOG_DEBUG("Failed to delete file");
}
spiLock->unlock();
#endif
break;
}
case meshtastic_AdminMessage_backup_preferences_tag: {
LOG_INFO("Client requesting to backup preferences");
if (nodeDB->backupPreferences(r->backup_preferences)) {
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
} else {
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
}
break;
}
case meshtastic_AdminMessage_restore_preferences_tag: {
LOG_INFO("Client requesting to restore preferences");
if (nodeDB->restorePreferences(r->backup_preferences,
SEGMENT_DEVICESTATE | SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_CHANNELS)) {
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
LOG_DEBUG("Rebooting after successful restore of preferences");
reboot(1000);
disableBluetooth();
} else {
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
}
break;
}
case meshtastic_AdminMessage_remove_backup_preferences_tag: {
LOG_INFO("Client requesting to remove backup preferences");
#ifdef FSCom
if (r->remove_backup_preferences == meshtastic_AdminMessage_BackupLocation_FLASH) {
spiLock->lock();
FSCom.remove(backupFileName);
spiLock->unlock();
} else if (r->remove_backup_preferences == meshtastic_AdminMessage_BackupLocation_SD) {
// TODO: After more mainline SD card support
LOG_ERROR("SD backup removal not implemented yet");
}
#endif
break;
}
@@ -637,6 +680,14 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
#if !MESHTASTIC_EXCLUDE_PKI
crypto->setDHPrivateKey(config.security.private_key.bytes);
#endif
if (config.security.is_managed && !(config.security.admin_key[0].size == 32 || config.security.admin_key[1].size == 32 ||
config.security.admin_key[2].size == 32)) {
config.security.is_managed = false;
const char *warning = "You must provide at least one admin public key to enable managed mode";
LOG_WARN(warning);
sendWarning(warning);
}
if (config.security.debug_log_api_enabled == c.payload_variant.security.debug_log_api_enabled &&
config.security.serial_enabled == c.payload_variant.security.serial_enabled)
requiresReboot = false;
@@ -980,7 +1031,7 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
}
#endif
#if HAS_ETHERNET
#if HAS_ETHERNET && !defined(USE_WS5500)
conn.has_ethernet = true;
conn.ethernet.has_status = true;
if (Ethernet.linkStatus() == LinkON) {

View File

@@ -1057,6 +1057,11 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled.");
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
requestFocus(); // Tell Screen::setFrames to move to our module's frame
#if defined(USE_EINK) && defined(USE_EINK_DYNAMICDISPLAY)
EInkDynamicDisplay *einkDisplay = static_cast<EInkDynamicDisplay *>(display);
einkDisplay->enableUnlimitedFastMode(); // Enable unlimited fast refresh while typing
#endif
#if defined(USE_VIRTUAL_KEYBOARD)
drawKeyboard(display, state, 0, 0);
#else

View File

@@ -46,11 +46,6 @@ meshtastic_MeshPacket *RoutingModule::allocReply()
return NULL;
assert(currentRequest);
// We only consider making replies if the request was a legit routing packet (not just something we were sniffing)
if (currentRequest->decoded.portnum == meshtastic_PortNum_ROUTING_APP) {
assert(0); // 1.2 refactoring fixme, Not sure if anything needs this yet?
// return allocDataProtobuf(u);
}
return NULL;
}

View File

@@ -468,81 +468,83 @@ void SerialModule::processWXSerial()
// Extract the current line
char line[meshtastic_Constants_DATA_PAYLOAD_LEN];
memset(line, '\0', sizeof(line));
memcpy(line, &serialBytes[lineStart], lineEnd - lineStart);
if (strstr(line, "Wind") != NULL) // we have a wind line
{
gotwind = true;
// Find the positions of "=" signs in the line
char *windDirPos = strstr(line, "WindDir = ");
char *windSpeedPos = strstr(line, "WindSpeed = ");
char *windGustPos = strstr(line, "WindGust = ");
if (lineEnd - lineStart < sizeof(line) - 1) {
memcpy(line, &serialBytes[lineStart], lineEnd - lineStart);
if (strstr(line, "Wind") != NULL) // we have a wind line
{
gotwind = true;
// Find the positions of "=" signs in the line
char *windDirPos = strstr(line, "WindDir = ");
char *windSpeedPos = strstr(line, "WindSpeed = ");
char *windGustPos = strstr(line, "WindGust = ");
if (windDirPos != NULL) {
// Extract data after "=" for WindDir
strcpy(windDir, windDirPos + 15); // Add 15 to skip "WindDir = "
double radians = GeoCoord::toRadians(strtof(windDir, nullptr));
dir_sum_sin += sin(radians);
dir_sum_cos += cos(radians);
dirCount++;
} else if (windSpeedPos != NULL) {
// Extract data after "=" for WindSpeed
strcpy(windVel, windSpeedPos + 15); // Add 15 to skip "WindSpeed = "
float newv = strtof(windVel, nullptr);
velSum += newv;
velCount++;
if (newv < lull || lull == -1)
lull = newv;
if (windDirPos != NULL) {
// Extract data after "=" for WindDir
strlcpy(windDir, windDirPos + 15, sizeof(windDir)); // Add 15 to skip "WindDir = "
double radians = GeoCoord::toRadians(strtof(windDir, nullptr));
dir_sum_sin += sin(radians);
dir_sum_cos += cos(radians);
dirCount++;
} else if (windSpeedPos != NULL) {
// Extract data after "=" for WindSpeed
strlcpy(windVel, windSpeedPos + 15, sizeof(windVel)); // Add 15 to skip "WindSpeed = "
float newv = strtof(windVel, nullptr);
velSum += newv;
velCount++;
if (newv < lull || lull == -1)
lull = newv;
} else if (windGustPos != NULL) {
strcpy(windGust, windGustPos + 15); // Add 15 to skip "WindSpeed = "
float newg = strtof(windGust, nullptr);
if (newg > gust)
gust = newg;
}
} else if (windGustPos != NULL) {
strlcpy(windGust, windGustPos + 15, sizeof(windGust)); // Add 15 to skip "WindSpeed = "
float newg = strtof(windGust, nullptr);
if (newg > gust)
gust = newg;
}
// these are also voltage data we care about possibly
} else if (strstr(line, "BatVoltage") != NULL) { // we have a battVoltage line
char *batVoltagePos = strstr(line, "BatVoltage = ");
if (batVoltagePos != NULL) {
strcpy(batVoltage, batVoltagePos + 17); // 18 for ws 80, 17 for ws85
batVoltageF = strtof(batVoltage, nullptr);
break; // last possible data we want so break
}
} else if (strstr(line, "CapVoltage") != NULL) { // we have a cappVoltage line
char *capVoltagePos = strstr(line, "CapVoltage = ");
if (capVoltagePos != NULL) {
strcpy(capVoltage, capVoltagePos + 17); // 18 for ws 80, 17 for ws85
capVoltageF = strtof(capVoltage, nullptr);
}
// GXTS04Temp = 24.4
} else if (strstr(line, "GXTS04Temp") != NULL) { // we have a temperature line
char *tempPos = strstr(line, "GXTS04Temp = ");
if (tempPos != NULL) {
strcpy(temperature, tempPos + 15); // 15 spaces for ws85
temperatureF = strtof(temperature, nullptr);
}
// these are also voltage data we care about possibly
} else if (strstr(line, "BatVoltage") != NULL) { // we have a battVoltage line
char *batVoltagePos = strstr(line, "BatVoltage = ");
if (batVoltagePos != NULL) {
strlcpy(batVoltage, batVoltagePos + 17, sizeof(batVoltage)); // 18 for ws 80, 17 for ws85
batVoltageF = strtof(batVoltage, nullptr);
break; // last possible data we want so break
}
} else if (strstr(line, "CapVoltage") != NULL) { // we have a cappVoltage line
char *capVoltagePos = strstr(line, "CapVoltage = ");
if (capVoltagePos != NULL) {
strlcpy(capVoltage, capVoltagePos + 17, sizeof(capVoltage)); // 18 for ws 80, 17 for ws85
capVoltageF = strtof(capVoltage, nullptr);
}
// GXTS04Temp = 24.4
} else if (strstr(line, "GXTS04Temp") != NULL) { // we have a temperature line
char *tempPos = strstr(line, "GXTS04Temp = ");
if (tempPos != NULL) {
strlcpy(temperature, tempPos + 15, sizeof(temperature)); // 15 spaces for ws85
temperatureF = strtof(temperature, nullptr);
}
} else if (strstr(line, "RainIntSum") != NULL) { // we have a rainsum line
// LOG_INFO(line);
char *pos = strstr(line, "RainIntSum = ");
if (pos != NULL) {
strcpy(rainStr, pos + 17); // 17 spaces for ws85
rainSum = int(strtof(rainStr, nullptr));
}
} else if (strstr(line, "Rain") != NULL) { // we have a rain line
if (strstr(line, "WaveRain") == NULL) { // skip WaveRain lines though.
} else if (strstr(line, "RainIntSum") != NULL) { // we have a rainsum line
// LOG_INFO(line);
char *pos = strstr(line, "Rain = ");
char *pos = strstr(line, "RainIntSum = ");
if (pos != NULL) {
strcpy(rainStr, pos + 17); // 17 spaces for ws85
rain = strtof(rainStr, nullptr);
strlcpy(rainStr, pos + 17, sizeof(rainStr)); // 17 spaces for ws85
rainSum = int(strtof(rainStr, nullptr));
}
} else if (strstr(line, "Rain") != NULL) { // we have a rain line
if (strstr(line, "WaveRain") == NULL) { // skip WaveRain lines though.
// LOG_INFO(line);
char *pos = strstr(line, "Rain = ");
if (pos != NULL) {
strlcpy(rainStr, pos + 17, sizeof(rainStr)); // 17 spaces for ws85
rain = strtof(rainStr, nullptr);
}
}
}
}
// Update lineStart for the next line
lineStart = lineEnd + 1;
// Update lineStart for the next line
lineStart = lineEnd + 1;
}
}
}
break;

View File

@@ -19,6 +19,10 @@
#include "mesh/wifi/WiFiAPClient.h"
#include <WiFi.h>
#endif
#if HAS_ETHERNET && defined(USE_WS5500)
#include <ETHClass2.h>
#define ETH ETH2
#endif // HAS_ETHERNET
#include "Default.h"
#if !defined(ARCH_NRF52) || NRF52_USE_JSON
#include "serialization/JSON.h"
@@ -113,7 +117,8 @@ inline void onReceiveProto(char *topic, byte *payload, size_t length)
// likely they discovered each other via a channel we have downlink enabled for
if (isToUs(p.get()) || (tx && tx->has_user && rx && rx->has_user))
router->enqueueReceivedMessage(p.release());
} else if (router && perhapsDecode(p.get())) // ignore messages if we don't have the channel key
} else if (router &&
perhapsDecode(p.get()) == DecodeState::DECODE_SUCCESS) // ignore messages if we don't have the channel key
router->enqueueReceivedMessage(p.release());
}
@@ -295,6 +300,11 @@ bool connectPubSub(const PubSubConfig &config, PubSubClient &pubSub, Client &cli
inline bool isConnectedToNetwork()
{
#ifdef USE_WS5500
if (ETH.connected())
return true;
#endif
#if HAS_WIFI
return WiFi.isConnected();
#elif HAS_ETHERNET

View File

@@ -14,7 +14,7 @@
#include <WiFiClientSecure.h>
#endif
#endif
#if HAS_ETHERNET
#if HAS_ETHERNET && !defined(USE_WS5500)
#include <EthernetClient.h>
#endif

View File

@@ -0,0 +1,92 @@
#include "WiFiOTA.h"
#include "configuration.h"
#include <Preferences.h>
#include <esp_ota_ops.h>
namespace WiFiOTA
{
static const char *nvsNamespace = "ota-wifi";
static const char *appProjectName = "OTA-WiFi";
static bool updated = false;
bool isUpdated()
{
return updated;
}
void initialize()
{
Preferences prefs;
prefs.begin(nvsNamespace);
if (prefs.getBool("updated")) {
LOG_INFO("First boot after OTA update");
updated = true;
prefs.putBool("updated", false);
}
prefs.end();
}
void recoverConfig(meshtastic_Config_NetworkConfig *network)
{
LOG_INFO("Recovering WiFi settings after OTA update");
Preferences prefs;
prefs.begin(nvsNamespace, true);
String ssid = prefs.getString("ssid");
String psk = prefs.getString("psk");
prefs.end();
network->wifi_enabled = true;
strncpy(network->wifi_ssid, ssid.c_str(), sizeof(network->wifi_ssid));
strncpy(network->wifi_psk, psk.c_str(), sizeof(network->wifi_psk));
}
void saveConfig(meshtastic_Config_NetworkConfig *network)
{
LOG_INFO("Saving WiFi settings for upcoming OTA update");
Preferences prefs;
prefs.begin(nvsNamespace);
prefs.putString("ssid", network->wifi_ssid);
prefs.putString("psk", network->wifi_psk);
prefs.putBool("updated", false);
prefs.end();
}
const esp_partition_t *getAppPartition()
{
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL);
}
bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc)
{
if (esp_ota_get_partition_description(part, app_desc) != ESP_OK)
return false;
if (strcmp(app_desc->project_name, appProjectName) != 0)
return false;
return true;
}
bool trySwitchToOTA()
{
const esp_partition_t *part = getAppPartition();
esp_app_desc_t app_desc;
if (!getAppDesc(part, &app_desc))
return false;
if (esp_ota_set_boot_partition(part) != ESP_OK)
return false;
return true;
}
String getVersion()
{
const esp_partition_t *part = getAppPartition();
esp_app_desc_t app_desc;
if (!getAppDesc(part, &app_desc))
return String();
return String(app_desc.version);
}
} // namespace WiFiOTA

View File

@@ -0,0 +1,18 @@
#ifndef WIFIOTA_H
#define WIFIOTA_H
#include "mesh-pb-constants.h"
#include <Arduino.h>
namespace WiFiOTA
{
void initialize();
bool isUpdated();
void recoverConfig(meshtastic_Config_NetworkConfig *network);
void saveConfig(meshtastic_Config_NetworkConfig *network);
bool trySwitchToOTA();
String getVersion();
} // namespace WiFiOTA
#endif // WIFIOTA_H

View File

@@ -176,6 +176,8 @@
#define HW_VENDOR meshtastic_HardwareModel_SEEED_XIAO_S3
#elif defined(MESH_TAB)
#define HW_VENDOR meshtastic_HardwareModel_MESH_TAB
#elif defined(T_ETH_ELITE)
#define HW_VENDOR meshtastic_HardwareModel_T_ETH_ELITE
#endif
// -----------------------------------------------------------------------------

View File

@@ -9,6 +9,8 @@
#include "nimble/NimbleBluetooth.h"
#endif
#include <WiFiOTA.h>
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
@@ -26,7 +28,9 @@
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
void setBluetoothEnable(bool enable)
{
#if HAS_WIFI
#ifdef USE_WS5500
if ((config.bluetooth.enabled == true) && (config.network.wifi_enabled == false))
#elif HAS_WIFI
if (!isWifiAvailable() && config.bluetooth.enabled == true)
#else
if (config.bluetooth.enabled == true)
@@ -137,12 +141,19 @@ void esp32Setup()
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
String BLEOTA = BleOta::getOtaAppVersion();
if (BLEOTA.isEmpty()) {
LOG_INFO("No OTA firmware available");
LOG_INFO("No BLE OTA firmware available");
} else {
LOG_INFO("OTA firmware version %s", BLEOTA.c_str());
LOG_INFO("BLE OTA firmware version %s", BLEOTA.c_str());
}
#else
LOG_INFO("No OTA firmware available");
#endif
#if !MESHTASTIC_EXCLUDE_WIFI
String version = WiFiOTA::getVersion();
if (version.isEmpty()) {
LOG_INFO("No WiFi OTA firmware available");
} else {
LOG_INFO("WiFi OTA firmware version %s", version.c_str());
}
WiFiOTA::initialize();
#endif
// enableModemSleep();

View File

@@ -14,7 +14,6 @@ Do not expect a working Meshtastic device with this target.
#define _VARIANT_EBYTE_E77_
#define USE_STM32WLx
#define MAX_NUM_NODES 10
#define LED_PIN PB4 // LED1
// #define LED_PIN PB3 // LED2

View File

@@ -12,4 +12,4 @@ lib_deps =
${nrf52840_base.lib_deps}
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
upload_protocol = nrfutil
upload_port = /dev/ttyACM1
;upload_port = /dev/ttyACM1

View File

@@ -16,4 +16,4 @@ lib_deps =
zinggjm/GxEPD2@^1.6.2
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
upload_protocol = nrfutil
upload_port = /dev/ttyACM1
;upload_port = /dev/ttyACM1

View File

@@ -12,4 +12,4 @@ lib_deps =
${nrf52840_base.lib_deps}
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
upload_protocol = nrfutil
upload_port = /dev/ttyACM1
;upload_port = /dev/ttyACM1

View File

@@ -5,8 +5,9 @@ board_build.flash_mode = qio
board_build.psram_type = opi
board_upload.flash_size = 8MB
board_upload.maximum_size = 8388608
board_build.partitions = default_8MB.csv
board = esp32-s3-devkitc-1
upload_port = /dev/ttyUSB0
;upload_port = /dev/ttyUSB0
board_level = extra
upload_protocol = esptool
build_flags =
@@ -32,8 +33,9 @@ board_build.flash_mode = qio
board_build.psram_type = opi
board_upload.flash_size = 8MB
board_upload.maximum_size = 8388608
board_build.partitions = default_8MB.csv
board = esp32-s3-devkitc-1
upload_port = /dev/ttyUSB0
;upload_port = /dev/ttyUSB0
board_level = extra
upload_protocol = esptool
build_flags =
@@ -59,8 +61,9 @@ board_build.flash_mode = qio
board_build.psram_type = opi
board_upload.flash_size = 8MB
board_upload.maximum_size = 8388608
board_build.partitions = default_8MB.csv
board = esp32-s3-devkitc-1
upload_port = /dev/ttyUSB0
;upload_port = /dev/ttyUSB0
board_level = extra
upload_protocol = esptool
build_flags =

View File

@@ -88,6 +88,7 @@ debug_tool = jlink
[env:t-energy-s3_e22]
extends = esp32s3_base
board = esp32-s3-devkitc-1
board_build.partitions = default_16MB.csv
board_level = extra
board_upload.flash_size = 16MB ;Specify the FLASH capacity as 16MB
board_build.arduino.memory_type = qio_opi ;Enable internal PSRAM
@@ -100,4 +101,4 @@ build_flags =
-D BOARD_HAS_PSRAM
-D ARDUINO_USB_MODE=0
-D ARDUINO_USB_CDC_ON_BOOT=1
-I variants/diy/t-energy-s3_e22
-I variants/diy/t-energy-s3_e22

View File

@@ -1,6 +1,7 @@
[env:dreamcatcher] ; 2301, latest revision
extends = esp32s3_base
board = esp32s3box
board_build.partitions = default_16MB.csv
board_level = extra
build_flags =
@@ -8,7 +9,7 @@ build_flags =
-D PRIVATE_HW
-D OTHERNET_DC_REV=2301
-I variants/dreamcatcher
-DARDUINO_USB_CDC_ON_BOOT=1
-D ARDUINO_USB_CDC_ON_BOOT=1
lib_deps = ${esp32s3_base.lib_deps}
earlephilhower/ESP8266Audio@^1.9.9
@@ -17,6 +18,7 @@ lib_deps = ${esp32s3_base.lib_deps}
[env:dreamcatcher-2206]
extends = esp32s3_base
board = esp32s3box
board_build.partitions = default_16MB.csv
board_level = extra
build_flags =
@@ -24,4 +26,4 @@ build_flags =
-D PRIVATE_HW
-D OTHERNET_DC_REV=2206
-I variants/dreamcatcher
-DARDUINO_USB_CDC_ON_BOOT=1
-D ARDUINO_USB_CDC_ON_BOOT=1

View File

@@ -4,6 +4,7 @@ board_level = extra
extends = esp32s3_base
upload_protocol = esptool
board = esp32-s3-pico
board_build.partitions = default_16MB.csv
board_upload.use_1200bps_touch = yes
board_upload.wait_for_upload_port = yes

View File

@@ -2,7 +2,7 @@
extends = esp32s3_base
board = heltec_wifi_lora_32_V3
board_check = true
board_build.partitions = default_8MB.csv
build_flags =
${esp32s3_base.build_flags} -I variants/heltec_capsule_sensor_v3
-D HELTEC_CAPSULE_SENSOR_V3

View File

@@ -2,7 +2,7 @@
extends = esp32s3_base
board = heltec_wifi_lora_32_V3
board_check = true
# Temporary until espressif creates a release with this new target
board_build.partitions = default_8MB.csv
build_flags =
${esp32s3_base.build_flags} -D HELTEC_V3 -I variants/heltec_v3
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.

View File

@@ -1,8 +1,9 @@
[env:heltec-vision-master-e213]
extends = esp32s3_base
board = heltec_vision_master_e213
board_build.partitions = default_8MB.csv
build_flags =
${esp32s3_base.build_flags}
${esp32s3_base.build_flags}
-Ivariants/heltec_vision_master_e213
-DHELTEC_VISION_MASTER_E213
-DUSE_EINK
@@ -22,6 +23,7 @@ upload_speed = 115200
[env:heltec-vision-master-e213-inkhud]
extends = esp32s3_base, inkhud
board = heltec_vision_master_e213
board_build.partitions = default_8MB.csv
build_src_filter =
${esp32_base.build_src_filter}
${inkhud.build_src_filter}

View File

@@ -2,6 +2,7 @@
[env:heltec-vision-master-e290]
extends = esp32s3_base
board = heltec_vision_master_e290
board_build.partitions = default_8MB.csv
build_flags =
${esp32s3_base.build_flags}
-I variants/heltec_vision_master_e290
@@ -26,6 +27,7 @@ upload_speed = 115200
[env:heltec-vision-master-e290-inkhud]
extends = esp32s3_base, inkhud
board = heltec_vision_master_e290
board_build.partitions = default_8MB.csv
build_src_filter =
${esp32_base.build_src_filter}
${inkhud.build_src_filter}

View File

@@ -1,11 +1,11 @@
[env:heltec-vision-master-t190]
extends = esp32s3_base
board = heltec_vision_master_t190
board_build.partitions = default_8MB.csv
build_flags =
${esp32s3_base.build_flags}
-Ivariants/heltec_vision_master_t190
-DHELTEC_VISION_MASTER_T190
; -D PRIVATE_HW
-DHELTEC_VISION_MASTER_T190
lib_deps =
${esp32s3_base.lib_deps}
lewisxhe/PCF8563_Library@^1.0.1

View File

@@ -2,6 +2,7 @@
[env:heltec-wireless-paper]
extends = esp32s3_base
board = heltec_wifi_lora_32_V3
board_build.partitions = default_8MB.csv
build_flags =
${esp32s3_base.build_flags}
-I variants/heltec_wireless_paper
@@ -23,6 +24,7 @@ upload_speed = 115200
[env:heltec-wireless-paper-inkhud]
extends = esp32s3_base, inkhud
board = heltec_wifi_lora_32_V3
board_build.partitions = default_8MB.csv
build_src_filter =
${esp32_base.build_src_filter}
${inkhud.build_src_filter}

View File

@@ -2,6 +2,7 @@
extends = esp32s3_base
board_level = extra
board = heltec_wifi_lora_32_V3
board_build.partitions = default_8MB.csv
build_flags =
${esp32s3_base.build_flags}
-I variants/heltec_wireless_paper_v1

View File

@@ -1,6 +1,7 @@
[env:heltec-wireless-tracker]
extends = esp32s3_base
board = heltec_wireless_tracker
board_build.partitions = default_8MB.csv
upload_protocol = esptool
build_flags =

View File

@@ -2,6 +2,7 @@
extends = esp32s3_base
board_level = extra
board = heltec_wireless_tracker
board_build.partitions = default_8MB.csv
upload_protocol = esptool
build_flags =
${esp32s3_base.build_flags} -I variants/heltec_wireless_tracker_V1_0

View File

@@ -1,7 +1,8 @@
[env:heltec-wsl-v3]
extends = esp32s3_base
board = heltec_wifi_lora_32_V3
board_build.partitions = default_8MB.csv
# Temporary until espressif creates a release with this new target
build_flags =
${esp32s3_base.build_flags} -D HELTEC_WSL_V3 -I variants/heltec_wsl_v3
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.

View File

@@ -4,6 +4,7 @@ board = icarus
board_level = extra
board_check = true
board_build.mcu = esp32s3
board_build.partitions = default_8MB.csv
upload_protocol = esptool
upload_speed = 921600
platform_packages = platformio/framework-arduinoespressif32@https://github.com/PowerFeather/powerfeather-meshtastic-arduino-lib/releases/download/2.0.16a/esp32-2.0.16.zip
@@ -15,5 +16,4 @@ build_unflags =
build_flags =
${esp32s3_base.build_flags} -D PRIVATE_HW -I variants/icarus
-DBOARD_HAS_PSRAM
-DARDUINO_USB_MODE=0
-DARDUINO_USB_MODE=0

View File

@@ -3,6 +3,7 @@
extends = esp32s3_base
board = m5stack-cores3
board_check = true
board_build.partitions = default_16MB.csv
upload_protocol = esptool
build_flags = ${esp32_base.build_flags}

View File

@@ -28,7 +28,6 @@ build_flags = ${esp32s3_base.build_flags}
-D USE_LOG_DEBUG
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
-D RADIOLIB_SPI_PARANOID=0
-D MAX_NUM_NODES=250
-D MAX_THREADS=40
-D HAS_SCREEN=0
-D HAS_TFT=1

View File

@@ -2,6 +2,7 @@
extends = esp32s3_base
board = bpi_picow_esp32_s3
board_check = true
board_build.partitions = default_8MB.csv
;OpenOCD flash method
;upload_protocol = esp-builtin
;Normal method
@@ -22,7 +23,6 @@ build_src_filter =
[env:picomputer-s3-tft]
extends = env:picomputer-s3
board_build.partitions = default_8MB.csv ; just for test
build_flags =
${env:picomputer-s3.build_flags}
@@ -35,7 +35,6 @@ build_flags =
-D INPUTDRIVER_MATRIX_TYPE=1
-D USE_PIN_BUZZER=PIN_BUZZER
-D USE_SX127x
-D MAX_NUM_NODES=200
-D HAS_SCREEN=0
-D HAS_TFT=1
-D RAM_SIZE=1024

View File

@@ -7,6 +7,5 @@ Do not expect a working Meshtastic device with this target.
#define _VARIANT_RAK3172_
#define USE_STM32WLx
#define MAX_NUM_NODES 10
#endif

View File

@@ -23,8 +23,9 @@ build_flags = ${rp2350_base.build_flags}
-DHAS_WIFI=1
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m33"
-fexceptions # for exception handling in MQTT
-DHAS_UDP_MULTICAST=1
build_src_filter = ${rp2350_base.build_src_filter} +<mesh/wifi/>
lib_deps =
${rp2350_base.lib_deps}
${networking_base.lib_deps}
debug_build_flags = ${rp2350_base.build_flags}, -g
debug_build_flags = ${rp2350_base.build_flags}, -g

View File

@@ -10,9 +10,10 @@ build_flags = ${rp2040_base.build_flags}
-DHW_SPI1_DEVICE
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus"
-fexceptions # for exception handling in MQTT
-DHAS_UDP_MULTICAST=1
build_src_filter = ${rp2040_base.build_src_filter} +<mesh/wifi/>
lib_deps =
${rp2040_base.lib_deps}
${networking_base.lib_deps}
debug_build_flags = ${rp2040_base.build_flags}, -g
debug_tool = cmsis-dap ; for e.g. Picotool
debug_tool = cmsis-dap ; for e.g. Picotool

View File

@@ -6,6 +6,7 @@ platform_packages =
board = seeed-sensecap-indicator
board_check = true
board_build.partitions = default_8MB.csv
upload_protocol = esptool
build_flags = ${esp32_base.build_flags}
@@ -32,7 +33,6 @@ lib_deps = ${esp32s3_base.lib_deps}
extends = env:seeed-sensecap-indicator
board_level = main
upload_speed = 460800
board_build.partitions = default_8MB.csv ; must be here for some reason, board.json is not enough !?
build_flags =
${env:seeed-sensecap-indicator.build_flags}
@@ -46,7 +46,6 @@ build_flags =
-D INPUTDRIVER_BUTTON_TYPE=38
-D HAS_TELEMETRY=0
-D CONFIG_DISABLE_HAL_LOCKS=1
-D MAX_NUM_NODES=250
-D HAS_SCREEN=0
-D HAS_TFT=1
-D DISPLAY_SET_RESOLUTION

View File

@@ -1,8 +1,8 @@
#include "variant.h"
#include "configuration.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
#include "configuration.h"
#include <map>
#include <memory>
#include <stddef.h>
@@ -58,8 +58,6 @@ const uint32_t g_ADigitalPinMap[] = {
31, // D32 is P0.10 (VBAT)
};
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
@@ -80,7 +78,6 @@ const uint32_t g_ADigitalPinMap[] = {
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
void initVariant()
{
// LED1 & LED2

View File

@@ -43,7 +43,6 @@ extern "C" {
* Buttons
*/
// Digital PINs
#define D0 (0ul)
#define D1 (1ul)
@@ -57,11 +56,15 @@ extern "C" {
#define D9 (9ul)
#define D10 (10ul)
/*Due to the lack of pins,and have to make sure gps standby work well we have temporarily removed the button.
There are some technical solutions that can solve this problem,
and we are currently exploring and researching them*/
// #define BUTTON_PIN D0 // This is the Program Button
// // #define BUTTON_NEED_PULLUP 1
// #define BUTTON_ACTIVE_LOW true
// #define BUTTON_ACTIVE_PULLUP false
#define BUTTON_PIN D0 // This is the Program Button
// #define BUTTON_NEED_PULLUP 1
#define BUTTON_ACTIVE_LOW true
#define BUTTON_ACTIVE_PULLUP false
/*
* Analog pins
*/
@@ -82,7 +85,6 @@ static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
#define ADC_RESOLUTION 12
#define PIN_SERIAL2_RX (-1)
#define PIN_SERIAL2_TX (-1)
@@ -95,7 +97,6 @@ static const uint8_t A5 = PIN_A5;
#define PIN_SPI_MOSI (10)
#define PIN_SPI_SCK (8)
static const uint8_t SS = D4;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
@@ -113,40 +114,36 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX126X_TXEN RADIOLIB_NC
#define SX126X_RXEN D4
#define SX126X_DIO2_AS_RF_SWITCH // DIO2 is used to control the RF switch really necessary!!!
#define SX126X_DIO2_AS_RF_SWITCH // DIO2 is used to control the RF switch really necessary!!!
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
/*
* Wire Interfaces
*/
#define I2C_NO_RESCAN // I2C is a bit finicky, don't scan too much
#define I2C_NO_RESCAN // I2C is a bit finicky, don't scan too much
#define WIRE_INTERFACES_COUNT 1 // 2
#define PIN_WIRE_SDA (24) //change to use the correct pins if needed
#define PIN_WIRE_SCL (25) //change to use the correct pins if needed
#define PIN_WIRE_SDA (24) // change to use the correct pins if needed
#define PIN_WIRE_SCL (25) // change to use the correct pins if needed
static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;
// GPS L76KB
#define GPS_L76K
#ifdef GPS_L76K
#define PIN_GPS_RX 32+12 // 44
#define PIN_GPS_TX 32+11 // 43
#define PIN_GPS_RX D6
#define PIN_GPS_TX D7
#define HAS_GPS 1
#define GPS_BAUDRATE 9600
#define GPS_THREAD_INTERVAL 50
#define PIN_SERIAL1_RX PIN_GPS_TX
#define PIN_SERIAL1_TX PIN_GPS_RX
#define PIN_GPS_STANDBY 2
#define PIN_GPS_STANDBY D0
#endif
// Battery
#define BAT_READ \

View File

@@ -2,7 +2,7 @@
extends = esp32s3_base
board = seeed-xiao-s3
board_check = true
board_build.mcu = esp32s3
board_build.partitions = default_8MB.csv
upload_protocol = esptool
upload_speed = 921600
lib_deps =

View File

@@ -2,6 +2,7 @@
extends = esp32s3_base
board = station-g2
board_check = true
board_build.partitions = default_16MB.csv
board_build.mcu = esp32s3
upload_protocol = esptool
;upload_port = /dev/ttyACM0
@@ -13,6 +14,6 @@ build_unflags =
-DARDUINO_USB_MODE=1
build_flags =
${esp32s3_base.build_flags} -D STATION_G2 -I variants/station-g2
-DBOARD_HAS_PSRAM
-DBOARD_HAS_PSRAM
-DSTATION_G2
-DARDUINO_USB_MODE=0
-DARDUINO_USB_MODE=0

View File

@@ -3,6 +3,7 @@
extends = esp32s3_base
board = t-deck
board_check = true
board_build.partitions = default_16MB.csv
upload_protocol = esptool
build_flags = ${esp32s3_base.build_flags}
@@ -20,7 +21,6 @@ lib_deps = ${esp32s3_base.lib_deps}
[env:t-deck-tft]
extends = env:t-deck
board_build.partitions = default_16MB.csv
build_flags =
${env:t-deck.build_flags}
@@ -38,7 +38,6 @@ build_flags =
-D INPUTDRIVER_ENCODER_DOWN=15
-D INPUTDRIVER_ENCODER_BTN=0
-D INPUTDRIVER_BUTTON_TYPE=0
-D MAX_NUM_NODES=250
-D HAS_SDCARD
-D HAS_SCREEN=0
-D HAS_TFT=1

View File

@@ -0,0 +1,26 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define USB_VID 0x303a
#define USB_PID 0x1001
// The default Wire will be mapped to PMU and RTC
static const uint8_t SDA = 17;
static const uint8_t SCL = 18;
// Default SPI will be mapped to Radio
static const uint8_t SS = 40;
static const uint8_t MOSI = 11;
static const uint8_t MISO = 9;
static const uint8_t SCK = 10;
#define SPI_MOSI (11)
#define SPI_SCK (10)
#define SPI_MISO (9)
#define SPI_CS (12)
#define SDCARD_CS SPI_CS
#endif /* Pins_Arduino_h */

View File

@@ -0,0 +1,17 @@
[env:t-eth-elite]
extends = esp32s3_base
board = esp32s3box
board_check = true
board_build.partitions = default_16MB.csv
build_flags =
${esp32s3_base.build_flags}
-D T_ETH_ELITE
-I variants/t-eth-elite
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
lib_ignore =
Ethernet
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/meshtastic/ETHClass2#v1.0.0

View File

@@ -0,0 +1,11 @@
#include "RadioLib.h"
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6
{LR11x0::MODE_STBY, {LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW}},
{LR11x0::MODE_TX, {LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH}},
{LR11x0::MODE_TX_HF, {LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW}},
{LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE,
};

View File

@@ -0,0 +1,83 @@
#define HAS_SDCARD
#define SDCARD_USE_SPI1
#define HAS_GPS 1
#define GPS_RX_PIN 39
#define GPS_TX_PIN 42
#define GPS_BAUDRATE_FIXED 1
#define GPS_BAUDRATE 9600
#define I2C_SDA 17 // I2C pins for this board
#define I2C_SCL 18
#define HAS_SCREEN 1 // Allow for OLED Screens on I2C Header of shield
#define LED_PIN 38 // If defined we will blink this LED
#define BUTTON_PIN 0 // If defined, this will be used for user button presses,
#define BUTTON_NEED_PULLUP
// TTGO uses a common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
// not found then probe for SX1262
#define USE_RF95 // RFM95/SX127x
#define USE_SX1262
#define USE_SX1280
#define USE_LR1121
#define LORA_SCK 10
#define LORA_MISO 9
#define LORA_MOSI 11
#define LORA_CS 40
#define LORA_RESET 46
// per SX1276_Receive_Interrupt/utilities.h
#define LORA_DIO0 8
#define LORA_DIO1 16
#define LORA_DIO2 RADIOLIB_NC
// per SX1262_Receive_Interrupt/utilities.h
#ifdef USE_SX1262
#define SX126X_CS LORA_CS
#define SX126X_DIO1 8
#define SX126X_BUSY 16
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif
// per SX128x_Receive_Interrupt/utilities.h
#ifdef USE_SX1280
#define SX128X_CS LORA_CS
#define SX128X_DIO1 8
#define SX128X_DIO2 33
#define SX128X_DIO3 34
#define SX128X_BUSY 16
#define SX128X_RESET LORA_RESET
#define SX128X_RXEN 13
#define SX128X_TXEN 38
#define SX128X_MAX_POWER 3
#endif
// LR1121
#ifdef USE_LR1121
#define LR1121_IRQ_PIN 8
#define LR1121_NRESET_PIN LORA_RESET
#define LR1121_BUSY_PIN 16
#define LR1121_SPI_NSS_PIN LORA_CS
#define LR1121_SPI_SCK_PIN LORA_SCK
#define LR1121_SPI_MOSI_PIN LORA_MOSI
#define LR1121_SPI_MISO_PIN LORA_MISO
#define LR11X0_DIO3_TCXO_VOLTAGE 3.0
#define LR11X0_DIO_AS_RF_SWITCH
#endif
#define HAS_ETHERNET 1
#define USE_WS5500 1 // this driver uses the same stack as the ESP32 Wifi driver
#define ETH_MISO_PIN 47
#define ETH_MOSI_PIN 21
#define ETH_SCLK_PIN 48
#define ETH_CS_PIN 45
#define ETH_INT_PIN 14
#define ETH_RST_PIN -1
#define ETH_ADDR 1

View File

@@ -3,6 +3,7 @@
extends = esp32s3_base
board = t-watch-s3
board_check = true
board_build.partitions = default_16MB.csv
upload_protocol = esptool
build_flags = ${esp32_base.build_flags}

View File

@@ -2,6 +2,7 @@
[env:tbeam-s3-core]
extends = esp32s3_base
board = tbeam-s3-core
board_build.partitions = default_8MB.csv
board_check = true
lib_deps =

View File

@@ -1,7 +1,6 @@
[env:tlora-v3-3-0-tcxo]
extends = esp32_base
board = ttgo-lora32-v21
board_level = extra
build_flags =
${esp32_base.build_flags}
-D TLORA_V2_1_16

View File

@@ -1,6 +1,7 @@
[env:tracksenger]
extends = esp32s3_base
board = heltec_wireless_tracker
board_build.partitions = default_8MB.csv
upload_protocol = esp-builtin
build_flags =
@@ -16,6 +17,7 @@ lib_deps =
[env:tracksenger-lcd]
extends = esp32s3_base
board = heltec_wireless_tracker
board_build.partitions = default_8MB.csv
upload_protocol = esp-builtin
build_flags =
@@ -31,6 +33,7 @@ lib_deps =
[env:tracksenger-oled]
extends = esp32s3_base
board = heltec_wireless_tracker
board_build.partitions = default_8MB.csv
upload_protocol = esp-builtin
build_flags =

View File

@@ -3,6 +3,7 @@
[env:unphone]
extends = esp32s3_base
board = unphone
board_build.partitions = default_8MB.csv
upload_speed = 921600
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
@@ -32,7 +33,6 @@ lib_deps = ${esp32s3_base.lib_deps}
[env:unphone-tft]
extends = env:unphone
board_build.partitions = default_8MB.csv
build_flags =
${env:unphone.build_flags}
-D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
@@ -42,7 +42,6 @@ build_flags =
-D MESHTASTIC_EXCLUDE_SERIAL=1
-D MESHTASTIC_EXCLUDE_SOCKETAPI=1
-D INPUTDRIVER_BUTTON_TYPE=21
-D MAX_NUM_NODES=200
-D MAX_THREADS=40
-D HAS_SCREEN=0
-D HAS_TFT=1

View File

@@ -13,7 +13,6 @@ Do not expect a working Meshtastic device with this target.
#define _VARIANT_WIOE5_
#define USE_STM32WLx
#define MAX_NUM_NODES 10
#define LED_PIN PB5
#define LED_STATE_ON 1

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 6
build = 1
build = 2