Esempio n. 1
0
/**
 * @brief Start the service.
 * Here we wish to start the service which means that we will respond to partner requests about it.
 * Starting a service also means that we can create the corresponding characteristics.
 * @return Start the service.
 */
void BLEService::start() {
// We ask the BLE runtime to start the service and then create each of the characteristics.
// We start the service through its local handle which was returned in the ESP_GATTS_CREATE_EVT event
// obtained as a result of calling esp_ble_gatts_create_service().
//
	ESP_LOGD(LOG_TAG, ">> start(): Starting service (esp_ble_gatts_start_service): %s", toString().c_str());
	if (m_handle == NULL_HANDLE) {
		ESP_LOGE(LOG_TAG, "<< !!! We attempted to start a service but don't know its handle!");
		return;
	}


	BLECharacteristic *pCharacteristic = m_characteristicMap.getFirst();

	while(pCharacteristic != nullptr) {
		m_lastCreatedCharacteristic = pCharacteristic;
		pCharacteristic->executeCreate(this);

		pCharacteristic = m_characteristicMap.getNext();
	}
	// Start each of the characteristics ... these are found in the m_characteristicMap.

	m_semaphoreStartEvt.take("start");
	esp_err_t errRc = ::esp_ble_gatts_start_service(m_handle);

	if (errRc != ESP_OK) {
		ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_start_service: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
		return;
	}
	m_semaphoreStartEvt.wait("start");

	ESP_LOGD(LOG_TAG, "<< start()");
} // start
void
BLEPeripheral::handleGapEvent(ble_client_gap_event_t event, struct ble_gap_event *event_data)
{
    if (BLE_CLIENT_GAP_EVENT_CONNECTED == event) {
        _state = BLE_PERIPH_STATE_CONNECTED;
        _central.setAddress(event_data->connected.peer_bda);

        if (_event_handlers[BLEConnected]) {
            _event_handlers[BLEConnected](_central);
        }
    } else if (BLE_CLIENT_GAP_EVENT_DISCONNECTED == event) {

        for (int i = 0; i < _num_attributes; i++) {
            BLEAttribute* attribute = _attributes[i];

            if (attribute->type() == BLETypeCharacteristic) {
                BLECharacteristic* characteristic = (BLECharacteristic*)attribute;

                characteristic->setCccdValue(_central, 0x0000); // reset CCCD
            }
        }

        if (_event_handlers[BLEDisconnected])
            _event_handlers[BLEDisconnected](_central);

        _state = BLE_PERIPH_STATE_READY;
        _central.clearAddress();

        _startAdvertising();
    } else if (BLE_CLIENT_GAP_EVENT_CONN_TIMEOUT == event) {
        _state = BLE_PERIPH_STATE_READY;

        _startAdvertising();
    }
}
void
BLEPeripheral::handleGattsEvent(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data)
{
    if (BLE_CLIENT_GATTS_EVENT_WRITE == event) {
        uint16_t handle = event_data->wr.attr_handle;

        for (int i = 0; i < _num_attributes; i++) {
            BLEAttribute* attribute = _attributes[i];

            if (attribute->type() != BLETypeCharacteristic) {
                continue;
            }

            BLECharacteristic* characteristic = (BLECharacteristic*)attribute;

            if (characteristic->valueHandle() == handle) {
                characteristic->setValue(_central, event_data->wr.data, event_data->wr.len);
                break;
            } else if (characteristic->cccdHandle() == handle) {
                uint16_t cccdValue = 0;

                memcpy(&cccdValue, event_data->wr.data, event_data->wr.len);

                characteristic->setCccdValue(_central, cccdValue);
                break;
            }
        }
    }
}
void bleConfigChangeHandler(BLECentral& central, BLECharacteristic& characteristic) {
  // config characteristic event handler
  DEBUG_PRINTLN("config change event");
  handle( (uint8_t*) characteristic.value(), characteristic.valueLength());
  DEBUG_PRINT("Pin: ");
  DEBUG_PRINTLN(pin);
}
void setup() {
  wait_for_serial();

  // set the UUID for the service this peripheral advertises:
  blePeripheral.setAdvertisedServiceUuid(whistlepunkService.uuid());

  // add service and characteristics
  blePeripheral.addAttribute(whistlepunkService);
  blePeripheral.addAttribute(valueCharacteristic);
  blePeripheral.addAttribute(configCharacteristic);
  blePeripheral.addAttribute(versionCharacteristic);
  versionCharacteristic.setValue(version);

  // assign event handlers for connected, disconnected to peripheral
  blePeripheral.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  blePeripheral.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
  valueCharacteristic.setEventHandler(BLESubscribed, bleNotificationSubscribeHandler);
  valueCharacteristic.setEventHandler(BLEUnsubscribed, bleNotificationUnsubscribeHandler);
  configCharacteristic.setEventHandler(BLEWritten, bleConfigChangeHandler);


  // advertise the service
  blePeripheral.begin();
  while (true) {
    blePeripheral.poll();
    if (blePeripheral.haveAddress()) {
      have_address = true;
      address = blePeripheral.getAddress();
      sprintf(BleLongName, "Sci%02x%02x", address[0], address[1]);
      blePeripheral.setLocalName(BleLongName);
      blePeripheral.begin();
      break;
    }
  }
}
void setup() {
  wait_for_serial();

  // set the local name peripheral advertises
  blePeripheral.setLocalName("Initial");
  // set the UUID for the service this peripheral advertises:
  blePeripheral.setAdvertisedServiceUuid(whistlepunkService.uuid());

  // add service and characteristics
  blePeripheral.addAttribute(whistlepunkService);
  blePeripheral.addAttribute(valueCharacteristic);
  blePeripheral.addAttribute(configCharacteristic);
  blePeripheral.addAttribute(versionCharacteristic);
  versionCharacteristic.setValue(version);

  // assign event handlers for connected, disconnected to peripheral
  blePeripheral.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  blePeripheral.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
  valueCharacteristic.setEventHandler(BLESubscribed, bleNotificationSubscribeHandler);
  valueCharacteristic.setEventHandler(BLEUnsubscribed, bleNotificationUnsubscribeHandler);
  configCharacteristic.setEventHandler(BLEWritten, bleConfigChangeHandler);

  ble_addr_t _local_bda;
  char       _device_name[BLE_MAX_DEVICE_NAME+1];
  ble_client_get_factory_config(&_local_bda, _device_name);
  sprintf(BleLongName, "Sci%02x%02x", _local_bda.addr[0], _local_bda.addr[1]);
  DEBUG_PRINT("Address is: ");
  DEBUG_PRINTLN(BleLongName);
  blePeripheral.setLocalName(BleLongName);

  // advertise the service
  blePeripheral.begin();
}
void BLEHID::sendData(BLECharacteristic& characteristic, unsigned char data[], unsigned char length) {
  // wait until we can notify
  while(!characteristic.canNotify()) {
    BLEHIDPeripheral::instance()->poll();
  }

  characteristic.setValue(data, length);
}
Esempio n. 8
0
void BLEPeripheral::begin() {
  unsigned char advertisementData[20];
  unsigned char scanData[20];

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

  if (this->_advertisedServiceUuid){
    BLEUuid advertisedServiceUuid = BLEUuid(this->_advertisedServiceUuid);
    unsigned char advertisedServiceUuidLength = advertisedServiceUuid.length();

    advertisementDataLength = 2 + advertisedServiceUuidLength;

    advertisementData[0] = (advertisedServiceUuidLength > 2) ? 0x06 : 0x02;
    advertisementData[1] = advertisedServiceUuidLength;

    memcpy(&advertisementData[2], advertisedServiceUuid.data(), advertisedServiceUuidLength);
  } else if (this->_manufacturerData && this->_manufacturerDataLength > 0) {
    if (this->_manufacturerDataLength > sizeof(advertisementData)) {
      this->_manufacturerDataLength = sizeof(advertisementData);
    }

    advertisementDataLength = 2 + this->_manufacturerDataLength;

    advertisementData[0] = 0xff;
    advertisementData[1] = this->_manufacturerDataLength;
    memcpy(&advertisementData[2], this->_manufacturerData, this->_manufacturerDataLength);
  }

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

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

    scanDataLength = 2 + localNameLength;

    scanData[0] = (originalLocalNameLength > sizeof(scanData)) ? 0x08 : 0x09;
    scanData[1] = localNameLength;

    memcpy(&scanData[2], this->_localName, localNameLength);
  }

  for (int i = 0; i < this->_numAttributes; i++) {
    BLEAttribute* attribute = this->_attributes[i];
    if (attribute->type() == BLETypeCharacteristic) {
      BLECharacteristic* characteristic = (BLECharacteristic*)attribute;

      characteristic->setValueChangeListener(*this);
    }
  }

  this->_nRF8001.begin(advertisementData, advertisementDataLength, scanData, scanDataLength, this->_attributes, this->_numAttributes);

  this->_nRF8001.requestAddress();
}
bool BLEPeripheral::begin()
{
    BleStatus status;

    status = _init();
    if (status != BLE_STATUS_SUCCESS) {
        return false;
    }

    /* Populate advertising data
     */
    _advDataInit();

    status = ble_client_gap_wr_adv_data(_adv_data, _adv_data_len);
    if (BLE_STATUS_SUCCESS != status) {
        return false;
    }

    uint16_t lastServiceHandle = 0;

    for (int i = 0; i < _num_attributes; i++) {
        BLEAttribute* attribute = _attributes[i];
        BLEAttributeType type = attribute->type();
        bool addResult = false;

        if (BLETypeService == type) {
            BLEService* service = (BLEService*)attribute;

            addResult = service->add();

            lastServiceHandle = service->handle();
        } else if (BLETypeCharacteristic == type) {
            BLECharacteristic* characteristic = (BLECharacteristic*)attribute;

            addResult = characteristic->add(lastServiceHandle);
        } else if (BLETypeDescriptor == type) {
            BLEDescriptor *descriptor = (BLEDescriptor*)attribute;

            if (strcmp(descriptor->uuid(), "2901") == 0 ||
                strcmp(descriptor->uuid(), "2902") == 0 ||
                strcmp(descriptor->uuid(), "2903") == 0 ||
                strcmp(descriptor->uuid(), "2904") == 0) {
                continue; // skip
            }

            addResult = descriptor->add(lastServiceHandle);
        }

        if (!addResult) {
            return false;
        }
    }

    return (_startAdvertising() == BLE_STATUS_SUCCESS);
}
void loop() {
  if (Serial) {
    if (!serialConnected) {
      serialConnected = true;
      DEBUG_PRINT(F("LongName: "));
      DEBUG_PRINTLN(BleLongName);
    }
  } else {
    if (serialConnected)
      serialConnected = false;
  }

  // poll peripheral
  blePeripheral.poll();

  if (valueCharacteristic.subscribed()) {
    int sensorValue = 0;
    if (pin_type == ANALOG) {
      sensorValue = analogRead(pin);
    } else if (pin_type == DIGITAL) {
      sensorValue = digitalRead(pin);
    } else {
      sensorValue = 666;
    }
    send_data(valueCharacteristic, millis(), sensorValue);
  }
#ifdef GOOSCI_DEVELOPER_MODE
  heartbeat();
#endif
}
Esempio n. 11
0
static void run() {
	BLEDevice::init("MYDEVICE");
	BLEServer *pServer = BLEDevice::createServer();

	BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID_BIN, 16, true));

	BLECharacteristic *pCharacteristic = pService->createCharacteristic(
		BLEUUID(CHARACTERISTIC_UUID),
		BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
	);

	pCharacteristic->setCallbacks(new MyCallbackHandler());

	pCharacteristic->setValue("Hello World");

	pService->start();

	BLEAdvertising *pAdvertising = pServer->getAdvertising();
	pAdvertising->start();
}
Esempio n. 12
0
bool nRF51822::updateCharacteristicValue(BLECharacteristic& characteristic) {
  bool success = true;

  for (int i = 0; i < this->_numLocalCharacteristics; i++) {
    struct localCharacteristicInfo* localCharacteristicInfo = &this->_localCharacteristicInfo[i];

    if (localCharacteristicInfo->characteristic == &characteristic) {
      if (&characteristic == this->_broadcastCharacteristic) {
        this->broadcastCharacteristic(characteristic);
      }

      uint16_t valueLength = characteristic.valueLength();

      sd_ble_gatts_value_set(localCharacteristicInfo->handles.value_handle, 0, &valueLength, characteristic.value());

      ble_gatts_hvx_params_t hvxParams;

      memset(&hvxParams, 0, sizeof(hvxParams));

      hvxParams.handle = localCharacteristicInfo->handles.value_handle;
      hvxParams.offset = 0;
      hvxParams.p_data = NULL;
      hvxParams.p_len  = &valueLength;

      if (localCharacteristicInfo->notifySubscribed) {
        if (this->_txBufferCount > 0) {
          this->_txBufferCount--;

          hvxParams.type = BLE_GATT_HVX_NOTIFICATION;

          sd_ble_gatts_hvx(this->_connectionHandle, &hvxParams);
        } else {
          success = false;
        }
      }

      if (localCharacteristicInfo->indicateSubscribed) {
        if (this->_txBufferCount > 0) {
          this->_txBufferCount--;

          hvxParams.type = BLE_GATT_HVX_INDICATION;

          sd_ble_gatts_hvx(this->_connectionHandle, &hvxParams);
        } else {
          success = false;
        }
      }
    }
  }

  return success;
}
Esempio n. 13
0
void updateHeartRate() {
  /* Read the current voltage level on the A0 analog input pin.
     This is used here to simulate the heart rate's measurement.
  */
  int heartRateMeasurement = analogRead(A0);
  int heartRate = map(heartRateMeasurement, 0, 1023, 0, 100);
  if (heartRate != oldHeartRate) {      // if the heart rate has changed
    Serial.print("Heart Rate is now: "); // print it
    Serial.println(heartRate);
    const unsigned char heartRateCharArray[2] = { 0, (char)heartRate };
    heartRateChar.setValue(heartRateCharArray, 2);  // and update the heart rate measurement characteristic
    oldHeartRate = heartRate;           // save the level for next comparison
  }
}
Esempio n. 14
0
bool nRF51822::broadcastCharacteristic(BLECharacteristic& characteristic) {
  bool success = false;

  for (int i = 0; i < this->_numLocalCharacteristics; i++) {
    struct localCharacteristicInfo* localCharacteristicInfo = &this->_localCharacteristicInfo[i];

    if (localCharacteristicInfo->characteristic == &characteristic) {
      if (characteristic.properties() & BLEBroadcast && localCharacteristicInfo->service) {
        unsigned char advData[31];
        unsigned char advDataLen = this->_advDataLen;

        // copy the existing advertisement data
        memcpy(advData, this->_advData, advDataLen);

        advDataLen += (4 + characteristic.valueLength());

        if (advDataLen <= 31) {
          BLEUuid uuid = BLEUuid(localCharacteristicInfo->service->uuid());

          advData[this->_advDataLen + 0] = 3 + characteristic.valueLength();
          advData[this->_advDataLen + 1] = 0x16;

          memcpy(&advData[this->_advDataLen + 2], uuid.data(), 2);
          memcpy(&advData[this->_advDataLen + 4], characteristic.value(), characteristic.valueLength());

          sd_ble_gap_adv_data_set(advData, advDataLen, NULL, 0); // update advertisement data
          success = true;

          this->_broadcastCharacteristic = &characteristic;
        }
      }
      break;
    }
  }

  return success;
}
BLECharacteristicImp::BLECharacteristicImp(BLECharacteristic& characteristic, 
                                           const BLEDevice& bledevice):
    BLEAttribute(characteristic.uuid(), BLETypeCharacteristic),
    _value_length(0),
    _value_buffer(NULL),
    _value_updated(false),
    _value_handle(0),
    _cccd_handle(0),
    _attr_chrc_value(NULL),
    _attr_cccd(NULL),
    _subscribed(false),
    _reading(false),
    _ble_device()
{
    unsigned char properties = characteristic._properties;
    _value_size = characteristic._value_size;
    _value = (unsigned char*)malloc(_value_size);
    if (_value == NULL)
    {
        errno = ENOMEM;
    }
    if (_value_size > BLE_MAX_ATTR_DATA_LEN)
    {
        _value_buffer = (unsigned char*)malloc(_value_size);
    }
    
    memset(&_ccc_cfg, 0, sizeof(_ccc_cfg));
    memset(&_ccc_value, 0, sizeof(_ccc_value));
    memset(&_gatt_chrc, 0, sizeof(_gatt_chrc));
    memset(&_sub_params, 0, sizeof(_sub_params));
    memset(&_discover_params, 0, sizeof(_discover_params));
    
    _ccc_value.cfg = &_ccc_cfg;
    _ccc_value.cfg_len = 1;
    if (BLERead & properties)
    {
        _gatt_chrc.properties |= BT_GATT_CHRC_READ;
    }
    if (BLEWrite & properties)
    {
        _gatt_chrc.properties |= BT_GATT_CHRC_WRITE;
    }
    if (BLEWriteWithoutResponse & properties)
    {
        _gatt_chrc.properties |= BT_GATT_CHRC_WRITE_WITHOUT_RESP;
    }
    if (BLENotify & properties)
    {
        _gatt_chrc.properties |= BT_GATT_CHRC_NOTIFY;
        _sub_params.value |= BT_GATT_CCC_NOTIFY;
    }
    if (BLEIndicate & properties)
    {
        _gatt_chrc.properties |= BT_GATT_CHRC_INDICATE;
        _sub_params.value |= BT_GATT_CCC_INDICATE;
    }
    _gatt_chrc.uuid = (bt_uuid_t*)this->bt_uuid();//&_characteristic_uuid;//this->uuid();

    memcpy(_event_handlers, characteristic._event_handlers, sizeof(_event_handlers));
    memcpy(_oldevent_handlers, characteristic._oldevent_handlers, sizeof(_oldevent_handlers));
    
    _sub_params.notify = profile_notify_process;
    
    if (NULL != characteristic._value)
    {
        memcpy(_value, characteristic._value, _value_size);
    }
        
    // Update BLE device object
    _ble_device.setAddress(*bledevice.bt_le_address());
    
    characteristic.setBLECharacteristicImp(this);
    memset(&_descriptors_header, 0, sizeof(_descriptors_header));
}
Esempio n. 16
0
void nRF51822::begin(unsigned char advertisementDataType,
                      unsigned char advertisementDataLength,
                      const unsigned char* advertisementData,
                      unsigned char scanDataType,
                      unsigned char scanDataLength,
                      const unsigned char* scanData,
                      BLELocalAttribute** localAttributes,
                      unsigned char numLocalAttributes,
                      BLERemoteAttribute** remoteAttributes,
                      unsigned char numRemoteAttributes)
{

#ifdef __RFduino__
  sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_SYNTH_250_PPM, NULL);
