mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-24 22:20:55 +01:00
Refactor advertisedDevice (#181)
* Stores complete advertisement payload and only performs parsing on demand. The advertised data is no longer parsed automatically as it is discovered, instead it will be parsed to find only the data requested by the user application when it makes a call to do so. This saves processing time and approximately 2.4k in flash size, with the new methods listed below included. Add more advertised device field methods: * Adds haveAdvInterval/getAdvInterval - checks if the interval is advertised / gets the advertisement interval value. * Adds haveConnParams/getMinInterval/getMaxInterval - checks if the parameters are advertised / get min value / get max value. * Adds haveURI/getURI - checks if a URI is advertised / gets the URI data. * Adds haveTargetAddress/getTargetAddressCount/getTargetAddress(index) - checks if a target address is present / gets a count of the addresses targeted / gets the address of the target at index.
This commit is contained in:
parent
51c49ba9fc
commit
9527c41486
4 changed files with 507 additions and 313 deletions
|
@ -28,25 +28,14 @@ static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
||||||
/**
|
/**
|
||||||
* @brief Constructor
|
* @brief Constructor
|
||||||
*/
|
*/
|
||||||
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() {
|
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() :
|
||||||
|
m_payload(62,0)
|
||||||
|
{
|
||||||
m_advType = 0;
|
m_advType = 0;
|
||||||
m_appearance = 0;
|
|
||||||
m_manufacturerData = "";
|
|
||||||
m_name = "";
|
|
||||||
m_rssi = -9999;
|
m_rssi = -9999;
|
||||||
m_txPower = 0;
|
m_callbackSent = false;
|
||||||
m_payloadLength = 0;
|
m_timestamp = 0;
|
||||||
m_payload = nullptr;
|
m_advLength = 0;
|
||||||
|
|
||||||
m_haveAppearance = false;
|
|
||||||
m_haveManufacturerData = false;
|
|
||||||
m_haveName = false;
|
|
||||||
m_haveRSSI = false;
|
|
||||||
m_haveServiceData = false;
|
|
||||||
m_haveServiceUUID = false;
|
|
||||||
m_haveTXPower = false;
|
|
||||||
m_callbackSent = false;
|
|
||||||
|
|
||||||
} // NimBLEAdvertisedDevice
|
} // NimBLEAdvertisedDevice
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,25 +71,126 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
|
||||||
* @return The appearance of the advertised device.
|
* @return The appearance of the advertised device.
|
||||||
*/
|
*/
|
||||||
uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
||||||
return m_appearance;
|
uint8_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(BLE_HS_ADV_TYPE_APPEARANCE, 0, &data_loc) > 0) {
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length == BLE_HS_ADV_APPEARANCE_LEN + 1) {
|
||||||
|
return *field->value | *(field->value + 1) << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
} // getAppearance
|
} // getAppearance
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the advertisement interval.
|
||||||
|
* @return The advertisement interval in 0.625ms units.
|
||||||
|
*/
|
||||||
|
uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
|
||||||
|
uint8_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL, 0, &data_loc) > 0) {
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length == BLE_HS_ADV_ADV_ITVL_LEN + 1) {
|
||||||
|
return *field->value | *(field->value + 1) << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} // getAdvInterval
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the preferred min connection interval.
|
||||||
|
* @return The preferred min connection interval in 1.25ms units.
|
||||||
|
*/
|
||||||
|
uint16_t NimBLEAdvertisedDevice::getMinInterval() {
|
||||||
|
uint8_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length == BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1) {
|
||||||
|
return *field->value | *(field->value + 1) << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} // getMinInterval
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the preferred max connection interval.
|
||||||
|
* @return The preferred max connection interval in 1.25ms units.
|
||||||
|
*/
|
||||||
|
uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
|
||||||
|
uint8_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length == BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1) {
|
||||||
|
return *(field->value + 2) | *(field->value + 3) << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} // getMaxInterval
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the manufacturer data.
|
* @brief Get the manufacturer data.
|
||||||
* @return The manufacturer data of the advertised device.
|
* @return The manufacturer data of the advertised device.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
||||||
return m_manufacturerData;
|
uint8_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, 0, &data_loc) > 0) {
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length > 1) {
|
||||||
|
return std::string((char*)field->value, field->length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
} // getManufacturerData
|
} // getManufacturerData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the URI from the advertisement.
|
||||||
|
* @return The URI data.
|
||||||
|
*/
|
||||||
|
std::string NimBLEAdvertisedDevice::getURI() {
|
||||||
|
uint8_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(BLE_HS_ADV_TYPE_URI, 0, &data_loc) > 0) {
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length > 1) {
|
||||||
|
return std::string((char*)field->value, field->length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
} // getURI
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the advertised name.
|
* @brief Get the advertised name.
|
||||||
* @return The name of the advertised device.
|
* @return The name of the advertised device.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getName() {
|
std::string NimBLEAdvertisedDevice::getName() {
|
||||||
return m_name;
|
uint8_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(BLE_HS_ADV_TYPE_COMP_NAME, 0, &data_loc) > 0 ||
|
||||||
|
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME, 0, &data_loc) > 0)
|
||||||
|
{
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length > 1) {
|
||||||
|
return std::string((char*)field->value, field->length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
} // getName
|
} // getName
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,17 +212,70 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() {
|
||||||
} // getScan
|
} // getScan
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of target addresses.
|
||||||
|
* @return The number of addresses.
|
||||||
|
*/
|
||||||
|
size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||||
|
uint8_t count = 0;
|
||||||
|
|
||||||
|
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the target address at the index.
|
||||||
|
* @param [in] index The index of the target address.
|
||||||
|
* @return The target address.
|
||||||
|
*/
|
||||||
|
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
||||||
|
ble_hs_adv_field *field = nullptr;
|
||||||
|
uint8_t count = 0;
|
||||||
|
uint8_t data_loc = 0xFF;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
|
||||||
|
|
||||||
|
if (count < index) {
|
||||||
|
index -= count;
|
||||||
|
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count > 0 && data_loc != 0xFF) {
|
||||||
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length < index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
||||||
|
index -= count - field->length / BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||||
|
}
|
||||||
|
if(field->length > index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
||||||
|
return NimBLEAddress(field->value + (index - 1) * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NimBLEAddress("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the service data.
|
* @brief Get the service data.
|
||||||
* @param [in] index The vector index of the service data requested.
|
* @param [in] index The index of the service data requested.
|
||||||
* @return The advertised service data or empty string if no data.
|
* @return The advertised service data or empty string if no data.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||||
if(index > m_serviceDataVec.size()) {
|
ble_hs_adv_field *field = nullptr;
|
||||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: index out of range");
|
uint8_t bytes;
|
||||||
return "";
|
uint8_t data_loc = findServiceData(index, &bytes);
|
||||||
|
|
||||||
|
if(data_loc != 0xFF) {
|
||||||
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length > bytes) {
|
||||||
|
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return m_serviceDataVec[index].second;
|
|
||||||
|
return "";
|
||||||
} //getServiceData
|
} //getServiceData
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,51 +284,148 @@ std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||||
* @param [in] uuid The uuid of the service data requested.
|
* @param [in] uuid The uuid of the service data requested.
|
||||||
* @return The advertised service data or empty string if no data.
|
* @return The advertised service data or empty string if no data.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) const {
|
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
|
||||||
for(auto &it : m_serviceDataVec) {
|
ble_hs_adv_field *field = nullptr;
|
||||||
if(it.first == uuid) {
|
uint8_t bytes;
|
||||||
return it.second;
|
uint8_t index = 0;
|
||||||
|
uint8_t data_loc = findServiceData(index, &bytes);
|
||||||
|
uint8_t uuidBytes = uuid.bitSize() / 8;
|
||||||
|
uint8_t plSize = m_payload.size() - 2;
|
||||||
|
|
||||||
|
while(data_loc < plSize) {
|
||||||
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(bytes == uuidBytes && NimBLEUUID(field->value, bytes, false) == uuid) {
|
||||||
|
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
data_loc = findServiceData(index, &bytes);
|
||||||
}
|
}
|
||||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: uuid not found");
|
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "No service data found");
|
||||||
return "";
|
return "";
|
||||||
} //getServiceData
|
} //getServiceData
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the advertised service UUID.
|
* @brief Get the UUID of the serice data at the index.
|
||||||
* @param [in] index The vector index of the service data UUID requested.
|
* @param [in] index The index of the service data UUID requested.
|
||||||
* @return The advertised service UUID or an empty UUID if not found.
|
* @return The advertised service data UUID or an empty UUID if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||||
if(!haveServiceData() || index > m_serviceDataVec.size()) {
|
ble_hs_adv_field *field = nullptr;
|
||||||
NIMBLE_LOGW(LOG_TAG, "getServiceDataUUID: index out of range");
|
uint8_t bytes;
|
||||||
return NimBLEUUID("");
|
uint8_t data_loc = findServiceData(index, &bytes);
|
||||||
|
|
||||||
|
if(data_loc != 0xFF) {
|
||||||
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length >= bytes) {
|
||||||
|
return NimBLEUUID(field->value, bytes, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return m_serviceDataVec[index].first;
|
|
||||||
|
return NimBLEUUID("");
|
||||||
} // getServiceDataUUID
|
} // getServiceDataUUID
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find the service data at the index.
|
||||||
|
* @param [in] index The index of the service data to find.
|
||||||
|
* @param [in] bytes A pointer to storage for the number of the bytes in the UUID.
|
||||||
|
* @return The index in the vector where the data is located, 0xFF if not found.
|
||||||
|
*/
|
||||||
|
uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||||
|
uint8_t data_loc = 0;
|
||||||
|
uint8_t found = 0;
|
||||||
|
|
||||||
|
*bytes = 0;
|
||||||
|
index++;
|
||||||
|
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16, index, &data_loc);
|
||||||
|
if(found == index) {
|
||||||
|
*bytes = 2;
|
||||||
|
return data_loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
index -= found;
|
||||||
|
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32, index, &data_loc);
|
||||||
|
if(found == index) {
|
||||||
|
*bytes = 4;
|
||||||
|
return data_loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
index -= found;
|
||||||
|
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128, index, &data_loc);
|
||||||
|
if(found == index) {
|
||||||
|
*bytes = 16;
|
||||||
|
return data_loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the count of advertised service data UUIDS
|
* @brief Get the count of advertised service data UUIDS
|
||||||
* @return The number of service data UUIDS in the vector.
|
* @return The number of service data UUIDS in the vector.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||||
return m_serviceDataVec.size();
|
uint8_t count = 0;
|
||||||
|
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32);
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128);
|
||||||
|
|
||||||
|
return count;
|
||||||
} // getServiceDataCount
|
} // getServiceDataCount
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Service UUID.
|
* @brief Get the Service UUID.
|
||||||
* @param [in] index The vector index of the service UUID requested.
|
* @param [in] index The index of the service UUID requested.
|
||||||
* @return The Service UUID of the advertised service, or an empty UUID if not found.
|
* @return The Service UUID of the advertised service, or an empty UUID if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||||
if(!haveServiceUUID() || index > m_serviceUUIDs.size()) {
|
uint8_t count = 0;
|
||||||
NIMBLE_LOGW(LOG_TAG, "getServiceUUID: index out of range");
|
uint8_t data_loc = 0;
|
||||||
return NimBLEUUID("");
|
uint8_t uuidBytes = 0;
|
||||||
|
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||||
|
ble_hs_adv_field *field = nullptr;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
count = findAdvField(type, index, &data_loc);
|
||||||
|
if(count >= index) {
|
||||||
|
if(type < BLE_HS_ADV_TYPE_INCOMP_UUIDS32) {
|
||||||
|
uuidBytes = 2;
|
||||||
|
} else if(type < BLE_HS_ADV_TYPE_INCOMP_UUIDS128) {
|
||||||
|
uuidBytes = 4;
|
||||||
|
} else {
|
||||||
|
uuidBytes = 16;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
type++;
|
||||||
|
index -= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(type <= BLE_HS_ADV_TYPE_COMP_UUIDS128);
|
||||||
|
|
||||||
|
if(uuidBytes > 0) {
|
||||||
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
// In the case of more than one field of service uuid's we need to adjust
|
||||||
|
// the index to account for the uuids of the previous fields.
|
||||||
|
if(field->length < index * uuidBytes) {
|
||||||
|
index -= count - field->length / uuidBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(field->length > uuidBytes * index) {
|
||||||
|
return NimBLEUUID(field->value + uuidBytes * (index - 1), uuidBytes, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return m_serviceUUIDs[index];
|
|
||||||
|
return NimBLEUUID("");
|
||||||
} // getServiceUUID
|
} // getServiceUUID
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,18 +434,32 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||||
* @return The count of services in the advertising packet.
|
* @return The count of services in the advertising packet.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||||
return m_serviceUUIDs.size();
|
uint8_t count = 0;
|
||||||
|
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS16);
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS32);
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS32);
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS128);
|
||||||
|
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS128);
|
||||||
|
|
||||||
|
return count;
|
||||||
} // getServiceUUIDCount
|
} // getServiceUUIDCount
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check advertised services for existance of the required UUID
|
* @brief Check advertised services for existance of the required UUID
|
||||||
|
* @param [in] uuid The service uuid to look for in the advertisement.
|
||||||
* @return Return true if service is advertised
|
* @return Return true if service is advertised
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const {
|
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) {
|
||||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
size_t count = getServiceUUIDCount();
|
||||||
if (m_serviceUUIDs[i].equals(uuid)) return true;
|
for(size_t i = 0; i < count; i++) {
|
||||||
|
if(uuid == getServiceUUID(i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} // isAdvertisingService
|
} // isAdvertisingService
|
||||||
|
|
||||||
|
@ -215,16 +469,43 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const
|
||||||
* @return The TX Power of the advertised device.
|
* @return The TX Power of the advertised device.
|
||||||
*/
|
*/
|
||||||
int8_t NimBLEAdvertisedDevice::getTXPower() {
|
int8_t NimBLEAdvertisedDevice::getTXPower() {
|
||||||
return m_txPower;
|
uint8_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL, 0, &data_loc) > 0) {
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length == BLE_HS_ADV_TX_PWR_LVL_LEN + 1) {
|
||||||
|
return *(int8_t*)field->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -99;
|
||||||
} // getTXPower
|
} // getTXPower
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Does this advertisement have preferred connection parameters?
|
||||||
|
* @return True if connection parameters are present.
|
||||||
|
*/
|
||||||
|
bool NimBLEAdvertisedDevice::haveConnParams() {
|
||||||
|
return findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE) > 0;
|
||||||
|
} // haveConnParams
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Does this advertisement have have the advertising interval?
|
||||||
|
* @return True if the advertisement interval is present.
|
||||||
|
*/
|
||||||
|
bool NimBLEAdvertisedDevice::haveAdvInterval() {
|
||||||
|
return findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL) > 0;
|
||||||
|
} // haveAdvInterval
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Does this advertisement have an appearance value?
|
* @brief Does this advertisement have an appearance value?
|
||||||
* @return True if there is an appearance value present.
|
* @return True if there is an appearance value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveAppearance() {
|
bool NimBLEAdvertisedDevice::haveAppearance() {
|
||||||
return m_haveAppearance;
|
return findAdvField(BLE_HS_ADV_TYPE_APPEARANCE) > 0;
|
||||||
} // haveAppearance
|
} // haveAppearance
|
||||||
|
|
||||||
|
|
||||||
|
@ -233,16 +514,36 @@ bool NimBLEAdvertisedDevice::haveAppearance() {
|
||||||
* @return True if there is manufacturer data present.
|
* @return True if there is manufacturer data present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveManufacturerData() {
|
bool NimBLEAdvertisedDevice::haveManufacturerData() {
|
||||||
return m_haveManufacturerData;
|
return findAdvField(BLE_HS_ADV_TYPE_MFG_DATA) > 0;
|
||||||
} // haveManufacturerData
|
} // haveManufacturerData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Does this advertisement have a URI?
|
||||||
|
* @return True if there is a URI present.
|
||||||
|
*/
|
||||||
|
bool NimBLEAdvertisedDevice::haveURI() {
|
||||||
|
return findAdvField(BLE_HS_ADV_TYPE_URI) > 0;
|
||||||
|
} // haveURI
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Does the advertisement contain a target address?
|
||||||
|
* @return True if an address is present.
|
||||||
|
*/
|
||||||
|
bool NimBLEAdvertisedDevice::haveTargetAddress() {
|
||||||
|
return findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR) > 0 ||
|
||||||
|
findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Does this advertisement have a name value?
|
* @brief Does this advertisement have a name value?
|
||||||
* @return True if there is a name value present.
|
* @return True if there is a name value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveName() {
|
bool NimBLEAdvertisedDevice::haveName() {
|
||||||
return m_haveName;
|
return findAdvField(BLE_HS_ADV_TYPE_COMP_NAME) > 0 ||
|
||||||
|
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME) > 0;
|
||||||
} // haveName
|
} // haveName
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,7 +552,7 @@ bool NimBLEAdvertisedDevice::haveName() {
|
||||||
* @return True if there is a signal strength value present.
|
* @return True if there is a signal strength value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveRSSI() {
|
bool NimBLEAdvertisedDevice::haveRSSI() {
|
||||||
return m_haveRSSI;
|
return m_rssi != -9999;
|
||||||
} // haveRSSI
|
} // haveRSSI
|
||||||
|
|
||||||
|
|
||||||
|
@ -260,7 +561,7 @@ bool NimBLEAdvertisedDevice::haveRSSI() {
|
||||||
* @return True if there is a service data value present.
|
* @return True if there is a service data value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveServiceData() {
|
bool NimBLEAdvertisedDevice::haveServiceData() {
|
||||||
return m_haveServiceData;
|
return getServiceDataCount() > 0;
|
||||||
} // haveServiceData
|
} // haveServiceData
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,7 +570,7 @@ bool NimBLEAdvertisedDevice::haveServiceData() {
|
||||||
* @return True if there is a service UUID value present.
|
* @return True if there is a service UUID value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
||||||
return m_haveServiceUUID;
|
return getServiceUUIDCount() > 0;
|
||||||
} // haveServiceUUID
|
} // haveServiceUUID
|
||||||
|
|
||||||
|
|
||||||
|
@ -278,143 +579,71 @@ bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
||||||
* @return True if there is a transmission power value present.
|
* @return True if there is a transmission power value present.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::haveTXPower() {
|
bool NimBLEAdvertisedDevice::haveTXPower() {
|
||||||
return m_haveTXPower;
|
return findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL) > 0;
|
||||||
} // haveTXPower
|
} // haveTXPower
|
||||||
|
|
||||||
|
|
||||||
/**
|
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_t *data_loc) {
|
||||||
* @brief Parse the advertising pay load.
|
ble_hs_adv_field *field = nullptr;
|
||||||
*
|
uint8_t data = 0;
|
||||||
* The pay load is a buffer of bytes that is either 31 bytes long or terminated by
|
uint8_t length = m_payload.size();
|
||||||
* a 0 length value. Each entry in the buffer has the format:
|
uint8_t count = 0;
|
||||||
* [length][type][data...]
|
|
||||||
*
|
if(length < 2) {
|
||||||
* The length does not include itself but does include everything after it until the next record. A record
|
return count;
|
||||||
* with a length value of 0 indicates a terminator.
|
|
||||||
*
|
|
||||||
* https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
|
|
||||||
*/
|
|
||||||
void NimBLEAdvertisedDevice::parseAdvertisement(uint8_t* payload, uint8_t length) {
|
|
||||||
struct ble_hs_adv_fields fields;
|
|
||||||
int rc = ble_hs_adv_parse_fields(&fields, payload, length);
|
|
||||||
if (rc != 0) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "Gap Event Parse ERROR.");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_payload = payload;
|
while (length > 1) {
|
||||||
m_payloadLength = length;
|
field = (ble_hs_adv_field*)&m_payload[data];
|
||||||
|
|
||||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
if (field->length >= length) {
|
||||||
char* pHex = NimBLEUtils::buildHexData(nullptr, m_payload, m_payloadLength);
|
return count;
|
||||||
NIMBLE_LOGD(LOG_TAG,"payload: %s", pHex);
|
|
||||||
free(pHex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fields.uuids16 != NULL) {
|
|
||||||
for (int i = 0; i < fields.num_uuids16; i++) {
|
|
||||||
setServiceUUID(NimBLEUUID(fields.uuids16[i].value));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (fields.uuids32 != NULL) {
|
if (field->type == type) {
|
||||||
for (int i = 0; i < fields.num_uuids32; i++) {
|
switch(type) {
|
||||||
setServiceUUID(NimBLEUUID(fields.uuids32[i].value));
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
||||||
}
|
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
||||||
}
|
count += field->length / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
if (fields.uuids128 != NULL) {
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS32:
|
||||||
for (int i = 0; i < fields.num_uuids128; i++) {
|
case BLE_HS_ADV_TYPE_COMP_UUIDS32:
|
||||||
setServiceUUID(NimBLEUUID(&fields.uuids128[i]));
|
count += field->length / 4;
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (fields.name != NULL) {
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS128:
|
||||||
setName(std::string(reinterpret_cast<char*>(fields.name), fields.name_len));
|
case BLE_HS_ADV_TYPE_COMP_UUIDS128:
|
||||||
}
|
count += field->length / 16;
|
||||||
|
break;
|
||||||
|
|
||||||
if (fields.tx_pwr_lvl_is_present) {
|
case BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR:
|
||||||
setTXPower(fields.tx_pwr_lvl);
|
case BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR:
|
||||||
}
|
count += field->length / 6;
|
||||||
|
break;
|
||||||
|
|
||||||
if (fields.svc_data_uuid16 != NULL ||
|
default:
|
||||||
fields.svc_data_uuid32 != NULL ||
|
count++;
|
||||||
fields.svc_data_uuid128 != NULL)
|
break;
|
||||||
{
|
|
||||||
ble_hs_adv_field *field;
|
|
||||||
uint8_t *data = payload;
|
|
||||||
while(length > 1) {
|
|
||||||
field = (ble_hs_adv_field*)data;
|
|
||||||
|
|
||||||
if(field->length > length) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID16) {
|
if(data_loc != nullptr) {
|
||||||
if(field->length > 2) {
|
if(index == 0 || count >= index) {
|
||||||
uint16_t uuid;
|
break;
|
||||||
memcpy(&uuid, field->value, 2);
|
|
||||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 2), field->length - 3));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID32) {
|
|
||||||
if(field->length > 4) {
|
|
||||||
uint32_t uuid;
|
|
||||||
memcpy(&uuid, field->value, 4);
|
|
||||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 4), field->length - 5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID128) {
|
|
||||||
if(field->length > 16) {
|
|
||||||
NimBLEUUID uuid(field->value, (size_t)16, false);
|
|
||||||
setServiceData(uuid, std::string(reinterpret_cast<char*>(field->value + 16), field->length - 17));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
length -= 1 + field->length;
|
|
||||||
data += 1 + field->length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
length -= 1 + field->length;
|
||||||
|
data += 1 + field->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fields.appearance_is_present) {
|
if(data_loc != nullptr && field != nullptr) {
|
||||||
setAppearance(fields.appearance);
|
*data_loc = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fields.mfg_data != NULL) {
|
return count;
|
||||||
setManufacturerData(std::string(reinterpret_cast<char*>(fields.mfg_data), fields.mfg_data_len));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: create storage and fucntions for these parameters
|
|
||||||
if (fields.public_tgt_addr != NULL) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, " public_tgt_addr=");
|
|
||||||
u8p = fields.public_tgt_addr;
|
|
||||||
for (i = 0; i < fields.num_public_tgt_addrs; i++) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "public_tgt_addr=%s ", addr_str(u8p));
|
|
||||||
u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
|
||||||
}
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fields.slave_itvl_range != NULL) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, " slave_itvl_range=");
|
|
||||||
print_bytes(fields.slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fields.adv_itvl_is_present) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, " adv_itvl=0x%04x\n", fields.adv_itvl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fields.uri != NULL) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, " uri=");
|
|
||||||
print_bytes(fields.uri, fields.uri_len);
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
} //parseAdvertisement
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -428,106 +657,22 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the adFlag for this device.
|
* @brief Set the adFlag for this device.
|
||||||
* @param [in] The discovered adFlag.
|
* @param [in] advType The advertisement flag data from the advertisement.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
|
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
|
||||||
m_advType = advType;
|
m_advType = advType;
|
||||||
} // setAdvType
|
} // setAdvType
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the appearance for this device.
|
|
||||||
* @param [in] The discovered appearance.
|
|
||||||
*/
|
|
||||||
void NimBLEAdvertisedDevice::setAppearance(uint16_t appearance) {
|
|
||||||
m_appearance = appearance;
|
|
||||||
m_haveAppearance = true;
|
|
||||||
} // setAppearance
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the manufacturer data for this device.
|
|
||||||
* @param [in] The discovered manufacturer data.
|
|
||||||
*/
|
|
||||||
void NimBLEAdvertisedDevice::setManufacturerData(std::string manufacturerData) {
|
|
||||||
m_manufacturerData = manufacturerData;
|
|
||||||
m_haveManufacturerData = true;
|
|
||||||
} // setManufacturerData
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the name for this device.
|
|
||||||
* @param [in] name The discovered name.
|
|
||||||
*/
|
|
||||||
void NimBLEAdvertisedDevice::setName(std::string name) {
|
|
||||||
m_name = name;
|
|
||||||
m_haveName = true;
|
|
||||||
} // setName
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the RSSI for this device.
|
* @brief Set the RSSI for this device.
|
||||||
* @param [in] rssi The discovered RSSI.
|
* @param [in] rssi The RSSI of the discovered device.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisedDevice::setRSSI(int rssi) {
|
void NimBLEAdvertisedDevice::setRSSI(int rssi) {
|
||||||
m_rssi = rssi;
|
m_rssi = rssi;
|
||||||
m_haveRSSI = true;
|
|
||||||
} // setRSSI
|
} // setRSSI
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the Service UUID for this device.
|
|
||||||
* @param [in] serviceUUID The discovered serviceUUID
|
|
||||||
*/
|
|
||||||
|
|
||||||
void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
|
|
||||||
return setServiceUUID(NimBLEUUID(serviceUUID));
|
|
||||||
} // setServiceUUID
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the Service UUID for this device.
|
|
||||||
* @param [in] serviceUUID The discovered serviceUUID
|
|
||||||
*/
|
|
||||||
void NimBLEAdvertisedDevice::setServiceUUID(NimBLEUUID serviceUUID) {
|
|
||||||
// Don't add duplicates
|
|
||||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
|
||||||
if (m_serviceUUIDs[i] == serviceUUID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_serviceUUIDs.push_back(serviceUUID);
|
|
||||||
m_haveServiceUUID = true;
|
|
||||||
} // setServiceUUID
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the ServiceData value.
|
|
||||||
* @param [in] uuid The UUID that the service data belongs to.
|
|
||||||
* @param [in] data The service data.
|
|
||||||
*/
|
|
||||||
void NimBLEAdvertisedDevice::setServiceData(NimBLEUUID uuid, std::string data) {
|
|
||||||
m_haveServiceData = true;
|
|
||||||
for(auto &it : m_serviceDataVec) {
|
|
||||||
if(it.first == uuid) {
|
|
||||||
it.second = data;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_serviceDataVec.push_back({uuid, data});
|
|
||||||
} //setServiceData
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the power level for this device.
|
|
||||||
* @param [in] txPower The discovered power level.
|
|
||||||
*/
|
|
||||||
void NimBLEAdvertisedDevice::setTXPower(int8_t txPower) {
|
|
||||||
m_txPower = txPower;
|
|
||||||
m_haveTXPower = true;
|
|
||||||
} // setTXPower
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a string representation of this device.
|
* @brief Create a string representation of this device.
|
||||||
* @return A string representation of this device.
|
* @return A string representation of this device.
|
||||||
|
@ -579,10 +724,35 @@ std::string NimBLEAdvertisedDevice::toString() {
|
||||||
* @return The advertisement payload.
|
* @return The advertisement payload.
|
||||||
*/
|
*/
|
||||||
uint8_t* NimBLEAdvertisedDevice::getPayload() {
|
uint8_t* NimBLEAdvertisedDevice::getPayload() {
|
||||||
return m_payload;
|
return &m_payload[0];
|
||||||
} // getPayload
|
} // getPayload
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores the payload of the advertised device in a vector.
|
||||||
|
* @param [in] payload The advertisement payload.
|
||||||
|
* @param [in] length The length of the payload in bytes.
|
||||||
|
* @param [in] append Indicates if the the data should be appended (scan response).
|
||||||
|
*/
|
||||||
|
void NimBLEAdvertisedDevice::setPayload(uint8_t *payload, uint8_t length, bool append) {
|
||||||
|
if(!append) {
|
||||||
|
m_advLength = length;
|
||||||
|
m_payload.assign(payload, payload + length);
|
||||||
|
} else {
|
||||||
|
m_payload.insert(m_payload.end(), payload, payload + length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the length of the advertisement data in the payload.
|
||||||
|
* @return The number of bytes in the payload that is from the advertisment.
|
||||||
|
*/
|
||||||
|
uint8_t NimBLEAdvertisedDevice::getAdvLength() {
|
||||||
|
return m_advLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the advertised device address type.
|
* @brief Get the advertised device address type.
|
||||||
* @return The device address type:
|
* @return The device address type:
|
||||||
|
@ -610,7 +780,7 @@ time_t NimBLEAdvertisedDevice::getTimestamp() {
|
||||||
* @return The size of the payload in bytes.
|
* @return The size of the payload in bytes.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
||||||
return m_payloadLength;
|
return m_payload.size();
|
||||||
} // getPayloadLength
|
} // getPayloadLength
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,11 @@ public:
|
||||||
NimBLEAddress getAddress();
|
NimBLEAddress getAddress();
|
||||||
uint8_t getAdvType();
|
uint8_t getAdvType();
|
||||||
uint16_t getAppearance();
|
uint16_t getAppearance();
|
||||||
|
uint16_t getAdvInterval();
|
||||||
|
uint16_t getMinInterval();
|
||||||
|
uint16_t getMaxInterval();
|
||||||
std::string getManufacturerData();
|
std::string getManufacturerData();
|
||||||
|
std::string getURI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A template to convert the service data to <type\>.
|
* @brief A template to convert the service data to <type\>.
|
||||||
|
@ -67,7 +71,7 @@ public:
|
||||||
NimBLEScan* getScan();
|
NimBLEScan* getScan();
|
||||||
size_t getServiceDataCount();
|
size_t getServiceDataCount();
|
||||||
std::string getServiceData(uint8_t index = 0);
|
std::string getServiceData(uint8_t index = 0);
|
||||||
std::string getServiceData(const NimBLEUUID &uuid) const;
|
std::string getServiceData(const NimBLEUUID &uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A template to convert the service data to <tt><type\></tt>.
|
* @brief A template to convert the service data to <tt><type\></tt>.
|
||||||
|
@ -106,12 +110,15 @@ public:
|
||||||
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
||||||
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
||||||
size_t getServiceUUIDCount();
|
size_t getServiceUUIDCount();
|
||||||
|
NimBLEAddress getTargetAddress(uint8_t index = 0);
|
||||||
|
size_t getTargetAddressCount();
|
||||||
int8_t getTXPower();
|
int8_t getTXPower();
|
||||||
uint8_t* getPayload();
|
uint8_t* getPayload();
|
||||||
|
uint8_t getAdvLength();
|
||||||
size_t getPayloadLength();
|
size_t getPayloadLength();
|
||||||
uint8_t getAddressType();
|
uint8_t getAddressType();
|
||||||
time_t getTimestamp();
|
time_t getTimestamp();
|
||||||
bool isAdvertisingService(const NimBLEUUID &uuid) const;
|
bool isAdvertisingService(const NimBLEUUID &uuid);
|
||||||
bool haveAppearance();
|
bool haveAppearance();
|
||||||
bool haveManufacturerData();
|
bool haveManufacturerData();
|
||||||
bool haveName();
|
bool haveName();
|
||||||
|
@ -119,46 +126,30 @@ public:
|
||||||
bool haveServiceData();
|
bool haveServiceData();
|
||||||
bool haveServiceUUID();
|
bool haveServiceUUID();
|
||||||
bool haveTXPower();
|
bool haveTXPower();
|
||||||
|
bool haveConnParams();
|
||||||
|
bool haveAdvInterval();
|
||||||
|
bool haveTargetAddress();
|
||||||
|
bool haveURI();
|
||||||
std::string toString();
|
std::string toString();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEScan;
|
friend class NimBLEScan;
|
||||||
|
|
||||||
void parseAdvertisement(uint8_t* payload, uint8_t length);
|
void setAddress(NimBLEAddress address);
|
||||||
void setAddress(NimBLEAddress address);
|
void setAdvType(uint8_t advType);
|
||||||
void setAdvType(uint8_t advType);
|
void setPayload(uint8_t *payload, uint8_t length, bool append);
|
||||||
void setAppearance(uint16_t appearance);
|
void setRSSI(int rssi);
|
||||||
void setManufacturerData(std::string manufacturerData);
|
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
||||||
void setName(std::string name);
|
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||||
void setRSSI(int rssi);
|
|
||||||
void setServiceData(NimBLEUUID serviceUUID, std::string data);
|
|
||||||
void setServiceUUID(const char* serviceUUID);
|
|
||||||
void setServiceUUID(NimBLEUUID serviceUUID);
|
|
||||||
void setTXPower(int8_t txPower);
|
|
||||||
|
|
||||||
bool m_haveAppearance;
|
|
||||||
bool m_haveManufacturerData;
|
|
||||||
bool m_haveName;
|
|
||||||
bool m_haveRSSI;
|
|
||||||
bool m_haveServiceData;
|
|
||||||
bool m_haveServiceUUID;
|
|
||||||
bool m_haveTXPower;
|
|
||||||
|
|
||||||
|
|
||||||
NimBLEAddress m_address = NimBLEAddress("");
|
NimBLEAddress m_address = NimBLEAddress("");
|
||||||
uint8_t m_advType;
|
uint8_t m_advType;
|
||||||
uint16_t m_appearance;
|
|
||||||
std::string m_manufacturerData;
|
|
||||||
std::string m_name;
|
|
||||||
int m_rssi;
|
int m_rssi;
|
||||||
int8_t m_txPower;
|
|
||||||
uint8_t* m_payload;
|
|
||||||
size_t m_payloadLength;
|
|
||||||
time_t m_timestamp;
|
time_t m_timestamp;
|
||||||
bool m_callbackSent;
|
bool m_callbackSent;
|
||||||
|
uint8_t m_advLength;
|
||||||
|
|
||||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
std::vector<uint8_t> m_payload;
|
||||||
std::vector<std::pair<NimBLEUUID, std::string>>m_serviceDataVec;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -64,7 +64,7 @@ NimBLEScan::~NimBLEScan() {
|
||||||
|
|
||||||
case BLE_GAP_EVENT_DISC: {
|
case BLE_GAP_EVENT_DISC: {
|
||||||
if(pScan->m_ignoreResults) {
|
if(pScan->m_ignoreResults) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Scan op in progress - ignoring results");
|
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,25 +93,35 @@ NimBLEScan::~NimBLEScan() {
|
||||||
advertisedDevice->setAddress(advertisedAddress);
|
advertisedDevice->setAddress(advertisedAddress);
|
||||||
advertisedDevice->setAdvType(event->disc.event_type);
|
advertisedDevice->setAdvType(event->disc.event_type);
|
||||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||||
NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
||||||
}
|
} else {
|
||||||
else{
|
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
|
||||||
NIMBLE_LOGI(LOG_TAG, "UPDATING PREVIOUSLY FOUND DEVICE: %s", advertisedAddress.toString().c_str());
|
|
||||||
}
|
|
||||||
advertisedDevice->setRSSI(event->disc.rssi);
|
|
||||||
if(event->disc.length_data > 0) {
|
|
||||||
advertisedDevice->parseAdvertisement(event->disc.data, event->disc.length_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
advertisedDevice->m_timestamp = time(nullptr);
|
advertisedDevice->m_timestamp = time(nullptr);
|
||||||
|
advertisedDevice->setRSSI(event->disc.rssi);
|
||||||
|
|
||||||
|
if(event->disc.length_data > 0) {
|
||||||
|
if(event->disc.event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||||
|
advertisedDevice->setPayload(event->disc.data, event->disc.length_data, false);
|
||||||
|
} else {
|
||||||
|
advertisedDevice->setPayload(event->disc.data, event->disc.length_data, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||||
if(pScan->m_wantDuplicates || !advertisedDevice->m_callbackSent) {
|
if(pScan->m_wantDuplicates || !advertisedDevice->m_callbackSent) {
|
||||||
// If not active scanning report the result to the listener.
|
// If not active scanning or scan response is not available
|
||||||
if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
|
// report the result to the callback now.
|
||||||
|
if(pScan->m_scan_params.passive ||
|
||||||
|
(event->disc.event_type != BLE_HCI_ADV_TYPE_ADV_IND &&
|
||||||
|
event->disc.event_type != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
|
||||||
|
{
|
||||||
advertisedDevice->m_callbackSent = true;
|
advertisedDevice->m_callbackSent = true;
|
||||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||||
|
|
||||||
// Otherwise wait for the scan response so we can report all of the data at once.
|
// Otherwise, wait for the scan response so we can report the complete data.
|
||||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||||
advertisedDevice->m_callbackSent = true;
|
advertisedDevice->m_callbackSent = true;
|
||||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||||
|
@ -123,7 +133,17 @@ NimBLEScan::~NimBLEScan() {
|
||||||
}
|
}
|
||||||
case BLE_GAP_EVENT_DISC_COMPLETE: {
|
case BLE_GAP_EVENT_DISC_COMPLETE: {
|
||||||
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
|
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
|
||||||
event->disc_complete.reason);
|
event->disc_complete.reason);
|
||||||
|
|
||||||
|
// If a device advertised with scan reponse available and it was not received
|
||||||
|
// the callback would not have been invoked, so do it here.
|
||||||
|
if(pScan->m_pAdvertisedDeviceCallbacks) {
|
||||||
|
for(auto &it : pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||||
|
if(!it->m_callbackSent) {
|
||||||
|
pScan->m_pAdvertisedDeviceCallbacks->onResult(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pScan->m_scanCompleteCB != nullptr) {
|
if (pScan->m_scanCompleteCB != nullptr) {
|
||||||
pScan->m_scanCompleteCB(pScan->m_scanResults);
|
pScan->m_scanCompleteCB(pScan->m_scanResults);
|
||||||
|
@ -342,7 +362,7 @@ bool NimBLEScan::stop() {
|
||||||
|
|
||||||
int rc = ble_gap_disc_cancel();
|
int rc = ble_gap_disc_cancel();
|
||||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d\n", rc);
|
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d", rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +385,7 @@ bool NimBLEScan::stop() {
|
||||||
* @details After disconnecting, it may be required in the case we were connected to a device without a public address.
|
* @details After disconnecting, it may be required in the case we were connected to a device without a public address.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::erase(const NimBLEAddress &address) {
|
void NimBLEScan::erase(const NimBLEAddress &address) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||||
|
|
||||||
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) {
|
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) {
|
||||||
if((*it)->getAddress() == address) {
|
if((*it)->getAddress() == address) {
|
||||||
|
|
|
@ -65,29 +65,42 @@ static const char* LOG_TAG = "NimBLEUUID";
|
||||||
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
|
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID value not 2, 4, 16 or 36 bytes");
|
|
||||||
m_valueSet = false;
|
m_valueSet = false;
|
||||||
}
|
}
|
||||||
} // NimBLEUUID(std::string)
|
} // NimBLEUUID(std::string)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a UUID from 16 bytes of memory.
|
* @brief Create a UUID from 2, 4, 16 bytes of memory.
|
||||||
* @param [in] pData The pointer to the start of the UUID.
|
* @param [in] pData The pointer to the start of the UUID.
|
||||||
* @param [in] size The size of the data.
|
* @param [in] size The size of the data.
|
||||||
* @param [in] msbFirst Is the MSB first in pData memory?
|
* @param [in] msbFirst Is the MSB first in pData memory?
|
||||||
*/
|
*/
|
||||||
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
||||||
if (size != 16) {
|
uint8_t *uuidValue = nullptr;
|
||||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID length not 16 bytes");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
|
||||||
|
|
||||||
|
switch(size) {
|
||||||
|
case 2:
|
||||||
|
uuidValue = (uint8_t*)&m_uuid.u16.value;
|
||||||
|
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
uuidValue = (uint8_t*)&m_uuid.u32.value;
|
||||||
|
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
uuidValue = m_uuid.u128.value;
|
||||||
|
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_valueSet = false;
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Invalid UUID size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (msbFirst) {
|
if (msbFirst) {
|
||||||
std::reverse_copy(pData, pData + 16, m_uuid.u128.value);
|
std::reverse_copy(pData, pData + size, uuidValue);
|
||||||
} else {
|
} else {
|
||||||
memcpy(m_uuid.u128.value, pData, 16);
|
memcpy(uuidValue, pData, size);
|
||||||
}
|
}
|
||||||
m_valueSet = true;
|
m_valueSet = true;
|
||||||
} // NimBLEUUID
|
} // NimBLEUUID
|
||||||
|
|
Loading…
Reference in a new issue