High level Bluetooth Low Energy API and radio abstraction layer

Dependents:   BLE_ANCS_SDAPI BLE_temperature BLE_HeartRate BLE_ANCS_SDAPI_IRC ... more

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 "ble/BLE.h"
00021 
00022 /**
00023 * @class HealthThermometerService
00024 * @brief BLE Health Thermometer Service. This service provides the location of the thermometer and the temperature.
00025 * Service:  https://developer.bluetooth.org/gatt/profiles/Pages/ProfileViewer.aspx?u=org.bluetooth.profile.health_thermometer.xml
00026 * Temperature Measurement: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml
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 ,      /*!< Eardrum. */
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(BLE &_ble, float initialTemp, uint8_t _location) :
00055         ble(_ble),
00056         valueBytes(initialTemp),
00057         tempMeasurement(GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, (TemperatureValueBytes *)valueBytes.getPointer(), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
00058         tempLocation(GattCharacteristic::UUID_TEMPERATURE_TYPE_CHAR, &_location) {
00059 
00060         GattCharacteristic *hrmChars[] = {&tempMeasurement, &tempLocation, };
00061         GattService         hrmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, hrmChars, sizeof(hrmChars) / sizeof(GattCharacteristic *));
00062 
00063         ble.addService(hrmService);
00064     }
00065 
00066     /**
00067     * @brief Update the temperature being broadcast.
00068     *
00069     * @param[in] temperature
00070     *                   Floating point value of the temperature.
00071     *
00072     */
00073     void updateTemperature(float temperature) {
00074         if (ble.getGapState().connected) {
00075             valueBytes.updateTemperature(temperature);
00076             ble.gattServer().write(tempMeasurement.getValueHandle(), valueBytes.getPointer(), sizeof(TemperatureValueBytes));
00077         }
00078     }
00079 
00080     /**
00081      * @brief Update the location.
00082      * @param loc
00083      *        New location value.
00084      */
00085     void updateLocation(SensorLocation_t  loc) {
00086         ble.gattServer().write(tempLocation.getValueHandle(), reinterpret_cast<uint8_t *>(&loc), sizeof(uint8_t));
00087     }
00088 
00089 private:
00090     /* Private internal representation for the bytes used to work with the vaulue of the temperature characteristic. */
00091     struct TemperatureValueBytes {
00092         static const unsigned OFFSET_OF_FLAGS    = 0;
00093         static const unsigned OFFSET_OF_VALUE    = OFFSET_OF_FLAGS + sizeof(uint8_t);
00094         static const unsigned SIZEOF_VALUE_BYTES = sizeof(uint8_t) + sizeof(float);
00095 
00096         static const unsigned TEMPERATURE_UNITS_FLAG_POS = 0;
00097         static const unsigned TIMESTAMP_FLAG_POS         = 1;
00098         static const unsigned TEMPERATURE_TYPE_FLAG_POS  = 2;
00099 
00100         static const uint8_t  TEMPERATURE_UNITS_CELSIUS    = 0;
00101         static const uint8_t  TEMPERATURE_UNITS_FAHRENHEIT = 1;
00102 
00103         TemperatureValueBytes(float initialTemperature) : bytes() {
00104             /* Assumption: temperature values are expressed in celsius */
00105             bytes[OFFSET_OF_FLAGS] =  (TEMPERATURE_UNITS_CELSIUS << TEMPERATURE_UNITS_FLAG_POS) |
00106                                       (false << TIMESTAMP_FLAG_POS) |
00107                                       (false << TEMPERATURE_TYPE_FLAG_POS);
00108             updateTemperature(initialTemperature);
00109         }
00110 
00111         void updateTemperature(float temp) {
00112             uint32_t temp_ieee11073 = quick_ieee11073_from_float(temp);
00113             memcpy(&bytes[OFFSET_OF_VALUE], &temp_ieee11073, sizeof(float));
00114         }
00115 
00116         uint8_t       *getPointer(void) {
00117             return bytes;
00118         }
00119 
00120         const uint8_t *getPointer(void) const {
00121             return bytes;
00122         }
00123 
00124 private:
00125         /**
00126          * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
00127          * @param temperature The temperature as a float.
00128          * @return The temperature in 11073-20601 FLOAT-Type format.
00129          */
00130         uint32_t quick_ieee11073_from_float(float temperature) {
00131             uint8_t  exponent = 0xFE; //Exponent is -2
00132             uint32_t mantissa = (uint32_t)(temperature * 100);
00133 
00134             return (((uint32_t)exponent) << 24) | mantissa;
00135         }
00136 
00137 private:
00138         /* First byte: 8-bit flags. Second field is a float holding the temperature value. */
00139         /* See https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
00140         uint8_t bytes[SIZEOF_VALUE_BYTES];
00141     };
00142 
00143 protected:
00144     BLE                                               &ble;
00145     TemperatureValueBytes                              valueBytes;
00146     ReadOnlyGattCharacteristic<TemperatureValueBytes>   tempMeasurement;
00147     ReadOnlyGattCharacteristic<uint8_t>                 tempLocation;
00148 };
00149 
00150 #endif /* #ifndef __BLE_HEALTH_THERMOMETER_SERVICE_H__*/