Skip to content

Commit

Permalink
Merge pull request #67 from tannewt/service_data
Browse files Browse the repository at this point in the history
Add support for service data
  • Loading branch information
dhalbert authored Feb 14, 2020
2 parents fb91fcb + 9b5b533 commit 4ab856d
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 5 deletions.
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

0 comments on commit 4ab856d

Please sign in to comment.