/**
|
*******************************************************************************
|
* @file app_ble_periph.c
|
* @create 2023-08-01
|
* @author Panchip BLE GROUP
|
* @note
|
* Copyright (c) 2022 Shanghai Panchip Microelectronics Co.,Ltd.
|
*
|
*******************************************************************************
|
*/
|
#include "app.h"
|
#include "pan_ble.h"
|
#include "app_log.h"
|
|
/*******************************************************************************
|
* Variable Define & Declaration
|
******************************************************************************/
|
/**@brief Connection handle */
|
static uint16_t conn_handle = 0xFFFF;
|
|
/**@brief BLE device name. */
|
static const char *device_name = "HX_SHENGJI_TAG";
|
|
/**@brief Heart-rate data send timer. */
|
static struct ble_npl_callout hr_tx_timer;
|
|
/**@brief Variable to simulate heart rate */
|
static uint8_t heartrate = 90;
|
|
static bool notify_state = 0;
|
|
/*******************************************************************************
|
* Function Declaration
|
******************************************************************************/
|
// hr data tx API
|
static void app_ble_hr_tx_timer_start(void);
|
static void app_ble_hr_tx_timer_stop(void);
|
static void app_ble_hr_tx_timer_cb(struct ble_npl_event *ev);
|
|
|
/*******************************************************************************
|
* Function Define
|
******************************************************************************/
|
static int app_ble_periph_gap_event_cb(struct ble_gap_event *event, void *arg)
|
{
|
struct ble_gap_conn_desc out_desc;
|
|
switch (event->type)
|
{
|
case BLE_GAP_EVENT_CONNECT:
|
/* A new connection was established or a connection attempt failed */
|
APP_LOG_INFO("peripheral connection %s; status=%d\n",
|
event->connect.status == 0 ? "established" : "failed",
|
event->connect.status);
|
|
if (event->connect.status != 0) {
|
app_ble_adv_start();
|
conn_handle = 0xFFFF;
|
break;
|
}
|
|
ble_gap_conn_find(event->conn_update.conn_handle, &out_desc);
|
APP_LOG("\t-peer_ota_addr:%s(at:%d)\r\n"
|
"\t-peer_id_addr:%s(at:%d)\r\n"
|
"\t-conn_intvl:%d us\r\n"
|
"\t-latency:%d\r\n"
|
"\t-to:%d ms\r\n",
|
addr_to_str(out_desc.peer_ota_addr.val),
|
out_desc.peer_ota_addr.type,
|
addr_to_str(out_desc.peer_id_addr.val),
|
out_desc.peer_id_addr.type,
|
out_desc.conn_itvl*1250,
|
out_desc.conn_latency,
|
out_desc.supervision_timeout*10);
|
|
conn_handle = event->connect.conn_handle;
|
|
break;
|
|
case BLE_GAP_EVENT_DISCONNECT:
|
APP_LOG_INFO("disconnect; reason=0x%02x\n", (uint8_t)event->disconnect.reason);
|
conn_handle = 0xFFFF; // invalid conn_handle
|
|
/* Connection terminated; resume advertising */
|
app_ble_adv_start();
|
break;
|
|
case BLE_GAP_EVENT_ADV_COMPLETE:
|
APP_LOG_INFO("adv duration expired - restart adv\n");
|
app_ble_adv_start();
|
break;
|
|
case BLE_GAP_EVENT_SUBSCRIBE:
|
APP_LOG_INFO("subscribe event; cur_notify=%d value handle; val_handle=%d\n",
|
event->subscribe.cur_notify, hrs_hrm_handle);
|
|
if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_WRITE)
|
{
|
if (event->subscribe.attr_handle == hrs_hrm_handle) {
|
notify_state = event->subscribe.cur_notify;
|
|
if(notify_state){
|
app_ble_hr_tx_timer_start();
|
}
|
else{
|
app_ble_hr_tx_timer_stop();
|
}
|
}
|
}
|
else if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM){
|
notify_state = false;
|
app_ble_hr_tx_timer_stop();
|
}
|
break;
|
|
case BLE_GAP_EVENT_MTU:
|
APP_LOG_INFO("mtu update event; conn_handle=%d mtu=%d\n",
|
event->mtu.conn_handle,
|
event->mtu.value);
|
break;
|
|
case BLE_GAP_EVENT_NOTIFY_TX:
|
APP_LOG_INFO("send notify ok\n");
|
break;
|
|
case BLE_GAP_EVENT_CONN_UPDATE:
|
{
|
ble_gap_conn_find(event->conn_update.conn_handle, &out_desc);
|
APP_LOG_INFO("conn upd cmpl: conn_handle:%d, itvl:%d us, latency:%d, to:%d ms\n",
|
out_desc.conn_handle,
|
out_desc.conn_itvl * 1250,
|
out_desc.conn_latency,
|
out_desc.supervision_timeout*10);
|
break;
|
}
|
|
default:
|
break;
|
}
|
|
return 0;
|
}
|
|
/*******************************************************************************
|
* HeartRate Notify
|
******************************************************************************/
|
static void app_ble_hr_tx_timer_stop(void)
|
{
|
ble_npl_callout_stop(&hr_tx_timer);
|
}
|
|
static void app_ble_hr_tx_timer_start(void)
|
{
|
int rc;
|
(void)rc;
|
|
rc = ble_npl_callout_reset(&hr_tx_timer, pdMS_TO_TICKS(1000));
|
app_assert(rc == 0);
|
}
|
|
static void app_ble_hr_tx_timer_cb(struct ble_npl_event *ev)
|
{
|
static uint8_t hrm[2];
|
int rc;
|
(void)rc;
|
|
if (!notify_state) {
|
app_ble_hr_tx_timer_stop();
|
heartrate = 90;
|
return;
|
}
|
|
hrm[0] = 0x06; /* contact of a sensor */
|
hrm[1] = heartrate; /* storing dummy data */
|
|
/* Simulation of heart beats */
|
heartrate++;
|
if (heartrate == 160) {
|
heartrate = 90;
|
}
|
|
rc = ble_svc_hrs_notify(conn_handle, hrm, sizeof(hrm));
|
if(rc){
|
APP_LOG_WRN("hrs send notify failed - rc:%d\n", rc);
|
}
|
|
/* restart timer */
|
app_ble_hr_tx_timer_start();
|
}
|
|
static void app_ble_hr_tx_timer_init(void)
|
{
|
ble_npl_callout_init(&hr_tx_timer, nimble_port_get_dflt_eventq(),
|
app_ble_hr_tx_timer_cb, NULL);
|
}
|
|
void app_ble_adv_start(void)
|
{
|
struct ble_gap_adv_params adv_params;
|
struct ble_hs_adv_fields fields;
|
int rc;
|
|
/* Set Adv Data */
|
memset(&fields, 0, sizeof(fields));
|
|
fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
|
|
fields.name = (uint8_t *)device_name;
|
fields.name_len = strlen(device_name);
|
fields.name_is_complete = 1;
|
|
rc = ble_gap_adv_set_fields(&fields);
|
if (rc != 0) {
|
APP_LOG_ERR("error setting advertisement data; rc=%d\n", rc);
|
return;
|
}
|
|
/* Figure out address to use while advertising (no privacy for now) */
|
uint8_t own_addr_type = 0;
|
rc = ble_hs_id_infer_auto(0, &own_addr_type);
|
if (rc != 0) {
|
APP_LOG_ERR("error determining address type; rc=%d\n", rc);
|
return;
|
}
|
|
/* Start Adv */
|
memset(&adv_params, 0, sizeof(adv_params));
|
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
|
rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params,
|
app_ble_periph_gap_event_cb, NULL);
|
if (rc != 0) {
|
APP_LOG_ERR("error enabling advertisement; rc=%d\n", rc);
|
return;
|
}
|
|
APP_LOG_INFO("Adv Start...\n");
|
}
|
//void shengji_start(void)
|
//{
|
// struct ble_gap_adv_params adv_params;
|
// int rc;
|
//
|
// /* Figure out address to use while advertising (no privacy for now) */
|
// uint8_t own_addr_type = 0;
|
// rc = ble_hs_id_infer_auto(0, &own_addr_type);
|
// if (rc != 0) {
|
// APP_LOG_ERR("error determining address type; rc=%d\n", rc);
|
// return;
|
// }
|
|
// /* Start Adv */
|
// memset(&adv_params, 0, sizeof(adv_params));
|
// adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
// adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
|
// rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params,
|
// app_ble_periph_gap_event_cb, NULL);
|
// if (rc != 0) {
|
// APP_LOG_ERR("error enabling advertisement; rc=%d\n", rc);
|
// return;
|
// }
|
//
|
// APP_LOG_INFO("Adv Start...\n");
|
//}
|
|
|
void app_ble_periph_init(void)
|
{
|
app_ble_hr_tx_timer_init();
|
}
|