Bluetooth: samples: Add dedicated Heartrate peripheral sample app
This can be used to focus on demonstrating a simple heartrate service. Change-Id: Ib59c653ebe356784592c8468767b45c5240ec67a Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
parent
843268d78d
commit
2b7a5229f2
7
samples/bluetooth/peripheral_hr/Makefile
Normal file
7
samples/bluetooth/peripheral_hr/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
BOARD ?= qemu_x86
|
||||
MDEF_FILE = prj.mdef
|
||||
KERNEL_TYPE = micro
|
||||
CONF_FILE ?= prj.conf
|
||||
QEMU_EXTRA_FLAGS = -serial unix:/tmp/bt-server-bredr
|
||||
|
||||
include $(ZEPHYR_BASE)/Makefile.inc
|
||||
4
samples/bluetooth/peripheral_hr/README
Normal file
4
samples/bluetooth/peripheral_hr/README
Normal file
@ -0,0 +1,4 @@
|
||||
For building shell with Nordic Bluetooth Low Energy stack (NBLE)
|
||||
use prj_nble.conf:
|
||||
|
||||
$ make CONF_FILE=prj_nble.conf BOARD=arduino_101
|
||||
9
samples/bluetooth/peripheral_hr/prj.conf
Normal file
9
samples/bluetooth/peripheral_hr/prj.conf
Normal file
@ -0,0 +1,9 @@
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_BLUETOOTH=y
|
||||
CONFIG_BLUETOOTH_LE=y
|
||||
CONFIG_BLUETOOTH_DEBUG=y
|
||||
CONFIG_BLUETOOTH_SMP=y
|
||||
CONFIG_TINYCRYPT=y
|
||||
CONFIG_TINYCRYPT_AES=y
|
||||
CONFIG_BLUETOOTH_PERIPHERAL=y
|
||||
CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y
|
||||
5
samples/bluetooth/peripheral_hr/prj.mdef
Normal file
5
samples/bluetooth/peripheral_hr/prj.mdef
Normal file
@ -0,0 +1,5 @@
|
||||
% Application : Bluetooth heartrate peripheral sample
|
||||
|
||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
||||
% ===================================================
|
||||
TASK MAIN 7 mainloop 2048 [EXE]
|
||||
4
samples/bluetooth/peripheral_hr/prj_nble.conf
Normal file
4
samples/bluetooth/peripheral_hr/prj_nble.conf
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NBLE=y
|
||||
CONFIG_ARC_INIT=n
|
||||
CONFIG_BLUETOOTH_DEBUG=y
|
||||
1
samples/bluetooth/peripheral_hr/src/Makefile
Normal file
1
samples/bluetooth/peripheral_hr/src/Makefile
Normal file
@ -0,0 +1 @@
|
||||
obj-y = main.o
|
||||
268
samples/bluetooth/peripheral_hr/src/main.c
Normal file
268
samples/bluetooth/peripheral_hr/src/main.c
Normal file
@ -0,0 +1,268 @@
|
||||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed 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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <misc/printk.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/uuid.h>
|
||||
#include <bluetooth/gatt.h>
|
||||
|
||||
#define DEVICE_NAME "Heartrate Monitor"
|
||||
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
||||
#define HEART_RATE_APPEARANCE 0x0341
|
||||
|
||||
static int read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, uint16_t len, uint16_t offset)
|
||||
{
|
||||
const char *name = attr->user_data;
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, name,
|
||||
strlen(name));
|
||||
}
|
||||
|
||||
static int read_appearance(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr, void *buf,
|
||||
uint16_t len, uint16_t offset)
|
||||
{
|
||||
uint16_t appearance = sys_cpu_to_le16(HEART_RATE_APPEARANCE);
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, &appearance,
|
||||
sizeof(appearance));
|
||||
}
|
||||
|
||||
static struct bt_gatt_ccc_cfg hrmc_ccc_cfg[CONFIG_BLUETOOTH_MAX_PAIRED] = {};
|
||||
static uint8_t simulate_hrm;
|
||||
|
||||
static void hrmc_ccc_cfg_changed(uint16_t value)
|
||||
{
|
||||
simulate_hrm = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int read_blsc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, uint16_t len, uint16_t offset)
|
||||
{
|
||||
uint8_t value = 0x01;
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, &value,
|
||||
sizeof(value));
|
||||
}
|
||||
|
||||
static struct bt_gatt_ccc_cfg blvl_ccc_cfg[CONFIG_BLUETOOTH_MAX_PAIRED] = {};
|
||||
static uint8_t simulate_blvl;
|
||||
static uint8_t battery = 100;
|
||||
|
||||
static void blvl_ccc_cfg_changed(uint16_t value)
|
||||
{
|
||||
simulate_blvl = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int read_blvl(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, uint16_t len, uint16_t offset)
|
||||
{
|
||||
const char *value = attr->user_data;
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
|
||||
sizeof(*value));
|
||||
}
|
||||
|
||||
static int read_model(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, uint16_t len, uint16_t offset)
|
||||
{
|
||||
const char *value = attr->user_data;
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
|
||||
strlen(value));
|
||||
}
|
||||
|
||||
static int read_manuf(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, uint16_t len, uint16_t offset)
|
||||
{
|
||||
const char *value = attr->user_data;
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
|
||||
strlen(value));
|
||||
}
|
||||
|
||||
static struct bt_gatt_attr gap_attrs[] = {
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_GAP),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_GAP_DEVICE_NAME, BT_GATT_CHRC_READ),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_GAP_DEVICE_NAME, BT_GATT_PERM_READ,
|
||||
read_name, NULL, DEVICE_NAME),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_GAP_APPEARANCE, BT_GATT_CHRC_READ),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_GAP_APPEARANCE, BT_GATT_PERM_READ,
|
||||
read_appearance, NULL, NULL),
|
||||
};
|
||||
|
||||
/* Heart Rate Service Declaration */
|
||||
static struct bt_gatt_attr hrs_attrs[] = {
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_HRS),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_HRS_MEASUREMENT, BT_GATT_CHRC_NOTIFY),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_HRS_MEASUREMENT, BT_GATT_PERM_READ, NULL,
|
||||
NULL, NULL),
|
||||
BT_GATT_CCC(hrmc_ccc_cfg, hrmc_ccc_cfg_changed),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_HRS_BODY_SENSOR, BT_GATT_CHRC_READ),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_HRS_BODY_SENSOR, BT_GATT_PERM_READ,
|
||||
read_blsc, NULL, NULL),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_HRS_CONTROL_POINT, BT_GATT_CHRC_WRITE),
|
||||
/* TODO: Add write permission and callback */
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_HRS_CONTROL_POINT, BT_GATT_PERM_READ, NULL,
|
||||
NULL, NULL),
|
||||
};
|
||||
|
||||
/* Battery Service Declaration */
|
||||
static struct bt_gatt_attr bas_attrs[] = {
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL,
|
||||
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_BAS_BATTERY_LEVEL, BT_GATT_PERM_READ,
|
||||
read_blvl, NULL, &battery),
|
||||
BT_GATT_CCC(blvl_ccc_cfg, blvl_ccc_cfg_changed),
|
||||
};
|
||||
|
||||
/* Device Information Service Declaration */
|
||||
static struct bt_gatt_attr dis_attrs[] = {
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_DIS),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MODEL_NUMBER, BT_GATT_CHRC_READ),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_DIS_MODEL_NUMBER, BT_GATT_PERM_READ,
|
||||
read_model, NULL, CONFIG_SOC),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MANUFACTURER_NAME,
|
||||
BT_GATT_CHRC_READ),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_DIS_MANUFACTURER_NAME, BT_GATT_PERM_READ,
|
||||
read_manuf, NULL, "Manufacturer"),
|
||||
};
|
||||
|
||||
static const struct bt_data ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x0d, 0x18, 0x0f, 0x18, 0x05, 0x18),
|
||||
};
|
||||
|
||||
static const struct bt_data sd[] = {
|
||||
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
|
||||
};
|
||||
|
||||
static void connected(struct bt_conn *conn, uint8_t err)
|
||||
{
|
||||
if (err) {
|
||||
printk("Connection failed (err %u)\n", err);
|
||||
} else {
|
||||
printk("Connected\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||
{
|
||||
printk("Disconnected (reason %u)\n", reason);
|
||||
}
|
||||
|
||||
static struct bt_conn_cb conn_callbacks = {
|
||||
.connected = connected,
|
||||
.disconnected = disconnected,
|
||||
};
|
||||
|
||||
static void bt_ready(int err)
|
||||
{
|
||||
if (err) {
|
||||
printk("Bluetooth init failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Bluetooth initialized\n");
|
||||
|
||||
bt_gatt_register(gap_attrs, ARRAY_SIZE(gap_attrs));
|
||||
bt_gatt_register(hrs_attrs, ARRAY_SIZE(hrs_attrs));
|
||||
bt_gatt_register(bas_attrs, ARRAY_SIZE(bas_attrs));
|
||||
bt_gatt_register(dis_attrs, ARRAY_SIZE(dis_attrs));
|
||||
|
||||
err = bt_le_adv_start(BT_LE_ADV(BT_LE_ADV_IND), ad, ARRAY_SIZE(ad),
|
||||
sd, ARRAY_SIZE(sd));
|
||||
if (err) {
|
||||
printk("Advertising failed to start (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Advertising successfully started\n");
|
||||
}
|
||||
|
||||
static void auth_cancel(struct bt_conn *conn)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
printk("Pairing cancelled: %s\n", addr);
|
||||
}
|
||||
|
||||
static struct bt_conn_auth_cb auth_cb_display = {
|
||||
.cancel = auth_cancel,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MICROKERNEL
|
||||
void mainloop(void)
|
||||
#else
|
||||
void main(void)
|
||||
#endif
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_enable(bt_ready);
|
||||
if (err) {
|
||||
printk("Bluetooth init failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
bt_conn_cb_register(&conn_callbacks);
|
||||
bt_conn_auth_cb_register(&auth_cb_display);
|
||||
|
||||
/* Implement notification. At the moment there is no suitable way
|
||||
* of starting delayed work so we do it here
|
||||
*/
|
||||
while (1) {
|
||||
static uint8_t hrm[2];
|
||||
|
||||
task_sleep(sys_clock_ticks_per_sec);
|
||||
|
||||
/* Heartrate measurements simulation */
|
||||
if (simulate_hrm) {
|
||||
hrm[0] = 0x06; /* uint8, sensor contact */
|
||||
hrm[1] = 90 + (sys_rand32_get() % 20);
|
||||
|
||||
bt_gatt_notify(NULL, &hrs_attrs[3], &hrm, sizeof(hrm));
|
||||
}
|
||||
|
||||
/* Battery level simulation */
|
||||
if (simulate_blvl) {
|
||||
battery -= 1;
|
||||
|
||||
if (!battery) {
|
||||
/* Software eco battery charger */
|
||||
battery = 100;
|
||||
}
|
||||
|
||||
bt_gatt_notify(NULL, &bas_attrs[3], &battery,
|
||||
sizeof(battery));
|
||||
}
|
||||
}
|
||||
}
|
||||
20
samples/bluetooth/peripheral_hr/testcase.ini
Normal file
20
samples/bluetooth/peripheral_hr/testcase.ini
Normal file
@ -0,0 +1,20 @@
|
||||
[test_x86]
|
||||
tags = bluetooth
|
||||
build_only = true
|
||||
arch_whitelist = x86
|
||||
# FIXME Doesn't work for ia32_pci
|
||||
config_whitelist = CONFIG_SOC="ia32"
|
||||
|
||||
[test_arm]
|
||||
tags = bluetooth
|
||||
build_only = true
|
||||
arch_whitelist = arm
|
||||
platform_exclude = arduino_due
|
||||
|
||||
[test_nble]
|
||||
tags = bluetooth
|
||||
build_only = true
|
||||
extra_args = CONF_FILE="prj_nble.conf"
|
||||
arch_whitelist = x86
|
||||
config_whitelist = CONFIG_SOC_QUARK_SE
|
||||
platform_whitelist = arduino_101
|
||||
Loading…
Reference in New Issue
Block a user