Skip to content

Commit

Permalink
gattlib-py: Added support for manufacturer data from GATT advertising
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviermartin committed Apr 11, 2024
1 parent 35566d1 commit f79e90c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 26 deletions.
14 changes: 12 additions & 2 deletions gattlib-py/gattlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ class GattlibAdvertisementData(Structure):
("data", c_void_p),
("data_length", c_size_t)]

# typedef struct {
# uint16_t manufacturer_id;
# uint8_t* data;
# size_t data_size;
# } gattlib_manufacturer_data_t;
class GattlibManufacturerData(Structure):
_fields_ = [("manufacturer_id", c_ushort),
("data", c_void_p),
("data_size", c_size_t)]


# int gattlib_adapter_open(const char* adapter_name, gattlib_adapter_t** adapter);
gattlib_adapter_open = gattlib.gattlib_adapter_open
Expand Down Expand Up @@ -212,13 +222,13 @@ class GattlibAdvertisementData(Structure):
# gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
# gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
gattlib_get_advertisement_data = gattlib.gattlib_get_advertisement_data
gattlib_get_advertisement_data.argtypes = [c_void_p, POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t), POINTER(c_uint16), POINTER(c_void_p), POINTER(c_size_t)]
gattlib_get_advertisement_data.argtypes = [c_void_p, POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t), POINTER(POINTER(GattlibManufacturerData)), POINTER(c_size_t)]

# int gattlib_get_advertisement_data_from_mac(gattlib_adapter_t* adapter, const char *mac_address,
# gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_length,
# gattlib_manufacturer_data_t** manufacturer_data, size_t* manufacturer_data_count)
gattlib_get_advertisement_data_from_mac = gattlib.gattlib_get_advertisement_data_from_mac
gattlib_get_advertisement_data_from_mac.argtypes = [c_void_p, c_char_p, POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t), POINTER(c_uint16), POINTER(c_void_p), POINTER(c_size_t)]
gattlib_get_advertisement_data_from_mac.argtypes = [c_void_p, c_char_p, POINTER(POINTER(GattlibAdvertisementData)), POINTER(c_size_t), POINTER(POINTER(GattlibManufacturerData)), POINTER(c_size_t)]

# int gattlib_mainloop_python(PyObject *handler, PyObject *user_data)
gattlib_mainloop = gattlib.gattlib_mainloop_python
Expand Down
28 changes: 16 additions & 12 deletions gattlib-py/gattlib/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from gattlib import *
from .device import Device
from .exception import handle_return, AdapterNotOpened
from .exception import handle_return
from .uuid import gattlib_uuid_to_int

GATTLIB_DISCOVER_FILTER_USE_UUID = (1 << 0)
Expand Down Expand Up @@ -238,18 +238,16 @@ def gattlib_get_advertisement_data_from_mac(self, mac_address):

_advertisement_data = POINTER(GattlibAdvertisementData)()
_advertisement_data_count = c_size_t(0)
_manufacturer_id = c_uint16(0)
_manufacturer_data = c_void_p(None)
_manufacturer_data = POINTER(GattlibManufacturerData)()
_manufacturer_data_len = c_size_t(0)

ret = gattlib_get_advertisement_data_from_mac(self._adapter, mac_address,
byref(_advertisement_data), byref(_advertisement_data_count),
byref(_manufacturer_id),
byref(_manufacturer_data), byref(_manufacturer_data_len))
handle_return(ret)

advertisement_data = {}
manufacturer_data = None
manufacturer_data = {}

for i in range(0, _advertisement_data_count.value):
service_data = _advertisement_data[i]
Expand All @@ -264,15 +262,21 @@ def gattlib_get_advertisement_data_from_mac(self, mac_address):

advertisement_data[uuid] = data

if _manufacturer_data_len.value > 0:
pointer_type = POINTER(c_byte * _manufacturer_data_len.value)
c_bytearray = cast(_manufacturer_data, pointer_type)
for i in range(0, _manufacturer_data_len.value):
_manufacturer_data = _manufacturer_data[i]

manufacturer_data = bytearray(_manufacturer_data_len.value)
for i in range(_manufacturer_data_len.value):
manufacturer_data[i] = c_bytearray.contents[i] & 0xFF
pointer_type = POINTER(c_byte * _manufacturer_data.data_size.value)
c_bytearray = cast(_manufacturer_data.data, pointer_type)

data = bytearray(_manufacturer_data.data_size.value)
for j in range(_manufacturer_data.data_size.value):
data[j] = c_bytearray.contents[j] & 0xFF

manufacturer_data[_manufacturer_data.manufacturer_id] = data

gattlib_free_mem(_manufacturer_data.data)

gattlib_free_mem(_advertisement_data)
gattlib_free_mem(_manufacturer_data)

return advertisement_data, _manufacturer_id.value, manufacturer_data
return advertisement_data, manufacturer_data
27 changes: 15 additions & 12 deletions gattlib-py/gattlib/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,25 +182,22 @@ def discover(self):
def get_advertisement_data(self):
_advertisement_data = POINTER(GattlibAdvertisementData)()
_advertisement_data_count = c_size_t(0)
_manufacturer_id = c_uint16(0)
_manufacturer_data = c_void_p(None)
_manufacturer_data = POINTER(GattlibManufacturerData)()
_manufacturer_data_len = c_size_t(0)

if self._connection is None:
ret = gattlib_get_advertisement_data_from_mac(self._adapter._adapter, self._addr,
byref(_advertisement_data), byref(_advertisement_data_count),
byref(_manufacturer_id),
byref(_manufacturer_data), byref(_manufacturer_data_len))
else:
ret = gattlib_get_advertisement_data(self._connection,
byref(_advertisement_data), byref(_advertisement_data_count),
byref(_manufacturer_id),
byref(_manufacturer_data), byref(_manufacturer_data_len))

handle_return(ret)

advertisement_data = {}
manufacturer_data = None
manufacturer_data = {}

for i in range(0, _advertisement_data_count.value):
service_data = _advertisement_data[i]
Expand All @@ -215,18 +212,24 @@ def get_advertisement_data(self):

advertisement_data[uuid] = data

if _manufacturer_data_len.value > 0:
pointer_type = POINTER(c_byte * _manufacturer_data_len.value)
c_bytearray = cast(_manufacturer_data, pointer_type)
for i in range(0, _manufacturer_data_len.value):
_manufacturer_data = _manufacturer_data[i]

manufacturer_data = bytearray(_manufacturer_data_len.value)
for i in range(_manufacturer_data_len.value):
manufacturer_data[i] = c_bytearray.contents[i] & 0xFF
pointer_type = POINTER(c_byte * _manufacturer_data.data_size.value)
c_bytearray = cast(_manufacturer_data.data, pointer_type)

data = bytearray(_manufacturer_data.data_size.value)
for j in range(_manufacturer_data.data_size.value):
data[j] = c_bytearray.contents[j] & 0xFF

manufacturer_data[_manufacturer_data.manufacturer_id] = data

gattlib_free_mem(_manufacturer_data.data)

gattlib_free_mem(_advertisement_data)
gattlib_free_mem(_manufacturer_data)

return advertisement_data, _manufacturer_id.value, manufacturer_data
return advertisement_data, manufacturer_data

@property
def services(self):
Expand Down

0 comments on commit f79e90c

Please sign in to comment.