This is a fork of mbed-os-example-ble-HeartRate maintained for Sequana compatibility. This application transmits a heart rate value using the Bluetooth SIG Heart Rate Profile. The heart rate value is provided by the application itself, not by a sensor, so that you don't have to get a sensor just to run the example. The canonical source for this example lives at https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_HeartRate
main.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <events/mbed_events.h> 00018 #include <mbed.h> 00019 #include "ble/BLE.h" 00020 #include "ble/gap/Gap.h" 00021 #include "ble/services/HeartRateService.h" 00022 #include "pretty_printer.h" 00023 00024 const static char DEVICE_NAME[] = "Heartrate"; 00025 00026 static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE); 00027 00028 class HeartrateDemo : ble::Gap::EventHandler { 00029 public: 00030 HeartrateDemo(BLE &ble, events::EventQueue &event_queue) : 00031 _ble(ble), 00032 _event_queue(event_queue), 00033 _led1(LED1, 1), 00034 _connected(false), 00035 _hr_uuid(GattService::UUID_HEART_RATE_SERVICE), 00036 _hr_counter(100), 00037 _hr_service(ble, _hr_counter, HeartRateService::LOCATION_FINGER), 00038 _adv_data_builder(_adv_buffer) { } 00039 00040 void start() { 00041 _ble.gap().setEventHandler(this); 00042 00043 _ble.init(this, &HeartrateDemo::on_init_complete); 00044 00045 _event_queue.call_every(500, this, &HeartrateDemo::blink); 00046 _event_queue.call_every(1000, this, &HeartrateDemo::update_sensor_value); 00047 00048 _event_queue.dispatch_forever(); 00049 } 00050 00051 private: 00052 /** Callback triggered when the ble initialization process has finished */ 00053 void on_init_complete(BLE::InitializationCompleteCallbackContext *params) { 00054 if (params->error != BLE_ERROR_NONE) { 00055 printf("Ble initialization failed."); 00056 return; 00057 } 00058 00059 print_mac_address(); 00060 00061 start_advertising(); 00062 } 00063 00064 void start_advertising() { 00065 /* Create advertising parameters and payload */ 00066 00067 ble::AdvertisingParameters adv_parameters( 00068 ble::advertising_type_t::CONNECTABLE_UNDIRECTED, 00069 ble::adv_interval_t(ble::millisecond_t(1000)) 00070 ); 00071 00072 _adv_data_builder.setFlags(); 00073 _adv_data_builder.setAppearance(ble::adv_data_appearance_t::GENERIC_HEART_RATE_SENSOR); 00074 _adv_data_builder.setLocalServiceList(mbed::make_Span(&_hr_uuid, 1)); 00075 _adv_data_builder.setName(DEVICE_NAME); 00076 00077 /* Setup advertising */ 00078 00079 ble_error_t error = _ble.gap().setAdvertisingParameters( 00080 ble::LEGACY_ADVERTISING_HANDLE, 00081 adv_parameters 00082 ); 00083 00084 if (error) { 00085 printf("_ble.gap().setAdvertisingParameters() failed\r\n"); 00086 return; 00087 } 00088 00089 error = _ble.gap().setAdvertisingPayload( 00090 ble::LEGACY_ADVERTISING_HANDLE, 00091 _adv_data_builder.getAdvertisingData() 00092 ); 00093 00094 if (error) { 00095 printf("_ble.gap().setAdvertisingPayload() failed\r\n"); 00096 return; 00097 } 00098 00099 /* Start advertising */ 00100 00101 error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE); 00102 00103 if (error) { 00104 printf("_ble.gap().startAdvertising() failed\r\n"); 00105 return; 00106 } 00107 } 00108 00109 void update_sensor_value() { 00110 if (_connected) { 00111 // Do blocking calls or whatever is necessary for sensor polling. 00112 // In our case, we simply update the HRM measurement. 00113 _hr_counter++; 00114 00115 // 100 <= HRM bps <=175 00116 if (_hr_counter == 175) { 00117 _hr_counter = 100; 00118 } 00119 00120 _hr_service.updateHeartRate(_hr_counter); 00121 } 00122 } 00123 00124 void blink(void) { 00125 _led1 = !_led1; 00126 } 00127 00128 private: 00129 /* Event handler */ 00130 00131 void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) { 00132 _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE); 00133 _connected = false; 00134 } 00135 00136 virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event) { 00137 if (event.getStatus() == BLE_ERROR_NONE) { 00138 _connected = true; 00139 } 00140 } 00141 00142 private: 00143 BLE &_ble; 00144 events::EventQueue &_event_queue; 00145 DigitalOut _led1; 00146 00147 bool _connected; 00148 00149 UUID _hr_uuid; 00150 00151 uint8_t _hr_counter; 00152 HeartRateService _hr_service; 00153 00154 uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE]; 00155 ble::AdvertisingDataBuilder _adv_data_builder; 00156 }; 00157 00158 /** Schedule processing of events from the BLE middleware in the event queue. */ 00159 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) { 00160 event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents)); 00161 } 00162 00163 int main() 00164 { 00165 BLE &ble = BLE::Instance(); 00166 ble.onEventsToProcess(schedule_ble_events); 00167 00168 HeartrateDemo demo(ble, event_queue); 00169 demo.start(); 00170 00171 return 0; 00172 } 00173
Generated on Thu Jul 14 2022 02:33:58 by 1.7.2