Update for latest nRF51822 code changes.

Dependencies:   BLE_API nRF51822

Fork of Puck by Nordic Pucks

Committer:
stiaje
Date:
Sun Mar 01 18:32:49 2015 +0000
Revision:
18:4c95a470d778
Merge documentation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
stiaje 18:4c95a470d778 1 #ifndef __PUCK_HPP__
stiaje 18:4c95a470d778 2 #define __PUCK_HPP__
stiaje 18:4c95a470d778 3
stiaje 18:4c95a470d778 4 #include "BLEDevice.h"
stiaje 18:4c95a470d778 5 #include <vector>
stiaje 18:4c95a470d778 6 #include "Log.h"
stiaje 18:4c95a470d778 7
stiaje 18:4c95a470d778 8 enum PuckState {
stiaje 18:4c95a470d778 9 CONNECTING,
stiaje 18:4c95a470d778 10 CONNECTED,
stiaje 18:4c95a470d778 11 ADVERTISING,
stiaje 18:4c95a470d778 12 DISCONNECTED
stiaje 18:4c95a470d778 13 };
stiaje 18:4c95a470d778 14
stiaje 18:4c95a470d778 15 const UUID stringToUUID(const char* str);
stiaje 18:4c95a470d778 16
stiaje 18:4c95a470d778 17 typedef void (*CharacteristicWriteCallback)(uint8_t* value);
stiaje 18:4c95a470d778 18
stiaje 18:4c95a470d778 19 typedef struct {
stiaje 18:4c95a470d778 20 const UUID* uuid;
stiaje 18:4c95a470d778 21 std::vector<CharacteristicWriteCallback>* callbacks;
stiaje 18:4c95a470d778 22 } CharacteristicWriteCallbacks;
stiaje 18:4c95a470d778 23
stiaje 18:4c95a470d778 24 /**
stiaje 18:4c95a470d778 25 * @brief A library for easier setup and prototyping of IoT devices (pucks), by collecting everything that is common for all pucks in one place.
stiaje 18:4c95a470d778 26 *
stiaje 18:4c95a470d778 27 */
stiaje 18:4c95a470d778 28 class Puck {
stiaje 18:4c95a470d778 29 private:
stiaje 18:4c95a470d778 30 Puck() {}
stiaje 18:4c95a470d778 31 Puck(const Puck&);
stiaje 18:4c95a470d778 32 Puck& operator=(const Puck&);
stiaje 18:4c95a470d778 33
stiaje 18:4c95a470d778 34 BLEDevice ble;
stiaje 18:4c95a470d778 35 uint8_t beaconPayload[25];
stiaje 18:4c95a470d778 36 PuckState state;
stiaje 18:4c95a470d778 37 std::vector<GattService*> services;
stiaje 18:4c95a470d778 38 std::vector<GattCharacteristic*> characteristics;
stiaje 18:4c95a470d778 39 std::vector<CharacteristicWriteCallbacks*> writeCallbacks;
stiaje 18:4c95a470d778 40 std::vector<CharacteristicWriteCallback> pendingCallbackStack;
stiaje 18:4c95a470d778 41 std::vector<uint8_t*> pendingCallbackParameterStack;
stiaje 18:4c95a470d778 42
stiaje 18:4c95a470d778 43 GattCharacteristic **previousCharacteristics;
stiaje 18:4c95a470d778 44
stiaje 18:4c95a470d778 45 public:
stiaje 18:4c95a470d778 46 static Puck &getPuck();
stiaje 18:4c95a470d778 47
stiaje 18:4c95a470d778 48 BLEDevice &getBle() { return ble; }
stiaje 18:4c95a470d778 49 PuckState getState() { return state; }
stiaje 18:4c95a470d778 50 void setState(PuckState state);
stiaje 18:4c95a470d778 51 void init(uint16_t minor);
stiaje 18:4c95a470d778 52 void startAdvertising();
stiaje 18:4c95a470d778 53 void stopAdvertising();
stiaje 18:4c95a470d778 54 void disconnect();
stiaje 18:4c95a470d778 55 bool drive();
stiaje 18:4c95a470d778 56 int countFreeMemory();
stiaje 18:4c95a470d778 57 void onDataWritten(uint16_t handle);
stiaje 18:4c95a470d778 58 void addCharacteristic(const UUID serviceUuid, const UUID characteristicUuid, int bytes, int properties = 0xA);
stiaje 18:4c95a470d778 59
stiaje 18:4c95a470d778 60 void onCharacteristicWrite(const UUID* uuid, CharacteristicWriteCallback callback);
stiaje 18:4c95a470d778 61 void updateCharacteristicValue(const UUID uuid, uint8_t* value, int length);
stiaje 18:4c95a470d778 62
stiaje 18:4c95a470d778 63 uint8_t* getCharacteristicValue(const UUID uuid);
stiaje 18:4c95a470d778 64 };
stiaje 18:4c95a470d778 65
stiaje 18:4c95a470d778 66 /**
stiaje 18:4c95a470d778 67 * @brief Returns singleton instance of puck object.
stiaje 18:4c95a470d778 68 *
stiaje 18:4c95a470d778 69 * @return singleton instance of puck object.
stiaje 18:4c95a470d778 70 */
stiaje 18:4c95a470d778 71 Puck &Puck::getPuck() {
stiaje 18:4c95a470d778 72 static Puck _puckSingletonInstance;
stiaje 18:4c95a470d778 73 return _puckSingletonInstance;
stiaje 18:4c95a470d778 74 }
stiaje 18:4c95a470d778 75
stiaje 18:4c95a470d778 76
stiaje 18:4c95a470d778 77 void onDisconnection(void) {
stiaje 18:4c95a470d778 78 LOG_INFO("Disconnected.\n");
stiaje 18:4c95a470d778 79 Puck::getPuck().setState(DISCONNECTED);
stiaje 18:4c95a470d778 80 }
stiaje 18:4c95a470d778 81
stiaje 18:4c95a470d778 82 void onConnection(void) {
stiaje 18:4c95a470d778 83 LOG_INFO("Connected.\n");
stiaje 18:4c95a470d778 84 Puck::getPuck().setState(CONNECTED);
stiaje 18:4c95a470d778 85 }
stiaje 18:4c95a470d778 86
stiaje 18:4c95a470d778 87 void onDataWrittenCallback(uint16_t handle) {
stiaje 18:4c95a470d778 88 Puck::getPuck().onDataWritten(handle);
stiaje 18:4c95a470d778 89 }
stiaje 18:4c95a470d778 90
stiaje 18:4c95a470d778 91 bool isEqualUUID(const UUID* uuidA, const UUID uuidB) {
stiaje 18:4c95a470d778 92 const uint8_t* uuidABase = uuidA->getBaseUUID();
stiaje 18:4c95a470d778 93 const uint8_t* uuidBBase = uuidB.getBaseUUID();
stiaje 18:4c95a470d778 94
stiaje 18:4c95a470d778 95 for(int i = 0; i < 16; i++) {
stiaje 18:4c95a470d778 96 if(uuidABase[i] != uuidBBase[i]) {
stiaje 18:4c95a470d778 97 return false;
stiaje 18:4c95a470d778 98 }
stiaje 18:4c95a470d778 99 }
stiaje 18:4c95a470d778 100 if(uuidA->getShortUUID() != uuidB.getShortUUID()) {
stiaje 18:4c95a470d778 101 return false;
stiaje 18:4c95a470d778 102 }
stiaje 18:4c95a470d778 103 return true;
stiaje 18:4c95a470d778 104 }
stiaje 18:4c95a470d778 105
stiaje 18:4c95a470d778 106 /**
stiaje 18:4c95a470d778 107 * @brief Returns UUID representation of a 16-character string.
stiaje 18:4c95a470d778 108 *
stiaje 18:4c95a470d778 109 */
stiaje 18:4c95a470d778 110 const UUID stringToUUID(const char* str) {
stiaje 18:4c95a470d778 111 uint8_t array[16];
stiaje 18:4c95a470d778 112 for(int i = 0; i < 16; i++) {
stiaje 18:4c95a470d778 113 array[i] = str[i];
stiaje 18:4c95a470d778 114 }
stiaje 18:4c95a470d778 115 return UUID(array);
stiaje 18:4c95a470d778 116 }
stiaje 18:4c95a470d778 117
stiaje 18:4c95a470d778 118 void Puck::disconnect() {
stiaje 18:4c95a470d778 119 ble.disconnect();
stiaje 18:4c95a470d778 120 }
stiaje 18:4c95a470d778 121
stiaje 18:4c95a470d778 122 /**
stiaje 18:4c95a470d778 123 * @brief Approximates malloc-able heap space. Do not use in production code, as it may crash.
stiaje 18:4c95a470d778 124 *
stiaje 18:4c95a470d778 125 */
stiaje 18:4c95a470d778 126 int Puck::countFreeMemory() {
stiaje 18:4c95a470d778 127 int blocksize = 256;
stiaje 18:4c95a470d778 128 int amount = 0;
stiaje 18:4c95a470d778 129 while (blocksize > 0) {
stiaje 18:4c95a470d778 130 amount += blocksize;
stiaje 18:4c95a470d778 131 LOG_VERBOSE("Trying to malloc %i bytes... ", amount);
stiaje 18:4c95a470d778 132 char *p = (char *) malloc(amount);
stiaje 18:4c95a470d778 133 if (p == NULL) {
stiaje 18:4c95a470d778 134 LOG_VERBOSE("FAIL!\n", amount);
stiaje 18:4c95a470d778 135 amount -= blocksize;
stiaje 18:4c95a470d778 136 blocksize /= 2;
stiaje 18:4c95a470d778 137 } else {
stiaje 18:4c95a470d778 138 free(p);
stiaje 18:4c95a470d778 139 LOG_VERBOSE("OK!\n", amount);
stiaje 18:4c95a470d778 140 }
stiaje 18:4c95a470d778 141 }
stiaje 18:4c95a470d778 142 LOG_DEBUG("Free memory: %i bytes.\n", amount);
stiaje 18:4c95a470d778 143 return amount;
stiaje 18:4c95a470d778 144 }
stiaje 18:4c95a470d778 145
stiaje 18:4c95a470d778 146 void Puck::setState(PuckState state) {
stiaje 18:4c95a470d778 147 LOG_DEBUG("Changed state to %i\n", state);
stiaje 18:4c95a470d778 148 this->state = state;
stiaje 18:4c95a470d778 149 }
stiaje 18:4c95a470d778 150
stiaje 18:4c95a470d778 151 /**
stiaje 18:4c95a470d778 152 * @brief Call after finishing configuring puck (adding services, characteristics, callbacks).
stiaje 18:4c95a470d778 153 Starts advertising over bluetooth le.
stiaje 18:4c95a470d778 154 *
stiaje 18:4c95a470d778 155 * @parameter minor
stiaje 18:4c95a470d778 156 * Minor number to use for iBeacon identifier.
stiaje 18:4c95a470d778 157 *
stiaje 18:4c95a470d778 158 */
stiaje 18:4c95a470d778 159 void Puck::init(uint16_t minor) {
stiaje 18:4c95a470d778 160 /*
stiaje 18:4c95a470d778 161 * The Beacon payload (encapsulated within the MSD advertising data structure)
stiaje 18:4c95a470d778 162 * has the following composition:
stiaje 18:4c95a470d778 163 * 128-Bit UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61
stiaje 18:4c95a470d778 164 * Major/Minor = 1337 / XXXX
stiaje 18:4c95a470d778 165 * Tx Power = C8
stiaje 18:4c95a470d778 166 */
stiaje 18:4c95a470d778 167 uint8_t beaconPayloadTemplate[] = {
stiaje 18:4c95a470d778 168 0x00, 0x00, // Company identifier code (0x004C == Apple)
stiaje 18:4c95a470d778 169 0x02, // ID
stiaje 18:4c95a470d778 170 0x15, // length of the remaining payload
stiaje 18:4c95a470d778 171 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, // UUID
stiaje 18:4c95a470d778 172 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61,
stiaje 18:4c95a470d778 173 0x13, 0x37, // the major value to differenciate a location (Our app requires 1337 as major number)
stiaje 18:4c95a470d778 174 0x00, 0x00, // the minor value to differenciate a location (Change this to differentiate location pucks)
stiaje 18:4c95a470d778 175 0xC8 // 2's complement of the Tx power (-56dB)
stiaje 18:4c95a470d778 176 };
stiaje 18:4c95a470d778 177 beaconPayloadTemplate[22] = minor >> 8;
stiaje 18:4c95a470d778 178 beaconPayloadTemplate[23] = minor & 255;
stiaje 18:4c95a470d778 179
stiaje 18:4c95a470d778 180 for (int i=0; i < 25; i++) {
stiaje 18:4c95a470d778 181 beaconPayload[i] = beaconPayloadTemplate[i];
stiaje 18:4c95a470d778 182 }
stiaje 18:4c95a470d778 183
stiaje 18:4c95a470d778 184 ble.init();
stiaje 18:4c95a470d778 185 LOG_DEBUG("Inited BLEDevice.\n");
stiaje 18:4c95a470d778 186 setState(DISCONNECTED);
stiaje 18:4c95a470d778 187
stiaje 18:4c95a470d778 188 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
stiaje 18:4c95a470d778 189 LOG_DEBUG("Accumulate advertising payload: BREDR_NOT_SUPPORTED.\n");
stiaje 18:4c95a470d778 190
stiaje 18:4c95a470d778 191 ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, beaconPayload, sizeof(beaconPayload));
stiaje 18:4c95a470d778 192 LOG_DEBUG("Accumulate advertising payload: beacon data.\n");
stiaje 18:4c95a470d778 193
stiaje 18:4c95a470d778 194 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
stiaje 18:4c95a470d778 195 LOG_DEBUG("Setting advertising type: ADV_CONNECTABLE_UNDIRECTED.\n");
stiaje 18:4c95a470d778 196
stiaje 18:4c95a470d778 197 int hundredMillisecondsInAdvertisingIntervalFormat = 160;
stiaje 18:4c95a470d778 198 ble.setAdvertisingInterval(hundredMillisecondsInAdvertisingIntervalFormat);
stiaje 18:4c95a470d778 199 LOG_DEBUG("Set advertising interval: 160 (100 ms).\n");
stiaje 18:4c95a470d778 200
stiaje 18:4c95a470d778 201 ble.onDisconnection(onDisconnection);
stiaje 18:4c95a470d778 202 ble.onConnection(onConnection);
stiaje 18:4c95a470d778 203 ble.onDataWritten(onDataWrittenCallback);
stiaje 18:4c95a470d778 204 LOG_DEBUG("Hooked up internal event handlers.\n");
stiaje 18:4c95a470d778 205
stiaje 18:4c95a470d778 206 for(int i = 0; i < services.size(); i++) {
stiaje 18:4c95a470d778 207 ble.addService(*services[i]);
stiaje 18:4c95a470d778 208 LOG_DEBUG("Added service %x to BLEDevice\n", services[i]);
stiaje 18:4c95a470d778 209 }
stiaje 18:4c95a470d778 210
stiaje 18:4c95a470d778 211 LOG_INFO("Inited puck as 0x%X.\n", minor);
stiaje 18:4c95a470d778 212 }
stiaje 18:4c95a470d778 213
stiaje 18:4c95a470d778 214 void Puck::startAdvertising() {
stiaje 18:4c95a470d778 215 ble.startAdvertising();
stiaje 18:4c95a470d778 216 LOG_INFO("Starting to advertise.\n");
stiaje 18:4c95a470d778 217 setState(ADVERTISING);
stiaje 18:4c95a470d778 218 }
stiaje 18:4c95a470d778 219
stiaje 18:4c95a470d778 220 void Puck::stopAdvertising() {
stiaje 18:4c95a470d778 221 if(state == ADVERTISING) {
stiaje 18:4c95a470d778 222 ble.stopAdvertising();
stiaje 18:4c95a470d778 223 LOG_INFO("Stopped advertising.\n");
stiaje 18:4c95a470d778 224 setState(DISCONNECTED);
stiaje 18:4c95a470d778 225 } else {
stiaje 18:4c95a470d778 226 LOG_WARN("Tried to stop advertising, but advertising is already stopped!\n");
stiaje 18:4c95a470d778 227 }
stiaje 18:4c95a470d778 228 }
stiaje 18:4c95a470d778 229
stiaje 18:4c95a470d778 230 /**
stiaje 18:4c95a470d778 231 * @brief Extends the given gatt service with the given gatt characteristic.
stiaje 18:4c95a470d778 232 * If the service doesn't exist, it is created.
stiaje 18:4c95a470d778 233 *
stiaje 18:4c95a470d778 234 * @param serviceUuid
stiaje 18:4c95a470d778 235 UUID of the gatt service to be extended.
stiaje 18:4c95a470d778 236 *
stiaje 18:4c95a470d778 237 * @param characteristicUuid
stiaje 18:4c95a470d778 238 * UUID to use for this characteristic.
stiaje 18:4c95a470d778 239 *
stiaje 18:4c95a470d778 240 * @param bytes
stiaje 18:4c95a470d778 241 * Length in bytes of this characteristic's value.
stiaje 18:4c95a470d778 242 *
stiaje 18:4c95a470d778 243 * @param properties
stiaje 18:4c95a470d778 244 * 8-bit bit field containing the characteristic's properties. See @ref ble_gatt_char_properties_t.
stiaje 18:4c95a470d778 245 *
stiaje 18:4c95a470d778 246 * @return Void.
stiaje 18:4c95a470d778 247 */
stiaje 18:4c95a470d778 248 void Puck::addCharacteristic(const UUID serviceUuid, const UUID characteristicUuid, int bytes, int properties) {
stiaje 18:4c95a470d778 249 MBED_ASSERT(bytes <= 20);
stiaje 18:4c95a470d778 250 uint16_t size = sizeof(uint8_t) * bytes;
stiaje 18:4c95a470d778 251 uint8_t* value = (uint8_t*) malloc(size);
stiaje 18:4c95a470d778 252 if(value == NULL) {
stiaje 18:4c95a470d778 253 LOG_ERROR("Unable to malloc value for characteristic. Possibly out of memory!\n");
stiaje 18:4c95a470d778 254 }
stiaje 18:4c95a470d778 255
stiaje 18:4c95a470d778 256 GattCharacteristic* characteristic = new GattCharacteristic(characteristicUuid, value, size, size, properties);
stiaje 18:4c95a470d778 257 characteristics.push_back(characteristic);
stiaje 18:4c95a470d778 258
stiaje 18:4c95a470d778 259
stiaje 18:4c95a470d778 260 GattService* service = NULL;
stiaje 18:4c95a470d778 261
stiaje 18:4c95a470d778 262 int removeIndex = -1;
stiaje 18:4c95a470d778 263 for(int i = 0; i < services.size(); i++) {
stiaje 18:4c95a470d778 264 if(isEqualUUID(&services[i]->getUUID(), serviceUuid)) {
stiaje 18:4c95a470d778 265 service = services[i];
stiaje 18:4c95a470d778 266 removeIndex = i;
stiaje 18:4c95a470d778 267 break;
stiaje 18:4c95a470d778 268 }
stiaje 18:4c95a470d778 269 }
stiaje 18:4c95a470d778 270 GattCharacteristic** characteristics = NULL;
stiaje 18:4c95a470d778 271 int characteristicsLength = 0;
stiaje 18:4c95a470d778 272 if(service != NULL) {
stiaje 18:4c95a470d778 273 characteristicsLength = service->getCharacteristicCount() + 1;
stiaje 18:4c95a470d778 274 characteristics = (GattCharacteristic**) malloc(sizeof(GattCharacteristic*) * characteristicsLength);
stiaje 18:4c95a470d778 275 if(characteristics == NULL) {
stiaje 18:4c95a470d778 276 LOG_ERROR("Unable to malloc array of characteristics for service creation. Possibly out of memory!\n");
stiaje 18:4c95a470d778 277 }
stiaje 18:4c95a470d778 278 for(int i = 0; i < characteristicsLength; i++) {
stiaje 18:4c95a470d778 279 characteristics[i] = service->getCharacteristic(i);
stiaje 18:4c95a470d778 280 }
stiaje 18:4c95a470d778 281 services.erase(services.begin() + removeIndex);
stiaje 18:4c95a470d778 282 delete service;
stiaje 18:4c95a470d778 283 free(previousCharacteristics);
stiaje 18:4c95a470d778 284 } else {
stiaje 18:4c95a470d778 285 characteristicsLength = 1;
stiaje 18:4c95a470d778 286 characteristics = (GattCharacteristic**) malloc(sizeof(GattCharacteristic*) * characteristicsLength);
stiaje 18:4c95a470d778 287 if(characteristics == NULL) {
stiaje 18:4c95a470d778 288 LOG_ERROR("Unable to malloc array of characteristics for service creation. Possibly out of memory!\n");
stiaje 18:4c95a470d778 289 }
stiaje 18:4c95a470d778 290 }
stiaje 18:4c95a470d778 291
stiaje 18:4c95a470d778 292 characteristics[characteristicsLength - 1] = characteristic;
stiaje 18:4c95a470d778 293 previousCharacteristics = characteristics;
stiaje 18:4c95a470d778 294 service = new GattService(serviceUuid, characteristics, characteristicsLength);
stiaje 18:4c95a470d778 295 services.push_back(service);
stiaje 18:4c95a470d778 296 LOG_DEBUG("Added characteristic.\n");
stiaje 18:4c95a470d778 297 }
stiaje 18:4c95a470d778 298
stiaje 18:4c95a470d778 299 /**
stiaje 18:4c95a470d778 300 * @brief Update the value of the given gatt characteristic.
stiaje 18:4c95a470d778 301 *
stiaje 18:4c95a470d778 302 * @param uuid
stiaje 18:4c95a470d778 303 UUID of the gatt characteristic to be updated.
stiaje 18:4c95a470d778 304 *
stiaje 18:4c95a470d778 305 * @param value
stiaje 18:4c95a470d778 306 * New value of the characteristic.
stiaje 18:4c95a470d778 307 *
stiaje 18:4c95a470d778 308 * @param length
stiaje 18:4c95a470d778 309 * Length in bytes of the characteristic's value.
stiaje 18:4c95a470d778 310 *
stiaje 18:4c95a470d778 311 * @return Void.
stiaje 18:4c95a470d778 312 */
stiaje 18:4c95a470d778 313 void Puck::updateCharacteristicValue(const UUID uuid, uint8_t* value, int length) {
stiaje 18:4c95a470d778 314 GattCharacteristic* characteristic = NULL;
stiaje 18:4c95a470d778 315 for( int i = 0; i < characteristics.size(); i++) {
stiaje 18:4c95a470d778 316 if(isEqualUUID(&characteristics[i]->getUUID(), uuid)) {
stiaje 18:4c95a470d778 317 characteristic = characteristics[i];
stiaje 18:4c95a470d778 318 break;
stiaje 18:4c95a470d778 319 }
stiaje 18:4c95a470d778 320 }
stiaje 18:4c95a470d778 321 if(characteristic != NULL) {
stiaje 18:4c95a470d778 322 ble.updateCharacteristicValue(characteristic->getHandle(), value, length);
stiaje 18:4c95a470d778 323 LOG_VERBOSE("Updated characteristic value.\n");
stiaje 18:4c95a470d778 324 } else {
stiaje 18:4c95a470d778 325 LOG_WARN("Tried to update an unkown characteristic!\n");
stiaje 18:4c95a470d778 326 }
stiaje 18:4c95a470d778 327 }
stiaje 18:4c95a470d778 328
stiaje 18:4c95a470d778 329 /**
stiaje 18:4c95a470d778 330 * @brief Pass control to the bluetooth stack, executing pending callbacks afterwards. Should be used inside a while condition loop.
stiaje 18:4c95a470d778 331 *
stiaje 18:4c95a470d778 332 * Example:
stiaje 18:4c95a470d778 333 * @code
stiaje 18:4c95a470d778 334 * while (puck->drive()) {
stiaje 18:4c95a470d778 335 * // Do stuff
stiaje 18:4c95a470d778 336 * }
stiaje 18:4c95a470d778 337 * @endcode
stiaje 18:4c95a470d778 338 *
stiaje 18:4c95a470d778 339 * @return true.
stiaje 18:4c95a470d778 340 *
stiaje 18:4c95a470d778 341 */
stiaje 18:4c95a470d778 342 bool Puck::drive() {
stiaje 18:4c95a470d778 343 ble.waitForEvent();
stiaje 18:4c95a470d778 344 if(state == DISCONNECTED) {
stiaje 18:4c95a470d778 345 startAdvertising();
stiaje 18:4c95a470d778 346 }
stiaje 18:4c95a470d778 347 while(pendingCallbackStack.size() > 0) {
stiaje 18:4c95a470d778 348 pendingCallbackStack.back()(pendingCallbackParameterStack.back());
stiaje 18:4c95a470d778 349 pendingCallbackStack.pop_back();
stiaje 18:4c95a470d778 350 pendingCallbackParameterStack.pop_back();
stiaje 18:4c95a470d778 351 }
stiaje 18:4c95a470d778 352 return true;
stiaje 18:4c95a470d778 353 }
stiaje 18:4c95a470d778 354
stiaje 18:4c95a470d778 355 /**
stiaje 18:4c95a470d778 356 * @brief Register callback to be triggered on characteristic write.
stiaje 18:4c95a470d778 357 *
stiaje 18:4c95a470d778 358 * @parameter uuid
stiaje 18:4c95a470d778 359 * UUID of the gatt characteristic to bind callback to.
stiaje 18:4c95a470d778 360 *
stiaje 18:4c95a470d778 361 * @parameter callback
stiaje 18:4c95a470d778 362 * CharacteristicWriteCallback to be executed on characteristic write.
stiaje 18:4c95a470d778 363 *
stiaje 18:4c95a470d778 364 * @return Void.
stiaje 18:4c95a470d778 365 *
stiaje 18:4c95a470d778 366 */
stiaje 18:4c95a470d778 367 void Puck::onCharacteristicWrite(const UUID* uuid, CharacteristicWriteCallback callback) {
stiaje 18:4c95a470d778 368 CharacteristicWriteCallbacks* cb = NULL;
stiaje 18:4c95a470d778 369 for(int i = 0; i< writeCallbacks.size(); i++) {
stiaje 18:4c95a470d778 370 if(isEqualUUID(writeCallbacks[i]->uuid, *uuid)) {
stiaje 18:4c95a470d778 371 cb = writeCallbacks[i];
stiaje 18:4c95a470d778 372 break;
stiaje 18:4c95a470d778 373 }
stiaje 18:4c95a470d778 374 }
stiaje 18:4c95a470d778 375 if(cb == NULL) {
stiaje 18:4c95a470d778 376 cb = (CharacteristicWriteCallbacks*) malloc(sizeof(CharacteristicWriteCallbacks));
stiaje 18:4c95a470d778 377 if(cb == NULL) {
stiaje 18:4c95a470d778 378 LOG_ERROR("Could not malloc CharacteristicWriteCallbacks container. Possibly out of memory!\n");
stiaje 18:4c95a470d778 379 }
stiaje 18:4c95a470d778 380 cb->uuid = uuid;
stiaje 18:4c95a470d778 381 cb->callbacks = new std::vector<CharacteristicWriteCallback>();
stiaje 18:4c95a470d778 382 writeCallbacks.push_back(cb);
stiaje 18:4c95a470d778 383 }
stiaje 18:4c95a470d778 384 cb->callbacks->push_back(callback);
stiaje 18:4c95a470d778 385 LOG_VERBOSE("Bound characteristic write callback (uuid: %x, callback: %x)\n", uuid, callback);
stiaje 18:4c95a470d778 386 }
stiaje 18:4c95a470d778 387
stiaje 18:4c95a470d778 388 /**
stiaje 18:4c95a470d778 389 * @brief Returns current value of provided gatt characteristic.
stiaje 18:4c95a470d778 390 *
stiaje 18:4c95a470d778 391 */
stiaje 18:4c95a470d778 392 uint8_t* Puck::getCharacteristicValue(const UUID uuid) {
stiaje 18:4c95a470d778 393 LOG_VERBOSE("Reading characteristic value for UUID %x\n", uuid);
stiaje 18:4c95a470d778 394 for(int i = 0; i < characteristics.size(); i++) {
stiaje 18:4c95a470d778 395 GattCharacteristic* characteristic = characteristics[i];
stiaje 18:4c95a470d778 396 if(isEqualUUID(&characteristic->getUUID(), uuid)) {
stiaje 18:4c95a470d778 397 return characteristic->getValuePtr();
stiaje 18:4c95a470d778 398 }
stiaje 18:4c95a470d778 399 }
stiaje 18:4c95a470d778 400 LOG_WARN("Tried to read an unknown characteristic!");
stiaje 18:4c95a470d778 401 return NULL;
stiaje 18:4c95a470d778 402 }
stiaje 18:4c95a470d778 403
stiaje 18:4c95a470d778 404 /**
stiaje 18:4c95a470d778 405 * @brief For internal use only. Exposed to hack around mbed framework limitation.
stiaje 18:4c95a470d778 406 *
stiaje 18:4c95a470d778 407 */
stiaje 18:4c95a470d778 408 void Puck::onDataWritten(uint16_t handle) {
stiaje 18:4c95a470d778 409 for (int i = 0; i < characteristics.size(); i++) {
stiaje 18:4c95a470d778 410 GattCharacteristic* characteristic = characteristics[i];
stiaje 18:4c95a470d778 411 if (characteristic->getHandle() == handle) {
stiaje 18:4c95a470d778 412 uint16_t maxLength = characteristic->getMaxLength();
stiaje 18:4c95a470d778 413 ble.readCharacteristicValue(handle, characteristic->getValuePtr(), &maxLength);
stiaje 18:4c95a470d778 414 for(int j = 0; j < writeCallbacks.size(); j++) {
stiaje 18:4c95a470d778 415 CharacteristicWriteCallbacks* characteristicWriteCallbacks = writeCallbacks[j];
stiaje 18:4c95a470d778 416 if(isEqualUUID(characteristicWriteCallbacks->uuid, characteristic->getUUID())) {
stiaje 18:4c95a470d778 417 for(int k = 0; k < characteristicWriteCallbacks->callbacks->size(); k++) {
stiaje 18:4c95a470d778 418 pendingCallbackStack.push_back(characteristicWriteCallbacks->callbacks->at(k));
stiaje 18:4c95a470d778 419 pendingCallbackParameterStack.push_back(characteristic->getValuePtr());
stiaje 18:4c95a470d778 420 }
stiaje 18:4c95a470d778 421 return;
stiaje 18:4c95a470d778 422 }
stiaje 18:4c95a470d778 423 }
stiaje 18:4c95a470d778 424 }
stiaje 18:4c95a470d778 425 }
stiaje 18:4c95a470d778 426 }
stiaje 18:4c95a470d778 427
stiaje 18:4c95a470d778 428
stiaje 18:4c95a470d778 429
stiaje 18:4c95a470d778 430 #endif // __PUCK_HPP__