Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
SimpleBLE.h
- Committer:
- janjongboom
- Date:
- 2016-05-09
- Revision:
- 0:0c885d287f5a
File content as of revision 0:0c885d287f5a:
/**
* Because BLE_API is too hard
*/
#include <string>
#include <vector>
#include <map>
#include "ble/BLE.h"
using namespace std;
template <class T>
class ReadOnlyCharacteristic {
public:
ReadOnlyCharacteristic(BLE* aBle, const uint16_t aCharUuid, bool enableNotify, T defaultValue) :
ble(aBle)
{
state = new ReadOnlyGattCharacteristic<T>(aCharUuid, new T(defaultValue), enableNotify ?
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
}
~ReadOnlyCharacteristic() {
// @todo clear defaultValue
if (state) {
free(state);
}
}
void update(T newValue) {
ble->gattServer().write(state->getValueHandle(), (uint8_t *)&newValue, sizeof(T));
}
ReadOnlyGattCharacteristic<T>* getChar(void) {
return state;
}
private:
BLE* ble;
ReadOnlyGattCharacteristic<T>* state;
};
template <class T>
class ReadWriteCharacteristic {
public:
ReadWriteCharacteristic(BLE* aBle, const uint16_t aCharUuid, bool enableNotify, T defaultValue) :
ble(aBle)
{
state = new ReadWriteGattCharacteristic<T>(aCharUuid, new T(defaultValue), enableNotify ?
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
}
~ReadWriteCharacteristic() {
// @todo clear defaultValue
if (state) {
free(state);
}
}
void update(T newValue) {
ble->gattServer().write(state->getValueHandle(), (uint8_t *)&newValue, sizeof(T));
}
ReadWriteGattCharacteristic<T>* getChar(void) {
return state;
}
private:
BLE* ble;
ReadWriteGattCharacteristic<T>* state;
};
class SimpleBLE {
public:
SimpleBLE(const char* aName, uint16_t aInterval = 1000) : name(aName), interval(aInterval) {
ble = &BLE::Instance();
}
~SimpleBLE() {}
// Start up the BLE service and just run with it!
void spin() {
ble->init(this, &SimpleBLE::bleInitComplete);
/* SpinWait for initialization to complete. This is necessary because the
* BLE object is used in the main loop below. */
while (ble->hasInitialized() == false) { /* spin loop */ }
while (true) {
ble->waitForEvent();
}
}
template <typename T>
ReadOnlyCharacteristic<T>* createReadOnlyChar(uint16_t serviceUuid,
uint16_t charUuid,
bool enableNotify,
T defaultValue) {
ReadOnlyCharacteristic<T>* c = new ReadOnlyCharacteristic<T>(ble, charUuid, enableNotify, defaultValue);
if (services.count(serviceUuid) == 0) {
services[serviceUuid] = new vector<GattCharacteristic*>();
}
services[serviceUuid]->push_back(c->getChar());
return c;
}
template <typename T>
ReadWriteCharacteristic<T>* createReadWriteChar(uint16_t serviceUuid,
uint16_t charUuid,
bool enableNotify,
T defaultValue,
void(*callback)(const uint8_t*, size_t)) {
ReadWriteCharacteristic<T>* c = new ReadWriteCharacteristic<T>(ble, charUuid, enableNotify, defaultValue);
if (services.count(serviceUuid) == 0) {
services[serviceUuid] = new vector<GattCharacteristic*>();
}
services[serviceUuid]->push_back(c->getChar());
writeCallbacks[c->getChar()] = (void*)callback;
return c;
}
void onDisconnection(Gap::DisconnectionEventCallback_t callback) {
ble->gap().onDisconnection(callback);
}
void onConnection(Gap::ConnectionEventCallback_t callback) {
ble->gap().onConnection(callback);
}
void onDataWrittenCallback(const GattWriteCallbackParams *params) {
// see if we know for which char this message is...
typedef std::map<GattCharacteristic*, void* >::iterator it_type;
for(it_type it = writeCallbacks.begin(); it != writeCallbacks.end(); it++) {
if (it->first->getValueHandle() == params->handle) {
void(*func)(const uint8_t*, size_t) = (void(*)(const uint8_t*, size_t))it->second;
func(params->data, params->len);
}
}
// handle corresponds to the characteristic being written
// then we can read data to get a buffer of the actual data
// if ((params->handle == ledServicePtr->getValueHandle()) && (params->len == 1)) {
// // When writing 1 -> turn LED on, 0 -> turn LED off
// char val = params->data[0];
// actuatedLED = val == 1 ? LED_ON : LED_OFF;
// }
}
private:
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
printf("bleInitComplete\r\n");
BLE& ble = params->ble;
ble_error_t error = params->error;
if (error != BLE_ERROR_NONE) {
printf("BLE Init error %d\r\n", error);
return;
}
/* Ensure that it is the default instance of BLE */
if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
return;
}
ble.gattServer().onDataWritten(this, &SimpleBLE::onDataWrittenCallback);
// let's add some services yo (why is there no 'auto' in mbed?)
uint16_t uuid16_list[services.size()];
size_t counter = 0;
typedef std::map<std::uint16_t, vector<GattCharacteristic*>* >::iterator it_type;
for(it_type it = services.begin(); it != services.end(); it++) {
printf("Creating service 0x%x\n", it->first);
uuid16_list[counter++] = it->first;
GattCharacteristic* charTable[it->second->size()];
for (size_t git = 0; git < it->second->size(); git++) {
charTable[git] = it->second->at(git);
}
GattService service(it->first, charTable, it->second->size());
ble.gattServer().addService(service);
}
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)name, strlen(name));
ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.gap().setAdvertisingInterval(interval);
ble.gap().startAdvertising();
printf("Started advertising\n");
}
BLE* ble;
const char* name;
uint16_t interval;
map<uint16_t, vector<GattCharacteristic*>* > services;
map<GattCharacteristic*, void*> writeCallbacks;
};