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

How to notify several characteristics in central

Hi, I am using ble_app_hrs_c as the base for central. I have included 5 characteristics in the peripheral and central side. How to make ble_nus_c_rx_notif_enable() to notify when any of the 5 characteristics is updated? At the moment, ble_nus_c_rx_notif_enable has only this: return cccd_configure(p_ble_nus_c->conn_handle,p_ble_nus_c->handles.nus_rx_cccd_handle, true);

How do I change it so that I get notification even when nus_rx_wheel_status_handle also receives a notification? My ble_nus_c_handles_t looks like this:

typedef struct {
    uint16_t                nus_rx_wheel_control_handle;      

    uint16_t                nus_rx_wheel_control_cccd_handle; /**< Handle of the CCCD of the NUS RX characteristic as provided by a discovery. */
    uint16_t                nus_rx_wheel_status_handle;	
    uint16_t                nus_rx_wheel_status_cccd_handle;	
    uint16_t                nus_rx_wheel_battery_handle;	
    uint16_t                nus_rx_wheel_battery_cccd_handle;		
    uint16_t                nus_rx_wheel_information_handle;	
    uint16_t                nus_rx_wheel_information_cccd_handle;		
    uint16_t                nus_rx_wheel_debug_handle;	
    uint16_t                nus_rx_wheel_debug_cccd_handle;		
    uint16_t                nus_tx_handle_wheel_control;      /**< Handle of the NUS TX characteristic as provided by a discovery. */
    uint16_t                nus_tx_handle_wheel_status;	
    uint16_t                nus_tx_handle_wheel_battery;	
    uint16_t                nus_tx_handle_wheel_information;		
    uint16_t                nus_tx_handle_wheel_debug;		
} ble_nus_c_handles_t;

The code works fine when I enable notification for one character at a time.

