diff options
-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); |