Find and Subscribe to multiple BT Characteristics

Hi,

I've tried a lot of different things.  Occasionally I've had promising results where I actually fine and subscribe to a single characteristic.  Most recently I've tried gatt_dm with no results, it finds service 1801 with 4 characteristics, then 1800 with 7 characteristics then errors out with Not enough memory for next attribute descriptor at handle 40.  

My Prj.conf file contains CONFIG_BT_GATT_DM_MAX_ATTRS=350 per another persons post with a similar problem.  The peripheral I'm connecting to from my central app has A LOT of characteristics (unfortunately I have to connect to it and deal with the issues of having a lot of characteristics (310))

I've tried this but it doesn't find all of the characteristics for some reason.  it will find one and subscribe to one as well but I have 5 I need to subscribe to as well as several i need handles to that i need to write to.

I am using NCS v2.2.0 on Windows 10 the nRF52832 is on a custom board, I've looked at central_HR and haven't really gotten anything to work.  I believe gatt_dm will do what I need but I need to figure out why it wont find more than 40 attributes.

Brian

Parents
  • Hello Brian,

    Can you please describe in a bit more detail what you are seeing? What happens when not all characteristics show up? Does the central application crash?

    Best regards,

    Edvin

  • When i try and find all services first (like the code in the link I referenced) i find all the services.  BUT when it moved to characteristics, it only finds between 5 and 10 characteristics.  I am leaving the UUID set at NULL so from my understanding it should return all characteristics.  when finished with characteristics, it finds the CCCD's and finds 3 (correct number).  

    What happens when not all characteristics show up?  Nothing, everything runs to completion.  No errors no indications that anything odd has happened.

    When i tried the central app, it does crash, I put in a ticket for that and didn't get a response before i went to central_gatt.  central gatt does not crash.  so I've been working off that as a base.  

    Currently ive modified everything to this:

    switch(discover_phase) {
            case DISC_PHASE_SERVICE:
                if(attr) {
    				// Getting here, attr->uuid will be BT_UUID_GATT_PRIMARY 
    				struct bt_gatt_service_val *svc_attr = attr->user_data;
    				memcpy(uuid_str,BT_UUID_128(svc_attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
    				printk("attr is a primary service.  UUID type is %d, val = %x\n", svc_attr->uuid->type, BT_UUID_16(svc_attr->uuid)->val);
    				if(!bt_uuid_cmp(svc_attr->uuid, BT_UUID_DRONE_RX_SERVICE))
    				{
    					printk("FOUND DRONE_RX SVC\n\n");
    					dront_rx_svc_handle = attr->handle;
    					discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                    	discover_params.start_handle = last_handle + 1;
    					err = bt_gatt_discover(conn, &discover_params);
    					if (err) {
    						printk("Discover failed - svc (err %d)\n", err);
    					}
    					last_handle = attr->handle;
    					discover_phase = DISC_PHASE_CHRC;
    					return BT_GATT_ITER_STOP;
    					}
    					last_handle = attr->handle;
                }
                else {
                    // No more service UUIDs.  Look for Characteristics. 
                    printk("No more services, looking for characteristics\n");
                    discover_params.uuid = NULL;
    				//memcpy(uuid_str,BT_UUID_128(discover_params.uuid)->val,16);
    				//printk("DISCOVER UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
                    discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                    discover_params.start_handle = last_handle + 1;
    
                    err = bt_gatt_discover(conn, &discover_params);
                    if (err) {
                        printk("Discover failed - svc (err %d)\n", err);
                    }
                    discover_phase = DISC_PHASE_CHRC;
                    return BT_GATT_ITER_STOP;
                }
    			return BT_GATT_ITER_CONTINUE;
                break;
    
    		case DISC_PHASE_CHRC:
                if(attr) 
    			{
    				// Getting here, attr->uuid will be BT_UUID_GATT_CHRC 
    				struct bt_gatt_chrc *chrc_attr = attr->user_data;
    				memcpy(uuid_str,BT_UUID_128(chrc_attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
    				printk("attr is a characteristic.  UUID type is %d, val = %x\n", chrc_attr->uuid->type, BT_UUID_16(chrc_attr->uuid)->val);
    
    				
    				
                    last_handle = attr->handle;
                }
                else {
                    // Ran out of characteristics, look for CCCDs 
                    printk("No more characteristics, looking for CCCDs\n");
                    //discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
            		//discover_params.start_handle = attr->handle + 1;
                    //discover_params.start_handle = last_handle + 1;
    
                    //err = bt_gatt_discover(conn, &discover_params);
                    //if (err) {
                    //    printk("Discover failed - chrc (err %d)\n", err);
                    //}
                    //discover_phase = DISC_PHASE_CCCD;
                    return BT_GATT_ITER_STOP;
                }
    			return BT_GATT_ITER_CONTINUE;
                break;
    	}
    }

    it selects a service, then looks for characteristics.  it then finds ALL of the characteristics BUT not all of the services.  Changing the code to not stop at my specific service <BT_UUID_DRONE_RX_SERVICE> results  in all services being found but only 3 characteristics for the LAST service only.

    What i need to do is capture 2 services and about 5 characteristics from each for reading and writing.  Finding the DRONE_RX_SERVICE and switching to characteristic discovery then doesn't find the TX_SERVICE.  

    I am a novice at this and its been a struggle to find appropriate documentation that says what happens when.  such as if you stop iterating at a service you cant go back to iterating through services anymore.  the gatt_dm seems like it does what i want/need but i cant get that to work at all.  My co-worker has done this stuff before however he did it before zephyr and a lot has changed apparently because he is struggling too.

Reply
  • When i try and find all services first (like the code in the link I referenced) i find all the services.  BUT when it moved to characteristics, it only finds between 5 and 10 characteristics.  I am leaving the UUID set at NULL so from my understanding it should return all characteristics.  when finished with characteristics, it finds the CCCD's and finds 3 (correct number).  

    What happens when not all characteristics show up?  Nothing, everything runs to completion.  No errors no indications that anything odd has happened.

    When i tried the central app, it does crash, I put in a ticket for that and didn't get a response before i went to central_gatt.  central gatt does not crash.  so I've been working off that as a base.  

    Currently ive modified everything to this:

    switch(discover_phase) {
            case DISC_PHASE_SERVICE:
                if(attr) {
    				// Getting here, attr->uuid will be BT_UUID_GATT_PRIMARY 
    				struct bt_gatt_service_val *svc_attr = attr->user_data;
    				memcpy(uuid_str,BT_UUID_128(svc_attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
    				printk("attr is a primary service.  UUID type is %d, val = %x\n", svc_attr->uuid->type, BT_UUID_16(svc_attr->uuid)->val);
    				if(!bt_uuid_cmp(svc_attr->uuid, BT_UUID_DRONE_RX_SERVICE))
    				{
    					printk("FOUND DRONE_RX SVC\n\n");
    					dront_rx_svc_handle = attr->handle;
    					discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                    	discover_params.start_handle = last_handle + 1;
    					err = bt_gatt_discover(conn, &discover_params);
    					if (err) {
    						printk("Discover failed - svc (err %d)\n", err);
    					}
    					last_handle = attr->handle;
    					discover_phase = DISC_PHASE_CHRC;
    					return BT_GATT_ITER_STOP;
    					}
    					last_handle = attr->handle;
                }
                else {
                    // No more service UUIDs.  Look for Characteristics. 
                    printk("No more services, looking for characteristics\n");
                    discover_params.uuid = NULL;
    				//memcpy(uuid_str,BT_UUID_128(discover_params.uuid)->val,16);
    				//printk("DISCOVER UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
                    discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                    discover_params.start_handle = last_handle + 1;
    
                    err = bt_gatt_discover(conn, &discover_params);
                    if (err) {
                        printk("Discover failed - svc (err %d)\n", err);
                    }
                    discover_phase = DISC_PHASE_CHRC;
                    return BT_GATT_ITER_STOP;
                }
    			return BT_GATT_ITER_CONTINUE;
                break;
    
    		case DISC_PHASE_CHRC:
                if(attr) 
    			{
    				// Getting here, attr->uuid will be BT_UUID_GATT_CHRC 
    				struct bt_gatt_chrc *chrc_attr = attr->user_data;
    				memcpy(uuid_str,BT_UUID_128(chrc_attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
    				printk("attr is a characteristic.  UUID type is %d, val = %x\n", chrc_attr->uuid->type, BT_UUID_16(chrc_attr->uuid)->val);
    
    				
    				
                    last_handle = attr->handle;
                }
                else {
                    // Ran out of characteristics, look for CCCDs 
                    printk("No more characteristics, looking for CCCDs\n");
                    //discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
            		//discover_params.start_handle = attr->handle + 1;
                    //discover_params.start_handle = last_handle + 1;
    
                    //err = bt_gatt_discover(conn, &discover_params);
                    //if (err) {
                    //    printk("Discover failed - chrc (err %d)\n", err);
                    //}
                    //discover_phase = DISC_PHASE_CCCD;
                    return BT_GATT_ITER_STOP;
                }
    			return BT_GATT_ITER_CONTINUE;
                break;
    	}
    }

    it selects a service, then looks for characteristics.  it then finds ALL of the characteristics BUT not all of the services.  Changing the code to not stop at my specific service <BT_UUID_DRONE_RX_SERVICE> results  in all services being found but only 3 characteristics for the LAST service only.

    What i need to do is capture 2 services and about 5 characteristics from each for reading and writing.  Finding the DRONE_RX_SERVICE and switching to characteristic discovery then doesn't find the TX_SERVICE.  

    I am a novice at this and its been a struggle to find appropriate documentation that says what happens when.  such as if you stop iterating at a service you cant go back to iterating through services anymore.  the gatt_dm seems like it does what i want/need but i cant get that to work at all.  My co-worker has done this stuff before however he did it before zephyr and a lot has changed apparently because he is struggling too.

Children
  • I don't know what I am looking at. Where is this snippet placed? 

  • This is the connected function:

    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	struct bt_conn_info conn_info;
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	LOG_DBG("Connecting to: %s", addr);
    
    	if (conn_err) {
    		LOG_DBG("%s: Failed to connect to %s (%u)\n", __func__, addr,
    		       conn_err);
    		return;
    	}
    	else {
    		LOG_DBG("Connected to (%s)\n",addr);
    	}
    
    	err = bt_conn_get_info(conn, &conn_info);
    	if (err) {
    		LOG_DBG("Failed to get connection info (%d).\n", err);		
    		return;
    	}
    
    	LOG_DBG("%s: %s role %u\n", __func__, addr, conn_info.role);
    
    	conn_connected = bt_conn_ref(conn);
    
    	//(void)mtu_exchange(conn);
    
    #if defined(CONFIG_BT_SMP)
    	if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
    		err = bt_conn_set_security(conn, BT_SECURITY_L2);
    		if (err) {
    			printk("Failed to set security (%d).\n", err);
    		}
    	}
    #endif
    
    	//err = bt_gatt_dm_start(conn, NULL, &discover_all_cb, NULL);
    	//if (err) {
    		//printk("Failed to start discovery (err %d)\n", err);
    	//}
    	if (conn == conn_connected) {		
    		discover_params.uuid = NULL;
    		discover_params.func = discover_services;
    		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
    		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
    		discover_params.type = BT_GATT_DISCOVER_PRIMARY;
    		discover_phase = DISC_PHASE_SERVICE;
    
    		err = bt_gatt_discover(conn_connected, &discover_params);
    		if (err)
    		{
    			printk("Discover failed(err %d)\n", err);
    			return;
    		}	
    		printk("end of discover in connect\n");
    
    	}
    }

    I set discovered_params.func to discover_services.  The snippet above is from discovered_services.  Here it is in its entirety

    uint8_t discover_services(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params)
    {
    	int err;
    	static uint16_t last_handle;
    	char uuid_str[16];
    	
    	if(attr) 
    	{		
            printk("[ATTRIBUTE] handle %u\n", attr->handle);	
    		printk("uuid type = %d, val=%x\n", attr->uuid->type,BT_UUID_16(attr->uuid)->val);	  
    	}
    
    	switch(discover_phase) {
            case DISC_PHASE_SERVICE:
                if(attr) {
    				// Getting here, attr->uuid will be BT_UUID_GATT_PRIMARY 
    				struct bt_gatt_service_val *svc_attr = attr->user_data;
    				memcpy(uuid_str,BT_UUID_128(svc_attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
    				printk("attr is a primary service.  UUID type is %d, val = %x\n", svc_attr->uuid->type, BT_UUID_16(svc_attr->uuid)->val);
    				if(!bt_uuid_cmp(svc_attr->uuid, BT_UUID_DRONE_RX_SERVICE))
    				{
    					printk("FOUND DRONE_RX SVC\n\n");
    					drone_rx_svc_handle = attr->handle;
    					discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                    	discover_params.start_handle = last_handle + 1;
    					err = bt_gatt_discover(conn, &discover_params);
    					if (err) {
    						printk("Discover failed - svc (err %d)\n", err);
    					}
    					last_handle = attr->handle;
    					discover_phase = DISC_PHASE_CHRC;
    					return BT_GATT_ITER_STOP;
    				}
    				
    				last_handle = attr->handle;
                }
                else {
                    // No more service UUIDs.  Look for Characteristics. 
                    printk("No more services, looking for characteristics\n");
                    discover_params.uuid = NULL;
    				//memcpy(uuid_str,BT_UUID_128(discover_params.uuid)->val,16);
    				//printk("DISCOVER UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
                    discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                    discover_params.start_handle = last_handle + 1;
    
                    err = bt_gatt_discover(conn, &discover_params);
                    if (err) {
                        printk("Discover failed - svc (err %d)\n", err);
                    }
    				last_handle=attr->handle;
                    discover_phase = DISC_PHASE_CHRC;
                    return BT_GATT_ITER_STOP;
                }
    			return BT_GATT_ITER_CONTINUE;
                break;
    
    		case DISC_PHASE_CHRC:
                if(attr) 
    			{
    				// Getting here, attr->uuid will be BT_UUID_GATT_CHRC 
    				struct bt_gatt_chrc *chrc_attr = attr->user_data;
    				memcpy(uuid_str,BT_UUID_128(chrc_attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
    				printk("attr is a characteristic.  UUID type is %d, val = %x\n", chrc_attr->uuid->type, BT_UUID_16(chrc_attr->uuid)->val);
    
    				if(!bt_uuid_cmp(chrc_attr->uuid,BT_UUID_DRONE_TX_SERVICE))
    				{
    					printk("FOUND DRONE_TX SVC\n\n");
    					drone_tx_svc_handle = attr->handle;
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_RX_NOACK))
    				{	
    					LOG_DBG("FOUND DRONE RX NOACK 0A\n\n");
    					drone_rx0a_handle = attr->handle;                	
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_TX_ACK))
    				{	
    					LOG_DBG("FOUND DRONE TX ACK FB0E\n\n");
    					drone_rx0a_handle = attr->handle;                	
    				}
    				
    				last_handle = attr->handle;
                }
                else {
                    // Ran out of characteristics, look for CCCDs 
                    printk("No more characteristics, looking for CCCDs\n");
                    discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
            		discover_params.start_handle = attr->handle + 1;
                    discover_params.start_handle = last_handle + 1;
    
                    err = bt_gatt_discover(conn, &discover_params);
                    if (err) {
                        printk("Discover failed - chrc (err %d)\n", err);
                    }
                    discover_phase = DISC_PHASE_CCCD;
                    return BT_GATT_ITER_STOP;
                }
    			
    			return BT_GATT_ITER_CONTINUE;
                break;
    		case DISC_PHASE_CCCD:
                if(attr) {
    				memcpy(uuid_str,BT_UUID_128(attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
                   
                    printk("attr is a CCCD.  UUID type is %d, val = %x\n", attr->uuid->type, BT_UUID_16(attr->uuid)->val);
                    if(attr->user_data == NULL) {
                        printk("user_data is NULL\n");
                    }
                    else {
                        struct bt_gatt_ccc *dope = attr->user_data;
    					
                        printk("user data is %x\n", dope->flags);
                    }
                    // Check if this CCCD is associated with Report charact 
                    //if(!bt_uuid_cmp(attr->uuid, &cis_report_char_uuid.uuid)) {
                    //    printk("Found CCCD for Report characteristic\n");
                    //    cccd_handle = attr->handle;
                    //}
                    last_handle = attr->handle;
                }
                else {
                    printk("Discovery complete\n");
                   
                }
                break;
        
    	}
    }

    Its not pretty, ive been trying to get things to work.  

    How about answering this question: How does the iteration work.  It seems that when you're looking for just services, it is scanning ALL of the services, characteristics, CCCD's etc.  so if you get to the end of the list with services and THEN look for characteristics they are no longer available to iterate through. 

    What exactly does BT_GATT_ITER_CONTINUE and BT_GATT_ITER_STOP do?  Does it stop at the current iteration point and return then allow you to restart somewhere else in the list or ???  I've been looking for a definition of how this iteration of characteristics and services works but haven't found one.

    My latest attempt at finding characteristics and services is to find the first service and then switch to characteristics and when I find the UUID of a service or characteristic I need then I simply record the handle and continue.  Once I finish, hopefully it'll work, ill try and get that done and tested today.

    Brian 

  • So after a lot of iterations i seem to now be able to get the 2 services and 8 characteristics i want to monitor.  Here is my final bit of code:

    The connect function:

    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	struct bt_conn_info conn_info;
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	LOG_DBG("Connecting to: %s", addr);
    
    	if (conn_err) {
    		LOG_DBG("%s: Failed to connect to %s (%u)\n", __func__, addr,
    		       conn_err);
    		return;
    	}
    	else {
    		LOG_DBG("Connected to (%s)\n",addr);
    	}
    
    	err = bt_conn_get_info(conn, &conn_info);
    	if (err) {
    		LOG_DBG("Failed to get connection info (%d).\n", err);		
    		return;
    	}
    
    	LOG_DBG("%s: %s role %u\n", __func__, addr, conn_info.role);
    
    	conn_connected = bt_conn_ref(conn);
    
    	//(void)mtu_exchange(conn);
    
    #if defined(CONFIG_BT_SMP)
    	if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
    		err = bt_conn_set_security(conn, BT_SECURITY_L2);
    		if (err) {
    			printk("Failed to set security (%d).\n", err);
    		}
    	}
    #endif
    	
    	if (conn == conn_connected) {		
    		discover_params.uuid = NULL;
    		discover_params.func = discover_services;
    		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
    		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
    		discover_params.type = BT_GATT_DISCOVER_PRIMARY;
    		discover_phase = DISC_PHASE_SERVICE;
    
    		err = bt_gatt_discover(conn_connected, &discover_params);
    		if (err)
    		{
    			printk("Discover failed(err %d)\n", err);
    			return;
    		}	
    		printk("end of discover in connect\n");
    
    	}
    }

    And the discover_services function:

    uint8_t discover_services(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params)
    {
    	int err;
    	static uint16_t last_handle;
    	char uuid_str[16];
    	
    	if(attr) 
    	{		
            printk("[ATTRIBUTE] handle %u\n", attr->handle);	
    		printk("uuid type = %d, val=%x\n", attr->uuid->type,BT_UUID_16(attr->uuid)->val);	  
    	}
    	switch(discover_phase) 
    	{
            case DISC_PHASE_SERVICE:
                if(attr) {
    				// Getting here, attr->uuid will be BT_UUID_GATT_PRIMARY 
    				struct bt_gatt_service_val *svc_attr = attr->user_data;
    				memcpy(uuid_str,BT_UUID_128(svc_attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
    				printk("attr is a primary service.  UUID type is %d, val = %x\n", svc_attr->uuid->type, BT_UUID_16(svc_attr->uuid)->val);
    				if(!bt_uuid_cmp(svc_attr->uuid, BT_UUID_DRONE_RX_SERVICE))
    				{
    					printk("FOUND DRONE_RX SVC\n\n");
    					drone_rx_svc_handle = attr->handle;
    					return BT_GATT_ITER_CONTINUE;
    				}
    
    				if(!bt_uuid_cmp(svc_attr->uuid, BT_UUID_DRONE_TX_SERVICE))
    				{
    					printk("FOUND DRONE_TX SVC\n\n");
    					drone_tx_svc_handle = attr->handle;
    					discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                    	discover_params.start_handle = last_handle + 1;
    					err = bt_gatt_discover(conn, &discover_params);
    					if (err) {
    						printk("Discover failed - svc (err %d)\n", err);
    					}
    					last_handle = attr->handle;
    					discover_phase = DISC_PHASE_CHRC;
    					return BT_GATT_ITER_STOP;
    				}
    				last_handle = attr->handle;
    				
                }
                else {
                    // No more service UUIDs.  Look for Characteristics. 
                    printk("No more services, looking for characteristics\n");
                    discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                    discover_params.start_handle = last_handle + 1;
    
                    err = bt_gatt_discover(conn, &discover_params);
                    if (err) {
                        printk("Discover failed - svc (err %d)\n", err);
                    }
    				last_handle=attr->handle;
                    discover_phase = DISC_PHASE_CHRC;
                    return BT_GATT_ITER_STOP;
                }           
    
    		case DISC_PHASE_CHRC:
                if(attr) 
    			{
    				// Getting here, attr->uuid will be BT_UUID_GATT_CHRC 
    				struct bt_gatt_chrc *chrc_attr = attr->user_data;
    				
    				memcpy(uuid_str,BT_UUID_128(chrc_attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
    				
    				printk("attr is a characteristic.  UUID type is %d, val = %x\n", chrc_attr->uuid->type, BT_UUID_16(chrc_attr->uuid)->val);
    
    				
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_RX_NOACK))
    				{	
    					LOG_DBG("FOUND DRONE RX NOACK FA0A\n\n");
    					drone_rx0a_handle = attr->handle;        
    					LOG_DBG("rx0a handle: %u ",drone_rx0a_handle);         	
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_RX_ACK))
    				{	
    					LOG_DBG("FOUND DRONE RX NOACK FA0B\n\n");
    					drone_rx0b_handle = attr->handle;          
    					LOG_DBG("rx0b handle: %u ",drone_rx0b_handle);        	
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_RX_HIPRI_ACK))
    				{	
    					LOG_DBG("FOUND DRONE RX HIPRO FA0C\n\n");
    					drone_rx0c_handle = attr->handle;                	
    					LOG_DBG("rx0c handle: %u ",drone_rx0c_handle);  
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_RX_STATE))
    				{	
    					LOG_DBG("FOUND DRONE RX STATE FA0E\n\n");
    					drone_rx0e_handle = attr->handle;                	
    					LOG_DBG("rx0e handle: %u ",drone_rx0e_handle);  
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_RX_ACK_ACK))
    				{	
    					LOG_DBG("FOUND DRONE RX ACKACK FA1E\n\n");
    					drone_rx1e_handle = attr->handle;    
    					LOG_DBG("rx1e handle: %u ",drone_rx1e_handle);              	
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_TX_ACK))
    				{	
    					LOG_DBG("FOUND DRONE TX ACK FB0E\n\n");
    					drone_tx0e_handle = attr->handle;      
    					LOG_DBG("tx0e handle: %u ",drone_tx0e_handle); 
    					subscribe_params.notify = notify_cb;
    					subscribe_params.value = BT_GATT_CCC_NOTIFY;
    					subscribe_params.ccc_handle = drone_tx0e_handle;
    
    					err = bt_gatt_subscribe(conn, &subscribe_params);
    					if (err && err != -EALREADY) {
    						printk("Subscribe failed (err %d)\n", err);
    					} else {
    						printk("[SUBSCRIBED ACK 0E]\n");
    					} 
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_TX_NOACK))
    				{	
    					LOG_DBG("FOUND DRONE TX NOACK FB0F\n\n");
    
    					drone_tx0f_handle = attr->handle;       
    					LOG_DBG("tx0f handle: %u ",drone_tx0f_handle); 
    					subscribe_params.notify = notify_cb;
    					subscribe_params.value = BT_GATT_CCC_NOTIFY;
    					subscribe_params.ccc_handle = drone_tx0f_handle;
    
    					err = bt_gatt_subscribe(conn, &subscribe_params);
    					if (err && err != -EALREADY) {
    						printk("Subscribe failed (err %d)\n", err);
    					} else {
    						printk("[SUBSCRIBED NOACK 0F]\n");
    					} 
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_TX_ACK_ACK))
    				{	
    					LOG_DBG("FOUND DRONE TX ACKACK FB1B\n\n");
    					drone_tx1b_handle = attr->handle;       
    					LOG_DBG("tx1b handle: %u ",drone_tx1b_handle); 
    					subscribe_params.notify = notify_cb;
    					subscribe_params.value = BT_GATT_CCC_NOTIFY;
    					subscribe_params.ccc_handle = drone_tx1b_handle;
    
    					err = bt_gatt_subscribe(conn, &subscribe_params);
    					if (err && err != -EALREADY) {
    						printk("Subscribe failed (err %d)\n", err);
    					} else {
    						printk("[SUBSCRIBED ACK ACK 1B]\n");
    					} 
    				}
    				if(!bt_uuid_cmp(chrc_attr->uuid, BT_UUID_DRONE_TX_HIPRI_ACK))
    				{	
    					LOG_DBG("FOUND DRONE TX HIPRI FB1C\n\n");
    					drone_tx1c_handle = attr->handle;       
    					LOG_DBG("tx1c handle: %u ",drone_tx1c_handle); 
    					subscribe_params.notify = notify_cb;
    					subscribe_params.value = BT_GATT_CCC_NOTIFY;
    					subscribe_params.ccc_handle = drone_tx1c_handle;
    
    					err = bt_gatt_subscribe(conn, &subscribe_params);
    					if (err && err != -EALREADY) {
    						printk("Subscribe failed (err %d)\n", err);
    					} else {
    						printk("[SUBSCRIBED HIPRI 1C]\n");
    					} 
    				}
    
    				last_handle = attr->handle;
                }
                else {
                    // Ran out of characteristics, look for CCCDs 
                    printk("No more characteristics, looking for CCCDs\n");
                    discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;        		
                    discover_params.start_handle = last_handle + 1;
    
                    err = bt_gatt_discover(conn, &discover_params);
                    if (err) {
                        printk("Discover failed - chrc (err %d)\n", err);
                    }
                    discover_phase = DISC_PHASE_CCCD;
                    return BT_GATT_ITER_STOP;
                }			
    			
                
    		case DISC_PHASE_CCCD:
                if(attr) {
    				memcpy(uuid_str,BT_UUID_128(attr->uuid)->val,16);
    				printk("UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",uuid_str[15],uuid_str[14],uuid_str[13],uuid_str[12],uuid_str[11],uuid_str[10],uuid_str[9],uuid_str[8],uuid_str[7],uuid_str[6],uuid_str[5],uuid_str[4],uuid_str[3],uuid_str[2],uuid_str[1],uuid_str[0]);
                   
                    printk("attr is a CCCD.  UUID type is %d, val = %x\n", attr->uuid->type, BT_UUID_16(attr->uuid)->val);
                    if(attr->user_data == NULL) {
                        printk("user_data is NULL\n");
                    }
                    else {
                        struct bt_gatt_ccc *dope = attr->user_data;
    					
                        printk("user data is %x\n", dope->flags);
                    }
                    // Check if this CCCD is associated with Report charact 
                    //if(!bt_uuid_cmp(attr->uuid, &cis_report_char_uuid.uuid)) {
                    //    printk("Found CCCD for Report characteristic\n");
                    //    cccd_handle = attr->handle;
                    //}
                    last_handle = attr->handle;
                }
                else {
                   printk("Discovery complete\n");
                   return BT_GATT_ITER_STOP;
                }
                break;
    		
        
    	}
    	return BT_GATT_ITER_CONTINUE;
    	
    }

    What im not sure i did correctly is the placement of the BT_GATT_ITER_CONTINUE and BT_GATT_ITER_STOP returns.  And I am also not sure i have done the notify_cb correctly.  I write to FA0A with this write command:

    LOG_DBG("sending data to %u",drone_rx0a_handle);
    	err = bt_gatt_write_without_response(conn, drone_rx0a_handle, data, data_len,false);
    	if (err) {
    		printk("%s: Write cmd failed (%d).\n", __func__, err);
    	}

    and I would expect my notify_cb function to be called but it isnt.

    here is the notify_cb:

    uint8_t notify_cb(struct bt_conn *conn, struct bt_gatt_subscribe_params *params,  const void *data, uint16_t length)
    {
    	if (!data) {
    		printk("[UNSUBSCRIBED]\n");
    		params->value_handle = 0U;
    	}
    
    	printk("[NOTIFICATION] data %p length %u\n", data, length);
    
    	return BT_GATT_ITER_CONTINUE;
    }

    Out of the 4 characteristics i subscribe to (I can see the [SUBSCRIBED] in the RTT output, 2 get [UNSUBSCRIBED] while characteristics are being found

    Here is a listing of the output on RTT of all of the debug:

    [00:00:21.301,025] <dbg> gatt_common: connected: connected: D0:3A:A7:09:E6:20 (random) role 0
    
    end of discover in connect
    [ATTRIBUTE] handle 1
    uuid type = 0, val=2800
    UID: fb000000-0020-007c-6820-007c6818011b
    attr is a primary service.  UUID type is 0, val = 1801
    UID: fb000000-0020-007c-6820-007c6818011b
    attr is a characteristic.  UUID type is 0, val = 1801
    UID: 00200044-0400-0200-0420-004424280000
    attr is a CCCD.  UUID type is 0, val = 2800
    user data is 4424
    [ATTRIBUTE] handle 16
    uuid type = 0, val=2800
    UID: fb000000-0020-007c-6820-007c6818001b
    attr is a primary service.  UUID type is 0, val = 1800
    UID: fb000000-0020-007c-6820-007c6818001b
    attr is a characteristic.  UUID type is 0, val = 1800
    UID: 00200044-0400-0200-1620-004424280000
    attr is a CCCD.  UUID type is 0, val = 2800
    user data is 4424
    [ATTRIBUTE] handle 32
    uuid type = 0, val=2800
    UID: 9a66fa00-0800-9191-11e4-012d1540cb8e
    attr is a primary service.  UUID type is 2, val = 40cb
    FOUND DRONE_RX SVC
    
    [ATTRIBUTE] handle 144
    uuid type = 0, val=2800
    UID: 9a66fb00-0800-9191-11e4-012d1540cb8e
    attr is a primary service.  UUID type is 2, val = 40cb
    FOUND DRONE_TX SVC
    
    [00:00:22.000,946] <dbg> central_gatt: central_gatt_write: Calling write
    [00:00:22.001,403] <dbg> gatt_common: write_cmd: sending data to 0
    [00:00:22.001,953] <dbg> gatt_common: write_cmd: data sent
    security_changed: to level 2 (err 0)
    [ATTRIBUTE] handle 17
    uuid type = 0, val=2803
    UID: 05000000-0000-0028-0000-02aea82a0044
    attr is a characteristic.  UUID type is 0, val = 2a00
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 19
    uuid type = 0, val=2803
    UID: 05000000-0000-0028-0000-02aea82a0144
    attr is a characteristic.  UUID type is 0, val = 2a01
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 21
    uuid type = 0, val=2803
    UID: 05000000-0000-0028-0000-02aea82a0444
    attr is a characteristic.  UUID type is 0, val = 2a04
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 33
    uuid type = 0, val=2803
    UID: 9a66fa00-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 36
    uuid type = 0, val=2803
    UID: 9a66fa01-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 39
    uuid type = 0, val=2803
    UID: 9a66fa02-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 42
    uuid type = 0, val=2803
    UID: 9a66fa03-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 45
    uuid type = 0, val=2803
    UID: 9a66fa04-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 48
    uuid type = 0, val=2803
    UID: 9a66fa05-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 51
    uuid type = 0, val=2803
    UID: 9a66fa06-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 54
    uuid type = 0, val=2803
    UID: 9a66fa07-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 57
    uuid type = 0, val=2803
    UID: 9a66fa08-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 60
    uuid type = 0, val=2803
    UID: 9a66fa09-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 63
    uuid type = 0, val=2803
    UID: 9a66fa0a-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:23.302,215] <dbg> central_gatt: discover_services: FOUND DRONE RX NOACK FA0A
    
    
    [00:00:23.302,734] <dbg> central_gatt: discover_services: rx0a handle: 63 
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 66
    uuid type = 0, val=2803
    UID: 9a66fa0b-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:23.402,221] <dbg> central_gatt: discover_services: FOUND DRONE RX NOACK FA0B
    
    
    [00:00:23.402,740] <dbg> central_gatt: discover_services: rx0b handle: 66 
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    Updated MTU: TX: 247 RX: 247 bytes
    le_param_req: int (0x0006, 0x0006) lat 0 to 500
    [ATTRIBUTE] handle 69
    uuid type = 0, val=2803
    UID: 9a66fa0c-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:23.502,532] <dbg> central_gatt: discover_services: FOUND DRONE RX HIPRO FA0C
    
    
    [00:00:23.503,051] <dbg> central_gatt: discover_services: rx0c handle: 69 
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 72
    uuid type = 0, val=2803
    UID: 9a66fa0d-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 75
    uuid type = 0, val=2803
    UID: 9a66fa0e-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:23.659,942] <dbg> central_gatt: discover_services: FOUND DRONE RX STATE FA0E
    
    
    [00:00:23.660,430] <dbg> central_gatt: discover_services: rx0e handle: 75 
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 78
    uuid type = 0, val=2803
    UID: 9a66fa0f-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 81
    uuid type = 0, val=2803
    UID: 9a66fa10-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 84
    uuid type = 0, val=2803
    UID: 9a66fa11-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 87
    uuid type = 0, val=2803
    UID: 9a66fa12-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 90
    uuid type = 0, val=2803
    UID: 9a66fa13-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 93
    uuid type = 0, val=2803
    UID: 9a66fa14-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 96
    uuid type = 0, val=2803
    UID: 9a66fa15-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 99
    uuid type = 0, val=2803
    UID: 9a66fa16-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 102
    uuid type = 0, val=2803
    UID: 9a66fa17-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 105
    uuid type = 0, val=2803
    UID: 9a66fa18-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 108
    uuid type = 0, val=2803
    UID: 9a66fa19-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 111
    uuid type = 0, val=2803
    UID: 9a66fa1a-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 114
    uuid type = 0, val=2803
    UID: 9a66fa1b-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 117
    uuid type = 0, val=2803
    UID: 9a66fa1c-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 120
    uuid type = 0, val=2803
    UID: 9a66fa1d-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 123
    uuid type = 0, val=2803
    UID: 9a66fa1e-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:23.770,385] <dbg> central_gatt: discover_services: FOUND DRONE RX ACKACK FA1E
    
    
    [00:00:23.770,874] <dbg> central_gatt: discover_services: rx1e handle: 123 
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 126
    uuid type = 0, val=2803
    UID: 9a66fa1f-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 145
    uuid type = 0, val=2803
    UID: 9a66fb00-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 148
    uuid type = 0, val=2803
    UID: 9a66fb01-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 151
    uuid type = 0, val=2803
    UID: 9a66fb02-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f8280300
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    le_param_updated: int 0x0006 lat 0 to 500
    [ATTRIBUTE] handle 154
    uuid type = 0, val=2803
    UID: 9a66fb03-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 157
    uuid type = 0, val=2803
    UID: 9a66fb04-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 160
    uuid type = 0, val=2803
    UID: 9a66fb05-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 163
    uuid type = 0, val=2803
    UID: 9a66fb06-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 166
    uuid type = 0, val=2803
    UID: 9a66fb07-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 169
    uuid type = 0, val=2803
    UID: 9a66fb08-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 172
    uuid type = 0, val=2803
    UID: 9a66fb09-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 175
    uuid type = 0, val=2803
    UID: 9a66fb0a-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 178
    uuid type = 0, val=2803
    UID: 9a66fb0b-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 181
    uuid type = 0, val=2803
    UID: 9a66fb0c-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 184
    uuid type = 0, val=2803
    UID: 9a66fb0d-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 187
    uuid type = 0, val=2803
    UID: 9a66fb0e-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:23.918,151] <dbg> central_gatt: discover_services: FOUND DRONE TX ACK FB0E
    
    
    [00:00:23.918,640] <dbg> central_gatt: discover_services: tx0e handle: 187 
    [SUBSCRIBED ACK 0E]
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 190
    uuid type = 0, val=2803
    UID: 9a66fb0f-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:23.921,386] <dbg> central_gatt: discover_services: FOUND DRONE TX NOACK FB0F
    
    
    [00:00:23.921,875] <dbg> central_gatt: discover_services: tx0f handle: 190 
    [SUBSCRIBED NOACK 0F]
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 193
    uuid type = 0, val=2803
    UID: 9a66fb10-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 196
    uuid type = 0, val=2803
    UID: 9a66fb11-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 199
    uuid type = 0, val=2803
    UID: 9a66fb12-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 202
    uuid type = 0, val=2803
    UID: 9a66fb13-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 205
    uuid type = 0, val=2803
    UID: 9a66fb14-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 208
    uuid type = 0, val=2803
    UID: 9a66fb15-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 211
    uuid type = 0, val=2803
    UID: 9a66fb16-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 214
    uuid type = 0, val=2803
    UID: 9a66fb17-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 217
    uuid type = 0, val=2803
    UID: 9a66fb18-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f828032c
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [UNSUBSCRIBED]
    [NOTIFICATION] data (nil) length 0
    [ATTRIBUTE] handle 220
    uuid type = 0, val=2803
    UID: 9a66fb19-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 223
    uuid type = 0, val=2803
    UID: 9a66fb1a-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 226
    uuid type = 0, val=2803
    UID: 9a66fb1b-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:24.004,821] <dbg> central_gatt: discover_services: FOUND DRONE TX ACKACK FB1B
    
    
    [00:00:24.005,310] <dbg> central_gatt: discover_services: tx1b handle: 226 
    [SUBSCRIBED ACK ACK 1B]
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 229
    uuid type = 0, val=2803
    UID: 9a66fb1c-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    [00:00:24.008,392] <dbg> central_gatt: discover_services: FOUND DRONE TX HIPRI FB1C
    
    
    [00:00:24.008,911] <dbg> central_gatt: discover_services: tx1c handle: 229 
    [SUBSCRIBED HIPRI 1C]
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 232
    uuid type = 0, val=2803
    UID: 9a66fb1d-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 235
    uuid type = 0, val=2803
    UID: 9a66fb1e-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 238
    uuid type = 0, val=2803
    UID: 9a66fb1f-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 273
    uuid type = 0, val=2803
    UID: 9a66fd22-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 276
    uuid type = 0, val=2803
    UID: 9a66fd23-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 279
    uuid type = 0, val=2803
    UID: 9a66fd24-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 289
    uuid type = 0, val=2803
    UID: 9a66fd52-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [UNSUBSCRIBED]
    [NOTIFICATION] data (nil) length 0
    [ATTRIBUTE] handle 292
    uuid type = 0, val=2803
    UID: 9a66fd53-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 295
    uuid type = 0, val=2803
    UID: 9a66fd54-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 305
    uuid type = 0, val=2803
    UID: 9a66fe01-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    [ATTRIBUTE] handle 308
    uuid type = 0, val=2803
    UID: 9a66fe02-0800-9191-11e4-012d1540cb8e
    attr is a characteristic.  UUID type is 2, val = 40cb
    UID: 31000000-0020-0021-4820-0019f82803a1
    attr is a CCCD.  UUID type is 0, val = 2803
    user data is 4428
    No more characteristics, looking for CCCDs
    [ATTRIBUTE] handle 309
    uuid type = 2, val=40cb
    UID: 9a66fe02-0800-9191-11e4-012d1540cb8e
    attr is a CCCD.  UUID type is 2, val = 40cb
    user_data is NULL
    [ATTRIBUTE] handle 310
    uuid type = 0, val=2902
    UID: 9a66fe02-0800-9191-11e4-012d1529028e
    attr is a CCCD.  UUID type is 0, val = 2902
    user_data is NULL
    Discovery complete
    [00:00:52.002,410] <dbg> central_gatt: central_gatt_write: Calling write
    [00:00:52.002,899] <dbg> gatt_common: write_cmd: sending data to 63
    [00:00:52.003,448] <dbg> gatt_common: write_cmd: data sent
    [00:01:22.003,936] <dbg> central_gatt: central_gatt_write: Calling write
    [00:01:22.004,425] <dbg> gatt_common: write_cmd: sending data to 63
    [00:01:22.004,974] <dbg> gatt_common: write_cmd: data sent
    

     Unfortunately I've never been able to get the Wireshark Nrf sniffer to work and don't currently have another sniffer available.  I'm working on getting one now.

    Please let me know if I've done something wrong in the ode above.

    Brian

  • Hello Brian,

    I am sorry, but these snippets confuse me. Is it possible to zip and send two applications, one peripheral and one central that I can use to replicate what you are seeing?

    I need to be able to run them on 2 DKs.

    Usually when we get questions about the discovery procedure, I just reference the samples, such as the peripheral_uart and central_uart samples. I suggest you use the bt_gatt_dm_start() instead of bt_gatt_discover() directly, and you don't need to handle the state machine (BT_GATT_ITER_CONTINUE and BT_GATT_ITER_STOP) 

    If you for some reason need to use bt_gatt_discover() directly, it should be fine. It is what bt_gatt_dm_start() does. But in that case, I suggest you look at the implementation of bt_gatt_dm_start() in gatt_dm.c, and implement something similiar.  This one handles the return values (BT_GATT_ITER_CONTINUE and BT_GATT_ITER_STOP).

    It looks like BT_GATT_ITER_CONTINUE should be returned when there are more services/characteristics to discover. BT_GATT_ITER_STOP should be used when you are either done, or if you run into an error.

    But I think you should investigate using bt_gatt_dm_start(), where you set the svc_uuid to NULL to discover all services. Then you call bt_gatt_dm_continue() to discover the next service when you are done handling one in the discovery_completed event.

    Best regards,

    Edvin

  • Hi,

    1) Cant send you code for the peripherial since i dont have it, it was existing firmware i need to connect to and use.  

    2) Seems like the usual answer from support, look at the central UART app, its seems like support doesn't think we research anything.  I've looked at it, I'm new to this, it doesn't really apply since I'm not using a UART and the device I'm connecting to doesn't have a UART for me to connect to to even try.  The 52dk board does and I can load it and it works. now what, the 52dk board doesn't connect to the peripheral I'm trying to scan.  The NRF connect app connects, scans and lists ALL of the services and characteristics and i can send and receive data using that BUT code isn't available for that app to see how it works.

    3) if you can look earlier in this ticket, you'll see that i said i tried the bt_gatt_dm_start but i get an error that there is not enough memory.  i found a post that said to increase 

    CONFIG_BT_GATT_DM_MAX_ATTRS=
    I increased that to 350 since i have so many characteristics.  still fails.  couldnt get any further using that.  This was in the initial post.
    I'll look at the implementation of gatt_dm and maybe ill be able to figure this out.  The documentation is severely lacking and doesn't explain much.
    I am at the point now, where i have been able to discover the services and characteristics but while trying to write, nothing happens.  i saved the handle for the characteristic i wanted to write to (63) and tried a write without response.  data is not getting sent from what i can tell.  If you have any ideas about that, please let em know.
Related