You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bledev on the P4: writes without response are sometimes lost while the P4 is notifying #79
Found while proving bledev.webble (PR stacked on #78): writes without response from a central to the P4 panel (BLE through its C6) are sometimes lost when the P4 is sending notifications at the same moment. Nothing on either side reports it.
What you'd see. The nus gate's ECHO phase stalls. The central sends all 16,384 bytes, and the P4's nus_gate_server.py logs ECHO echoed 15904 of 16384. Everything the P4 sends does arrive.
The evidence, 2026-09-24, MicroPython 1.29 kitchen-sink + speaker-usermod image with micropython-pydevices#10, aioble 0.6.2, bledev from #78 (the webble branch's tests/bledev_web/):
Central
Runs
ECHO stalls
Bytes lost
Chrome on the S21, page MTU 23 (820 writes of 20 bytes)
3
2
480, 960
Chrome on the S21, page MTU 247
5
0
Chrome on Windows, page MTU 247 (board's MTU stuck at 23, #80)
11
2
3,172, and one run whose count I didn't read
UP (writes only, no notifications going the other way) never lost a byte in any run.
On the phone, Android's log shows every write sent with status 0, the 4-byte tail included, so the writes left the phone.
With mpftp monitor on the P4's UART for four Windows runs, nothing was printed, but none of those four lost data either.
Not established: where the writes go. Candidates are the ESP-Hosted HCI path to the C6, NimBLE dropping ATT write commands when it's out of buffers while notifying, or the MicroPython IRQ path (invoke_irq_handler prints and swallows an exception from the handler, and mpble copies each captured write inside that handler). The next step is to count _IRQ_GATTS_WRITE events on the board beside the bytes received, which separates "never reached Python" from "reached Python and was dropped".
This breaks bledev's "nothing is dropped quietly" rule on the P4, so a stream over nus needs its own check (or writes with response) there until it's understood.
Same cause as #87, and fixed by the same line: micropython-pydevices#12. ESP-Hosted's receive path on the P4 drops writes when NimBLE's ACL buffers are full. They fill while the host task waits on Python, which is busy notifying. Each lost write logs E vhci_drv: Rx: alloc_acl_from_ll failed on the UART, but only outside the raw REPL. That's why the monitored runs here showed nothing.
The test was the laptop (bleak, Windows) running nus_client.py's 16 KB up, down and echo against nus_server.py on the P4, with a hard reset before each run.
Fixed by micropython-pydevices#12, merged 2026-09-25: NimBLE host flow control (CONFIG_BT_NIMBLE_HS_FLOW_CTRL=y) stops ESP-Hosted dropping ACL packets on the P4. The echo-while-notifying gate from the laptop went from 8 of 10 failing to 0 of 10, and reverting the line brought the failures back.
Found while proving
bledev.webble(PR stacked on #78): writes without response from a central to the P4 panel (BLE through its C6) are sometimes lost when the P4 is sending notifications at the same moment. Nothing on either side reports it.What you'd see. The nus gate's ECHO phase stalls. The central sends all 16,384 bytes, and the P4's
nus_gate_server.pylogsECHO echoed 15904 of 16384. Everything the P4 sends does arrive.The evidence, 2026-09-24, MicroPython 1.29 kitchen-sink + speaker-usermod image with micropython-pydevices#10, aioble 0.6.2, bledev from #78 (the webble branch's
tests/bledev_web/):mpftp monitoron the P4's UART for four Windows runs, nothing was printed, but none of those four lost data either.Not established: where the writes go. Candidates are the ESP-Hosted HCI path to the C6, NimBLE dropping ATT write commands when it's out of buffers while notifying, or the MicroPython IRQ path (
invoke_irq_handlerprints and swallows an exception from the handler, and mpble copies each captured write inside that handler). The next step is to count_IRQ_GATTS_WRITEevents on the board beside the bytes received, which separates "never reached Python" from "reached Python and was dropped".This breaks bledev's "nothing is dropped quietly" rule on the P4, so a stream over nus needs its own check (or writes with response) there until it's understood.