samples: Bluetooth: Added central health thermometer
Added central sample to read die temperature value from peripheral device. Signed-off-by: Charan Pudiyaneravana Venkatesh <charan.pv@sixoctets.com> Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
6ec8349875
commit
afcf01d7dc
5 changed files with 334 additions and 0 deletions
10
samples/bluetooth/central_ht/CMakeLists.txt
Normal file
10
samples/bluetooth/central_ht/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
# 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(central_ht)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
||||
|
||||
zephyr_library_include_directories($ENV{ZEPHYR_BASE}/samples/bluetooth)
|
25
samples/bluetooth/central_ht/README.rst
Normal file
25
samples/bluetooth/central_ht/README.rst
Normal file
|
@ -0,0 +1,25 @@
|
|||
.. _bluetooth_central_ht:
|
||||
|
||||
Bluetooth: Central / Health Thermometer sensor
|
||||
##############################################
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
Similar to the :ref:`Central <bluetooth_central>` sample, except that this
|
||||
application specifically looks for health thermometer sensor and reports the
|
||||
die temperature readings once connected.
|
||||
|
||||
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/central_ht` in the
|
||||
Zephyr tree.
|
||||
|
||||
See :ref:`bluetooth samples section <bluetooth-samples>` for details.
|
5
samples/bluetooth/central_ht/prj.conf
Normal file
5
samples/bluetooth/central_ht/prj.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
CONFIG_BT=y
|
||||
CONFIG_BT_DEBUG_LOG=y
|
||||
CONFIG_BT_CENTRAL=y
|
||||
CONFIG_BT_SMP=y
|
||||
CONFIG_BT_GATT_CLIENT=y
|
7
samples/bluetooth/central_ht/sample.yaml
Normal file
7
samples/bluetooth/central_ht/sample.yaml
Normal file
|
@ -0,0 +1,7 @@
|
|||
sample:
|
||||
name: Bluetooth Central HT
|
||||
tests:
|
||||
sample.bluetooth.central_ht:
|
||||
arch_whitelist: x86
|
||||
harness: bluetooth
|
||||
tags: bluetooth
|
287
samples/bluetooth/central_ht/src/main.c
Normal file
287
samples/bluetooth/central_ht/src/main.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 SixOctets Systems
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <sys/printk.h>
|
||||
#include <sys/byteorder.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/uuid.h>
|
||||
#include <bluetooth/gatt.h>
|
||||
|
||||
static int scan_start(void);
|
||||
|
||||
static struct bt_conn *default_conn;
|
||||
static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
|
||||
static struct bt_gatt_discover_params discover_params;
|
||||
static struct bt_gatt_subscribe_params subscribe_params;
|
||||
|
||||
static double pow(double x, double y)
|
||||
{
|
||||
double result = 1;
|
||||
|
||||
if (y < 0) {
|
||||
y = -y;
|
||||
while (y--) {
|
||||
result /= x;
|
||||
}
|
||||
} else {
|
||||
while (y--) {
|
||||
result *= x;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static u8_t notify_func(struct bt_conn *conn,
|
||||
struct bt_gatt_subscribe_params *params,
|
||||
const void *data, u16_t length)
|
||||
{
|
||||
double temperature;
|
||||
u32_t mantissa;
|
||||
s8_t exponent;
|
||||
|
||||
if (!data) {
|
||||
printk("[UNSUBSCRIBED]\n");
|
||||
params->value_handle = 0U;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
/* temperature value display */
|
||||
mantissa = sys_get_le24(&((u8_t *)data)[1]);
|
||||
exponent = ((u8_t *)data)[4];
|
||||
temperature = (double)mantissa * pow(10, exponent);
|
||||
|
||||
printf("Temperature %gC.\n", temperature);
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static u8_t discover_func(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr,
|
||||
struct bt_gatt_discover_params *params)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!attr) {
|
||||
printk("Discover complete\n");
|
||||
(void)memset(params, 0, sizeof(*params));
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
printk("[ATTRIBUTE] handle %u\n", attr->handle);
|
||||
|
||||
if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_HTS)) {
|
||||
memcpy(&uuid, BT_UUID_HTS_MEASUREMENT, sizeof(uuid));
|
||||
discover_params.uuid = &uuid.uuid;
|
||||
discover_params.start_handle = attr->handle + 1;
|
||||
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
|
||||
err = bt_gatt_discover(conn, &discover_params);
|
||||
if (err) {
|
||||
printk("Discover failed (err %d)\n", err);
|
||||
}
|
||||
} else if (!bt_uuid_cmp(discover_params.uuid,
|
||||
BT_UUID_HTS_MEASUREMENT)) {
|
||||
memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
|
||||
discover_params.uuid = &uuid.uuid;
|
||||
discover_params.start_handle = attr->handle + 2;
|
||||
discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
|
||||
subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
|
||||
|
||||
err = bt_gatt_discover(conn, &discover_params);
|
||||
if (err) {
|
||||
printk("Discover failed (err %d)\n", err);
|
||||
}
|
||||
} else {
|
||||
subscribe_params.notify = notify_func;
|
||||
subscribe_params.value = BT_GATT_CCC_INDICATE;
|
||||
subscribe_params.ccc_handle = attr->handle;
|
||||
|
||||
err = bt_gatt_subscribe(conn, &subscribe_params);
|
||||
if (err && err != -EALREADY) {
|
||||
printk("Subscribe failed (err %d)\n", err);
|
||||
} else {
|
||||
printk("[SUBSCRIBED]\n");
|
||||
}
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
static void connected(struct bt_conn *conn, u8_t conn_err)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
int err;
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
if (conn_err) {
|
||||
printk("Failed to connect to %s (%u)\n", addr, conn_err);
|
||||
|
||||
bt_conn_unref(default_conn);
|
||||
default_conn = NULL;
|
||||
|
||||
scan_start();
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Connected: %s\n", addr);
|
||||
|
||||
if (conn == default_conn) {
|
||||
memcpy(&uuid, BT_UUID_HTS, sizeof(uuid));
|
||||
discover_params.uuid = &uuid.uuid;
|
||||
discover_params.func = discover_func;
|
||||
discover_params.start_handle = 0x0001;
|
||||
discover_params.end_handle = 0xffff;
|
||||
discover_params.type = BT_GATT_DISCOVER_PRIMARY;
|
||||
|
||||
err = bt_gatt_discover(default_conn, &discover_params);
|
||||
if (err) {
|
||||
printk("Discover failed(err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool eir_found(struct bt_data *data, void *user_data)
|
||||
{
|
||||
bt_addr_le_t *addr = user_data;
|
||||
int i;
|
||||
|
||||
printk("[AD]: %u data_len %u\n", data->type, data->data_len);
|
||||
|
||||
switch (data->type) {
|
||||
case BT_DATA_UUID16_SOME:
|
||||
case BT_DATA_UUID16_ALL:
|
||||
if (data->data_len % sizeof(u16_t) != 0U) {
|
||||
printk("AD malformed\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->data_len; i += sizeof(u16_t)) {
|
||||
struct bt_uuid *uuid;
|
||||
u16_t u16;
|
||||
int err;
|
||||
|
||||
memcpy(&u16, &data->data[i], sizeof(u16));
|
||||
uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16));
|
||||
if (bt_uuid_cmp(uuid, BT_UUID_HTS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = bt_le_scan_stop();
|
||||
if (err) {
|
||||
printk("Stop LE scan failed (err %d)\n", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
|
||||
BT_LE_CONN_PARAM_DEFAULT,
|
||||
&default_conn);
|
||||
if (err) {
|
||||
printk("Create connection failed (err %d)\n",
|
||||
err);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t type,
|
||||
struct net_buf_simple *ad)
|
||||
{
|
||||
char dev[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(addr, dev, sizeof(dev));
|
||||
printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n",
|
||||
dev, type, ad->len, rssi);
|
||||
|
||||
/* We're only interested in connectable events */
|
||||
if (type == BT_HCI_ADV_IND || type == BT_HCI_ADV_DIRECT_IND) {
|
||||
bt_data_parse(ad, eir_found, (void *)addr);
|
||||
}
|
||||
}
|
||||
|
||||
static int scan_start(void)
|
||||
{
|
||||
/* Use active scanning and disable duplicate filtering to handle any
|
||||
* devices that might update their advertising data at runtime.
|
||||
*/
|
||||
struct bt_le_scan_param scan_param = {
|
||||
.type = BT_LE_SCAN_TYPE_ACTIVE,
|
||||
.filter_dup = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
|
||||
.interval = BT_GAP_SCAN_FAST_INTERVAL,
|
||||
.window = BT_GAP_SCAN_FAST_WINDOW,
|
||||
};
|
||||
|
||||
return bt_le_scan_start(&scan_param, device_found);
|
||||
}
|
||||
|
||||
static void disconnected(struct bt_conn *conn, u8_t reason)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
int err;
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
|
||||
|
||||
if (default_conn != conn) {
|
||||
return;
|
||||
}
|
||||
|
||||
bt_conn_unref(default_conn);
|
||||
default_conn = NULL;
|
||||
|
||||
err = scan_start();
|
||||
if (err) {
|
||||
printk("Scanning failed to start (err %d)\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
static struct bt_conn_cb conn_callbacks = {
|
||||
.connected = connected,
|
||||
.disconnected = disconnected,
|
||||
};
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_enable(NULL);
|
||||
if (err) {
|
||||
printk("Bluetooth init failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Bluetooth initialized\n");
|
||||
|
||||
bt_conn_cb_register(&conn_callbacks);
|
||||
|
||||
err = scan_start();
|
||||
|
||||
if (err) {
|
||||
printk("Scanning failed to start (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Scanning successfully started\n");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue