164 lines
4.8 KiB
Python
164 lines
4.8 KiB
Python
import re
|
|
from enum import Enum
|
|
from typing import Dict
|
|
|
|
import bluetooth_numbers
|
|
|
|
from ._types import RawServiceClass
|
|
|
|
|
|
def _service_name_to_enum_name(service_name: str) -> str:
|
|
"""
|
|
Convert a service name to an enum-key compatible string.
|
|
"""
|
|
ret = service_name.title()
|
|
ret = re.sub(r"\(.+?\)", "", ret)
|
|
ret = re.sub(r"\s+", "_", ret)
|
|
ret = re.sub(r"[^a-zA-Z0-9_]", "", ret)
|
|
ret = re.sub(r"_+", "_", ret)
|
|
return ret.upper()
|
|
|
|
|
|
_service_classes: Dict[RawServiceClass, str] = {
|
|
0x0: "Unknown",
|
|
0x1000: "Service Discovery Server Service Class ID",
|
|
0x1001: "Browse Group Descriptor Service Class ID",
|
|
0x1101: "Serial Port",
|
|
0x1102: "LAN Access Using PPP",
|
|
0x1103: "Dialup Networking",
|
|
0x1104: "IR MC Sync",
|
|
0x1105: "OBEX Object Push",
|
|
0x1106: "OBEX File Transfer",
|
|
0x1107: "IR MC Sync Command",
|
|
0x1108: "Headset",
|
|
0x1109: "Cordless Telephony",
|
|
0x110A: "Audio Source",
|
|
0x110B: "Audio Sink",
|
|
0x110C: "A/V Remote Control Target",
|
|
0x110D: "Advanced Audio Distribution",
|
|
0x110E: "A/V Remote Control",
|
|
0x110F: "A/V Remote Control Controller",
|
|
0x1110: "Intercom",
|
|
0x1111: "Fax",
|
|
0x1112: "Headset Audio Gateway",
|
|
0x1113: "WAP",
|
|
0x1114: "WAP Client",
|
|
0x1115: "PANU",
|
|
0x1116: "NAP",
|
|
0x1117: "GN",
|
|
0x1118: "Direct Printing",
|
|
0x1119: "Reference Printing",
|
|
0x111A: "Basic Imaging Profile",
|
|
0x111B: "Imaging Responder",
|
|
0x111C: "Imaging Automatic Archive",
|
|
0x111D: "Imaging Referenced Objects",
|
|
0x111E: "Handsfree",
|
|
0x111F: "Handsfree Audio Gateway",
|
|
0x1120: "Direct Printing Reference Objects Service",
|
|
0x1121: "Reflected UI",
|
|
0x1122: "Basic Printing",
|
|
0x1123: "Printing Status",
|
|
0x1124: "Human Interface Device Service",
|
|
0x1125: "Hard Copy Cable Replacement",
|
|
0x1126: "HCR Print",
|
|
0x1127: "HCR Scan",
|
|
0x1128: "Common ISDN Access",
|
|
0x112D: "SIM Access",
|
|
0x112E: "Phone Book Access PCE",
|
|
0x112F: "Phone Book Access PSE",
|
|
0x1130: "Phone Book Access",
|
|
0x1131: "Headset NS",
|
|
0x1132: "Message Access Server",
|
|
0x1133: "Message Notification Server",
|
|
0x1134: "Message Notification Profile",
|
|
0x1135: "GNSS",
|
|
0x1136: "GNSS Server",
|
|
0x1137: "3D Display",
|
|
0x1138: "3D Glasses",
|
|
0x1139: "3D Synchronization",
|
|
0x113A: "MPS Profile",
|
|
0x113B: "MPS SC",
|
|
0x113C: "CTN Access Service",
|
|
0x113D: "CTN Notification Service",
|
|
0x113E: "CTN Profile",
|
|
0x1200: "PnP Information",
|
|
0x1201: "Generic Networking",
|
|
0x1202: "Generic File Transfer",
|
|
0x1203: "Generic Audio",
|
|
0x1204: "Generic Telephony",
|
|
0x1205: "UPNP Service",
|
|
0x1206: "UPNP IP Service",
|
|
0x1300: "ESDP UPNP IP PAN",
|
|
0x1301: "ESDP UPNP IP LAP",
|
|
0x1302: "ESDP UPNP L2CAP",
|
|
0x1303: "Video Source",
|
|
0x1304: "Video Sink",
|
|
0x1305: "Video Distribution",
|
|
0x1400: "HDP",
|
|
0x1401: "HDP Source",
|
|
0x1402: "HDP Sink",
|
|
}
|
|
"""
|
|
Directory of known Bluetooth service UUIDs.
|
|
|
|
See
|
|
https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf,
|
|
Section 3.3.
|
|
"""
|
|
|
|
# Update the base services with the GATT service UUIDs defined in ``bluetooth_numbers``. See
|
|
# https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf,
|
|
# Section 3.4
|
|
_service_classes.update(bluetooth_numbers.service)
|
|
|
|
_service_classes_by_name: Dict[str, RawServiceClass] = {
|
|
name: cls for cls, name in _service_classes.items()
|
|
}
|
|
|
|
|
|
class _ServiceClassMeta:
|
|
"""
|
|
Metaclass for :class:`ServiceClass`.
|
|
"""
|
|
|
|
value: RawServiceClass
|
|
""" The raw service class value. """
|
|
|
|
@classmethod
|
|
def get(cls, value: RawServiceClass) -> "ServiceClass":
|
|
"""
|
|
:param value: The raw service class UUID.
|
|
:return: The parsed :class:`ServiceClass` instance, or
|
|
``ServiceClass.UNKNOWN``.
|
|
"""
|
|
try:
|
|
return ServiceClass(value)
|
|
except ValueError:
|
|
return ServiceClass.UNKNOWN # type: ignore
|
|
|
|
@classmethod
|
|
def by_name(cls, name: str) -> "ServiceClass":
|
|
"""
|
|
:param name: The name of the service class.
|
|
:return: The :class:`ServiceClass` instance, or
|
|
``ServiceClass.UNKNOWN``.
|
|
"""
|
|
return (
|
|
ServiceClass(_service_classes_by_name.get(name))
|
|
or ServiceClass.UNKNOWN # type: ignore
|
|
)
|
|
|
|
def __str__(self) -> str:
|
|
return _service_classes.get(self.value, ServiceClass(0).value)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<{self.value}: {str(self)}>"
|
|
|
|
|
|
ServiceClass = Enum( # type: ignore
|
|
"ServiceClass",
|
|
{_service_name_to_enum_name(name): cls for cls, name in _service_classes.items()},
|
|
type=_ServiceClassMeta,
|
|
)
|
|
""" Enumeration of known Bluetooth services. """
|