diff --git a/include/bluetooth/uuid.h b/include/bluetooth/uuid.h index 2965f3290ed..4d0f60a4893 100644 --- a/include/bluetooth/uuid.h +++ b/include/bluetooth/uuid.h @@ -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 */ diff --git a/samples/bluetooth/gatt/hts.c b/samples/bluetooth/gatt/hts.c new file mode 100644 index 00000000000..baed303f9f7 --- /dev/null +++ b/samples/bluetooth/gatt/hts.c @@ -0,0 +1,86 @@ +/** @file + * @brief HTS Service sample + */ + +/* + * Copyright (c) 2019 Aaron Tsui + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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; + } + } +} diff --git a/samples/bluetooth/gatt/hts.h b/samples/bluetooth/gatt/hts.h new file mode 100644 index 00000000000..e243426c59d --- /dev/null +++ b/samples/bluetooth/gatt/hts.h @@ -0,0 +1,20 @@ +/** @file + * @brief HTS Service sample + */ + +/* + * Copyright (c) 2019 Aaron Tsui + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef __cplusplus +extern "C" { +#endif + +void hts_init(void); +void hts_indicate(void); + +#ifdef __cplusplus +} +#endif diff --git a/samples/bluetooth/peripheral_ht/CMakeLists.txt b/samples/bluetooth/peripheral_ht/CMakeLists.txt new file mode 100644 index 00000000000..3568428436c --- /dev/null +++ b/samples/bluetooth/peripheral_ht/CMakeLists.txt @@ -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) diff --git a/samples/bluetooth/peripheral_ht/README.rst b/samples/bluetooth/peripheral_ht/README.rst new file mode 100644 index 00000000000..ff3ae990360 --- /dev/null +++ b/samples/bluetooth/peripheral_ht/README.rst @@ -0,0 +1,26 @@ +.. _peripheral_ht: + +Bluetooth: Peripheral HT +######################## + +Overview +******** + +Similar to the :ref:`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 ` for details. diff --git a/samples/bluetooth/peripheral_ht/prj.conf b/samples/bluetooth/peripheral_ht/prj.conf new file mode 100644 index 00000000000..b8a3baf916d --- /dev/null +++ b/samples/bluetooth/peripheral_ht/prj.conf @@ -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 diff --git a/samples/bluetooth/peripheral_ht/sample.yaml b/samples/bluetooth/peripheral_ht/sample.yaml new file mode 100644 index 00000000000..f7dc07d51f4 --- /dev/null +++ b/samples/bluetooth/peripheral_ht/sample.yaml @@ -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 + diff --git a/samples/bluetooth/peripheral_ht/src/main.c b/samples/bluetooth/peripheral_ht/src/main.c new file mode 100644 index 00000000000..03e27c0e587 --- /dev/null +++ b/samples/bluetooth/peripheral_ht/src/main.c @@ -0,0 +1,120 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2019 Aaron Tsui + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +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(); + } +}