"""Experimental RFCOMM/serial adapter for the shared Samsung session.""" import queue import time from controller.session import Session from controller.transport import open_stream from controller.worker import ConnectionWorker class Link(ConnectionWorker): def __init__(self, port, events, channel=1, prepare=False): super().__init__(port, events) self.channel = channel self.prepare = prepare def work(self): self.events.put(("log", f"Opening {self.port} (direct RFCOMM uses channel {self.channel})")) def report(text): self.events.put(("status", text)) self.events.put(("log", text)) with open_stream(self.port, self.channel, self.prepare, report) as stream: session = Session(strict_checksums=True) def send(packet): if stream.write(packet) != len(packet): raise OSError("Incomplete Bluetooth write") self.events.put(("log", "TX " + packet.hex(" "))) report("Bluetooth connected; waiting for speaker handshake…") send(session.start()) deadline = time.monotonic() + 10 last_sent = time.monotonic() while not self.stopped.is_set(): chunk = stream.read(1024) if chunk: self.events.put(("log", "RX " + chunk.hex(" "))) update = session.receive(chunk) self.publish(update) for packet in update.outgoing: send(packet) last_sent = time.monotonic() if not session.ready and time.monotonic() > deadline: raise TimeoutError( "No completed speaker handshake. Close the phone app and check the TX/RX log." ) if session.ready and time.monotonic() - last_sent >= 0.1: try: payload = self.commands.get_nowait() except queue.Empty: continue send(session.command(payload)) last_sent = time.monotonic()