This example uses the Health Thermometer Profile to send thermometer information: The canonical source for this example lives at https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_Thermometer

Thermometer

This example uses the Health Thermometer Profile to send thermometer information:

  • Sensor location: thermometer placement on the body. The default value in this application is the ear (``LOCATION_EAR``). The characteristic description shows the other possible values.
  • Temperature: the initial temperature is 39.6, and it's incremented by 0.1 every half second. It resets to 39.6 when it reaches 43.0.

For more information see:

  • Temperature Type: GATT characteristic details for temperature type (sensor location).

Running the application

Requirements

The sample application can be seen on any BLE scanner on a smartphone. If you don't have a scanner on your phone, please install :

- nRF Master Control Panel for Android.

- LightBlue for iPhone.

Hardware requirements are in the main readme.

Building instructions

Building with mbed CLI

If you'd like to use mbed CLI to build this, then you should refer to the main readme. The instructions here relate to using the developer.mbed.org Online Compiler

In order to build this example in the mbed Online Compiler, first import the example using the ‘Import’ button on the right hand side.

Next, select a platform to build for. This must either be a platform that supports BLE, for example the NRF51-DK, or one of the following:

List of platforms supporting Bluetooth Low Energy

Or you must also add a piece of hardware and the supporting library that includes a Bluetooth Low Energy driver for that hardware, for example the K64F or NUCLEO_F401RE with the X-NUCLEO-IDB05A1

List of components supporting Bluetooth Low Energy.

Once you have selected your platform, compile the example and drag and drop the resulting binary onto your board.

For general instructions on using the mbed Online Compiler, please see the mbed Handbook

Checking for success

Note: Screens captures depicted below show what is expected from this example if the scanner used is *nRF Master Control Panel* version 4.0.5. If you encounter any difficulties consider trying another scanner or another version of nRF Master Control Panel. Alternative scanners may require reference to their manuals.

  • Build the application and install it on your board as explained in the building instructions.
  • Open the BLE scanner on your phone.
  • Start a scan.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-Thermometer/raw-file/a27dfda81620/img/start_scan.png

figure 1 How to start scan using nRF Master Control Panel 4.0.5

  • Find your device; it should be named *Therm*.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-Thermometer/raw-file/a27dfda81620/img/scan_results.png

figure 2 Scan results using nRF Master Control Panel 4.0.5

  • Establish a connection with your device.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-Thermometer/raw-file/a27dfda81620/img/connection.png

figure 3 How to establish a connection using Master Control Panel 4.0.5

  • Discover the services and the characteristics on the device. The *Health Thermometer* service has the UUID `0x1809` and includes the *Temperature Measurement* characteristic which has the UUID `0x2A1C`.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-Thermometer/raw-file/a27dfda81620/img/discovery.png

figure 4 Representation of the Thermometer service using Master Control Panel 4.0.5

  • Register for the notifications sent by the *Temperature Measurement* characteristic.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-Thermometer/raw-file/a27dfda81620/img/register_to_notifications.png

figure 5 How to register to notifications using Master Control Panel 4.0.5

  • You should see the temperature value change every half second. It begins at 39.6, goes up to 43.0 (in steps of 0.1), resets to 39.6 and so on.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-Thermometer/raw-file/a27dfda81620/img/notifications.png

figure 6 Notifications view using Master Control Panel 4.0.5

Committer:
mbed_official
Date:
Tue Jul 23 12:04:16 2019 +0100
Revision:
79:16042006e938
Parent:
74:b082fa6d75eb
Merge pull request #245 from paul-szczepanek-arm/master

