samples: bluetooth: peripheral_ht: Health Thermometer sample

Adding Health Thermometer Service sample. Refer to Health Thermometer
Profile Specification for detailed information about the Health
Thermometer Profile.

Signed-off-by: Aaron Tsui <aaron.tsui@outlook.com>
This commit is contained in:
Aaron Tsui 2019-06-04 15:10:58 +08:00 committed by Johan Hedberg
commit b0e58d62ab
8 changed files with 298 additions and 0 deletions

View file

@ -91,6 +91,10 @@ struct bt_uuid_128 {
* @brief Current Time Service
*/
#define BT_UUID_CTS BT_UUID_DECLARE_16(0x1805)
/** @def BT_UUID_HTS
* @brief Health Thermometer Service
*/
#define BT_UUID_HTS BT_UUID_DECLARE_16(0x1809)
/** @def BT_UUID_DIS
* @brief Device Information Service
*/
@ -207,6 +211,10 @@ struct bt_uuid_128 {
* @brief BAS Characteristic Battery Level
*/
#define BT_UUID_BAS_BATTERY_LEVEL BT_UUID_DECLARE_16(0x2a19)
/** @def BT_UUID_HTS_MEASUREMENT
* @brief HTS Characteristic Measurement Value
*/
#define BT_UUID_HTS_MEASUREMENT BT_UUID_DECLARE_16(0x2a1c)
/** @def BT_UUID_HIDS_BOOT_KB_IN_REPORT
* @brief HID Characteristic Boot Keyboard Input Report
*/

View file

@ -0,0 +1,86 @@
/** @file
* @brief HTS Service sample
*/
/*
* Copyright (c) 2019 Aaron Tsui <aaron.tsui@outlook.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.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>
static struct bt_gatt_ccc_cfg htmc_ccc_cfg[BT_GATT_CCC_MAX] = {};
static u8_t simulate_htm;
static u8_t indicating;
static struct bt_gatt_indicate_params ind_params;
static u8_t temperature = 20U;
static void htmc_ccc_cfg_changed(const struct bt_gatt_attr *attr,
u16_t value)
{
simulate_htm = (value == BT_GATT_CCC_INDICATE) ? 1 : 0;
}
static void indicate_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
u8_t err)
{
printk("Indication %s\n", err != 0U ? "fail" : "success");
indicating = 0U;
}
/* Heart Rate Service Declaration */
BT_GATT_SERVICE_DEFINE(hts_svc,
BT_GATT_PRIMARY_SERVICE(BT_UUID_HTS),
BT_GATT_CHARACTERISTIC(BT_UUID_HTS_MEASUREMENT, BT_GATT_CHRC_INDICATE,
BT_GATT_PERM_NONE, NULL, NULL, NULL),
BT_GATT_CCC(htmc_ccc_cfg, htmc_ccc_cfg_changed),
/* more optional Characteristics */
);
void hts_init(void)
{
}
void hts_indicate(void)
{
/* Temperature measurements simulation */
if (simulate_htm) {
if (indicating) {
return;
}
temperature++;
if (temperature == 30U) {
temperature = 20U;
}
static u8_t htm[1 + 4];
htm[0] = 0x0; /* uint8, temperature in celsius*/
/* (IEEE-11073 32-bit FLOAT). */
htm[1] = temperature; /* mantissa = temperature*/
htm[2] = htm[3] = htm[4] = 0; /* sign = 0, exponent= 0 */
ind_params.attr = &hts_svc.attrs[2];
ind_params.func = indicate_cb;
ind_params.data = &htm;
ind_params.len = sizeof(htm);
if (bt_gatt_indicate(NULL, &ind_params) == 0) {
indicating = 1U;
}
}
}

View file

@ -0,0 +1,20 @@
/** @file
* @brief HTS Service sample
*/
/*
* Copyright (c) 2019 Aaron Tsui <aaron.tsui@outlook.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef __cplusplus
extern "C" {
#endif
void hts_init(void);
void hts_indicate(void);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,15 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(peripheral_ht)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE
${app_sources}
../gatt/hts.c
../gatt/bas.c
)
zephyr_library_include_directories($ENV{ZEPHYR_BASE}/samples/bluetooth)

View file

@ -0,0 +1,26 @@
.. _peripheral_ht:
Bluetooth: Peripheral HT
########################
Overview
********
Similar to the :ref:`Peripheral <ble_peripheral>` sample, except that this
application specifically exposes the HT (Health Thermometer) GATT Service. Once a device
connects it will generate dummy temperature values.
Requirements
************
* BlueZ running on the host, or
* A board with BLE support
Building and Running
********************
This sample can be found under :zephyr_file:`samples/bluetooth/peripheral_ht` in the
Zephyr tree.
See :ref:`bluetooth samples section <bluetooth-samples>` for details.

View file

@ -0,0 +1,9 @@
CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_SMP=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_GATT_DIS=y
CONFIG_BT_GATT_DIS_PNP=n
CONFIG_BT_DEVICE_NAME="Zephyr Health Thermometer"
CONFIG_BT_DEVICE_APPEARANCE=768
CONFIG_BT_ATT_ENFORCE_FLOW=n

View file

@ -0,0 +1,14 @@
sample:
description: TBD
name: TBD
tests:
sample.bluetooth.peripheral_ht:
harness: bluetooth
platform_whitelist: qemu_cortex_m3 qemu_x86
tags: bluetooth
sample.bluetooth.peripheral_ht.frdm_kw41z_shield:
harness: bluetooth
platform_whitelist: mimxrt1020_evk mimxrt1050_evk mimxrt1060_evk frdm_k64f
tags: bluetooth
extra_args: SHIELD=frdm_kw41z

View file

@ -0,0 +1,120 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2019 Aaron Tsui <aaron.tsui@outlook.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.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>
#include <gatt/hts.h>
#include <gatt/bas.h>
struct bt_conn *default_conn;
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,
0x09, 0x18, /* Health Thermometer Service */
0x0a, 0x18, /* Device Information Service */
0x0f, 0x18), /* Battery Service */
};
static void connected(struct bt_conn *conn, u8_t err)
{
if (err) {
printk("Connection failed (err %u)\n", err);
} else {
default_conn = bt_conn_ref(conn);
printk("Connected\n");
}
}
static void disconnected(struct bt_conn *conn, u8_t reason)
{
printk("Disconnected (reason %u)\n", reason);
if (default_conn) {
bt_conn_unref(default_conn);
default_conn = NULL;
}
}
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");
hts_init();
bas_init();
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
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,
};
void main(void)
{
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 indicate. At the moment there is no suitable way
* of starting delayed work so we do it here
*/
while (1) {
k_sleep(MSEC_PER_SEC);
/* Temperature measurements simulation */
hts_indicate();
/* Battery level simulation */
bas_notify();
}
}