Skip to content
Permalink
Browse files

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>
  • Loading branch information...
overheat authored and jhedberg committed Jun 4, 2019
1 parent db167c6 commit b0e58d62ab0f881df662dbee245f1e900217181b
@@ -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
*/
@@ -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;
}
}
}
@@ -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
@@ -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)
@@ -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.
@@ -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
@@ -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

@@ -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();
}
}

0 comments on commit b0e58d6

Please sign in to comment.
You can’t perform that action at this time.