BLE demo for the Health-Thermometer service.

Dependencies:   BLE_API mbed nRF51822 X_NUCLEO_IDB0XA1

This example demonstrates how to use the Health Thermometer Service. The Health Thermometer service reports two pieces of information, Temperature and Sensor Location.

API

Import library

Public Types

enum SensorLocation_t {
LOCATION_ARMPIT = 1, LOCATION_BODY , LOCATION_EAR , LOCATION_FINGER ,
LOCATION_GI_TRACT , LOCATION_MOUTH , LOCATION_RECTUM , LOCATION_TOE ,
LOCATION_EAR_DRUM
}

Public Member Functions

HealthThermometerService ( BLE &_ble, float initialTemp, uint8_t _location)
Add the Health Thermometer Service to an existing BLE object, initialize with temperature and location.
void updateTemperature (float temperature)
Update the temperature being broadcast.
void updateLocation ( SensorLocation_t loc)
Update the location.

Technical Details

Further Technical Details can be found at the following links

Committer:
Vincent Coubard
Date:
Tue Sep 20 13:47:58 2016 +0100
Revision:
17:9ce6c0171634
Parent:
15:57860d1cd14d
Update the libraries.
Add st shield support.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 0:d01bde90471b 1 /* mbed Microcontroller Library
rgrover1 0:d01bde90471b 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 0:d01bde90471b 3 *
rgrover1 0:d01bde90471b 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 0:d01bde90471b 5 * you may not use this file except in compliance with the License.
rgrover1 0:d01bde90471b 6 * You may obtain a copy of the License at
rgrover1 0:d01bde90471b 7 *
rgrover1 0:d01bde90471b 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 0:d01bde90471b 9 *
rgrover1 0:d01bde90471b 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 0:d01bde90471b 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 0:d01bde90471b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 0:d01bde90471b 13 * See the License for the specific language governing permissions and
rgrover1 0:d01bde90471b 14 * limitations under the License.
rgrover1 0:d01bde90471b 15 */
rgrover1 0:d01bde90471b 16
rgrover1 0:d01bde90471b 17 #include "mbed.h"
andresag 15:57860d1cd14d 18 #include "ble/BLE.h"
andresag 15:57860d1cd14d 19 #include "ble/services/HealthThermometerService.h"
rgrover1 0:d01bde90471b 20
rgrover1 4:83c07b0e93d6 21 DigitalOut led1(LED1);
rgrover1 0:d01bde90471b 22
andresag 15:57860d1cd14d 23 static HealthThermometerService *thermometerServicePtr;
andresag 15:57860d1cd14d 24
andresag 15:57860d1cd14d 25 static const char DEVICE_NAME[] = "Therm";
rgrover1 0:d01bde90471b 26 static const uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE};
rgrover1 0:d01bde90471b 27 static volatile bool triggerSensorPolling = false;
andresag 15:57860d1cd14d 28 static float currentTemperature = 39.6;
rgrover1 0:d01bde90471b 29
mbedAustin 8:63addc0221e7 30 /* Restart Advertising on disconnection*/
rgrover1 14:677ef88025b8 31 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
rgrover1 0:d01bde90471b 32 {
andresag 15:57860d1cd14d 33 BLE::Instance().gap().startAdvertising();
rgrover1 0:d01bde90471b 34 }
rgrover1 0:d01bde90471b 35
rgrover1 10:9a7e23066427 36 void periodicCallback(void)
rgrover1 10:9a7e23066427 37 {
rgrover1 10:9a7e23066427 38 led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
rgrover1 10:9a7e23066427 39
rgrover1 10:9a7e23066427 40 /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
rgrover1 10:9a7e23066427 41 * heavy-weight sensor polling from the main thread. */
rgrover1 10:9a7e23066427 42 triggerSensorPolling = true;
rgrover1 10:9a7e23066427 43 }
rgrover1 10:9a7e23066427 44
andresag 15:57860d1cd14d 45 /**
andresag 15:57860d1cd14d 46 * This function is called when the ble initialization process has failed
andresag 15:57860d1cd14d 47 */
andresag 15:57860d1cd14d 48 void onBleInitError(BLE &ble, ble_error_t error)
rgrover1 0:d01bde90471b 49 {
andresag 15:57860d1cd14d 50 /* Avoid compiler warnings */
andresag 15:57860d1cd14d 51 (void) ble;
andresag 15:57860d1cd14d 52 (void) error;
andresag 15:57860d1cd14d 53 /* Initialization error handling should go here */
andresag 15:57860d1cd14d 54 }
rgrover1 10:9a7e23066427 55
andresag 15:57860d1cd14d 56 /**
andresag 15:57860d1cd14d 57 * Callback triggered when the ble initialization process has finished
andresag 15:57860d1cd14d 58 */
andresag 15:57860d1cd14d 59 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
andresag 15:57860d1cd14d 60 {
andresag 15:57860d1cd14d 61 BLE& ble = params->ble;
andresag 15:57860d1cd14d 62 ble_error_t error = params->error;
andresag 15:57860d1cd14d 63
andresag 15:57860d1cd14d 64 if (error != BLE_ERROR_NONE) {
andresag 15:57860d1cd14d 65 /* In case of error, forward the error handling to onBleInitError */
andresag 15:57860d1cd14d 66 onBleInitError(ble, error);
andresag 15:57860d1cd14d 67 return;
andresag 15:57860d1cd14d 68 }
andresag 15:57860d1cd14d 69
andresag 15:57860d1cd14d 70 /* Ensure that it is the default instance of BLE */
andresag 15:57860d1cd14d 71 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
andresag 15:57860d1cd14d 72 return;
andresag 15:57860d1cd14d 73 }
andresag 15:57860d1cd14d 74
rgrover1 13:30f6f65629b5 75 ble.gap().onDisconnection(disconnectionCallback);
rgrover1 0:d01bde90471b 76
rgrover1 10:9a7e23066427 77 /* Setup primary service. */
andresag 15:57860d1cd14d 78 thermometerServicePtr = new HealthThermometerService(ble, currentTemperature, HealthThermometerService::LOCATION_EAR);
rgrover1 10:9a7e23066427 79
rgrover1 0:d01bde90471b 80 /* setup advertising */
rgrover1 13:30f6f65629b5 81 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
rgrover1 13:30f6f65629b5 82 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
rgrover1 13:30f6f65629b5 83 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::THERMOMETER_EAR);
rgrover1 13:30f6f65629b5 84 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
rgrover1 13:30f6f65629b5 85 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
rgrover1 13:30f6f65629b5 86 ble.gap().setAdvertisingInterval(1000); /* 1000ms */
andresag 15:57860d1cd14d 87 ble.gap().startAdvertising();
andresag 15:57860d1cd14d 88 }
andresag 15:57860d1cd14d 89
andresag 15:57860d1cd14d 90 int main(void)
andresag 15:57860d1cd14d 91 {
andresag 15:57860d1cd14d 92 led1 = 1;
andresag 15:57860d1cd14d 93 Ticker ticker;
andresag 15:57860d1cd14d 94 ticker.attach(periodicCallback, 1);
andresag 15:57860d1cd14d 95
andresag 15:57860d1cd14d 96 BLE &ble = BLE::Instance();
andresag 15:57860d1cd14d 97 ble.init(bleInitComplete);
andresag 15:57860d1cd14d 98
andresag 15:57860d1cd14d 99 /* SpinWait for initialization to complete. This is necessary because the
andresag 15:57860d1cd14d 100 * BLE object is used in the main loop below. */
andresag 15:57860d1cd14d 101 while (ble.hasInitialized() == false) { /* spin loop */ }
rgrover1 0:d01bde90471b 102
mbedAustin 8:63addc0221e7 103 while (true) {
andresag 15:57860d1cd14d 104 if (triggerSensorPolling && ble.gap().getState().connected) {
rgrover1 10:9a7e23066427 105 triggerSensorPolling = false;
rgrover1 10:9a7e23066427 106
rgrover1 10:9a7e23066427 107 /* In our case, we simply update the dummy temperature measurement. */
rgrover1 10:9a7e23066427 108 currentTemperature += 0.1;
andresag 15:57860d1cd14d 109 thermometerServicePtr->updateTemperature(currentTemperature);
rgrover1 10:9a7e23066427 110 } else {
rgrover1 10:9a7e23066427 111 ble.waitForEvent();
rgrover1 10:9a7e23066427 112 }
rgrover1 0:d01bde90471b 113 }
rgrover1 0:d01bde90471b 114 }