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:
parent
db167c606d
commit
b0e58d62ab
8 changed files with 298 additions and 0 deletions
|
@ -91,6 +91,10 @@ struct bt_uuid_128 {
|
||||||
* @brief Current Time Service
|
* @brief Current Time Service
|
||||||
*/
|
*/
|
||||||
#define BT_UUID_CTS BT_UUID_DECLARE_16(0x1805)
|
#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
|
/** @def BT_UUID_DIS
|
||||||
* @brief Device Information Service
|
* @brief Device Information Service
|
||||||
*/
|
*/
|
||||||
|
@ -207,6 +211,10 @@ struct bt_uuid_128 {
|
||||||
* @brief BAS Characteristic Battery Level
|
* @brief BAS Characteristic Battery Level
|
||||||
*/
|
*/
|
||||||
#define BT_UUID_BAS_BATTERY_LEVEL BT_UUID_DECLARE_16(0x2a19)
|
#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
|
/** @def BT_UUID_HIDS_BOOT_KB_IN_REPORT
|
||||||
* @brief HID Characteristic Boot Keyboard Input Report
|
* @brief HID Characteristic Boot Keyboard Input Report
|
||||||
*/
|
*/
|
||||||
|
|
86
samples/bluetooth/gatt/hts.c
Normal file
86
samples/bluetooth/gatt/hts.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
samples/bluetooth/gatt/hts.h
Normal file
20
samples/bluetooth/gatt/hts.h
Normal 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
|
15
samples/bluetooth/peripheral_ht/CMakeLists.txt
Normal file
15
samples/bluetooth/peripheral_ht/CMakeLists.txt
Normal 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)
|
26
samples/bluetooth/peripheral_ht/README.rst
Normal file
26
samples/bluetooth/peripheral_ht/README.rst
Normal 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.
|
9
samples/bluetooth/peripheral_ht/prj.conf
Normal file
9
samples/bluetooth/peripheral_ht/prj.conf
Normal 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
|
14
samples/bluetooth/peripheral_ht/sample.yaml
Normal file
14
samples/bluetooth/peripheral_ht/sample.yaml
Normal 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
|
||||||
|
|
120
samples/bluetooth/peripheral_ht/src/main.c
Normal file
120
samples/bluetooth/peripheral_ht/src/main.c
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue