/**@briefFunctionforhandlingtheConnectevent.
*@param[in]p_hrsHeartRateServicestructure.
*@param[in]p_ble_evtEventreceivedfromtheBLEstack.
staticvoidon_connect(ble_hrs_t*p_hrs,ble_evt_t*p_ble_evt)
{
p_hrs->conn_handle=p_ble_evt->evt.gap_evt.conn_handle;
}
/**@briefFunctionforhandlingtheDisconnectevent.
*
*@param[in]p_hrsHeartRateServicestructure.
*@param[in]p_ble_evtEventreceivedfromtheBLEstack.
staticvoidon_disconnect(ble_hrs_t*p_hrs,ble_evt_t*p_ble_evt)
{
UNUSED_PARAMETER(p_ble_evt);
p_hrs->conn_handle=BLE_CONN_HANDLE_INVALID;
}
/**@briefFunctionforhandlingwriteeventstotheHeartRateMeasurementcharacteristic.
*@param[in]p_hrsHeartRateServicestructure.
*@param[in]p_evt_writeWriteeventreceivedfromtheBLEstack.
*/
staticvoidon_hrm_cccd_write(ble_hrs_t*p_hrs,ble_gatts_evt_write_t*p_evt_write)
{
if(p_evt_write->len==2)
{
//CCCDwritten,updatenotificationstate
if(p_hrs->evt_handler!
=NULL)
{
ble_hrs_evt_tevt;
if(ble_srv_is_notification_enabled(p_evt_write->data))
{
evt.evt_type=BLE_HRS_EVT_NOTIFICATION_ENABLED;
}
else
{
evt.evt_type=BLE_HRS_EVT_NOTIFICATION_DISABLED;
}
p_hrs->evt_handler(p_hrs,&evt);
}
}
}
/**@briefFunctionforhandlingtheWriteevent.
*
*@param[in]p_hrsHeartRateServicestructure.
*@param[in]p_ble_evtEventreceivedfromtheBLEstack.
*/
staticvoidon_write(ble_hrs_t*p_hrs,ble_evt_t*p_ble_evt)
{
ble_gatts_evt_write_t*p_evt_write=&p_ble_evt->evt.gatts_evt.params.write;
if(p_evt_write->handle==p_hrs->hrm_handles.cccd_handle)
{
on_hrm_cccd_write(p_hrs,p_evt_write);
}
}
voidble_hrs_on_ble_evt(ble_hrs_t*p_hrs,ble_evt_t*p_ble_evt)
{
switch(p_ble_evt->header.evt_id)
{
caseBLE_GAP_EVT_CONNECTED:
on_connect(p_hrs,p_ble_evt);
break;
caseBLE_GAP_EVT_DISCONNECTED:
on_disconnect(p_hrs,p_ble_evt);
break;
caseBLE_GATTS_EVT_WRITE:
on_write(p_hrs,p_ble_evt);
break;
default:
//Noimplementationneeded.
break;
}
}
/**@briefFunctionforencodingaHeartRateMeasurement.
*
*@param[in]p_hrsHeartRateServicestructure.
*@param[in]heart_rateMeasurementtobeencoded.
*@param[out]p_encoded_bufferBufferwheretheencodeddatawillbewritten.
*
*@returnSizeofencodeddata.
*/
staticuint8_thrm_encode(ble_hrs_t*p_hrs,uint16_theart_rate,uint8_t*p_encoded_buffer)
{
uint8_tflags=0;
uint8_tlen=1;
inti;
//Setsensorcontactrelatedflags
if(p_hrs->is_sensor_contact_supported)
{
flags|=HRM_FLAG_MASK_SENSOR_CONTACT_SUPPORTED;
}
if(p_hrs->is_sensor_contact_detected)
{
flags|=HRM_FLAG_MASK_SENSOR_CONTACT_DETECTED;
}
//Encodeheartratemeasurement
if(heart_rate>0xff)
{
flags|=HRM_FLAG_MASK_HR_VALUE_16BIT;
len+=uint16_encode(heart_rate,&p_encoded_buffer[len]);
}
else
{
p_encoded_buffer[len++]=(uint8_t)heart_rate;
}
//Encoderr_intervalvalues
if(p_hrs->rr_interval_count>0)
{
flags|=HRM_FLAG_MASK_RR_INTERVAL_INCLUDED;
}
for(i=0;irr_interval_count;i++)
{
if(len+sizeof(uint16_t)>MAX_HRM_LEN)
{
//Notallstoredrr_intervalvaluescanfitintotheencodedhrm,
//movetheremainingvaluestothestartofthebuffer.
memmove(&p_hrs->rr_interval[0],
&p_hrs->rr_interval[i],
(p_hrs->rr_interval_count-i)*sizeof(uint16_t));
break;
}
len+=uint16_encode(p_hrs->rr_interval[i],&p_encoded_buffer[len]);
}
p_hrs->rr_interval_count-=i;
//Addflags
p_encoded_buffer[0]=flags;
returnlen;
}
/**@briefFunctionforaddingtheHeartRateMeasurementcharacteristic.
*
*@param[in]p_hrsHeartRateServicestructure.
*@param[in]p_hrs_initInformationneededtoinitializetheservice.
*
*@returnNRF_SUCCESSonsuccess,otherwiseanerrorcode.
*/
staticuint32_theart_rate_measurement_char_add(ble_hrs_t*p_hrs,
constble_hrs_init_t*p_hrs_init)
{
ble_gatts_char_md_tchar_md;
ble_gatts_attr_md_tcccd_md;
ble_gatts_attr_tattr_char_value;
ble_uuid_tble_uuid;
ble_gatts_attr_md_tattr_md;
uint8_tencoded_initial_hrm[MAX_HRM_LEN];
memset(&cccd_md,0,sizeof(cccd_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
cccd_md.write_perm=p_hrs_init->hrs_hrm_attr_md.cccd_write_perm;
cccd_md.vloc=BLE_GATTS_VLOC_STACK;
memset(&char_md,0,sizeof(char_md));
char_md.char_props.notify=1;
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=&cccd_md;
char_md.p_sccd_md=NULL;
BLE_UUID_