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 Aug 11 09:42:01 2014 +0000
Revision:
13:93d3574e9e36
Parent:
12:8a8cc109f048
Child:
14:9eda2d99fc1d
Upgrade to newest BLE_API and nRF library.

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