diff --git a/.github/actions/build-variant/action.yml b/.github/actions/build-variant/action.yml
index 80d2a56bb..b3303d393 100644
--- a/.github/actions/build-variant/action.yml
+++ b/.github/actions/build-variant/action.yml
@@ -51,6 +51,7 @@ runs:
file: build.tar
target: build.tar
token: ${{ inputs.github_token }}
+ version: tags/v2.5.3
- name: Unpack web ui
if: inputs.include-web-ui == 'true'
diff --git a/.github/workflows/build_raspbian.yml b/.github/workflows/build_raspbian.yml
index 1fd8fad30..e857ae635 100644
--- a/.github/workflows/build_raspbian.yml
+++ b/.github/workflows/build_raspbian.yml
@@ -13,8 +13,8 @@ jobs:
- name: Install libbluetooth
shell: bash
run: |
- apt-get update -y --fix-missing
- apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
+ sudo apt-get update -y --fix-missing
+ sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
- name: Checkout code
uses: actions/checkout@v4
diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml
index efdbd2637..37164b758 100644
--- a/.github/workflows/main_matrix.yml
+++ b/.github/workflows/main_matrix.yml
@@ -203,6 +203,7 @@ jobs:
./device-*.sh
./device-*.bat
./littlefs-*.bin
+ ./littlefswebui-*.bin
./bleota*bin
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30
diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml
index 75b4bd6ea..040712e1d 100644
--- a/.trunk/trunk.yaml
+++ b/.trunk/trunk.yaml
@@ -1,6 +1,6 @@
version: 0.1
cli:
- version: 1.22.7
+ version: 1.22.8
plugins:
sources:
- id: trunk
@@ -8,20 +8,20 @@ plugins:
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- - trufflehog@3.83.2
+ - trufflehog@3.83.6
- yamllint@1.35.1
- bandit@1.7.10
- - checkov@3.2.277
+ - checkov@3.2.287
- terrascan@1.19.9
- trivy@0.56.2
#- trufflehog@3.63.2-rc0
- taplo@0.9.3
- - ruff@0.7.2
+ - ruff@0.7.3
- isort@5.13.2
- markdownlint@0.42.0
- oxipng@9.1.2
- svgo@3.3.2
- - actionlint@1.7.3
+ - actionlint@1.7.4
- flake8@7.1.1
- hadolint@2.12.0
- shfmt@3.6.0
diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini
index 1f17bc691..d6a756bec 100644
--- a/arch/esp32/esp32.ini
+++ b/arch/esp32/esp32.ini
@@ -46,7 +46,7 @@ lib_deps =
${radiolib_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.2
- https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
+ https://github.com/dbinfrago/libpax.git#3cdc0371c375676a97967547f4065607d4c53fd1
lewisxhe/XPowersLib@^0.2.6
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
rweather/Crypto@^0.4.0
diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini
index ff0cfcbf5..d75f86306 100644
--- a/arch/nrf52/nrf52.ini
+++ b/arch/nrf52/nrf52.ini
@@ -15,6 +15,8 @@ build_flags =
-Isrc/platform/nrf52
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
-DMESHTASTIC_EXCLUDE_AUDIO=1
+ -DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
+ -DMAX_NUM_NODES=80
build_src_filter =
${arduino_base.build_src_filter} - - - - - - - - - -
diff --git a/arch/rp2xx0/rp2040.ini b/arch/rp2xx0/rp2040.ini
index 17b5df618..85efa583c 100644
--- a/arch/rp2xx0/rp2040.ini
+++ b/arch/rp2xx0/rp2040.ini
@@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
-platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12
+platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico 4.2.1
extends = arduino_base
-platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.0.3
+platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#996c3bfab9758f12c07aa20cc6d352e630c16987 ; 4.2.1 with fix for sporadic hangs
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
diff --git a/arch/rp2xx0/rp2350.ini b/arch/rp2xx0/rp2350.ini
index 33bb36ad1..6daf59bdf 100644
--- a/arch/rp2xx0/rp2350.ini
+++ b/arch/rp2xx0/rp2350.ini
@@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2350_base]
-platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9e55f6db5c56b9867c69fe473f388beea4546672
+platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico 4.2.1
extends = arduino_base
-platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#a6ab6e1f95bc1428d667d55ea7173c0744acc03c ; 4.0.2+
+platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#96c3bfab9758f12c07aa20cc6d352e630c16987 ; 4.2.1 with fix for sporadic hangs
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@@ -22,4 +22,4 @@ lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
- rweather/Crypto
+ rweather/Crypto
\ No newline at end of file
diff --git a/bin/base64_to_hex.py b/bin/base64_to_hex.py
new file mode 100644
index 000000000..07c559b9e
--- /dev/null
+++ b/bin/base64_to_hex.py
@@ -0,0 +1,33 @@
+import sys
+import base64
+
+def base64_to_hex_string(b64_string):
+ try:
+ # Decode the Base64 string to raw bytes
+ decoded_bytes = base64.b64decode(b64_string)
+ except Exception as e:
+ raise ValueError(f"Invalid Base64 input: {e}")
+
+ # Check if the decoded result is exactly 32 bytes
+ if len(decoded_bytes) != 32:
+ raise ValueError("Decoded Base64 input must be exactly 32 bytes.")
+
+ # Convert each byte to its hex representation
+ hex_values = [f"0x{byte:02x}" for byte in decoded_bytes]
+
+ # Join the formatted hex values with commas
+ formatted_output = "{ " + ", ".join(hex_values) + " };"
+ return formatted_output
+
+if __name__ == "__main__":
+ # Check if a Base64 string was provided in command line arguments
+ if len(sys.argv) != 2:
+ print("Usage: python script.py ")
+ sys.exit(1)
+
+ b64_string = sys.argv[1]
+ try:
+ formatted_hex = base64_to_hex_string(b64_string)
+ print(formatted_hex)
+ except ValueError as e:
+ print(e)
diff --git a/bin/build-esp32.sh b/bin/build-esp32.sh
index adb6ab12a..f8d808ced 100755
--- a/bin/build-esp32.sh
+++ b/bin/build-esp32.sh
@@ -35,6 +35,11 @@ cp $SRCBIN $OUTDIR/$basename-update.bin
echo "Building Filesystem for ESP32 targets"
pio run --environment $1 -t buildfs
+cp .pio/build/$1/littlefs.bin $OUTDIR/littlefswebui-$VERSION.bin
+# Remove webserver files from the filesystem and rebuild
+ls -l data/static # Diagnostic list of files
+rm -rf data/static
+pio run --environment $1 -t buildfs
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR
diff --git a/bin/build-native.sh b/bin/build-native.sh
index e8ed61bcf..cda77b064 100755
--- a/bin/build-native.sh
+++ b/bin/build-native.sh
@@ -27,5 +27,4 @@ rm -r $OUTDIR/* || true
platformio pkg update --environment native || platformioFailed
pio run --environment native || platformioFailed
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
-cp bin/device-install.* $OUTDIR
-cp bin/device-update.* $OUTDIR
+cp bin/native-install.* $OUTDIR
diff --git a/bin/device-install.bat b/bin/device-install.bat
index f8ca9e408..c18be89a8 100755
--- a/bin/device-install.bat
+++ b/bin/device-install.bat
@@ -1,6 +1,7 @@
@ECHO OFF
set PYTHON=python
+set WEB_APP=0
:: Determine the correct esptool command to use
where esptool >nul 2>&1
@@ -12,13 +13,14 @@ if %ERRORLEVEL% EQU 0 (
goto GETOPTS
:HELP
-echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME]
+echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME] [--web]
echo Flash image file to device, but first erasing and writing system information
echo.
echo -h Display this help and exit
echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%)
echo -f FILENAME The .bin file to flash. Custom to your device type and region.
+echo --web Flash WEB APP.
goto EOF
:GETOPTS
@@ -27,6 +29,7 @@ if /I "%1"=="--help" goto HELP
if /I "%1"=="-F" set "FILENAME=%2" & SHIFT
if /I "%1"=="-p" set ESPTOOL_PORT=%2 & SHIFT
if /I "%1"=="-P" set PYTHON=%2 & SHIFT
+if /I "%1"=="--web" set WEB_APP=1 & SHIFT
SHIFT
IF NOT "__%1__"=="____" goto GETOPTS
@@ -49,8 +52,14 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
) else (
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota-s3.bin
)
- for %%f in (littlefs-*.bin) do (
- %ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
+ IF %WEB_APP%==1 (
+ for %%f in (littlefswebui-*.bin) do (
+ %ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
+ )
+ ) else (
+ for %%f in (littlefs-*.bin) do (
+ %ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
+ )
)
) else (
echo "Invalid file: %FILENAME%"
diff --git a/bin/device-install.sh b/bin/device-install.sh
index b2a5684ee..e09c61ba6 100755
--- a/bin/device-install.sh
+++ b/bin/device-install.sh
@@ -1,6 +1,7 @@
#!/bin/sh
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
+WEB_APP=false
# Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
@@ -19,16 +20,26 @@ set -e
# Usage info
show_help() {
cat <SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
+ audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_MCLK);
audioOut->SetGain(0.2);
};
diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp
index 0ea1309cc..238359952 100644
--- a/src/ButtonThread.cpp
+++ b/src/ButtonThread.cpp
@@ -1,4 +1,5 @@
#include "ButtonThread.h"
+#include "../userPrefs.h"
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_GPS
#include "GPS.h"
@@ -26,12 +27,12 @@ using namespace concurrency;
ButtonThread *buttonThread; // Declared extern in header
volatile ButtonThread::ButtonEventType ButtonThread::btnEvent = ButtonThread::BUTTON_EVENT_NONE;
-#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
+#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
OneButton ButtonThread::userButton; // Get reference to static member
#endif
ButtonThread::ButtonThread() : OSThread("Button")
{
-#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
+#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
#if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
@@ -39,7 +40,12 @@ ButtonThread::ButtonThread() : OSThread("Button")
LOG_DEBUG("Use GPIO%02d for button", settingsMap[user]);
}
#elif defined(BUTTON_PIN)
- int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
+#if !defined(USERPREFS_BUTTON_PIN)
+ int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
+#endif
+#ifdef USERPREFS_BUTTON_PIN
+ int pin = config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN; // Resolved button pin
+#endif
#if defined(HELTEC_CAPSULE_SENSOR_V3)
this->userButton = OneButton(pin, false, false);
#elif defined(BUTTON_ACTIVE_LOW)
@@ -59,7 +65,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
#endif
#endif
-#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
+#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
userButton.attachClick(userButtonPressed);
userButton.setClickMs(BUTTON_CLICK_MS);
userButton.setPressMs(BUTTON_LONGPRESS_MS);
@@ -102,7 +108,7 @@ int32_t ButtonThread::runOnce()
// If the button is pressed we suppress CPU sleep until release
canSleep = true; // Assume we should not keep the board awake
-#if defined(BUTTON_PIN)
+#if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN)
userButton.tick();
canSleep &= userButton.isIdle();
#elif defined(ARCH_PORTDUINO)
@@ -130,7 +136,12 @@ int32_t ButtonThread::runOnce()
return 50;
}
#ifdef BUTTON_PIN
+#if !defined(USERPREFS_BUTTON_PIN)
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
+#endif
+#if defined(USERPREFS_BUTTON_PIN)
+ if (((config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN) !=
+#endif
moduleConfig.canned_message.inputbroker_pin_press) ||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
!moduleConfig.canned_message.enabled) {
@@ -244,7 +255,12 @@ void ButtonThread::attachButtonInterrupts()
#elif defined(BUTTON_PIN)
// Interrupt for user button, during normal use. Improves responsiveness.
attachInterrupt(
+#if !defined(USERPREFS_BUTTON_PIN)
config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN,
+#endif
+#if defined(USERPREFS_BUTTON_PIN)
+ config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN,
+#endif
[]() {
ButtonThread::userButton.tick();
runASAP = true;
@@ -273,8 +289,13 @@ void ButtonThread::detachButtonInterrupts()
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
detachInterrupt(settingsMap[user]);
#elif defined(BUTTON_PIN)
+#if !defined(USERPREFS_BUTTON_PIN)
detachInterrupt(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
#endif
+#if defined(USERPREFS_BUTTON_PIN)
+ detachInterrupt(config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN);
+#endif
+#endif
#ifdef BUTTON_PIN_ALT
detachInterrupt(BUTTON_PIN_ALT);
@@ -315,7 +336,7 @@ void ButtonThread::userButtonMultiPressed(void *callerThread)
// Non-static method, runs during callback. Grabs info while still valid
void ButtonThread::storeClickCount()
{
-#ifdef BUTTON_PIN
+#if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN)
multipressClickCount = userButton.getNumberClicks();
#endif
}
diff --git a/src/ButtonThread.h b/src/ButtonThread.h
index 9cd7b3dac..a01a1718f 100644
--- a/src/ButtonThread.h
+++ b/src/ButtonThread.h
@@ -38,7 +38,7 @@ class ButtonThread : public concurrency::OSThread
void storeClickCount();
private:
-#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
+#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
static OneButton userButton; // Static - accessed from an interrupt
#endif
#ifdef BUTTON_PIN_ALT
diff --git a/src/Power.cpp b/src/Power.cpp
index ab09cd08c..a354b74e2 100644
--- a/src/Power.cpp
+++ b/src/Power.cpp
@@ -251,7 +251,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasINA()) {
- LOG_DEBUG("Use INA on I2C addr 0x%x for device battery voltage", config.power.device_battery_ina_address);
return getINAVoltage();
}
#endif
@@ -271,7 +270,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
config.power.adc_multiplier_override > 0 ? config.power.adc_multiplier_override : ADC_MULTIPLIER;
// Do not call analogRead() often.
const uint32_t min_read_interval = 5000;
- if (!Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
+ if (!initial_read_done || !Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
last_read_time_ms = millis();
uint32_t raw = 0;
@@ -614,7 +613,7 @@ void Power::shutdown()
#ifdef PIN_LED3
ledOff(PIN_LED3);
#endif
- doDeepSleep(DELAY_FOREVER, false);
+ doDeepSleep(DELAY_FOREVER, false, false);
#endif
}
diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp
index 7aa454d34..00dd6c942 100644
--- a/src/PowerFSM.cpp
+++ b/src/PowerFSM.cpp
@@ -55,9 +55,14 @@ static void sdsEnter()
{
LOG_DEBUG("State: SDS");
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
- doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false);
+ doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, false);
}
+static void lowBattSDSEnter()
+{
+ LOG_DEBUG("State: Lower batt SDS");
+ doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, true);
+}
extern Power *power;
static void shutdownEnter()
@@ -247,6 +252,7 @@ static void bootEnter()
State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN");
State stateSDS(sdsEnter, NULL, NULL, "SDS");
+State stateLowBattSDS(lowBattSDSEnter, NULL, NULL, "SDS");
State stateLS(lsEnter, lsIdle, lsExit, "LS");
State stateNB(nbEnter, NULL, NULL, "NB");
State stateDARK(darkEnter, NULL, NULL, "DARK");
@@ -291,12 +297,12 @@ void PowerFSM_setup()
"Press"); // Allow button to work while in serial API
// Handle critically low power battery by forcing deep sleep
- powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
- powerFSM.add_transition(&stateLS, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
- powerFSM.add_transition(&stateNB, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
- powerFSM.add_transition(&stateDARK, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
- powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
- powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
+ powerFSM.add_transition(&stateBOOT, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
+ powerFSM.add_transition(&stateLS, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
+ powerFSM.add_transition(&stateNB, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
+ powerFSM.add_transition(&stateDARK, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
+ powerFSM.add_transition(&stateON, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
+ powerFSM.add_transition(&stateSERIAL, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
// Handle being told to power off
powerFSM.add_transition(&stateBOOT, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
diff --git a/src/configuration.h b/src/configuration.h
index 1f98cb60f..01ec64bea 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -149,6 +149,7 @@ along with this program. If not, see .
#define NAU7802_ADDR 0x2A
#define MAX30102_ADDR 0x57
#define MLX90614_ADDR_DEF 0x5A
+#define CGRADSENS_ADDR 0x66
// -----------------------------------------------------------------------------
// ACCELEROMETER
diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h
index fe34d379f..525ebeaa2 100644
--- a/src/detect/ScanI2C.h
+++ b/src/detect/ScanI2C.h
@@ -64,7 +64,8 @@ class ScanI2C
ICM20948,
MAX30102,
TPS65233,
- MPR121KB
+ MPR121KB,
+ CGRADSENS
} DeviceType;
// typedef uint8_t DeviceAddress;
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index 7b655527c..604b2d2f3 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -317,19 +317,34 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
break;
case INA3221_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
- LOG_DEBUG("Register MFG_UID: 0x%x", registerValue);
+ LOG_DEBUG("Register MFG_UID FE: 0x%x", registerValue);
if (registerValue == 0x5449) {
LOG_INFO("INA3221 sensor found at address 0x%x", (uint8_t)addr.address);
type = INA3221;
} else {
- LOG_INFO("DFRobot Lark weather station found at address 0x%x", (uint8_t)addr.address);
- type = DFROBOT_LARK;
+ /* check the first 2 bytes of the 6 byte response register
+ LARK FW 1.0 should return:
+ RESPONSE_STATUS STATUS_SUCCESS (0x53)
+ RESPONSE_CMD CMD_GET_VERSION (0x05)
+ RESPONSE_LEN_L 0x02
+ RESPONSE_LEN_H 0x00
+ RESPONSE_PAYLOAD 0x01
+ RESPONSE_PAYLOAD+1 0x00
+ */
+ registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 2);
+ LOG_DEBUG("Register MFG_UID 05: 0x%x", registerValue);
+ if (registerValue == 0x5305) {
+ LOG_INFO("DFRobot Lark weather station found at address 0x%x", (uint8_t)addr.address);
+ type = DFROBOT_LARK;
+ }
+ // else: probably a RAK12500/UBLOX GPS on I2C
}
break;
case MCP9808_ADDR:
// We need to check for STK8BAXX first, since register 0x07 is new data flag for the z-axis and can produce some
// weird result. and register 0x00 doesn't seems to be colliding with MCP9808 and LIS3DH chips.
{
+#ifdef HAS_STK8XXX
// Check register 0x00 for 0x8700 response to ID STK8BA53 chip.
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 2);
if (registerValue == 0x8700) {
@@ -337,6 +352,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
LOG_INFO("STK8BAXX accelerometer found");
break;
}
+#endif
// Check register 0x07 for 0x0400 response to ID MCP9808 chip.
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
@@ -468,6 +484,16 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
}
break;
+ case CGRADSENS_ADDR:
+ // Register 0x00 of the RadSens sensor contains is product identifier 0x7D
+ registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
+ if (registerValue == 0x7D) {
+ type = CGRADSENS;
+ LOG_INFO("ClimateGuard RadSens Geiger-Muller Sensor found");
+ break;
+ }
+ break;
+
default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated", addr.address);
}
diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp
index 099a21f82..a6db85950 100644
--- a/src/gps/GPS.cpp
+++ b/src/gps/GPS.cpp
@@ -788,7 +788,8 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
void GPS::writePinEN(bool on)
{
// Abort: if conflict with Canned Messages when using Wisblock(?)
- if (HW_VENDOR == meshtastic_HardwareModel_RAK4631 && (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
+ if ((HW_VENDOR == meshtastic_HardwareModel_RAK4631 || HW_VENDOR == meshtastic_HardwareModel_WISMESH_TAP) &&
+ (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
return;
// Write and log
diff --git a/src/gps/GPS.h b/src/gps/GPS.h
index cd61c5444..cb970f7db 100644
--- a/src/gps/GPS.h
+++ b/src/gps/GPS.h
@@ -64,6 +64,95 @@ const char *getDOPString(uint32_t dop);
*/
class GPS : private concurrency::OSThread
{
+ public:
+ meshtastic_Position p = meshtastic_Position_init_default;
+
+ /** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
+ * implementations. Those boards will set this public variable to a custom implementation.
+ *
+ * Normally set by GPS::createGPS()
+ */
+ GpioVirtPin *enablePin = NULL;
+
+ virtual ~GPS();
+
+ /** We will notify this observable anytime GPS state has changed meaningfully */
+ Observable newStatus;
+
+ /**
+ * Returns true if we succeeded
+ */
+ virtual bool setup();
+
+ // re-enable the thread
+ void enable();
+
+ // Disable the thread
+ int32_t disable() override;
+
+ // toggle between enabled/disabled
+ void toggleGpsMode();
+
+ // Change the power state of the GPS - for power saving / shutdown
+ void setPowerState(GPSPowerState newState, uint32_t sleepMs = 0);
+
+ /// Returns true if we have acquired GPS lock.
+ virtual bool hasLock();
+
+ /// Returns true if there's valid data flow with the chip.
+ virtual bool hasFlow();
+
+ /// Return true if we are connected to a GPS
+ bool isConnected() const { return hasGPS; }
+
+ bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; }
+
+ // Empty the input buffer as quickly as possible
+ void clearBuffer();
+
+ virtual bool factoryReset();
+
+ // Creates an instance of the GPS class.
+ // Returns the new instance or null if the GPS is not present.
+ static GPS *createGps();
+
+ // Wake the GPS hardware - ready for an update
+ void up();
+
+ // Let the GPS hardware save power between updates
+ void down();
+
+ protected:
+ /// Record that we have a GPS
+ void setConnected();
+
+ /** Subclasses should look for serial rx characters here and feed it to their GPS parser
+ *
+ * Return true if we received a valid message from the GPS
+ */
+ virtual bool whileActive();
+
+ /**
+ * Perform any processing that should be done only while the GPS is awake and looking for a fix.
+ * Override this method to check for new locations
+ *
+ * @return true if we've acquired a time
+ */
+ virtual bool lookForTime();
+
+ /**
+ * Perform any processing that should be done only while the GPS is awake and looking for a fix.
+ * Override this method to check for new locations
+ *
+ * @return true if we've acquired a new location
+ */
+ virtual bool lookForLocation();
+
+ GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
+
+ private:
+ GPS() : concurrency::OSThread("GPS") {}
+
TinyGPSPlus reader;
uint8_t fixQual = 0; // fix quality from GPGGA
uint32_t lastChecksumFailCount = 0;
@@ -75,7 +164,6 @@ class GPS : private concurrency::OSThread
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
uint8_t fixType = 0; // fix type from GPGSA
#endif
- private:
#if GPS_BAUDRATE_FIXED
// if GPS_BAUDRATE is specified in variant, only try that.
const int serialSpeeds[1] = {GPS_BAUDRATE};
@@ -113,7 +201,6 @@ class GPS : private concurrency::OSThread
CallbackObserver notifyDeepSleepObserver = CallbackObserver(this, &GPS::prepareDeepSleep);
- public:
/** If !NULL we will use this serial port to construct our GPS */
#if defined(ARCH_RP2040)
static SerialUART *_serial_gps;
@@ -167,53 +254,6 @@ class GPS : private concurrency::OSThread
const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
- meshtastic_Position p = meshtastic_Position_init_default;
-
- /** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
- * implementations. Those boards will set this public variable to a custom implementation.
- *
- * Normally set by GPS::createGPS()
- */
- GpioVirtPin *enablePin = NULL;
-
- GPS() : concurrency::OSThread("GPS") {}
-
- virtual ~GPS();
-
- /** We will notify this observable anytime GPS state has changed meaningfully */
- Observable newStatus;
-
- /**
- * Returns true if we succeeded
- */
- virtual bool setup();
-
- // re-enable the thread
- void enable();
-
- // Disable the thread
- int32_t disable() override;
-
- // toggle between enabled/disabled
- void toggleGpsMode();
-
- // Change the power state of the GPS - for power saving / shutdown
- void setPowerState(GPSPowerState newState, uint32_t sleepMs = 0);
-
- /// Returns true if we have acquired GPS lock.
- virtual bool hasLock();
-
- /// Returns true if there's valid data flow with the chip.
- virtual bool hasFlow();
-
- /// Return true if we are connected to a GPS
- bool isConnected() const { return hasGPS; }
-
- bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; }
-
- // Empty the input buffer as quickly as possible
- void clearBuffer();
-
// Create a ublox packet for editing in memory
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
@@ -229,59 +269,6 @@ class GPS : private concurrency::OSThread
GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
- virtual bool factoryReset();
-
- // Creates an instance of the GPS class.
- // Returns the new instance or null if the GPS is not present.
- static GPS *createGps();
-
- // Wake the GPS hardware - ready for an update
- void up();
-
- // Let the GPS hardware save power between updates
- void down();
-
- protected:
- /**
- * Perform any processing that should be done only while the GPS is awake and looking for a fix.
- * Override this method to check for new locations
- *
- * @return true if we've acquired a time
- */
-
- /**
- * Perform any processing that should be done only while the GPS is awake and looking for a fix.
- * Override this method to check for new locations
- *
- * @return true if we've acquired a new location
- */
-
- /// Record that we have a GPS
- void setConnected();
-
- /** Subclasses should look for serial rx characters here and feed it to their GPS parser
- *
- * Return true if we received a valid message from the GPS
- */
- virtual bool whileActive();
-
- /**
- * Perform any processing that should be done only while the GPS is awake and looking for a fix.
- * Override this method to check for new locations
- *
- * @return true if we've acquired a time
- */
- virtual bool lookForTime();
-
- /**
- * Perform any processing that should be done only while the GPS is awake and looking for a fix.
- * Override this method to check for new locations
- *
- * @return true if we've acquired a new location
- */
- virtual bool lookForLocation();
-
- private:
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);
@@ -320,10 +307,7 @@ class GPS : private concurrency::OSThread
uint8_t fixeddelayCtr = 0;
const char *powerStateToString();
-
- protected:
- GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
};
extern GPS *gps;
-#endif // Exclude GPS
\ No newline at end of file
+#endif // Exclude GPS
diff --git a/src/gps/NMEAWPL.cpp b/src/gps/NMEAWPL.cpp
index f528c4607..f4249ca62 100644
--- a/src/gps/NMEAWPL.cpp
+++ b/src/gps/NMEAWPL.cpp
@@ -23,7 +23,7 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, c
{
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
char type = isCaltopoMode ? 'P' : 'N';
- uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
+ uint32_t len = snprintf(buf, bufsz, "\r\n$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(),
geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(), name);
diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index bd0133740..a875c11d6 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -101,9 +101,9 @@ std::vector moduleFrames;
static char ourId[5];
// vector where symbols (string) are displayed in bottom corner of display.
-std::vector functionSymbals;
-// string displayed in bottom right corner of display. Created from elements in functionSymbals vector
-std::string functionSymbalString = "";
+std::vector functionSymbol;
+// string displayed in bottom right corner of display. Created from elements in functionSymbol vector
+std::string functionSymbolString = "";
#if HAS_GPS
// GeoCoord object for the screen
@@ -243,10 +243,10 @@ static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
static void drawFunctionOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
{
// LOG_DEBUG("Draw function overlay");
- if (functionSymbals.begin() != functionSymbals.end()) {
+ if (functionSymbol.begin() != functionSymbol.end()) {
char buf[64];
display->setFont(FONT_SMALL);
- snprintf(buf, sizeof(buf), "%s", functionSymbalString.c_str());
+ snprintf(buf, sizeof(buf), "%s", functionSymbolString.c_str());
display->drawString(SCREEN_WIDTH - display->getStringWidth(buf), SCREEN_HEIGHT - FONT_HEIGHT_SMALL, buf);
}
}
@@ -396,7 +396,7 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
display->drawFastImage(x, y, 16, 8, imgBuffer);
}
-#ifdef T_WATCH_S3
+#if defined(DISPLAY_CLOCK_FRAME)
void Screen::drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode, float scale)
{
@@ -958,55 +958,65 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
display->setColor(WHITE);
#ifndef EXCLUDE_EMOJI
- if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\U0001F44D") == 0) {
+ const char *msg = reinterpret_cast(mp.decoded.payload.bytes);
+ if (strcmp(msg, "\U0001F44D") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
thumbup);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\U0001F44E") == 0) {
+ } else if (strcmp(msg, "\U0001F44E") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
thumbdown);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "❓") == 0) {
+ } else if (strcmp(msg, "\U0001F60A") == 0 || strcmp(msg, "\U0001F600") == 0 || strcmp(msg, "\U0001F642") == 0 ||
+ strcmp(msg, "\U0001F609") == 0 ||
+ strcmp(msg, "\U0001F601") == 0) { // matches 5 different common smileys, so that the phone user doesn't have to
+ // remember which one is compatible
+ display->drawXbm(x + (SCREEN_WIDTH - smiley_width) / 2,
+ y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - smiley_height) / 2 + 2 + 5, smiley_width, smiley_height,
+ smiley);
+ } else if (strcmp(msg, "❓") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - question_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - question_height) / 2 + 2 + 5, question_width, question_height,
question);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "‼️") == 0) {
+ } else if (strcmp(msg, "‼️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - bang_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - bang_height) / 2 + 2 + 5,
bang_width, bang_height, bang);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\U0001F4A9") == 0) {
+ } else if (strcmp(msg, "\U0001F4A9") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - poo_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - poo_height) / 2 + 2 + 5,
poo_width, poo_height, poo);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\xf0\x9f\xa4\xa3") == 0) {
+ } else if (strcmp(msg, "\U0001F923") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - haha_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - haha_height) / 2 + 2 + 5,
haha_width, haha_height, haha);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\U0001F44B") == 0) {
+ } else if (strcmp(msg, "\U0001F44B") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - wave_icon_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - wave_icon_height) / 2 + 2 + 5, wave_icon_width,
wave_icon_height, wave_icon);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\U0001F920") == 0) {
+ } else if (strcmp(msg, "\U0001F920") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - cowboy_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cowboy_height) / 2 + 2 + 5, cowboy_width, cowboy_height,
cowboy);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\U0001F42D") == 0) {
+ } else if (strcmp(msg, "\U0001F42D") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - deadmau5_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - deadmau5_height) / 2 + 2 + 5, deadmau5_width, deadmau5_height,
deadmau5);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
+ } else if (strcmp(msg, "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - sun_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - sun_height) / 2 + 2 + 5,
sun_width, sun_height, sun);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\u2614") == 0) {
+ } else if (strcmp(msg, "\u2614") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - rain_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - rain_height) / 2 + 2 + 10,
rain_width, rain_height, rain);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "☁️") == 0) {
+ } else if (strcmp(msg, "☁️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - cloud_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cloud_height) / 2 + 2 + 5, cloud_width, cloud_height, cloud);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "🌫️") == 0) {
+ } else if (strcmp(msg, "🌫️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - fog_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - fog_height) / 2 + 2 + 5,
fog_width, fog_height, fog);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "\xf0\x9f\x98\x88") == 0) {
+ } else if (strcmp(msg, "\U0001F608") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - devil_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil);
- } else if (strcmp(reinterpret_cast(mp.decoded.payload.bytes), "♥️") == 0) {
+ } else if (strcmp(msg, "♥️") == 0 || strcmp(msg, "\U0001F9E1") == 0 || strcmp(msg, "\U00002763") == 0 ||
+ strcmp(msg, "\U00002764") == 0 || strcmp(msg, "\U0001F495") == 0 || strcmp(msg, "\U0001F496") == 0 ||
+ strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F496") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart);
} else {
@@ -2058,7 +2068,7 @@ void Screen::setFrames(FrameFocus focus)
focus = FOCUS_FAULT; // Change our "focus" parameter, to ensure we show the fault frame
}
-#ifdef T_WATCH_S3
+#if defined(DISPLAY_CLOCK_FRAME)
normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame;
#endif
@@ -2242,24 +2252,24 @@ void Screen::decreaseBrightness()
/* TO DO: add little popup in center of screen saying what brightness level it is set to*/
}
-void Screen::setFunctionSymbal(std::string sym)
+void Screen::setFunctionSymbol(std::string sym)
{
- if (std::find(functionSymbals.begin(), functionSymbals.end(), sym) == functionSymbals.end()) {
- functionSymbals.push_back(sym);
- functionSymbalString = "";
- for (auto symbol : functionSymbals) {
- functionSymbalString = symbol + " " + functionSymbalString;
+ if (std::find(functionSymbol.begin(), functionSymbol.end(), sym) == functionSymbol.end()) {
+ functionSymbol.push_back(sym);
+ functionSymbolString = "";
+ for (auto symbol : functionSymbol) {
+ functionSymbolString = symbol + " " + functionSymbolString;
}
setFastFramerate();
}
}
-void Screen::removeFunctionSymbal(std::string sym)
+void Screen::removeFunctionSymbol(std::string sym)
{
- functionSymbals.erase(std::remove(functionSymbals.begin(), functionSymbals.end(), sym), functionSymbals.end());
- functionSymbalString = "";
- for (auto symbol : functionSymbals) {
- functionSymbalString = symbol + " " + functionSymbalString;
+ functionSymbol.erase(std::remove(functionSymbol.begin(), functionSymbol.end(), sym), functionSymbol.end());
+ functionSymbolString = "";
+ for (auto symbol : functionSymbol) {
+ functionSymbolString = symbol + " " + functionSymbolString;
}
setFastFramerate();
}
@@ -2689,7 +2699,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
int Screen::handleInputEvent(const InputEvent *event)
{
-#ifdef T_WATCH_S3
+#if defined(DISPLAY_CLOCK_FRAME)
// For the T-Watch, intercept touches to the 'toggle digital/analog watch face' button
uint8_t watchFaceFrame = error_code ? 1 : 0;
@@ -2747,4 +2757,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
-#endif // HAS_SCREEN
\ No newline at end of file
+#endif // HAS_SCREEN
diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h
index 3066c0c17..2a77ca575 100644
--- a/src/graphics/Screen.h
+++ b/src/graphics/Screen.h
@@ -24,8 +24,8 @@ class Screen
void startFirmwareUpdateScreen() {}
void increaseBrightness() {}
void decreaseBrightness() {}
- void setFunctionSymbal(std::string) {}
- void removeFunctionSymbal(std::string) {}
+ void setFunctionSymbol(std::string) {}
+ void removeFunctionSymbol(std::string) {}
void startAlert(const char *) {}
void endAlert() {}
};
@@ -282,8 +282,8 @@ class Screen : public concurrency::OSThread
void increaseBrightness();
void decreaseBrightness();
- void setFunctionSymbal(std::string sym);
- void removeFunctionSymbal(std::string sym);
+ void setFunctionSymbol(std::string sym);
+ void removeFunctionSymbol(std::string sym);
/// Stops showing the boot screen.
void stopBootScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BOOT_SCREEN}); }
@@ -554,7 +554,7 @@ class Screen : public concurrency::OSThread
static void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
-#ifdef T_WATCH_S3
+#if defined(DISPLAY_CLOCK_FRAME)
static void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
@@ -605,4 +605,4 @@ class Screen : public concurrency::OSThread
} // namespace graphics
-#endif
\ No newline at end of file
+#endif
diff --git a/src/graphics/images.h b/src/graphics/images.h
index 2b0854a33..b757dcf30 100644
--- a/src/graphics/images.h
+++ b/src/graphics/images.h
@@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
-#ifdef T_WATCH_S3
+#if defined(DISPLAY_CLOCK_FRAME)
const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0xe3, 0x1f,
0xf3, 0x3f, 0x33, 0x30, 0x33, 0x33, 0x33, 0x33, 0x03, 0x33, 0xff, 0x33,
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};
@@ -56,6 +56,16 @@ static unsigned char thumbdown[] PROGMEM = {
0x80, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
};
+#define smiley_height 30
+#define smiley_width 30
+static unsigned char smiley[] PROGMEM = {
+ 0x00, 0xfe, 0x0f, 0x00, 0x80, 0x01, 0x30, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x02,
+ 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x10, 0x02, 0x0e, 0x0e, 0x10, 0x02, 0x09, 0x12, 0x10,
+ 0x01, 0x09, 0x12, 0x20, 0x01, 0x0f, 0x1e, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
+ 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x81, 0x00, 0x20, 0x20,
+ 0x82, 0x00, 0x20, 0x10, 0x02, 0x01, 0x10, 0x10, 0x04, 0x02, 0x08, 0x08, 0x04, 0xfc, 0x07, 0x08, 0x08, 0x00, 0x00, 0x04,
+ 0x10, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x40, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0xfe, 0x0f, 0x00};
+
#define question_height 25
#define question_width 25
static unsigned char question[] PROGMEM = {
diff --git a/src/main.cpp b/src/main.cpp
index 10f163291..7b866f331 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -617,6 +617,7 @@ void setup()
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102)
+ SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS)
i2cScanner.reset();
#endif
diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp
index d5e00b837..81ea72381 100644
--- a/src/mesh/FloodingRouter.cpp
+++ b/src/mesh/FloodingRouter.cpp
@@ -29,6 +29,17 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
if (Router::cancelSending(p->from, p->id))
txRelayCanceled++;
}
+
+ /* If the original transmitter is doing retransmissions (hopStart equals hopLimit) for a reliable transmission, e.g., when
+ the ACK got lost, we will handle the packet again to make sure it gets an ACK to its packet. */
+ bool isRepeated = p->hop_start > 0 && p->hop_start == p->hop_limit;
+ if (isRepeated) {
+ LOG_DEBUG("Repeated reliable tx");
+ if (!perhapsRebroadcast(p) && isToUs(p) && p->want_ack) {
+ sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
+ }
+ }
+
return true;
}
@@ -41,14 +52,8 @@ bool FloodingRouter::isRebroadcaster()
config.device.rebroadcast_mode != meshtastic_Config_DeviceConfig_RebroadcastMode_NONE;
}
-void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
+bool FloodingRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p)
{
- bool isAckorReply = (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) && (p->decoded.request_id != 0);
- if (isAckorReply && !isToUs(p) && !isBroadcast(p->to)) {
- // do not flood direct message that is ACKed or replied to
- LOG_DEBUG("Rxd an ACK/reply not for me, cancel rebroadcast");
- Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
- }
if (!isToUs(p) && (p->hop_limit > 0) && !isFromUs(p)) {
if (p->id != 0) {
if (isRebroadcaster()) {
@@ -67,6 +72,8 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
// Note: we are careful to resend using the original senders node id
// We are careful not to call our hooked version of send() - because we don't want to check this again
Router::send(tosend);
+
+ return true;
} else {
LOG_DEBUG("No rebroadcast: Role = CLIENT_MUTE or Rebroadcast Mode = NONE");
}
@@ -74,6 +81,21 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
LOG_DEBUG("Ignore 0 id broadcast");
}
}
+
+ return false;
+}
+
+void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
+{
+ bool isAckorReply = (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) && (p->decoded.request_id != 0);
+ if (isAckorReply && !isToUs(p) && !isBroadcast(p->to)) {
+ // do not flood direct message that is ACKed or replied to
+ LOG_DEBUG("Rxd an ACK/reply not for me, cancel rebroadcast");
+ Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
+ }
+
+ perhapsRebroadcast(p);
+
// handle the packet as normal
Router::sniffReceived(p, c);
-}
+}
\ No newline at end of file
diff --git a/src/mesh/FloodingRouter.h b/src/mesh/FloodingRouter.h
index 0ed2b5582..52614f391 100644
--- a/src/mesh/FloodingRouter.h
+++ b/src/mesh/FloodingRouter.h
@@ -31,6 +31,10 @@ class FloodingRouter : public Router, protected PacketHistory
private:
bool isRebroadcaster();
+ /** Check if we should rebroadcast this packet, and do so if needed
+ * @return true if rebroadcasted */
+ bool perhapsRebroadcast(const meshtastic_MeshPacket *p);
+
public:
/**
* Constructor
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index ed6e59ac1..44a28eea2 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -61,6 +61,16 @@ meshtastic_LocalConfig config;
meshtastic_LocalModuleConfig moduleConfig;
meshtastic_ChannelFile channelFile;
+#ifdef USERPREFS_USE_ADMIN_KEY_0
+static unsigned char userprefs_admin_key_0[] = USERPREFS_USE_ADMIN_KEY_0;
+#endif
+#ifdef USERPREFS_USE_ADMIN_KEY_1
+static unsigned char userprefs_admin_key_1[] = USERPREFS_USE_ADMIN_KEY_1;
+#endif
+#ifdef USERPREFS_USE_ADMIN_KEY_2
+static unsigned char userprefs_admin_key_2[] = USERPREFS_USE_ADMIN_KEY_2;
+#endif
+
bool meshtastic_DeviceState_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
{
if (ostream) {
@@ -114,7 +124,7 @@ NodeDB::NodeDB()
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
int saveWhat = 0;
- bool hasUniqueId = false;
+ // bool hasUniqueId = false;
// Get device unique id
#if defined(ARCH_ESP32) && defined(ESP_EFUSE_OPTIONAL_UNIQUE_ID)
uint32_t unique_id[4];
@@ -246,6 +256,31 @@ NodeDB::NodeDB()
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
config.position.gps_enabled = 0;
}
+#ifdef USERPREFS_FIXED_GPS
+ if (myNodeInfo.reboot_count == 1) { // Check if First boot ever or after Factory Reset.
+ meshtastic_Position fixedGPS = meshtastic_Position_init_default;
+#ifdef USERPREFS_FIXED_GPS_LAT
+ fixedGPS.latitude_i = (int32_t)(USERPREFS_FIXED_GPS_LAT * 1e7);
+ fixedGPS.has_latitude_i = true;
+#endif
+#ifdef USERPREFS_FIXED_GPS_LON
+ fixedGPS.longitude_i = (int32_t)(USERPREFS_FIXED_GPS_LON * 1e7);
+ fixedGPS.has_longitude_i = true;
+#endif
+#ifdef USERPREFS_FIXED_GPS_ALT
+ fixedGPS.altitude = USERPREFS_FIXED_GPS_ALT;
+ fixedGPS.has_altitude = true;
+#endif
+#if defined(USERPREFS_FIXED_GPS_LAT) && defined(USERPREFS_FIXED_GPS_LON)
+ fixedGPS.location_source = meshtastic_Position_LocSource_LOC_MANUAL;
+ config.has_position = true;
+ info->has_position = true;
+ info->position = TypeConversions::ConvertToPositionLite(fixedGPS);
+ nodeDB->setLocalPosition(fixedGPS);
+ config.position.fixed_position = true;
+#endif
+ }
+#endif
saveToDisk(saveWhat);
}
@@ -381,11 +416,37 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#else
config.lora.ignore_mqtt = false;
#endif
-#ifdef USERPREFS_USE_ADMIN_KEY
- memcpy(config.security.admin_key[0].bytes, USERPREFS_ADMIN_KEY, 32);
- config.security.admin_key[0].size = 32;
- config.security.admin_key_count = 1;
+ // Initialize admin_key_count to zero
+ byte numAdminKeys = 0;
+
+#ifdef USERPREFS_USE_ADMIN_KEY_0
+ // Check if USERPREFS_ADMIN_KEY_0 is non-empty
+ if (sizeof(userprefs_admin_key_0) > 0) {
+ memcpy(config.security.admin_key[0].bytes, userprefs_admin_key_0, 32);
+ config.security.admin_key[0].size = 32;
+ numAdminKeys++;
+ }
#endif
+
+#ifdef USERPREFS_USE_ADMIN_KEY_1
+ // Check if USERPREFS_ADMIN_KEY_1 is non-empty
+ if (sizeof(userprefs_admin_key_1) > 0) {
+ memcpy(config.security.admin_key[1].bytes, userprefs_admin_key_1, 32);
+ config.security.admin_key[1].size = 32;
+ numAdminKeys++;
+ }
+#endif
+
+#ifdef USERPREFS_USE_ADMIN_KEY_2
+ // Check if USERPREFS_ADMIN_KEY_2 is non-empty
+ if (sizeof(userprefs_admin_key_2) > 0) {
+ memcpy(config.security.admin_key[2].bytes, userprefs_admin_key_2, 32);
+ config.security.admin_key[2].size = 32;
+ numAdminKeys++;
+ }
+#endif
+ config.security.admin_key_count = numAdminKeys;
+
if (shouldPreserveKey) {
config.security.private_key.size = 32;
memcpy(config.security.private_key.bytes, private_key_temp, config.security.private_key.size);
@@ -438,8 +499,13 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#else
bool hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
#endif
+#ifdef USERPREFS_FIXED_BLUETOOTH
+ config.bluetooth.fixed_pin = USERPREFS_FIXED_BLUETOOTH;
+ config.bluetooth.mode = meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
+#else
config.bluetooth.mode = hasScreen ? meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN
: meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
+#endif
// for backward compat, default position flags are ALT+MSL
config.position.position_flags =
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL |
@@ -452,7 +518,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#ifdef RAK4630
config.display.wake_on_tap_or_motion = true;
#endif
-#ifdef T_WATCH_S3
+#if defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR)
config.display.screen_on_secs = 30;
config.display.wake_on_tap_or_motion = true;
#endif
@@ -476,7 +542,7 @@ void NodeDB::initConfigIntervals()
config.display.screen_on_secs = default_screen_on_secs;
-#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014)
+#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014) || defined(SENSECAP_INDICATOR)
config.power.is_power_saving = true;
config.display.screen_on_secs = 30;
config.power.wait_bluetooth_secs = 30;
@@ -793,8 +859,13 @@ void NodeDB::loadFromDisk()
0; // Mark the current device state as completely unusable, so that if we fail reading the entire file from
// disk we will still factoryReset to restore things.
+#ifdef ARCH_ESP32
+ if (FSCom.exists("/static/static"))
+ rmDir("/static/static"); // Remove bad static web files bundle from initial 2.5.13 release
+#endif
+
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
- auto state = loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES * sizeof(meshtastic_NodeInfo),
+ auto state = loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES_FS * sizeof(meshtastic_NodeInfo),
sizeof(meshtastic_DeviceState), &meshtastic_DeviceState_msg, &devicestate);
// See https://github.com/meshtastic/firmware/issues/4184#issuecomment-2269390786
@@ -813,6 +884,10 @@ void NodeDB::loadFromDisk()
meshNodes = &devicestate.node_db_lite;
numMeshNodes = devicestate.node_db_lite.size();
}
+ if (numMeshNodes > MAX_NUM_NODES) {
+ LOG_WARN("Node count %d exceeds MAX_NUM_NODES %d, truncating", numMeshNodes, MAX_NUM_NODES);
+ numMeshNodes = MAX_NUM_NODES;
+ }
meshNodes->resize(MAX_NUM_NODES);
state = loadProto(configFileName, meshtastic_LocalConfig_size, sizeof(meshtastic_LocalConfig), &meshtastic_LocalConfig_msg,
@@ -828,6 +903,54 @@ void NodeDB::loadFromDisk()
}
}
+ // Make sure we load hard coded admin keys even when the configuration file has none.
+ // Initialize admin_key_count to zero
+ byte numAdminKeys = 0;
+ uint16_t sum = 0;
+#ifdef USERPREFS_USE_ADMIN_KEY_0
+ for (uint8_t b = 0; b < 32; b++) {
+ sum += config.security.admin_key[0].bytes[b];
+ }
+ if (sum == 0) {
+ numAdminKeys += 1;
+ LOG_INFO("Admin 0 key zero. Loading hard coded key from user preferences.");
+ memcpy(config.security.admin_key[0].bytes, userprefs_admin_key_0, 32);
+ config.security.admin_key[0].size = 32;
+ config.security.admin_key_count = numAdminKeys;
+ saveToDisk(SEGMENT_CONFIG);
+ }
+#endif
+
+#ifdef USERPREFS_USE_ADMIN_KEY_1
+ sum = 0;
+ for (uint8_t b = 0; b < 32; b++) {
+ sum += config.security.admin_key[1].bytes[b];
+ }
+ if (sum == 0) {
+ numAdminKeys += 1;
+ LOG_INFO("Admin 1 key zero. Loading hard coded key from user preferences.");
+ memcpy(config.security.admin_key[1].bytes, userprefs_admin_key_1, 32);
+ config.security.admin_key[1].size = 32;
+ config.security.admin_key_count = numAdminKeys;
+ saveToDisk(SEGMENT_CONFIG);
+ }
+#endif
+
+#ifdef USERPREFS_USE_ADMIN_KEY_2
+ sum = 0;
+ for (uint8_t b = 0; b < 32; b++) {
+ sum += config.security.admin_key[2].bytes[b];
+ }
+ if (sum == 0) {
+ numAdminKeys += 1;
+ LOG_INFO("Admin 2 key zero. Loading hard coded key from user preferences.");
+ memcpy(config.security.admin_key[2].bytes, userprefs_admin_key_2, 32);
+ config.security.admin_key[2].size = 32;
+ config.security.admin_key_count = numAdminKeys;
+ saveToDisk(SEGMENT_CONFIG);
+ }
+#endif
+
state = loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig),
&meshtastic_LocalModuleConfig_msg, &moduleConfig);
if (state != LoadFileResult::LOAD_SUCCESS) {
@@ -1231,12 +1354,12 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
int oldestBoringIndex = -1;
for (int i = 1; i < numMeshNodes; i++) {
// Simply the oldest non-favorite node
- if (!meshNodes->at(i).is_favorite && meshNodes->at(i).last_heard < oldest) {
+ if (!meshNodes->at(i).is_favorite && !meshNodes->at(i).is_ignored && meshNodes->at(i).last_heard < oldest) {
oldest = meshNodes->at(i).last_heard;
oldestIndex = i;
}
// The oldest "boring" node
- if (!meshNodes->at(i).is_favorite && meshNodes->at(i).user.public_key.size == 0 &&
+ if (!meshNodes->at(i).is_favorite && !meshNodes->at(i).is_ignored && meshNodes->at(i).user.public_key.size == 0 &&
meshNodes->at(i).last_heard < oldestBoring) {
oldestBoring = meshNodes->at(i).last_heard;
oldestBoringIndex = i;
@@ -1286,4 +1409,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
LOG_ERROR("A critical failure occurred, portduino is exiting");
exit(2);
#endif
-}
+}
\ No newline at end of file
diff --git a/src/mesh/PacketHistory.cpp b/src/mesh/PacketHistory.cpp
index 94337d092..6eb4b6ea1 100644
--- a/src/mesh/PacketHistory.cpp
+++ b/src/mesh/PacketHistory.cpp
@@ -38,13 +38,6 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd
seenRecently = false;
}
- /* If the original transmitter is doing retransmissions (hopStart equals hopLimit) for a reliable transmission, e.g., when the
- ACK got lost, we will handle the packet again to make sure it gets an ACK/response to its packet. */
- if (seenRecently && p->hop_start > 0 && p->hop_start == p->hop_limit) {
- LOG_DEBUG("Repeated reliable tx");
- seenRecently = false;
- }
-
if (seenRecently) {
LOG_DEBUG("Found existing packet record for fr=0x%x,to=0x%x,id=0x%x", p->from, p->to, p->id);
}
diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp
index f0d137e2c..53b66ff0a 100644
--- a/src/mesh/RadioInterface.cpp
+++ b/src/mesh/RadioInterface.cpp
@@ -601,8 +601,6 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
// LOG_DEBUG("Send queued packet on mesh (txGood=%d,rxGood=%d,rxBad=%d)", rf95.txGood(), rf95.rxGood(), rf95.rxBad());
assert(p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag); // It should have already been encoded by now
- lastTxStart = millis();
-
radioBuffer.header.from = p->from;
radioBuffer.header.to = p->to;
radioBuffer.header.id = p->id;
diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp
index 23ef3d6f1..5f82a41ce 100644
--- a/src/mesh/RadioLibInterface.cpp
+++ b/src/mesh/RadioLibInterface.cpp
@@ -278,7 +278,8 @@ void RadioLibInterface::onNotify(uint32_t notification)
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
setTransmitDelay();
} else {
- // Send any outgoing packets we have ready
+ // Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
+ // actual transmission as short as possible
meshtastic_MeshPacket *txp = txQueue.dequeue();
assert(txp);
bool sent = startSend(txp);
@@ -470,7 +471,8 @@ void RadioLibInterface::setStandby()
/** start an immediate transmit */
bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
{
- printPacket("Start low level send", txp);
+ /* NOTE: Minimize the actions before startTransmit() to keep the time between
+ channel scan and actual transmit as low as possible to avoid collisions. */
if (disabled || !config.lora.tx_enabled) {
LOG_WARN("Drop Tx packet because LoRa Tx disabled");
packetPool.release(txp);
@@ -489,6 +491,9 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
completeSending();
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // Transmitter off now
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
+ } else {
+ lastTxStart = millis();
+ printPacket("Started Tx", txp);
}
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register
diff --git a/src/mesh/ReliableRouter.cpp b/src/mesh/ReliableRouter.cpp
index a5fa3e585..3e2850bcf 100644
--- a/src/mesh/ReliableRouter.cpp
+++ b/src/mesh/ReliableRouter.cpp
@@ -176,9 +176,9 @@ bool ReliableRouter::stopRetransmission(GlobalPacketId key)
if (old->numRetransmissions < NUM_RETRANSMISSIONS - 1) {
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
cancelSending(getFrom(p), p->id);
- // now free the pooled copy for retransmission too
- packetPool.release(p);
}
+ // now free the pooled copy for retransmission too
+ packetPool.release(p);
auto numErased = pending.erase(key);
assert(numErased == 1);
return true;
diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp
index 0b46ca3b9..7b792db30 100644
--- a/src/mesh/Router.cpp
+++ b/src/mesh/Router.cpp
@@ -651,6 +651,13 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
return;
}
+ meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->from);
+ if (node != NULL && node->is_ignored) {
+ LOG_DEBUG("Ignore msg, 0x%x is ignored", p->from);
+ packetPool.release(p);
+ return;
+ }
+
if (p->from == NODENUM_BROADCAST) {
LOG_DEBUG("Ignore msg from broadcast address");
packetPool.release(p);
diff --git a/src/mesh/TypeConversions.cpp b/src/mesh/TypeConversions.cpp
index 550f87021..5fc6b8a64 100644
--- a/src/mesh/TypeConversions.cpp
+++ b/src/mesh/TypeConversions.cpp
@@ -12,6 +12,7 @@ meshtastic_NodeInfo TypeConversions::ConvertToNodeInfo(const meshtastic_NodeInfo
info.channel = lite->channel;
info.via_mqtt = lite->via_mqtt;
info.is_favorite = lite->is_favorite;
+ info.is_ignored = lite->is_ignored;
if (lite->has_hops_away) {
info.has_hops_away = true;
diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h
index d802eb3da..bbf633ef5 100644
--- a/src/mesh/generated/meshtastic/admin.pb.h
+++ b/src/mesh/generated/meshtastic/admin.pb.h
@@ -180,6 +180,10 @@ typedef struct _meshtastic_AdminMessage {
meshtastic_DeviceUIConfig get_ui_config_response;
/* Tell the node to store UI data persistently. */
meshtastic_DeviceUIConfig store_ui_config;
+ /* Set specified node-num to be ignored on the NodeDB on the device */
+ uint32_t set_ignored_node;
+ /* Set specified node-num to be un-ignored on the NodeDB on the device */
+ uint32_t remove_ignored_node;
/* Begins an edit transaction for config, module config, owner, and channel settings changes
This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings) */
bool begin_edit_settings;
@@ -279,6 +283,8 @@ extern "C" {
#define meshtastic_AdminMessage_get_ui_config_request_tag 44
#define meshtastic_AdminMessage_get_ui_config_response_tag 45
#define meshtastic_AdminMessage_store_ui_config_tag 46
+#define meshtastic_AdminMessage_set_ignored_node_tag 47
+#define meshtastic_AdminMessage_remove_ignored_node_tag 48
#define meshtastic_AdminMessage_begin_edit_settings_tag 64
#define meshtastic_AdminMessage_commit_edit_settings_tag 65
#define meshtastic_AdminMessage_factory_reset_device_tag 94
@@ -329,6 +335,8 @@ X(a, STATIC, ONEOF, FIXED32, (payload_variant,set_time_only,set_time_only)
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_ui_config_request,get_ui_config_request), 44) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_ui_config_response,get_ui_config_response), 45) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,store_ui_config,store_ui_config), 46) \
+X(a, STATIC, ONEOF, UINT32, (payload_variant,set_ignored_node,set_ignored_node), 47) \
+X(a, STATIC, ONEOF, UINT32, (payload_variant,remove_ignored_node,remove_ignored_node), 48) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_edit_settings), 64) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \
X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \
diff --git a/src/mesh/generated/meshtastic/device_ui.pb.h b/src/mesh/generated/meshtastic/device_ui.pb.h
index 5c1e067ab..107aa8846 100644
--- a/src/mesh/generated/meshtastic/device_ui.pb.h
+++ b/src/mesh/generated/meshtastic/device_ui.pb.h
@@ -49,6 +49,8 @@ typedef enum _meshtastic_Language {
meshtastic_Language_DUTCH = 12,
/* Greek */
meshtastic_Language_GREEK = 13,
+ /* Norwegian */
+ meshtastic_Language_NORWEGIAN = 14,
/* Simplified Chinese (experimental) */
meshtastic_Language_SIMPLIFIED_CHINESE = 30,
/* Traditional Chinese (experimental) */
@@ -84,6 +86,7 @@ typedef struct _meshtastic_NodeHighlight {
char node_name[16];
} meshtastic_NodeHighlight;
+typedef PB_BYTES_ARRAY_T(16) meshtastic_DeviceUIConfig_calibration_data_t;
typedef struct _meshtastic_DeviceUIConfig {
/* A version integer used to invalidate saved files when we make incompatible changes. */
uint32_t version;
@@ -109,6 +112,8 @@ typedef struct _meshtastic_DeviceUIConfig {
/* Node list highlightening */
bool has_node_highlight;
meshtastic_NodeHighlight node_highlight;
+ /* 8 integers for screen calibration data */
+ meshtastic_DeviceUIConfig_calibration_data_t calibration_data;
} meshtastic_DeviceUIConfig;
@@ -132,10 +137,10 @@ extern "C" {
/* Initializer values for message structs */
-#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default}
+#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}}
#define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, ""}
#define meshtastic_NodeHighlight_init_default {0, 0, 0, 0, ""}
-#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero}
+#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}}
#define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, ""}
#define meshtastic_NodeHighlight_init_zero {0, 0, 0, 0, ""}
@@ -164,6 +169,7 @@ extern "C" {
#define meshtastic_DeviceUIConfig_language_tag 11
#define meshtastic_DeviceUIConfig_node_filter_tag 12
#define meshtastic_DeviceUIConfig_node_highlight_tag 13
+#define meshtastic_DeviceUIConfig_calibration_data_tag 14
/* Struct field encoding specification for nanopb */
#define meshtastic_DeviceUIConfig_FIELDLIST(X, a) \
@@ -179,7 +185,8 @@ X(a, STATIC, SINGULAR, BOOL, banner_enabled, 9) \
X(a, STATIC, SINGULAR, UINT32, ring_tone_id, 10) \
X(a, STATIC, SINGULAR, UENUM, language, 11) \
X(a, STATIC, OPTIONAL, MESSAGE, node_filter, 12) \
-X(a, STATIC, OPTIONAL, MESSAGE, node_highlight, 13)
+X(a, STATIC, OPTIONAL, MESSAGE, node_highlight, 13) \
+X(a, STATIC, SINGULAR, BYTES, calibration_data, 14)
#define meshtastic_DeviceUIConfig_CALLBACK NULL
#define meshtastic_DeviceUIConfig_DEFAULT NULL
#define meshtastic_DeviceUIConfig_node_filter_MSGTYPE meshtastic_NodeFilter
@@ -215,7 +222,7 @@ extern const pb_msgdesc_t meshtastic_NodeHighlight_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_DEVICE_UI_PB_H_MAX_SIZE meshtastic_DeviceUIConfig_size
-#define meshtastic_DeviceUIConfig_size 99
+#define meshtastic_DeviceUIConfig_size 117
#define meshtastic_NodeFilter_size 36
#define meshtastic_NodeHighlight_size 25
diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h
index 39d056061..e52a914e0 100644
--- a/src/mesh/generated/meshtastic/deviceonly.pb.h
+++ b/src/mesh/generated/meshtastic/deviceonly.pb.h
@@ -87,6 +87,11 @@ typedef struct _meshtastic_NodeInfoLite {
/* True if node is in our favorites list
Persists between NodeDB internal clean ups */
bool is_favorite;
+ /* True if node is in our ignored list
+ Persists between NodeDB internal clean ups */
+ bool is_ignored;
+ /* Last byte of the node number of the node that should be used as the next hop to reach this node. */
+ uint8_t next_hop;
} meshtastic_NodeInfoLite;
/* This message is never sent over the wire, but it is used for serializing DB
@@ -150,12 +155,12 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN}
#define meshtastic_UserLite_init_default {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}}
-#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0}
+#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0}
#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_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}, {0}}
#define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0}
#define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN}
#define meshtastic_UserLite_init_zero {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}}
-#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0}
+#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0}
#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_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}, {0}}
#define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0}
@@ -182,6 +187,8 @@ extern "C" {
#define meshtastic_NodeInfoLite_via_mqtt_tag 8
#define meshtastic_NodeInfoLite_hops_away_tag 9
#define meshtastic_NodeInfoLite_is_favorite_tag 10
+#define meshtastic_NodeInfoLite_is_ignored_tag 11
+#define meshtastic_NodeInfoLite_next_hop_tag 12
#define meshtastic_DeviceState_my_node_tag 2
#define meshtastic_DeviceState_owner_tag 3
#define meshtastic_DeviceState_receive_queue_tag 5
@@ -226,7 +233,9 @@ X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \
X(a, STATIC, SINGULAR, UINT32, channel, 7) \
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \
X(a, STATIC, OPTIONAL, UINT32, hops_away, 9) \
-X(a, STATIC, SINGULAR, BOOL, is_favorite, 10)
+X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) \
+X(a, STATIC, SINGULAR, BOOL, is_ignored, 11) \
+X(a, STATIC, SINGULAR, UINT32, next_hop, 12)
#define meshtastic_NodeInfoLite_CALLBACK NULL
#define meshtastic_NodeInfoLite_DEFAULT NULL
#define meshtastic_NodeInfoLite_user_MSGTYPE meshtastic_UserLite
@@ -279,7 +288,7 @@ extern const pb_msgdesc_t meshtastic_ChannelFile_msg;
/* meshtastic_DeviceState_size depends on runtime parameters */
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_ChannelFile_size
#define meshtastic_ChannelFile_size 718
-#define meshtastic_NodeInfoLite_size 183
+#define meshtastic_NodeInfoLite_size 188
#define meshtastic_PositionLite_size 28
#define meshtastic_UserLite_size 96
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index e45d60a19..3e195e7f5 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -212,6 +212,9 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_MS24SF1 = 82,
/* Lilygo TLora-C6 with the new ESP32-C6 MCU */
meshtastic_HardwareModel_TLORA_C6 = 83,
+ /* WisMesh Tap
+ RAK-4631 w/ TFT in injection modled case */
+ meshtastic_HardwareModel_WISMESH_TAP = 84,
/* ------------------------------------------------------------------------------------------------------------------------------------------
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.
------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -751,6 +754,12 @@ typedef struct _meshtastic_MeshPacket {
meshtastic_MeshPacket_public_key_t public_key;
/* Indicates whether the packet was en/decrypted using PKI */
bool pki_encrypted;
+ /* Last byte of the node number of the node that should be used as the next hop in routing.
+ Set by the firmware internally, clients are not supposed to set this. */
+ uint8_t next_hop;
+ /* Last byte of the node number of the node that will relay/relayed this packet.
+ Set by the firmware internally, clients are not supposed to set this. */
+ uint8_t relay_node;
} meshtastic_MeshPacket;
/* The bluetooth to device link:
@@ -797,6 +806,9 @@ typedef struct _meshtastic_NodeInfo {
/* True if node is in our favorites list
Persists between NodeDB internal clean ups */
bool is_favorite;
+ /* True if node is in our ignored list
+ Persists between NodeDB internal clean ups */
+ bool is_ignored;
} meshtastic_NodeInfo;
typedef PB_BYTES_ARRAY_T(16) meshtastic_MyNodeInfo_device_id_t;
@@ -1156,8 +1168,8 @@ extern "C" {
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
-#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0}
-#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0}
+#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0}
+#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0}
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, ""}
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
@@ -1181,8 +1193,8 @@ extern "C" {
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
-#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0}
-#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0}
+#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0}
+#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0}
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, ""}
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
@@ -1277,6 +1289,8 @@ extern "C" {
#define meshtastic_MeshPacket_hop_start_tag 15
#define meshtastic_MeshPacket_public_key_tag 16
#define meshtastic_MeshPacket_pki_encrypted_tag 17
+#define meshtastic_MeshPacket_next_hop_tag 18
+#define meshtastic_MeshPacket_relay_node_tag 19
#define meshtastic_NodeInfo_num_tag 1
#define meshtastic_NodeInfo_user_tag 2
#define meshtastic_NodeInfo_position_tag 3
@@ -1287,6 +1301,7 @@ extern "C" {
#define meshtastic_NodeInfo_via_mqtt_tag 8
#define meshtastic_NodeInfo_hops_away_tag 9
#define meshtastic_NodeInfo_is_favorite_tag 10
+#define meshtastic_NodeInfo_is_ignored_tag 11
#define meshtastic_MyNodeInfo_my_node_num_tag 1
#define meshtastic_MyNodeInfo_reboot_count_tag 8
#define meshtastic_MyNodeInfo_min_app_version_tag 11
@@ -1470,7 +1485,9 @@ X(a, STATIC, SINGULAR, UENUM, delayed, 13) \
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 14) \
X(a, STATIC, SINGULAR, UINT32, hop_start, 15) \
X(a, STATIC, SINGULAR, BYTES, public_key, 16) \
-X(a, STATIC, SINGULAR, BOOL, pki_encrypted, 17)
+X(a, STATIC, SINGULAR, BOOL, pki_encrypted, 17) \
+X(a, STATIC, SINGULAR, UINT32, next_hop, 18) \
+X(a, STATIC, SINGULAR, UINT32, relay_node, 19)
#define meshtastic_MeshPacket_CALLBACK NULL
#define meshtastic_MeshPacket_DEFAULT NULL
#define meshtastic_MeshPacket_payload_variant_decoded_MSGTYPE meshtastic_Data
@@ -1485,7 +1502,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \
X(a, STATIC, SINGULAR, UINT32, channel, 7) \
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \
X(a, STATIC, OPTIONAL, UINT32, hops_away, 9) \
-X(a, STATIC, SINGULAR, BOOL, is_favorite, 10)
+X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) \
+X(a, STATIC, SINGULAR, BOOL, is_ignored, 11)
#define meshtastic_NodeInfo_CALLBACK NULL
#define meshtastic_NodeInfo_DEFAULT NULL
#define meshtastic_NodeInfo_user_MSGTYPE meshtastic_User
@@ -1719,12 +1737,12 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_FromRadio_size 510
#define meshtastic_Heartbeat_size 0
#define meshtastic_LogRecord_size 426
-#define meshtastic_MeshPacket_size 367
+#define meshtastic_MeshPacket_size 375
#define meshtastic_MqttClientProxyMessage_size 501
#define meshtastic_MyNodeInfo_size 77
#define meshtastic_NeighborInfo_size 258
#define meshtastic_Neighbor_size 22
-#define meshtastic_NodeInfo_size 317
+#define meshtastic_NodeInfo_size 319
#define meshtastic_NodeRemoteHardwarePin_size 29
#define meshtastic_Position_size 144
#define meshtastic_QueueStatus_size 23
diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h
index 309c01dc7..874eef60f 100644
--- a/src/mesh/generated/meshtastic/telemetry.pb.h
+++ b/src/mesh/generated/meshtastic/telemetry.pb.h
@@ -77,7 +77,9 @@ typedef enum _meshtastic_TelemetrySensorType {
/* MLX90614 non-contact IR temperature sensor */
meshtastic_TelemetrySensorType_MLX90614 = 31,
/* SCD40/SCD41 CO2, humidity, temperature sensor */
- meshtastic_TelemetrySensorType_SCD4X = 32
+ meshtastic_TelemetrySensorType_SCD4X = 32,
+ /* ClimateGuard RadSens, radiation, Geiger-Muller Tube */
+ meshtastic_TelemetrySensorType_RADSENS = 33
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@@ -155,6 +157,9 @@ typedef struct _meshtastic_EnvironmentMetrics {
/* Wind lull in m/s */
bool has_wind_lull;
float wind_lull;
+ /* Radiation in µR/h */
+ bool has_radiation;
+ float radiation;
} meshtastic_EnvironmentMetrics;
/* Power Metrics (voltage / current / etc) */
@@ -299,8 +304,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
-#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SCD4X
-#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SCD4X+1))
+#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RADSENS
+#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RADSENS+1))
@@ -313,7 +318,7 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0}
-#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
+#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@@ -321,7 +326,7 @@ extern "C" {
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
#define meshtastic_Nau7802Config_init_default {0, 0}
#define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0}
-#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
+#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@@ -352,6 +357,7 @@ extern "C" {
#define meshtastic_EnvironmentMetrics_weight_tag 15
#define meshtastic_EnvironmentMetrics_wind_gust_tag 16
#define meshtastic_EnvironmentMetrics_wind_lull_tag 17
+#define meshtastic_EnvironmentMetrics_radiation_tag 18
#define meshtastic_PowerMetrics_ch1_voltage_tag 1
#define meshtastic_PowerMetrics_ch1_current_tag 2
#define meshtastic_PowerMetrics_ch2_voltage_tag 3
@@ -422,7 +428,8 @@ X(a, STATIC, OPTIONAL, UINT32, wind_direction, 13) \
X(a, STATIC, OPTIONAL, FLOAT, wind_speed, 14) \
X(a, STATIC, OPTIONAL, FLOAT, weight, 15) \
X(a, STATIC, OPTIONAL, FLOAT, wind_gust, 16) \
-X(a, STATIC, OPTIONAL, FLOAT, wind_lull, 17)
+X(a, STATIC, OPTIONAL, FLOAT, wind_lull, 17) \
+X(a, STATIC, OPTIONAL, FLOAT, radiation, 18)
#define meshtastic_EnvironmentMetrics_CALLBACK NULL
#define meshtastic_EnvironmentMetrics_DEFAULT NULL
@@ -521,12 +528,12 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg;
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
#define meshtastic_AirQualityMetrics_size 78
#define meshtastic_DeviceMetrics_size 27
-#define meshtastic_EnvironmentMetrics_size 85
+#define meshtastic_EnvironmentMetrics_size 91
#define meshtastic_HealthMetrics_size 11
#define meshtastic_LocalStats_size 60
#define meshtastic_Nau7802Config_size 16
#define meshtastic_PowerMetrics_size 30
-#define meshtastic_Telemetry_size 92
+#define meshtastic_Telemetry_size 98
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp
index efa816438..64f7164c9 100644
--- a/src/mesh/http/ContentHandler.cpp
+++ b/src/mesh/http/ContentHandler.cpp
@@ -74,6 +74,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
ResourceNode *nodeAPIv1ToRadioOptions = new ResourceNode("/api/v1/toradio", "OPTIONS", &handleAPIv1ToRadio);
ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "PUT", &handleAPIv1ToRadio);
+ ResourceNode *nodeAPIv1FromRadioOptions = new ResourceNode("/api/v1/fromradio", "OPTIONS", &handleAPIv1FromRadio);
ResourceNode *nodeAPIv1FromRadio = new ResourceNode("/api/v1/fromradio", "GET", &handleAPIv1FromRadio);
// ResourceNode *nodeHotspotApple = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot);
@@ -100,6 +101,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
// Secure nodes
secureServer->registerNode(nodeAPIv1ToRadioOptions);
secureServer->registerNode(nodeAPIv1ToRadio);
+ secureServer->registerNode(nodeAPIv1FromRadioOptions);
secureServer->registerNode(nodeAPIv1FromRadio);
// secureServer->registerNode(nodeHotspotApple);
// secureServer->registerNode(nodeHotspotAndroid);
@@ -121,6 +123,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
// Insecure nodes
insecureServer->registerNode(nodeAPIv1ToRadioOptions);
insecureServer->registerNode(nodeAPIv1ToRadio);
+ insecureServer->registerNode(nodeAPIv1FromRadioOptions);
insecureServer->registerNode(nodeAPIv1FromRadio);
// insecureServer->registerNode(nodeHotspotApple);
// insecureServer->registerNode(nodeHotspotAndroid);
@@ -163,6 +166,12 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
res->setHeader("Access-Control-Allow-Methods", "GET");
res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/protobufs/master/meshtastic/mesh.proto");
+ if (req->getMethod() == "OPTIONS") {
+ res->setStatusCode(204); // Success with no content
+ // res->print(""); @todo remove
+ return;
+ }
+
uint8_t txBuf[MAX_STREAM_BUF_SIZE];
uint32_t len = 1;
diff --git a/src/mesh/mesh-pb-constants.h b/src/mesh/mesh-pb-constants.h
index f91c48560..039b36d8d 100644
--- a/src/mesh/mesh-pb-constants.h
+++ b/src/mesh/mesh-pb-constants.h
@@ -23,6 +23,8 @@
#define MAX_NUM_NODES 100
#endif
+#define MAX_NUM_NODES_FS 100
+
/// Max number of channels allowed
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))
diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp
index faf5ce3de..779576d64 100644
--- a/src/mesh/wifi/WiFiAPClient.cpp
+++ b/src/mesh/wifi/WiFiAPClient.cpp
@@ -20,6 +20,8 @@
#include
#include
static void WiFiEvent(WiFiEvent_t event);
+#elif defined(ARCH_RP2040)
+#include
#endif
#ifndef DISABLE_NTP
@@ -59,19 +61,25 @@ static void onNetworkConnected()
// Start web server
LOG_INFO("Start WiFi network services");
-#ifdef ARCH_ESP32
// start mdns
- if (!MDNS.begin("Meshtastic")) {
+ if (
+#ifdef ARCH_RP2040
+ !moduleConfig.mqtt.enabled && // MDNS is not supported when MQTT is enabled on ARCH_RP2040
+#endif
+ !MDNS.begin("Meshtastic")) {
LOG_ERROR("Error setting up MDNS responder!");
} else {
- LOG_INFO("mDNS responder started");
LOG_INFO("mDNS Host: Meshtastic.local");
+#ifdef ARCH_ESP32
MDNS.addService("http", "tcp", 80);
MDNS.addService("https", "tcp", 443);
- }
-#else // ESP32 handles this in WiFiEvent
- LOG_INFO("Obtained IP address: %s", WiFi.localIP().toString().c_str());
+#elif defined(ARCH_RP2040)
+ // ARCH_RP2040 does not support HTTPS, create a "meshtastic" service
+ MDNS.addService("meshtastic", "tcp", 4403);
+ // ESP32 handles this in WiFiEvent
+ LOG_INFO("Obtained IP address: %s", WiFi.localIP().toString().c_str());
#endif
+ }
#ifndef DISABLE_NTP
LOG_INFO("Start NTP time client");
@@ -129,7 +137,7 @@ static int32_t reconnectWiFi()
// Make sure we clear old connection credentials
#ifdef ARCH_ESP32
WiFi.disconnect(false, true);
-#else
+#elif defined(ARCH_RP2040)
WiFi.disconnect(false);
#endif
LOG_INFO("Reconnecting to WiFi access point %s", wifiName);
@@ -193,7 +201,7 @@ void deinitWifi()
if (isWifiAvailable()) {
#ifdef ARCH_ESP32
WiFi.disconnect(true, false);
-#else
+#elif defined(ARCH_RP2040)
WiFi.disconnect(true);
#endif
WiFi.mode(WIFI_OFF);
@@ -229,15 +237,15 @@ bool initWifi()
if (config.network.address_mode == meshtastic_Config_NetworkConfig_AddressMode_STATIC &&
config.network.ipv4_config.ip != 0) {
-#ifndef ARCH_RP2040
+#ifdef ARCH_ESP32
WiFi.config(config.network.ipv4_config.ip, config.network.ipv4_config.gateway, config.network.ipv4_config.subnet,
config.network.ipv4_config.dns);
-#else
+#elif defined(ARCH_RP2040)
WiFi.config(config.network.ipv4_config.ip, config.network.ipv4_config.dns, config.network.ipv4_config.gateway,
config.network.ipv4_config.subnet);
#endif
}
-#ifndef ARCH_RP2040
+#ifdef ARCH_ESP32
WiFi.onEvent(WiFiEvent);
WiFi.setAutoReconnect(true);
WiFi.setSleep(false);
diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp
index 5401e1fdb..c81b6ede4 100644
--- a/src/modules/AdminModule.cpp
+++ b/src/modules/AdminModule.cpp
@@ -283,6 +283,28 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
}
break;
}
+ case meshtastic_AdminMessage_set_ignored_node_tag: {
+ LOG_INFO("Client received set_ignored_node command");
+ meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(r->set_ignored_node);
+ if (node != NULL) {
+ node->is_ignored = true;
+ node->has_device_metrics = false;
+ node->has_position = false;
+ node->user.public_key.size = 0;
+ node->user.public_key.bytes[0] = 0;
+ saveChanges(SEGMENT_DEVICESTATE, false);
+ }
+ break;
+ }
+ case meshtastic_AdminMessage_remove_ignored_node_tag: {
+ LOG_INFO("Client received remove_ignored_node command");
+ meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(r->remove_ignored_node);
+ if (node != NULL) {
+ node->is_ignored = false;
+ saveChanges(SEGMENT_DEVICESTATE, false);
+ }
+ break;
+ }
case meshtastic_AdminMessage_set_fixed_position_tag: {
LOG_INFO("Client received set_fixed_position command");
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
@@ -504,6 +526,11 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
requiresReboot = false;
}
config.power = c.payload_variant.power;
+ if (c.payload_variant.power.on_battery_shutdown_after_secs > 0 &&
+ c.payload_variant.power.on_battery_shutdown_after_secs < 30) {
+ LOG_WARN("Tried to set on_battery_shutdown_after_secs too low, set to min 30 seconds");
+ config.power.on_battery_shutdown_after_secs = 30;
+ }
break;
case meshtastic_Config_network_tag:
LOG_INFO("Set config: WiFi");
diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp
index 37409b43b..a96fcc080 100644
--- a/src/modules/CannedMessageModule.cpp
+++ b/src/modules/CannedMessageModule.cpp
@@ -55,7 +55,7 @@ CannedMessageModule::CannedMessageModule()
LOG_INFO("CannedMessageModule is enabled");
// T-Watch interface currently has no way to select destination type, so default to 'node'
-#if defined(T_WATCH_S3) || defined(RAK14014)
+#if defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
#endif
@@ -81,7 +81,7 @@ int CannedMessageModule::splitConfiguredMessages()
String canned_messages = cannedMessageModuleConfig.messages;
-#if defined(T_WATCH_S3) || defined(RAK14014)
+#if defined(USE_VIRTUAL_KEYBOARD)
String separator = canned_messages.length() ? "|" : "";
canned_messages = "[---- Free Text ----]" + separator + canned_messages;
@@ -150,7 +150,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
}
if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT)) {
-#if defined(T_WATCH_S3) || defined(RAK14014)
+#if defined(USE_VIRTUAL_KEYBOARD)
if (this->currentMessageIndex == 0) {
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
@@ -177,7 +177,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
this->currentMessageIndex = -1;
-#if !defined(T_WATCH_S3) && !defined(RAK14014)
+#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->freetext = ""; // clear freetext
this->cursor = 0;
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
@@ -190,7 +190,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
(event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
(event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
-#if defined(T_WATCH_S3) || defined(RAK14014)
+#if defined(USE_VIRTUAL_KEYBOARD)
if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
this->payload = INPUT_BROKER_MSG_LEFT;
} else if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
@@ -234,13 +234,13 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
screen->decreaseBrightness();
LOG_DEBUG("Decrease Screen Brightness");
break;
- case INPUT_BROKER_MSG_FN_SYMBOL_ON: // draw modifier (function) symbal
+ case INPUT_BROKER_MSG_FN_SYMBOL_ON: // draw modifier (function) symbol
if (screen)
- screen->setFunctionSymbal("Fn");
+ screen->setFunctionSymbol("Fn");
break;
- case INPUT_BROKER_MSG_FN_SYMBOL_OFF: // remove modifier (function) symbal
+ case INPUT_BROKER_MSG_FN_SYMBOL_OFF: // remove modifier (function) symbol
if (screen)
- screen->removeFunctionSymbal("Fn");
+ screen->removeFunctionSymbol("Fn");
break;
// mute (switch off/toggle) external notifications on fn+m
case INPUT_BROKER_MSG_MUTE_TOGGLE:
@@ -249,13 +249,13 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
externalNotificationModule->setMute(false);
showTemporaryMessage("Notifications \nEnabled");
if (screen)
- screen->removeFunctionSymbal("M"); // remove the mute symbol from the bottom right corner
+ screen->removeFunctionSymbol("M"); // remove the mute symbol from the bottom right corner
} else {
externalNotificationModule->stopNow(); // this will turn off all GPIO and sounds and idle the loop
externalNotificationModule->setMute(true);
showTemporaryMessage("Notifications \nDisabled");
if (screen)
- screen->setFunctionSymbal("M"); // add the mute symbol to the bottom right corner
+ screen->setFunctionSymbol("M"); // add the mute symbol to the bottom right corner
}
}
break;
@@ -308,11 +308,11 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
break;
}
if (screen && (event->kbchar != INPUT_BROKER_MSG_FN_SYMBOL_ON)) {
- screen->removeFunctionSymbal("Fn"); // remove modifier (function) symbal
+ screen->removeFunctionSymbol("Fn"); // remove modifier (function) symbol
}
}
-#if defined(T_WATCH_S3) || defined(RAK14014)
+#if defined(USE_VIRTUAL_KEYBOARD)
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
String keyTapped = keyForCoordinates(event->touchX, event->touchY);
@@ -446,7 +446,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
-#if !defined(T_WATCH_S3) && !defined(RAK14014)
+#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(SENSECAP_INDICATOR)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@@ -459,7 +459,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
-#if !defined(T_WATCH_S3) && !defined(RAK14014)
+#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@@ -479,7 +479,7 @@ int32_t CannedMessageModule::runOnce()
powerFSM.trigger(EVENT_PRESS);
return INT32_MAX;
} else {
-#if defined(T_WATCH_S3) || defined(RAK14014)
+#if defined(USE_VIRTUAL_KEYBOARD)
sendText(this->dest, indexChannels[this->channel], this->messages[this->currentMessageIndex], true);
#else
sendText(NODENUM_BROADCAST, channels.getPrimaryIndex(), this->messages[this->currentMessageIndex], true);
@@ -496,7 +496,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
-#if !defined(T_WATCH_S3) && !defined(RAK14014)
+#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@@ -513,7 +513,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
-#if !defined(T_WATCH_S3) && !defined(RAK14014)
+#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@@ -526,7 +526,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
-#if !defined(T_WATCH_S3) && !defined(RAK14014)
+#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@@ -672,7 +672,7 @@ int32_t CannedMessageModule::runOnce()
break;
}
if (screen)
- screen->removeFunctionSymbal("Fn");
+ screen->removeFunctionSymbol("Fn");
}
this->lastTouchMillis = millis();
@@ -769,7 +769,7 @@ void CannedMessageModule::showTemporaryMessage(const String &message)
setIntervalFromNow(2000);
}
-#if defined(T_WATCH_S3) || defined(RAK14014)
+#if defined(USE_VIRTUAL_KEYBOARD)
String CannedMessageModule::keyForCoordinates(uint x, uint y)
{
@@ -1055,7 +1055,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled.");
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
requestFocus(); // Tell Screen::setFrames to move to our module's frame
-#if defined(T_WATCH_S3) || defined(RAK14014)
+#if defined(USE_VIRTUAL_KEYBOARD)
drawKeyboard(display, state, 0, 0);
#else
diff --git a/src/modules/CannedMessageModule.h b/src/modules/CannedMessageModule.h
index 4427be144..fd9ffc9b6 100644
--- a/src/modules/CannedMessageModule.h
+++ b/src/modules/CannedMessageModule.h
@@ -102,7 +102,7 @@ class CannedMessageModule : public SinglePortModule, public Observabledecoded.payload.bytes[p->decoded.payload.size + 1] = '\0'; // Bell character
p->decoded.payload.size++;
}
- LOG_INFO("Send message id=%d, dest=%x, msg=%.*s", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
lastSentToMesh = millis();
- service->sendToMesh(p);
+ if (!channels.isDefaultChannel(0)) {
+ LOG_INFO("Send message id=%d, dest=%x, msg=%.*s", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
+ service->sendToMesh(p);
+ } else
+ LOG_ERROR("Message not allow on Public channel");
delete[] message;
}
@@ -140,14 +143,16 @@ void DetectionSensorModule::sendCurrentStateMessage(bool state)
{
char *message = new char[40];
sprintf(message, "%s state: %i", moduleConfig.detection_sensor.name, state);
-
meshtastic_MeshPacket *p = allocDataPacket();
p->want_ack = false;
p->decoded.payload.size = strlen(message);
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
- LOG_INFO("Send message id=%d, dest=%x, msg=%.*s", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
lastSentToMesh = millis();
- service->sendToMesh(p);
+ if (!channels.isDefaultChannel(0)) {
+ LOG_INFO("Send message id=%d, dest=%x, msg=%.*s", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
+ service->sendToMesh(p);
+ } else
+ LOG_ERROR("Message not allow on Public channel");
delete[] message;
}
@@ -156,4 +161,4 @@ bool DetectionSensorModule::hasDetectionEvent()
bool currentState = digitalRead(moduleConfig.detection_sensor.monitor_pin);
// LOG_DEBUG("Detection Sensor Module: Current state: %i", currentState);
return (moduleConfig.detection_sensor.detection_trigger_type & 1) ? currentState : !currentState;
-}
\ No newline at end of file
+}
diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp
index d88f275b9..3ec6ff690 100644
--- a/src/modules/ExternalNotificationModule.cpp
+++ b/src/modules/ExternalNotificationModule.cpp
@@ -119,12 +119,13 @@ int32_t ExternalNotificationModule::runOnce()
if (externalTurnedOn[1] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
millis()) {
- setExternalState(0, !getExternal(1));
+ setExternalState(1, !getExternal(1));
}
if (externalTurnedOn[2] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
millis()) {
- setExternalState(0, !getExternal(2));
+ LOG_DEBUG("EXTERNAL 2 %d compared to %d", externalTurnedOn[2]+moduleConfig.external_notification.output_ms, millis());
+ setExternalState(2, !getExternal(2));
}
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
red = (colorState & 4) ? brightnessValues[brightnessIndex] : 0; // Red enabled on colorState = 4,5,6,7
diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp
index f80d3eb67..d977cfdec 100644
--- a/src/modules/PositionModule.cpp
+++ b/src/modules/PositionModule.cpp
@@ -146,11 +146,20 @@ bool PositionModule::hasQualityTimesource()
#if MESHTASTIC_EXCLUDE_GPS
bool hasGpsOrRtc = (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
#else
- bool hasGpsOrRtc = (gps && gps->isConnected()) || (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
+ bool hasGpsOrRtc = hasGPS() || (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
#endif
return hasGpsOrRtc || setFromPhoneOrNtpToday;
}
+bool PositionModule::hasGPS()
+{
+#if MESHTASTIC_EXCLUDE_GPS
+ return false;
+#else
+ return gps && gps->isConnected();
+#endif
+}
+
meshtastic_MeshPacket *PositionModule::allocReply()
{
if (precision == 0) {
@@ -194,10 +203,21 @@ meshtastic_MeshPacket *PositionModule::allocReply()
p.precision_bits = precision;
p.has_latitude_i = true;
p.has_longitude_i = true;
- p.time = getValidTime(RTCQualityNTP) > 0 ? getValidTime(RTCQualityNTP) : localPosition.time;
+ // Always use NTP / GPS time if available
+ if (getValidTime(RTCQualityNTP) > 0) {
+ p.time = getValidTime(RTCQualityNTP);
+ } else if (rtc_found.address != ScanI2C::ADDRESS_NONE.address) {
+ LOG_INFO("Use RTC time for position");
+ p.time = getValidTime(RTCQualityDevice);
+ } else if (getRTCQuality() < RTCQualityNTP) {
+ LOG_INFO("Strip low RTCQuality (%d) time from position", getRTCQuality());
+ p.time = 0;
+ }
if (config.position.fixed_position) {
p.location_source = meshtastic_Position_LocSource_LOC_MANUAL;
+ } else {
+ p.location_source = localPosition.location_source;
}
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) {
@@ -242,20 +262,6 @@ meshtastic_MeshPacket *PositionModule::allocReply()
p.has_ground_speed = true;
}
- // Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
- // nodes shouldn't trust it anyways) Note: we allow a device with a local GPS or NTP to include the time, so that devices
- // without can get time.
- if (getRTCQuality() < RTCQualityNTP) {
- LOG_INFO("Strip time %u from position", p.time);
- p.time = 0;
- } else if (rtc_found.address != ScanI2C::ADDRESS_NONE.address) {
- LOG_INFO("Use RTC time %u for position", p.time);
- p.time = getValidTime(RTCQualityDevice);
- } else {
- p.time = getValidTime(RTCQualityNTP);
- LOG_INFO("Provide time to mesh %u", p.time);
- }
-
LOG_INFO("Position reply: time=%i lat=%i lon=%i", p.time, p.latitude_i, p.longitude_i);
// TAK Tracker devices should send their position in a TAK packet over the ATAK port
@@ -364,7 +370,7 @@ int32_t PositionModule::runOnce()
sleepOnNextExecution = false;
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(config.position.position_broadcast_secs);
LOG_DEBUG("Sleep for %ims, then awaking to send position again", nightyNightMs);
- doDeepSleep(nightyNightMs, false);
+ doDeepSleep(nightyNightMs, false, false);
}
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
diff --git a/src/modules/PositionModule.h b/src/modules/PositionModule.h
index 41b86b795..1e4aa5d29 100644
--- a/src/modules/PositionModule.h
+++ b/src/modules/PositionModule.h
@@ -61,6 +61,7 @@ class PositionModule : public ProtobufModule, private concu
uint32_t precision;
void sendLostAndFoundText();
bool hasQualityTimesource();
+ bool hasGPS();
const uint32_t minimumTimeThreshold =
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
diff --git a/src/modules/PowerStressModule.cpp b/src/modules/PowerStressModule.cpp
index 80b14c756..d487fe6fc 100644
--- a/src/modules/PowerStressModule.cpp
+++ b/src/modules/PowerStressModule.cpp
@@ -111,7 +111,7 @@ int32_t PowerStressModule::runOnce()
setBluetoothEnable(true);
break;
case meshtastic_PowerStressMessage_Opcode_CPU_DEEPSLEEP:
- doDeepSleep(sleep_msec, true);
+ doDeepSleep(sleep_msec, true, true);
break;
case meshtastic_PowerStressMessage_Opcode_CPU_FULLON: {
uint32_t start_msec = millis();
diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp
index 32f9d9bc6..531be274e 100644
--- a/src/modules/SerialModule.cpp
+++ b/src/modules/SerialModule.cpp
@@ -204,9 +204,11 @@ int32_t SerialModule::runOnce()
lastNmeaTime = millis();
uint32_t readIndex = 0;
const meshtastic_NodeInfoLite *tempNodeInfo = nodeDB->readNextMeshNode(readIndex);
- while (tempNodeInfo != NULL && tempNodeInfo->has_user && hasValidPosition(tempNodeInfo)) {
- printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true);
- serialPrint->printf("%s", outbuf);
+ while (tempNodeInfo != NULL) {
+ if (tempNodeInfo->has_user && hasValidPosition(tempNodeInfo)) {
+ printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true);
+ serialPrint->printf("%s", outbuf);
+ }
tempNodeInfo = nodeDB->readNextMeshNode(readIndex);
}
}
diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp
index 1f479d6f1..4989b88e2 100644
--- a/src/modules/Telemetry/DeviceTelemetry.cpp
+++ b/src/modules/Telemetry/DeviceTelemetry.cpp
@@ -77,9 +77,10 @@ meshtastic_MeshPacket *DeviceTelemetryModule::allocReply()
// Check for a request for device metrics
if (decoded->which_variant == meshtastic_Telemetry_device_metrics_tag) {
LOG_INFO("Device telemetry reply to request");
-
- meshtastic_Telemetry telemetry = getDeviceTelemetry();
- return allocDataProtobuf(telemetry);
+ return allocDataProtobuf(getDeviceTelemetry());
+ } else if (decoded->which_variant == meshtastic_Telemetry_local_stats_tag) {
+ LOG_INFO("Device telemetry reply w/ LocalStats to request");
+ return allocDataProtobuf(getLocalStatsTelemetry());
}
}
return NULL;
@@ -112,7 +113,7 @@ meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry()
return t;
}
-void DeviceTelemetryModule::sendLocalStatsToPhone()
+meshtastic_Telemetry DeviceTelemetryModule::getLocalStatsTelemetry()
{
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
telemetry.which_variant = meshtastic_Telemetry_local_stats_tag;
@@ -142,7 +143,12 @@ void DeviceTelemetryModule::sendLocalStatsToPhone()
LOG_INFO("num_packets_tx=%i, num_packets_rx=%i, num_packets_rx_bad=%i", telemetry.variant.local_stats.num_packets_tx,
telemetry.variant.local_stats.num_packets_rx, telemetry.variant.local_stats.num_packets_rx_bad);
- meshtastic_MeshPacket *p = allocDataProtobuf(telemetry);
+ return telemetry;
+}
+
+void DeviceTelemetryModule::sendLocalStatsToPhone()
+{
+ meshtastic_MeshPacket *p = allocDataProtobuf(getLocalStatsTelemetry());
p->to = NODENUM_BROADCAST;
p->decoded.want_response = false;
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
diff --git a/src/modules/Telemetry/DeviceTelemetry.h b/src/modules/Telemetry/DeviceTelemetry.h
index 29818d4eb..19b7d5b01 100644
--- a/src/modules/Telemetry/DeviceTelemetry.h
+++ b/src/modules/Telemetry/DeviceTelemetry.h
@@ -42,6 +42,8 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
private:
meshtastic_Telemetry getDeviceTelemetry();
+ meshtastic_Telemetry getLocalStatsTelemetry();
+
void sendLocalStatsToPhone();
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t sendStatsToPhoneIntervalMs = 15 * SECONDS_IN_MINUTE * 1000; // Send stats to phone every 15 minutes
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index c18944ebd..92d964f7d 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -25,6 +25,7 @@
#include "Sensor/BMP085Sensor.h"
#include "Sensor/BMP280Sensor.h"
#include "Sensor/BMP3XXSensor.h"
+#include "Sensor/CGRadSensSensor.h"
#include "Sensor/DFRobotLarkSensor.h"
#include "Sensor/LPS22HBSensor.h"
#include "Sensor/MCP9808Sensor.h"
@@ -60,6 +61,7 @@ BMP3XXSensor bmp3xxSensor;
#ifdef T1000X_SENSOR_EN
T1000xSensor t1000xSensor;
#endif
+CGRadSensSensor cgRadSens;
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
@@ -74,7 +76,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval,
default_telemetry_broadcast_interval_secs);
LOG_DEBUG("Sleep for %ims, then awake to send metrics again", nightyNightMs);
- doDeepSleep(nightyNightMs, true);
+ doDeepSleep(nightyNightMs, true, false);
}
uint32_t result = UINT32_MAX;
@@ -147,6 +149,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = nau7802Sensor.runOnce();
if (max17048Sensor.hasSensor())
result = max17048Sensor.runOnce();
+ if (cgRadSens.hasSensor())
+ result = cgRadSens.runOnce();
#endif
}
return result;
@@ -210,16 +214,19 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
// Display "Env. From: ..." on its own
display->drawString(x, y, "Env. From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
- String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
- if (moduleConfig.telemetry.environment_display_fahrenheit) {
- last_temp =
- String(UnitConversions::CelsiusToFahrenheit(lastMeasurement.variant.environment_metrics.temperature), 0) + "°F";
- }
+ if (lastMeasurement.variant.environment_metrics.has_temperature ||
+ lastMeasurement.variant.environment_metrics.has_relative_humidity) {
+ String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
+ if (moduleConfig.telemetry.environment_display_fahrenheit) {
+ last_temp =
+ String(UnitConversions::CelsiusToFahrenheit(lastMeasurement.variant.environment_metrics.temperature), 0) + "°F";
+ }
- // Continue with the remaining details
- display->drawString(x, y += _fontHeight(FONT_SMALL),
- "Temp/Hum: " + last_temp + " / " +
- String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
+ // Continue with the remaining details
+ display->drawString(x, y += _fontHeight(FONT_SMALL),
+ "Temp/Hum: " + last_temp + " / " +
+ String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
+ }
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0) {
display->drawString(x, y += _fontHeight(FONT_SMALL),
@@ -243,6 +250,10 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
if (lastMeasurement.variant.environment_metrics.weight != 0)
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg");
+
+ if (lastMeasurement.variant.environment_metrics.radiation != 0)
+ display->drawString(x, y += _fontHeight(FONT_SMALL),
+ "Rad: " + String(lastMeasurement.variant.environment_metrics.radiation, 2) + "µR/h");
}
bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
@@ -263,6 +274,8 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
t->variant.environment_metrics.wind_speed, t->variant.environment_metrics.wind_direction,
t->variant.environment_metrics.weight);
+ LOG_INFO("(Received from %s): radiation=%fµR/h", sender, t->variant.environment_metrics.radiation);
+
#endif
// release previous packet before occupying a new spot
if (lastMeasurementPacket != nullptr)
@@ -390,6 +403,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
valid = valid && max17048Sensor.getMetrics(m);
hasSensor = true;
}
+ if (cgRadSens.hasSensor()) {
+ valid = valid && cgRadSens.getMetrics(m);
+ hasSensor = true;
+ }
#endif
return valid && hasSensor;
@@ -443,6 +460,8 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
LOG_INFO("Send: wind speed=%fm/s, direction=%d degrees, weight=%fkg", m.variant.environment_metrics.wind_speed,
m.variant.environment_metrics.wind_direction, m.variant.environment_metrics.weight);
+ LOG_INFO("Send: radiation=%fµR/h", m.variant.environment_metrics.radiation);
+
sensor_read_error_count = 0;
meshtastic_MeshPacket *p = allocDataProtobuf(m);
@@ -585,6 +604,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
if (result != AdminMessageHandleResult::NOT_HANDLED)
return result;
}
+ if (cgRadSens.hasSensor()) {
+ result = cgRadSens.handleAdminMessage(mp, request, response);
+ if (result != AdminMessageHandleResult::NOT_HANDLED)
+ return result;
+ }
return result;
}
diff --git a/src/modules/Telemetry/HealthTelemetry.cpp b/src/modules/Telemetry/HealthTelemetry.cpp
index 7cacdc6c1..22534e9f5 100644
--- a/src/modules/Telemetry/HealthTelemetry.cpp
+++ b/src/modules/Telemetry/HealthTelemetry.cpp
@@ -40,7 +40,7 @@ int32_t HealthTelemetryModule::runOnce()
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.health_update_interval,
default_telemetry_broadcast_interval_secs);
LOG_DEBUG("Sleep for %ims, then awake to send metrics again", nightyNightMs);
- doDeepSleep(nightyNightMs, true);
+ doDeepSleep(nightyNightMs, true, false);
}
uint32_t result = UINT32_MAX;
diff --git a/src/modules/Telemetry/PowerTelemetry.cpp b/src/modules/Telemetry/PowerTelemetry.cpp
index 409585f44..367643849 100644
--- a/src/modules/Telemetry/PowerTelemetry.cpp
+++ b/src/modules/Telemetry/PowerTelemetry.cpp
@@ -28,7 +28,7 @@ int32_t PowerTelemetryModule::runOnce()
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.power_update_interval,
default_telemetry_broadcast_interval_secs);
LOG_DEBUG("Sleep for %ims, then awake to send metrics again", nightyNightMs);
- doDeepSleep(nightyNightMs, true);
+ doDeepSleep(nightyNightMs, true, false);
}
uint32_t result = UINT32_MAX;
diff --git a/src/modules/Telemetry/Sensor/CGRadSensSensor.cpp b/src/modules/Telemetry/Sensor/CGRadSensSensor.cpp
new file mode 100644
index 000000000..5e69cc22f
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/CGRadSensSensor.cpp
@@ -0,0 +1,75 @@
+/*
+ * Support for the ClimateGuard RadSens Dosimeter
+ * A fun and educational sensor for Meshtastic; not for safety critical applications.
+ */
+#include "configuration.h"
+
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
+
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "CGRadSensSensor.h"
+#include "TelemetrySensor.h"
+#include
+#include
+
+CGRadSensSensor::CGRadSensSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_RADSENS, "RadSens") {}
+
+int32_t CGRadSensSensor::runOnce()
+{
+ // Initialize the sensor following the same pattern as RCWL9620Sensor
+ LOG_INFO("Init sensor: %s", sensorName);
+ if (!hasSensor()) {
+ return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
+ }
+
+ status = true;
+ begin(nodeTelemetrySensorsMap[sensorType].second, nodeTelemetrySensorsMap[sensorType].first);
+
+ return initI2CSensor();
+}
+
+void CGRadSensSensor::setup() {}
+
+void CGRadSensSensor::begin(TwoWire *wire, uint8_t addr)
+{
+ // Store the Wire and address to the sensor following the same pattern as RCWL9620Sensor
+ _wire = wire;
+ _addr = addr;
+ _wire->begin();
+}
+
+float CGRadSensSensor::getStaticRadiation()
+{
+ // Read a register, following the same pattern as the RCWL9620Sensor
+ uint32_t data;
+ _wire->beginTransmission(_addr); // Transfer data to addr.
+ _wire->write(0x06); // Radiation intensity (static period T = 500 sec)
+ if (_wire->endTransmission() == 0) {
+ if (_wire->requestFrom(_addr, (uint8_t)3)) {
+ ; // Request 3 bytes
+ data = _wire->read();
+ data <<= 8;
+ data |= _wire->read();
+ data <<= 8;
+ data |= _wire->read();
+
+ // As per the data sheet for the RadSens
+ // Register 0x06 contains the reading in 0.1 * μR / h
+ float microRadPerHr = float(data) / 10.0;
+ return microRadPerHr;
+ }
+ }
+ return -1.0;
+}
+
+bool CGRadSensSensor::getMetrics(meshtastic_Telemetry *measurement)
+{
+ // Store the meansurement in the the appropriate fields of the protobuf
+ measurement->variant.environment_metrics.has_radiation = true;
+
+ LOG_DEBUG("CGRADSENS getMetrics");
+ measurement->variant.environment_metrics.radiation = getStaticRadiation();
+
+ return true;
+}
+#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/CGRadSensSensor.h b/src/modules/Telemetry/Sensor/CGRadSensSensor.h
new file mode 100644
index 000000000..3b15a19a2
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/CGRadSensSensor.h
@@ -0,0 +1,30 @@
+/*
+ * Support for the ClimateGuard RadSens Dosimeter
+ * A fun and educational sensor for Meshtastic; not for safety critical applications.
+ */
+#include "configuration.h"
+
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
+
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include
+
+class CGRadSensSensor : public TelemetrySensor
+{
+ private:
+ uint8_t _addr = 0x66;
+ TwoWire *_wire = &Wire;
+
+ protected:
+ virtual void setup() override;
+ void begin(TwoWire *wire = &Wire, uint8_t addr = 0x66);
+ float getStaticRadiation();
+
+ public:
+ CGRadSensSensor();
+ virtual int32_t runOnce() override;
+ virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/modules/esp32/PaxcounterModule.cpp b/src/modules/esp32/PaxcounterModule.cpp
index 89e486f82..b27586771 100644
--- a/src/modules/esp32/PaxcounterModule.cpp
+++ b/src/modules/esp32/PaxcounterModule.cpp
@@ -95,7 +95,9 @@ int32_t PaxcounterModule::runOnce()
// internal processing initialization
libpax_counter_init(handlePaxCounterReportRequest, &count_from_libpax,
- moduleConfig.paxcounter.paxcounter_update_interval, 0);
+ Default::getConfiguredOrDefault(moduleConfig.paxcounter.paxcounter_update_interval,
+ default_telemetry_broadcast_interval_secs),
+ 0);
libpax_counter_start();
} else {
sendInfo(NODENUM_BROADCAST);
diff --git a/src/motion/AccelerometerThread.h b/src/motion/AccelerometerThread.h
index 8d1260195..95f09910f 100755
--- a/src/motion/AccelerometerThread.h
+++ b/src/motion/AccelerometerThread.h
@@ -7,7 +7,9 @@
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#include "../concurrency/OSThread.h"
+#ifdef HAS_BMA423
#include "BMA423Sensor.h"
+#endif
#include "BMX160Sensor.h"
#include "ICM20948Sensor.h"
#include "LIS3DHSensor.h"
@@ -17,7 +19,9 @@
#ifdef HAS_QMA6100P
#include "QMA6100PSensor.h"
#endif
+#ifdef HAS_STK8XXX
#include "STK8XXXSensor.h"
+#endif
extern ScanI2C::DeviceAddress accelerometer_found;
@@ -79,9 +83,11 @@ class AccelerometerThread : public concurrency::OSThread
#endif
switch (device.type) {
+#ifdef HAS_BMA423
case ScanI2C::DeviceType::BMA423:
sensor = new BMA423Sensor(device);
break;
+#endif
case ScanI2C::DeviceType::MPU6050:
sensor = new MPU6050Sensor(device);
break;
@@ -94,9 +100,11 @@ class AccelerometerThread : public concurrency::OSThread
case ScanI2C::DeviceType::LSM6DS3:
sensor = new LSM6DS3Sensor(device);
break;
+#ifdef HAS_STK8XXX
case ScanI2C::DeviceType::STK8BAXX:
sensor = new STK8XXXSensor(device);
break;
+#endif
case ScanI2C::DeviceType::ICM20948:
sensor = new ICM20948Sensor(device);
break;
diff --git a/src/motion/BMA423Sensor.cpp b/src/motion/BMA423Sensor.cpp
index 382b595e1..d7058bab0 100755
--- a/src/motion/BMA423Sensor.cpp
+++ b/src/motion/BMA423Sensor.cpp
@@ -1,6 +1,6 @@
#include "BMA423Sensor.h"
-#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
+#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423)
using namespace MotionSensorI2C;
diff --git a/src/motion/BMA423Sensor.h b/src/motion/BMA423Sensor.h
index 0bc0ddf8c..455315aa9 100755
--- a/src/motion/BMA423Sensor.h
+++ b/src/motion/BMA423Sensor.h
@@ -4,7 +4,7 @@
#include "MotionSensor.h"
-#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
+#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423)
#include
#include
diff --git a/src/motion/STK8XXXSensor.cpp b/src/motion/STK8XXXSensor.cpp
index 8e9b1a63e..377ee3c37 100755
--- a/src/motion/STK8XXXSensor.cpp
+++ b/src/motion/STK8XXXSensor.cpp
@@ -1,6 +1,6 @@
#include "STK8XXXSensor.h"
-#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
+#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_STK8XXX)
STK8XXXSensor::STK8XXXSensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
diff --git a/src/motion/STK8XXXSensor.h b/src/motion/STK8XXXSensor.h
index 190b916b4..cff98d87d 100755
--- a/src/motion/STK8XXXSensor.h
+++ b/src/motion/STK8XXXSensor.h
@@ -4,7 +4,7 @@
#include "MotionSensor.h"
-#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
+#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_STK8XXX)
#ifdef STK8XXX_INT
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index 0e2710940..3d5948976 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -545,9 +545,11 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me
// mp_decoded will not be decoded when it's PKI encrypted and not directed to us
if (mp_decoded.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
+ // For uplinking other's packets, check if it's not OK to MQTT or if it's an older packet without the bitfield
+ bool dontUplink = !mp_decoded.decoded.has_bitfield ||
+ (mp_decoded.decoded.has_bitfield && !(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK));
// check for the lowest bit of the data bitfield set false, and the use of one of the default keys.
- if (!isFromUs(&mp_decoded) && !isMqttServerAddressPrivate && mp_decoded.decoded.has_bitfield &&
- !(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK) &&
+ if (!isFromUs(&mp_decoded) && !isMqttServerAddressPrivate && dontUplink &&
(ch.settings.psk.size < 2 || (ch.settings.psk.size == 16 && memcmp(ch.settings.psk.bytes, defaultpsk, 16)) ||
(ch.settings.psk.size == 32 && memcmp(ch.settings.psk.bytes, eventpsk, 32)))) {
LOG_INFO("MQTT onSend - Not forwarding packet due to DontMqttMeBro flag");
diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h
index b2b7b5a20..ce99244ba 100644
--- a/src/platform/nrf52/architecture.h
+++ b/src/platform/nrf52/architecture.h
@@ -47,6 +47,8 @@
#define HW_VENDOR meshtastic_HardwareModel_PPR
#elif defined(RAK2560)
#define HW_VENDOR meshtastic_HardwareModel_RAK2560
+#elif defined(WISMESH_TAP)
+#define HW_VENDOR meshtastic_HardwareModel_WISMESH_TAP
#elif defined(RAK4630)
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
#elif defined(TTGO_T_ECHO)
diff --git a/src/serialization/MeshPacketSerializer.cpp b/src/serialization/MeshPacketSerializer.cpp
index 05a98f7a6..b4603186b 100644
--- a/src/serialization/MeshPacketSerializer.cpp
+++ b/src/serialization/MeshPacketSerializer.cpp
@@ -78,6 +78,7 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
msgPayload["wind_direction"] = new JSONValue((uint)decoded->variant.environment_metrics.wind_direction);
msgPayload["wind_gust"] = new JSONValue(decoded->variant.environment_metrics.wind_gust);
msgPayload["wind_lull"] = new JSONValue(decoded->variant.environment_metrics.wind_lull);
+ msgPayload["radiation"] = new JSONValue(decoded->variant.environment_metrics.radiation);
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
msgPayload["pm10"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm10_standard);
msgPayload["pm25"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm25_standard);
diff --git a/src/serialization/MeshPacketSerializer_nRF52.cpp b/src/serialization/MeshPacketSerializer_nRF52.cpp
index 15b8b1a34..89ecddfad 100644
--- a/src/serialization/MeshPacketSerializer_nRF52.cpp
+++ b/src/serialization/MeshPacketSerializer_nRF52.cpp
@@ -77,6 +77,7 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
jsonObj["payload"]["wind_direction"] = (uint)decoded->variant.environment_metrics.wind_direction;
jsonObj["payload"]["wind_gust"] = decoded->variant.environment_metrics.wind_gust;
jsonObj["payload"]["wind_lull"] = decoded->variant.environment_metrics.wind_lull;
+ jsonObj["payload"]["radiation"] = decoded->variant.environment_metrics.radiation;
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
jsonObj["payload"]["pm10"] = (unsigned int)decoded->variant.air_quality_metrics.pm10_standard;
jsonObj["payload"]["pm25"] = (unsigned int)decoded->variant.air_quality_metrics.pm25_standard;
diff --git a/src/sleep.cpp b/src/sleep.cpp
index a50f7aac3..05597cdfa 100644
--- a/src/sleep.cpp
+++ b/src/sleep.cpp
@@ -187,7 +187,7 @@ static void waitEnterSleep(bool skipPreflight = false)
notifySleep.notifyObservers(NULL);
}
-void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
+void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveNodeDb = false)
{
if (INCLUDE_vTaskSuspend && (msecToWake == portMAX_DELAY)) {
LOG_INFO("Enter deep sleep forever");
@@ -219,7 +219,9 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
screen->doDeepSleep(); // datasheet says this will draw only 10ua
- nodeDB->saveToDisk();
+ if (!skipSaveNodeDb) {
+ nodeDB->saveToDisk();
+ }
#ifdef PIN_POWER_EN
pinMode(PIN_POWER_EN, INPUT); // power off peripherals
diff --git a/src/sleep.h b/src/sleep.h
index 6ac420769..8d3cb17e8 100644
--- a/src/sleep.h
+++ b/src/sleep.h
@@ -4,7 +4,7 @@
#include "Observer.h"
#include "configuration.h"
-void doDeepSleep(uint32_t msecToWake, bool skipPreflight), cpuDeepSleep(uint32_t msecToWake);
+void doDeepSleep(uint32_t msecToWake, bool skipPreflight, bool skipSaveNodeDb), cpuDeepSleep(uint32_t msecToWake);
#ifdef ARCH_ESP32
#include "esp_sleep.h"
diff --git a/userPrefs.h b/userPrefs.h
index 58a44fef0..00f04149a 100644
--- a/userPrefs.h
+++ b/userPrefs.h
@@ -68,10 +68,40 @@ static unsigned char icon_bits[] = {
0x98, 0x3F, 0xF0, 0x23, 0x00, 0xFC, 0x0F, 0xE0, 0x7F, 0x00, 0xFC, 0x03, 0x80, 0xFF, 0x01, 0xFC, 0x00, 0x00, 0x3E, 0x00, 0x70,
0x00, 0x00, 0x1C, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00};
*/
+
/*
-#define USERPREFS_USE_ADMIN_KEY 1
-static unsigned char USERPREFS_ADMIN_KEY[] = {0xcd, 0xc0, 0xb4, 0x3c, 0x53, 0x24, 0xdf, 0x13, 0xca, 0x5a, 0xa6,
- 0x0c, 0x0d, 0xec, 0x85, 0x5a, 0x4c, 0xf6, 0x1a, 0x96, 0x04, 0x1a,
- 0x3e, 0xfc, 0xbb, 0x8e, 0x33, 0x71, 0xe5, 0xfc, 0xff, 0x3c};
+ * PKI Admin keys.
+ * If a Admin key is set with '{};'
+ * then it will be ignored, a PKI key must have a size of 32 byte.
+ */
+/*
+#define USERPREFS_USE_ADMIN_KEY_0 \
+ { \
+ 0xcd, 0xc0, 0xb4, 0x3c, 0x53, 0x24, 0xdf, 0x13, 0xca, 0x5a, 0xa6, 0x0c, 0x0d, 0xec, 0x85, 0x5a, 0x4c, 0xf6, 0x1a, 0x96, \
+ 0x04, 0x1a, 0x3e, 0xfc, 0xbb, 0x8e, 0x33, 0x71, 0xe5, 0xfc, 0xff, 0x3c \
+ };
*/
+// #define USERPREFS_USE_ADMIN_KEY_1 {};
+// #define USERPREFS_USE_ADMIN_KEY_2 {};
+
+/*
+ * USERPREF_FIXED_GPS_LAT and USERPREF_FIXED_GPS_LON must be set, USERPREF_FIXED_GPS_ALT is optional
+ *
+ * Fixed GPS is Eiffel Tower, Paris, France
+ */
+// #define USERPREFS_FIXED_GPS
+// #define USERPREFS_FIXED_GPS_LAT 48.85873920
+// #define USERPREFS_FIXED_GPS_LON 2.294508368
+// #define USERPREFS_FIXED_GPS_ALT 0
+
+/*
+ * Set Fixed Bluetooth paring code
+ */
+// #define USERPREFS_FIXED_BLUETOOTH 121212
+
+/*
+ * Will overwrite BUTTON_PIN if set
+ */
+// #define USERPREFS_BUTTON_PIN 36
+
#endif
\ No newline at end of file
diff --git a/variants/diy/platformio.ini b/variants/diy/platformio.ini
index 00ff88da2..83e2175c8 100644
--- a/variants/diy/platformio.ini
+++ b/variants/diy/platformio.ini
@@ -2,6 +2,7 @@
[env:meshtastic-diy-v1]
extends = esp32_base
board = esp32doit-devkit-v1
+board_level = extra
board_check = true
build_flags =
${esp32_base.build_flags}
diff --git a/variants/dreamcatcher/platformio.ini b/variants/dreamcatcher/platformio.ini
index 46f9b9871..c57849d96 100644
--- a/variants/dreamcatcher/platformio.ini
+++ b/variants/dreamcatcher/platformio.ini
@@ -11,7 +11,7 @@ build_flags =
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps = ${esp32s3_base.lib_deps}
- earlephilhower/ESP8266Audio@^1.9.7
+ earlephilhower/ESP8266Audio@^1.9.9
earlephilhower/ESP8266SAM@^1.0.1
[env:dreamcatcher-2206]
diff --git a/variants/dreamcatcher/variant.h b/variants/dreamcatcher/variant.h
index eb95a95dd..7835979e1 100644
--- a/variants/dreamcatcher/variant.h
+++ b/variants/dreamcatcher/variant.h
@@ -60,6 +60,7 @@
#define DAC_I2S_BCK 21
#define DAC_I2S_WS 9
#define DAC_I2S_DOUT 48
+#define DAC_I2S_MCLK 44
#define BIAS_T_ENABLE 7 // needs to be low
#define BIAS_T_VALUE 0
diff --git a/variants/radiomaster_900_bandit/platformio.ini b/variants/radiomaster_900_bandit/platformio.ini
index 4ff8a6ea2..010791d8a 100644
--- a/variants/radiomaster_900_bandit/platformio.ini
+++ b/variants/radiomaster_900_bandit/platformio.ini
@@ -6,9 +6,11 @@ build_flags =
-DRADIOMASTER_900_BANDIT
-DVTABLES_IN_FLASH=1
-DCONFIG_DISABLE_HAL_LOCKS=1
+ -DHAS_STK8XXX=1
-O2
-Ivariants/radiomaster_900_bandit
board_build.f_cpu = 240000000L
upload_protocol = esptool
lib_deps =
- ${esp32_base.lib_deps}
\ No newline at end of file
+ ${esp32_base.lib_deps}
+ https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
diff --git a/variants/rak11310/platformio.ini b/variants/rak11310/platformio.ini
index c7b3504fe..923cedaa3 100644
--- a/variants/rak11310/platformio.ini
+++ b/variants/rak11310/platformio.ini
@@ -3,6 +3,7 @@ extends = rp2040_base
board = wiscore_rak11300
upload_protocol = picotool
# keep an old SDK to use less memory.
+platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.7.2
# add our variants files to the include and src paths
@@ -13,5 +14,5 @@ build_flags = ${rp2040_base.build_flags}
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus"
lib_deps =
${rp2040_base.lib_deps}
-debug_build_flags = ${rp2040_base.build_flags}
+debug_build_flags = ${rp2040_base.build_flags}, -g
debug_tool = cmsis-dap ; for e.g. Picotool
\ No newline at end of file
diff --git a/variants/rak_wismeshtap/platformio.ini b/variants/rak_wismeshtap/platformio.ini
index 38b988dff..bcf46b90d 100644
--- a/variants/rak_wismeshtap/platformio.ini
+++ b/variants/rak_wismeshtap/platformio.ini
@@ -1,17 +1,18 @@
; The very slick RAK wireless RAK10701 Field Tester device. Note you will have to flash to Arduino bootloader to use this firmware. Be aware touch is not currently working.
[env:rak_wismeshtap]
extends = nrf52840_base
-board_level = extra
board = wiscore_rak4631
-build_flags = ${nrf52840_base.build_flags} -Ivariants/rak_wismeshtap -D RAK_4631
+build_flags = ${nrf52840_base.build_flags} -Ivariants/rak_wismeshtap -DWISMESH_TAP -DRAK_4631
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-DEINK_DISPLAY_MODEL=GxEPD2_213_BN
-DEINK_WIDTH=250
-DEINK_HEIGHT=122
-DMESHTASTIC_EXCLUDE_WIFI=1
- -DMESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION=1
- -DMESHTASTIC_EXCLUDE_WAYPOINT=1
+ -DMESHTASTIC_EXCLUDE_DETECTIONSENSOR=1
+ -DMESHTASTIC_EXCLUDE_STOREFORWARD=1
+ -DMESHTASTIC_EXCLUDE_POWER_TELEMETRY=1
+ -DMESHTASTIC_EXCLUDE_ATAK=1
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak_wismeshtap> + + +
lib_deps =
${nrf52840_base.lib_deps}
@@ -24,4 +25,4 @@ lib_deps =
beegee-tokyo/RAK14014-FT6336U @ 1.0.1
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
-;upload_protocol = jlink
\ No newline at end of file
+;upload_protocol = jlink
diff --git a/variants/rak_wismeshtap/variant.h b/variants/rak_wismeshtap/variant.h
index 19eb841fe..c21a11ac1 100644
--- a/variants/rak_wismeshtap/variant.h
+++ b/variants/rak_wismeshtap/variant.h
@@ -271,13 +271,8 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
#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
@@ -311,7 +306,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
#define SCREEN_TOUCH_INT WB_IO6
#define CANNED_MESSAGE_MODULE_ENABLE 1
-
+#define USE_VIRTUAL_KEYBOARD 1
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
diff --git a/variants/rp2040-lora/platformio.ini b/variants/rp2040-lora/platformio.ini
index 8499f6f3c..4c578fb2b 100644
--- a/variants/rp2040-lora/platformio.ini
+++ b/variants/rp2040-lora/platformio.ini
@@ -12,5 +12,5 @@ build_flags = ${rp2040_base.build_flags}
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus"
lib_deps =
${rp2040_base.lib_deps}
-debug_build_flags = ${rp2040_base.build_flags}
+debug_build_flags = ${rp2040_base.build_flags}, -g
debug_tool = cmsis-dap ; for e.g. Picotool
\ No newline at end of file
diff --git a/variants/rpipico/platformio.ini b/variants/rpipico/platformio.ini
index e4b9e479f..9c62ebcb5 100644
--- a/variants/rpipico/platformio.ini
+++ b/variants/rpipico/platformio.ini
@@ -12,5 +12,5 @@ build_flags = ${rp2040_base.build_flags}
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus"
lib_deps =
${rp2040_base.lib_deps}
-debug_build_flags = ${rp2040_base.build_flags}
+debug_build_flags = ${rp2040_base.build_flags}, -g
debug_tool = cmsis-dap ; for e.g. Picotool
\ No newline at end of file
diff --git a/variants/rpipico2/platformio.ini b/variants/rpipico2/platformio.ini
index a63414418..24714efd5 100644
--- a/variants/rpipico2/platformio.ini
+++ b/variants/rpipico2/platformio.ini
@@ -12,5 +12,5 @@ build_flags = ${rp2350_base.build_flags}
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus"
lib_deps =
${rp2350_base.lib_deps}
-debug_build_flags = ${rp2350_base.build_flags}
+debug_build_flags = ${rp2350_base.build_flags}, -g
debug_tool = cmsis-dap ; for e.g. Picotool
\ No newline at end of file
diff --git a/variants/rpipicow/platformio.ini b/variants/rpipicow/platformio.ini
index 2600b4b38..7a43ece3b 100644
--- a/variants/rpipicow/platformio.ini
+++ b/variants/rpipicow/platformio.ini
@@ -14,5 +14,5 @@ build_src_filter = ${rp2040_base.build_src_filter} +
lib_deps =
${rp2040_base.lib_deps}
${networking_base.lib_deps}
-debug_build_flags = ${rp2040_base.build_flags}
+debug_build_flags = ${rp2040_base.build_flags}, -g
debug_tool = cmsis-dap ; for e.g. Picotool
\ No newline at end of file
diff --git a/variants/seeed-sensecap-indicator/variant.h b/variants/seeed-sensecap-indicator/variant.h
index 217b66ac4..aec61f0bc 100644
--- a/variants/seeed-sensecap-indicator/variant.h
+++ b/variants/seeed-sensecap-indicator/variant.h
@@ -39,12 +39,13 @@
#define TOUCH_I2C_PORT 0
#define TOUCH_SLAVE_ADDRESS 0x48
-// Buzzer
-#define PIN_BUZZER 19
+// in future, we may want to add a buzzer and add all sensors to the indicator via a data protocol for now only GPS is supported
+// // Buzzer
+// #define PIN_BUZZER 19
-#define HAS_GPS 0
-#undef GPS_RX_PIN
-#undef GPS_TX_PIN
+#define GPS_RX_PIN 20
+#define GPS_TX_PIN 19
+#define HAS_GPS 1
#define USE_SX1262
#define USE_SX1268
@@ -65,3 +66,6 @@
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
+
+#define USE_VIRTUAL_KEYBOARD 1
+#define DISPLAY_CLOCK_FRAME 1
diff --git a/variants/t-deck/platformio.ini b/variants/t-deck/platformio.ini
index a63ff57a7..16769e2f2 100644
--- a/variants/t-deck/platformio.ini
+++ b/variants/t-deck/platformio.ini
@@ -15,5 +15,5 @@ build_flags = ${esp32_base.build_flags}
lib_deps = ${esp32s3_base.lib_deps}
lovyan03/LovyanGFX@^1.1.9
- earlephilhower/ESP8266Audio@^1.9.7
+ earlephilhower/ESP8266Audio@^1.9.9
earlephilhower/ESP8266SAM@^1.0.1
\ No newline at end of file
diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h
index 9860d608f..6d398391e 100644
--- a/variants/t-deck/variant.h
+++ b/variants/t-deck/variant.h
@@ -73,6 +73,7 @@
#define DAC_I2S_BCK 7
#define DAC_I2S_WS 5
#define DAC_I2S_DOUT 6
+#define DAC_I2S_MCLK 21 // GPIO lrck mic
// LoRa
#define USE_SX1262
diff --git a/variants/t-watch-s3/platformio.ini b/variants/t-watch-s3/platformio.ini
index 1f5fc278b..005c4d021 100644
--- a/variants/t-watch-s3/platformio.ini
+++ b/variants/t-watch-s3/platformio.ini
@@ -9,10 +9,12 @@ build_flags = ${esp32_base.build_flags}
-DT_WATCH_S3
-Ivariants/t-watch-s3
-DPCF8563_RTC=0x51
+ -DHAS_BMA423=1
lib_deps = ${esp32s3_base.lib_deps}
lovyan03/LovyanGFX@^1.1.9
lewisxhe/PCF8563_Library@1.0.1
adafruit/Adafruit DRV2605 Library@^1.2.2
- earlephilhower/ESP8266Audio@^1.9.7
- earlephilhower/ESP8266SAM@^1.0.1
\ No newline at end of file
+ earlephilhower/ESP8266Audio@^1.9.9
+ earlephilhower/ESP8266SAM@^1.0.1
+ lewisxhe/SensorLib@0.2.0
diff --git a/variants/t-watch-s3/variant.h b/variants/t-watch-s3/variant.h
index 9f939d859..5a6aebfa2 100644
--- a/variants/t-watch-s3/variant.h
+++ b/variants/t-watch-s3/variant.h
@@ -34,6 +34,7 @@
#define DAC_I2S_BCK 48
#define DAC_I2S_WS 15
#define DAC_I2S_DOUT 46
+#define DAC_I2S_MCLK 0
#define HAS_AXP2101
@@ -71,3 +72,6 @@
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for
// the sx1262interface code)
+
+#define USE_VIRTUAL_KEYBOARD 1
+#define DISPLAY_CLOCK_FRAME 1
diff --git a/version.properties b/version.properties
index 91c1f4823..bed14bad5 100644
--- a/version.properties
+++ b/version.properties
@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 5
-build = 12
+build = 14