diff --git a/build.sh b/build.sh index fe8c2739..2dd3b984 100755 --- a/build.sh +++ b/build.sh @@ -1615,6 +1615,17 @@ is_esp32_usb_wifi_companion_ota_build() { esac } +requires_esp32_companion_full_ota_fallback() { + # Some classic ESP32 companions cannot hold their configured high-capacity + # contact, channel, and offline-queue tables together with LoRa OTA in + # internal DRAM. Keep their ordinary high-capacity image unchanged and emit + # a separately named FULL OTA image with the companion default capacities. + case "${1,,}" in + heltec_v2_companion_radio_wifi|lilygo_tlora_v2_1_1_6_companion_radio_wifi|meshadventurer_sx1262_companion_radio_usb|meshadventurer_sx1268_companion_radio_usb) return 0 ;; + *) return 1 ;; + esac +} + is_lora_ota_build() { local env_name=$1 local env_name_lc=${env_name,,} @@ -1622,6 +1633,9 @@ is_lora_ota_build() { # ESP32 USB and WiFi companions keep OTA so they can seed a host folder over # serial or TCP and can participate in LoRa OTA without using the FULL profile. if is_esp32_usb_wifi_companion_ota_build "$env_name"; then + if requires_esp32_companion_full_ota_fallback "$env_name" && [ "$ESP32_FULL_BUILD" != "1" ]; then + return 1 + fi return 0 fi @@ -1675,6 +1689,10 @@ requires_esp32_portable_app_slot() { supports_esp32_full_build() { local env_name=$1 + if requires_esp32_companion_full_ota_fallback "$env_name"; then + return 0 + fi + [ "${PIO_ENV_FULL_BUILD_BY_NAME[$env_name]:-0}" = "1" ] \ && ! is_esp32_companion_build "$env_name" \ && ! is_lora_ota_only_target "$env_name" @@ -1728,6 +1746,11 @@ apply_esp32_full_size_profile() { append_platformio_build_unflags "-DDISABLE_WIFI_OTA=1 -DLIGHTWEIGHT_WIFI_OTA=1" export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -UDISABLE_WIFI_OTA -ULIGHTWEIGHT_WIFI_OTA" fi + + if requires_esp32_companion_full_ota_fallback "$env_name"; then + append_platformio_build_unflags "-DMAX_CONTACTS=160 -DMAX_GROUP_CHANNELS=40 -DOFFLINE_QUEUE_SIZE=128" + export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DMAX_CONTACTS=100 -DMAX_GROUP_CHANNELS=8 -DOFFLINE_QUEUE_SIZE=16" + fi } apply_lora_ota_no_external_sensors_profile() { diff --git a/docs/ota_easy.md b/docs/ota_easy.md index 0aa541a7..e8f32896 100644 --- a/docs/ota_easy.md +++ b/docs/ota_easy.md @@ -60,17 +60,19 @@ install the matching merged image over USB once before installing later non-merg ### Choose the source radio Use an ESP32 **MeshCore companion** as the source node. It receives the update folder from the computer, -then advertises it over LoRa. Current ESP32 USB and WiFi companion artifacts include `-ota-` in their -filenames and compile in the required OTA transport. Connect to that companion either by USB serial or by -WiFi. For USB serial, confirm that its USB CLI accepts: +then advertises it over LoRa. Current ESP32 USB and WiFi companion OTA artifacts include `-ota-` in their +filenames and compile in the required OTA transport. A small set of high-capacity classic ESP32 companions +keep their normal image and provide a separate `-full-ota-` image with 100 contacts, 8 group channels, and +a 16-frame offline queue. Install that variant's merged image over USB once before using it. Connect the +companion either by USB serial or by WiFi. For USB serial, confirm that its USB CLI accepts: ```text ota folder on ``` -If an older build reports that `OTA_FOLDER_SERIAL` is not compiled in, install a current `-ota-` companion -build first. Do **not** use a KISS modem: KISS firmware is a TNC/KISS frame interface and does not provide -the MeshCore CLI or the OTA-folder transport that `motatool serve` requires. +If an older build reports that `OTA_FOLDER_SERIAL` is not compiled in, install a current `-ota-` or +`-full-ota-` companion build first. Do **not** use a KISS modem: KISS firmware is a TNC/KISS frame interface +and does not provide the MeshCore CLI or the OTA-folder transport that `motatool serve` requires. For a companion connected by WiFi, use its dedicated OTA seeder connection instead: diff --git a/docs/ota_protocol.md b/docs/ota_protocol.md index d8372524..4dc9ea49 100644 --- a/docs/ota_protocol.md +++ b/docs/ota_protocol.md @@ -109,7 +109,10 @@ The "reconstructed image" referenced by the manifest is the full `BODY || EndF` ESP32 companion firmware is exempt from the portable-slot limit. USB and WiFi companion artifacts retain LoRa OTA and carry `-ota-` in their filenames so they can seed a host folder over serial or TCP; they keep -their target partition table rather than using the FULL profile. Every other ESP32 artifact, including room, +their target partition table rather than using the FULL profile. A small set of high-capacity classic ESP32 +companions cannot combine their configured contact, group-channel, and offline-queue capacities with LoRa +OTA in internal DRAM. Their normal artifacts remain unchanged, and option 3 also emits `-full-ota-` variants +with 100 contacts, 8 group channels, and a 16-frame offline queue. Every other ESP32 artifact, including room, sensor, and repeater roles, must fit the legacy slot from `0x10000` up to `0x150000` (`0x140000`, 1,310,720 bytes), including the 56-byte `EndF` trailer. The build checks both that limit and the target's actual app partition. For every standalone ESP32 and nRF52 repeater, `build.sh` also @@ -132,7 +135,8 @@ not apply to companion builds. Ordinary repeater builds remain sensor-enabled; o `*_lora_ota_no_external_sensors` siblings omit sensors for LoRa distribution. Option 3 in `build.sh` also emits `*-full-ota-*` ESP32 artifacts for non-companion roles where the portable -profile removes a compiled feature. Menu option 8, or `build-full-esp32-firmwares`, builds only those FULL +profile removes a compiled feature and for the constrained companion fallbacks described above. Menu +option 8, or `build-full-esp32-firmwares`, builds only those FULL artifacts. FULL builds restore WebConfig, the full CLI and observer feature set, full ElegantOTA where that target declares the required library, and LoRa OTA for every included role, including room servers, sensors, observers, and bridges. They use expanded A/B partition