diff --git a/src/benlink/controller.py b/src/benlink/controller.py index a9d12aa..676a85f 100644 --- a/src/benlink/controller.py +++ b/src/benlink/controller.py @@ -150,6 +150,7 @@ def handle_event(event): from dataclasses import dataclass import typing as t import sys +import asyncio from .command import ( CommandConnection, @@ -290,14 +291,36 @@ async def rc_battery_level(self) -> int: return await self._conn.get_rc_battery_level() async def send_tnc_data(self, data: bytes) -> None: - if len(data) > 50: - raise ValueError("Data too long -- TODO: implement fragmentation") - - await self._conn.send_tnc_data_fragment(TncDataFragment( - is_final_fragment=True, - fragment_id=0, - data=data - )) + chunk_size = 50 + max_retries = 2 # Total transmissions = 1 original + 1 retry + total_fragments = (len(data) + chunk_size - 1) // chunk_size + # Send twice because first packet always fails + for retry in range(max_retries): + fragment_id = 0 + + for i in range(0, len(data), chunk_size): + chunk = data[i:i+chunk_size] + is_final = (i + chunk_size) >= len(data) + + payload = TncDataFragment( + data=chunk, + fragment_id=fragment_id, + is_final_fragment=is_final, + ) + + command = SendTncDataFragment(payload) + + await self._conn.send_tnc_data_fragment(command) + if fragment_id == 0 and total_fragments > 1: + # Add small delay between fragments + await asyncio.sleep(0.01) + await self._conn.send_tnc_data_fragment(command) # Repeat because first fragment always fails + + fragment_id += 1 + + # Add delay between retransmissions if not the last attempt + if retry < max_retries - 1: + await asyncio.sleep(0.1) def add_event_handler(self, handler: EventHandler) -> t.Callable[[], None]: return self._conn.add_event_handler(handler)