This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

BLE Central: Service Not Found, while trying to implement a DFU Client

Hello.

I wish to implement a DFU Client. One (USB connected) nRF52840 based device should update an other (Wireless) nRF52840 device.

As the SDK only has a DFU service and not a DFU client, I'd figured I'd have to implement that myself. As a base, I started at ble_lbs_c.

I have replaced

#define LBS_UUID_BASE {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, \
0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00}
#define LBS_UUID_SERVICE 0x1523

by

#define BLE_DFU_UUID_BASE     { 0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, \
                            0x60, 0x4F, 0x15, 0xF3, 0x00, 0x00, 0xC9, 0x8E }
#define BLE_DFU_SERVICE (0xFE59)

Now, the central connects to a peripheral in bootloader, but it is not able to find the bootloader service.

When I scan the device with the Android version of nRF Connect, it does show there is a service 0xFE59.

When I add a on_adv_report handler, a call to ble_advdata_uuid_find reveals there is no uuid data in the advertisement.

How can I properly detect the DFU Service running on a peripheral from a central?

Parents
  • Hi,

    If you mimic ble_lbs_c, you can see how it searches for the characteristics in the loop ble_lbs_on_db_disc_evt() which is called from the discovery even handler in main.c. Can you show how you have handled the service discovery in your code? The same procedure is the same with any service.

  • Here it is, this is a modified version of the original, with just the characteristics replaced, and a "service not found" log added.

    void ble_dfu_on_db_disc_evt(ble_dfu_c_t *p_ble_dfu_c,
    		ble_db_discovery_evt_t const *p_evt) {
    	// Check if the Led Button Service was discovered.
    	if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE
    			&& p_evt->params.discovered_db.srv_uuid.uuid == BLE_DFU_SERVICE
    			&& p_evt->params.discovered_db.srv_uuid.type
    					== p_ble_dfu_c->uuid_type) {
    		ble_dfu_c_evt_t evt;
    
    		evt.evt_type = BLE_LBS_C_EVT_DISCOVERY_COMPLETE;
    		evt.conn_handle = p_evt->conn_handle;
    
    		for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++) {
    			const ble_gatt_db_char_t *p_char =
    					&(p_evt->params.discovered_db.charateristics[i]);
    			switch (p_char->characteristic.uuid.uuid) {
    			case BLE_DFU_BUTTONLESS_CHAR_UUID:
    				NRF_LOG_DEBUG("Setting BLE_DFU_BUTTONLESS_CHAR_UUID.")
    				;
    				evt.params.peer_db.dfu_buttonless =
    						p_char->characteristic.handle_value;
    				break;
    
    			case BLE_DFU_PACKET_CHAR_UUID:
    				NRF_LOG_DEBUG("Setting BLE_DFU_PACKET_CHAR_UUID.")
    				;
    				evt.params.peer_db.dfu_packet =
    						p_char->characteristic.handle_value;
    				break;
    			case BLE_DFU_CONTROL_CHAR_UUID:
    				NRF_LOG_DEBUG("Setting BLE_DFU_CONTROL_CHAR_UUID.")
    				;
    				evt.params.peer_db.dfu_control =
    						p_char->characteristic.handle_value;
    				break;
    
    			default:
    				break;
    			}
    		}
    
    		NRF_LOG_DEBUG("DFU Service discovered at peer.");
    		//If the instance has been assigned prior to db_discovery, assign the db_handles
    		if (p_ble_dfu_c->conn_handle != BLE_CONN_HANDLE_INVALID) {
    			if ((p_ble_dfu_c->peer_lbs_db.dfu_buttonless
    					== BLE_GATT_HANDLE_INVALID)
    					&& (p_ble_dfu_c->peer_lbs_db.dfu_control
    							== BLE_GATT_HANDLE_INVALID)
    					&& (p_ble_dfu_c->peer_lbs_db.dfu_packet
    							== BLE_GATT_HANDLE_INVALID)
    					&& (p_ble_dfu_c->peer_lbs_db.dfu_cccd_handle
    							== BLE_GATT_HANDLE_INVALID)) {
    				p_ble_dfu_c->peer_lbs_db = evt.params.peer_db;
    			}
    		}
    
    		p_ble_dfu_c->evt_handler(p_ble_dfu_c, &evt);
    
    	} else {
    		NRF_LOG_INFO("SERVICE NOT FOUND!");
    	}
    }

    So, in the first case, I get an evt_type = BLE_DB_DISCOVERY_SRV_NOT_FOUND

    WIth the extra call to the soft device, it ends up with BLE_DB_DISCOVERY_COMPLETE and char_count = 0

