mirror of https://github.com/labapart/gattlib
gattlib: Introduce helper function to select Eddystone devices
parent
50129fe753
commit
193c86590e
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# GattLib - GATT Library
|
||||
#
|
||||
# Copyright (C) 2016-2017 Olivier Martin <olivier@labapart.org>
|
||||
# Copyright (C) 2016-2019 Olivier Martin <olivier@labapart.org>
|
||||
#
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
@ -76,7 +76,8 @@ set(gattlib_SRCS gattlib_adapter.c
|
|||
gattlib_connect.c
|
||||
gattlib_discover.c
|
||||
gattlib_read_write.c
|
||||
${CMAKE_SOURCE_DIR}/common/gattlib_common.c)
|
||||
${CMAKE_SOURCE_DIR}/common/gattlib_common.c
|
||||
${CMAKE_SOURCE_DIR}/common/gattlib_eddystone.c)
|
||||
|
||||
# Added Glib support
|
||||
pkg_search_module(GLIB REQUIRED glib-2.0)
|
||||
|
|
|
@ -289,9 +289,49 @@ int gattlib_discover_desc_range(gatt_connection_t* connection, int start, int en
|
|||
*descriptors = descriptor_data.descriptors;
|
||||
*descriptor_count = descriptor_data.descriptors_count;
|
||||
|
||||
return 0;
|
||||
return GATTLIB_SUCCESS;
|
||||
}
|
||||
|
||||
int gattlib_discover_desc(gatt_connection_t* connection, gattlib_descriptor_t** descriptors, int* descriptor_count) {
|
||||
return gattlib_discover_desc_range(connection, 0x0001, 0xffff, descriptors, descriptor_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to retrieve Advertisement Data from a MAC Address
|
||||
*
|
||||
* @param adapter is the adapter the new device has been seen
|
||||
* @param mac_address is the MAC address of the device to get the RSSI
|
||||
* @param advertisement_data is an array of Service UUID and their respective data
|
||||
* @param advertisement_data_count is the number of elements in the advertisement_data array
|
||||
* @param manufacturer_id is the ID of the Manufacturer ID
|
||||
* @param manufacturer_data is the data following Manufacturer ID
|
||||
* @param manufacturer_data_size is the size of manufacturer_data
|
||||
*
|
||||
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
|
||||
*/
|
||||
int gattlib_get_advertisement_data(gatt_connection_t *connection,
|
||||
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
|
||||
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size)
|
||||
{
|
||||
return GATTLIB_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to retrieve Advertisement Data from a MAC Address
|
||||
*
|
||||
* @param adapter is the adapter the new device has been seen
|
||||
* @param mac_address is the MAC address of the device to get the RSSI
|
||||
* @param advertisement_data is an array of Service UUID and their respective data
|
||||
* @param advertisement_data_count is the number of elements in the advertisement_data array
|
||||
* @param manufacturer_id is the ID of the Manufacturer ID
|
||||
* @param manufacturer_data is the data following Manufacturer ID
|
||||
* @param manufacturer_data_size is the size of manufacturer_data
|
||||
*
|
||||
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
|
||||
*/
|
||||
int gattlib_get_advertisement_data_from_mac(void *adapter, const char *mac_address,
|
||||
gattlib_advertisement_data_t **advertisement_data, size_t *advertisement_data_count,
|
||||
uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size)
|
||||
{
|
||||
return GATTLIB_NOT_SUPPORTED;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "gattlib_internal.h"
|
||||
|
||||
#define EDDYSTONE_SERVICE_UUID "0000FEAA-0000-1000-8000-00805F9B34FB"
|
||||
|
||||
struct on_eddystone_discovered_device_arg {
|
||||
gattlib_discovered_device_with_data_t discovered_device_cb;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
static void on_eddystone_discovered_device(void *adapter, const char* addr, const char* name, void *user_data)
|
||||
{
|
||||
struct on_eddystone_discovered_device_arg *callback_data = user_data;
|
||||
gattlib_advertisement_data_t *advertisement_data;
|
||||
size_t advertisement_data_count;
|
||||
uint16_t manufacturer_id;
|
||||
uint8_t *manufacturer_data;
|
||||
size_t manufacturer_data_size;
|
||||
int ret;
|
||||
|
||||
ret = gattlib_get_advertisement_data_from_mac(adapter, addr,
|
||||
&advertisement_data, &advertisement_data_count,
|
||||
&manufacturer_id, &manufacturer_data, &manufacturer_data_size);
|
||||
if (ret != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback_data->discovered_device_cb(adapter, addr, name,
|
||||
advertisement_data, advertisement_data_count,
|
||||
manufacturer_id, manufacturer_data, manufacturer_data_size,
|
||||
callback_data->user_data);
|
||||
}
|
||||
|
||||
int gattlib_adapter_scan_eddystone(void *adapter, int16_t rssi_threshold, uint32_t eddsytone_types,
|
||||
gattlib_discovered_device_with_data_t discovered_device_cb, int timeout, void *user_data)
|
||||
{
|
||||
uuid_t eddystone_uuid;
|
||||
uint32_t enabled_filters = GATTLIB_DISCOVER_FILTER_USE_UUID;
|
||||
int ret;
|
||||
|
||||
ret = gattlib_string_to_uuid(EDDYSTONE_SERVICE_UUID, strlen(EDDYSTONE_SERVICE_UUID) + 1, &eddystone_uuid);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Fail to convert characteristic TX to UUID.\n");
|
||||
return GATTLIB_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
uuid_t *uuid_filter_list[] = { &eddystone_uuid, NULL };
|
||||
|
||||
if (eddsytone_types & GATTLIB_EDDYSTONE_LIMIT_RSSI) {
|
||||
enabled_filters |= GATTLIB_DISCOVER_FILTER_USE_RSSI;
|
||||
}
|
||||
|
||||
struct on_eddystone_discovered_device_arg callback_data = {
|
||||
.discovered_device_cb = discovered_device_cb,
|
||||
.user_data = user_data
|
||||
};
|
||||
|
||||
return gattlib_adapter_scan_enable_with_filter(adapter, uuid_filter_list, rssi_threshold, enabled_filters,
|
||||
on_eddystone_discovered_device, timeout, &callback_data);
|
||||
}
|
|
@ -87,6 +87,7 @@ set(gattlib_SRCS gattlib.c
|
|||
gattlib_stream.c
|
||||
bluez5/lib/uuid.c
|
||||
${CMAKE_SOURCE_DIR}/common/gattlib_common.c
|
||||
${CMAKE_SOURCE_DIR}/common/gattlib_eddystone.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/org-bluez-adaptater1.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/org-bluez-device1.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/org-bluez-gattcharacteristic1.c
|
||||
|
|
|
@ -52,6 +52,8 @@ int get_advertisement_data_from_device(OrgBluezDevice1 *bluez_device1,
|
|||
return GATTLIB_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*manufacturer_id = 0;
|
||||
*manufacturer_data_size = 0;
|
||||
manufacturer_data_variant = org_bluez_device1_get_manufacturer_data(bluez_device1);
|
||||
if (manufacturer_data_variant != NULL) {
|
||||
fprintf(stderr, "Warning: Manufacturer Data not supported: %s\n",
|
||||
|
@ -92,6 +94,8 @@ int get_advertisement_data_from_device(OrgBluezDevice1 *bluez_device1,
|
|||
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
*advertisement_data_count = 0;
|
||||
}
|
||||
|
||||
return GATTLIB_SUCCESS;
|
||||
|
|
|
@ -8,40 +8,30 @@ from gattlib import adapter
|
|||
parser = argparse.ArgumentParser(description='Gattlib Find Eddystone device example')
|
||||
args = parser.parse_args()
|
||||
|
||||
EDDYSTONE_COMMON_DATA_UUID = 'FEAA'
|
||||
|
||||
EDDYSTONE_URL_SCHEME_PREFIX = {
|
||||
0x00: "http://www.",
|
||||
0x01: "https://www.",
|
||||
0x02: "http://",
|
||||
0x03: "https://",
|
||||
}
|
||||
|
||||
# Use default adapter
|
||||
default_adapter = adapter.Adapter()
|
||||
|
||||
|
||||
def on_discovered_ble_device(device, user_data):
|
||||
def on_eddystone_device_found(device, advertisement_data, manufacturer_id, manufacturer_data, user_data):
|
||||
rssi = default_adapter.get_rssi_from_mac(device.id)
|
||||
print("Find Eddystone device %s (RSSI:%d)" % (device.id, rssi))
|
||||
|
||||
# Retrieve Advertisement Data
|
||||
advertisement_data, manufacturer_id, manufacturer_data = default_adapter.gattlib_get_advertisement_data_from_mac(device.id)
|
||||
|
||||
# Service Data
|
||||
service_data = advertisement_data[0xFEAA]
|
||||
if service_data[0] == 0x00:
|
||||
print("Eddystone UID: TX Power:0x%x NID:%s BID:%s" % (service_data[1], service_data[2:12], service_data[12:18]))
|
||||
elif service_data[0] == 0x10:
|
||||
print("Eddystone URL: TX Power:0x%x URL:%s%s" % (service_data[1], EDDYSTONE_URL_SCHEME_PREFIX[service_data[2]], service_data[3:].decode("utf-8")))
|
||||
elif service_data[0] == 0x20:
|
||||
eddystone_data = advertisement_data[adapter.EDDYSTONE_COMMON_DATA_UUID]
|
||||
if eddystone_data[0] == adapter.EDDYSTONE_TYPE_UID:
|
||||
print("Eddystone UID: TX Power:0x%x NID:%s BID:%s" % (eddystone_data[1], eddystone_data[2:12], eddystone_data[12:18]))
|
||||
elif eddystone_data[0] == adapter.EDDYSTONE_TYPE_URL:
|
||||
print("Eddystone URL: TX Power:0x%x URL:%s%s" % (eddystone_data[1], adapter.EDDYSTONE_URL_SCHEME_PREFIX[eddystone_data[2]], eddystone_data[3:].decode("utf-8")))
|
||||
elif eddystone_data[0] == adapter.EDDYSTONE_TYPE_TLM:
|
||||
print("Eddystone TLM")
|
||||
elif service_data[0] == 0x30:
|
||||
elif eddystone_data[0] == adapter.EDDYSTONE_TYPE_EID:
|
||||
print("Eddystone EID")
|
||||
else:
|
||||
print("Eddystone frame not supported: 0x%x" % service_data[0])
|
||||
print("Eddystone frame not supported: 0x%x" % eddystone_data[0])
|
||||
|
||||
|
||||
# Scan for 30 seconds
|
||||
default_adapter.open()
|
||||
default_adapter.scan_enable(on_discovered_ble_device, 30, uuids=[EDDYSTONE_COMMON_DATA_UUID])
|
||||
default_adapter.scan_eddystone_enable(on_eddystone_device_found,
|
||||
adapter.GATTLIB_EDDYSTONE_TYPE_UID | adapter.GATTLIB_EDDYSTONE_TYPE_URL | adapter.GATTLIB_EDDYSTONE_TYPE_TLM | adapter.GATTLIB_EDDYSTONE_TYPE_EID,
|
||||
30) # Look for 30 seconds
|
||||
|
|
|
@ -2,14 +2,32 @@
|
|||
|
||||
import argparse
|
||||
|
||||
from gattlib import device
|
||||
from gattlib import adapter, device
|
||||
|
||||
from environment_service import environment_service
|
||||
from sound_service import sound_service
|
||||
|
||||
# Use default adapter
|
||||
default_adapter = adapter.Adapter()
|
||||
|
||||
|
||||
def on_thingy_device_found(device, user_data):
|
||||
print("Found Nordic Thingy!")
|
||||
|
||||
# We pick-up the first device. Disable scanning
|
||||
default_adapter.scan_disable()
|
||||
|
||||
# Connect to the found device
|
||||
device.connect()
|
||||
device.discover()
|
||||
|
||||
args = user_data
|
||||
args.func(args, device)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Gattlib example for Nordic Thingy')
|
||||
parser.add_argument('mac', type=str, help='Mac Address of the GATT device to connect')
|
||||
parser.add_argument('--mac', type=str, help='Mac Address of the GATT device to connect')
|
||||
subparsers = parser.add_subparsers(help='sub-command help')
|
||||
|
||||
environment_parser = subparsers.add_parser('environment', help='Environment Command')
|
||||
|
@ -24,9 +42,18 @@ if __name__ == '__main__':
|
|||
if not hasattr(args, 'func'):
|
||||
raise RuntimeError("Please specify the command to launch: 'environment', 'sound'")
|
||||
|
||||
gatt_device = device.Device(adapter=None, addr=args.mac)
|
||||
gatt_device.connect()
|
||||
gatt_device.discover()
|
||||
if args.mac:
|
||||
gatt_device = device.Device(adapter=None, addr=mac)
|
||||
gatt_device.connect()
|
||||
gatt_device.discover()
|
||||
|
||||
# Launch the sub-command specific function
|
||||
args.func(args, gatt_device)
|
||||
# Launch the sub-command specific function
|
||||
args.func(args, gatt_device)
|
||||
else:
|
||||
default_adapter.open()
|
||||
|
||||
NORDIC_THINGY_CONFIGURATION_SERVICE = "EF680100-9B35-4933-9B10-52FFA9740042"
|
||||
|
||||
default_adapter.scan_enable(on_thingy_device_found, timeout=10,
|
||||
uuids=[NORDIC_THINGY_CONFIGURATION_SERVICE],
|
||||
user_data=args)
|
||||
|
|
|
@ -40,6 +40,10 @@ def play_sample(config_characteristic, speaker_characteristic):
|
|||
config_characteristic.write(sound_config)
|
||||
# Test speaker
|
||||
speaker_characteristic.write(b'\x03')
|
||||
|
||||
# Wait a bit before finishing
|
||||
time.sleep(1)
|
||||
|
||||
m_mainloop.quit()
|
||||
|
||||
|
||||
|
@ -85,6 +89,10 @@ def play_wav_file(config_characteristic, speaker_characteristic, wav_filepath):
|
|||
|
||||
stream.close()
|
||||
print("All WAV file has been sent")
|
||||
|
||||
# Wait a bit before finishing
|
||||
time.sleep(1)
|
||||
|
||||
m_mainloop.quit()
|
||||
|
||||
|
||||
|
|
|
@ -66,12 +66,25 @@ gattlib_adapter_open = gattlib.gattlib_adapter_open
|
|||
gattlib_adapter_open.argtypes = [c_char_p, POINTER(c_void_p)]
|
||||
|
||||
# typedef void (*gattlib_discovered_device_t)(void *adapter, const char* addr, const char* name, void *user_data)
|
||||
gattlib_discovered_device_type = CFUNCTYPE(None, c_void_p, c_char_p, c_char_p, c_void_p)
|
||||
gattlib_discovered_device_type = CFUNCTYPE(None, c_void_p, c_char_p, c_char_p, py_object)
|
||||
|
||||
# typedef void (*gattlib_discovered_device_with_data_t)(void *adapter, const char* addr, const char* name,
|
||||
# gattlib_advertisement_data_t *advertisement_data, size_t advertisement_data_count,
|
||||
# uint16_t manufacturer_id, uint8_t *manufacturer_data, size_t manufacturer_data_size,
|
||||
# void *user_data);
|
||||
gattlib_discovered_device_with_data_type = CFUNCTYPE(None, c_void_p, c_char_p, c_char_p,
|
||||
POINTER(GattlibAdvertisementData), c_size_t, c_uint16, c_void_p, c_size_t,
|
||||
py_object)
|
||||
|
||||
# int gattlib_adapter_scan_enable_with_filter(void *adapter, uuid_t **uuid_list, int16_t rssi_threshold, uint32_t enabled_filters,
|
||||
# gattlib_discovered_device_t discovered_device_cb, int timeout, void *user_data)
|
||||
gattlib_adapter_scan_enable_with_filter = gattlib.gattlib_adapter_scan_enable_with_filter
|
||||
gattlib_adapter_scan_enable_with_filter.argtypes = [c_void_p, POINTER(POINTER(GattlibUuid)), c_int16, c_uint32, gattlib_discovered_device_type, c_int, c_void_p]
|
||||
gattlib_adapter_scan_enable_with_filter.argtypes = [c_void_p, POINTER(POINTER(GattlibUuid)), c_int16, c_uint32, gattlib_discovered_device_type, c_int, py_object]
|
||||
|
||||
# int gattlib_adapter_scan_eddystone(void *adapter, int16_t rssi_threshold, uint32_t eddsytone_types,
|
||||
# gattlib_discovered_device_with_data_t discovered_device_cb, int timeout, void *user_data)
|
||||
gattlib_adapter_scan_eddystone = gattlib.gattlib_adapter_scan_eddystone
|
||||
gattlib_adapter_scan_eddystone.argtypes = [c_void_p, c_int16, c_uint32, gattlib_discovered_device_with_data_type, c_int, py_object]
|
||||
|
||||
# int gattlib_discover_primary(gatt_connection_t* connection, gattlib_primary_service_t** services, int* services_count);
|
||||
gattlib_discover_primary = gattlib.gattlib_discover_primary
|
||||
|
|
|
@ -1,17 +1,38 @@
|
|||
from gattlib import *
|
||||
from .device import Device
|
||||
from .exception import handle_return
|
||||
from .exception import handle_return, AdapterNotOpened
|
||||
from .uuid import gattlib_uuid_to_int
|
||||
|
||||
GATTLIB_DISCOVER_FILTER_USE_UUID = (1 << 0)
|
||||
GATTLIB_DISCOVER_FILTER_USE_RSSI = (1 << 1)
|
||||
|
||||
GATTLIB_EDDYSTONE_TYPE_UID = (1 << 0)
|
||||
GATTLIB_EDDYSTONE_TYPE_URL = (1 << 1)
|
||||
GATTLIB_EDDYSTONE_TYPE_TLM = (1 << 2)
|
||||
GATTLIB_EDDYSTONE_TYPE_EID = (1 << 3)
|
||||
GATTLIB_EDDYSTONE_LIMIT_RSSI = (1 << 4)
|
||||
|
||||
EDDYSTONE_TYPE_UID = 0x00
|
||||
EDDYSTONE_TYPE_URL = 0x10
|
||||
EDDYSTONE_TYPE_TLM = 0x20
|
||||
EDDYSTONE_TYPE_EID = 0x30
|
||||
|
||||
EDDYSTONE_COMMON_DATA_UUID = 0xFEAA
|
||||
|
||||
EDDYSTONE_URL_SCHEME_PREFIX = {
|
||||
0x00: "http://www.",
|
||||
0x01: "https://www.",
|
||||
0x02: "http://",
|
||||
0x03: "https://",
|
||||
}
|
||||
|
||||
|
||||
class Adapter:
|
||||
|
||||
def __init__(self, name=c_char_p(None)):
|
||||
self._name = name
|
||||
self._adapter = c_void_p(None)
|
||||
self._is_opened = False # Note: 'self._adapter != c_void_p(None)' does not seem to return the expected result
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -23,10 +44,15 @@ class Adapter:
|
|||
return []
|
||||
|
||||
def open(self):
|
||||
return gattlib_adapter_open(self._name, byref(self._adapter))
|
||||
ret = gattlib_adapter_open(self._name, byref(self._adapter))
|
||||
if ret == 0:
|
||||
self._is_opened = True
|
||||
return ret
|
||||
|
||||
def close(self):
|
||||
return gattlib.gattlib_adapter_close(self._adapter)
|
||||
ret = gattlib.gattlib_adapter_close(self._adapter)
|
||||
self._is_opened = False
|
||||
return ret
|
||||
|
||||
def on_discovered_device(self, adapter, addr, name, user_data):
|
||||
device = Device(self, addr, name)
|
||||
|
@ -36,6 +62,9 @@ class Adapter:
|
|||
assert on_discovered_device_callback != None
|
||||
self.on_discovered_device_callback = on_discovered_device_callback
|
||||
|
||||
if not self._is_opened:
|
||||
raise AdapterNotOpened()
|
||||
|
||||
enabled_filters = 0
|
||||
uuid_list = None
|
||||
rssi = 0
|
||||
|
@ -66,6 +95,58 @@ class Adapter:
|
|||
timeout, user_data)
|
||||
handle_return(ret)
|
||||
|
||||
@staticmethod
|
||||
def on_discovered_ble_device_with_details(adapter, mac_addr, name, advertisement_data_buffer, advertisement_data_count,
|
||||
manufacturer_id, manufacturer_data_buffer, manufacturer_data_size,
|
||||
user_data):
|
||||
advertisement_data = {}
|
||||
manufacturer_data = None
|
||||
|
||||
for i in range(0, advertisement_data_count):
|
||||
service_data = advertisement_data_buffer[i]
|
||||
uuid = gattlib_uuid_to_int(service_data.uuid)
|
||||
|
||||
pointer_type = POINTER(c_byte * service_data.data_length)
|
||||
c_bytearray = cast(service_data.data, pointer_type)
|
||||
|
||||
data = bytearray(service_data.data_length)
|
||||
for i in range(service_data.data_length):
|
||||
data[i] = c_bytearray.contents[i] & 0xFF
|
||||
|
||||
advertisement_data[uuid] = data
|
||||
|
||||
if manufacturer_data_size > 0:
|
||||
pointer_type = POINTER(c_byte * manufacturer_data_size)
|
||||
c_bytearray = cast(manufacturer_data_buffer, pointer_type)
|
||||
|
||||
manufacturer_data = bytearray(manufacturer_data_size)
|
||||
for i in range(manufacturer_data_size):
|
||||
manufacturer_data[i] = c_bytearray.contents[i] & 0xFF
|
||||
|
||||
device = Device(user_data["adapter"], mac_addr, name)
|
||||
user_data["callback"](device, advertisement_data, manufacturer_id, manufacturer_data, user_data["user_data"])
|
||||
|
||||
def scan_eddystone_enable(self, on_discovered_device_callback, eddystone_filters, timeout, rssi_threshold=None, user_data=None):
|
||||
if not self._is_opened:
|
||||
raise AdapterNotOpened()
|
||||
|
||||
rssi = 0
|
||||
|
||||
if rssi_threshold is not None:
|
||||
eddystone_filters |= GATTLIB_EDDYSTONE_LIMIT_RSSI
|
||||
rssi = int(rssi_threshold)
|
||||
|
||||
args = {
|
||||
"adapter": self,
|
||||
"callback": on_discovered_device_callback,
|
||||
"user_data": user_data
|
||||
}
|
||||
|
||||
ret = gattlib_adapter_scan_eddystone(self._adapter, rssi, eddystone_filters,
|
||||
gattlib_discovered_device_with_data_type(Adapter.on_discovered_ble_device_with_details),
|
||||
timeout, args)
|
||||
handle_return(ret)
|
||||
|
||||
def scan_disable(self):
|
||||
ret = gattlib.gattlib_adapter_scan_disable(self._adapter)
|
||||
handle_return(ret)
|
||||
|
|
|
@ -1,32 +1,44 @@
|
|||
GATTLIB_SUCCESS = 0
|
||||
GATTLIB_INVALID_PARAMETER = 1
|
||||
GATTLIB_NOT_FOUND = 2
|
||||
GATTLIB_OUT_OF_MEMORY = 3
|
||||
GATTLIB_NOT_SUPPORTED = 4
|
||||
GATTLIB_DEVICE_ERROR = 5
|
||||
GATTLIB_ERROR_DBUS = 6
|
||||
GATTLIB_SUCCESS = 0
|
||||
GATTLIB_INVALID_PARAMETER = 1
|
||||
GATTLIB_NOT_FOUND = 2
|
||||
GATTLIB_OUT_OF_MEMORY = 3
|
||||
GATTLIB_NOT_SUPPORTED = 4
|
||||
GATTLIB_DEVICE_ERROR = 5
|
||||
GATTLIB_ERROR_DBUS = 6
|
||||
|
||||
|
||||
class GattlibException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class AdapterNotOpened(GattlibException):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidParameter(GattlibException):
|
||||
pass
|
||||
|
||||
|
||||
class NotFound(GattlibException):
|
||||
pass
|
||||
|
||||
|
||||
class OutOfMemory(GattlibException):
|
||||
pass
|
||||
|
||||
|
||||
class NotSupported(GattlibException):
|
||||
pass
|
||||
|
||||
|
||||
class DeviceError(GattlibException):
|
||||
pass
|
||||
|
||||
|
||||
class DBusError(GattlibException):
|
||||
pass
|
||||
|
||||
|
||||
def handle_return(ret):
|
||||
if ret == GATTLIB_INVALID_PARAMETER:
|
||||
raise InvalidParameter()
|
||||
|
|
|
@ -56,6 +56,8 @@ extern "C" {
|
|||
#define GATTLIB_NOT_SUPPORTED 4
|
||||
#define GATTLIB_DEVICE_ERROR 5
|
||||
#define GATTLIB_ERROR_DBUS 6
|
||||
#define GATTLIB_ERROR_BLUEZ 7
|
||||
#define GATTLIB_ERROR_INTERNAL 8
|
||||
|
||||
/* GATT Characteristic Properties Bitfield values */
|
||||
#define GATTLIB_CHARACTERISTIC_BROADCAST 0x01
|
||||
|
@ -93,9 +95,21 @@ extern "C" {
|
|||
#define GATTLIB_DISCOVER_FILTER_USE_UUID (1 << 0)
|
||||
#define GATTLIB_DISCOVER_FILTER_USE_RSSI (1 << 1)
|
||||
|
||||
#define GATTLIB_EDDYSTONE_TYPE_UID (1 << 0)
|
||||
#define GATTLIB_EDDYSTONE_TYPE_URL (1 << 1)
|
||||
#define GATTLIB_EDDYSTONE_TYPE_TLM (1 << 2)
|
||||
#define GATTLIB_EDDYSTONE_TYPE_EID (1 << 3)
|
||||
#define GATTLIB_EDDYSTONE_LIMIT_RSSI (1 << 4)
|
||||
|
||||
typedef struct _gatt_connection_t gatt_connection_t;
|
||||
typedef struct _gatt_stream_t gatt_stream_t;
|
||||
|
||||
typedef struct {
|
||||
uuid_t uuid;
|
||||
uint8_t* data;
|
||||
size_t data_length;
|
||||
} gattlib_advertisement_data_t;
|
||||
|
||||
typedef void (*gattlib_event_handler_t)(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data);
|
||||
|
||||
/**
|
||||
|
@ -116,6 +130,24 @@ typedef void (*gattlib_disconnection_handler_t)(void* user_data);
|
|||
*/
|
||||
typedef void (*gattlib_discovered_device_t)(void *adapter, const char* addr, const char* name, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Handler called on new discovered BLE device
|
||||
*
|
||||
* @param adapter is the adapter that has found the BLE device
|
||||
* @param addr is the MAC address of the BLE device
|
||||
* @param name is the name of BLE device if advertised
|
||||
* @param advertisement_data is an array of Service UUID and their respective data
|
||||
* @param advertisement_data_count is the number of elements in the advertisement_data array
|
||||
* @param manufacturer_id is the ID of the Manufacturer ID
|
||||
* @param manufacturer_data is the data following Manufacturer ID
|
||||
* @param manufacturer_data_size is the size of manufacturer_data
|
||||
* @param user_data Data defined when calling `gattlib_register_on_disconnect()`
|
||||
*/
|
||||
typedef void (*gattlib_discovered_device_with_data_t)(void *adapter, const char* addr, const char* name,
|
||||
gattlib_advertisement_data_t *advertisement_data, size_t advertisement_data_count,
|
||||
uint16_t manufacturer_id, uint8_t *manufacturer_data, size_t manufacturer_data_size,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Handler called on asynchronous connection when connection is ready
|
||||
*
|
||||
|
@ -173,6 +205,23 @@ int gattlib_adapter_scan_enable(void* adapter, gattlib_discovered_device_t disco
|
|||
int gattlib_adapter_scan_enable_with_filter(void *adapter, uuid_t **uuid_list, int16_t rssi_threshold, uint32_t enabled_filters,
|
||||
gattlib_discovered_device_t discovered_device_cb, int timeout, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Enable Eddystone Bluetooth Device scanning on a given adapter
|
||||
*
|
||||
* @param adapter is the context of the newly opened adapter
|
||||
* @param rssi_threshold is the imposed RSSI threshold for the returned devices.
|
||||
* @param eddystone_types defines the type(s) of Eddystone advertisement data type to select.
|
||||
* The types are defined by the macros `GATTLIB_EDDYSTONE_TYPE_*`. The macro `GATTLIB_EDDYSTONE_LIMIT_RSSI`
|
||||
* can also be used to limit RSSI with rssi_threshold.
|
||||
* @param discovered_device_cb is the function callback called for each new Bluetooth device discovered
|
||||
* @param timeout defines the duration of the Bluetooth scanning
|
||||
* @param user_data is the data passed to the callback `discovered_device_cb()`
|
||||
*
|
||||
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
|
||||
*/
|
||||
int gattlib_adapter_scan_eddystone(void *adapter, int16_t rssi_threshold, uint32_t eddsytone_types,
|
||||
gattlib_discovered_device_with_data_t discovered_device_cb, int timeout, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Disable Bluetooth scanning on a given adapter
|
||||
*
|
||||
|
@ -252,12 +301,6 @@ typedef struct {
|
|||
uuid_t uuid;
|
||||
} gattlib_descriptor_t;
|
||||
|
||||
typedef struct {
|
||||
uuid_t uuid;
|
||||
uint8_t* data;
|
||||
size_t data_length;
|
||||
} gattlib_advertisement_data_t;
|
||||
|
||||
/**
|
||||
* @brief Function to discover GATT Services
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue