init

Dependencies:   BLE_API mbed nRF51822

Committer:
jslater8
Date:
Mon Aug 17 09:50:14 2015 +0000
Revision:
3:88f7aa6c2a75
Parent:
2:2a2b4781cd8a
initial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jslater8 0:ef5229893eb9 1 /* mbed Microcontroller Library
jslater8 0:ef5229893eb9 2 * Copyright (c) 2006-2015 ARM Limited
jslater8 0:ef5229893eb9 3 *
jslater8 0:ef5229893eb9 4 * Licensed under the Apache License, Version 2.0 (the "License");
jslater8 0:ef5229893eb9 5 * you may not use this file except in compliance with the License.
jslater8 0:ef5229893eb9 6 * You may obtain a copy of the License at
jslater8 0:ef5229893eb9 7 *
jslater8 0:ef5229893eb9 8 * http://www.apache.org/licenses/LICENSE-2.0
jslater8 0:ef5229893eb9 9 *
jslater8 0:ef5229893eb9 10 * Unless required by applicable law or agreed to in writing, software
jslater8 0:ef5229893eb9 11 * distributed under the License is distributed on an "AS IS" BASIS,
jslater8 0:ef5229893eb9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
jslater8 0:ef5229893eb9 13 * See the License for the specific language governing permissions and
jslater8 0:ef5229893eb9 14 * limitations under the License.
jslater8 0:ef5229893eb9 15 */
jslater8 3:88f7aa6c2a75 16
jslater8 0:ef5229893eb9 17 #include "mbed.h"
jslater8 0:ef5229893eb9 18 #include "BLE.h"
jslater8 0:ef5229893eb9 19 #include "ble/DiscoveredCharacteristic.h"
jslater8 0:ef5229893eb9 20 #include "ble/DiscoveredService.h"
jslater8 0:ef5229893eb9 21 #define DUMP_ADV_DATA 0
jslater8 0:ef5229893eb9 22
jslater8 3:88f7aa6c2a75 23 #define ASSERT_NO_FAILURE(CMD) do { \
jslater8 3:88f7aa6c2a75 24 ble_error_t error = (CMD); \
jslater8 3:88f7aa6c2a75 25 if (error == BLE_ERROR_NONE){ \
jslater8 3:88f7aa6c2a75 26 printf("{{success}}\r\n"); \
jslater8 3:88f7aa6c2a75 27 } else{ \
jslater8 3:88f7aa6c2a75 28 printf("{{failure}} %s at line %u ERROR CODE: %u\r\n", #CMD, __LINE__, (error)); \
jslater8 3:88f7aa6c2a75 29 return; \
jslater8 3:88f7aa6c2a75 30 } \
jslater8 3:88f7aa6c2a75 31 }while (0)
jslater8 3:88f7aa6c2a75 32 #define CHECK_EQUALS(X,Y) ((X)==(Y)) ? (printf("{{success}}\r\n")) : printf("{{failure}}\r\n");
jslater8 0:ef5229893eb9 33
jslater8 3:88f7aa6c2a75 34 BLE ble;
jslater8 3:88f7aa6c2a75 35 Gap::Address_t address;
jslater8 2:2a2b4781cd8a 36
jslater8 0:ef5229893eb9 37 DiscoveredCharacteristic HRMCharacteristic;
jslater8 3:88f7aa6c2a75 38 bool HRMFound = false;
jslater8 1:30f1232e4c17 39 DiscoveredCharacteristic LEDCharacteristic;
jslater8 3:88f7aa6c2a75 40 bool LEDFound = false;
jslater8 3:88f7aa6c2a75 41 DiscoveredCharacteristic BTNCharacteristic;
jslater8 3:88f7aa6c2a75 42 bool BTNFound = false;
jslater8 2:2a2b4781cd8a 43 Gap::Handle_t deviceAHandle;
jslater8 0:ef5229893eb9 44
jslater8 0:ef5229893eb9 45
jslater8 3:88f7aa6c2a75 46 /*
jslater8 3:88f7aa6c2a75 47 * Call back when a service is discovered
jslater8 3:88f7aa6c2a75 48 */
jslater8 3:88f7aa6c2a75 49 void serviceDiscoveryCallback(const DiscoveredService *service)
jslater8 3:88f7aa6c2a75 50 {
jslater8 0:ef5229893eb9 51 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
jslater8 0:ef5229893eb9 52 printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
jslater8 0:ef5229893eb9 53 } else {
jslater8 0:ef5229893eb9 54 printf("S UUID-");
jslater8 0:ef5229893eb9 55 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
jslater8 0:ef5229893eb9 56 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
jslater8 0:ef5229893eb9 57 printf("%02x", longUUIDBytes[i]);
jslater8 0:ef5229893eb9 58 }
jslater8 0:ef5229893eb9 59 printf("attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
jslater8 0:ef5229893eb9 60 }
jslater8 0:ef5229893eb9 61 }
jslater8 0:ef5229893eb9 62
jslater8 3:88f7aa6c2a75 63 /*
jslater8 3:88f7aa6c2a75 64 * Call back when a characteristic is discovered
jslater8 3:88f7aa6c2a75 65 */
jslater8 3:88f7aa6c2a75 66 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP)
jslater8 3:88f7aa6c2a75 67 {
jslater8 3:88f7aa6c2a75 68 if (characteristicP->getUUID().getShortUUID() == 0x2a37) { /* Searches for HRM Characteristic*/
jslater8 3:88f7aa6c2a75 69 HRMCharacteristic = *characteristicP;
jslater8 3:88f7aa6c2a75 70 HRMFound = true;
jslater8 1:30f1232e4c17 71 }
jslater8 3:88f7aa6c2a75 72 if (characteristicP->getUUID().getShortUUID() == 0xA001) { /* Searches for LED Characteristic*/
jslater8 1:30f1232e4c17 73 LEDCharacteristic = *characteristicP;
jslater8 3:88f7aa6c2a75 74 LEDFound = true;
jslater8 3:88f7aa6c2a75 75 }
jslater8 3:88f7aa6c2a75 76 if (characteristicP->getUUID().getShortUUID() == 0xA003) {
jslater8 3:88f7aa6c2a75 77 BTNCharacteristic = *characteristicP;
jslater8 3:88f7aa6c2a75 78 BTNFound = true;
jslater8 0:ef5229893eb9 79 }
jslater8 0:ef5229893eb9 80 }
jslater8 0:ef5229893eb9 81
jslater8 3:88f7aa6c2a75 82 /*
jslater8 3:88f7aa6c2a75 83 * Call back when device is connected
jslater8 3:88f7aa6c2a75 84 */
jslater8 3:88f7aa6c2a75 85 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
jslater8 3:88f7aa6c2a75 86 {
jslater8 3:88f7aa6c2a75 87 printf("Connected to: %d:%d:%d:%d:%d:%d\n",
jslater8 3:88f7aa6c2a75 88 params->peerAddr[0], params->peerAddr[1], params->peerAddr[2], params->peerAddr[3], params->peerAddr[4], params->peerAddr[5]);
jslater8 0:ef5229893eb9 89 if (params->role == Gap::CENTRAL) {
jslater8 3:88f7aa6c2a75 90 deviceAHandle = params->handle; /* Handle for device A so it is it possible to disconnect*/
jslater8 3:88f7aa6c2a75 91 ASSERT_NO_FAILURE(ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback));
jslater8 0:ef5229893eb9 92 }
jslater8 0:ef5229893eb9 93 }
jslater8 0:ef5229893eb9 94
jslater8 3:88f7aa6c2a75 95 /*
jslater8 3:88f7aa6c2a75 96 * The callback for reading a characteristic, print depends on what characteristic is read
jslater8 3:88f7aa6c2a75 97 */
jslater8 3:88f7aa6c2a75 98 void readCharacteristic(const GattReadCallbackParams *response)
jslater8 3:88f7aa6c2a75 99 {
jslater8 0:ef5229893eb9 100 if (response->handle == HRMCharacteristic.getValueHandle()) {
jslater8 1:30f1232e4c17 101 printf("HRMCounter: %d\n", response->data[1]);
jslater8 1:30f1232e4c17 102 }
jslater8 1:30f1232e4c17 103 if (response->handle == LEDCharacteristic.getValueHandle()) {
jslater8 1:30f1232e4c17 104 printf("LED: %d\n", response->data[0]);
jslater8 3:88f7aa6c2a75 105 }
jslater8 3:88f7aa6c2a75 106 if (response->handle == BTNCharacteristic.getValueHandle()) {
jslater8 3:88f7aa6c2a75 107 printf("BTN: %d\n", response->data[0]);
jslater8 3:88f7aa6c2a75 108 }
jslater8 3:88f7aa6c2a75 109 }
jslater8 3:88f7aa6c2a75 110
jslater8 3:88f7aa6c2a75 111 /*
jslater8 3:88f7aa6c2a75 112 * Tests connecting devices. Devices must be disconnected for this test
jslater8 3:88f7aa6c2a75 113 */
jslater8 3:88f7aa6c2a75 114 void connectTest()
jslater8 3:88f7aa6c2a75 115 {
jslater8 3:88f7aa6c2a75 116 if (!(ble.gap().getState().connected)) {
jslater8 3:88f7aa6c2a75 117 ASSERT_NO_FAILURE(ble.gap().connect(address, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL));
jslater8 3:88f7aa6c2a75 118 } else {
jslater8 3:88f7aa6c2a75 119 printf("Devices already connected\n");
jslater8 0:ef5229893eb9 120 }
jslater8 0:ef5229893eb9 121 }
jslater8 0:ef5229893eb9 122
jslater8 3:88f7aa6c2a75 123 /*
jslater8 3:88f7aa6c2a75 124 * Tests reading from to the heart rate characteristic. Devices need to be connected for this test.
jslater8 3:88f7aa6c2a75 125 */
jslater8 3:88f7aa6c2a75 126 void readTest(){
jslater8 3:88f7aa6c2a75 127 if (!(ble.gap().getState().connected)) {
jslater8 3:88f7aa6c2a75 128 printf("Devices must be connected before this test can be run\n");
jslater8 3:88f7aa6c2a75 129 return;
jslater8 1:30f1232e4c17 130 }
jslater8 3:88f7aa6c2a75 131 if (HRMFound) {
jslater8 3:88f7aa6c2a75 132 ASSERT_NO_FAILURE(HRMCharacteristic.read());
jslater8 3:88f7aa6c2a75 133 } else {
jslater8 3:88f7aa6c2a75 134 printf("Characteristic not found\r\n");
jslater8 3:88f7aa6c2a75 135 }
jslater8 0:ef5229893eb9 136 }
jslater8 0:ef5229893eb9 137
jslater8 3:88f7aa6c2a75 138 /**
jslater8 3:88f7aa6c2a75 139 * Tests writing to the LED Characteristic. Then reads from the callback to verify that the write is correct.
jslater8 3:88f7aa6c2a75 140 * Devices need to be connected for this test.
jslater8 3:88f7aa6c2a75 141 */
jslater8 3:88f7aa6c2a75 142 void writeTest()
jslater8 3:88f7aa6c2a75 143 {
jslater8 3:88f7aa6c2a75 144 if (!(ble.gap().getState().connected)) {
jslater8 1:30f1232e4c17 145 printf("Devices must be connected before this test can be run\n");
jslater8 1:30f1232e4c17 146 return;
jslater8 1:30f1232e4c17 147 }
jslater8 3:88f7aa6c2a75 148 if (LEDFound) {
jslater8 3:88f7aa6c2a75 149 uint8_t write_value = 1;
jslater8 3:88f7aa6c2a75 150 ASSERT_NO_FAILURE(LEDCharacteristic.write(sizeof(write_value), &write_value)); /* When write finishes, writeCallback is called */
jslater8 3:88f7aa6c2a75 151 } else {
jslater8 3:88f7aa6c2a75 152 printf("Characeristic not found\r\n");
jslater8 1:30f1232e4c17 153 }
jslater8 1:30f1232e4c17 154 }
jslater8 3:88f7aa6c2a75 155
jslater8 3:88f7aa6c2a75 156 /**
jslater8 3:88f7aa6c2a75 157 * Tests disconnecting devices. If it is already connected it prints a message
jslater8 3:88f7aa6c2a75 158 */
jslater8 3:88f7aa6c2a75 159 void disconnectTest()
jslater8 3:88f7aa6c2a75 160 {
jslater8 3:88f7aa6c2a75 161 if ((ble.gap().getState().connected)) {
jslater8 3:88f7aa6c2a75 162 ASSERT_NO_FAILURE(ble.gap().disconnect(deviceAHandle, Gap::REMOTE_USER_TERMINATED_CONNECTION));
jslater8 3:88f7aa6c2a75 163 } else {
jslater8 3:88f7aa6c2a75 164 printf("Devices not connected\n");
jslater8 3:88f7aa6c2a75 165 }
jslater8 3:88f7aa6c2a75 166 }
jslater8 3:88f7aa6c2a75 167
jslater8 3:88f7aa6c2a75 168 void notificationTest()
jslater8 3:88f7aa6c2a75 169 {
jslater8 3:88f7aa6c2a75 170 if (!ble.gap().getState().connected) {
jslater8 1:30f1232e4c17 171 printf("Devices must be connected before this test can be run\n");
jslater8 1:30f1232e4c17 172 return;
jslater8 1:30f1232e4c17 173 }
jslater8 3:88f7aa6c2a75 174 if (BTNFound) {
jslater8 3:88f7aa6c2a75 175 uint16_t value = BLE_HVX_NOTIFICATION;
jslater8 3:88f7aa6c2a75 176 ASSERT_NO_FAILURE(ble.gattClient().write(GattClient::GATT_OP_WRITE_REQ,
jslater8 3:88f7aa6c2a75 177 deviceAHandle,
jslater8 3:88f7aa6c2a75 178 BTNCharacteristic.getValueHandle() + 1, /* HACK Alert. We're assuming that CCCD descriptor immediately follows the value attribute. */
jslater8 3:88f7aa6c2a75 179 sizeof(uint16_t), /* HACK Alert! size should be made into a BLE_API constant. */
jslater8 3:88f7aa6c2a75 180 reinterpret_cast<const uint8_t *>(&value)));
jslater8 3:88f7aa6c2a75 181 } else {
jslater8 3:88f7aa6c2a75 182 printf("Characteristic not found\r\r");
jslater8 1:30f1232e4c17 183 }
jslater8 1:30f1232e4c17 184 }
jslater8 1:30f1232e4c17 185
jslater8 3:88f7aa6c2a75 186 /**
jslater8 3:88f7aa6c2a75 187 * Controls which tests are run from input from PC
jslater8 3:88f7aa6c2a75 188 */
jslater8 3:88f7aa6c2a75 189 void commandInterpreter()
jslater8 3:88f7aa6c2a75 190 {
jslater8 3:88f7aa6c2a75 191 char command[50];
jslater8 3:88f7aa6c2a75 192 while (true) {
jslater8 3:88f7aa6c2a75 193 scanf("%s", command); /* Takes a string from the host test and decides what test to use. */
jslater8 3:88f7aa6c2a75 194 if (!strcmp(command, "connect")) {
jslater8 3:88f7aa6c2a75 195 connectTest();
jslater8 3:88f7aa6c2a75 196 } else if (!strcmp(command, "disconnect")) {
jslater8 3:88f7aa6c2a75 197 disconnectTest();
jslater8 3:88f7aa6c2a75 198 } else if (!strcmp(command, "read")) {
jslater8 3:88f7aa6c2a75 199 readTest();
jslater8 3:88f7aa6c2a75 200 } else if (!strcmp(command, "write")) {
jslater8 3:88f7aa6c2a75 201 writeTest();
jslater8 3:88f7aa6c2a75 202 } else if (!strcmp(command, "notification")) {
jslater8 3:88f7aa6c2a75 203 notificationTest();
jslater8 3:88f7aa6c2a75 204 }
jslater8 1:30f1232e4c17 205 }
jslater8 1:30f1232e4c17 206 }
jslater8 1:30f1232e4c17 207
jslater8 3:88f7aa6c2a75 208 /**
jslater8 3:88f7aa6c2a75 209 * Call back for writing to LED characteristic.
jslater8 3:88f7aa6c2a75 210 */
jslater8 3:88f7aa6c2a75 211 void writeCallback(const GattWriteCallbackParams *params)
jslater8 3:88f7aa6c2a75 212 {
jslater8 3:88f7aa6c2a75 213 if (params->handle == LEDCharacteristic.getValueHandle()) {
jslater8 3:88f7aa6c2a75 214 ASSERT_NO_FAILURE(LEDCharacteristic.read());
jslater8 3:88f7aa6c2a75 215 } else if (params->handle == BTNCharacteristic.getValueHandle() + 1) {
jslater8 3:88f7aa6c2a75 216 printf("Sync\r\n");
jslater8 3:88f7aa6c2a75 217 }
jslater8 3:88f7aa6c2a75 218 }
jslater8 3:88f7aa6c2a75 219
jslater8 3:88f7aa6c2a75 220 void hvxCallback(const GattHVXCallbackParams *params) {
jslater8 3:88f7aa6c2a75 221 printf("Button: ");
jslater8 3:88f7aa6c2a75 222 for (unsigned index = 0; index < params->len; index++) {
jslater8 3:88f7aa6c2a75 223 printf("%02x", params->data[index]);
jslater8 3:88f7aa6c2a75 224 }
jslater8 3:88f7aa6c2a75 225 printf("\r\n");
jslater8 0:ef5229893eb9 226 }
jslater8 0:ef5229893eb9 227
jslater8 0:ef5229893eb9 228 int main(void)
jslater8 0:ef5229893eb9 229 {
jslater8 3:88f7aa6c2a75 230 printf("{{end}}\n"); /* Hands control over to Python script */
jslater8 3:88f7aa6c2a75 231 scanf("%hhu", &address[0]);
jslater8 3:88f7aa6c2a75 232 scanf("%hhu", &address[1]);
jslater8 3:88f7aa6c2a75 233 scanf("%hhu", &address[2]);
jslater8 3:88f7aa6c2a75 234 scanf("%hhu", &address[3]);
jslater8 3:88f7aa6c2a75 235 scanf("%hhu", &address[4]);
jslater8 3:88f7aa6c2a75 236 scanf("%hhu", &address[5]);
jslater8 3:88f7aa6c2a75 237
jslater8 3:88f7aa6c2a75 238 ASSERT_NO_FAILURE(ble.init());
jslater8 3:88f7aa6c2a75 239 ASSERT_NO_FAILURE(ble.gap().setScanParams(500 /* scan interval */, 200 /* scan window */));
jslater8 3:88f7aa6c2a75 240 printf("ASSERTIONS DONE\r\n");
jslater8 0:ef5229893eb9 241 ble.gap().onConnection(connectionCallback);
jslater8 3:88f7aa6c2a75 242 ble.gattClient().onDataRead(readCharacteristic);
jslater8 3:88f7aa6c2a75 243 ble.gattClient().onDataWrite(writeCallback);
jslater8 3:88f7aa6c2a75 244 ble.gattClient().onHVX(hvxCallback);
jslater8 1:30f1232e4c17 245 commandInterpreter();
jslater8 0:ef5229893eb9 246 }