Checks / tests (ubuntu-latest, 3.11) (push) Canceled after 0s
Checks / tests (ubuntu-latest, 3.14) (push) Canceled after 0s
Checks / tests (windows-latest, 3.11) (push) Canceled after 0s
Checks / tests (windows-latest, 3.14) (push) Canceled after 0s
Checks / package (push) Canceled after 0s
56 lines
2.1 KiB
Python
56 lines
2.1 KiB
Python
"""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()
|