Created
November 2, 2020 10:22
-
-
Save ladislas/a93937dbaeca08ed60f04ce704a22721 to your computer and use it in GitHub Desktop.
Mbed BLE Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Leka - LekaOS | |
// Copyright 2020 APF France handicap | |
// SPDX-License-Identifier: Apache-2.0 | |
#include "events/mbed_events.h" | |
#include "ble/BLE.h" | |
#include "ble/Gap.h" | |
#include "ble/services/HeartRateService.h" | |
#include "pretty_printer.h" | |
const static char DEVICE_NAME[] = "Heartrate"; | |
static events::EventQueue event_queue(/* event count */ 32 * EVENTS_EVENT_SIZE); | |
class HeartrateDemo : ble::Gap::EventHandler | |
{ | |
public: | |
HeartrateDemo(BLE &ble, events::EventQueue &event_queue) | |
: _ble(ble), | |
_event_queue(event_queue), | |
// _led1(LED1, 1), | |
_connected(false), | |
_hr_uuid(GattService::UUID_HEART_RATE_SERVICE), | |
_hr_counter(100), | |
_hr_service(ble, _hr_counter, HeartRateService::LOCATION_FINGER), | |
_adv_data_builder(_adv_buffer) | |
{ | |
} | |
void start() | |
{ | |
_ble.gap().setEventHandler(this); | |
_ble.init(this, &HeartrateDemo::on_init_complete); | |
// _event_queue.call_every(500ms, this, &HeartrateDemo::blink); | |
_event_queue.call_every(1000ms, this, &HeartrateDemo::update_sensor_value); | |
// _event_queue.dispatch_forever(); | |
// printf("dispatch_forever\n"); | |
} | |
private: | |
/** Callback triggered when the ble initialization process has finished */ | |
void on_init_complete(BLE::InitializationCompleteCallbackContext *params) | |
{ | |
if (params->error != BLE_ERROR_NONE) { | |
printf("Ble initialization failed."); | |
return; | |
} | |
print_mac_address(); | |
start_advertising(); | |
} | |
void start_advertising() | |
{ | |
/* Create advertising parameters and payload */ | |
ble::AdvertisingParameters adv_parameters(ble::advertising_type_t::CONNECTABLE_UNDIRECTED, | |
ble::adv_interval_t(ble::millisecond_t(1000))); | |
_adv_data_builder.setFlags(); | |
_adv_data_builder.setAppearance(ble::adv_data_appearance_t::GENERIC_HEART_RATE_SENSOR); | |
_adv_data_builder.setLocalServiceList(mbed::make_Span(&_hr_uuid, 1)); | |
_adv_data_builder.setName(DEVICE_NAME); | |
/* Setup advertising */ | |
ble_error_t error = _ble.gap().setAdvertisingParameters(ble::LEGACY_ADVERTISING_HANDLE, adv_parameters); | |
if (error) { | |
printf("_ble.gap().setAdvertisingParameters() failed\r\n"); | |
return; | |
} | |
error = | |
_ble.gap().setAdvertisingPayload(ble::LEGACY_ADVERTISING_HANDLE, _adv_data_builder.getAdvertisingData()); | |
if (error) { | |
printf("_ble.gap().setAdvertisingPayload() failed\r\n"); | |
return; | |
} | |
/* Start advertising */ | |
error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE); | |
if (error) { | |
printf("_ble.gap().startAdvertising() failed\r\n"); | |
return; | |
} | |
} | |
void update_sensor_value() | |
{ | |
if (_connected) { | |
// Do blocking calls or whatever is necessary for sensor polling. | |
// In our case, we simply update the HRM measurement. | |
_hr_counter++; | |
// 100 <= HRM bps <=175 | |
if (_hr_counter == 175) { | |
_hr_counter = 100; | |
} | |
_hr_service.updateHeartRate(_hr_counter); | |
} | |
} | |
// void blink(void) { _led1 = !_led1; } | |
private: | |
/* Event handler */ | |
void onDisconnectionComplete(const ble::DisconnectionCompleteEvent &) | |
{ | |
_ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE); | |
_connected = false; | |
} | |
virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event) | |
{ | |
if (event.getStatus() == BLE_ERROR_NONE) { | |
_connected = true; | |
} | |
} | |
private: | |
BLE &_ble; | |
events::EventQueue &_event_queue; | |
// DigitalOut _led1; | |
bool _connected; | |
UUID _hr_uuid; | |
uint8_t _hr_counter; | |
HeartRateService _hr_service; | |
uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE]; | |
ble::AdvertisingDataBuilder _adv_data_builder; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Leka - LekaOS | |
// Copyright 2020 APF France handicap | |
// SPDX-License-Identifier: Apache-2.0 | |
#include <mbed.h> | |
#include "LKBLE.h" | |
Thread thread_ble_event_queue; | |
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) | |
{ | |
event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents)); | |
} | |
int main() | |
{ | |
BLE &ble = BLE::Instance(); | |
ble.onEventsToProcess(schedule_ble_events); | |
HeartrateDemo demo(ble, event_queue); | |
demo.start(); | |
thread_ble_event_queue.start(callback(&event_queue, &EventQueue::dispatch_forever)); | |
while (true) { | |
rtos::ThisThread::sleep_for(5s); | |
} | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Leka - LekaOS | |
// Copyright 2020 APF France handicap | |
// SPDX-License-Identifier: Apache-2.0 | |
#ifndef _LEKA_OS_LIB_BLE_PRETTY_PRINTER_H_ | |
#define _LEKA_OS_LIB_BLE_PRETTY_PRINTER_H_ | |
#include "ble/BLE.h" | |
inline void print_error(ble_error_t error, const char *msg) | |
{ | |
printf("%s: ", msg); | |
switch (error) { | |
case BLE_ERROR_NONE: | |
printf("BLE_ERROR_NONE: No error"); | |
break; | |
case BLE_ERROR_BUFFER_OVERFLOW: | |
printf( | |
"BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted"); | |
break; | |
case BLE_ERROR_NOT_IMPLEMENTED: | |
printf( | |
"BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the " | |
"target HW"); | |
break; | |
case BLE_ERROR_PARAM_OUT_OF_RANGE: | |
printf("BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range"); | |
break; | |
case BLE_ERROR_INVALID_PARAM: | |
printf("BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid"); | |
break; | |
case BLE_STACK_BUSY: | |
printf("BLE_STACK_BUSY: The stack is busy"); | |
break; | |
case BLE_ERROR_INVALID_STATE: | |
printf("BLE_ERROR_INVALID_STATE: Invalid state"); | |
break; | |
case BLE_ERROR_NO_MEM: | |
printf("BLE_ERROR_NO_MEM: Out of Memory"); | |
break; | |
case BLE_ERROR_OPERATION_NOT_PERMITTED: | |
printf("BLE_ERROR_OPERATION_NOT_PERMITTED"); | |
break; | |
case BLE_ERROR_INITIALIZATION_INCOMPLETE: | |
printf("BLE_ERROR_INITIALIZATION_INCOMPLETE"); | |
break; | |
case BLE_ERROR_ALREADY_INITIALIZED: | |
printf("BLE_ERROR_ALREADY_INITIALIZED"); | |
break; | |
case BLE_ERROR_UNSPECIFIED: | |
printf("BLE_ERROR_UNSPECIFIED: Unknown error"); | |
break; | |
case BLE_ERROR_INTERNAL_STACK_FAILURE: | |
printf("BLE_ERROR_INTERNAL_STACK_FAILURE: internal stack failure"); | |
break; | |
case BLE_ERROR_NOT_FOUND: | |
printf("BLE_ERROR_NOT_FOUND"); | |
break; | |
default: | |
printf("Unknown error"); | |
} | |
printf("\r\n"); | |
} | |
/** print device address to the terminal */ | |
inline void print_address(const ble::address_t &addr) | |
{ | |
printf("%02x:%02x:%02x:%02x:%02x:%02x\r\n", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); | |
} | |
inline void print_mac_address() | |
{ | |
/* Print out device MAC address to the console*/ | |
ble::own_address_type_t addr_type; | |
ble::address_t address; | |
BLE::Instance().gap().getAddress(addr_type, address); | |
printf("DEVICE MAC ADDRESS: "); | |
print_address(address); | |
} | |
inline const char *phy_to_string(ble::phy_t phy) | |
{ | |
switch (phy.value()) { | |
case ble::phy_t::LE_1M: | |
return "LE 1M"; | |
case ble::phy_t::LE_2M: | |
return "LE 2M"; | |
case ble::phy_t::LE_CODED: | |
return "LE coded"; | |
default: | |
return "invalid PHY"; | |
} | |
} | |
#endif // _LEKA_OS_LIB_BLE_PRETTY_PRINTER_H_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment