Skip to content

Commit

Permalink
Fix broken controller regexp scheme in the bluetoothctl parser (#599)
Browse files Browse the repository at this point in the history
This commit fixes the controller parser scheme in order to take care
and extract some extra attributes, the manufacturer and version.
The order of the attributes appearing in the regexp scheme must follow
the order they appear in the `bluetoothctl show` outputs.

A new test has been added to test outputs with these extra attrs.

Co-authored-by: Kelly Brazil <kellyjonbrazil@gmail.com>
  • Loading branch information
tzeikob and kellyjonbrazil authored Oct 18, 2024
1 parent 78150de commit c5e0642
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
16 changes: 14 additions & 2 deletions jc/parsers/bluetoothctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
Controller:
[
{
"manufacturer": string,
"version": string,
"name": string,
"is_default": boolean,
"is_public": boolean,
Expand Down Expand Up @@ -127,6 +129,8 @@ class info():
Controller = TypedDict(
"Controller",
{
"manufacturer": str,
"version": str,
"name": str,
"is_default": bool,
"is_public": bool,
Expand Down Expand Up @@ -175,7 +179,9 @@ class info():
_controller_head_pattern = r"Controller (?P<address>([0-9A-F]{2}:){5}[0-9A-F]{2}) (?P<name>.+)"

_controller_line_pattern = (
r"(\s*Name:\s*(?P<name>.+)"
r"(\s*Manufacturer:\s*(?P<manufacturer>.+)"
+ r"|\s*Version:\s*(?P<version>.+)"
+ r"|\s*Name:\s*(?P<name>.+)"
+ r"|\s*Alias:\s*(?P<alias>.+)"
+ r"|\s*Class:\s*(?P<class>.+)"
+ r"|\s*Powered:\s*(?P<powered>.+)"
Expand Down Expand Up @@ -203,6 +209,8 @@ def _parse_controller(next_lines: List[str]) -> Optional[Controller]:
return None

controller: Controller = {
"manufacturer": '',
"version": '',
"name": '',
"is_default": False,
"is_public": False,
Expand Down Expand Up @@ -241,7 +249,11 @@ def _parse_controller(next_lines: List[str]) -> Optional[Controller]:

matches = result.groupdict()

if matches["name"]:
if matches["manufacturer"]:
controller["manufacturer"] = matches["manufacturer"]
elif matches["version"]:
controller["version"] = matches["version"]
elif matches["name"]:
controller["name"] = matches["name"]
elif matches["alias"]:
controller["alias"] = matches["alias"]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Controller 48:A4:72:3C:96:63 (public)
Manufacturer: 0x0002 (2)
Version: 0x08 (8)
Name: ubuntu
Alias: ubuntu
Class: 0x007c0104 (8126724)
Powered: yes
Discoverable: yes
DiscoverableTimeout: 0x000000b4 (180)
Pairable: yes
UUID: Message Notification Se.. (00001133-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
UUID: OBEX Object Push (00001105-0000-1000-8000-00805f9b34fb)
UUID: Message Access Server (00001132-0000-1000-8000-00805f9b34fb)
UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
UUID: IrMC Sync (00001104-0000-1000-8000-00805f9b34fb)
UUID: Vendor specific (00005005-0000-1000-8000-0002ee000001)
UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: Phonebook Access Server (0000112f-0000-1000-8000-00805f9b34fb)
UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)
UUID: Device Information (0000180a-0000-1000-8000-00805f9b34fb)
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb)
UUID: Audio Source (0000110a-0000-1000-8000-00805f9b34fb)
UUID: OBEX File Transfer (00001106-0000-1000-8000-00805f9b34fb)
UUID: Handsfree (0000111e-0000-1000-8000-00805f9b34fb)
Modalias: usb:v1D6Bp0246d0548
Discovering: yes
Roles: central
Roles: peripheral
Advertising Features:
ActiveInstances: 0x00 (0)
SupportedInstances: 0x05 (5)
SupportedIncludes: tx-power
SupportedIncludes: appearance
SupportedIncludes: local-name
52 changes: 52 additions & 0 deletions tests/test_bluetoothctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,58 @@ def test_bluetoothctl_controller(self):
if actual:
for k, v in expected.items():
self.assertEqual(v, actual[0][k], f"Controller regex failed on {k}")

def test_bluetoothctl_controller_with_manufacturer(self):
"""
Test 'bluetoothctl' with controller having manufacturer attr
"""

with open("tests/fixtures/generic/bluetoothctl_controller_with_manufacturer.out", "r") as f:
output = f.read()

actual = parse(output, quiet=True)

self.assertIsNotNone(actual)
self.assertIsNotNone(actual[0])

expected = {
"manufacturer": "0x0002 (2)",
"version": "0x08 (8)",
"address": "48:A4:72:3C:96:63",
"is_public": True,
"name": "ubuntu",
"alias": "ubuntu",
"class": "0x007c0104 (8126724)",
"powered": "yes",
"discoverable": "yes",
"discoverable_timeout": "0x000000b4 (180)",
"pairable": "yes",
"uuids": [
"Message Notification Se.. (00001133-0000-1000-8000-00805f9b34fb)",
"A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)",
"OBEX Object Push (00001105-0000-1000-8000-00805f9b34fb)",
"Message Access Server (00001132-0000-1000-8000-00805f9b34fb)",
"PnP Information (00001200-0000-1000-8000-00805f9b34fb)",
"IrMC Sync (00001104-0000-1000-8000-00805f9b34fb)",
"Vendor specific (00005005-0000-1000-8000-0002ee000001)",
"A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)",
"Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)",
"Phonebook Access Server (0000112f-0000-1000-8000-00805f9b34fb)",
"Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)",
"Device Information (0000180a-0000-1000-8000-00805f9b34fb)",
"Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)",
"Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb)",
"Audio Source (0000110a-0000-1000-8000-00805f9b34fb)",
"OBEX File Transfer (00001106-0000-1000-8000-00805f9b34fb)",
"Handsfree (0000111e-0000-1000-8000-00805f9b34fb)"
],
"modalias": "usb:v1D6Bp0246d0548",
"discovering": "yes"
}

if actual:
for k, v in expected.items():
self.assertEqual(v, actual[0][k], f"Controller regex failed on {k}")

def test_bluetoothctl_controllers(self):
"""
Expand Down

0 comments on commit c5e0642

Please sign in to comment.