Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(app-shell,usb-bridge): improve flex usb communication #14170

Merged
merged 7 commits into from
Dec 12, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix(usb-bridge): limit send bandwidth
Desktop OS serial drivers often have very small incoming data buffers on
their serial connections because well serial is typically slow... unless
you've actually got usb on both sides.

The default value of 2048/.01s (204.8kB/s) should be further developed
but it's going to be a good idea to keep this smaller than we think
necessary to support slow client hardware.
  • Loading branch information
sfoster1 committed Dec 11, 2023
commit bb374997aa1a7b7bf18b503eb1217beb27630968
23 changes: 16 additions & 7 deletions usb-bridge/ot3usb/serial_thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@

QUEUE_MAX_ITEMS = 100

DEFAULT_PACKET_LIMIT = 2048

def _try_write_all_data(serial: serial.Serial, data: bytes) -> None:

def _try_write_all_data(serial: serial.Serial, data: bytes, packet_limit: int) -> None:
sent = 0
tries = 0
if len(data) == 0:
return
while sent < len(data):
try:
sent += serial.write(data[sent:])
sent += serial.write(data[sent:min(sent+packet_limit, len(data))])
except Exception as e:
# Any exception means we need to quit
print(f"Failed to write: {e}")
Expand All @@ -31,17 +33,24 @@ def _try_write_all_data(serial: serial.Serial, data: bytes) -> None:
time.sleep(0.01)


def _worker(queue: QUEUE_TYPE) -> None:
def _worker(queue: QUEUE_TYPE, packet_limit: int) -> None:
while True:
ser, data = queue.get()
_try_write_all_data(ser, data)
_try_write_all_data(ser, data, packet_limit)


def create_worker_thread(packet_limit: int = DEFAULT_PACKET_LIMIT) -> Tuple[threading.Thread, QUEUE_TYPE]:
"""Create a serial worker thread. Returns the comms queue.

packet_limit is a maximum size for a single usb packet which is sent no more
frequently than every 10 ms, establishing an effective bandwidth limit. This
may be required to allow clients to process data in time, since many desktop
OS serial drivers do not have very large data buffers.
"""

def create_worker_thread() -> Tuple[threading.Thread, QUEUE_TYPE]:
"""Create a serial worker thread. Returns the comms queue."""
queue: QUEUE_TYPE = Queue(QUEUE_MAX_ITEMS)
thread = threading.Thread(
target=_worker, name="serial worker", kwargs={"queue": queue}
target=_worker, name="serial worker", kwargs={"queue": queue, "packet_limit": packet_limit}
)

return (thread, queue)