forked from auracaster/bumble_mirror
add support for data type classes
This commit is contained in:
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -104,5 +104,8 @@
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"python-envs.defaultEnvManager": "ms-python.python:system",
|
||||
"python-envs.pythonProjects": []
|
||||
"python-envs.pythonProjects": [],
|
||||
"nrf-connect.applications": [
|
||||
"${workspaceFolder}/extras/zephyr/hci_usb"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ import bumble.device
|
||||
import bumble.logging
|
||||
import bumble.transport
|
||||
import bumble.utils
|
||||
from bumble import company_ids, core, gatt, hci
|
||||
from bumble import company_ids, core, data_types, gatt, hci
|
||||
from bumble.audio import io as audio_io
|
||||
from bumble.colors import color
|
||||
from bumble.profiles import bap, bass, le_audio, pbp
|
||||
@@ -859,21 +859,13 @@ async def run_transmit(
|
||||
)
|
||||
broadcast_audio_announcement = bap.BroadcastAudioAnnouncement(broadcast_id)
|
||||
|
||||
advertising_manufacturer_data = (
|
||||
b''
|
||||
if manufacturer_data is None
|
||||
else bytes(
|
||||
core.AdvertisingData(
|
||||
[
|
||||
(
|
||||
core.AdvertisingData.MANUFACTURER_SPECIFIC_DATA,
|
||||
struct.pack('<H', manufacturer_data[0])
|
||||
+ manufacturer_data[1],
|
||||
)
|
||||
]
|
||||
)
|
||||
advertising_data_types: list[core.DataType] = [
|
||||
data_types.BroadcastName(broadcast_name)
|
||||
]
|
||||
if manufacturer_data is not None:
|
||||
advertising_data_types.append(
|
||||
data_types.ManufacturerSpecificData(*manufacturer_data)
|
||||
)
|
||||
)
|
||||
|
||||
advertising_set = await device.create_advertising_set(
|
||||
advertising_parameters=bumble.device.AdvertisingParameters(
|
||||
@@ -885,12 +877,7 @@ async def run_transmit(
|
||||
),
|
||||
advertising_data=(
|
||||
broadcast_audio_announcement.get_advertising_data()
|
||||
+ bytes(
|
||||
core.AdvertisingData(
|
||||
[(core.AdvertisingData.BROADCAST_NAME, broadcast_name.encode())]
|
||||
)
|
||||
)
|
||||
+ advertising_manufacturer_data
|
||||
+ bytes(core.AdvertisingData(advertising_data_types))
|
||||
),
|
||||
periodic_advertising_parameters=bumble.device.PeriodicAdvertisingParameters(
|
||||
periodic_advertising_interval_min=80,
|
||||
|
||||
@@ -37,7 +37,7 @@ import click
|
||||
|
||||
import bumble
|
||||
import bumble.logging
|
||||
from bumble import utils
|
||||
from bumble import data_types, utils
|
||||
from bumble.colors import color
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import AdvertisingParameters, CisLink, Device, DeviceConfiguration
|
||||
@@ -330,22 +330,13 @@ class Speaker:
|
||||
advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes(device_config.name, 'utf-8'),
|
||||
data_types.CompleteLocalName(device_config.name),
|
||||
data_types.Flags(
|
||||
AdvertisingData.Flags.LE_GENERAL_DISCOVERABLE_MODE
|
||||
| AdvertisingData.Flags.BR_EDR_NOT_SUPPORTED
|
||||
),
|
||||
(
|
||||
AdvertisingData.FLAGS,
|
||||
bytes(
|
||||
[
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_NOT_SUPPORTED_FLAG
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(pacs.PublishedAudioCapabilitiesService.UUID),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[pacs.PublishedAudioCapabilitiesService.UUID]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
41
apps/pair.py
41
apps/pair.py
@@ -23,6 +23,7 @@ import struct
|
||||
import click
|
||||
from prompt_toolkit.shortcuts import PromptSession
|
||||
|
||||
from bumble import data_types
|
||||
from bumble.a2dp import make_audio_sink_service_sdp_records
|
||||
from bumble.att import (
|
||||
ATT_INSUFFICIENT_AUTHENTICATION_ERROR,
|
||||
@@ -34,6 +35,7 @@ from bumble.core import (
|
||||
UUID,
|
||||
AdvertisingData,
|
||||
Appearance,
|
||||
DataType,
|
||||
PhysicalTransport,
|
||||
ProtocolError,
|
||||
)
|
||||
@@ -506,33 +508,21 @@ async def pair(
|
||||
if mode == 'dual':
|
||||
flags |= AdvertisingData.Flags.SIMULTANEOUS_LE_BR_EDR_CAPABLE
|
||||
|
||||
ad_structs = [
|
||||
(
|
||||
AdvertisingData.FLAGS,
|
||||
bytes([flags]),
|
||||
),
|
||||
(AdvertisingData.COMPLETE_LOCAL_NAME, 'Bumble'.encode()),
|
||||
advertising_data_types: list[DataType] = [
|
||||
data_types.Flags(flags),
|
||||
data_types.CompleteLocalName('Bumble'),
|
||||
]
|
||||
if service_uuids_16:
|
||||
ad_structs.append(
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
b"".join(bytes(uuid) for uuid in service_uuids_16),
|
||||
)
|
||||
advertising_data_types.append(
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(service_uuids_16)
|
||||
)
|
||||
if service_uuids_32:
|
||||
ad_structs.append(
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
|
||||
b"".join(bytes(uuid) for uuid in service_uuids_32),
|
||||
)
|
||||
advertising_data_types.append(
|
||||
data_types.IncompleteListOf32BitServiceUUIDs(service_uuids_32)
|
||||
)
|
||||
if service_uuids_128:
|
||||
ad_structs.append(
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
|
||||
b"".join(bytes(uuid) for uuid in service_uuids_128),
|
||||
)
|
||||
advertising_data_types.append(
|
||||
data_types.IncompleteListOf128BitServiceUUIDs(service_uuids_128)
|
||||
)
|
||||
|
||||
if advertise_appearance:
|
||||
@@ -559,13 +549,10 @@ async def pair(
|
||||
advertise_appearance_int = int(
|
||||
Appearance(category_enum, subcategory_enum)
|
||||
)
|
||||
ad_structs.append(
|
||||
(
|
||||
AdvertisingData.APPEARANCE,
|
||||
struct.pack('<H', advertise_appearance_int),
|
||||
)
|
||||
advertising_data_types.append(
|
||||
data_types.Appearance(category_enum, subcategory_enum)
|
||||
)
|
||||
device.advertising_data = bytes(AdvertisingData(ad_structs))
|
||||
device.advertising_data = bytes(AdvertisingData(advertising_data_types))
|
||||
await device.start_advertising(
|
||||
auto_restart=True,
|
||||
own_address_type=(
|
||||
|
||||
12
apps/scan.py
12
apps/scan.py
@@ -20,6 +20,7 @@ import asyncio
|
||||
import click
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.colors import color
|
||||
from bumble.device import Advertisement, Device
|
||||
from bumble.hci import HCI_LE_1M_PHY, HCI_LE_CODED_PHY, Address, HCI_Constant
|
||||
@@ -94,13 +95,22 @@ class AdvertisementPrinter:
|
||||
else:
|
||||
phy_info = ''
|
||||
|
||||
details = separator.join(
|
||||
[
|
||||
data_type.to_string(use_label=True)
|
||||
for data_type in data_types.data_types_from_advertising_data(
|
||||
advertisement.data
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
print(
|
||||
f'>>> {color(address, address_color)} '
|
||||
f'[{color(address_type_string, type_color)}]{address_qualifier}'
|
||||
f'{resolution_qualifier}:{separator}'
|
||||
f'{phy_info}'
|
||||
f'RSSI:{advertisement.rssi:4} {rssi_bar}{separator}'
|
||||
f'{advertisement.data.to_string(separator)}\n'
|
||||
f'{details}\n'
|
||||
)
|
||||
|
||||
def on_advertisement(self, advertisement):
|
||||
|
||||
808
bumble/core.py
808
bumble/core.py
File diff suppressed because it is too large
Load Diff
1018
bumble/data_types.py
Normal file
1018
bumble/data_types.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -45,7 +45,18 @@ from typing import (
|
||||
|
||||
from typing_extensions import Self
|
||||
|
||||
from bumble import core, gatt_client, gatt_server, hci, l2cap, pairing, sdp, smp, utils
|
||||
from bumble import (
|
||||
core,
|
||||
data_types,
|
||||
gatt_client,
|
||||
gatt_server,
|
||||
hci,
|
||||
l2cap,
|
||||
pairing,
|
||||
sdp,
|
||||
smp,
|
||||
utils,
|
||||
)
|
||||
from bumble.att import ATT_CID, ATT_DEFAULT_MTU, ATT_PDU
|
||||
from bumble.colors import color
|
||||
from bumble.core import (
|
||||
@@ -2049,9 +2060,7 @@ class DeviceConfiguration:
|
||||
connectable: bool = True
|
||||
discoverable: bool = True
|
||||
advertising_data: bytes = bytes(
|
||||
AdvertisingData(
|
||||
[(AdvertisingData.COMPLETE_LOCAL_NAME, bytes(DEVICE_DEFAULT_NAME, 'utf-8'))]
|
||||
)
|
||||
AdvertisingData([data_types.CompleteLocalName(DEVICE_DEFAULT_NAME)])
|
||||
)
|
||||
irk: bytes = bytes(16) # This really must be changed for any level of security
|
||||
keystore: Optional[str] = None
|
||||
@@ -2095,9 +2104,7 @@ class DeviceConfiguration:
|
||||
self.advertising_data = bytes.fromhex(advertising_data)
|
||||
elif name is not None:
|
||||
self.advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[(AdvertisingData.COMPLETE_LOCAL_NAME, bytes(self.name, 'utf-8'))]
|
||||
)
|
||||
AdvertisingData([data_types.CompleteLocalName(self.name)])
|
||||
)
|
||||
|
||||
# Load scan response data
|
||||
@@ -3544,14 +3551,7 @@ class Device(utils.CompositeEventEmitter):
|
||||
# Synthesize an inquiry response if none is set already
|
||||
if self.inquiry_response is None:
|
||||
self.inquiry_response = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes(self.name, 'utf-8'),
|
||||
)
|
||||
]
|
||||
)
|
||||
AdvertisingData([data_types.CompleteLocalName(self.name)])
|
||||
)
|
||||
|
||||
# Update the controller
|
||||
|
||||
@@ -2135,6 +2135,7 @@ class Address:
|
||||
if len(address) == 12 + 5:
|
||||
# Form with ':' separators
|
||||
address = address.replace(':', '')
|
||||
|
||||
self.address_bytes = bytes(reversed(bytes.fromhex(address)))
|
||||
|
||||
if len(self.address_bytes) != 6:
|
||||
|
||||
@@ -21,7 +21,7 @@ import logging
|
||||
import struct
|
||||
from typing import Any, Callable, Optional, Union
|
||||
|
||||
from bumble import gatt, gatt_client, l2cap, utils
|
||||
from bumble import data_types, gatt, gatt_client, l2cap, utils
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Connection, Device
|
||||
|
||||
@@ -185,12 +185,11 @@ class AshaService(gatt.TemplateService):
|
||||
return bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.SERVICE_DATA_16_BIT_UUID,
|
||||
bytes(gatt.GATT_ASHA_SERVICE)
|
||||
+ bytes([self.protocol_version, self.capability])
|
||||
data_types.ServiceData16BitUUID(
|
||||
gatt.GATT_ASHA_SERVICE,
|
||||
bytes([self.protocol_version, self.capability])
|
||||
+ self.hisyncid[:4],
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -27,7 +27,7 @@ from collections.abc import Sequence
|
||||
|
||||
from typing_extensions import Self
|
||||
|
||||
from bumble import core, gatt, hci, utils
|
||||
from bumble import core, data_types, gatt, hci, utils
|
||||
from bumble.profiles import le_audio
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@@ -257,11 +257,10 @@ class UnicastServerAdvertisingData:
|
||||
return bytes(
|
||||
core.AdvertisingData(
|
||||
[
|
||||
(
|
||||
core.AdvertisingData.SERVICE_DATA_16_BIT_UUID,
|
||||
data_types.ServiceData16BitUUID(
|
||||
gatt.GATT_AUDIO_STREAM_CONTROL_SERVICE,
|
||||
struct.pack(
|
||||
'<2sBIB',
|
||||
bytes(gatt.GATT_AUDIO_STREAM_CONTROL_SERVICE),
|
||||
'<BIB',
|
||||
self.announcement_type,
|
||||
self.available_audio_contexts,
|
||||
len(self.metadata),
|
||||
@@ -490,12 +489,8 @@ class BroadcastAudioAnnouncement:
|
||||
return bytes(
|
||||
core.AdvertisingData(
|
||||
[
|
||||
(
|
||||
core.AdvertisingData.SERVICE_DATA_16_BIT_UUID,
|
||||
(
|
||||
bytes(gatt.GATT_BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE)
|
||||
+ bytes(self)
|
||||
),
|
||||
data_types.ServiceData16BitUUID(
|
||||
gatt.GATT_BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE, bytes(self)
|
||||
)
|
||||
]
|
||||
)
|
||||
@@ -607,12 +602,8 @@ class BasicAudioAnnouncement:
|
||||
return bytes(
|
||||
core.AdvertisingData(
|
||||
[
|
||||
(
|
||||
core.AdvertisingData.SERVICE_DATA_16_BIT_UUID,
|
||||
(
|
||||
bytes(gatt.GATT_BASIC_AUDIO_ANNOUNCEMENT_SERVICE)
|
||||
+ bytes(self)
|
||||
),
|
||||
data_types.ServiceData16BitUUID(
|
||||
gatt.GATT_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, bytes(self)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ import struct
|
||||
import sys
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Device
|
||||
from bumble.profiles.battery_service import BatteryService
|
||||
@@ -47,15 +48,14 @@ async def main() -> None:
|
||||
device.advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble Battery', 'utf-8'),
|
||||
data_types.CompleteLocalName('Bumble Battery'),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[battery_service.uuid]
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(battery_service.uuid),
|
||||
data_types.Appearance(
|
||||
data_types.Appearance.Category.WEARABLE_AUDIO_DEVICE,
|
||||
data_types.Appearance.WearableAudioDeviceSubcategory.EARBUD,
|
||||
),
|
||||
(AdvertisingData.APPEARANCE, struct.pack('<H', 0x0340)),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -20,6 +20,7 @@ import struct
|
||||
import sys
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Device
|
||||
from bumble.profiles.device_information_service import DeviceInformationService
|
||||
@@ -53,11 +54,11 @@ async def main() -> None:
|
||||
device.advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble Device', 'utf-8'),
|
||||
data_types.CompleteLocalName('Bumble Device'),
|
||||
data_types.Appearance(
|
||||
data_types.Appearance.Category.HEART_RATE_SENSOR,
|
||||
data_types.Appearance.HeartRateSensorSubcategory.GENERIC_HEART_RATE_SENSOR,
|
||||
),
|
||||
(AdvertisingData.APPEARANCE, struct.pack('<H', 0x0340)),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -24,6 +24,7 @@ import sys
|
||||
import time
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Device
|
||||
from bumble.profiles.device_information_service import DeviceInformationService
|
||||
@@ -88,15 +89,14 @@ async def main() -> None:
|
||||
device.advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble Heart', 'utf-8'),
|
||||
data_types.CompleteLocalName('Bumble Heart'),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[heart_rate_service.uuid]
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(heart_rate_service.uuid),
|
||||
data_types.Appearance(
|
||||
data_types.Appearance.Category.HEART_RATE_SENSOR,
|
||||
data_types.Appearance.HeartRateSensorSubcategory.GENERIC_HEART_RATE_SENSOR,
|
||||
),
|
||||
(AdvertisingData.APPEARANCE, struct.pack('<H', 0x0340)),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -23,6 +23,7 @@ import sys
|
||||
import websockets
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.colors import color
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Connection, Device, Peer
|
||||
@@ -341,16 +342,18 @@ async def keyboard_device(device, command):
|
||||
device.advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble Keyboard', 'utf-8'),
|
||||
data_types.CompleteLocalName('Bumble Keyboard'),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[GATT_HUMAN_INTERFACE_DEVICE_SERVICE]
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(GATT_HUMAN_INTERFACE_DEVICE_SERVICE),
|
||||
data_types.Appearance(
|
||||
data_types.Appearance.Category.HUMAN_INTERFACE_DEVICE,
|
||||
data_types.Appearance.HumanInterfaceDeviceSubcategory.KEYBOARD,
|
||||
),
|
||||
data_types.Flags(
|
||||
AdvertisingData.Flags.LE_LIMITED_DISCOVERABLE_MODE
|
||||
| AdvertisingData.Flags.BR_EDR_NOT_SUPPORTED
|
||||
),
|
||||
(AdvertisingData.APPEARANCE, struct.pack('<H', 0x03C1)),
|
||||
(AdvertisingData.FLAGS, bytes([0x05])),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -20,6 +20,7 @@ import struct
|
||||
import sys
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import AdvertisingType, Device
|
||||
from bumble.hci import Address
|
||||
@@ -60,7 +61,10 @@ async def main() -> None:
|
||||
device.scan_response_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(AdvertisingData.APPEARANCE, struct.pack('<H', 0x0340)),
|
||||
data_types.Appearance(
|
||||
data_types.Appearance.Category.HEART_RATE_SENSOR,
|
||||
data_types.Appearance.HeartRateSensorSubcategory.GENERIC_HEART_RATE_SENSOR,
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ from typing import Optional
|
||||
import websockets
|
||||
|
||||
import bumble.logging
|
||||
from bumble import decoder, gatt
|
||||
from bumble import data_types, decoder, gatt
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import AdvertisingParameters, Device
|
||||
from bumble.profiles import asha
|
||||
@@ -78,14 +78,10 @@ async def main() -> None:
|
||||
bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes(device.name, 'utf-8'),
|
||||
),
|
||||
(AdvertisingData.FLAGS, bytes([0x06])),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(gatt.GATT_ASHA_SERVICE),
|
||||
data_types.CompleteLocalName(device.name),
|
||||
data_types.Flags(AdvertisingData.Flags(0x06)),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[gatt.GATT_ASHA_SERVICE]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -20,6 +20,7 @@ import secrets
|
||||
import sys
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Device
|
||||
from bumble.hci import Address
|
||||
@@ -66,23 +67,14 @@ async def main() -> None:
|
||||
bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes(f'Bumble LE Audio-{i}', 'utf-8'),
|
||||
data_types.CompleteLocalName(f'Bumble LE Audio-{i}'),
|
||||
data_types.Flags(
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_HOST_FLAG
|
||||
| AdvertisingData.BR_EDR_CONTROLLER_FLAG
|
||||
),
|
||||
(
|
||||
AdvertisingData.FLAGS,
|
||||
bytes(
|
||||
[
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_HOST_FLAG
|
||||
| AdvertisingData.BR_EDR_CONTROLLER_FLAG
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(CoordinatedSetIdentificationService.UUID),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[CoordinatedSetIdentificationService.UUID]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -19,6 +19,7 @@ import asyncio
|
||||
import sys
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Device
|
||||
from bumble.profiles.hap import (
|
||||
@@ -71,23 +72,14 @@ async def main() -> None:
|
||||
advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble HearingAccessService', 'utf-8'),
|
||||
data_types.CompleteLocalName('Bumble HearingAccessService'),
|
||||
data_types.Flags(
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_HOST_FLAG
|
||||
| AdvertisingData.BR_EDR_CONTROLLER_FLAG
|
||||
),
|
||||
(
|
||||
AdvertisingData.FLAGS,
|
||||
bytes(
|
||||
[
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_HOST_FLAG
|
||||
| AdvertisingData.BR_EDR_CONTROLLER_FLAG
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(HearingAccessService.UUID),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[HearingAccessService.UUID]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -23,6 +23,7 @@ from typing import Optional
|
||||
import websockets
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import (
|
||||
AdvertisingEventProperties,
|
||||
@@ -106,17 +107,10 @@ async def main() -> None:
|
||||
advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble LE Audio', 'utf-8'),
|
||||
),
|
||||
(
|
||||
AdvertisingData.FLAGS,
|
||||
bytes([AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG]),
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(PublishedAudioCapabilitiesService.UUID),
|
||||
data_types.CompleteLocalName('Bumble LE Audio'),
|
||||
data_types.Flags(AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[PublishedAudioCapabilitiesService.UUID]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -24,6 +24,7 @@ import struct
|
||||
import sys
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Device
|
||||
from bumble.hci import CodecID, CodingFormat, HCI_IsoDataPacket
|
||||
@@ -111,23 +112,14 @@ async def main() -> None:
|
||||
bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble LE Audio', 'utf-8'),
|
||||
data_types.CompleteLocalName('Bumble LE Audio'),
|
||||
data_types.Flags(
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_HOST_FLAG
|
||||
| AdvertisingData.BR_EDR_CONTROLLER_FLAG
|
||||
),
|
||||
(
|
||||
AdvertisingData.FLAGS,
|
||||
bytes(
|
||||
[
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_HOST_FLAG
|
||||
| AdvertisingData.BR_EDR_CONTROLLER_FLAG
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(PublishedAudioCapabilitiesService.UUID),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[PublishedAudioCapabilitiesService.UUID]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -24,6 +24,7 @@ from typing import Optional
|
||||
import websockets
|
||||
|
||||
import bumble.logging
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import AdvertisingEventProperties, AdvertisingParameters, Device
|
||||
from bumble.hci import CodecID, CodingFormat, OwnAddressType
|
||||
@@ -127,23 +128,14 @@ async def main() -> None:
|
||||
bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble LE Audio', 'utf-8'),
|
||||
data_types.CompleteLocalName('Bumble LE Audio'),
|
||||
data_types.Flags(
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_HOST_FLAG
|
||||
| AdvertisingData.BR_EDR_CONTROLLER_FLAG
|
||||
),
|
||||
(
|
||||
AdvertisingData.FLAGS,
|
||||
bytes(
|
||||
[
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_HOST_FLAG
|
||||
| AdvertisingData.BR_EDR_CONTROLLER_FLAG
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(PublishedAudioCapabilitiesService.UUID),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[PublishedAudioCapabilitiesService.UUID]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -16,7 +16,13 @@
|
||||
# Imports
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
from bumble.core import UUID, AdvertisingData, Appearance, get_dict_key_by_value
|
||||
from bumble.core import (
|
||||
UUID,
|
||||
AdvertisingData,
|
||||
Appearance,
|
||||
ClassOfDevice,
|
||||
get_dict_key_by_value,
|
||||
)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@@ -93,6 +99,24 @@ def test_appearance() -> None:
|
||||
assert int(a) == 0x3333
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def test_class_of_device() -> None:
|
||||
c1 = ClassOfDevice(
|
||||
ClassOfDevice.MajorServiceClasses.AUDIO
|
||||
| ClassOfDevice.MajorServiceClasses.RENDERING,
|
||||
ClassOfDevice.MajorDeviceClass.AUDIO_VIDEO,
|
||||
ClassOfDevice.AudioVideoMinorDeviceClass.CAMCORDER,
|
||||
)
|
||||
assert str(c1) == "ClassOfDevice(RENDERING|AUDIO,AUDIO_VIDEO/CAMCORDER)"
|
||||
|
||||
c2 = ClassOfDevice(
|
||||
ClassOfDevice.MajorServiceClasses.AUDIO,
|
||||
ClassOfDevice.MajorDeviceClass.AUDIO_VIDEO,
|
||||
0x123,
|
||||
)
|
||||
assert str(c2) == "ClassOfDevice(AUDIO,AUDIO_VIDEO/0x123)"
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
test_ad_data()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
import struct
|
||||
|
||||
from bumble import data_types
|
||||
from bumble.core import AdvertisingData
|
||||
from bumble.device import Device
|
||||
from bumble.hci import HCI_Reset_Command
|
||||
@@ -65,24 +66,18 @@ class HeartRateMonitor:
|
||||
self.device.advertising_data = bytes(
|
||||
AdvertisingData(
|
||||
[
|
||||
(
|
||||
AdvertisingData.FLAGS,
|
||||
bytes(
|
||||
[
|
||||
AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG
|
||||
| AdvertisingData.BR_EDR_NOT_SUPPORTED_FLAG
|
||||
]
|
||||
),
|
||||
data_types.Flags(
|
||||
AdvertisingData.Flags.LE_GENERAL_DISCOVERABLE_MODE
|
||||
| AdvertisingData.Flags.BR_EDR_NOT_SUPPORTED
|
||||
),
|
||||
(
|
||||
AdvertisingData.COMPLETE_LOCAL_NAME,
|
||||
bytes('Bumble Heart', 'utf-8'),
|
||||
data_types.CompleteLocalName('Bumble Heart'),
|
||||
data_types.IncompleteListOf16BitServiceUUIDs(
|
||||
[self.heart_rate_service.uuid]
|
||||
),
|
||||
(
|
||||
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
||||
bytes(self.heart_rate_service.uuid),
|
||||
data_types.Appearance(
|
||||
data_types.Appearance.Category.HEART_RATE_SENSOR,
|
||||
data_types.Appearance.HeartRateSensorSubcategory.GENERIC_HEART_RATE_SENSOR,
|
||||
),
|
||||
(AdvertisingData.APPEARANCE, struct.pack('<H', 0x0340)),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user