Skip to content

Add example exercising the GattClient API. #111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BLE_GattClient/.mbed
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ROOT=.
TARGET=NRF52_DK
231 changes: 231 additions & 0 deletions BLE_GattClient/BLEProcess.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef GATT_EXAMPLE_BLE_PROCESS_H_
#define GATT_EXAMPLE_BLE_PROCESS_H_

#include <stdint.h>
#include <stdio.h>

#include "events/Eventqueue.h"
#include "platform/Callback.h"
#include "platform/NonCopyable.h"

#include "ble/BLE.h"
#include "ble/Gap.h"
#include "ble/GapAdvertisingParams.h"
#include "ble/GapAdvertisingData.h"
#include "ble/FunctionPointerWithContext.h"

/**
* Handle initialization and shutdown of the BLE Instance.
*
* Setup advertising payload and manage advertising state.
* Delegate to GattClientProcess once the connection is established.
*/
class BLEProcess : private mbed::NonCopyable<BLEProcess> {
public:
/**
* Construct a BLEProcess from an event queue and a ble interface.
*
* Call start() to initiate ble processing.
*/
BLEProcess(events::EventQueue &event_queue, BLE &ble_interface) :
_event_queue(event_queue),
_ble_interface(ble_interface),
_post_init_cb() {
}

~BLEProcess()
{
stop();
}

/**
* Initialize the ble interface, configure it and start advertising.
*/
bool start()
{
printf("Ble process started.\r\n");

if (_ble_interface.hasInitialized()) {
printf("Error: the ble instance has already been initialized.\r\n");
return false;
}

_ble_interface.onEventsToProcess(
makeFunctionPointer(this, &BLEProcess::schedule_ble_events)
);

ble_error_t error = _ble_interface.init(
this, &BLEProcess::when_init_complete
);

if (error) {
printf("Error: %u returned by BLE::init.\r\n", error);
return false;
}

return true;
}

/**
* Close existing connections and stop the process.
*/
void stop()
{
if (_ble_interface.hasInitialized()) {
_ble_interface.shutdown();
printf("Ble process stopped.");
}
}

/**
* Subscription to the ble interface initialization event.
*
* @param[in] cb The callback object that will be called when the ble
* interface is initialized.
*/
void on_init(mbed::Callback<void(BLE&, events::EventQueue&)> cb)
{
_post_init_cb = cb;
}

private:
/**
* Sets up adverting payload and start advertising.
*
* This function is invoked when the ble interface is initialized.
*/
void when_init_complete(BLE::InitializationCompleteCallbackContext *event)
{
if (event->error) {
printf("Error %u during the initialization\r\n", event->error);
return;
}
printf("Ble instance initialized\r\n");

Gap &gap = _ble_interface.gap();
ble_error_t error = gap.setAdvertisingPayload(make_advertising_data());
if (error) {
printf("Error %u during gap.setAdvertisingPayload\r\n", error);
return;
}

gap.setAdvertisingParams(make_advertising_params());

gap.onConnection(this, &BLEProcess::when_connection);
gap.onDisconnection(this, &BLEProcess::when_disconnection);

start_advertising();

if (_post_init_cb) {
_post_init_cb(_ble_interface, _event_queue);
}
}

/**
* Start the gatt client process when a connection event is received.
*/
void when_connection(const Gap::ConnectionCallbackParams_t *connection_event)
{
printf("Connected.\r\n");
}

/**
* Stop the gatt client process when the device is disconnected then restart
* advertising.
*/
void when_disconnection(const Gap::DisconnectionCallbackParams_t *event)
{
printf("Disconnected.\r\n");
start_advertising();
}

/**
* Setup the advertising parameters.
*/
void setup_advertising()
{
Gap &gap = _ble_interface.gap();
gap.setAdvertisingPayload(make_advertising_data());
gap.setAdvertisingParams(make_advertising_params());
}

/**
* Start the advertising process; it ends when a device connects.
*/
void start_advertising()
{
ble_error_t error = _ble_interface.gap().startAdvertising();
if (error) {
printf("Error %u during gap.startAdvertising.\r\n", error);
} else {
printf("Advertising started.\r\n");
}
}

/**
* Schedule processing of events from the BLE middleware in the event queue.
*/
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *event)
{
_event_queue.call(mbed::callback(&event->ble, &BLE::processEvents));
}

/**
* Build data advertised by the BLE interface.
*/
static GapAdvertisingData make_advertising_data(void)
{
static const uint8_t device_name[] = "GattClient";
GapAdvertisingData advertising_data;

// add advertising flags
advertising_data.addFlags(
GapAdvertisingData::LE_GENERAL_DISCOVERABLE |
GapAdvertisingData::BREDR_NOT_SUPPORTED
);

// add device name
advertising_data.addData(
GapAdvertisingData::COMPLETE_LOCAL_NAME,
device_name,
sizeof(device_name)
);

return advertising_data;
}

/**
* Build advertising parameters used by the BLE interface.
*/
static GapAdvertisingParams make_advertising_params(void)
{
return GapAdvertisingParams(
/* type */ GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED,
/* interval */ GapAdvertisingParams::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(500),
/* timeout */ 0
);
}

events::EventQueue &_event_queue;
BLE &_ble_interface;
mbed::Callback<void(BLE&, events::EventQueue&)> _post_init_cb;
};


#endif /* GATT_EXAMPLE_BLE_PROCESS_H_ */
33 changes: 33 additions & 0 deletions BLE_GattClient/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# BLE Gatt Client example

This application demonstrates detailed uses of the GattClient APIs.

When the application is started it advertises itself to its environment with the
device name `GattClient`. Once you have connected to the device with your mobile
phone, the application starts a discovery of the GATT server exposed by your
mobile phone.

After the discovery, this application reads the value of the characteristics
discovered and subscribes to the characteristics emitting notifications or
indications.

The device prints the value of any indication or notification received from the
mobile phone.

# Running the application

## Requirements

You may use a generic BLE scanners:

- [nRF Master Control Panel](https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp) for Android.

- [LightBlue](https://itunes.apple.com/gb/app/lightblue-bluetooth-low-energy/id557428110?mt=8) for iPhone.

Hardware requirements are in the [main readme](https://github.com/ARMmbed/mbed-os-example-ble/blob/master/README.md).

## Building instructions

Building instructions for all samples are in the [main readme](https://github.com/ARMmbed/mbed-os-example-ble/blob/master/README.md).


Loading