Graduation Thesis, use Nucleo and X-Nucleo BLE
Dependencies: PulseSensor GSM Thermometer KalmanFilter
Diff: application/ble_healthcare_service.h
- 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__ */