#else
  sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); // sd_nvic_EnableIRQ(SWI2_IRQn);
#endif

#ifdef NRF51_S130
  ble_enable_params_t enableParams = {
      .gatts_enable_params = {
          .service_changed = true
      }
  };

  sd_ble_enable(&enableParams);
#endif

#ifdef NRF_51822_DEBUG
  ble_version_t version;

  sd_ble_version_get(&version);

  Serial.print(F("version = "));
  Serial.print(version.version_number);
  Serial.print(F(" "));
  Serial.print(version.company_id);
  Serial.print(F(" "));
  Serial.print(version.subversion_number);
  Serial.println();
#endif

  ble_gap_conn_params_t gap_conn_params;

  gap_conn_params.min_conn_interval = 40;  // in 1.25ms units
  gap_conn_params.max_conn_interval = 80;  // in 1.25ms unit
  gap_conn_params.slave_latency     = 0;
  gap_conn_params.conn_sup_timeout  = 4000 / 10; // in 10ms unit

  sd_ble_gap_ppcp_set(&gap_conn_params);
  sd_ble_gap_tx_power_set(0);

  unsigned char srData[31];
  unsigned char srDataLen = 0;

  this->_advDataLen = 0;

  // flags
  this->_advData[this->_advDataLen + 0] = 2;
  this->_advData[this->_advDataLen + 1] = 0x01;
  this->_advData[this->_advDataLen + 2] = 0x06;

  this->_advDataLen += 3;

  if (advertisementDataType && advertisementDataLength && advertisementData) {
    this->_advData[this->_advDataLen + 0] = advertisementDataLength + 1;
    this->_advData[this->_advDataLen + 1] = advertisementDataType;
    this->_advDataLen += 2;

    memcpy(&this->_advData[this->_advDataLen], advertisementData, advertisementDataLength);

    this->_advDataLen += advertisementDataLength;
  }

  if (scanDataType && scanDataLength && scanData) {
    srData[0] = scanDataLength + 1;
    srData[1] = scanDataType;
    memcpy(&srData[2], scanData, scanDataLength);

    srDataLen = 2 + scanDataLength;
  }

  sd_ble_gap_adv_data_set(this->_advData, this->_advDataLen, srData, srDataLen);
  sd_ble_gap_appearance_set(0);

  for (int i = 0; i < numLocalAttributes; i++) {
    BLELocalAttribute *localAttribute = localAttributes[i];

    if (localAttribute->type() == BLETypeCharacteristic) {
      this->_numLocalCharacteristics++;
    }
  }

  this->_numLocalCharacteristics -= 3; // 0x2a00, 0x2a01, 0x2a05

  this->_localCharacteristicInfo = (struct localCharacteristicInfo*)malloc(sizeof(struct localCharacteristicInfo) * this->_numLocalCharacteristics);

  unsigned char localCharacteristicIndex = 0;

  uint16_t handle = 0;
  BLEService *lastService = NULL;

  for (int i = 0; i < numLocalAttributes; i++) {
    BLELocalAttribute *localAttribute = localAttributes[i];
    BLEUuid uuid = BLEUuid(localAttribute->uuid());
    const unsigned char* uuidData = uuid.data();
    unsigned char value[255];

    ble_uuid_t nordicUUID;

    if (uuid.length() == 2) {
      nordicUUID.uuid = (uuidData[1] << 8) | uuidData[0];
      nordicUUID.type = BLE_UUID_TYPE_BLE;
    } else {
      unsigned char uuidDataTemp[16];

      memcpy(&uuidDataTemp, uuidData, sizeof(uuidDataTemp));

      nordicUUID.uuid = (uuidData[13] << 8) | uuidData[12];

      uuidDataTemp[13] = 0;
      uuidDataTemp[12] = 0;

      sd_ble_uuid_vs_add((ble_uuid128_t*)&uuidDataTemp, &nordicUUID.type);
    }

    if (localAttribute->type() == BLETypeService) {
      BLEService *service = (BLEService *)localAttribute;

      if (strcmp(service->uuid(), "1800") == 0 || strcmp(service->uuid(), "1801") == 0) {
        continue; // skip
      }

      sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &nordicUUID, &handle);

      lastService = service;
    } else if (localAttribute->type() == BLETypeCharacteristic) {
      BLECharacteristic *characteristic = (BLECharacteristic *)localAttribute;

      if (strcmp(characteristic->uuid(), "2a00") == 0) {
        ble_gap_conn_sec_mode_t secMode;
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&secMode); // no security is needed

        sd_ble_gap_device_name_set(&secMode, characteristic->value(), characteristic->valueLength());
      } else if (strcmp(characteristic->uuid(), "2a01") == 0) {
        const uint16_t *appearance = (const uint16_t*)characteristic->value();

        sd_ble_gap_appearance_set(*appearance);
      } else if (strcmp(characteristic->uuid(), "2a05") == 0) {
        // do nothing
      } else {
        uint8_t properties = characteristic->properties() & 0xfe;
        uint16_t valueLength = characteristic->valueLength();

        this->_localCharacteristicInfo[localCharacteristicIndex].characteristic = characteristic;
        this->_localCharacteristicInfo[localCharacteristicIndex].notifySubscribed = false;
        this->_localCharacteristicInfo[localCharacteristicIndex].indicateSubscribed = false;
        this->_localCharacteristicInfo[localCharacteristicIndex].service = lastService;

        ble_gatts_char_md_t characteristicMetaData;
        ble_gatts_attr_md_t clientCharacteristicConfigurationMetaData;
        ble_gatts_attr_t    characteristicValueAttribute;
        ble_gatts_attr_md_t characteristicValueAttributeMetaData;

        memset(&characteristicMetaData, 0, sizeof(characteristicMetaData));

        memcpy(&characteristicMetaData.char_props, &properties, 1);

        characteristicMetaData.p_char_user_desc  = NULL;
        characteristicMetaData.p_char_pf         = NULL;
        characteristicMetaData.p_user_desc_md    = NULL;
        characteristicMetaData.p_cccd_md         = NULL;
        characteristicMetaData.p_sccd_md         = NULL;

        if (properties & (BLENotify | BLEIndicate)) {
          memset(&clientCharacteristicConfigurationMetaData, 0, sizeof(clientCharacteristicConfigurationMetaData));

          BLE_GAP_CONN_SEC_MODE_SET_OPEN(&clientCharacteristicConfigurationMetaData.read_perm);
          BLE_GAP_CONN_SEC_MODE_SET_OPEN(&clientCharacteristicConfigurationMetaData.write_perm);

          clientCharacteristicConfigurationMetaData.vloc = BLE_GATTS_VLOC_STACK;

          characteristicMetaData.p_cccd_md = &clientCharacteristicConfigurationMetaData;
        }

        memset(&characteristicValueAttributeMetaData, 0, sizeof(characteristicValueAttributeMetaData));

        if (properties & (BLERead | BLENotify | BLEIndicate)) {
          if (this->_bondStore) {
            BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&characteristicValueAttributeMetaData.read_perm);
          } else {
            BLE_GAP_CONN_SEC_MODE_SET_OPEN(&characteristicValueAttributeMetaData.read_perm);
          }
        }

        if (properties & (BLEWriteWithoutResponse | BLEWrite)) {
          if (this->_bondStore) {
            BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&characteristicValueAttributeMetaData.write_perm);
          } else {
            BLE_GAP_CONN_SEC_MODE_SET_OPEN(&characteristicValueAttributeMetaData.write_perm);
          }
        }

        characteristicValueAttributeMetaData.vloc       = BLE_GATTS_VLOC_STACK;
        characteristicValueAttributeMetaData.rd_auth    = 0;
        characteristicValueAttributeMetaData.wr_auth    = 0;
        characteristicValueAttributeMetaData.vlen       = !characteristic->fixedLength();

        for (int j = (i + 1); j < numLocalAttributes; j++) {
          localAttribute = localAttributes[j];

          if (localAttribute->type() != BLETypeDescriptor) {
            break;
          }

          BLEDescriptor *descriptor = (BLEDescriptor *)localAttribute;

          if (strcmp(descriptor->uuid(), "2901") == 0) {
            characteristicMetaData.p_char_user_desc        = (uint8_t*)descriptor->value();
            characteristicMetaData.char_user_desc_max_size = descriptor->valueLength();
            characteristicMetaData.char_user_desc_size     = descriptor->valueLength();
          } else if (strcmp(descriptor->uuid(), "2904") == 0) {
            characteristicMetaData.p_char_pf = (ble_gatts_char_pf_t *)descriptor->value();
          }
        }

        memset(&characteristicValueAttribute, 0, sizeof(characteristicValueAttribute));

        characteristicValueAttribute.p_uuid       = &nordicUUID;
        characteristicValueAttribute.p_attr_md    = &characteristicValueAttributeMetaData;
        characteristicValueAttribute.init_len     = valueLength;
        characteristicValueAttribute.init_offs    = 0;
        characteristicValueAttribute.max_len      = characteristic->valueSize();
        characteristicValueAttribute.p_value      = NULL;

        sd_ble_gatts_characteristic_add(BLE_GATT_HANDLE_INVALID, &characteristicMetaData, &characteristicValueAttribute, &this->_localCharacteristicInfo[localCharacteristicIndex].handles);

        if (valueLength) {
          for (int j = 0; j < valueLength; j++) {
            value[j] = (*characteristic)[j];
          }

          sd_ble_gatts_value_set(this->_localCharacteristicInfo[localCharacteristicIndex].handles.value_handle, 0, &valueLength, value);
        }

        localCharacteristicIndex++;
      }
    } else if (localAttribute->type() == BLETypeDescriptor) {
      BLEDescriptor *descriptor = (BLEDescriptor *)localAttribute;

      if (strcmp(descriptor->uuid(), "2901") == 0 ||
          strcmp(descriptor->uuid(), "2902") == 0 ||
          strcmp(descriptor->uuid(), "2903") == 0 ||
          strcmp(descriptor->uuid(), "2904") == 0) {
        continue; // skip
      }

      uint16_t valueLength = descriptor->valueLength();

      ble_gatts_attr_t descriptorAttribute;
      ble_gatts_attr_md_t descriptorMetaData;

      memset(&descriptorAttribute, 0, sizeof(descriptorAttribute));
      memset(&descriptorMetaData, 0, sizeof(descriptorMetaData));

      descriptorMetaData.vloc = BLE_GATTS_VLOC_STACK;
      descriptorMetaData.vlen = (valueLength == descriptor->valueLength()) ? 0 : 1;

      if (this->_bondStore) {
        BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&descriptorMetaData.read_perm);
      } else {
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&descriptorMetaData.read_perm);
      }

      descriptorAttribute.p_uuid    = &nordicUUID;
      descriptorAttribute.p_attr_md = &descriptorMetaData;
      descriptorAttribute.init_len  = valueLength;
      descriptorAttribute.max_len   = descriptor->valueLength();
      descriptorAttribute.p_value   = NULL;

      sd_ble_gatts_descriptor_add(BLE_GATT_HANDLE_INVALID, &descriptorAttribute, &handle);

      if (valueLength) {
        for (int j = 0; j < valueLength; j++) {
          value[j] = (*descriptor)[j];
        }

        sd_ble_gatts_value_set(handle, 0, &valueLength, value);
      }
    }
  }

  if ( numRemoteAttributes > 0) {
    numRemoteAttributes -= 2; // 0x1801, 0x2a05
  }

  for (int i = 0; i < numRemoteAttributes; i++) {
    BLERemoteAttribute *remoteAttribute = remoteAttributes[i];

    if (remoteAttribute->type() == BLETypeService) {
      this->_numRemoteServices++;
    } else if (remoteAttribute->type() == BLETypeCharacteristic) {
      this->_numRemoteCharacteristics++;
    }
  }

  this->_remoteServiceInfo = (struct remoteServiceInfo*)malloc(sizeof(struct remoteServiceInfo) * this->_numRemoteServices);
  this->_remoteCharacteristicInfo = (struct remoteCharacteristicInfo*)malloc(sizeof(struct remoteCharacteristicInfo) * this->_numRemoteCharacteristics);

  BLERemoteService *lastRemoteService = NULL;
  unsigned char remoteServiceIndex = 0;
  unsigned char remoteCharacteristicIndex = 0;

  for (int i = 0; i < numRemoteAttributes; i++) {
    BLERemoteAttribute *remoteAttribute = remoteAttributes[i];
    BLEUuid uuid = BLEUuid(remoteAttribute->uuid());
    const unsigned char* uuidData = uuid.data();

    ble_uuid_t nordicUUID;

    if (uuid.length() == 2) {
      nordicUUID.uuid = (uuidData[1] << 8) | uuidData[0];
      nordicUUID.type = BLE_UUID_TYPE_BLE;
    } else {
      unsigned char uuidDataTemp[16];

      memcpy(&uuidDataTemp, uuidData, sizeof(uuidDataTemp));

      nordicUUID.uuid = (uuidData[13] << 8) | uuidData[12];

      uuidDataTemp[13] = 0;
      uuidDataTemp[12] = 0;

      sd_ble_uuid_vs_add((ble_uuid128_t*)&uuidDataTemp, &nordicUUID.type);
    }

    if (remoteAttribute->type() == BLETypeService) {
      this->_remoteServiceInfo[remoteServiceIndex].service = lastRemoteService = (BLERemoteService *)remoteAttribute;
      this->_remoteServiceInfo[remoteServiceIndex].uuid = nordicUUID;

      memset(&this->_remoteServiceInfo[remoteServiceIndex].handlesRange, 0, sizeof(this->_remoteServiceInfo[remoteServiceIndex].handlesRange));

      remoteServiceIndex++;
    } else if (remoteAttribute->type() == BLETypeCharacteristic) {
      this->_remoteCharacteristicInfo[remoteCharacteristicIndex].characteristic = (BLERemoteCharacteristic *)remoteAttribute;
      this->_remoteCharacteristicInfo[remoteCharacteristicIndex].service = lastRemoteService;
      this->_remoteCharacteristicInfo[remoteCharacteristicIndex].uuid = nordicUUID;

      memset(&this->_remoteCharacteristicInfo[remoteCharacteristicIndex].properties, 0, sizeof(this->_remoteCharacteristicInfo[remoteCharacteristicIndex].properties));
      this->_remoteCharacteristicInfo[remoteCharacteristicIndex].valueHandle = 0;

      remoteCharacteristicIndex++;
    }
  }

  if (this->_bondStore && this->_bondStore->hasData()) {
#ifdef NRF_51822_DEBUG
    Serial.println(F("Restoring bond data"));
#endif
#ifdef NRF51_S130
    this->_bondStore->getData(this->_bondData, 0, sizeof(this->_bondData));
#else
    this->_bondStore->getData(this->_authStatusBuffer, 0, sizeof(this->_authStatusBuffer));
#endif
  }

  this->startAdvertising();

