Releases: MicroPythonOS/MicroPythonOS
Releases · MicroPythonOS/MicroPythonOS
Release list
0.19.0
Board Support:
- ESP32-S3: add setting to (de)activate USB host mode at runtime using USB On-The-Go to allow for USB HUBs, mice, keyboards and display adapters instead of the default USB-CDC (serial console) mode
- ESP32-S3: add USB hub and hub-behind-hub support (these do count as 1 or 2 USB devices, taking away from the maximum of 3 on ESP32-S3)
- ESP32-S3: add USB display adapter support (DisplayLink DL-1xx, e.g. DL-165/DL-195 fully validated; T6/MS91xx protocol code vendored for ESP32-P4 but untested)
- ESP32-S3: add USB Human Interface Device (HID) keyboard support
- ESP32-S3: add USB Human HID mice support with theme-aware cursor
Frameworks:
- SettingsActivity:
dont_persistentries with adefault_valuenow show "(defaults to X)" in the list instead of "(not persisted)" - topmenu: fix swipe-up-to-close never firing — the close gesture only listened for SCROLL events (which require drawer content taller than the viewport) while real drags deliver PRESSED/PRESSING/RELEASED; the drawer now tracks the press drag and closes once it moves upward past the notification-bar height, with per-event debug logging of position and target
- topmenu: drawer now extends from below the notification bar all the way to the bottom screen edge instead of a fixed 90% height, closing the tappable strip of the underlying app that stayed visible beneath it
OS:
- ESP32-S3: cap ESP-IDF log strings at the ERROR default (LOG_MAXIMUM_EQUALS_DEFAULT), saving ~42 KB of app flash (micropython.bin 3,666,864 → 3,624,784 B); MicroPython logging is unaffected, C logs can no longer be raised above ERROR at runtime
- ESP32-S3: disable Ethernet (ETH_ENABLED=n plus the SPI-Ethernet drivers, which would otherwise force-select it back on), saving ~24 KB of app flash (micropython.bin 3,624,784 → 3,600,688 B); no supported S3 board has an Ethernet PHY
Full Changelog: 0.18.1...0.19.0
0.18.1
Builtin Apps:
- AppStore: speedup loading from 18 to 6 seconds
- AppStore: load list icons lazily for visible rows only (250ms viewport loader, capped per-tick work) instead of rendering every icon upfront
Frameworks:
- InfiniteList: dynamic initial list sizing instead of hard-coded 18 items
Full Changelog: 0.18.0...0.18.1
0.18.0
Board Support:
- Add Waveshare ESP32-S3-Touch-LCD-3.5 (3.5' 320x480 ST7796 over SPI with LCD reset/CS on a PCA9554 IO expander, FT6336 touch, QMI8658 IMU, AXP2101 battery management); vendors the st7796 display driver and adds a PCA9554 expander driver
- UNIHIKER K10: improve two-button navigation, correct camera preview orientation, and restore button input after camera operations
- unix/macOS/web: compiler fallback to bytecode on architectures without a native emitter (e.g. macOS on Apple Silicon) instead of runtime-loaded apps using @micropython.native/@micropython.viper failing to import with SyntaxError 'invalid micropython decorator'
- Waveshare ESP32-S3-Touch-LCD-3.5: ES8311 audio support (speaker output + microphone input over I2S, DAC volume default tuned by ear on hardware)
Builtin Apps:
- AppStore and OSUpdate: defer boot service import and start by 120s and 90s respectively via delay_s in manifest intent_filter, moving their module imports out of the boot path
- AppStore and OSUpdate: fix cooldown blocking the first update check for 60s after boot on ESP32 (ticks_ms counts from boot)
- AppStore: add 'Scan QR' button that opens an app's detail screen from a scanned app link (https://badgehub.eu/page/project/APP_ID, micropythonos://app/APP_ID or mpos://app/APP_ID)
- AppStore: fix insert_app_list_item not hiding items that don't match the selected category filter, causing remote-only apps to leak into the 'Installed' view
- AppStore: guard against segfault when the activity leaves the foreground during an async download (e.g. back_screen() while the index is downloading)
- AppStore: open a QR deep link's app detail screen immediately when the app is already known locally, instead of waiting for the index download
Frameworks:
- AppManager: apps can declare URL handlers via 'urlPattern' in manifest intent_filters; patterns matching the official store host, mpos:// or micropythonos:// are reserved and rejected; multiple matching handlers open the chooser
- AppManager: boot services can declare delay_s in their intent_filter; services with delay_s > 0 are imported and started asynchronously after the delay, keeping non-critical module imports out of the boot path
- AudioManager: WAVStream on desktop and web now honors set_repeat()/repeat_count (was ESP32-only), so the MusicPlayer Repeat checkbox works across all platforms
- AudioManager: WAVStream on ESP32 drains remaining I2S audio by wall-clock instead of a fixed sleep, fixing on_complete delays of up to 2s for low-sample-rate clips
- Camera: after decoding a QR code in free-scan mode, show an 'Open in App Store' / 'Open link' chip when the code is an app link the OS can open
- Camera: gracefully handle boards with no camera hardware (e.g. fri3d_2026) — show a 'No camera found' status instead of crashing on get_cameras()[0]
- DeepLink: new mpos.content.deeplink module with strict app-link parsing (exact host allowlist, identity-only links) and URL dispatch
- DNS (async_dns): single-flight lookups per name with a synchronous fallback when no worker thread can be spawned (e.g. boot-time thread pressure), so concurrent websocket/download connections no longer fail with 'can't create thread'
- FileExplorer: pick mode with a path_pattern now lists only matching files (directories stay listed) — non-matching files could never be selected and taps on them were silently ignored, so listing them was pure clutter; browse mode still lists everything
- focus_direction: skip stale widgets from inactive screens during navigation
- FontManager: cache emoji codepoints for keyboard input by @fdb
- FontManager: stop leaking an app's TTF and emoji fonts after the app closes by @fdb
- fs_driver: widen callback exception handling from OSError to Exception, supporting non-seekable streams like DeflateIO
- Nostr: surface NIP-47 (NWC) error replies through the error callback instead of silently discarding them. An UNAUTHORIZED reply (e.g. a retired wallet connection) previously left apps stuck on their connecting state forever, indistinguishable from a dead relay; identical repeated errors are forwarded once, and an error reply now also resets the relay silence watchdog since the wallet service is demonstrably answering
- Screenshot: move the BMP encoder out of the web server into mpos.ui.testing.encode_bmp(), which both now share, and add save_screenshot_bmp() to capture the screen straight into a file
- SharedPreferences: get_dict_item() and get_list_item_dict() now return copies, fixing silent write loss when mutating returned items
- TaskManager: add create_supervised_task(restart_on_return=True) and use it for the aiorepl console, so it is restarted when it exits
- TaskManager: create_task returns None when the task manager is disabled, preventing C-level crashes from asyncio.create_task on ESP32 when called from a disabled test runner context
- topmenu: close_drawer() now accepts an animate parameter, matching the existing close_bar() API
- topmenu: replace group.remove_all_objs() + rebuild with per-object lv.group_remove_obj() in _remove_focusables_from_group, avoiding DEFOCUSED event dispatch mid-cleanup and eliminating repeated linked-list node allocations that fragmented the LVGL heap
- View: clear the shared default focus group before the screen is deleted to prevent dangling LVGL pointer accumulation across activity transitions
OS:
- aiorepl: stop Ctrl-D in the non-raw REPL loop from shutting asyncio down; it now ends the line like Ctrl-C
- aiorepl: survive stdin EOF (host disconnect) by polling for reconnection instead of exiting, so the serial console no longer dies permanently after mpremote/raw-REPL connection attempts
- boot: disable the Ctrl-C interrupt character while mpos.main boots (restored on the REPL fallback paths), so hosts connecting over serial mid-boot (e.g. mpremote entering raw REPL) can no longer silently abort the boot scripts and leave the OS half-started at the REPL
- builtin: compress the frozen /builtin filesystem archive (freezefs --compress), saving ~39 KB of firmware flash, and strip development junk (pycache, .DS_Store, backup files) from it during the build (#268)
- lvgl_micropython: add general-punctuation glyphs to Montserrat fonts
- lvgl_micropython: add native-decorator bytecode fallback for builds without a native emitter like the unix port on aarch64 (Apple Silicon macOS) and the wasm/web port
- lvgl_micropython: compress Montserrat 10-18 fonts to save ~19 KB of flash space
- main.py: skip the lib/ override when lib/mpos is from a different release than the frozen firmware, instead of letting a stale lib/ (as flashed by the web installer) shadow the new frozen modules after an OTA update and crash the launcher at boot (#239)
- nostr: improve connection management, watchdog, error management
- sdl_keyboard: CTRL-SHIFT-S (CMD-SHIFT-S on macOS) saves a timestamped BMP screenshot in the current directory, at the screen's own pixel size instead of the scaled SDL window
Testing:
- howto_app: clear auto_start_app_early SharedPreferences in setUp so the 'Don't show again' checkbox reliably starts unchecked
- mpos.ui.testing: simulate_click() now pumps simulated-indev reads during the hold, so LONG_PRESSED fires even when the scheduler is blocked
- mpos_controller: click_button() now clicks the innermost clickable widget containing the text, instead of the outermost ancestor that sent clicks to the screen center
- mpos_controller: write paste-mode payloads in chunks, draining echoed input between chunks to avoid PTY-buffer deadlock
- on-device: increase timeouts for about_app (10→15s), launcher_splash dialog (8→15s), and fs_driver image loading (5→15s with upfront render wait) to account for device latency
- on-device: relax timing thresholds for infinite_list (scroll drags, render waits, set_data) and navigation_leaks (32→2048 bytes/round) on ESP32 where the slower CPU exceeds desktop expectations
- on-device: skip websocket (requires internet), nostr_local_relay (WebSocket on localhost unreliable), and scan_bluetooth simulation-mode detection (BLE-dependent)
- test_battery_voltage: skip ADC/caching/voltage classes on boards that override BatteryManager to read the io_expander (no battery ADC, e.g. fri3d_2026)
- test_calibration_check_bug: use the real IMU (auto-detected) instead of hardware mocks; save/restore calibration
- test_runner/mpos_controller: self-check that unittest assertions aren't no-ops from an -O3 build; auto-repair from lib/unittest when possible, and fail loudly with a diagnostic when not — previously stripped assertions reported vacuously green
- test_runner: catch subprocess timeout when a device freezes mid-test so the runner can retry (with --reset) instead of crashing
- test_runner: disable notification sound on macOS/darwin in the settings because it causes a hang on headless CI runners
- test_runner: save/restore asyncio.core globals around nested event loops, preventing segfaults when tests run inside the TaskManager's paste-mode event loop
- test_runner: USB device unbind/rebind and automatic recovery when relay reset fails to bring the device back; also CDC PID polling (0x4001/0x1001) for ESP32-S3 USB enumeration
Merged branches
- Revert "FontManager: free TTF and emoji fonts instead of leaking them per app" by @ThomasFarstrike in #254
- FontManager: free an app's TTF and emoji fonts when the app quits by @fdb in #258
- floodit: Tweaks, display "game ended" dialog and allow new game by @pavelmachek in #242
- Fix UNIHIKER K10 two-button navigation by @...
0.18.0-rc2
Board Support:
- Add Waveshare ESP32-S3-Touch-LCD-3.5 (3.5' 320x480 ST7796 over SPI with LCD reset/CS on a PCA9554 IO expander, FT6336 touch, QMI8658 IMU, AXP2101 battery management); vendors the st7796 display driver and adds a PCA9554 expander driver
- UNIHIKER K10: improve two-button navigation, correct camera preview orientation, and restore button input after camera operations
- unix/macOS/web: compiler fallback to bytecode on architectures without a native emitter (e.g. macOS on Apple Silicon) instead of runtime-loaded apps using @micropython.native/@micropython.viper failing to import with SyntaxError 'invalid micropython decorator'
- Waveshare ESP32-S3-Touch-LCD-3.5: ES8311 audio support (speaker output + microphone input over I2S, DAC volume default tuned by ear on hardware)
Builtin Apps:
- AppStore and OSUpdate: defer boot service import and start by 120s and 90s respectively via delay_s in manifest intent_filter, moving their module imports out of the boot path
- AppStore and OSUpdate: fix cooldown blocking the first update check for 60s after boot on ESP32 (ticks_ms counts from boot)
- AppStore: add 'Scan QR' button that opens an app's detail screen from a scanned app link (https://badgehub.eu/page/project/APP_ID, micropythonos://app/APP_ID or mpos://app/APP_ID)
- AppStore: fix insert_app_list_item not hiding items that don't match the selected category filter, causing remote-only apps to leak into the 'Installed' view
- AppStore: guard against segfault when the activity leaves the foreground during an async download (e.g. back_screen() while the index is downloading)
- AppStore: open a QR deep link's app detail screen immediately when the app is already known locally, instead of waiting for the index download
Frameworks:
- AppManager: apps can declare URL handlers via 'urlPattern' in manifest intent_filters; patterns matching the official store host, mpos:// or micropythonos:// are reserved and rejected; multiple matching handlers open the chooser
- AppManager: boot services can declare delay_s in their intent_filter; services with delay_s > 0 are imported and started asynchronously after the delay, keeping non-critical module imports out of the boot path
- AudioManager: WAVStream on desktop and web now honors set_repeat()/repeat_count (was ESP32-only), so the MusicPlayer Repeat checkbox works across all platforms
- AudioManager: WAVStream on ESP32 drains remaining I2S audio by wall-clock instead of a fixed sleep, fixing on_complete delays of up to 2s for low-sample-rate clips
- Camera: after decoding a QR code in free-scan mode, show an 'Open in App Store' / 'Open link' chip when the code is an app link the OS can open
- Camera: gracefully handle boards with no camera hardware (e.g. fri3d_2026) — show a 'No camera found' status instead of crashing on get_cameras()[0]
- DeepLink: new mpos.content.deeplink module with strict app-link parsing (exact host allowlist, identity-only links) and URL dispatch
- DNS (async_dns): single-flight lookups per name with a synchronous fallback when no worker thread can be spawned (e.g. boot-time thread pressure), so concurrent websocket/download connections no longer fail with 'can't create thread'
- FileExplorer: pick mode with a path_pattern now lists only matching files (directories stay listed) — non-matching files could never be selected and taps on them were silently ignored, so listing them was pure clutter; browse mode still lists everything
- focus_direction: skip stale widgets from inactive screens during navigation
- FontManager: cache emoji codepoints for keyboard input by @fdb
- FontManager: stop leaking an app's TTF and emoji fonts after the app closes by @fdb
- fs_driver: widen callback exception handling from OSError to Exception, supporting non-seekable streams like DeflateIO
- Nostr: surface NIP-47 (NWC) error replies through the error callback instead of silently discarding them. An UNAUTHORIZED reply (e.g. a retired wallet connection) previously left apps stuck on their connecting state forever, indistinguishable from a dead relay; identical repeated errors are forwarded once, and an error reply now also resets the relay silence watchdog since the wallet service is demonstrably answering
- Screenshot: move the BMP encoder out of the web server into mpos.ui.testing.encode_bmp(), which both now share, and add save_screenshot_bmp() to capture the screen straight into a file
- SharedPreferences: get_dict_item() and get_list_item_dict() now return copies, fixing silent write loss when mutating returned items
- TaskManager: add create_supervised_task(restart_on_return=True) and use it for the aiorepl console, so it is restarted when it exits
- TaskManager: create_task returns None when the task manager is disabled, preventing C-level crashes from asyncio.create_task on ESP32 when called from a disabled test runner context
- topmenu: close_drawer() now accepts an animate parameter, matching the existing close_bar() API
- topmenu: replace group.remove_all_objs() + rebuild with per-object lv.group_remove_obj() in _remove_focusables_from_group, avoiding DEFOCUSED event dispatch mid-cleanup and eliminating repeated linked-list node allocations that fragmented the LVGL heap
- View: clear the shared default focus group before the screen is deleted to prevent dangling LVGL pointer accumulation across activity transitions
OS:
- aiorepl: stop Ctrl-D in the non-raw REPL loop from shutting asyncio down; it now ends the line like Ctrl-C
- aiorepl: survive stdin EOF (host disconnect) by polling for reconnection instead of exiting, so the serial console no longer dies permanently after mpremote/raw-REPL connection attempts
- boot: disable the Ctrl-C interrupt character while mpos.main boots (restored on the REPL fallback paths), so hosts connecting over serial mid-boot (e.g. mpremote entering raw REPL) can no longer silently abort the boot scripts and leave the OS half-started at the REPL
- builtin: compress the frozen /builtin filesystem archive (freezefs --compress), saving ~39 KB of firmware flash, and strip development junk (pycache, .DS_Store, backup files) from it during the build (#268)
- lvgl_micropython: add general-punctuation glyphs to Montserrat fonts
- lvgl_micropython: add native-decorator bytecode fallback for builds without a native emitter like the unix port on aarch64 (Apple Silicon macOS) and the wasm/web port
- lvgl_micropython: compress Montserrat 10-18 fonts to save ~19 KB of flash space
- main.py: skip the lib/ override when lib/mpos is from a different release than the frozen firmware, instead of letting a stale lib/ (as flashed by the web installer) shadow the new frozen modules after an OTA update and crash the launcher at boot (#239)
- nostr: improve connection management, watchdog, error management
- sdl_keyboard: CTRL-SHIFT-S (CMD-SHIFT-S on macOS) saves a timestamped BMP screenshot in the current directory, at the screen's own pixel size instead of the scaled SDL window
Testing:
- howto_app: clear auto_start_app_early SharedPreferences in setUp so the 'Don't show again' checkbox reliably starts unchecked
- mpos.ui.testing: simulate_click() now pumps simulated-indev reads during the hold, so LONG_PRESSED fires even when the scheduler is blocked
- mpos_controller: click_button() now clicks the innermost clickable widget containing the text, instead of the outermost ancestor that sent clicks to the screen center
- mpos_controller: write paste-mode payloads in chunks, draining echoed input between chunks to avoid PTY-buffer deadlock
- on-device: increase timeouts for about_app (10→15s), launcher_splash dialog (8→15s), and fs_driver image loading (5→15s with upfront render wait) to account for device latency
- on-device: relax timing thresholds for infinite_list (scroll drags, render waits, set_data) and navigation_leaks (32→2048 bytes/round) on ESP32 where the slower CPU exceeds desktop expectations
- on-device: skip websocket (requires internet), nostr_local_relay (WebSocket on localhost unreliable), and scan_bluetooth simulation-mode detection (BLE-dependent)
- test_battery_voltage: skip ADC/caching/voltage classes on boards that override BatteryManager to read the io_expander (no battery ADC, e.g. fri3d_2026)
- test_calibration_check_bug: use the real IMU (auto-detected) instead of hardware mocks; save/restore calibration
- test_runner/mpos_controller: self-check that unittest assertions aren't no-ops from an -O3 build; auto-repair from lib/unittest when possible, and fail loudly with a diagnostic when not — previously stripped assertions reported vacuously green
- test_runner: catch subprocess timeout when a device freezes mid-test so the runner can retry (with --reset) instead of crashing
- test_runner: disable notification sound on macOS/darwin in the settings because it causes a hang on headless CI runners
- test_runner: save/restore asyncio.core globals around nested event loops, preventing segfaults when tests run inside the TaskManager's paste-mode event loop
- test_runner: USB device unbind/rebind and automatic recovery when relay reset fails to bring the device back; also CDC PID polling (0x4001/0x1001) for ESP32-S3 USB enumeration
What's Changed
- Revert "FontManager: free TTF and emoji fonts instead of leaking them per app" by @ThomasFarstrike in #254
- FontManager: free an app's TTF and emoji fonts when the app quits by @fdb in #258
- floodit: Tweaks, display "game ended" dialog and allow new game by @pavelmachek in #242
- Fix UNIHIKER K10 two-button navigation by @leezisheng in #251
- QR-code app deep links: scan a store link to install an app by @bitcoin3us in #249
- ...
0.17.3
Board Support:
- WebAssembly: expose WebExpander (= simulated Fri3d expander) through mpos.io_expander like on fri3d_2026 board by @DrSkunk
Builtin Apps:
- AppStore: apply dropdown filter when adding to list so apps don't show up unnecessarily (less glitchy)
Frameworks:
- View: fix two LVGL memory leaks in activity navigation by @fdb
What's Changed
- dj_addon: remove version check by @bertouttier in #252
- Appstore improve loading by @ThomasFarstrike in #253
- Add mpos module import and initialize io_expander in linux.py by @DrSkunk in #250
- Fix two LVGL memory leaks in activity navigation by @fdb in #247
Full Changelog: 0.17.2...0.17.3
0.17.2
Builtin Apps:
- AppStore: fix "Update N Apps" button and "Updates (0)" dropdown behavior when opened before the background update check has run
Full Changelog: 0.17.1...0.17.2
0.17.1
Builtin Apps:
- AppStore: fix 'Update' button in app detail activity
- AppStore: improve 'Update N Apps' button behavior
Frameworks:
- View: fix crash when navigating back from an app launched via notification drawer
0.17.0
Board Support:
- Fri3d 2026: update CH32 firmware to 2.0.3 which fixes issue with 2 consecutive i2c register writes (fixes #224)
- Adapt freenove_esp32s3_display, fri3d_2024, fri3d_2026, lilygo_t4, lilygo_t_hmi, matouch_esp32_s3_spi_ips_2_8_with_camera_ov3660 and squixl to SDCardManager API changes
Builtin Apps:
- AppStore: add new 'Installed' category and show it by default (or 'All' if there are no apps installed)
- AppStore: fix double update check (when network established + some time after boot)
- OSUpdate: fix double update check (when network established + some time after boot)
- OSUpdate: randomly select between update mirrors (updates.micropythonos.com and updates.micropythonos.org) for redundancy
- OSUpdate: if wifi is connected but update check fails (due to server error, for example) don't go into 'Waiting for WiFi' state
Frameworks:
- AudioManager: fix buzzer buzzing along when PWM instance is created and fix clicking sound on PWM init (#233) by @cheops
- DownloadManager: resumption offset after connection loss that could prevent over-the-air update (ESP_ERR_OTA_VALIDATE_FAILED) if wifi was lost during update download
- InputManager: add back screen and drawer menu disable/enable APIs so apps receive those keys as regular lv.KEY.ESC / lv.KEY.HOME press
- InfiniteList: add new
mpos.ui.InfiniteListvirtual-scrolling list widget that only renders visible items, keeping memory and render cost bounded even with thousands of entries - SDCardManager: integrate 'sdcard' module functionality and cleanup legacy module
- Focus: add_focus_highlight with mode='bg' now defaults to 100% background opacity, was 30%
- Focus: bg-mode focus handler now scrolls the focused widget into view (matching the border-mode handler)
OS:
- Optimize status bar clock to reduce allocations from ~4.5 KB/s to ~224 B/s (#244) by @fdb
- SPI: expose Device.lock()/unlock() for shared-bus arbitration between multiple drivers
- SPI: fix MicroPython's ESP32 SPI driver DMA failures due to incorrect txdata/rxdata flags
- WiFi: set default country code to Japan instead of World to support channel 12, 13 and 14 (including active scan, meaning hidden SSIDs)
What's Changed
- Audiomanager pwm by @cheops in #233
- scripts/mpos_controller: give the serial port to mpremote by @fdb in #226
- Sdcard api rework by @ThomasFarstrike in #232
- DJ Addon: LED's herstellen en bundle_apps.sh robuuster maken by @lepirlouit in #243
- Status bar clock: stop allocating kilobytes per second by @fdb in #244
- mpos_controller: accept CRLF sentinel endings in read_until by @fdb in #227
New Contributors
- @cheops made their first contribution in #233
- @fdb made their first contribution in #226
- @lepirlouit made their first contribution in #243
Full Changelog: 0.16.1...0.17.0
0.16.1
Board Support:
- Linux and WebAssembly: initialize mock IMU sensor if no real IMU sensor is present
- Fri3d 2026: increase LoRa SPI frequency from 500 kHz to 16 Mhz to speed up transfers and reduce bus collisions
Builtin Apps:
- AppStore: add special 'Updates' category, opened by default when update notification is pressed
- AppStore: add app ratings support
- AppStore: make app version and description focusable so they can be scrolled using arrow keys
- OSUpdate: improve update progress UI
OS:
- Add simple way to force DeviceInfo.hardware_id, skip board detection, and customize hardware board initialization #215
- App class: support multiple categories in MANIFEST.JSON (
'categories'array), normalize to title-caseself.categorieslist withcategoryproperty for backward compatibility - Fix WiFi network switch not actually changing network — disconnect from current network before connecting to new one #220
- Focus restoration fix: navigating back now correctly restores the previously focused widget
- sdl_keyboard: fix CTRL-C and CTRL-V on textarea
- aiowebsocket: reduce reconnect frequency to reduce performance impact
- Tweak TaskHandler's period from 1ms to 2ms to improve asyncio performance at the cost of slightly increased callback latency
- micropython-nostr: log background relay connection failures at INFO instead of ERROR to avoid REPL pollution breaking file transfers
Development:
- Add Python-level line coverage via sys.settrace (mpcov build variant)
- Add
--coverageflag to test_runner.py for collecting per-file line coverage - Add
make build-mpos-unix-coveragetarget - Add HTML coverage report with expandable inline source (scripts/coverage_report.py)
- Add scripts/coverage.sh for automated coverage runs with clustered/partial test support
- Add scripts/cyclonatic_complexity.sh for per-function cyclomatic complexity reports
- build_mpos.sh: restore @micropython.native/@micropython.viper decorators after desktop/web builds (via EXIT trap) so local builds no longer leave the working tree modified
- WAVStream: refactor play() to reduce cyclomatic complexity (69→42) by extracting read_decode_chunk() and play_desktop()
Merged pull requests
- Add web and desktop audio support by @DrSkunk in #212
- Add caching to ci/cd by @DrSkunk in #218
- build_mpos.sh: restore native/viper decorators after desktop builds by @bitcoin3us in #219
- Bundle sample data in web builds by @DrSkunk in #217
- lora/sx1262: fix intermittent false negatives and hangs on shared SPI bus by @steemandavid in #222
- Add Sensor mocking for web build by @DrSkunk in #228
New Contributors
- @steemandavid made their first contribution in #222
Full Changelog: 0.16.0...0.16.1
0.16.0
Builtin Apps:
- AppStore: add category filter
- AppStore: add 'Work in Progress' filter
- AppStore: hide work_in_progress apps by default (toggle with setting)
- AppStore: ignore punctuation when alphabetically sorting apps
- AppStore: report app install to BadgeHub report/install API for statistics
- AppStore: optimize icon display and add blurhash support
- AppStore: show 'Loading details...' instead of 'Unknown' while loading app details
- OSUpdate: make long changelog scrollable with arrow keys
Frameworks:
- App: don't search for local icons if app isn't installed locally to reduce storage access time
- AppManager: cleanup /prefs/appfullname and /cache/appfullname when uninstalling app
- DownloadManager: add post_url() for HTTP POST requests (needed for BadgeHub report/install API call)
- DownloadManager: reduce log level of missing Content-Length from warning to info to avoid polluting REPL
OS:
- aiowebsocket: add exponential reconnect backoff so unreachable relays stop exhausting the thread pool (#191) by @jnuyens
- async_dns: resolve .local domains synchronously on desktop because mDNS is not thread safe
Merged pull requests
- mirror led index by @DrSkunk in #200
- fix(nostr): exponential reconnect backoff so unreachable relays stop exhausting the thread pool (#191) by @jnuyens in #201
- LightsManager fix for Freenove ESP32-S3 by @scott-macg in #204
- Appstore blurhash by @ThomasFarstrike in #203
- Appstore badgehub report install by @ThomasFarstrike in #205
- AppStore: prioritize visible icons and simplify lazy icon queue by @ThomasFarstrike in #206
- Appstore filter by @ThomasFarstrike in #208
New Contributors
- @scott-macg made their first contribution in #204
- @ThomasFarstrike made their first contribution in #203
Full Changelog: 0.15.1...0.16.0