High level Bluetooth Low Energy API and radio abstraction layer

Dependencies:   nRF51822

Dependents:   LinkNode_LIS3DH

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Thu Jul 02 09:06:11 2015 +0100
Revision:
714:a6130aaa0fd9
Synchronized with git rev 7e8977d8
Author: Rohit Grover
Release 0.3.8
=============

This is a minor set of enhancements before we yotta-ize BLE_API.

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

* Minor rework for class UUID; added a default and copy constructor; and a != operator.

* Added copy constructor and accessors for GapAdvertisingParams.

* GapScanningParams:: remove unnecessary checks for SCAN_TIMEOUT_MAX.

* Add a comment header block to explain why BLEDevice::init() may not be safe
to call from global static context.

* Introduce GattAttribute::INVALID_HANDLE.

* Replace some deprecated uses of Gap::address_t with Gap::Address_t.

Bugfixes
~~~~~~~~

* None.

Who changed what in which revision?

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