Dependencies:   BLE_API mbed nRF51822

Fork of CoolTourHat by Karl Engelhardt

main.cpp

Committer:
pajowu
Date:
2017-03-05
Revision:
23:ba3d7a28096d
Parent:
22:406127954d1f
Child:
24:78ef9deab4bc

File content as of revision 23:ba3d7a28096d:

#include "mbed.h"
#include "ble/BLE.h"
#include "ble/BLEProtocol.h"
#include "ble/GapAdvertisingData.h"
#include "ble/DiscoveredService.h"
#include "ble/DiscoveredCharacteristic.h"

BLE &ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
Serial pc(USBTX, USBRX);
// Connect handle
uint16_t peripheral_handle = GattAttribute::INVALID_HANDLE;
uint16_t client_handle = GattAttribute::INVALID_HANDLE;

DiscoveredCharacteristic interests_other;
DiscoveredCharacteristic alarm_read_other;
DiscoveredCharacteristic alarm_write_other;

const uint8_t NRF_SUCCESS = 1;
const uint8_t NRF_ERROR_NOT_FOUND = 2;

uint16_t customServiceUUID  = 0x6f6c;
uint16_t interestUUID       = 0x0001;
uint16_t alertUUID          = 0x0002;
uint16_t alertReadUUID      = 0x0003;

const static char     DEVICE_NAME[]        = "CoolTourHat";
static const uint16_t uuid16_list[]        = {0xFFFF}; //Custom UUID, FFFF is reserved for development


static uint8_t interestValue[22] = {0x01, 0xFF};
ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(interestValue)> interestChar(interestUUID, interestValue);


static uint8_t alertValue[1] = {0};
WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(alertValue)> alarmChar(alertUUID, alertValue);
static uint8_t alertReadValue[1] = {0};
ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(alertReadValue)> readAlarmChar(alertReadUUID, alertReadValue);

/* Set up custom service */
GattCharacteristic *characteristics[] = {&interestChar, &alarmChar, &readAlarmChar};
GattService        customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));


/*
 *  Restart advertising when phone app disconnects
*/

void alarm() {
    pc.printf("ALARRRRM\r\n");
    wait(0.1);
}
void onAlarmWritten(const GattWriteCallbackParams *response) {
    alarm();
    alarm_write_other.write(1, (uint8_t[1]) {0x01}, onAlarmWritten);
}
void onDataRead(const GattReadCallbackParams *response) {
    if (response->len == 22) {
        bool a = false;
        for (unsigned i=0;i<=22;i++) {
            if (response->data[i] ^ interestValue[i] != 0)
                a = true;
        }
        if (a) {
            alarm_write_other.write(1, (uint8_t[1]) {0x01}, onAlarmWritten);
        }

    } else {
        pc.printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
        for (unsigned index = 0; index < response->len; index++) {
            pc.printf("%c[%02x]", response->data[index], response->data[index]);
        }
        pc.printf("\r\n");
    }
}
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
{
    BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
}


void discoveredServiceCallBack(const DiscoveredService *service) {
  pc.printf("\r\n----Servuce Discovered"); pc.printf("\n");

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


}

