Compare commits

..

1 Commits

Author SHA1 Message Date
Gilles Boccon-Gibod a0b5606047 don't user a parser for a usb source 2024-08-11 20:57:45 -07:00
4 changed files with 39 additions and 44 deletions
+6 -33
View File
@@ -168,7 +168,6 @@ class ConsoleApp:
'remote-services': None,
'local-values': None,
'remote-values': None,
'remote-attributes': None,
},
'filter': {
'address': None,
@@ -217,7 +216,6 @@ class ConsoleApp:
)
self.local_values_text = FormattedTextControl()
self.remote_values_text = FormattedTextControl()
self.remote_attributes_text = FormattedTextControl()
self.log_height = Dimension(min=7, weight=4)
self.log_max_lines = 100
self.log_lines = []
@@ -244,12 +242,6 @@ class ConsoleApp:
Frame(Window(self.remote_values_text), title='Remote Values'),
filter=Condition(lambda: self.top_tab == 'remote-values'),
),
ConditionalContainer(
Frame(
Window(self.remote_attributes_text), title='Remote Attributes'
),
filter=Condition(lambda: self.top_tab == 'remote-attributes'),
),
ConditionalContainer(
Frame(Window(self.log_text, height=self.log_height), title='Log'),
filter=Condition(lambda: self.top_tab == 'log'),
@@ -512,8 +504,6 @@ class ConsoleApp:
await self.connected_peer.discover_all()
self.append_to_output('Service Discovery done!')
self.show_remote_services(self.connected_peer.services)
async def discover_attributes(self):
if not self.connected_peer:
self.show_error('not connected')
@@ -524,7 +514,7 @@ class ConsoleApp:
attributes = await self.connected_peer.discover_attributes()
self.append_to_output(f'discovered {len(attributes)} attributes...')
await self.show_remote_attributes(attributes)
self.show_attributes(attributes)
def find_remote_characteristic(self, param) -> Optional[CharacteristicProxy]:
if not self.connected_peer:
@@ -669,6 +659,7 @@ class ConsoleApp:
connection_parameters_preferences=connection_parameters_preferences,
timeout=DEFAULT_CONNECTION_TIMEOUT,
)
self.top_tab = 'services'
except bumble.core.TimeoutError:
self.show_error('connection timed out')
@@ -739,20 +730,19 @@ class ConsoleApp:
'remote-services',
'local-values',
'remote-values',
'remote-attributes',
}:
self.top_tab = params[0]
self.ui.invalidate()
while self.top_tab == 'local-values':
await self.show_local_values()
await self.do_show_local_values()
await asyncio.sleep(1)
while self.top_tab == 'remote-values':
await self.show_remote_values()
await self.do_show_remote_values()
await asyncio.sleep(1)
async def show_local_values(self):
async def do_show_local_values(self):
prettytable = PrettyTable()
field_names = ["Service", "Characteristic", "Descriptor"]
@@ -807,7 +797,7 @@ class ConsoleApp:
self.local_values_text.text = prettytable.get_string()
self.ui.invalidate()
async def show_remote_values(self):
async def do_show_remote_values(self):
prettytable = PrettyTable(
field_names=[
"Connection",
@@ -841,23 +831,6 @@ class ConsoleApp:
self.remote_values_text.text = prettytable.get_string()
self.ui.invalidate()
async def show_remote_attributes(self, attributes):
lines = []
for attribute in attributes:
lines.append(('ansimagenta', str(attribute) + "\n"))
try:
value = await attribute.read_value()
lines.append(('ansicyan', value.hex() + "\n"))
except bumble.core.ProtocolError as error:
lines.append(("ansired", f"!!! Protocol Error ({error})\n"))
except bumble.core.TimeoutError:
lines.append(("ansired", "!!! Timeout\n"))
except Exception as error:
lines.append(("ansired", f"!!! Error ({error})\n"))
self.remote_attributes_text.text = lines
self.ui.invalidate()
async def do_get_phy(self, _):
if not self.connected_peer:
self.show_error('not connected')
-1
View File
@@ -977,7 +977,6 @@ class Client:
offset += len(part)
self.cache_value(attribute_handle, attribute_value)
# Return the value as bytes
return attribute_value
+24 -7
View File
@@ -248,26 +248,26 @@ class AsyncPipeSink:
# -----------------------------------------------------------------------------
class ParserSource:
class BaseSource:
"""
Base class designed to be subclassed by transport-specific source classes
"""
terminated: asyncio.Future[None]
parser: PacketParser
sink: Optional[TransportSink]
def __init__(self) -> None:
self.parser = PacketParser()
self.terminated = asyncio.get_running_loop().create_future()
self.sink = None
def set_packet_sink(self, sink: TransportSink) -> None:
self.parser.set_packet_sink(sink)
self.sink = sink
def on_transport_lost(self) -> None:
self.terminated.set_result(None)
if self.parser.sink:
if hasattr(self.parser.sink, 'on_transport_lost'):
self.parser.sink.on_transport_lost()
if self.sink:
if hasattr(self.sink, 'on_transport_lost'):
self.sink.on_transport_lost()
async def wait_for_termination(self) -> None:
"""
@@ -280,6 +280,23 @@ class ParserSource:
pass
# -----------------------------------------------------------------------------
class ParserSource(BaseSource):
"""
Base class for sources that use an HCI parser.
"""
parser: PacketParser
def __init__(self) -> None:
super().__init__()
self.parser = PacketParser()
def set_packet_sink(self, sink: TransportSink) -> None:
super().set_packet_sink(sink)
self.parser.set_packet_sink(sink)
# -----------------------------------------------------------------------------
class StreamPacketSource(asyncio.Protocol, ParserSource):
def data_received(self, data: bytes) -> None:
+9 -3
View File
@@ -24,7 +24,7 @@ import platform
import usb1
from bumble.transport.common import Transport, ParserSource, TransportInitError
from bumble.transport.common import Transport, BaseSource, TransportInitError
from bumble import hci
from bumble.colors import color
@@ -208,7 +208,7 @@ async def open_usb_transport(spec: str) -> Transport:
except usb1.USBError:
logger.debug('OUT transfer likely already completed')
class UsbPacketSource(asyncio.Protocol, ParserSource):
class UsbPacketSource(asyncio.Protocol, BaseSource):
def __init__(self, device, metadata, acl_in, events_in):
super().__init__()
self.device = device
@@ -285,7 +285,13 @@ async def open_usb_transport(spec: str) -> Transport:
packet = await self.queue.get()
except asyncio.CancelledError:
return
self.parser.feed_data(packet)
if self.sink:
try:
self.sink.on_packet(packet)
except Exception as error:
logger.exception(
color(f'!!! Exception in sink.on_packet: {error}', 'red')
)
def close(self):
self.closed = True