Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API nRF51822
Fork of Puck by
Puck.h@6:211ffef3b88e, 2014-07-23 (annotated)
- Committer:
- sigveseb
- Date:
- Wed Jul 23 14:34:21 2014 +0000
- Revision:
- 6:211ffef3b88e
- Parent:
- 5:2f2a2ac6b231
- Parent:
- 4:91506772210d
- Child:
- 7:c07c01c2a741
merge
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| sigveseb | 3:5432b38585ea | 1 | #ifndef __PUCK_HPP__ | 
| sigveseb | 3:5432b38585ea | 2 | #define __PUCK_HPP__ | 
| sigveseb | 3:5432b38585ea | 3 | |
| sigveseb | 3:5432b38585ea | 4 | #include "BLEDevice.h" | 
| sigveseb | 3:5432b38585ea | 5 | #include <vector> | 
| sigveseb | 3:5432b38585ea | 6 | |
| sigveseb | 3:5432b38585ea | 7 | |
| sigveseb | 3:5432b38585ea | 8 | #ifdef LOG_LEVEL_VERBOSE | 
| sigveseb | 3:5432b38585ea | 9 | #define __PUCK_LOG_LEVEL_VERBOSE__ | 
| sigveseb | 3:5432b38585ea | 10 | #endif | 
| sigveseb | 3:5432b38585ea | 11 | #ifdef LOG_LEVEL_DEBUG | 
| sigveseb | 3:5432b38585ea | 12 | #define __PUCK_LOG_LEVEL_DEBUG__ | 
| sigveseb | 3:5432b38585ea | 13 | #endif | 
| sigveseb | 3:5432b38585ea | 14 | #ifdef LOG_LEVEL_INFO | 
| sigveseb | 3:5432b38585ea | 15 | #define __PUCK_LOG_LEVEL_INFO__ | 
| sigveseb | 3:5432b38585ea | 16 | #endif | 
| sigveseb | 3:5432b38585ea | 17 | #ifdef LOG_LEVEL_WARN | 
| sigveseb | 3:5432b38585ea | 18 | #define __PUCK_LOG_LEVEL_WARN__ | 
| sigveseb | 3:5432b38585ea | 19 | #endif | 
| sigveseb | 3:5432b38585ea | 20 | #ifdef LOG_LEVEL_ERROR | 
| sigveseb | 3:5432b38585ea | 21 | #define __PUCK_LOG_LEVEL_ERROR__ | 
| sigveseb | 3:5432b38585ea | 22 | #endif | 
| sigveseb | 3:5432b38585ea | 23 | |
| sigveseb | 3:5432b38585ea | 24 | #ifdef __PUCK_LOG_LEVEL_VERBOSE__ | 
| sigveseb | 3:5432b38585ea | 25 | #define LOG_VERBOSE(fmt, ...) do { logger.printf("[V] "); logger.printf(fmt, ##__VA_ARGS__); } while(0) | 
| sigveseb | 3:5432b38585ea | 26 | #define __PUCK_LOG_LEVEL_DEBUG__ | 
| sigveseb | 3:5432b38585ea | 27 | #else | 
| sigveseb | 3:5432b38585ea | 28 | #define LOG_VERBOSE(fmt, ...) | 
| sigveseb | 3:5432b38585ea | 29 | #endif | 
| sigveseb | 3:5432b38585ea | 30 | |
| sigveseb | 3:5432b38585ea | 31 | #ifdef __PUCK_LOG_LEVEL_DEBUG__ | 
| sigveseb | 3:5432b38585ea | 32 | #define LOG_DEBUG(fmt, ...) do { logger.printf("[D] "); logger.printf(fmt, ##__VA_ARGS__); } while(0) | 
| sigveseb | 3:5432b38585ea | 33 | #define __PUCK_LOG_LEVEL_INFO__ | 
| sigveseb | 3:5432b38585ea | 34 | #else | 
| sigveseb | 3:5432b38585ea | 35 | #define LOG_DEBUG(fmt, ...) | 
| sigveseb | 3:5432b38585ea | 36 | #endif | 
| sigveseb | 3:5432b38585ea | 37 | |
| sigveseb | 3:5432b38585ea | 38 | #ifdef __PUCK_LOG_LEVEL_INFO__ | 
| sigveseb | 3:5432b38585ea | 39 | #define LOG_INFO(fmt, ...) do { logger.printf("[I] "); logger.printf(fmt, ##__VA_ARGS__); } while(0) | 
| sigveseb | 3:5432b38585ea | 40 | #define __PUCK_LOG_LEVEL_WARN__ | 
| sigveseb | 3:5432b38585ea | 41 | #else | 
| sigveseb | 3:5432b38585ea | 42 | #define LOG_INFO(fmt, ...) | 
| sigveseb | 3:5432b38585ea | 43 | #endif | 
| sigveseb | 3:5432b38585ea | 44 | |
| sigveseb | 3:5432b38585ea | 45 | #ifdef __PUCK_LOG_LEVEL_WARN__ | 
| sigveseb | 3:5432b38585ea | 46 | #define LOG_WARN(fmt, ...) do { logger.printf("![W] "); logger.printf(fmt, ##__VA_ARGS__); } while(0) | 
| sigveseb | 3:5432b38585ea | 47 | #define __PUCK_LOG_LEVEL_ERROR__ | 
| sigveseb | 3:5432b38585ea | 48 | #else | 
| sigveseb | 3:5432b38585ea | 49 | #define LOG_WARN(fmt, ...) | 
| sigveseb | 3:5432b38585ea | 50 | #endif | 
| sigveseb | 3:5432b38585ea | 51 | |
| sigveseb | 3:5432b38585ea | 52 | #ifdef __PUCK_LOG_LEVEL_ERROR__ | 
| sigveseb | 3:5432b38585ea | 53 | #define LOG_ERROR(fmt, ...) do { logger.printf("!![E] "); logger.printf(fmt, ##__VA_ARGS__); } while(0) | 
| sigveseb | 3:5432b38585ea | 54 | #else | 
| sigveseb | 3:5432b38585ea | 55 | #define LOG_ERROR(fmt, ...) | 
| sigveseb | 3:5432b38585ea | 56 | #endif | 
| sigveseb | 3:5432b38585ea | 57 | |
| sigveseb | 3:5432b38585ea | 58 | #ifdef __PUCK_LOG_LEVEL_ERROR__ | 
| sigveseb | 3:5432b38585ea | 59 | Serial logger(USBTX, USBRX); | 
| sigveseb | 3:5432b38585ea | 60 | #endif | 
| sigveseb | 3:5432b38585ea | 61 | |
| sigveseb | 3:5432b38585ea | 62 | |
| sigveseb | 3:5432b38585ea | 63 | enum PuckState { | 
| sigveseb | 3:5432b38585ea | 64 | CONNECTING, | 
| sigveseb | 3:5432b38585ea | 65 | CONNECTED, | 
| sigveseb | 3:5432b38585ea | 66 | ADVERTISING, | 
| sigveseb | 3:5432b38585ea | 67 | DISCONNECTED | 
| sigveseb | 3:5432b38585ea | 68 | }; | 
| sigveseb | 3:5432b38585ea | 69 | |
| sigveseb | 3:5432b38585ea | 70 | const UUID stringToUUID(const char* str); | 
| sigveseb | 3:5432b38585ea | 71 | |
| sigveseb | 3:5432b38585ea | 72 | typedef void (*CharacteristicWriteCallback)(uint8_t* value); | 
| sigveseb | 3:5432b38585ea | 73 | |
| sigveseb | 3:5432b38585ea | 74 | typedef struct { | 
| sigveseb | 3:5432b38585ea | 75 | const UUID* uuid; | 
| sigveseb | 3:5432b38585ea | 76 | std::vector<CharacteristicWriteCallback>* callbacks; | 
| sigveseb | 3:5432b38585ea | 77 | } CharacteristicWriteCallbacks; | 
| sigveseb | 3:5432b38585ea | 78 | |
| sigveseb | 3:5432b38585ea | 79 | |
| sigveseb | 3:5432b38585ea | 80 | class Puck { | 
| sigveseb | 3:5432b38585ea | 81 | private: | 
| sigveseb | 3:5432b38585ea | 82 | Puck() {} | 
| sigveseb | 3:5432b38585ea | 83 | Puck(const Puck&); | 
| sigveseb | 3:5432b38585ea | 84 | Puck& operator=(const Puck&); | 
| sigveseb | 3:5432b38585ea | 85 | |
| sigveseb | 3:5432b38585ea | 86 | BLEDevice ble; | 
| sigveseb | 3:5432b38585ea | 87 | uint8_t beaconPayload[25]; | 
| sigveseb | 3:5432b38585ea | 88 | PuckState state; | 
| sigveseb | 3:5432b38585ea | 89 | std::vector<GattService*> services; | 
| sigveseb | 3:5432b38585ea | 90 | std::vector<GattCharacteristic*> characteristics; | 
| sigveseb | 3:5432b38585ea | 91 | std::vector<CharacteristicWriteCallbacks*> writeCallbacks; | 
| sigveseb | 3:5432b38585ea | 92 | std::vector<CharacteristicWriteCallback> pendingCallbackStack; | 
| sigveseb | 3:5432b38585ea | 93 | std::vector<uint8_t*> pendingCallbackParameterStack; | 
| sigveseb | 3:5432b38585ea | 94 | |
| stiaje | 4:91506772210d | 95 | GattCharacteristic **previousCharacteristics; | 
| stiaje | 4:91506772210d | 96 | |
| sigveseb | 3:5432b38585ea | 97 | public: | 
| sigveseb | 3:5432b38585ea | 98 | static Puck &getPuck(); | 
| sigveseb | 3:5432b38585ea | 99 | |
| stiaje | 5:2f2a2ac6b231 | 100 | BLEDevice &getBle() { return ble; } | 
| sigveseb | 3:5432b38585ea | 101 | PuckState getState() { return state; } | 
| sigveseb | 3:5432b38585ea | 102 | void setState(PuckState state); | 
| sigveseb | 3:5432b38585ea | 103 | void init(uint16_t minor); | 
| sigveseb | 3:5432b38585ea | 104 | void startAdvertising(); | 
| sigveseb | 3:5432b38585ea | 105 | void stopAdvertising(); | 
| sigveseb | 3:5432b38585ea | 106 | bool drive(); | 
| sigveseb | 3:5432b38585ea | 107 | void onDataWritten(uint16_t handle); | 
| sigveseb | 3:5432b38585ea | 108 | void addCharacteristic(const UUID serviceUuid, const UUID characteristicUuid, int bytes, int properties = 0xA); | 
| sigveseb | 3:5432b38585ea | 109 | void onCharacteristicWrite(const UUID uuid, CharacteristicWriteCallback callback); | 
| sigveseb | 3:5432b38585ea | 110 | uint8_t* getCharacteristicValue(const UUID uuid); | 
| sigveseb | 3:5432b38585ea | 111 | }; | 
| sigveseb | 3:5432b38585ea | 112 | |
| sigveseb | 3:5432b38585ea | 113 | Puck &Puck::getPuck() { | 
| sigveseb | 3:5432b38585ea | 114 | static Puck _puckSingletonInstance; | 
| sigveseb | 3:5432b38585ea | 115 | return _puckSingletonInstance; | 
| sigveseb | 3:5432b38585ea | 116 | } | 
| sigveseb | 3:5432b38585ea | 117 | |
| sigveseb | 3:5432b38585ea | 118 | |
| sigveseb | 3:5432b38585ea | 119 | void onDisconnection(void) { | 
| sigveseb | 3:5432b38585ea | 120 | LOG_INFO("Disconnected.\n"); | 
| sigveseb | 3:5432b38585ea | 121 | Puck::getPuck().setState(DISCONNECTED); | 
| sigveseb | 3:5432b38585ea | 122 | } | 
| sigveseb | 3:5432b38585ea | 123 | |
| sigveseb | 3:5432b38585ea | 124 | void onConnection(void) { | 
| sigveseb | 3:5432b38585ea | 125 | LOG_INFO("Connected.\n"); | 
| sigveseb | 3:5432b38585ea | 126 | Puck::getPuck().setState(CONNECTED); | 
| sigveseb | 3:5432b38585ea | 127 | } | 
| sigveseb | 3:5432b38585ea | 128 | |
| sigveseb | 3:5432b38585ea | 129 | void onDataWrittenCallback(uint16_t handle) { | 
| sigveseb | 3:5432b38585ea | 130 | Puck::getPuck().onDataWritten(handle); | 
| sigveseb | 3:5432b38585ea | 131 | } | 
| sigveseb | 3:5432b38585ea | 132 | |
| sigveseb | 3:5432b38585ea | 133 | bool isEqualUUID(const UUID* uuidA, const UUID uuidB) { | 
| sigveseb | 3:5432b38585ea | 134 | const uint8_t* uuidABase = uuidA->getBaseUUID(); | 
| sigveseb | 3:5432b38585ea | 135 | const uint8_t* uuidBBase = uuidB.getBaseUUID(); | 
| sigveseb | 3:5432b38585ea | 136 | if(uuidA->getShortUUID() != uuidB.getShortUUID()) { | 
| sigveseb | 3:5432b38585ea | 137 | return false; | 
| sigveseb | 3:5432b38585ea | 138 | } | 
| sigveseb | 3:5432b38585ea | 139 | for(int i = 0; i < 16; i++) { | 
| sigveseb | 3:5432b38585ea | 140 | if(uuidABase[i] != uuidBBase[i]) { | 
| sigveseb | 3:5432b38585ea | 141 | return false; | 
| sigveseb | 3:5432b38585ea | 142 | } | 
| sigveseb | 3:5432b38585ea | 143 | } | 
| sigveseb | 3:5432b38585ea | 144 | return true; | 
| sigveseb | 3:5432b38585ea | 145 | } | 
| sigveseb | 3:5432b38585ea | 146 | |
| sigveseb | 3:5432b38585ea | 147 | const UUID stringToUUID(const char* str) { | 
| sigveseb | 3:5432b38585ea | 148 | uint8_t array[16]; | 
| sigveseb | 3:5432b38585ea | 149 | for(int i = 0; i < 16; i++) { | 
| sigveseb | 3:5432b38585ea | 150 | array[i] = str[i]; | 
| sigveseb | 3:5432b38585ea | 151 | } | 
| sigveseb | 3:5432b38585ea | 152 | return UUID(array); | 
| sigveseb | 3:5432b38585ea | 153 | } | 
| sigveseb | 3:5432b38585ea | 154 | |
| sigveseb | 3:5432b38585ea | 155 | void Puck::setState(PuckState state) { | 
| sigveseb | 3:5432b38585ea | 156 | LOG_DEBUG("Changed state to %i\n", state); | 
| sigveseb | 3:5432b38585ea | 157 | this->state = state; | 
| sigveseb | 3:5432b38585ea | 158 | } | 
| sigveseb | 3:5432b38585ea | 159 | |
| sigveseb | 3:5432b38585ea | 160 | void Puck::init(uint16_t minor) { | 
| sigveseb | 3:5432b38585ea | 161 | /* | 
| sigveseb | 3:5432b38585ea | 162 | * The Beacon payload (encapsulated within the MSD advertising data structure) | 
| sigveseb | 3:5432b38585ea | 163 | * has the following composition: | 
| sigveseb | 3:5432b38585ea | 164 | * 128-Bit UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 | 
| sigveseb | 3:5432b38585ea | 165 | * Major/Minor = 1337 / XXXX | 
| sigveseb | 3:5432b38585ea | 166 | * Tx Power = C8 | 
| sigveseb | 3:5432b38585ea | 167 | */ | 
| sigveseb | 3:5432b38585ea | 168 | uint8_t beaconPayloadTemplate[] = { | 
| sigveseb | 3:5432b38585ea | 169 | 0x00, 0x00, // Company identifier code (0x004C == Apple) | 
| sigveseb | 3:5432b38585ea | 170 | 0x02, // ID | 
| sigveseb | 3:5432b38585ea | 171 | 0x15, // length of the remaining payload | 
| sigveseb | 3:5432b38585ea | 172 | 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, // UUID | 
| sigveseb | 3:5432b38585ea | 173 | 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61, | 
| sigveseb | 3:5432b38585ea | 174 | 0x13, 0x37, // the major value to differenciate a location (Our app requires 1337 as major number) | 
| sigveseb | 3:5432b38585ea | 175 | 0x00, 0x00, // the minor value to differenciate a location (Change this to differentiate location pucks) | 
| sigveseb | 3:5432b38585ea | 176 | 0xC8 // 2's complement of the Tx power (-56dB) | 
| sigveseb | 3:5432b38585ea | 177 | }; | 
| sigveseb | 3:5432b38585ea | 178 | beaconPayloadTemplate[22] = minor >> 8; | 
| sigveseb | 3:5432b38585ea | 179 | beaconPayloadTemplate[23] = minor & 255; | 
| sigveseb | 3:5432b38585ea | 180 | |
| sigveseb | 3:5432b38585ea | 181 | for (int i=0; i < 25; i++) { | 
| sigveseb | 3:5432b38585ea | 182 | beaconPayload[i] = beaconPayloadTemplate[i]; | 
| sigveseb | 3:5432b38585ea | 183 | } | 
| sigveseb | 3:5432b38585ea | 184 | |
| sigveseb | 3:5432b38585ea | 185 | ble.init(); | 
| sigveseb | 3:5432b38585ea | 186 | LOG_VERBOSE("Inited BLEDevice.\n"); | 
| sigveseb | 3:5432b38585ea | 187 | setState(DISCONNECTED); | 
| sigveseb | 3:5432b38585ea | 188 | |
| sigveseb | 3:5432b38585ea | 189 | ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); | 
| sigveseb | 3:5432b38585ea | 190 | LOG_VERBOSE("Accumulate advertising payload: BREDR_NOT_SUPPORTED.\n"); | 
| sigveseb | 3:5432b38585ea | 191 | |
| sigveseb | 3:5432b38585ea | 192 | ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, beaconPayload, sizeof(beaconPayload)); | 
| sigveseb | 3:5432b38585ea | 193 | LOG_VERBOSE("Accumulate advertising payload: beacon data.\n"); | 
| sigveseb | 3:5432b38585ea | 194 | |
| sigveseb | 3:5432b38585ea | 195 | ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); | 
| sigveseb | 3:5432b38585ea | 196 | LOG_VERBOSE("Setting advertising type: ADV_CONNECTABLE_UNDIRECTED.\n"); | 
| sigveseb | 3:5432b38585ea | 197 | |
| sigveseb | 3:5432b38585ea | 198 | int hundredMillisecondsInAdvertisingIntervalFormat = 160; | 
| sigveseb | 3:5432b38585ea | 199 | ble.setAdvertisingInterval(hundredMillisecondsInAdvertisingIntervalFormat); | 
| sigveseb | 3:5432b38585ea | 200 | LOG_VERBOSE("Set advertising interval: 160 (100 ms).\n"); | 
| sigveseb | 3:5432b38585ea | 201 | |
| sigveseb | 3:5432b38585ea | 202 | ble.onDisconnection(onDisconnection); | 
| sigveseb | 3:5432b38585ea | 203 | ble.onConnection(onConnection); | 
| sigveseb | 3:5432b38585ea | 204 | ble.onDataWritten(onDataWrittenCallback); | 
| sigveseb | 3:5432b38585ea | 205 | |
| sigveseb | 3:5432b38585ea | 206 | for(int i = 0; i < services.size(); i++) { | 
| sigveseb | 3:5432b38585ea | 207 | ble.addService(*services[i]); | 
| sigveseb | 3:5432b38585ea | 208 | LOG_VERBOSE("Added service %x to BLEDevice\n", services[i]); | 
| sigveseb | 3:5432b38585ea | 209 | } | 
| sigveseb | 3:5432b38585ea | 210 | |
| sigveseb | 3:5432b38585ea | 211 | LOG_INFO("Inited puck as 0x%X.\n", minor); | 
| sigveseb | 3:5432b38585ea | 212 | } | 
| sigveseb | 3:5432b38585ea | 213 | |
| sigveseb | 3:5432b38585ea | 214 | void Puck::startAdvertising() { | 
| sigveseb | 3:5432b38585ea | 215 | ble.startAdvertising(); | 
| sigveseb | 3:5432b38585ea | 216 | LOG_INFO("Starting to advertise.\n"); | 
| sigveseb | 3:5432b38585ea | 217 | setState(ADVERTISING); | 
| sigveseb | 3:5432b38585ea | 218 | } | 
| sigveseb | 3:5432b38585ea | 219 | |
| sigveseb | 3:5432b38585ea | 220 | void Puck::stopAdvertising() { | 
| sigveseb | 3:5432b38585ea | 221 | if(state == ADVERTISING) { | 
| sigveseb | 3:5432b38585ea | 222 | ble.stopAdvertising(); | 
| sigveseb | 3:5432b38585ea | 223 | LOG_INFO("Stopped advertising.\n"); | 
| sigveseb | 3:5432b38585ea | 224 | setState(DISCONNECTED); | 
| sigveseb | 3:5432b38585ea | 225 | } else { | 
| sigveseb | 3:5432b38585ea | 226 | LOG_WARN("Tried to stop advertising, but advertising is already stopped!\n"); | 
| sigveseb | 3:5432b38585ea | 227 | } | 
| sigveseb | 3:5432b38585ea | 228 | } | 
| sigveseb | 3:5432b38585ea | 229 | |
| sigveseb | 3:5432b38585ea | 230 | |
| sigveseb | 3:5432b38585ea | 231 | void Puck::addCharacteristic(const UUID serviceUuid, const UUID characteristicUuid, int bytes, int properties) { | 
| sigveseb | 3:5432b38585ea | 232 | MBED_ASSERT(bytes <= 20); | 
| sigveseb | 3:5432b38585ea | 233 | |
| sigveseb | 3:5432b38585ea | 234 | uint16_t size = sizeof(uint8_t) * bytes; | 
| sigveseb | 3:5432b38585ea | 235 | uint8_t* value = (uint8_t*) malloc(size); | 
| sigveseb | 3:5432b38585ea | 236 | GattCharacteristic* characteristic = new GattCharacteristic(characteristicUuid, value, size, size, properties); | 
| sigveseb | 3:5432b38585ea | 237 | characteristics.push_back(characteristic); | 
| sigveseb | 3:5432b38585ea | 238 | GattService* service = NULL; | 
| sigveseb | 3:5432b38585ea | 239 | int removeIndex = -1; | 
| sigveseb | 3:5432b38585ea | 240 | for(int i = 0; i < services.size(); i++) { | 
| sigveseb | 3:5432b38585ea | 241 | if(isEqualUUID(&services[i]->getUUID(), serviceUuid)) { | 
| sigveseb | 3:5432b38585ea | 242 | service = services[i]; | 
| sigveseb | 3:5432b38585ea | 243 | removeIndex = i; | 
| sigveseb | 3:5432b38585ea | 244 | break; | 
| sigveseb | 3:5432b38585ea | 245 | } | 
| sigveseb | 3:5432b38585ea | 246 | } | 
| sigveseb | 3:5432b38585ea | 247 | GattCharacteristic** characteristics = NULL; | 
| sigveseb | 3:5432b38585ea | 248 | int characteristicsLength = 0; | 
| sigveseb | 3:5432b38585ea | 249 | if(service != NULL) { | 
| sigveseb | 3:5432b38585ea | 250 | characteristicsLength = service->getCharacteristicCount() + 1; | 
| sigveseb | 3:5432b38585ea | 251 | characteristics = (GattCharacteristic**) malloc(sizeof(GattCharacteristic*) * characteristicsLength); | 
| sigveseb | 3:5432b38585ea | 252 | for(int i = 0; i < characteristicsLength; i++) { | 
| sigveseb | 3:5432b38585ea | 253 | characteristics[i] = service->getCharacteristic(i); | 
| sigveseb | 3:5432b38585ea | 254 | } | 
| sigveseb | 3:5432b38585ea | 255 | services.erase(services.begin() + removeIndex); | 
| sigveseb | 3:5432b38585ea | 256 | delete service; | 
| stiaje | 4:91506772210d | 257 | free(previousCharacteristics); | 
| sigveseb | 3:5432b38585ea | 258 | } else { | 
| sigveseb | 3:5432b38585ea | 259 | characteristicsLength = 1; | 
| sigveseb | 3:5432b38585ea | 260 | characteristics = (GattCharacteristic**) malloc(sizeof(GattCharacteristic*) * characteristicsLength); | 
| sigveseb | 3:5432b38585ea | 261 | } | 
| sigveseb | 3:5432b38585ea | 262 | characteristics[characteristicsLength - 1] = characteristic; | 
| stiaje | 4:91506772210d | 263 | previousCharacteristics = characteristics; | 
| sigveseb | 3:5432b38585ea | 264 | service = new GattService(serviceUuid, characteristics, characteristicsLength); | 
| sigveseb | 3:5432b38585ea | 265 | services.push_back(service); | 
| sigveseb | 3:5432b38585ea | 266 | } | 
| sigveseb | 3:5432b38585ea | 267 | |
| sigveseb | 3:5432b38585ea | 268 | bool Puck::drive() { | 
| sigveseb | 3:5432b38585ea | 269 | ble.waitForEvent(); | 
| sigveseb | 3:5432b38585ea | 270 | if(state == DISCONNECTED) { | 
| sigveseb | 3:5432b38585ea | 271 | startAdvertising(); | 
| sigveseb | 3:5432b38585ea | 272 | } | 
| sigveseb | 3:5432b38585ea | 273 | while(pendingCallbackStack.size() > 0) { | 
| sigveseb | 3:5432b38585ea | 274 | LOG_VERBOSE("PendingCallbackStack size: %i\n", pendingCallbackStack.size()); | 
| sigveseb | 3:5432b38585ea | 275 | pendingCallbackStack.back()(pendingCallbackParameterStack.back()); | 
| sigveseb | 3:5432b38585ea | 276 | pendingCallbackStack.pop_back(); | 
| sigveseb | 3:5432b38585ea | 277 | pendingCallbackParameterStack.pop_back(); | 
| sigveseb | 3:5432b38585ea | 278 | LOG_VERBOSE("Callback fired\n"); | 
| sigveseb | 3:5432b38585ea | 279 | } | 
| sigveseb | 3:5432b38585ea | 280 | return true; | 
| sigveseb | 3:5432b38585ea | 281 | } | 
| sigveseb | 3:5432b38585ea | 282 | |
| sigveseb | 3:5432b38585ea | 283 | |
| sigveseb | 3:5432b38585ea | 284 | void Puck::onCharacteristicWrite(const UUID uuid, CharacteristicWriteCallback callback) { | 
| sigveseb | 3:5432b38585ea | 285 | CharacteristicWriteCallbacks* cb = NULL; | 
| sigveseb | 3:5432b38585ea | 286 | for(int i = 0; i< writeCallbacks.size(); i++) { | 
| sigveseb | 3:5432b38585ea | 287 | if(isEqualUUID(writeCallbacks[i]->uuid, uuid)) { | 
| sigveseb | 3:5432b38585ea | 288 | cb = writeCallbacks[i]; | 
| sigveseb | 3:5432b38585ea | 289 | break; | 
| sigveseb | 3:5432b38585ea | 290 | } | 
| sigveseb | 3:5432b38585ea | 291 | } | 
| sigveseb | 3:5432b38585ea | 292 | if(cb == NULL) { | 
| sigveseb | 3:5432b38585ea | 293 | cb = (CharacteristicWriteCallbacks*) malloc(sizeof(CharacteristicWriteCallbacks)); | 
| sigveseb | 3:5432b38585ea | 294 | cb->uuid = &uuid; | 
| sigveseb | 3:5432b38585ea | 295 | cb->callbacks = new std::vector<CharacteristicWriteCallback>(); | 
| sigveseb | 3:5432b38585ea | 296 | writeCallbacks.push_back(cb); | 
| sigveseb | 3:5432b38585ea | 297 | } | 
| sigveseb | 3:5432b38585ea | 298 | cb->callbacks->push_back(callback); | 
| sigveseb | 3:5432b38585ea | 299 | LOG_VERBOSE("Bound characteristic write callback (uuid: %x, callback: %x)\n", uuid, callback); | 
| sigveseb | 3:5432b38585ea | 300 | } | 
| sigveseb | 3:5432b38585ea | 301 | |
| sigveseb | 3:5432b38585ea | 302 | |
| sigveseb | 3:5432b38585ea | 303 | uint8_t* Puck::getCharacteristicValue(const UUID uuid) { | 
| sigveseb | 3:5432b38585ea | 304 | LOG_VERBOSE("Reading characteristic value for UUID %x\n", uuid); | 
| sigveseb | 3:5432b38585ea | 305 | for(int i = 0; i < characteristics.size(); i++) { | 
| sigveseb | 3:5432b38585ea | 306 | GattCharacteristic* characteristic = characteristics[i]; | 
| sigveseb | 3:5432b38585ea | 307 | if(isEqualUUID(&characteristic->getUUID(), uuid)) { | 
| sigveseb | 3:5432b38585ea | 308 | return characteristic->getValuePtr(); | 
| sigveseb | 3:5432b38585ea | 309 | } | 
| sigveseb | 3:5432b38585ea | 310 | } | 
| sigveseb | 3:5432b38585ea | 311 | LOG_WARN("Tried to read an unknown characteristic!"); | 
| sigveseb | 3:5432b38585ea | 312 | return NULL; | 
| sigveseb | 3:5432b38585ea | 313 | } | 
| sigveseb | 3:5432b38585ea | 314 | |
| sigveseb | 3:5432b38585ea | 315 | |
| sigveseb | 3:5432b38585ea | 316 | void Puck::onDataWritten(uint16_t handle) { | 
| sigveseb | 3:5432b38585ea | 317 | for (int i = 0; i < characteristics.size(); i++) { | 
| sigveseb | 3:5432b38585ea | 318 | GattCharacteristic* characteristic = characteristics[i]; | 
| sigveseb | 3:5432b38585ea | 319 | if (characteristic->getHandle() == handle) { | 
| sigveseb | 3:5432b38585ea | 320 | uint16_t maxLength = characteristic->getMaxLength(); | 
| sigveseb | 3:5432b38585ea | 321 | ble.readCharacteristicValue(handle, characteristic->getValuePtr(), &maxLength); | 
| sigveseb | 3:5432b38585ea | 322 | for(int j = 0; j < writeCallbacks.size(); j++) { | 
| sigveseb | 3:5432b38585ea | 323 | CharacteristicWriteCallbacks* characteristicWriteCallbacks = writeCallbacks[j]; | 
| sigveseb | 3:5432b38585ea | 324 | if(isEqualUUID(characteristicWriteCallbacks->uuid, characteristic->getUUID())) { | 
| sigveseb | 3:5432b38585ea | 325 | for(int k = 0; k < characteristicWriteCallbacks->callbacks->size(); k++) { | 
| sigveseb | 3:5432b38585ea | 326 | pendingCallbackStack.push_back(characteristicWriteCallbacks->callbacks->at(k)); | 
| sigveseb | 3:5432b38585ea | 327 | pendingCallbackParameterStack.push_back(characteristic->getValuePtr()); | 
| sigveseb | 3:5432b38585ea | 328 | } | 
| sigveseb | 3:5432b38585ea | 329 | } | 
| sigveseb | 3:5432b38585ea | 330 | return; | 
| sigveseb | 3:5432b38585ea | 331 | } | 
| sigveseb | 3:5432b38585ea | 332 | } | 
| sigveseb | 3:5432b38585ea | 333 | } | 
| sigveseb | 3:5432b38585ea | 334 | } | 
| sigveseb | 3:5432b38585ea | 335 | |
| sigveseb | 3:5432b38585ea | 336 | |
| sigveseb | 3:5432b38585ea | 337 | |
| sigveseb | 3:5432b38585ea | 338 | #endif // __PUCK_HPP__ | 
