From 4d5ccbdd98a5108bb99085811238c347fb286128 Mon Sep 17 00:00:00 2001 From: mikecarper Date: Sat, 22 Aug 2026 13:27:01 -0700 Subject: [PATCH] Retain GPS in RAK nRF52 OTA repeaters --- docs/cli_build_matrix.md | 2 +- docs/ota_easy.md | 10 ++++----- docs/ota_nrf52_bootloader_update.md | 8 ++++---- docs/ota_protocol.md | 8 ++++---- docs/ota_user_guide.md | 17 +++++++-------- docs/rak3401_mota_chain.md | 6 +++++- tools/mota/test_mota.py | 32 +++++++++++++++++++++++++++++ variants/rak3401/platformio.ini | 10 +++++---- variants/rak4631/platformio.ini | 21 ++++++++++++------- 9 files changed, 79 insertions(+), 35 deletions(-) diff --git a/docs/cli_build_matrix.md b/docs/cli_build_matrix.md index 1b7a4022b..28c7bd6a6 100644 --- a/docs/cli_build_matrix.md +++ b/docs/cli_build_matrix.md @@ -41,7 +41,7 @@ retain 50 because their MQTT discovery tables are constrained by internal DRAM. | ESP32 MQTT observer or ESP-NOW bridge | Always uses the expanded FULL partition profile. The build never substitutes a reduced CLI to fit the legacy application slot. | | FULL ESP32 | Uses the matching MQTT target with logging off and keeps the complete command surface supported by that role and hardware. | | FULL ESP32 logging | Uses the matching non-MQTT target with debug and packet logging enabled, session-only `get/set usb.logging` control, and the complete command surface supported by that role and hardware. | -| `no_external_sensors` | Removes optional external-sensor drivers and their settings; it does not remove core repeater discovery or routing commands. On RAK3401, this profile also compiles out GPS, so RAK12501 requires the ordinary full-sensor build. | +| `no_external_sensors` | Removes optional external-sensor drivers and their settings; it does not remove core repeater discovery or routing commands. GPS-preserving RAK nRF52 OTA profiles retain their GPS commands and provider. The RAK4631 Serial1 RS232 bridge remains GPS-off because both features require Serial1. | `logging`, `OTA`, and `FULL` describe independent build features. Do not infer that a command is missing merely because `logging` appears in the filename. diff --git a/docs/ota_easy.md b/docs/ota_easy.md index 344d72076..6102bd1dc 100644 --- a/docs/ota_easy.md +++ b/docs/ota_easy.md @@ -68,12 +68,10 @@ overlapping window. `build.sh` provides a `*_repeater_lora_ota_no_external_sensors` build for standalone ESP32 and nRF52 repeater targets that need a smaller internal update workspace. Those siblings omit optional external I2C environmental sensors while retaining board-native features such as displays, buttons, battery monitoring, -and integrated GPS where the target uses the GPS-preserving lean profile. The -RAK3401 target is an explicit exception: -`RAK_3401_repeater_lora_ota_no_external_sensors` compiles out GPS and cannot -use a RAK12501. Use the ordinary full-sensor `RAK_3401_repeater` build with a -RAK12501 in sensor slot A when GPS is required; slot D conflicts with the -RAK13302 radio's BUSY/DIO1 lines. Selected nRF52 boards with matched external +and GPS where the target uses the GPS-preserving lean profile. The RAK3401 OTA +repeater retains RAK12501 support in sensor slot A; slot D conflicts with the +RAK13302 radio's BUSY/DIO1 lines. The RAK4631 OTA repeater retains GPS except +for its Serial1 RS232 bridge, which uses the same UART. Selected nRF52 boards with matched external QSPI application and bootloader support can instead make the normal full-sensor repeater install-capable; those targets do not need to reserve internal flash for the downloaded container. Other normal repeaters can still serve as diff --git a/docs/ota_nrf52_bootloader_update.md b/docs/ota_nrf52_bootloader_update.md index 3859d9afd..947a7aaa6 100644 --- a/docs/ota_nrf52_bootloader_update.md +++ b/docs/ota_nrf52_bootloader_update.md @@ -142,10 +142,10 @@ stable release uses `0xFF`, and low-byte zero or all-ones values are rejected. There is no remote rollback/migration override; intentional rollback uses USB/BLE DFU or SWD. -The `no_external_sensors` profiles omit optional/add-on sensor and GPS packages -to preserve flash headroom. Board-integrated GPS can be retained by a board's -recipe. The RAK3401 lean target specifically omits RAK12501/add-on GPS; use the -ordinary full-sensor target when that module is required. +The `no_external_sensors` profiles omit optional/add-on sensor packages to +preserve flash headroom. A board recipe can retain GPS. The RAK3401 OTA +repeater retains RAK12501 GPS in sensor slot A, and the RAK4631 OTA repeater +retains GPS except where a Serial1 RS232 bridge owns the same UART. Boards with onboard external flash are not silently redirected to internal staging. Mesh Solar, Nano G2 Ultra, T-Impulse Plus, ThinkNode M8, T-Echo diff --git a/docs/ota_protocol.md b/docs/ota_protocol.md index 6dd77ec4b..8973cece9 100644 --- a/docs/ota_protocol.md +++ b/docs/ota_protocol.md @@ -128,10 +128,10 @@ established target-specific 1920 KiB or larger A/B app layout and are checked ag partition. For every standalone ESP32 and nRF52 repeater, `build.sh` also exposes an explicit `*_lora_ota_no_external_sensors` artifact: the ordinary repeater remains sensor-enabled, while that sibling disables optional external environmental-sensor drivers for LoRa distribution. Integrated GPS and other -board-native telemetry remain enabled where the target selects the GPS-preserving lean profile. RAK3401 is -the explicit exception: `RAK_3401_repeater_lora_ota_no_external_sensors` undefines `ENV_INCLUDE_GPS`, so it -does not detect or use a RAK12501. RAK12501 GPS requires the ordinary full-sensor `RAK_3401_repeater` build -and sensor slot A; slot D conflicts with the RAK13302 radio's BUSY/DIO1 lines. +board-native telemetry remain enabled where the target selects the GPS-preserving lean profile. The RAK3401 +OTA repeater also retains RAK12501 GPS support; install that module in sensor slot A because slot D conflicts +with the RAK13302 radio's BUSY/DIO1 lines. RAK4631 OTA repeaters retain GPS except for the Serial1 RS232 +bridge, whose bridge and GPS would contend for the same UART. ESP32 siblings retain the compact browser WiFi updater and use the full 254-entry neighbor table. RP2040 and STM32 targets are not offered because those platforms do not yet have a safe bootloader/apply path. diff --git a/docs/ota_user_guide.md b/docs/ota_user_guide.md index 573907376..0d5ac86aa 100644 --- a/docs/ota_user_guide.md +++ b/docs/ota_user_guide.md @@ -39,14 +39,15 @@ install-capable `lora_ota_no_external_sensors` sibling is smaller: - Keepteen LT1, LilyGo T-Impulse Plus, Mesh Pocket, and Nano G2 Ultra - Minewsemi ME25LS01, RAK3401, SenseCAP Solar, and Wio WM1110 -RAK3401 is an important GPS exception: its -`RAK_3401_repeater_lora_ota_no_external_sensors` image compiles out GPS support -as well as the optional environmental sensors. It will not detect or use a -RAK12501. For RAK12501 GPS, use the ordinary full-sensor -`RAK_3401_repeater` build and install the GPS in sensor slot A. Slot D's GPS -reset/PPS lines conflict with the RAK13302 radio's BUSY/DIO1 lines. The -full-sensor RAK3401 build is not the self-updating target described by the -RAK3401 compact OTA chain. +The RAK3401 `RAK_3401_repeater_lora_ota_no_external_sensors` image retains +RAK12501 GPS while omitting the other optional environmental sensors. Install +the GPS in sensor slot A. Slot D's reset/PPS lines conflict with the RAK13302 +radio's BUSY/DIO1 lines. + +The RAK4631 internal-flash OTA repeater likewise retains GPS. A RAK12501 can +use sensor slot A or D; a RAK12500 can use slot A or C. The RAK4631 Serial1 +RS232 OTA bridge is the exception because the bridge owns the GPS UART. The +Serial2 RS232 OTA bridge retains GPS on Serial1. Selected nRF52 repeaters with dedicated external QSPI can now stage the complete package off-chip, so their normal full-sensor repeater build can diff --git a/docs/rak3401_mota_chain.md b/docs/rak3401_mota_chain.md index 98bdae152..56032f3c3 100644 --- a/docs/rak3401_mota_chain.md +++ b/docs/rak3401_mota_chain.md @@ -34,7 +34,7 @@ target: - endpoint packed version: `0x01110102` (EndF tools render this as `1.17.1.2`) - deployment target key: `63d8df6387eaffd2e25db7d2a8ad967a65202182a48d681d7e7a9260f917280d` -### GPS limitation +### Historical endpoint GPS limitation This chain's exact `RAK_3401_repeater_lora_ota_no_external_sensors` endpoint compiles with `ENV_INCLUDE_GPS` removed. It will not detect, configure, or read @@ -44,6 +44,10 @@ A. Do not use slot D with the RAK13302 1 W radio: the GPS reset/PPS signals would overlap the radio's BUSY/DIO1 signals. The full-sensor build is a different target and is not an endpoint of this compact OTA chain. +This limitation describes the immutable released chain endpoint identified +above. Newly built RAK3401 OTA repeater firmware retains RAK12501 support in +slot A, but that newer image is not retroactively part of this exact chain. + Do not use the chain on another target ID, hardware family, starting image, or firmware body hash. The runner checks all four. diff --git a/tools/mota/test_mota.py b/tools/mota/test_mota.py index dc27fded0..2f715e60f 100644 --- a/tools/mota/test_mota.py +++ b/tools/mota/test_mota.py @@ -79,6 +79,38 @@ def test_ota_target_generation_honors_explicit_disable(): assert "RAK_3401_repeater_lora_ota_no_external_sensors" in release_aliases() +def test_rak_nrf52_ota_profiles_keep_gps_where_uart_is_available(): + root = Path(__file__).resolve().parents[2] + + def env_section(path, name): + text = path.read_text(encoding="utf-8") + return text.split(f"[env:{name}]", 1)[1].split("\n[", 1)[0] + + rak4631_path = root / "variants/rak4631/platformio.ini" + gps_profiles = ( + env_section(rak4631_path, "RAK_4631_repeater_lora_ota_no_external_sensors"), + env_section( + rak4631_path, + "RAK_4631_repeater_bridge_rs232_serial2_lora_ota_no_external_sensors", + ), + env_section( + root / "variants/rak3401/platformio.ini", + "RAK_3401_repeater_lora_ota_no_external_sensors", + ), + ) + for profile in gps_profiles: + assert "${nrf52_no_external_sensors_keep_gps.build_flags}" in profile + assert "${nrf52_no_external_sensors_keep_gps.lib_deps}" in profile + assert "SparkFun u-blox GNSS Arduino Library" in profile + + serial1_bridge = env_section( + rak4631_path, + "RAK_4631_repeater_bridge_rs232_serial1_lora_ota_no_external_sensors", + ) + assert "${nrf52_no_external_sensors.build_flags}" in serial1_bridge + assert "WITH_RS232_BRIDGE=Serial1" in serial1_bridge + + def test_hardware_id_for_env(): assert ml.hardware_id_for_env("RAK_4631_repeater") == "RAK4631" assert ml.hardware_id_for_env("RAK_4631_companion_radio_usb") == "RAK4631" diff --git a/variants/rak3401/platformio.ini b/variants/rak3401/platformio.ini index 57d188a7b..f7467102d 100644 --- a/variants/rak3401/platformio.ini +++ b/variants/rak3401/platformio.ini @@ -48,15 +48,15 @@ build_src_filter = ${rak3401.build_src_filter} + +<../examples/simple_repeater> -; Explicit lean alternative to the full-sensor, non-OTA repeater above. This -; profile also removes ENV_INCLUDE_GPS: use RAK_3401_repeater with a RAK12501 -; in sensor slot A when GPS is required (slot D conflicts with radio BUSY/DIO1). +; Explicit lean alternative to the full-sensor, non-OTA repeater above. It removes optional +; environmental sensors while retaining RAK12501 GPS support. Use sensor slot A: slot D conflicts +; with the RAK13302 radio's BUSY/DIO1 wiring. The legacy target name remains stable for OTA compatibility. [env:RAK_3401_repeater_lora_ota_no_external_sensors] extends = rak3401 extra_scripts = ${nrf52_lora_ota.extra_scripts} build_flags = ${rak3401.build_flags} - ${nrf52_no_external_sensors.build_flags} + ${nrf52_no_external_sensors_keep_gps.build_flags} -D DISPLAY_CLASS=SSD1306Display -D ADVERT_NAME='"RAK3401 1W Repeater"' -D ADVERT_LAT=0.0 @@ -76,7 +76,9 @@ build_src_filter = ${rak3401.build_src_filter} +<../examples/simple_repeater> lib_deps = ${nrf52_lora_ota.lib_deps} + ${nrf52_no_external_sensors_keep_gps.lib_deps} adafruit/Adafruit SSD1306 @ ^2.5.13 + sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27 [env:RAK_3401_room_server] extends = rak3401 diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index d69e200c4..28a904e15 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -87,15 +87,16 @@ build_src_filter = ${rak4631.build_src_filter} + +<../examples/simple_repeater> -; Lean OTA target for space-constrained RAK4631 repeaters. This removes only optional external -; environmental/GPS sensor packages. RAK4631Board::getBattMilliVolts(), repeater telemetry, and -; battery.alert remain part of the board/repeater sources below. +; Lean OTA target for space-constrained RAK4631 repeaters. This removes optional external +; environmental sensor packages while retaining RAK12500/RAK12501 GPS support. The legacy +; no_external_sensors target name remains stable for OTA compatibility. RAK4631Board::getBattMilliVolts(), +; repeater telemetry, and battery.alert remain part of the board/repeater sources below. [env:RAK_4631_repeater_lora_ota_no_external_sensors] extends = rak4631 extra_scripts = ${nrf52_lora_ota.extra_scripts} build_flags = ${rak4631.build_flags} - ${nrf52_no_external_sensors.build_flags} + ${nrf52_no_external_sensors_keep_gps.build_flags} -D DISPLAY_CLASS=SSD1306Display -D ADVERT_NAME='"RAK4631 LoRa OTA No Ext Sensors"' -D ADVERT_LAT=0.0 @@ -110,7 +111,9 @@ build_src_filter = ${nrf52_lora_ota.build_src_filter} +<../examples/simple_repeater> lib_deps = ${nrf52_lora_ota.lib_deps} + ${nrf52_no_external_sensors_keep_gps.lib_deps} adafruit/Adafruit SSD1306 @ ^2.5.13 + sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27 [env:RAK_4631_repeater_ethernet] extends = rak4631 @@ -158,7 +161,8 @@ build_src_filter = ${rak4631.build_src_filter} + +<../examples/simple_repeater> -; Explicit lean alternative to the full-sensor, non-OTA Serial1 bridge above. +; Explicit lean alternative to the full-sensor, non-OTA Serial1 bridge above. GPS remains disabled: +; both the RAK12501 and this bridge require Serial1, so enabling both would corrupt both protocols. [env:RAK_4631_repeater_bridge_rs232_serial1_lora_ota_no_external_sensors] extends = rak4631 build_flags = @@ -206,12 +210,13 @@ build_src_filter = ${rak4631.build_src_filter} + +<../examples/simple_repeater> -; Explicit lean alternative to the full-sensor, non-OTA Serial2 bridge above. +; Explicit lean alternative to the full-sensor, non-OTA Serial2 bridge above. GPS remains available +; on Serial1 because this bridge owns Serial2. [env:RAK_4631_repeater_bridge_rs232_serial2_lora_ota_no_external_sensors] extends = rak4631 build_flags = ${rak4631.build_flags} - ${nrf52_no_external_sensors.build_flags} + ${nrf52_no_external_sensors_keep_gps.build_flags} -D DISPLAY_CLASS=SSD1306Display -D ADVERT_NAME='"RS232 Bridge"' -D ADVERT_LAT=0.0 @@ -227,7 +232,9 @@ build_src_filter = ${rak4631.build_src_filter} +<../examples/simple_repeater> lib_deps = ${nrf52_lora_ota.lib_deps} + ${nrf52_no_external_sensors_keep_gps.lib_deps} adafruit/Adafruit SSD1306 @ ^2.5.13 + sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27 [env:RAK_4631_room_server] extends = rak4631