aaaa

Dependencies:   mbed

Fork of mbed-os-example-ble-EddystoneObserver by mbed-os-examples

source/main.cpp

Committer:
fbdp1202
Date:
2017-06-12
Revision:
33:d83bd71e5d82
Parent:
29:083b9a2cb114
Child:
34:b2d964ce740f

File content as of revision 33:d83bd71e5d82:

/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <events/mbed_events.h>
#include "mbed.h"
#include "ble/BLE.h"
#include "ble/DiscoveredCharacteristic.h" 
#include "ble/DiscoveredService.h" 
#include "ble/services/HeartRateService.h" 


//static const int URI_MAX_LENGTH = 18;             // Maximum size of service data in ADV packets

static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
static const char PEER_NAME[] = "HRM"; 
static DiscoveredCharacteristic ledCharacteristic; 
static bool triggerLedCharacteristic; 

DigitalOut led1(LED1, 1);

ReadOnlyGattCharacteristic<uint32_t> readFrom(uuid, valuePtr,
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);

void periodicCallback(void)
{
    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
}

//void decodeURI(const uint8_t* uriData, const size_t uriLen)
//{
//    const char *prefixes[] = {
//        "http://www.",
//        "https://www.",
//        "http://",
//        "https://",
//        "urn:uuid:"
//    };
//    const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
//    const char *suffixes[] = {
//        ".com/",
//        ".org/",
//        ".edu/",
//        ".net/",
//        ".info/",
//        ".biz/",
//        ".gov/",
//        ".com",
//        ".org",
//        ".edu",
//        ".net",
//        ".info",
//        ".biz",
//        ".gov"
//    };
//    const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
//
//    size_t index = 0;
//
//    /* First byte is the URL Scheme. */
//    if (uriData[index] < NUM_PREFIXES) {
//        printf("%s", prefixes[uriData[index]]);
//        index++;
//    } else {
//        printf("URL Scheme was not encoded!");
//        return;
//    }
//
//    /* From second byte onwards we can have a character or a suffix */
//    while(index < uriLen) {
//        if (uriData[index] < NUM_SUFFIXES) {
//            printf("%s", suffixes[uriData[index]]);
//        } else {
//            printf("%c", uriData[index]);
//        }
//        index++;
//    }
//
//    printf("\n\r");
//}

void serviceDiscoveryCallback(const DiscoveredService *service) { 
    if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) { 
        printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle()); 
    } else { 
        printf("S UUID-"); 
        const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID(); 
        for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { 
            printf("%02x", longUUIDBytes[i]); 
        } 
        printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle()); 
    } 
} 

void updateLedCharacteristic(void) { 
    if (!BLE::Instance().gattClient().isServiceDiscoveryActive()) { 
        ledCharacteristic.read(); 
    } 
} 

void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) { 
    printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast()); 
    if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */ 
        ledCharacteristic        = *characteristicP; 
        triggerLedCharacteristic = true; 
    } 
} 

 void triggerToggledWrite(const GattReadCallbackParams *response) { 
    printf("triggerToggledWrite\n");
     if (response->handle == ledCharacteristic.getValueHandle()) { 
         printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len); 
         for (unsigned index = 0; index < response->len; index++) { 
             printf("%c[%02x]", response->data[index], response->data[index]); 
         } 
         printf("\r\n"); 
 

         uint8_t toggledValue = response->data[0] ^ 0x1; 
         ledCharacteristic.write(1, &toggledValue); 
     } 
 } 
 

 void triggerRead(const GattWriteCallbackParams *response) { 
    printf("triggerRead\n");
     if (response->handle == ledCharacteristic.getValueHandle()) { 
         ledCharacteristic.read(); 
     } 
 } 
 
/*
 * This function is called every time we scan an advertisement.
 */
void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
{
//    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 
//    ); 
//    struct AdvertisingData_t {
//        uint8_t                        length; /* doesn't include itself */
//        GapAdvertisingData::DataType_t dataType;
//        uint8_t                        data[1];
//    } AdvDataPacket;
//
//    struct ApplicationData_t {
//        uint8_t applicationSpecificId[2];
//        uint8_t frameType;
//        uint8_t advPowerLevels;
//        uint8_t uriData[URI_MAX_LENGTH];
//    } AppDataPacket;
//
//    const uint8_t BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)] = {0xAA, 0xFE};
//    const uint8_t FRAME_TYPE_URL                              = 0x10;
//    const uint8_t APPLICATION_DATA_OFFSET                     = sizeof(ApplicationData_t) + sizeof(AdvDataPacket.dataType) - sizeof(AppDataPacket.uriData);
//
//    AdvertisingData_t *pAdvData;
//    size_t index = 0;
//    while(index < params->advertisingDataLen) {
//        pAdvData = (AdvertisingData_t *)&params->advertisingData[index];
//        if (pAdvData->dataType == GapAdvertisingData::SERVICE_DATA) {
//            ApplicationData_t *pAppData = (ApplicationData_t *) pAdvData->data;
//            if (!memcmp(pAppData->applicationSpecificId, BEACON_UUID, sizeof(BEACON_UUID)) && (pAppData->frameType == FRAME_TYPE_URL)) {
//                decodeURI(pAppData->uriData, pAdvData->length - APPLICATION_DATA_OFFSET);
//                break;
//            }
//        }
//        index += (pAdvData->length + 1);
//    }

    for (uint8_t i = 0; i < params->advertisingDataLen; ++i) { 

        const uint8_t record_length = params->advertisingData[i]; 
        if (record_length == 0) { 
            continue; 
        } 
        const uint8_t type = params->advertisingData[i + 1]; 
        const uint8_t* value = params->advertisingData + i + 2; 
        const uint8_t value_length = record_length - 1; 


        if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) { 
            if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) { 
                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 
                ); 
                BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL); 
                break; 
            } 
        } 
        i += record_length; 
    }    
}

void discoveryTerminationCallback(Gap::Handle_t connectionHandle) { 
    printf("terminated SD for handle %u\r\n", connectionHandle); 
    if (triggerLedCharacteristic) { 
        triggerLedCharacteristic = false; 
        eventQueue.call(updateLedCharacteristic); 
    } 
} 

void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { 
    printf("connectionCallback\n");
    printf("params->role: %01x\n", params->role);
    if (params->role == Gap::CENTRAL) { 
        printf("ROLE: CENTRAL\n");
        BLE &ble = BLE::Instance(); 
        ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback); 
        ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, GattService::UUID_HEART_RATE_SERVICE, 0xa001); 
    } 
} 

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) { 
    printf("disconnected\r\n"); 
    /* Start scanning and try to connect again */ 
    BLE::Instance().gap().startScan(advertisementCallback); 
} 

void onBleInitError(BLE &ble, ble_error_t error)
{
   /* Initialization error handling should go here */
}

void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        onBleInitError(ble, error);
        return;
    }

    if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback); 
    ble.gap().onConnection(connectionCallback); 

    ble.gap().setScanParams(1800 /* scan interval */, 1500 /* scan window */);
    ble.gap().startScan(advertisementCallback);
}

void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
    BLE &ble = BLE::Instance();
    eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
}

int main()
{
    eventQueue.call_every(500, periodicCallback);

    BLE &ble = BLE::Instance();
    ble.onEventsToProcess(scheduleBleEventsProcessing);
    ble.init(bleInitComplete);

    eventQueue.dispatch_forever();

    return 0;
}