SimpleBLE prototype

Dependencies:   BLE_API mbed nRF51822

Committer:
janjongboom
Date:
Wed May 11 08:58:49 2016 +0000
Revision:
1:acae50e4bc88
Parent:
0:0c885d287f5a
LightSensor

Who changed what in which revision?

UserRevisionLine numberNew contents of line
janjongboom 0:0c885d287f5a 1 /**
janjongboom 0:0c885d287f5a 2 * Because BLE_API is too hard
janjongboom 0:0c885d287f5a 3 */
janjongboom 0:0c885d287f5a 4 #include <string>
janjongboom 0:0c885d287f5a 5 #include <vector>
janjongboom 0:0c885d287f5a 6 #include <map>
janjongboom 0:0c885d287f5a 7 #include "ble/BLE.h"
janjongboom 0:0c885d287f5a 8
janjongboom 0:0c885d287f5a 9 using namespace std;
janjongboom 0:0c885d287f5a 10
janjongboom 0:0c885d287f5a 11 template <class T>
janjongboom 0:0c885d287f5a 12 class ReadOnlyCharacteristic {
janjongboom 0:0c885d287f5a 13 public:
janjongboom 0:0c885d287f5a 14 ReadOnlyCharacteristic(BLE* aBle, const uint16_t aCharUuid, bool enableNotify, T defaultValue) :
janjongboom 0:0c885d287f5a 15 ble(aBle)
janjongboom 0:0c885d287f5a 16 {
janjongboom 0:0c885d287f5a 17 state = new ReadOnlyGattCharacteristic<T>(aCharUuid, new T(defaultValue), enableNotify ?
janjongboom 0:0c885d287f5a 18 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:0c885d287f5a 19 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
janjongboom 0:0c885d287f5a 20 }
janjongboom 0:0c885d287f5a 21
janjongboom 0:0c885d287f5a 22 ~ReadOnlyCharacteristic() {
janjongboom 0:0c885d287f5a 23 // @todo clear defaultValue
janjongboom 0:0c885d287f5a 24 if (state) {
janjongboom 0:0c885d287f5a 25 free(state);
janjongboom 0:0c885d287f5a 26 }
janjongboom 0:0c885d287f5a 27 }
janjongboom 0:0c885d287f5a 28
janjongboom 0:0c885d287f5a 29 void update(T newValue) {
janjongboom 0:0c885d287f5a 30 ble->gattServer().write(state->getValueHandle(), (uint8_t *)&newValue, sizeof(T));
janjongboom 0:0c885d287f5a 31 }
janjongboom 0:0c885d287f5a 32
janjongboom 0:0c885d287f5a 33 ReadOnlyGattCharacteristic<T>* getChar(void) {
janjongboom 0:0c885d287f5a 34 return state;
janjongboom 0:0c885d287f5a 35 }
janjongboom 0:0c885d287f5a 36
janjongboom 0:0c885d287f5a 37 private:
janjongboom 0:0c885d287f5a 38 BLE* ble;
janjongboom 0:0c885d287f5a 39 ReadOnlyGattCharacteristic<T>* state;
janjongboom 0:0c885d287f5a 40 };
janjongboom 0:0c885d287f5a 41
janjongboom 0:0c885d287f5a 42 template <class T>
janjongboom 0:0c885d287f5a 43 class ReadWriteCharacteristic {
janjongboom 0:0c885d287f5a 44 public:
janjongboom 0:0c885d287f5a 45 ReadWriteCharacteristic(BLE* aBle, const uint16_t aCharUuid, bool enableNotify, T defaultValue) :
janjongboom 0:0c885d287f5a 46 ble(aBle)
janjongboom 0:0c885d287f5a 47 {
janjongboom 0:0c885d287f5a 48 state = new ReadWriteGattCharacteristic<T>(aCharUuid, new T(defaultValue), enableNotify ?
janjongboom 0:0c885d287f5a 49 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY :
janjongboom 0:0c885d287f5a 50 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
janjongboom 0:0c885d287f5a 51 }
janjongboom 0:0c885d287f5a 52
janjongboom 0:0c885d287f5a 53 ~ReadWriteCharacteristic() {
janjongboom 0:0c885d287f5a 54 // @todo clear defaultValue
janjongboom 0:0c885d287f5a 55 if (state) {
janjongboom 0:0c885d287f5a 56 free(state);
janjongboom 0:0c885d287f5a 57 }
janjongboom 0:0c885d287f5a 58 }
janjongboom 0:0c885d287f5a 59
janjongboom 0:0c885d287f5a 60 void update(T newValue) {
janjongboom 0:0c885d287f5a 61 ble->gattServer().write(state->getValueHandle(), (uint8_t *)&newValue, sizeof(T));
janjongboom 0:0c885d287f5a 62 }
janjongboom 0:0c885d287f5a 63
janjongboom 0:0c885d287f5a 64 ReadWriteGattCharacteristic<T>* getChar(void) {
janjongboom 0:0c885d287f5a 65 return state;
janjongboom 0:0c885d287f5a 66 }
janjongboom 0:0c885d287f5a 67
janjongboom 0:0c885d287f5a 68 private:
janjongboom 0:0c885d287f5a 69 BLE* ble;
janjongboom 0:0c885d287f5a 70 ReadWriteGattCharacteristic<T>* state;
janjongboom 0:0c885d287f5a 71 };
janjongboom 0:0c885d287f5a 72
janjongboom 0:0c885d287f5a 73 class SimpleBLE {
janjongboom 0:0c885d287f5a 74 public:
janjongboom 0:0c885d287f5a 75 SimpleBLE(const char* aName, uint16_t aInterval = 1000) : name(aName), interval(aInterval) {
janjongboom 0:0c885d287f5a 76 ble = &BLE::Instance();
janjongboom 0:0c885d287f5a 77 }
janjongboom 0:0c885d287f5a 78 ~SimpleBLE() {}
janjongboom 0:0c885d287f5a 79
janjongboom 0:0c885d287f5a 80 // Start up the BLE service and just run with it!
janjongboom 0:0c885d287f5a 81 void spin() {
janjongboom 0:0c885d287f5a 82 ble->init(this, &SimpleBLE::bleInitComplete);
janjongboom 0:0c885d287f5a 83
janjongboom 0:0c885d287f5a 84 /* SpinWait for initialization to complete. This is necessary because the
janjongboom 0:0c885d287f5a 85 * BLE object is used in the main loop below. */
janjongboom 0:0c885d287f5a 86 while (ble->hasInitialized() == false) { /* spin loop */ }
janjongboom 0:0c885d287f5a 87
janjongboom 0:0c885d287f5a 88 while (true) {
janjongboom 0:0c885d287f5a 89 ble->waitForEvent();
janjongboom 0:0c885d287f5a 90 }
janjongboom 0:0c885d287f5a 91 }
janjongboom 0:0c885d287f5a 92
janjongboom 0:0c885d287f5a 93 template <typename T>
janjongboom 0:0c885d287f5a 94 ReadOnlyCharacteristic<T>* createReadOnlyChar(uint16_t serviceUuid,
janjongboom 0:0c885d287f5a 95 uint16_t charUuid,
janjongboom 0:0c885d287f5a 96 bool enableNotify,
janjongboom 0:0c885d287f5a 97 T defaultValue) {
janjongboom 0:0c885d287f5a 98 ReadOnlyCharacteristic<T>* c = new ReadOnlyCharacteristic<T>(ble, charUuid, enableNotify, defaultValue);
janjongboom 0:0c885d287f5a 99
janjongboom 0:0c885d287f5a 100 if (services.count(serviceUuid) == 0) {
janjongboom 0:0c885d287f5a 101 services[serviceUuid] = new vector<GattCharacteristic*>();
janjongboom 0:0c885d287f5a 102 }
janjongboom 0:0c885d287f5a 103
janjongboom 0:0c885d287f5a 104 services[serviceUuid]->push_back(c->getChar());
janjongboom 0:0c885d287f5a 105
janjongboom 0:0c885d287f5a 106 return c;
janjongboom 0:0c885d287f5a 107 }
janjongboom 0:0c885d287f5a 108
janjongboom 0:0c885d287f5a 109 template <typename T>
janjongboom 0:0c885d287f5a 110 ReadWriteCharacteristic<T>* createReadWriteChar(uint16_t serviceUuid,
janjongboom 0:0c885d287f5a 111 uint16_t charUuid,
janjongboom 0:0c885d287f5a 112 bool enableNotify,
janjongboom 0:0c885d287f5a 113 T defaultValue,
janjongboom 0:0c885d287f5a 114 void(*callback)(const uint8_t*, size_t)) {
janjongboom 0:0c885d287f5a 115 ReadWriteCharacteristic<T>* c = new ReadWriteCharacteristic<T>(ble, charUuid, enableNotify, defaultValue);
janjongboom 0:0c885d287f5a 116
janjongboom 0:0c885d287f5a 117 if (services.count(serviceUuid) == 0) {
janjongboom 0:0c885d287f5a 118 services[serviceUuid] = new vector<GattCharacteristic*>();
janjongboom 0:0c885d287f5a 119 }
janjongboom 0:0c885d287f5a 120
janjongboom 0:0c885d287f5a 121 services[serviceUuid]->push_back(c->getChar());
janjongboom 0:0c885d287f5a 122 writeCallbacks[c->getChar()] = (void*)callback;
janjongboom 0:0c885d287f5a 123
janjongboom 0:0c885d287f5a 124 return c;
janjongboom 0:0c885d287f5a 125 }
janjongboom 0:0c885d287f5a 126
janjongboom 0:0c885d287f5a 127 void onDisconnection(Gap::DisconnectionEventCallback_t callback) {
janjongboom 0:0c885d287f5a 128 ble->gap().onDisconnection(callback);
janjongboom 0:0c885d287f5a 129 }
janjongboom 0:0c885d287f5a 130
janjongboom 0:0c885d287f5a 131 void onConnection(Gap::ConnectionEventCallback_t callback) {
janjongboom 0:0c885d287f5a 132 ble->gap().onConnection(callback);
janjongboom 0:0c885d287f5a 133 }
janjongboom 0:0c885d287f5a 134
janjongboom 0:0c885d287f5a 135 void onDataWrittenCallback(const GattWriteCallbackParams *params) {
janjongboom 0:0c885d287f5a 136 // see if we know for which char this message is...
janjongboom 0:0c885d287f5a 137 typedef std::map<GattCharacteristic*, void* >::iterator it_type;
janjongboom 0:0c885d287f5a 138 for(it_type it = writeCallbacks.begin(); it != writeCallbacks.end(); it++) {
janjongboom 0:0c885d287f5a 139 if (it->first->getValueHandle() == params->handle) {
janjongboom 0:0c885d287f5a 140 void(*func)(const uint8_t*, size_t) = (void(*)(const uint8_t*, size_t))it->second;
janjongboom 0:0c885d287f5a 141
janjongboom 0:0c885d287f5a 142 func(params->data, params->len);
janjongboom 0:0c885d287f5a 143 }
janjongboom 0:0c885d287f5a 144 }
janjongboom 0:0c885d287f5a 145
janjongboom 0:0c885d287f5a 146 // handle corresponds to the characteristic being written
janjongboom 0:0c885d287f5a 147 // then we can read data to get a buffer of the actual data
janjongboom 0:0c885d287f5a 148 // if ((params->handle == ledServicePtr->getValueHandle()) && (params->len == 1)) {
janjongboom 0:0c885d287f5a 149 // // When writing 1 -> turn LED on, 0 -> turn LED off
janjongboom 0:0c885d287f5a 150 // char val = params->data[0];
janjongboom 0:0c885d287f5a 151 // actuatedLED = val == 1 ? LED_ON : LED_OFF;
janjongboom 0:0c885d287f5a 152 // }
janjongboom 0:0c885d287f5a 153 }
janjongboom 0:0c885d287f5a 154
janjongboom 0:0c885d287f5a 155
janjongboom 0:0c885d287f5a 156 private:
janjongboom 0:0c885d287f5a 157 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
janjongboom 0:0c885d287f5a 158 {
janjongboom 0:0c885d287f5a 159 printf("bleInitComplete\r\n");
janjongboom 0:0c885d287f5a 160
janjongboom 0:0c885d287f5a 161 BLE& ble = params->ble;
janjongboom 0:0c885d287f5a 162 ble_error_t error = params->error;
janjongboom 0:0c885d287f5a 163
janjongboom 0:0c885d287f5a 164 if (error != BLE_ERROR_NONE) {
janjongboom 0:0c885d287f5a 165 printf("BLE Init error %d\r\n", error);
janjongboom 0:0c885d287f5a 166 return;
janjongboom 0:0c885d287f5a 167 }
janjongboom 0:0c885d287f5a 168
janjongboom 0:0c885d287f5a 169 /* Ensure that it is the default instance of BLE */
janjongboom 0:0c885d287f5a 170 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
janjongboom 0:0c885d287f5a 171 return;
janjongboom 0:0c885d287f5a 172 }
janjongboom 0:0c885d287f5a 173
janjongboom 0:0c885d287f5a 174 ble.gattServer().onDataWritten(this, &SimpleBLE::onDataWrittenCallback);
janjongboom 0:0c885d287f5a 175
janjongboom 0:0c885d287f5a 176 // let's add some services yo (why is there no 'auto' in mbed?)
janjongboom 0:0c885d287f5a 177 uint16_t uuid16_list[services.size()];
janjongboom 0:0c885d287f5a 178
janjongboom 0:0c885d287f5a 179 size_t counter = 0;
janjongboom 0:0c885d287f5a 180 typedef std::map<std::uint16_t, vector<GattCharacteristic*>* >::iterator it_type;
janjongboom 0:0c885d287f5a 181 for(it_type it = services.begin(); it != services.end(); it++) {
janjongboom 0:0c885d287f5a 182 printf("Creating service 0x%x\n", it->first);
janjongboom 0:0c885d287f5a 183
janjongboom 0:0c885d287f5a 184 uuid16_list[counter++] = it->first;
janjongboom 0:0c885d287f5a 185
janjongboom 0:0c885d287f5a 186 GattCharacteristic* charTable[it->second->size()];
janjongboom 0:0c885d287f5a 187 for (size_t git = 0; git < it->second->size(); git++) {
janjongboom 0:0c885d287f5a 188 charTable[git] = it->second->at(git);
janjongboom 0:0c885d287f5a 189 }
janjongboom 0:0c885d287f5a 190 GattService service(it->first, charTable, it->second->size());
janjongboom 0:0c885d287f5a 191 ble.gattServer().addService(service);
janjongboom 0:0c885d287f5a 192 }
janjongboom 0:0c885d287f5a 193
janjongboom 0:0c885d287f5a 194 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
janjongboom 0:0c885d287f5a 195 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
janjongboom 0:0c885d287f5a 196 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)name, strlen(name));
janjongboom 0:0c885d287f5a 197 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
janjongboom 0:0c885d287f5a 198 ble.gap().setAdvertisingInterval(interval);
janjongboom 0:0c885d287f5a 199 ble.gap().startAdvertising();
janjongboom 0:0c885d287f5a 200
janjongboom 0:0c885d287f5a 201 printf("Started advertising\n");
janjongboom 0:0c885d287f5a 202 }
janjongboom 0:0c885d287f5a 203
janjongboom 0:0c885d287f5a 204 BLE* ble;
janjongboom 0:0c885d287f5a 205 const char* name;
janjongboom 0:0c885d287f5a 206 uint16_t interval;
janjongboom 0:0c885d287f5a 207 map<uint16_t, vector<GattCharacteristic*>* > services;
janjongboom 0:0c885d287f5a 208 map<GattCharacteristic*, void*> writeCallbacks;
janjongboom 0:0c885d287f5a 209 };
janjongboom 0:0c885d287f5a 210