BLE PLX profile with customized services (raw data).

Dependencies:   MtSense06

https://mtmtechblog.files.wordpress.com/2016/04/mtsense06-post-title.jpeg?w=772 https://blog.mtmtech.com.tw/2016/06/28/pulse-oximeter-with-mtconnect04/

Committer:
johnathanlyu
Date:
Fri Mar 31 08:05:22 2017 +0000
Revision:
2:7a08b9410b96
Parent:
1:0ec0e5694c4a
add feature UART show raw data.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bcc6 0:528034040a12 1 /* Copyright (c) 2016 MtM Technology Corporation, MIT License
bcc6 0:528034040a12 2 *
bcc6 0:528034040a12 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
bcc6 0:528034040a12 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
bcc6 0:528034040a12 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
bcc6 0:528034040a12 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
bcc6 0:528034040a12 7 * furnished to do so, subject to the following conditions:
bcc6 0:528034040a12 8 *
bcc6 0:528034040a12 9 * The above copyright notice and this permission notice shall be included in all copies or
bcc6 0:528034040a12 10 * substantial portions of the Software.
bcc6 0:528034040a12 11 *
bcc6 0:528034040a12 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
bcc6 0:528034040a12 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
bcc6 0:528034040a12 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
bcc6 0:528034040a12 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
bcc6 0:528034040a12 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bcc6 0:528034040a12 17 */
bcc6 0:528034040a12 18 #ifndef __BLE_PULSE_OXIMETER_SERVICE_H__
bcc6 0:528034040a12 19 #define __BLE_PULSE_OXIMETER_SERVICE_H__
bcc6 0:528034040a12 20
bcc6 0:528034040a12 21 #include "ble/BLE.h"
bcc6 0:528034040a12 22
bcc6 0:528034040a12 23 class PulseOximeterService {
bcc6 0:528034040a12 24 public:
bcc6 0:528034040a12 25 PulseOximeterService(BLE &_ble, float spo2, float pr) :
bcc6 0:528034040a12 26 ble(_ble),
bcc6 0:528034040a12 27 plxMeasValueBytes(spo2, pr),
bcc6 0:528034040a12 28 plxFeatValueBytes(),
bcc6 0:528034040a12 29 rawValueBytes(),
bcc6 0:528034040a12 30 flagSigValueBytes(),
bcc6 0:528034040a12 31 plxSpotCheckMeasurementCharacteristic(0x2A5E/* UUID:PLX Spot-Check Measurement */,
bcc6 0:528034040a12 32 plxMeasValueBytes.getPointer(),
bcc6 0:528034040a12 33 PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES,
bcc6 0:528034040a12 34 PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES,
bcc6 0:528034040a12 35 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE,
bcc6 0:528034040a12 36 NULL, 0, false
bcc6 0:528034040a12 37 ),
bcc6 0:528034040a12 38 plxFeaturesCharacteristic(0x2A60/* UUID:PLX Features */,
bcc6 0:528034040a12 39 plxFeatValueBytes.getPointer(),
bcc6 0:528034040a12 40 PlxFeaturesValueBytes::SIZEOF_VALUE_BYTES,
bcc6 0:528034040a12 41 PlxFeaturesValueBytes::SIZEOF_VALUE_BYTES,
bcc6 0:528034040a12 42 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ,
bcc6 0:528034040a12 43 NULL, 0, false
bcc6 0:528034040a12 44 ),
bcc6 0:528034040a12 45 rawDataCharacteristic(0x2B00/* UUID:Self defined for raw data */,
bcc6 0:528034040a12 46 rawValueBytes.getPointer(),
bcc6 0:528034040a12 47 RawDataValueBytes::SIZEOF_VALUE_BYTES,
bcc6 0:528034040a12 48 RawDataValueBytes::SIZEOF_VALUE_BYTES,
bcc6 0:528034040a12 49 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY,
bcc6 0:528034040a12 50 NULL, 0, false
bcc6 0:528034040a12 51 ),
bcc6 0:528034040a12 52 signalCharacteristic(0x2B01/* UUID:Self defined for flag & signal */,
bcc6 0:528034040a12 53 flagSigValueBytes.getPointer(),
bcc6 0:528034040a12 54 FlagSignalValueBytes::SIZEOF_VALUE_BYTES,
bcc6 0:528034040a12 55 FlagSignalValueBytes::SIZEOF_VALUE_BYTES,
bcc6 0:528034040a12 56 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ,
bcc6 0:528034040a12 57 NULL, 0, false
bcc6 0:528034040a12 58 )
bcc6 0:528034040a12 59 {
bcc6 0:528034040a12 60 GattCharacteristic *charTable[] = {
bcc6 0:528034040a12 61 &plxSpotCheckMeasurementCharacteristic,
bcc6 0:528034040a12 62 &plxFeaturesCharacteristic,
bcc6 0:528034040a12 63 &rawDataCharacteristic,
bcc6 0:528034040a12 64 &signalCharacteristic
bcc6 0:528034040a12 65 };
bcc6 0:528034040a12 66 GattService PulseOximeterService(0x1822/* UUID:Pulse Oximeter Service */, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
bcc6 0:528034040a12 67 ble.gattServer().addService(PulseOximeterService);
bcc6 0:528034040a12 68 }
bcc6 0:528034040a12 69
bcc6 0:528034040a12 70 void updatePlxMeas(float spo2, float pr) {
bcc6 0:528034040a12 71 plxMeasValueBytes.updatePlxSpotCheckMeasurement(spo2, pr);
bcc6 0:528034040a12 72 ble.gattServer().write(plxSpotCheckMeasurementCharacteristic.getValueHandle(),
bcc6 0:528034040a12 73 plxMeasValueBytes.getPointer(),
bcc6 0:528034040a12 74 PlxSpotCheckMeasurementValueBytes::SIZEOF_VALUE_BYTES
bcc6 0:528034040a12 75 );
bcc6 0:528034040a12 76 }
bcc6 0:528034040a12 77
bcc6 0:528034040a12 78 void updateRaw(uint8_t *raw) {
bcc6 0:528034040a12 79 rawValueBytes.updateRawData(raw);
bcc6 0:528034040a12 80 ble.gattServer().write(rawDataCharacteristic.getValueHandle(),
bcc6 0:528034040a12 81 rawValueBytes.getPointer(),
bcc6 0:528034040a12 82 RawDataValueBytes::SIZEOF_VALUE_BYTES
bcc6 0:528034040a12 83 );
bcc6 0:528034040a12 84 }
bcc6 0:528034040a12 85
bcc6 0:528034040a12 86 void updateStatusFlagAndSignalQuality(uint8_t statusFlag, uint8_t signalQuality) {
bcc6 0:528034040a12 87 flagSigValueBytes.updateFlagSignal(statusFlag, signalQuality);
bcc6 0:528034040a12 88 ble.gattServer().write(signalCharacteristic.getValueHandle(),
bcc6 0:528034040a12 89 flagSigValueBytes.getPointer(),
bcc6 0:528034040a12 90 FlagSignalValueBytes::SIZEOF_VALUE_BYTES
bcc6 0:528034040a12 91 );
bcc6 0:528034040a12 92 }
bcc6 0:528034040a12 93 //==================================================================================
bcc6 0:528034040a12 94 private:
bcc6 0:528034040a12 95 struct PlxSpotCheckMeasurementValueBytes {
bcc6 0:528034040a12 96 static const unsigned OFFSET_OF_FLAGS = 0;
bcc6 0:528034040a12 97 static const unsigned OFFSET_OF_SPO2 = 1;
bcc6 0:528034040a12 98 static const unsigned OFFSET_OF_PR = 3;
bcc6 0:528034040a12 99 static const unsigned SIZEOF_VALUE_BYTES = 5;
bcc6 0:528034040a12 100
bcc6 0:528034040a12 101 PlxSpotCheckMeasurementValueBytes(float spo2, float pr) : bytes() {
bcc6 0:528034040a12 102 bytes[OFFSET_OF_FLAGS] = 0x00; /* All fields aren't present */
bcc6 0:528034040a12 103 updatePlxSpotCheckMeasurement(spo2, pr);
bcc6 0:528034040a12 104 }
bcc6 0:528034040a12 105
bcc6 0:528034040a12 106 void updatePlxSpotCheckMeasurement(float spo2, float pr) {
bcc6 0:528034040a12 107 uint16_t sfloat_spo2 = ieee11073_SFLOAT(spo2);
bcc6 0:528034040a12 108 uint16_t sfloat_pr = ieee11073_SFLOAT(pr);
bcc6 1:0ec0e5694c4a 109 #if 0
bcc6 0:528034040a12 110 memcpy(&bytes[OFFSET_OF_SPO2], &sfloat_spo2, sizeof(uint16_t));
bcc6 0:528034040a12 111 memcpy(&bytes[OFFSET_OF_PR], &sfloat_pr, sizeof(uint16_t));
bcc6 1:0ec0e5694c4a 112 #else
bcc6 1:0ec0e5694c4a 113 bytes[OFFSET_OF_SPO2+0] = (uint8_t)(sfloat_spo2 >> 8);
bcc6 1:0ec0e5694c4a 114 bytes[OFFSET_OF_SPO2+1] = (uint8_t)(sfloat_spo2 >> 0);
bcc6 1:0ec0e5694c4a 115 bytes[OFFSET_OF_PR+0] = (uint8_t)(sfloat_pr >> 8);
bcc6 1:0ec0e5694c4a 116 bytes[OFFSET_OF_PR+1] = (uint8_t)(sfloat_pr >> 0);
bcc6 1:0ec0e5694c4a 117 #endif
bcc6 0:528034040a12 118 }
bcc6 0:528034040a12 119
bcc6 0:528034040a12 120 uint8_t *getPointer(void) { return bytes; }
bcc6 0:528034040a12 121 const uint8_t *getPointer(void) const { return bytes; }
bcc6 0:528034040a12 122
bcc6 0:528034040a12 123 uint16_t ieee11073_SFLOAT(float v) {
bcc6 0:528034040a12 124 /* Bitmap: eeee_mmmm_mmmm_mmmm */
bcc6 0:528034040a12 125 /* Exponent: 4bits, Base10, 2'sComplement */
bcc6 0:528034040a12 126 /* Mantissa: 12bits, 2's Complement */
bcc6 0:528034040a12 127 uint8_t exponent = 0;
bcc6 0:528034040a12 128 uint16_t mantissa = (uint16_t)v;
bcc6 0:528034040a12 129 return (((uint16_t)exponent) << 12) | mantissa;
bcc6 0:528034040a12 130 }
bcc6 0:528034040a12 131
bcc6 0:528034040a12 132 uint8_t bytes[SIZEOF_VALUE_BYTES];
bcc6 0:528034040a12 133 };
bcc6 0:528034040a12 134 //-------------------------------------------------------------------------------
bcc6 0:528034040a12 135 struct PlxFeaturesValueBytes {
bcc6 0:528034040a12 136 static const unsigned OFFSET_OF_SUPPORTED_FEATURES = 0;
bcc6 0:528034040a12 137 static const unsigned SIZEOF_VALUE_BYTES = 2;
bcc6 0:528034040a12 138
bcc6 0:528034040a12 139 PlxFeaturesValueBytes() : bytes() {
bcc6 0:528034040a12 140 memset(bytes, 0x00, SIZEOF_VALUE_BYTES); /* All features aren't support */
bcc6 0:528034040a12 141 }
bcc6 0:528034040a12 142
bcc6 0:528034040a12 143 void updatePlxFeatures(uint16_t feat) {
bcc6 0:528034040a12 144 memcpy(&bytes[OFFSET_OF_SUPPORTED_FEATURES], &feat, SIZEOF_VALUE_BYTES);
bcc6 0:528034040a12 145 }
bcc6 0:528034040a12 146
bcc6 0:528034040a12 147 uint8_t *getPointer(void) { return bytes; }
bcc6 0:528034040a12 148 const uint8_t *getPointer(void) const { return bytes; }
bcc6 0:528034040a12 149
bcc6 0:528034040a12 150 uint8_t bytes[SIZEOF_VALUE_BYTES];
bcc6 0:528034040a12 151 };
bcc6 0:528034040a12 152 //-------------------------------------------------------------------------------
bcc6 0:528034040a12 153 struct RawDataValueBytes {
bcc6 0:528034040a12 154 static const unsigned OFFSET_OF_RAW = 0;
bcc6 0:528034040a12 155 static const unsigned SIZEOF_VALUE_BYTES = 18;
bcc6 0:528034040a12 156
bcc6 0:528034040a12 157 RawDataValueBytes() : bytes() {
bcc6 0:528034040a12 158 memset(bytes, 0x00, SIZEOF_VALUE_BYTES);
bcc6 0:528034040a12 159 }
bcc6 0:528034040a12 160
bcc6 0:528034040a12 161 void updateRawData(uint8_t *raw) {
bcc6 0:528034040a12 162 memcpy(&bytes[OFFSET_OF_RAW], raw, SIZEOF_VALUE_BYTES);
bcc6 0:528034040a12 163 }
bcc6 0:528034040a12 164
bcc6 0:528034040a12 165 uint8_t *getPointer(void) { return bytes; }
bcc6 0:528034040a12 166 const uint8_t *getPointer(void) const { return bytes; }
bcc6 0:528034040a12 167
bcc6 0:528034040a12 168 uint8_t bytes[SIZEOF_VALUE_BYTES];
bcc6 0:528034040a12 169 };
bcc6 0:528034040a12 170 //-------------------------------------------------------------------------------
bcc6 0:528034040a12 171 struct FlagSignalValueBytes {
bcc6 0:528034040a12 172 static const unsigned OFFSET_OF_FLAG = 0;
bcc6 0:528034040a12 173 static const unsigned OFFSET_OF_SIGNAL_QUALITY = 1;
bcc6 0:528034040a12 174 static const unsigned SIZEOF_VALUE_BYTES = 2;
bcc6 0:528034040a12 175
bcc6 0:528034040a12 176 FlagSignalValueBytes() : bytes() {
bcc6 0:528034040a12 177 memset(bytes, 0x00, SIZEOF_VALUE_BYTES);
bcc6 0:528034040a12 178 }
bcc6 0:528034040a12 179
bcc6 0:528034040a12 180 void updateFlagSignal(uint8_t statusFlag, uint8_t signalQuality) {
bcc6 0:528034040a12 181 bytes[OFFSET_OF_FLAG] = statusFlag;
bcc6 0:528034040a12 182 bytes[OFFSET_OF_SIGNAL_QUALITY] = signalQuality;
bcc6 0:528034040a12 183 }
bcc6 0:528034040a12 184
bcc6 0:528034040a12 185 uint8_t *getPointer(void) { return bytes; }
bcc6 0:528034040a12 186 const uint8_t *getPointer(void) const { return bytes; }
bcc6 0:528034040a12 187
bcc6 0:528034040a12 188 uint8_t bytes[SIZEOF_VALUE_BYTES];
bcc6 0:528034040a12 189 };
bcc6 0:528034040a12 190 //==================================================================================
bcc6 0:528034040a12 191 protected:
bcc6 0:528034040a12 192 BLE &ble;
bcc6 0:528034040a12 193
bcc6 0:528034040a12 194 PlxSpotCheckMeasurementValueBytes plxMeasValueBytes;
bcc6 0:528034040a12 195 PlxFeaturesValueBytes plxFeatValueBytes;
bcc6 0:528034040a12 196 RawDataValueBytes rawValueBytes;
bcc6 0:528034040a12 197 FlagSignalValueBytes flagSigValueBytes;
bcc6 0:528034040a12 198
bcc6 0:528034040a12 199 GattCharacteristic plxSpotCheckMeasurementCharacteristic;
bcc6 0:528034040a12 200 GattCharacteristic plxFeaturesCharacteristic;
bcc6 0:528034040a12 201 GattCharacteristic rawDataCharacteristic;
bcc6 0:528034040a12 202 GattCharacteristic signalCharacteristic;
bcc6 0:528034040a12 203 };
bcc6 0:528034040a12 204
bcc6 0:528034040a12 205 #endif /* #ifndef __BLE_PULSE_OXIMETER_SERVICE_H__*/