Bill Schilit / BLE_API

Fork of BLE_API by Bluetooth Low Energy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HealthThermometerService.h Source File

HealthThermometerService.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef __BLE_HEALTH_THERMOMETER_SERVICE_H__
00018 #define __BLE_HEALTH_THERMOMETER_SERVICE_H__
00019 
00020 #include "BLEDevice.h"
00021 
00022 /**
00023 * @class HealthThermometerService
00024 * @brief BLE Health Thermometer Service. This service provides the location of the thermometer and the temperature.  <br>
00025 * Service:  https://developer.bluetooth.org/gatt/profiles/Pages/ProfileViewer.aspx?u=org.bluetooth.profile.health_thermometer.xml <br>
00026 * Temperature Measurement: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml <br>
00027 * Temperature Type: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_type.xml
00028 */
00029 class HealthThermometerService {
00030 public:
00031     /**
00032     * @enum Sensor Location
00033     * @brief Location of sensor on the body
00034     */
00035     enum SensorLocation_t  {
00036         LOCATION_ARMPIT  = 1,    /*!< armpit */
00037         LOCATION_BODY ,          /*!< body */
00038         LOCATION_EAR ,           /*!< ear */
00039         LOCATION_FINGER ,        /*!< finger */
00040         LOCATION_GI_TRACT ,      /*!< GI tract */
00041         LOCATION_MOUTH ,         /*!< mouth */
00042         LOCATION_RECTUM ,        /*!< rectum */
00043         LOCATION_TOE ,           /*!< toe */
00044         LOCATION_EAR_DRUM ,      /*!< ear drum */
00045     };
00046 
00047 public:
00048     /**
00049      * @brief Add the Health Thermometer Service to an existing ble object, initialize with temperature and location.
00050      * @param[ref] _ble         reference to the BLE device
00051      * @param[in] initialTemp  initial value in celsius
00052      * @param[in] _location
00053      */
00054     HealthThermometerService(BLEDevice &_ble, float initialTemp, uint8_t _location) :
00055         ble(_ble),
00056         valueBytes(initialTemp),
00057         tempMeasurement(GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, valueBytes.getPointer(),
00058                         sizeof(TemperatureValueBytes), sizeof(TemperatureValueBytes),
00059                         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
00060         tempLocation(GattCharacteristic::UUID_TEMPERATURE_TYPE_CHAR, (uint8_t *)&_location, sizeof(_location), sizeof(_location),
00061                      GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ) {
00062 
00063         GattCharacteristic *hrmChars[] = {&tempMeasurement, &tempLocation, };
00064         GattService         hrmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, hrmChars, sizeof(hrmChars) / sizeof(GattCharacteristic *));
00065 
00066         ble.addService(hrmService);
00067     }
00068 
00069     /**
00070     * @brief Update the temperature being broadcast
00071     *
00072     * @param[in] temperature
00073     *                   Floating point value of the temperature
00074     *
00075     */
00076     void updateTemperature(float temperature) {
00077         if (ble.getGapState().connected) {
00078             valueBytes.updateTemperature(temperature);
00079             ble.updateCharacteristicValue (tempMeasurement.getValueAttribute().getHandle(), valueBytes.getPointer(), sizeof(TemperatureValueBytes));
00080         }
00081     }
00082 
00083     /**
00084      * @brief Update the location.
00085      * @param loc
00086      *        new location value.
00087      */
00088     void updateLocation(SensorLocation_t  loc) {
00089         ble.updateCharacteristicValue (tempLocation.getValueHandle(), reinterpret_cast<uint8_t *>(&loc), sizeof(uint8_t));
00090     }
00091 
00092 private:
00093     /* Private internal representation for the bytes used to work with the vaulue of the heart-rate characteristic. */
00094     struct TemperatureValueBytes {
00095         static const unsigned OFFSET_OF_FLAGS    = 0;
00096         static const unsigned OFFSET_OF_VALUE    = OFFSET_OF_FLAGS + sizeof(uint8_t);
00097         static const unsigned SIZEOF_VALUE_BYTES = sizeof(uint8_t) + sizeof(float);
00098 
00099         static const unsigned TEMPERATURE_UNITS_FLAG_POS = 0;
00100         static const unsigned TIMESTAMP_FLAG_POS         = 1;
00101         static const unsigned TEMPERATURE_TYPE_FLAG_POS  = 2;
00102 
00103         static const uint8_t  TEMPERATURE_UNITS_CELSIUS    = 0;
00104         static const uint8_t  TEMPERATURE_UNITS_FAHRENHEIT = 1;
00105 
00106         TemperatureValueBytes(float initialTemperature) : bytes() {
00107             /* assumption: temperature values are expressed in Celsius */
00108             bytes[OFFSET_OF_FLAGS] =  (TEMPERATURE_UNITS_CELSIUS << TEMPERATURE_UNITS_FLAG_POS) |
00109                                       (false << TIMESTAMP_FLAG_POS) |
00110                                       (false << TEMPERATURE_TYPE_FLAG_POS);
00111             updateTemperature(initialTemperature);
00112         }
00113 
00114         void updateTemperature(float temp) {
00115             uint32_t temp_ieee11073 = quick_ieee11073_from_float(temp);
00116             memcpy(&bytes[OFFSET_OF_VALUE], &temp_ieee11073, sizeof(float));
00117         }
00118 
00119         uint8_t       *getPointer(void) {
00120             return bytes;
00121         }
00122 
00123         const uint8_t *getPointer(void) const {
00124             return bytes;
00125         }
00126 
00127 private:
00128         /**
00129          * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
00130          * @param temperature The temperature as a float.
00131          * @return The temperature in 11073-20601 FLOAT-Type format.
00132          */
00133         uint32_t quick_ieee11073_from_float(float temperature) {
00134             uint8_t  exponent = 0xFE; //exponent is -2
00135             uint32_t mantissa = (uint32_t)(temperature * 100);
00136 
00137             return (((uint32_t)exponent) << 24) | mantissa;
00138         }
00139 
00140 private:
00141         /* First byte = 8-bit flags, Second field is a float holding the temperature value. */
00142         /* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
00143         uint8_t bytes[SIZEOF_VALUE_BYTES];
00144     };
00145 
00146 private:
00147     BLEDevice             &ble;
00148     TemperatureValueBytes  valueBytes;
00149     GattCharacteristic     tempMeasurement;
00150     GattCharacteristic     tempLocation;
00151 };
00152 
00153 #endif /* #ifndef __BLE_HEALTH_THERMOMETER_SERVICE_H__*/