gattlib-py: Added support for manufacturer data from GATT advertising

pull/277/head 0.7.1
Olivier Martin 2024-04-11 22:00:24 +02:00
parent 35566d198a
commit f79e90ce02
3 changed files with 43 additions and 26 deletions

View File

@ -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
@ -212,13 +222,13 @@ gattlib_get_rssi_from_mac.argtypes = [c_void_p, c_char_p, POINTER(c_int16)]
# 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

View File

@ -9,7 +9,7 @@ from uuid import UUID
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)
@ -238,18 +238,16 @@ class Adapter:
_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]
@ -264,15 +262,21 @@ class Adapter:
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

View File

@ -182,25 +182,22 @@ class Device:
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]
@ -215,18 +212,24 @@ class Device:
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):