Graduation Thesis, use Nucleo and X-Nucleo BLE

Dependencies:   PulseSensor GSM Thermometer KalmanFilter

Committer:
DuyLionTran
Date:
Wed Feb 14 01:29:53 2018 +0000
Revision:
1:9eadd2dc4b6e
Parent:
0:64ca984b3efd
Child:
2:16f6cfcd7505
version 0.8 02-12-2018

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DuyLionTran 0:64ca984b3efd 1 #ifndef __BLE_HEALTHCARE_SERVICE_H__
DuyLionTran 0:64ca984b3efd 2 #define __BLE_HEALTHCARE_SERVICE_H__
DuyLionTran 0:64ca984b3efd 3
DuyLionTran 0:64ca984b3efd 4 #include "ble/BLE.h"
DuyLionTran 0:64ca984b3efd 5
DuyLionTran 0:64ca984b3efd 6 /**
DuyLionTran 0:64ca984b3efd 7 * @class HealthCareService
DuyLionTran 0:64ca984b3efd 8 * @brief
DuyLionTran 0:64ca984b3efd 9 */
DuyLionTran 0:64ca984b3efd 10 class HealthCareService {
DuyLionTran 0:64ca984b3efd 11 public:
DuyLionTran 0:64ca984b3efd 12 /**
DuyLionTran 0:64ca984b3efd 13 * @brief Location of sensor on the body.
DuyLionTran 0:64ca984b3efd 14 */
DuyLionTran 0:64ca984b3efd 15 enum TemperatureSensorLocation_t {
DuyLionTran 0:64ca984b3efd 16 TEMPERATURE_LOCATION_ARMPIT = 1, /*!< Armpit. */
DuyLionTran 0:64ca984b3efd 17 TEMPERATURE_LOCATION_BODY, /*!< Body. */
DuyLionTran 0:64ca984b3efd 18 TEMPERATURE_LOCATION_EAR, /*!< Ear. */
DuyLionTran 0:64ca984b3efd 19 TEMPERATURE_LOCATION_FINGER, /*!< Finger. */
DuyLionTran 0:64ca984b3efd 20 TEMPERATURE_LOCATION_GI_TRACT, /*!< GI tract */
DuyLionTran 0:64ca984b3efd 21 TEMPERATURE_LOCATION_MOUTH, /*!< Mouth. */
DuyLionTran 0:64ca984b3efd 22 TEMPERATURE_LOCATION_RECTUM, /*!< Rectum. */
DuyLionTran 0:64ca984b3efd 23 TEMPERATURE_LOCATION_TOE, /*!< Toe. */
DuyLionTran 0:64ca984b3efd 24 TEMPERATURE_LOCATION_EAR_DRUM, /*!< Eardrum. */
DuyLionTran 0:64ca984b3efd 25 };
DuyLionTran 0:64ca984b3efd 26 /**
DuyLionTran 0:64ca984b3efd 27 * Intended location of the heart rate sensor.
DuyLionTran 0:64ca984b3efd 28 */
DuyLionTran 0:64ca984b3efd 29 enum HeartRateSensorLocation_t {
DuyLionTran 0:64ca984b3efd 30 HRM_LOCATION_OTHER = 0, /*!< Other lacation. */
DuyLionTran 0:64ca984b3efd 31 HRM_LOCATION_CHEST = 1, /*!< Chest. */
DuyLionTran 0:64ca984b3efd 32 HRM_LOCATION_WRIST = 2, /*!< Wrist. */
DuyLionTran 0:64ca984b3efd 33 HRM_LOCATION_FINGER, /*!< Finger. */
DuyLionTran 0:64ca984b3efd 34 HRM_LOCATION_HAND, /*!< Hand. */
DuyLionTran 0:64ca984b3efd 35 HRM_LOCATION_EAR_LOBE, /*!< Ear lob. */
DuyLionTran 0:64ca984b3efd 36 HRM_LOCATION_FOOT, /*!< Foot. */
DuyLionTran 0:64ca984b3efd 37 };
DuyLionTran 0:64ca984b3efd 38
DuyLionTran 0:64ca984b3efd 39 public:
DuyLionTran 0:64ca984b3efd 40 /**
DuyLionTran 0:64ca984b3efd 41 * @param[in] _ble Reference to the BLE device.
DuyLionTran 0:64ca984b3efd 42 * @param[in] initialTemp Initial value in celsius.
DuyLionTran 0:64ca984b3efd 43 * @param[in] _tempLocation Location of the thermometer.
DuyLionTran 0:64ca984b3efd 44 * @param[in] hrmCounter Heart beats per minute measured by the heart rate sensor.
DuyLionTran 0:64ca984b3efd 45 * @param[in] _HRMlocation Intended location of the heart rate sensor.
DuyLionTran 0:64ca984b3efd 46 */
DuyLionTran 0:64ca984b3efd 47 HealthCareService(BLE &_ble,
DuyLionTran 0:64ca984b3efd 48 float initialTemp,
DuyLionTran 0:64ca984b3efd 49 uint8_t _tempLocation,
DuyLionTran 0:64ca984b3efd 50 // ) :
DuyLionTran 1:9eadd2dc4b6e 51 uint8_t hrmCounter,
DuyLionTran 0:64ca984b3efd 52 uint8_t _hrmLocation) :
DuyLionTran 0:64ca984b3efd 53 ble(_ble),
DuyLionTran 0:64ca984b3efd 54 temperatureValueByte(initialTemp),
DuyLionTran 1:9eadd2dc4b6e 55 hrmValueByte(hrmCounter),
DuyLionTran 0:64ca984b3efd 56 tempMeasurement(GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
DuyLionTran 0:64ca984b3efd 57 (TemperatureValueBytes *)temperatureValueByte.getPointer(),
DuyLionTran 0:64ca984b3efd 58 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
DuyLionTran 0:64ca984b3efd 59 tempLocation(GattCharacteristic::UUID_TEMPERATURE_TYPE_CHAR,
DuyLionTran 0:64ca984b3efd 60 &_tempLocation),
DuyLionTran 1:9eadd2dc4b6e 61 hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR,
DuyLionTran 1:9eadd2dc4b6e 62 (HeartRateValueBytes *)hrmValueByte.getPointer(),
DuyLionTran 0:64ca984b3efd 63 // hrmValueByte.getNumValueBytes(),
DuyLionTran 0:64ca984b3efd 64 // HeartRateValueBytes::MAX_VALUE_BYTES,
DuyLionTran 1:9eadd2dc4b6e 65 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
DuyLionTran 0:64ca984b3efd 66 hrmLocation(
DuyLionTran 0:64ca984b3efd 67 GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR,
DuyLionTran 0:64ca984b3efd 68 reinterpret_cast<uint8_t*>(&_hrmLocation))
DuyLionTran 0:64ca984b3efd 69
DuyLionTran 0:64ca984b3efd 70 {
DuyLionTran 1:9eadd2dc4b6e 71 GattCharacteristic *HealthCareChars[] = {&tempMeasurement, &tempLocation, &hrmRate,&hrmLocation};
DuyLionTran 0:64ca984b3efd 72 GattService HealthCareService(GattService::UUID_HEART_RATE_SERVICE , HealthCareChars, sizeof(HealthCareChars) / sizeof(GattCharacteristic *));
DuyLionTran 0:64ca984b3efd 73
DuyLionTran 0:64ca984b3efd 74 ble.addService(HealthCareService);
DuyLionTran 0:64ca984b3efd 75 }
DuyLionTran 0:64ca984b3efd 76
DuyLionTran 0:64ca984b3efd 77 /**
DuyLionTran 0:64ca984b3efd 78 * @brief Update the temperature being broadcast.
DuyLionTran 0:64ca984b3efd 79 * @param[in] temperature Floating point value of the temperature.
DuyLionTran 0:64ca984b3efd 80 */
DuyLionTran 0:64ca984b3efd 81 void updateTemperature(float temperature) {
DuyLionTran 0:64ca984b3efd 82 if (ble.getGapState().connected) {
DuyLionTran 0:64ca984b3efd 83 temperatureValueByte.updateTemperature(temperature);
DuyLionTran 0:64ca984b3efd 84 ble.gattServer().write(tempMeasurement.getValueHandle(), temperatureValueByte.getPointer(), sizeof(TemperatureValueBytes));
DuyLionTran 0:64ca984b3efd 85 }
DuyLionTran 0:64ca984b3efd 86 }
DuyLionTran 0:64ca984b3efd 87
DuyLionTran 0:64ca984b3efd 88 /**
DuyLionTran 0:64ca984b3efd 89 * @brief Update the location.
DuyLionTran 0:64ca984b3efd 90 * @param loc New location value.
DuyLionTran 0:64ca984b3efd 91 */
DuyLionTran 0:64ca984b3efd 92 void updateLocation(TemperatureSensorLocation_t loc) {
DuyLionTran 0:64ca984b3efd 93 ble.gattServer().write(tempLocation.getValueHandle(), reinterpret_cast<uint8_t *>(&loc), sizeof(uint8_t));
DuyLionTran 0:64ca984b3efd 94 }
DuyLionTran 0:64ca984b3efd 95
DuyLionTran 0:64ca984b3efd 96 /**
DuyLionTran 0:64ca984b3efd 97 * Update the heart rate that the service exposes.
DuyLionTran 0:64ca984b3efd 98 * The server sends a notification of the new value to clients that have
DuyLionTran 0:64ca984b3efd 99 * subscribed to updates of the heart rate measurement characteristic; clients
DuyLionTran 0:64ca984b3efd 100 * reading the heart rate measurement characteristic after the update obtain
DuyLionTran 0:64ca984b3efd 101 * the updated value.
DuyLionTran 0:64ca984b3efd 102 *
DuyLionTran 0:64ca984b3efd 103 * @param[in] hrmCounter Heart rate measured in BPM.
DuyLionTran 0:64ca984b3efd 104 * @attention This function must be called in the execution context of the BLE stack.
DuyLionTran 0:64ca984b3efd 105 */
DuyLionTran 0:64ca984b3efd 106 void updateHeartRate(uint16_t hrmCounter) {
DuyLionTran 1:9eadd2dc4b6e 107 hrmValueByte.updateHeartRate(hrmCounter);
DuyLionTran 1:9eadd2dc4b6e 108 ble.gattServer().write(
DuyLionTran 1:9eadd2dc4b6e 109 hrmRate.getValueHandle(),
DuyLionTran 1:9eadd2dc4b6e 110 hrmValueByte.getPointer(),
DuyLionTran 1:9eadd2dc4b6e 111 hrmValueByte.getNumValueBytes()
DuyLionTran 1:9eadd2dc4b6e 112 );
DuyLionTran 0:64ca984b3efd 113 }
DuyLionTran 0:64ca984b3efd 114
DuyLionTran 0:64ca984b3efd 115 private:
DuyLionTran 0:64ca984b3efd 116 /* Private internal representation for the bytes used to work with the vaulue of the temperature characteristic. */
DuyLionTran 0:64ca984b3efd 117 struct TemperatureValueBytes {
DuyLionTran 0:64ca984b3efd 118 static const unsigned OFFSET_OF_FLAGS = 0;
DuyLionTran 0:64ca984b3efd 119 static const unsigned OFFSET_OF_VALUE = OFFSET_OF_FLAGS + sizeof(uint8_t);
DuyLionTran 0:64ca984b3efd 120 static const unsigned SIZEOF_VALUE_BYTES = sizeof(uint8_t) + sizeof(float);
DuyLionTran 0:64ca984b3efd 121
DuyLionTran 0:64ca984b3efd 122 static const unsigned TEMPERATURE_UNITS_FLAG_POS = 0;
DuyLionTran 0:64ca984b3efd 123 static const unsigned TIMESTAMP_FLAG_POS = 1;
DuyLionTran 0:64ca984b3efd 124 static const unsigned TEMPERATURE_TYPE_FLAG_POS = 2;
DuyLionTran 0:64ca984b3efd 125
DuyLionTran 0:64ca984b3efd 126 static const uint8_t TEMPERATURE_UNITS_CELSIUS = 0;
DuyLionTran 0:64ca984b3efd 127 static const uint8_t TEMPERATURE_UNITS_FAHRENHEIT = 1;
DuyLionTran 0:64ca984b3efd 128
DuyLionTran 0:64ca984b3efd 129 TemperatureValueBytes(float initialTemperature) : bytes() {
DuyLionTran 0:64ca984b3efd 130 /* Assumption: temperature values are expressed in celsius */
DuyLionTran 0:64ca984b3efd 131 bytes[OFFSET_OF_FLAGS] = (TEMPERATURE_UNITS_CELSIUS << TEMPERATURE_UNITS_FLAG_POS) |
DuyLionTran 0:64ca984b3efd 132 (false << TIMESTAMP_FLAG_POS) |
DuyLionTran 0:64ca984b3efd 133 (false << TEMPERATURE_TYPE_FLAG_POS);
DuyLionTran 0:64ca984b3efd 134 updateTemperature(initialTemperature);
DuyLionTran 0:64ca984b3efd 135 }
DuyLionTran 0:64ca984b3efd 136
DuyLionTran 0:64ca984b3efd 137 void updateTemperature(float temp) {
DuyLionTran 0:64ca984b3efd 138 uint32_t temp_ieee11073 = quick_ieee11073_from_float(temp);
DuyLionTran 0:64ca984b3efd 139 memcpy(&bytes[OFFSET_OF_VALUE], &temp_ieee11073, sizeof(float));
DuyLionTran 0:64ca984b3efd 140 }
DuyLionTran 0:64ca984b3efd 141
DuyLionTran 0:64ca984b3efd 142 uint8_t *getPointer(void) {
DuyLionTran 0:64ca984b3efd 143 return bytes;
DuyLionTran 0:64ca984b3efd 144 }
DuyLionTran 0:64ca984b3efd 145
DuyLionTran 0:64ca984b3efd 146 const uint8_t *getPointer(void) const {
DuyLionTran 0:64ca984b3efd 147 return bytes;
DuyLionTran 0:64ca984b3efd 148 }
DuyLionTran 0:64ca984b3efd 149
DuyLionTran 0:64ca984b3efd 150 private:
DuyLionTran 0:64ca984b3efd 151 /**
DuyLionTran 0:64ca984b3efd 152 * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
DuyLionTran 0:64ca984b3efd 153 * @param temperature The temperature as a float.
DuyLionTran 0:64ca984b3efd 154 * @return The temperature in 11073-20601 FLOAT-Type format.
DuyLionTran 0:64ca984b3efd 155 */
DuyLionTran 0:64ca984b3efd 156 uint32_t quick_ieee11073_from_float(float temperature) {
DuyLionTran 0:64ca984b3efd 157 uint8_t exponent = 0xFE; //Exponent is -2
DuyLionTran 0:64ca984b3efd 158 uint32_t mantissa = (uint32_t)(temperature * 100);
DuyLionTran 0:64ca984b3efd 159
DuyLionTran 0:64ca984b3efd 160 return (((uint32_t)exponent) << 24) | mantissa;
DuyLionTran 0:64ca984b3efd 161 }
DuyLionTran 0:64ca984b3efd 162
DuyLionTran 0:64ca984b3efd 163 private:
DuyLionTran 0:64ca984b3efd 164 /* First byte: 8-bit flags. Second field is a float holding the temperature value. */
DuyLionTran 0:64ca984b3efd 165 /* See https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
DuyLionTran 0:64ca984b3efd 166 uint8_t bytes[SIZEOF_VALUE_BYTES];
DuyLionTran 0:64ca984b3efd 167 };
DuyLionTran 0:64ca984b3efd 168
DuyLionTran 0:64ca984b3efd 169 protected:
DuyLionTran 0:64ca984b3efd 170 /*
DuyLionTran 0:64ca984b3efd 171 * Heart rate measurement value.
DuyLionTran 0:64ca984b3efd 172 */
DuyLionTran 0:64ca984b3efd 173 struct HeartRateValueBytes {
DuyLionTran 0:64ca984b3efd 174 /* 1 byte for the Flags, and up to two bytes for heart rate value. */
DuyLionTran 0:64ca984b3efd 175 static const unsigned MAX_VALUE_BYTES = 3;
DuyLionTran 0:64ca984b3efd 176 static const unsigned FLAGS_BYTE_INDEX = 0;
DuyLionTran 0:64ca984b3efd 177
DuyLionTran 0:64ca984b3efd 178 static const unsigned VALUE_FORMAT_BITNUM = 0;
DuyLionTran 0:64ca984b3efd 179 static const uint8_t VALUE_FORMAT_FLAG = (1 << VALUE_FORMAT_BITNUM);
DuyLionTran 0:64ca984b3efd 180
DuyLionTran 0:64ca984b3efd 181 HeartRateValueBytes(uint16_t hrmCounter) : valueBytes() {
DuyLionTran 0:64ca984b3efd 182 updateHeartRate(hrmCounter);
DuyLionTran 0:64ca984b3efd 183 }
DuyLionTran 0:64ca984b3efd 184
DuyLionTran 0:64ca984b3efd 185 void updateHeartRate(uint16_t hrmCounter) {
DuyLionTran 0:64ca984b3efd 186 if (hrmCounter <= 255) {
DuyLionTran 0:64ca984b3efd 187 valueBytes[FLAGS_BYTE_INDEX] &= ~VALUE_FORMAT_FLAG;
DuyLionTran 0:64ca984b3efd 188 valueBytes[FLAGS_BYTE_INDEX + 1] = hrmCounter;
DuyLionTran 0:64ca984b3efd 189 } else {
DuyLionTran 0:64ca984b3efd 190 valueBytes[FLAGS_BYTE_INDEX] |= VALUE_FORMAT_FLAG;
DuyLionTran 0:64ca984b3efd 191 valueBytes[FLAGS_BYTE_INDEX + 1] = (uint8_t)(hrmCounter & 0xFF);
DuyLionTran 0:64ca984b3efd 192 valueBytes[FLAGS_BYTE_INDEX + 2] = (uint8_t)(hrmCounter >> 8);
DuyLionTran 0:64ca984b3efd 193 }
DuyLionTran 0:64ca984b3efd 194 }
DuyLionTran 0:64ca984b3efd 195
DuyLionTran 0:64ca984b3efd 196 uint8_t *getPointer(void) {
DuyLionTran 0:64ca984b3efd 197 return valueBytes;
DuyLionTran 0:64ca984b3efd 198 }
DuyLionTran 0:64ca984b3efd 199
DuyLionTran 0:64ca984b3efd 200 const uint8_t *getPointer(void) const {
DuyLionTran 0:64ca984b3efd 201 return valueBytes;
DuyLionTran 0:64ca984b3efd 202 }
DuyLionTran 0:64ca984b3efd 203
DuyLionTran 0:64ca984b3efd 204 unsigned getNumValueBytes(void) const {
DuyLionTran 0:64ca984b3efd 205 if (valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) {
DuyLionTran 0:64ca984b3efd 206 return 1 + sizeof(uint16_t);
DuyLionTran 0:64ca984b3efd 207 }
DuyLionTran 0:64ca984b3efd 208 else {
DuyLionTran 0:64ca984b3efd 209 return 1 + sizeof(uint8_t);
DuyLionTran 0:64ca984b3efd 210 }
DuyLionTran 0:64ca984b3efd 211 }
DuyLionTran 0:64ca984b3efd 212
DuyLionTran 0:64ca984b3efd 213 private:
DuyLionTran 0:64ca984b3efd 214 uint8_t valueBytes[MAX_VALUE_BYTES];
DuyLionTran 0:64ca984b3efd 215 };
DuyLionTran 0:64ca984b3efd 216
DuyLionTran 0:64ca984b3efd 217
DuyLionTran 0:64ca984b3efd 218 protected:
DuyLionTran 0:64ca984b3efd 219 BLE &ble;
DuyLionTran 0:64ca984b3efd 220 TemperatureValueBytes temperatureValueByte;
DuyLionTran 1:9eadd2dc4b6e 221 HeartRateValueBytes hrmValueByte;
DuyLionTran 0:64ca984b3efd 222
DuyLionTran 0:64ca984b3efd 223 ReadOnlyGattCharacteristic<TemperatureValueBytes> tempMeasurement;
DuyLionTran 0:64ca984b3efd 224 ReadOnlyGattCharacteristic<uint8_t> tempLocation;
DuyLionTran 0:64ca984b3efd 225
DuyLionTran 1:9eadd2dc4b6e 226 ReadOnlyGattCharacteristic<HeartRateValueBytes> hrmRate;
DuyLionTran 0:64ca984b3efd 227 ReadOnlyGattCharacteristic<uint8_t> hrmLocation;
DuyLionTran 0:64ca984b3efd 228 };
DuyLionTran 0:64ca984b3efd 229
DuyLionTran 0:64ca984b3efd 230
DuyLionTran 0:64ca984b3efd 231 #endif /* __BLE_HEALTHCARE_SERVICE_H__ */