Pinned to some recent date

Committer:
Simon Cooksey
Date:
Thu Nov 17 16:43:53 2016 +0000
Revision:
0:fb7af294d5d9
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Simon Cooksey 0:fb7af294d5d9 1 /* mbed Microcontroller Library
Simon Cooksey 0:fb7af294d5d9 2 * Copyright (c) 2006-2013 ARM Limited
Simon Cooksey 0:fb7af294d5d9 3 *
Simon Cooksey 0:fb7af294d5d9 4 * Licensed under the Apache License, Version 2.0 (the "License");
Simon Cooksey 0:fb7af294d5d9 5 * you may not use this file except in compliance with the License.
Simon Cooksey 0:fb7af294d5d9 6 * You may obtain a copy of the License at
Simon Cooksey 0:fb7af294d5d9 7 *
Simon Cooksey 0:fb7af294d5d9 8 * http://www.apache.org/licenses/LICENSE-2.0
Simon Cooksey 0:fb7af294d5d9 9 *
Simon Cooksey 0:fb7af294d5d9 10 * Unless required by applicable law or agreed to in writing, software
Simon Cooksey 0:fb7af294d5d9 11 * distributed under the License is distributed on an "AS IS" BASIS,
Simon Cooksey 0:fb7af294d5d9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Simon Cooksey 0:fb7af294d5d9 13 * See the License for the specific language governing permissions and
Simon Cooksey 0:fb7af294d5d9 14 * limitations under the License.
Simon Cooksey 0:fb7af294d5d9 15 */
Simon Cooksey 0:fb7af294d5d9 16
Simon Cooksey 0:fb7af294d5d9 17 #ifndef __BLE_HEART_RATE_SERVICE_H__
Simon Cooksey 0:fb7af294d5d9 18 #define __BLE_HEART_RATE_SERVICE_H__
Simon Cooksey 0:fb7af294d5d9 19
Simon Cooksey 0:fb7af294d5d9 20 #include "ble/BLE.h"
Simon Cooksey 0:fb7af294d5d9 21
Simon Cooksey 0:fb7af294d5d9 22 /**
Simon Cooksey 0:fb7af294d5d9 23 * @class HeartRateService
Simon Cooksey 0:fb7af294d5d9 24 * @brief BLE Service for HeartRate. This BLE Service contains the location of the sensor and the heart rate in beats per minute.
Simon Cooksey 0:fb7af294d5d9 25 * Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml
Simon Cooksey 0:fb7af294d5d9 26 * HRM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
Simon Cooksey 0:fb7af294d5d9 27 * Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml
Simon Cooksey 0:fb7af294d5d9 28 */
Simon Cooksey 0:fb7af294d5d9 29 class HeartRateService {
Simon Cooksey 0:fb7af294d5d9 30 public:
Simon Cooksey 0:fb7af294d5d9 31 /**
Simon Cooksey 0:fb7af294d5d9 32 * @enum SensorLocation
Simon Cooksey 0:fb7af294d5d9 33 * @brief Location of the heart rate sensor on body.
Simon Cooksey 0:fb7af294d5d9 34 */
Simon Cooksey 0:fb7af294d5d9 35 enum {
Simon Cooksey 0:fb7af294d5d9 36 LOCATION_OTHER = 0, /*!< Other location. */
Simon Cooksey 0:fb7af294d5d9 37 LOCATION_CHEST, /*!< Chest. */
Simon Cooksey 0:fb7af294d5d9 38 LOCATION_WRIST, /*!< Wrist. */
Simon Cooksey 0:fb7af294d5d9 39 LOCATION_FINGER, /*!< Finger. */
Simon Cooksey 0:fb7af294d5d9 40 LOCATION_HAND, /*!< Hand. */
Simon Cooksey 0:fb7af294d5d9 41 LOCATION_EAR_LOBE, /*!< Earlobe. */
Simon Cooksey 0:fb7af294d5d9 42 LOCATION_FOOT, /*!< Foot. */
Simon Cooksey 0:fb7af294d5d9 43 };
Simon Cooksey 0:fb7af294d5d9 44
Simon Cooksey 0:fb7af294d5d9 45 public:
Simon Cooksey 0:fb7af294d5d9 46 /**
Simon Cooksey 0:fb7af294d5d9 47 * @brief Constructor with 8-bit HRM Counter value.
Simon Cooksey 0:fb7af294d5d9 48 *
Simon Cooksey 0:fb7af294d5d9 49 * @param[ref] _ble
Simon Cooksey 0:fb7af294d5d9 50 * Reference to the underlying BLE.
Simon Cooksey 0:fb7af294d5d9 51 * @param[in] hrmCounter (8-bit)
Simon Cooksey 0:fb7af294d5d9 52 * Initial value for the HRM counter.
Simon Cooksey 0:fb7af294d5d9 53 * @param[in] location
Simon Cooksey 0:fb7af294d5d9 54 * Sensor's location.
Simon Cooksey 0:fb7af294d5d9 55 */
Simon Cooksey 0:fb7af294d5d9 56 HeartRateService(BLE &_ble, uint8_t hrmCounter, uint8_t location) :
Simon Cooksey 0:fb7af294d5d9 57 ble(_ble),
Simon Cooksey 0:fb7af294d5d9 58 valueBytes(hrmCounter),
Simon Cooksey 0:fb7af294d5d9 59 hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
Simon Cooksey 0:fb7af294d5d9 60 valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
Simon Cooksey 0:fb7af294d5d9 61 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
Simon Cooksey 0:fb7af294d5d9 62 hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, &location),
Simon Cooksey 0:fb7af294d5d9 63 controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) {
Simon Cooksey 0:fb7af294d5d9 64 setupService();
Simon Cooksey 0:fb7af294d5d9 65 }
Simon Cooksey 0:fb7af294d5d9 66
Simon Cooksey 0:fb7af294d5d9 67 /**
Simon Cooksey 0:fb7af294d5d9 68 * @brief Constructor with a 16-bit HRM Counter value.
Simon Cooksey 0:fb7af294d5d9 69 *
Simon Cooksey 0:fb7af294d5d9 70 * @param[in] _ble
Simon Cooksey 0:fb7af294d5d9 71 * Reference to the underlying BLE.
Simon Cooksey 0:fb7af294d5d9 72 * @param[in] hrmCounter (8-bit)
Simon Cooksey 0:fb7af294d5d9 73 * Initial value for the HRM counter.
Simon Cooksey 0:fb7af294d5d9 74 * @param[in] location
Simon Cooksey 0:fb7af294d5d9 75 * Sensor's location.
Simon Cooksey 0:fb7af294d5d9 76 */
Simon Cooksey 0:fb7af294d5d9 77 HeartRateService(BLE &_ble, uint16_t hrmCounter, uint8_t location) :
Simon Cooksey 0:fb7af294d5d9 78 ble(_ble),
Simon Cooksey 0:fb7af294d5d9 79 valueBytes(hrmCounter),
Simon Cooksey 0:fb7af294d5d9 80 hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
Simon Cooksey 0:fb7af294d5d9 81 valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
Simon Cooksey 0:fb7af294d5d9 82 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
Simon Cooksey 0:fb7af294d5d9 83 hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, &location),
Simon Cooksey 0:fb7af294d5d9 84 controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) {
Simon Cooksey 0:fb7af294d5d9 85 setupService();
Simon Cooksey 0:fb7af294d5d9 86 }
Simon Cooksey 0:fb7af294d5d9 87
Simon Cooksey 0:fb7af294d5d9 88 /**
Simon Cooksey 0:fb7af294d5d9 89 * @brief Set a new 8-bit value for the heart rate.
Simon Cooksey 0:fb7af294d5d9 90 *
Simon Cooksey 0:fb7af294d5d9 91 * @param[in] hrmCounter
Simon Cooksey 0:fb7af294d5d9 92 * Heart rate in BPM.
Simon Cooksey 0:fb7af294d5d9 93 */
Simon Cooksey 0:fb7af294d5d9 94 void updateHeartRate(uint8_t hrmCounter) {
Simon Cooksey 0:fb7af294d5d9 95 valueBytes.updateHeartRate(hrmCounter);
Simon Cooksey 0:fb7af294d5d9 96 ble.gattServer().write(hrmRate.getValueHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
Simon Cooksey 0:fb7af294d5d9 97 }
Simon Cooksey 0:fb7af294d5d9 98
Simon Cooksey 0:fb7af294d5d9 99 /**
Simon Cooksey 0:fb7af294d5d9 100 * Set a new 16-bit value for the heart rate.
Simon Cooksey 0:fb7af294d5d9 101 *
Simon Cooksey 0:fb7af294d5d9 102 * @param[in] hrmCounter
Simon Cooksey 0:fb7af294d5d9 103 * Heart rate in BPM.
Simon Cooksey 0:fb7af294d5d9 104 */
Simon Cooksey 0:fb7af294d5d9 105 void updateHeartRate(uint16_t hrmCounter) {
Simon Cooksey 0:fb7af294d5d9 106 valueBytes.updateHeartRate(hrmCounter);
Simon Cooksey 0:fb7af294d5d9 107 ble.gattServer().write(hrmRate.getValueHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
Simon Cooksey 0:fb7af294d5d9 108 }
Simon Cooksey 0:fb7af294d5d9 109
Simon Cooksey 0:fb7af294d5d9 110 /**
Simon Cooksey 0:fb7af294d5d9 111 * This callback allows the heart rate service to receive updates to the
Simon Cooksey 0:fb7af294d5d9 112 * controlPoint characteristic.
Simon Cooksey 0:fb7af294d5d9 113 *
Simon Cooksey 0:fb7af294d5d9 114 * @param[in] params
Simon Cooksey 0:fb7af294d5d9 115 * Information about the characterisitc being updated.
Simon Cooksey 0:fb7af294d5d9 116 */
Simon Cooksey 0:fb7af294d5d9 117 virtual void onDataWritten(const GattWriteCallbackParams *params) {
Simon Cooksey 0:fb7af294d5d9 118 if (params->handle == controlPoint.getValueAttribute().getHandle()) {
Simon Cooksey 0:fb7af294d5d9 119 /* Do something here if the new value is 1; else you can override this method by
Simon Cooksey 0:fb7af294d5d9 120 * extending this class.
Simon Cooksey 0:fb7af294d5d9 121 * @NOTE: If you are extending this class, be sure to also call
Simon Cooksey 0:fb7af294d5d9 122 * ble.onDataWritten(this, &ExtendedHRService::onDataWritten); in
Simon Cooksey 0:fb7af294d5d9 123 * your constructor.
Simon Cooksey 0:fb7af294d5d9 124 */
Simon Cooksey 0:fb7af294d5d9 125 }
Simon Cooksey 0:fb7af294d5d9 126 }
Simon Cooksey 0:fb7af294d5d9 127
Simon Cooksey 0:fb7af294d5d9 128 protected:
Simon Cooksey 0:fb7af294d5d9 129 void setupService(void) {
Simon Cooksey 0:fb7af294d5d9 130 GattCharacteristic *charTable[] = {&hrmRate, &hrmLocation, &controlPoint};
Simon Cooksey 0:fb7af294d5d9 131 GattService hrmService(GattService::UUID_HEART_RATE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Simon Cooksey 0:fb7af294d5d9 132
Simon Cooksey 0:fb7af294d5d9 133 ble.addService(hrmService);
Simon Cooksey 0:fb7af294d5d9 134 ble.onDataWritten(this, &HeartRateService::onDataWritten);
Simon Cooksey 0:fb7af294d5d9 135 }
Simon Cooksey 0:fb7af294d5d9 136
Simon Cooksey 0:fb7af294d5d9 137 protected:
Simon Cooksey 0:fb7af294d5d9 138 /* Private internal representation for the bytes used to work with the value of the heart rate characteristic. */
Simon Cooksey 0:fb7af294d5d9 139 struct HeartRateValueBytes {
Simon Cooksey 0:fb7af294d5d9 140 static const unsigned MAX_VALUE_BYTES = 3; /* Flags, and up to two bytes for heart rate. */
Simon Cooksey 0:fb7af294d5d9 141 static const unsigned FLAGS_BYTE_INDEX = 0;
Simon Cooksey 0:fb7af294d5d9 142
Simon Cooksey 0:fb7af294d5d9 143 static const unsigned VALUE_FORMAT_BITNUM = 0;
Simon Cooksey 0:fb7af294d5d9 144 static const uint8_t VALUE_FORMAT_FLAG = (1 << VALUE_FORMAT_BITNUM);
Simon Cooksey 0:fb7af294d5d9 145
Simon Cooksey 0:fb7af294d5d9 146 HeartRateValueBytes(uint8_t hrmCounter) : valueBytes() {
Simon Cooksey 0:fb7af294d5d9 147 updateHeartRate(hrmCounter);
Simon Cooksey 0:fb7af294d5d9 148 }
Simon Cooksey 0:fb7af294d5d9 149
Simon Cooksey 0:fb7af294d5d9 150 HeartRateValueBytes(uint16_t hrmCounter) : valueBytes() {
Simon Cooksey 0:fb7af294d5d9 151 updateHeartRate(hrmCounter);
Simon Cooksey 0:fb7af294d5d9 152 }
Simon Cooksey 0:fb7af294d5d9 153
Simon Cooksey 0:fb7af294d5d9 154 void updateHeartRate(uint8_t hrmCounter) {
Simon Cooksey 0:fb7af294d5d9 155 valueBytes[FLAGS_BYTE_INDEX] &= ~VALUE_FORMAT_FLAG;
Simon Cooksey 0:fb7af294d5d9 156 valueBytes[FLAGS_BYTE_INDEX + 1] = hrmCounter;
Simon Cooksey 0:fb7af294d5d9 157 }
Simon Cooksey 0:fb7af294d5d9 158
Simon Cooksey 0:fb7af294d5d9 159 void updateHeartRate(uint16_t hrmCounter) {
Simon Cooksey 0:fb7af294d5d9 160 valueBytes[FLAGS_BYTE_INDEX] |= VALUE_FORMAT_FLAG;
Simon Cooksey 0:fb7af294d5d9 161 valueBytes[FLAGS_BYTE_INDEX + 1] = (uint8_t)(hrmCounter & 0xFF);
Simon Cooksey 0:fb7af294d5d9 162 valueBytes[FLAGS_BYTE_INDEX + 2] = (uint8_t)(hrmCounter >> 8);
Simon Cooksey 0:fb7af294d5d9 163 }
Simon Cooksey 0:fb7af294d5d9 164
Simon Cooksey 0:fb7af294d5d9 165 uint8_t *getPointer(void) {
Simon Cooksey 0:fb7af294d5d9 166 return valueBytes;
Simon Cooksey 0:fb7af294d5d9 167 }
Simon Cooksey 0:fb7af294d5d9 168
Simon Cooksey 0:fb7af294d5d9 169 const uint8_t *getPointer(void) const {
Simon Cooksey 0:fb7af294d5d9 170 return valueBytes;
Simon Cooksey 0:fb7af294d5d9 171 }
Simon Cooksey 0:fb7af294d5d9 172
Simon Cooksey 0:fb7af294d5d9 173 unsigned getNumValueBytes(void) const {
Simon Cooksey 0:fb7af294d5d9 174 return 1 + ((valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) ? sizeof(uint16_t) : sizeof(uint8_t));
Simon Cooksey 0:fb7af294d5d9 175 }
Simon Cooksey 0:fb7af294d5d9 176
Simon Cooksey 0:fb7af294d5d9 177 private:
Simon Cooksey 0:fb7af294d5d9 178 /* First byte: 8-bit values, no extra info. Second byte: uint8_t HRM value */
Simon Cooksey 0:fb7af294d5d9 179 /* See https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
Simon Cooksey 0:fb7af294d5d9 180 uint8_t valueBytes[MAX_VALUE_BYTES];
Simon Cooksey 0:fb7af294d5d9 181 };
Simon Cooksey 0:fb7af294d5d9 182
Simon Cooksey 0:fb7af294d5d9 183 protected:
Simon Cooksey 0:fb7af294d5d9 184 BLE &ble;
Simon Cooksey 0:fb7af294d5d9 185
Simon Cooksey 0:fb7af294d5d9 186 HeartRateValueBytes valueBytes;
Simon Cooksey 0:fb7af294d5d9 187 uint8_t controlPointValue;
Simon Cooksey 0:fb7af294d5d9 188
Simon Cooksey 0:fb7af294d5d9 189 GattCharacteristic hrmRate;
Simon Cooksey 0:fb7af294d5d9 190 ReadOnlyGattCharacteristic<uint8_t> hrmLocation;
Simon Cooksey 0:fb7af294d5d9 191 WriteOnlyGattCharacteristic<uint8_t> controlPoint;
Simon Cooksey 0:fb7af294d5d9 192 };
Simon Cooksey 0:fb7af294d5d9 193
Simon Cooksey 0:fb7af294d5d9 194 #endif /* #ifndef __BLE_HEART_RATE_SERVICE_H__*/