diff --git a/bluez/gattlib_connect.c b/bluez/gattlib_connect.c index e7b5314..f828695 100644 --- a/bluez/gattlib_connect.c +++ b/bluez/gattlib_connect.c @@ -554,6 +554,11 @@ int gattlib_get_rssi(gatt_connection_t *connection, int16_t *rssi) return GATTLIB_NOT_SUPPORTED; } +int gattlib_get_rssi_from_mac(void *adapter, const char *mac_address, int16_t *rssi) +{ + return GATTLIB_NOT_SUPPORTED; +} + int gattlib_get_advertisement_data(gatt_connection_t *connection, gattlib_advertisement_data_t **advertisement_data, uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) { diff --git a/dbus/gattlib.c b/dbus/gattlib.c index 8491a1d..70dfbbe 100644 --- a/dbus/gattlib.c +++ b/dbus/gattlib.c @@ -93,7 +93,28 @@ gboolean on_handle_device_property_change( return TRUE; } -static void get_object_path_from_mac(const char *adapter_name, const char *mac_address, char *object_path, size_t object_path_len) +void get_device_path_from_mac_with_adapter(OrgBluezAdapter1* adapter, const char *mac_address, char *object_path, size_t object_path_len) +{ + char device_address_str[20 + 1]; + const char* adapter_path = g_dbus_proxy_get_object_path((GDBusProxy *)ORG_BLUEZ_ADAPTER1_PROXY(adapter)); + + // Transform string from 'DA:94:40:95:E0:87' to 'dev_DA_94_40_95_E0_87' + strncpy(device_address_str, mac_address, sizeof(device_address_str)); + for (int i = 0; i < strlen(device_address_str); i++) { + if (device_address_str[i] == ':') { + device_address_str[i] = '_'; + } + } + + // Force a null-terminated character + device_address_str[20] = '\0'; + + // Generate object path like: /org/bluez/hci0/dev_DA_94_40_95_E0_87 + snprintf(object_path, object_path_len, "%s/dev_%s", adapter_path, device_address_str); +} + + +void get_device_path_from_mac(const char *adapter_name, const char *mac_address, char *object_path, size_t object_path_len) { char device_address_str[20 + 1]; const char* adapter; @@ -132,7 +153,7 @@ gatt_connection_t *gattlib_connect(const char *src, const char *dst, unsigned lo GError *error = NULL; char object_path[100]; - get_object_path_from_mac(src, dst, object_path, sizeof(object_path)); + get_device_path_from_mac(src, dst, object_path, sizeof(object_path)); gattlib_context_t* conn_context = calloc(sizeof(gattlib_context_t), 1); if (conn_context == NULL) { @@ -1344,7 +1365,8 @@ int gattlib_notification_stop(gatt_connection_t* connection, const uuid_t* uuid) } } -int gattlib_get_rssi(gatt_connection_t *connection, int16_t *rssi) { +int gattlib_get_rssi(gatt_connection_t *connection, int16_t *rssi) +{ gattlib_context_t* conn_context = connection->context; if (rssi == NULL) { @@ -1356,6 +1378,39 @@ int gattlib_get_rssi(gatt_connection_t *connection, int16_t *rssi) { return GATTLIB_SUCCESS; } +int gattlib_get_rssi_from_mac(void *adapter, const char *mac_address, int16_t *rssi) +{ + GError *error = NULL; + char object_path[100]; + + if (rssi == NULL) { + return GATTLIB_INVALID_PARAMETER; + } + + if (adapter != NULL) { + get_device_path_from_mac_with_adapter((OrgBluezAdapter1*)adapter, mac_address, object_path, sizeof(object_path)); + } else { + get_device_path_from_mac(NULL, mac_address, object_path, sizeof(object_path)); + } + + OrgBluezDevice1* bluez_device1 = org_bluez_device1_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, + G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, + "org.bluez", + object_path, + NULL, + &error); + if (error) { + fprintf(stderr, "Failed to connection to new DBus Bluez Device: %s\n", + error->message); + g_error_free(error); + return GATTLIB_ERROR_DBUS; + } + + *rssi = org_bluez_device1_get_rssi(bluez_device1); + return GATTLIB_SUCCESS; +} + int gattlib_get_advertisement_data(gatt_connection_t *connection, gattlib_advertisement_data_t **advertisement_data, uint16_t *manufacturer_id, uint8_t **manufacturer_data, size_t *manufacturer_data_size) { diff --git a/dbus/gattlib_internal.h b/dbus/gattlib_internal.h index 81da9b7..2fcc249 100644 --- a/dbus/gattlib_internal.h +++ b/dbus/gattlib_internal.h @@ -55,4 +55,7 @@ typedef struct { gboolean stop_scan_func(gpointer data); +void get_device_path_from_mac_with_adapter(OrgBluezAdapter1* adapter, const char *mac_address, char *object_path, size_t object_path_len); +void get_device_path_from_mac(const char *adapter_name, const char *mac_address, char *object_path, size_t object_path_len); + #endif diff --git a/gattlib-py/examples/find_eddystone/find_eddystone.py b/gattlib-py/examples/find_eddystone/find_eddystone.py index 81533c7..3490bd8 100755 --- a/gattlib-py/examples/find_eddystone/find_eddystone.py +++ b/gattlib-py/examples/find_eddystone/find_eddystone.py @@ -10,14 +10,15 @@ args = parser.parse_args() EDDYSTONE_COMMON_DATA_UUID = 'FEAA' - -def on_discovered_ble_device(device): - print("Find Eddystone device %s" % device.id) - - # Use default adapter default_adapter = adapter.Adapter() + +def on_discovered_ble_device(device, user_data): + rssi = default_adapter.get_rssi_from_mac(device.id) + print("Find Eddystone device %s (RSSI:%d)" % (device.id, rssi)) + + # Scan for 30 seconds default_adapter.open() default_adapter.scan_enable(on_discovered_ble_device, 30, uuids=[EDDYSTONE_COMMON_DATA_UUID]) diff --git a/gattlib-py/gattlib/__init__.py b/gattlib-py/gattlib/__init__.py index e775f29..0f505b9 100644 --- a/gattlib-py/gattlib/__init__.py +++ b/gattlib-py/gattlib/__init__.py @@ -97,3 +97,7 @@ gattlib_register_on_disconnect.argtypes = [c_void_p, py_object, py_object] # int gattlib_get_rssi(gatt_connection_t *connection, int16_t *rssi) gattlib_get_rssi = gattlib.gattlib_get_rssi gattlib_get_rssi.argtypes = [c_void_p, POINTER(c_int16)] + +# int gattlib_get_rssi_from_mac(void *adapter, const char *mac_address, int16_t *rssi) +gattlib_get_rssi_from_mac = gattlib.gattlib_get_rssi_from_mac +gattlib_get_rssi_from_mac.argtypes = [c_void_p, c_char_p, POINTER(c_int16)] diff --git a/gattlib-py/gattlib/adapter.py b/gattlib-py/gattlib/adapter.py index 5c97893..8a1ea0a 100644 --- a/gattlib-py/gattlib/adapter.py +++ b/gattlib-py/gattlib/adapter.py @@ -67,3 +67,11 @@ class Adapter: def scan_disable(self): ret = gattlib.gattlib_adapter_scan_disable(self._adapter) handle_return(ret) + + def get_rssi_from_mac(self, mac_address): + if isinstance(mac_address, str): + mac_address = mac_address.encode("utf-8") + + rssi = c_int16(0) + gattlib_get_rssi_from_mac(self._adapter, mac_address, byref(rssi)) + return rssi.value diff --git a/include/gattlib.h b/include/gattlib.h index 3afa6e3..94e825e 100644 --- a/include/gattlib.h +++ b/include/gattlib.h @@ -350,6 +350,20 @@ void gattlib_register_indication(gatt_connection_t* connection, gattlib_event_ha */ int gattlib_get_rssi(gatt_connection_t *connection, int16_t *rssi); +/** + * @brief Function to retrieve RSSI from a MAC Address + * + * @note: This function is mainly used before a connection is established. Once the connection + * established, the function `gattlib_get_rssi()` should be preferred. + * + * @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 rssi is the Received Signal Strength Indicator of the remote device + * + * @return GATTLIB_SUCCESS on success or GATTLIB_* error code + */ +int gattlib_get_rssi_from_mac(void *adapter, const char *mac_address, int16_t *rssi); + /** * @brief Function to retrieve Advertisement Data of the GATT connection *