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:
sigveseb
Date:
Fri Feb 27 17:31:47 2015 +0000
Revision:
15:bfc682889c15
Parent:
14:9eda2d99fc1d
Child:
18:4c95a470d778
Update data write callbacks to use new BLE_API flow

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