|  | /** @file | 
|  | *  @brief HTS Service sample | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Copyright (c) 2020 SixOctets Systems | 
|  | * Copyright (c) 2019 Aaron Tsui <aaron.tsui@outlook.com> | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <stddef.h> | 
|  | #include <string.h> | 
|  | #include <errno.h> | 
|  |  | 
|  | #include <zephyr/kernel.h> | 
|  | #include <zephyr/drivers/sensor.h> | 
|  | #include <zephyr/sys/printk.h> | 
|  | #include <zephyr/sys/byteorder.h> | 
|  |  | 
|  | #include <zephyr/bluetooth/bluetooth.h> | 
|  | #include <zephyr/bluetooth/hci.h> | 
|  | #include <zephyr/bluetooth/conn.h> | 
|  | #include <zephyr/bluetooth/uuid.h> | 
|  | #include <zephyr/bluetooth/gatt.h> | 
|  |  | 
|  | #ifdef CONFIG_TEMP_NRF5 | 
|  | static const struct device *temp_dev = DEVICE_DT_GET_ANY(nordic_nrf_temp); | 
|  | #define TEMP_SENSOR_CHAN SENSOR_CHAN_DIE_TEMP | 
|  | #elif DT_HAS_ALIAS(dht0) | 
|  | static const struct device *temp_dev = DEVICE_DT_GET(DT_ALIAS(dht0)); | 
|  | #define TEMP_SENSOR_CHAN SENSOR_CHAN_AMBIENT_TEMP | 
|  | #else | 
|  | static const struct device *temp_dev; | 
|  | #define TEMP_SENSOR_CHAN SENSOR_CHAN_AMBIENT_TEMP | 
|  | #endif | 
|  |  | 
|  | static uint8_t simulate_htm; | 
|  | static uint8_t indicating; | 
|  | static struct bt_gatt_indicate_params ind_params; | 
|  |  | 
|  | static void htmc_ccc_cfg_changed(const struct bt_gatt_attr *attr, | 
|  | uint16_t value) | 
|  | { | 
|  | simulate_htm = (value == BT_GATT_CCC_INDICATE) ? 1 : 0; | 
|  | } | 
|  |  | 
|  | static void indicate_cb(struct bt_conn *conn, | 
|  | struct bt_gatt_indicate_params *params, uint8_t err) | 
|  | { | 
|  | printk("Indication %s\n", err != 0U ? "fail" : "success"); | 
|  | } | 
|  |  | 
|  | static void indicate_destroy(struct bt_gatt_indicate_params *params) | 
|  | { | 
|  | printk("Indication complete\n"); | 
|  | indicating = 0U; | 
|  | } | 
|  |  | 
|  | /* Health Thermometer 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_changed, | 
|  | BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), | 
|  | /* more optional Characteristics */ | 
|  | ); | 
|  |  | 
|  | void hts_init(void) | 
|  | { | 
|  | if (temp_dev == NULL || !device_is_ready(temp_dev)) { | 
|  | printk("no temperature device; using simulated data\n"); | 
|  | temp_dev = NULL; | 
|  | } else { | 
|  | printk("temp device is %p, name is %s\n", temp_dev, | 
|  | temp_dev->name); | 
|  | } | 
|  | } | 
|  |  | 
|  | void hts_indicate(void) | 
|  | { | 
|  | /* Temperature measurements simulation */ | 
|  | struct sensor_value temp_value; | 
|  |  | 
|  | if (simulate_htm) { | 
|  | static uint8_t htm[5]; | 
|  | static double temperature = 20U; | 
|  | uint32_t mantissa; | 
|  | uint8_t exponent; | 
|  | int r; | 
|  |  | 
|  | if (indicating) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!temp_dev) { | 
|  | temperature++; | 
|  | if (temperature == 30U) { | 
|  | temperature = 20U; | 
|  | } | 
|  |  | 
|  | goto gatt_indicate; | 
|  | } | 
|  |  | 
|  | r = sensor_sample_fetch(temp_dev); | 
|  | if (r) { | 
|  | printk("sensor_sample_fetch failed return: %d\n", r); | 
|  | } | 
|  |  | 
|  | r = sensor_channel_get(temp_dev, TEMP_SENSOR_CHAN, &temp_value); | 
|  | if (r) { | 
|  | printk("sensor_channel_get failed return: %d\n", r); | 
|  | } | 
|  |  | 
|  | temperature = sensor_value_to_double(&temp_value); | 
|  |  | 
|  | gatt_indicate: | 
|  | printf("temperature is %gC\n", temperature); | 
|  |  | 
|  | mantissa = (uint32_t)(temperature * 100); | 
|  | exponent = (uint8_t)-2; | 
|  |  | 
|  | htm[0] = 0; /* temperature in celsius */ | 
|  | sys_put_le24(mantissa, (uint8_t *)&htm[1]); | 
|  | htm[4] = exponent; | 
|  |  | 
|  | ind_params.attr = &hts_svc.attrs[2]; | 
|  | ind_params.func = indicate_cb; | 
|  | ind_params.destroy = indicate_destroy; | 
|  | ind_params.data = &htm; | 
|  | ind_params.len = sizeof(htm); | 
|  |  | 
|  | if (bt_gatt_indicate(NULL, &ind_params) == 0) { | 
|  | indicating = 1U; | 
|  | } | 
|  | } | 
|  | } |