Graduation Thesis, use Nucleo and X-Nucleo BLE

Dependencies:   PulseSensor GSM Thermometer KalmanFilter

Revision:
0:64ca984b3efd
Child:
1:9eadd2dc4b6e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/application/ble_healthcare_service.h	Tue Feb 13 18:53:45 2018 +0000
@@ -0,0 +1,231 @@
+#ifndef __BLE_HEALTHCARE_SERVICE_H__
+#define __BLE_HEALTHCARE_SERVICE_H__
+
+#include "ble/BLE.h"
+
+/**
+  * @class HealthCareService
+  * @brief 
+  */
+class HealthCareService {   
+public: 
+    /**
+      * @brief Location of sensor on the body.
+      */
+    enum TemperatureSensorLocation_t {
+        TEMPERATURE_LOCATION_ARMPIT = 1,    /*!< Armpit. */
+        TEMPERATURE_LOCATION_BODY,          /*!< Body. */
+        TEMPERATURE_LOCATION_EAR,           /*!< Ear. */
+        TEMPERATURE_LOCATION_FINGER,        /*!< Finger. */
+        TEMPERATURE_LOCATION_GI_TRACT,      /*!< GI tract */
+        TEMPERATURE_LOCATION_MOUTH,         /*!< Mouth. */
+        TEMPERATURE_LOCATION_RECTUM,        /*!< Rectum. */
+        TEMPERATURE_LOCATION_TOE,           /*!< Toe. */
+        TEMPERATURE_LOCATION_EAR_DRUM,      /*!< Eardrum. */
+    };
+    /**
+      * Intended location of the heart rate sensor.
+      */
+    enum HeartRateSensorLocation_t {
+        HRM_LOCATION_OTHER = 0,     /*!< Other lacation. */
+        HRM_LOCATION_CHEST = 1,     /*!< Chest. */
+        HRM_LOCATION_WRIST = 2,     /*!< Wrist. */
+        HRM_LOCATION_FINGER,        /*!< Finger. */
+        HRM_LOCATION_HAND,          /*!< Hand. */
+        HRM_LOCATION_EAR_LOBE,      /*!< Ear lob. */
+        HRM_LOCATION_FOOT,          /*!< Foot. */
+    };    
+    
+public:     
+    /** 
+      * @param[in] _ble             Reference to the BLE device.
+      * @param[in] initialTemp      Initial value in celsius.
+      * @param[in] _tempLocation    Location of the thermometer.
+      * @param[in] hrmCounter       Heart beats per minute measured by the heart rate sensor.
+      * @param[in] _HRMlocation     Intended location of the heart rate sensor.
+      */
+    HealthCareService(BLE &_ble, 
+                      float initialTemp, 
+                      uint8_t  _tempLocation,
+//                      ) :
+//                      uint16_t hrmCounter,
+                      uint8_t _hrmLocation) :
+        ble(_ble), 
+        temperatureValueByte(initialTemp),
+//        hrmValueByte(hrmCounter),
+        tempMeasurement(GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, 
+                       (TemperatureValueBytes *)temperatureValueByte.getPointer(), 
+                       GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+        tempLocation(GattCharacteristic::UUID_TEMPERATURE_TYPE_CHAR, 
+                    &_tempLocation),
+//        hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR,
+//               (HeartRateValueBytes *)hrmValueByte.getPointer(),
+//                hrmValueByte.getNumValueBytes(),
+//                HeartRateValueBytes::MAX_VALUE_BYTES,
+//                GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+        hrmLocation(
+            GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR,
+            reinterpret_cast<uint8_t*>(&_hrmLocation))                    
+        
+        {
+            GattCharacteristic *HealthCareChars[] = {&tempMeasurement, &tempLocation, &hrmLocation};
+            GattService         HealthCareService(GattService::UUID_HEART_RATE_SERVICE , HealthCareChars, sizeof(HealthCareChars) / sizeof(GattCharacteristic *));
+
+            ble.addService(HealthCareService);
+        }
+
+    /**
+      * @brief Update the temperature being broadcast.
+      * @param[in] temperature Floating point value of the temperature.
+      */
+    void updateTemperature(float temperature) {
+        if (ble.getGapState().connected) {
+            temperatureValueByte.updateTemperature(temperature);
+            ble.gattServer().write(tempMeasurement.getValueHandle(), temperatureValueByte.getPointer(), sizeof(TemperatureValueBytes));
+        }
+    }
+    
+    /**
+      * @brief Update the location.
+      * @param loc New location value.     
+      */
+    void updateLocation(TemperatureSensorLocation_t loc) {
+        ble.gattServer().write(tempLocation.getValueHandle(), reinterpret_cast<uint8_t *>(&loc), sizeof(uint8_t));
+    }
+    
+    /**
+      * Update the heart rate that the service exposes.
+      * The server sends a notification of the new value to clients that have
+      * subscribed to updates of the heart rate measurement characteristic; clients
+      * reading the heart rate measurement characteristic after the update obtain
+      * the updated value.
+      *
+      * @param[in] hrmCounter Heart rate measured in BPM.
+      * @attention This function must be called in the execution context of the BLE stack.
+      */
+    void updateHeartRate(uint16_t hrmCounter) {
+//        hrmValueByte.updateHeartRate(hrmCounter);
+//        ble.gattServer().write(
+//            hrmRate.getValueHandle(),
+//            hrmValueByte.getPointer(),
+//            hrmValueByte.getNumValueBytes()
+//        );
+    }
+    
+private:
+    /* Private internal representation for the bytes used to work with the vaulue of the temperature characteristic. */
+    struct TemperatureValueBytes {
+        static const unsigned OFFSET_OF_FLAGS    = 0;
+        static const unsigned OFFSET_OF_VALUE    = OFFSET_OF_FLAGS + sizeof(uint8_t);
+        static const unsigned SIZEOF_VALUE_BYTES = sizeof(uint8_t) + sizeof(float);
+
+        static const unsigned TEMPERATURE_UNITS_FLAG_POS = 0;
+        static const unsigned TIMESTAMP_FLAG_POS         = 1;
+        static const unsigned TEMPERATURE_TYPE_FLAG_POS  = 2;
+
+        static const uint8_t  TEMPERATURE_UNITS_CELSIUS    = 0;
+        static const uint8_t  TEMPERATURE_UNITS_FAHRENHEIT = 1;
+
+        TemperatureValueBytes(float initialTemperature) : bytes() {
+            /* Assumption: temperature values are expressed in celsius */
+            bytes[OFFSET_OF_FLAGS] =  (TEMPERATURE_UNITS_CELSIUS << TEMPERATURE_UNITS_FLAG_POS) |
+                                      (false << TIMESTAMP_FLAG_POS) |
+                                      (false << TEMPERATURE_TYPE_FLAG_POS);
+            updateTemperature(initialTemperature);
+        }
+
+        void updateTemperature(float temp) {
+            uint32_t temp_ieee11073 = quick_ieee11073_from_float(temp);
+            memcpy(&bytes[OFFSET_OF_VALUE], &temp_ieee11073, sizeof(float));
+        }
+
+        uint8_t       *getPointer(void) {
+            return bytes;
+        }
+
+        const uint8_t *getPointer(void) const {
+            return bytes;
+        }
+
+private:
+        /**
+          * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
+          * @param temperature The temperature as a float.
+          * @return The temperature in 11073-20601 FLOAT-Type format.
+          */
+        uint32_t quick_ieee11073_from_float(float temperature) {
+            uint8_t  exponent = 0xFE; //Exponent is -2
+            uint32_t mantissa = (uint32_t)(temperature * 100);
+
+            return (((uint32_t)exponent) << 24) | mantissa;
+        }
+
+private:
+        /* First byte: 8-bit flags. Second field is a float holding the temperature value. */
+        /* See https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
+        uint8_t bytes[SIZEOF_VALUE_BYTES];
+    };
+
+protected:
+    /*
+     * Heart rate measurement value.
+     */
+    struct HeartRateValueBytes {
+        /* 1 byte for the Flags, and up to two bytes for heart rate value. */
+        static const unsigned MAX_VALUE_BYTES = 3;
+        static const unsigned FLAGS_BYTE_INDEX = 0;
+
+        static const unsigned VALUE_FORMAT_BITNUM = 0;
+        static const uint8_t  VALUE_FORMAT_FLAG = (1 << VALUE_FORMAT_BITNUM);
+
+        HeartRateValueBytes(uint16_t hrmCounter) : valueBytes() {
+            updateHeartRate(hrmCounter);
+        }
+
+        void updateHeartRate(uint16_t hrmCounter) {
+            if (hrmCounter <= 255) {
+                valueBytes[FLAGS_BYTE_INDEX] &= ~VALUE_FORMAT_FLAG;
+                valueBytes[FLAGS_BYTE_INDEX + 1] = hrmCounter;
+            } else {
+                valueBytes[FLAGS_BYTE_INDEX] |= VALUE_FORMAT_FLAG;
+                valueBytes[FLAGS_BYTE_INDEX + 1] = (uint8_t)(hrmCounter & 0xFF);
+                valueBytes[FLAGS_BYTE_INDEX + 2] = (uint8_t)(hrmCounter >> 8);
+            }
+        }
+
+        uint8_t *getPointer(void) {
+            return valueBytes;
+        }
+
+        const uint8_t *getPointer(void) const {
+            return valueBytes;
+        }
+
+        unsigned getNumValueBytes(void) const {
+            if (valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) {
+                return 1 + sizeof(uint16_t);
+            } 
+            else {
+                return 1 + sizeof(uint8_t);
+            }
+        }
+
+    private:
+        uint8_t valueBytes[MAX_VALUE_BYTES];
+    };
+
+
+protected:
+    BLE                                               &ble;
+    TemperatureValueBytes                              temperatureValueByte;
+//    HeartRateValueBytes                                hrmValueByte;
+
+    ReadOnlyGattCharacteristic<TemperatureValueBytes>  tempMeasurement;
+    ReadOnlyGattCharacteristic<uint8_t>                tempLocation;
+
+//    ReadOnlyGattCharacteristic<HeartRateValueBytes>    hrmRate;
+    ReadOnlyGattCharacteristic<uint8_t>                hrmLocation;    
+};
+
+
+#endif /* __BLE_HEALTHCARE_SERVICE_H__ */