Lightly modified version of the BLE stack, that doesn't bring up a DFUService by default... as we have our own.

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Thu Jan 22 09:59:44 2015 +0000
Revision:
277:1407d2f1ce3c
Parent:
243:98f930d14515
Child:
338:fd32ec0ebd98
Synchronized with git rev 4a268db0
Author: Rohit Grover
Release 0.2.11
=============

Enhancements
~~~~~~~~~~~~

* Use template classes to simplify definitions of GattCharacteristic within services.

Bugfixes
~~~~~~~~

Compatibility
~~~~~~~~~~~~~

This release is API compatible with 0.2.4.

Who changed what in which revision?

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