<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/58880/setting-custom-gatt-characteristic-data</link><description>Hi, 
 I want to set a custom value to my Gatt characteristic value. I can do this by writing to the characteristic in my app or the NRF_connect application. 
 What I want to do is based on an event or the data I receive to change the GATT characteristic</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 11 May 2020 12:00:05 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/58880/setting-custom-gatt-characteristic-data" /><item><title>RE: Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/thread/249184?ContentTypeID=1</link><pubDate>Mon, 11 May 2020 12:00:05 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5d78e951-445b-4b7c-be47-320bd0dbde45</guid><dc:creator>Sigurd</dc:creator><description>&lt;p&gt;As indicated in my second reply, you can get the&amp;nbsp;BLE_ERROR_GATTS_INVALID_ATTR_TYPE if&amp;nbsp;&lt;span&gt;the handle you are using is pointing to a characteristic that don&amp;#39;t support notifications (char_props.notify).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This seems to be the case here, since you have&amp;nbsp;char_md.char_props.notify = 0; in your code(custom_value_char_add() function).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/thread/238991?ContentTypeID=1</link><pubDate>Tue, 10 Mar 2020 08:05:50 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b1cf12a2-c4fb-4f33-8998-da58a3db706d</guid><dc:creator>Thomas</dc:creator><description>&lt;p&gt;I call the ble_cus_custom_value_update() within my ble_cus.c code.&lt;/p&gt;
&lt;p&gt;I do it within a statemachine that handles processing of incoming data. This incoming data is handled via two statemachines. Process_Command and process_selected_value. Within this I have a help command that if run prints out help info is: . Then runs the command( this is for testing). Below is my code:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;quot;sdk_common.h&amp;quot;
#include &amp;quot;ble_srv_common.h&amp;quot;
#include &amp;quot;ble_cus.h&amp;quot;
#include &amp;lt;string.h&amp;gt;
#include &amp;quot;nrf_gpio.h&amp;quot;
#include &amp;quot;boards.h&amp;quot;
#include &amp;quot;nrf_log.h&amp;quot;

bool CMD_STARTED = false;
bool Print_log_enabled = false;//If ==1 enable printing log if == 0 dissabled
bool Processing_Commands = false;
static uint8_t m_custom_value = 77;
//Statemachine for GATT commands
enum
{
    CMD_BLE_STATE_START,
    CMD_BLE_STATE_STOP,
    CMD_BLE_STATE_SELECT_COMMAND,
    CMD_BLE_STATE_UART_LOGGING,
    CMD_BLE_STATE_SD_LOGGING,
    CMD_BLE_STATE_READ_A_DATUM,
    CMD_BLE_STATE_TIME_STAMP_START,//Might need several due to data limitations
    CMD_BLE_STATE_TIME_STAMP_RECEIVE_YEAR,
    CMD_BLE_STATE_TIME_STAMP_RECEIVE_MONTH,
    CMD_BLE_STATE_TIME_STAMP_RECEIVE_DAY,
    CMD_BLE_STATE_TIME_STAMP_RECEIVE_HOUR,
    CMD_BLE_STATE_TIME_STAMP_RECEIVE_MINUTE,
    CMD_BLE_STATE_TIME_STAMP_RECEIVE_SECOND,
    CMD_BLE_STATE_GET_LOG,//Get the SD card log
    CMD_BLE_STATE_HELP,
    CMD_BLE_STATE_ERROR,
} CMD_BLE_STATE_VALUE;


