diff options
author | Sven Gothel <[email protected]> | 2020-06-25 00:30:09 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-06-25 00:30:09 +0200 |
commit | a1a31f0b59b9896a04973846bfad2aa0bc9e8d1f (patch) | |
tree | 782d40db1b54693d32d07d841a8cca4a3bb08573 | |
parent | 8693aa160c4c4f7b72c34c99e7550a224a856644 (diff) |
GATTHandler/DBTDevice (incl Java): Add ping[GATT](), testing device availability via retrieval of GATT info
Issues a ping to the device, validating whether it is still reachable.
This method could be periodically utilized to shorten the underlying OS disconnect period
after turning the device off, which lies within 7-13s.
In case the device is no more reachable, disconnect will be initiated due to the occurring IO error.
+++
Implementation attempts to read the mandatory APPEARANCE CharacteristicValue
of the mandatory GENERIC_ACCESS service.
-rw-r--r-- | api/direct_bt/DBTDevice.hpp | 17 | ||||
-rw-r--r-- | api/direct_bt/GATTHandler.hpp | 13 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTDevice.java | 14 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTDevice.cxx | 13 | ||||
-rw-r--r-- | java/org/tinyb/BluetoothDevice.java | 15 | ||||
-rw-r--r-- | java/tinyb/dbus/DBusDevice.java | 3 | ||||
-rw-r--r-- | src/direct_bt/DBTDevice.cpp | 19 | ||||
-rw-r--r-- | src/direct_bt/GATTHandler.cpp | 21 |
8 files changed, 115 insertions, 0 deletions
diff --git a/api/direct_bt/DBTDevice.hpp b/api/direct_bt/DBTDevice.hpp index 6c8097d1..e01ecaab 100644 --- a/api/direct_bt/DBTDevice.hpp +++ b/api/direct_bt/DBTDevice.hpp @@ -326,6 +326,23 @@ namespace direct_bt { std::shared_ptr<GenericAccess> getGATTGenericAccess(); /** + * Issues a GATT ping to the device, validating whether it is still reachable. + * <p> + * This method could be periodically utilized to shorten the underlying OS disconnect period + * after turning the device off, which lies within 7-13s. + * </p> + * <p> + * In case the device is no more reachable, the GATTHandler will initiate disconnect due to the occurring IO error. + * will issue a disconnect. + * </p> + * <p> + * See {@link #getGATTServices()} regarding GATT initialization. + * </p> + * @return {@code true} if successful, otherwise false in case no GATT services exists etc. + */ + bool pingGATT(); + + /** * Explicit disconnecting an open GATTHandler, which is usually performed via disconnect() * <p> * Implementation will also discard the GATTHandler reference. diff --git a/api/direct_bt/GATTHandler.hpp b/api/direct_bt/GATTHandler.hpp index 253077d0..92a79c38 100644 --- a/api/direct_bt/GATTHandler.hpp +++ b/api/direct_bt/GATTHandler.hpp @@ -374,6 +374,19 @@ namespace direct_bt { std::shared_ptr<DeviceInformation> getDeviceInformation(std::vector<GATTServiceRef> & primServices); std::shared_ptr<DeviceInformation> getDeviceInformation(std::vector<GATTCharacteristicRef> & deviceInfoCharDeclList); + + /** + * Issues a ping to the device, validating whether it is still reachable. + * <p> + * This method could be periodically utilized to shorten the underlying OS disconnect period + * after turning the device off, which lies within 7-13s. + * </p> + * <p> + * In case the device is no more reachable, disconnect will be initiated due to the occurring IO error. + * </p> + * @return {@code true} if successful, otherwise false in case no GATT services exists etc. + */ + bool ping(); }; } // namespace direct_bt diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java index e2390a51..6c1b6342 100644 --- a/java/direct_bt/tinyb/DBTDevice.java +++ b/java/direct_bt/tinyb/DBTDevice.java @@ -521,6 +521,20 @@ public class DBTDevice extends DBTObject implements BluetoothDevice } private native List<BluetoothGattService> getServicesImpl(); + @Override + public boolean pingGATT() { + try { + return pingGATTImpl(); + } catch (final Throwable t) { + if(DEBUG) { + System.err.println("Caught "+t.getMessage()+" on thread "+Thread.currentThread().toString()); + t.printStackTrace(); + } + } + return false; + } + private native boolean pingGATTImpl(); + /* property accessors: */ @Override diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx index 465aa87d..958fdba2 100644 --- a/java/jni/direct_bt/DBTDevice.cxx +++ b/java/jni/direct_bt/DBTDevice.cxx @@ -378,6 +378,19 @@ jobject Java_direct_1bt_tinyb_DBTDevice_getServicesImpl(JNIEnv *env, jobject obj return nullptr; } +jboolean Java_direct_1bt_tinyb_DBTDevice_pingGATTImpl(JNIEnv *env, jobject obj) +{ + try { + DBTDevice *device = getInstance<DBTDevice>(env, obj); + JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE); + + return device->pingGATT() ? JNI_TRUE : JNI_FALSE; + } catch(...) { + rethrow_and_raise_java_exception(env); + } + return JNI_FALSE; +} + jstring Java_direct_1bt_tinyb_DBTDevice_getIcon(JNIEnv *env, jobject obj) { try { diff --git a/java/org/tinyb/BluetoothDevice.java b/java/org/tinyb/BluetoothDevice.java index c8035001..d693eb6b 100644 --- a/java/org/tinyb/BluetoothDevice.java +++ b/java/org/tinyb/BluetoothDevice.java @@ -140,6 +140,21 @@ public interface BluetoothDevice extends BluetoothObject List<BluetoothGattService> getServices(); /** + * Issues a GATT ping to the device, validating whether it is still reachable. + * <p> + * This method could be periodically utilized to shorten the underlying OS disconnect period + * after turning the device off, which lies within 7-13s. + * </p> + * <p> + * In case the device is no more reachable, disconnect will be initiated due to the occurring IO error. + * </p> + * + * @return {@code true} if successful, otherwise false in case no GATT services exists etc. + * @since 2.0.0 + */ + boolean pingGATT(); + + /** * Returns the timestamp in monotonic milliseconds when this device instance has been created, * either via its initial discovery or its initial direct connection. * diff --git a/java/tinyb/dbus/DBusDevice.java b/java/tinyb/dbus/DBusDevice.java index 9e523dd8..09524836 100644 --- a/java/tinyb/dbus/DBusDevice.java +++ b/java/tinyb/dbus/DBusDevice.java @@ -105,6 +105,9 @@ public class DBusDevice extends DBusObject implements BluetoothDevice @Override public native List<BluetoothGattService> getServices(); + @Override + public boolean pingGATT() { return false; } // FIXME + /* D-Bus property accessors: */ @Override diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp index e5d32a1e..45a7c52c 100644 --- a/src/direct_bt/DBTDevice.cpp +++ b/src/direct_bt/DBTDevice.cpp @@ -490,6 +490,25 @@ std::vector<std::shared_ptr<GATTService>> DBTDevice::getGATTServices() { return gattServices; } +bool DBTDevice::pingGATT() { + const std::lock_guard<std::recursive_mutex> lock(mtx_gatt); // RAII-style acquire and relinquish via destructor + if( nullptr == gattHandler || !gattHandler->isOpen() ) { + connectGATT(); + if( nullptr == gattHandler || !gattHandler->isOpen() ) { + ERR_PRINT("DBTDevice::getServices: connectGATT failed"); + return std::vector<std::shared_ptr<GATTService>>(); + } + } + std::vector<std::shared_ptr<GATTService>> & gattServices = gattHandler->getServices(); // reference of the GATTHandler's list + if( gattServices.size() == 0 ) { // discover services + gattServices = gattHandler->discoverCompletePrimaryServices(); // same reference of the GATTHandler's list + if( gattServices.size() == 0 ) { // nothing discovered + return false; + } + } + return gattHandler->ping(); +} + std::shared_ptr<GenericAccess> DBTDevice::getGATTGenericAccess() { const std::lock_guard<std::recursive_mutex> lock(mtx_gatt); // RAII-style acquire and relinquish via destructor return gattGenericAccess; diff --git a/src/direct_bt/GATTHandler.cpp b/src/direct_bt/GATTHandler.cpp index e744f936..0a5ee71b 100644 --- a/src/direct_bt/GATTHandler.cpp +++ b/src/direct_bt/GATTHandler.cpp @@ -899,6 +899,27 @@ std::shared_ptr<GenericAccess> GATTHandler::getGenericAccess(std::vector<GATTSer return res; } +bool GATTHandler::ping() { + std::shared_ptr<GenericAccess> res = nullptr; + for(size_t i=0; i<services.size() && nullptr == res; i++) { + std::vector<GATTCharacteristicRef> & genericAccessCharDeclList = services.at(i)->characteristicList; + POctets value(32, 0); + + for(size_t i=0; i<genericAccessCharDeclList.size(); i++) { + const GATTCharacteristic & charDecl = *genericAccessCharDeclList.at(i); + if( _GENERIC_ACCESS != *charDecl.service->type ) { + continue; + } + if( _APPEARANCE == *charDecl.value_type ) { + if( readCharacteristicValue(charDecl, value.resize(0)) ) { + return true; + } + } + } + } + return false; +} + std::shared_ptr<DeviceInformation> GATTHandler::getDeviceInformation(std::vector<GATTCharacteristicRef> & characteristicDeclList) { std::shared_ptr<DeviceInformation> res = nullptr; POctets value(number(Defaults::MAX_ATT_MTU), 0); |