Reply
  • Here it is, this is a modified version of the original, with just the characteristics replaced, and a "service not found" log added.

    void ble_dfu_on_db_disc_evt(ble_dfu_c_t *p_ble_dfu_c,
    		ble_db_discovery_evt_t const *p_evt) {
    	// Check if the Led Button Service was discovered.
    	if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE
    			&& p_evt->params.discovered_db.srv_uuid.uuid == BLE_DFU_SERVICE
    			&& p_evt->params.discovered_db.srv_uuid.type
    					== p_ble_dfu_c->uuid_type) {
    		ble_dfu_c_evt_t evt;
    
    		evt.evt_type = BLE_LBS_C_EVT_DISCOVERY_COMPLETE;
    		evt.conn_handle = p_evt->conn_handle;
    
    		for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++) {
    			const ble_gatt_db_char_t *p_char =
    					&(p_evt->params.discovered_db.charateristics[i]);
    			switch (p_char->characteristic.uuid.uuid) {
    			case BLE_DFU_BUTTONLESS_CHAR_UUID:
    				NRF_LOG_DEBUG("Setting BLE_DFU_BUTTONLESS_CHAR_UUID.")
    				;
    				evt.params.peer_db.dfu_buttonless =
    						p_char->characteristic.handle_value;
    				break;
    
    			case BLE_DFU_PACKET_CHAR_UUID:
    				NRF_LOG_DEBUG("Setting BLE_DFU_PACKET_CHAR_UUID.")
    				;
    				evt.params.peer_db.dfu_packet =
    						p_char->characteristic.handle_value;
    				break;
    			case BLE_DFU_CONTROL_CHAR_UUID:
    				NRF_LOG_DEBUG("Setting BLE_DFU_CONTROL_CHAR_UUID.")
    				;
    				evt.params.peer_db.dfu_control =
    						p_char->characteristic.handle_value;
    				break;
    
    			default:
    				break;
    			}
    		}
    
    		NRF_LOG_DEBUG("DFU Service discovered at peer.");
    		//If the instance has been assigned prior to db_discovery, assign the db_handles
    		if (p_ble_dfu_c->conn_handle != BLE_CONN_HANDLE_INVALID) {
    			if ((p_ble_dfu_c->peer_lbs_db.dfu_buttonless
    					== BLE_GATT_HANDLE_INVALID)
    					&& (p_ble_dfu_c->peer_lbs_db.dfu_control
    							== BLE_GATT_HANDLE_INVALID)
    					&& (p_ble_dfu_c->peer_lbs_db.dfu_packet
    							== BLE_GATT_HANDLE_INVALID)
    					&& (p_ble_dfu_c->peer_lbs_db.dfu_cccd_handle
    							== BLE_GATT_HANDLE_INVALID)) {
    				p_ble_dfu_c->peer_lbs_db = evt.params.peer_db;
    			}
    		}
    
    		p_ble_dfu_c->evt_handler(p_ble_dfu_c, &evt);
    
    	} else {
    		NRF_LOG_INFO("SERVICE NOT FOUND!");
    	}
    }

    So, in the first case, I get an evt_type = BLE_DB_DISCOVERY_SRV_NOT_FOUND

    WIth the extra call to the soft device, it ends up with BLE_DB_DISCOVERY_COMPLETE and char_count = 0

Children
  • Hi,

    I have not seen how you configure the SoftDevice and service discovery, but the typical reason for detecting the DFU service but not the DFU characteristics is failing to consider that the DFU characteristics are custom UUID's even thought the DFU service is a registered UUID. Therefore you need to:

    1. Add vendor-specific base UUID to use with the Buttonless DFU characteristic when configuring the service discovery module, using, for instance, this snippet (BLE_NORDIC_VENDOR_BASE_UUID is defined in ble_dfu.h):

     

        // Add vendor specific base UUID to use with the Buttonless DFU characteristic.
        ble_uuid128_t   nordic_base_uuid = BLE_NORDIC_VENDOR_BASE_UUID;
        ret_code_t err_code = sd_ble_uuid_vs_add(&nordic_base_uuid, &m_dfu_char_uuid_type);
        VERIFY_SUCCESS(err_code);

    2. For the above to work you must also make sure you have allocated memory for a custom UUID in the SoftDevice configuration. If not, the call to sd_ble_uuid_vs_add will return NRF_ERROR_NO_MEM). To do that, increment NRF_SDH_BLE_VS_UUID_COUNT in your sdk_config.h, and adust the app ram start and size address according to what is printed in the debug log.

    If this does not solve the problem, then please let me see more of your code, at least how you configure the service discovery (similar to for instance ble_lbs_c_init()).

Related