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

Can I create Characteristic with Notification only, no Read, no Write

Can I create Characteristic with Notification only, no Read, no Write

I can remove the //char_md.char_props.write = 1; and only the Read and Notify Properties show up in MCP (or the iPhone)

When I comment out the char_md.char_props.read = 1;

Advertising stops and I can not connect to the device.

All I need is a Notification. The server collects data on three (3) sensors, and sends the data using three (3) services. 6-bytes per service, nonstop.

So actually one characteristic with a Notification per service.

Note: I guess eventually with a client app, one would Enable the Notification, and then ignore the Read property.

Any help appreciated

  • It is possible, but you are doing something wrong elsewhere (setting value of characteristic maybe?). When there is only notification possible, don't set the value, but just send notification.

  • Can you post the function where you set the attributes and add the characteristic?

  • Bjørn

    I have it working. It seems than with no delay between CCCD updates, the code freezes. So it seems with both write and read out, the Notification keeps the code busy. I now have a 2sec delay between updates, and removed write and read, and it works fine.

    static uint32_t our_char_add(ble_os_t * p_our_service) { uint32_t err_code = 0; // Variable to hold return codes from library and softdevice functions

    // OUR_JOB: Step 2.A, Add a custom characteristic UUID
    ble_uuid_t          char_uuid;
    ble_uuid128_t       base_uuid = BLE_UUID_OUR_BASE_UUID;
    char_uuid.uuid      = BLE_UUID_OUR_CHARACTERISTC_UUID;
    sd_ble_uuid_vs_add(&base_uuid, &char_uuid.type);
    APP_ERROR_CHECK(err_code);
    
    // OUR_JOB: Step 2.F Add read/write properties to our characteristic
    ble_gatts_char_md_t char_md;
    memset(&char_md, 0, sizeof(char_md));
    //GvR
    //char_md.char_props.read = 1;
    //GvR
    //char_md.char_props.write = 1;
    
    
    // OUR_JOB: Step 3.A, Configuring Client Characteristic Configuration Descriptor metadata and add to char_md structure
    ble_gatts_attr_md_t cccd_md;
    memset(&cccd_md, 0, sizeof(cccd_md));
    //GvR
    //BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&cccd_md.read_perm);
    //BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&cccd_md.write_perm);
    
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
    cccd_md.vloc                = BLE_GATTS_VLOC_STACK;    
    char_md.p_cccd_md           = &cccd_md;
    char_md.char_props.notify   = 1;
    
    
    // OUR_JOB: Step 2.B, Configure the attribute metadata
    ble_gatts_attr_md_t attr_md;
    memset(&attr_md, 0, sizeof(attr_md)); 
    attr_md.vloc        = BLE_GATTS_VLOC_STACK;   
    
    
    // OUR_JOB: Step 2.G, Set read/write security levels to our characteristic
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
    
    
    // OUR_JOB: Step 2.C, Configure the characteristic value attribute
    ble_gatts_attr_t    attr_char_value;
    memset(&attr_char_value, 0, sizeof(attr_char_value));        
    attr_char_value.p_uuid      = &char_uuid;
    attr_char_value.p_attr_md   = &attr_md;
    
    // OUR_JOB: Step 2.H, Set characteristic length in number of bytes
    //attr_char_value.max_len     = 3;
    //attr_char_value.init_len    = 3;
    //uint8_t value[3]            = {0x00, 0x73, 0xCF};
    attr_char_value.max_len     = 6;
    attr_char_value.init_len    = 6;
    uint8_t value[6]            = {0x16, 0x15, 0x14, 0x13, 0x12, 0x11};
    //uint8_t value[4]            = {0xA0,0xB1,0xC2,0xD3};
    //uint8_t value[4]            = {0x00, 0x73,0x63,0x63};
    
    attr_char_value.p_value     = value;
    
    // OUR_JOB: Step 2.E, Add our new characteristic to the service
    err_code = sd_ble_gatts_characteristic_add(p_our_service->service_handle,
                                       &char_md,
                                       &attr_char_value,
                                       &p_our_service->char_handles);
    APP_ERROR_CHECK(err_code);
    
    NRF_LOG_INFO("\r\nService handle: %#x\n\r", p_our_service->service_handle);
    NRF_LOG_INFO("Char value handle: %#x\r\n", p_our_service->char_handles.value_handle);
    NRF_LOG_INFO("Char cccd handle: %#x\r\n\r\n", p_our_service->char_handles.cccd_handle);
    
    return NRF_SUCCESS;
    

    }

  • It seems than with no delay between CCCD updates, the code freezes. So it seems with both write and read out, the Notification keeps the code busy. I now have a 2sec delay between updates, and removed write and read, and it works fine.

    Are you enabling and disabling Notifications(writting to the CCCD) or do you mean that you are notifying the value of the characteristic very often using sd_ble_gatts_hvx?

  • Bjørn, Yes, I mean updating the characteristic, not en/disabling of Notification.

    I actually just tested it. I call

    void our_termperature_characteristic_update(ble_os_t *p_our_service, int8_t *temperature_value)

    which calls sd_ble_gatts_hvx(p_our_service->conn_handle, &hvx_params);

    I call three (3) Characteristic updates in succession sv(1..3)_termperature_characteristic_update() One after the other, no delay, and it seems to work.

    In between the three updates, there is timer delay.

    I decreased the timer interrupt to 1ms in between the tree calls, just to test, so all looks good. In the real world I have this timer set to 2 or 3 seconds.

    I assume something else was wrong earlier.

    Thanks

Related