Parents
  • If you are using write request you have to enable one notification at the time, because you can only do one write request at the time, you have to wait for the response before you send a new one.

    And I think you must use write request to write to descriptors. You could of course try to use write command instead.

  • Hi Petter, Thanks for the reply. In the central code, in the ble_nus_c_rx_notif_enable, I have configured only one of the characteristics as shown below:

    uint32_t ble_nus_c_rx_notif_enable(ble_nus_c_t * p_ble_nus_c)
    {
        VERIFY_PARAM_NOT_NULL(p_ble_nus_c);
    
        if ( (p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID)
           ||(p_ble_nus_c->handles.nus_rx_debug_cccd_handle == BLE_GATT_HANDLE_INVALID)
    			||(p_ble_nus_c->handles.nus_rx_speed_cccd_handle == BLE_GATT_HANDLE_INVALID)
    			||(p_ble_nus_c->handles.nus_rx_information_cccd_handle == BLE_GATT_HANDLE_INVALID)
           )
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
    		return cccd_configure(p_ble_nus_c->conn_handle,p_ble_nus_c->handles.nus_rx_speed_cccd_handle, true);
    
    }
    

    I have configured only for 1 characteristic in ble_nus_c_rx_notif_enable because, if I configure for more than 1 characteristic, I get NRF_ERROR_BUSY error. Also, upon discovery event, I assign cccd handles for all the characteristics as shown below:

    void ble_nus_c_on_db_disc_evt(ble_nus_c_t * p_ble_nus_c, ble_db_discovery_evt_t * p_evt)
    {
        ble_nus_c_evt_t nus_c_evt;
        memset(&nus_c_evt,0,sizeof(ble_nus_c_evt_t));
    
        ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;
    
        // Check if the NUS was discovered.
        if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
            p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_NUS_SERVICE &&
            p_evt->params.discovered_db.srv_uuid.type == p_ble_nus_c->uuid_type)
        {
    
            uint32_t i;
    
            for (i = 0; i < p_evt->params.discovered_db.char_count; i++)
            {
                switch (p_chars[i].characteristic.uuid.uuid)
                {
    
                    case BLE_UUID_NUS_RX_SPEED_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_speed_handle = p_chars[i].characteristic.handle_value;
                        nus_c_evt.handles.nus_rx_speed_cccd_handle = p_chars[i].cccd_handle;
                        break;
    
                    case BLE_UUID_NUS_TX_SPEED_CHARACTERISTIC:
                        nus_c_evt.handles.nus_tx_handle_speed = p_chars[i].characteristic.handle_value;
                        break;
    								
                    case BLE_UUID_NUS_RX_INFORMATION_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_information_handle = p_chars[i].characteristic.handle_value;
                        nus_c_evt.handles.nus_rx_information_cccd_handle = p_chars[i].cccd_handle;
                        break;
    
                    case BLE_UUID_NUS_TX_INFORMATION_CHARACTERISTIC:
                        nus_c_evt.handles.nus_tx_handle_information = p_chars[i].characteristic.handle_value;
                        break;								
    
    								
                    case BLE_UUID_NUS_RX_DEBUG_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_debug_handle = p_chars[i].characteristic.handle_value;
                        nus_c_evt.handles.nus_rx_debug_cccd_handle = p_chars[i].cccd_handle;
                        break;
    
                    case BLE_UUID_NUS_TX_DEBUG_CHARACTERISTIC:
                        nus_c_evt.handles.nus_tx_handle_debug = p_chars[i].characteristic.handle_value;
                        break;		
    
                    case BLE_UUID_NUS_RX_CONTROL_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_control_handle = p_chars[i].characteristic.handle_value;
                        nus_c_evt.handles.nus_rx_control_cccd_handle = p_chars[i].cccd_handle;
                        break;
    
                    case BLE_UUID_NUS_TX_CONTROL_CHARACTERISTIC:
                        nus_c_evt.handles.nus_tx_handle_control = p_chars[i].characteristic.handle_value;
                        break;									
    								
    
                    default:
                        break;
                }
            }
            if (p_ble_nus_c->evt_handler != NULL)
            {
                nus_c_evt.conn_handle = p_evt->conn_handle;
                nus_c_evt.evt_type    = BLE_NUS_C_EVT_DISCOVERY_COMPLETE;
                p_ble_nus_c->evt_handler(p_ble_nus_c, &nus_c_evt);
            }
        }
    }
    

    Also I have used the following routines:

    static uint32_t cccd_configure(uint16_t conn_handle, uint16_t cccd_handle, bool enable)
    {
        uint8_t buf[BLE_CCCD_VALUE_LEN];
    
        buf[0] = enable ? BLE_GATT_HVX_NOTIFICATION : 0;
        buf[1] = 0;
    
        const ble_gattc_write_params_t write_params = {
            .write_op = BLE_GATT_OP_WRITE_REQ,
            .flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
            .handle   = cccd_handle,
            .offset   = 0,
            .len      = sizeof(buf),
            .p_value  = buf
        };
    
        return sd_ble_gattc_write(conn_handle, &write_params);
    }
    
    uint32_t ble_nus_c_handles_assign(ble_nus_c_t * p_ble_nus,
                                      const uint16_t conn_handle,
                                      const ble_nus_c_handles_t * p_peer_handles)
    {
        VERIFY_PARAM_NOT_NULL(p_ble_nus);
    
        p_ble_nus->conn_handle = conn_handle;
        if (p_peer_handles != NULL)
        {
            p_ble_nus->handles.nus_rx_control_cccd_handle = p_peer_handles->nus_rx_control_cccd_handle;
            p_ble_nus->handles.nus_rx_control_handle      = p_peer_handles->nus_rx_control_handle;
            p_ble_nus->handles.nus_tx_handle_control      = p_peer_handles->nus_tx_handle_control;
    			
            p_ble_nus->handles.nus_rx_speed_cccd_handle = p_peer_handles->nus_rx_speed_cccd_handle;
            p_ble_nus->handles.nus_rx_speed_handle      = p_peer_handles->nus_rx_speed_handle;
            p_ble_nus->handles.nus_tx_handle_speed      = p_peer_handles->nus_tx_handle_speed;		
    			
            p_ble_nus->handles.nus_rx_information_cccd_handle = p_peer_handles->nus_rx_information_cccd_handle;
            p_ble_nus->handles.nus_rx_information_handle      = p_peer_handles->nus_rx_information_handle;
            p_ble_nus->handles.nus_tx_handle_information      = p_peer_handles->nus_tx_handle_information;				
    			
    
            p_ble_nus->handles.nus_rx_debug_cccd_handle = p_peer_handles->nus_rx_debug_cccd_handle;
            p_ble_nus->handles.nus_rx_debug_handle      = p_peer_handles->nus_rx_debug_handle;
            p_ble_nus->handles.nus_tx_handle_debug      = p_peer_handles->nus_tx_handle_debug;			
        }
        return NRF_SUCCESS;
    }
    
