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

Fork of Puck by Nordic Pucks

Committer:
aleksanb
Date:
Mon Feb 23 15:25:22 2015 +0000
Revision:
14:9eda2d99fc1d
Parent:
13:93d3574e9e36
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__