void discoveredCharacteristicCallBack(const DiscoveredCharacteristic *chars) {
  pc.printf("\r\n----Characteristic Discovered"); pc.printf("\n");
    pc.printf("Chars UUID type        : %x\n", chars->getUUID().shortOrLong()); pc.printf("\n");// 0 16bit_uuid, 1 128bit_uuid

    pc.printf("S UUID-%04x\r\n", chars->getUUID().getShortUUID());


  pc.printf("properties_read        : %d\n", chars->getProperties().read());
  pc.printf("properties_writeWoResp : %d\n", chars->getProperties().writeWoResp());
  pc.printf("properties_write       : %d\n", chars->getProperties().write());
  pc.printf("properties_notify      : %d\n", chars->getProperties().notify());

  pc.printf("declHandle             : %x\n", chars->getDeclHandle());
  pc.printf("valueHandle            : %x\n", chars->getValueHandle());
  pc.printf("lastHandle             : %x\n", chars->getLastHandle());
  if (chars->getUUID().getShortUUID() == 0x0001) {
    pc.printf("interests_other\n");
    interests_other = *chars;
  } else if (chars->getUUID().getShortUUID() == 0x0002) {
    pc.printf("alarm_write_other\n");
    alarm_write_other = *chars;
  } else if (chars->getUUID().getShortUUID() == 0x0003) {
    pc.printf("alarm_read_other\n");
    alarm_read_other = *chars;
    interests_other.read(0, onDataRead);
  }

}
void writeCharCallback(const GattWriteCallbackParams *params)
{
    if(params->handle == alarmChar.getValueHandle()) {
        if(params->len == 1 && params->data[0] == 0x01) {            
            pc.printf("alarm\n");
            static uint8_t v[1] = {0x01};
            BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(readAlarmChar.getValueHandle(), 
                v, sizeof(v));
            alarm();
            pc.printf("alarm stop\n");
            v[0] = 0x00;
            BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(readAlarmChar.getValueHandle(), v, sizeof(v));
        }
    }
}
uint32_t ble_advdata_parser(uint8_t type, uint8_t advdata_len, uint8_t *p_advdata, uint8_t *len, uint8_t *p_field_data) {
  uint8_t index=0;
  uint8_t field_length, field_type;

  while(index<advdata_len) {
    field_length = p_advdata[index];
    field_type   = p_advdata[index+1];
    if(field_type == type) {
      memcpy(p_field_data, &p_advdata[index+2], (field_length-1));
      *len = field_length - 1;
      return NRF_SUCCESS;
    }
    index += field_length + 1;
  }
  return NRF_ERROR_NOT_FOUND;
}
void scanCallBack(const Gap::AdvertisementCallbackParams_t *params) {
  pc.printf("Scan CallBack \n");
  pc.printf("PerrAddress: ");
  for(uint8_t index=0; index<6; index++) {
    pc.printf("%02x ", params->peerAddr[index]);
  }
  pc.printf("\n");
  pc.printf("The Rssi : ");
  pc.printf("%d\n", params->rssi);

  // Get local name in advertisement
  uint8_t len=0;
  uint8_t adv_name[31];
  if(NRF_SUCCESS == ble_advdata_parser(GapAdvertisingData::COMPLETE_LOCAL_NAME, params->advertisingDataLen, (uint8_t *)params->advertisingData, &len, adv_name)) {
    pc.printf("Complete name len : %d\n", len);
    pc.printf("Complete name is  : %s\n", (const char*)adv_name);
    if((len >= 10) && (memcmp("CoolTourHat", adv_name, 10) == 0x00)) {
      pc.printf("Find device, stop scanning and start connecting\n");
      ble.gap().stopScan();
      ble.connect(params->peerAddr, BLEProtocol::AddressType::RANDOM_STATIC, NULL, NULL);
    }
  }
}
void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
    pc.printf("terminated SD for handle %u\r\n", connectionHandle);
}
void connectionCallBack( const Gap::ConnectionCallbackParams_t *params ) {
  if(params->role == Gap::CENTRAL) {
    pc.printf("Central, connected to remote device\n");
    pc.printf("The conn handle : %x\n", params->handle);

    pc.printf("  The peerAddr : ");
    for(uint8_t index=6; index>0; index--) {
      pc.printf("%02x ", params->peerAddr[index-1]);
    }
    ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
    // Start to discovery
    ble.gattClient().launchServiceDiscovery(params->handle, discoveredServiceCallBack, discoveredCharacteristicCallBack, 0x6f6c);//, customServiceUUID, interestUUID);
  }
  else {
    pc.printf("peripheral, be connected by a central device\n");
    peripheral_handle = params->handle;
    pc.printf("The conn handle : %x\n", params->handle);
  }
}

void disconnectionCallBack(const Gap::DisconnectionCallbackParams_t *params) {
  pc.printf("Disconnected handler  %x\n", params->handle);
  pc.printf("Disconnected reson %x \n", params->reason);
  if(peripheral_handle == params->handle) {
    peripheral_handle = 0;
    pc.printf("Restart advertising\n");
    ble.startAdvertising();
  }
  else if(client_handle == params->handle) {
    client_handle = 0;
    pc.printf("Restart scanning\n");
    ble.startScan(scanCallBack);
  }
}

 
void onDataWrite(const GattWriteCallbackParams *response) {
    pc.printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
        for (unsigned index = 0; index < response->len; index++) {
            pc.printf("%c[%02x]", response->data[index], response->data[index]);
        }
        pc.printf("\r\n");
 
}
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE &ble          = params->ble;
    ble_error_t error = params->error;
    
    if (error != BLE_ERROR_NONE) {
        return;
    }

    ble.onConnection(connectionCallBack);
    ble.onDisconnection(disconnectionCallBack);
    ble.gattServer().onDataWritten(writeCharCallback);

    /* Setup advertising */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // BLE only, no classic BT
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising type
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet
    ble.gap().setAdvertisingInterval(100); // 100ms.

    /* Add our custom service */
    ble.addService(customService);

    /* Start advertising */
    ble.gap().startAdvertising();
    ble.setScanParams(2000, 200, 0, false);
    // start scanning
    ble.startScan(scanCallBack);
    pc.printf("Start scanning\n");
    // start advertising
    ble.startAdvertising();
    pc.printf("Start advertising\n");
}

int main(void)
{
    
    /* initialize stuff */
    pc.printf("\n\r********* Starting Main Loop *********\n\r");
    
    
    ble.init(bleInitComplete);

    while (ble.hasInitialized()  == false) {}

    while (true) {
        ble.waitForEvent();
    }
}