A library for easier setup and prototyping of IoT devices (pucks), by collecting everything that is common for all pucks in one place.

Dependencies:   BLE_API nRF51822

Dependents:   ir-puck display-puck ir-puck2 BLE_ScoringDevice ... more

/media/uploads/stiaje/header.jpg

Introduction

Raspberry Pi took the maker community by storm when it launched in 2012. With its internet access it allowed small projects to be internet-of-things enabled. We have created a platform to take this one step further.

Our platform, called the Puck platform, is an internet of things platform for mbed. mbed makes it easy to program embedded hardware for people new to embedded systems. Our platform is built upon the first mbed chip with Bluetooth, the nRF51822 created by Nordic Semiconductor. We hope to create a community around these BLE devices where people contribute to the project, and share their designs with each other. Everything is open-source, of course, with lots of supporting materials.

We make it easy to rapidly prototype and develop Bluetooth LE enabled devices - get up and running in under 10 lines of code.

Tutorials and in-depth documentation is available at the project's GitHub page

Pucks

We've developed a handful of awesome examples to demonstrate the platform. These examples are named 'Pucks'. By talking to the internet through your smartphone, the barrier to creating your own Internet of Things device is lower than ever.

Committer:
aleksanb
Date:
Mon Feb 23 15:25:22 2015 +0000
Revision:
14:9eda2d99fc1d
Parent:
13:93d3574e9e36
Child:
15:bfc682889c15
Update Puck library to newest versions of BLE_API.h, mbed.h.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cristea 12:8a8cc109f048 1 /**
cristea 12:8a8cc109f048 2 * Copyright 2014 Nordic Semiconductor
cristea 12:8a8cc109f048 3 *
cristea 12:8a8cc109f048 4 * Licensed under the Apache License, Version 2.0 (the "License");
cristea 12:8a8cc109f048 5 * you may not use this file except in compliance with the License.
cristea 12:8a8cc109f048 6 * You may obtain a copy of the License at
cristea 12:8a8cc109f048 7 *
cristea 12:8a8cc109f048 8 * http://www.apache.org/licenses/LICENSE-2.0
cristea 12:8a8cc109f048 9 *
cristea 12:8a8cc109f048 10 * Unless required by applicable law or agreed to in writing, software
cristea 12:8a8cc109f048 11 * distributed under the License is distributed on an "AS IS" BASIS,
cristea 12:8a8cc109f048 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
cristea 12:8a8cc109f048 13 * See the License for the specific language governing permissions and
cristea 12:8a8cc109f048 14 * limitations under the License
cristea 12:8a8cc109f048 15 */
cristea 12:8a8cc109f048 16
cristea 12:8a8cc109f048 17
sigveseb 3:5432b38585ea 18 #ifndef __PUCK_HPP__
sigveseb 3:5432b38585ea 19 #define __PUCK_HPP__
sigveseb 3:5432b38585ea 20
sigveseb 3:5432b38585ea 21 #include "BLEDevice.h"
aleksanb 14:9eda2d99fc1d 22 #include "mbed.h"
aleksanb 14:9eda2d99fc1d 23 #include "Log.h"
sigveseb 3:5432b38585ea 24 #include <vector>
sigveseb 3:5432b38585ea 25
sigveseb 9:ba0527c6b6d0 26 enum PuckState {
sigveseb 3:5432b38585ea 27 CONNECTING,
sigveseb 3:5432b38585ea 28 CONNECTED,
sigveseb 3:5432b38585ea 29 ADVERTISING,
sigveseb 3:5432b38585ea 30 DISCONNECTED
sigveseb 3:5432b38585ea 31 };
sigveseb 3:5432b38585ea 32
sigveseb 3:5432b38585ea 33 const UUID stringToUUID(const char* str);
sigveseb 3:5432b38585ea 34
sigveseb 3:5432b38585ea 35 typedef void (*CharacteristicWriteCallback)(uint8_t* value);
sigveseb 3:5432b38585ea 36
sigveseb 3:5432b38585ea 37 typedef struct {
sigveseb 3:5432b38585ea 38 const UUID* uuid;
sigveseb 3:5432b38585ea 39 std::vector<CharacteristicWriteCallback>* callbacks;
sigveseb 3:5432b38585ea 40 } CharacteristicWriteCallbacks;
sigveseb 3:5432b38585ea 41
sigveseb 3:5432b38585ea 42
sigveseb 3:5432b38585ea 43 class Puck {
sigveseb 3:5432b38585ea 44 private:
sigveseb 3:5432b38585ea 45 Puck() {}
sigveseb 3:5432b38585ea 46 Puck(const Puck&);
sigveseb 3:5432b38585ea 47 Puck& operator=(const Puck&);
sigveseb 3:5432b38585ea 48
sigveseb 3:5432b38585ea 49 BLEDevice ble;
sigveseb 3:5432b38585ea 50 uint8_t beaconPayload[25];
sigveseb 3:5432b38585ea 51 PuckState state;
sigveseb 3:5432b38585ea 52 std::vector<GattService*> services;
sigveseb 3:5432b38585ea 53 std::vector<GattCharacteristic*> characteristics;
sigveseb 3:5432b38585ea 54 std::vector<CharacteristicWriteCallbacks*> writeCallbacks;
sigveseb 3:5432b38585ea 55 std::vector<CharacteristicWriteCallback> pendingCallbackStack;
sigveseb 3:5432b38585ea 56 std::vector<uint8_t*> pendingCallbackParameterStack;
sigveseb 3:5432b38585ea 57
stiaje 4:91506772210d 58 GattCharacteristic **previousCharacteristics;
stiaje 4:91506772210d 59
sigveseb 3:5432b38585ea 60 public:
sigveseb 3:5432b38585ea 61 static Puck &getPuck();
sigveseb 3:5432b38585ea 62
stiaje 5:2f2a2ac6b231 63 BLEDevice &getBle() { return ble; }
sigveseb 3:5432b38585ea 64 PuckState getState() { return state; }
sigveseb 3:5432b38585ea 65 void setState(PuckState state);
sigveseb 3:5432b38585ea 66 void init(uint16_t minor);
sigveseb 3:5432b38585ea 67 void startAdvertising();
sigveseb 3:5432b38585ea 68 void stopAdvertising();
sigveseb 9:ba0527c6b6d0 69 void disconnect();
sigveseb 3:5432b38585ea 70 bool drive();
sigveseb 9:ba0527c6b6d0 71 int countFreeMemory();
sigveseb 3:5432b38585ea 72 void onDataWritten(uint16_t handle);
sigveseb 3:5432b38585ea 73 void addCharacteristic(const UUID serviceUuid, const UUID characteristicUuid, int bytes, int properties = 0xA);
stiaje 10:67e4694f2d74 74
sigveseb 9:ba0527c6b6d0 75 void onCharacteristicWrite(const UUID* uuid, CharacteristicWriteCallback callback);
sigveseb 8:49ffd38fb401 76 void updateCharacteristicValue(const UUID uuid, uint8_t* value, int length);
stiaje 10:67e4694f2d74 77
sigveseb 3:5432b38585ea 78 uint8_t* getCharacteristicValue(const UUID uuid);
sigveseb 3:5432b38585ea 79 };
sigveseb 3:5432b38585ea 80
sigveseb 3:5432b38585ea 81 Puck &Puck::getPuck() {
sigveseb 3:5432b38585ea 82 static Puck _puckSingletonInstance;
sigveseb 3:5432b38585ea 83 return _puckSingletonInstance;
sigveseb 3:5432b38585ea 84 }
sigveseb 3:5432b38585ea 85
aleksanb 14:9eda2d99fc1d 86 void onDisconnection(Gap::Handle_t handle, Gap::DisconnectionReason_t disconnectReason) {
sigveseb 3:5432b38585ea 87 LOG_INFO("Disconnected.\n");
sigveseb 3:5432b38585ea 88 Puck::getPuck().setState(DISCONNECTED);
sigveseb 3:5432b38585ea 89 }
sigveseb 3:5432b38585ea 90
aleksanb 14:9eda2d99fc1d 91 void onConnection(Gap::Handle_t handle,
aleksanb 14:9eda2d99fc1d 92 Gap::addr_type_t peerAddrType,
aleksanb 14:9eda2d99fc1d 93 const Gap::address_t peerAddr,
aleksanb 14:9eda2d99fc1d 94 const Gap::ConnectionParams_t * connectionParams) {
sigveseb 3:5432b38585ea 95 LOG_INFO("Connected.\n");
sigveseb 3:5432b38585ea 96 Puck::getPuck().setState(CONNECTED);
sigveseb 3:5432b38585ea 97 }
sigveseb 3:5432b38585ea 98
aleksanb 14:9eda2d99fc1d 99 void onDataWrittenCallback(const GattCharacteristicWriteCBParams *context) {
aleksanb 14:9eda2d99fc1d 100 Puck::getPuck().onDataWritten(context->charHandle);
sigveseb 3:5432b38585ea 101 }
sigveseb 3:5432b38585ea 102
sigveseb 3:5432b38585ea 103 bool isEqualUUID(const UUID* uuidA, const UUID uuidB) {
sigveseb 3:5432b38585ea 104 const uint8_t* uuidABase = uuidA->getBaseUUID();
sigveseb 3:5432b38585ea 105 const uint8_t* uuidBBase = uuidB.getBaseUUID();
sigveseb 9:ba0527c6b6d0 106
sigveseb 3:5432b38585ea 107 for(int i = 0; i < 16; i++) {
sigveseb 3:5432b38585ea 108 if(uuidABase[i] != uuidBBase[i]) {
sigveseb 3:5432b38585ea 109 return false;
sigveseb 3:5432b38585ea 110 }
sigveseb 3:5432b38585ea 111 }
sigveseb 9:ba0527c6b6d0 112 if(uuidA->getShortUUID() != uuidB.getShortUUID()) {
sigveseb 9:ba0527c6b6d0 113 return false;
sigveseb 9:ba0527c6b6d0 114 }
sigveseb 3:5432b38585ea 115 return true;
sigveseb 3:5432b38585ea 116 }
sigveseb 3:5432b38585ea 117
sigveseb 3:5432b38585ea 118 const UUID stringToUUID(const char* str) {
sigveseb 3:5432b38585ea 119 uint8_t array[16];
sigveseb 3:5432b38585ea 120 for(int i = 0; i < 16; i++) {
sigveseb 3:5432b38585ea 121 array[i] = str[i];
sigveseb 3:5432b38585ea 122 }
sigveseb 3:5432b38585ea 123 return UUID(array);
sigveseb 3:5432b38585ea 124 }
sigveseb 3:5432b38585ea 125
sigveseb 9:ba0527c6b6d0 126 void Puck::disconnect() {
aleksanb 14:9eda2d99fc1d 127 ble.disconnect(Gap::LOCAL_HOST_TERMINATED_CONNECTION);
sigveseb 9:ba0527c6b6d0 128 }
sigveseb 9:ba0527c6b6d0 129
sigveseb 9:ba0527c6b6d0 130 int Puck::countFreeMemory() {
sigveseb 9:ba0527c6b6d0 131 int blocksize = 256;
sigveseb 9:ba0527c6b6d0 132 int amount = 0;
sigveseb 9:ba0527c6b6d0 133 while (blocksize > 0) {
sigveseb 9:ba0527c6b6d0 134 amount += blocksize;
sigveseb 9:ba0527c6b6d0 135 LOG_VERBOSE("Trying to malloc %i bytes... ", amount);
sigveseb 9:ba0527c6b6d0 136 char *p = (char *) malloc(amount);
sigveseb 9:ba0527c6b6d0 137 if (p == NULL) {
sigveseb 9:ba0527c6b6d0 138 LOG_VERBOSE("FAIL!\n", amount);
sigveseb 9:ba0527c6b6d0 139 amount -= blocksize;
sigveseb 9:ba0527c6b6d0 140 blocksize /= 2;
sigveseb 9:ba0527c6b6d0 141 } else {
sigveseb 9:ba0527c6b6d0 142 free(p);
sigveseb 9:ba0527c6b6d0 143 LOG_VERBOSE("OK!\n", amount);
sigveseb 9:ba0527c6b6d0 144 }
sigveseb 9:ba0527c6b6d0 145 }
sigveseb 9:ba0527c6b6d0 146 LOG_DEBUG("Free memory: %i bytes.\n", amount);
sigveseb 9:ba0527c6b6d0 147 return amount;
sigveseb 9:ba0527c6b6d0 148 }
sigveseb 9:ba0527c6b6d0 149
sigveseb 3:5432b38585ea 150 void Puck::setState(PuckState state) {
sigveseb 3:5432b38585ea 151 LOG_DEBUG("Changed state to %i\n", state);
sigveseb 3:5432b38585ea 152 this->state = state;
sigveseb 3:5432b38585ea 153 }
sigveseb 3:5432b38585ea 154
sigveseb 3:5432b38585ea 155 void Puck::init(uint16_t minor) {
sigveseb 3:5432b38585ea 156 /*
sigveseb 3:5432b38585ea 157 * The Beacon payload (encapsulated within the MSD advertising data structure)
sigveseb 3:5432b38585ea 158 * has the following composition:
sigveseb 3:5432b38585ea 159 * 128-Bit UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61
sigveseb 3:5432b38585ea 160 * Major/Minor = 1337 / XXXX
sigveseb 3:5432b38585ea 161 * Tx Power = C8
sigveseb 3:5432b38585ea 162 */
sigveseb 3:5432b38585ea 163 uint8_t beaconPayloadTemplate[] = {
sigveseb 3:5432b38585ea 164 0x00, 0x00, // Company identifier code (0x004C == Apple)
sigveseb 3:5432b38585ea 165 0x02, // ID
sigveseb 3:5432b38585ea 166 0x15, // length of the remaining payload
sigveseb 3:5432b38585ea 167 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, // UUID
sigveseb 3:5432b38585ea 168 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61,
sigveseb 3:5432b38585ea 169 0x13, 0x37, // the major value to differenciate a location (Our app requires 1337 as major number)
sigveseb 3:5432b38585ea 170 0x00, 0x00, // the minor value to differenciate a location (Change this to differentiate location pucks)
sigveseb 3:5432b38585ea 171 0xC8 // 2's complement of the Tx power (-56dB)
sigveseb 3:5432b38585ea 172 };
sigveseb 3:5432b38585ea 173 beaconPayloadTemplate[22] = minor >> 8;
sigveseb 3:5432b38585ea 174 beaconPayloadTemplate[23] = minor & 255;
sigveseb 3:5432b38585ea 175
sigveseb 3:5432b38585ea 176 for (int i=0; i < 25; i++) {
sigveseb 3:5432b38585ea 177 beaconPayload[i] = beaconPayloadTemplate[i];
sigveseb 3:5432b38585ea 178 }
sigveseb 3:5432b38585ea 179
sigveseb 3:5432b38585ea 180 ble.init();
sigveseb 9:ba0527c6b6d0 181 LOG_DEBUG("Inited BLEDevice.\n");
sigveseb 3:5432b38585ea 182 setState(DISCONNECTED);
sigveseb 3:5432b38585ea 183
sigveseb 3:5432b38585ea 184 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
sigveseb 9:ba0527c6b6d0 185 LOG_DEBUG("Accumulate advertising payload: BREDR_NOT_SUPPORTED.\n");
sigveseb 3:5432b38585ea 186
sigveseb 3:5432b38585ea 187 ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, beaconPayload, sizeof(beaconPayload));
sigveseb 9:ba0527c6b6d0 188 LOG_DEBUG("Accumulate advertising payload: beacon data.\n");
sigveseb 3:5432b38585ea 189
sigveseb 3:5432b38585ea 190 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
sigveseb 9:ba0527c6b6d0 191 LOG_DEBUG("Setting advertising type: ADV_CONNECTABLE_UNDIRECTED.\n");
sigveseb 3:5432b38585ea 192
sigveseb 3:5432b38585ea 193 int hundredMillisecondsInAdvertisingIntervalFormat = 160;
sigveseb 3:5432b38585ea 194 ble.setAdvertisingInterval(hundredMillisecondsInAdvertisingIntervalFormat);
sigveseb 9:ba0527c6b6d0 195 LOG_DEBUG("Set advertising interval: 160 (100 ms).\n");
sigveseb 3:5432b38585ea 196
sigveseb 3:5432b38585ea 197 ble.onDisconnection(onDisconnection);
sigveseb 3:5432b38585ea 198 ble.onConnection(onConnection);
sigveseb 3:5432b38585ea 199 ble.onDataWritten(onDataWrittenCallback);
sigveseb 9:ba0527c6b6d0 200 LOG_DEBUG("Hooked up internal event handlers.\n");
sigveseb 3:5432b38585ea 201
sigveseb 3:5432b38585ea 202 for(int i = 0; i < services.size(); i++) {
sigveseb 3:5432b38585ea 203 ble.addService(*services[i]);
sigveseb 9:ba0527c6b6d0 204 LOG_DEBUG("Added service %x to BLEDevice\n", services[i]);
sigveseb 3:5432b38585ea 205 }
sigveseb 3:5432b38585ea 206
sigveseb 3:5432b38585ea 207 LOG_INFO("Inited puck as 0x%X.\n", minor);
sigveseb 3:5432b38585ea 208 }
sigveseb 3:5432b38585ea 209
sigveseb 3:5432b38585ea 210 void Puck::startAdvertising() {
sigveseb 3:5432b38585ea 211 ble.startAdvertising();
sigveseb 3:5432b38585ea 212 LOG_INFO("Starting to advertise.\n");
sigveseb 3:5432b38585ea 213 setState(ADVERTISING);
sigveseb 3:5432b38585ea 214 }
sigveseb 3:5432b38585ea 215
sigveseb 3:5432b38585ea 216 void Puck::stopAdvertising() {
sigveseb 3:5432b38585ea 217 if(state == ADVERTISING) {
sigveseb 3:5432b38585ea 218 ble.stopAdvertising();
sigveseb 3:5432b38585ea 219 LOG_INFO("Stopped advertising.\n");
sigveseb 3:5432b38585ea 220 setState(DISCONNECTED);
sigveseb 3:5432b38585ea 221 } else {
sigveseb 3:5432b38585ea 222 LOG_WARN("Tried to stop advertising, but advertising is already stopped!\n");
sigveseb 3:5432b38585ea 223 }
sigveseb 3:5432b38585ea 224 }
sigveseb 3:5432b38585ea 225
sigveseb 3:5432b38585ea 226
sigveseb 3:5432b38585ea 227 void Puck::addCharacteristic(const UUID serviceUuid, const UUID characteristicUuid, int bytes, int properties) {
sigveseb 3:5432b38585ea 228 MBED_ASSERT(bytes <= 20);
sigveseb 3:5432b38585ea 229 uint16_t size = sizeof(uint8_t) * bytes;
sigveseb 3:5432b38585ea 230 uint8_t* value = (uint8_t*) malloc(size);
sigveseb 9:ba0527c6b6d0 231 if(value == NULL) {
sigveseb 9:ba0527c6b6d0 232 LOG_ERROR("Unable to malloc value for characteristic. Possibly out of memory!\n");
sigveseb 9:ba0527c6b6d0 233 }
sigveseb 9:ba0527c6b6d0 234
sigveseb 3:5432b38585ea 235 GattCharacteristic* characteristic = new GattCharacteristic(characteristicUuid, value, size, size, properties);
sigveseb 3:5432b38585ea 236 characteristics.push_back(characteristic);
sigveseb 9:ba0527c6b6d0 237
sigveseb 9:ba0527c6b6d0 238
sigveseb 3:5432b38585ea 239 GattService* service = NULL;
sigveseb 9:ba0527c6b6d0 240
sigveseb 3:5432b38585ea 241 int removeIndex = -1;
sigveseb 3:5432b38585ea 242 for(int i = 0; i < services.size(); i++) {
sigveseb 3:5432b38585ea 243 if(isEqualUUID(&services[i]->getUUID(), serviceUuid)) {
sigveseb 3:5432b38585ea 244 service = services[i];
sigveseb 3:5432b38585ea 245 removeIndex = i;
sigveseb 3:5432b38585ea 246 break;
sigveseb 3:5432b38585ea 247 }
sigveseb 3:5432b38585ea 248 }
sigveseb 3:5432b38585ea 249 GattCharacteristic** characteristics = NULL;
sigveseb 3:5432b38585ea 250 int characteristicsLength = 0;
sigveseb 3:5432b38585ea 251 if(service != NULL) {
sigveseb 3:5432b38585ea 252 characteristicsLength = service->getCharacteristicCount() + 1;
sigveseb 3:5432b38585ea 253 characteristics = (GattCharacteristic**) malloc(sizeof(GattCharacteristic*) * characteristicsLength);
sigveseb 9:ba0527c6b6d0 254 if(characteristics == NULL) {
sigveseb 9:ba0527c6b6d0 255 LOG_ERROR("Unable to malloc array of characteristics for service creation. Possibly out of memory!\n");
sigveseb 9:ba0527c6b6d0 256 }
sigveseb 3:5432b38585ea 257 for(int i = 0; i < characteristicsLength; i++) {
sigveseb 3:5432b38585ea 258 characteristics[i] = service->getCharacteristic(i);
sigveseb 3:5432b38585ea 259 }
sigveseb 3:5432b38585ea 260 services.erase(services.begin() + removeIndex);
sigveseb 3:5432b38585ea 261 delete service;
stiaje 4:91506772210d 262 free(previousCharacteristics);
sigveseb 3:5432b38585ea 263 } else {
sigveseb 3:5432b38585ea 264 characteristicsLength = 1;
sigveseb 3:5432b38585ea 265 characteristics = (GattCharacteristic**) malloc(sizeof(GattCharacteristic*) * characteristicsLength);
sigveseb 9:ba0527c6b6d0 266 if(characteristics == NULL) {
sigveseb 9:ba0527c6b6d0 267 LOG_ERROR("Unable to malloc array of characteristics for service creation. Possibly out of memory!\n");
sigveseb 9:ba0527c6b6d0 268 }
sigveseb 3:5432b38585ea 269 }
sigveseb 9:ba0527c6b6d0 270
sigveseb 3:5432b38585ea 271 characteristics[characteristicsLength - 1] = characteristic;
stiaje 4:91506772210d 272 previousCharacteristics = characteristics;
sigveseb 3:5432b38585ea 273 service = new GattService(serviceUuid, characteristics, characteristicsLength);
sigveseb 3:5432b38585ea 274 services.push_back(service);
sigveseb 9:ba0527c6b6d0 275 LOG_DEBUG("Added characteristic.\n");
sigveseb 3:5432b38585ea 276 }
sigveseb 3:5432b38585ea 277
sigveseb 8:49ffd38fb401 278 void Puck::updateCharacteristicValue(const UUID uuid, uint8_t* value, int length) {
sigveseb 8:49ffd38fb401 279 GattCharacteristic* characteristic = NULL;
aleksanb 14:9eda2d99fc1d 280 for(int i = 0; i < characteristics.size(); i++) {
aleksanb 14:9eda2d99fc1d 281 GattAttribute &gattAttribute = characteristics[i]->getValueAttribute();
aleksanb 14:9eda2d99fc1d 282 if(isEqualUUID(&gattAttribute.getUUID(), uuid)) {
sigveseb 8:49ffd38fb401 283 characteristic = characteristics[i];
aleksanb 14:9eda2d99fc1d 284 break;
aleksanb 14:9eda2d99fc1d 285 }
sigveseb 8:49ffd38fb401 286 }
sigveseb 8:49ffd38fb401 287 if(characteristic != NULL) {
aleksanb 14:9eda2d99fc1d 288 ble.updateCharacteristicValue(characteristic->getValueHandle(), value, length);
sigveseb 8:49ffd38fb401 289 LOG_VERBOSE("Updated characteristic value.\n");
sigveseb 8:49ffd38fb401 290 } else {
sigveseb 8:49ffd38fb401 291 LOG_WARN("Tried to update an unkown characteristic!\n");
sigveseb 8:49ffd38fb401 292 }
sigveseb 8:49ffd38fb401 293 }
sigveseb 8:49ffd38fb401 294
sigveseb 3:5432b38585ea 295 bool Puck::drive() {
aleksanb 14:9eda2d99fc1d 296 if(state == DISCONNECTED) {
aleksanb 14:9eda2d99fc1d 297 startAdvertising();
aleksanb 14:9eda2d99fc1d 298 }
aleksanb 14:9eda2d99fc1d 299
sigveseb 3:5432b38585ea 300 ble.waitForEvent();
aleksanb 14:9eda2d99fc1d 301
sigveseb 3:5432b38585ea 302 while(pendingCallbackStack.size() > 0) {
sigveseb 3:5432b38585ea 303 pendingCallbackStack.back()(pendingCallbackParameterStack.back());
sigveseb 3:5432b38585ea 304 pendingCallbackStack.pop_back();
sigveseb 3:5432b38585ea 305 pendingCallbackParameterStack.pop_back();
sigveseb 3:5432b38585ea 306 }
sigveseb 3:5432b38585ea 307 return true;
sigveseb 3:5432b38585ea 308 }
sigveseb 3:5432b38585ea 309
sigveseb 3:5432b38585ea 310
sigveseb 9:ba0527c6b6d0 311 void Puck::onCharacteristicWrite(const UUID* uuid, CharacteristicWriteCallback callback) {
sigveseb 3:5432b38585ea 312 CharacteristicWriteCallbacks* cb = NULL;
sigveseb 3:5432b38585ea 313 for(int i = 0; i< writeCallbacks.size(); i++) {
sigveseb 9:ba0527c6b6d0 314 if(isEqualUUID(writeCallbacks[i]->uuid, *uuid)) {
sigveseb 3:5432b38585ea 315 cb = writeCallbacks[i];
sigveseb 3:5432b38585ea 316 break;
sigveseb 3:5432b38585ea 317 }
sigveseb 3:5432b38585ea 318 }
sigveseb 3:5432b38585ea 319 if(cb == NULL) {
sigveseb 3:5432b38585ea 320 cb = (CharacteristicWriteCallbacks*) malloc(sizeof(CharacteristicWriteCallbacks));
sigveseb 9:ba0527c6b6d0 321 if(cb == NULL) {
sigveseb 9:ba0527c6b6d0 322 LOG_ERROR("Could not malloc CharacteristicWriteCallbacks container. Possibly out of memory!\n");
sigveseb 9:ba0527c6b6d0 323 }
sigveseb 9:ba0527c6b6d0 324 cb->uuid = uuid;
sigveseb 3:5432b38585ea 325 cb->callbacks = new std::vector<CharacteristicWriteCallback>();
sigveseb 3:5432b38585ea 326 writeCallbacks.push_back(cb);
sigveseb 3:5432b38585ea 327 }
sigveseb 3:5432b38585ea 328 cb->callbacks->push_back(callback);
sigveseb 3:5432b38585ea 329 LOG_VERBOSE("Bound characteristic write callback (uuid: %x, callback: %x)\n", uuid, callback);
sigveseb 3:5432b38585ea 330 }
sigveseb 3:5432b38585ea 331
sigveseb 3:5432b38585ea 332
sigveseb 3:5432b38585ea 333 uint8_t* Puck::getCharacteristicValue(const UUID uuid) {
sigveseb 3:5432b38585ea 334 LOG_VERBOSE("Reading characteristic value for UUID %x\n", uuid);
sigveseb 3:5432b38585ea 335 for(int i = 0; i < characteristics.size(); i++) {
aleksanb 14:9eda2d99fc1d 336 GattAttribute &gattAttribute = characteristics[i]->getValueAttribute();
aleksanb 14:9eda2d99fc1d 337 if(isEqualUUID(&gattAttribute.getUUID(), uuid)) {
aleksanb 14:9eda2d99fc1d 338 return gattAttribute.getValuePtr();
sigveseb 3:5432b38585ea 339 }
sigveseb 3:5432b38585ea 340 }
sigveseb 3:5432b38585ea 341 LOG_WARN("Tried to read an unknown characteristic!");
sigveseb 3:5432b38585ea 342 return NULL;
sigveseb 3:5432b38585ea 343 }
sigveseb 3:5432b38585ea 344
sigveseb 3:5432b38585ea 345
sigveseb 3:5432b38585ea 346 void Puck::onDataWritten(uint16_t handle) {
sigveseb 3:5432b38585ea 347 for (int i = 0; i < characteristics.size(); i++) {
sigveseb 3:5432b38585ea 348 GattCharacteristic* characteristic = characteristics[i];
aleksanb 14:9eda2d99fc1d 349
aleksanb 14:9eda2d99fc1d 350 if (characteristic->getValueHandle() == handle) {
aleksanb 14:9eda2d99fc1d 351 GattAttribute &gattAttribute = characteristic->getValueAttribute();
aleksanb 14:9eda2d99fc1d 352
sigveseb 3:5432b38585ea 353 for(int j = 0; j < writeCallbacks.size(); j++) {
sigveseb 3:5432b38585ea 354 CharacteristicWriteCallbacks* characteristicWriteCallbacks = writeCallbacks[j];
aleksanb 14:9eda2d99fc1d 355
aleksanb 14:9eda2d99fc1d 356 if(isEqualUUID(characteristicWriteCallbacks->uuid, gattAttribute.getUUID())) {
sigveseb 3:5432b38585ea 357 for(int k = 0; k < characteristicWriteCallbacks->callbacks->size(); k++) {
sigveseb 3:5432b38585ea 358 pendingCallbackStack.push_back(characteristicWriteCallbacks->callbacks->at(k));
aleksanb 14:9eda2d99fc1d 359 pendingCallbackParameterStack.push_back(gattAttribute.getValuePtr());
sigveseb 3:5432b38585ea 360 }
sigveseb 9:ba0527c6b6d0 361 return;
sigveseb 3:5432b38585ea 362 }
sigveseb 3:5432b38585ea 363 }
sigveseb 3:5432b38585ea 364 }
sigveseb 3:5432b38585ea 365 }
sigveseb 3:5432b38585ea 366 }
sigveseb 3:5432b38585ea 367
sigveseb 3:5432b38585ea 368
sigveseb 3:5432b38585ea 369 #endif // __PUCK_HPP__