Repository navigation
ESP32 lows: hotspot by interface, setup validation, one OTA at a time, WPA2 floor - #577
Conversation
…, WPA2 floor The nine "ESP32 — low" items of docs/embedded-todo.md: - The hotspot check decides by the address the connection arrived on (fos_wifi_addr_is_portal_ap), not the peer's range, so a home LAN on 192.168.4.0/24 no longer counts as the hotspot. - /api/setup and the console share the panel check (fos_display_panel_known) and a mount-point rule (fos_assets_mount_point_valid, host-tested); neither checked assets_path before. An unchanged legacy value still saves. - Cloud and backend OTA take one lock; the cloud task waits up to 15 min, then logs `ota:cloud skipped another-ota-running`. - An over-long console line is refused once and dropped to its newline (fos_console_line.h, host-tested, in the e2e-docker host-test step). - The asset job queue's storage comes from PSRAM (internal on the C3). - wake_schedule aligns to local time from the same offset the schedule uses (fos_wake_aligned_sleep_seconds, host-tested across Brussels DST). - The status JSON drops the retired OTA fields; nothing reads them. - Wi-Fi joins WPA2-PSK and up only. WPA1-only (TKIP) networks stop connecting; mixed WPA/WPA2 and WPA3 keep working. - The unused usb_api get-asset / upload-asset / asset-op go (-1,312 B). S3 8 MB app: +128 bytes for the batch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ESP32 firmware sizeBuilt from da5fc6a by this run; compared with the latest release v2026.10.16.
Breakdown by subsystem —
|
| Subsystem | This PR | v2026.10.16 | Δ |
|---|---|---|---|
| FrameOS core (Nim) | 476,051 | 475,930 | +121 (+0.0%) |
| QuickJS | 360,285 | 360,285 | ±0 |
| pixie | 296,919 | 296,959 | -40 (-0.0%) |
| Wi-Fi stack | 295,296 | 295,296 | ±0 |
| Nim stdlib | 247,632 | 247,612 | +20 (+0.0%) |
| ESP-IDF misc | 181,413 | 181,343 | +70 (+0.0%) |
| FrameOS apps (Nim) | 181,348 | 181,348 | ±0 |
| Embedded font | 146,358 | 146,358 | ±0 |
| fos_* firmware shell (C) | 136,750 | 136,501 | +249 (+0.2%) |
| String pool (attributed to efuse) | 136,684 | 136,729 | -45 (-0.0%) |
| mbedTLS + certificates | 132,427 | 132,427 | ±0 |
| lwIP / HTTP / WebSocket | 126,935 | 126,939 | -4 (-0.0%) |
| libc / libm / newlib | 116,263 | 116,263 | ±0 |
| Storage (SPIFFS / FatFS / SD / NVS) | 94,068 | 94,068 | ±0 |
| Nim packages (chrono, zippy, chroma, qrgen, ...) | 70,320 | 70,320 | ±0 |
| Display drivers (C) | 65,029 | 64,962 | +67 (+0.1%) |
| Crypto (monocypher) | 35,141 | 35,141 | ±0 |
| Total mapped flash | 3,098,919 | 3,098,481 | +438 (+0.0%) |
Inside each subsystem
FrameOS core (Nim) — 476,051
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
frameos/js_runtime |
115,656 | 115,612 | +44 (+0.0%) |
frameos/utils |
110,853 | 110,853 | ±0 |
frameos/interpreter.nim |
100,679 | 100,659 | +20 (+0.0%) |
embedded_main.nim |
19,120 | 19,120 | ±0 |
embedded_runtime.nim |
17,593 | 17,593 | ±0 |
lib/tz.nim |
16,589 | 16,589 | ±0 |
frameos_nim_glue.c.obj |
11,427 | 11,455 | -28 (-0.2%) |
frameos/planner.nim |
9,574 | 9,574 | ±0 |
frameos/event_loop.nim |
8,143 | 8,143 | ±0 |
frameos/types.nim |
7,715 | 7,715 | ±0 |
frameos/values.nim |
7,528 | 7,528 | ±0 |
frameos/apps.nim |
6,431 | 6,431 | ±0 |
frameos/single_scene_host.nim |
6,379 | 6,379 | ±0 |
frameos/spool.nim |
5,560 | 5,560 | ±0 |
frameos/input_state.nim |
4,676 | 4,676 | ±0 |
embedded_scene.nim |
4,654 | 4,654 | ±0 |
frameos/events_gen.nim |
3,967 | 3,967 | ±0 |
fos_netguard.c.obj |
3,532 | 3,532 | ±0 |
frameos/app_config.nim |
2,734 | 2,734 | ±0 |
frameos/node_config.nim |
2,582 | 2,582 | ±0 |
frameos/app_capabilities.nim |
2,473 | 2,473 | ±0 |
frameos/events.nim |
2,335 | 2,335 | ±0 |
frameos/reboot_reason.nim |
2,332 | 2,332 | ±0 |
frameos/refresh_interval.nim |
1,593 | 1,593 | ±0 |
frameos/runtime_diagnostics.nim |
775 | 775 | ±0 |
fos_version.c.obj |
413 | 328 | +85 (+25.9%) |
frameos/event_log.nim |
407 | 407 | ±0 |
frameos/channels.nim |
153 | 153 | ±0 |
frameos/ids.nim |
120 | 120 | ±0 |
frameos/hal |
44 | 44 | ±0 |
frameos/retired_apps.nim |
14 | 14 | ±0 |
QuickJS — 360,285
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
quickjs.c.obj |
287,746 | 287,746 | ±0 |
libunicode.c.obj |
50,178 | 50,178 | ±0 |
libregexp.c.obj |
14,007 | 14,007 | ±0 |
dtoa.c.obj |
5,689 | 5,689 | ±0 |
cutils.c.obj |
2,141 | 2,141 | ±0 |
fos_qjs_glue.c.obj |
449 | 449 | ±0 |
fos_quickjs_tz.c.obj |
75 | 75 | ±0 |
pixie — 296,919
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
pixie/fontformats/opentype.nim |
56,062 | 56,066 | -4 (-0.0%) |
pixie/fileformats/webp.nim |
36,937 | 36,937 | ±0 |
pixie/fileformats/svg.nim |
35,546 | 35,546 | ±0 |
pixie/paths.nim |
31,592 | 31,616 | -24 (-0.1%) |
pixie/fileformats/jpeg.nim |
29,160 | 29,164 | -4 (-0.0%) |
pixie/fileformats/png.nim |
21,475 | 21,475 | ±0 |
pixie/images.nim |
15,445 | 15,445 | ±0 |
pixie/fonts.nim |
10,301 | 10,301 | ±0 |
pixie/paints.nim |
9,019 | 9,023 | -4 (-0.0%) |
pixie/fileformats/bmp.nim |
7,612 | 7,612 | ±0 |
pixie/common.nim |
7,154 | 7,158 | -4 (-0.1%) |
pixie/blends.nim |
6,622 | 6,622 | ±0 |
pixie/fileformats/gif.nim |
5,737 | 5,737 | ±0 |
pixie.nim |
5,243 | 5,243 | ±0 |
pixie/inflatestream.nim |
5,164 | 5,156 | +8 (+0.2%) |
pixie/fileformats/webp_vp8_tables.nim |
3,881 | 3,881 | ±0 |
pixie/fileformats/ppm.nim |
3,520 | 3,520 | ±0 |
pixie/contexts.nim |
2,951 | 2,951 | ±0 |
pixie/fileformats/qoi.nim |
2,437 | 2,437 | ±0 |
pixie/internal.nim |
506 | 502 | +4 (+0.8%) |
pixie/rgb565.nim |
315 | 327 | -12 (-3.7%) |
pixie/fontformats/svgfont.nim |
190 | 190 | ±0 |
pixie/decodebudget.nim |
50 | 50 | ±0 |
Wi-Fi stack — 295,296
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
libnet80211.a |
136,148 | 136,148 | ±0 |
libpp.a |
62,158 | 62,158 | ±0 |
libwpa_supplicant.a |
54,904 | 54,904 | ±0 |
libphy.a |
34,176 | 34,176 | ±0 |
libesp_wifi.a |
4,788 | 4,788 | ±0 |
libesp_phy.a |
2,541 | 2,541 | ±0 |
libesp_coex.a |
291 | 291 | ±0 |
libcore.a |
287 | 287 | ±0 |
libespnow.a |
3 | 3 | ±0 |
Nim stdlib — 247,632
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
pure/collections/tables.nim |
72,122 | 72,114 | +8 (+0.0%) |
system.nim |
48,179 | 48,163 | +16 (+0.0%) |
pure/unicode.nim |
17,324 | 17,324 | ±0 |
pure/times.nim |
16,493 | 16,493 | ±0 |
pure/json.nim |
13,478 | 13,478 | ±0 |
std/private/dragonbox.nim |
10,348 | 10,348 | ±0 |
pure/strutils.nim |
7,847 | 7,847 | ±0 |
pure/parsexml.nim |
5,802 | 5,802 | ±0 |
pure/algorithm.nim |
5,324 | 5,324 | ±0 |
pure/base64.nim |
5,107 | 5,107 | ±0 |
pure/hashes.nim |
4,003 | 4,003 | ±0 |
std/formatfloat.nim |
3,476 | 3,476 | ±0 |
pure/xmlparser.nim |
3,407 | 3,407 | ±0 |
pure/parsejson.nim |
3,392 | 3,392 | ±0 |
pure/uri.nim |
2,988 | 2,988 | ±0 |
pure/streams.nim |
2,749 | 2,749 | ±0 |
pure/strformat.nim |
2,380 | 2,380 | ±0 |
std/syncio.nim |
2,282 | 2,282 | ±0 |
pure/collections/sets.nim |
2,089 | 2,089 | ±0 |
pure/xmltree.nim |
1,862 | 1,862 | ±0 |
pure/lexbase.nim |
1,775 | 1,775 | ±0 |
pure/parseutils.nim |
1,741 | 1,741 | ±0 |
system/exceptions.nim |
1,530 | 1,530 | ±0 |
pure/strtabs.nim |
1,507 | 1,507 | ±0 |
pure/pathnorm.nim |
1,212 | 1,212 | ±0 |
pure/collections/lists.nim |
990 | 990 | ±0 |
std/private/ospaths2.nim |
966 | 966 | ±0 |
pure/collections/deques.nim |
844 | 844 | ±0 |
pure/math.nim |
839 | 839 | ±0 |
pure/options.nim |
815 | 815 | ±0 |
pure/random.nim |
688 | 688 | ±0 |
std/private/digitsutils.nim |
617 | 617 | ±0 |
std/private/osdirs.nim |
510 | 510 | ±0 |
std/oserrors.nim |
489 | 489 | ±0 |
std/monotimes.nim |
485 | 485 | ±0 |
system/dollars.nim |
431 | 431 | ±0 |
std/private/oscommon.nim |
325 | 325 | ±0 |
std/envvars.nim |
306 | 310 | -4 (-1.3%) |
std/private/ossymlinks.nim |
187 | 187 | ±0 |
std/private/decode_helpers.nim |
181 | 181 | ±0 |
pure/bitops.nim |
162 | 162 | ±0 |
pure/os.nim |
99 | 99 | ±0 |
std/private/osfiles.nim |
96 | 96 | ±0 |
core/macros.nim |
89 | 89 | ±0 |
std/assertions.nim |
87 | 87 | ±0 |
system/ctypes.nim |
9 | 9 | ±0 |
ESP-IDF misc — 181,413
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
libesp_hw_support.a |
37,620 | 37,620 | ±0 |
libhal.a |
21,865 | 21,865 | ±0 |
libfreertos.a |
17,240 | 17,240 | ±0 |
libesp_system.a |
13,736 | 13,736 | ±0 |
libesp_driver_uart.a |
11,627 | 11,627 | ±0 |
libheap.a |
8,660 | 8,660 | ±0 |
libesp_driver_i2c.a |
8,062 | 8,062 | ±0 |
libesp_driver_spi.a |
7,760 | 7,760 | ±0 |
libconsole.a |
5,733 | 5,733 | ±0 |
libjson.a |
4,940 | 4,940 | ±0 |
libesp_driver_gpio.a |
3,878 | 3,878 | ±0 |
libbootloader_support.a |
3,813 | 3,813 | ±0 |
libxtensa.a |
3,691 | 3,691 | ±0 |
libesp_driver_usb_serial_jtag.a |
3,408 | 3,408 | ±0 |
libesp_ringbuf.a |
3,322 | 3,322 | ±0 |
libesp_event.a |
3,241 | 3,241 | ±0 |
libesp_driver_ledc.a |
3,054 | 3,054 | ±0 |
libapp_update.a |
2,484 | 2,414 | +70 (+2.9%) |
libesp_mm.a |
2,451 | 2,451 | ±0 |
libesp_timer.a |
2,337 | 2,337 | ±0 |
libsoc.a |
2,316 | 2,316 | ±0 |
libesp_adc.a |
2,285 | 2,285 | ±0 |
libesp_psram.a |
2,172 | 2,172 | ±0 |
libpthread.a |
1,397 | 1,397 | ±0 |
liblog.a |
1,375 | 1,375 | ±0 |
libesp_security.a |
1,050 | 1,050 | ±0 |
libesp_rom.a |
902 | 902 | ±0 |
libesp_app_format.a |
507 | 507 | ±0 |
libxt_hal.a |
437 | 437 | ±0 |
libesp_common.a |
26 | 26 | ±0 |
libesp_pm.a |
24 | 24 | ±0 |
FrameOS apps (Nim) — 181,348
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
apps/data/icalJson |
50,262 | 50,262 | ±0 |
apps/render/calendar |
29,944 | 29,944 | ±0 |
apps/data/localImage |
10,340 | 10,340 | ±0 |
apps/render/split |
9,389 | 9,389 | ±0 |
apps/data/eventsToAgenda |
8,568 | 8,568 | ±0 |
apps/render/zoomPan |
8,360 | 8,360 | ±0 |
apps/apps.nim |
7,208 | 7,208 | ±0 |
apps/render/text |
5,234 | 5,234 | ±0 |
apps/data/xmlToJson |
5,190 | 5,190 | ±0 |
apps/render/svg |
4,583 | 4,583 | ±0 |
apps/render/image |
4,423 | 4,423 | ±0 |
apps/logic/setAsState |
3,181 | 3,181 | ±0 |
apps/data/downloadImage |
3,128 | 3,128 | ±0 |
apps/data/qr |
3,017 | 3,017 | ±0 |
apps/render/gradient |
2,983 | 2,983 | ±0 |
apps/data/rotateImage |
2,939 | 2,939 | ±0 |
apps/data/downloadUrl |
2,774 | 2,774 | ±0 |
apps/data/resizeImage |
2,312 | 2,312 | ±0 |
apps/data/newImage |
2,175 | 2,175 | ±0 |
apps/render/color |
2,059 | 2,059 | ±0 |
apps/render/opacity |
2,055 | 2,055 | ±0 |
apps/data/log |
2,053 | 2,053 | ±0 |
apps/data/prettyJson |
1,947 | 1,947 | ±0 |
apps/data/clock |
1,718 | 1,718 | ±0 |
apps/data/parseJson |
1,585 | 1,585 | ±0 |
apps/logic/nextSleepDuration |
1,394 | 1,394 | ±0 |
apps/logic/ifElse |
1,311 | 1,311 | ±0 |
apps/logic/breakIfRendering |
1,216 | 1,216 | ±0 |
Embedded font — 146,358
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
assets/fonts.nim |
146,358 | 146,358 | ±0 |
fos_ firmware shell (C)* — 136,750
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
fos_http.c.obj |
22,252 | 22,185 | +67 (+0.3%) |
fos_cloud.c.obj |
19,672 | 19,651 | +21 (+0.1%) |
fos_console.c.obj |
13,061 | 14,001 | -940 (-6.7%) |
fos_client.c.obj |
12,975 | 12,957 | +18 (+0.1%) |
fos_settings.c.obj |
7,722 | 7,722 | ±0 |
fos_scenes.c.obj |
7,515 | 7,515 | ±0 |
fos_ota.c.obj |
5,902 | 5,639 | +263 (+4.7%) |
fos_cloud_contract.c.obj |
4,768 | 4,768 | ±0 |
fos_config.c.obj |
4,619 | 4,619 | ±0 |
fos_wifi.c.obj |
3,295 | 3,189 | +106 (+3.3%) |
fos_assets.c.obj |
3,124 | 3,124 | ±0 |
fos_sd_probe.c.obj |
2,753 | 2,753 | ±0 |
fos_buttons.c.obj |
2,737 | 2,737 | ±0 |
fos_schedule.c.obj |
2,624 | 2,614 | +10 (+0.4%) |
fos_assets_sd.c.obj |
2,484 | 2,484 | ±0 |
fos_events.c.obj |
2,332 | 2,332 | ±0 |
fos_panel_draw.c.obj |
2,229 | 2,229 | ±0 |
main.c.obj |
1,703 | 1,703 | ±0 |
fos_config_parse.c.obj |
1,467 | 1,467 | ±0 |
fos_url_guard.c.obj |
1,397 | 1,397 | ±0 |
fos_tz.c.obj |
1,294 | 1,294 | ±0 |
fos_buzzer.c.obj |
1,162 | 1,162 | ±0 |
fos_battery.c.obj |
1,140 | 1,140 | ±0 |
fos_minisig.c.obj |
1,140 | 1,140 | ±0 |
fos_backend_http.c.obj |
1,072 | 1,072 | ±0 |
fos_commands.c.obj |
940 | 940 | ±0 |
fos_status_screen.c.obj |
893 | 893 | ±0 |
fos_lan_access.c.obj |
841 | 841 | ±0 |
fos_scene_state.c.obj |
650 | 650 | ±0 |
fos_wake.c.obj |
598 | 199 | +399 (+200.5%) |
fos_assets_path.c.obj |
564 | 259 | +305 (+117.8%) |
fos_framebuffer.c.obj |
483 | 483 | ±0 |
fos_button_timing.c.obj |
434 | 434 | ±0 |
fos_board.c.obj |
334 | 334 | ±0 |
fos_power.c.obj |
241 | 241 | ±0 |
fos_battery_filter.c.obj |
214 | 214 | ±0 |
fos_json_guard.c.obj |
119 | 119 | ±0 |
String pool (attributed to efuse) — 136,684
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
esp_efuse_utility.c.obj |
135,638 | 135,683 | -45 (-0.0%) |
esp_efuse_rtc_calib.c.obj |
566 | 566 | ±0 |
esp_efuse_table.c.obj |
268 | 268 | ±0 |
esp_efuse_api.c.obj |
151 | 151 | ±0 |
esp_efuse_startup.c.obj |
61 | 61 | ±0 |
mbedTLS + certificates — 132,427
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
libmbedcrypto.a |
71,291 | 71,291 | ±0 |
libmbedtls.a |
45,799 | 45,799 | ±0 |
libmbedx509.a |
7,080 | 7,080 | ±0 |
libesp-tls.a |
6,705 | 6,705 | ±0 |
libesp_https_server.a |
1,552 | 1,552 | ±0 |
lwIP / HTTP / WebSocket — 126,935
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
liblwip.a |
78,525 | 78,529 | -4 (-0.0%) |
libhttp_parser.a |
10,350 | 10,350 | ±0 |
libesp_http_server.a |
10,020 | 10,020 | ±0 |
libtcp_transport.a |
8,245 | 8,245 | ±0 |
libespressif__esp_websocket_client.a |
6,822 | 6,822 | ±0 |
libesp_http_client.a |
6,666 | 6,666 | ±0 |
libesp_netif.a |
6,307 | 6,307 | ±0 |
libc / libm / newlib — 116,263
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
libc.a |
76,471 | 76,471 | ±0 |
libm.a |
31,563 | 31,563 | ±0 |
libnewlib.a |
6,609 | 6,609 | ±0 |
libstdc++.a |
1,476 | 1,476 | ±0 |
libgcc.a |
98 | 98 | ±0 |
libcxx.a |
46 | 46 | ±0 |
Storage (SPIFFS / FatFS / SD / NVS) — 94,068
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
libspiffs.a |
20,380 | 20,380 | ±0 |
libfatfs.a |
20,141 | 20,141 | ±0 |
libspi_flash.a |
14,168 | 14,168 | ±0 |
libnvs_flash.a |
13,665 | 13,665 | ±0 |
libsdmmc.a |
13,013 | 13,013 | ±0 |
libvfs.a |
6,196 | 6,196 | ±0 |
libesp_driver_sdspi.a |
3,866 | 3,866 | ±0 |
libesp_partition.a |
1,956 | 1,956 | ±0 |
libesp_vfs_console.a |
678 | 678 | ±0 |
libnvs_sec_provider.a |
5 | 5 | ±0 |
Nim packages (chrono, zippy, chroma, qrgen, ...) — 70,320
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
QRgen 3.1.0 |
21,886 | 21,886 | ±0 |
chrono 0.3.1 |
15,025 | 15,049 | -24 (-0.2%) |
zippy 0.10.19 |
14,936 | 14,936 | ±0 |
chroma 1.0.0 |
14,388 | 14,368 | +20 (+0.1%) |
checksums 0.2.1 |
3,290 | 3,290 | ±0 |
flatty 0.3.4 |
530 | 530 | ±0 |
jsony 1.1.5 |
148 | 148 | ±0 |
bumpy 1.1.3 |
117 | 113 | +4 (+3.5%) |
Display drivers (C) — 65,029
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
(everything else) |
21,278 | 21,278 | ±0 |
frameos_panel_table.c.obj |
6,685 | 6,685 | ±0 |
EPD_13in3e.c.obj |
1,796 | 1,796 | ±0 |
EPD_3in7.c.obj |
1,564 | 1,564 | ±0 |
EPD_5in79.c.obj |
1,481 | 1,481 | ±0 |
DEV_Debug.c.obj |
1,313 | 1,313 | ±0 |
EPD_2in7.c.obj |
1,292 | 1,292 | ±0 |
EPD_4in2.c.obj |
1,262 | 1,262 | ±0 |
EPD_7in3e.c.obj |
1,208 | 1,208 | ±0 |
EPD_4in2_V2.c.obj |
1,184 | 1,184 | ±0 |
DEV_Config_esp.c.obj |
1,180 | 1,180 | ±0 |
EPD_4in26.c.obj |
1,123 | 1,123 | ±0 |
| 29 smaller rows | 23,663 | 23,596 | +67 (+0.3%) |
Crypto (monocypher) — 35,141
| Part | This PR | v2026.10.16 | Δ |
|---|---|---|---|
monocypher.c.obj |
31,916 | 31,916 | ±0 |
monocypher-ed25519.c.obj |
3,225 | 3,225 | ±0 |
Biggest movers (per object)
| Object | Δ | This PR | Baseline |
|---|---|---|---|
fos_console.c.obj |
-940 | 13,061 | 14,001 |
fos_ota.c.obj |
+263 | 5,902 | 5,639 |
fos_http.c.obj |
+67 | 22,252 | 22,185 |
esp_efuse_utility.c.obj |
-45 | 135,638 | 135,683 |
frameos/js_runtime/app_runtime.nim |
+28 | 72,810 | 72,782 |
frameos_nim_glue.c.obj |
-28 | 11,427 | 11,455 |
pkgs/pixie-6.1.0/pixie/paths.nim |
-24 | 31,592 | 31,616 |
pkgs/chrono-0.3.1/chrono.nim |
-24 | 15,025 | 15,049 |
fos_cloud.c.obj |
+21 | 19,672 | 19,651 |
frameos/interpreter.nim |
+20 | 100,679 | 100,659 |
fos_client.c.obj |
+18 | 12,975 | 12,957 |
pkgs/chroma-1.0.0/chroma.nim |
+16 | 4,834 | 4,818 |
nim/lib/system.nim |
+16 | 48,179 | 48,163 |
pkgs/pixie-6.1.0/pixie/inflatestream.nim |
+8 | 5,164 | 5,156 |
nim/lib/pure/collections/tables.nim |
+8 | 72,122 | 72,114 |
Largest 30 objects
| Object | Subsystem | This PR | v2026.10.16 | Δ |
|---|---|---|---|---|
quickjs.c.obj |
QuickJS | 287,746 | 287,746 | ±0 |
assets/fonts.nim |
Embedded font | 146,358 | 146,358 | ±0 |
esp_efuse_utility.c.obj |
String pool (attributed to efuse) | 135,638 | 135,683 | -45 (-0.0%) |
frameos/interpreter.nim |
FrameOS core (Nim) | 100,679 | 100,659 | +20 (+0.0%) |
frameos/js_runtime/app_runtime.nim |
FrameOS core (Nim) | 72,810 | 72,782 | +28 (+0.0%) |
nim/lib/pure/collections/tables.nim |
Nim stdlib | 72,122 | 72,114 | +8 (+0.0%) |
pkgs/pixie-6.1.0/pixie/fontformats/opentype.nim |
pixie | 56,062 | 56,066 | -4 (-0.0%) |
libunicode.c.obj |
QuickJS | 50,178 | 50,178 | ±0 |
nim/lib/system.nim |
Nim stdlib | 48,179 | 48,163 | +16 (+0.0%) |
apps/data/icalJson/ical.nim |
FrameOS apps (Nim) | 44,746 | 44,746 | ±0 |
pkgs/pixie-6.1.0/pixie/fileformats/webp.nim |
pixie | 36,937 | 36,937 | ±0 |
pkgs/pixie-6.1.0/pixie/fileformats/svg.nim |
pixie | 35,546 | 35,546 | ±0 |
frameos/utils/image.nim |
FrameOS core (Nim) | 35,259 | 35,259 | ±0 |
monocypher.c.obj |
Crypto (monocypher) | 31,916 | 31,916 | ±0 |
pkgs/pixie-6.1.0/pixie/paths.nim |
pixie | 31,592 | 31,616 | -24 (-0.1%) |
frameos/js_runtime/runtime.nim |
FrameOS core (Nim) | 31,338 | 31,330 | +8 (+0.0%) |
pkgs/pixie-6.1.0/pixie/fileformats/jpeg.nim |
pixie | 29,160 | 29,164 | -4 (-0.0%) |
apps/render/calendar/app.nim |
FrameOS apps (Nim) | 22,841 | 22,841 | ±0 |
fos_http.c.obj |
fos_* firmware shell (C) | 22,252 | 22,185 | +67 (+0.3%) |
pkgs/pixie-6.1.0/pixie/fileformats/png.nim |
pixie | 21,475 | 21,475 | ±0 |
fos_cloud.c.obj |
fos_* firmware shell (C) | 19,672 | 19,651 | +21 (+0.1%) |
embedded_main.nim |
FrameOS core (Nim) | 19,120 | 19,120 | ±0 |
x509_crt_bundle.S.obj |
mbedTLS + certificates | 17,928 | 17,928 | ±0 |
embedded_runtime.nim |
FrameOS core (Nim) | 17,593 | 17,593 | ±0 |
nim/lib/pure/unicode.nim |
Nim stdlib | 17,324 | 17,324 | ±0 |
frameos/utils/asset_colors.nim |
FrameOS core (Nim) | 17,028 | 17,028 | ±0 |
lib/tz.nim |
FrameOS core (Nim) | 16,589 | 16,589 | ±0 |
frameos/utils/status_screen.nim |
FrameOS core (Nim) | 16,551 | 16,551 | ±0 |
nim/lib/pure/times.nim |
Nim stdlib | 16,493 | 16,493 | ±0 |
ieee80211_ioctl.o |
Wi-Fi stack | 15,592 | 15,592 | ±0 |
Flash = .text + .rodata from the linker map via esp_idf_size; "Inside each subsystem" splits every bucket one level down (the Nim core by directory, apps by app, packages by package, ESP-IDF by archive) over all objects, not just the largest. "String pool (attributed to efuse)" is the linker's merged string-literal pool for the whole image, not efuse code — see docs/esp32-image-size.md.
The nine items in the "ESP32 — low" list of
docs/embedded-todo.md. The Pico items are left for #499, which rewrites that half.Hotspot check by interface.
request_from_hotspotdecides by the address the connection arrived on (fos_wifi_addr_is_portal_ap()): the AP interface must be up, and the station must not hold that same address. Before, any client on a home LAN numbered 192.168.4.0/24 counted as being on the hotspot./api/setupvalidation. The console and the setup form now sharefos_display_panel_known()and a newfos_assets_mount_point_valid(), which has host tests. The mount-point rule:.or../stateor/devThe console never validated
assets_patheither, so both paths check it now. A value that hasn't changed still saves, so a legacy setting can't block saving Wi-Fi.One OTA at a time. The cloud OTA task takes the backend check's lock. It waits up to 15 min, then logs
ota:cloud skipped another-ota-running. The "already running" flag is set atomically.Over-long console line. It is refused once and everything up to its newline is dropped. The logic is the header-only
fos_console_line.h, tested bytests/test_fos_console_line.c, which is added to the e2e-docker host-test step.Asset job queue in PSRAM. Its ~5 KB of storage now comes from
fos_big_malloc(internal heap on the C3). The control block stays internal.wake_schedulein local time. It aligns using the offset the schedule already uses: the configured zone, else the provider's flat offset. The logic isfos_wake_aligned_sleep_seconds(), with host tests for UTC, +5:30 and Brussels across both 2026 DST changes. Only frames withwake_scheduleon are affected.Retired OTA status fields removed:
retryAttempts,requestMode,resumable,bootRequestSupported,partialRequestBytes,wifiSettleMs. Nothing on the backend, the cloud or the SPA reads them.WPA2 floor.⚠️ WPA1-only (TKIP) networks stop connecting and log
no_ap_found_in_authmode_threshold. Mixed WPA/WPA2 and WPA3 keep working.Unused USB commands deleted. Nothing calls
get-asset,upload-assetorasset-op(searched the SPA, cloud-frontend, backend, e2e and docs), so they're gone, saving 1,312 B measured on S3.Size: the S3 8 MB app is 3,119,952 B, against 3,119,824 B on main: +128 B for the batch.
Checks
ci_build_image.sh:esp32-s3andesp32-c3both build with-Werror.test_esp32_*.py+test_embedded_firmware.py, 115 passed.Bench
wake_scheduleon and a time zone set wakes on local boundaries.set assets_pathand the setup page refuse bad mount points.🤖 Generated with Claude Code