示例#1
0
/**
 * 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");
}
示例#2
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();
}
示例#3
0
/**
 * @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;
}
示例#4
0
/**
 * 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");
}
示例#5
0
/*
    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();
    }
}
示例#6
0
/**
 * 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");
}
示例#7
0
/**
 * 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);
}
示例#8
0
/*
    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();
}
示例#9
0
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);
}
示例#10
0
/**
 * 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");
}
示例#11
0
/*
    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;
            }
        }
    }
}
示例#12
0
/**
 * 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");
}
示例#13
0
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
        }
    }
}
示例#14
0
/**
 * 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));
}
示例#15
0
/**
 * 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");
}
示例#16
0
/*
    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);
}
示例#17
0
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);
}
示例#18
0
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);
}
示例#19
0
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    ble.gap().startAdvertising(); // restart advertising
}