Fix name of template for IAR
.
Commit copied from https://github.com/ARMmbed/mbed-os-example-ble

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 2:cc8349878a7d 1 /* mbed Microcontroller Library
mbed_official 2:cc8349878a7d 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 2:cc8349878a7d 3 *
mbed_official 2:cc8349878a7d 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 2:cc8349878a7d 5 * you may not use this file except in compliance with the License.
mbed_official 2:cc8349878a7d 6 * You may obtain a copy of the License at
mbed_official 2:cc8349878a7d 7 *
mbed_official 2:cc8349878a7d 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 2:cc8349878a7d 9 *
mbed_official 2:cc8349878a7d 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 2:cc8349878a7d 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 2:cc8349878a7d 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 2:cc8349878a7d 13 * See the License for the specific language governing permissions and
mbed_official 2:cc8349878a7d 14 * limitations under the License.
mbed_official 2:cc8349878a7d 15 */
mbed_official 2:cc8349878a7d 16
mbed_official 11:4e356c89ad66 17 #include <events/mbed_events.h>
mbed_official 2:cc8349878a7d 18 #include "mbed.h"
mbed_official 2:cc8349878a7d 19 #include "ble/BLE.h"
mbed_official 2:cc8349878a7d 20 #include "ble/services/HealthThermometerService.h"
mbed_official 74:b082fa6d75eb 21 #include "pretty_printer.h"
mbed_official 2:cc8349878a7d 22
mbed_official 2:cc8349878a7d 23 DigitalOut led1(LED1, 1);
mbed_official 2:cc8349878a7d 24
mbed_official 74:b082fa6d75eb 25 const static char DEVICE_NAME[] = "Therm";
mbed_official 2:cc8349878a7d 26
mbed_official 74:b082fa6d75eb 27 static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);
mbed_official 2:cc8349878a7d 28
mbed_official 79:16042006e938 29 class ThermometerDemo : ble::Gap::EventHandler {
mbed_official 74:b082fa6d75eb 30 public:
mbed_official 79:16042006e938 31 ThermometerDemo(BLE &ble, events::EventQueue &event_queue) :
mbed_official 74:b082fa6d75eb 32 _ble(ble),
mbed_official 74:b082fa6d75eb 33 _event_queue(event_queue),
mbed_official 79:16042006e938 34 _sensor_event_id(0),
mbed_official 74:b082fa6d75eb 35 _thermometer_uuid(GattService::UUID_HEALTH_THERMOMETER_SERVICE),
mbed_official 79:16042006e938 36 _current_temperature(39.6f),
mbed_official 74:b082fa6d75eb 37 _thermometer_service(NULL),
mbed_official 74:b082fa6d75eb 38 _adv_data_builder(_adv_buffer) { }
mbed_official 2:cc8349878a7d 39
mbed_official 74:b082fa6d75eb 40 void start() {
mbed_official 74:b082fa6d75eb 41 _ble.gap().setEventHandler(this);
mbed_official 74:b082fa6d75eb 42
mbed_official 79:16042006e938 43 _ble.init(this, &ThermometerDemo::on_init_complete);
mbed_official 2:cc8349878a7d 44
mbed_official 79:16042006e938 45 _event_queue.call_every(500, this, &ThermometerDemo::blink);
mbed_official 74:b082fa6d75eb 46
mbed_official 74:b082fa6d75eb 47 _event_queue.dispatch_forever();
mbed_official 2:cc8349878a7d 48 }
mbed_official 2:cc8349878a7d 49
mbed_official 74:b082fa6d75eb 50 private:
mbed_official 74:b082fa6d75eb 51 /** Callback triggered when the ble initialization process has finished */
mbed_official 74:b082fa6d75eb 52 void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
mbed_official 74:b082fa6d75eb 53 if (params->error != BLE_ERROR_NONE) {
mbed_official 74:b082fa6d75eb 54 print_error(params->error, "Ble initialization failed.");
mbed_official 74:b082fa6d75eb 55 return;
mbed_official 74:b082fa6d75eb 56 }
mbed_official 44:10b42e19e84b 57
mbed_official 74:b082fa6d75eb 58 print_mac_address();
mbed_official 2:cc8349878a7d 59
mbed_official 74:b082fa6d75eb 60 /* Setup primary service. */
mbed_official 74:b082fa6d75eb 61 _thermometer_service = new HealthThermometerService(_ble, _current_temperature, HealthThermometerService::LOCATION_EAR);
mbed_official 74:b082fa6d75eb 62
mbed_official 74:b082fa6d75eb 63 start_advertising();
mbed_official 2:cc8349878a7d 64 }
mbed_official 2:cc8349878a7d 65
mbed_official 74:b082fa6d75eb 66 void start_advertising() {
mbed_official 74:b082fa6d75eb 67 /* Create advertising parameters and payload */
mbed_official 74:b082fa6d75eb 68
mbed_official 74:b082fa6d75eb 69 ble::AdvertisingParameters adv_parameters(
mbed_official 74:b082fa6d75eb 70 ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
mbed_official 74:b082fa6d75eb 71 ble::adv_interval_t(ble::millisecond_t(1000))
mbed_official 74:b082fa6d75eb 72 );
mbed_official 74:b082fa6d75eb 73
mbed_official 74:b082fa6d75eb 74 _adv_data_builder.setFlags();
mbed_official 74:b082fa6d75eb 75 _adv_data_builder.setLocalServiceList(mbed::make_Span(&_thermometer_uuid, 1));
mbed_official 74:b082fa6d75eb 76 _adv_data_builder.setAppearance(ble::adv_data_appearance_t::THERMOMETER_EAR);
mbed_official 74:b082fa6d75eb 77 _adv_data_builder.setName(DEVICE_NAME);
mbed_official 74:b082fa6d75eb 78
mbed_official 74:b082fa6d75eb 79 /* Setup advertising */
mbed_official 74:b082fa6d75eb 80
mbed_official 74:b082fa6d75eb 81 ble_error_t error = _ble.gap().setAdvertisingParameters(
mbed_official 74:b082fa6d75eb 82 ble::LEGACY_ADVERTISING_HANDLE,
mbed_official 74:b082fa6d75eb 83 adv_parameters
mbed_official 74:b082fa6d75eb 84 );
mbed_official 74:b082fa6d75eb 85
mbed_official 74:b082fa6d75eb 86 if (error) {
mbed_official 74:b082fa6d75eb 87 print_error(error, "_ble.gap().setAdvertisingParameters() failed");
mbed_official 74:b082fa6d75eb 88 return;
mbed_official 74:b082fa6d75eb 89 }
mbed_official 74:b082fa6d75eb 90
mbed_official 74:b082fa6d75eb 91 error = _ble.gap().setAdvertisingPayload(
mbed_official 74:b082fa6d75eb 92 ble::LEGACY_ADVERTISING_HANDLE,
mbed_official 74:b082fa6d75eb 93 _adv_data_builder.getAdvertisingData()
mbed_official 74:b082fa6d75eb 94 );
mbed_official 74:b082fa6d75eb 95
mbed_official 74:b082fa6d75eb 96 if (error) {
mbed_official 74:b082fa6d75eb 97 print_error(error, "_ble.gap().setAdvertisingPayload() failed");
mbed_official 74:b082fa6d75eb 98 return;
mbed_official 74:b082fa6d75eb 99 }
mbed_official 74:b082fa6d75eb 100
mbed_official 74:b082fa6d75eb 101 /* Start advertising */
mbed_official 74:b082fa6d75eb 102
mbed_official 74:b082fa6d75eb 103 error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
mbed_official 74:b082fa6d75eb 104
mbed_official 74:b082fa6d75eb 105 if (error) {
mbed_official 74:b082fa6d75eb 106 print_error(error, "_ble.gap().startAdvertising() failed");
mbed_official 74:b082fa6d75eb 107 return;
mbed_official 74:b082fa6d75eb 108 }
mbed_official 2:cc8349878a7d 109 }
mbed_official 2:cc8349878a7d 110
mbed_official 74:b082fa6d75eb 111 void update_sensor_value() {
mbed_official 79:16042006e938 112 _current_temperature = (_current_temperature + 0.1f > 43.0f) ? 39.6f : _current_temperature + 0.1f;
mbed_official 79:16042006e938 113 _thermometer_service->updateTemperature(_current_temperature);
mbed_official 74:b082fa6d75eb 114 }
mbed_official 2:cc8349878a7d 115
mbed_official 74:b082fa6d75eb 116 void blink(void) {
mbed_official 74:b082fa6d75eb 117 led1 = !led1;
mbed_official 74:b082fa6d75eb 118 }
mbed_official 74:b082fa6d75eb 119
mbed_official 74:b082fa6d75eb 120 private:
mbed_official 74:b082fa6d75eb 121 /* Event handler */
mbed_official 2:cc8349878a7d 122
mbed_official 79:16042006e938 123 virtual void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
mbed_official 79:16042006e938 124 _event_queue.cancel(_sensor_event_id);
mbed_official 74:b082fa6d75eb 125 _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
mbed_official 74:b082fa6d75eb 126 }
mbed_official 74:b082fa6d75eb 127
mbed_official 79:16042006e938 128 virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event) {
mbed_official 79:16042006e938 129 if (event.getStatus() == BLE_ERROR_NONE) {
mbed_official 79:16042006e938 130 _sensor_event_id = _event_queue.call_every(1000, this, &ThermometerDemo::update_sensor_value);
mbed_official 79:16042006e938 131 }
mbed_official 79:16042006e938 132 }
mbed_official 79:16042006e938 133
mbed_official 74:b082fa6d75eb 134 private:
mbed_official 74:b082fa6d75eb 135 BLE &_ble;
mbed_official 74:b082fa6d75eb 136 events::EventQueue &_event_queue;
mbed_official 74:b082fa6d75eb 137
mbed_official 79:16042006e938 138 int _sensor_event_id;
mbed_official 79:16042006e938 139
mbed_official 74:b082fa6d75eb 140 UUID _thermometer_uuid;
mbed_official 44:10b42e19e84b 141
mbed_official 79:16042006e938 142 float _current_temperature;
mbed_official 74:b082fa6d75eb 143 HealthThermometerService *_thermometer_service;
mbed_official 2:cc8349878a7d 144
mbed_official 74:b082fa6d75eb 145 uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
mbed_official 74:b082fa6d75eb 146 ble::AdvertisingDataBuilder _adv_data_builder;
mbed_official 74:b082fa6d75eb 147 };
mbed_official 74:b082fa6d75eb 148
mbed_official 74:b082fa6d75eb 149 /** Schedule processing of events from the BLE middleware in the event queue. */
mbed_official 74:b082fa6d75eb 150 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
mbed_official 74:b082fa6d75eb 151 event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
mbed_official 2:cc8349878a7d 152 }
mbed_official 2:cc8349878a7d 153
mbed_official 2:cc8349878a7d 154 int main()
mbed_official 2:cc8349878a7d 155 {
mbed_official 74:b082fa6d75eb 156 BLE &ble = BLE::Instance();
mbed_official 74:b082fa6d75eb 157 ble.onEventsToProcess(schedule_ble_events);
mbed_official 2:cc8349878a7d 158
mbed_official 79:16042006e938 159 ThermometerDemo demo(ble, event_queue);
mbed_official 74:b082fa6d75eb 160 demo.start();
mbed_official 2:cc8349878a7d 161
mbed_official 2:cc8349878a7d 162 return 0;
mbed_official 2:cc8349878a7d 163 }