void BLEPeripheral::begin() {
  unsigned char advertisementDataType = 0;
  unsigned char scanDataType = 0;

  unsigned char advertisementDataLength = 0;
  unsigned char scanDataLength = 0;

  unsigned char advertisementData[BLE_ADVERTISEMENT_DATA_MAX_VALUE_LENGTH];
  unsigned char scanData[BLE_SCAN_DATA_MAX_VALUE_LENGTH];

  if (this->_serviceSolicitationUuid){
    BLEUuid serviceSolicitationUuid = BLEUuid(this->_serviceSolicitationUuid);

    advertisementDataLength = serviceSolicitationUuid.length();
    advertisementDataType = (advertisementDataLength > 2) ? 0x15 : 0x14;

    memcpy(advertisementData, serviceSolicitationUuid.data(), advertisementDataLength);
  } else if (this->_advertisedServiceUuid){
    BLEUuid advertisedServiceUuid = BLEUuid(this->_advertisedServiceUuid);

    advertisementDataLength = advertisedServiceUuid.length();
    advertisementDataType = (advertisementDataLength > 2) ? 0x06 : 0x02;

    memcpy(advertisementData, advertisedServiceUuid.data(), advertisementDataLength);
  } else if (this->_manufacturerData && this->_manufacturerDataLength > 0) {
    advertisementDataLength = this->_manufacturerDataLength;

    if (advertisementDataLength > sizeof(advertisementData)) {
      advertisementDataLength = sizeof(advertisementData);
    }

    advertisementDataType = 0xff;

    memcpy(advertisementData, this->_manufacturerData, advertisementDataLength);
  }

  if (this->_localName){
    unsigned char localNameLength = strlen(this->_localName);
    scanDataLength = localNameLength;

    if (scanDataLength > sizeof(scanData)) {
      scanDataLength = sizeof(scanData);
    }

    scanDataType = (localNameLength > scanDataLength) ? 0x08 : 0x09;

    memcpy(scanData, this->_localName, scanDataLength);
  }

  if (this->_localAttributes == NULL) {
    this->initLocalAttributes();
  }

  for (int i = 0; i < this->_numLocalAttributes; i++) {
    BLELocalAttribute* localAttribute = this->_localAttributes[i];
    if (localAttribute->type() == BLETypeCharacteristic) {
      BLECharacteristic* characteristic = (BLECharacteristic*)localAttribute;

      characteristic->setValueChangeListener(*this);
    }
  }

  for (int i = 0; i < this->_numRemoteAttributes; i++) {
    BLERemoteAttribute* remoteAttribute = this->_remoteAttributes[i];
    if (remoteAttribute->type() == BLETypeCharacteristic) {
      BLERemoteCharacteristic* remoteCharacteristic = (BLERemoteCharacteristic*)remoteAttribute;

      remoteCharacteristic->setValueChangeListener(*this);
    }
  }

  if (this->_numRemoteAttributes) {
    this->addRemoteAttribute(this->_remoteGenericAttributeService);
    this->addRemoteAttribute(this->_remoteServicesChangedCharacteristic);
  }

  this->_device->begin(advertisementDataType, advertisementDataLength, advertisementData,
                        scanDataType, scanDataLength, scanData,
                        this->_localAttributes, this->_numLocalAttributes,
                        this->_remoteAttributes, this->_numRemoteAttributes);

  this->_device->requestAddress();
}
void BLEPeripheral::begin() {
  unsigned char advertisementDataSize = 0;

  BLEEirData advertisementData[3];
  BLEEirData scanData;

  scanData.length = 0;

  unsigned char remainingAdvertisementDataLength = BLE_ADVERTISEMENT_DATA_MAX_VALUE_LENGTH + 2;
  if (this->_serviceSolicitationUuid){
    BLEUuid serviceSolicitationUuid = BLEUuid(this->_serviceSolicitationUuid);

    unsigned char uuidLength = serviceSolicitationUuid.length();
    advertisementData[advertisementDataSize].length = uuidLength;
    advertisementData[advertisementDataSize].type = (uuidLength > 2) ? 0x15 : 0x14;

    memcpy(advertisementData[advertisementDataSize].data, serviceSolicitationUuid.data(), uuidLength);
    advertisementDataSize += 1;
    remainingAdvertisementDataLength -= uuidLength + 2;
  }
  if (this->_advertisedServiceUuid){
    BLEUuid advertisedServiceUuid = BLEUuid(this->_advertisedServiceUuid);

    unsigned char uuidLength = advertisedServiceUuid.length();
    if (uuidLength + 2 <= remainingAdvertisementDataLength) {
      advertisementData[advertisementDataSize].length = uuidLength;
      advertisementData[advertisementDataSize].type = (uuidLength > 2) ? 0x06 : 0x02;

      memcpy(advertisementData[advertisementDataSize].data, advertisedServiceUuid.data(), uuidLength);
      advertisementDataSize += 1;
      remainingAdvertisementDataLength -= uuidLength + 2;
    }
  }
  if (this->_manufacturerData && this->_manufacturerDataLength > 0) {
    if (remainingAdvertisementDataLength >= 3) {
      unsigned char dataLength = this->_manufacturerDataLength;

      if (dataLength + 2 > remainingAdvertisementDataLength) {
        dataLength = remainingAdvertisementDataLength - 2;
      }

      advertisementData[advertisementDataSize].length = dataLength;
      advertisementData[advertisementDataSize].type = 0xff;

      memcpy(advertisementData[advertisementDataSize].data, this->_manufacturerData, dataLength);
      advertisementDataSize += 1;
      remainingAdvertisementDataLength -= dataLength + 2;
    }
  }

  if (this->_localName){
    unsigned char localNameLength = strlen(this->_localName);
    scanData.length = localNameLength;

    if (scanData.length > BLE_SCAN_DATA_MAX_VALUE_LENGTH) {
      scanData.length = BLE_SCAN_DATA_MAX_VALUE_LENGTH;
    }

    scanData.type = (localNameLength > scanData.length) ? 0x08 : 0x09;

    memcpy(scanData.data, this->_localName, scanData.length);
  }

  if (this->_localAttributes == NULL) {
    this->initLocalAttributes();
  }

  for (int i = 0; i < this->_numLocalAttributes; i++) {
    BLELocalAttribute* localAttribute = this->_localAttributes[i];
    if (localAttribute->type() == BLETypeCharacteristic) {
      BLECharacteristic* characteristic = (BLECharacteristic*)localAttribute;

      characteristic->setValueChangeListener(*this);
    }
  }

  for (int i = 0; i < this->_numRemoteAttributes; i++) {
    BLERemoteAttribute* remoteAttribute = this->_remoteAttributes[i];
    if (remoteAttribute->type() == BLETypeCharacteristic) {
      BLERemoteCharacteristic* remoteCharacteristic = (BLERemoteCharacteristic*)remoteAttribute;

      remoteCharacteristic->setValueChangeListener(*this);
    }
  }

  if (this->_numRemoteAttributes) {
    this->addRemoteAttribute(this->_remoteGenericAttributeService);
    this->addRemoteAttribute(this->_remoteServicesChangedCharacteristic);
  }

  this->_device->begin(advertisementDataSize, advertisementData,
                        scanData.length > 0 ? 1 : 0, &scanData,
                        this->_localAttributes, this->_numLocalAttributes,
                        this->_remoteAttributes, this->_numRemoteAttributes);

  this->_device->requestAddress();
}