init
Dependencies: BLE_API mbed nRF51822
Diff: main.cpp
- Revision:
- 2:95c770f35636
- Parent:
- 1:4bdebb81dcd5
--- a/main.cpp Mon Jul 27 07:30:47 2015 +0000 +++ b/main.cpp Mon Aug 17 09:49:55 2015 +0000 @@ -20,167 +20,197 @@ #include "ble/services/BatteryService.h" #include "ble/services/DeviceInformationService.h" #include "LEDService.h" - -#define BLE_CHECK(X) (X == BLE_ERROR_NONE) ? (printf("{{success}}\r\n")) : printf("{{failure}} %s at line %u ERROR CODE: %u\r\n", #X, __LINE__, (X)); -#define BLE_EQUAL(X,Y) ((X)==(Y)) ? (printf("{{sucess}}\n")) : printf("{{failure}}\n"); +#include "ButtonService.h" -BLE ble; -DigitalOut led1(LED1); -Gap::Address_t address; -Gap::AddressType_t *addressType; +#define ASSERT_NO_FAILURE(CMD) do { \ + ble_error_t error = (CMD); \ + if (error == BLE_ERROR_NONE){ \ + printf("{{success}}\r\n"); \ + } else{ \ + printf("{{failure}} %s at line %u ERROR CODE: %u\r\n", #CMD, __LINE__, (error)); \ + return; \ + } \ + }while (0) +#define CHECK_EQUALS(X,Y) ((X)==(Y)) ? (printf("{{success}}\r\n")) : printf("{{failure}}\r\n"); -const static char DEVICE_NAME[] = "HRMTEST"; -static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE, - GattService::UUID_DEVICE_INFORMATION_SERVICE, - LEDService::LED_SERVICE_UUID}; -static volatile bool triggerSensorPolling = false; +BLE ble; +Gap::Address_t address; +GapAdvertisingData::Appearance appearance; + +const static char DEVICE_NAME[] = "HRMTEST"; +static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE, + GattService::UUID_DEVICE_INFORMATION_SERVICE, + LEDService::LED_SERVICE_UUID}; + +ButtonService *btnServicePtr; void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { ble.gap().startAdvertising(); // restart advertising } -void periodicCallback(void) -{ - led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ - - /* Note that the periodicCallback() executes in interrupt context, so it is safer to do - * heavy-weight sensor polling from the main thread. */ +void connectionCallback(const Gap::ConnectionCallbackParams_t *params){ + printf("Connected to: %d:%d:%d:%d:%d:%d\n", + params->peerAddr[0], params->peerAddr[1], params->peerAddr[2], params->peerAddr[3], params->peerAddr[4], params->peerAddr[5]); } -void connectionCallback(const Gap::ConnectionCallbackParams_t *params){ - printf("Connected to: %d:%d:%d:%d:%d:%d\n", params->peerAddr[0], params->peerAddr[1], params->peerAddr[2], params->peerAddr[3], params->peerAddr[4], params->peerAddr[5]); - -} - -void dataReadCallback(const GattReadCallbackParams *params){ - printf("%d\n", params->data[1]); -} - -void testDeviceName(){ - if (ble.gap().getState().connected){ +void testDeviceName() +{ + if (ble.gap().getState().connected) { printf("Device must be disconnected\n"); return; } - uint8_t deviceName[10]; - uint8_t deviceNameIn[] = {0x4A, 0x4F, 0x53, 0x48, 0x54, 0x45, 0x53, 0x54, 0x00}; - unsigned length = 10; - BLE_CHECK(ble.gap().setDeviceName(deviceNameIn)); + + uint8_t deviceNameIn[] = "Josh-test"; + ASSERT_NO_FAILURE(ble.gap().setDeviceName(deviceNameIn)); wait(0.5); - BLE_CHECK(ble.gap().getDeviceName(deviceName, &length)); - wait(0.5); - for (int i = 0; i < length; i++){ - printf("%02x ", deviceName[i]); + + const size_t MAX_DEVICE_NAME_LEN = 50; + uint8_t deviceName[MAX_DEVICE_NAME_LEN]; + unsigned length = MAX_DEVICE_NAME_LEN; + ASSERT_NO_FAILURE(ble.gap().getDeviceName(deviceName, &length)); + printf("ASSERTIONS DONE\r\n"); + for (unsigned i = 0; i < length; i++) { + printf("%c", deviceName[i]); } printf("\r\n"); - for (int i = 0; i < 8; i++){ - printf("%02x ", deviceNameIn[i]); + for (unsigned i = 0; i < strlen((char *)deviceNameIn); i++) { + printf("%c", deviceNameIn[i]); } printf("\r\n"); } -void testAppearance(){ - if ((ble.gap().getState().connected)){ +void testAppearance() +{ + if ((ble.gap().getState().connected)) { printf("Device must be disconnected\n"); return; } - GapAdvertisingData::Appearance appearance; - BLE_CHECK(ble.gap().setAppearance(GapAdvertisingData::GENERIC_PHONE)); - wait(0.5); - BLE_CHECK(ble.gap().getAppearance(&appearance)); - wait(0.5); - printf("%d\r\n",appearance); -} -void connParams(){ - if ((ble.gap().getState().connected)){ + ASSERT_NO_FAILURE(ble.gap().setAppearance(GapAdvertisingData::GENERIC_PHONE)); + ASSERT_NO_FAILURE(ble.gap().getAppearance(&appearance)); + printf("ASSERTIONS DONE\r\n"); + printf("%d\r\n", appearance); +} + +void connParams() +{ + if ((ble.gap().getState().connected)) { printf("Device must be disconnected\n"); return; } + Gap::ConnectionParams_t params; - Gap::ConnectionParams_t paramsOut = {50,500,0,500}; + Gap::ConnectionParams_t paramsOut = {50, 500, 0, 500}; Gap::ConnectionParams_t temp; - BLE_CHECK(ble.gap().getPreferredConnectionParams(&temp)); - BLE_CHECK(ble.gap().setPreferredConnectionParams(¶msOut)); + + ASSERT_NO_FAILURE(ble.gap().getPreferredConnectionParams(&temp)); + ASSERT_NO_FAILURE(ble.gap().setPreferredConnectionParams(¶msOut)); + + printf("ASSERTIONS DONE\r\n"); + ble.gap().getPreferredConnectionParams(¶ms); + printf("%d\n", params.minConnectionInterval); printf("%d\n", params.maxConnectionInterval); printf("%d\n", params.slaveLatency); printf("%d\n", params.connectionSupervisionTimeout); + ble.gap().setPreferredConnectionParams(&temp); - -} +} + +void notificationTest(void) { + btnServicePtr->updateButtonState(true); +} + +void commandInterpreter(void) +{ + const static size_t MAX_SIZEOF_COMMAND = 50; + while (true) { + char command[MAX_SIZEOF_COMMAND]; + scanf("%s", command); + + if (!strcmp(command, "setDeviceName")) { + testDeviceName(); + } else if (!strcmp(command, "appearance")) { + testAppearance(); + } else if (!strcmp(command, "connParam")) { + connParams(); + } else if (!strcmp(command, "notification")) { + notificationTest(); + } + } +} -void commandInterpreter(void){ - char command[50]; - while(1){ - scanf("%s", command); - if (!strcmp(command, "setDeviceName")) testDeviceName(); - else if (!strcmp(command, "setAppearance")) testAppearance(); - else if (!strcmp(command, "testConnectionParams")) connParams(); +/** + * @return 0 if basic assumptions are validated. Non-zero returns are used to + * terminate the second-level python script early. + */ +unsigned verifyBasicAssumptions() +{ + ble.gap().onDisconnection(disconnectionCallback); + ble.gap().onConnection(connectionCallback); + + /* Setup advertising. */ + if (ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE)) { + return 1; + } + if (ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list))) { + return 1; } + if (ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR)) { + return 1; + } + if (ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME))) { + return 1; + } + ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.gap().setAdvertisingInterval(1000); /* 1000ms */ + + if (ble.gap().startAdvertising()) { + return 1; + } + + const char *version = ble.getVersion(); + printf("%s\r\n", version); + if (!strcmp(version, "")) return 1; + return 0; } int main(void) { - led1 = 1; - Ticker ticker; - ticker.attach(periodicCallback, 1); // blink LED every second - - BLE_CHECK(ble.init()); - ble.gap().onDisconnection(disconnectionCallback); - ble.gap().onConnection(connectionCallback); - /* Setup primary service. */ - uint8_t hrmCounter = 100; // init HRM to 100bps - HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER); - - bool initialValueForLEDCharacteristic = false; - LEDService ledService(ble, initialValueForLEDCharacteristic); + unsigned errorCode = ble.init(); + if (errorCode == 0) { + uint8_t hrmCounter = 100; // init HRM to 100bps + HeartRateService *hrService = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER); + + bool initialValueForLEDCharacteristic = false; + LEDService *ledService = new LEDService(ble, initialValueForLEDCharacteristic); - /* Setup auxiliary service. */ - DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); + DeviceInformationService *deviceInfo = new DeviceInformationService(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); + + btnServicePtr = new ButtonService(ble, false); + } + errorCode |= verifyBasicAssumptions(); + if (errorCode == 0) { + printf("{{success}}\r\n{{end}}\r\n"); /* hand over control from the host test to the python script. */ + } else { + printf("{{failure}}\r\n{{end}}\r\n"); /* hand over control from the host test to the python script. */ + } - /* Setup advertising. */ - BLE_CHECK(ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE)); - BLE_CHECK(ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list))); - BLE_CHECK(ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR)); - BLE_CHECK(ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME))); - ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); - ble.gap().setAdvertisingInterval(1000); /* 1000ms */ + unsigned synchronize; + scanf("%u", &synchronize); - BLE_CHECK(ble.gap().startAdvertising()); - BLE_CHECK(ble.gap().getAddress(addressType, address)); - printf("{{success}}" "\n" "{{end}}" "\n"); - int x; - scanf("%d" , &x); + if (errorCode != 0) { + printf("Initial basic assumptions failed\r\n"); + return -1; + } + + Gap::AddressType_t addressType; + ASSERT_NO_FAILURE(ble.gap().getAddress(&addressType, address)); + + /* write out the MAC address to allow the second level python script to target this device. */ printf("%d:%d:%d:%d:%d:%d\n", address[0], address[1], address[2], address[3], address[4], address[5]); + commandInterpreter(); -/* - scanf("%d", &x); - testDeviceName(); - //printf("%d\n",ble.gattServer().onDataRead(dataReadCallback)); - scanf("%d", &x); - testAppearance(); - scanf("%d", &x); - connParams(); - // infinite loop - while (1) { - // check for trigger from periodicCallback() - if (triggerSensorPolling && ble.getGapState().connected) { - triggerSensorPolling = false; - - // Do blocking calls or whatever is necessary for sensor polling. - // In our case, we simply update the HRM measurement. - hrmCounter++; - // 100 <= HRM bps <=175 - if (hrmCounter == 175) { - hrmCounter = 100; - } - // update bps - hrService.updateHeartRate(hrmCounter); - } else { - ble.waitForEvent(); // low power wait for event - } - } -*/ }