Files
TencentOS-tiny/examples/nimble_heart_rate_sensor/main.c
daishengdong 0700d27b70 add more nimble example
1. make heart rate sensor example really work
using nRF Toolbox HRM
2. add master device scan example
3. add gatt server example(seems not working)
2019-11-12 19:56:52 +08:00

295 lines
7.7 KiB
C

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "console/console.h"
#include "config/private_syscfg.h"
#include "nimble/ble.h"
#include "host/ble_hs.h"
#include "host/ble_gatt.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "blehr_sens.h"
#include "nimble/nimble_port_tencentos_tiny.h"
static bool notify_state;
/* Connection handle */
static uint16_t conn_handle;
static const char *device_name = "Heart Rate Sensor";
static int blehr_gap_event(struct ble_gap_event *event, void *arg);
static uint8_t ble_addr_type;
/* Sending notify data timer */
static struct ble_npl_callout blehr_tx_timer;
/* Variable to simulate heart beats */
static uint8_t heartrate = 90;
static ble_uuid16_t svc_adv_uuids[] =
{
{ BLE_UUID_TYPE_16, GATT_HRS_UUID }
};
/*
* Enables advertising with parameters:
* o General discoverable mode
* o Undirected connectable mode
*/
static void
blehr_advertise(void)
{
struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields fields;
int rc;
/*
* Set the advertisement data included in our advertisements:
* o Flags (indicates advertisement type and other general info)
* o Advertising tx power
* o Device name
*/
memset(&fields, 0, sizeof(fields));
/*
* Advertise two flags:
* o Discoverability in forthcoming advertisement (general)
* o BLE-only (BR/EDR unsupported)
*/
fields.flags = BLE_HS_ADV_F_DISC_GEN |
BLE_HS_ADV_F_BREDR_UNSUP;
/*
* Indicate that the TX power level field should be included; have the
* stack fill this value automatically. This is done by assigning the
* special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
*/
fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
fields.name = (uint8_t *)device_name;
fields.name_len = strlen(device_name);
fields.name_is_complete = 1;
/*** 0x02,0x03 - 16-bit service class UUIDs. */
fields.num_uuids16 = 1;
fields.uuids16 = svc_adv_uuids;
fields.uuids16_is_complete = 1;
rc = ble_gap_adv_set_fields(&fields);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc);
return;
}
/*** 0xff - Manufacturer specific data. */
memset(&fields, 0, sizeof(fields));
fields.mfg_data = (uint8_t*)"GZH:Bluetooth-BLE,177341833";
fields.mfg_data_len = 27;
rc = ble_gap_adv_rsp_set_fields(&fields);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc);
return;
}
/* Begin advertising */
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(ble_addr_type, NULL, BLE_HS_FOREVER,
&adv_params, blehr_gap_event, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc);
return;
}
}
static void
blehr_tx_hrate_stop(void)
{
ble_npl_callout_stop(&blehr_tx_timer);
}
/* Reset heartrate measurment */
static void
blehr_tx_hrate_reset(void)
{
int rc;
rc = ble_npl_callout_reset(&blehr_tx_timer, OS_TICKS_PER_SEC);
assert(rc == 0);
}
/* This functions simulates heart beat and notifies it to the client */
static void
blehr_tx_hrate(struct os_event *ev)
{
static uint8_t hrm[2];
int rc;
struct os_mbuf *om;
if (!notify_state) {
blehr_tx_hrate_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;
}
om = ble_hs_mbuf_from_flat(hrm, sizeof(hrm));
rc = ble_gattc_notify_custom(conn_handle, hrs_hrm_handle, om);
assert(rc == 0);
blehr_tx_hrate_reset();
}
static int
blehr_gap_event(struct ble_gap_event *event, void *arg)
{
switch (event->type) {
case BLE_GAP_EVENT_CONNECT:
/* A new connection was established or a connection attempt failed */
MODLOG_DFLT(INFO, "connection %s; status=%d\n",
event->connect.status == 0 ? "established" : "failed",
event->connect.status);
if (event->connect.status != 0) {
/* Connection failed; resume advertising */
blehr_advertise();
conn_handle = 0;
}
else {
conn_handle = event->connect.conn_handle;
}
break;
case BLE_GAP_EVENT_DISCONNECT:
MODLOG_DFLT(INFO, "disconnect; reason=%d\n", event->disconnect.reason);
conn_handle = BLE_HS_CONN_HANDLE_NONE; /* reset conn_handle */
/* Connection terminated; resume advertising */
blehr_advertise();
break;
case BLE_GAP_EVENT_ADV_COMPLETE:
MODLOG_DFLT(INFO, "adv complete\n");
blehr_advertise();
break;
case BLE_GAP_EVENT_SUBSCRIBE:
MODLOG_DFLT(INFO, "subscribe event; cur_notify=%d\n value handle; "
"val_handle=%d\n",
event->subscribe.cur_notify, hrs_hrm_handle);
if (event->subscribe.attr_handle == hrs_hrm_handle) {
notify_state = event->subscribe.cur_notify;
blehr_tx_hrate_reset();
} else if (event->subscribe.attr_handle != hrs_hrm_handle) {
notify_state = event->subscribe.cur_notify;
blehr_tx_hrate_stop();
}
break;
case BLE_GAP_EVENT_MTU:
MODLOG_DFLT(INFO, "mtu update event; conn_handle=%d mtu=%d\n",
event->mtu.conn_handle,
event->mtu.value);
break;
}
return 0;
}
static void
blehr_on_sync(void)
{
int rc;
/* Use privacy */
rc = ble_hs_id_infer_auto(0, &ble_addr_type);
assert(rc == 0);
/* Begin advertising */
blehr_advertise();
}
int ble_boot(void)
{
int rc = 0;
/* Initialize the NimBLE host configuration */
ble_hs_cfg.sync_cb = blehr_on_sync;
ble_npl_callout_init(&blehr_tx_timer, nimble_port_get_dflt_eventq(),
blehr_tx_hrate, NULL);
/* verify and add our custom services */
rc = gatt_svr_init();
assert(rc == 0);
/* Set the default device name */
rc = ble_svc_gap_device_name_set(device_name);
assert(rc == 0);
/* run an event loop for handling the heart rate update events */
extern void nimble_port_run(void);
nimble_port_tencentos_tiny_init(nimble_port_run);
return 0;
}
k_task_t ble_boot_task;
k_stack_t ble_boot_stack[512];
int main(void)
{
board_init();
/* Initialize OS */
tos_knl_init();
nimble_port_init();
tos_task_create(&ble_boot_task, "boot", ble_boot, NULL,
4,
ble_boot_stack, sizeof(ble_boot_stack),
0);
tos_knl_start();
}