Demo Glucose Service

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_HeartRate by Bluetooth Low Energy

BLE_Glucose_demo implements the Glucose Service which enables a collector device to connect and interact with.

There is a brief sample code edited with Android Studio for demo this BLE_Glucose_demo example, and it is public on github, everyone can clone it by this URL: https://github.com/Marcomissyou/BluetoothLeGlucose.git. It is convenient for you to development your BLE idea.

There is also provided apk file so you can download and install it directly then demo this code, but make sure your Android phone supports Bluetooth 4.0. /media/uploads/Marcomissyou/bleglucoseservice.apk

Committer:
Marcomissyou
Date:
Fri May 29 07:16:24 2015 +0000
Revision:
63:fc6117c32419
Child:
64:8cd9416028a7
First Commit.; For Glucose Demo.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Marcomissyou 63:fc6117c32419 1 /* mbed Microcontroller Library
Marcomissyou 63:fc6117c32419 2 * Copyright (c) 2006-2013 ARM Limited
Marcomissyou 63:fc6117c32419 3 *
Marcomissyou 63:fc6117c32419 4 * Licensed under the Apache License, Version 2.0 (the "License");
Marcomissyou 63:fc6117c32419 5 * you may not use this file except in compliance with the License.
Marcomissyou 63:fc6117c32419 6 * You may obtain a copy of the License at
Marcomissyou 63:fc6117c32419 7 *
Marcomissyou 63:fc6117c32419 8 * http://www.apache.org/licenses/LICENSE-2.0
Marcomissyou 63:fc6117c32419 9 *
Marcomissyou 63:fc6117c32419 10 * Unless required by applicable law or agreed to in writing, software
Marcomissyou 63:fc6117c32419 11 * distributed under the License is distributed on an "AS IS" BASIS,
Marcomissyou 63:fc6117c32419 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Marcomissyou 63:fc6117c32419 13 * See the License for the specific language governing permissions and
Marcomissyou 63:fc6117c32419 14 * limitations under the License.
Marcomissyou 63:fc6117c32419 15 */
Marcomissyou 63:fc6117c32419 16
Marcomissyou 63:fc6117c32419 17 #ifndef __BLE_GLUCOSE_SERVICE_H__
Marcomissyou 63:fc6117c32419 18 #define __BLE_GLUCOSE_SERVICE_H__
Marcomissyou 63:fc6117c32419 19
Marcomissyou 63:fc6117c32419 20 #include "BLEDevice.h"
Marcomissyou 63:fc6117c32419 21 /**
Marcomissyou 63:fc6117c32419 22 * @class GlucoseService
Marcomissyou 63:fc6117c32419 23 * @brief BLE Glucose Service. This service displays the Glucose measurement value represented as a 16bit Float format.<br>
Marcomissyou 63:fc6117c32419 24 * @This example can be demonstrated with Blood Pressure Android App downloaded from
Marcomissyou 63:fc6117c32419 25 * @https://github.com/Marcomissyou/BluetoothLeGlucose.git
Marcomissyou 63:fc6117c32419 26 */
Marcomissyou 63:fc6117c32419 27 static uint16_t SEQUENCE_NUMBER = 11111;
Marcomissyou 63:fc6117c32419 28 static uint16_t BASE_TIME_YEAR = 2015;
Marcomissyou 63:fc6117c32419 29 static uint8_t BASE_TIME_MONTH = 5;
Marcomissyou 63:fc6117c32419 30 static uint8_t BASE_TIME_DAY = 29;
Marcomissyou 63:fc6117c32419 31 static uint8_t BASE_TIME_HOURS = 17;
Marcomissyou 63:fc6117c32419 32 static uint8_t BASE_TIME_MINUTES = 30;
Marcomissyou 63:fc6117c32419 33 static uint8_t BASE_TIME_SECONDS = 45;
Marcomissyou 63:fc6117c32419 34
Marcomissyou 63:fc6117c32419 35 class GlucoseService {
Marcomissyou 63:fc6117c32419 36 public:
Marcomissyou 63:fc6117c32419 37 GlucoseService(BLEDevice &_ble, float GluMeasure, uint16_t GluFeature =2111):
Marcomissyou 63:fc6117c32419 38 ble(_ble),
Marcomissyou 63:fc6117c32419 39 GluReceiveBuffer(),
Marcomissyou 63:fc6117c32419 40 GluReceive_flag(),
Marcomissyou 63:fc6117c32419 41 GlucoseMeasurementValue(GluMeasure),
Marcomissyou 63:fc6117c32419 42 GlucoseFeatureValue(GluFeature),
Marcomissyou 63:fc6117c32419 43 GlucoseValue(GattCharacteristic::UUID_GLUCOSE_MEASUREMENT_CHAR, GlucoseMeasurementValue.getPointer(),
Marcomissyou 63:fc6117c32419 44 12, 12,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
Marcomissyou 63:fc6117c32419 45 GlucoseFeature(GattCharacteristic::UUID_GLUCOSE_FEATURE_CHAR, &GluFeature),
Marcomissyou 63:fc6117c32419 46 GluControlPoint(GattCharacteristic::UUID_RECORD_ACCESS_CONTROL_POINT_CHAR, GluReceiveBuffer, 4, 4,
Marcomissyou 63:fc6117c32419 47 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE)
Marcomissyou 63:fc6117c32419 48 {
Marcomissyou 63:fc6117c32419 49 setupService();
Marcomissyou 63:fc6117c32419 50 }
Marcomissyou 63:fc6117c32419 51
Marcomissyou 63:fc6117c32419 52 void updateGlucoseMeasurement(float GluMeasure) {
Marcomissyou 63:fc6117c32419 53 GlucoseMeasurementValue.updateGlucoseMeasurement(GluMeasure);
Marcomissyou 63:fc6117c32419 54 ble.updateCharacteristicValue(GlucoseValue.getValueAttribute().getHandle(), GlucoseMeasurementValue.getPointer(), 12);
Marcomissyou 63:fc6117c32419 55 }
Marcomissyou 63:fc6117c32419 56
Marcomissyou 63:fc6117c32419 57 virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
Marcomissyou 63:fc6117c32419 58 if (params->charHandle == GluControlPoint.getValueAttribute().getHandle()) {
Marcomissyou 63:fc6117c32419 59 uint16_t bytesRead = params->len;
Marcomissyou 63:fc6117c32419 60 if (bytesRead <= 4) {
Marcomissyou 63:fc6117c32419 61 memcpy(GluReceiveBuffer, params->data, bytesRead);
Marcomissyou 63:fc6117c32419 62 GluReceive_flag = 1;
Marcomissyou 63:fc6117c32419 63 }
Marcomissyou 63:fc6117c32419 64 }
Marcomissyou 63:fc6117c32419 65 }
Marcomissyou 63:fc6117c32419 66
Marcomissyou 63:fc6117c32419 67 bool is_GluReceived(){
Marcomissyou 63:fc6117c32419 68 if(GluReceive_flag ==1){
Marcomissyou 63:fc6117c32419 69 return true;
Marcomissyou 63:fc6117c32419 70 }
Marcomissyou 63:fc6117c32419 71 return false;
Marcomissyou 63:fc6117c32419 72 }
Marcomissyou 63:fc6117c32419 73
Marcomissyou 63:fc6117c32419 74 uint8_t *getControlPoint(){
Marcomissyou 63:fc6117c32419 75 return GluReceiveBuffer;
Marcomissyou 63:fc6117c32419 76 }
Marcomissyou 63:fc6117c32419 77
Marcomissyou 63:fc6117c32419 78 void CleanFlag(){
Marcomissyou 63:fc6117c32419 79 GluReceive_flag = 0;
Marcomissyou 63:fc6117c32419 80 }
Marcomissyou 63:fc6117c32419 81
Marcomissyou 63:fc6117c32419 82 private:
Marcomissyou 63:fc6117c32419 83 void setupService(void) {
Marcomissyou 63:fc6117c32419 84 static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */
Marcomissyou 63:fc6117c32419 85 if (serviceAdded) {
Marcomissyou 63:fc6117c32419 86 return;
Marcomissyou 63:fc6117c32419 87 }
Marcomissyou 63:fc6117c32419 88 GattCharacteristic *charTable[] = {&GlucoseValue, &GlucoseFeature, &GluControlPoint}; //, &GlucoseContext
Marcomissyou 63:fc6117c32419 89 GattService GluService(GattService::UUID_GLUCOSE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Marcomissyou 63:fc6117c32419 90 ble.addService(GluService);
Marcomissyou 63:fc6117c32419 91 serviceAdded = true;
Marcomissyou 63:fc6117c32419 92 ble.onDataWritten(this, &GlucoseService::onDataWritten);
Marcomissyou 63:fc6117c32419 93 }
Marcomissyou 63:fc6117c32419 94
Marcomissyou 63:fc6117c32419 95 //==========================================================================================================
Marcomissyou 63:fc6117c32419 96 private:
Marcomissyou 63:fc6117c32419 97 struct GlucoseMeasurementBytes {
Marcomissyou 63:fc6117c32419 98 static const unsigned FLAGS_BYTE_INDEX = 0;
Marcomissyou 63:fc6117c32419 99 static const unsigned TIME_OFFSET_PRESENT = 0;
Marcomissyou 63:fc6117c32419 100 static const unsigned GLUCOSE_CONCENTRATION_Type_Sample_Location = 1;
Marcomissyou 63:fc6117c32419 101 static const unsigned GLUCOSE_CONCENTRATION_UNIT = 1; // 0 = kg/L, 1 = mol/L
Marcomissyou 63:fc6117c32419 102 static const unsigned SENSOR_STATUS_ANNUNCIATION = 0;
Marcomissyou 63:fc6117c32419 103 static const unsigned CONTEXT_INFORMATION_FOLLOWS_FALSE = 0;
Marcomissyou 63:fc6117c32419 104 static const unsigned CONTEXT_INFORMATION_FOLLOWS_TRUE = 1;
Marcomissyou 63:fc6117c32419 105 static const unsigned VALUE_FORMAT_BITNUM = 0;
Marcomissyou 63:fc6117c32419 106 static const uint8_t VALUE_FORMAT_FLAG = 0;
Marcomissyou 63:fc6117c32419 107
Marcomissyou 63:fc6117c32419 108 // Initial setting Glucose measurement value
Marcomissyou 63:fc6117c32419 109 GlucoseMeasurementBytes(uint16_t GluMeasure) : GlucoseMeasurementValue() {
Marcomissyou 63:fc6117c32419 110 updateGlucoseMeasurement(GluMeasure);
Marcomissyou 63:fc6117c32419 111 }
Marcomissyou 63:fc6117c32419 112
Marcomissyou 63:fc6117c32419 113 void updateDataAndSequneceNumber(){
Marcomissyou 63:fc6117c32419 114 SEQUENCE_NUMBER++;
Marcomissyou 63:fc6117c32419 115 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+3], &BASE_TIME_YEAR, 2);
Marcomissyou 63:fc6117c32419 116 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+5], &BASE_TIME_MONTH, 1);
Marcomissyou 63:fc6117c32419 117 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+6], &BASE_TIME_DAY, 1);
Marcomissyou 63:fc6117c32419 118 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+7], &BASE_TIME_HOURS, 1);
Marcomissyou 63:fc6117c32419 119 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+8], &BASE_TIME_MINUTES, 1);
Marcomissyou 63:fc6117c32419 120 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+9], &BASE_TIME_SECONDS, 1);
Marcomissyou 63:fc6117c32419 121
Marcomissyou 63:fc6117c32419 122 }
Marcomissyou 63:fc6117c32419 123
Marcomissyou 63:fc6117c32419 124 void updateGlucoseMeasurement(float GluMeasure) {
Marcomissyou 63:fc6117c32419 125 GlucoseMeasurementValue[FLAGS_BYTE_INDEX] = (TIME_OFFSET_PRESENT << 0)|(GLUCOSE_CONCENTRATION_Type_Sample_Location << 1)
Marcomissyou 63:fc6117c32419 126 |(GLUCOSE_CONCENTRATION_UNIT << 2)|(SENSOR_STATUS_ANNUNCIATION << 3)
Marcomissyou 63:fc6117c32419 127 |(CONTEXT_INFORMATION_FOLLOWS_FALSE << 4);
Marcomissyou 63:fc6117c32419 128
Marcomissyou 63:fc6117c32419 129 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+1], &SEQUENCE_NUMBER, 2);
Marcomissyou 63:fc6117c32419 130 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+3], &BASE_TIME_YEAR, 2);
Marcomissyou 63:fc6117c32419 131 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+5], &BASE_TIME_MONTH, 1);
Marcomissyou 63:fc6117c32419 132 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+6], &BASE_TIME_DAY, 1);
Marcomissyou 63:fc6117c32419 133 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+7], &BASE_TIME_HOURS, 1);
Marcomissyou 63:fc6117c32419 134 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+8], &BASE_TIME_MINUTES, 1);
Marcomissyou 63:fc6117c32419 135 memcpy(&GlucoseMeasurementValue[FLAGS_BYTE_INDEX+9], &BASE_TIME_SECONDS, 1);
Marcomissyou 63:fc6117c32419 136 uint16_t GluMeasureData = ieee11073_float16(GluMeasure);
Marcomissyou 63:fc6117c32419 137 GlucoseMeasurementValue[FLAGS_BYTE_INDEX + 10] = (uint8_t)(GluMeasureData & 0xFF);
Marcomissyou 63:fc6117c32419 138 GlucoseMeasurementValue[FLAGS_BYTE_INDEX + 11] = (uint8_t)(GluMeasureData >> 8);
Marcomissyou 63:fc6117c32419 139 }
Marcomissyou 63:fc6117c32419 140
Marcomissyou 63:fc6117c32419 141 uint8_t *getPointer(void) {
Marcomissyou 63:fc6117c32419 142 return GlucoseMeasurementValue;
Marcomissyou 63:fc6117c32419 143 }
Marcomissyou 63:fc6117c32419 144
Marcomissyou 63:fc6117c32419 145 uint16_t ieee11073_float16(float GluMeasure) {
Marcomissyou 63:fc6117c32419 146 uint8_t exponent = 0;
Marcomissyou 63:fc6117c32419 147 uint16_t mantissa = (uint16_t)GluMeasure;
Marcomissyou 63:fc6117c32419 148 return ((exponent << 12)&0xF0) | (mantissa << 0) & 0x0FFF ;
Marcomissyou 63:fc6117c32419 149 }
Marcomissyou 63:fc6117c32419 150
Marcomissyou 63:fc6117c32419 151 uint8_t GlucoseMeasurementValue[14];
Marcomissyou 63:fc6117c32419 152 };
Marcomissyou 63:fc6117c32419 153
Marcomissyou 63:fc6117c32419 154 private:
Marcomissyou 63:fc6117c32419 155 BLEDevice &ble;
Marcomissyou 63:fc6117c32419 156 GlucoseMeasurementBytes GlucoseMeasurementValue;
Marcomissyou 63:fc6117c32419 157 GattCharacteristic GlucoseValue;
Marcomissyou 63:fc6117c32419 158 uint16_t GlucoseFeatureValue;
Marcomissyou 63:fc6117c32419 159 ReadWriteGattCharacteristic<uint16_t> GlucoseFeature;
Marcomissyou 63:fc6117c32419 160 uint8_t GluReceiveBuffer[4];
Marcomissyou 63:fc6117c32419 161 uint8_t GluReceive_flag;
Marcomissyou 63:fc6117c32419 162 GattCharacteristic GluControlPoint;
Marcomissyou 63:fc6117c32419 163 };
Marcomissyou 63:fc6117c32419 164 #endif /* #ifndef __BLE_GLUCOSE_SERVICE_H__*/