Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions adafruit_ble/advertising/standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,71 @@ def __set__(self, obj, value):
else:
obj.manufacturer_data.data[self._key] = struct.pack(self._format, *value)

# TODO: Handle service data.
class ServiceData(AdvertisingDataField):
"""Encapsulates service data. It is read as a memoryview which can be manipulated or set as a
bytearray to change the size."""
def __init__(self, service):
if isinstance(service.uuid, StandardUUID):
self._adt = 0x16
elif isinstance(service.uuid, VendorUUID):
self._adt = 0x21
self._prefix = bytes(service.uuid)

def __get__(self, obj, cls):
# If not present at all and mutable, then we init it, otherwise None.
if self._adt not in obj.data_dict:
if obj.mutable:
obj.data_dict[self._adt] = bytearray(self._prefix)
else:
return None

all_service_data = obj.data_dict[self._adt]
# Handle a list of existing data. This doesn't support multiple service data ADTs for the
# same service.
if isinstance(all_service_data, list):
for i, service_data in enumerate(all_service_data):
if service_data.startswith(self._prefix):
if not isinstance(service_data, bytearray):
service_data = bytearray(service_data)
all_service_data[i] = service_data
return memoryview(service_data)[len(self._prefix):]
if obj.mutable:
service_data = bytearray(self._prefix)
all_service_data.append(service_data)
return memoryview(service_data)[len(self._prefix):]
# Existing data is a single set of bytes.
elif isinstance(all_service_data, (bytes, bytearray)):
service_data = all_service_data
if not bytes(service_data).startswith(self._prefix):
if not obj.mutable:
return None
# Upgrade the value to a list.
service_data = bytearray(self._prefix)
obj.data_dict[self._adt] = [service_data, service_data]
if not isinstance(service_data, bytearray):
service_data = bytearray(service_data)
obj.data_dict[self._adt] = service_data
return memoryview(service_data)[len(self._prefix):]

return None

# SERVICE_DATA_128BIT_UUID = 0x21
# """Service data with 128 bit UUID."""

# SERVICE_DATA_16_BIT_UUID = 0x16
# """Service data with 16 bit UUID."""
def __set__(self, obj, value):
if not obj.mutable:
raise RuntimeError("Advertisement immutable")
if not isinstance(value, bytearray):
raise TypeError("Value must be bytearray")
full_value = bytearray(self._prefix) + value
if self._adt not in obj.data_dict:
obj.data_dict[self._adt] = full_value
return

all_service_data = obj.data_dict[self._adt]
if isinstance(all_service_data, list):
for i, service_data in enumerate(all_service_data):
if service_data.startswith(self._prefix):
all_service_data[i] = full_value
return
all_service_data.append(full_value)
elif isinstance(all_service_data, (bytes, bytearray)):
obj.data_dict[self._adt] = full_value
7 changes: 7 additions & 0 deletions adafruit_ble/uuid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ def __eq__(self, other):
def __str__(self):
return str(self.bleio_uuid)

def __bytes__(self):
if self.bleio_uuid.size == 128:
return self.bleio_uuid.uuid128
b = bytearray(2)
self.bleio_uuid.pack_into(b)
return bytes(b)

def pack_into(self, buffer, offset=0):
"""Packs the UUID into the buffer at the given offset."""
self.bleio_uuid.pack_into(buffer, offset=offset)
Expand Down