Graduation Thesis, use Nucleo and X-Nucleo BLE
Dependencies: PulseSensor GSM Thermometer KalmanFilter
Application/ble_healthcare_service.h
- Committer:
- DuyLionTran
- Date:
- 2018-06-23
- Revision:
- 25:8621ebb6ea0c
- Parent:
- 17:b7c2db3e7282
File content as of revision 25:8621ebb6ea0c:
#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_UNKNOWN = 0, /*!< Unknown. */ 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 location. */ 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. */ }; const static uint16_t DEVICE_INFO_SERVICE_UUID = 0x180A; const static uint16_t USER_DATA_SERVICE_UUID = 0x181C; const static uint16_t USER_DATA_DIGITAL_CHARACTERISTIC_UUID = 0x2A57; 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. * @param[in] controlVal_1 Optional control value 1 */ HealthCareService(BLE &_ble, float initialTemp, uint8_t _tempLocation, // ) : uint16_t hrmCounter, uint8_t _hrmLocation, uint8_t controlVal_1 ) : 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, 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)), controlState(USER_DATA_DIGITAL_CHARACTERISTIC_UUID, &controlVal_1) /* UUID_GLUCOSE_SERVICE UUID_HEALTH_THERMOMETER_SERVICE */ { GattCharacteristic *HealthThermChars[] = {&tempMeasurement, &tempLocation}; GattService HealthThermService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, HealthThermChars, sizeof(HealthThermChars) / sizeof(GattCharacteristic *)); ble.addService(HealthThermService); GattCharacteristic *HRMChars[] = {&hrmRate, &hrmLocation}; GattService HRMService(GattService::UUID_HEART_RATE_SERVICE , HRMChars, sizeof(HRMChars) / sizeof(GattCharacteristic *)); ble.addService(HRMService); GattCharacteristic *CONChars[] = {&controlState}; GattService CONService(USER_DATA_SERVICE_UUID , CONChars, sizeof(CONChars) / sizeof(GattCharacteristic *)); ble.addService(CONService); } GattAttribute::Handle_t getValueHandle() const { return controlState.getValueHandle(); } GattAttribute::Handle_t getTypeHandle() const { return tempLocation.getValueHandle(); } GattAttribute::Handle_t getLocationHandle() const { return hrmLocation.getValueHandle(); } /** * @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 temperature location. * @param loc New location value. */ void updateType(uint8_t loc) { ble.gattServer().write(tempLocation.getValueHandle(), reinterpret_cast<uint8_t *>(&loc), sizeof(uint8_t)); } /** * @brief Update the temperature location. * @param loc New location value. */ void updateLocation(uint8_t loc) { ble.gattServer().write(hrmLocation.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; ReadWriteGattCharacteristic<uint8_t> tempLocation; GattCharacteristic hrmRate; ReadWriteGattCharacteristic<uint8_t> hrmLocation; ReadWriteGattCharacteristic<uint8_t> controlState; }; #endif /* __BLE_HEALTHCARE_SERVICE_H__ */