mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-17 08:12:32 +00:00
Compare commits
90 Commits
no-arduino
...
v2.6.13.05
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12680ad9cd | ||
|
|
0561f2ca4b | ||
|
|
58743021c8 | ||
|
|
2fb46ce5d5 | ||
|
|
8be76a56c7 | ||
|
|
2c206febab | ||
|
|
db1eac12af | ||
|
|
56e67cb434 | ||
|
|
e9d5e36738 | ||
|
|
f71fdef3fd | ||
|
|
5e92145324 | ||
|
|
89a4589b68 | ||
|
|
20991d8b53 | ||
|
|
3ab9005b2f | ||
|
|
aabc5b7cf2 | ||
|
|
afcd97c154 | ||
|
|
cbdd7eae70 | ||
|
|
6374ffea35 | ||
|
|
1a6bb97f16 | ||
|
|
4f0b95e910 | ||
|
|
a81b41cbfb | ||
|
|
465fe18a89 | ||
|
|
bd0e25f3f5 | ||
|
|
9861e82f0a | ||
|
|
fcefd592e2 | ||
|
|
8a8a7cdefc | ||
|
|
8f9e569825 | ||
|
|
b0c5327585 | ||
|
|
f1dd623ce9 | ||
|
|
ac52edd11a | ||
|
|
66d5dde956 | ||
|
|
7dfbcc8f1d | ||
|
|
28244148a2 | ||
|
|
e623c70bd0 | ||
|
|
425f384b1f | ||
|
|
1557219bad | ||
|
|
691917b956 | ||
|
|
cc0fbfbd21 | ||
|
|
5d0bf03b01 | ||
|
|
8ff99437cb | ||
|
|
ba93097bb7 | ||
|
|
de098cca4c | ||
|
|
8faa04afdb | ||
|
|
fede1b8597 | ||
|
|
8557bd031d | ||
|
|
4e6418b635 | ||
|
|
a1a5503fe9 | ||
|
|
3b94981e56 | ||
|
|
f299447216 | ||
|
|
5f0c8863fd | ||
|
|
f9d17cdee0 | ||
|
|
68a28a177f | ||
|
|
60ec05e536 | ||
|
|
730cd388d6 | ||
|
|
6549b0477c | ||
|
|
8304cae010 | ||
|
|
0ad9758cfd | ||
|
|
e5f6804421 | ||
|
|
720add72b2 | ||
|
|
693b11db1d | ||
|
|
4bf2dd04ae | ||
|
|
c6c2a4d4dd | ||
|
|
79b8e7b1cf | ||
|
|
cf4f088337 | ||
|
|
22cb20d294 | ||
|
|
1eacdd0629 | ||
|
|
67e3d57412 | ||
|
|
7924ef87b5 | ||
|
|
3dec521f75 | ||
|
|
57a33790ed | ||
|
|
484af8eb9f | ||
|
|
b8970d66a1 | ||
|
|
e78033bb85 | ||
|
|
8bd7adca47 | ||
|
|
f67aec40e8 | ||
|
|
46c7d74760 | ||
|
|
15d2ae17f8 | ||
|
|
91579c4650 | ||
|
|
79b710a108 | ||
|
|
ba296db701 | ||
|
|
c0e1616382 | ||
|
|
070deb290f | ||
|
|
76f7207463 | ||
|
|
55b2bbf937 | ||
|
|
a5716cf25c | ||
|
|
4d81280ac2 | ||
|
|
9ce44556ce | ||
|
|
be0c7d73a3 | ||
|
|
d833a9ea61 | ||
|
|
5cd74f4b53 |
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
open_collective: meshtastic
|
||||
5
.github/pull_request_template.md
vendored
5
.github/pull_request_template.md
vendored
@@ -1,6 +1,7 @@
|
||||
## 🙏 Thank you for sending in a pull request, here's some tips to get started!
|
||||
|
||||
### ❌ (Please delete all these tips and replace them with your text) ❌
|
||||
|
||||
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
|
||||
to say "Hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
|
||||
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
|
||||
@@ -15,12 +16,12 @@
|
||||
- If you do not have the affected hardware to test your code changes adequately against regressions, please indicate this, so that contributors and commnunity members can help test your changes.
|
||||
- If your PR gets accepted you can request a "Contributor" role in the Meshtastic Discord
|
||||
|
||||
|
||||
## 🤝 Attestations
|
||||
|
||||
- [ ] I have tested that my proposed changes behave as described.
|
||||
- [ ] I have tested that my proposed changes do not cause any obvious regressions on the following devices:
|
||||
- [ ] Heltec (Lora32) V3
|
||||
- [ ] LilyGo T-Deck
|
||||
- [ ] LilyGo T-Deck
|
||||
- [ ] LilyGo T-Beam
|
||||
- [ ] RAK WisBlock 4631
|
||||
- [ ] Seeed Studio T-1000E tracker card
|
||||
|
||||
2
.github/workflows/daily_packaging.yml
vendored
2
.github/workflows/daily_packaging.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: Daily Packaging
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 9 * * *
|
||||
- cron: 0 2 * * *
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
|
||||
@@ -8,15 +8,15 @@ plugins:
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.435
|
||||
- renovate@40.34.4
|
||||
- checkov@3.2.442
|
||||
- renovate@40.60.3
|
||||
- prettier@3.5.3
|
||||
- trufflehog@3.88.34
|
||||
- trufflehog@3.89.2
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.8.3
|
||||
- trivy@0.62.1
|
||||
- bandit@1.8.5
|
||||
- trivy@0.63.0
|
||||
- taplo@0.9.3
|
||||
- ruff@0.11.11
|
||||
- ruff@0.12.0
|
||||
- isort@6.0.1
|
||||
- markdownlint@0.45.0
|
||||
- oxipng@9.1.5
|
||||
@@ -28,7 +28,7 @@ lint:
|
||||
- shellcheck@0.10.0
|
||||
- black@25.1.0
|
||||
- git-diff-check
|
||||
- gitleaks@8.26.0
|
||||
- gitleaks@8.27.2
|
||||
- clang-format@16.0.3
|
||||
ignore:
|
||||
- linters: [ALL]
|
||||
|
||||
@@ -37,3 +37,4 @@ Join our community and help improve Meshtastic! 🚀
|
||||
## Stats
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions
|
||||
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
|
||||
|
||||
FROM python:3.13-alpine3.21 AS builder
|
||||
FROM python:3.13-alpine3.22 AS builder
|
||||
ARG PIO_ENV=native
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
|
||||
@@ -27,7 +27,7 @@ RUN bash ./bin/build-native.sh "$PIO_ENV" && \
|
||||
|
||||
# ##### PRODUCTION BUILD #############
|
||||
|
||||
FROM alpine:3.21
|
||||
FROM alpine:3.22
|
||||
LABEL org.opencontainers.image.title="Meshtastic" \
|
||||
org.opencontainers.image.description="Alpine Meshtastic daemon" \
|
||||
org.opencontainers.image.url="https://meshtastic.org" \
|
||||
|
||||
@@ -4,7 +4,7 @@ extends = arduino_base
|
||||
custom_esp32_kind = esp32
|
||||
platform =
|
||||
# renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32
|
||||
platformio/espressif32@6.10.0
|
||||
platformio/espressif32@6.11.0
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
[portduino_base]
|
||||
platform =
|
||||
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
||||
https://github.com/meshtastic/platform-native/archive/622341c6de8a239704318b10c3dbb00c21a3eab3.zip
|
||||
https://github.com/meshtastic/platform-native/archive/681ee029207e9fd040afa223df6e54074cbbe084.zip
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
extends = arduino_base
|
||||
platform =
|
||||
# renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32
|
||||
platformio/ststm32@19.1.0
|
||||
platformio/ststm32@19.2.0
|
||||
platform_packages =
|
||||
# TODO renovate
|
||||
platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
|
||||
|
||||
@@ -23,4 +23,4 @@ for BOARD in $BOARDS; do
|
||||
CHECK="${CHECK} -e ${BOARD}"
|
||||
done
|
||||
|
||||
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high
|
||||
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt --inline-suppr" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high
|
||||
|
||||
21
bin/config.d/lora-RAK6421.yaml
Normal file
21
bin/config.d/lora-RAK6421.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
Lora:
|
||||
|
||||
### RAK13300in Slot 1
|
||||
Module: sx1262
|
||||
IRQ: 22 #IO6
|
||||
Reset: 16 # IO4
|
||||
Busy: 24 # IO5
|
||||
# Ant_sw: 13 # IO3
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
# CS: 8
|
||||
|
||||
|
||||
### RAK13300in Slot 2 pins
|
||||
# IRQ: 18 #IO6
|
||||
# Reset: 24 # IO4
|
||||
# Busy: 19 # IO5
|
||||
# # Ant_sw: 23 # IO3
|
||||
# spidev: spidev0.1
|
||||
# # CS: 7
|
||||
18
bin/config.d/lora-lyra-picocalc-wio-sx1262.yaml
Normal file
18
bin/config.d/lora-lyra-picocalc-wio-sx1262.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
gpiochip: 0
|
||||
MOSI: 12
|
||||
MISO: 13
|
||||
IRQ: 1
|
||||
Busy: 23
|
||||
Reset: 22
|
||||
RXen: 0
|
||||
gpiochip: 1
|
||||
CS: 9
|
||||
SCK: 11
|
||||
# TXen: bridge to DIO2 on E22 module
|
||||
SX126X_MAX_POWER: 22
|
||||
spidev: spidev1.0
|
||||
spiSpeed: 2000000
|
||||
@@ -12,6 +12,7 @@ SET "BIGDB16=0"
|
||||
SET "ESPTOOL_BAUD=115200"
|
||||
SET "ESPTOOL_CMD="
|
||||
SET "LOGCOUNTER=0"
|
||||
SET "BPS_RESET=0"
|
||||
|
||||
@REM FIXME: Determine mcu from PlatformIO variant, this is unmaintainable.
|
||||
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
|
||||
@@ -24,7 +25,7 @@ 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 Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] (--web) [--1200bps-reset]
|
||||
ECHO.
|
||||
ECHO Options:
|
||||
ECHO -f filename The firmware .bin file to flash. Custom to your device type and region. (required)
|
||||
@@ -35,13 +36,16 @@ ECHO -P python Specify alternate python interpreter to use to invoke
|
||||
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 --1200bps-reset Attempt to place the device in correct mode. (1200bps Reset)
|
||||
ECHO Some hardware requires this twice.
|
||||
ECHO.
|
||||
ECHO Example: %SCRIPT_NAME% -p COM17 --1200bps-reset
|
||||
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.1]
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.2]
|
||||
ECHO Meshtastic
|
||||
GOTO eof
|
||||
|
||||
@@ -58,10 +62,13 @@ 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"
|
||||
IF /I "%~1"=="--1200bps-reset" SET "BPS_RESET=1"
|
||||
SHIFT
|
||||
GOTO getopts
|
||||
:endopts
|
||||
|
||||
IF %BPS_RESET% EQU 1 GOTO skip-filename
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..."
|
||||
IF "__!FILENAME!__"=="____" (
|
||||
CALL :LOG_MESSAGE DEBUG "Missing -f filename input."
|
||||
@@ -95,6 +102,9 @@ IF NOT "!FILENAME:update=!"=="!FILENAME!" (
|
||||
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!"
|
||||
)
|
||||
|
||||
:skip-filename
|
||||
SET "ESPTOOL_BAUD=1200"
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
|
||||
IF NOT "__%PYTHON%__"=="____" (
|
||||
SET "ESPTOOL_CMD=!PYTHON! -m esptool"
|
||||
@@ -133,6 +143,12 @@ IF "__!ESPTOOL_PORT!__" == "____" (
|
||||
)
|
||||
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
|
||||
|
||||
IF %BPS_RESET% EQU 1 (
|
||||
@REM Attempt to change mode via 1200bps Reset.
|
||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! --after no_reset read_flash_status
|
||||
GOTO eof
|
||||
)
|
||||
|
||||
@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!" (
|
||||
@@ -254,6 +270,7 @@ EXIT /B %ERRORLEVEL%
|
||||
IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||
CALL :RESET_ERROR
|
||||
!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4
|
||||
IF %BPS_RESET% EQU 1 GOTO :eof
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||
EXIT /B %ERRORLEVEL%
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
|
||||
WEB_APP=false
|
||||
BPS_RESET=false
|
||||
TFT_BUILD=false
|
||||
MCU=""
|
||||
|
||||
@@ -32,47 +33,50 @@ BIGDB_16MB=(
|
||||
"ESP32-S3-Pico"
|
||||
"m5stack-cores3"
|
||||
"station-g2"
|
||||
"t-eth-elite"
|
||||
"t-watch-s3"
|
||||
"t-eth-elite"
|
||||
"t-watch-s3"
|
||||
"elecrow-adv-35-tft"
|
||||
"elecrow-adv-24-28-tft"
|
||||
"elecrow-adv1-43-50-70-tft"
|
||||
)
|
||||
S3_VARIANTS=(
|
||||
"s3"
|
||||
"-v3"
|
||||
"t-deck"
|
||||
"wireless-paper"
|
||||
"wireless-tracker"
|
||||
"station-g2"
|
||||
"unphone"
|
||||
"t-eth-elite"
|
||||
"mesh-tab"
|
||||
"dreamcatcher"
|
||||
"ESP32-S3-Pico"
|
||||
"seeed-sensecap-indicator"
|
||||
"heltec_capsule_sensor_v3"
|
||||
"vision-master"
|
||||
"icarus"
|
||||
"tracksenger"
|
||||
"elecrow-adv"
|
||||
"s3"
|
||||
"-v3"
|
||||
"t-deck"
|
||||
"wireless-paper"
|
||||
"wireless-tracker"
|
||||
"station-g2"
|
||||
"unphone"
|
||||
"t-eth-elite"
|
||||
"mesh-tab"
|
||||
"dreamcatcher"
|
||||
"ESP32-S3-Pico"
|
||||
"seeed-sensecap-indicator"
|
||||
"heltec_capsule_sensor_v3"
|
||||
"vision-master"
|
||||
"icarus"
|
||||
"tracksenger"
|
||||
"elecrow-adv"
|
||||
)
|
||||
|
||||
# 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 <<EOF
|
||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME] [--web]
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME] [--web] [--1200bps-reset]
|
||||
Flash image file to device, but first erasing and writing system information.
|
||||
|
||||
-h Display this help and exit.
|
||||
@@ -80,137 +84,146 @@ Flash image file to device, but first erasing and writing system information.
|
||||
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-f FILENAME The firmware .bin file to flash. Custom to your device type and region.
|
||||
--web Enable WebUI. (Default: false)
|
||||
--1200bps-reset Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset)
|
||||
|
||||
EOF
|
||||
}
|
||||
# Parse arguments using a single while loop
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-p)
|
||||
ESPTOOL_CMD="$ESPTOOL_CMD --port $2"
|
||||
shift
|
||||
;;
|
||||
-P)
|
||||
PYTHON="$2"
|
||||
shift
|
||||
;;
|
||||
-f)
|
||||
FILENAME="$2"
|
||||
shift
|
||||
;;
|
||||
--web)
|
||||
WEB_APP=true
|
||||
;;
|
||||
--) # Stop parsing options
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift # Move to the next argument
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-p)
|
||||
ESPTOOL_CMD="$ESPTOOL_CMD --port $2"
|
||||
shift
|
||||
;;
|
||||
-P)
|
||||
PYTHON="$2"
|
||||
shift
|
||||
;;
|
||||
-f)
|
||||
FILENAME="$2"
|
||||
shift
|
||||
;;
|
||||
--web)
|
||||
WEB_APP=true
|
||||
;;
|
||||
--1200bps-reset)
|
||||
BPS_RESET=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
|
||||
if [[ $BPS_RESET == true ]]; then
|
||||
$ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -z "$FILENAME" ] && [ -n "$1" ] && {
|
||||
FILENAME="$1"
|
||||
shift
|
||||
}
|
||||
|
||||
if [[ $FILENAME != firmware-* ]]; then
|
||||
if [[ "$FILENAME" != firmware-* ]]; then
|
||||
echo "Filename must be a firmware-* file."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 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//-tft-/}" != "$FILENAME" ]]; then
|
||||
TFT_BUILD=true
|
||||
if [[ $WEB_APP == true ]] && [[ $TFT_BUILD == true ]]; then
|
||||
echo "Cannot enable WebUI (--web) and MUI."
|
||||
exit 1
|
||||
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 BigDB 8mb and OTA OFFSET.
|
||||
for variant in "${BIGDB_8MB[@]}"; do
|
||||
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
||||
OFFSET=0x670000
|
||||
OTA_OFFSET=0x340000
|
||||
fi
|
||||
done
|
||||
# littlefs* offset for BigDB 8mb and OTA OFFSET.
|
||||
for variant in "${BIGDB_8MB[@]}"; do
|
||||
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
||||
OFFSET=0x670000
|
||||
OTA_OFFSET=0x340000
|
||||
fi
|
||||
done
|
||||
|
||||
# littlefs* offset for BigDB 16mb and OTA OFFSET.
|
||||
for variant in "${BIGDB_16MB[@]}"; do
|
||||
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
||||
OFFSET=0xc90000
|
||||
OTA_OFFSET=0x650000
|
||||
fi
|
||||
done
|
||||
# littlefs* offset for BigDB 16mb and OTA OFFSET.
|
||||
for variant in "${BIGDB_16MB[@]}"; do
|
||||
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
||||
OFFSET=0xc90000
|
||||
OTA_OFFSET=0x650000
|
||||
fi
|
||||
done
|
||||
|
||||
# Account for S3 board's different OTA partition
|
||||
# FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
|
||||
for variant in "${S3_VARIANTS[@]}"; do
|
||||
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
||||
MCU="esp32s3"
|
||||
fi
|
||||
done
|
||||
# Account for S3 board's different OTA partition
|
||||
# FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
|
||||
for variant in "${S3_VARIANTS[@]}"; do
|
||||
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
||||
MCU="esp32s3"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$MCU" != "esp32s3" ]; then
|
||||
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
|
||||
OTAFILE=bleota.bin
|
||||
else
|
||||
OTAFILE=bleota-c3.bin
|
||||
fi
|
||||
else
|
||||
OTAFILE=bleota-s3.bin
|
||||
fi
|
||||
if [ "$MCU" != "esp32s3" ]; then
|
||||
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
|
||||
OTAFILE=bleota.bin
|
||||
else
|
||||
OTAFILE=bleota-c3.bin
|
||||
fi
|
||||
else
|
||||
OTAFILE=bleota-s3.bin
|
||||
fi
|
||||
|
||||
# Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-".
|
||||
if [ "$WEB_APP" = true ]; then
|
||||
SPIFFSFILE=littlefswebui-${BASENAME}
|
||||
else
|
||||
SPIFFSFILE=littlefs-${BASENAME}
|
||||
fi
|
||||
# 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
|
||||
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}"
|
||||
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
|
||||
|
||||
@@ -8,12 +8,13 @@ SET "PYTHON="
|
||||
SET "ESPTOOL_BAUD=115200"
|
||||
SET "ESPTOOL_CMD="
|
||||
SET "LOGCOUNTER=0"
|
||||
SET "CHANGE_MODE=0"
|
||||
|
||||
GOTO getopts
|
||||
:help
|
||||
ECHO Flash image file to device, but leave existing system intact.
|
||||
ECHO.
|
||||
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python]
|
||||
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] [--change-mode]
|
||||
ECHO.
|
||||
ECHO Options:
|
||||
ECHO -f filename The update .bin file to flash. Custom to your device type and region. (required)
|
||||
@@ -23,12 +24,15 @@ ECHO If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
ECHO -P python Specify alternate python interpreter to use to invoke esptool. (default: python)
|
||||
ECHO If supplied the script will use python.
|
||||
ECHO If not supplied the script will try to find esptool in Path.
|
||||
ECHO --change-mode Attempt to place the device in correct mode. (1200bps Reset)
|
||||
ECHO Some hardware requires this twice.
|
||||
ECHO.
|
||||
ECHO Example: %SCRIPT_NAME% -p COM17 --change-mode
|
||||
ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4-update.bin -p COM11
|
||||
GOTO eof
|
||||
|
||||
:version
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.1]
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.2]
|
||||
ECHO Meshtastic
|
||||
GOTO eof
|
||||
|
||||
@@ -44,10 +48,13 @@ IF /I "%~1"=="-f" SET "FILENAME=%~2" & SHIFT
|
||||
IF "%~1"=="-p" SET "ESPTOOL_PORT=%~2" & SHIFT
|
||||
IF /I "%~1"=="--port" SET "ESPTOOL_PORT=%~2" & SHIFT
|
||||
IF "%~1"=="-P" SET "PYTHON=%~2" & SHIFT
|
||||
IF /I "%~1"=="--change-mode" SET "CHANGE_MODE=1"
|
||||
SHIFT
|
||||
GOTO getopts
|
||||
:endopts
|
||||
|
||||
IF %CHANGE_MODE% EQU 1 GOTO skip-filename
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..."
|
||||
IF "__!FILENAME!__"=="____" (
|
||||
CALL :LOG_MESSAGE DEBUG "Missing -f filename input."
|
||||
@@ -77,6 +84,9 @@ IF "!FILENAME:update=!"=="!FILENAME!" (
|
||||
CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!"
|
||||
)
|
||||
|
||||
:skip-filename
|
||||
SET "ESPTOOL_BAUD=1200"
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
|
||||
IF NOT "__%PYTHON%__"=="____" (
|
||||
SET "ESPTOOL_CMD=!PYTHON! -m esptool"
|
||||
@@ -115,6 +125,12 @@ IF "__!ESPTOOL_PORT!__" == "____" (
|
||||
)
|
||||
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
|
||||
|
||||
IF %CHANGE_MODE% EQU 1 (
|
||||
@REM Attempt to change mode via 1200bps Reset.
|
||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! --after no_reset read_flash_status
|
||||
GOTO eof
|
||||
)
|
||||
|
||||
@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
|
||||
@@ -135,6 +151,7 @@ EXIT /B %ERRORLEVEL%
|
||||
IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||
CALL :RESET_ERROR
|
||||
!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4
|
||||
IF %CHANGE_MODE% EQU 1 GOTO :eof
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||
EXIT /B %ERRORLEVEL%
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
|
||||
CHANGE_MODE=false
|
||||
|
||||
# Determine the correct esptool command to use
|
||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||
@@ -17,14 +18,15 @@ fi
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
|
||||
Usage: $(basename "$0") [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--change-mode]
|
||||
Flash image file to device, leave existing system intact."
|
||||
|
||||
-h Display this help and exit
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-f FILENAME The *update.bin file to flash. Custom to your device type.
|
||||
|
||||
--change-mode Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset)
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -36,13 +38,16 @@ while getopts ":hp:P:f:" opt; do
|
||||
exit 0
|
||||
;;
|
||||
p) ESPTOOL_CMD="$ESPTOOL_CMD --port ${OPTARG}"
|
||||
;;
|
||||
;;
|
||||
P) PYTHON=${OPTARG}
|
||||
;;
|
||||
f) FILENAME=${OPTARG}
|
||||
;;
|
||||
--change-mode)
|
||||
CHANGE_MODE=true
|
||||
;;
|
||||
*)
|
||||
echo "Invalid flag."
|
||||
echo "Invalid flag."
|
||||
show_help >&2
|
||||
exit 1
|
||||
;;
|
||||
@@ -50,17 +55,22 @@ while getopts ":hp:P:f:" opt; do
|
||||
done
|
||||
shift "$((OPTIND-1))"
|
||||
|
||||
[ -z "$FILENAME" -a -n "$1" ] && {
|
||||
FILENAME=$1
|
||||
if [[ $CHANGE_MODE == true ]]; then
|
||||
$ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -z "$FILENAME" ] && [ -n "$1" ] && {
|
||||
FILENAME="$1"
|
||||
shift
|
||||
}
|
||||
|
||||
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
|
||||
printf "Trying to flash update ${FILENAME}"
|
||||
$ESPTOOL_CMD --baud 115200 write_flash 0x10000 ${FILENAME}
|
||||
echo "Trying to flash update ${FILENAME}"
|
||||
$ESPTOOL_CMD --baud 115200 write_flash 0x10000 "${FILENAME}"
|
||||
else
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -27,7 +27,7 @@ for subdir, dirs, files in os.walk(rootdir):
|
||||
if c.startswith("env:"):
|
||||
section = config[c].name[4:]
|
||||
if "extends" in config[config[c].name]:
|
||||
if config[config[c].name]["extends"] == options[0] + "_base":
|
||||
if options[0] + "_base" in config[config[c].name]["extends"]:
|
||||
if "board_level" in config[config[c].name]:
|
||||
if (
|
||||
config[config[c].name]["board_level"] == "extra"
|
||||
|
||||
@@ -87,6 +87,15 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.6.13" date="2025-06-16">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.13</url>
|
||||
</release>
|
||||
<release version="2.6.12" date="2025-06-15">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.12</url>
|
||||
</release>
|
||||
<release version="2.6.11" date="2025-06-02">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.11</url>
|
||||
</release>
|
||||
<release version="2.6.10" date="2025-05-25">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.10</url>
|
||||
</release>
|
||||
|
||||
@@ -48,6 +48,6 @@
|
||||
"require_upload_port": true,
|
||||
"wait_for_upload_port": true
|
||||
},
|
||||
"url": "FIXME",
|
||||
"url": "https://www.elecrow.com/thinknode-m1-meshtastic-lora-signal-transceiver-powered-by-nrf52840-with-154-screen-support-gps.html",
|
||||
"vendor": "ELECROW"
|
||||
}
|
||||
|
||||
52
boards/gat562_mesh_trial_tracker.json
Normal file
52
boards/gat562_mesh_trial_tracker.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x239A", "0x8029"],
|
||||
["0x239A", "0x0029"],
|
||||
["0x239A", "0x002A"],
|
||||
["0x239A", "0x802A"]
|
||||
],
|
||||
"usb_product": "GAT562 Mesh Trial Tracker",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "gat562_mesh_trial_tracker",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"svd_path": "nrf52840.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino", "freertos"],
|
||||
"name": "GAT562 Mesh Trial Tracker",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
|
||||
"use_1200bps_touch": true,
|
||||
"require_upload_port": true,
|
||||
"wait_for_upload_port": true
|
||||
},
|
||||
"url": "http://www.gat-iot.com/",
|
||||
"vendor": "GAT-IOT"
|
||||
}
|
||||
@@ -48,6 +48,6 @@
|
||||
"require_upload_port": true,
|
||||
"wait_for_upload_port": true
|
||||
},
|
||||
"url": "FIXME",
|
||||
"url": "https://heltec.org/project/mesh-node-t114/",
|
||||
"vendor": "Heltec"
|
||||
}
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x2886", "0x0166"]
|
||||
],
|
||||
"hwids": [["0x2886", "0x0166"]],
|
||||
"usb_product": "XIAO-BOOT",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "seeed_xiao_nrf52840_kit",
|
||||
|
||||
10
debian/changelog
vendored
10
debian/changelog
vendored
@@ -1,4 +1,4 @@
|
||||
meshtasticd (2.6.10.0) UNRELEASED; urgency=medium
|
||||
meshtasticd (2.6.13.0) UNRELEASED; urgency=medium
|
||||
|
||||
[ Austin Lane ]
|
||||
* Initial packaging
|
||||
@@ -16,4 +16,10 @@ meshtasticd (2.6.10.0) UNRELEASED; urgency=medium
|
||||
[ ]
|
||||
* GitHub Actions Automatic version bump
|
||||
|
||||
-- <github-actions[bot]@users.noreply.github.com> Sun, 25 May 2025 20:46:49 +0000
|
||||
[ ]
|
||||
* GitHub Actions Automatic version bump
|
||||
|
||||
[ ]
|
||||
* GitHub Actions Automatic version bump
|
||||
|
||||
-- <github-actions[bot]@users.noreply.github.com> Mon, 16 Jun 2025 02:10:49 +0000
|
||||
|
||||
@@ -108,7 +108,7 @@ lib_deps =
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||
https://github.com/meshtastic/device-ui/archive/37e2fb84a8d1b7d8cc1e2ed00d34cfb1f284bd59.zip
|
||||
https://github.com/meshtastic/device-ui/archive/301f11e584cbeccf08af923bb2a0e02b669bda0b.zip
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
[environmental_base]
|
||||
|
||||
Submodule protobufs updated: 24c7a3d287...b818a000ef
@@ -59,82 +59,82 @@ class AmbientLightingThread : public concurrency::OSThread
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG("AmbientLighting init");
|
||||
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
|
||||
#ifdef HAS_NCP5623
|
||||
if (_type == ScanI2C::NCP5623) {
|
||||
rgb.begin();
|
||||
#endif
|
||||
#ifdef HAS_LP5562
|
||||
} else if (_type == ScanI2C::LP5562) {
|
||||
rgbw.begin();
|
||||
if (_type == ScanI2C::LP5562) {
|
||||
rgbw.begin();
|
||||
#endif
|
||||
#ifdef RGBLED_RED
|
||||
pinMode(RGBLED_RED, OUTPUT);
|
||||
pinMode(RGBLED_GREEN, OUTPUT);
|
||||
pinMode(RGBLED_BLUE, OUTPUT);
|
||||
pinMode(RGBLED_RED, OUTPUT);
|
||||
pinMode(RGBLED_GREEN, OUTPUT);
|
||||
pinMode(RGBLED_BLUE, OUTPUT);
|
||||
#endif
|
||||
#ifdef HAS_NEOPIXEL
|
||||
pixels.begin(); // Initialise the pixel(s)
|
||||
pixels.clear(); // Set all pixel colors to 'off'
|
||||
pixels.setBrightness(moduleConfig.ambient_lighting.current);
|
||||
pixels.begin(); // Initialise the pixel(s)
|
||||
pixels.clear(); // Set all pixel colors to 'off'
|
||||
pixels.setBrightness(moduleConfig.ambient_lighting.current);
|
||||
#endif
|
||||
setLighting();
|
||||
setLighting();
|
||||
#endif
|
||||
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override
|
||||
{
|
||||
protected:
|
||||
int32_t runOnce() override
|
||||
{
|
||||
#ifdef HAS_RGB_LED
|
||||
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
|
||||
if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) {
|
||||
if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) {
|
||||
#endif
|
||||
setLighting();
|
||||
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
|
||||
setLighting();
|
||||
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
|
||||
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return disable();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return disable();
|
||||
}
|
||||
|
||||
// When shutdown() is issued, setLightingOff will be called.
|
||||
CallbackObserver<AmbientLightingThread, void *> notifyDeepSleepObserver =
|
||||
CallbackObserver<AmbientLightingThread, void *>(this, &AmbientLightingThread::setLightingOff);
|
||||
// When shutdown() is issued, setLightingOff will be called.
|
||||
CallbackObserver<AmbientLightingThread, void *> notifyDeepSleepObserver =
|
||||
CallbackObserver<AmbientLightingThread, void *>(this, &AmbientLightingThread::setLightingOff);
|
||||
|
||||
private:
|
||||
ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
|
||||
private:
|
||||
ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
|
||||
|
||||
// Turn RGB lighting off, is used in junction to shutdown()
|
||||
int setLightingOff(void *unused)
|
||||
{
|
||||
// Turn RGB lighting off, is used in junction to shutdown()
|
||||
int setLightingOff(void *unused)
|
||||
{
|
||||
#ifdef HAS_NCP5623
|
||||
rgb.setCurrent(0);
|
||||
rgb.setRed(0);
|
||||
rgb.setGreen(0);
|
||||
rgb.setBlue(0);
|
||||
LOG_INFO("OFF: NCP5623 Ambient lighting");
|
||||
rgb.setCurrent(0);
|
||||
rgb.setRed(0);
|
||||
rgb.setGreen(0);
|
||||
rgb.setBlue(0);
|
||||
LOG_INFO("OFF: NCP5623 Ambient lighting");
|
||||
#endif
|
||||
#ifdef HAS_LP5562
|
||||
rgbw.setCurrent(0);
|
||||
rgbw.setRed(0);
|
||||
rgbw.setGreen(0);
|
||||
rgbw.setBlue(0);
|
||||
rgbw.setWhite(0);
|
||||
LOG_INFO("OFF: LP5562 Ambient lighting");
|
||||
rgbw.setCurrent(0);
|
||||
rgbw.setRed(0);
|
||||
rgbw.setGreen(0);
|
||||
rgbw.setBlue(0);
|
||||
rgbw.setWhite(0);
|
||||
LOG_INFO("OFF: LP5562 Ambient lighting");
|
||||
#endif
|
||||
#ifdef HAS_NEOPIXEL
|
||||
pixels.clear();
|
||||
pixels.show();
|
||||
LOG_INFO("OFF: NeoPixel Ambient lighting");
|
||||
pixels.clear();
|
||||
pixels.show();
|
||||
LOG_INFO("OFF: NeoPixel Ambient lighting");
|
||||
#endif
|
||||
#ifdef RGBLED_CA
|
||||
analogWrite(RGBLED_RED, 255 - 0);
|
||||
analogWrite(RGBLED_GREEN, 255 - 0);
|
||||
analogWrite(RGBLED_BLUE, 255 - 0);
|
||||
LOG_INFO("OFF: Ambient light RGB Common Anode");
|
||||
analogWrite(RGBLED_RED, 255 - 0);
|
||||
analogWrite(RGBLED_GREEN, 255 - 0);
|
||||
analogWrite(RGBLED_BLUE, 255 - 0);
|
||||
LOG_INFO("OFF: Ambient light RGB Common Anode");
|
||||
#elif defined(RGBLED_RED)
|
||||
analogWrite(RGBLED_RED, 0);
|
||||
analogWrite(RGBLED_GREEN, 0);
|
||||
@@ -142,56 +142,57 @@ class AmbientLightingThread : public concurrency::OSThread
|
||||
LOG_INFO("OFF: Ambient light RGB Common Cathode");
|
||||
#endif
|
||||
#ifdef UNPHONE
|
||||
unphone.rgb(0, 0, 0);
|
||||
LOG_INFO("OFF: unPhone Ambient lighting");
|
||||
unphone.rgb(0, 0, 0);
|
||||
LOG_INFO("OFF: unPhone Ambient lighting");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setLighting()
|
||||
{
|
||||
void setLighting()
|
||||
{
|
||||
#ifdef HAS_NCP5623
|
||||
rgb.setCurrent(moduleConfig.ambient_lighting.current);
|
||||
rgb.setRed(moduleConfig.ambient_lighting.red);
|
||||
rgb.setGreen(moduleConfig.ambient_lighting.green);
|
||||
rgb.setBlue(moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
|
||||
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
rgb.setCurrent(moduleConfig.ambient_lighting.current);
|
||||
rgb.setRed(moduleConfig.ambient_lighting.red);
|
||||
rgb.setGreen(moduleConfig.ambient_lighting.green);
|
||||
rgb.setBlue(moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d",
|
||||
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
#ifdef HAS_LP5562
|
||||
rgbw.setCurrent(moduleConfig.ambient_lighting.current);
|
||||
rgbw.setRed(moduleConfig.ambient_lighting.red);
|
||||
rgbw.setGreen(moduleConfig.ambient_lighting.green);
|
||||
rgbw.setBlue(moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
|
||||
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
rgbw.setCurrent(moduleConfig.ambient_lighting.current);
|
||||
rgbw.setRed(moduleConfig.ambient_lighting.red);
|
||||
rgbw.setGreen(moduleConfig.ambient_lighting.green);
|
||||
rgbw.setBlue(moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
|
||||
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
#ifdef HAS_NEOPIXEL
|
||||
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||
moduleConfig.ambient_lighting.blue),
|
||||
0, NEOPIXEL_COUNT);
|
||||
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||
moduleConfig.ambient_lighting.blue),
|
||||
0, NEOPIXEL_COUNT);
|
||||
|
||||
// RadioMaster Bandit has addressable LED at the two buttons
|
||||
// this allow us to set different lighting for them in variant.h file.
|
||||
#ifdef RADIOMASTER_900_BANDIT
|
||||
#if defined(BUTTON1_COLOR) && defined(BUTTON1_COLOR_INDEX)
|
||||
pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
|
||||
pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
|
||||
#endif
|
||||
#if defined(BUTTON2_COLOR) && defined(BUTTON2_COLOR_INDEX)
|
||||
pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1);
|
||||
pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1);
|
||||
#endif
|
||||
#endif
|
||||
pixels.show();
|
||||
LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
|
||||
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||
moduleConfig.ambient_lighting.blue);
|
||||
pixels.show();
|
||||
LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
|
||||
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
#ifdef RGBLED_CA
|
||||
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
|
||||
analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
|
||||
analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
|
||||
analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
|
||||
analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#elif defined(RGBLED_RED)
|
||||
analogWrite(RGBLED_RED, moduleConfig.ambient_lighting.red);
|
||||
analogWrite(RGBLED_GREEN, moduleConfig.ambient_lighting.green);
|
||||
@@ -200,11 +201,12 @@ class AmbientLightingThread : public concurrency::OSThread
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
#ifdef UNPHONE
|
||||
unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||
moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
|
||||
@@ -88,10 +88,16 @@ class BluetoothStatus : public Status
|
||||
break;
|
||||
case ConnectionState::CONNECTED:
|
||||
LOG_DEBUG("BluetoothStatus CONNECTED");
|
||||
#ifdef BLE_LED
|
||||
digitalWrite(BLE_LED, HIGH);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ConnectionState::DISCONNECTED:
|
||||
LOG_DEBUG("BluetoothStatus DISCONNECTED");
|
||||
#ifdef BLE_LED
|
||||
digitalWrite(BLE_LED, LOW);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -102,4 +108,4 @@ class BluetoothStatus : public Status
|
||||
|
||||
} // namespace meshtastic
|
||||
|
||||
extern meshtastic::BluetoothStatus *bluetoothStatus;
|
||||
extern meshtastic::BluetoothStatus *bluetoothStatus;
|
||||
|
||||
@@ -9,17 +9,23 @@ namespace concurrency
|
||||
Lock::Lock() : handle(xSemaphoreCreateBinary())
|
||||
{
|
||||
assert(handle);
|
||||
assert(xSemaphoreGive(handle));
|
||||
if (xSemaphoreGive(handle) == false) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void Lock::lock()
|
||||
{
|
||||
assert(xSemaphoreTake(handle, portMAX_DELAY));
|
||||
if (xSemaphoreTake(handle, portMAX_DELAY) == false) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void Lock::unlock()
|
||||
{
|
||||
assert(xSemaphoreGive(handle));
|
||||
if (xSemaphoreGive(handle) == false) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#else
|
||||
Lock::Lock() {}
|
||||
|
||||
@@ -81,7 +81,43 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// #define REGULATORY_LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_SG_923
|
||||
|
||||
// Total system gain in dBm to subtract from Tx power to remain within regulatory and Tx PA limits
|
||||
// This value should be set in variant.h and is PA gain + antenna gain (if variant has a non-removable antenna)
|
||||
// The value consists of PA gain + antenna gain (if variant has a non-removable antenna)
|
||||
// TX_GAIN_LORA should be set with definitions below for common modules, or in variant.h.
|
||||
|
||||
// Gain for common modules with transmit PAs
|
||||
#ifdef EBYTE_E22_900M30S
|
||||
// 10dB PA gain and 30dB rated output; based on measurements from
|
||||
// https://github.com/S5NC/EBYTE_ESP32-S3/blob/main/E22-900M30S%20power%20output%20testing.txt
|
||||
#define TX_GAIN_LORA 7
|
||||
#define SX126X_MAX_POWER 22
|
||||
#endif
|
||||
|
||||
#ifdef EBYTE_E22_900M33S
|
||||
// 25dB PA gain and 33dB rated output; based on TX Power Curve from E22-900M33S_UserManual_EN_v1.0.pdf
|
||||
#define TX_GAIN_LORA 25
|
||||
#define SX126X_MAX_POWER 8
|
||||
#endif
|
||||
|
||||
#ifdef NICERF_MINIF27
|
||||
// Note that datasheet power level of 9 corresponds with SX1262 at 22dBm
|
||||
// Maximum output power of 29dBm with VCC_PA = 5V
|
||||
#define TX_GAIN_LORA 7
|
||||
#define SX126X_MAX_POWER 22
|
||||
#endif
|
||||
|
||||
#ifdef NICERF_F30_HF
|
||||
// Maximum output power of 29.6dBm with VCC = 5V and SX1262 at 22dBm
|
||||
#define TX_GAIN_LORA 8
|
||||
#define SX126X_MAX_POWER 22
|
||||
#endif
|
||||
|
||||
#ifdef NICERF_F30_LF
|
||||
// Maximum output power of 32.0dBm with VCC = 5V and SX1262 at 22dBm
|
||||
#define TX_GAIN_LORA 10
|
||||
#define SX126X_MAX_POWER 22
|
||||
#endif
|
||||
|
||||
// Default system gain to 0 if not defined
|
||||
#ifndef TX_GAIN_LORA
|
||||
#define TX_GAIN_LORA 0
|
||||
#endif
|
||||
@@ -193,6 +229,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// -----------------------------------------------------------------------------
|
||||
#define FT6336U_ADDR 0x48
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RAK12035VB Soil Monitor (using RAK12023 up to 3 RAK12035 monitors can be connected)
|
||||
// - the default i2c address for this sensor is 0x20, and users are instructed to
|
||||
// set 0x21 and 0x22 for the second and third sensor if present.
|
||||
// -----------------------------------------------------------------------------
|
||||
#define RAK120351_ADDR 0x20
|
||||
#define RAK120352_ADDR 0x21
|
||||
#define RAK120353_ADDR 0x22
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// BIAS-T Generator
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -70,6 +70,7 @@ class ScanI2C
|
||||
DFROBOT_RAIN,
|
||||
DPS310,
|
||||
LTR390UV,
|
||||
RAK12035,
|
||||
TCA8418KB,
|
||||
PCT2075,
|
||||
} DeviceType;
|
||||
|
||||
@@ -358,7 +358,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
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) {
|
||||
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0xe9c || registerValue == 0xc8d) {
|
||||
type = SHT4X;
|
||||
logFoundDevice("SHT4X", (uint8_t)addr.address);
|
||||
} else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) {
|
||||
@@ -423,9 +423,21 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
logFoundDevice("BMA423", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
case TCA9535_ADDR:
|
||||
case RAK120352_ADDR:
|
||||
case RAK120353_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x02), 1);
|
||||
if (registerValue == addr.address) { // RAK12035 returns its I2C address at 0x02 (eg 0x20)
|
||||
type = RAK12035;
|
||||
logFoundDevice("RAK12035", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = TCA9535;
|
||||
logFoundDevice("TCA9535", (uint8_t)addr.address);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535", (uint8_t)addr.address);
|
||||
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);
|
||||
|
||||
@@ -467,18 +467,27 @@ class LGFX : public lgfx::LGFX_Device
|
||||
|
||||
// The following setting values are general initial values for each panel, so please comment out any
|
||||
// unknown items and try them.
|
||||
|
||||
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
|
||||
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
|
||||
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
||||
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
||||
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
||||
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||
#if defined(T_WATCH_S3)
|
||||
cfg.panel_width = 240;
|
||||
cfg.panel_height = 240;
|
||||
cfg.memory_width = 240;
|
||||
cfg.memory_height = 320;
|
||||
cfg.offset_x = 0;
|
||||
cfg.offset_y = 0; // No vertical shift needed — panel is top-aligned
|
||||
cfg.offset_rotation = 2; // Rotate 180° to correct upside-down layout
|
||||
#else
|
||||
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
|
||||
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
|
||||
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
||||
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
||||
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
||||
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||
#endif
|
||||
#ifdef TFT_DUMMY_READ_PIXELS
|
||||
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
|
||||
#else
|
||||
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
|
||||
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
|
||||
#endif
|
||||
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
||||
cfg.readable = true; // Set to true if data can be read
|
||||
|
||||
@@ -5,7 +5,7 @@ E-Ink display driver
|
||||
- Manufacturer: DKE
|
||||
- Size: 2.13 inch
|
||||
- Resolution: 122px x 250px
|
||||
- Flex connector marking: FPC-7528B
|
||||
- Flex connector marking (not a unique identifier): FPC-7528B
|
||||
|
||||
Note: this is from an older generation of DKE panels, which still used Solomon Systech controller ICs.
|
||||
DKE's website suggests that the latest DEPG0213BN displays may use Fitipower controllers instead.
|
||||
|
||||
@@ -5,7 +5,7 @@ E-Ink display driver
|
||||
- Manufacturer: DKE
|
||||
- Size: 2.9 inch
|
||||
- Resolution: 128px x 296px
|
||||
- Flex connector marking: FPC-7519 rev.b
|
||||
- Flex connector marking (not a unique identifier): FPC-7519 rev.b
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -9,12 +9,9 @@ void GDEY0154D67::configScanning()
|
||||
{
|
||||
// "Driver output control"
|
||||
sendCommand(0x01);
|
||||
sendData(0xC7);
|
||||
sendData(0xC7); // Scan until gate 199 (200px vertical res.)
|
||||
sendData(0x00);
|
||||
sendData(0x00);
|
||||
|
||||
// To-do: delete this method?
|
||||
// Values set here might be redundant: C7, 00, 00 seems to be default
|
||||
}
|
||||
|
||||
// Specify which information is used to control the sequence of voltages applied to move the pixels
|
||||
@@ -52,10 +49,10 @@ void GDEY0154D67::detachFromUpdate()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
return beginPolling(50, 500); // At least 500ms for fast refresh
|
||||
return beginPolling(50, 300); // At least 300ms for fast refresh
|
||||
case FULL:
|
||||
default:
|
||||
return beginPolling(100, 2000); // At least 2 seconds for full refresh
|
||||
return beginPolling(100, 1500); // At least 1.5 seconds for full refresh
|
||||
}
|
||||
}
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
@@ -5,7 +5,7 @@ E-Ink display driver
|
||||
- Manufacturer: Goodisplay
|
||||
- Size: 1.54 inch
|
||||
- Resolution: 200px x 200px
|
||||
- Flex connector marking: FPC-B001
|
||||
- Flex connector marking (not a unique identifier): FPC-B001
|
||||
|
||||
*/
|
||||
|
||||
@@ -31,9 +31,9 @@ class GDEY0154D67 : public SSD16XX
|
||||
GDEY0154D67() : SSD16XX(width, height, supported) {}
|
||||
|
||||
protected:
|
||||
virtual void configScanning() override;
|
||||
virtual void configWaveform() override;
|
||||
virtual void configUpdateSequence() override;
|
||||
void configScanning() override;
|
||||
void configWaveform() override;
|
||||
void configUpdateSequence() override;
|
||||
void detachFromUpdate() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@ void GDEY0213B74::configScanning()
|
||||
sendData(0xF9);
|
||||
sendData(0x00);
|
||||
sendData(0x00);
|
||||
|
||||
// To-do: delete this method?
|
||||
// Values set here might be redundant: F9, 00, 00 seems to be default
|
||||
}
|
||||
|
||||
// Specify which information is used to control the sequence of voltages applied to move the pixels
|
||||
|
||||
@@ -5,7 +5,9 @@ E-Ink display driver
|
||||
- Manufacturer: Goodisplay
|
||||
- Size: 2.13 inch
|
||||
- Resolution: 250px x 122px
|
||||
- Flex connector marking: FPC-A002
|
||||
- Flex connector marking (not a unique identifier):
|
||||
- FPC-A002
|
||||
- FPC-A005 20.06.15 TRX
|
||||
|
||||
*/
|
||||
|
||||
|
||||
61
src/graphics/niche/Drivers/EInk/HINK_E0213A289.cpp
Normal file
61
src/graphics/niche/Drivers/EInk/HINK_E0213A289.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "./HINK_E0213A289.h"
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
using namespace NicheGraphics::Drivers;
|
||||
|
||||
// Map the display controller IC's output to the connected panel
|
||||
void HINK_E0213A289::configScanning()
|
||||
{
|
||||
// "Driver output control"
|
||||
// Scan gates from 0 to 249 (vertical resolution 250px)
|
||||
sendCommand(0x01);
|
||||
sendData(0xF9); // Maximum gate # (249, bits 0-7)
|
||||
sendData(0x00); // Maximum gate # (bit 8)
|
||||
sendData(0x00); // (Do not invert scanning order)
|
||||
}
|
||||
|
||||
// Specify which information is used to control the sequence of voltages applied to move the pixels
|
||||
// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
|
||||
// the controller IC's OTP memory, when the update procedure begins.
|
||||
void HINK_E0213A289::configWaveform()
|
||||
{
|
||||
sendCommand(0x3C); // Border waveform:
|
||||
sendData(0x05); // Screen border should follow LUT1 waveform (actively drive pixels white)
|
||||
|
||||
sendCommand(0x18); // Temperature sensor:
|
||||
sendData(0x80); // Use internal temperature sensor to select an appropriate refresh waveform
|
||||
}
|
||||
|
||||
// Describes the sequence of events performed by the displays controller IC during a refresh
|
||||
// Includes "power up", "load settings from memory", "update the pixels", etc
|
||||
void HINK_E0213A289::configUpdateSequence()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
sendCommand(0x22); // Set "update sequence"
|
||||
sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
|
||||
break;
|
||||
|
||||
case FULL:
|
||||
default:
|
||||
sendCommand(0x22); // Set "update sequence"
|
||||
sendData(0xF7); // Will load LUT from OTP memory
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Once the refresh operation has been started,
|
||||
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
|
||||
// Only used when refresh is "async"
|
||||
void HINK_E0213A289::detachFromUpdate()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
return beginPolling(50, 500); // At least 500ms for fast refresh
|
||||
case FULL:
|
||||
default:
|
||||
return beginPolling(100, 1000); // At least 1 second for full refresh (quick; display only blinks pixels once)
|
||||
}
|
||||
}
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
44
src/graphics/niche/Drivers/EInk/HINK_E0213A289.h
Normal file
44
src/graphics/niche/Drivers/EInk/HINK_E0213A289.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
|
||||
E-Ink display driver
|
||||
- HINK_E0213A289
|
||||
- Manufacturer: Holitech
|
||||
- Size: 2.13 inch
|
||||
- Resolution: 122px x 250px
|
||||
- Flex connector label (not a unique identifier): FPC-7528B
|
||||
|
||||
Note: as of Feb. 2025, these panels are used for "WeActStudio 2.13in B&W" display modules
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "./SSD16XX.h"
|
||||
|
||||
namespace NicheGraphics::Drivers
|
||||
{
|
||||
class HINK_E0213A289 : public SSD16XX
|
||||
{
|
||||
// Display properties
|
||||
private:
|
||||
static constexpr uint32_t width = 122;
|
||||
static constexpr uint32_t height = 250;
|
||||
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
|
||||
|
||||
public:
|
||||
HINK_E0213A289() : SSD16XX(width, height, supported, 1) {}
|
||||
|
||||
protected:
|
||||
void configScanning() override;
|
||||
void configWaveform() override;
|
||||
void configUpdateSequence() override;
|
||||
void detachFromUpdate() override;
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::Drivers
|
||||
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
@@ -5,7 +5,7 @@ E-Ink display driver
|
||||
- Manufacturer: Holitech
|
||||
- Size: 4.2 inch
|
||||
- Resolution: 400px x 300px
|
||||
- Flex connector marking: HINK-E042A07-FPC-A1
|
||||
- Flex connector marking (not a unique identifier): HINK-E042A07-FPC-A1
|
||||
- Silver sticker with QR code, marked: HE042A87
|
||||
|
||||
Note: as of Feb. 2025, these panels are used for "WeActStudio 4.2in B&W" display modules
|
||||
|
||||
@@ -5,7 +5,6 @@ E-Ink display driver
|
||||
- Manufacturer: WISEVAST
|
||||
- Size: 2.13 inch
|
||||
- Resolution: 122px x 255px
|
||||
- Flex connector marking: Soldering connector, no connector is needed
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ E-Ink display driver
|
||||
- Manufacturer: Wisevast
|
||||
- Size: 2.13 inch
|
||||
- Resolution: 122px x 250px
|
||||
- Flex connector marking: HINK-E0213A162-FPC-A0 (Hidden, printed on back-side)
|
||||
- Flex connector marking (not a unique identifier): HINK-E0213A162-FPC-A0 (Hidden, printed on back-side)
|
||||
|
||||
Note: this display uses an uncommon controller IC, Fitipower JD79656.
|
||||
It is implemented as a "one-off", directly inheriting the EInk base class, unlike SSD16XX displays.
|
||||
|
||||
59
src/graphics/niche/Drivers/EInk/ZJY128296_029EAAMFGN.cpp
Normal file
59
src/graphics/niche/Drivers/EInk/ZJY128296_029EAAMFGN.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "./ZJY128296_029EAAMFGN.h"
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
using namespace NicheGraphics::Drivers;
|
||||
|
||||
// Map the display controller IC's output to the connected panel
|
||||
void ZJY128296_029EAAMFGN::configScanning()
|
||||
{
|
||||
// "Driver output control"
|
||||
// Scan gates from 0 to 295 (vertical resolution 296px)
|
||||
sendCommand(0x01);
|
||||
sendData(0x27); // Number of gates (295, bits 0-7)
|
||||
sendData(0x01); // Number of gates (295, bit 8)
|
||||
sendData(0x00); // (Do not invert scanning order)
|
||||
}
|
||||
|
||||
// Specify which information is used to control the sequence of voltages applied to move the pixels
|
||||
// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
|
||||
// the controller IC's OTP memory, when the update procedure begins.
|
||||
void ZJY128296_029EAAMFGN::configWaveform()
|
||||
{
|
||||
sendCommand(0x3C); // Border waveform:
|
||||
sendData(0x05); // Screen border should follow LUT1 waveform (actively drive pixels white)
|
||||
|
||||
sendCommand(0x18); // Temperature sensor:
|
||||
sendData(0x80); // Use internal temperature sensor to select an appropriate refresh waveform
|
||||
}
|
||||
|
||||
void ZJY128296_029EAAMFGN::configUpdateSequence()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
sendCommand(0x22); // Set "update sequence"
|
||||
sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
|
||||
break;
|
||||
|
||||
case FULL:
|
||||
default:
|
||||
sendCommand(0x22); // Set "update sequence"
|
||||
sendData(0xF7); // Will load LUT from OTP memory
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Once the refresh operation has been started,
|
||||
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
|
||||
// Only used when refresh is "async"
|
||||
void ZJY128296_029EAAMFGN::detachFromUpdate()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
return beginPolling(50, 300); // At least 300ms for fast refresh
|
||||
case FULL:
|
||||
default:
|
||||
return beginPolling(100, 2000); // At least 2 seconds for full refresh
|
||||
}
|
||||
}
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
44
src/graphics/niche/Drivers/EInk/ZJY128296_029EAAMFGN.h
Normal file
44
src/graphics/niche/Drivers/EInk/ZJY128296_029EAAMFGN.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
|
||||
E-Ink display driver
|
||||
- ZJY128296-029EAAMFGN
|
||||
- Manufacturer: Zhongjingyuan
|
||||
- Size: 2.9 inch
|
||||
- Resolution: 128px x 296px
|
||||
- Flex connector label (not a unique identifier): FPC-A005 20.06.15 TRX
|
||||
|
||||
Note: as of Feb. 2025, these panels are used for "WeActStudio 2.9in B&W" display modules
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "./SSD16XX.h"
|
||||
|
||||
namespace NicheGraphics::Drivers
|
||||
{
|
||||
class ZJY128296_029EAAMFGN : public SSD16XX
|
||||
{
|
||||
// Display properties
|
||||
private:
|
||||
static constexpr uint32_t width = 128;
|
||||
static constexpr uint32_t height = 296;
|
||||
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
|
||||
|
||||
public:
|
||||
ZJY128296_029EAAMFGN() : SSD16XX(width, height, supported) {}
|
||||
|
||||
protected:
|
||||
void configScanning() override;
|
||||
void configWaveform() override;
|
||||
void configUpdateSequence() override;
|
||||
void detachFromUpdate() override;
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::Drivers
|
||||
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
32
src/graphics/niche/Drivers/EInk/ZJY200200_0154DAAMFGN.h
Normal file
32
src/graphics/niche/Drivers/EInk/ZJY200200_0154DAAMFGN.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
E-Ink display driver
|
||||
- ZJY200200-0154DAAMFGN
|
||||
- Manufacturer: Zhongjingyuan
|
||||
- Size: 1.54 inch
|
||||
- Resolution: 200px x 200px
|
||||
- Flex connector marking: FPC-B001
|
||||
|
||||
Note: as of Feb. 2025, these panels are used for "WeActStudio 1.54in B&W" display modules
|
||||
|
||||
This *is* a distinct panel, however the driver is currently identical to GDEY0154D67
|
||||
We recognize it as separate now, to avoid breaking any custom builds if the drivers do need to diverge in future.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "./GDEY0154D67.h"
|
||||
|
||||
namespace NicheGraphics::Drivers
|
||||
{
|
||||
|
||||
typedef GDEY0154D67 ZJY200200_0154DAAMFGN;
|
||||
|
||||
} // namespace NicheGraphics::Drivers
|
||||
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "RTC.h"
|
||||
#include "modules/AdminModule.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "modules/TextMessageModule.h"
|
||||
#include "sleep.h"
|
||||
|
||||
@@ -37,6 +38,10 @@ void InkHUD::Events::begin()
|
||||
|
||||
void InkHUD::Events::onButtonShort()
|
||||
{
|
||||
// Cancel any beeping, buzzing, blinking
|
||||
// Some button handling suppressed if we are dismissing an external notification (see below)
|
||||
bool dismissedExt = dismissExternalNotification();
|
||||
|
||||
// Check which system applet wants to handle the button press (if any)
|
||||
SystemApplet *consumer = nullptr;
|
||||
for (SystemApplet *sa : inkhud->systemApplets) {
|
||||
@@ -49,7 +54,7 @@ void InkHUD::Events::onButtonShort()
|
||||
// If no system applet is handling input, default behavior instead is to cycle applets
|
||||
if (consumer)
|
||||
consumer->onButtonShortPress();
|
||||
else
|
||||
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
|
||||
inkhud->nextApplet();
|
||||
}
|
||||
|
||||
@@ -204,4 +209,24 @@ int InkHUD::Events::beforeLightSleep(void *unused)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Silence all ongoing beeping, blinking, buzzing, coming from the external notification module
|
||||
// Returns true if an external notification was active, and we dismissed it
|
||||
// Button handling changes depending on our result
|
||||
bool InkHUD::Events::dismissExternalNotification()
|
||||
{
|
||||
// Abort if not using external notifications
|
||||
if (!moduleConfig.external_notification.enabled)
|
||||
return false;
|
||||
|
||||
// Abort if nothing to dismiss
|
||||
if (!externalNotificationModule->nagging())
|
||||
return false;
|
||||
|
||||
// Stop the beep buzz blink
|
||||
externalNotificationModule->stopNow();
|
||||
|
||||
// Inform that we did indeed dismiss an external notification
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -62,6 +62,9 @@ class Events
|
||||
CallbackObserver<Events, void *> lightSleepObserver = CallbackObserver<Events, void *>(this, &Events::beforeLightSleep);
|
||||
#endif
|
||||
|
||||
// End any externalNotification beeping, buzzing, blinking etc
|
||||
bool dismissExternalNotification();
|
||||
|
||||
// If set, InkHUD's data will be erased during onReboot
|
||||
bool eraseOnReboot = false;
|
||||
};
|
||||
|
||||
33
src/main.cpp
33
src/main.cpp
@@ -337,12 +337,22 @@ void setup()
|
||||
|
||||
#ifdef LED_POWER
|
||||
pinMode(LED_POWER, OUTPUT);
|
||||
digitalWrite(LED_POWER, HIGH);
|
||||
digitalWrite(LED_POWER, LED_STATE_ON);
|
||||
#endif
|
||||
|
||||
#ifdef USER_LED
|
||||
pinMode(USER_LED, OUTPUT);
|
||||
digitalWrite(USER_LED, LOW);
|
||||
digitalWrite(USER_LED, HIGH ^ LED_STATE_ON);
|
||||
#endif
|
||||
|
||||
#ifdef WIFI_LED
|
||||
pinMode(WIFI_LED, OUTPUT);
|
||||
digitalWrite(WIFI_LED, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef BLE_LED
|
||||
pinMode(BLE_LED, OUTPUT);
|
||||
digitalWrite(BLE_LED, LOW);
|
||||
#endif
|
||||
|
||||
#if defined(T_DECK)
|
||||
@@ -482,19 +492,6 @@ void setup()
|
||||
|
||||
fsInit();
|
||||
|
||||
#if defined(_SEEED_XIAO_NRF52840_SENSE_H_)
|
||||
|
||||
pinMode(CHARGE_LED, INPUT); // sets to detect if charge LED is on or off to see if USB is plugged in
|
||||
|
||||
pinMode(HICHG, OUTPUT);
|
||||
digitalWrite(HICHG, LOW); // 100 mA charging current if set to LOW and 50mA (actually about 20mA) if set to HIGH
|
||||
|
||||
pinMode(BAT_READ, OUTPUT);
|
||||
digitalWrite(BAT_READ, LOW); // This is pin P0_14 = 14 and by pullling low to GND it provices path to read on pin 32 (P0,31)
|
||||
// PIN_VBAT the voltage from divider on XIAO board
|
||||
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
#if defined(I2C_SDA1) && defined(ARCH_RP2040)
|
||||
Wire1.setSDA(I2C_SDA1);
|
||||
@@ -732,6 +729,7 @@ void setup()
|
||||
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);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RAK12035, meshtastic_TelemetrySensorType_RAK12035);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PCT2075, meshtastic_TelemetrySensorType_PCT2075);
|
||||
|
||||
i2cScanner.reset();
|
||||
@@ -931,6 +929,11 @@ void setup()
|
||||
service = new MeshService();
|
||||
service->init();
|
||||
|
||||
if (nodeDB->keyIsLowEntropy) {
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
|
||||
}
|
||||
|
||||
// Now that the mesh service is created, create any modules
|
||||
setupModules();
|
||||
|
||||
|
||||
@@ -3,12 +3,17 @@
|
||||
#include "architecture.h"
|
||||
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||
#include "NodeDB.h"
|
||||
#include "aes-ccm.h"
|
||||
#include "meshUtils.h"
|
||||
#include <Crypto.h>
|
||||
#include <Curve25519.h>
|
||||
#include <RNG.h>
|
||||
#include <SHA256.h>
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN)
|
||||
#if !defined(ARCH_STM32WL)
|
||||
#define CryptRNG RNG
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create a public/private key pair with Curve25519.
|
||||
@@ -18,6 +23,14 @@
|
||||
*/
|
||||
void CryptoEngine::generateKeyPair(uint8_t *pubKey, uint8_t *privKey)
|
||||
{
|
||||
// Mix in any randomness we can, to make key generation stronger.
|
||||
CryptRNG.begin(optstr(APP_VERSION));
|
||||
if (myNodeInfo.device_id.size == 16) {
|
||||
CryptRNG.stir(myNodeInfo.device_id.bytes, myNodeInfo.device_id.size);
|
||||
}
|
||||
auto noise = random();
|
||||
CryptRNG.stir((uint8_t *)&noise, sizeof(noise));
|
||||
|
||||
LOG_DEBUG("Generate Curve25519 keypair");
|
||||
Curve25519::dh1(public_key, private_key);
|
||||
memcpy(pubKey, public_key, sizeof(public_key));
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Default.h"
|
||||
#include "FSCommon.h"
|
||||
#include "MeshRadio.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PacketHistory.h"
|
||||
#include "PowerFSM.h"
|
||||
@@ -261,7 +262,7 @@ NodeDB::NodeDB()
|
||||
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN || MESHTASTIC_EXCLUDE_PKI)
|
||||
|
||||
if (!owner.is_licensed) {
|
||||
if (!owner.is_licensed && config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
||||
bool keygenSuccess = false;
|
||||
if (config.security.private_key.size == 32) {
|
||||
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
|
||||
@@ -287,6 +288,16 @@ NodeDB::NodeDB()
|
||||
crypto->setDHPrivateKey(config.security.private_key.bytes);
|
||||
}
|
||||
#endif
|
||||
keyIsLowEntropy = checkLowEntropyPublicKey(config.security.public_key);
|
||||
if (keyIsLowEntropy) {
|
||||
LOG_WARN("Erasing low entropy keys");
|
||||
config.security.private_key.size = 0;
|
||||
memfll(config.security.private_key.bytes, '\0', sizeof(config.security.private_key.bytes));
|
||||
config.security.public_key.size = 0;
|
||||
memfll(config.security.public_key.bytes, '\0', sizeof(config.security.public_key.bytes));
|
||||
owner.public_key.size = 0;
|
||||
memfll(owner.public_key.bytes, '\0', sizeof(owner.public_key.bytes));
|
||||
}
|
||||
// Include our owner in the node db under our nodenum
|
||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
|
||||
info->user = TypeConversions::ConvertToUserLite(owner);
|
||||
@@ -499,6 +510,21 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
|
||||
config.lora.override_duty_cycle = false;
|
||||
config.lora.config_ok_to_mqtt = false;
|
||||
|
||||
#ifdef USERPREFS_CONFIG_DEVICE_ROLE
|
||||
// Restrict ROUTER*, LOST AND FOUND, and REPEATER roles for security reasons
|
||||
if (IS_ONE_OF(USERPREFS_CONFIG_DEVICE_ROLE, meshtastic_Config_DeviceConfig_Role_ROUTER,
|
||||
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_REPEATER,
|
||||
meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND)) {
|
||||
LOG_WARN("ROUTER roles are restricted, falling back to CLIENT role");
|
||||
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
|
||||
} else {
|
||||
config.device.role = USERPREFS_CONFIG_DEVICE_ROLE;
|
||||
}
|
||||
#else
|
||||
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; // Default to client.
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_CONFIG_LORA_REGION
|
||||
config.lora.region = USERPREFS_CONFIG_LORA_REGION;
|
||||
#else
|
||||
@@ -671,6 +697,11 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_CONFIG_DEVICE_ROLE
|
||||
// Apply role-specific defaults when role is set via user preferences
|
||||
installRoleDefaults(config.device.role);
|
||||
#endif
|
||||
|
||||
initConfigIntervals();
|
||||
}
|
||||
|
||||
@@ -1514,15 +1545,25 @@ void NodeDB::addFromContact(meshtastic_SharedContact contact)
|
||||
return;
|
||||
}
|
||||
info->num = contact.node_num;
|
||||
info->last_heard = getValidTime(RTCQualityNTP);
|
||||
info->has_user = true;
|
||||
info->user = TypeConversions::ConvertToUserLite(contact.user);
|
||||
info->is_favorite = true;
|
||||
// Mark the node's key as manually verified to indicate trustworthiness.
|
||||
info->bitfield |= NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK;
|
||||
updateGUIforNode = info;
|
||||
powerFSM.trigger(EVENT_NODEDB_UPDATED);
|
||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||
if (contact.should_ignore) {
|
||||
// If should_ignore is set,
|
||||
// we need to clear the public key and other cruft, in addition to setting the node as ignored
|
||||
info->is_ignored = true;
|
||||
info->has_device_metrics = false;
|
||||
info->has_position = false;
|
||||
info->user.public_key.size = 0;
|
||||
info->user.public_key.bytes[0] = 0;
|
||||
} else {
|
||||
info->last_heard = getValidTime(RTCQualityNTP);
|
||||
info->is_favorite = true;
|
||||
info->bitfield |= NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK;
|
||||
// Mark the node's key as manually verified to indicate trustworthiness.
|
||||
updateGUIforNode = info;
|
||||
powerFSM.trigger(EVENT_NODEDB_UPDATED);
|
||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||
}
|
||||
saveNodeDatabaseToDisk();
|
||||
}
|
||||
|
||||
@@ -1536,8 +1577,22 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
||||
}
|
||||
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||
if (p.public_key.size > 0) {
|
||||
if (p.public_key.size == 32 && nodeId != nodeDB->getNodeNum()) {
|
||||
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
|
||||
|
||||
// Alert the user if a remote node is advertising public key that matches our own
|
||||
if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0 && !duplicateWarned) {
|
||||
duplicateWarned = true;
|
||||
char warning[] = "Remote device %s has advertised your public key. This may indicate a compromised key. You may need "
|
||||
"to regenerate your public keys.";
|
||||
LOG_WARN(warning, p.long_name);
|
||||
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
|
||||
cn->which_payload_variant = meshtastic_ClientNotification_duplicated_public_key_tag;
|
||||
cn->level = meshtastic_LogRecord_Level_WARNING;
|
||||
cn->time = getValidTime(RTCQualityFromNet);
|
||||
sprintf(cn->message, warning, p.long_name);
|
||||
service->sendClientNotification(cn);
|
||||
}
|
||||
}
|
||||
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
|
||||
LOG_INFO("Public Key set for node, not updating!");
|
||||
@@ -1712,6 +1767,39 @@ UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
|
||||
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
|
||||
}
|
||||
|
||||
bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t keyToTest)
|
||||
{
|
||||
if (keyToTest.size == 32) {
|
||||
uint8_t keyHash[32] = {0};
|
||||
memcpy(keyHash, keyToTest.bytes, keyToTest.size);
|
||||
crypto->hash(keyHash, 32);
|
||||
if (memcmp(keyHash, LOW_ENTROPY_HASH1, sizeof(LOW_ENTROPY_HASH1)) ==
|
||||
0 || // should become an array that gets looped through rather than this abomination
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH2, sizeof(LOW_ENTROPY_HASH2)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH3, sizeof(LOW_ENTROPY_HASH3)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH4, sizeof(LOW_ENTROPY_HASH4)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH5, sizeof(LOW_ENTROPY_HASH5)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH6, sizeof(LOW_ENTROPY_HASH6)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH7, sizeof(LOW_ENTROPY_HASH7)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH8, sizeof(LOW_ENTROPY_HASH8)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH9, sizeof(LOW_ENTROPY_HASH9)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH10, sizeof(LOW_ENTROPY_HASH10)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH11, sizeof(LOW_ENTROPY_HASH11)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH12, sizeof(LOW_ENTROPY_HASH12)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH13, sizeof(LOW_ENTROPY_HASH13)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH14, sizeof(LOW_ENTROPY_HASH14)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH15, sizeof(LOW_ENTROPY_HASH15)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH16, sizeof(LOW_ENTROPY_HASH16)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH17, sizeof(LOW_ENTROPY_HASH17)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH18, sizeof(LOW_ENTROPY_HASH18)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH19, sizeof(LOW_ENTROPY_HASH19)) == 0 ||
|
||||
memcmp(keyHash, LOW_ENTROPY_HASH20, sizeof(LOW_ENTROPY_HASH20)) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
|
||||
{
|
||||
bool success = false;
|
||||
@@ -1822,4 +1910,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
|
||||
LOG_ERROR("A critical failure occurred, portduino is exiting");
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,70 @@
|
||||
#include "PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
||||
|
||||
static const uint8_t LOW_ENTROPY_HASH1[] = {0xf4, 0x7e, 0xcc, 0x17, 0xe6, 0xb4, 0xa3, 0x22, 0xec, 0xee, 0xd9,
|
||||
0x08, 0x4f, 0x39, 0x63, 0xea, 0x80, 0x75, 0xe1, 0x24, 0xce, 0x05,
|
||||
0x36, 0x69, 0x63, 0xb2, 0xcb, 0xc0, 0x28, 0xd3, 0x34, 0x8b};
|
||||
static const uint8_t LOW_ENTROPY_HASH2[] = {0x5a, 0x9e, 0xa2, 0xa6, 0x8a, 0xa6, 0x66, 0xc1, 0x5f, 0x55, 0x00,
|
||||
0x64, 0xa3, 0xa6, 0xfe, 0x71, 0xc0, 0xbb, 0x82, 0xc3, 0x32, 0x3d,
|
||||
0x7a, 0x7a, 0xe3, 0x6e, 0xfd, 0xdd, 0xad, 0x3a, 0x66, 0xb9};
|
||||
static const uint8_t LOW_ENTROPY_HASH3[] = {0xb3, 0xdf, 0x3b, 0x2e, 0x67, 0xb6, 0xd5, 0xf8, 0xdf, 0x76, 0x2c,
|
||||
0x45, 0x5e, 0x2e, 0xbd, 0x16, 0xc5, 0xf8, 0x67, 0xaa, 0x15, 0xf8,
|
||||
0x92, 0x0b, 0xdf, 0x5a, 0x66, 0x50, 0xac, 0x0d, 0xbb, 0x2f};
|
||||
static const uint8_t LOW_ENTROPY_HASH4[] = {0x3b, 0x8f, 0x86, 0x3a, 0x38, 0x1f, 0x77, 0x39, 0xa9, 0x4e, 0xef,
|
||||
0x91, 0x18, 0x5a, 0x62, 0xe1, 0xaa, 0x9d, 0x36, 0xea, 0xce, 0x60,
|
||||
0x35, 0x8d, 0x9d, 0x1f, 0xf4, 0xb8, 0xc9, 0x13, 0x6a, 0x5d};
|
||||
static const uint8_t LOW_ENTROPY_HASH5[] = {0x36, 0x7e, 0x2d, 0xe1, 0x84, 0x5f, 0x42, 0x52, 0x29, 0x11, 0x0a,
|
||||
0x25, 0x64, 0x54, 0x6a, 0x6b, 0xfd, 0xb6, 0x65, 0xff, 0x15, 0x1a,
|
||||
0x51, 0x71, 0x22, 0x40, 0x57, 0xf6, 0x91, 0x9b, 0x64, 0x58};
|
||||
static const uint8_t LOW_ENTROPY_HASH6[] = {0x16, 0x77, 0xeb, 0xa4, 0x52, 0x91, 0xfb, 0x26, 0xcf, 0x8f, 0xd7,
|
||||
0xd9, 0xd1, 0x5d, 0xc4, 0x68, 0x73, 0x75, 0xed, 0xc5, 0x95, 0x58,
|
||||
0xee, 0x90, 0x56, 0xd4, 0x2f, 0x31, 0x29, 0xf7, 0x8c, 0x1f};
|
||||
static const uint8_t LOW_ENTROPY_HASH7[] = {0x31, 0x8c, 0xa9, 0x5e, 0xed, 0x3c, 0x12, 0xbf, 0x97, 0x9c, 0x47,
|
||||
0x8e, 0x98, 0x9d, 0xc2, 0x3e, 0x86, 0x23, 0x90, 0x29, 0xc8, 0xb0,
|
||||
0x20, 0xf8, 0xb1, 0xb0, 0xaa, 0x19, 0x2a, 0xcf, 0x0a, 0x54};
|
||||
static const uint8_t LOW_ENTROPY_HASH8[] = {0xa4, 0x8a, 0x99, 0x0e, 0x51, 0xdc, 0x12, 0x20, 0xf3, 0x13, 0xf5,
|
||||
0x2b, 0x3a, 0xe2, 0x43, 0x42, 0xc6, 0x52, 0x98, 0xcd, 0xbb, 0xca,
|
||||
0xb1, 0x31, 0xa0, 0xd4, 0xd6, 0x30, 0xf3, 0x27, 0xfb, 0x49};
|
||||
static const uint8_t LOW_ENTROPY_HASH9[] = {0xd2, 0x3f, 0x13, 0x8d, 0x22, 0x04, 0x8d, 0x07, 0x59, 0x58, 0xa0,
|
||||
0xf9, 0x55, 0xcf, 0x30, 0xa0, 0x2e, 0x2f, 0xca, 0x80, 0x20, 0xe4,
|
||||
0xde, 0xa1, 0xad, 0xd9, 0x58, 0xb3, 0x43, 0x2b, 0x22, 0x70};
|
||||
static const uint8_t LOW_ENTROPY_HASH10[] = {0x40, 0x41, 0xec, 0x6a, 0xd2, 0xd6, 0x03, 0xe4, 0x9a, 0x9e, 0xbd,
|
||||
0x6c, 0x0a, 0x9b, 0x75, 0xa4, 0xbc, 0xab, 0x6f, 0xa7, 0x95, 0xff,
|
||||
0x2d, 0xf6, 0xe9, 0xb9, 0xab, 0x4c, 0x0c, 0x1c, 0xd0, 0x3b};
|
||||
static const uint8_t LOW_ENTROPY_HASH11[] = {0x22, 0x49, 0x32, 0x2b, 0x00, 0xf9, 0x22, 0xfa, 0x17, 0x02, 0xe9,
|
||||
0x64, 0x82, 0xf0, 0x4d, 0x1b, 0xc7, 0x04, 0xfc, 0xdc, 0x8c, 0x5e,
|
||||
0xb6, 0xd9, 0x16, 0xd6, 0x37, 0xce, 0x59, 0xaa, 0x09, 0x49};
|
||||
static const uint8_t LOW_ENTROPY_HASH12[] = {0x48, 0x6f, 0x1e, 0x48, 0x97, 0x88, 0x64, 0xac, 0xe8, 0xeb, 0x30,
|
||||
0xa3, 0xc3, 0xe1, 0xcf, 0x97, 0x39, 0xa6, 0x55, 0x5b, 0x5f, 0xbf,
|
||||
0x18, 0xb7, 0x3a, 0xdf, 0xa8, 0x75, 0xe7, 0x9d, 0xe0, 0x1e};
|
||||
static const uint8_t LOW_ENTROPY_HASH13[] = {0x09, 0xb4, 0xe2, 0x6d, 0x28, 0x98, 0xc9, 0x47, 0x66, 0x46, 0xbf,
|
||||
0xff, 0x58, 0x17, 0x91, 0xaa, 0xc3, 0xbf, 0x4a, 0x9d, 0x0b, 0x88,
|
||||
0xb1, 0xf1, 0x03, 0xdd, 0x61, 0xd7, 0xba, 0x9e, 0x64, 0x98};
|
||||
static const uint8_t LOW_ENTROPY_HASH14[] = {0x39, 0x39, 0x84, 0xe0, 0x22, 0x2f, 0x7d, 0x78, 0x45, 0x18, 0x72,
|
||||
0xb4, 0x13, 0xd2, 0x01, 0x2f, 0x3c, 0xa1, 0xb0, 0xfe, 0x39, 0xd0,
|
||||
0xf1, 0x3c, 0x72, 0xd6, 0xef, 0x54, 0xd5, 0x77, 0x22, 0xa0};
|
||||
static const uint8_t LOW_ENTROPY_HASH15[] = {0x0a, 0xda, 0x5f, 0xec, 0xff, 0x5c, 0xc0, 0x2e, 0x5f, 0xc4, 0x8d,
|
||||
0x03, 0xe5, 0x80, 0x59, 0xd3, 0x5d, 0x49, 0x86, 0xe9, 0x8d, 0xf6,
|
||||
0xf6, 0x16, 0x35, 0x3d, 0xf9, 0x9b, 0x29, 0x55, 0x9e, 0x64};
|
||||
static const uint8_t LOW_ENTROPY_HASH16[] = {0x08, 0x56, 0xF0, 0xD7, 0xEF, 0x77, 0xD6, 0x11, 0x1C, 0x8F, 0x95,
|
||||
0x2D, 0x3C, 0xDF, 0xB1, 0x22, 0xBF, 0x60, 0x9B, 0xE5, 0xA9, 0xC0,
|
||||
0x6E, 0x4B, 0x01, 0xDC, 0xD1, 0x57, 0x44, 0xB2, 0xA5, 0xCF};
|
||||
static const uint8_t LOW_ENTROPY_HASH17[] = {0x2C, 0xB2, 0x77, 0x85, 0xD6, 0xB7, 0x48, 0x9C, 0xFE, 0xBC, 0x80,
|
||||
0x26, 0x60, 0xF4, 0x6D, 0xCE, 0x11, 0x31, 0xA2, 0x1E, 0x33, 0x0A,
|
||||
0x6D, 0x2B, 0x00, 0xFA, 0x0C, 0x90, 0x95, 0x8F, 0x5C, 0x6B};
|
||||
static const uint8_t LOW_ENTROPY_HASH18[] = {0xFA, 0x59, 0xC8, 0x6E, 0x94, 0xEE, 0x75, 0xC9, 0x9A, 0xB0, 0xFE,
|
||||
0x89, 0x36, 0x40, 0xC9, 0x99, 0x4A, 0x3B, 0xF4, 0xAA, 0x12, 0x24,
|
||||
0xA2, 0x0F, 0xF9, 0xD1, 0x08, 0xCB, 0x78, 0x19, 0xAA, 0xE5};
|
||||
static const uint8_t LOW_ENTROPY_HASH19[] = {0x6E, 0x42, 0x7A, 0x4A, 0x8C, 0x61, 0x62, 0x22, 0xA1, 0x89, 0xD3,
|
||||
0xA4, 0xC2, 0x19, 0xA3, 0x83, 0x53, 0xA7, 0x7A, 0x0A, 0x89, 0xE2,
|
||||
0x54, 0x52, 0x62, 0x3D, 0xE7, 0xCA, 0x8C, 0xF6, 0x6A, 0x60};
|
||||
static const uint8_t LOW_ENTROPY_HASH20[] = {0x20, 0x27, 0x2F, 0xBA, 0x0C, 0x99, 0xD7, 0x29, 0xF3, 0x11, 0x35,
|
||||
0x89, 0x9D, 0x0E, 0x24, 0xA1, 0xC3, 0xCB, 0xDF, 0x8A, 0xF1, 0xC6,
|
||||
0xFE, 0xD0, 0xD7, 0x9F, 0x92, 0xD6, 0x8F, 0x59, 0xBF, 0xE4};
|
||||
static const char LOW_ENTROPY_WARNING[] = "Compromised keys detected, please regenerate.";
|
||||
#endif
|
||||
/*
|
||||
DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a
|
||||
#define here.
|
||||
@@ -87,6 +151,9 @@ class NodeDB
|
||||
Observable<const meshtastic::NodeStatus *> newStatus;
|
||||
pb_size_t numMeshNodes;
|
||||
|
||||
bool keyIsLowEntropy = false;
|
||||
bool hasWarned = false;
|
||||
|
||||
/// don't do mesh based algorithm for node id assignment (initially)
|
||||
/// instead just store in flash - possibly even in the initial alpha release do this hack
|
||||
NodeDB();
|
||||
@@ -205,11 +272,14 @@ class NodeDB
|
||||
|
||||
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
||||
|
||||
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t keyToTest);
|
||||
|
||||
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
|
||||
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
||||
int restoreWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
|
||||
private:
|
||||
bool duplicateWarned = false;
|
||||
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
|
||||
|
||||
@@ -7,152 +7,377 @@
|
||||
#endif
|
||||
#include "Throttle.h"
|
||||
|
||||
PacketHistory::PacketHistory()
|
||||
#define PACKETHISTORY_MAX \
|
||||
max((int)(MAX_NUM_NODES * 2.0), 100) // x2..3 Should suffice. Empirical setup. 16B per record malloc'ed, but no less than 100
|
||||
|
||||
#define RECENT_WARN_AGE (10 * 60 * 1000L) // Warn if the packet that gets removed was more recent than 10 min
|
||||
|
||||
#define VERBOSE_PACKET_HISTORY 0 // Set to 1 for verbose logging, 2 for heavy debugging
|
||||
#define PACKET_HISTORY_TRACE_AGING 1 // Set to 1 to enable logging of the age of re/used history slots
|
||||
|
||||
PacketHistory::PacketHistory(uint32_t size) : recentPacketsCapacity(0), recentPackets(NULL) // Initialize members
|
||||
{
|
||||
recentPackets.reserve(MAX_NUM_NODES); // Prealloc the worst case # of records - to prevent heap fragmentation
|
||||
// setup our periodic task
|
||||
if (size < 4 || size > PACKETHISTORY_MAX) { // Copilot suggested - makes sense
|
||||
LOG_WARN("Packet History - Invalid size %d, using default %d", size, PACKETHISTORY_MAX);
|
||||
size = PACKETHISTORY_MAX; // Use default size if invalid
|
||||
}
|
||||
|
||||
// Allocate memory for the recent packets array
|
||||
recentPacketsCapacity = size;
|
||||
recentPackets = new PacketRecord[recentPacketsCapacity];
|
||||
if (!recentPackets) { // No logging here, console/log probably uninitialized yet.
|
||||
LOG_ERROR("Packet History - Memory allocation failed for size=%d entries / %d Bytes", size,
|
||||
sizeof(PacketRecord) * recentPacketsCapacity);
|
||||
recentPacketsCapacity = 0; // mark allocation fail
|
||||
return; // return early
|
||||
}
|
||||
|
||||
// Initialize the recent packets array to zero
|
||||
memset(recentPackets, 0, sizeof(PacketRecord) * recentPacketsCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recentBroadcasts and return true if we have already seen this packet
|
||||
*/
|
||||
PacketHistory::~PacketHistory()
|
||||
{
|
||||
recentPacketsCapacity = 0;
|
||||
delete[] recentPackets;
|
||||
recentPackets = NULL;
|
||||
}
|
||||
|
||||
/** Update recentPackets and return true if we have already seen this packet */
|
||||
bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpdate, bool *wasFallback, bool *weWereNextHop)
|
||||
{
|
||||
if (!initOk()) {
|
||||
LOG_ERROR("Packet History - Was Seen Recently: NOT INITIALIZED!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p->id == 0) {
|
||||
LOG_DEBUG("Ignore message with zero id");
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - Was Seen Recently: ID is 0, not a floodable message");
|
||||
#endif
|
||||
return false; // Not a floodable message ID, so we don't care
|
||||
}
|
||||
|
||||
PacketRecord r;
|
||||
memset(&r, 0, sizeof(PacketRecord)); // Initialize the record to zero
|
||||
|
||||
// Save basic info from checked packet
|
||||
r.id = p->id;
|
||||
r.sender = getFrom(p);
|
||||
r.rxTimeMsec = millis();
|
||||
r.sender = getFrom(p); // If 0 then use our ID
|
||||
r.next_hop = p->next_hop;
|
||||
r.relayed_by[0] = p->relay_node;
|
||||
// LOG_INFO("Add relayed_by 0x%x for id=0x%x", p->relay_node, r.id);
|
||||
|
||||
auto found = recentPackets.find(r);
|
||||
bool seenRecently = (found != recentPackets.end()); // found not equal to .end() means packet was seen recently
|
||||
r.rxTimeMsec = millis(); //
|
||||
if (r.rxTimeMsec == 0) // =0 every 49.7 days? 0 is special
|
||||
r.rxTimeMsec = 1;
|
||||
|
||||
if (seenRecently &&
|
||||
!Throttle::isWithinTimespanMs(found->rxTimeMsec, FLOOD_EXPIRE_TIME)) { // Check whether found packet has already expired
|
||||
recentPackets.erase(found); // Erase and pretend packet has not been seen recently
|
||||
found = recentPackets.end();
|
||||
seenRecently = false;
|
||||
}
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - Was Seen Recently: @start s=%08x id=%08x / to=%08x nh=%02x rn=%02x / wUpd=%s / wasFb?%d wWNH?%d",
|
||||
r.sender, r.id, p->to, p->next_hop, p->relay_node, withUpdate ? "YES" : "NO", wasFallback ? *wasFallback : -1,
|
||||
weWereNextHop ? *weWereNextHop : -1);
|
||||
#endif
|
||||
|
||||
PacketRecord *found = find(r.sender, r.id); // Find the packet record in the recentPackets array
|
||||
bool seenRecently = (found != NULL); // If found -> the packet was seen recently
|
||||
|
||||
if (seenRecently) {
|
||||
LOG_DEBUG("Found existing packet record for fr=0x%x,to=0x%x,id=0x%x", p->from, p->to, p->id);
|
||||
uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum());
|
||||
uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum()); // Get our relay ID from our node number
|
||||
|
||||
if (wasFallback) {
|
||||
// If it was seen with a next-hop not set to us and now it's NO_NEXT_HOP_PREFERENCE, and the relayer relayed already
|
||||
// before, it's a fallback to flooding. If we didn't already relay and the next-hop neither, we might need to handle
|
||||
// it now.
|
||||
if (found->sender != nodeDB->getNodeNum() && found->next_hop != NO_NEXT_HOP_PREFERENCE &&
|
||||
found->next_hop != ourRelayID && p->next_hop == NO_NEXT_HOP_PREFERENCE && wasRelayer(p->relay_node, found) &&
|
||||
!wasRelayer(ourRelayID, found) && !wasRelayer(found->next_hop, found)) {
|
||||
found->next_hop != ourRelayID && p->next_hop == NO_NEXT_HOP_PREFERENCE && wasRelayer(p->relay_node, *found) &&
|
||||
!wasRelayer(ourRelayID, *found) &&
|
||||
!wasRelayer(
|
||||
found->next_hop,
|
||||
*found)) { // If we were not the next hop and the next hop is not us, and we are not relaying this packet
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - Was Seen Recently: f=%08x id=%08x nh=%02x rn=%02x oID=%02x, wasFbk=%d-set TRUE",
|
||||
p->from, p->id, p->next_hop, p->relay_node, ourRelayID, wasFallback ? *wasFallback : -1);
|
||||
#endif
|
||||
*wasFallback = true;
|
||||
} else {
|
||||
// debug log only
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - Was Seen Recently: f=%08x id=%08x nh=%02x rn=%02x oID=%02x, wasFbk=%d-no change",
|
||||
p->from, p->id, p->next_hop, p->relay_node, ourRelayID, wasFallback ? *wasFallback : -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we were the next hop for this packet
|
||||
if (weWereNextHop) {
|
||||
*weWereNextHop = found->next_hop == ourRelayID;
|
||||
*weWereNextHop = (found->next_hop == ourRelayID);
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - Was Seen Recently: f=%08x id=%08x nh=%02x rn=%02x foundnh=%02x oID=%02x -> wWNH=%s",
|
||||
p->from, p->id, p->next_hop, p->relay_node, found->next_hop, ourRelayID, (*weWereNextHop) ? "YES" : "NO");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (withUpdate) {
|
||||
if (found != recentPackets.end()) { // delete existing to updated timestamp and relayed_by (re-insert)
|
||||
if (found != NULL) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - Was Seen Recently: s=%08x id=%08x nh=%02x rby=%02x %02x %02x age=%d wUpd BEFORE",
|
||||
found->sender, found->id, found->next_hop, found->relayed_by[0], found->relayed_by[1], found->relayed_by[2],
|
||||
millis() - found->rxTimeMsec);
|
||||
#endif
|
||||
|
||||
// Add the existing relayed_by to the new record
|
||||
for (uint8_t i = 0; i < NUM_RELAYERS - 1; i++) {
|
||||
if (found->relayed_by[i])
|
||||
for (uint8_t i = 0; i < (NUM_RELAYERS - 1); i++) {
|
||||
if (found->relayed_by[i] != 0)
|
||||
r.relayed_by[i + 1] = found->relayed_by[i];
|
||||
}
|
||||
r.next_hop = found->next_hop; // keep the original next_hop (such that we check whether we were originally asked)
|
||||
recentPackets.erase(found); // as unsorted_set::iterator is const (can't update - so re-insert..)
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - Was Seen Recently: s=%08x id=%08x nh=%02x rby=%02x %02x %02x age=%d wUpd AFTER", r.sender,
|
||||
r.id, r.next_hop, r.relayed_by[0], r.relayed_by[1], r.relayed_by[2], millis() - r.rxTimeMsec);
|
||||
#endif
|
||||
// TODO: have direct *found entry - can modify directly without local copy _vs_ not convolute the code by this
|
||||
}
|
||||
recentPackets.insert(r);
|
||||
LOG_DEBUG("Add packet record fr=0x%x, id=0x%x", p->from, p->id);
|
||||
}
|
||||
|
||||
// Capacity is reerved, so only purge expired packets if recentPackets fills past 90% capacity
|
||||
// Expiry is normally dealt with after having searched/found a packet (above)
|
||||
if (recentPackets.size() > (MAX_NUM_NODES * 0.9)) {
|
||||
clearExpiredRecentPackets();
|
||||
insert(r); // Insert or update the packet record in the history
|
||||
}
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - Was Seen Recently: @exit s=%08x id=%08x (to=%08x) relby=%02x %02x %02x nxthop=%02x rxT=%d "
|
||||
"found?%s seenRecently?%s wUpd?%s",
|
||||
r.sender, r.id, p->to, r.relayed_by[0], r.relayed_by[1], r.relayed_by[2], r.next_hop, r.rxTimeMsec,
|
||||
found ? "YES" : "NO ", seenRecently ? "YES" : "NO ", withUpdate ? "YES" : "NO ");
|
||||
#endif
|
||||
|
||||
return seenRecently;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all recent packets, and remove all older than FLOOD_EXPIRE_TIME
|
||||
*/
|
||||
void PacketHistory::clearExpiredRecentPackets()
|
||||
/** Find a packet record in history.
|
||||
* @return pointer to PacketRecord if found, NULL if not found */
|
||||
PacketHistory::PacketRecord *PacketHistory::find(NodeNum sender, PacketId id)
|
||||
{
|
||||
LOG_DEBUG("recentPackets size=%ld", recentPackets.size());
|
||||
if (sender == 0 || id == 0) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - find: s=%08x id=%08x sender/id=0->NOT FOUND", sender, id);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (auto it = recentPackets.begin(); it != recentPackets.end();) {
|
||||
if (!Throttle::isWithinTimespanMs(it->rxTimeMsec, FLOOD_EXPIRE_TIME)) {
|
||||
it = recentPackets.erase(it); // erase returns iterator pointing to element immediately following the one erased
|
||||
} else {
|
||||
++it;
|
||||
PacketRecord *it = NULL;
|
||||
for (it = recentPackets; it < (recentPackets + recentPacketsCapacity); ++it) {
|
||||
if (it->id == id && it->sender == sender) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - find: s=%08x id=%08x FOUND nh=%02x rby=%02x %02x %02x age=%d slot=%d/%d", it->sender,
|
||||
it->id, it->next_hop, it->relayed_by[0], it->relayed_by[1], it->relayed_by[2], millis() - (it->rxTimeMsec),
|
||||
it - recentPackets, recentPacketsCapacity);
|
||||
#endif
|
||||
// only the first match is returned, so be careful not to create duplicate entries
|
||||
return it; // Return pointer to the found record
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("recentPackets size=%ld (after clearing expired packets)", recentPackets.size());
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - find: s=%08x id=%08x NOT FOUND", sender, id);
|
||||
#endif
|
||||
return NULL; // Not found
|
||||
}
|
||||
|
||||
/** Insert/Replace oldest PacketRecord in recentPackets. */
|
||||
void PacketHistory::insert(PacketRecord &r)
|
||||
{
|
||||
uint32_t now_millis = millis(); // Should not jump with time changes
|
||||
uint32_t OldtrxTimeMsec = 0;
|
||||
PacketRecord *tu = NULL; // Will insert here.
|
||||
PacketRecord *it = NULL;
|
||||
|
||||
// Find a free, matching or oldest used slot in the recentPackets array
|
||||
for (it = recentPackets; it < (recentPackets + recentPacketsCapacity); ++it) {
|
||||
if (it->id == 0 && it->sender == 0 /*&& rxTimeMsec == 0*/) { // Record is empty
|
||||
tu = it; // Remember the free slot
|
||||
#if VERBOSE_PACKET_HISTORY >= 2
|
||||
LOG_DEBUG("Packet History - insert: Free slot@ %d/%d", tu - recentPackets, recentPacketsCapacity);
|
||||
#endif
|
||||
// We have that, Exit the loop
|
||||
it = (recentPackets + recentPacketsCapacity);
|
||||
} else if (it->id == r.id && it->sender == r.sender) { // Record matches the packet we want to insert
|
||||
tu = it; // Remember the matching slot
|
||||
OldtrxTimeMsec = now_millis - it->rxTimeMsec; // ..and save current entry's age
|
||||
#if VERBOSE_PACKET_HISTORY >= 2
|
||||
LOG_DEBUG("Packet History - insert: Matched slot@ %d/%d age=%d", tu - recentPackets, recentPacketsCapacity,
|
||||
OldtrxTimeMsec);
|
||||
#endif
|
||||
// We have that, Exit the loop
|
||||
it = (recentPackets + recentPacketsCapacity);
|
||||
} else {
|
||||
if (it->rxTimeMsec == 0) {
|
||||
LOG_WARN(
|
||||
"Packet History - insert: Found packet s=%08x id=%08x with rxTimeMsec = 0, slot %d/%d. Should never happen!",
|
||||
it->sender, it->id, it - recentPackets, recentPacketsCapacity);
|
||||
}
|
||||
if ((now_millis - it->rxTimeMsec) > OldtrxTimeMsec) { // 49.7 days rollover friendly
|
||||
OldtrxTimeMsec = now_millis - it->rxTimeMsec;
|
||||
tu = it; // remember the oldest packet
|
||||
#if VERBOSE_PACKET_HISTORY >= 2
|
||||
LOG_DEBUG("Packet History - insert: Older slot@ %d/%d age=%d", tu - recentPackets, recentPacketsCapacity,
|
||||
OldtrxTimeMsec);
|
||||
#endif
|
||||
}
|
||||
// keep looking for oldest till entire array is checked
|
||||
}
|
||||
}
|
||||
|
||||
if (tu == NULL) {
|
||||
LOG_ERROR("Packet History - insert: No free slot, no matched packet, no oldest to reuse. Something leaked."); // mx
|
||||
// assert(false); // This should never happen, we should always have at least one packet to clear
|
||||
return; // Return early if we can't update the history
|
||||
}
|
||||
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
if (tu->id == 0 && tu->sender == 0) {
|
||||
LOG_DEBUG("Packet History - insert: slot@ %d/%d is NEW", tu - recentPackets, recentPacketsCapacity);
|
||||
} else if (tu->id == r.id && tu->sender == r.sender) {
|
||||
LOG_DEBUG("Packet History - insert: slot@ %d/%d MATCHED, age=%d", tu - recentPackets, recentPacketsCapacity,
|
||||
OldtrxTimeMsec);
|
||||
} else {
|
||||
LOG_DEBUG("Packet History - insert: slot@ %d/%d REUSE OLDEST, age=%d", tu - recentPackets, recentPacketsCapacity,
|
||||
OldtrxTimeMsec);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we are reusing a slot, we should warn if the packet is too recent
|
||||
#if RECENT_WARN_AGE > 0
|
||||
if (tu->rxTimeMsec && (OldtrxTimeMsec < RECENT_WARN_AGE)) {
|
||||
if (!(tu->id == r.id && tu->sender == r.sender)) {
|
||||
LOG_WARN("Packet History - insert: Reusing slot aged %ds < %ds RECENT_WARN_AGE", OldtrxTimeMsec / 1000,
|
||||
RECENT_WARN_AGE / 1000);
|
||||
} else {
|
||||
// debug only
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_WARN("Packet History - insert: Reusing slot aged %.3fs < %ds with MATCHED PACKET - this is normal",
|
||||
OldtrxTimeMsec / 1000., RECENT_WARN_AGE / 1000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if PACKET_HISTORY_TRACE_AGING
|
||||
if (tu->rxTimeMsec != 0) {
|
||||
LOG_INFO("Packet History - insert: Reusing slot aged %.3fs TRACE %s", OldtrxTimeMsec / 1000.,
|
||||
(tu->id == r.id && tu->sender == r.sender) ? "MATCHED PACKET" : "OLDEST SLOT");
|
||||
} else {
|
||||
LOG_INFO("Packet History - insert: Using new slot @uptime %.3fs TRACE NEW", millis() / 1000.);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - insert: Store slot@ %d/%d s=%08x id=%08x nh=%02x rby=%02x %02x %02x rxT=%d BEFORE",
|
||||
tu - recentPackets, recentPacketsCapacity, tu->sender, tu->id, tu->next_hop, tu->relayed_by[0], tu->relayed_by[1],
|
||||
tu->relayed_by[2], tu->rxTimeMsec);
|
||||
#endif
|
||||
|
||||
if (r.rxTimeMsec == 0) {
|
||||
LOG_WARN("Packet History - insert: I will not store packet with rxTimeMsec = 0.");
|
||||
return; // Return early if we can't update the history
|
||||
}
|
||||
|
||||
*tu = r; // store the packet
|
||||
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - insert: Store slot@ %d/%d s=%08x id=%08x nh=%02x rby=%02x %02x %02x rxT=%d AFTER",
|
||||
tu - recentPackets, recentPacketsCapacity, tu->sender, tu->id, tu->next_hop, tu->relayed_by[0], tu->relayed_by[1],
|
||||
tu->relayed_by[2], tu->rxTimeMsec);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given an ID and sender
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender)
|
||||
{
|
||||
if (relayer == 0)
|
||||
return false;
|
||||
|
||||
PacketRecord r = {.sender = sender, .id = id, .rxTimeMsec = 0, .next_hop = 0};
|
||||
auto found = recentPackets.find(r);
|
||||
|
||||
if (found == recentPackets.end()) {
|
||||
if (!initOk()) {
|
||||
LOG_ERROR("PacketHistory - wasRelayer: NOT INITIALIZED!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return wasRelayer(relayer, found);
|
||||
if (relayer == 0) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - was relayer: s=%08x id=%08x / rl=%02x=zero. NO", sender, id, relayer);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
PacketRecord *found = find(sender, id);
|
||||
|
||||
if (found == NULL) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - was relayer: s=%08x id=%08x / rl=%02x / PR not found. NO", sender, id, relayer);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if VERBOSE_PACKET_HISTORY >= 2
|
||||
LOG_DEBUG("Packet History - was relayer: s=%08x id=%08x nh=%02x age=%d rls=%02x %02x %02x InHistory,check:%02x",
|
||||
found->sender, found->id, found->next_hop, millis() - found->rxTimeMsec, found->relayed_by[0], found->relayed_by[1],
|
||||
found->relayed_by[2], relayer);
|
||||
#endif
|
||||
return wasRelayer(relayer, *found);
|
||||
}
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, std::unordered_set<PacketRecord, PacketRecordHashFunction>::iterator r)
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, PacketRecord &r)
|
||||
{
|
||||
for (uint8_t i = 0; i < NUM_RELAYERS; i++) {
|
||||
if (r->relayed_by[i] == relayer) {
|
||||
if (r.relayed_by[i] == relayer) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - was rel.PR.: s=%08x id=%08x rls=%02x %02x %02x / rl=%02x? YES", r.sender, r.id,
|
||||
r.relayed_by[0], r.relayed_by[1], r.relayed_by[2], relayer);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - was rel.PR.: s=%08x id=%08x rls=%02x %02x %02x / rl=%02x? NO", r.sender, r.id, r.relayed_by[0],
|
||||
r.relayed_by[1], r.relayed_by[2], relayer);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove a relayer from the list of relayers of a packet in the history given an ID and sender
|
||||
void PacketHistory::removeRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender)
|
||||
{
|
||||
PacketRecord r = {.sender = sender, .id = id, .rxTimeMsec = 0, .next_hop = 0};
|
||||
auto found = recentPackets.find(r);
|
||||
|
||||
if (found == recentPackets.end()) {
|
||||
if (!initOk()) {
|
||||
LOG_ERROR("Packet History - remove Relayer: NOT INITIALIZED!");
|
||||
return;
|
||||
}
|
||||
// Make a copy of the found record
|
||||
r.next_hop = found->next_hop;
|
||||
r.rxTimeMsec = found->rxTimeMsec;
|
||||
|
||||
// Only add the relayers that are not the one we want to remove
|
||||
uint8_t j = 0;
|
||||
for (uint8_t i = 0; i < NUM_RELAYERS; i++) {
|
||||
if (found->relayed_by[i] != relayer) {
|
||||
r.relayed_by[j] = found->relayed_by[i];
|
||||
j++;
|
||||
}
|
||||
PacketRecord *found = find(sender, id);
|
||||
if (found == NULL) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - remove Relayer s=%08x id=%08x (rl=%02x) NOT FOUND", sender, id, relayer);
|
||||
#endif
|
||||
return; // Nothing to remove
|
||||
}
|
||||
|
||||
recentPackets.erase(found);
|
||||
recentPackets.insert(r);
|
||||
}
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - remove Relayer s=%08x id=%08x rby=%02x %02x %02x, rl:%02x BEFORE", found->sender, found->id,
|
||||
found->relayed_by[0], found->relayed_by[1], found->relayed_by[2], relayer);
|
||||
#endif
|
||||
|
||||
// nexthop and rxTimeMsec too stay in found entry
|
||||
|
||||
uint8_t j = 0;
|
||||
uint8_t i = 0;
|
||||
for (; i < NUM_RELAYERS; i++) {
|
||||
if (found->relayed_by[i] != relayer) {
|
||||
found->relayed_by[j] = found->relayed_by[i];
|
||||
j++;
|
||||
} else
|
||||
found->relayed_by[i] = 0;
|
||||
}
|
||||
for (; j < NUM_RELAYERS; j++) { // Clear the rest of the relayed_by array
|
||||
found->relayed_by[j] = 0;
|
||||
}
|
||||
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
LOG_DEBUG("Packet History - remove Relayer s=%08x id=%08x rby=%02x %02x %02x rl:%02x AFTER - removed?%d", found->sender,
|
||||
found->id, found->relayed_by[0], found->relayed_by[1], found->relayed_by[2], relayer, i != j);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,49 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "NodeDB.h"
|
||||
#include <unordered_set>
|
||||
|
||||
/// We clear our old flood record 10 minutes after we see the last of it
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
#define FLOOD_EXPIRE_TIME (5 * 1000L) // Don't allow too many packets to accumulate when fuzzing.
|
||||
#else
|
||||
#define FLOOD_EXPIRE_TIME (10 * 60 * 1000L)
|
||||
#endif
|
||||
|
||||
#define NUM_RELAYERS \
|
||||
3 // Number of relayer we keep track of. Use 3 to be efficient with memory alignment of PacketRecord to 16 bytes
|
||||
|
||||
/**
|
||||
* A record of a recent message broadcast
|
||||
*/
|
||||
struct PacketRecord {
|
||||
NodeNum sender;
|
||||
PacketId id;
|
||||
uint32_t rxTimeMsec; // Unix time in msecs - the time we received it
|
||||
uint8_t next_hop; // The next hop asked for this packet
|
||||
uint8_t relayed_by[NUM_RELAYERS]; // Array of nodes that relayed this packet
|
||||
|
||||
bool operator==(const PacketRecord &p) const { return sender == p.sender && id == p.id; }
|
||||
};
|
||||
|
||||
class PacketRecordHashFunction
|
||||
{
|
||||
public:
|
||||
size_t operator()(const PacketRecord &p) const { return (std::hash<NodeNum>()(p.sender)) ^ (std::hash<PacketId>()(p.id)); }
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a mixin that adds a record of past packets we have seen
|
||||
*/
|
||||
class PacketHistory
|
||||
{
|
||||
private:
|
||||
std::unordered_set<PacketRecord, PacketRecordHashFunction> recentPackets;
|
||||
struct PacketRecord { // A record of a recent message broadcast, no need to be visible outside this class.
|
||||
NodeNum sender;
|
||||
PacketId id;
|
||||
uint32_t rxTimeMsec; // Unix time in msecs - the time we received it, 0 means empty
|
||||
uint8_t next_hop; // The next hop asked for this packet
|
||||
uint8_t relayed_by[NUM_RELAYERS]; // Array of nodes that relayed this packet
|
||||
}; // 4B + 4B + 4B + 1B + 3B = 16B
|
||||
|
||||
void clearExpiredRecentPackets(); // clear all recentPackets older than FLOOD_EXPIRE_TIME
|
||||
uint32_t recentPacketsCapacity =
|
||||
0; // Can be set in constructor, no need to recompile. Used to allocate memory for mx_recentPackets.
|
||||
PacketRecord *recentPackets = NULL; // Simple and fixed in size. Debloat.
|
||||
|
||||
/** Find a packet record in history.
|
||||
* @param sender NodeNum
|
||||
* @param id PacketId
|
||||
* @return pointer to PacketRecord if found, NULL if not found */
|
||||
PacketRecord *find(NodeNum sender, PacketId id);
|
||||
|
||||
/** Insert/Replace oldest PacketRecord in mx_recentPackets.
|
||||
* @param r PacketRecord to insert or replace */
|
||||
void insert(PacketRecord &r); // Insert or replace a packet record in the history
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool wasRelayer(const uint8_t relayer, PacketRecord &r);
|
||||
|
||||
PacketHistory(const PacketHistory &); // non construction-copyable
|
||||
PacketHistory &operator=(const PacketHistory &); // non copyable
|
||||
public:
|
||||
PacketHistory();
|
||||
explicit PacketHistory(uint32_t size = -1); // Constructor with size parameter, default is PACKETHISTORY_MAX
|
||||
~PacketHistory();
|
||||
|
||||
/**
|
||||
* Update recentBroadcasts and return true if we have already seen this packet
|
||||
@@ -59,10 +57,9 @@ class PacketHistory
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool wasRelayer(const uint8_t relayer, std::unordered_set<PacketRecord, PacketRecordHashFunction>::iterator r);
|
||||
|
||||
// Remove a relayer from the list of relayers of a packet in the history given an ID and sender
|
||||
void removeRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
||||
};
|
||||
|
||||
// To check if the PacketHistory was initialized correctly by constructor
|
||||
bool initOk(void) { return recentPackets != NULL && recentPacketsCapacity != 0; }
|
||||
};
|
||||
|
||||
@@ -548,6 +548,20 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
|
||||
numbytes += MESHTASTIC_PKC_OVERHEAD;
|
||||
p->channel = 0;
|
||||
p->pki_encrypted = true;
|
||||
|
||||
// warn the user about a low entropy key
|
||||
if (nodeDB->keyIsLowEntropy) {
|
||||
LOG_WARN(LOW_ENTROPY_WARNING);
|
||||
if (!nodeDB->hasWarned) {
|
||||
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
|
||||
cn->which_payload_variant = meshtastic_ClientNotification_low_entropy_key_tag;
|
||||
cn->level = meshtastic_LogRecord_Level_WARNING;
|
||||
cn->time = getValidTime(RTCQualityFromNet);
|
||||
sprintf(cn->message, LOW_ENTROPY_WARNING);
|
||||
service->sendClientNotification(cn);
|
||||
nodeDB->hasWarned = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (p->pki_encrypted == true) {
|
||||
// Client specifically requested PKI encryption
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
PB_BIND(meshtastic_AdminMessage, meshtastic_AdminMessage, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_AdminMessage_InputEvent, meshtastic_AdminMessage_InputEvent, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_HamParameters, meshtastic_HamParameters, AUTO)
|
||||
|
||||
|
||||
|
||||
@@ -91,6 +91,18 @@ typedef enum _meshtastic_KeyVerificationAdmin_MessageType {
|
||||
} meshtastic_KeyVerificationAdmin_MessageType;
|
||||
|
||||
/* Struct definitions */
|
||||
/* Input event message to be sent to the node. */
|
||||
typedef struct _meshtastic_AdminMessage_InputEvent {
|
||||
/* The input event code */
|
||||
uint8_t event_code;
|
||||
/* Keyboard character code */
|
||||
uint8_t kb_char;
|
||||
/* The touch X coordinate */
|
||||
uint16_t touch_x;
|
||||
/* The touch Y coordinate */
|
||||
uint16_t touch_y;
|
||||
} meshtastic_AdminMessage_InputEvent;
|
||||
|
||||
/* Parameters for setting up Meshtastic for ameteur radio usage */
|
||||
typedef struct _meshtastic_HamParameters {
|
||||
/* Amateur radio call sign, eg. KD2ABC */
|
||||
@@ -118,6 +130,8 @@ typedef struct _meshtastic_SharedContact {
|
||||
/* The User of the contact */
|
||||
bool has_user;
|
||||
meshtastic_User user;
|
||||
/* Add this contact to the blocked / ignored list */
|
||||
bool should_ignore;
|
||||
} meshtastic_SharedContact;
|
||||
|
||||
/* This message is used by a client to initiate or complete a key verification */
|
||||
@@ -191,6 +205,9 @@ typedef struct _meshtastic_AdminMessage {
|
||||
meshtastic_AdminMessage_BackupLocation restore_preferences;
|
||||
/* Remove backups of the node's preferences */
|
||||
meshtastic_AdminMessage_BackupLocation remove_backup_preferences;
|
||||
/* Send an input event to the node.
|
||||
This is used to trigger physical input events like button presses, touch events, etc. */
|
||||
meshtastic_AdminMessage_InputEvent send_input_event;
|
||||
/* Set the owner for this node */
|
||||
meshtastic_User set_owner;
|
||||
/* Set channels (using the new API).
|
||||
@@ -293,22 +310,29 @@ extern "C" {
|
||||
|
||||
|
||||
|
||||
|
||||
#define meshtastic_KeyVerificationAdmin_message_type_ENUMTYPE meshtastic_KeyVerificationAdmin_MessageType
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_AdminMessage_init_default {0, {0}, {0, {0}}}
|
||||
#define meshtastic_AdminMessage_InputEvent_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_HamParameters_init_default {"", 0, 0, ""}
|
||||
#define meshtastic_NodeRemoteHardwarePinsResponse_init_default {0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}}
|
||||
#define meshtastic_SharedContact_init_default {0, false, meshtastic_User_init_default}
|
||||
#define meshtastic_SharedContact_init_default {0, false, meshtastic_User_init_default, 0}
|
||||
#define meshtastic_KeyVerificationAdmin_init_default {_meshtastic_KeyVerificationAdmin_MessageType_MIN, 0, 0, false, 0}
|
||||
#define meshtastic_AdminMessage_init_zero {0, {0}, {0, {0}}}
|
||||
#define meshtastic_AdminMessage_InputEvent_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_HamParameters_init_zero {"", 0, 0, ""}
|
||||
#define meshtastic_NodeRemoteHardwarePinsResponse_init_zero {0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}}
|
||||
#define meshtastic_SharedContact_init_zero {0, false, meshtastic_User_init_zero}
|
||||
#define meshtastic_SharedContact_init_zero {0, false, meshtastic_User_init_zero, 0}
|
||||
#define meshtastic_KeyVerificationAdmin_init_zero {_meshtastic_KeyVerificationAdmin_MessageType_MIN, 0, 0, false, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_AdminMessage_InputEvent_event_code_tag 1
|
||||
#define meshtastic_AdminMessage_InputEvent_kb_char_tag 2
|
||||
#define meshtastic_AdminMessage_InputEvent_touch_x_tag 3
|
||||
#define meshtastic_AdminMessage_InputEvent_touch_y_tag 4
|
||||
#define meshtastic_HamParameters_call_sign_tag 1
|
||||
#define meshtastic_HamParameters_tx_power_tag 2
|
||||
#define meshtastic_HamParameters_frequency_tag 3
|
||||
@@ -316,6 +340,7 @@ extern "C" {
|
||||
#define meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_tag 1
|
||||
#define meshtastic_SharedContact_node_num_tag 1
|
||||
#define meshtastic_SharedContact_user_tag 2
|
||||
#define meshtastic_SharedContact_should_ignore_tag 3
|
||||
#define meshtastic_KeyVerificationAdmin_message_type_tag 1
|
||||
#define meshtastic_KeyVerificationAdmin_remote_nodenum_tag 2
|
||||
#define meshtastic_KeyVerificationAdmin_nonce_tag 3
|
||||
@@ -345,6 +370,7 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_backup_preferences_tag 24
|
||||
#define meshtastic_AdminMessage_restore_preferences_tag 25
|
||||
#define meshtastic_AdminMessage_remove_backup_preferences_tag 26
|
||||
#define meshtastic_AdminMessage_send_input_event_tag 27
|
||||
#define meshtastic_AdminMessage_set_owner_tag 32
|
||||
#define meshtastic_AdminMessage_set_channel_tag 33
|
||||
#define meshtastic_AdminMessage_set_config_tag 34
|
||||
@@ -402,6 +428,7 @@ X(a, STATIC, ONEOF, UINT32, (payload_variant,set_scale,set_scale), 23) \
|
||||
X(a, STATIC, ONEOF, UENUM, (payload_variant,backup_preferences,backup_preferences), 24) \
|
||||
X(a, STATIC, ONEOF, UENUM, (payload_variant,restore_preferences,restore_preferences), 25) \
|
||||
X(a, STATIC, ONEOF, UENUM, (payload_variant,remove_backup_preferences,remove_backup_preferences), 26) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,send_input_event,send_input_event), 27) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \
|
||||
@@ -441,6 +468,7 @@ X(a, STATIC, SINGULAR, BYTES, session_passkey, 101)
|
||||
#define meshtastic_AdminMessage_payload_variant_get_device_connection_status_response_MSGTYPE meshtastic_DeviceConnectionStatus
|
||||
#define meshtastic_AdminMessage_payload_variant_set_ham_mode_MSGTYPE meshtastic_HamParameters
|
||||
#define meshtastic_AdminMessage_payload_variant_get_node_remote_hardware_pins_response_MSGTYPE meshtastic_NodeRemoteHardwarePinsResponse
|
||||
#define meshtastic_AdminMessage_payload_variant_send_input_event_MSGTYPE meshtastic_AdminMessage_InputEvent
|
||||
#define meshtastic_AdminMessage_payload_variant_set_owner_MSGTYPE meshtastic_User
|
||||
#define meshtastic_AdminMessage_payload_variant_set_channel_MSGTYPE meshtastic_Channel
|
||||
#define meshtastic_AdminMessage_payload_variant_set_config_MSGTYPE meshtastic_Config
|
||||
@@ -451,6 +479,14 @@ X(a, STATIC, SINGULAR, BYTES, session_passkey, 101)
|
||||
#define meshtastic_AdminMessage_payload_variant_add_contact_MSGTYPE meshtastic_SharedContact
|
||||
#define meshtastic_AdminMessage_payload_variant_key_verification_MSGTYPE meshtastic_KeyVerificationAdmin
|
||||
|
||||
#define meshtastic_AdminMessage_InputEvent_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, event_code, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, kb_char, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, touch_x, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, touch_y, 4)
|
||||
#define meshtastic_AdminMessage_InputEvent_CALLBACK NULL
|
||||
#define meshtastic_AdminMessage_InputEvent_DEFAULT NULL
|
||||
|
||||
#define meshtastic_HamParameters_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, call_sign, 1) \
|
||||
X(a, STATIC, SINGULAR, INT32, tx_power, 2) \
|
||||
@@ -467,7 +503,8 @@ X(a, STATIC, REPEATED, MESSAGE, node_remote_hardware_pins, 1)
|
||||
|
||||
#define meshtastic_SharedContact_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, node_num, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, user, 2)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, should_ignore, 3)
|
||||
#define meshtastic_SharedContact_CALLBACK NULL
|
||||
#define meshtastic_SharedContact_DEFAULT NULL
|
||||
#define meshtastic_SharedContact_user_MSGTYPE meshtastic_User
|
||||
@@ -481,6 +518,7 @@ X(a, STATIC, OPTIONAL, UINT32, security_number, 4)
|
||||
#define meshtastic_KeyVerificationAdmin_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_AdminMessage_msg;
|
||||
extern const pb_msgdesc_t meshtastic_AdminMessage_InputEvent_msg;
|
||||
extern const pb_msgdesc_t meshtastic_HamParameters_msg;
|
||||
extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePinsResponse_msg;
|
||||
extern const pb_msgdesc_t meshtastic_SharedContact_msg;
|
||||
@@ -488,6 +526,7 @@ extern const pb_msgdesc_t meshtastic_KeyVerificationAdmin_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg
|
||||
#define meshtastic_AdminMessage_InputEvent_fields &meshtastic_AdminMessage_InputEvent_msg
|
||||
#define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg
|
||||
#define meshtastic_NodeRemoteHardwarePinsResponse_fields &meshtastic_NodeRemoteHardwarePinsResponse_msg
|
||||
#define meshtastic_SharedContact_fields &meshtastic_SharedContact_msg
|
||||
@@ -495,11 +534,12 @@ extern const pb_msgdesc_t meshtastic_KeyVerificationAdmin_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_ADMIN_PB_H_MAX_SIZE meshtastic_AdminMessage_size
|
||||
#define meshtastic_AdminMessage_InputEvent_size 14
|
||||
#define meshtastic_AdminMessage_size 511
|
||||
#define meshtastic_HamParameters_size 31
|
||||
#define meshtastic_KeyVerificationAdmin_size 25
|
||||
#define meshtastic_NodeRemoteHardwarePinsResponse_size 496
|
||||
#define meshtastic_SharedContact_size 123
|
||||
#define meshtastic_SharedContact_size 125
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -65,6 +65,8 @@ PB_BIND(meshtastic_Config_SessionkeyConfig, meshtastic_Config_SessionkeyConfig,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -88,6 +88,23 @@ typedef enum _meshtastic_Config_DeviceConfig_RebroadcastMode {
|
||||
meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY = 5
|
||||
} meshtastic_Config_DeviceConfig_RebroadcastMode;
|
||||
|
||||
/* Defines buzzer behavior for audio feedback */
|
||||
typedef enum _meshtastic_Config_DeviceConfig_BuzzerMode {
|
||||
/* Default behavior.
|
||||
Buzzer is enabled for all audio feedback including button presses and alerts. */
|
||||
meshtastic_Config_DeviceConfig_BuzzerMode_ALL_ENABLED = 0,
|
||||
/* Disabled.
|
||||
All buzzer audio feedback is disabled. */
|
||||
meshtastic_Config_DeviceConfig_BuzzerMode_DISABLED = 1,
|
||||
/* Notifications Only.
|
||||
Buzzer is enabled only for notifications and alerts, but not for button presses.
|
||||
External notification config determines the specifics of the notification behavior. */
|
||||
meshtastic_Config_DeviceConfig_BuzzerMode_NOTIFICATIONS_ONLY = 2,
|
||||
/* Non-notification system buzzer tones only.
|
||||
Buzzer is enabled only for non-notification tones such as button presses, startup, shutdown, but not for alerts. */
|
||||
meshtastic_Config_DeviceConfig_BuzzerMode_SYSTEM_ONLY = 3
|
||||
} meshtastic_Config_DeviceConfig_BuzzerMode;
|
||||
|
||||
/* Bit field of boolean configuration options, indicating which optional
|
||||
fields to include when assembling POSITION messages.
|
||||
Longitude, latitude, altitude, speed, heading, and DOP
|
||||
@@ -266,7 +283,9 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
|
||||
/* Philippines 868mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_PH_868 = 20,
|
||||
/* Philippines 915mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_PH_915 = 21
|
||||
meshtastic_Config_LoRaConfig_RegionCode_PH_915 = 21,
|
||||
/* Australia / New Zealand 433MHz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_ANZ_433 = 22
|
||||
} meshtastic_Config_LoRaConfig_RegionCode;
|
||||
|
||||
/* Standard predefined channel settings
|
||||
@@ -335,6 +354,9 @@ typedef struct _meshtastic_Config_DeviceConfig {
|
||||
char tzdef[65];
|
||||
/* If true, disable the default blinking LED (LED_PIN) behavior on the device */
|
||||
bool led_heartbeat_disabled;
|
||||
/* Controls buzzer behavior for audio feedback
|
||||
Defaults to ENABLED */
|
||||
meshtastic_Config_DeviceConfig_BuzzerMode buzzer_mode;
|
||||
} meshtastic_Config_DeviceConfig;
|
||||
|
||||
/* Position Config */
|
||||
@@ -618,6 +640,10 @@ extern "C" {
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY+1))
|
||||
|
||||
#define _meshtastic_Config_DeviceConfig_BuzzerMode_MIN meshtastic_Config_DeviceConfig_BuzzerMode_ALL_ENABLED
|
||||
#define _meshtastic_Config_DeviceConfig_BuzzerMode_MAX meshtastic_Config_DeviceConfig_BuzzerMode_SYSTEM_ONLY
|
||||
#define _meshtastic_Config_DeviceConfig_BuzzerMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_BuzzerMode)(meshtastic_Config_DeviceConfig_BuzzerMode_SYSTEM_ONLY+1))
|
||||
|
||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MIN meshtastic_Config_PositionConfig_PositionFlags_UNSET
|
||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED
|
||||
#define _meshtastic_Config_PositionConfig_PositionFlags_ARRAYSIZE ((meshtastic_Config_PositionConfig_PositionFlags)(meshtastic_Config_PositionConfig_PositionFlags_SPEED+1))
|
||||
@@ -655,8 +681,8 @@ extern "C" {
|
||||
#define _meshtastic_Config_DisplayConfig_CompassOrientation_ARRAYSIZE ((meshtastic_Config_DisplayConfig_CompassOrientation)(meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED+1))
|
||||
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_PH_915
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_PH_915+1))
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_ANZ_433
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_ANZ_433+1))
|
||||
|
||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
|
||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO
|
||||
@@ -669,6 +695,7 @@ extern "C" {
|
||||
|
||||
#define meshtastic_Config_DeviceConfig_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
|
||||
#define meshtastic_Config_DeviceConfig_rebroadcast_mode_ENUMTYPE meshtastic_Config_DeviceConfig_RebroadcastMode
|
||||
#define meshtastic_Config_DeviceConfig_buzzer_mode_ENUMTYPE meshtastic_Config_DeviceConfig_BuzzerMode
|
||||
|
||||
#define meshtastic_Config_PositionConfig_gps_mode_ENUMTYPE meshtastic_Config_PositionConfig_GpsMode
|
||||
|
||||
@@ -692,7 +719,7 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0, _meshtastic_Config_DeviceConfig_BuzzerMode_MIN}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0, 0}
|
||||
@@ -703,7 +730,7 @@ extern "C" {
|
||||
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_SessionkeyConfig_init_default {0}
|
||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0, _meshtastic_Config_DeviceConfig_BuzzerMode_MIN}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0, 0}
|
||||
@@ -726,6 +753,7 @@ extern "C" {
|
||||
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
|
||||
#define meshtastic_Config_DeviceConfig_tzdef_tag 11
|
||||
#define meshtastic_Config_DeviceConfig_led_heartbeat_disabled_tag 12
|
||||
#define meshtastic_Config_DeviceConfig_buzzer_mode_tag 13
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
|
||||
#define meshtastic_Config_PositionConfig_fixed_position_tag 3
|
||||
@@ -849,7 +877,8 @@ X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \
|
||||
X(a, STATIC, SINGULAR, STRING, tzdef, 11) \
|
||||
X(a, STATIC, SINGULAR, BOOL, led_heartbeat_disabled, 12)
|
||||
X(a, STATIC, SINGULAR, BOOL, led_heartbeat_disabled, 12) \
|
||||
X(a, STATIC, SINGULAR, UENUM, buzzer_mode, 13)
|
||||
#define meshtastic_Config_DeviceConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_DeviceConfig_DEFAULT NULL
|
||||
|
||||
@@ -995,7 +1024,7 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg;
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
|
||||
#define meshtastic_Config_BluetoothConfig_size 10
|
||||
#define meshtastic_Config_DeviceConfig_size 98
|
||||
#define meshtastic_Config_DeviceConfig_size 100
|
||||
#define meshtastic_Config_DisplayConfig_size 32
|
||||
#define meshtastic_Config_LoRaConfig_size 85
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
|
||||
@@ -55,6 +55,8 @@ typedef enum _meshtastic_Language {
|
||||
meshtastic_Language_SLOVENIAN = 15,
|
||||
/* Ukrainian */
|
||||
meshtastic_Language_UKRAINIAN = 16,
|
||||
/* Bulgarian */
|
||||
meshtastic_Language_BULGARIAN = 17,
|
||||
/* Simplified Chinese (experimental) */
|
||||
meshtastic_Language_SIMPLIFIED_CHINESE = 30,
|
||||
/* Traditional Chinese (experimental) */
|
||||
|
||||
@@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* meshtastic_NodeDatabase_size depends on runtime parameters */
|
||||
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
|
||||
#define meshtastic_BackupPreferences_size 2269
|
||||
#define meshtastic_BackupPreferences_size 2271
|
||||
#define meshtastic_ChannelFile_size 718
|
||||
#define meshtastic_DeviceState_size 1722
|
||||
#define meshtastic_NodeInfoLite_size 196
|
||||
|
||||
@@ -187,7 +187,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size
|
||||
#define meshtastic_LocalConfig_size 745
|
||||
#define meshtastic_LocalConfig_size 747
|
||||
#define meshtastic_LocalModuleConfig_size 669
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -60,6 +60,12 @@ PB_BIND(meshtastic_KeyVerificationNumberRequest, meshtastic_KeyVerificationNumbe
|
||||
PB_BIND(meshtastic_KeyVerificationFinal, meshtastic_KeyVerificationFinal, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_DuplicatedPublicKey, meshtastic_DuplicatedPublicKey, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_LowEntropyKey, meshtastic_LowEntropyKey, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_FileInfo, meshtastic_FileInfo, AUTO)
|
||||
|
||||
|
||||
|
||||
@@ -258,6 +258,15 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1_EINK = 100,
|
||||
/* Reserved ID for future and past use */
|
||||
meshtastic_HardwareModel_QWANTZ_TINY_ARMS = 101,
|
||||
/* *
|
||||
Lilygo T-Deck Pro */
|
||||
meshtastic_HardwareModel_T_DECK_PRO = 102,
|
||||
/* *
|
||||
Lilygo TLora Pager */
|
||||
meshtastic_HardwareModel_T_LORA_PAGER = 103,
|
||||
/* *
|
||||
GAT562 Mesh Trial Tracker */
|
||||
meshtastic_HardwareModel_GAT562_MESH_TRIAL_TRACKER = 104,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
@@ -949,6 +958,14 @@ typedef struct _meshtastic_KeyVerificationFinal {
|
||||
char verification_characters[10];
|
||||
} meshtastic_KeyVerificationFinal;
|
||||
|
||||
typedef struct _meshtastic_DuplicatedPublicKey {
|
||||
char dummy_field;
|
||||
} meshtastic_DuplicatedPublicKey;
|
||||
|
||||
typedef struct _meshtastic_LowEntropyKey {
|
||||
char dummy_field;
|
||||
} meshtastic_LowEntropyKey;
|
||||
|
||||
/* A notification message from the device to the client
|
||||
To be used for important messages that should to be displayed to the user
|
||||
in the form of push notifications or validation messages when saving
|
||||
@@ -968,6 +985,8 @@ typedef struct _meshtastic_ClientNotification {
|
||||
meshtastic_KeyVerificationNumberInform key_verification_number_inform;
|
||||
meshtastic_KeyVerificationNumberRequest key_verification_number_request;
|
||||
meshtastic_KeyVerificationFinal key_verification_final;
|
||||
meshtastic_DuplicatedPublicKey duplicated_public_key;
|
||||
meshtastic_LowEntropyKey low_entropy_key;
|
||||
} payload_variant;
|
||||
} meshtastic_ClientNotification;
|
||||
|
||||
@@ -1248,6 +1267,8 @@ extern "C" {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
|
||||
|
||||
|
||||
@@ -1280,6 +1301,8 @@ extern "C" {
|
||||
#define meshtastic_KeyVerificationNumberInform_init_default {0, "", 0}
|
||||
#define meshtastic_KeyVerificationNumberRequest_init_default {0, ""}
|
||||
#define meshtastic_KeyVerificationFinal_init_default {0, "", 0, ""}
|
||||
#define meshtastic_DuplicatedPublicKey_init_default {0}
|
||||
#define meshtastic_LowEntropyKey_init_default {0}
|
||||
#define meshtastic_FileInfo_init_default {"", 0}
|
||||
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
|
||||
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||
@@ -1309,6 +1332,8 @@ extern "C" {
|
||||
#define meshtastic_KeyVerificationNumberInform_init_zero {0, "", 0}
|
||||
#define meshtastic_KeyVerificationNumberRequest_init_zero {0, ""}
|
||||
#define meshtastic_KeyVerificationFinal_init_zero {0, "", 0, ""}
|
||||
#define meshtastic_DuplicatedPublicKey_init_zero {0}
|
||||
#define meshtastic_LowEntropyKey_init_zero {0}
|
||||
#define meshtastic_FileInfo_init_zero {"", 0}
|
||||
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
|
||||
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||
@@ -1446,6 +1471,8 @@ extern "C" {
|
||||
#define meshtastic_ClientNotification_key_verification_number_inform_tag 11
|
||||
#define meshtastic_ClientNotification_key_verification_number_request_tag 12
|
||||
#define meshtastic_ClientNotification_key_verification_final_tag 13
|
||||
#define meshtastic_ClientNotification_duplicated_public_key_tag 14
|
||||
#define meshtastic_ClientNotification_low_entropy_key_tag 15
|
||||
#define meshtastic_FileInfo_file_name_tag 1
|
||||
#define meshtastic_FileInfo_size_bytes_tag 2
|
||||
#define meshtastic_Compressed_portnum_tag 1
|
||||
@@ -1714,12 +1741,16 @@ X(a, STATIC, SINGULAR, UENUM, level, 3) \
|
||||
X(a, STATIC, SINGULAR, STRING, message, 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_number_inform,payload_variant.key_verification_number_inform), 11) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_number_request,payload_variant.key_verification_number_request), 12) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_final,payload_variant.key_verification_final), 13)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_final,payload_variant.key_verification_final), 13) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,duplicated_public_key,payload_variant.duplicated_public_key), 14) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,low_entropy_key,payload_variant.low_entropy_key), 15)
|
||||
#define meshtastic_ClientNotification_CALLBACK NULL
|
||||
#define meshtastic_ClientNotification_DEFAULT NULL
|
||||
#define meshtastic_ClientNotification_payload_variant_key_verification_number_inform_MSGTYPE meshtastic_KeyVerificationNumberInform
|
||||
#define meshtastic_ClientNotification_payload_variant_key_verification_number_request_MSGTYPE meshtastic_KeyVerificationNumberRequest
|
||||
#define meshtastic_ClientNotification_payload_variant_key_verification_final_MSGTYPE meshtastic_KeyVerificationFinal
|
||||
#define meshtastic_ClientNotification_payload_variant_duplicated_public_key_MSGTYPE meshtastic_DuplicatedPublicKey
|
||||
#define meshtastic_ClientNotification_payload_variant_low_entropy_key_MSGTYPE meshtastic_LowEntropyKey
|
||||
|
||||
#define meshtastic_KeyVerificationNumberInform_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT64, nonce, 1) \
|
||||
@@ -1742,6 +1773,16 @@ X(a, STATIC, SINGULAR, STRING, verification_characters, 4)
|
||||
#define meshtastic_KeyVerificationFinal_CALLBACK NULL
|
||||
#define meshtastic_KeyVerificationFinal_DEFAULT NULL
|
||||
|
||||
#define meshtastic_DuplicatedPublicKey_FIELDLIST(X, a) \
|
||||
|
||||
#define meshtastic_DuplicatedPublicKey_CALLBACK NULL
|
||||
#define meshtastic_DuplicatedPublicKey_DEFAULT NULL
|
||||
|
||||
#define meshtastic_LowEntropyKey_FIELDLIST(X, a) \
|
||||
|
||||
#define meshtastic_LowEntropyKey_CALLBACK NULL
|
||||
#define meshtastic_LowEntropyKey_DEFAULT NULL
|
||||
|
||||
#define meshtastic_FileInfo_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, file_name, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, size_bytes, 2)
|
||||
@@ -1853,6 +1894,8 @@ extern const pb_msgdesc_t meshtastic_ClientNotification_msg;
|
||||
extern const pb_msgdesc_t meshtastic_KeyVerificationNumberInform_msg;
|
||||
extern const pb_msgdesc_t meshtastic_KeyVerificationNumberRequest_msg;
|
||||
extern const pb_msgdesc_t meshtastic_KeyVerificationFinal_msg;
|
||||
extern const pb_msgdesc_t meshtastic_DuplicatedPublicKey_msg;
|
||||
extern const pb_msgdesc_t meshtastic_LowEntropyKey_msg;
|
||||
extern const pb_msgdesc_t meshtastic_FileInfo_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ToRadio_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Compressed_msg;
|
||||
@@ -1884,6 +1927,8 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
||||
#define meshtastic_KeyVerificationNumberInform_fields &meshtastic_KeyVerificationNumberInform_msg
|
||||
#define meshtastic_KeyVerificationNumberRequest_fields &meshtastic_KeyVerificationNumberRequest_msg
|
||||
#define meshtastic_KeyVerificationFinal_fields &meshtastic_KeyVerificationFinal_msg
|
||||
#define meshtastic_DuplicatedPublicKey_fields &meshtastic_DuplicatedPublicKey_msg
|
||||
#define meshtastic_LowEntropyKey_fields &meshtastic_LowEntropyKey_msg
|
||||
#define meshtastic_FileInfo_fields &meshtastic_FileInfo_msg
|
||||
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
|
||||
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg
|
||||
@@ -1905,6 +1950,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
||||
#define meshtastic_Compressed_size 239
|
||||
#define meshtastic_Data_size 269
|
||||
#define meshtastic_DeviceMetadata_size 54
|
||||
#define meshtastic_DuplicatedPublicKey_size 0
|
||||
#define meshtastic_FileInfo_size 236
|
||||
#define meshtastic_FromRadio_size 510
|
||||
#define meshtastic_Heartbeat_size 0
|
||||
@@ -1913,6 +1959,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
||||
#define meshtastic_KeyVerificationNumberRequest_size 52
|
||||
#define meshtastic_KeyVerification_size 79
|
||||
#define meshtastic_LogRecord_size 426
|
||||
#define meshtastic_LowEntropyKey_size 0
|
||||
#define meshtastic_MeshPacket_size 378
|
||||
#define meshtastic_MqttClientProxyMessage_size 501
|
||||
#define meshtastic_MyNodeInfo_size 77
|
||||
|
||||
@@ -46,6 +46,10 @@ uint8_t wifiDisconnectReason = 0;
|
||||
// Stores our hostname
|
||||
char ourHost[16];
|
||||
|
||||
// To replace blocking wifi connect delay with a non-blocking sleep
|
||||
static unsigned long wifiReconnectStartMillis = 0;
|
||||
static bool wifiReconnectPending = false;
|
||||
|
||||
bool APStartupComplete = 0;
|
||||
|
||||
unsigned long lastrun_ntp = 0;
|
||||
@@ -160,17 +164,30 @@ static int32_t reconnectWiFi()
|
||||
#endif
|
||||
LOG_INFO("Reconnecting to WiFi access point %s", wifiName);
|
||||
|
||||
delay(5000);
|
||||
// Start the non-blocking wait for 5 seconds
|
||||
wifiReconnectStartMillis = millis();
|
||||
wifiReconnectPending = true;
|
||||
// Do not attempt to connect yet, wait for the next invocation
|
||||
return 5000; // Schedule next check soon
|
||||
}
|
||||
|
||||
if (!WiFi.isConnected()) {
|
||||
// Check if we are ready to proceed with the WiFi connection after the 5s wait
|
||||
if (wifiReconnectPending) {
|
||||
if (millis() - wifiReconnectStartMillis >= 5000) {
|
||||
if (!WiFi.isConnected()) {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
WiFi.useStaticBuffers(true);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
WiFi.useStaticBuffers(true);
|
||||
WiFi.mode(WIFI_STA);
|
||||
#endif
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
}
|
||||
isReconnecting = false;
|
||||
wifiReconnectPending = false;
|
||||
} else {
|
||||
// Still waiting for 5s to elapse
|
||||
return 100; // Check again soon
|
||||
}
|
||||
isReconnecting = false;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
@@ -193,8 +210,6 @@ static int32_t reconnectWiFi()
|
||||
|
||||
if (config.network.wifi_enabled && !WiFi.isConnected()) {
|
||||
#ifdef ARCH_RP2040 // (ESP32 handles this in WiFiEvent)
|
||||
/* If APStartupComplete, but we're not connected, try again.
|
||||
Shouldn't try again before APStartupComplete. */
|
||||
needReconnect = APStartupComplete;
|
||||
#endif
|
||||
return 1000; // check once per second
|
||||
@@ -327,9 +342,15 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||
LOG_INFO("Connected to access point");
|
||||
#ifdef WIFI_LED
|
||||
digitalWrite(WIFI_LED, HIGH);
|
||||
#endif
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
LOG_INFO("Disconnected from WiFi access point");
|
||||
#ifdef WIFI_LED
|
||||
digitalWrite(WIFI_LED, LOW);
|
||||
#endif
|
||||
if (!isReconnecting) {
|
||||
WiFi.disconnect(false, true);
|
||||
syslog.disable();
|
||||
@@ -378,9 +399,15 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_START:
|
||||
LOG_INFO("WiFi access point started");
|
||||
#ifdef WIFI_LED
|
||||
digitalWrite(WIFI_LED, HIGH);
|
||||
#endif
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_STOP:
|
||||
LOG_INFO("WiFi access point stopped");
|
||||
#ifdef WIFI_LED
|
||||
digitalWrite(WIFI_LED, LOW);
|
||||
#endif
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
|
||||
LOG_INFO("Client connected");
|
||||
@@ -474,4 +501,4 @@ uint8_t getWifiDisconnectReason()
|
||||
{
|
||||
return wifiDisconnectReason;
|
||||
}
|
||||
#endif
|
||||
#endif // HAS_WIFI
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "SPILock.h"
|
||||
#include "meshUtils.h"
|
||||
#include <FSCommon.h>
|
||||
#include <ctype.h> // for better whitespace handling
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
#include "BleOta.h"
|
||||
#endif
|
||||
@@ -155,6 +156,28 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
*/
|
||||
case meshtastic_AdminMessage_set_owner_tag:
|
||||
LOG_DEBUG("Client set owner");
|
||||
// Validate names
|
||||
if (*r->set_owner.long_name) {
|
||||
const char *start = r->set_owner.long_name;
|
||||
// Skip all whitespace (space, tab, newline, etc)
|
||||
while (*start && isspace((unsigned char)*start))
|
||||
start++;
|
||||
if (*start == '\0') {
|
||||
LOG_WARN("Rejected long_name: must contain at least 1 non-whitespace character");
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*r->set_owner.short_name) {
|
||||
const char *start = r->set_owner.short_name;
|
||||
while (*start && isspace((unsigned char)*start))
|
||||
start++;
|
||||
if (*start == '\0') {
|
||||
LOG_WARN("Rejected short_name: must contain at least 1 non-whitespace character");
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
handleSetOwner(r->set_owner);
|
||||
break;
|
||||
|
||||
@@ -661,6 +684,24 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
config.lora = c.payload_variant.lora;
|
||||
// If we're setting region for the first time, init the region
|
||||
if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
||||
if (!owner.is_licensed) {
|
||||
bool keygenSuccess = false;
|
||||
if (config.security.private_key.size == 32) {
|
||||
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
|
||||
keygenSuccess = true;
|
||||
}
|
||||
} else {
|
||||
LOG_INFO("Generate new PKI keys");
|
||||
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
|
||||
keygenSuccess = true;
|
||||
}
|
||||
if (keygenSuccess) {
|
||||
config.security.public_key.size = 32;
|
||||
config.security.private_key.size = 32;
|
||||
owner.public_key.size = 32;
|
||||
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
|
||||
}
|
||||
}
|
||||
config.lora.tx_enabled = true;
|
||||
initRegion();
|
||||
if (myRegion->dutyCycle < 100) {
|
||||
@@ -681,11 +722,16 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
LOG_INFO("Set config: Security");
|
||||
config.security = c.payload_variant.security;
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN) && !(MESHTASTIC_EXCLUDE_PKI)
|
||||
// We check for a potentially valid private key, and a blank public key, and regen the public key if needed.
|
||||
if (config.security.private_key.size == 32 && !memfll(config.security.private_key.bytes, 0, 32) &&
|
||||
(config.security.public_key.size == 0 || memfll(config.security.public_key.bytes, 0, 32))) {
|
||||
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
|
||||
config.security.public_key.size = 32;
|
||||
// If the client set the key to blank, go ahead and regenerate so long as we're not in ham mode
|
||||
if (!owner.is_licensed && config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
||||
if (config.security.private_key.size != 32) {
|
||||
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
|
||||
|
||||
} else if (config.security.public_key.size != 32) {
|
||||
// We check for a potentially valid private key, and a blank public key, and regen the public key if needed.
|
||||
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
|
||||
config.security.public_key.size = 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1135,6 +1181,27 @@ void AdminModule::handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uic
|
||||
|
||||
void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p)
|
||||
{
|
||||
// Validate ham parameters before setting since this would bypass validation in the owner struct
|
||||
if (*p.call_sign) {
|
||||
const char *start = p.call_sign;
|
||||
// Skip all whitespace
|
||||
while (*start && isspace((unsigned char)*start))
|
||||
start++;
|
||||
if (*start == '\0') {
|
||||
LOG_WARN("Rejected ham call_sign: must contain at least 1 non-whitespace character");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (*p.short_name) {
|
||||
const char *start = p.short_name;
|
||||
while (*start && isspace((unsigned char)*start))
|
||||
start++;
|
||||
if (*start == '\0') {
|
||||
LOG_WARN("Rejected ham short_name: must contain at least 1 non-whitespace character");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Set call sign and override lora limitations for licensed use
|
||||
strncpy(owner.long_name, p.call_sign, sizeof(owner.long_name));
|
||||
strncpy(owner.short_name, p.short_name, sizeof(owner.short_name));
|
||||
|
||||
@@ -293,6 +293,12 @@ bool ExternalNotificationModule::getExternal(uint8_t index)
|
||||
return externalCurrentState[index];
|
||||
}
|
||||
|
||||
// Allow other firmware components to determine whether a notification is ongoing
|
||||
bool ExternalNotificationModule::nagging()
|
||||
{
|
||||
return isNagging;
|
||||
}
|
||||
|
||||
void ExternalNotificationModule::stopNow()
|
||||
{
|
||||
rtttl::stop();
|
||||
|
||||
@@ -40,6 +40,8 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency:
|
||||
void setMute(bool mute) { isMuted = mute; }
|
||||
bool getMute() { return isMuted; }
|
||||
|
||||
bool nagging();
|
||||
|
||||
void stopNow();
|
||||
|
||||
void handleGetRingtone(const meshtastic_MeshPacket &req, meshtastic_AdminMessage *response);
|
||||
|
||||
@@ -265,7 +265,6 @@ meshtastic_MeshPacket *PositionModule::allocPositionPacket()
|
||||
}
|
||||
|
||||
LOG_INFO("Position packet: time=%i lat=%i lon=%i", p.time, p.latitude_i, p.longitude_i);
|
||||
lastSentToMesh = millis();
|
||||
|
||||
// TAK Tracker devices should send their position in a TAK packet over the ATAK port
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)
|
||||
@@ -276,13 +275,18 @@ meshtastic_MeshPacket *PositionModule::allocPositionPacket()
|
||||
|
||||
meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
{
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND && lastSentToMesh &&
|
||||
Throttle::isWithinTimespanMs(lastSentToMesh, 3 * 60 * 1000)) {
|
||||
LOG_DEBUG("Skip Position reply since we sent it <3min ago");
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND && lastSentReply &&
|
||||
Throttle::isWithinTimespanMs(lastSentReply, 3 * 60 * 1000)) {
|
||||
LOG_DEBUG("Skip Position reply since we sent a reply <3min ago");
|
||||
ignoreRequest = true; // Mark it as ignored for MeshModule
|
||||
return nullptr;
|
||||
}
|
||||
return allocPositionPacket();
|
||||
|
||||
meshtastic_MeshPacket *reply = allocPositionPacket();
|
||||
if (reply) {
|
||||
lastSentReply = millis(); // Track when we sent this reply
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *PositionModule::allocAtakPli()
|
||||
|
||||
@@ -63,7 +63,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
||||
void sendLostAndFoundText();
|
||||
bool hasQualityTimesource();
|
||||
bool hasGPS();
|
||||
uint32_t lastSentToMesh = 0; // Last time we sent our position to the mesh
|
||||
uint32_t lastSentReply = 0; // Last time we sent a position reply (used for reply throttling only)
|
||||
|
||||
const uint32_t minimumTimeThreshold =
|
||||
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#include <OLEDDisplayUi.h>
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
||||
// Sensors
|
||||
|
||||
// Sensors
|
||||
#include "Sensor/CGRadSensSensor.h"
|
||||
#include "Sensor/RCWL9620Sensor.h"
|
||||
#include "Sensor/nullSensor.h"
|
||||
@@ -101,6 +101,13 @@ SHTC3Sensor shtc3Sensor;
|
||||
NullSensor shtc3Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
|
||||
#include "Sensor/RAK12035Sensor.h"
|
||||
RAK12035Sensor rak12035Sensor;
|
||||
#else
|
||||
NullSensor rak12035Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_VEML7700.h>)
|
||||
#include "Sensor/VEML7700Sensor.h"
|
||||
VEML7700Sensor veml7700Sensor;
|
||||
@@ -173,6 +180,7 @@ NullSensor pct2075Sensor;
|
||||
|
||||
RCWL9620Sensor rcwl9620Sensor;
|
||||
CGRadSensSensor cgRadSens;
|
||||
|
||||
#endif
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
#include "Sensor/T1000xSensor.h"
|
||||
@@ -182,6 +190,7 @@ T1000xSensor t1000xSensor;
|
||||
#include "Sensor/IndicatorSensor.h"
|
||||
IndicatorSensor indicatorSensor;
|
||||
#endif
|
||||
|
||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
||||
|
||||
@@ -288,6 +297,11 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
|
||||
result = rak9154Sensor.runOnce();
|
||||
#endif
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
|
||||
if (rak12035Sensor.hasSensor()) {
|
||||
result = rak12035Sensor.runOnce();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
// it's possible to have this module enabled, only for displaying values on the screen.
|
||||
@@ -625,6 +639,14 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
||||
valid = valid && rak9154Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
#endif
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && \
|
||||
RAK_4631 == \
|
||||
1 // Not really needed, but may as well just skip at a lower level it if no library or not a RAK_4631
|
||||
if (rak12035Sensor.hasSensor()) {
|
||||
valid = valid && rak12035Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return valid && hasSensor;
|
||||
}
|
||||
@@ -679,6 +701,9 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
|
||||
LOG_INFO("Send: radiation=%fµR/h", m.variant.environment_metrics.radiation);
|
||||
|
||||
LOG_INFO("Send: soil_temperature=%f, soil_moisture=%u", m.variant.environment_metrics.soil_temperature,
|
||||
m.variant.environment_metrics.soil_moisture);
|
||||
|
||||
sensor_read_error_count = 0;
|
||||
|
||||
meshtastic_MeshPacket *p = allocDataProtobuf(m);
|
||||
@@ -850,8 +875,17 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && \
|
||||
RAK_4631 == \
|
||||
1 // Not really needed, but may as well just skip it at a lower level if no library or not a RAK_4631
|
||||
if (rak12035Sensor.hasSensor()) {
|
||||
result = rak12035Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -29,12 +29,15 @@ bool HostMetricsModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
|
||||
if (t->which_variant == meshtastic_Telemetry_host_metrics_tag) {
|
||||
#ifdef DEBUG_PORT
|
||||
const char *sender = getSenderShortName(mp);
|
||||
if (t->variant.host_metrics.has_user_string)
|
||||
t->variant.host_metrics.user_string[sizeof(t->variant.host_metrics.user_string) - 1] = '\0';
|
||||
|
||||
LOG_INFO("(Received Host Metrics from %s): uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f, %s",
|
||||
sender, t->variant.host_metrics.uptime_seconds, t->variant.host_metrics.diskfree1_bytes,
|
||||
LOG_INFO("(Received Host Metrics from %s): uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f", sender,
|
||||
t->variant.host_metrics.uptime_seconds, t->variant.host_metrics.diskfree1_bytes,
|
||||
t->variant.host_metrics.freemem_bytes, static_cast<float>(t->variant.host_metrics.load1) / 100,
|
||||
static_cast<float>(t->variant.host_metrics.load5) / 100,
|
||||
static_cast<float>(t->variant.host_metrics.load15) / 100, t->variant.host_metrics.user_string);
|
||||
static_cast<float>(t->variant.host_metrics.load15) / 100);
|
||||
// t->variant.host_metrics.has_user_string ? t->variant.host_metrics.user_string : "");
|
||||
#endif
|
||||
}
|
||||
return false; // Let others look at this message also if they want
|
||||
@@ -110,7 +113,8 @@ meshtastic_Telemetry HostMetricsModule::getHostMetrics()
|
||||
if (settingsStrings[hostMetrics_user_command] != "") {
|
||||
std::string userCommandResult = exec(settingsStrings[hostMetrics_user_command].c_str());
|
||||
if (userCommandResult.length() > 1) {
|
||||
strncpy(t.variant.host_metrics.user_string, userCommandResult.c_str(), 200);
|
||||
strncpy(t.variant.host_metrics.user_string, userCommandResult.c_str(), sizeof(t.variant.host_metrics.user_string));
|
||||
t.variant.host_metrics.user_string[sizeof(t.variant.host_metrics.user_string) - 1] = '\0';
|
||||
t.variant.host_metrics.has_user_string = true;
|
||||
}
|
||||
}
|
||||
@@ -120,11 +124,12 @@ meshtastic_Telemetry HostMetricsModule::getHostMetrics()
|
||||
bool HostMetricsModule::sendMetrics()
|
||||
{
|
||||
meshtastic_Telemetry telemetry = getHostMetrics();
|
||||
LOG_INFO("Send: uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f %s",
|
||||
LOG_INFO("Send: uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f",
|
||||
telemetry.variant.host_metrics.uptime_seconds, telemetry.variant.host_metrics.diskfree1_bytes,
|
||||
telemetry.variant.host_metrics.freemem_bytes, static_cast<float>(telemetry.variant.host_metrics.load1) / 100,
|
||||
static_cast<float>(telemetry.variant.host_metrics.load5) / 100,
|
||||
static_cast<float>(telemetry.variant.host_metrics.load15) / 100, telemetry.variant.host_metrics.user_string);
|
||||
static_cast<float>(telemetry.variant.host_metrics.load15) / 100);
|
||||
// telemetry.variant.host_metrics.has_user_string ? telemetry.variant.host_metrics.user_string : "");
|
||||
|
||||
meshtastic_MeshPacket *p = allocDataProtobuf(telemetry);
|
||||
p->to = NODENUM_BROADCAST;
|
||||
@@ -135,4 +140,4 @@ bool HostMetricsModule::sendMetrics()
|
||||
service->sendToMesh(p, RX_SRC_LOCAL, true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -8,16 +8,24 @@
|
||||
#include "VoltageSensor.h"
|
||||
#include <INA3221.h>
|
||||
|
||||
#ifndef INA3221_ENV_CH
|
||||
#define INA3221_ENV_CH INA3221_CH1
|
||||
#endif
|
||||
|
||||
#ifndef INA3221_BAT_CH
|
||||
#define INA3221_BAT_CH INA3221_CH1
|
||||
#endif
|
||||
|
||||
class INA3221Sensor : public TelemetrySensor, VoltageSensor, CurrentSensor
|
||||
{
|
||||
private:
|
||||
INA3221 ina3221 = INA3221(INA3221_ADDR42_SDA);
|
||||
|
||||
// channel to report voltage/current for environment metrics
|
||||
ina3221_ch_t ENV_CH = INA3221_CH1;
|
||||
static const ina3221_ch_t ENV_CH = INA3221_ENV_CH;
|
||||
|
||||
// channel to report battery voltage for device_battery_ina_address
|
||||
ina3221_ch_t BAT_CH = INA3221_CH1;
|
||||
static const ina3221_ch_t BAT_CH = INA3221_BAT_CH;
|
||||
|
||||
// get a single measurement for a channel
|
||||
struct _INA3221Measurement getMeasurement(ina3221_ch_t ch);
|
||||
|
||||
109
src/modules/Telemetry/Sensor/RAK12035Sensor.cpp
Normal file
109
src/modules/Telemetry/Sensor/RAK12035Sensor.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "RAK12035Sensor.h"
|
||||
|
||||
RAK12035Sensor::RAK12035Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_RAK12035, "RAK12035") {}
|
||||
|
||||
int32_t RAK12035Sensor::runOnce()
|
||||
{
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
// TODO:: check for up to 2 additional sensors and start them if present.
|
||||
sensor.set_sensor_addr(RAK120351_ADDR);
|
||||
delay(100);
|
||||
sensor.begin(nodeTelemetrySensorsMap[sensorType].first);
|
||||
|
||||
// Get sensor firmware version
|
||||
uint8_t data = 0;
|
||||
sensor.get_sensor_version(&data);
|
||||
if (data != 0) {
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
LOG_INFO("RAK12035Sensor Init Succeed \nSensor1 Firmware version: %i, Sensor Name: %s", data, sensorName);
|
||||
status = true;
|
||||
sensor.sensor_sleep();
|
||||
} else {
|
||||
// If we reach here, it means the sensor did not initialize correctly.
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
LOG_ERROR("RAK12035Sensor Init Failed");
|
||||
status = false;
|
||||
}
|
||||
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void RAK12035Sensor::setup()
|
||||
{
|
||||
// Set the calibration values
|
||||
// Reading the saved calibration values from the sensor.
|
||||
// TODO:: Check for and run calibration check for up to 2 additional sensors if present.
|
||||
uint16_t zero_val = 0;
|
||||
uint16_t hundred_val = 0;
|
||||
uint16_t default_zero_val = 550;
|
||||
uint16_t default_hundred_val = 420;
|
||||
sensor.sensor_on();
|
||||
delay(200);
|
||||
sensor.get_dry_cal(&zero_val);
|
||||
sensor.get_wet_cal(&hundred_val);
|
||||
delay(200);
|
||||
if (zero_val == 0 || zero_val <= hundred_val) {
|
||||
LOG_INFO("Dry calibration value is %d", zero_val);
|
||||
LOG_INFO("Wet calibration value is %d", hundred_val);
|
||||
LOG_INFO("This does not make sense. You can recalibrate this sensor using the calibration sketch included here: "
|
||||
"https://github.com/RAKWireless/RAK12035_SoilMoisture.");
|
||||
LOG_INFO("For now, setting default calibration value for Dry Calibration: %d", default_zero_val);
|
||||
sensor.set_dry_cal(default_zero_val);
|
||||
sensor.get_dry_cal(&zero_val);
|
||||
LOG_INFO("Dry calibration reset complete. New value is %d", zero_val);
|
||||
}
|
||||
if (hundred_val == 0 || hundred_val >= zero_val) {
|
||||
LOG_INFO("Dry calibration value is %d", zero_val);
|
||||
LOG_INFO("Wet calibration value is %d", hundred_val);
|
||||
LOG_INFO("This does not make sense. You can recalibrate this sensor using the calibration sketch included here: "
|
||||
"https://github.com/RAKWireless/RAK12035_SoilMoisture.");
|
||||
LOG_INFO("For now, setting default calibration value for Wet Calibration: %d", default_hundred_val);
|
||||
sensor.set_wet_cal(default_hundred_val);
|
||||
sensor.get_wet_cal(&hundred_val);
|
||||
LOG_INFO("Wet calibration reset complete. New value is %d", hundred_val);
|
||||
}
|
||||
sensor.sensor_sleep();
|
||||
delay(200);
|
||||
LOG_INFO("Dry calibration value is %d", zero_val);
|
||||
LOG_INFO("Wet calibration value is %d", hundred_val);
|
||||
}
|
||||
|
||||
bool RAK12035Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
// TODO:: read and send metrics for up to 2 additional soil monitors if present.
|
||||
// -- how to do this.. this could get a little complex..
|
||||
// ie - 1> we combine them into an average and send that, 2> we send them as separate metrics
|
||||
// ^-- these scenarios would require different handling of the metrics in the receiving end and maybe a setting in the
|
||||
// device ui and an additional proto for that?
|
||||
measurement->variant.environment_metrics.has_soil_temperature = true;
|
||||
measurement->variant.environment_metrics.has_soil_moisture = true;
|
||||
|
||||
uint8_t moisture = 0;
|
||||
uint16_t temp = 0;
|
||||
bool success = false;
|
||||
|
||||
sensor.sensor_on();
|
||||
delay(200);
|
||||
success = sensor.get_sensor_moisture(&moisture);
|
||||
delay(200);
|
||||
success &= sensor.get_sensor_temperature(&temp);
|
||||
delay(200);
|
||||
sensor.sensor_sleep();
|
||||
|
||||
if (success == false) {
|
||||
LOG_ERROR("Failed to read sensor data");
|
||||
return false;
|
||||
}
|
||||
measurement->variant.environment_metrics.soil_temperature = ((float)temp / 10.0f);
|
||||
measurement->variant.environment_metrics.soil_moisture = moisture;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
28
src/modules/Telemetry/Sensor/RAK12035Sensor.h
Normal file
28
src/modules/Telemetry/Sensor/RAK12035Sensor.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<RAK12035_SoilMoisture.h>) && defined(RAK_4631)
|
||||
#ifndef _MT_RAK12035VBSENSOR_H
|
||||
#define _MT_RAK12035VBSENSOR_H
|
||||
#endif
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "RAK12035_SoilMoisture.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
class RAK12035Sensor : public TelemetrySensor
|
||||
{
|
||||
private:
|
||||
RAK12035 sensor;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
RAK12035Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
};
|
||||
#endif
|
||||
@@ -41,21 +41,36 @@ void RCWL9620Sensor::begin(TwoWire *wire, uint8_t addr, uint8_t sda, uint8_t scl
|
||||
|
||||
float RCWL9620Sensor::getDistance()
|
||||
{
|
||||
uint32_t data;
|
||||
_wire->beginTransmission(_addr); // Transfer data to addr.
|
||||
_wire->write(0x01);
|
||||
_wire->endTransmission(); // Stop data transmission with the Ultrasonic
|
||||
// Unit.
|
||||
uint32_t data = 0;
|
||||
uint8_t b1 = 0, b2 = 0, b3 = 0;
|
||||
|
||||
_wire->requestFrom(_addr,
|
||||
(uint8_t)3); // Request 3 bytes from Ultrasonic Unit.
|
||||
LOG_DEBUG("[RCWL9620] Start measure command");
|
||||
|
||||
_wire->beginTransmission(_addr);
|
||||
_wire->write(0x01); // À tester aussi sans cette ligne si besoin
|
||||
uint8_t result = _wire->endTransmission();
|
||||
LOG_DEBUG("[RCWL9620] endTransmission result = %d", result);
|
||||
delay(100); // délai pour laisser le capteur répondre
|
||||
|
||||
LOG_DEBUG("[RCWL9620] Read i2c data:");
|
||||
_wire->requestFrom(_addr, (uint8_t)3);
|
||||
|
||||
if (_wire->available() < 3) {
|
||||
LOG_DEBUG("[RCWL9620] less than 3 octets !");
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
b1 = _wire->read();
|
||||
b2 = _wire->read();
|
||||
b3 = _wire->read();
|
||||
|
||||
data = ((uint32_t)b1 << 16) | ((uint32_t)b2 << 8) | b3;
|
||||
|
||||
float Distance = float(data) / 1000.0;
|
||||
|
||||
LOG_DEBUG("[RCWL9620] Bytes readed = %02X %02X %02X", b1, b2, b3);
|
||||
LOG_DEBUG("[RCWL9620] data=%.2f, level=%.2f", (double)data, (double)Distance);
|
||||
|
||||
data = _wire->read();
|
||||
data <<= 8;
|
||||
data |= _wire->read();
|
||||
data <<= 8;
|
||||
data |= _wire->read();
|
||||
float Distance = float(data) / 1000;
|
||||
if (Distance > 4500.00) {
|
||||
return 4500.00;
|
||||
} else {
|
||||
@@ -63,4 +78,4 @@ float RCWL9620Sensor::getDistance()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -763,7 +763,10 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me
|
||||
}
|
||||
entry->topic = std::move(topic);
|
||||
entry->envBytes.assign(bytes, numBytes);
|
||||
assert(mqttQueue.enqueue(entry, 0));
|
||||
if (mqttQueue.enqueue(entry, 0) == false) {
|
||||
LOG_CRIT("Failed to add a message to mqttQueue!");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,11 @@ void NimbleBluetooth::deinit()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
LOG_INFO("Disable bluetooth until reboot");
|
||||
|
||||
#ifdef BLE_LED
|
||||
digitalWrite(BLE_LED, LOW);
|
||||
#endif
|
||||
|
||||
NimBLEDevice::deinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -56,9 +56,11 @@ void updateBatteryLevel(uint8_t level) {}
|
||||
void getMacAddr(uint8_t *dmac)
|
||||
{
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C6) && defined(CONFIG_SOC_IEEE802154_SUPPORTED)
|
||||
assert(esp_base_mac_addr_get(dmac) == ESP_OK);
|
||||
auto res = esp_base_mac_addr_get(dmac);
|
||||
assert(res == ESP_OK);
|
||||
#else
|
||||
assert(esp_efuse_mac_get_default(dmac) == ESP_OK);
|
||||
auto res = esp_efuse_mac_get_default(dmac);
|
||||
assert(res == ESP_OK);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_RAK2560
|
||||
#elif defined(WISMESH_TAP)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_WISMESH_TAP
|
||||
#elif defined(GAT562_MESH_TRIAL_TRACKER)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_GAT562_MESH_TRIAL_TRACKER
|
||||
#elif defined(RAK4630)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
|
||||
#elif defined(TTGO_T_ECHO)
|
||||
@@ -85,6 +87,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_SEEED_SOLAR_NODE
|
||||
#elif defined(HELTEC_MESH_POCKET)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_POCKET
|
||||
#elif defined(NOMADSTAR_METEOR_PRO)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO
|
||||
#elif defined(SEEED_WIO_TRACKER_L1)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1
|
||||
#else
|
||||
@@ -139,4 +143,4 @@
|
||||
#if !defined(PIN_SERIAL_RX) && !defined(NRF52840_XXAA)
|
||||
// No serial ports on this board - ONLY use segger in memory console
|
||||
#define USE_SEGGER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -308,6 +308,9 @@ void cpuDeepSleep(uint32_t msecToWake)
|
||||
nrf_gpio_cfg_default(SCREEN_TOUCH_INT);
|
||||
nrf_gpio_cfg_default(WB_I2C1_SCL);
|
||||
nrf_gpio_cfg_default(WB_I2C1_SDA);
|
||||
|
||||
// nrf_gpio_cfg_default(WB_I2C2_SCL);
|
||||
// nrf_gpio_cfg_default(WB_I2C2_SDA);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MESHLINK
|
||||
|
||||
@@ -332,7 +332,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_ESP32) && defined(I2C_SDA)
|
||||
#if !MESHTASTIC_EXCLUDE_I2C && defined(ARCH_ESP32) && defined(I2C_SDA)
|
||||
// Added by https://github.com/meshtastic/firmware/pull/4418
|
||||
// Possibly to support Heltec Capsule Sensor?
|
||||
Wire.end();
|
||||
@@ -542,4 +542,4 @@ void enableLoraInterrupt()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
// "USERPREFS_CONFIG_LORA_REGION": "meshtastic_Config_LoRaConfig_RegionCode_US",
|
||||
// "USERPREFS_CONFIG_OWNER_LONG_NAME": "My Long Name",
|
||||
// "USERPREFS_CONFIG_OWNER_SHORT_NAME": "MLN",
|
||||
// "USERPREFS_CONFIG_DEVICE_ROLE": "meshtastic_Config_DeviceConfig_Role_CLIENT", // Defaults to CLIENT. ROUTER*, LOST AND FOUND, and REPEATER roles are restricted.
|
||||
// "USERPREFS_EVENT_MODE": "1",
|
||||
// "USERPREFS_FIXED_BLUETOOTH": "121212",
|
||||
// "USERPREFS_FIXED_GPS": "",
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#define PIN_GPS_EN 4
|
||||
#define GPS_POWER_TOGGLE // Moved definition from platformio.ini to here
|
||||
|
||||
#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
|
||||
#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
|
||||
// Note: On the ESP32 base version, gpio34-39 are input-only, and do not have internal pull-ups.
|
||||
// If 39 is not being used for a button, it is suggested to remove the #define.
|
||||
#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
|
||||
#define ADC_MULTIPLIER 1.85 // (R1 = 470k, R2 = 680k)
|
||||
|
||||
62
variants/diy/nrf52_promicro_diy_tcxo/custom_build_tasks.py
Normal file
62
variants/diy/nrf52_promicro_diy_tcxo/custom_build_tasks.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# Simplifies DIY InkHUD builds, with presets for several common E-Ink displays
|
||||
# - build using custom task in Platformio's "Project Tasks" panel
|
||||
# - build with `pio run -e <variant> -t build_weact_154` (or similar)
|
||||
|
||||
# Silence trunk's objections to the import statements
|
||||
# trunk-ignore-all(ruff/F821)
|
||||
# trunk-ignore-all(flake8/F821)
|
||||
|
||||
from SCons.Script import COMMAND_LINE_TARGETS
|
||||
|
||||
Import("env")
|
||||
Import("projenv")
|
||||
|
||||
# Custom targets
|
||||
# These wrappers just run the normal build task under a different target name
|
||||
# We intercept the build later on, based on the target name
|
||||
env.AddTarget(
|
||||
name="build_weact_154",
|
||||
dependencies=["buildprog"],
|
||||
actions=None,
|
||||
title='Build (WeAct 1.54")',
|
||||
)
|
||||
env.AddTarget(
|
||||
name="build_weact_213",
|
||||
dependencies=["buildprog"],
|
||||
actions=None,
|
||||
title='Build (WeAct 2.13")',
|
||||
)
|
||||
env.AddTarget(
|
||||
name="build_weact_290",
|
||||
dependencies=["buildprog"],
|
||||
actions=None,
|
||||
title='Build (WeAct 2.9")',
|
||||
)
|
||||
env.AddTarget(
|
||||
name="build_weact_420",
|
||||
dependencies=["buildprog"],
|
||||
actions=None,
|
||||
title='Build (WeAct 4.2")',
|
||||
)
|
||||
|
||||
# Check whether a build was started via one of our custom targets above
|
||||
|
||||
if "build_weact_154" in COMMAND_LINE_TARGETS:
|
||||
print('Building for WeAct 1.54" Display')
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "ZJY200200_0154DAAMFGN"))
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
|
||||
|
||||
elif "build_weact_213" in COMMAND_LINE_TARGETS:
|
||||
print('Building for WeAct 2.13" Display')
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "HINK_E0213A289"))
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "10"))
|
||||
|
||||
elif "build_weact_290" in COMMAND_LINE_TARGETS:
|
||||
print('Building for WeAct 2.9" Display')
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "ZJY128296_029EAAMFGN"))
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
|
||||
|
||||
elif "build_weact_420" in COMMAND_LINE_TARGETS:
|
||||
print('Building for WeAct 4.2" Display')
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "HINK_E042A87"))
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
|
||||
94
variants/diy/nrf52_promicro_diy_tcxo/nicheGraphics.h
Normal file
94
variants/diy/nrf52_promicro_diy_tcxo/nicheGraphics.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
// InkHUD-specific components
|
||||
// ---------------------------
|
||||
#include "graphics/niche/InkHUD/InkHUD.h"
|
||||
|
||||
// Applets
|
||||
#include "graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/DM/DMApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/Positions/PositionsApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h"
|
||||
|
||||
// Shared NicheGraphics components
|
||||
// --------------------------------
|
||||
#include "graphics/niche/Drivers/EInk/HINK_E0213A289.h" // WeAct 2.13"
|
||||
#include "graphics/niche/Drivers/EInk/HINK_E042A87.h" // WeAct 4.2"
|
||||
#include "graphics/niche/Drivers/EInk/ZJY128296_029EAAMFGN.h" // WeAct 2.9"
|
||||
#include "graphics/niche/Drivers/EInk/ZJY200200_0154DAAMFGN.h" // WeACt 1.54"
|
||||
|
||||
#include "graphics/niche/Inputs/TwoButton.h"
|
||||
|
||||
#if !defined(INKHUD_BUILDCONF_DRIVER) || !defined(INKHUD_BUILDCONF_DISPLAYRESILIENCE)
|
||||
#error If not using a DIY preset, display model and resilience must be set manually
|
||||
#endif
|
||||
|
||||
void setupNicheGraphics()
|
||||
{
|
||||
using namespace NicheGraphics;
|
||||
|
||||
// SPI
|
||||
// -----------------------------
|
||||
SPI.begin();
|
||||
|
||||
// Driver
|
||||
// -----------------------------
|
||||
|
||||
// Use E-Ink driver
|
||||
Drivers::EInk *driver = new Drivers::INKHUD_BUILDCONF_DRIVER;
|
||||
driver->begin(&SPI, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES);
|
||||
|
||||
// InkHUD
|
||||
// ----------------------------
|
||||
|
||||
InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance();
|
||||
|
||||
// Set the driver
|
||||
inkhud->setDriver(driver);
|
||||
|
||||
// Set how many FAST updates per FULL update.
|
||||
inkhud->setDisplayResilience(INKHUD_BUILDCONF_DISPLAYRESILIENCE); // Suggest roughly ten
|
||||
|
||||
// Prepare fonts
|
||||
InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252;
|
||||
InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252;
|
||||
|
||||
// Init settings, and customize defaults
|
||||
// Values ignored individually if found saved to flash
|
||||
inkhud->persistence->settings.rotation = (driver->height > driver->width ? 1 : 0); // Rotate 90deg to landscape, if needed
|
||||
inkhud->persistence->settings.userTiles.maxCount = 4;
|
||||
inkhud->persistence->settings.optionalFeatures.batteryIcon = true;
|
||||
|
||||
// Pick applets
|
||||
// Note: order of applets determines priority of "auto-show" feature
|
||||
inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet);
|
||||
inkhud->addApplet("DMs", new InkHUD::DMApplet, true, false, 3); // Default on tile 3
|
||||
inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0), true, false, 2); // Default on tile 2
|
||||
inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1));
|
||||
inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true, false, 1); // Default on tile 1
|
||||
inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet, true, false, 0); // Default on tile 0
|
||||
inkhud->addApplet("Heard", new InkHUD::HeardApplet, true); // Background
|
||||
|
||||
// Start running InkHUD
|
||||
inkhud->begin();
|
||||
|
||||
// Buttons
|
||||
// --------------------------
|
||||
|
||||
Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component
|
||||
|
||||
// Setup the main user button
|
||||
buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin(), true); // Internal pull up
|
||||
buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); });
|
||||
buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); });
|
||||
|
||||
buttons->start();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -22,26 +22,26 @@ extern "C" {
|
||||
/*
|
||||
NRF52 PRO MICRO PIN ASSIGNMENT
|
||||
|
||||
| Pin <EFBFBD> | Function <EFBFBD> | <EFBFBD> | Pin <EFBFBD> <20> | Function <EFBFBD> <20> | RF95 |
|
||||
| Pin | Function | | Pin | Function | RF95 |
|
||||
| ----- | ----------- | --- | -------- | ------------ | ----- |
|
||||
| Gnd <EFBFBD> | <EFBFBD> <20> <20> <20> <20> <20> | <EFBFBD> | vbat <EFBFBD> <20> | <20> <20> <20> <20> <20> <20> | |
|
||||
| P0.06 | Serial2 RX | <EFBFBD> | vbat <EFBFBD> <20> | <20> <20> <20> <20> <20> <20> | |
|
||||
| P0.08 | Serial2 TX | <EFBFBD> | Gnd <EFBFBD> <20> | <EFBFBD> <20> <20> <20> <20> <20> | |
|
||||
| Gnd <EFBFBD> | <EFBFBD> <20> <20> <20> <20> <20> | <EFBFBD> | reset <EFBFBD> | <EFBFBD> <20> <20> <20> <20> <20> | |
|
||||
| Gnd <EFBFBD> | <EFBFBD> <20> <20> <20> <20> <20> | <EFBFBD> | ext_vcc | *see 0.13 <EFBFBD> | |
|
||||
| P0.17 | RXEN <EFBFBD> <20> <20> | <EFBFBD> | P0.31 <EFBFBD> | BATTERY_PIN | |
|
||||
| P0.20 | GPS_RX <EFBFBD> <20> | <EFBFBD> | P0.29 <EFBFBD> | BUSY <EFBFBD> <20> <20> <20> | DIO0 |
|
||||
| P0.22 | GPS_TX <EFBFBD> <20> | <EFBFBD> | P0.02 <EFBFBD> | MISO | MISO |
|
||||
| P0.24 | GPS_EN <EFBFBD> <20> | <EFBFBD> | P1.15 <EFBFBD> | MOSI <EFBFBD> <20> <20> <20> | MOSI |
|
||||
| P1.00 | BUTTON_PIN | <EFBFBD> | P1.13 <EFBFBD> | CS <EFBFBD> <20> <20> <20> <20> | CS <EFBFBD> |
|
||||
| P0.11 | SCL <EFBFBD> <20> <20> <20> | <EFBFBD> | P1.11 <EFBFBD> | SCK <EFBFBD> <20> <20> <20> | SCK |
|
||||
| P1.04 | SDA <EFBFBD> <20> <20> <20> | <EFBFBD> | P0.10 <EFBFBD> | DIO1/IRQ <EFBFBD> <20> | DIO1 |
|
||||
| P1.06 | Free pin <EFBFBD> | <EFBFBD> | P0.09 <EFBFBD> | RESET <EFBFBD> <20> <20> | RST |
|
||||
| <EFBFBD> <20> <20> | <20> <20> <20> <20> <20> <20> | <EFBFBD> | <EFBFBD> <20> <20> <20> | <20> <20> <20> <20> <20> <20> | |
|
||||
| <EFBFBD> <20> <20> | Mid board <EFBFBD> | <EFBFBD> | <EFBFBD> <20> <20> <20> | Internal <EFBFBD> <20> | |
|
||||
| P1.01 | Free pin <EFBFBD> | <EFBFBD> | 0.15 <EFBFBD> <20> | LED <EFBFBD> <20> <20> <20> | |
|
||||
| P1.02 | Free pin <EFBFBD> | <EFBFBD> | 0.13 <EFBFBD> <20> | 3V3_EN <EFBFBD> <20> <20> | |
|
||||
| P1.07 | Free pin <EFBFBD> | <EFBFBD> | <EFBFBD> <20> <20> <20> | <20> <20> <20> <20> <20> <20> | |
|
||||
| Gnd | | | vbat | | |
|
||||
| P0.06 | Serial2 RX | | vbat | | |
|
||||
| P0.08 | Serial2 TX | | Gnd | | |
|
||||
| Gnd | | | reset | | |
|
||||
| Gnd | | | ext_vcc | *see 0.13 | |
|
||||
| P0.17 | RXEN | | P0.31 | BATTERY_PIN | |
|
||||
| P0.20 | GPS_RX | | P0.29 | BUSY | DIO0 |
|
||||
| P0.22 | GPS_TX | | P0.02 | MISO | MISO |
|
||||
| P0.24 | GPS_EN | | P1.15 | MOSI | MOSI |
|
||||
| P1.00 | BUTTON_PIN | | P1.13 | CS | CS |
|
||||
| P0.11 | SCL | | P1.11 | SCK | SCK |
|
||||
| P1.04 | SDA | | P0.10 | DIO1/IRQ | DIO1 |
|
||||
| P1.06 | Free pin | | P0.09 | RESET | RST |
|
||||
| | | | | | |
|
||||
| | Mid board | | | Internal | |
|
||||
| P1.01 | Free pin | | 0.15 | LED | |
|
||||
| P1.02 | Free pin | | 0.13 | 3V3_EN | |
|
||||
| P1.07 | Free pin | | | | |
|
||||
*/
|
||||
|
||||
// Number of pins defined in PinDescription array
|
||||
@@ -185,6 +185,12 @@ settings.
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL
|
||||
|
||||
// E-Ink DIY
|
||||
#define PIN_EINK_CS (32 + 7)
|
||||
#define PIN_EINK_DC (32 + 2)
|
||||
#define PIN_EINK_RES (32 + 1)
|
||||
#define PIN_EINK_BUSY (32 + 6)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -68,6 +68,34 @@ lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
debug_tool = jlink
|
||||
|
||||
; NRF52 ProMicro w/ E-Ink display
|
||||
[env:nrf52_promicro_diy-inkhud]
|
||||
board_level = extra
|
||||
extends = nrf52840_base, inkhud
|
||||
board = promicro-nrf52840
|
||||
build_flags =
|
||||
${nrf52840_base.build_flags}
|
||||
${inkhud.build_flags}
|
||||
-I variants/diy/nrf52_promicro_diy_tcxo
|
||||
-D NRF52_PROMICRO_DIY
|
||||
build_src_filter =
|
||||
${nrf52_base.build_src_filter}
|
||||
${inkhud.build_src_filter}
|
||||
+<../variants/diy/nrf52_promicro_diy_tcxo>
|
||||
lib_deps =
|
||||
${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX
|
||||
${nrf52840_base.lib_deps}
|
||||
extra_scripts =
|
||||
${env.extra_scripts}
|
||||
variants/diy/nrf52_promicro_diy_tcxo/custom_build_tasks.py ; Add to PIO's Project Tasks pane: preset builds for common displays
|
||||
|
||||
; Seeed Xiao BLE: https://www.digikey.com/en/products/detail/seeed-technology-co-ltd/102010448/16652893
|
||||
[env:xiao_ble]
|
||||
extends = env:seeed_xiao_nrf52840_kit
|
||||
board_level = extra
|
||||
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags} -D PRIVATE_HW -DXIAO_BLE_LEGACY_PINOUT -DEBYTE_E22 -DEBYTE_E22_900M30S
|
||||
build_unflags = -DGPS_L76K
|
||||
|
||||
; Seeed XIAO nRF52840 + XIAO Wio SX1262 DIY
|
||||
[env:seeed-xiao-nrf52840-wio-sx1262]
|
||||
board = xiao_ble_sense
|
||||
|
||||
@@ -52,4 +52,11 @@ const uint32_t g_ADigitalPinMap[] = {
|
||||
|
||||
// VBAT
|
||||
31, // D32 is P0.10 (VBAT)
|
||||
};
|
||||
};
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
// Set BQ25101 ISET to 100mA instead of 50mA
|
||||
pinMode(HICHG, OUTPUT);
|
||||
digitalWrite(HICHG, LOW);
|
||||
}
|
||||
|
||||
@@ -164,7 +164,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
// -------
|
||||
// P0_14 = 14 Reads battery voltage from divider on signal board.
|
||||
// PIN_VBAT is reading voltage divider on XIAO and is program pin 32 / or P0.31
|
||||
#define BAT_READ 14
|
||||
#define ADC_CTRL VBAT_ENABLE
|
||||
#define ADC_CTRL_ENABLED LOW
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 10
|
||||
#define CHARGE_LED 23 // P0_17 = 17 D23 YELLOW CHARGE LED
|
||||
#define HICHG 22 // P0_13 = 13 D22 Charge-select pin for Lipo for 100 mA instead of default 50mA charge
|
||||
|
||||
@@ -48,7 +48,7 @@ lib_deps = ${esp32s3_base.lib_deps}
|
||||
lovyan03/LovyanGFX@1.2.0 ; note: v1.2.7 breaks the elecrow 7" display functionality
|
||||
hideakitai/TCA9534@0.1.1
|
||||
|
||||
[crowpanel_small] ; 2.4, 2.8, 3.5 inch
|
||||
[crowpanel_small_esp32s3_base] ; 2.4, 2.8, 3.5 inch
|
||||
extends = crowpanel_base
|
||||
build_flags =
|
||||
${crowpanel_base.build_flags}
|
||||
@@ -62,7 +62,7 @@ build_flags =
|
||||
-D VIEW_320x240
|
||||
-D MAP_FULL_REDRAW
|
||||
|
||||
[crowpanel_large] ; 4.3, 5.0, 7.0 inch
|
||||
[crowpanel_large_esp32s3_base] ; 4.3, 5.0, 7.0 inch
|
||||
extends = crowpanel_base
|
||||
build_flags =
|
||||
${crowpanel_base.build_flags}
|
||||
@@ -73,9 +73,9 @@ build_flags =
|
||||
-D DISPLAY_SET_RESOLUTION
|
||||
|
||||
[env:elecrow-adv-24-28-tft]
|
||||
extends = crowpanel_small
|
||||
extends = crowpanel_small_esp32s3_base
|
||||
build_flags =
|
||||
${crowpanel_small.build_flags}
|
||||
${crowpanel_small_esp32s3_base.build_flags}
|
||||
-D SPI_FREQUENCY=80000000
|
||||
-D LGFX_SCREEN_WIDTH=240
|
||||
-D LGFX_SCREEN_HEIGHT=320
|
||||
@@ -96,9 +96,9 @@ build_flags =
|
||||
-D LGFX_TOUCH_ROTATION=0
|
||||
|
||||
[env:elecrow-adv-35-tft]
|
||||
extends = crowpanel_small
|
||||
extends = crowpanel_small_esp32s3_base
|
||||
build_flags =
|
||||
${crowpanel_small.build_flags}
|
||||
${crowpanel_small_esp32s3_base.build_flags}
|
||||
-D LV_CACHE_DEF_SIZE=2097152
|
||||
-D SPI_FREQUENCY=60000000
|
||||
-D LGFX_SCREEN_WIDTH=320
|
||||
@@ -122,7 +122,7 @@ build_flags =
|
||||
|
||||
; 4.3, 5.0, 7.0 inch 800x480 IPS (V1)
|
||||
[env:elecrow-adv1-43-50-70-tft]
|
||||
extends = crowpanel_large
|
||||
extends = crowpanel_large_esp32s3_base
|
||||
build_flags =
|
||||
${crowpanel_large.build_flags}
|
||||
${crowpanel_large_esp32s3_base.build_flags}
|
||||
-D VIEW_320x240
|
||||
|
||||
13
variants/gat562_mesh_trial_tracker/platformio.ini
Normal file
13
variants/gat562_mesh_trial_tracker/platformio.ini
Normal file
@@ -0,0 +1,13 @@
|
||||
; The very slick RAK wireless RAK 4631 / 4630 board - Unified firmware for 5005/19003, with or without OLED RAK 1921
|
||||
[env:gat562_mesh_trial_tracker]
|
||||
extends = nrf52840_base
|
||||
board = gat562_mesh_trial_tracker
|
||||
board_check = true
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/gat562_mesh_trial_tracker -D GAT562_MESH_TRIAL_TRACKER
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/gat562_mesh_trial_tracker>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
45
variants/gat562_mesh_trial_tracker/variant.cpp
Normal file
45
variants/gat562_mesh_trial_tracker/variant.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "variant.h"
|
||||
#include "nrf.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[] = {
|
||||
// P0
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
|
||||
// P1
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
// LED1 & LED2
|
||||
pinMode(PIN_LED1, OUTPUT);
|
||||
ledOff(PIN_LED1);
|
||||
|
||||
pinMode(PIN_LED2, OUTPUT);
|
||||
ledOff(PIN_LED2);
|
||||
|
||||
// 3V3 Power Rail
|
||||
pinMode(PIN_3V3_EN, OUTPUT);
|
||||
digitalWrite(PIN_3V3_EN, HIGH);
|
||||
}
|
||||
288
variants/gat562_mesh_trial_tracker/variant.h
Normal file
288
variants/gat562_mesh_trial_tracker/variant.h
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _VARIANT_GAT562_MESH_TRIAL_TRACKER_
|
||||
#define _VARIANT_GAT562_MESH_TRIAL_TRACKER_
|
||||
|
||||
#define GAT562_MESH_TRIAL_TRACKER
|
||||
|
||||
// led pin 2 (blue), see https://github.com/meshtastic/firmware/blob/master/src/mesh/NodeDB.cpp#L723
|
||||
#define RAK4630
|
||||
|
||||
/** Master clock frequency */
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
#define USE_LFXO // Board uses 32khz crystal for LF
|
||||
// define USE_LFRC // Board uses RC for LF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// Number of pins defined in PinDescription array
|
||||
#define PINS_COUNT (48)
|
||||
#define NUM_DIGITAL_PINS (48)
|
||||
#define NUM_ANALOG_INPUTS (6)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED1 (35)
|
||||
#define PIN_LED2 (36)
|
||||
|
||||
#define LED_BUILTIN PIN_LED1
|
||||
#define LED_CONN PIN_LED2
|
||||
|
||||
#define LED_GREEN PIN_LED1
|
||||
#define LED_BLUE PIN_LED2
|
||||
|
||||
#define LED_STATE_ON 1 // State when LED is litted
|
||||
|
||||
/*
|
||||
* Buttons
|
||||
*/
|
||||
|
||||
#define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
|
||||
#define BUTTON_NEED_PULLUP
|
||||
#define PIN_BUTTON2 12
|
||||
#define PIN_BUTTON3 24
|
||||
#define PIN_BUTTON4 25
|
||||
|
||||
/*
|
||||
* Analog pins
|
||||
*/
|
||||
#define PIN_A0 (5)
|
||||
#define PIN_A1 (31)
|
||||
#define PIN_A2 (28)
|
||||
#define PIN_A3 (29)
|
||||
#define PIN_A4 (30)
|
||||
#define PIN_A5 (31)
|
||||
#define PIN_A6 (0xff)
|
||||
#define PIN_A7 (0xff)
|
||||
|
||||
static const uint8_t A0 = PIN_A0;
|
||||
static const uint8_t A1 = PIN_A1;
|
||||
static const uint8_t A2 = PIN_A2;
|
||||
static const uint8_t A3 = PIN_A3;
|
||||
static const uint8_t A4 = PIN_A4;
|
||||
static const uint8_t A5 = PIN_A5;
|
||||
static const uint8_t A6 = PIN_A6;
|
||||
static const uint8_t A7 = PIN_A7;
|
||||
#define ADC_RESOLUTION 14
|
||||
|
||||
// Other pins
|
||||
#define PIN_AREF (2)
|
||||
#define PIN_NFC1 (9)
|
||||
#define PIN_NFC2 (10)
|
||||
|
||||
static const uint8_t AREF = PIN_AREF;
|
||||
|
||||
/*
|
||||
* Serial interfaces
|
||||
*/
|
||||
#define PIN_SERIAL1_RX (15)
|
||||
#define PIN_SERIAL1_TX (16)
|
||||
|
||||
// Connected to Jlink CDC
|
||||
#define PIN_SERIAL2_RX (8)
|
||||
#define PIN_SERIAL2_TX (6)
|
||||
|
||||
/*
|
||||
* SPI Interfaces
|
||||
*/
|
||||
#define SPI_INTERFACES_COUNT 2
|
||||
|
||||
#define PIN_SPI_MISO (45)
|
||||
#define PIN_SPI_MOSI (44)
|
||||
#define PIN_SPI_SCK (43)
|
||||
|
||||
#define PIN_SPI1_MISO (29) // (0 + 29)
|
||||
#define PIN_SPI1_MOSI (30) // (0 + 30)
|
||||
#define PIN_SPI1_SCK (3) // (0 + 3)
|
||||
|
||||
static const uint8_t SS = 42;
|
||||
static const uint8_t MOSI = PIN_SPI_MOSI;
|
||||
static const uint8_t MISO = PIN_SPI_MISO;
|
||||
static const uint8_t SCK = PIN_SPI_SCK;
|
||||
|
||||
/*
|
||||
* eink display pins
|
||||
*/
|
||||
|
||||
// #define PIN_EINK_CS (0 + 26)
|
||||
// #define PIN_EINK_BUSY (0 + 4)
|
||||
// #define PIN_EINK_DC (0 + 17)
|
||||
// #define PIN_EINK_RES (-1)
|
||||
// #define PIN_EINK_SCLK (0 + 3)
|
||||
// #define PIN_EINK_MOSI (0 + 30) // also called SDI
|
||||
|
||||
// #define USE_EINK
|
||||
|
||||
// Display - OLED connected via I2C
|
||||
#define HAS_SCREEN 1
|
||||
#define USE_SSD1306
|
||||
|
||||
// RAKRGB
|
||||
// #define HAS_NCP5623
|
||||
|
||||
/*
|
||||
* Wire Interfaces
|
||||
*/
|
||||
#define WIRE_INTERFACES_COUNT 1
|
||||
|
||||
#define PIN_WIRE_SDA (13)
|
||||
#define PIN_WIRE_SCL (14)
|
||||
|
||||
// QSPI Pins
|
||||
#define PIN_QSPI_SCK 3
|
||||
#define PIN_QSPI_CS 26
|
||||
#define PIN_QSPI_IO0 30
|
||||
#define PIN_QSPI_IO1 29
|
||||
#define PIN_QSPI_IO2 28
|
||||
#define PIN_QSPI_IO3 2
|
||||
|
||||
// On-board QSPI Flash
|
||||
#define EXTERNAL_FLASH_DEVICES IS25LP080D
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
|
||||
/* @note RAK5005-O GPIO mapping to RAK4631 GPIO ports
|
||||
RAK5005-O <-> nRF52840
|
||||
IO1 <-> P0.17 (Arduino GPIO number 17)
|
||||
IO2 <-> P1.02 (Arduino GPIO number 34)
|
||||
IO3 <-> P0.21 (Arduino GPIO number 21)
|
||||
IO4 <-> P0.04 (Arduino GPIO number 4)
|
||||
IO5 <-> P0.09 (Arduino GPIO number 9)
|
||||
IO6 <-> P0.10 (Arduino GPIO number 10)
|
||||
IO7 <-> P0.28 (Arduino GPIO number 28)
|
||||
SW1 <-> P0.01 (Arduino GPIO number 1)
|
||||
A0 <-> P0.04/AIN2 (Arduino Analog A2
|
||||
A1 <-> P0.31/AIN7 (Arduino Analog A7
|
||||
SPI_CS <-> P0.26 (Arduino GPIO number 26)
|
||||
*/
|
||||
|
||||
// RAK4630 LoRa module
|
||||
|
||||
/* Setup of the SX1262 LoRa module ( https://docs.rakwireless.com/Product-Categories/WisBlock/RAK4631/Datasheet/ )
|
||||
|
||||
P1.10 NSS SPI NSS (Arduino GPIO number 42)
|
||||
P1.11 SCK SPI CLK (Arduino GPIO number 43)
|
||||
P1.12 MOSI SPI MOSI (Arduino GPIO number 44)
|
||||
P1.13 MISO SPI MISO (Arduino GPIO number 45)
|
||||
P1.14 BUSY BUSY signal (Arduino GPIO number 46)
|
||||
P1.15 DIO1 DIO1 event interrupt (Arduino GPIO number 47)
|
||||
P1.06 NRESET NRESET manual reset of the SX1262 (Arduino GPIO number 38)
|
||||
|
||||
Important for successful SX1262 initialization:
|
||||
|
||||
* Setup DIO2 to control the antenna switch
|
||||
* Setup DIO3 to control the TCXO power supply
|
||||
* Setup the SX1262 to use it's DCDC regulator and not the LDO
|
||||
* RAK4630 schematics show GPIO P1.07 connected to the antenna switch, but it should not be initialized, as DIO2 will do the
|
||||
control of the antenna switch
|
||||
|
||||
SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
|
||||
|
||||
*/
|
||||
|
||||
// configure the SET pin on the RAK12039 sensor board to disable the sensor while not reading
|
||||
// air quality telemetry. PIN_NFC2 doesn't seem to be used anywhere else in the codebase, but if
|
||||
// you're having problems with your node behaving weirdly when a RAK12039 board isn't connected,
|
||||
// try disabling this.
|
||||
// #define PMSA003I_ENABLE_PIN PIN_NFC2
|
||||
|
||||
// #define DETECTION_SENSOR_EN 4
|
||||
|
||||
#define USE_SX1262
|
||||
#define SX126X_CS (42)
|
||||
#define SX126X_DIO1 (47)
|
||||
#define SX126X_BUSY (46)
|
||||
#define SX126X_RESET (38)
|
||||
// #define SX126X_TXEN (39)
|
||||
// #define SX126X_RXEN (37)
|
||||
#define SX126X_POWER_EN (37)
|
||||
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
|
||||
// Testing USB detection
|
||||
#define NRF_APM
|
||||
|
||||
// enables 3.3V periphery like GPS or IO Module
|
||||
// Do not toggle this for GPS power savings
|
||||
#define PIN_3V3_EN (34)
|
||||
|
||||
// RAK1910 GPS module
|
||||
// If using the wisblock GPS module and pluged into Port A on WisBlock base
|
||||
// IO1 is hooked to PPS (pin 12 on header) = gpio 17
|
||||
// IO2 is hooked to GPS RESET = gpio 34, but it can not be used to this because IO2 is ALSO used to control 3V3_S power (1 is on).
|
||||
// Therefore must be 1 to keep peripherals powered
|
||||
// Power is on the controllable 3V3_S rail
|
||||
// #define PIN_GPS_RESET (34)
|
||||
// #define PIN_GPS_EN PIN_3V3_EN
|
||||
#define PIN_GPS_PPS (17) // Pulse per second input from the GPS
|
||||
|
||||
#define GPS_BAUDRATE 9600
|
||||
|
||||
#define GPS_RX_PIN PIN_SERIAL1_RX
|
||||
#define GPS_TX_PIN PIN_SERIAL1_TX
|
||||
|
||||
// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press
|
||||
|
||||
// RAK12002 RTC Module
|
||||
// #define RV3028_RTC (uint8_t)0b1010010
|
||||
|
||||
// RAK18001 Buzzer in Slot C
|
||||
// #define PIN_BUZZER 21 // IO3 is PWM2
|
||||
// NEW: set this via protobuf instead!
|
||||
|
||||
// Battery
|
||||
// The battery sense is hooked to pin A0 (5)
|
||||
#define BATTERY_PIN PIN_A0
|
||||
// and has 12 bit resolution
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||
#define BATTERY_SENSE_RESOLUTION 4096.0
|
||||
#undef AREF_VOLTAGE
|
||||
#define AREF_VOLTAGE 3.0
|
||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||
#define ADC_MULTIPLIER 1.73
|
||||
|
||||
// #define HAS_RTC 1
|
||||
|
||||
// #define HAS_ETHERNET 1
|
||||
|
||||
// #define RAK_4631 1
|
||||
|
||||
// #define PIN_ETHERNET_RESET 21
|
||||
// #define PIN_ETHERNET_SS PIN_EINK_CS
|
||||
// #define ETH_SPI_PORT SPI1
|
||||
// #define AQ_SET_PIN 10
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Arduino objects - C++ only
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
62
variants/heltec_mesh_node_t114-inkhud/custom_build_tasks.py
Normal file
62
variants/heltec_mesh_node_t114-inkhud/custom_build_tasks.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# Simplifies DIY InkHUD builds, with presets for several common E-Ink displays
|
||||
# - build using custom task in Platformio's "Project Tasks" panel
|
||||
# - build with `pio run -e <variant> -t build_weact_154` (or similar)
|
||||
|
||||
# Silence trunk's objections to the import statements
|
||||
# trunk-ignore-all(ruff/F821)
|
||||
# trunk-ignore-all(flake8/F821)
|
||||
|
||||
from SCons.Script import COMMAND_LINE_TARGETS
|
||||
|
||||
Import("env")
|
||||
Import("projenv")
|
||||
|
||||
# Custom targets
|
||||
# These wrappers just run the normal build task under a different target name
|
||||
# We intercept the build later on, based on the target name
|
||||
env.AddTarget(
|
||||
name="build_weact_154",
|
||||
dependencies=["buildprog"],
|
||||
actions=None,
|
||||
title='Build (WeAct 1.54")',
|
||||
)
|
||||
env.AddTarget(
|
||||
name="build_weact_213",
|
||||
dependencies=["buildprog"],
|
||||
actions=None,
|
||||
title='Build (WeAct 2.13")',
|
||||
)
|
||||
env.AddTarget(
|
||||
name="build_weact_290",
|
||||
dependencies=["buildprog"],
|
||||
actions=None,
|
||||
title='Build (WeAct 2.9")',
|
||||
)
|
||||
env.AddTarget(
|
||||
name="build_weact_420",
|
||||
dependencies=["buildprog"],
|
||||
actions=None,
|
||||
title='Build (WeAct 4.2")',
|
||||
)
|
||||
|
||||
# Check whether a build was started via one of our custom targets above
|
||||
|
||||
if "build_weact_154" in COMMAND_LINE_TARGETS:
|
||||
print('Building for WeAct 1.54" Display')
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "ZJY200200_0154DAAMFGN"))
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
|
||||
|
||||
elif "build_weact_213" in COMMAND_LINE_TARGETS:
|
||||
print('Building for WeAct 2.13" Display')
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "HINK_E0213A289"))
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "10"))
|
||||
|
||||
elif "build_weact_290" in COMMAND_LINE_TARGETS:
|
||||
print('Building for WeAct 2.9" Display')
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "ZJY128296_029EAAMFGN"))
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
|
||||
|
||||
elif "build_weact_420" in COMMAND_LINE_TARGETS:
|
||||
print('Building for WeAct 4.2" Display')
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DRIVER", "HINK_E042A87"))
|
||||
projenv["CPPDEFINES"].append(("INKHUD_BUILDCONF_DISPLAYRESILIENCE", "15"))
|
||||
95
variants/heltec_mesh_node_t114-inkhud/nicheGraphics.h
Normal file
95
variants/heltec_mesh_node_t114-inkhud/nicheGraphics.h
Normal file
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
// InkHUD-specific components
|
||||
// ---------------------------
|
||||
#include "graphics/niche/InkHUD/InkHUD.h"
|
||||
|
||||
// Applets
|
||||
#include "graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/DM/DMApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/Positions/PositionsApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h"
|
||||
#include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h"
|
||||
|
||||
// Shared NicheGraphics components
|
||||
// --------------------------------
|
||||
#include "graphics/niche/Drivers/EInk/HINK_E0213A289.h" // WeAct 2.13"
|
||||
#include "graphics/niche/Drivers/EInk/HINK_E042A87.h" // WeAct 4.2"
|
||||
#include "graphics/niche/Drivers/EInk/ZJY128296_029EAAMFGN.h" // WeAct 2.9"
|
||||
#include "graphics/niche/Drivers/EInk/ZJY200200_0154DAAMFGN.h" // WeACt 1.54"
|
||||
|
||||
#include "graphics/niche/Inputs/TwoButton.h"
|
||||
|
||||
#if !defined(INKHUD_BUILDCONF_DRIVER) || !defined(INKHUD_BUILDCONF_DISPLAYRESILIENCE)
|
||||
// cppcheck-suppress preprocessorErrorDirective
|
||||
#error If not using a DIY preset, display model and resilience must be set manually
|
||||
#endif
|
||||
|
||||
void setupNicheGraphics()
|
||||
{
|
||||
using namespace NicheGraphics;
|
||||
|
||||
// SPI
|
||||
// -----------------------------
|
||||
SPI1.begin();
|
||||
|
||||
// Driver
|
||||
// -----------------------------
|
||||
|
||||
// Use E-Ink driver
|
||||
Drivers::EInk *driver = new Drivers::INKHUD_BUILDCONF_DRIVER;
|
||||
driver->begin(&SPI1, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY, PIN_EINK_RES);
|
||||
|
||||
// InkHUD
|
||||
// ----------------------------
|
||||
|
||||
InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance();
|
||||
|
||||
// Set the driver
|
||||
inkhud->setDriver(driver);
|
||||
|
||||
// Set how many FAST updates per FULL update.
|
||||
inkhud->setDisplayResilience(INKHUD_BUILDCONF_DISPLAYRESILIENCE); // Suggest roughly ten
|
||||
|
||||
// Prepare fonts
|
||||
InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252;
|
||||
InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252;
|
||||
|
||||
// Init settings, and customize defaults
|
||||
// Values ignored individually if found saved to flash
|
||||
inkhud->persistence->settings.rotation = (driver->height > driver->width ? 1 : 0); // Rotate 90deg to landscape, if needed
|
||||
inkhud->persistence->settings.userTiles.maxCount = 4;
|
||||
inkhud->persistence->settings.optionalFeatures.batteryIcon = true;
|
||||
|
||||
// Pick applets
|
||||
// Note: order of applets determines priority of "auto-show" feature
|
||||
inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet);
|
||||
inkhud->addApplet("DMs", new InkHUD::DMApplet, true, false, 3); // Default on tile 3
|
||||
inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0), true, false, 2); // Default on tile 2
|
||||
inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1));
|
||||
inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true, false, 1); // Default on tile 1
|
||||
inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet, true, false, 0); // Default on tile 0
|
||||
inkhud->addApplet("Heard", new InkHUD::HeardApplet, true); // Background
|
||||
|
||||
// Start running InkHUD
|
||||
inkhud->begin();
|
||||
|
||||
// Buttons
|
||||
// --------------------------
|
||||
|
||||
Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // Shared NicheGraphics component
|
||||
|
||||
// #0: Main User Button
|
||||
buttons->setWiring(0, Inputs::TwoButton::getUserButtonPin());
|
||||
buttons->setHandlerShortPress(0, [inkhud]() { inkhud->shortpress(); });
|
||||
buttons->setHandlerLongPress(0, [inkhud]() { inkhud->longpress(); });
|
||||
|
||||
buttons->start();
|
||||
}
|
||||
|
||||
#endif
|
||||
19
variants/heltec_mesh_node_t114-inkhud/platformio.ini
Normal file
19
variants/heltec_mesh_node_t114-inkhud/platformio.ini
Normal file
@@ -0,0 +1,19 @@
|
||||
[env:heltec-mesh-node-t114-inkhud]
|
||||
board_level = extra
|
||||
extends = nrf52840_base, inkhud
|
||||
board = heltec_mesh_node_t114
|
||||
board_check = true
|
||||
build_flags =
|
||||
${nrf52840_base.build_flags}
|
||||
${inkhud.build_flags}
|
||||
-I variants/heltec_mesh_node_t114-inkhud
|
||||
build_src_filter =
|
||||
${nrf52_base.build_src_filter}
|
||||
${inkhud.build_src_filter}
|
||||
lib_deps =
|
||||
${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX
|
||||
${nrf52840_base.lib_deps}
|
||||
lewisxhe/PCF8563_Library@^1.0.1
|
||||
extra_scripts =
|
||||
${env.extra_scripts}
|
||||
variants/diy/nrf52_promicro_diy_tcxo/custom_build_tasks.py ; Add to PIO's Project Tasks pane: preset builds for common displays
|
||||
38
variants/heltec_mesh_node_t114-inkhud/variant.cpp
Normal file
38
variants/heltec_mesh_node_t114-inkhud/variant.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "variant.h"
|
||||
#include "nrf.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[] = {
|
||||
// P0 - pins 0 and 1 are hardwired for xtal and should never be enabled
|
||||
0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
|
||||
// P1
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
// LED1
|
||||
pinMode(PIN_LED1, OUTPUT);
|
||||
ledOff(PIN_LED1);
|
||||
}
|
||||
175
variants/heltec_mesh_node_t114-inkhud/variant.h
Normal file
175
variants/heltec_mesh_node_t114-inkhud/variant.h
Normal file
@@ -0,0 +1,175 @@
|
||||
// Unlike many other InkHUD variants, this environment does require its own variant.h file
|
||||
// This is because the default T114 variant maps SPI1 pins to the optional TFT display, and those pins are not broken out
|
||||
|
||||
#ifndef _VARIANT_HELTEC_NRF_
|
||||
#define _VARIANT_HELTEC_NRF_
|
||||
/** Master clock frequency */
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
#define USE_LFXO // Board uses 32khz crystal for LF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#define HELTEC_MESH_NODE_T114
|
||||
|
||||
// Number of pins defined in PinDescription array
|
||||
#define PINS_COUNT (48)
|
||||
#define NUM_DIGITAL_PINS (48)
|
||||
#define NUM_ANALOG_INPUTS (1)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED1 (32 + 3) // green (confirmed on 1.0 board)
|
||||
#define LED_BLUE PIN_LED1 // fake for bluefruit library
|
||||
#define LED_GREEN PIN_LED1
|
||||
#define LED_BUILTIN LED_GREEN
|
||||
#define LED_STATE_ON 0 // State when LED is lit
|
||||
|
||||
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||
#define NEOPIXEL_COUNT 2 // How many neopixels are connected
|
||||
#define NEOPIXEL_DATA 14 // gpio pin used to send data to the neopixels
|
||||
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // type of neopixels in use
|
||||
|
||||
/*
|
||||
* Buttons
|
||||
*/
|
||||
#define PIN_BUTTON1 (32 + 10)
|
||||
// #define PIN_BUTTON2 (0 + 18) // 0.18 is labeled on the board as RESET but we configure it in the bootloader as a regular
|
||||
// GPIO
|
||||
|
||||
/*
|
||||
No longer populated on PCB
|
||||
*/
|
||||
#define PIN_SERIAL2_RX (0 + 9)
|
||||
#define PIN_SERIAL2_TX (0 + 10)
|
||||
// #define PIN_SERIAL2_EN (0 + 17)
|
||||
|
||||
/*
|
||||
* I2C
|
||||
*/
|
||||
|
||||
#define WIRE_INTERFACES_COUNT 2
|
||||
|
||||
// I2C bus 0
|
||||
// Routed to footprint for PCF8563TS RTC
|
||||
// Not populated on T114 V1, maybe in future?
|
||||
#define PIN_WIRE_SDA (0 + 26) // P0.26
|
||||
#define PIN_WIRE_SCL (0 + 27) // P0.27
|
||||
|
||||
// I2C bus 1
|
||||
// Available on header pins, for general use
|
||||
#define PIN_WIRE1_SDA (0 + 16) // P0.16
|
||||
#define PIN_WIRE1_SCL (0 + 13) // P0.13
|
||||
|
||||
/*
|
||||
* Lora radio
|
||||
*/
|
||||
|
||||
#define USE_SX1262
|
||||
// #define USE_SX1268
|
||||
#define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead
|
||||
#define LORA_CS (0 + 24)
|
||||
#define SX126X_DIO1 (0 + 20)
|
||||
// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching
|
||||
// #define SX1262_DIO3 (0 + 21)
|
||||
// This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not drive from the
|
||||
// main
|
||||
// CPU?
|
||||
#define SX126X_BUSY (0 + 17)
|
||||
#define SX126X_RESET (0 + 25)
|
||||
// Not really an E22 but TTGO seems to be trying to clone that
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
|
||||
/*
|
||||
* E-Ink DIY
|
||||
*/
|
||||
#define PIN_EINK_MOSI (0 + 8) // also called SDA
|
||||
#define PIN_EINK_SCLK (0 + 7)
|
||||
#define PIN_EINK_CS (32 + 12)
|
||||
#define PIN_EINK_DC (32 + 14)
|
||||
#define PIN_EINK_RES (0 + 5)
|
||||
#define PIN_EINK_BUSY (32 + 15)
|
||||
|
||||
/*
|
||||
* GPS pins
|
||||
*/
|
||||
|
||||
#define GPS_L76K
|
||||
|
||||
// #define PIN_GPS_RESET (32 + 6) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
|
||||
#define GPS_RESET_MODE LOW
|
||||
// #define PIN_GPS_EN (21)
|
||||
#define VEXT_ENABLE (0 + 21)
|
||||
#define PERIPHERAL_WARMUP_MS 1000 // Make sure I2C QuickLink has stable power before continuing
|
||||
#define VEXT_ON_VALUE HIGH
|
||||
// #define GPS_EN_ACTIVE HIGH
|
||||
#define PIN_GPS_STANDBY (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake
|
||||
#define PIN_GPS_PPS (32 + 4)
|
||||
// Seems to be missing on this new board
|
||||
// #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS
|
||||
#define GPS_TX_PIN (32 + 5) // This is for bits going TOWARDS the CPU
|
||||
#define GPS_RX_PIN (32 + 7) // This is for bits going TOWARDS the GPS
|
||||
|
||||
#define GPS_THREAD_INTERVAL 50
|
||||
|
||||
#define PIN_SERIAL1_RX GPS_TX_PIN
|
||||
#define PIN_SERIAL1_TX GPS_RX_PIN
|
||||
|
||||
// PCF8563 RTC Module
|
||||
#define PCF8563_RTC 0x51
|
||||
|
||||
/*
|
||||
* SPI Interfaces
|
||||
*/
|
||||
#define SPI_INTERFACES_COUNT 2
|
||||
|
||||
// For LORA, spi 0
|
||||
#define PIN_SPI_MISO (0 + 23)
|
||||
#define PIN_SPI_MOSI (0 + 22)
|
||||
#define PIN_SPI_SCK (0 + 19)
|
||||
|
||||
#define PIN_SPI1_MISO -1
|
||||
#define PIN_SPI1_MOSI PIN_EINK_MOSI
|
||||
#define PIN_SPI1_SCK PIN_EINK_SCLK
|
||||
|
||||
// #define PIN_PWR_EN (0 + 6)
|
||||
|
||||
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
||||
// #define USE_SEGGER
|
||||
|
||||
// Battery
|
||||
// The battery sense is hooked to pin A0 (4)
|
||||
// it is defined in the anlaolgue pin section of this file
|
||||
// and has 12 bit resolution
|
||||
|
||||
#define ADC_CTRL 6
|
||||
#define ADC_CTRL_ENABLED HIGH
|
||||
#define BATTERY_PIN 4
|
||||
#define ADC_RESOLUTION 14
|
||||
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||
#define BATTERY_SENSE_RESOLUTION 4096.0
|
||||
#undef AREF_VOLTAGE
|
||||
#define AREF_VOLTAGE 3.0
|
||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||
#define ADC_MULTIPLIER (4.90F)
|
||||
|
||||
#define HAS_RTC 0
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Arduino objects - C++ only
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user