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
Diff: SimpleBLE.h
- Revision:
- 0:0c885d287f5a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SimpleBLE.h Mon May 09 13:19:09 2016 +0000
@@ -0,0 +1,210 @@
+/**
+ * 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;
+};
+