Fork of BLE_SecureHeartRate : should this 'work' i.e. require a secure connection on an nRF51-DK? Hopefully I'm just missing something obvious - or is this broken?
Dependencies: BLE_API mbed nRF51822
Fork of BLE_SecureHeartRate by
HeartRateSecService.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_SEC_SAMPLE_SERVICE_H__ 00018 #define __BLE_HEART_RATE_SEC_SAMPLE_SERVICE_H__ 00019 00020 #include "BLE.h" 00021 00022 /** 00023 * @class HeartRateSecService 00024 * @brief BLE Service for HeartRate. This BLE Service contains the location of the sensor, the heartrate in beats per minute. <br> 00025 * Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml <br> 00026 * HRM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml <br> 00027 * Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml 00028 */ 00029 class HeartRateSecService { 00030 public: 00031 /** 00032 * @enum SensorLocation 00033 * @brief Location of HeartRate sensor on body. 00034 */ 00035 enum { 00036 LOCATION_OTHER = 0, /*!< Other Location */ 00037 LOCATION_CHEST , /*!< Chest */ 00038 LOCATION_WRIST , /*!< Wrist */ 00039 LOCATION_FINGER , /*!< Finger */ 00040 LOCATION_HAND , /*!< Hand */ 00041 LOCATION_EAR_LOBE , /*!< Earlobe */ 00042 LOCATION_FOOT , /*!< Foot */ 00043 }; 00044 00045 public: 00046 /** 00047 * @brief Constructor with 8bit HRM Counter value. 00048 * 00049 * @param[ref] _ble 00050 * Reference to the underlying BLEDevice. 00051 * @param[in] hrmCounter (8-bit) 00052 * initial value for the hrm counter. 00053 * @param[in] location 00054 * Sensor's location. 00055 */ 00056 HeartRateSecService(BLE &_ble, uint8_t hrmCounter, uint8_t location) : 00057 ble(_ble), 00058 valueBytes(hrmCounter), 00059 hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(), 00060 valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES, 00061 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY), 00062 hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, &location), 00063 controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) { 00064 setupService(); 00065 } 00066 00067 /** 00068 * @brief Constructor with a 16-bit HRM Counter value. 00069 * 00070 * @param[in] _ble 00071 * Reference to the underlying BLEDevice. 00072 * @param[in] hrmCounter (8-bit) 00073 * initial value for the hrm counter. 00074 * @param[in] location 00075 * Sensor's location. 00076 */ 00077 HeartRateSecService(BLE &_ble, uint16_t hrmCounter, uint8_t location) : 00078 ble(_ble), 00079 valueBytes(hrmCounter), 00080 hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(), 00081 valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES, 00082 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY), 00083 hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, &location), 00084 controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) { 00085 setupService(); 00086 } 00087 00088 /*void setSecurityStatus(Gap::Handle_t handle) { 00089 SecurityManager::LinkSecurityStatus_t status; 00090 ble_error_t ret = ble.securityManager().setLinkSecurity(handle, &status); 00091 if (BLE_ERROR_NONE == ret) { 00092 printf("OK: getLinkSecurity status: "); 00093 switch (status) { 00094 case SecurityManager::NOT_ENCRYPTED: // The link is not secured. 00095 printf("NOT_ENCRYPTED"); 00096 break; 00097 case SecurityManager::ENCRYPTION_IN_PROGRESS: // Link security is being established 00098 printf("ENCRYPTION_IN_PROGRESS"); 00099 break; 00100 case SecurityManager::ENCRYPTED: 00101 printf("ENCRYPTED"); 00102 break; 00103 } 00104 printf("\r\n"); 00105 } else { 00106 printf("FAIL: getLinkSecurity ret %i\r\n", ret); 00107 } 00108 }*/ 00109 00110 void outputSecurityStatus (Gap::Handle_t handle) { 00111 SecurityManager::LinkSecurityStatus_t status; 00112 ble_error_t ret = ble.securityManager().getLinkSecurity(handle, &status); 00113 if (BLE_ERROR_NONE == ret) { 00114 printf("OK: getLinkSecurity status: "); 00115 switch (status) { 00116 case SecurityManager::NOT_ENCRYPTED: /**< The link is not secured. */ 00117 printf("NOT_ENCRYPTED"); 00118 break; 00119 case SecurityManager::ENCRYPTION_IN_PROGRESS: /**< Link security is being established.*/ 00120 printf("ENCRYPTION_IN_PROGRESS"); 00121 break; 00122 case SecurityManager::ENCRYPTED: 00123 printf("ENCRYPTED"); 00124 break; 00125 } 00126 printf("\r\n"); 00127 } else { 00128 printf("FAIL: getLinkSecurity ret %i\r\n", ret); 00129 } 00130 } 00131 00132 /** 00133 * @brief Set a new 8-bit value for heart rate. 00134 * 00135 * @param[in] hrmCounter 00136 * HeartRate in bpm. 00137 */ 00138 void updateHeartRate(uint8_t hrmCounter) { 00139 valueBytes.updateHeartRate(hrmCounter); 00140 ble.gattServer().write(hrmRate.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes()); 00141 } 00142 00143 /** 00144 * Set a new 16-bit value for heart rate. 00145 * 00146 * @param[in] hrmCounter 00147 * HeartRate in bpm. 00148 */ 00149 void updateHeartRate(uint16_t hrmCounter) { 00150 valueBytes.updateHeartRate(hrmCounter); 00151 ble.gattServer().write(hrmRate.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes()); 00152 } 00153 00154 /** 00155 * This callback allows the HeartRateSecService to receive updates to the 00156 * controlPoint Characteristic. 00157 * 00158 * @param[in] params 00159 * Information about the characterisitc being updated. 00160 */ 00161 virtual void onDataWritten(const GattWriteCallbackParams *params) { 00162 if (params->handle == controlPoint.getValueAttribute().getHandle()) { 00163 /* Do something here if the new value is 1; else you can override this method by 00164 * extending this class. 00165 * @NOTE: if you are extending this class, be sure to also call 00166 * ble.onDataWritten(this, &ExtendedHRService::onDataWritten); in 00167 * your constructor. 00168 */ 00169 } 00170 } 00171 00172 private: 00173 void setupService(void) { 00174 static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */ 00175 if (serviceAdded) { 00176 return; 00177 } 00178 00179 hrmRate.requireSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM); 00180 00181 GattCharacteristic *charTable[] = {&hrmRate, &hrmLocation, &controlPoint}; 00182 GattService hrmService(GattService::UUID_HEART_RATE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *)); 00183 00184 ble.gattServer().addService(hrmService); 00185 serviceAdded = true; 00186 00187 ble.gattServer().onDataWritten(this, &HeartRateSecService::onDataWritten); 00188 } 00189 00190 private: 00191 /* Private internal representation for the bytes used to work with the vaulue of the heart-rate characteristic. */ 00192 struct HeartRateValueBytes { 00193 static const unsigned MAX_VALUE_BYTES = 3; /* FLAGS + up to two bytes for heart-rate */ 00194 static const unsigned FLAGS_BYTE_INDEX = 0; 00195 00196 static const unsigned VALUE_FORMAT_BITNUM = 0; 00197 static const uint8_t VALUE_FORMAT_FLAG = (1 << VALUE_FORMAT_BITNUM); 00198 00199 HeartRateValueBytes(uint8_t hrmCounter) : valueBytes() { 00200 updateHeartRate(hrmCounter); 00201 } 00202 00203 HeartRateValueBytes(uint16_t hrmCounter) : valueBytes() { 00204 updateHeartRate(hrmCounter); 00205 } 00206 00207 void updateHeartRate(uint8_t hrmCounter) { 00208 valueBytes[FLAGS_BYTE_INDEX] &= ~VALUE_FORMAT_FLAG; 00209 valueBytes[FLAGS_BYTE_INDEX + 1] = hrmCounter; 00210 } 00211 00212 void updateHeartRate(uint16_t hrmCounter) { 00213 valueBytes[FLAGS_BYTE_INDEX] |= VALUE_FORMAT_FLAG; 00214 valueBytes[FLAGS_BYTE_INDEX + 1] = (uint8_t)(hrmCounter & 0xFF); 00215 valueBytes[FLAGS_BYTE_INDEX + 2] = (uint8_t)(hrmCounter >> 8); 00216 } 00217 00218 uint8_t *getPointer(void) { 00219 return valueBytes; 00220 } 00221 00222 const uint8_t *getPointer(void) const { 00223 return valueBytes; 00224 } 00225 00226 unsigned getNumValueBytes(void) const { 00227 return 1 + ((valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) ? sizeof(uint16_t) : sizeof(uint8_t)); 00228 } 00229 00230 private: 00231 /* First byte = 8-bit values, no extra info, Second byte = uint8_t HRM value */ 00232 /* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */ 00233 uint8_t valueBytes[MAX_VALUE_BYTES]; 00234 }; 00235 00236 private: 00237 BLE &ble; 00238 00239 HeartRateValueBytes valueBytes; 00240 uint8_t controlPointValue; 00241 00242 GattCharacteristic hrmRate; 00243 ReadOnlyGattCharacteristic<uint8_t> hrmLocation; 00244 WriteOnlyGattCharacteristic<uint8_t> controlPoint; 00245 }; 00246 00247 #endif /* #ifndef __BLE_HEART_RATE_SEC_SAMPLE_SERVICE_H__*/
Generated on Mon Aug 15 2022 20:41:50 by 1.7.2