[BREAKING] Refactor NimBLEAdvertised device.

* Construct the device with the parameters from the advertisement in the initialization list.
* Removed no longer needed methods; setAddress, setAdvType, setRSSI, setSetId, setPrimaryPhy, setSecondaryPhy, setPeriodicInterval.
* Removed `hasRSSI()` method, the RSSI is always reported so this is redundant.
* Replace setPayload with new method; `update` which will update the device info when new advertisement data is received.
* getPayload now returns `const std::vector<uint8_t>` instead of a pointer to internal memory.
* Added `begin` and `end` read-only iterators for convienience and use in range loops.
* Timestamp removed, if needed then the app should track the time in the callback.
* Consolidate some functions to use getPayloadByType.
* Add optional index parameter to getPayloadByType.
* Change payload indexing to use 0 as the first item.
* Code cleanup and apply const correctness.
This commit is contained in:
h2zero 2024-07-17 19:52:01 -06:00 committed by h2zero
parent 6279817143
commit c2ab790e1d
3 changed files with 353 additions and 497 deletions

File diff suppressed because it is too large Load diff

View file

@ -12,8 +12,9 @@
* Author: kolban
*/
#ifndef COMPONENTS_NIMBLEADVERTISEDDEVICE_H_
#define COMPONENTS_NIMBLEADVERTISEDDEVICE_H_
#ifndef NIMBLE_CPP_ADVERTISED_DEVICE_H_
#define NIMBLE_CPP_ADVERTISED_DEVICE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
@ -23,14 +24,13 @@
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "host/ble_hs_adv.h"
# include "host/ble_gap.h"
# else
# include "nimble/nimble/host/include/host/ble_hs_adv.h"
# include "nimble/nimble/host/include/host/ble_gap.h"
# endif
#include <map>
# include <vector>
#include <time.h>
class NimBLEScan;
/**
@ -41,19 +41,58 @@ class NimBLEScan;
*/
class NimBLEAdvertisedDevice {
public:
NimBLEAdvertisedDevice();
NimBLEAdvertisedDevice() = default;
NimBLEAddress getAddress();
uint8_t getAdvType();
uint8_t getAdvFlags();
uint16_t getAppearance();
uint16_t getAdvInterval();
uint16_t getMinInterval();
uint16_t getMaxInterval();
uint8_t getManufacturerDataCount();
std::string getManufacturerData(uint8_t index = 0);
std::string getURI();
std::string getPayloadByType(uint16_t type);
uint8_t getAdvType() const;
uint8_t getAdvFlags() const;
uint16_t getAppearance() const;
uint16_t getAdvInterval() const;
uint16_t getMinInterval() const;
uint16_t getMaxInterval() const;
uint8_t getManufacturerDataCount() const;
const NimBLEAddress& getAddress() const;
std::string getManufacturerData(uint8_t index = 0) const;
std::string getURI() const;
std::string getPayloadByType(uint16_t type, uint8_t index = 0) const;
std::string getName() const;
int8_t getRSSI() const;
NimBLEScan* getScan() const;
uint8_t getServiceDataCount() const;
std::string getServiceData(uint8_t index = 0) const;
std::string getServiceData(const NimBLEUUID& uuid) const;
NimBLEUUID getServiceDataUUID(uint8_t index = 0) const;
NimBLEUUID getServiceUUID(uint8_t index = 0) const;
uint8_t getServiceUUIDCount() const;
NimBLEAddress getTargetAddress(uint8_t index = 0) const;
uint8_t getTargetAddressCount() const;
int8_t getTXPower() const;
uint8_t getAdvLength() const;
uint8_t getAddressType() const;
bool isAdvertisingService(const NimBLEUUID& uuid) const;
bool haveAppearance() const;
bool haveManufacturerData() const;
bool haveName() const;
bool haveServiceData() const;
bool haveServiceUUID() const;
bool haveTXPower() const;
bool haveConnParams() const;
bool haveAdvInterval() const;
bool haveTargetAddress() const;
bool haveURI() const;
bool haveType(uint16_t type) const;
std::string toString() const;
bool isConnectable() const;
bool isLegacyAdvertisement() const;
# if CONFIG_BT_NIMBLE_EXT_ADV
uint8_t getSetId() const;
uint8_t getPrimaryPhy() const;
uint8_t getSecondaryPhy() const;
uint16_t getPeriodicInterval() const;
# endif
const std::vector<uint8_t>& getPayload() const;
const std::vector<uint8_t>::const_iterator begin() const;
const std::vector<uint8_t>::const_iterator end() const;
/**
* @brief A template to convert the service data to <type\>.
@ -64,20 +103,13 @@ public:
* @details <b>Use:</b> <tt>getManufacturerData<type>(skipSizeCheck);</tt>
*/
template <typename T>
T getManufacturerData(bool skipSizeCheck = false) {
T getManufacturerData(bool skipSizeCheck = false) const {
std::string data = getManufacturerData();
if (!skipSizeCheck && data.size() < sizeof(T)) return T();
const char* pData = data.data();
return *((T*)pData);
}
std::string getName();
int getRSSI();
NimBLEScan* getScan();
uint8_t getServiceDataCount();
std::string getServiceData(uint8_t index = 0);
std::string getServiceData(const NimBLEUUID &uuid);
/**
* @brief A template to convert the service data to <tt><type\></tt>.
* @tparam T The type to convert the data to.
@ -88,7 +120,7 @@ public:
* @details <b>Use:</b> <tt>getServiceData<type>(skipSizeCheck);</tt>
*/
template <typename T>
T getServiceData(uint8_t index = 0, bool skipSizeCheck = false) {
T getServiceData(uint8_t index = 0, bool skipSizeCheck = false) const {
std::string data = getServiceData(index);
if (!skipSizeCheck && data.size() < sizeof(T)) return T();
const char* pData = data.data();
@ -105,79 +137,37 @@ public:
* @details <b>Use:</b> <tt>getServiceData<type>(skipSizeCheck);</tt>
*/
template <typename T>
T getServiceData(const NimBLEUUID &uuid, bool skipSizeCheck = false) {
T getServiceData(const NimBLEUUID& uuid, bool skipSizeCheck = false) const {
std::string data = getServiceData(uuid);
if (!skipSizeCheck && data.size() < sizeof(T)) return T();
const char* pData = data.data();
return *((T*)pData);
}
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
NimBLEUUID getServiceUUID(uint8_t index = 0);
uint8_t getServiceUUIDCount();
NimBLEAddress getTargetAddress(uint8_t index = 0);
uint8_t getTargetAddressCount();
int8_t getTXPower();
uint8_t* getPayload();
uint8_t getAdvLength();
size_t getPayloadLength();
uint8_t getAddressType();
time_t getTimestamp();
bool isAdvertisingService(const NimBLEUUID &uuid);
bool haveAppearance();
bool haveManufacturerData();
bool haveName();
bool haveRSSI();
bool haveServiceData();
bool haveServiceUUID();
bool haveTXPower();
bool haveConnParams();
bool haveAdvInterval();
bool haveTargetAddress();
bool haveURI();
bool haveType(uint16_t type);
std::string toString();
bool isConnectable();
bool isLegacyAdvertisement();
#if CONFIG_BT_NIMBLE_EXT_ADV
uint8_t getSetId();
uint8_t getPrimaryPhy();
uint8_t getSecondaryPhy();
uint16_t getPeriodicInterval();
#endif
private:
friend class NimBLEScan;
void setAddress(NimBLEAddress address);
void setAdvType(uint8_t advType, bool isLegacyAdv);
void setPayload(const uint8_t *payload, uint8_t length, bool append);
void setRSSI(int rssi);
#if CONFIG_BT_NIMBLE_EXT_ADV
void setSetId(uint8_t sid) { m_sid = sid; }
void setPrimaryPhy(uint8_t phy) { m_primPhy = phy; }
void setSecondaryPhy(uint8_t phy) { m_secPhy = phy; }
void setPeriodicInterval(uint16_t itvl) { m_periodicItvl = itvl; }
#endif
uint8_t findAdvField(uint8_t type, uint8_t index = 0, size_t * data_loc = nullptr);
size_t findServiceData(uint8_t index, uint8_t* bytes);
NimBLEAdvertisedDevice(const ble_gap_event* event, uint8_t eventType);
void update(const ble_gap_event* event, uint8_t eventType);
uint8_t findAdvField(uint8_t type, uint8_t index = 0, size_t* data_loc = nullptr) const;
size_t findServiceData(uint8_t index, uint8_t* bytes) const;
NimBLEAddress m_address{};
uint8_t m_advType{};
int8_t m_rssi{};
uint8_t m_callbackSent{};
uint8_t m_advLength{};
NimBLEAddress m_address;
uint8_t m_advType;
int m_rssi;
time_t m_timestamp;
uint8_t m_callbackSent;
uint8_t m_advLength;
# if CONFIG_BT_NIMBLE_EXT_ADV
bool m_isLegacyAdv;
uint8_t m_sid;
uint8_t m_primPhy;
uint8_t m_secPhy;
uint16_t m_periodicItvl;
bool m_isLegacyAdv{};
uint8_t m_sid{};
uint8_t m_primPhy{};
uint8_t m_secPhy{};
uint16_t m_periodicItvl{};
# endif
std::vector<uint8_t> m_payload;
};
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */
#endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */
#endif /* NIMBLE_CPP_ADVERTISED_DEVICE_H_ */

View file

@ -111,29 +111,17 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
return 0;
}
advertisedDevice = new NimBLEAdvertisedDevice();
advertisedDevice->setAddress(advertisedAddress);
advertisedDevice->setAdvType(event_type, isLegacyAdv);
#if CONFIG_BT_NIMBLE_EXT_ADV
advertisedDevice->setSetId(disc.sid);
advertisedDevice->setPrimaryPhy(disc.prim_phy);
advertisedDevice->setSecondaryPhy(disc.sec_phy);
advertisedDevice->setPeriodicInterval(disc.periodic_adv_itvl);
#endif
advertisedDevice = new NimBLEAdvertisedDevice(event, event_type);
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
} else if (advertisedDevice != nullptr) {
advertisedDevice->update(event, event_type);
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
} else {
// Scan response from unknown device
return 0;
}
advertisedDevice->m_timestamp = time(nullptr);
advertisedDevice->setRSSI(disc.rssi);
advertisedDevice->setPayload(disc.data, disc.length_data, (isLegacyAdv &&
event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP));
if (pScan->m_pScanCallbacks) {
if (advertisedDevice->m_callbackSent == 0 || !pScan->m_scan_params.filter_duplicates) {
advertisedDevice->m_callbackSent = 1;