#ifdef __RFduino__
  RFduinoBLE_enabled = 1;
#endif
}
void BLEPeripheral::BLEDeviceCharacteristicValueChanged(BLEDevice& device, BLECharacteristic& characteristic, const unsigned char* value, unsigned char valueLength) {
  characteristic.setValue(this->_central, value, valueLength);
}
void BLEPeripheral::BLEDeviceCharacteristicSubscribedChanged(BLEDevice& device, BLECharacteristic& characteristic, bool subscribed) {
  characteristic.setSubscribed(this->_central, subscribed);
}
Esempio n. 19
0
void BLESerial::_received(BLECentral& /*central*/, BLECharacteristic& rxCharacteristic) {
  BLESerial::_instance->_received(rxCharacteristic.value(), rxCharacteristic.valueLength());
}
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();
}
Esempio n. 21
0
void BLEPeripheral::nRF8001CharacteristicValueChanged(nRF8001& nRF8001, BLECharacteristic& characteristic, const unsigned char* value, unsigned char valueLength) {
  characteristic.setValue(this->_central, value, valueLength);
}
Esempio n. 22
0
void BLEPeripheral::nRF8001CharacteristicSubscribedChanged(nRF8001& nRF8001, BLECharacteristic& characteristic, bool subscribed) {
  characteristic.setSubscribed(this->_central, subscribed);
}
Esempio n. 23
0
/**
 * @brief Handle a GATTS server event.
 */