uint32_t ble_cus_init(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
{
    //Init statemachine for reading the commands

    CMD_BLE_STATE_VALUE = CMD_BLE_STATE_START;//Move to start state
    CMD_STARTED = true;

    if (p_cus == NULL || p_cus_init == NULL)
    {
        return NRF_ERROR_NULL;
    }

    uint32_t   err_code;
    ble_uuid_t ble_uuid;

    // Initialize service structure
    //p_cus-&amp;gt;evt_handler               = p_cus_init-&amp;gt;evt_handler;
    p_cus-&amp;gt;conn_handle               = BLE_CONN_HANDLE_INVALID;
    //p_cus-&amp;gt;conn_handle               = BLE_CONN_HANDLE_INVALID;

    // Add Custom Service UUID
    ble_uuid128_t base_uuid = {CUSTOM_SERVICE_UUID_BASE};
    err_code =  sd_ble_uuid_vs_add(&amp;amp;base_uuid, &amp;amp;p_cus-&amp;gt;uuid_type);
    VERIFY_SUCCESS(err_code);
    
    ble_uuid.type = p_cus-&amp;gt;uuid_type;
    ble_uuid.uuid = CUSTOM_SERVICE_UUID;

    // Add the Custom Service
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &amp;amp;ble_uuid, &amp;amp;p_cus-&amp;gt;service_handle);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    // Add Custom Value characteristic
    return custom_value_char_add(p_cus, p_cus_init);
}
uint32_t custom_value_char_add(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
{
    uint32_t            err_code;
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;

    memset(&amp;amp;char_md, 0, sizeof(char_md));

    char_md.char_props.read   = 1;
    char_md.char_props.write  = 1;
    char_md.char_props.notify = 0; 
    char_md.p_char_user_desc  = NULL;
    char_md.p_char_pf         = NULL;
    char_md.p_user_desc_md    = NULL;
    char_md.p_cccd_md         = NULL; 
    char_md.p_sccd_md         = NULL;
		
    memset(&amp;amp;attr_md, 0, sizeof(attr_md));

    attr_md.read_perm  = p_cus_init-&amp;gt;custom_value_char_attr_md.read_perm;
    attr_md.write_perm = p_cus_init-&amp;gt;custom_value_char_attr_md.write_perm;
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;

    ble_uuid.type = p_cus-&amp;gt;uuid_type;
    ble_uuid.uuid = CUSTOM_VALUE_CHAR_UUID;

    memset(&amp;amp;attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid    = &amp;amp;ble_uuid;
    attr_char_value.p_attr_md = &amp;amp;attr_md;
    attr_char_value.init_len  = sizeof(uint32_t);//was Uint8_t
    attr_char_value.init_offs = 0;
    attr_char_value.max_len   = sizeof(uint32_t);

    err_code = sd_ble_gatts_characteristic_add(p_cus-&amp;gt;service_handle, &amp;amp;char_md,
                                               &amp;amp;attr_char_value,
                                               &amp;amp;p_cus-&amp;gt;custom_value_handles);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    return NRF_SUCCESS;
}

void ble_cus_on_ble_evt( ble_evt_t const * p_ble_evt, void * p_context)
{
   ble_cus_t * p_cus = (ble_cus_t *) p_context;

   if (p_cus == NULL || p_ble_evt == NULL)
   {
       return;
   }
   
   switch (p_ble_evt-&amp;gt;header.evt_id)
   {
       case BLE_GAP_EVT_CONNECTED:
           on_connect(p_cus, p_ble_evt);
           break;

       case BLE_GAP_EVT_DISCONNECTED:
           on_disconnect(p_cus, p_ble_evt);
           break;
       case BLE_GATTS_EVT_WRITE:
           on_write(p_cus, p_ble_evt);
           break;
       default:
           // No implementation needed.
           break;
   }
}
void on_connect(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt)
{
    p_cus-&amp;gt;conn_handle = p_ble_evt-&amp;gt;evt.gap_evt.conn_handle;

}
void on_disconnect(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt)
{
    UNUSED_PARAMETER(p_ble_evt);
    p_cus-&amp;gt;conn_handle = BLE_CONN_HANDLE_INVALID;
}
void on_write(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt)
{
    ble_gatts_evt_write_t * p_evt_write = &amp;amp;p_ble_evt-&amp;gt;evt.gatts_evt.params.write;
    
    uint32_t found_data = 0;
    
    // Check if the handle passed with the event matches the Custom Value Characteristic handle.
    if (p_evt_write-&amp;gt;handle == p_cus-&amp;gt;custom_value_handles.value_handle)
    {
        memcpy(&amp;amp;found_data, p_ble_evt-&amp;gt;evt.gatts_evt.params.write.data, p_ble_evt-&amp;gt;evt.gatts_evt.params.write.len);

        Process_Command(p_cus, p_ble_evt,found_data);
    }
}
uint32_t ble_cus_custom_value_update(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt, uint8_t custom_value)
{
    NRF_LOG_INFO(&amp;quot;In ble_cus_custom_value_update. \r\n&amp;quot;); 
    if (p_cus == NULL)
    {
        return NRF_ERROR_NULL;
    }

    uint32_t err_code = NRF_SUCCESS;
    ble_gatts_value_t gatts_value;

    // Initialize value struct.
    memset(&amp;amp;gatts_value, 0, sizeof(gatts_value));

    gatts_value.len     = sizeof(uint8_t);
    gatts_value.offset  = 0;
    gatts_value.p_value = &amp;amp;custom_value;

    // Update database.
    err_code = sd_ble_gatts_value_set(p_cus-&amp;gt;conn_handle,
                                      p_cus-&amp;gt;custom_value_handles.value_handle,
                                      &amp;amp;gatts_value);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    // Send value if connected and notifying.
    if ((p_cus-&amp;gt;conn_handle != BLE_CONN_HANDLE_INVALID)) 
    {
        ble_gatts_hvx_params_t hvx_params;

        memset(&amp;amp;hvx_params, 0, sizeof(hvx_params));

        hvx_params.handle = p_cus-&amp;gt;custom_value_handles.value_handle;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
        hvx_params.offset = gatts_value.offset;
        hvx_params.p_len  = &amp;amp;gatts_value.len;
        hvx_params.p_data = gatts_value.p_value;

        err_code = sd_ble_gatts_hvx(p_cus-&amp;gt;conn_handle, &amp;amp;hvx_params);
    }
    else
    {
        err_code = NRF_ERROR_INVALID_STATE;
    }


    return err_code;
}
void Process_Command(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt, uint32_t command)
{
    if((command == CMD_BLE_START) &amp;amp;&amp;amp; (CMD_STARTED == 0))
    {
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_START;//Move to start state
        CMD_STARTED = true; 
    }
    NRF_LOG_INFO(&amp;quot;Command is: %d&amp;quot;,command);
    if(Processing_Commands == false){
        switch (CMD_BLE_STATE_VALUE)
        {
          case CMD_BLE_STATE_START://Start command issued
               //See next command
               NRF_LOG_INFO(&amp;quot;Start state&amp;quot;);
               CMD_BLE_STATE_VALUE = CMD_BLE_STATE_SELECT_COMMAND;  
               break;//Removed break as to fall into other states
           case CMD_BLE_STATE_SELECT_COMMAND://Start command issued
               //See next command
               NRF_LOG_INFO(&amp;quot;Command state&amp;quot;);
               if(command == CMD_BLE_STOP)
               {
                  CMD_BLE_STATE_VALUE = CMD_BLE_STATE_STOP;//Move to stop state
                  NRF_LOG_INFO(&amp;quot;Go to stop state&amp;quot;);
               }
               else if(command == CMD_BLE_HELP)//HELP
               {
                  CMD_BLE_STATE_VALUE = CMD_BLE_STATE_HELP;//Move to help state
                  NRF_LOG_INFO(&amp;quot;Go to help state&amp;quot;);
               }
               else if(command == CMD_BLE_SD_LOG)//SD Logging
               {
                  CMD_BLE_STATE_VALUE = CMD_BLE_STATE_SD_LOGGING;//Move to SD logging state
                  NRF_LOG_INFO(&amp;quot;Go to SD log state&amp;quot;);
               }
               else if(command == CMD_BLE_UART_LOG)//UART LOGGING
               {
                  CMD_BLE_STATE_VALUE = CMD_BLE_STATE_UART_LOGGING;//Move to uart log state
                  NRF_LOG_INFO(&amp;quot;Go to UART state&amp;quot;);
               }
               else if(command == CMD_BLE_READ_DATAM)//Read a datam
               {
                  CMD_BLE_STATE_VALUE = CMD_BLE_STATE_READ_A_DATUM;//Move to help state
                  NRF_LOG_INFO(&amp;quot;Go to Read datum state&amp;quot;);
               }
               else if(command == CMD_BLE_TIME_STAMP_START)//Receive the timestamp
               {
                  CMD_BLE_STATE_VALUE = CMD_BLE_STATE_TIME_STAMP_START;//Go to reading the timestamp date
                  Processing_Commands = true;//Set to process the rest of the commands
                  NRF_LOG_INFO(&amp;quot;Go to Timestamp state&amp;quot;);
               }
               else if(command == CMD_BLE_GET_LOG)//Get the log
               {
                  CMD_BLE_STATE_VALUE = CMD_BLE_STATE_GET_LOG;//Get the log
                  NRF_LOG_INFO(&amp;quot;Go to log state&amp;quot;);
               }
               else
               {
                  CMD_BLE_STATE_VALUE = CMD_BLE_STATE_ERROR;//Move to error state unknown command
                  NRF_LOG_INFO(&amp;quot;Go to error state&amp;quot;);
               }
               if(Processing_Commands == false){
                  Process_Selected_state(p_cus, p_ble_evt, command);//Run the command
               }
               break;//Removed break as to fall into other states
           default:
               // No implementation needed.
               break;
         }
    }//End of case statements
    if(Processing_Commands == true){
        Process_Selected_state(p_cus, p_ble_evt, command);//Run the command
    }
}
void Process_Selected_state(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt, uint32_t command)
{
switch (CMD_BLE_STATE_VALUE)
{
    ret_code_t err_code;
    case CMD_BLE_STATE_HELP:
        NRF_LOG_INFO(&amp;quot;Help state&amp;quot;);
        NRF_LOG_INFO(&amp;quot;Help info is:&amp;quot;);
        err_code = ble_cus_custom_value_update(p_cus, p_ble_evt,m_custom_value);
        APP_ERROR_CHECK(err_code);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_SELECT_COMMAND;  
        break;
    case CMD_BLE_STATE_SD_LOGGING:
        NRF_LOG_INFO(&amp;quot;SD card LOG state&amp;quot;);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_SELECT_COMMAND;  
        break;
    case CMD_BLE_STATE_UART_LOGGING:
        NRF_LOG_INFO(&amp;quot;Uart Logging state&amp;quot;);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_SELECT_COMMAND;
        if(Print_log_enabled == 1)//Toggle the printing
        {
            Print_log_enabled = 0;
            NRF_LOG_INFO(&amp;quot;Logging disabled&amp;quot;);
        }
        else
        {
            Print_log_enabled = 1;
            NRF_LOG_INFO(&amp;quot;Logging enabled&amp;quot;);
        }
        break;
   case CMD_BLE_STATE_READ_A_DATUM:
        NRF_LOG_INFO(&amp;quot;Reading datam state&amp;quot;);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_SELECT_COMMAND;
        SD_CARD_Read_Line();//Run the read command for the SD card reading
        break;
    case CMD_BLE_STATE_TIME_STAMP_START:
        NRF_LOG_INFO(&amp;quot;Receiving Time stamp data&amp;quot;);
        //CMD_BLE_STATE_VALUE = CMD_BLE_STATE_SELECT_COMMAND;
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_TIME_STAMP_RECEIVE_YEAR;
        //Need to read the time stamp data here
        break;
    case CMD_BLE_STATE_TIME_STAMP_RECEIVE_YEAR:
        NRF_LOG_INFO(&amp;quot;Receving year&amp;quot;);
        Time_Year = command;//Set the year
        NRF_LOG_INFO(&amp;quot;Year data is: %d&amp;quot;,Time_Year);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_TIME_STAMP_RECEIVE_MONTH;
        break;
    case CMD_BLE_STATE_TIME_STAMP_RECEIVE_MONTH:
        Time_Month = command;//Set the month
        NRF_LOG_INFO(&amp;quot;Receving month&amp;quot;);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_TIME_STAMP_RECEIVE_DAY;
        break;
    case CMD_BLE_STATE_TIME_STAMP_RECEIVE_DAY:
        Time_Day = command;//Set the day
        NRF_LOG_INFO(&amp;quot;Receving day&amp;quot;);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_TIME_STAMP_RECEIVE_HOUR;
        break;
    case CMD_BLE_STATE_TIME_STAMP_RECEIVE_HOUR:
        Time_Hour = command;//Set the hour
        NRF_LOG_INFO(&amp;quot;Receving hour&amp;quot;);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_TIME_STAMP_RECEIVE_MINUTE;
        break;
    case CMD_BLE_STATE_TIME_STAMP_RECEIVE_MINUTE:
        Time_Minute = command;//Set the minute
        NRF_LOG_INFO(&amp;quot;Receving minute&amp;quot;);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_TIME_STAMP_RECEIVE_SECOND;
        break;
    case CMD_BLE_STATE_TIME_STAMP_RECEIVE_SECOND:
        Time_Second = command;//Set the second
        NRF_LOG_INFO(&amp;quot;Receving second&amp;quot;);
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_SELECT_COMMAND;//Finished
        Processing_Commands = false;//Finished processing the
        Convert_time(Time_Year,Time_Month,Time_Day,Time_Hour,Time_Minute,Time_Second);
        NRF_LOG_INFO(&amp;quot;Time in unix is: %d &amp;quot;,Unix_Time);
        break;
    case CMD_BLE_STATE_GET_LOG:
        NRF_LOG_INFO(&amp;quot;Sending SD card log&amp;quot;);
        //Need to send the SD card log here]
        break;
    case CMD_BLE_STATE_STOP://Stop command issued
        NRF_LOG_INFO(&amp;quot;Stop state&amp;quot;);
        CMD_STARTED = false;//Ready for next command
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_START;  
        break;
    case CMD_BLE_STATE_ERROR://Stop command issued
        NRF_LOG_INFO(&amp;quot;Error state&amp;quot;);
        NRF_LOG_INFO(&amp;quot;Unknown command:&amp;quot;);
        CMD_STARTED = false;//Ready for next command
        CMD_BLE_STATE_VALUE = CMD_BLE_STATE_START;  
        break;
    default:
    // No implementation needed.
    break;
    }
}
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/thread/238924?ContentTypeID=1</link><pubDate>Mon, 09 Mar 2020 16:43:44 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:60c8a144-5fdf-49a5-a004-8a0948cb269a</guid><dc:creator>Sigurd</dc:creator><description>&lt;p&gt;1) Could you post the code for the place where you call&amp;nbsp;&lt;span&gt;ble_cus_custom_value_update()?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;2) Can you post your&amp;nbsp;ble_cus.c code ?&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/thread/238909?ContentTypeID=1</link><pubDate>Mon, 09 Mar 2020 15:57:03 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:56488180-24d1-4b5a-8a93-fc1b5c87d391</guid><dc:creator>Thomas</dc:creator><description>&lt;p&gt;I believe I added the service and characteristic properly. I did follow that tutorial but here is my init code non the less.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The data for p_cus and the event is passed in from the on_write statement inside of the gatt connection itself.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;uint32_t ble_cus_init(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
{
    //Init statemachine for reading the commands

    CMD_BLE_STATE_VALUE = CMD_BLE_STATE_START;//Move to start state
    CMD_STARTED = true;

    if (p_cus == NULL || p_cus_init == NULL)
    {
        return NRF_ERROR_NULL;
    }

    uint32_t   err_code;
    ble_uuid_t ble_uuid;

    // Initialize service structure
    //p_cus-&amp;gt;evt_handler               = p_cus_init-&amp;gt;evt_handler;
    p_cus-&amp;gt;conn_handle               = BLE_CONN_HANDLE_INVALID;
    //p_cus-&amp;gt;conn_handle               = BLE_CONN_HANDLE_INVALID;

    // Add Custom Service UUID
    ble_uuid128_t base_uuid = {CUSTOM_SERVICE_UUID_BASE};
    err_code =  sd_ble_uuid_vs_add(&amp;amp;base_uuid, &amp;amp;p_cus-&amp;gt;uuid_type);
    VERIFY_SUCCESS(err_code);
    
    ble_uuid.type = p_cus-&amp;gt;uuid_type;
    ble_uuid.uuid = CUSTOM_SERVICE_UUID;

    // Add the Custom Service
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &amp;amp;ble_uuid, &amp;amp;p_cus-&amp;gt;service_handle);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    // Add Custom Value characteristic
    return custom_value_char_add(p_cus, p_cus_init);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You are correct though it is sd_ble_gatt_hvx that is the issue. So how can I write to it? Do I change it from having notifications enabled to something that is not?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/thread/238904?ContentTypeID=1</link><pubDate>Mon, 09 Mar 2020 15:40:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:20d87c02-4f09-4d1b-8546-138917cb4eb2</guid><dc:creator>Sigurd</dc:creator><description>&lt;p&gt;Did you add the service /&amp;nbsp;c&lt;span&gt;haracteristic like this ?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/bjornspockeli/custom_ble_service_example/blob/SDK_v15.0.0/ble_cus.c#L198"&gt;https://github.com/bjornspockeli/custom_ble_service_example/blob/SDK_v15.0.0/ble_cus.c#L198&lt;/a&gt;&lt;/p&gt;
[quote user="ThomasMorris"]It returns an error: 3400. 0r 0x00003400[/quote]
&lt;p&gt;&amp;nbsp;This is &lt;a href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s140.api.v6.1.1%2Fgroup___b_l_e___e_r_r_o_r_s___g_a_t_t_s.html&amp;amp;anchor=ga050988950fb5cfb9e64b1f91f8872b45"&gt;BLE_ERROR_GATTS_INVALID_ATTR_TYPE&lt;/a&gt;&lt;span&gt;&amp;nbsp;.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;If you call&amp;nbsp;sd_ble_gatts_hvx() and the return error code is:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;* @retval ::BLE_ERROR_GATTS_INVALID_ATTR_TYPE Invalid attribute type(s) supplied, only characteristic values may be notified and indicated.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Then I think either hvx_params.handle is wrong (maybe it&amp;#39;s not the correct handle to the characteristic that can notify values), or the handle you are using is pointing to a characteristic that don&amp;#39;t support notifications (char_props.notify).&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/thread/238893?ContentTypeID=1</link><pubDate>Mon, 09 Mar 2020 15:26:24 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5d6416ed-2696-4d12-baad-585495e69137</guid><dc:creator>Thomas</dc:creator><description>&lt;p&gt;Also another question(Completely non related). I found a post you commented on about timing and calender&amp;#39;s. I have downloaded the example and it works. But, can I add this functionality to my code as in the comments it says to add soft device support. If my GATT connection is maintained e.g. I&amp;#39;m transferring data between two devices; will the date still increment each second?&lt;/p&gt;
&lt;p&gt;Thanks,&lt;/p&gt;
&lt;p&gt;Post is here:&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/25086/local-time-utc-and-timezones"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/25086/local-time-utc-and-timezones&lt;/a&gt;. With a link to the github.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/thread/238838?ContentTypeID=1</link><pubDate>Mon, 09 Mar 2020 13:36:07 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c1864344-a4ea-4e5f-a5ae-85fe8073e9c4</guid><dc:creator>Thomas</dc:creator><description>&lt;p&gt;Thanks for your response. Sorry I forgot to add on calling the function(from within my gatt connection code). It returns an error: 3400. 0r 0x00003400. Just to add some context I am receiving a command from a GATT connection via a mobile application which if passed(Correct command) i then output some text via uart and call the ble_cus_custom_value_update();&lt;/p&gt;
&lt;p&gt;I am not however, sure why this crash occurs. Thanks&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Setting Custom Gatt characteristic data.</title><link>https://devzone.nordicsemi.com/thread/238824?ContentTypeID=1</link><pubDate>Mon, 09 Mar 2020 13:21:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:766aa124-43d1-43a0-95c5-c726db5312af</guid><dc:creator>Sigurd</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user=""]What I want to do is based on an event or the data I receive to change the GATT characteristic data for my app to receive. I tried using this code which, did not change the data.[/quote]
&lt;p&gt;&amp;nbsp;So you are calling&amp;nbsp;ble_cus_custom_value_update() to update the value? but the value is not updated? Did you get any errors codes returned from ble_cus_custom_value_update() ?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>