Holla back

Fork of BLE_API by Bluetooth Low Energy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HeartRateService.h Source File

HeartRateService.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef __BLE_HEART_RATE_SERVICE_H__
00018 #define __BLE_HEART_RATE_SERVICE_H__
00019 
00020 #include "BLEDevice.h"
00021 
00022 /* Heart Rate Service */
00023 /* Service:  https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml */
00024 /* HRM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
00025 /* Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml */
00026 class HeartRateService {
00027 public:
00028     enum {
00029         LOCATION_OTHER = 0,
00030         LOCATION_CHEST,
00031         LOCATION_WRIST,
00032         LOCATION_FINGER,
00033         LOCATION_HAND,
00034         LOCATION_EAR_LOBE,
00035         LOCATION_FOOT,
00036     };
00037 
00038 public:
00039     /**
00040      * Constructor.
00041      *
00042      * param[in] _ble
00043      *               Reference to the underlying BLEDevice.
00044      * param[in] hrmCounter (8-bit)
00045      *               initial value for the hrm counter.
00046      * param[in] location
00047      *               Sensor's location.
00048      */
00049     HeartRateService(BLEDevice &_ble, uint8_t hrmCounter, uint8_t location) :
00050         ble(_ble),
00051         valueBytes(hrmCounter),
00052         hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
00053                 valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
00054                 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
00055         hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, (uint8_t *)&location, sizeof(location), sizeof(location),
00056                     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
00057         controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, (uint8_t *)&controlPointValue,
00058                      sizeof(controlPointValue), sizeof(controlPointValue), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) {
00059         setupService();
00060     }
00061 
00062     /**
00063      * Same constructor as above, but with a 16-bit HRM Counter value.
00064      */
00065     HeartRateService(BLEDevice &_ble, uint16_t hrmCounter, uint8_t location) :
00066         ble(_ble),
00067         valueBytes(hrmCounter),
00068         hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
00069                 valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
00070                 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
00071         hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, (uint8_t *)&location, sizeof(location), sizeof(location),
00072                     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
00073         controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, (uint8_t *)&controlPointValue,
00074                      sizeof(controlPointValue), sizeof(controlPointValue), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) {
00075         setupService();
00076     }
00077 
00078     /**
00079      * Set a new 8-bit value for heart rate.
00080      */
00081     void updateHeartRate(uint8_t hrmCounter) {
00082         valueBytes.updateHeartRate(hrmCounter);
00083         ble.updateCharacteristicValue(hrmRate.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
00084     }
00085 
00086     /**
00087      * Set a new 16-bit value for heart rate.
00088      */
00089     void updateHeartRate(uint16_t hrmCounter) {
00090         valueBytes.updateHeartRate(hrmCounter);
00091         ble.updateCharacteristicValue(hrmRate.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
00092     }
00093 
00094     /**
00095      * This callback allows the UART service to receive updates to the
00096      * txCharacteristic. The application should forward the call to this
00097      * function from the global onDataWritten() callback handler; or if that's
00098      * not used, this method can be used as a callback directly.
00099      */
00100     virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
00101         if (params->charHandle == controlPoint.getValueAttribute().getHandle()) {
00102             /* Do something here if the new value is 1; else you can override this method by
00103              * extending this class.
00104              * @NOTE: if you are extending this class, be sure to also call
00105              * ble.onDataWritten(this, &ExtendedHRService::onDataWritten); in
00106              * your constructor.
00107              */
00108         }
00109     }
00110 
00111 private:
00112     void setupService(void) {
00113         static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */
00114         if (serviceAdded) {
00115             return;
00116         }
00117 
00118         GattCharacteristic *charTable[] = {&hrmRate, &hrmLocation, &controlPoint};
00119         GattService         hrmService(GattService::UUID_HEART_RATE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
00120 
00121         ble.addService(hrmService);
00122         serviceAdded = true;
00123 
00124         ble.onDataWritten(this, &HeartRateService::onDataWritten);
00125     }
00126 
00127 private:
00128     /* Private internal representation for the bytes used to work with the vaulue of the heart-rate characteristic. */
00129     struct HeartRateValueBytes {
00130         static const unsigned MAX_VALUE_BYTES  = 3; /* FLAGS + up to two bytes for heart-rate */
00131         static const unsigned FLAGS_BYTE_INDEX = 0;
00132 
00133         static const unsigned VALUE_FORMAT_BITNUM = 0;
00134         static const uint8_t  VALUE_FORMAT_FLAG   = (1 << VALUE_FORMAT_BITNUM);
00135 
00136         HeartRateValueBytes(uint8_t hrmCounter) : valueBytes() {
00137             updateHeartRate(hrmCounter);
00138         }
00139 
00140         HeartRateValueBytes(uint16_t hrmCounter) : valueBytes() {
00141             updateHeartRate(hrmCounter);
00142         }
00143 
00144         void updateHeartRate(uint8_t hrmCounter) {
00145             valueBytes[FLAGS_BYTE_INDEX] &= ~VALUE_FORMAT_FLAG;
00146             valueBytes[FLAGS_BYTE_INDEX + 1] = hrmCounter;
00147         }
00148 
00149         void updateHeartRate(uint16_t hrmCounter) {
00150             valueBytes[FLAGS_BYTE_INDEX] |= VALUE_FORMAT_FLAG;
00151             valueBytes[FLAGS_BYTE_INDEX + 1] = (uint8_t)(hrmCounter & 0xFF);
00152             valueBytes[FLAGS_BYTE_INDEX + 2] = (uint8_t)(hrmCounter >> 8);
00153         }
00154 
00155         uint8_t *getPointer(void) {
00156             return valueBytes;
00157         }
00158 
00159         const uint8_t *getPointer(void) const {
00160             return valueBytes;
00161         }
00162 
00163         unsigned getNumValueBytes(void) const {
00164             return 1 + ((valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) ? sizeof(uint16_t) : sizeof(uint8_t));
00165         }
00166 
00167     private:
00168         /* First byte = 8-bit values, no extra info, Second byte = uint8_t HRM value */
00169         /* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
00170         uint8_t valueBytes[MAX_VALUE_BYTES];
00171     };
00172 
00173 private:
00174     BLEDevice           &ble;
00175     HeartRateValueBytes  valueBytes;
00176     uint8_t              controlPointValue;
00177     GattCharacteristic   hrmRate;
00178     GattCharacteristic   hrmLocation;
00179     GattCharacteristic   controlPoint;
00180 };
00181 
00182 #endif /* #ifndef __BLE_HEART_RATE_SERVICE_H__*/