This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

CTS (current time service) import to NUS in nrf52810

Hi Sir/Miss,

I use SDK 17.0.2 version and softdevice s112 7.2.0 version to develop in nrf52810.

And, I base on this project (NUS with static passkey) which imports CTS_C to my project. (reference ble_app_cts_c example)

Except that services, I add GLS, DIS and BAS. 

For this requirement, add cts service in service_init(), current_time_error_handler, db_discovery_init and scheduler_init in project

static void on_cts_c_evt(ble_cts_c_t * p_cts, ble_cts_c_evt_t * p_evt)
{
    ret_code_t err_code;

    switch (p_evt->evt_type)
    {
        case BLE_CTS_C_EVT_DISCOVERY_COMPLETE:
            NRF_LOG_INFO("Current Time Service discovered on server.");
            err_code = ble_cts_c_handles_assign(&m_cts_c,
                                                p_evt->conn_handle,
                                                &p_evt->params.char_handles);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_CTS_C_EVT_DISCOVERY_FAILED:
            NRF_LOG_INFO("Current Time Service not found on server. ");
            // CTS not found in this case we just disconnect. There is no reason to stay
            // in the connection for this simple app since it all wants is to interact with CT
            if (p_evt->conn_handle != BLE_CONN_HANDLE_INVALID)
            {
                err_code = sd_ble_gap_disconnect(p_evt->conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_CTS_C_EVT_DISCONN_COMPLETE:
            NRF_LOG_INFO("Disconnect Complete.");
            break;

        case BLE_CTS_C_EVT_CURRENT_TIME:
            NRF_LOG_INFO("Current Time received.");
            current_time_print(p_evt);
            break;

        case BLE_CTS_C_EVT_INVALID_TIME:
            NRF_LOG_INFO("Invalid Time received.");
            break;

        default:
            break;
    }
}

void services_init(void)
{
    uint32_t           err_code;
    ble_nus_init_t     nus_init;
    
    ble_gls_init_t     gls_init;
    ble_dis_sys_id_t   sys_id_init;
    ble_bas_init_t     bas_init;    
        
    nrf_ble_qwr_init_t qwr_init = {0};
    
    ble_cts_c_init_t   cts_init = {0};

    // Initialize Queued Write Module.
    qwr_init.error_handler = nrf_qwr_error_handler;

    err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
    APP_ERROR_CHECK(err_code);
    
    // Initialize CTS.
    cts_init.evt_handler   = on_cts_c_evt;
    cts_init.error_handler = current_time_error_handler;
    cts_init.p_gatt_queue  = &m_ble_gatt_queue;
    err_code               = ble_cts_c_init(&m_cts_c, &cts_init);
    APP_ERROR_CHECK(err_code);
    
    // Initialize Glucose Service - sample selection of feature bits.
    memset(&gls_init, 0, sizeof(gls_init));

    gls_init.evt_handler          = NULL;
    gls_init.p_gatt_queue         = &m_ble_gatt_queue;
    gls_init.error_handler        = service_error_handler;
    gls_init.feature              = 0;
    gls_init.feature             |= BLE_GLS_FEATURE_LOW_BATT;
    gls_init.feature             |= BLE_GLS_FEATURE_TEMP_HIGH_LOW;
    gls_init.feature             |= BLE_GLS_FEATURE_GENERAL_FAULT;
    gls_init.is_context_supported = false;

    // Here the sec level for the Glucose Service can be changed/increased.
    gls_init.gl_meas_cccd_wr_sec = SEC_MITM;//SEC_JUST_WORKS;
    gls_init.gl_feature_rd_sec   = SEC_MITM;//SEC_JUST_WORKS;
    gls_init.racp_cccd_wr_sec    = SEC_MITM;//SEC_JUST_WORKS;
    gls_init.racp_wr_sec         = SEC_MITM;//SEC_JUST_WORKS;

    err_code = ble_gls_init(&m_gls, &gls_init);
    APP_ERROR_CHECK(err_code);
    
    // Initialize NUS.
    memset(&nus_init, 0, sizeof(nus_init));

    nus_init.data_handler = nus_data_handler;

    err_code = ble_nus_init(&m_nus, &nus_init);
    APP_ERROR_CHECK(err_code);

    
    // Initialize Battery Service.
    memset(&bas_init, 0, sizeof(bas_init));

    // Here the sec level for the Battery Service can be changed/increased.
    bas_init.bl_rd_sec        = SEC_OPEN;
    bas_init.bl_cccd_wr_sec   = SEC_OPEN;
    bas_init.bl_report_rd_sec = SEC_OPEN;

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&m_bas, &bas_init);
    APP_ERROR_CHECK(err_code);
    

    // Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);

	
    ble_srv_ascii_to_utf8(&dis_init.serial_num_str, M_device_serial_num);
    ble_srv_ascii_to_utf8(&dis_init.model_num_str, M_device_model_name);
    ble_srv_ascii_to_utf8(&dis_init.hw_rev_str, M_device_pcb_ver);
    ble_srv_ascii_to_utf8(&dis_init.fw_rev_str, M_device_fw_ver);
    ble_srv_ascii_to_utf8(&dis_init.sw_rev_str, SW_VER);
    
    dis_init.hw_rev_str.length = DEVICE_PCB_VER_LEN;

	// Get device mac address
    ble_gap_addr_t device_addr;
    uint8_t temp_sys_manufacturer_id[5];
    uint8_t temp_sys_organizationally_unique_id[3];
    
    memset(&sys_id_init, 0, sizeof(sys_id_init));
    
    err_code = sd_ble_gap_addr_get(&device_addr);
    APP_ERROR_CHECK(err_code);
    
    
    //uint8_t *a = device_addr->addr[0];
    
    for(uint8_t i = 0; i < 6; i++)
    {
      if(i < 3)
        temp_sys_organizationally_unique_id[2 - i] = device_addr.addr[i];
      else
        temp_sys_manufacturer_id[5 - i] = device_addr.addr[i];
    }
    temp_sys_manufacturer_id[3] = 0xFF;
    temp_sys_manufacturer_id[4] = 0xFE;
    
    uint32_t sys_manufacturer_id = 0, sys_organizationally_unique_id = 0;
    
    sys_manufacturer_id |= temp_sys_manufacturer_id[0];
    sys_manufacturer_id |= temp_sys_manufacturer_id[1] << 8;
    sys_manufacturer_id |= temp_sys_manufacturer_id[2] << 16;
    sys_manufacturer_id |= temp_sys_manufacturer_id[3] << 24;    
    sys_id_init.manufacturer_id = sys_manufacturer_id;
    sys_id_init.manufacturer_id |= ((uint64_t)temp_sys_manufacturer_id[4] << 32);
    
    sys_organizationally_unique_id |= temp_sys_organizationally_unique_id[0];
    sys_organizationally_unique_id |= temp_sys_organizationally_unique_id[1] << 8;
    sys_organizationally_unique_id |= temp_sys_organizationally_unique_id[2] << 16;  
    sys_id_init.organizationally_unique_id = sys_organizationally_unique_id;
    
    dis_init.p_sys_id = &sys_id_init;
	

    dis_init.dis_char_rd_sec = SEC_OPEN;

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);
}