Reply
  • Hi Petter, Thanks for the reply. In the central code, in the ble_nus_c_rx_notif_enable, I have configured only one of the characteristics as shown below:

    uint32_t ble_nus_c_rx_notif_enable(ble_nus_c_t * p_ble_nus_c)
    {
        VERIFY_PARAM_NOT_NULL(p_ble_nus_c);
    
        if ( (p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID)
           ||(p_ble_nus_c->handles.nus_rx_debug_cccd_handle == BLE_GATT_HANDLE_INVALID)
    			||(p_ble_nus_c->handles.nus_rx_speed_cccd_handle == BLE_GATT_HANDLE_INVALID)
    			||(p_ble_nus_c->handles.nus_rx_information_cccd_handle == BLE_GATT_HANDLE_INVALID)
           )
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
    		return cccd_configure(p_ble_nus_c->conn_handle,p_ble_nus_c->handles.nus_rx_speed_cccd_handle, true);
    
    }
    

    I have configured only for 1 characteristic in ble_nus_c_rx_notif_enable because, if I configure for more than 1 characteristic, I get NRF_ERROR_BUSY error. Also, upon discovery event, I assign cccd handles for all the characteristics as shown below:

    void ble_nus_c_on_db_disc_evt(ble_nus_c_t * p_ble_nus_c, ble_db_discovery_evt_t * p_evt)
    {
        ble_nus_c_evt_t nus_c_evt;
        memset(&nus_c_evt,0,sizeof(ble_nus_c_evt_t));
    
        ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;
    
        // Check if the NUS was discovered.
        if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
            p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_NUS_SERVICE &&
            p_evt->params.discovered_db.srv_uuid.type == p_ble_nus_c->uuid_type)
        {
    
            uint32_t i;
    
            for (i = 0; i < p_evt->params.discovered_db.char_count; i++)
            {
                switch (p_chars[i].characteristic.uuid.uuid)
                {
    
                    case BLE_UUID_NUS_RX_SPEED_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_speed_handle = p_chars[i].characteristic.handle_value;
                        nus_c_evt.handles.nus_rx_speed_cccd_handle = p_chars[i].cccd_handle;
                        break;
    
                    case BLE_UUID_NUS_TX_SPEED_CHARACTERISTIC:
                        nus_c_evt.handles.nus_tx_handle_speed = p_chars[i].characteristic.handle_value;
                        break;
    								
                    case BLE_UUID_NUS_RX_INFORMATION_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_information_handle = p_chars[i].characteristic.handle_value;
                        nus_c_evt.handles.nus_rx_information_cccd_handle = p_chars[i].cccd_handle;
                        break;
    
                    case BLE_UUID_NUS_TX_INFORMATION_CHARACTERISTIC:
                        nus_c_evt.handles.nus_tx_handle_information = p_chars[i].characteristic.handle_value;
                        break;								
    
    								
                    case BLE_UUID_NUS_RX_DEBUG_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_debug_handle = p_chars[i].characteristic.handle_value;
                        nus_c_evt.handles.nus_rx_debug_cccd_handle = p_chars[i].cccd_handle;
                        break;
    
                    case BLE_UUID_NUS_TX_DEBUG_CHARACTERISTIC:
                        nus_c_evt.handles.nus_tx_handle_debug = p_chars[i].characteristic.handle_value;
                        break;		
    
                    case BLE_UUID_NUS_RX_CONTROL_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_control_handle = p_chars[i].characteristic.handle_value;
                        nus_c_evt.handles.nus_rx_control_cccd_handle = p_chars[i].cccd_handle;
                        break;
    
                    case BLE_UUID_NUS_TX_CONTROL_CHARACTERISTIC:
                        nus_c_evt.handles.nus_tx_handle_control = p_chars[i].characteristic.handle_value;
                        break;									
    								
    
                    default:
                        break;
                }
            }
            if (p_ble_nus_c->evt_handler != NULL)
            {
                nus_c_evt.conn_handle = p_evt->conn_handle;
                nus_c_evt.evt_type    = BLE_NUS_C_EVT_DISCOVERY_COMPLETE;
                p_ble_nus_c->evt_handler(p_ble_nus_c, &nus_c_evt);
            }
        }
    }
    

    Also I have used the following routines:

    static uint32_t cccd_configure(uint16_t conn_handle, uint16_t cccd_handle, bool enable)
    {
        uint8_t buf[BLE_CCCD_VALUE_LEN];
    
        buf[0] = enable ? BLE_GATT_HVX_NOTIFICATION : 0;
        buf[1] = 0;
    
        const ble_gattc_write_params_t write_params = {
            .write_op = BLE_GATT_OP_WRITE_REQ,
            .flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
            .handle   = cccd_handle,
            .offset   = 0,
            .len      = sizeof(buf),
            .p_value  = buf
        };
    
        return sd_ble_gattc_write(conn_handle, &write_params);
    }
    
    uint32_t ble_nus_c_handles_assign(ble_nus_c_t * p_ble_nus,
                                      const uint16_t conn_handle,
                                      const ble_nus_c_handles_t * p_peer_handles)
    {
        VERIFY_PARAM_NOT_NULL(p_ble_nus);
    
        p_ble_nus->conn_handle = conn_handle;
        if (p_peer_handles != NULL)
        {
            p_ble_nus->handles.nus_rx_control_cccd_handle = p_peer_handles->nus_rx_control_cccd_handle;
            p_ble_nus->handles.nus_rx_control_handle      = p_peer_handles->nus_rx_control_handle;
            p_ble_nus->handles.nus_tx_handle_control      = p_peer_handles->nus_tx_handle_control;
    			
            p_ble_nus->handles.nus_rx_speed_cccd_handle = p_peer_handles->nus_rx_speed_cccd_handle;
            p_ble_nus->handles.nus_rx_speed_handle      = p_peer_handles->nus_rx_speed_handle;
            p_ble_nus->handles.nus_tx_handle_speed      = p_peer_handles->nus_tx_handle_speed;		
    			
            p_ble_nus->handles.nus_rx_information_cccd_handle = p_peer_handles->nus_rx_information_cccd_handle;
            p_ble_nus->handles.nus_rx_information_handle      = p_peer_handles->nus_rx_information_handle;
            p_ble_nus->handles.nus_tx_handle_information      = p_peer_handles->nus_tx_handle_information;				
    			
    
            p_ble_nus->handles.nus_rx_debug_cccd_handle = p_peer_handles->nus_rx_debug_cccd_handle;
            p_ble_nus->handles.nus_rx_debug_handle      = p_peer_handles->nus_rx_debug_handle;
            p_ble_nus->handles.nus_tx_handle_debug      = p_peer_handles->nus_tx_handle_debug;			
        }
        return NRF_SUCCESS;
    }
    
Children
No Data
Related