mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-10-23 03:01:27 +00:00
Cover WiFi scan fixes across every ESP32 recipe
This commit is contained in:
1 parent
df5e591319
commit
7581fa3abd
8 files changed
+130
-11
No files matched your search
@@ -274,7 +274,11 @@ jobs:
|
||||
python3 -B test/test_esp32_boot_file_lifecycle.py -v
|
||||
|
||||
- name: Verify WiFi OTA startup and WebConfig handoff
|
||||
run: python3 -B test/test_wifi_ota_start.py -v
|
||||
run: |
|
||||
python3 -B test/test_wifi_ota_start.py -v
|
||||
python3 -B test/test_webconfig_ap_start.py -v
|
||||
python3 -B test/test_esp32_wifi_scan_fix.py -v
|
||||
python3 -B test/test_esp32_wifi_scan_recipes.py -v
|
||||
|
||||
- name: Verify browser OTA completion and immediate HTTP listener restart
|
||||
run: python3 -B test/test_async_web_lifecycle.py -v
|
||||
|
||||
@@ -3983,6 +3983,21 @@ append_platformio_extra_script() {
|
||||
export PLATFORMIO_EXTRA_SCRIPTS
|
||||
}
|
||||
|
||||
ensure_esp32_wifi_scan_fix() {
|
||||
local env_platform=$1
|
||||
local pio_env_name=$2
|
||||
local hook="pre:scripts/esp32_wifi_scan_fix.py"
|
||||
local item
|
||||
local -a hooks=()
|
||||
[ "$env_platform" = "ESP32_PLATFORM" ] || return 0
|
||||
pio_env_option_contains "$pio_env_name" extra_scripts "scripts/esp32_wifi_scan_fix.py" && return 0
|
||||
read -r -a hooks <<< "${PLATFORMIO_EXTRA_SCRIPTS//$'\n'/ }"
|
||||
for item in "${hooks[@]}"; do
|
||||
[ "$item" = "$hook" ] && return 0
|
||||
done
|
||||
append_platformio_extra_script "$hook"
|
||||
}
|
||||
|
||||
apply_lora_ota_flag_order_fix() {
|
||||
local env_name=$1
|
||||
local pio_env_name=$2
|
||||
@@ -5108,6 +5123,9 @@ build_firmware_one_profile() {
|
||||
unset MESHCORE_COMPANION_RADIO_FULL
|
||||
fi
|
||||
|
||||
# Keep the reviewed scan SDK fix when a target overrides extra_scripts.
|
||||
ensure_esp32_wifi_scan_fix "$env_platform" "$pio_env_name"
|
||||
|
||||
if [ "$env_platform" = "ESP32_PLATFORM" ] \
|
||||
&& ! pio_env_option_contains "$pio_env_name" extra_scripts \
|
||||
"scripts/check_esp32_dram.py"; then
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Heltec V4 scan-first AP validation — 2026-10-06
|
||||
# Heltec V4 scan-first AP validation - 2026-10-06
|
||||
|
||||
The expanded-partition Full repeater is the recommended image for these V4s.
|
||||
Minimal remains a compatibility profile for the smaller portable OTA slot;
|
||||
@@ -48,7 +48,7 @@ ordinary standard profiles retain their existing implementations.
|
||||
| Minimal app | PASS, 1,281,576 bytes; 29,144 bytes spare in the 1,310,720-byte portable slot; 6 capability markers and memory gate passed. |
|
||||
| Minimal SHA-256 | `4f0d55aa3c0c85e76c50a2ba60738294515552dafa5e9496d6a33d73f1072e27` |
|
||||
| Minimal running body hash | `060106D2CA3CA669` |
|
||||
| Focused host suite | PASS, 65 Python tests, including four compiled AP fixture variants: Arduino 2/3 × open/password AP. |
|
||||
| Focused host suite | PASS, 65 Python tests, including four compiled AP fixture variants: Arduino 2/3 x open/password AP. |
|
||||
| Build profile tests | PASS, `test/test_build_profiles.sh`. |
|
||||
|
||||
New AP fixtures exercise stale independent SDK state despite successful facade
|
||||
@@ -106,7 +106,7 @@ Private credentials, scanned network names, and saved secret values are excluded
|
||||
|
||||
## Remaining boundaries
|
||||
|
||||
- 11–14 mA current consumption is unmeasured. There is no current meter in this
|
||||
- 11-14 mA current consumption is unmeasured. There is no current meter in this
|
||||
setup; attached native USB and enabled USB logging inhibit light sleep.
|
||||
- Requested ESP-NOW state was checked, but actual packet exchange needs a known
|
||||
second peer.
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Resolve all tracked ESP32 scan hooks and execute builder fallback without PIO."""
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import unittest
|
||||
|
||||
from platformio.project.config import ProjectConfig
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
HOOK = "pre:scripts/esp32_wifi_scan_fix.py"
|
||||
|
||||
|
||||
class Esp32WiFiScanRecipeTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Developer-local overlays must not alter the tracked regression matrix.
|
||||
cls.config = ProjectConfig(str(ROOT / "platformio.ini"), parse_extra=False)
|
||||
for path in sorted((ROOT / "variants").glob("*/platformio.ini")):
|
||||
cls.config.read(str(path), parse_extra=False)
|
||||
cls.config.read(str(ROOT / "tools/hil/profile_switch.ini"), parse_extra=False)
|
||||
|
||||
def test_every_resolved_esp32_recipe_has_exactly_one_direct_scan_hook(self):
|
||||
tested = []
|
||||
for section in self.config.sections():
|
||||
if not section.startswith("env:"):
|
||||
continue
|
||||
platform = self.config.get(section, "platform", "").lower()
|
||||
if "espressif32" not in platform and "pioarduino" not in platform:
|
||||
continue
|
||||
with self.subTest(target=section):
|
||||
hooks = self.config.get(section, "extra_scripts", [])
|
||||
self.assertEqual(hooks.count(HOOK), 1, hooks)
|
||||
tested.append(section)
|
||||
self.assertGreater(len(tested), 400)
|
||||
for name in ("heltec_v4_partition_migrator", "xiao_s3_partition_legacy_seed",
|
||||
"esp32_c3_4mb_partition_migrator", "profile_switch_heltec_v4"):
|
||||
self.assertIn("env:" + name, tested)
|
||||
|
||||
def fallback(self, platform, configured, ambient="", disabled=False):
|
||||
options = [["env:fixture", [["extra_scripts", configured]]]]
|
||||
shell = r'''
|
||||
source "$1/build_legacy.sh"
|
||||
pio() { printf 'FORBIDDEN_PLATFORMIO\n' >&2; return 99; }
|
||||
PIO_CONFIG_JSON=$2
|
||||
PLATFORMIO_EXTRA_SCRIPTS=$3
|
||||
if [ "$5" = 1 ]; then
|
||||
append_platformio_extra_script() { :; }
|
||||
fi
|
||||
ensure_esp32_wifi_scan_fix "$4" fixture
|
||||
ensure_esp32_wifi_scan_fix "$4" fixture
|
||||
printf '%s' "$PLATFORMIO_EXTRA_SCRIPTS"
|
||||
'''
|
||||
result = subprocess.run(["bash", "-c", shell, "scan-hook", str(ROOT),
|
||||
json.dumps(options), ambient, platform,
|
||||
"1" if disabled else "0"], cwd=ROOT,
|
||||
capture_output=True, text=True, timeout=15)
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
self.assertNotIn("FORBIDDEN_PLATFORMIO", result.stdout + result.stderr)
|
||||
return result.stdout
|
||||
|
||||
def test_actual_builder_fallback_preserves_overrides_and_is_idempotent(self):
|
||||
ambient = "pre:scripts/fixture_private.py"
|
||||
self.assertEqual(self.fallback("ESP32_PLATFORM", [], ambient), ambient + "\n" + HOOK)
|
||||
self.assertEqual(self.fallback("ESP32_PLATFORM", [HOOK], ambient), ambient)
|
||||
self.assertEqual(self.fallback("ESP32_PLATFORM", [], ambient + "\n" + HOOK), ambient + "\n" + HOOK)
|
||||
self.assertEqual(self.fallback("NRF52_PLATFORM", [], ambient), ambient)
|
||||
|
||||
def test_disabled_fallback_cannot_satisfy_missing_hook(self):
|
||||
self.assertNotIn(HOOK, self.fallback("ESP32_PLATFORM", [], disabled=True))
|
||||
self.assertIn(HOOK, self.fallback("ESP32_PLATFORM", []))
|
||||
|
||||
def test_fallback_precedes_recipe_binding_and_suite_is_wired_in_ci(self):
|
||||
source = (ROOT / "build_legacy.sh").read_text()
|
||||
body = source[source.index("build_firmware_one_profile() {"):]
|
||||
self.assertLess(body.index('ensure_esp32_wifi_scan_fix "$env_platform" "$pio_env_name"'),
|
||||
body.index("BUILD_RECIPE_SHA256=$(compute_build_recipe_digest"))
|
||||
self.assertIn(" python3 -B test/test_esp32_wifi_scan_recipes.py -v\n",
|
||||
(ROOT / ".github/workflows/run-unit-tests.yml").read_text())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -13,7 +13,9 @@ lib_deps =
|
||||
Wire
|
||||
https://github.com/jgromes/RadioLib.git#187ef24791c3d844939b2be13a68bd890bd04e4c
|
||||
rweather/Crypto @ ^0.4.0
|
||||
extra_scripts = post:scripts/check_firmware_ram.py
|
||||
extra_scripts =
|
||||
pre:scripts/esp32_wifi_scan_fix.py
|
||||
post:scripts/check_firmware_ram.py
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-D ESP32_PLATFORM
|
||||
@@ -48,7 +50,9 @@ board_upload.flash_size = 8MB
|
||||
lib_deps =
|
||||
${env:profile_switch_xiao.lib_deps}
|
||||
lovyan03/LovyanGFX @ ^1.2.7
|
||||
extra_scripts = post:scripts/check_firmware_ram.py
|
||||
extra_scripts =
|
||||
pre:scripts/esp32_wifi_scan_fix.py
|
||||
post:scripts/check_firmware_ram.py
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-D ESP32_PLATFORM
|
||||
@@ -84,7 +88,9 @@ board_upload.flash_size = 16MB
|
||||
board_build.partitions = default_16MB.csv
|
||||
upload_speed = 115200
|
||||
lib_deps = ${env:profile_switch_xiao.lib_deps}
|
||||
extra_scripts = post:scripts/check_firmware_ram.py
|
||||
extra_scripts =
|
||||
pre:scripts/esp32_wifi_scan_fix.py
|
||||
post:scripts/check_firmware_ram.py
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-D ESP32_PLATFORM
|
||||
|
||||
@@ -9,7 +9,9 @@ board_build.partitions = default.csv
|
||||
board_build.flash_mode = dio
|
||||
board_upload.flash_size = 4MB
|
||||
board_upload.maximum_size = 4194304
|
||||
extra_scripts = post:scripts/check_firmware_ram.py
|
||||
extra_scripts =
|
||||
pre:scripts/esp32_wifi_scan_fix.py
|
||||
post:scripts/check_firmware_ram.py
|
||||
build_flags =
|
||||
-D ESP32_PLATFORM
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=0
|
||||
|
||||
@@ -897,7 +897,9 @@ board_build.flash_mode = dio
|
||||
; repeater build restores its normal USB serial setting.
|
||||
; This standalone image runs its own Wi-Fi OTA server. Reserve the generic
|
||||
; ESP32 baseline plus its always-on Wi-Fi budget in the linked-image proof.
|
||||
extra_scripts = post:scripts/check_firmware_ram.py
|
||||
extra_scripts =
|
||||
pre:scripts/esp32_wifi_scan_fix.py
|
||||
post:scripts/check_firmware_ram.py
|
||||
build_flags =
|
||||
-D ESP32_PLATFORM
|
||||
-D MESH_MIN_RUNTIME_HEAP=100352
|
||||
|
||||
@@ -88,7 +88,9 @@ board_build.partitions = default.csv
|
||||
board_build.flash_mode = dio
|
||||
; This is a standalone ESP32 utility, but it still hosts a Wi-Fi OTA server.
|
||||
; Reserve the generic ESP32 baseline plus its always-on Wi-Fi budget.
|
||||
extra_scripts = post:scripts/check_firmware_ram.py
|
||||
extra_scripts =
|
||||
pre:scripts/esp32_wifi_scan_fix.py
|
||||
post:scripts/check_firmware_ram.py
|
||||
build_flags =
|
||||
-D ESP32_PLATFORM
|
||||
-D MESH_MIN_RUNTIME_HEAP=100352
|
||||
@@ -118,7 +120,9 @@ framework = arduino
|
||||
board_build.partitions = default.csv
|
||||
board_build.flash_mode = dio
|
||||
; The disposable seed also runs an always-on Wi-Fi OTA server.
|
||||
extra_scripts = post:scripts/check_firmware_ram.py
|
||||
extra_scripts =
|
||||
pre:scripts/esp32_wifi_scan_fix.py
|
||||
post:scripts/check_firmware_ram.py
|
||||
build_flags =
|
||||
-D ESP32_PLATFORM
|
||||
-D MESH_MIN_RUNTIME_HEAP=100352
|
||||
|
||||
Reference in new issue
Block a user