void db_discovery_init(void)
{
    ble_db_discovery_init_t db_init;

    memset(&db_init, 0, sizeof(ble_db_discovery_init_t));

    db_init.evt_handler  = db_disc_handler;
    db_init.p_gatt_queue = &m_ble_gatt_queue;

    ret_code_t err_code = ble_db_discovery_init(&db_init);
    APP_ERROR_CHECK(err_code);
}

My process is getting device name, FW version and etc from other's MCU. Then, nRF52810 starts advertising.

I use APP nRF connect to test it.

When APP connects with device, it can be discover CTS in advertised service.

But, it can not enter on_cts_evt in BLE_CTS_C_EVT_DISCOVERY_COMPLETE when I set break point in this code.

In cts_c example, it can have  the event to enter this function.

Therefore, I can't get current time from phone.

Which part is missing in my project?

Please help.

Thank you.

0652.sdk_config.h

  • you need to trigger te cts_discovery event handler from the d_disc_handler as below

    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
        ble_cts_c_on_db_disc_evt(&m_cts_c, p_evt);
    }

    Without this, your CTS service will not know of any discovery events and hence cannot trigger and event callbacks for any relevant attribute handles.

  • I've added it in db_discovery_init() and check it which function is put after gatt_init() before this post.

    But, it still can't be trigger. Is there any other factor causing this problem?

    Thank you for your reply.

    void db_discovery_init(void)
    {
        ble_db_discovery_init_t db_init;
    
        memset(&db_init, 0, sizeof(ble_db_discovery_init_t));
    
        db_init.evt_handler  = db_disc_handler;
        db_init.p_gatt_queue = &m_ble_gatt_queue;
    
        ret_code_t err_code = ble_db_discovery_init(&db_init);
        APP_ERROR_CHECK(err_code);
    }

  • No, i can't think of anything. I need to get your project for debugging. Can you please attach a minimalist zipped project to reproduce the problem at my end?

  • Here is my project. Please check this.

    I'm not sure your IAR version. Therefore, I try to modify .ewp file to 8.40.2.

    Maybe, that might work.

    Please check it.

    If there are issues in IDE problem, please tell me.

    Thanks a lot.

  • Hi, I did not manage to compile it with the network license we have. Can you please give me link to the installer for this version so that i can download it and run it with trial version. Right now i have difficulty finding the installer for version 8.40.2

Related