For Blood Pressure Demo
BLE_BloodPressure_demo implements Blood Pressure Service which enables a collector device to connect and interact with it. the service spec can be found here. User can download the APP 'nRF Connect' or 'nRF Toolbox' available in both App Store and Google Play to scan the adverting and connect to the module.
BloodPressureService.h@2:64cead334a4c, 2017-04-20 (annotated)
- Committer:
- tsungta
- Date:
- Thu Apr 20 10:25:42 2017 +0000
- Revision:
- 2:64cead334a4c
- Parent:
- 1:fc03791a9842
Update to support NQ620 and NNN50 platform
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
wgd8700 | 1:fc03791a9842 | 1 | #include "BLE.h" |
Marcomissyou | 0:546d7178e278 | 2 | //#include "Gap.h" |
Marcomissyou | 0:546d7178e278 | 3 | |
Marcomissyou | 0:546d7178e278 | 4 | /* |
Marcomissyou | 0:546d7178e278 | 5 | * @This example can be demonstrated with Blood Pressure Android App downloaded from |
Marcomissyou | 0:546d7178e278 | 6 | * @https://github.com/Marcomissyou/BluetoothLeBooldPressure.git |
Marcomissyou | 0:546d7178e278 | 7 | * @Author: Marco.Hsu |
Marcomissyou | 0:546d7178e278 | 8 | * @Email: marco.missyou@gmail.com |
Marcomissyou | 0:546d7178e278 | 9 | */ |
Marcomissyou | 0:546d7178e278 | 10 | class BloodPressureService { |
Marcomissyou | 0:546d7178e278 | 11 | public: |
Marcomissyou | 0:546d7178e278 | 12 | BloodPressureService(BLEDevice &_ble, float Systolic, float Diastolic, float mean_arterial, uint16_t BloodFeature): |
Marcomissyou | 0:546d7178e278 | 13 | ble(_ble), |
Marcomissyou | 0:546d7178e278 | 14 | BloodPressureValue(Systolic, Diastolic, mean_arterial), |
Marcomissyou | 0:546d7178e278 | 15 | BloodFeatureValue(BloodFeature), |
Marcomissyou | 0:546d7178e278 | 16 | //GlucoseFeatureValue(GluFeature), |
Marcomissyou | 0:546d7178e278 | 17 | BloodPressureGatt(GattCharacteristic::UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR, BloodPressureValue.getPointer(), |
Marcomissyou | 0:546d7178e278 | 18 | sizeof(uint8_t), BloodPressureStruc::MAX_VALUE_BYTES, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE), |
Marcomissyou | 0:546d7178e278 | 19 | BloodFeature(GattCharacteristic::UUID_BLOOD_PRESSURE_FEATURE_CHAR, &BloodFeatureValue) { |
Marcomissyou | 0:546d7178e278 | 20 | setupService(); |
Marcomissyou | 0:546d7178e278 | 21 | } |
Marcomissyou | 0:546d7178e278 | 22 | |
Marcomissyou | 0:546d7178e278 | 23 | void updateBloodPressureMeasurement(float Systolic, float Diastolic, float mean_arterial) { |
Marcomissyou | 0:546d7178e278 | 24 | BloodPressureValue.uploadBloodPressureValue(Systolic, Diastolic, mean_arterial); |
Marcomissyou | 0:546d7178e278 | 25 | ble.updateCharacteristicValue(BloodPressureGatt.getValueAttribute().getHandle(), BloodPressureValue.getPointer(), 6); |
Marcomissyou | 0:546d7178e278 | 26 | } |
Marcomissyou | 0:546d7178e278 | 27 | |
Marcomissyou | 0:546d7178e278 | 28 | |
Marcomissyou | 0:546d7178e278 | 29 | |
Marcomissyou | 0:546d7178e278 | 30 | private: |
Marcomissyou | 0:546d7178e278 | 31 | void setupService(void) { |
Marcomissyou | 0:546d7178e278 | 32 | static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */ |
Marcomissyou | 0:546d7178e278 | 33 | if (serviceAdded) { |
Marcomissyou | 0:546d7178e278 | 34 | return; |
Marcomissyou | 0:546d7178e278 | 35 | } |
Marcomissyou | 0:546d7178e278 | 36 | |
Marcomissyou | 0:546d7178e278 | 37 | GattCharacteristic *charTable[] = {&BloodPressureGatt, &BloodFeature}; |
Marcomissyou | 0:546d7178e278 | 38 | GattService BloodService(GattService::UUID_BLOOD_PRESSURE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *)); |
Marcomissyou | 0:546d7178e278 | 39 | |
Marcomissyou | 0:546d7178e278 | 40 | ble.addService(BloodService); |
Marcomissyou | 0:546d7178e278 | 41 | serviceAdded = true; |
Marcomissyou | 0:546d7178e278 | 42 | |
Marcomissyou | 0:546d7178e278 | 43 | } |
Marcomissyou | 0:546d7178e278 | 44 | |
Marcomissyou | 0:546d7178e278 | 45 | //========================================================================================================== |
Marcomissyou | 0:546d7178e278 | 46 | private: |
Marcomissyou | 0:546d7178e278 | 47 | struct BloodPressureStruc { |
Marcomissyou | 0:546d7178e278 | 48 | static const unsigned MAX_VALUE_BYTES = 8; |
Marcomissyou | 0:546d7178e278 | 49 | static const unsigned FLAGS_BYTE_INDEX = 0; |
Marcomissyou | 0:546d7178e278 | 50 | |
Marcomissyou | 0:546d7178e278 | 51 | static const unsigned Blood_Pressure_Units_Flag = 0; // 0 in units of mmHg, 1 in units of kPa |
Marcomissyou | 0:546d7178e278 | 52 | static const unsigned Time_Stamp_Flag = 0; // |
Marcomissyou | 0:546d7178e278 | 53 | static const unsigned Pulse_Rate_Flag = 0; |
Marcomissyou | 0:546d7178e278 | 54 | static const unsigned User_ID_Flag = 0; |
Marcomissyou | 0:546d7178e278 | 55 | static const unsigned Measurement_Status_Flag = 0; |
Marcomissyou | 0:546d7178e278 | 56 | |
Marcomissyou | 0:546d7178e278 | 57 | static const unsigned VALUE_FORMAT_BITNUM = 0; |
Marcomissyou | 0:546d7178e278 | 58 | static const uint8_t VALUE_FORMAT_FLAG = 0; |
Marcomissyou | 0:546d7178e278 | 59 | |
Marcomissyou | 0:546d7178e278 | 60 | // Initial setting Blood Pressure measurement value |
Marcomissyou | 0:546d7178e278 | 61 | BloodPressureStruc(float Systolic, float Diastolic, float mean_arterial) : BloodPressureValue() { |
Marcomissyou | 0:546d7178e278 | 62 | uploadBloodPressureValue(Systolic, Diastolic, mean_arterial); |
Marcomissyou | 0:546d7178e278 | 63 | } |
Marcomissyou | 0:546d7178e278 | 64 | |
Marcomissyou | 0:546d7178e278 | 65 | // function to update Blood Pressure measurement value in unit of mmHg |
Marcomissyou | 0:546d7178e278 | 66 | void uploadBloodPressureValue(float Systolic, float Diastolic, float mean_arterial) { |
Marcomissyou | 0:546d7178e278 | 67 | uint16_t ieee11073_Systolic = ieee11073_float16(Systolic); |
Marcomissyou | 0:546d7178e278 | 68 | uint16_t ieee11073_Diastolic = ieee11073_float16(Diastolic); |
Marcomissyou | 0:546d7178e278 | 69 | uint16_t ieee11073_mean_arterial = ieee11073_float16(mean_arterial); |
Marcomissyou | 0:546d7178e278 | 70 | BloodPressureValue[FLAGS_BYTE_INDEX] = (Blood_Pressure_Units_Flag << 0)|(Time_Stamp_Flag << 1)| |
Marcomissyou | 0:546d7178e278 | 71 | (Pulse_Rate_Flag << 2)|(User_ID_Flag << 3)|(Measurement_Status_Flag << 4); |
Marcomissyou | 0:546d7178e278 | 72 | //memcpy(&BloodPressureValue[FLAGS_BYTE_INDEX], &ieee11073_Systolic, 2); |
Marcomissyou | 0:546d7178e278 | 73 | //memcpy(&BloodPressureValue[FLAGS_BYTE_INDEX+2], &ieee11073_Diastolic, 2); |
Marcomissyou | 0:546d7178e278 | 74 | //memcpy(&BloodPressureValue[FLAGS_BYTE_INDEX+4], &ieee11073_mean_arterial, 2); |
Marcomissyou | 0:546d7178e278 | 75 | BloodPressureValue[FLAGS_BYTE_INDEX + 1] = (uint8_t)(ieee11073_Systolic &0xff); |
Marcomissyou | 0:546d7178e278 | 76 | BloodPressureValue[FLAGS_BYTE_INDEX + 2] = (uint8_t)(ieee11073_Systolic >> 8); |
Marcomissyou | 0:546d7178e278 | 77 | BloodPressureValue[FLAGS_BYTE_INDEX + 3] = (uint8_t)(ieee11073_Diastolic &0xff); |
Marcomissyou | 0:546d7178e278 | 78 | BloodPressureValue[FLAGS_BYTE_INDEX + 4] = (uint8_t)(ieee11073_Diastolic >> 8); |
Marcomissyou | 0:546d7178e278 | 79 | BloodPressureValue[FLAGS_BYTE_INDEX + 5] = (uint8_t)(ieee11073_mean_arterial &0xff); |
Marcomissyou | 0:546d7178e278 | 80 | BloodPressureValue[FLAGS_BYTE_INDEX + 6] = (uint8_t)(ieee11073_mean_arterial >>8); |
Marcomissyou | 0:546d7178e278 | 81 | } |
Marcomissyou | 0:546d7178e278 | 82 | |
Marcomissyou | 0:546d7178e278 | 83 | |
Marcomissyou | 0:546d7178e278 | 84 | uint8_t *getPointer(void) { |
Marcomissyou | 0:546d7178e278 | 85 | return BloodPressureValue; |
Marcomissyou | 0:546d7178e278 | 86 | } |
Marcomissyou | 0:546d7178e278 | 87 | |
Marcomissyou | 0:546d7178e278 | 88 | const uint8_t *getPointer(void) const { |
Marcomissyou | 0:546d7178e278 | 89 | return BloodPressureValue; |
Marcomissyou | 0:546d7178e278 | 90 | } |
Marcomissyou | 0:546d7178e278 | 91 | |
Marcomissyou | 0:546d7178e278 | 92 | uint16_t ieee11073_float16(float BloodPressure) { |
Marcomissyou | 0:546d7178e278 | 93 | uint8_t exponent = 0; |
Marcomissyou | 0:546d7178e278 | 94 | uint16_t mantissa = (uint16_t)BloodPressure; |
Marcomissyou | 0:546d7178e278 | 95 | return ((exponent << 12)&0xF0) | (mantissa << 0) & 0x0FFF ; |
Marcomissyou | 0:546d7178e278 | 96 | } |
Marcomissyou | 0:546d7178e278 | 97 | private: |
Marcomissyou | 0:546d7178e278 | 98 | uint8_t BloodPressureValue[MAX_VALUE_BYTES]; |
Marcomissyou | 0:546d7178e278 | 99 | }; |
Marcomissyou | 0:546d7178e278 | 100 | |
Marcomissyou | 0:546d7178e278 | 101 | |
Marcomissyou | 0:546d7178e278 | 102 | private: |
Marcomissyou | 0:546d7178e278 | 103 | BLEDevice &ble; |
Marcomissyou | 0:546d7178e278 | 104 | |
Marcomissyou | 0:546d7178e278 | 105 | BloodPressureStruc BloodPressureValue; |
Marcomissyou | 0:546d7178e278 | 106 | GattCharacteristic BloodPressureGatt; // data carrier |
Marcomissyou | 0:546d7178e278 | 107 | |
Marcomissyou | 0:546d7178e278 | 108 | uint16_t BloodFeatureValue; |
Marcomissyou | 0:546d7178e278 | 109 | ReadOnlyGattCharacteristic<uint16_t> BloodFeature; |
Marcomissyou | 0:546d7178e278 | 110 | |
Marcomissyou | 0:546d7178e278 | 111 | }; |