/** * Test to change advertisement interval */ void changeIntervalTest(void) { ble.gap().setAdvertisingTimeout(0); ble.gap().setAdvertisingInterval(500); /* in milliseconds. */ ASSERT_NO_FAILURE(ble.gap().startAdvertising()); printf("ASSERTIONS DONE\r\n"); }
/** * Test of the ble shutdown function. Reinitializes and makes sure it */ void shutdownTest(void) { ASSERT_NO_FAILURE(ble.shutdown()); ASSERT_NO_FAILURE(ble.init()); ASSERT_NO_FAILURE(ble.gap().startAdvertising()); printf("ASSERTIONS DONE\r\n"); }
/** * @return 0 if basic assumptions are validated. Non-zero returns are used to * terminate the second-level python script early. */ unsigned verifyBasicAssumptions() { if (ble.init()) { return 1; } /* Read in the MAC address of this peripheral. The corresponding central will be * commanded to co-ordinate with this address. */ Gap::AddressType_t addressType; Gap::Address_t address; if (ble.gap().getAddress(&addressType, address)) { return 1; } /* TODO: if this fails, then bail out with a useful report. */ /* Check that the state is one of the valid values. */ Gap::GapState_t state = ble.gap().getState(); if ((state.connected == 1) || (state.advertising == 1)) { printf("{{failure}} ble.gap().getState() at line %u\r\n", __LINE__); /* writing out {{failure}} will halt the host test runner. */ return 1; } const char *version = ble.getVersion(); printf("%s\r\n", version); printf("{{success}}\r\n"); return 0; }
/** * Callback triggered when the ble initialization process has finished */ void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) { BLE& ble = params->ble; ble_error_t error = params->error; if (error != BLE_ERROR_NONE) { // in case of error, forward the error handling to onBleInitError onBleInitError(ble, error); return; } // ensure that it is the default instance of BLE if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { return; } /** * The Beacon payload has the following composition: * 128-Bit / 16byte UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 * Major/Minor = 0x1122 / 0x3344 * Tx Power = 0xC8 = 200, 2's compliment is 256-200 = (-56dB) * * Note: please remember to calibrate your beacons TX Power for more accurate results. */ const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61}; uint16_t majorNumber = 1122; uint16_t minorNumber = 3344; uint16_t txPower = 0xC8; iBeacon ibeacon(ble, uuid, majorNumber, minorNumber, txPower); ble.gap().setAdvertisingInterval(1000); /* 1000ms. */ ble.gap().startAdvertising(); }
void app_start(int, char *[]) { ble.init(); ble.onDisconnection(disconnectionCallback); /* * Load parameters from (platform specific) persistent storage. Parameters * can be set to non-default values while the URIBeacon is in configuration * mode (within the first 60 seconds of power-up). Thereafter, parameters * get copied out to persistent storage before switching to normal URIBeacon * operation. */ bool fetchedFromPersistentStorage = loadURIBeaconConfigParams(¶ms); /* Initialize a URIBeaconConfig service providing config params, default URI, and power levels. */ static URIBeaconConfigService::PowerLevels_t defaultAdvPowerLevels = {-20, -4, 0, 10}; // Values for ADV packets related to firmware levels uriBeaconConfig = new URIBeaconConfigService(ble, params, !fetchedFromPersistentStorage, "http://uribeacon.org", defaultAdvPowerLevels); if (!uriBeaconConfig->configuredSuccessfully()) { error("failed to accommodate URI"); } // Setup auxiliary services to allow over-the-air firmware updates, etc DFUService *dfu = new DFUService(ble); DeviceInformationService *deviceInfo = new DeviceInformationService(ble, "ARM", "UriBeacon", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); ble.startAdvertising(); /* Set the whole thing in motion. After this call a GAP central can scan the URIBeaconConfig * service. This can then be switched to the normal URIBeacon functionality after a timeout. */ /* Post a timeout callback to be invoked in ADVERTISEMENT_TIMEOUT_SECONDS to affect the switch to beacon mode. */ minar::Scheduler::postCallback(timeout).delay(minar::milliseconds(CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS * 1000)); }
/** * Test to change advertisement timeout. */ void setTimeoutTest(void) { ble.gap().clearAdvertisingPayload(); ble.gap().clearScanResponse(); ble.gap().setAdvertisingTimeout(5); /* 5 seconds */ ASSERT_NO_FAILURE(ble.gap().startAdvertising()); printf("ASSERTIONS DONE\r\n"); }
/** * Stop advertising the UriBeaconConfig Service after a delay; and switch to normal URIBeacon. */ void timeout(void) { Gap::GapState_t state; state = ble.getGapState(); if (!state.connected) { /* don't switch if we're in a connected state. */ uriBeaconConfig->setupURIBeaconAdvertisements(); ble.startAdvertising(); } else { minar::Scheduler::postCallback(timeout).delay(minar::milliseconds(CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS * 1000)); } }
void initializeSecurity(BLE &ble) { bool enableBonding = true; bool requireMITM = HID_SECURITY_REQUIRE_MITM; ble.securityManager().onSecuritySetupInitiated(securitySetupInitiatedCallback); ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback); ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); ble.securityManager().init(enableBonding, requireMITM, HID_SECURITY_IOCAPS); }
/* Start or stop scanning. Device becomes central. */ void button1ISR() { if (!scanning) { scanning = true; printf("start scan\r\n"); ble.gap().setScanParams(1000, 1000); ble.gap().startScan(advertisementCallback); } else { scanning = false; printf("stop scan\r\n"); ble.gap().stopScan(); } }
/** * Test for setting and getting MAC address */ void setAddrTest(void) { Gap::AddressType_t addressType; Gap::Address_t origAddress; ble.gap().getAddress(&addressType, origAddress); const static Gap::Address_t newAddress = {110, 100, 100, 100, 100, 100}; /* A randomly chosen address for assigning to the peripheral. */ ASSERT_NO_FAILURE(ble.gap().setAddress(Gap::ADDR_TYPE_PUBLIC, newAddress)); Gap::Address_t fetchedAddress; ASSERT_NO_FAILURE(ble.gap().getAddress(&addressType, fetchedAddress)); printf("ASSERTIONS DONE\r\n"); printf("%d:%d:%d:%d:%d:%d\n", newAddress[0], newAddress[1], newAddress[2], newAddress[3], newAddress[4], newAddress[5]); printf("%d:%d:%d:%d:%d:%d\n", fetchedAddress[0], fetchedAddress[1], fetchedAddress[2], fetchedAddress[3], fetchedAddress[4], fetchedAddress[5]); ble.gap().setAddress(Gap::ADDR_TYPE_PUBLIC, origAddress); }
/* Function called when BLE device has been disconnected. */ void whenDisconnected(Gap::Handle_t, Gap::DisconnectionReason_t) { printf("main: Disconnected!\r\n"); printf("main: Restarting the advertising process\r\n"); watch->stop(); watch->reset(); ble.gap().startAdvertising(); }
void initializeHOGP(BLE &ble) { static const uint16_t uuid16_list[] = {GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, GattService::UUID_DEVICE_INFORMATION_SERVICE, GattService::UUID_BATTERY_SERVICE}; DeviceInformationService deviceInfo(ble, "ARM", "m1", "abc", "def", "ghi", "jkl"); BatteryService batteryInfo(ble, 80); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // see 5.1.2: HID over GATT Specification (pg. 25) ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // 30ms to 50ms is recommended (5.1.2) ble.gap().setAdvertisingInterval(50); }
/** * Test for advertising using an iBeacon */ void setupIBeaconTest(void) { /* setup the iBeacon */ const static uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61}; uint16_t majorNumber = 1122; uint16_t minorNumber = 3344; uint16_t txPower = 0xC8; iBeacon ibeacon(ble, uuid, majorNumber, minorNumber, txPower); uint16_t interval_value = 1000; ble.gap().setAdvertisingInterval(interval_value); /* 1000ms. */ CHECK_EQUALS(ble.gap().getAdvertisingParams().getInterval(), interval_value); ble.gap().setAdvertisingTimeout(0); CHECK_EQUALS(ble.gap().getAdvertisingParams().getTimeout(), 0); ASSERT_NO_FAILURE(ble.gap().startAdvertising()); printf("ASSERTIONS DONE\r\n"); }
/* Handler for when advertisement beacons are received. */ void advertisementCallback(const Gap::AdvertisementCallbackParams_t* params) { #if VERBOSE_DEBUG_OUTPUT printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n", params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type); #endif // scan through advertisement data for (uint8_t idx = 0; idx < params->advertisingDataLen; ) { uint8_t fieldLength = params->advertisingData[idx]; uint8_t fieldType = params->advertisingData[idx + 1]; const uint8_t* fieldValue = &(params->advertisingData[idx + 2]); idx += fieldLength + 1; // find 16-bit service IDs if ((fieldType == GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS) || (fieldType == GapAdvertisingData::INCOMPLETE_LIST_16BIT_SERVICE_IDS)) { // compare short UUID UUID beaconUUID((fieldValue[1] << 8) | fieldValue[0]); if (beaconUUID == uuid) { // set lowest latency for fastest transfer Gap::ConnectionParams_t fast; ble.gap().getPreferredConnectionParams(&fast); fast.minConnectionInterval = 16; // 20 ms fast.maxConnectionInterval = 32; // 40 ms fast.slaveLatency = 0; // connect to peripheral, this stops the scanning ble.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, &fast, NULL); break; } } } }
/** * Test to change advertisement payload */ void changePayloadTest(void) { ble.gap().clearAdvertisingPayload(); ble.gap().setAdvertisingTimeout(0); ASSERT_NO_FAILURE(ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::LE_GENERAL_DISCOVERABLE | GapAdvertisingData::BREDR_NOT_SUPPORTED)); ASSERT_NO_FAILURE(ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::OUTDOOR_GENERIC)); ASSERT_NO_FAILURE(ble.gap().accumulateAdvertisingPayloadTxPower(10)); /* in dbm. */ const static uint8_t trivialAdvPayload[] = {123, 123, 123, 123, 123}; ASSERT_NO_FAILURE(ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, trivialAdvPayload, sizeof(trivialAdvPayload))); ble.gap().setAdvertisingInterval(500); /* in milliseconds. */ ASSERT_NO_FAILURE(ble.gap().startAdvertising()); printf("ASSERTIONS DONE\r\n"); }
/** * Test to change add a scan response */ void responseTest(void) { ble.gap().clearAdvertisingPayload(); ble.gap().clearScanResponse(); ble.gap().setAdvertisingTimeout(0); ble.setAdvertisingType(GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED); const static uint8_t trivialAdvPayload[] = {50, 50, 50, 50, 50}; ASSERT_NO_FAILURE(ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, trivialAdvPayload, sizeof(trivialAdvPayload))); const static uint8_t trivialScanResponse[] = {50, 50, 50, 50, 50}; ASSERT_NO_FAILURE(ble.gap().accumulateScanResponse(GapAdvertisingData::SERVICE_DATA, trivialScanResponse, sizeof(trivialScanResponse))); ble.gap().setAdvertisingInterval(500); /* in units of milliseconds. */ ASSERT_NO_FAILURE(ble.gap().startAdvertising()); printf("ASSERTIONS DONE\r\n"); }
/** * Reset function run after every test. */ void resetStateForNextTest(void) { ble.gap().stopAdvertising(); ble.gap().clearAdvertisingPayload(); ble.gap().clearScanResponse(); ble.gap().setAdvertisingTimeout(0); ble.gap().setAdvertisingInterval(1000); const static uint8_t trivialAdvPayload[] = {0, 0, 0, 0, 0}; ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, trivialAdvPayload, sizeof(trivialAdvPayload)); }
void WrittenHandler(const GattWriteCallbackParams *Handler) { uint8_t buf[TXRX_BUF_LEN]; uint16_t bytesRead; if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) { ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), buf, &bytesRead); memset(txPayload, 0, TXRX_BUF_LEN); memcpy(txPayload, buf, TXRX_BUF_LEN); if(bytesRead>=3) { Motor1.write(txPayload[0]>100?0:1); Motor2.write(txPayload[1]>100?0:1); Led1.write(txPayload[2]>100?0:1); Led2.write(txPayload[2]>100?0:1); } } }
int main(void) { app_start(0, NULL); for(;;) { // send notification outside of interrupt context if (sendHello) { ble_error_t result = bts->updateCharacteristicValue((const uint8_t*)"hello", 5); if (result == BLE_ERROR_NONE) { sendHello = false; } } ble.waitForEvent(); } }
/* Handler called when Block Transfer Client Read completes. */ void clientReadDone(Block* block) { printf("main: read done\r\n"); #if VERBOSE_DEBUG_OUTPUT // print block content for (std::size_t idx = 0; idx < block->getLength(); idx++) { printf("%02X", block->at(idx)); } printf("\r\n"); #endif // compare read and write block bool matches = true; if (block->getLength() != writeBlock.getLength()) { matches = false; } else { for (std::size_t idx = 0; idx < block->getLength(); idx++) { matches = matches && (block->at(idx) == writeBlock.at(idx)); } } if (matches) { printf("main: buffers match\r\n"); } else { printf("main: buffers differ\r\n"); } // disconnect ble.gap().disconnect(connectionHandle, Gap::REMOTE_USER_TERMINATED_CONNECTION); }
void app_start(int, char*[]) { unsigned errorCode = verifyBasicAssumptions(); printf("{{end}}\r\n"); // tells mbedhtrun to finish and hand control over to the second level python script. /* Synchronize with the second python script--wait for something to arrive on the console. */ unsigned syncer; scanf("%d",&syncer); if (errorCode) { printf("Initial basic assumptions failed\r\n"); /* this will halt the second level python script. */ return; } /* Refetch the address to write out to the console. */ Gap::Address_t address; Gap::AddressType_t addressType; ASSERT_NO_FAILURE(ble.gap().getAddress(&addressType, address)); printf("%d:%d:%d:%d:%d:%d\n", address[0], address[1], address[2], address[3], address[4], address[5]); /* sends the MAC address to the host PC. */ /* Setup console input handler to allow command interpretation. */ console.attach(serialHandler); }
void app_start(int, char *[]) { buffer = (uint8_t*)malloc(24); memset(buffer, 0, 24); console.attach(serialHandler); printf("{{end}}\r\n"); // setup buttons // button1.mode(PullUp); // Delay for initial pullup to take effect wait(.01); // button1.fall(button1ISR); // button2.mode(PullUp); // Delay for initial pullup to take effect wait(.01); // button2.fall(button2ISR); /*************************************************************************/ /*************************************************************************/ /* bluetooth le */ ble.init(); // security ble.securityManager().onSecuritySetupInitiated(securityInitiated); ble.securityManager().onSecuritySetupCompleted(securityCompleted); ble.securityManager().onLinkSecured(linkSecured); ble.securityManager().onSecurityContextStored(contextStored); ble.securityManager().onPasskeyDisplay(passkeyDisplay); // connection status handlers ble.gap().onConnection(whenConnected); ble.gap().onDisconnection(whenDisconnected); // set preferred connection parameters to lowest latency Gap::ConnectionParams_t fast; ble.gap().getPreferredConnectionParams(&fast); fast.minConnectionInterval = 16; // 20 ms fast.maxConnectionInterval = 32; // 40 ms fast.slaveLatency = 0; ble.gap().setPreferredConnectionParams(&fast); /* construct advertising beacon */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED|GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME) - 1); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, uuid.getBaseUUID(), uuid.getLen()); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(200); // Apple uses device name instead of beacon name ble.gap().setDeviceName((const uint8_t*) DEVICE_NAME); // ble setup complete - start advertising ble.gap().startAdvertising(); /*************************************************************************/ /*************************************************************************/ bts = new BlockTransferService(); btc = new BlockTransferClient(); watch = new Timer(); bts->init(uuid, SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK); #if 0 writeBlock.push_back(&writeBlockFragment2); writeBlock.push_back(&writeBlockFragment3); writeBlock.push_back(&writeBlockFragment4); #endif // set callback functions bts->setWriteAuthorizationCallback(blockServerWriteHandler, &receiveBlock); bts->setReadAuthorizationCallback(blockServerReadHandler); printf("BlockTransfer: %s %s %d\r\n", __DATE__, __TIME__, MAX_INDEX_SET_SIZE); }
int main(void) { ble.init(); ble.onDisconnection(disconnectionCallback); ble.onDataWritten(WrittenHandler); // setup advertising ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_PHONE); ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)NAME, sizeof(NAME) - 1); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid)); ble.setAdvertisingPayload(); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.setActiveScan(false); ble.setAdvertisingInterval(100); ble.addService(uartService); ble.startAdvertising(); while(1) { ble.waitForEvent(); } }
/** * Callback triggered upon a disconnection event. Needs to re-enable advertisements. */ void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) { ble.startAdvertising(); }
int main(void) { led1 = 1; Ticker ticker; ticker.attach(periodicCallback, 1); // blink LED every second ble.init(); ble.gap().onDisconnection(disconnectionCallback); /* Setup primary service. */ uint8_t hrmCounter = 100; // init HRM to 100bps HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER); /* Setup auxiliary service. */ DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); /* Setup advertising. */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); 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 */ ble.gap().startAdvertising(); // 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 } } }
void app_start(int argc, char *argv[]) { ble.init(bleInitComplete); }
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { ble.gap().startAdvertising(); // restart advertising }