void BLEService::handleGATTServerEvent(
		esp_gatts_cb_event_t      event,
		esp_gatt_if_t             gatts_if,
		esp_ble_gatts_cb_param_t *param) {


	switch(event) {
	  // ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service.
		// add_char:
		// - esp_gatt_status_t status
		// - uint16_t attr_handle
		// - uint16_t service_handle
		// - esp_bt_uuid_t char_uuid

		// If we have reached the correct service, then locate the characteristic and remember the handle
		// for that characteristic.
		case ESP_GATTS_ADD_CHAR_EVT: {
			if (m_handle == param->add_char.service_handle) {
				BLECharacteristic *pCharacteristic = getCharacteristic(BLEUUID(param->add_char.char_uuid));
				if (pCharacteristic == nullptr) {
					ESP_LOGE(LOG_TAG, "Expected to find characteristic with UUID: %s, but didnt!",
							BLEUUID(param->add_char.char_uuid).toString().c_str());
					dump();
					m_semaphoreAddCharEvt.give();
					break;
				}
				pCharacteristic->setHandle(param->add_char.attr_handle);
				m_characteristicMap.setByHandle(param->add_char.attr_handle, pCharacteristic);
				//ESP_LOGD(tag, "Characteristic map: %s", m_characteristicMap.toString().c_str());
				m_semaphoreAddCharEvt.give();
				break;
			} // Reached the correct service.
			break;
		} // ESP_GATTS_ADD_CHAR_EVT

		// ESP_GATTS_START_EVT
		//
		// start:
		// esp_gatt_status_t status
		// uint16_t service_handle
		case ESP_GATTS_START_EVT: {
			if (param->start.service_handle == getHandle()) {
				m_semaphoreStartEvt.give();
			}
			break;
		} // ESP_GATTS_START_EVT


		// ESP_GATTS_CREATE_EVT
		// Called when a new service is registered as having been created.
		//
		// create:
		// * esp_gatt_status_t status
		// * uint16_t service_handle
		// * esp_gatt_srvc_id_t service_id
		// * - esp_gatt_id id
		// *   - esp_bt_uuid uuid
		// *   - uint8_t inst_id
		// * - bool is_primary
		//
		case ESP_GATTS_CREATE_EVT: {
			if (getUUID().equals(BLEUUID(param->create.service_id.id.uuid))) {
				setHandle(param->create.service_handle);
				m_semaphoreCreateEvt.give();
			}
			break;
		} // ESP_GATTS_CREATE_EVT

		default: {
			break;
		} // Default
	} // Switch

	m_characteristicMap.handleGATTServerEvent(event, gatts_if, param);
} // handleGATTServerEvent
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();
}