1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-15 00:05:11 +02:00

Fix broken controller regexp scheme in the bluetoothctl parser (#599)

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>
This commit is contained in:
Jake Ob
2024-10-18 19:50:51 +03:00
committed by GitHub
parent 78150ded70
commit c5e0642b0b
3 changed files with 103 additions and 2 deletions

View File

@ -28,6 +28,8 @@ a controller and a device but there might be fields corresponding to one entity.
Controller:
[
{
"manufacturer": string,
"version": string,
"name": string,
"is_default": boolean,
"is_public": boolean,
@ -127,6 +129,8 @@ try:
Controller = TypedDict(
"Controller",
{
"manufacturer": str,
"version": str,
"name": str,
"is_default": bool,
"is_public": bool,
@ -175,7 +179,9 @@ except ImportError:
_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>.+)"
@ -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,
@ -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"]

View File

@ -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

View File

@ -104,6 +104,58 @@ class BluetoothctlTests(unittest.TestCase):
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):
"""