I wrote a Python program that both reads and writes a L2CAP connection via a bluetooth socket (see example below) to talk to some hardware. However the code may want to do too much IO for the bluetooth adapter too handle, so I equipped it to handle laggy reads and writes by slowing down the bar
loop if needed, as this is preferable to delay when responding to requests.
sock = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP)
sock.connect((bt_addr, bt_port))
sock.setblocking(False)
stall_loop = asyncio.Event()
stall_loop.set()
async def bar():
while True:
await stall_loop.wait()
await loop.sock_sendall(generate_data(time.time()))
await asyncio.sleep(maybe_to_small_delay)
async def foo():
while True:
await request = loop.sock_recv(sock, 400)
stall_loop.clear()
await loop.sock_sendall(generate_response(request))
stall_loop.set()
asyncio.gather(foo, bar)
The problem however is that neither of these loops see any notable slowdown until bar
freezes for seconds at a time.
I timed the execution of both loops using time.time()
and execution time is mere milliseconds including the IO (except when bar
freezes), but anything written by foo
may only be sent with up to 15s of delay (as reported by tshark
and comparing to the time python considers the write done)
The behavior I want is the write to only return once the data is actually transmitted in order to retain a responsive foo
and a bar
as close to the wanted speed as possible.
I assume the culprit is some kind of buffering policy that buffers a large amount of data until the buffer is full and then flushes it completely. How can I either disable this bahviour and/or limit the buffer size to e.g. 2 packets? I couldn't find documentaion on ioctl
for bluez.
Versions:
- Raspbian on kernel 5.10.17-vl7+
- Python 3.7.3
- bluez 5.50