2020-03-29 17:44:20 -06:00
|
|
|
/*
|
2024-12-12 19:21:03 -07:00
|
|
|
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
|
|
|
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
2020-03-29 17:44:20 -06:00
|
|
|
*
|
2024-12-12 19:21:03 -07:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2020-05-13 22:03:56 -06:00
|
|
|
*
|
2024-12-12 19:21:03 -07:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2020-03-29 17:44:20 -06:00
|
|
|
*
|
2024-12-12 19:21:03 -07:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
|
|
|
|
2020-05-13 22:03:56 -06:00
|
|
|
#include "nimconfig.h"
|
2021-12-29 08:08:25 -07:00
|
|
|
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
# include "NimBLEDevice.h"
|
|
|
|
# include "NimBLEAdvertisedDevice.h"
|
|
|
|
# include "NimBLEUtils.h"
|
|
|
|
# include "NimBLELog.h"
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
# include <climits>
|
2022-04-10 10:21:45 -06:00
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Constructor
|
2024-07-17 19:52:01 -06:00
|
|
|
* @param [in] event The advertisement event data.
|
|
|
|
*/
|
|
|
|
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice(const ble_gap_event* event, uint8_t eventType)
|
|
|
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
|
|
|
: m_address{event->ext_disc.addr},
|
|
|
|
m_advType{eventType},
|
|
|
|
m_rssi{event->ext_disc.rssi},
|
|
|
|
m_callbackSent{0},
|
|
|
|
m_advLength{event->ext_disc.length_data},
|
|
|
|
m_isLegacyAdv{!!(event->ext_disc.props & BLE_HCI_ADV_LEGACY_MASK)},
|
|
|
|
m_sid{event->ext_disc.sid},
|
|
|
|
m_primPhy{event->ext_disc.prim_phy},
|
|
|
|
m_secPhy{event->ext_disc.sec_phy},
|
|
|
|
m_periodicItvl{event->ext_disc.periodic_adv_itvl},
|
|
|
|
m_payload(event->ext_disc.data, event->ext_disc.data + event->ext_disc.length_data) {
|
|
|
|
# else
|
|
|
|
: m_address{event->disc.addr},
|
|
|
|
m_advType{eventType},
|
|
|
|
m_rssi{event->disc.rssi},
|
|
|
|
m_callbackSent{0},
|
|
|
|
m_advLength{event->disc.length_data},
|
2024-10-06 15:03:11 -06:00
|
|
|
m_payload(event->disc.data, event->disc.data + event->disc.length_data) {
|
2024-07-17 19:52:01 -06:00
|
|
|
# endif
|
2020-03-29 17:44:20 -06:00
|
|
|
} // NimBLEAdvertisedDevice
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
/**
|
|
|
|
* @brief Update the advertisement data.
|
|
|
|
* @param [in] event The advertisement event data.
|
|
|
|
*/
|
|
|
|
void NimBLEAdvertisedDevice::update(const ble_gap_event* event, uint8_t eventType) {
|
|
|
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
|
|
|
const auto& disc = event->ext_disc;
|
|
|
|
m_isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
|
|
|
|
# else
|
|
|
|
const auto& disc = event->disc;
|
|
|
|
# endif
|
|
|
|
|
|
|
|
m_rssi = disc.rssi;
|
|
|
|
if (eventType == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP && isLegacyAdvertisement()) {
|
|
|
|
m_payload.insert(m_payload.end(), disc.data, disc.data + disc.length_data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_advLength = disc.length_data;
|
|
|
|
m_payload.assign(disc.data, disc.data + disc.length_data);
|
|
|
|
m_callbackSent = 0; // new data, reset callback sent flag
|
|
|
|
} // update
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
/**
|
2020-07-08 19:27:26 -06:00
|
|
|
* @brief Get the address of the advertising device.
|
2020-03-29 17:44:20 -06:00
|
|
|
* @return The address of the advertised device.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
const NimBLEAddress& NimBLEAdvertisedDevice::getAddress() const {
|
2020-03-29 17:44:20 -06:00
|
|
|
return m_address;
|
|
|
|
} // getAddress
|
2020-05-25 18:52:46 -06:00
|
|
|
|
|
|
|
/**
|
2020-07-08 19:27:26 -06:00
|
|
|
* @brief Get the advertisement type.
|
|
|
|
* @return The advertising type the device is reporting:
|
|
|
|
* * BLE_HCI_ADV_TYPE_ADV_IND (0) - indirect advertising
|
2022-07-31 11:00:12 -06:00
|
|
|
* * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) - direct advertising - high duty cycle
|
2020-07-08 19:27:26 -06:00
|
|
|
* * BLE_HCI_ADV_TYPE_ADV_SCAN_IND (2) - indirect scan response
|
2022-07-31 11:00:12 -06:00
|
|
|
* * BLE_HCI_ADV_TYPE_ADV_NONCONN_IND (3) - indirect advertising - not connectable
|
2020-07-08 19:27:26 -06:00
|
|
|
* * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD (4) - direct advertising - low duty cycle
|
2020-05-25 18:52:46 -06:00
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getAdvType() const {
|
2020-05-25 18:52:46 -06:00
|
|
|
return m_advType;
|
2020-07-30 14:57:47 -06:00
|
|
|
} // getAdvType
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2023-04-06 20:11:50 +02:00
|
|
|
/**
|
|
|
|
* @brief Get the advertisement flags.
|
|
|
|
* @return The advertisement flags, a bitmask of:
|
|
|
|
* BLE_HS_ADV_F_DISC_LTD (0x01) - limited discoverability
|
|
|
|
* BLE_HS_ADV_F_DISC_GEN (0x02) - general discoverability
|
|
|
|
* BLE_HS_ADV_F_BREDR_UNSUP - BR/EDR not supported
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getAdvFlags() const {
|
|
|
|
size_t data_loc;
|
|
|
|
if (findAdvField(BLE_HS_ADV_TYPE_FLAGS, 0, &data_loc) > 0) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length == BLE_HS_ADV_FLAGS_LEN + 1) {
|
2023-04-06 20:11:50 +02:00
|
|
|
return *field->value;
|
|
|
|
}
|
|
|
|
}
|
2024-07-17 19:52:01 -06:00
|
|
|
|
2023-04-06 20:11:50 +02:00
|
|
|
return 0;
|
|
|
|
} // getAdvFlags
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the appearance.
|
|
|
|
*
|
|
|
|
* A %BLE device can declare its own appearance. The appearance is how it would like to be shown to an end user
|
2022-07-31 11:00:12 -06:00
|
|
|
* typically in the form of an icon.
|
2020-03-29 17:44:20 -06:00
|
|
|
*
|
|
|
|
* @return The appearance of the advertised device.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint16_t NimBLEAdvertisedDevice::getAppearance() const {
|
|
|
|
size_t data_loc;
|
|
|
|
if (findAdvField(BLE_HS_ADV_TYPE_APPEARANCE, 0, &data_loc) > 0) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length == BLE_HS_ADV_APPEARANCE_LEN + 1) {
|
2021-01-30 18:06:29 -07:00
|
|
|
return *field->value | *(field->value + 1) << 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getAppearance
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
/**
|
|
|
|
* @brief Get the advertisement interval.
|
|
|
|
* @return The advertisement interval in 0.625ms units.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint16_t NimBLEAdvertisedDevice::getAdvInterval() const {
|
|
|
|
size_t data_loc;
|
|
|
|
if (findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL, 0, &data_loc) > 0) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length == BLE_HS_ADV_ADV_ITVL_LEN + 1) {
|
2021-01-30 18:06:29 -07:00
|
|
|
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.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint16_t NimBLEAdvertisedDevice::getMinInterval() const {
|
|
|
|
size_t data_loc;
|
|
|
|
if (findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length == BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1) {
|
2021-01-30 18:06:29 -07:00
|
|
|
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.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint16_t NimBLEAdvertisedDevice::getMaxInterval() const {
|
|
|
|
size_t data_loc;
|
|
|
|
if (findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length == BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1) {
|
2021-01-30 18:06:29 -07:00
|
|
|
return *(field->value + 2) | *(field->value + 3) << 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} // getMaxInterval
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the manufacturer data.
|
2023-04-06 14:32:50 -06:00
|
|
|
* @param [in] index The index of the of the manufacturer data set to get.
|
|
|
|
* @return The manufacturer data.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
std::string NimBLEAdvertisedDevice::getManufacturerData(uint8_t index) const {
|
|
|
|
return getPayloadByType(BLE_HS_ADV_TYPE_MFG_DATA, index);
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getManufacturerData
|
|
|
|
|
2023-04-06 14:32:50 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the count of manufacturer data sets.
|
|
|
|
* @return The number of manufacturer data sets.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getManufacturerDataCount() const {
|
2023-04-06 14:32:50 -06:00
|
|
|
return findAdvField(BLE_HS_ADV_TYPE_MFG_DATA);
|
|
|
|
} // getManufacturerDataCount
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
/**
|
|
|
|
* @brief Get the URI from the advertisement.
|
|
|
|
* @return The URI data.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
std::string NimBLEAdvertisedDevice::getURI() const {
|
|
|
|
return getPayloadByType(BLE_HS_ADV_TYPE_URI);
|
2021-01-30 18:06:29 -07:00
|
|
|
} // getURI
|
|
|
|
|
2023-11-25 11:23:37 -03:00
|
|
|
/**
|
2024-07-17 19:52:01 -06:00
|
|
|
* @brief Get the data from any type available in the advertisement.
|
|
|
|
* @param [in] type The advertised data type BLE_HS_ADV_TYPE.
|
|
|
|
* @param [in] index The index of the data type.
|
|
|
|
* @return The data available under the type `type`.
|
|
|
|
*/
|
|
|
|
std::string NimBLEAdvertisedDevice::getPayloadByType(uint16_t type, uint8_t index) const {
|
|
|
|
size_t data_loc;
|
|
|
|
if (findAdvField(type, index, &data_loc) > 0) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length > 1) {
|
2023-11-25 11:23:37 -03:00
|
|
|
return std::string((char*)field->value, field->length - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
} // getPayloadByType
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
2020-07-08 19:27:26 -06:00
|
|
|
* @brief Get the advertised name.
|
2020-03-29 17:44:20 -06:00
|
|
|
* @return The name of the advertised device.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
std::string NimBLEAdvertisedDevice::getName() const {
|
|
|
|
return getPayloadByType(BLE_HS_ADV_TYPE_COMP_NAME);
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getName
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the RSSI.
|
|
|
|
* @return The RSSI of the advertised device.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
int8_t NimBLEAdvertisedDevice::getRSSI() const {
|
2020-03-29 17:44:20 -06:00
|
|
|
return m_rssi;
|
|
|
|
} // getRSSI
|
|
|
|
|
|
|
|
/**
|
2020-07-08 19:27:26 -06:00
|
|
|
* @brief Get the scan object that created this advertised device.
|
2020-03-29 17:44:20 -06:00
|
|
|
* @return The scan object.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
NimBLEScan* NimBLEAdvertisedDevice::getScan() const {
|
2020-07-28 20:09:54 -06:00
|
|
|
return NimBLEDevice::getScan();
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getScan
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
/**
|
|
|
|
* @brief Get the number of target addresses.
|
|
|
|
* @return The number of addresses.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getTargetAddressCount() const {
|
2024-11-10 13:31:37 -07:00
|
|
|
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
|
2024-07-17 19:52:01 -06:00
|
|
|
count += findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR);
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the target address at the index.
|
|
|
|
* @param [in] index The index of the target address.
|
|
|
|
* @return The target address.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) const {
|
|
|
|
size_t data_loc = ULONG_MAX;
|
|
|
|
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
|
|
|
|
if (count < index + 1) {
|
2021-01-30 18:06:29 -07:00
|
|
|
index -= count;
|
2024-11-10 13:31:37 -07:00
|
|
|
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
if (count > 0 && data_loc != ULONG_MAX) {
|
|
|
|
index++;
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length < index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
|
|
|
// In the case of more than one field of target addresses we need to adjust the index
|
2021-01-30 18:06:29 -07:00
|
|
|
index -= count - field->length / BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
|
|
|
}
|
2024-07-17 19:52:01 -06:00
|
|
|
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, field->type};
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-04 19:17:13 -06:00
|
|
|
return NimBLEAddress{};
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the service data.
|
2021-01-30 18:06:29 -07:00
|
|
|
* @param [in] index The index of the service data requested.
|
2020-07-28 20:09:54 -06:00
|
|
|
* @return The advertised service data or empty string if no data.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) const {
|
2021-01-30 18:06:29 -07:00
|
|
|
uint8_t bytes;
|
2024-07-17 19:52:01 -06:00
|
|
|
size_t data_loc = findServiceData(index, &bytes);
|
|
|
|
if (data_loc != ULONG_MAX) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length > bytes) {
|
|
|
|
const char* field_data = reinterpret_cast<const char*>(field->value + bytes);
|
|
|
|
return std::string(field_data, field->length - bytes - 1);
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
2020-07-28 20:09:54 -06:00
|
|
|
}
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
return "";
|
2024-07-17 19:52:01 -06:00
|
|
|
} // getServiceData
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
/**
|
2020-07-28 20:09:54 -06:00
|
|
|
* @brief Get the service data.
|
|
|
|
* @param [in] uuid The uuid of the service data requested.
|
|
|
|
* @return The advertised service data or empty string if no data.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID& uuid) const {
|
2021-01-30 18:06:29 -07:00
|
|
|
uint8_t bytes;
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t index = 0;
|
|
|
|
size_t data_loc = findServiceData(index, &bytes);
|
|
|
|
size_t pl_size = m_payload.size() - 2;
|
|
|
|
uint8_t uuid_bytes = uuid.bitSize() / 8;
|
|
|
|
|
|
|
|
while (data_loc < pl_size) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
2024-07-12 20:42:53 -06:00
|
|
|
if (bytes == uuid_bytes && NimBLEUUID(field->value, bytes) == uuid) {
|
2024-07-17 19:52:01 -06:00
|
|
|
const char* field_data = reinterpret_cast<const char*>(field->value + bytes);
|
|
|
|
return std::string(field_data, field->length - bytes - 1);
|
2020-07-28 20:09:54 -06:00
|
|
|
}
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
index++;
|
|
|
|
data_loc = findServiceData(index, &bytes);
|
2020-07-28 20:09:54 -06:00
|
|
|
}
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
NIMBLE_LOGI(LOG_TAG, "No service data found");
|
2020-07-28 20:09:54 -06:00
|
|
|
return "";
|
2024-07-17 19:52:01 -06:00
|
|
|
} // getServiceData
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2020-07-28 20:09:54 -06:00
|
|
|
/**
|
2022-07-31 11:00:12 -06:00
|
|
|
* @brief Get the UUID of the service data at the index.
|
2021-01-30 18:06:29 -07:00
|
|
|
* @param [in] index The index of the service data UUID requested.
|
|
|
|
* @return The advertised service data UUID or an empty UUID if not found.
|
2020-07-28 20:09:54 -06:00
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) const {
|
2021-01-30 18:06:29 -07:00
|
|
|
uint8_t bytes;
|
2024-07-17 19:52:01 -06:00
|
|
|
size_t data_loc = findServiceData(index, &bytes);
|
|
|
|
if (data_loc != ULONG_MAX) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length >= bytes) {
|
2024-07-12 20:42:53 -06:00
|
|
|
return NimBLEUUID(field->value, bytes);
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
2020-07-28 20:09:54 -06:00
|
|
|
}
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
return NimBLEUUID("");
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getServiceDataUUID
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
/**
|
|
|
|
* @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.
|
2022-04-10 10:21:45 -06:00
|
|
|
* @return The index in the vector where the data is located, ULONG_MAX if not found.
|
2021-01-30 18:06:29 -07:00
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t* bytes) const {
|
2021-01-30 18:06:29 -07:00
|
|
|
*bytes = 0;
|
2024-07-17 19:52:01 -06:00
|
|
|
|
|
|
|
size_t data_loc = 0;
|
|
|
|
uint8_t found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16, index, &data_loc);
|
|
|
|
if (found > index) {
|
2021-01-30 18:06:29 -07:00
|
|
|
*bytes = 2;
|
|
|
|
return data_loc;
|
|
|
|
}
|
|
|
|
|
|
|
|
index -= found;
|
2024-11-10 13:31:37 -07:00
|
|
|
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32, index, &data_loc);
|
2024-07-17 19:52:01 -06:00
|
|
|
if (found > index) {
|
2021-01-30 18:06:29 -07:00
|
|
|
*bytes = 4;
|
|
|
|
return data_loc;
|
|
|
|
}
|
|
|
|
|
|
|
|
index -= found;
|
2024-11-10 13:31:37 -07:00
|
|
|
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128, index, &data_loc);
|
2024-07-17 19:52:01 -06:00
|
|
|
if (found > index) {
|
2021-01-30 18:06:29 -07:00
|
|
|
*bytes = 16;
|
|
|
|
return data_loc;
|
|
|
|
}
|
|
|
|
|
2022-04-10 10:21:45 -06:00
|
|
|
return ULONG_MAX;
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
2020-07-28 20:09:54 -06:00
|
|
|
* @brief Get the count of advertised service data UUIDS
|
|
|
|
* @return The number of service data UUIDS in the vector.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getServiceDataCount() const {
|
2024-11-10 13:31:37 -07:00
|
|
|
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
|
2024-07-17 19:52:01 -06:00
|
|
|
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32);
|
|
|
|
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128);
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
return count;
|
2020-07-28 20:09:54 -06:00
|
|
|
} // getServiceDataCount
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the Service UUID.
|
2021-01-30 18:06:29 -07:00
|
|
|
* @param [in] index The index of the service UUID requested.
|
2020-07-28 20:09:54 -06:00
|
|
|
* @return The Service UUID of the advertised service, or an empty UUID if not found.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) const {
|
|
|
|
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
|
|
|
size_t data_loc = 0;
|
|
|
|
uint8_t uuid_bytes = 0;
|
|
|
|
uint8_t count = 0;
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
do {
|
|
|
|
count = findAdvField(type, index, &data_loc);
|
2024-07-17 19:52:01 -06:00
|
|
|
if (count > index) {
|
|
|
|
if (type < BLE_HS_ADV_TYPE_INCOMP_UUIDS32) {
|
|
|
|
uuid_bytes = 2;
|
|
|
|
} else if (type < BLE_HS_ADV_TYPE_INCOMP_UUIDS128) {
|
|
|
|
uuid_bytes = 4;
|
2021-01-30 18:06:29 -07:00
|
|
|
} else {
|
2024-07-17 19:52:01 -06:00
|
|
|
uuid_bytes = 16;
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
type++;
|
|
|
|
index -= count;
|
|
|
|
}
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
} while (type <= BLE_HS_ADV_TYPE_COMP_UUIDS128);
|
2021-01-30 18:06:29 -07:00
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
if (uuid_bytes > 0) {
|
|
|
|
index++;
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
2021-01-30 18:06:29 -07:00
|
|
|
// 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.
|
2024-07-17 19:52:01 -06:00
|
|
|
if (field->length < index * uuid_bytes) {
|
|
|
|
index -= count - field->length / uuid_bytes;
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
if (field->length > uuid_bytes * index) {
|
2024-07-12 20:42:53 -06:00
|
|
|
return NimBLEUUID(field->value + uuid_bytes * (index - 1), uuid_bytes);
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
2020-07-28 20:09:54 -06:00
|
|
|
}
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
return NimBLEUUID("");
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getServiceUUID
|
|
|
|
|
2020-08-15 07:40:01 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the number of services advertised
|
|
|
|
* @return The count of services in the advertising packet.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getServiceUUIDCount() const {
|
2024-11-10 13:31:37 -07:00
|
|
|
uint8_t count = findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
|
2024-07-17 19:52:01 -06:00
|
|
|
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);
|
2021-01-30 18:06:29 -07:00
|
|
|
|
|
|
|
return count;
|
2020-08-15 07:40:01 -06:00
|
|
|
} // getServiceUUIDCount
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
2022-07-31 11:00:12 -06:00
|
|
|
* @brief Check advertised services for existence of the required UUID
|
2021-01-30 18:06:29 -07:00
|
|
|
* @param [in] uuid The service uuid to look for in the advertisement.
|
2020-03-29 17:44:20 -06:00
|
|
|
* @return Return true if service is advertised
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID& uuid) const {
|
2021-01-30 18:06:29 -07:00
|
|
|
size_t count = getServiceUUIDCount();
|
2024-07-17 19:52:01 -06:00
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
|
|
if (uuid == getServiceUUID(i)) {
|
2021-01-30 18:06:29 -07:00
|
|
|
return true;
|
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
2021-01-30 18:06:29 -07:00
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
return false;
|
2020-07-08 19:27:26 -06:00
|
|
|
} // isAdvertisingService
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the TX Power.
|
|
|
|
* @return The TX Power of the advertised device.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
int8_t NimBLEAdvertisedDevice::getTXPower() const {
|
2022-04-10 10:21:45 -06:00
|
|
|
size_t data_loc = 0;
|
2024-07-17 19:52:01 -06:00
|
|
|
if (findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL, 0, &data_loc) > 0) {
|
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data_loc]);
|
|
|
|
if (field->length == BLE_HS_ADV_TX_PWR_LVL_LEN + 1) {
|
2021-01-30 18:06:29 -07:00
|
|
|
return *(int8_t*)field->value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -99;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getTXPower
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have preferred connection parameters?
|
|
|
|
* @return True if connection parameters are present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveConnParams() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
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.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveAdvInterval() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
return findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL) > 0;
|
|
|
|
} // haveAdvInterval
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have an appearance value?
|
|
|
|
* @return True if there is an appearance value present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveAppearance() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
return findAdvField(BLE_HS_ADV_TYPE_APPEARANCE) > 0;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // haveAppearance
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have manufacturer data?
|
|
|
|
* @return True if there is manufacturer data present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveManufacturerData() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
return findAdvField(BLE_HS_ADV_TYPE_MFG_DATA) > 0;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // haveManufacturerData
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have a URI?
|
|
|
|
* @return True if there is a URI present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveURI() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
return findAdvField(BLE_HS_ADV_TYPE_URI) > 0;
|
|
|
|
} // haveURI
|
|
|
|
|
2023-11-25 11:23:37 -03:00
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have a adv type `type`?
|
|
|
|
* @return True if there is a `type` present.
|
2024-07-17 19:52:01 -06:00
|
|
|
*/
|
|
|
|
bool NimBLEAdvertisedDevice::haveType(uint16_t type) const {
|
2023-11-25 11:23:37 -03:00
|
|
|
return findAdvField(type) > 0;
|
|
|
|
}
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
/**
|
|
|
|
* @brief Does the advertisement contain a target address?
|
|
|
|
* @return True if an address is present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveTargetAddress() const {
|
|
|
|
return findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR) > 0 || findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR) > 0;
|
2021-01-30 18:06:29 -07:00
|
|
|
}
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have a name value?
|
|
|
|
* @return True if there is a name value present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveName() const {
|
|
|
|
return findAdvField(BLE_HS_ADV_TYPE_COMP_NAME) > 0;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // haveName
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have a service data value?
|
|
|
|
* @return True if there is a service data value present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveServiceData() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
return getServiceDataCount() > 0;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // haveServiceData
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have a service UUID value?
|
|
|
|
* @return True if there is a service UUID value present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveServiceUUID() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
return getServiceUUIDCount() > 0;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // haveServiceUUID
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does this advertisement have a transmission power value?
|
|
|
|
* @return True if there is a transmission power value present.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::haveTXPower() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
return findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL) > 0;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // haveTXPower
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
2022-04-10 10:21:45 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the set ID of the extended advertisement.
|
|
|
|
* @return The set ID.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getSetId() const {
|
2022-04-10 10:21:45 -06:00
|
|
|
return m_sid;
|
|
|
|
} // getSetId
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the primary PHY used by this advertisement.
|
|
|
|
* @return The PHY type, one of:
|
|
|
|
* * BLE_HCI_LE_PHY_1M
|
|
|
|
* * BLE_HCI_LE_PHY_CODED
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getPrimaryPhy() const {
|
2022-04-10 10:21:45 -06:00
|
|
|
return m_primPhy;
|
|
|
|
} // getPrimaryPhy
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the primary PHY used by this advertisement.
|
|
|
|
* @return The PHY type, one of:
|
|
|
|
* * BLE_HCI_LE_PHY_1M
|
|
|
|
* * BLE_HCI_LE_PHY_2M
|
|
|
|
* * BLE_HCI_LE_PHY_CODED
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getSecondaryPhy() const {
|
2022-04-10 10:21:45 -06:00
|
|
|
return m_secPhy;
|
|
|
|
} // getSecondaryPhy
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the periodic interval of the advertisement.
|
|
|
|
* @return The periodic advertising interval, 0 if not periodic advertising.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint16_t NimBLEAdvertisedDevice::getPeriodicInterval() const {
|
2022-04-10 10:21:45 -06:00
|
|
|
return m_periodicItvl;
|
|
|
|
} // getPeriodicInterval
|
2024-07-17 19:52:01 -06:00
|
|
|
# endif
|
2022-04-10 10:21:45 -06:00
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, size_t* data_loc) const {
|
2022-04-10 10:21:45 -06:00
|
|
|
size_t length = m_payload.size();
|
|
|
|
size_t data = 0;
|
|
|
|
uint8_t count = 0;
|
2020-07-28 20:09:54 -06:00
|
|
|
|
2022-04-10 10:21:45 -06:00
|
|
|
while (length > 2) {
|
2024-07-17 19:52:01 -06:00
|
|
|
const ble_hs_adv_field* field = reinterpret_cast<const ble_hs_adv_field*>(&m_payload[data]);
|
2021-01-30 18:06:29 -07:00
|
|
|
if (field->length >= length) {
|
|
|
|
return count;
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
if (field->type == type || (type == BLE_HS_ADV_TYPE_COMP_NAME && field->type == BLE_HS_ADV_TYPE_INCOMP_NAME)) {
|
2022-04-10 10:21:45 -06:00
|
|
|
switch (type) {
|
2021-01-30 18:06:29 -07:00
|
|
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
|
|
|
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
|
|
|
count += field->length / 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS32:
|
|
|
|
case BLE_HS_ADV_TYPE_COMP_UUIDS32:
|
|
|
|
count += field->length / 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS128:
|
|
|
|
case BLE_HS_ADV_TYPE_COMP_UUIDS128:
|
|
|
|
count += field->length / 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR:
|
|
|
|
case BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR:
|
|
|
|
count += field->length / 6;
|
|
|
|
break;
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
case BLE_HS_ADV_TYPE_COMP_NAME:
|
|
|
|
// keep looking for complete name, else use this
|
|
|
|
if (data_loc != nullptr && field->type == BLE_HS_ADV_TYPE_INCOMP_NAME) {
|
|
|
|
*data_loc = data;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
// fall through
|
2021-01-30 18:06:29 -07:00
|
|
|
default:
|
|
|
|
count++;
|
|
|
|
break;
|
2020-07-28 20:09:54 -06:00
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2022-04-10 10:21:45 -06:00
|
|
|
if (data_loc != nullptr) {
|
2024-07-17 19:52:01 -06:00
|
|
|
if (count > index) { // assumes index values default to 0
|
2021-01-30 18:06:29 -07:00
|
|
|
break;
|
2020-07-28 20:09:54 -06:00
|
|
|
}
|
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
length -= 1 + field->length;
|
2024-07-17 19:52:01 -06:00
|
|
|
data += 1 + field->length;
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
if (data_loc != nullptr && count > index) {
|
2021-01-30 18:06:29 -07:00
|
|
|
*data_loc = data;
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
2020-07-28 20:09:54 -06:00
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
return count;
|
2024-07-17 19:52:01 -06:00
|
|
|
} // findAdvField
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create a string representation of this device.
|
|
|
|
* @return A string representation of this device.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
std::string NimBLEAdvertisedDevice::toString() const {
|
2020-03-29 17:44:20 -06:00
|
|
|
std::string res = "Name: " + getName() + ", Address: " + getAddress().toString();
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
if (haveAppearance()) {
|
|
|
|
char val[6];
|
|
|
|
snprintf(val, sizeof(val), "%d", getAppearance());
|
|
|
|
res += ", appearance: ";
|
|
|
|
res += val;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (haveManufacturerData()) {
|
2024-11-10 13:31:37 -07:00
|
|
|
auto mfgData = getManufacturerData();
|
|
|
|
res += ", manufacturer data: ";
|
|
|
|
res += NimBLEUtils::dataToHexString(reinterpret_cast<const uint8_t*>(mfgData.data()), mfgData.length());
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (haveServiceUUID()) {
|
|
|
|
res += ", serviceUUID: " + getServiceUUID().toString();
|
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
if (haveTXPower()) {
|
2020-03-31 20:16:27 -06:00
|
|
|
char val[5];
|
2020-03-29 17:44:20 -06:00
|
|
|
snprintf(val, sizeof(val), "%d", getTXPower());
|
|
|
|
res += ", txPower: ";
|
|
|
|
res += val;
|
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2022-04-10 10:21:45 -06:00
|
|
|
if (haveServiceData()) {
|
2024-11-10 13:31:37 -07:00
|
|
|
uint8_t count = getServiceDataCount();
|
2024-07-17 19:52:01 -06:00
|
|
|
res += "\nService Data:";
|
|
|
|
for (uint8_t i = 0; i < count; i++) {
|
2020-07-28 20:09:54 -06:00
|
|
|
res += "\nUUID: " + std::string(getServiceDataUUID(i));
|
|
|
|
res += ", Data: " + getServiceData(i);
|
|
|
|
}
|
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
return res;
|
|
|
|
|
|
|
|
} // toString
|
|
|
|
|
2021-01-30 18:06:29 -07:00
|
|
|
/**
|
|
|
|
* @brief Get the length of the advertisement data in the payload.
|
2022-07-31 11:00:12 -06:00
|
|
|
* @return The number of bytes in the payload that is from the advertisement.
|
2021-01-30 18:06:29 -07:00
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getAdvLength() const {
|
2021-01-30 18:06:29 -07:00
|
|
|
return m_advLength;
|
|
|
|
}
|
|
|
|
|
2020-07-08 19:27:26 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the advertised device address type.
|
|
|
|
* @return The device address type:
|
|
|
|
* * BLE_ADDR_PUBLIC (0x00)
|
|
|
|
* * BLE_ADDR_RANDOM (0x01)
|
|
|
|
* * BLE_ADDR_PUBLIC_ID (0x02)
|
|
|
|
* * BLE_ADDR_RANDOM_ID (0x03)
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
uint8_t NimBLEAdvertisedDevice::getAddressType() const {
|
2020-07-30 14:57:47 -06:00
|
|
|
return m_address.getType();
|
2020-07-08 19:27:26 -06:00
|
|
|
} // getAddressType
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2022-04-10 10:21:45 -06:00
|
|
|
/**
|
|
|
|
* @brief Check if this device is advertising as connectable.
|
|
|
|
* @return True if the device is connectable.
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::isConnectable() const {
|
|
|
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
2022-04-10 10:21:45 -06:00
|
|
|
if (m_isLegacyAdv) {
|
2024-07-17 19:52:01 -06:00
|
|
|
return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
|
2022-04-10 10:21:45 -06:00
|
|
|
}
|
2024-07-17 19:52:01 -06:00
|
|
|
# endif
|
|
|
|
return (m_advType & BLE_HCI_ADV_CONN_MASK) || (m_advType & BLE_HCI_ADV_DIRECT_MASK);
|
2022-04-10 10:21:45 -06:00
|
|
|
} // isConnectable
|
|
|
|
|
2024-11-18 09:37:46 -07:00
|
|
|
/**
|
|
|
|
* @brief Check if this device is advertising as scannable.
|
|
|
|
* @return True if the device is scannable.
|
|
|
|
*/
|
|
|
|
bool NimBLEAdvertisedDevice::isScannable() const {
|
|
|
|
return isLegacyAdvertisement() && (m_advType == BLE_HCI_ADV_TYPE_ADV_IND || m_advType == BLE_HCI_ADV_TYPE_ADV_SCAN_IND);
|
|
|
|
} // isScannable
|
|
|
|
|
2022-04-10 10:21:45 -06:00
|
|
|
/**
|
|
|
|
* @brief Check if this advertisement is a legacy or extended type
|
|
|
|
* @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
|
|
|
|
*/
|
2024-07-17 19:52:01 -06:00
|
|
|
bool NimBLEAdvertisedDevice::isLegacyAdvertisement() const {
|
|
|
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
2022-04-10 10:21:45 -06:00
|
|
|
return m_isLegacyAdv;
|
|
|
|
# else
|
|
|
|
return true;
|
2024-07-17 19:52:01 -06:00
|
|
|
# endif
|
2022-04-10 10:21:45 -06:00
|
|
|
} // isLegacyAdvertisement
|
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the payload advertised by the device.
|
|
|
|
* @return The advertisement payload.
|
|
|
|
*/
|
|
|
|
const std::vector<uint8_t>& NimBLEAdvertisedDevice::getPayload() const {
|
|
|
|
return m_payload;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the begin iterator for the payload.
|
|
|
|
* @return A read only iterator pointing to the first byte in the payload.
|
|
|
|
*/
|
|
|
|
const std::vector<uint8_t>::const_iterator NimBLEAdvertisedDevice::begin() const {
|
|
|
|
return m_payload.cbegin();
|
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-17 19:52:01 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the end iterator for the payload.
|
|
|
|
* @return A read only iterator pointing to one past the last byte of the payload.
|
|
|
|
*/
|
|
|
|
const std::vector<uint8_t>::const_iterator NimBLEAdvertisedDevice::end() const {
|
|
|
|
return m_payload.cend();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|