2121# include " NimBLEClient.h"
2222# include " NimBLERemoteService.h"
2323# include " NimBLERemoteCharacteristic.h"
24+ # include " NimBLERemoteGattUtils.h"
2425# include " NimBLEDevice.h"
2526# include " NimBLELog.h"
2627
@@ -101,8 +102,8 @@ NimBLEClient::~NimBLEClient() {
101102 */
102103void NimBLEClient::deleteServices () {
103104 // Delete all the services.
104- for (auto & it : m_svcVec) {
105- delete it ;
105+ for (auto & svc : m_svcVec) {
106+ delete svc ;
106107 }
107108
108109 std::vector<NimBLERemoteService*>().swap (m_svcVec);
@@ -243,8 +244,7 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
243244 break ;
244245
245246 default :
246- NIMBLE_LOGE (LOG_TAG,
247- " Failed to connect to %s, rc=%d; %s" ,
247+ NIMBLE_LOGE (LOG_TAG, " Failed to connect to %s, rc=%d; %s" ,
248248 std::string (m_peerAddress).c_str (),
249249 rc,
250250 NimBLEUtils::returnCodeToString (rc));
@@ -631,48 +631,15 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) {
631631 */
632632NimBLERemoteService* NimBLEClient::getService (const NimBLEUUID& uuid) {
633633 NIMBLE_LOGD (LOG_TAG, " >> getService: uuid: %s" , uuid.toString ().c_str ());
634+ NimBLERemoteService *pSvc = nullptr ;
634635
635- for (auto & it : m_svcVec) {
636- if (it->getUUID () == uuid) {
637- NIMBLE_LOGD (LOG_TAG, " << getService: found the service with uuid: %s" , uuid.toString ().c_str ());
638- return it;
639- }
640- }
641-
642- size_t prevSize = m_svcVec.size ();
643- if (retrieveServices (&uuid)) {
644- if (m_svcVec.size () > prevSize) {
645- return m_svcVec.back ();
646- }
647-
648- // If the request was successful but 16/32 bit uuid not found
649- // try again with the 128 bit uuid.
650- if (uuid.bitSize () == BLE_UUID_TYPE_16 || uuid.bitSize () == BLE_UUID_TYPE_32) {
651- NimBLEUUID uuid128 (uuid);
652- uuid128.to128 ();
653- if (retrieveServices (&uuid128)) {
654- if (m_svcVec.size () > prevSize) {
655- return m_svcVec.back ();
656- }
657- }
658- } else {
659- // If the request was successful but the 128 bit uuid not found
660- // try again with the 16 bit uuid.
661- NimBLEUUID uuid16 (uuid);
662- uuid16.to16 ();
663- // if the uuid was 128 bit but not of the BLE base type this check will fail
664- if (uuid16.bitSize () == BLE_UUID_TYPE_16) {
665- if (retrieveServices (&uuid16)) {
666- if (m_svcVec.size () > prevSize) {
667- return m_svcVec.back ();
668- }
669- }
670- }
671- }
672- }
636+ NimBLERemoteGattUtils::getAttr<NimBLERemoteService>(uuid, &pSvc, m_svcVec,
637+ [this ](const NimBLEUUID* u, NimBLERemoteService** svc) {
638+ return retrieveServices (u, svc);
639+ });
673640
674- NIMBLE_LOGD (LOG_TAG, " << getService: not found " );
675- return nullptr ;
641+ NIMBLE_LOGD (LOG_TAG, " << getService: %sfound " , !pSvc ? " not " : " " );
642+ return pSvc ;
676643} // getService
677644
678645/* *
@@ -725,20 +692,17 @@ bool NimBLEClient::discoverAttributes() {
725692 * * Here we ask the server for its set of services and wait until we have received them all.
726693 * @return true on success otherwise false if an error occurred
727694 */
728- bool NimBLEClient::retrieveServices (const NimBLEUUID* uuidFilter) {
695+ bool NimBLEClient::retrieveServices (const NimBLEUUID* uuid, NimBLERemoteService **out) {
696+ NIMBLE_LOGD (LOG_TAG, " >> retrieveServices()" );
697+ NimBLETaskData taskData (this );
729698 if (!isConnected ()) {
730699 NIMBLE_LOGE (LOG_TAG, " Disconnected, could not retrieve services -aborting" );
731700 return false ;
732701 }
733702
734- int rc = 0 ;
735- NimBLETaskData taskData (this );
736-
737- if (uuidFilter == nullptr ) {
738- rc = ble_gattc_disc_all_svcs (m_connHandle, NimBLEClient::serviceDiscoveredCB, &taskData);
739- } else {
740- rc = ble_gattc_disc_svc_by_uuid (m_connHandle, uuidFilter->getBase (), NimBLEClient::serviceDiscoveredCB, &taskData);
741- }
703+ int rc = (uuid == nullptr )
704+ ? ble_gattc_disc_all_svcs (m_connHandle, svcDiscCB, &taskData)
705+ : ble_gattc_disc_svc_by_uuid (m_connHandle, uuid->getBase (), svcDiscCB, &taskData);
742706
743707 if (rc != 0 ) {
744708 NIMBLE_LOGE (LOG_TAG, " ble_gattc_disc_all_svcs: rc=%d %s" , rc, NimBLEUtils::returnCodeToString (rc));
@@ -748,53 +712,45 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) {
748712
749713 NimBLEUtils::taskWait (taskData, BLE_NPL_TIME_FOREVER);
750714 rc = taskData.m_flags ;
751- if (rc == 0 || rc == BLE_HS_EDONE) {
752- return true ;
715+ if (rc != BLE_HS_EDONE) {
716+ m_lastErr = rc;
717+ NIMBLE_LOGE (LOG_TAG, " Could not retrieve services, rc=%d %s" , rc, NimBLEUtils::returnCodeToString (rc));
718+ return false ;
753719 }
754720
755- m_lastErr = rc ;
756- NIMBLE_LOGE (LOG_TAG, " Could not retrieve services, rc= %d %s " , rc, NimBLEUtils::returnCodeToString (rc ));
757- return false ;
721+ *out = m_svcVec. back () ;
722+ NIMBLE_LOGD (LOG_TAG, " << retrieveServices(): found %d services. " , m_svcVec. size ( ));
723+ return true ;
758724} // getServices
759725
760726/* *
761727 * @brief Callback for the service discovery API function.
762728 * @details When a service is found or there is none left or there was an error
763729 * the API will call this and report findings.
764730 */
765- int NimBLEClient::serviceDiscoveredCB (uint16_t connHandle,
766- const struct ble_gatt_error * error,
767- const struct ble_gatt_svc * service,
768- void * arg) {
769- NIMBLE_LOGD (LOG_TAG,
770- " Service Discovered >> status: %d handle: %d" ,
771- error->status ,
772- (error->status == 0 ) ? service->start_handle : -1 );
773-
774- NimBLETaskData* pTaskData = (NimBLETaskData*)arg;
775- NimBLEClient* pClient = (NimBLEClient*)pTaskData->m_pInstance ;
776-
777- if (error->status == BLE_HS_ENOTCONN) {
778- NIMBLE_LOGE (LOG_TAG, " << Service Discovered; Disconnected" );
779- NimBLEUtils::taskRelease (*pTaskData, error->status );
780- return error->status ;
781- }
731+ int NimBLEClient::svcDiscCB (uint16_t connHandle,
732+ const struct ble_gatt_error * error,
733+ const struct ble_gatt_svc * service,
734+ void * arg) {
735+ const int rc = error->status ;
736+ auto pTaskData = (NimBLETaskData*)arg;
737+ auto pClient = (NimBLEClient*)pTaskData->m_pInstance ;
738+ NIMBLE_LOGD (LOG_TAG, " Service Discovered >> status: %d handle: %d" , rc, (rc == 0 ) ? service->start_handle : -1 );
782739
783740 // Make sure the service discovery is for this device
784741 if (pClient->getConnHandle () != connHandle) {
785742 return 0 ;
786743 }
787744
788- if (error->status == 0 ) {
789- // Found a service - add it to the vector
745+ if (rc == 0 ) { // Found a service - add it to the vector
790746 pClient->m_svcVec .push_back (new NimBLERemoteService (pClient, service));
791747 return 0 ;
792748 }
793749
794750 NimBLEUtils::taskRelease (*pTaskData, error->status );
795- NIMBLE_LOGD (LOG_TAG, " << Service Discovered" );
751+ NIMBLE_LOGD (LOG_TAG, " << Service Discovered%s " , (rc == BLE_HS_ENOTCONN) ? " ; Not connected " : " " );
796752 return error->status ;
797- } // serviceDiscoveredCB
753+ } // serviceDiscCB
798754
799755/* *
800756 * @brief Get the value of a specific characteristic associated with a specific service.
@@ -803,8 +759,7 @@ int NimBLEClient::serviceDiscoveredCB(uint16_t connHandle,
803759 * @returns characteristic value or an empty value if not found.
804760 */
805761NimBLEAttValue NimBLEClient::getValue (const NimBLEUUID& serviceUUID, const NimBLEUUID& characteristicUUID) {
806- NIMBLE_LOGD (LOG_TAG,
807- " >> getValue: serviceUUID: %s, characteristicUUID: %s" ,
762+ NIMBLE_LOGD (LOG_TAG, " >> getValue: serviceUUID: %s, characteristicUUID: %s" ,
808763 serviceUUID.toString ().c_str (),
809764 characteristicUUID.toString ().c_str ());
810765
@@ -833,15 +788,14 @@ bool NimBLEClient::setValue(const NimBLEUUID& serviceUUID,
833788 const NimBLEUUID& characteristicUUID,
834789 const NimBLEAttValue& value,
835790 bool response) {
836- NIMBLE_LOGD (LOG_TAG,
837- " >> setValue: serviceUUID: %s, characteristicUUID: %s" ,
791+ NIMBLE_LOGD (LOG_TAG, " >> setValue: serviceUUID: %s, characteristicUUID: %s" ,
838792 serviceUUID.toString ().c_str (),
839793 characteristicUUID.toString ().c_str ());
840794
841795 bool ret = false ;
842796 auto pService = getService (serviceUUID);
843797 if (pService != nullptr ) {
844- NimBLERemoteCharacteristic* pChar = pService->getCharacteristic (characteristicUUID);
798+ auto pChar = pService->getCharacteristic (characteristicUUID);
845799 if (pChar != nullptr ) {
846800 ret = pChar->writeValue (value, response);
847801 }
@@ -858,11 +812,13 @@ bool NimBLEClient::setValue(const NimBLEUUID& serviceUUID,
858812 */
859813NimBLERemoteCharacteristic* NimBLEClient::getCharacteristic (uint16_t handle) {
860814 for (const auto & svc : m_svcVec) {
861- if (svc->getStartHandle () <= handle && handle <= svc->getEndHandle ()) {
862- for (const auto & chr : svc->m_vChars ) {
863- if (chr->getHandle () == handle) {
864- return chr;
865- }
815+ if (svc->getStartHandle () > handle && handle > svc->getEndHandle ()) {
816+ continue ;
817+ }
818+
819+ for (const auto & chr : svc->m_vChars ) {
820+ if (chr->getHandle () == handle) {
821+ return chr;
866822 }
867823 }
868824 }
@@ -882,28 +838,28 @@ uint16_t NimBLEClient::getMTU() const {
882838 * @brief Callback for the MTU exchange API function.
883839 * @details When the MTU exchange is complete the API will call this and report the new MTU.
884840 */
885- int NimBLEClient::exchangeMTUCb (uint16_t conn_handle , const ble_gatt_error* error, uint16_t mtu, void * arg) {
886- NIMBLE_LOGD (LOG_TAG, " exchangeMTUCb : status=%d, mtu=%d" , error->status , mtu);
841+ int NimBLEClient::exchangeMTUCB (uint16_t connHandle , const ble_gatt_error* error, uint16_t mtu, void * arg) {
842+ NIMBLE_LOGD (LOG_TAG, " exchangeMTUCB : status=%d, mtu=%d" , error->status , mtu);
887843
888844 NimBLEClient* pClient = (NimBLEClient*)arg;
889- if (pClient->getConnHandle () != conn_handle ) {
845+ if (pClient->getConnHandle () != connHandle ) {
890846 return 0 ;
891847 }
892848
893849 if (error->status != 0 ) {
894- NIMBLE_LOGE (LOG_TAG, " exchangeMTUCb () rc=%d %s" , error->status , NimBLEUtils::returnCodeToString (error->status ));
850+ NIMBLE_LOGE (LOG_TAG, " exchangeMTUCB () rc=%d %s" , error->status , NimBLEUtils::returnCodeToString (error->status ));
895851 pClient->m_lastErr = error->status ;
896852 }
897853
898854 return 0 ;
899- } // exchangeMTUCb
855+ } // exchangeMTUCB
900856
901857/* *
902858 * @brief Begin the MTU exchange process with the server.
903859 * @returns true if the request was sent successfully.
904860 */
905861bool NimBLEClient::exchangeMTU () {
906- int rc = ble_gattc_exchange_mtu (m_connHandle, NimBLEClient::exchangeMTUCb , this );
862+ int rc = ble_gattc_exchange_mtu (m_connHandle, NimBLEClient::exchangeMTUCB , this );
907863 if (rc != 0 ) {
908864 NIMBLE_LOGE (LOG_TAG, " MTU exchange error; rc=%d %s" , rc, NimBLEUtils::returnCodeToString (rc));
909865 m_lastErr = rc;
@@ -989,25 +945,25 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
989945 pClient->m_pClientCallbacks ->onConnect (pClient);
990946 }
991947
992- if (pClient->m_config .exchangeMTU ) {
993- if (!pClient->exchangeMTU ()) {
994- rc = pClient->m_lastErr ; // sets the error in the task data
995- break ;
996- }
997-
998- return 0 ; // return as we may have a task waiting for the MTU before releasing it.
948+ if (!pClient->m_config .exchangeMTU ) {
949+ break ;
999950 }
1000- } else {
1001- pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
1002951
1003- if (pClient->m_config .asyncConnect ) {
1004- pClient->m_pClientCallbacks ->onConnectFail (pClient, rc);
1005- if (pClient->m_config .deleteOnConnectFail ) {
1006- NimBLEDevice::deleteClient (pClient);
1007- }
952+ if (!pClient->exchangeMTU ()) {
953+ rc = pClient->m_lastErr ; // sets the error in the task data
954+ break ;
1008955 }
956+
957+ return 0 ; // return as we may have a task waiting for the MTU before releasing it.
1009958 }
1010959
960+ pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
961+ if (pClient->m_config .asyncConnect ) {
962+ pClient->m_pClientCallbacks ->onConnectFail (pClient, rc);
963+ if (pClient->m_config .deleteOnConnectFail ) {
964+ NimBLEDevice::deleteClient (pClient);
965+ }
966+ }
1011967 break ;
1012968 } // BLE_GAP_EVENT_CONNECT
1013969
@@ -1035,23 +991,23 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
1035991 continue ;
1036992 }
1037993
1038- NIMBLE_LOGD (LOG_TAG,
1039- " checking service %s for handle: %d" ,
994+ NIMBLE_LOGD (LOG_TAG, " checking service %s for handle: %d" ,
1040995 svc->getUUID ().toString ().c_str (),
1041996 event->notify_rx .attr_handle );
1042997
1043998 for (const auto & chr : svc->m_vChars ) {
1044- if (chr->getHandle () == event->notify_rx .attr_handle ) {
1045- NIMBLE_LOGD (LOG_TAG, " Got Notification for characteristic %s" , chr->toString ().c_str ());
999+ if (chr->getHandle () != event->notify_rx .attr_handle ) {
1000+ continue ;
1001+ }
10461002
1047- uint32_t data_len = OS_MBUF_PKTLEN (event->notify_rx .om );
1048- chr->m_value .setValue (event->notify_rx .om ->om_data , data_len);
1003+ NIMBLE_LOGD (LOG_TAG, " Got Notification for characteristic %s" , chr->toString ().c_str ());
1004+ uint32_t data_len = OS_MBUF_PKTLEN (event->notify_rx .om );
1005+ chr->m_value .setValue (event->notify_rx .om ->om_data , data_len);
10491006
1050- if (chr->m_notifyCallback != nullptr ) {
1051- chr->m_notifyCallback (chr, event->notify_rx .om ->om_data , data_len, !event->notify_rx .indication );
1052- }
1053- break ;
1007+ if (chr->m_notifyCallback != nullptr ) {
1008+ chr->m_notifyCallback (chr, event->notify_rx .om ->om_data , data_len, !event->notify_rx .indication );
10541009 }
1010+ break ;
10551011 }
10561012 }
10571013
@@ -1064,8 +1020,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
10641020 return 0 ;
10651021 }
10661022 NIMBLE_LOGD (LOG_TAG, " Peer requesting to update connection parameters" );
1067- NIMBLE_LOGD (LOG_TAG,
1068- " MinInterval: %d, MaxInterval: %d, Latency: %d, Timeout: %d" ,
1023+ NIMBLE_LOGD (LOG_TAG, " MinInterval: %d, MaxInterval: %d, Latency: %d, Timeout: %d" ,
10691024 event->conn_update_req .peer_params ->itvl_min ,
10701025 event->conn_update_req .peer_params ->itvl_max ,
10711026 event->conn_update_req .peer_params ->latency ,
0 commit comments